#three.js
#three.js
Вопрос:
Недавно я создал цилиндр, который лежит на боку. Затем я добавляю куб к каждому из его сегментов, вычисляя центральную точку каждой грани 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));
Однако следующим шагом в моей логике, который отлично работал для кубов, было вычисление поворота с использованием просмотра и передачи нормалей граней и положения, проходящего в текущей грани, и вычисления центральной точки двух граней. Поскольку каждая грань моего цилиндра состоит из двух три, я могу обмануть это таким образом!
Эти функции выглядят следующим образом:
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;
}
Затем я добавляю основные фрагменты, я прокомментировал две строки, отвечающие за вращение и положение, поскольку они больше не работают с моей моделью, но отлично работают с тестовым объектом cube, который я использовал. Я что-то упускаю из виду? Появляются основные плитки, но это похоже на то, что изменение матрицы, которое я внес, переопределяется копией lookat и position.
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);
}
Вот как это выглядит на средней отметке моего цилиндра с обеих сторон: