Issue accessing object on mouseover in THREE.js - javascript

I am working with the threex domevents by Jeromeetienne: https://github.com/jeromeetienne/threex.domevents to handle my hover over of rendered in objects in my canvas
I am having some issue when updating the perspective view when the user changes the type of object, my dom sets the event listener but it seems to never get called. Here is the overview:
When user first loads the page, we set our camera:
// setup local vars
var camera = new THREE.PerspectiveCamera(40,window.innerWidth / window.innerHeight,1,10000);
camera.position.set(500, 800, 1300);// 1st = swing (left or right) 2nd = up or down 3rd = zoom
camera.lookAt( new THREE.Vector3());
camera.positionID = 1;// default
camera.positionType = 'sideView';// default
this.cam = camera;
Than we set our renderer:
renderer = new THREE.CanvasRenderer();
renderer.setClearColor( 0xf0f0f0 );
renderer.setSize( window.innerWidth, window.innerHeight );
Now when a user clicks the canvas, an object is added. We first get our positioning and call a intersectofobjects to see if we are actually on the canvas (mousedown):
event.preventDefault();
this.mouse.x = ( event.clientX / this.renderer.domElement.width ) * 2 - 1;
this.mouse.y = - ( event.clientY / this.renderer.domElement.height ) * 2 + 1;
this.raycaster.setFromCamera( this.mouse, this.camera.cam );
var intersects = this.raycaster.intersectObjects( this.blocks );
After we actually figure out that we are on the plane, we setup our object:
var voxel = new THREE.Mesh( this.room.cubeGeometry.clone(), this.room.cubeMaterial.clone() );
voxel.geometry.computeBoundingBox();
voxel.position.copy( intersect.point ).add( intersect.face.normal );
voxel.position.divideScalar( this.room.divideScalar ).floor().multiplyScalar( this.room.multiplyScalar ).addScalar( this.room.addScalar );
After we setup our object we setup the event listeners on the object
// get our dom event to attach to object
var domEvents = new THREEx.DomEvents(this.camera.cam, this.renderer.domElement);
// DOM events for inside 3d rendering
domEvents.addEventListener(voxel, 'mouseover', this.onDocumentMouseOverCube.bind(this),false);
domEvents.addEventListener(voxel, 'mouseout', this.onDocumentMouseOutCube.bind(this),false);
this.scene.add( voxel );
this.blocks.push( voxel );
this.rooms.push(voxel);
this.render();
This works perfect on first use. It only seems to stop working when the user changes the object that they want to place on the screen, here is how.
We have a gui object that handles our connection with the UI and the core, when someone chooses to add a different object, we call:
jQuery(".changeRoomType.active").removeClass('active');
jQuery(event.srcElement).toggleClass('active');
this.canvas.room.updateRoomType(event.srcElement.id);
Now when room.updateRoomType...() is called it initiates an object like this:
var cubeGeometry = new THREE.BoxGeometry( 100, 50, 100,2,1,2 );// moving to roomObj
var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff80,overdraw: 1 } ); // moving to roomObj
var cubeTmpHoverMaterial = new THREE.MeshLambertMaterial({ color: 0x00ff80, transparent: true, overdraw: 0, opacity:0.5});// used to give a transparency to the cube tmp view // moving to roomObj
var divideScalar = 50;
var multiplyScalar = 50;
var addScalar = 25;
var additionalZ = 25;
var additionalX = 25;
this.divideScalar = divideScalar;
this.multiplyScalar = multiplyScalar;
this.addScalar = addScalar;
var colorNormal = 0x00ff80;
var colorHover = 0xE4E4E4;
var colorTmpHover = 0xEAEAEA;
var colorRemove = 0xE23434;
this.colorNormal = colorNormal;
this.colorHover = colorHover;
this.colorTmpHover = colorTmpHover;
this.colorRemove = colorRemove;
this.additionalZ = additionalZ;
this.additionalX = additionalX;
this.cubeGeometry = cubeGeometry;
this.cubeMaterial = cubeMaterial;
this.cubeTmpHoverMaterial = cubeTmpHoverMaterial;
Now after this point the mouseover and mouseout on the object seem to never work anymore. My question is why is this? Am I not updating my camera perspective after changing the object type to be displayed?
EDIT:
Please note that our initiated object that is first selected on page load is the following:
var cubeGeometry = new THREE.BoxGeometry( 50, 50, 50,1,1,1 );// moving to roomObj
var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff80, overdraw: 1 } ); // moving to roomObj
var cubeTmpHoverMaterial = new THREE.MeshLambertMaterial({ color: 0x00ff80, transparent: true, overdraw: 0,opacity:0.5});// used to give a transparency to the cube tmp view // moving to roomObj
var divideScalar = 50;
var multiplyScalar = 50;
var addScalar = 25;
var additionalZ = 0;
var additionalX = 0;
this.additionalZ = additionalZ;
this.additionalX = additionalX;
var colorNormal = 0x00ff80;
var colorHover = 0xE4E4E4;
var colorTmpHover = 0xEAEAEA;
var colorRemove = 0xE23434;
this.colorNormal = colorNormal;
this.colorHover = colorHover;
this.colorTmpHover = colorTmpHover;
this.colorRemove = colorRemove;
this.cubeGeometry = cubeGeometry;
this.cubeMaterial = cubeMaterial;
this.cubeTmpHoverMaterial = cubeTmpHoverMaterial;
The other object that was called above shown in the original question demonstrates our other object size. After this is called it seems to stop recognizing the location of our mouseover and mouseout on the object and or its being placed on someplace else it should not be.

Related

Why is my canvas element showing only a black screen?

I'm setting up a 3d asset viewer in Three.js. I'm running the code on a Plesk server provided by the university and have it linked via Dreamweaver. I'm a total newbie to JS and it was suggested in many threads and posts that I wrap my code within an 'init();' function. Up doing so, and clearing any errors that the code had, it is now showing a black screen, rather than the 3d model it would show before.
I've spent the whole day error checking removing problems that I was having which included the 'canvas' not being created inside the 'container' div, and the 'onWindowResize' function. All these problems have been resolved, and there are no errors in the code apparently. I've got ambient lights in the code and there was a working skybox, so I'm sure its not a problem with position of camera or lack of lighting.
I know that you need as little code as possible, but I have no idea where the problem is coming from, so a majority of the code on the page is here :
<div id="container" ></div>
<script>
let container;
let camera;
let controls;
let scene;
let renderer;
init();
animate;
function init(){
// Renderer - WebGL is primary Renderer for Three.JS
var renderer = new THREE.WebGLRenderer({antialias : true});
renderer.setClearColor(0xEEEEEE, 0.5);
// Selects and applies parameters to the 'Container' div
var container = document.querySelector("#container");
container.appendChild(renderer.domElement);
renderer.setSize(container.clientWidth, container.clientHeight);
// Perspective Camera (FOV, aspect ratio based on container, near, far)
var camera = new THREE.PerspectiveCamera( 75, container.clientWidth / container.clientHeight, 0.1, 1000);
camera.position.x = 750;
camera.position.y = 500;
camera.position.z = 1250;
// Scene will contain all objects in the world
var scene = new THREE.Scene();
//Lighting (Colour, intensity)
var light1Ambient = new THREE.AmbientLight(0xffffff , 0.3);
scene.add(light1Ambient);
var light1Point = new THREE.PointLight(0xfff2c1, 0.5, 0, 2);
scene.add(light1Point);
var light2Point = new THREE.PointLight(0xd6e3ff, 0.4, 0, 2);
scene.add(light2Point);
// All basic Geomety
var newPlane = new THREE.PlaneGeometry(250,250,100,100);
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial( {color: 0x00ff00} )
);
scene.add(mesh);
// Water
water = new THREE.Water(newPlane,
{
textureWidth: 512,
textureHeight: 512,
waterNormals: new THREE.TextureLoader().load( 'http://up826703.ct.port.ac.uk/CTPRO/textures/waternormals.jpg', function ( texture ) {
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
} ),
alpha: 1.0,
sunDirection: light1Point.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 0.5,
fog: scene.fog !== undefined
}
);
water.rotation.x = - Math.PI / 2;
scene.add( water );
// All Materials (Normal for Debugging) (Lambert: color)
var material = new THREE.MeshLambertMaterial({color: 0xF3FFE2});
var materialNew = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
// Skybox
var skybox = new THREE.BoxGeometry(1000,1000, 1000);
var skyboxMaterials =
[
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_ft.jpg"), side: THREE.DoubleSide }),
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_bk.jpg"), side: THREE.DoubleSide }),
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_up.jpg"), side: THREE.DoubleSide }),
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_dn.jpg"), side: THREE.DoubleSide }),
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_rt.jpg"), side: THREE.DoubleSide }),
new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_lf.jpg"), side: THREE.DoubleSide }),
];
var skyboxMaterial = new THREE.MeshFaceMaterial(skyboxMaterials);
var skyMesh = new THREE.Mesh (skybox, skyboxMaterial);
scene.add(skyMesh);
//Grid Helper Beneath Ship
scene.add(new THREE.GridHelper(250, 250));
//OBJ Model Loading
var objLoader = new THREE.OBJLoader();
objLoader.load('http://up826703.ct.port.ac.uk/CTPRO/models/ship1.obj', function(object){
scene.add(object);
});
// Object positioning
water.position.y = -2.5;
// Misc Positioning
light1Point.position.z =20;
light1Point.position.x = 25;
// z - front-back position
light2Point.position.z = -400;
// x - left-right
light2Point.position.x = -25;
// y - up- down
light2Point.position.y = 250;
window.addEventListener("resize", onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(container.clientWidth, container.clientHeight);
};
};
// Canvas adapts size based on changing windows size
//Render loop
var animate = function(){
water.material.uniforms[ "time" ].value += 1.0 / 120.0;
function drawFrame(ts){
var center = new THREE.Vector2(0,0);
window.requestAnimationFrame(drawFrame);
var vLength = newPlane.geometry.vertices.length;
for (var i = 0; i < vLength; i++) {
var v = newPlane.geometry.vertices[i];
var dist = new THREE.Vector2(v.x, v.y).sub(center);
var size = 2.0;
var magnitude = 8;
v.z = Math.sin(dist.length()/-size + (ts/900)) * magnitude;
}
newPlane.geometry.verticesNeedUpdate = true;
};
requestAnimationFrame(animate)
renderer.render(scene, camera);
controls.update();
}
</script>
I'm no professional, so I'm sorry if this is super rough for those of you with experience!
I need to point out, before wrapping all of this in the init(); function, it was working perfectly.
When working, I should see a crudely modeled ship sitting in some water, with a cloud skybox. The controls were working and it would auto rotate.
Right now it does none of this. The obj loader is working as seen in the chrome console log OBJLoader: 1661.970703125ms but again, nothing is actually displayed, it's just a black screen.
Thanks to anyone who's able to help me out with this!
this line
animate;
needs to a function call
animate();
Also you probably need to change the code below where you create the animate function from
var animate = function(){
To this
function animate(){
The reason is named functions are defined when the code is loaded but variables var are created when the code is executed. So with code like this
init();
animate();
var animate = function(){ ...
animate doesn't actually exist at the point the code tries to call it whereas with this
init();
animate();
function animate(){ ...
it does exist
You could also re-arrange the code so for example define animate before you use it should work.
var animate = function(){
...
};
init();
animate();
It also appear some are declared inside init which means that are not available to animate. So for example
var renderer = new THREE.WebGLRenderer({antialias : true});
declares a new variable renderer that only init can see. You wanted to set the renderer variable that is outside of init so change the code to
renderer = new THREE.WebGLRenderer({antialias : true});
controls is never defined so you probably need to define it or comment out
controls.update();
to
// controls.update();
note: you might find these tutorials helpful although if you're new to JavaScript you should probably spend time learning JavaScript

Rotation around object using Three.js hierarchy (THREE.Group())

So I have the following javascript code:
var group = new THREE.Group();
var staffGeometry = new THREE.BoxGeometry(0.5, 6, 0.5);
var staffMaterial = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var staffCube = new THREE.Mesh( staffGeometry, staffMaterial );
staffCube.position.x = -21;
staffCube.position.y = 1;
staffCube.position.z = -19;
group.add(staffCube);
//scene.add( staffCube );
var geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 );
var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
var torusKnot = new THREE.Mesh( geometry, material );
torusKnot.position.x = -21;
torusKnot.position.y = 4.8;
torusKnot.position.z = -19;
torusKnot.scale.set(0.08, 0.08, 0.08);
group.add(torusKnot);
//scene.add( torusKnot );
var ballGeometry1 = new THREE.IcosahedronGeometry(0.5);
var ballMaterial1 = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var ball1 = new THREE.Mesh(ballGeometry1, ballMaterial1);
ball1.position.x = -22.5;
ball1.position.y = 4.5;
ball1.position.z = -20.5;
group.add(ball1);
//scene.add(ball1);
var ballGeometry2 = new THREE.IcosahedronGeometry(0.5);
var ballMaterial2 = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var ball2 = new THREE.Mesh(ballGeometry2, ballMaterial2);
ball2.position.x = -22;
ball2.position.y = 6.5;
ball2.position.z = -20;
group.add(ball2);
//scene.add(ball2);
scene.add(group);
The THREE.Group() was an attempt to utilize hierarchy. I can't seem to find ANY useful examples or documentation on THREE.Group so not even sure if I'm using hierarchy correctly. My goal was to set the staff in place, and make it easier to do stuff with the other components through hierarchy.
Mainly, I want ball1 and ball2 to circle around the staff. I am not sure how to access them within the group so that they can use taurusKnots location (head of staff) to translate to, rotate on taurusKnots Y, then translate back.
Any help on utilizing hierarchy with three.js to achieve this would be awesome! Like I said, all I can find online are people saying to use Group() for hierarchy, but nothing is said or can be found (by me at least) on how to access members and actually utilize the hierarchy you establish.

Bounding Box of a stl object in three.js

Good day everyone,
I have come across several posts about this topic but no solution would work. I have an object that I load with the help of the STLLoader in three.js for which I would like to get a bounding box.
// Add stl objects and a name
function addSTLObject(url, name) {
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
scene.add(mesh);
});
}
and I am loading this object as follows:
addSTLObject('model/cases/iphone5.stl', 'phone-model');
var phoneModelAdded = scene.getObjectByName('phone-model', true);
Now I have tried the solutions provided here: https://github.com/mrdoob/three.js/issues/3471 and here Any way to get a bounding box from a three.js Object3D?
var bbox = new THREE.Box3().setFromObject(phoneModelAdded);
var geometry = phoneModel.children[0].children[0].geometry;
geometry.computeBoundingBox();
While the first solution gives me an error saying "Cannot read property 'updateMatrixWorld' of undefined", the second gives me no error at all but does nothing and if I try accessing the "geometry" property it says that it doesn't exist.
Does someone have a working solution?
Any help is appreciated.
Have a good day!
EDIT:
// Add stl objects and a name
function addSTLObject(url, name) {
var bbox;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
bbox = new THREE.Box3().setFromObject(mesh);
scene.add(mesh);
return bbox;
});
}
and aftwards
var bbox = addSTLObject('model/cases/iphone5.stl', 'phone-model');
scene.add(bbox);
Error: "THREE.Object3D.add: object not an instance of THREE.Object3D"
EDIT 2:
var bbox, bboxComputed = false;
function addSTLObject(url, name) {
var bbox;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
bbox = new THREE.BoundingBoxHelper(mesh);
bbox.update();
bboxComputed = true;
scene.add(mesh);
});
}
addSTLObject('model/cases/iphone5.stl', 'phone-model');
var myInterval = setInterval( function(){
if( bboxComputed ) {
alert( bbox.box.min, bbox.box.max, bbox.box.size() );
scene.add(bbox);
clearInterval( myInterval );
bboxComputed = false;
}
}, 100 );
This won't work.
EDIT 3:
I was trying to set up a function that would have everything I need and give back an object with all of the calculated information:
function calculateSTLProperties(url, name) {
var STLObject, STLbbox, STLComputed = false, STLGeometry;
var loader = new THREE.STLLoader();
loader.load(url, function (geometry) {
var material = new THREE.MeshPhongMaterial({ color: 0xff5533 });
var mesh = new THREE.Mesh(geometry, material);
// To scale element, use:
// mesh.scale.set(0.01, 0.01, 0.01);
// Add a name to the object to find it if it needs to be removed
mesh.name = name;
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
// Compute a bounding box for the element
STLbbox = new THREE.BoundingBoxHelper(mesh);
STLbbox.update();
// Get the geometry of the case
STLGeometry = geometry;
STLComputed = true;
});
// Set an interval to wait for the corresponding bounding box and geometry to be computed
var myInterval = setInterval( function(){
if( STLComputed ) {
STLObject = {
"geometry" : STLGeometry,
"bbox" : STLbbox,
"x" : STLbbox.box.size().x,
"y" : STLbbox.box.size().y,
"z" : STLbbox.box.size().z
};
clearInterval( myInterval );
bboxComputed = false;
}
}, 100 );
return STLObject;
}
Unfortunately, somehow the object doesn't get passed through and I end up with an "undefined" in the end when trying to save it:
var STLObjectLoaded = calculateSTLProperties('model/cases/iphone5.stl', 'phone-model');
console.log(STLObjectLoaded);
What am I missing?
Model loading is asynchronous so all you computations should happen after the model has loaded. Add a callback, which is called when the model has loaded and add there the call to the bbox. The way you have it the scene.getObjectByName() call is being made with an empty object which you also verify ("if I try accessing the "geometry" property it says that it doesn't exist")
Update:
Use:
var bbox = new THREE.BoundingBoxHelper( mesh ); bbox.update();
scene.add( bbox );
from inside the loader.load() function.
The setFromObject() call only create the bounding box but not the geometry for the bbox.
Update II
If you want the bbox to be available outside your loader.load() function you would need to use a global variable
var bboxComputed = false;
which you set to true right after you compute the bbox inside your loader.load() function:
scene.add( bbox );
bboxComputed = true;
Then in your main instead of using:
console.log( bbox.box.min, bbox.box.max, bbox.box.size() );
you would use something like:
var myInterval = setInterval( function(){
if( bboxComputed ) {
console.log( bbox.box.min, bbox.box.max, bbox.box.size() );
clearInterval( myInterval );
}
}, 100 );
I am setting a delay of 0.1 second and when the bbox has finally been computed I clear the interval so that it does not run forever.
As of three.js R125, the recommended way to do this is with the loadAsync method, which is now native to three.js:
https://threejs.org/docs/#api/en/loaders/Loader.loadAsync
That method returns a promise. You could then use a 'then' to get the geometry of the STL and create the mesh. You could also use a traditional callback as in earlier answers, or an async/await structure, but I think the example below using the native three.js method is the simplest way. The example shows how you can get geometry to a global variable once the promise is resolved and the STL file is loaded:
// Global variables for bounding boxes
let bbox;
const loader = new STLLoader();
const promise = loader.loadAsync('model1.stl');
promise.then(function ( geometry ) {
const material = new THREE.MeshPhongMaterial();
const mesh = new THREE.Mesh( geometry, material );
mesh.geometry.computeBoundingBox();
bbox = mesh.geometry.boundingBox;
scene.add( mesh );
buildScene();
console.log('STL file loaded!');
}).catch(failureCallback);
function failureCallback(){
console.log('Could not load STL file!');
}
function buildScene() {
console.log('STL file is loaded, so now build the scene');
// !VA bounding box of the STL mesh accessible now
console.log(bbox);
// Build the rest of your scene...
}

three.js - cloning textures and onLoad

My goal is to create a cube/box with a single texture but different repeat values for each of the sides. Working code is below:
var cubeMaker = function(w,h,d, tName)
{
var g = new THREE.CubeGeometry( 50*w, 50*h, 50*d );
var tx = THREE.ImageUtils.loadTexture( tName );
var ty = THREE.ImageUtils.loadTexture( tName );
var tz = THREE.ImageUtils.loadTexture( tName );
tx.wrapS = tx.wrapT = THREE.RepeatWrapping;
ty.wrapS = ty.wrapT = THREE.RepeatWrapping;
tz.wrapS = tz.wrapT = THREE.RepeatWrapping;
tx.repeat.set(d,h);
ty.repeat.set(w,d);
tz.repeat.set(w,h);
var mx = new THREE.MeshBasicMaterial( {map: tx} );
var my = new THREE.MeshBasicMaterial( {map: ty} );
var mz = new THREE.MeshBasicMaterial( {map: tz} );
var mArray = [mx,mx,my,my,mz,mz];
var m6 = new THREE.MeshFaceMaterial( mArray );
var cube = new THREE.Mesh(g, m6);
return cube;
}
However, it seems wasteful to load the texture three times. Earlier, I instead tried passing a texture as an argument to the function (instead of a string representing the filename), as follows:
var cubeMaker = function(w,h,d, texture)
{
...
var tx = texture.clone();
var ty = texture.clone();
var tz = texture.clone();
...
but then the textures didn't appear in the scene, only solid black images appeared in their place. My best guess is that the texture image hadn't finished loading before the clone methods were called, and perhaps some kind of null value was copied instead. Is there some way to use an onLoad method to wait long enough so that the clone function works as intended?
Note: I have tried the suggestion from Can't clone() Texture but it does not solve my issue.
Thanks for any assistance!
Load your texture once, and move the rest of your code into the loader callback function. You also have to set the needsUpdate flag to true when you clone your texture.
var tx = THREE.ImageUtils.loadTexture( tName, undefined, function() {
var ty = tx.clone();
ty.needsUpdate = true; // important!
var tz = tx.clone();
tz.needsUpdate = true; // important!
tx.wrapS = tx.wrapT = THREE.RepeatWrapping;
ty.wrapS = ty.wrapT = THREE.RepeatWrapping;
tz.wrapS = tz.wrapT = THREE.RepeatWrapping;
tx.repeat.set( 1, 1 );
ty.repeat.set( 2, 1 );
tz.repeat.set( 2, 2 );
var mx = new THREE.MeshBasicMaterial( { map: tx } );
var my = new THREE.MeshBasicMaterial( { map: ty } );
var mz = new THREE.MeshBasicMaterial( { map: tz } );
var mArray = [ mx, mx, my, my, mz, mz ];
var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( mArray ) );
scene.add( mesh );
} );
Why don't you create then your texture outside of your function and just use this texture inside of your function, assigning it to special variable for each side? That way for sure you are going to load it just once.

Three.js - Edit plane geometry

So, I want to make a simple terrain editor. So, on mouseDown, I want the selected face to move up.
The intersection works great, and I try to modify the geometry like so:
var intersects2 = ray.intersectObjects([plane]);
if (intersects2.length > 0) {
var face = intersects2[0].face;
var obj1 = intersects2[0].object;
var geo = obj1.geometry;
geo.vertices[face.a].z += 50;
geo.vertices[100].z += 50;
geo.vertices[0].z += 50;
geo.computeVertexNormals();
geo.computeFaceNormals();
geo.__dirtyVertices = true;
geo.__dirtyNormals = true;
console.log(face.a);
}
The console log shows the correct vertex index, but nothing on the plane moves. Any ideas why?
The plane is created like this:
var planegeo = new THREE.PlaneGeometry( 500, 500, 10, 10 );
planegeo.dynamic = true;
plane = new THREE.Mesh( planegeo, new THREE.MeshPhongMaterial( { color: 0x99ff66 } ) );
plane.receiveShadow = true;
scene.add( plane );
Looking at your code, it looks like you are using syntax pre R49. It may just be that you need to update your dirty flag code to (assuming you are now using a newer library!):
geo.verticesNeedUpdate = true;
geo.normalsNeedUpdate = true;

Categories

Resources