Three.js mouse picking, 3D model with OBJMTLLoader - three.js

i started programing with Three.js. Now i have a problem, when i load an Object with the OBJMTLLoader i dont get any access to change the position of the object with mouseMove. I have pushed the obects into the objects array but it doesnt work. If anybody could help or knowes a good tutorial would be really fine. I hope the structure how i wrote the question is clear....its the first time i´m using stacko.
These are my variables and the function i try to change the objects:
var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
var objects = [];
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera(mouse,camera);
intersects = raycaster.intersectObjects(objects);
if (intersects.length> 0) {
intersects[0].object.position.set(5, 5 ,5);
}
}
Here i load the object with the OBJMTLLoader....this works:)
var loader = new THREE.OBJMTLLoader();
loader.load('models/sofa4.obj', 'models/sofa4.mtl', function(object) {
// console.log(object);
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
child.material.shininess = 0;
// console.log(child.material);
}
});
object.position.z = 2;
object.position.y = -5.95;
object.scale.set(0.05,0.05,0.05);
scene.add(object);
objects.push(object);
});

Related

Determine the object that was clicked in three.js

I wish to detect when an object has been clicked. I am generating a page from the three.js editor. It is a brilliant environment.
Following the advice from this post (https://mandemeskel.wordpress.com/2013/08/19/mouse-events-raycasting-with-three-js/) I ended up with the following code. I have placed a comment where I am having a problem.
function mousedown( event ) {
var scene = this.parent;
var projector = new THREE.Projector();
var mouse_vector = new THREE.Vector3(),
mouse = { x: 0, y: 0, z: 1 },
ray = new THREE.Raycaster( new THREE.Vector3(0,0,0), new THREE.Vector3(0,0,0) ),
intersects = [];
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
mouse_vector.set( mouse.x, mouse.y, mouse.z );
// How do I get the camera?
projector.unprojectVector( mouse_vector, camera );
var direction = mouse_vector.sub( camera.position ).normalize();
ray.set( camera.position, direction );
var object = scene.getObjectByProperty( 'uuid', this.uuid, true );
intersects = ray.intersectObject( object );
if( intersects.length ) {
alert( "hit" );
event.preventDefault();
}
}
I have temporarily fixed the problem by modifying app.js in the published page. By moving the camera variable to be global I got around it, but it is obviously a fudge. Is there any way to access the camera generated by the editor without modifying app.js?
var camera;
var APP = {
Player: function () {
....
The awesome mrdoob has modified the editor to include a getCamera() call
https://github.com/mrdoob/three.js/issues/7510#issuecomment-153059247
The default camera can now be accessed by
var camera = player.getCamera();

How to store Model loaded by ColladaLoader in Three.js?

Since the Three.js migration (r68 -> r69) the ColladaLoader returns a Scene instead of an Object3D. How can I get the loaded Object3D now? I want store the loaded Object in a var to use it everytime.
var newpos = Cube.position;
var oLoader = new THREE.ColladaLoader();
oLoader.load('models/logo.dae',
function(collada)
{
var object = collada.scene;
var skin = collada.skins[0];
object.rotation.x = -Math.PI / 2;
object.rotation.z = Math.PI / 2;
object.position.x = newpos.x;
object.position.y = newpos.y+1.85;
object.position.z = newpos.z;
object.scale.set(0.75, 0.75, 0.75);
object.updateMatrix();
scene.add(object);
},
function ( xhr ) {
// console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
}
);
The ColladaLoader returns a scene because the loaded Model is'nt created as a 3DObject. The ColladaLoader creates a new scene added to your scene including the loaded .dae-Model. (Now it returns a group) That's because not every Model is just one Object. Check the childs of the dae.scene that you loaded, it helps a lot.

three.js orthographic camera object picking

i am trying to pick objects in a scene where i use an orthographic camera.
my code fragment already works, but it is not precise.
i already found some answers on stackoverflow, but those are deprecated or won't work anymore at all.
here is my code onMouseDown
function onDocumentMouseUp( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
var pos = camera.position;
var ray = new THREE.Raycaster(pos, vector.unproject(camera).sub(camera.position).normalize());
var intersects = ray.intersectObjects(objects);
if (intersects.length > 0) {
console.log("touched:" + intersects[0]);
}
else {
console.log("not touched");
}
}
please see http://jsfiddle.net/ujzpe07t/1/
if you click some pixels away left/right/above/below the cube, it still tells me that the object was touched.
i am using three.js r69.
any hints would be very much appreciated.
thanks, cheers!
Here is the pattern to use when raycasting (picking) with either an orthographic camera or a perspective camera:
var raycaster = new THREE.Raycaster(); // create once
var mouse = new THREE.Vector2(); // create once
...
mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( objects, recursiveFlag );
three.js r.84

Picking Object3D loaded via OBJMTLLoader

When we load an Object3D with OBJMTLLoader, it is not possible to use raycaster to pick this object with mouse. Intersection array length is always 0. Any one knows the reason? Below is the code...
The loader routine
var loader2 = new THREE.OBJMTLLoader();
loader2.load('/assets/unwrap/masa/dogtasmasa.obj', '/assets/unwrap/masa/dogtasmasa.mtl', function (object) {
object.position.y = 1.5;
object.position.x = 0;
object.position.z = 2;
object.rotateX(-Math.PI / 2);
object.rotateZ(-Math.PI / 2);
object.scale.set(0.04, 0.04, 0.04);
object.castShadow = true;
scene.add(object);
});
and the picking
function onDocumentMouseDown(event) {
event.preventDefault();
SCREEN_WIDTH = window.innerWidth - 5;
SCREEN_HEIGHT = window.innerHeight - 5;
var vector = new THREE.Vector3((event.clientX / SCREEN_WIDTH) * 2 - 1, -(event.clientY / SCREEN_HEIGHT) * 2 + 1, 0.5);
projector.unprojectVector(vector, camera);
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
for (var i = 0; i < intersects.length; i++) {
var obj = intersects[i].object;
controls.enabled = false;
tControls.attach();
}
}
else {
controls.enabled = true;
tControls.detach();
}
}
The scene is the whole browser window. Any other mesh cerated via THREE types can be picked, but object3d not...
Thanks for all kinds of help
Add the recursive flag like so:
var intersects = raycaster.intersectObjects( objects, true );
three.js r.66

Three js How to move scene

I would like to move the container (which contains my 3d objects)
Could you tell me how?
I am using Three JS
THREE.DragControls = function(camera, scene, domElement) {
this.childs = [];
this.childOffsets = [];
if (scene instanceof THREE.Scene) {
childs = scene.children;
scene = scene.children;
}
var _projector = new THREE.Projector();
var mouse = new THREE.Vector3();
var offset = new THREE.Vector3();
var selected;
domElement.addEventListener('mousemove', onDocumentMouseMove, false);
domElement.addEventListener('mousedown', onDocumentMouseDown, false);
domElement.addEventListener('mouseup', onDocumentMouseUp, false);
function onDocumentMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / domElement.width) * 2 - 1;
mouse.y = -(event.clientY / domElement.height) * 2 + 1;
var ray = _projector.pickingRay(mouse, camera);
if (selected) {
var targetPos = ray.ray.direction.clone().multiplyScalar(selected.distance).add(ray.ray.origin);
selected.object.position.copy(targetPos.sub(offset));
return;
}
var intersects = ray.intersectObjects(scene);
if (intersects.length > 0) {
domElement.style.cursor = 'pointer';
} else {
domElement.style.cursor = 'auto';
}
}
function onDocumentMouseDown(event) {
event.preventDefault();
mouse.x = (event.clientX / domElement.width) * 2 - 1;
mouse.y = -(event.clientY / domElement.height) * 2 + 1;
var ray = _projector.pickingRay(mouse, camera);
var intersects = ray.intersectObjects(scene);
if (intersects.length > 0) {
selected = intersects[0];
offset.copy(selected.point).sub(selected.object.position);
domElement.style.cursor = 'move';
}
}
function onDocumentMouseUp(event) {
event.preventDefault();
if (selected) {
selected = null;
}
domElement.style.cursor = 'auto';
}
}
If I understand correctly you would like to MOVE all 3D Objects within a scene?
The way I did that is to create a THREE.Group(). E.g.
var holder = new THREE.Group();
Then add all models/lights/etc to that holder group. Then add the holder to the scene.
var scene = new THREE.Scene();
holder.add(model);
scene.add(holder);
Then moving the holder would move all objects added to it.
I think you are asking for moving you're scene container which maybe a canvas or a dom element if that's the case you can apply drag and drop to your container which is rendering your scene.
Reference below :
https://www.google.com/url?sa=t&source=web&rct=j&url=https://konvajs.org/docs/drag_and_drop/Drag_and_Drop.html&ved=2ahUKEwjOscW6zpj1AhXSEXAKHb21Bz8QFnoECAYQAQ&usg=AOvVaw2aV1F114SqLcBDVL8BiN0Q

Resources