2

I have been looking for a way to add uv-mapping to my custom geometry in three.js. I have found ways of doing it but none of the solutions I have found work. Could anyone explain how uv-mapping works and how to do it properly?

var s = 100;
var MapHeight = function(x, y, mult){
    var map = new Array(x);
    for(var i = 0; i < x; i++){
        map[i] = new Array(y);
        for (var j = 0; j < y; j++) {
            map[i][j] = Math.sin((i*12+j)/10)*mult;
        }
    }
    return map;
};
var heightMap = MapHeight(s, s, 0.3);
var loader = new THREE.TextureLoader();
var sandTex = loader.load("Textures/sand.jpeg");
var div = 2;
var Sand = function(color){
    var geo = new THREE.Geometry();
    var i;
    for (i = 0; i < s; i++) {
        for (var j = 0; j < s; j++) {
            geo.vertices.push(new THREE.Vector3(i/div, heightMap[i][j], j/div));
        }
    }
    for (i = 0; i < (s)*(s-1); i++) {
        if (!Number.isInteger((i+1)/s)){
            geo.faces.push(new THREE.Face3(i, i+1, i+s+1));
            geo.faces.push(new THREE.Face3(i, i+s+1, i+s));
        }
    }
    geo.computeVertexNormals();
    geo.computeFaceNormals();
    geo.center();
    var mesh = new THREE.Mesh(
        geo,
        new THREE.MeshStandardMaterial({map: map})
    );
    return mesh;
};

Right now when I try adding UV-mapping to my geometry, the result is either a black material or my program doesn't run.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174

1 Answers1

3

The texture coordinates have to be add per face, to the 1st layer UV layer.
See THREE.Geometry.faceVertexUvs

Create and array at the UV layer:

geo.faceVertexUvs[0] = [];

And add an array of 3 THREE.Vector2 for each triangle face:

geo.faceVertexUvs[0].push([
    new THREE.Vector2(u0, v1),
    new THREE.Vector2(u1, v1),
    new THREE.Vector2(u2, v2)
]);

Apply this to your code as follows:

var geo = new THREE.Geometry();
var i;
var uv = [];
for (i = 0; i < s; i++) {
    for (var j = 0; j < s; j++) {
        geo.vertices.push(new THREE.Vector3(i/div, heightMap[i][j], j/div));
        uv.push(new THREE.Vector2((i-1)/s, (j-1)/s));
    }
}

geo.faceVertexUvs[0] = [];
for (i = 0; i < (s)*(s-1); i++) {
    if (!Number.isInteger((i+1)/s)){

        var vi = [i, i+1, i+s+1, i+s];

        geo.faces.push(new THREE.Face3(vi[0], vi[1], vi[2]));
        geo.faces.push(new THREE.Face3(vi[0], vi[2], vi[3]));

        geo.faceVertexUvs[0].push([ uv[vi[0]], uv[vi[1]], uv[vi[2]] ]);
        geo.faceVertexUvs[0].push([ uv[vi[0]], uv[vi[2]], uv[vi[3]] ]);
    }
}
geo.computeVertexNormals();
geo.computeFaceNormals();
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Thanks for the answer, my texture appears on my custom geometry. But the texture appears blurry – Argentum Manus Apr 05 '19 at 20:53
  • @ArgentumManus I can't see your textures. This is a new aspect and an extends your initial question. Texture have the [.minFilter](https://threejs.org/docs/#api/en/textures/Texture.minFilter) and [.magFilter](https://threejs.org/docs/#api/en/textures/Texture.magFilter) property. How do you create the textures? – Rabbid76 Apr 05 '19 at 21:09