I'm using TrackballControls to rotate the camera in my scene using the mouse but also need to be able to rotate individual objects in the scene using the mouse. I'd like to be able to toggle on/off TrackballControls to accomplish this. However, so far there are issues with everything I've tried. This is how my controls are defined:
var controls; // global
inside init():
controls = new THREE.TrackballControls( camera );
controls.addEventListener( 'change', render );
and finally in animate():
controls.update();
So far, I've tried:
Removing the event listener like this: controls.removeEventListener( 'change', render ); which didn't change anything; controls worked the same as it always has.
Conditionally updating the controls like this:
(global)
var enableControls = true;
(in animate)
if (enableControls == true) {
controls.update();
}
and then toggling enableControls using a KeyDown event. This seemed to work, because when enableControls was false I could rotate an object without moving the camera. However, when I update again, the camera moves significantly (it moves to where it would have been based on my clicking/dragging done while I wasn't updating).
I tried both of these separately and in conjunction with one another with no luck.
To disable TrackballControls, all you need to do is set
controls.enabled = false;
Also, you likely do not need controls.addEventListener( 'change', render ); since you are calling controls.update() in the animation loop.
three.js r.67
Related
Does anyone have a code to force orbit controls in three.js to move the scene on mousemove instead of click + mousemove I've tried using the answer in this thread:
How to recreate the Three.js OrbitControl movement on mouse move?
but sadly it throws an error "Maximum call stack size exceeded error" and I just get a black canvas with nothing in it...
I also tried changing
scope.domElement.addEventListener( 'mousedown', onMouseDown, false );
to
scope.domElement.addEventListener( 'mousemove', onMouseDown, false );
In the OrbitControls.js file but that seems to freeze when moving and stops every now and again...
Has anyone managed to solve this?
Thanks in advance!
How about this; https://jsfiddle.net/EthanHermsey/e3b501cw/51/
document.addEventListener('mousemove', function(e){
let scale = -0.01;
orbit.rotateY( e.movementX * scale );
orbit.rotateX( e.movementY * scale );
orbit.rotation.z = 0; //this is important to keep the camera level..
})
//the camera rotation pivot
orbit = new THREE.Object3D();
orbit.rotation.order = "YXZ"; //this is important to keep level, so Z should be the last axis to rotate in order...
orbit.position.copy( mesh.position );
scene.add(orbit );
//offset the camera and add it to the pivot
//you could adapt the code so that you can 'zoom' by changing the z value in camera.position in a mousewheel event..
let cameraDistance = 1;
camera.position.z = cameraDistance;
orbit.add( camera );
Use an Object3D that acts as a pivot for the camera. It rotates on mouse movement.
EDIT: I found my own answer but found a way. You can enable auto rotate with the mouse position, but you have to make OrbitControl's handleMouseMoveRotate public, by copying the function and setting it as this.handleMouseMoveRotate.
Then in setup you add an event listener and send the event to the controls.
document.body.addEventListener( 'mousemove', ( e )=>{
controls.handleMouseMoveRotate( e )
});
And make sure to set controls.enableRotate = false;
I am making an application very similar to what's on this shutterfly customization page, except more concise. I really like the preview, but I need guidance on how to rotate the object the way they do in their preview. Currently, I'm using THREE.OrbitControls(), but my object rolls out of view and the camera isn't focused on the actual object. I tried focusing on the object, but I get an error.
Edited to add: My object is a .ply file so I'm using PLYLoader.
I found this other perfect example of what I want to do that uses mouse events: https://jsfiddle.net/n6u6asza/1735/
It's clever, but I want to use three.js libraries instead of these mouse events because my object keeps disappearing when I remove the controls and if I can keep my code shorter, that'd be ideal. I've spent several hours reading about OrbitControls(), but nothing I've tried has kept the object focused so it seems I'm only rotating the object.
The control code:
controls = new THREE.OrbitControls( camera, renderer.domElement);
controls.minPolarAngle = toRadians(0); //was trying to limit the object
controls.maxPolarAngle = toRadians(45); //movement with these
controls.enablePan = false;
controls.enableZoom = false;
//controls.enabled = false;
controls.update();
I also have a basic animate function. I want to later implement auto rotate as a button option.
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
Just to recap, my question is:
How do I keep focus on an object when rotating the camera?
OR
How do I rotate the object without moving the camera?
Edited to add my object code:
var loader = new THREE.PLYLoader();
loader.load( 'sleeve.ply', function ( geometry ) {
geometry.computeVertexNormals();
var material = new THREE.MeshStandardMaterial( { color: 0xffffff } );
sleeve = new THREE.Mesh( geometry, material );
scene.add( sleeve );
});
To keep focus on an object you should use https://threejs.org/docs/#api/en/core/Object3D.lookAt
object.lookAt(x,y,z) or object.lookAt(vector);
For controls you should change the target https://threejs.org/docs/#examples/controls/OrbitControls.target
controls.target = object;
Or you can modify transform controls, if you want to rotate object and not rotate camera around object.
https://threejs.org/examples/?q=control#misc_controls_transform
I would like to recreate the Three.js OrbitControl movement without the click & drag, i.e. simply making the camera following mouse movement.
I tried to recreate it from scratch, but it was too much effort as the problem is that the camera moves on three axis, not just two. I'm pretty sure some has done before.
Specifically I would like the camera to move around the scene origin keeping the same distance from it.
I had the same requirement as OP. This is how I solved it, with help from Leeft's comments:
Update OrbitControls.js to change scope of function handleMouseMoveRotate from
function handleMouseMoveRotate( event )
to
this.handleMouseMoveRotate = function ( event )
This is required for you to manually use this method from within your own code.
In the JS code which loads the model, use the dispose method to remove the default mouse controls and add your own event handler for mousemove which manually calls handleMouseMoveRotate:
init();
animate();
function init() {
// Set up Camera, Scene and OrbitControls
camera = new THREE.PerspectiveCamera( 45, containerWidth / containerHeight );
scene = new THREE.Scene();
controls = new THREE.OrbitControls(camera);
// Remove default OrbitControls event listeners
controls.dispose();
controls.update();
... // omitted for brevity: Load model and Renderer
document.addEventListener('mousemove', onDocumentMouseMove, false);
}
function onDocumentMouseMove( event ) {
// Manually fire the event in OrbitControls
controls.handleMouseMoveRotate(event);
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
controls.update();
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
NOTE: this solution removes ALL library listeners. If you are interested you can enable them again copying them from here to the end of the update method.
I have a
function createControls(){ return new THREE.TrackballControls( camera,domElement );}
which is created with
THREE.TrackballControls=function(object, domElement){.....}
controls = createControls(camera, renderer.domElement);
restoreView(controls, vars);
addDefaultKeyEventListener();
and after resizing the webgl container the controls dont work correct..to be precise there is an event where when the user clicks on the screen a yellow ball moves to the exact place on a plain at the 3d space. After the resize event the ball moves at a spot which has a offset of that place i suppose related with the resized scale. When i try to redefine controls variable it crashes..
How can i update the controls having new camera and renderer.domElement input variables?
TrackballControls have a method for that : handleResize(). So if you create your controls with
controls=new THREE.TrackballControls(...);
You just have to add
controls.handleResize();
into the function called at the resize event.
I am preparing an application which shows a 3D model of a building and it works fine now. I was trying to control "PerspectiveCamera" using LookAt. However, I noticed LookAt does not work when I have the following line in animate function.
controls.update(1);
Therefore, I disabled this line (see below):
function animate(time) {
requestAnimationFrame( animate );
//controls.update(1);
TWEEN.update(time);
renderer.render( scene, camera );
}
However, I lose my mouse control (cannot zoom in/out) when I disable that line. If I enable that line , LookAt does not work properly.
Any suggestion? Thanks.
Just call camera.lookAt() in the animation loop if you're using the controls. That will get it to re-point to whatever you want to lookAt() after you've moved things around with the controls.