我已经卡住了一段时间,弄清楚为什么我无法从高度图图像生成带法线的纹理网格。我正在使用TerrainTest(http://libgdx.googlecode.com/svn/trunk/tests/gdx-tests/src/com/badlogic/gdx/tests/TerrainTest.java)代码,并且只添加了用于生成法线和tex坐标的代码:
private void calcNormals(short[] indices, float[] verts) {
Vector3 point1=new Vector3(), point2=new Vector3(), point3=new Vector3();
for (int i = 0; i < indices.length; i += 3) {
int i1 = getPositionStart(indices[i + 0]);
int i2 = getPositionStart(indices[i + 1]);
int i3 = getPositionStart(indices[i + 2]);
point1.set(verts[i1 + 0], verts[i1 + 1], verts[i1 + 2]);
point2.set(verts[i2 + 0], verts[i2 + 1], verts[i2 + 2]);
point3.set(verts[i3 + 0], verts[i3 + 1], verts[i3 + 2]);
Vector3 v1 = new Vector3().set(point2).sub(point1);
Vector3 v2 = new Vector3().set(point3).sub(point1);
Vector3 nor = v1.crs(v2).nor();
addNormal(indices[i + 0], verts, nor.x, nor.y, nor.z);
addNormal(indices[i + 1], verts, nor.x, nor.y, nor.z);
addNormal(indices[i + 2], verts, nor.x, nor.y, nor.z);
}
}
我在修改后的buildVertices()方法中添加纹理坐标:
public void buildVertices() {
int heightPitch = height + 1;
int widthPitch = width + 1;
int idx = 0;
int hIdx = 0;
Gdx.app.log("DBG","height map size="+heightMap.length);
for (int z = 0; z < heightPitch; z++) {
for (int x = 0; x < widthPitch; x++) {
// POSITION
vertices[idx++] = x;
vertices[idx++] = heightMap[hIdx++] * strength;
vertices[idx++] = z;
// NORMAL, skip these for now
idx += 3;
// COLOR
vertices[idx++] = Color.WHITE.toFloatBits();
// TEXTURE
vertices[idx++] = (x / (float) width);
vertices[idx++] = (z / (float) height);
}
}
}
这是我在TerrainTest.TerrainChunk类中更改过的唯一代码。
然后我创建一个网格: int vertexSize = 3 + 3 + 1 + 2;
TerrainChunk chunk = new TerrainChunk(4, 4, vertexSize, "textures/heightmap.png", 10);
groundMesh = new Mesh(true, chunk.vertices.length / 3, chunk.indices.length,
new VertexAttribute(Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE),
new VertexAttribute(Usage.Normal, 3, ShaderProgram.NORMAL_ATTRIBUTE),
new VertexAttribute(Usage.ColorPacked, 4, ShaderProgram.COLOR_ATTRIBUTE),
new VertexAttribute(Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE));
groundMesh.setVertices(chunk.vertices);
groundMesh.setIndices(chunk.indices);
之后我只从网格中创建一个btBvhTriangleMeshShape和一个模型:
Material material = new Material(ColorAttribute.createDiffuse(Color.WHITE), ColorAttribute.createSpecular(Color.WHITE),
FloatAttribute.createShininess(16f));
Model result = new Model();
int chunkNum = 0;
MeshPart meshPart = new MeshPart();
meshPart.id = "terrainChunk" + chunkNum;
meshPart.indexOffset = 0;
meshPart.numVertices = groundMesh.getNumIndices();
meshPart.primitiveType = GL20.GL_TRIANGLES;
meshPart.mesh = groundMesh;
btTriangleIndexVertexArray bttiva = new btTriangleIndexVertexArray(meshPart);
btBvhTriangleMeshShape heightFieldShape = new btBvhTriangleMeshShape(bttiva, true);
NodePart nodePart = new NodePart();
nodePart.material = material;
nodePart.meshPart = meshPart;
Node node = new Node();
node.id = "terrainNode" + chunkNum;
node.parts.add(nodePart);
result.meshes.add(groundMesh);
result.materials.add(material);
result.nodes.add(node);
result.meshParts.add(meshPart);
result.manageDisposable(groundMesh);
我用DebugDrawModes.DBG_DrawNormals |渲染Mesh和btShape DebugDrawModes.DBG_DrawWireframe所以我可以看到btShape的连线和法线。
无论我做什么,网格和rigidBody的法线都指向下方(-y),并且网格的纹理在其底部以均匀的颜色(如纹理的平均颜色)绘制。奇怪的是,无论我是否改变法线计算(即使用-normal.y而不是+ normal.y),debugdraw的法线都不会改变!网格只能从下面看到。我已经在groundMesh.getVertices()中打印了所有数据,一切似乎都适合我。下面是为每个顶点打印的9个组件(2x2 TerrainChunk用于测试):
DBG: Vertex: 0.0,9.803922,0.0,0.07673953,0.9784201,0.19184695,-1.7014117E38,0.0,0.0
DBG: Vertex: 1.0,9.725491,0.0,0.15213917,0.96989024,0.19017535,-1.7014117E38,0.5,0.0
DBG: Vertex: 2.0,9.6470585,0.0,0.07541871,0.96157986,0.26396275,-1.7014117E38,1.0,0.0
DBG: Vertex: 0.0,9.607843,1.0,0.11272618,0.9581794,0.2630302,-1.7014117E38,0.0,0.5
DBG: Vertex: 1.0,9.529411,1.0,0.21905276,0.93097335,0.29206917,-1.7014117E38,0.5,0.5
DBG: Vertex: 2.0,9.372549,1.0,0.14450188,0.9212023,0.36125556,-1.7014117E38,1.0,0.5
DBG: Vertex: 0.0,9.333333,2.0,0.11272618,0.9581794,0.2630302,-1.7014117E38,0.0,1.0
DBG: Vertex: 1.0,9.215687,2.0,0.21905276,0.93097335,0.29206917,-1.7014117E38,0.5,1.0
DBG: Vertex: 2.0,8.980392,2.0,0.21905276,0.93097335,0.29206917,-1.7014117E38,1.0,1.0
法线(指数3,4和5)都指向上方!但是debugdraw的法线指向下方,网格只能从下面看到。
如果我改变法线的计算方式,所以它会产生一些其他的值,我可以看到这在我打印顶点的内容时确认但是调试和网格保持不变..这怎么可能,它就像网格完全一样忽略了正常值。
答案 0 :(得分:2)
这似乎是renderpipeline下面的某个问题。背面剔除的法线似乎不是由所提供的法线决定的,而是由三角形的缠绕决定的(由顶点顺序引起)。
解决方法,用于更改构建网格时提供索引的顺序。
例如,在LibGDX TerrainTest(基于你的代码)中,在 buildIndices 方法中创建了索引:
indices[idx++] = i1;
indices[idx++] = i2;
indices[idx++] = i3;
indices[idx++] = i3;
indices[idx++] = i4;
indices[idx++] = i1;
更改每个三角形的最后两个索引的顺序,如下所示:
indices[idx++] = i1;
indices[idx++] = i3; //i3 is exchanged
indices[idx++] = i2; //with i2
indices[idx++] = i3;
indices[idx++] = i1; //i1 is exchanged
indices[idx++] = i4; //with i4
这将改变三角形的“缠绕”,现在它应该正确呈现。
解决方案将在LibGDX bugtracker中提交一个错误,以便修复它,因为我不认为这是预期的行为。
(PS:我希望这还不算太晚,但是因为这让我很头疼,我想也许它可以帮助一些人。)