我最近创建了一个侧放的圆柱体。然后,我通过计算每个面 tris 的中心点将一个立方体添加到它的每个段中,并使其与立方体完美配合。
我现在正在尝试用模型替换立方体。该模型是一个平坦的地面,因此本质上是一个立方体。我遇到了一些问题。
第一个问题是,当我将地面模型添加到圆柱体时,由于圆柱体在其一侧,地面 0,0,0 被错误地翻转。我通过执行以下操作解决了这个问题:
ground.model.scene.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI / 2));
ground.model.scene.applyMatrix(new THREE.Matrix4().makeRotationY(Math.PI));
然而,我的逻辑中对立方体完美工作的下一步是使用查看和传递面法线以及通过当前面的位置计算旋转并计算两个面的中心点。由于我的圆柱体的每个面都由两个 tris 组成,所以我可以这样欺骗它!
这些函数如下所示:
averageFaceNormals(index){
var faceAvg = new THREE.Vector3();
faceAvg.x = (this.cylinder.geometry.faces[index].normal.x +
this.cylinder.geometry.faces[index+1].normal.x) / 2;
faceAvg.y = (this.cylinder.geometry.faces[index].normal.y +
this.cylinder.geometry.faces[index+1].normal.y) / 2;
faceAvg.z = (this.cylinder.geometry.faces[index].normal.z +
this.cylinder.geometry.faces[index+1].normal.z) / 2;
return faceAvg;
}
calculateFacePositions(index){
var geo = this.cylinder.geometry;
var faceA = this.cylinder.geometry.faces[index];
var verticesA = geo.vertices;
var v1A = verticesA[faceA.a];
var v2A = verticesA[faceA.b];
var v3A = verticesA[faceA.c];
var centroidA = new THREE.Vector3();
centroidA.x = ( v1A.x + v2A.x + v3A.x ) / 3;
centroidA.y = ( v1A.y + v2A.y + v3A.y ) / 3;
centroidA.z = ( v1A.z + v2A.z + v3A.z ) / 3;
var faceB = this.cylinder.geometry.faces[index+1];
var verticesB = geo.vertices;
var v1B = verticesB[faceB.a];
var v2B = verticesB[faceB.b];
var v3B = verticesB[faceB.c];
var centroidB = new THREE.Vector3();
centroidB.x = ( v1B.x + v2B.x + v3B.x ) / 3;
centroidB.y = ( v1B.y + v2B.y + v3B.y ) / 3;
centroidB.z = ( v1B.z + v2B.z + v3B.z ) / 3;
var centroidAverage = new THREE.Vector3();
centroidAverage.addVectors(centroidA, centroidB);
centroidAverage.x = centroidAverage.x / 2;
centroidAverage.y = centroidAverage.y / 2;
centroidAverage.z = centroidAverage.z / 2;
return centroidAverage;
}
然后这是我添加地砖的地方,我注释掉了负责旋转和位置的两条线,因为它们不再适用于我的模型,而是完美地适用于我一直使用的立方体测试对象。我忽略了什么吗?地面瓷砖产生,但就像我所做的矩阵更改被查看和位置副本覆盖。
for(var i = 0; i < this.cylinder.geometry.faces.length; i+=2){
var ground = new Ground("ground", this.preload);
ground.model.scene.applyMatrix(new THREE.Matrix4().makeRotationZ(Math.PI / 2));
ground.model.scene.applyMatrix(new THREE.Matrix4().makeRotationY(Math.PI));
//ground.model.scene.lookAt(this.averageFaceNormals(i));
//ground.model.scene.position.copy(this.calculateFacePositions(i));
this.cylinder.add(ground.model.scene);
}
编辑:所以我目前已经取得了一些进展,它似乎用更少的代码工作得更好,但我已经改变了我的放置循环看起来像这样:
for(var i = 0; i < this.cylinder.geometry.faces.length; i+=2){
var ground = new Ground("ground", this.preload);
var afn = this.averageFaceNormals(i);
ground.model.scene.up = afn.clone().normalize();
ground.model.scene.lookAt(new Vector3(afn.x,afn.y,afn.z));
ground.model.scene.position.copy(this.calculateFacePositions(i));
this.cylinder.add(ground.model.scene);
}
似乎我只需要让每个地面都将旋转值翻转为 0,但我不知道如何去做。复制/设置似乎不起作用,我不确定是否需要使用欧拉或向量。
这可能很明显,但这是我第一次使用 ThreeJS,所以感谢您对我的包容!
编辑#2:好的,所以我已经取得了更大的进步,并按照我的需要铺设了地砖!现在我注意到,似乎我的一半瓷砖被翻转放置在 X 上,这导致一半圆柱体没有正确排列。
我更新的展示位置代码:
for(var i = 0; i < this.cylinder.geometry.faces.length; i+=2){
var ground = new Ground("ground", this.preload);
var afn = this.averageFaceNormals(i);
ground.model.scene.up = afn.clone().normalize();
ground.model.scene.lookAt(afn);
ground.model.scene.rotateX(Math.PI/2);
ground.model.scene.position.copy(this.calculateFacePositions(i));
this.cylinder.add(ground.model.scene);
}
这是我的圆柱体两侧中间标记处的样子:

