Three.js rotate boxes towards mouse position doens't work - javascript

I have several randomly generated boxes that I want to rotate towards the mouse position. I tried to get the mouse position and then use lookAt(mouse3D)to rotate the boxes towards the mouse coordinates, but they don't change their rotation at all. I don't even want them to rotate towards the mouse position within the 3D space, simply towards the mouse position as it is on the screen.
Currently I get the mouse position like this:
function onDocumentMouseMove( event ) {
mouse3D = new THREE.Vector3(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1,
camera.position.z );
}
Here's an example I found which I wasn't able to apply to my problem: http://mrdoob.github.io/three.js/examples/misc_lookat.html
I created JSFiddle with my current approach:
https://jsfiddle.net/nrub93m7/

I just added this method to your jsfiddle link:
function onDocumentMouseMove( event )
{
mouse3D = new THREE.Vector3( event.clientX, event.clientY, 0);
}

Related

Problem with click corner of fabricjs using threejs raycast

i'm trying to recreate this app, and it is currently working now. But i can't click the corner of the text perfectly, it always need to be offset.
https://jsfiddle.net/naonvl/ecdxfkbm/3/
right now, it's hard to scale the text. i think the getRealPosition is not correct so the mouse X and Y also not precise.
Does anyone know how to fix this?
The problem is i set getIntersects like this
var getIntersects = function (point, objects) {
mouse.set(point.x * 2 - 0.97, -(point.y * 2) + 0.97);
raycaster.setFromCamera(mouse, camera);
return raycaster.intersectObjects(objects);
};
compare to three.js example here https://threejs.org/examples/#webgl_raycast_texture
function getIntersects( point, objects ) {
mouse.set( ( point.x * 2 ) - 1, - ( point.y * 2 ) + 1 );
raycaster.setFromCamera( mouse, camera );
return raycaster.intersectObjects( objects, false );
}
i miss calculate the mouse.set there, i change the calculation and tweak X and Y position of mouse by adding 3 to each of them, and it raycasted perfectly in the center of mouse pointer

three.js first person camera rotation

I've looked for help of first player rotation on three.js for a while but most of the answers are outdated with functions which currently don't exist in the updated library.
I'm trying to make my code run so that the camera will rotate around it's own axis according to the position of the mouse on the screen.
The current rotation code is:
var scale = 10;
function viewKeys(){
document.addEventListener("mousemove", MouseMove, true);
function MouseMove(event) {
mouseX = event.clientX - divOffsetWidth;
mouseY = event.clientY - divOffsetHeight;
}
}
divOffset variables make the mouse positions read relative to the center of the HTML div.
function viewAnimate(){
camera.rotation.x = -((3/2)*(Math.PI*mouseY)) / (scale);
camera.rotation.y = -(2*(Math.PI*mouseX)) / (scale);
}
The viewKeys() function is called in the init() function and the viewAnimate() function is called within the animate() function.
Currently the code can rotate normally when the camera's position is (0,0,0) but if I move to a different position it looks as if the camera is rotating relative to the whole environment's axis.
I am aware that there are lots of control librarys for three.js but I would like to understand how to be able to rotate something on its own axis myself.
How do you suppose I change the rotation so that it works correctly?
If you want to rotate the camera yourself via the mouse, you will have to understand how Euler rotations work in three.js. See this answer.
One way to implement what you want is by using a pattern like so:
var scale = 1;
var mouseX = 0;
var mouseY = 0;
camera.rotation.order = "YXZ"; // this is not the default
document.addEventListener( "mousemove", mouseMove, false );
function mouseMove( event ) {
mouseX = - ( event.clientX / renderer.domElement.clientWidth ) * 2 + 1;
mouseY = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
camera.rotation.x = mouseY / scale;
camera.rotation.y = mouseX / scale;
}
I agree with you that experimenting with this would be a good learning experience.
three.js r.89

Threejs object selection issue

Im currently working on an small web-application which is using threejs. I ran into the following issue:
I build a prototype which contains my threejs content and everything works well here (The canvas is in the prototype window.innerWidth and window.innerHeight => so has the same size as my Browser window. Selecting works well but I want to use the canvas on my web page application and picking of 3d surfaces needs to work as well there.
I discovered as soon as I change the margin or top via CSS of the canvas it doesn't work anymore. The web-application is based on a scroll page and the threejs canvas is inside a div container which can only be seen by scrolling through the page.
For picking I use the following logic/code -> this one works well in the "fullscreen prototype" but not in the web application page
self.renderer.domElement.addEventListener( 'click', function(event){
event.preventDefault();
//CONVERT MOUSE POSITION TO CORRECT VECTOR
var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
//TRANSLATES A 2D POINT FROM Normalized Device Coordinates TO RAYCASTER THAT CAN BE USED FOR PICKING
self.projector.unprojectVector( vector, self.camera );
//RAYCASTER IS NEEDED TO DETECT INTERACTION WITH CUBE SURFACE
var raycaster = new THREE.Raycaster( self.camera.position, vector.sub( self.camera.position ).normalize() );
var intersects = raycaster.intersectObjects( self.scene.children );
//CHANGE COLOR BASED ON INTERSECTION WITH ELEMENT
if ( intersects.length > 0 ) {
//SELECTED OBJECT
}
}, false );
I think that the calculation is wrong for the var vector but I just can't figure it out how to do it correctly.
Any help would be appreciated
Thank you
best reards
200% way
var x = event.offsetX == undefined ? event.layerX : event.offsetX;
var y = event.offsetY == undefined ? event.layerY : event.offsetY;
var vector = new THREE.Vector3();
vector.set( ( x / renderer.domElement.width ) * 2 - 1, - ( y / renderer.domElement.height ) * 2 + 1, 0.5 );
projector.unprojectVector( vector, camera );
Or see this example. Look at messages in the console.
<script src="js/controls/EventsControls.js"></script>
EventsControls = new EventsControls( camera, renderer.domElement );
EventsControls.draggable = false;
EventsControls.onclick = function() {
console.log( this.focused.name );
}
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
EventsControls.attach( mesh );
//
function render() {
EventsControls.update();
controls.update();
renderer.render(scene, camera);
}
If you want to use it in your webpage, you probably need to calculate the vector with the width and height from your canvas element instead of the window which is your whole browser window.

Three.js Click and Drag - Object Lagging Behind Pointer

I've created a near exact implementation of the Three.js Draggable Cubes example, except that my implementation ignores the z axis for movement in 2D. The example can be found here: http://threejs.org/examples/#webgl_interactive_draggablecubes
While I am able to click and move around my object, if I move the mouse too fast, the object will lag behind; the mouse pointer will move to it's location and then the object will follow the mouses path to the location. This issue is also noticeable in the Three.js example. Try dragging one of the cubes at anything beyond a moderate speed.
I've tried a few things to get the object to be directly under the mouse pointer but none have worked. The closest I think I might have come to a solution was by changing the mouse position update in the MouseMove event. However, it appears that the Three.js implementation of the code returns values between 1 and -1 rather than the screen X and Y coordinates, which leads me to wonder if the original implementation is causing the lag.
//Original Implementation - Works With Lag
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
console.log(mouse.x + "," + mouse.y); //Output: -0.9729166666666667,0.8596858638743455
//My Implementation - Does Not Work
mouse.x = event.clientX - (window.innerWidth / 2);
mouse.y = event.clientY - (window.innerHeight / 2);
console.log(mouse.x + "," + mouse.y); //Output: -934,-410.5
//Update Function
void Update()
{
var vector = new THREE.Vector3(mouse.x, mouse.y, 1);
projector.unprojectVector(vector, camera);
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObject(plane);
meshToMove.position.x = intersects[0].point.x;
meshToMove.position.y = intersects[0].point.y;
}
//Main Loop
function Loop()
{
Update();
Render();
requestAnimationFrame(Loop);
}
Q: How can I update the three.js Draggable Cubes example so that objects don't lag behind the mouse during a click and drag?

three js camera movement to point

I'm actually working on a website using three.js. You can see a demo here: https://c9.io/frescogusto/demi/workspace/demi_0.3.html
It's on canvas to be viewable on ios and android.
Question is: how do I move the camera from its position to the position of the object that has been clicked? Do I have to use translate method on every axis or there is a faster way?
thanks in advance
pp
renderer.domElement.addEventListener('mousedown', function(event) {
event.preventDefault();
var vector = new THREE.Vector3(
renderer.devicePixelRatio * (event.pageX - this.offsetLeft) / this.width * 2 - 1,
- renderer.devicePixelRatio * (event.pageY - this.offsetTop) / this.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(YOUR_CLICKABLE_OBJECTS);
if (intersects.length) {
camera.position = intersects[0].point;
// Alternatively, camera.position = intersects[0].object.position.clone();
}
}, false);
This code:
Registers a listener on the mousedown event
Projects the clicked location in 2D screen space into a location in 3D scene space
Casts an imaginary line (a ray) from the camera towards the click
Checks whether any objects intersect with that line; the first object to intersect is the one that was clicked
Snaps the camera to the clicked position
If you'd rather transition the camera slowly to the clicked location instead of snapping it there immediately, you may want to look into a tweening library like TweenJS to help you with the timing of the transition.
(P.S.: I think renderer.devicePixelRatio is only present for the WebGL renderer. You can just remove it for other renderers.)

Categories

Resources