Skip to content
Advertisement

Three.js Materials are reversed depending on direction of view

I am using Three.js to model a home. The idea is that I can show the home to an architect and discuss it further. The project is supposed to be walkable, so I put together it all on this site. If you visit the site to view the code, use arrow keys to move horizontally relative to the grass, use W/S to move up/down, and A/D to yaw view.

https://bsdillon.github.io/cs200_Spring2020/ThreeJs/solarhouse.html

I was able to make panels (cubes actually) and put textures on them. Everything looks great except that the walls look different depending on the direction of view. See the image below. I added a red line and yellow triangle to help make the geometry more obvious. The image on the left shows the external view of a panel with a clapboard exterior and an open doorway on the left. The image on the right shows the same panel viewed from inside the structure. You can see that from inside the door is still on the left (it should appear on the right) and the stick frame interior also appears to be reversed.

enter image description here

I never noticed this before, but it appears to be the standard for the way I set up these panels. Apparently I’m doing something wrong. The question is how can I show the texture so that the views will be consistent.

var materialArray = new Object();//I set up an object I set up to store materials

function makeMaterial2(filename, repeatX, repeatY)//a method for creating materials from an image file
{
  var m = new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( filename ), transparent: true, opacity: 0.9, color: 0xffffff }); 
  return m;
}

//two examples of the material creation I implemented
materialArray["rDoor"] = makeMaterial2("doorRight.png",false,false);
materialArray["crDoor"] = makeMaterial2("doorRightClapboard.png",false,false);

function drawPanel2(x,y,z,x2,y2,z2,str)//this funciton creates a cube with the material in question
{
  var cubegeometry = new THREE.BoxGeometry(Math.abs(x-x2),Math.abs(y-y2),Math.abs(z-z2));
  var cube = new THREE.Mesh(cubegeometry, materialArray[str]);
  cube.position.set((x+x2)/2,(y+y2)/2,(z+z2)/2);
  return cube;
}

//adding the panels to the scene with the materials
scene.add(drawPanel2(-10,level,front,0,level+height,front,"rDoor"));
scene.add(drawPanel2(-10,level,front+margin,0,level+height,front+margin,"crDoor"));

Advertisement

Answer

You are using a simple BoxGeometry that has standard UV texture coodinates. A texture mapped on this geometry will look the same from all sides (see box example). However, you want that the open space of the door is at the same position. You could do one of the following to achieve that:

  1. Apply different materials and textures to different sides of the box. The 6 sides of BoxGeometry are already indexed for multi material usage.

    a) You’ll have to flip a texture in an image editing software and save it separately. Load these multiple textures.

    b) Clone the texture and set texture.wrapS = THREE.RepeatWrapping; texture.repeat.x = - 1; to flip it (How to flip a Three.js texture horizontally).

    Create an array of 6 materials each with its according texture and pass it to the Mesh.

  2. Change the UV texture coordinates of BoxGeometry, such that one side will show the texture flipped.

  3. Your boxes are flat. 4 sides aren’t visible. Instead of a BoxGeometry, you could also create a PlaneGeometry. Set material.side: THREE.DoubleSide such that the plane will be visible from both sides. Following this approach, you’ll have to rework your drawPanel2 method, because you can’t just flatten one side of the geometry, but you have to rotate the plane according the intended orientation of the panel.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement