Положение и поворот модели после использования applyMatrix — ThreeJS

#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);
    }
  

Вот как это выглядит на средней отметке моего цилиндра с обеих сторон:

введите описание изображения здесь