When using textures in OpenGL (ThreeJS uses this via WebGL), its important that you properly set the UV parameters on your faces.
These UV parameters tell how to morph and transform an 2d texture into 3d space.
Lets see the UV parameters on our simple box model (new THREE.BoxGeometry()
):
[[
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}]
]]
This looks scary
To understand these coordinates, you have to understand that our box is made up of 12 "faces", or triangles in this case, 2 triangles per side.
Interesting things happen when we modify 1 of the coordinates in the UV grid:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 3,3,3 );
var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
new THREE.TextureLoader().load( "https://threejs.org/examples/textures/uv_grid_opengl.jpg", (texture) => {
material.map = texture;
renderer.render( scene, camera );
});
geometry.faceVertexUvs =
[[
[{"x":0,"y":1},{"x":0,"y":-1},{"x":2,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
[{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
[{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}]
]]
var cube = new THREE.Mesh( geometry, material );
cube.rotation.x = Math.PI / 3
cube.rotation.y = 0
cube.rotation.z = Math.PI / 3
scene.add( cube );
camera.position.z = 5;
body { margin: 0; font-size: 0; }
canvas { width: 100%; height: 100% }
<script src="https://threejs.org/build/three.js"></script>
Notice how the texture shifts? This is how UV coordinates help you apply a 2d texture to any 3d surface. (Try to also play around with Texture.wrapS)
The problem
At the moment, inside your code, you are loading your objects from an external source, most likely an OBJ file (based on the fact that you are using an ObjectLoader), and since an MAT file was not present, there is no information present about the properties of the materials.
This means that the objects you are trying to render to screen, don't have any "texture coordinates", and we need to "provide" this information in some way.
While its possible to hand craft this data, this isn't always so saleable, so we have to fallback to another alternative, generating this data based on the position of the item.
Generating UV coordinates is a complex topic, as there are many different mappings for this, and I recommend you find and use one of the solutions at "THREE.js generate UV coordinate - StackOverflow" for this.