Help to Calculate uvs for polygon

Hi, im trying to calculate the uvs for a polygon, which is at a random position where plane has an angle 90° to the center vector, and also not exactly flat, but almost. I have a shader which then applies textures to multiple polygons.
So i need to translate it to the center and then rotate it sich that the plane matches an axis. Then calculate uvs such that the polygon is inside the square texture

This is the code i have:

const polyVertices = [];
      const center = new THREE.Vector3().copy(t.averagePosition);
      t.corners
        .map(c => c.position)
        .forEach((c, i, arr) => {
          polyVertices.push(c.x, c.y, c.z);
          polyVertices.push(t.averagePosition.x, t.averagePosition.y, t.averagePosition.z);
          const next = arr[i + 1] || arr[0];
          polyVertices.push(next.x, next.y, next.z);
          colors.push(col, col, col);
        });
      const dir = new THREE.Vector3(0,1,0);
      const polyGeometry = new THREE.BufferGeometry();
      polyGeometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(polyVertices), 3));
      const mesh = new THREE.Mesh(polyGeometry);
      mesh.quaternion.setFromUnitVectors(center.clone().normalize(), dir.clone().normalize());
      const box = new THREE.Box3();
      box.setFromObject(mesh);
      const size = box.getSize();
      polyGeometry.translate(-center.x, -center.y, -center.z)
      polyGeometry.translate(size.x/2, size.y/2, size.z / 2)
      const verts = polyGeometry.getAttribute('position');
      for (let i = 0; i < verts.array.length; i += 3) {
        const v = new THREE.Vector3().fromBufferAttribute(verts, i);
        mesh.localToWorld(v);
        uvs.push(v.x / size.x, v.z / size.z);
      }
    });

But if i just set the uvs to

uvs.push(...[
            0.0, 0.0,
            1.0, 0.0,
            1.0, 1.0,
            0.0, 1.0,
          ]);

It works, but looks weird

How weird? Please post the texture and the result.

Hi,
Here is the result and the texture.
The texture is applied to each triangle instead of the polygon.

20211025_071656
Screenshot 2020-11-17 144627

@Patrick_Pircher
Find the bounding box/rectangle for your polygon and compute uv for vertices.
Something like this, if your polygon is on XY-plane:

let pos = geometry.attributes.position;
let bbox = new THREE.Box3().setFromBufferAttribute( pos );
let size = new THREE.Vector3();
bbox.getSize(size);
let v3 = new THREE.Vector3();
for(let i = 0; i < pos.count; i++){
  v3.fromBufferAttribute(pos, i);
  let u = (v3.x - bbox.min.x) / size.x;
  let v = (v3.y - bbox.min.y) / size.y;
  geometry.attributes.uv.setXY(i, u, v);
}
geometry.attributes.uv.needsUpdate = true;
3 Likes

Thanks, i will try that out. But the main problem then is to move and rotate the polygon correctly to be on the xy plane. But i think that’s working correctly now, so moving and rotate

When you’re trying to debug texturing problems, I find it much easier to use a test texture with a known (and recognisable!) pattern, instead of a seemingly random structure on it. Try this, for example:

As far as rotating the polygon correctly into the xy-plane:
compute the normal for one triangle face (assuming, all vertices of the polygon are co-planar), then use that normal as a “handle” to rotate the plane, until that handle becomes parallel to the z-axis.

You can compute those angles as follows:

rotY = atan(x / z)
rotX = atan(y / z)

with (x, y, z) being the three components of your normal vector.

2 Likes

Hi, trying to apply texture here:.

But no luck so far

Alright, finally have it working. Using setXY on uvs didn’t seem to work.