代码初始化
This commit is contained in:
1 parent
c2f5cd98ff
commit
e3efeb74ad
2439 files changed
+305661
-1
No files matched your search
@@ -0,0 +1,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""由 box_of_nails 方块贴图(64x64 UV展开图)生成 16x16 的物品图标。
|
||||
|
||||
采用等轴测投影组合盒子可见的三个面(顶面 + 正面 + 右侧面),
|
||||
源贴图中三个面所在的像素区域(由 blockbench 模型 UV 推出):
|
||||
正面 north px (8, 8) - (18, 13) 10 x 5
|
||||
右侧 east px (0, 8) - (8, 13) 8 x 5
|
||||
顶面 up px (8, 13) - (18, 21) 10 x 8
|
||||
盒子模型尺寸: 宽 10 单位(x) x 高 5 单位(y) x 深 8 单位(z),1 单位 = 1 贴图像素。
|
||||
"""
|
||||
import math
|
||||
import os
|
||||
from PIL import Image
|
||||
|
||||
ROOT = r"e:\MCStudioDownload\work\3027246179@qq.com\Cpp\AddOn\0aaaa4f2f16c46e8964025a5ab0ecc02"
|
||||
RES = os.path.join(ROOT, "resource_pack_t7eJjrxY")
|
||||
SRC = os.path.join(RES, "textures", "blocks", "box_of_nails.png")
|
||||
DST = os.path.join(RES, "textures", "items", "box_of_nails.png")
|
||||
|
||||
OUT = 16 # 最终图标边长
|
||||
SS = 4 # 超采样倍数
|
||||
SIZE = OUT * SS # 渲染画布边长
|
||||
|
||||
TEX_FRONT = (8, 8, 18, 13) # 正面 north
|
||||
TEX_WEST = (18, 8, 26, 13) # 左侧面 west
|
||||
TEX_TOP = (8, 13, 18, 21) # 顶面 up
|
||||
|
||||
W, H, D = 10.0, 5.0, 8.0 # 盒子宽/高/深(模型单位)
|
||||
|
||||
|
||||
def rasterize(dst, src, origin, uvec, vvec, rect):
|
||||
"""把源贴图矩形 rect 以平行四边形(origin + s*uvec + t*vvec)填到 dst。"""
|
||||
x0, y0, x1, y1 = rect
|
||||
ox, oy = origin
|
||||
ux, uy = uvec
|
||||
vx, vy = vvec
|
||||
det = ux * vy - uy * vx
|
||||
if abs(det) < 1e-9:
|
||||
return
|
||||
corners = [origin, (ox + ux, oy + uy), (ox + ux + vx, oy + uy + vy), (ox + vx, oy + vy)]
|
||||
minx = max(0, int(math.floor(min(c[0] for c in corners))))
|
||||
maxx = min(dst.width - 1, int(math.ceil(max(c[0] for c in corners))))
|
||||
miny = max(0, int(math.floor(min(c[1] for c in corners))))
|
||||
maxy = min(dst.height - 1, int(math.ceil(max(c[1] for c in corners))))
|
||||
px = dst.load()
|
||||
spx = src.load()
|
||||
sw, sh = src.size
|
||||
for py in range(miny, maxy + 1):
|
||||
dy = py + 0.5 - oy
|
||||
for pxx in range(minx, maxx + 1):
|
||||
dx = pxx + 0.5 - ox
|
||||
s = (vy * dx - vx * dy) / det
|
||||
t = (-uy * dx + ux * dy) / det
|
||||
if s < 0.0 or s >= 1.0 or t < 0.0 or t >= 1.0:
|
||||
continue
|
||||
sx = int(x0 + s * (x1 - x0))
|
||||
sy = int(y0 + t * (y1 - y0))
|
||||
sx = min(max(sx, 0), sw - 1)
|
||||
sy = min(max(sy, 0), sh - 1)
|
||||
px[pxx, py] = spx[sx, sy]
|
||||
|
||||
|
||||
def main():
|
||||
src = Image.open(SRC).convert("RGBA")
|
||||
dst = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0))
|
||||
|
||||
cx = math.cos(math.radians(30.0))
|
||||
cy = math.sin(math.radians(30.0))
|
||||
# 画布内每模型单位对应的像素数(保证盒子完整落在画布内)
|
||||
margin = 4
|
||||
u = min((SIZE - 2 * margin) / ((W + D) * cx),
|
||||
(SIZE - 2 * margin) / ((W + D) * cy + H))
|
||||
|
||||
wv = (W * u * cx, -W * u * cy) # 宽度方向 x(右后上)
|
||||
dv = (-D * u * cx, -D * u * cy) # 深度方向 z(左后上)
|
||||
vv = (0.0, H * u) # 竖直向下
|
||||
|
||||
# 前上顶点 F(俯视时最靠近观察者的角),整体居中
|
||||
content_w = (W + D) * u * cx
|
||||
content_h = (W + D) * u * cy + H * u
|
||||
fx = (SIZE - content_w) / 2.0 + D * u * cx
|
||||
fy = (SIZE - content_h) / 2.0 + (W + D) * u * cy
|
||||
f = (fx, fy)
|
||||
|
||||
rasterize(dst, src, f, dv, vv, TEX_WEST) # 左侧面
|
||||
rasterize(dst, src, f, wv, vv, TEX_FRONT) # 正面
|
||||
rasterize(dst, src, f, wv, dv, TEX_TOP) # 顶面
|
||||
|
||||
icon = dst.resize((OUT, OUT), Image.BOX)
|
||||
os.makedirs(os.path.dirname(DST), exist_ok=True)
|
||||
icon.save(DST)
|
||||
print("icon ->", DST, icon.size)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user