8

I want to give each face of a THREE.js sphere it's own texture. So I let a SphereGeometry calculate the vertices and convert each face to a PlaneGeometry using the vertices of the faces.

THREE.SpherePlaneGeometry = function ( v1, v2, v3, v4 ) {

  THREE.Geometry.call( this );

  var normal = new THREE.Vector3( 0, 1, 0 );

  this.vertices.push( v1.clone() );
  this.vertices.push( v2.clone() );
  this.vertices.push( v3.clone() );
  this.vertices.push( v4.clone() );

  var face = new THREE.Face4( 0, 1, 2, 3 );

  face.normal.copy( normal );
  face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone() );

  this.faces.push( face );

  var uvs = [
    new THREE.UV( 1.0, 0.0 ),
    new THREE.UV( 0.0, 0.0 ),
    new THREE.UV( 0.0, 1.0 ),
    new THREE.UV( 1.0, 1.0 ),
  ];
  this.faceVertexUvs[ 0 ].push( uvs );

};

to be sure all of this runs later with the returned geometry:

geometry.computeCentroids();
geometry.computeFaceNormals();
geometry.verticesNeedUpdate = true;
geometry.uvsNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.tangentsNeedUpdate = true;
geometry.elementsNeedUpdate = true;
geometry.dynamic = true;

By applying this texture:

texture

I got this result:

sphere

What can be done to remove the distortion between the red and green points? For the poles one vertice is used twice, but it could be better, any idea?

mrdoob
  • 19,334
  • 4
  • 63
  • 62
Torsten Becker
  • 4,330
  • 2
  • 21
  • 22
  • 1
    It looks like this is a similar question: http://stackoverflow.com/questions/6046929/problem-gltexgen-in-open-gl-es-2-0 and the more general is: How to texture a projected Quad? However, is there a solution using THREE.js? – Torsten Becker Aug 20 '12 at 15:36
  • as noiv said ,it seems that the top quads are triangulated wrong and, I would suggest making a middle point for each quad and make 4 triangles and try then using the texture... maybe even use u,v of the phi and delta to cover the entire sphere and use somekind of repeat factor... – EliSherer Aug 21 '12 at 19:02
  • @EliSherer, overtesselation would solve it, but poly count should remain same. Another approach called projective interpolation is ruled out as it moves the problem to the edge of the quads: http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/ – Torsten Becker Aug 22 '12 at 00:35

2 Answers2

3

This is a tricky problem. Our texture mapping is still affine.

blah

At some point we'll need to experiment with perspective correct texture mapping. I have read somewhere something about interpolating a w... but I'm not really sure that this would solve your problem.

To simplify the problem... look at the affine mapped quad in texture mapping image. Imagine that you move the top left vertex into the top right. By doing that you're basically turning the left triangle into a simple line that goes from bottom left to top right. This basically mean that you it won't be visible. Because the vertices of the right triangle have not been moved, the triangle is still there, visible, with the UVs asigned to each vertex.

So the only solutions I can think would be:

  1. Add one level of tessellation to those polygons.
  2. Having a special pre-corrected texture (either using canvas or photoshop) for these possible cases.
Community
  • 1
  • 1
mrdoob
  • 19,334
  • 4
  • 63
  • 62
  • I'm not sure whether it's same problem. Maybe it results in same solution or I need a solution to both. But I do not have a rectangle distorted while projected, it's a trapezoid. I found this description useful: http://www.xyzw.us/~cass/qcoord/. However, I have no clue where to start to implement this receipt: "This is good, because instead of specifying the texture coordinates for the upper vertices as (s,t) coordinates of (0, 1) and (1, 1), we can specify them as (s,t,r,q) coordinates of (0, width, 0, width) and (width, width, 0, width)!" It really sounds so simple. – Torsten Becker Aug 24 '12 at 02:15
2

There are several issues here.

First, you do not need to convert each face of your geometry to plane geometry -- unless for some reason you want to. You can see how this can be handled in the Fiddles below.

Second, your problem is your UV settings.

Here is a Fiddle ( http://jsfiddle.net/PBjEE/ ) showing a problem similar to yours. I have used a simpler geometry, but like yours, the quad faces are trapezoids. In the Fiddle, I followed your approach of setting the UVs for each face to be the corners of the texture, (0,1), (0,0), (1,0), and (1,1). The result is a distorted circle.

Here is another Fiddle ( http://jsfiddle.net/PBjEE/1/ ) where the distortion is removed by changing the UV coordinates.

The UV coordinates must define a trapezoid having the same proportions as the face.

WestLangley
  • 102,557
  • 10
  • 276
  • 276
  • Ah. Now I see what he was referring to with trapezoid. My eyes totally ignored that distortion and focused on the top triangles :P – mrdoob Aug 27 '12 at 08:38
  • The circles are fine, but the texture is cropped: http://jsfiddle.net/noiv/3Spe3/ . Can't do this with e.g. Google Map tiles. https://mts1.google.com/vt/lyrs=m@183042665&x=129&y=95&z=8 – Torsten Becker Aug 28 '12 at 01:02
  • To be fair, your question was "What can be done to remove the distortion?" This is a solution to that problem. It seems you are adding new requirements now. Perhaps you can make a new post? – WestLangley Aug 28 '12 at 02:13
  • Keeping texture intact was not exactly a hidden requirement. But I'll prep a better fiddle and repost. Btw: your fiddle revealed already next question: How to set up lights? – Torsten Becker Aug 28 '12 at 09:13