THREEJS Sprite repeat texture - javascript

I've got a sprite and i'm trying to make the texture repeat over and over.
I think I have the right settings but it doesn't seem to be doing what I expect, am I doing something wrong?
Here's my result:
And this is my code:
var bgTexture = new THREE.TextureLoader().load('/bg.png');
var spriteMaterial = new THREE.SpriteMaterial({ map: bgTexture });
spriteMaterial.wrapS = spriteMaterial.wrapT = THREE.RepeatWrapping;
spriteMaterial.map.offset.set( 0, 0 );
spriteMaterial.map.repeat.set( 10, 1 );
var sprite = new THREE.Sprite(spriteMaterial);
sprite.position.y = 0;
sprite.position.y = 0;
sprite.scale.x = 10;
sprite.scale.y = 1;
this.scene.add(sprite);

The properties .wrapS and .wrapT have to be set to the Texture rather than the SpriteMaterial:
spriteMaterial.wrapS = spriteMaterial.wrapT = THREE.RepeatWrapping;
spriteMaterial.map.wrapS = spriteMaterial.map.wrapT = THREE.RepeatWrapping;

Related

How to save decal position with Three.js?

I'm looking for a way to store and reload the decals that produced in This example ( source-code), so when a user "paints" a new splatter - he could save it and later on - reloads it.
I've tried many ways but unfortunately none of them seems to work.
My approach was to save the position, rotation and scale and then build them like this :
function loadLeePerrySmith(callback) {
var loader = new THREE.JSONLoader();
loader.load('assets/LeePerrySmith.js', function (geometry) {
geometry.verticesNeedUpdate = true;
geometry.elementsNeedUpdate = true;
geometry.morphTargetsNeedUpdate = true;
geometry.uvsNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.colorsNeedUpdate = true;
geometry.tangentsNeedUpdate = true;
var material = new THREE.MeshPhongMaterial({
map: THREE.ImageUtils.loadTexture('assets/Map-COL.jpg'),
specularMap: THREE.ImageUtils.loadTexture('assets/Map-SPEC.jpg'),
normalMap: THREE.ImageUtils.loadTexture('assets/Map-NOR.jpg'),
shininess: 10
});
mesh = new THREE.Mesh(geometry, material);
// ALL FOLLOWING VECTORS SHOULD COME FROM D.B
var pos = new THREE.Vector3(0.18564199509178245, 23.11243036463454, 21.79273328636014);
var rot = new THREE.Vector3(-0.24357513937426453, -0.07708039421506024, 4.358263365975027);
var some = new THREE.Vector3(20.694949486021706, 20.694949486021706, 20.694949486021706);
var check = new THREE.Vector3(1, 1, 1);
var m = new THREE.Mesh(new THREE.DecalGeometry(mesh, pos, rot, some, check), decalMaterial);
scene.add(mesh);
decals.push(m);
scene.add(m);
mesh.scale.set(10, 10, 10);
});
}
Adding a simple timeOut did the trick
setTimeout(function(){
let m = new THREE.Mesh(new DecalGeometry(mesh, pos, rot,
size), decalMateria2);
decals.push(m);
scene.add(m);
},100)

ThreeCSG don't give expected result

I want to create a simple app in three.js
For this app, I need to subtract two meshes and I have found that ThreeCSG can do this. But somehow I don't get the expected result.
I have copied the code from an example, but even this doesn't work properly.
Trying some other function like the union. But instead of merging two meshes into one it removes it.
link to ThreeCSG: https://github.com/chandlerprall/ThreeCSG/blob/master/ThreeCSG.js
result that I get when subtracting
result that I get when I use union
var materialNormal = new THREE.MeshNormalMaterial( { side: THREE.DoubleSide } );
var diceCube = new THREE.Mesh( new THREE.BoxGeometry(10,10,10), materialNormal);
diceCube.position.x = 0;
diceCube.position.y = 5;
diceCube.position.z = 0;
diceCube.geometry.computeFaceNormals();
diceCube.geometry.computeVertexNormals();
var cubeBSP = new ThreeBSP(diceCube);
var sphereGeometry = new THREE.SphereGeometry(7.5,16,8);
var sphereMesh = new THREE.Mesh(sphereGeometry, materialNormal);
sphereMesh.scale.x = 0.17;
sphereMesh.scale.y = 0.17;
sphereMesh.scale.z = 0.17;
//coords of the spheres
var xPositions = [ 0, 3 ]; // coordinates for xPositions of sphereMesh
var yPositions = [ 10, 10 ];
var zPositions = [ 0, 0 ];
var diceDots = new THREE.Geometry();
for(var i = 0; i < xPositions.length; i++){
sphereMesh.position.x = xPositions[i];
sphereMesh.position.y = yPositions[i];
sphereMesh.position.z = zPositions[i];
sphereMesh.updateMatrix();
diceDots.merge( sphereMesh.geometry, sphereMesh.matrix );
}
var material = new THREE.MeshPhongMaterial( { color: 0xffaa00 });
var dotsMesh = new THREE.Mesh(diceDots);
dotsMesh.geometry.computeFaceNormals();
dotsMesh.geometry.computeVertexNormals();
var dotsBSP = new ThreeBSP(dotsMesh);
var resultBSP = cubeBSP.subtract(dotsBSP);
result = resultBSP.toMesh(material);
scene.add(result);
I have found a solution.
The threeCSG I used was corrupted this one works exactly how it must be done.
Link to working ThreeCSG: https://github.com/oathihs/ThreeCSG/blob/master/dist/THREE.CSG.js

Loading a random texture in three.js

Suppose I have 10 objects and I want for each object to be given a texture picked for me randomly out of a pool of 10 textures. How do I go about that for this mesh object?
for(var int = 0; int <= 10 ; int++)
{ var loader = new THREE.TextureLoader();
var testMat = new THREE.MeshPhongMaterial({ map: loader.load('images/image1') });
var testGeo = new THREE.SphereGeometry(50, 50, 50);
testSphere = new THREE.Mesh(testGeo, testMat);
testSphere.position.set(distance, 100, 100);
scene.add(testSphere); }
Assuming all of your texture-images are named in a numeric/sequential manner, you could do:
...
var testMat = new THREE.MeshPhongMaterial({ map: loader.load('images/image' + THREE.Math.randInt(1, 10) ) });
...
If not, then you'd make a list of filenames in a manner similar to this, and choose a random value from the list:
var texturesList = [
'images/image1',
'images/some-other-image',
'images/yet-another-image',
...
'images/10th-image'
];
...
...
var randIndex = THREE.Math.randInt(0, texturesList.length - 1);
var randTexture = loader.load(texturesList[randIndex]);
var testMat = new THREE.MeshPhongMaterial({ map: randTexture });
...

How to repeat a displacement map in three.js

In a three.js rendering, I have a small texture which I want to repeat multiple times. For this texture there is the map, a displacement map, a normal map, an ambient occlusion map and a specular map. As long as the repeating pattern is 1 in the x and 1 in the y direction, the image looks as expected. There is displacement where expected.
If the repeat values are greater than 1, all of the maps appear to scaled correctly except for the displacement map. The displacement map does not appear to be repeated. The displace is the same as shown in the previous image.
A code snippet for applying these maps to a plane follows:
///////////////////////////////////////////////
// add texture plane for a test
xRep = 1;
yRep = 1;
var loader = new THREE.TextureLoader();
var tex = loader.load('images/img.png');
tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
tex.repeat.set(xRep, yRep);
var nloader = new THREE.TextureLoader();
var ntex = loader.load('images/img-normal.png');
ntex.wrapS = ntex.wrapT = THREE.RepeatWrapping;
ntex.repeat.set(xRep, yRep);
var aloader = new THREE.TextureLoader();
var atex = aloader.load('images/img-ao.png');
atex.wrapS = atex.wrapT = THREE.RepeatWrapping;
atex.repeat.set(xRep, yRep);
var dloader = new THREE.TextureLoader();
var dtex = dloader.load('images/img-v003-disp.png');
dtex.wrapS = dtex.wrapT = THREE.RepeatWrapping;
dtex.repeat.set(xRep, yRep);
var sloader = new THREE.TextureLoader();
var stex = sloader.load('images/img-v003-spec.png');
stex.wrapS = stex.wrapT = THREE.RepeatWrapping;
stex.repeat.set(xRep, yRep);
var faceMaterial = new THREE.MeshPhongMaterial({
color: 0xa0a0a0,
shininess: 30,
//map : tex,
//bumpMap : tex,
//bumpScale : 1,
displacementMap: dtex,
displacementScale: 10,
normalMap: ntex,
//normalScale : (1,1),
aoMap: atex,
//aoMapIntensity : 1,
specularMap: stex
//_last: 0
});
face = new THREE.Mesh(new THREE.PlaneGeometry(50, 50, 256, 256),
faceMaterial);
face.position.z = 50;
face.receiveShadow = true;
face.castShadow = true;
scene.add(face);
How can this snippet be modified so the displacement map is repeated the same as the other maps?
Note: This issue appear to be related to the discussion at issue #7826 on Git hub.
You want your displacement map to repeat, but the displacement map does not honor the offset repeat value in the current version of three.js.
A work-around is to modify the UVs of your geometry.
Suppose you want the displacement map to be repeated 3 times. Then, multiply your UVs by 3.
Using PlaneBufferGeometry, follow this pattern to do so:
var uvs = geometry.attributes.uv.array;
for ( var i = 0; i < uvs.length; i ++ ) uvs[ i ] *= 3;
For the other textures, if you wanted to, you could compensate by scaling their repeat values accordingly:
texture.repeat.set( 1 / 3, 1 / 3 );
If you are changing the buffer geometry UVs after rendering at least once, you will need to set:
mesh.geometry.attributes.uv.needsUpdate = true;
Also, be sure to read this post.
three.js r.79

Why mesh created with ThreeBSP.js is not working properly with any material other than MeshNormalMaterial?

The dice looks like a dice only if I use MeshNormalMaterial in the second last line (result = resultBSP.toMesh(materialNormal);). With any other material it just looks like a cube with no subtraction (dots) on it. The ThreeBSP (ThreeCSG upgrade) library I am using is located here.
There is no problem with using the MeshNormalMaterial. It just doesn't have almost any options to modify it. (It doesn't take parameters like other materials).
Here is my function that I am using to create a dice:
function buildDice(){
var materialNormal = new THREE.MeshNormalMaterial();
var diceCube = new THREE.Mesh( new THREE.BoxGeometry(100,100,100), materialNormal);
diceCube.position.x = 0;
diceCube.position.y = 50;
diceCube.position.z = 0;
diceCube.geometry.computeFaceNormals();
diceCube.geometry.computeVertexNormals();
var cubeBSP = new ThreeBSP(diceCube);
var sphereGeometry = new THREE.SphereGeometry(75,16,8);
var sphereMesh = new THREE.Mesh(sphereGeometry, materialNormal);
sphereMesh.scale.x = 0.17;
sphereMesh.scale.y = 0.17;
sphereMesh.scale.z = 0.17;
//coords of the spheres
var xPositions = [....]; // coordinates for xPositions of sphereMesh
var yPositions = [....];
var zPositions = [....];
var diceDots = new THREE.Geometry();
for(var i = 0; i < xPositions.length; i++){
sphereMesh.position.x = xPositions[i];
sphereMesh.position.y = yPositions[i];
sphereMesh.position.z = zPositions[i];
THREE.GeometryUtils.merge(diceDots, sphereMesh);
}
var dotsMesh = new THREE.Mesh(diceDots, materialNormal);
dotsMesh.geometry.computeFaceNormals();
dotsMesh.geometry.computeVertexNormals();
var dotsBSP = new ThreeBSP(dotsMesh);
var resultBSP = cubeBSP.subtract(dotsBSP);
result = resultBSP.toMesh(materialNormal);
scene.add(result);
}
It does work with other Materials, for example with a THREE.MeshPhongMaterial. This jsfiddle using your buildDice()-function may help you:
http://jsfiddle.net/L0rdzbej/152/
You have to update the mesh´s matrix before merging the geometry, and best not to use deprecated functions for this.
Three.js r73

Categories