【发布时间】:2019-01-31 18:54:55
【问题描述】:
我尝试将多个网格与一个变换矩阵合并为一个网格。 每个网格有 4 个数据集。
- 顶点
- 指数
- 纹理坐标
- 法线
我尝试这样做的方式应该是懒惰的,并且不会花费那么多 CPU。 这是一个 3 步过程。
- 将每个顶点和法线与变换矩阵相乘。
- 将每个网格的顶点、纹理坐标和法线合并到 3 个大数组中。
- 将每个网格的索引合并到一个数组中,但使用之前网格的总和作为偏移量。例如:如果网格 1 有 800 个索引,则必须将 800 添加到网格 2 的所有索引中。
这种方法有两个大问题。
- 重复的顶点不共享
- 由于剪裁不可见的部分不会被移除
但这没关系,因为这应该是一个没有太多 CPU 使用率的惰性方法。它已经是为草和灌木创建网格的最佳选择。
我已经尝试过实现这个方法,如下所示:
public static final MeshData mergeLazy(List<MeshData> meshes, List<Matrix4f> transformations) {
int lengthVertices = 0;
int lengthNormals = 0;
int lengthTexCoords = 0;
int lengthIndices = 0;
ArrayList<Integer> indexLengths = new ArrayList<>();
for(MeshData mesh : meshes) {
lengthVertices += mesh.getVertices().length;
lengthNormals += mesh.getNormals().length;
lengthTexCoords += mesh.getTextureCoordinates().length;
int length = mesh.getIndices().length;
lengthIndices += length;
indexLengths.add(length);
}
float[] vertices = new float[lengthVertices];
float[] texCoords = new float[lengthTexCoords];
float[] normals = new float[lengthNormals];
int[] indices = new int[lengthIndices];
int iv = 0;
int ivt = 0;
int ivn = 0;
int i = 0;
int indexLength = 0;
for(int im = 0; im < meshes.size(); im++) {
MeshData mesh = meshes.get(im);
float[] mVertices = mesh.getVertices();
float[] mTexCoords = mesh.getTextureCoordinates();
float[] mNormals = mesh.getNormals();
int[] mIndices = mesh.getIndices();
Matrix4f transformation = transformations.get(im);
for(int index = 0; index < mVertices.length; index += 3) {
Vector3f vertex = MatrixUtil.multiply(transformation, mVertices[index], mVertices[index + 1], mVertices[index + 2]);
vertices[iv++] = vertex.x;
vertices[iv++] = vertex.y;
vertices[iv++] = vertex.z;
Vector3f normal = MatrixUtil.multiply(transformation, mNormals[index], mNormals[index + 1], mNormals[index + 2]);
normals[ivn++] = normal.x;
normals[ivn++] = normal.y;
normals[ivn++] = normal.z;
}
for(int index = 0; index < mTexCoords.length; index++) {
texCoords[ivt++] = mTexCoords[index];
}
for(int index = 0; index < mIndices.length; index++) {
indices[i++] = indexLength + mIndices[index];
}
indexLength += indexLengths.get(im);
}
MeshData data = new MeshData();
data.setIndices(indices);
data.setNormals(normals);
data.setTextureCoordinates(texCoords);
data.setVertices(vertices);
return data;
}
最后我实际上有一个网格,并且变换的乘法也适用....对于旋转和缩放,但问题来了。
与转换相乘不适用于翻译。 我将矩阵与向量相乘的方法如下所示:
public static final Vector3f multiply(Matrix4f matrix, float x, float y, float z) {
Vector3f result = new Vector3f();
result.x = x * matrix.m00 + y * matrix.m01 + z * matrix.m02;
result.y = x * matrix.m10 + y * matrix.m11 + z * matrix.m12;
result.z = x * matrix.m20 + y * matrix.m21 + z * matrix.m22;
return result;
}
第二个问题是第二个网格的纹理有些偏离。
如您所见,第二个网格只有大约 1/4 的实际纹理。
我用来生成这个网格的代码如下所示:
Material grassMaterial = new Material();
grassMaterial.setMinBrightness(0.1F);
grassMaterial.setColorMap(new Texture(new XImgTextureReader().read(new FileInputStream("res/textures/grass2.ximg"))));
grassMaterial.setAffectedByLight(true);
grassMaterial.setTransparent(true);
grassMaterial.setUpwardsNormals(true);
grassMaterial.setFog(fog);
MeshData quad = Quad.generateMeshData(
new Vector3f(0.0F, 1F, 0.0F),
new Vector3f(0.0F, 0.0F, 0.0F),
new Vector3f(1F, 0.0F, 0.0F),
new Vector3f(1F, 1F, 0.0F)
);
StaticMesh grassMesh = new StaticMesh(MeshUtil.mergeLazy(Arrays.asList(quad, quad), Arrays.asList(
MatrixUtil.createTransformationMatrx(
new Vector3f(0.0F, 0.0F, 0.0F),
new Vector3f(0.0F, 0.0F, 0.0F),
new Vector3f(1.0F, 1.0F, 1.0F)
),
MatrixUtil.createTransformationMatrx(
new Vector3f(0F, 0.0F, -0F),
new Vector3f(0.0F, 90.0F, 0.0F),
new Vector3f(1.0F, 1.0F, 1.0F)
)
)));
grassMesh.setCullMode(StaticMesh.CULLING_DISABLED);
Entity grass = new Entity();
grass.setShaderPipeline(shaderPipeline);
grass.setMaterial(grassMaterial);
grass.setMesh(grassMesh);
grass.setTranslation(0, 0, 1);
我现在的问题是:我做错了什么?为什么纹理如此怪异,为什么转换的乘法对翻译不起作用?
如果您需要更多代码,我有一个带有 Eclipse 项目的 GitHub 存储库:https://github.com/RalleYTN/Heroica-Fabulis
【问题讨论】:
-
必须是
result.x = x*matrix.m00 + y*matrix.m01 + z*matrix.m02 + 1.0*matrix.m03;... -
整个方法不是只有在网格使用相同纹理时才有效吗?
-
@BDL 是的。这是一种懒惰的方法来创建许多不同的草和灌木网格,它们从每一侧使用相同的纹理。
-
@Rabbid76 结果还是一样,但是你是对的,应该是这样的。
-
哦,应该是
result.x = x*matrix.m00 + y * matrix.m10 + z*matrix.m20 + matrix.m30;。通常翻译是(m30,m31,m32)。请注意,数学矩阵和 OpenGL 矩阵的内存映像之间存在差异。
标签: java opengl 3d lwjgl matrix-multiplication