three.js: вычисление faceVertexUvs в пользовательской геометрии для наложения текстуры - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть этот пример здесь: https://jsfiddle.net/NiklasKnaack/L1cqbdr9/82/

function createPlanetFace( radiusX, radiusY, radiusZ, localUp, resolution ) {

    const face = {};
  face.geometry = new THREE.Geometry();
  face.geometry.faceVertexUvs[ 0 ] = [];
  face.verticesOriginal = [];
  face.verticesNormalized = [];

    const axisA = new THREE.Vector3( localUp.y, localUp.z, localUp.x );
  const axisB = new THREE.Vector3().crossVectors( localUp, axisA );

  for ( let y = 0; y < resolution; y++ ) {

    for ( let x = 0; x < resolution; x++ ) {

        const index = x + y * resolution;

        const percent = new THREE.Vector2( x, y );
      percent.x /= ( resolution - 1 );
      percent.y /= ( resolution - 1 );

      const vertex = new THREE.Vector3();
      vertex.x = ( localUp.x + ( percent.x - 0.5 ) * 2 * axisA.x + ( percent.y - 0.5 ) * 2 * axisB.x ) * radiusX;
      vertex.y = ( localUp.y + ( percent.x - 0.5 ) * 2 * axisA.y + ( percent.y - 0.5 ) * 2 * axisB.y ) * radiusY;
      vertex.z = ( localUp.z + ( percent.x - 0.5 ) * 2 * axisA.z + ( percent.y - 0.5 ) * 2 * axisB.z ) * radiusZ;

            face.verticesOriginal[ index ] = new THREE.Vector3( vertex.x, vertex.y, vertex.z );

      vertex.normalize();//create a sphere

      vertex.x += vertex.x * radiusX / 2;
      vertex.y += vertex.y * radiusY / 2;
      vertex.z += vertex.z * radiusZ / 2;

      face.verticesNormalized[ index ] = new THREE.Vector3( vertex.x, vertex.y, vertex.z );

      face.geometry.vertices[ index ] = vertex;

      //if ( index % 6 === 0 && index > 0 && x !== resolution - 1 && y !== resolution - 1 ) {
      if ( x !== resolution - 1 && y !== resolution - 1 ) {

        const triangle1 = new THREE.Face3( index, index + resolution + 1, index + resolution );
        const triangle2 = new THREE.Face3( index, index + 1, index + resolution + 1 );

        face.geometry.faces.push( triangle1, triangle2 );

      }

    }

  }

  //face.geometry.computeBoundingSphere();
  //face.geometry.computeVertexNormals();
  //face.geometry.computeFaceNormals();

  return face;

};

Для этого я хотел бы рассчитать UV, чтобы загруженная текстура отображалась правильно.

В принципе, функция createPlanetFace создает плоскость. Из этих 6 плоскостей создается куб или сфера. (См. Пример) Пока это уже работает, только текстура не отображается, потому что UV не хватает. После долгих исследований и попыток я получаю либо ошибки в консоли, либо полностью искаженную текстуру, либо просто нет текстуры вообще. Вот почему я стер свои жалкие попытки расчета UV. Примеры, которые я нашел по этой теме, разные. По крайней мере, большинство из них. Теперь я достиг точки, когда я не могу идти дальше и мне нужна твоя помощь.

Заранее спасибо.

1 Ответ

0 голосов
/ 14 сентября 2018

Вот развёрнутая коробка, которую я недавно написал для обычной геометрии:

function boxUnwrapUVs(geometry) {
    for (var i = 0; i < geometry.faces.length; i++) {
        var face = geometry.faces[i];
        var faceUVs = geometry.faceVertexUvs[0][i]
        var va = geometry.vertices[geometry.faces[i].a]
        var vb = geometry.vertices[geometry.faces[i].b]
        var vc = geometry.vertices[geometry.faces[i].c]
        var vab = new THREE.Vector3().copy(vb).sub(va)
        var vac = new THREE.Vector3().copy(vc).sub(va)
        //now we have 2 vectors to get the cross product of...
        var vcross = new THREE.Vector3().copy(vab).cross(vac);
        //Find the largest axis of the plane normal...
        vcross.set(Math.abs(vcross.x), Math.abs(vcross.y), Math.abs(vcross.z))
        var majorAxis = vcross.x > vcross.y ? (vcross.x > vcross.z ? 'x' : vcross.y > vcross.z ? 'y' : vcross.y > vcross.z) : vcross.y > vcross.z ? 'y' : 'z'
        //Take the other two axis from the largest axis
        var uAxis = majorAxis == 'x' ? 'y' : majorAxis == 'y' ? 'x' : 'x';
        var vAxis = majorAxis == 'x' ? 'z' : majorAxis == 'y' ? 'z' : 'y';
        faceUVs[0].set(va[uAxis], va[vAxis])
        faceUVs[1].set(vb[uAxis], vb[vAxis])
        faceUVs[2].set(vc[uAxis], vc[vAxis])
    }
    geometry.elementsNeedUpdate = geometry.verticesNeedUpdate = true;
}

Это полезно?

edit: Я переписал твой пример, потому что он был слишком сложен для меня, чтобы понять ...

https://jsfiddle.net/manthrax/dL6kxuf2/1/

...