Search code examples
three.jsquaternions

Error with a class for creating faces with three.js quaternion from two vectors


I'm creating a class to make the faces of an object, but I'm having problens with the quaternion. When I use the baseNormal vector as (0,0,0) the vertical faces disappears and i get this error.

THREE.DirectGeometry: Faceless geometries are not supported.

enter image description here

But, when i do baseNormal vector as (0,0,1) all the faces became horizontal and far way from the solide. Can some one help me?

enter image description here

"use strict";

// Classe Tface
// Representa visualmente o face

//three
import * as THREE from "three";
import { Object3D } from "three/src/core/Object3D.js";
import { Vector3 } from "three/src/math/Vector3";
import { Triangle } from "three/src/math/Triangle";

/**
 * @param nome: string
 * @param arrTponto = []
 * @param arrFaces = []
 */

class Tface extends Object3D {
  constructor(nome, arrTponto, arrFaces) {
    //Parametros: string, Vector3(X,Y,Z)

    super();

    this.type = "Tface";
    //name of face
    this.nome = nome;
    //receives  Tpontos array
    this.arrPt = arrTponto;
    //receives array of points name that makes up the face
    this.arrFaces = arrFaces;
  }
  /* recebe o array de pontos e o array com o nomes dos pontos de cada face, compara ambos 
e separa os pontos de cada face determina a normal de cada face, cria a malha da mesma e adiciona na cena.
*/

  //intersect array of point names with Tponto array (vector3)
  criaFace() {
    this.points = [];
    this.arrFaces.forEach((elemento) => {
      this.arrPt.forEach((e) => {
        if (e.nome == elemento) {
          this.pontV = new Vector3(e.X, e.Y, e.Z);
          this.points.push(this.pontV);
        }
      });
    });

    //determines the normal of the faces
    this.triangulo = new Triangle(
      this.points[2],
      this.points[1],
      this.points[0]
    );
    this.normal = new Vector3();
    this.triangulo.getNormal(this.normal);

    this.baseNormal = new Vector3(0, 0, 1);

    this.quaternion.setFromUnitVectors(this.normal, this.baseNormal);

    this.tempPoints = [];
    this.points.forEach((p) => {
      this.tempPoints.push(p.clone().applyQuaternion(this.quaternion));
      console.log(p, this.tempPoints);
    });

    //generates the face mesh
    this.shape = new THREE.Shape(this.tempPoints);
    this.shapeGeom = new THREE.ShapeGeometry(this.shape);
    this.mesh = new THREE.Mesh(
      this.shapeGeom,
      new THREE.MeshBasicMaterial({
        color: 0xfcee2b,
        side: THREE.DoubleSide,
        transparent: true,
        opacity: 0.6,
        wireframe: false,
      })
    );

    this.mesh.geometry.vertices = this.points;
    this.name = String;
    this.mesh.name;
    //add face to the scene
    this.add(this.mesh);

    this.geom = new THREE.BufferGeometry().setFromPoints(this.points);
    this.matLines = new THREE.LineBasicMaterial({ color: "red" });
    this.lines = new THREE.LineLoop(this.geom, this.matLines);
    this.lines.name = "line" + String(this.name);
    this.add(this.lines);

    //requestRenderIfNotRequested();
  }
  dispose() {
    //libera a memória
    this.children.forEach((element) => {
      element.material.dispose();
      element.geometry.dispose();
    });
    this.children = [];
  }
  update(nome, pt) {
    //atualiza o ponto: nome e posição
    this.nome = nome;
    this.children.forEach((element) => {
      element.position.copy(pt);
    });
  }
}

export { Tface };

Solution

  • Please notice that both parameters of Quaternion.setFromUnitVectors() are expected to have unit length. The vector (0,0,0) is not a unit vector since it has a length of 0. So you need to use a different input vector.