6

I have been searching around and haven't found any really good answer to my question yet.. The thing is that I have this sphere.. just a basic sphere, and I want to flip the normals so the sphere gets the sort of "hollow/carved effect" and then plater on apply my textures to the "inside" of the sphere. any ideas of how to flip the normals?

Also.. if its not possible to do this in three.js.. would it be possible to import a model where the normals are already flipped and get the effect I'm looking for?

Inx
  • 2,364
  • 7
  • 38
  • 55
  • 7
    Try `material.side = THREE.BackSide` instead and see if the result is acceptable to you. – WestLangley Jan 30 '14 at 17:13
  • That could work I guess... any other ideas are most welcome as well :) I will try the above and ill get back with how it went – Inx Jan 30 '14 at 19:40
  • Tanks for The hela.. seems till have the desiered effect :-) – Inx Jan 31 '14 at 06:05

4 Answers4

22

This answer only applies to versions of three.js prior to r.125.

The Legacy Geometry class has been removed.


You can flip the normals in your geometry by reversing the winding order of your faces. You then have to fix UVs.

for ( var i = 0; i < geometry.faces.length; i ++ ) {

    var face = geometry.faces[ i ];
    var temp = face.a;
    face.a = face.c;
    face.c = temp;
    
}

geometry.computeFaceNormals();
geometry.computeVertexNormals();

var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
for ( var i = 0; i < faceVertexUvs.length; i ++ ) {

    var temp = faceVertexUvs[ i ][ 0 ];
    faceVertexUvs[ i ][ 0 ] = faceVertexUvs[ i ][ 2 ];
    faceVertexUvs[ i ][ 2 ] = temp;
    
}

However, you can get the same effect by simply setting Material.side = THREE.BackSide, or Material.side = THREE.DoubleSide.

In either case, your texture will be rendered flipped. You can either flip your texture before-hand, or build a model outside of three.js and import it.

three.js r.124

WestLangley
  • 102,557
  • 10
  • 276
  • 276
  • Well,it confuse me,using code above in a skybox,I have to set `side:THREE.FrontSide`,but the texture is still rendered flipped.With fliping the texture ,I get alias.So i have to build another BoxGeometry?Why BoxGeometry built from vertex will render it without flipping texture? – aboutqx Feb 24 '16 at 09:49
  • 1
    @aboutqx If you have a question, you need to ask it in a new post. – WestLangley Feb 24 '16 at 10:50
  • This solution is the way to get the ray caster to work. Ray caster only sees on side, doubleSide doesn't work. – arpo Jan 03 '17 at 09:27
  • @arpo Raycaster supports `THREE.DoubleSide` for meshes. – WestLangley Jan 03 '17 at 09:57
  • @westlangley Strange, I posted this a while ago, and I haven't got it working, have to try again. http://stackoverflow.com/questions/40864144/ray-casting-on-a-plane-geometry-only-works-from-on-direction – arpo Jan 03 '17 at 09:59
  • 1
    @WestLangley for the hundredth time your help save my life! Thank you! – atom Mar 04 '21 at 08:47
  • It's not worth it to make your mesh/CAD exporter to export with the "right" normals. Instead use the `Material.side = THREE.DoubleSide` as @WestLangley pointed out. This saved me a lot of trouble!! – Raphael Setin Jul 01 '21 at 20:31
  • Here's the code to unwind vertices with modern versions of THREE.js. Seems like unwinding vertices still has some niche use-cases like export to GLTF/GLB where BackSide is unsupported. ```for ( var i = 0; i < geometry.index.array.length-1; i=i +3 ) { var temp = skyGeo.index.array[i]; geometry.index.array[i] = skyGeo.index.array[i+2]; geometry.index.array[i+2] = temp; } ``` Longer explanation avail here: https://discourse.threejs.org/t/gltfexporter-ignores-material-side-1-backside/23766 This info should be added to answer (too many pending edits rn). – Llama D'Attore Aug 04 '23 at 01:11
4

When you are creating material for your sphere, specify {side:THREE.DoubleSide}. This will make faces visible from both sides.

You can also change it anytime after your material is created.

lot
  • 1,434
  • 18
  • 23
1

It is fixed !!

The flip of an object with a negative scale object.scale.x = -1 also reverse the normals since three.js r89 (see: Support reflection matrices. #12787).

(But I have to upgrade to r91 to solve my normal issue.)

Jérémie Boulay
  • 400
  • 4
  • 13
-2

Another way is to simply flip the normals manually by making your object's geometry dynamic.

mesh.geometry.dynamic = true
mesh.geometry.__dirtyVertices = true;
mesh.geometry.__dirtyNormals = true;

mesh.flipSided = true;

//flip every vertex normal in mesh by multiplying normal by -1
for(var i = 0; i<mesh.geometry.faces.length; i++) {
    mesh.geometry.faces[i].normal.x = -1*mesh.geometry.faces[i].normal.x;
    mesh.geometry.faces[i].normal.y = -1*mesh.geometry.faces[i].normal.y;
    mesh.geometry.faces[i].normal.z = -1*mesh.geometry.faces[i].normal.z;
}

mesh.geometry.computeVertexNormals();
mesh.geometry.computeFaceNormals();
Ali Hammoud
  • 325
  • 2
  • 12