Texture on dynamically created object

Hi!
I have a code, following by this topic: ( Click ).

My code:

	function addObject3D( Object )
	{
		var AllFaces = new THREE.Group();
		for(var f=0; f < Object.Faces.length; f++)
		{
			var points = [];
			Object.Faces[f].Vertices3D.forEach(r => {
				points.push(new THREE.Vector3(r.x, r.y, r.z));
			});

			var tri = new THREE.Triangle(points[2], points[1], points[0]);
			var normal = new THREE.Vector3();
			tri.getNormal(normal);

			var baseNormal = new THREE.Vector3(0, 0, 1);
			var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, baseNormal);

			var tempPoints = [];
			points.forEach(p => {
				tempPoints.push(p.clone().applyQuaternion(quaternion));
			})

			var shape = new THREE.Shape(tempPoints);
			var shapeGeom = new THREE.ShapeGeometry(shape);

			var Texture = new THREE.TextureLoader().load( 'graphic/3D/wood2.jpg' );
			var Material = new THREE.MeshBasicMaterial( { map: Texture } );
			Material.side = THREE.DoubleSide;

			var mesh = new THREE.Mesh( shapeGeom, Material ) ;

			mesh.geometry.vertices = points;

			AllFaces.add(mesh);
		}
		
		return AllFaces;
	}

And it’s work fine, when I use THREE.MeshBasicMaterial, but when I try to use a texture, the object has a solid color.
How to fix it?
How to use a texture on object created by vertices?

Thanks :wink:

This line should not be necessary. Does it work when you remove it? If not, please try to provide a live demo with your code.

Without this line, the resulting shape will be at the plane, parallel to XY-plane.

The idea is, using a quaternion, put points to a plane, parallel to XY-plane, build a shape and a geometry of THREE.ShapeGeometry() and apply original points, as we have a set of faces, we just use old points instead of current ones in the geometry.

There are UVs for the shape from the fiddle:
Shape_UVs

And there’s no surprise why:

1 Like

I wrote a short code to fix this thing:

var box = new THREE.Box3().setFromObject(mesh);
var size = new THREE.Vector3();
box.getSize(size)
mesh.geometry.faceVertexUvs[0].forEach(fvUvs => {
  fvUvs.forEach(fvUv => {
    fvUv.x = (fvUv.x - box.min.x) / size.x;
    fvUv.y = 1 - (fvUv.y - box.min.y) / size.y;
  });
});

https://jsfiddle.net/prisoner849/k0vg5ore/
I’m not sure though, how correct that approach is, but, at least, it works :slight_smile:

2 Likes

There 2D object in 3D space (by Vertices) - #11 by hofk I wrote:
It seems that non-complanar points also work. Only uv’s missing!

Now they are available! Thanks to prisoner849.:+1:t2:

2 Likes

It work’s!
Thank you again! :smiley:

Hey, Im also trying to apply a texture on a ShapeGeometry. The shape is flat on the y axes, y = 0. When I run the following code, the shape gets white because of the color change, but there is no texture showing, but it is there.

 public setFloorTexture(texture: string) {

        if(texture == null) return

        var box = new THREE.Box3().setFromObject(this.floor);
        var size = new THREE.Vector3();
        box.getSize(size)

        this.floor.geometry['faceVertexUvs'][0].forEach(fvUvs => {
          fvUvs.forEach(fvUv => {
            fvUv.x = (fvUv.x - box.min.x) / size.x;
            fvUv.y = 1 - (fvUv.y - box.min.y) / size.y;
          });
        });

        TextureManager.instance.load(Globals.PATH + texture, (tex)=> {

            tex.anisotropy = Color.anisotropy

            tex.wrapS = THREE.RepeatWrapping
            tex.wrapT = THREE.RepeatWrapping
            tex.repeat.set(4, 4)
            tex.encoding = THREE.sRGBEncoding

            this.floor.material['map'] = tex

            this.floor.material['color'] = new THREE.Color(0xFFFFFF)
        })
    }

Here is a version for THREE.ShapeBufferGeometry():
https://jsfiddle.net/prisoner849/yn2z0e1w/

изображение

4 Likes

@prisoner849
I am using THREE.ExtrudeGeometry some how manage to add texture but the frequency of the texture is not constant is changing according to the area of shape

Is there any way to make it constant ?

Please see the difference in ground floor and first floor

Use a custom UV generator, that you can pass as a property in the object of extrude settings.

https://jsfiddle.net/prisoner849/39tbpgo1/

изображение

At least that generateTopUV function:

 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
    
    var box = new THREE.Box3().setFromArray(vertices);
    var size = new THREE.Vector3();
    box.getSize(size);
    
	var a_x = vertices[ indexA * 3 ];
	var a_y = vertices[ indexA * 3 + 1 ];
	var b_x = vertices[ indexB * 3 ];
	var b_y = vertices[ indexB * 3 + 1 ];
	var c_x = vertices[ indexC * 3 ];
	var c_y = vertices[ indexC * 3 + 1 ];

	return [
		new THREE.Vector2( (a_x - box.min.x) / size.x, (a_y - box.min.y) / size.y ),
		new THREE.Vector2(  (b_x - box.min.x) / size.x, (b_y - box.min.y) / size.y ),
		new THREE.Vector2(  (c_x - box.min.x) / size.x, (c_y - box.min.y) / size.y )
	];

}

And use the same concept with THREE.Box3() in generateSideWallUV, if you want :slight_smile:

1 Like

@prisoner849
Still getting the same issue
or even something more odd

@abdulqadir Well, you know better what and how in your code works.

@abdulqadir I’ve often seen especially new users who struggle with the build-in geometry generators like ExtrudeGeometry. If you need vertex data which can’t be generated by default, I highly suggest you use a tool like Blender to author your models if possible. Otherwise you have to invest a certain amount of time to better understand how vertex data like texture coordinates can be generated.

1 Like

I agree with @Mugen87.

It is not easy at first to generate such data correctly. But I myself was just interested in it and it is possible with some commitment. The exercise does it then.

An example for such calculations in my addon
Addon to create special / extended geometries
see e.g.
https://github.com/hofk/THREEg.js/blob/42dfd7a44ea6a327e0164466ad7c04f14b4c9a12/THREEg.js from line 435, 1779 …

see also
https://hofk.de/main/threejs/sandboxthreeg/
https://github.com/hofk/THREEg.js
https://hofk.de/main/threejs/sandboxthreeg/MagicSphereTHREEg.html