模型烘焙,就是把一个四边形,通过一步步方法,烘焙成供mc渲染管线使用来渲染一个四边形面的BakedQuad对象。
可以首先来看看BakedModel的构造方法
1 2 3 4 5 6 7 8
| public BakedQuad(int[] pVertices, int pTintIndex, Direction pDirection, TextureAtlasSprite pSprite, boolean pShade, boolean hasAmbientOcclusion) { this.vertices = pVertices; this.tintIndex = pTintIndex; this.direction = pDirection; this.sprite = pSprite; this.shade = pShade; this.hasAmbientOcclusion = hasAmbientOcclusion; }
|
其中vertices是最重要的顶点数据,是int[32]数组,它是由四个顶点构成,每个顶点数据由8个int数据构成,拼接为32长度的数组。
direction是这个面的朝向,用于mc进行单面剔除来优化渲染。
sprite是这个面的材质精灵图。
这时候我们来看一下烘焙模型的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| for (ModelQuadLayer pc : mpc) { getFaceUvs(uvs, direction ,from, to,pc.uvs); BlockFaceUV blockFaceUV = new BlockFaceUV(uvs,0); TextureAtlasSprite sprite = pc.sprite; int tint = pc.tint; var data = net.minecraftforge.client.model.ForgeFaceData.DEFAULT; var pVertices = makeVertices(sprite,blockFaceUV,pos,direction,to,from); BakedQuad quad = new BakedQuad(pVertices,tint,direction,sprite,true,true); applyingLightmap(data.blockLight(), data.skyLight()).processInPlace(quad); applyingColor(data.color()).processInPlace(quad); if (region.isEdge) { builder.getList(direction).add(quad); } else { builder.getList(null).add(quad); } }
|
getFaceUVs方法中将float[4] uvs进行变换,由from和to两个Vector3f对象和direction方向得出在材质平面上的长方形的两个顶点坐标。
得到float[4]{u1,v1,u2,v2}
得到了uv,就要开始烘焙顶点数据了,也就是makeVertices方法,这个方法从原版的模型烘焙类FaceBakery中抄来
1 2 3 4 5 6 7 8 9 10
| private int[] makeVertices(TextureAtlasSprite sprite, BlockFaceUV pBlockFaceUV,float[] pos, Direction direction, int[] to, int[] from) { int[] data = new int[32];
for(int vertexNum = 0; vertexNum < 4; ++vertexNum) { getVertexPos(pos, direction, vertexNum, to, from); this.fillVertex(data, vertexNum, new Vector3f(pos[0],pos[1],pos[2]), sprite, pBlockFaceUV); }
return data; }
|
在这里分别把四个顶点的数据通过fillVertex方法写进data[32],返回装好了顶点数据的浮点数数组
1 2 3 4 5 6 7 8
| private void fillVertex(int[] pVertexData, int pVertexIndex, Vector3f pVector, TextureAtlasSprite pSprite, BlockFaceUV pBlockFaceUV) { int i = pVertexIndex * 8; pVertexData[i] = Float.floatToRawIntBits(pVector.x()); pVertexData[i + 1] = Float.floatToRawIntBits(pVector.y()); pVertexData[i + 2] = Float.floatToRawIntBits(pVector.z()); pVertexData[i + 4] = Float.floatToRawIntBits(pSprite.getU((double)pBlockFaceUV.getU(pVertexIndex) * .999 + pBlockFaceUV.getU((pVertexIndex + 2) % 4) * .001)); pVertexData[i + 4 + 1] = Float.floatToRawIntBits(pSprite.getV((double)pBlockFaceUV.getV(pVertexIndex) * .999 + pBlockFaceUV.getV((pVertexIndex + 2) % 4) * .001)); }
|
最后再用原版方法为面补上色彩和光照数据,结束模型烘焙
1 2
| applyingLightmap(data.blockLight(), data.skyLight()).processInPlace(quad); applyingColor(data.color()).processInPlace(quad);
|