Rotate camera around object vs rotate object around its center - performance

I would like to create an object into the center of a scene (there is nothing else) in three.js and I need controls. I am not want to use Orbit or Trackball controls.
So the question is which way is more performance: rotate the camera around the object or rotate the object?

In general, and I don't really need to say this, fewer operations yields better performance.
For your simple example​ case...
If you have a camera, a light, and a single object, then moving the object will be faster. Even if you parent the light to the camera, there would be more matrix operations to move the camera/light.
But that's where it ends.
If you have more objects than you do camera+lights, then it's better to rotate the camera and lights around the object(s). This is the approach used by most controls (including TrackballControls and OrbitControls) because you almost always have more scene objects than cameras+lights.
Recommendation: Unless you're never going to use your control for scenes with more than one object, rotate the camera around the objects. Just watch out for gimbal lock.

Related

Can't get Three.js camera up direction

I need to get the camera up direction and i've tried many ways with no luck, i'm not an expert of quaternions so i'm doubting i did it right.
I've tried:
camera.up
camera.up.applyMatrix4(camera.matrixWorld);
new THREE.Vertex3(0,1,0).applyMatrix4(camera.matrixWorld);
camera.up.normalize().applyMatrix4(camera.matrixWorld);
after this i create two planes passing by two points of my interest, and add the plane helper to the scene and i can see they are very far from where i was expecting them. (i'm expecting two planes that looks like the top and bottom of the camera frustum).
P.s. the camera is a shadow camera of a directional light so an orthographic camera, and i manipulate the directional light position and target before doing this operation, but i've called updateMatrixWorld on the light, on it's target and the camera, on the camera i've called also updateProjectionMatrix... still no results
I've made a sandbox to see what i've tried till now, and better visualize what i want to achieve:
https://codesandbox.io/embed/throbbing-cache-j5yse
once i manage to get the green arrow to point to the top of the blue triangle of the camera helper i'm good to go
In the normal render flow, shadow camera matrices are updated as part of rendering the shadow map (WebGLShadowMap.render).
However, if you want the updated matrix values before the render, then you'll need to update them manually (you already understand this part).
The shadow camera is a property of (not a child of) the DirectionalLight. As such, it doesn't follow the same rules as other scene objects when it comes to updating its matrices (because it's not really a child of the scene). Instead, you need to call the shadow property's updateMatrices method (inherited from LightShadow.updateMatrices).
const dl = new THREE.DirectionalLight(0xffffff, 1)
dl.shadow.updateMatrices(dl) // <<------------------------ Updates the shadow camera
This updates the shadow camera with information from the DirectionalLight's own matrix, and its target's matrix, to properly orient the shadow camera.
Finally, it looks like you're trying to get the "world up" of the camera. Personally, I'd use the convenience function localToWorld:
let up = new THREE.Vector3(0, 1, 0)
dl.shadow.camera.localToWorld(up) // destructively converts "up" from local-to-camera into world coordinates
via trial and errors i've figured out that what gave me the correct result was:
calling
directionalLight.shadow.updateMatrices(...)
and then
new THREE.Vector3(0,1,0).applyQuaternion(directionalLight.shadow.camera.quaternion)

How to prevent culling or simply redraw on iTowns globe rotation outside of mouse, touch or key events?

I'm attempting to rotate the "globe" in iTowns in real time by adding a frame requester (in three.js this would be the requestAnimationFrame loop).
I am attempting to use iTowns to provide a real time 3D earth map simulation. As part of this I have an interval firing every second and playhead controls to manipulate time. I'm trying to rotate an earth representation along the z-axis because in iTowns that is the polar axis. I need to check the time every frame because I can calculate the earth rotation in radians/sec quite easily and as I manipulate the playhead to speed up time I can get a fluidly rotating earth. Also I'm utilizing the default Ortho layer provided in iTowns to add a geographic layer on top of the blue marble default.
// this.view is an iTowns/src/Core/Prefab/GlobeView
const globeLayer = this.view.getLayerById("globe");
const globe = globeLayer.object3d;
this.view.addFrameRequester(MAIN_LOOP_EVENTS.UPDATE_START, () => {
globe.rotation.z = ConversionUtils.toRadians(this.globals.getSceneRotation());
});
The globe rotates, however I believe iTowns is performing some sort of culling of the map tiles/globe. What happens is at some point as the earth rotation is taking place a portion of the globe no longer renders. If this was related to the Ortho layer I believe the blue marble would still show. We have another version of the application without any iTowns and we can rotate a Three.js SphereGeometry without any culling using the same mechanics; so I am 99% sure it is not an issue with Three.js unless iTowns is doing something I don't see.
How do I prevent the culling, which I see is documented as an optimization? Better yet, how can I tell it to redraw properly?
I've tried the following but to no apparent effect:
this.view.notifyChange(globeLayer, true);
this.view.notifyChange(undefined, true);
this.view.notifyChange(this.view.controls.camera, true);
globe.updateMatrixWorld(true);
There is "culling" logic in:
- iTowns/src/Core/Prefab/GlobeLayer.js
- iTowns/src/Layer/TiledGeometryLayer.js
This is invoked from iTowns/src/Core/MainLoop.js. Bubbling up to the method scheduleViewUpdate which is invoked on iTowns/src/Core/View.js notifyChange.
Further digging leads me to believe iTowns/src/Controls/GlobeControls.js, specifically the cameraTarget attribute that I can't manipulate, is either the answer or is related.
I am hoping I am missing something and there is a way to code this up. Alternatively, I realize the suggestion may be fork or PR iTowns.
It is worth noting I do not want to change the camera position, just rotate the globe because there are other objects also moving in the scene i.e. satellites in orbit.

Is possible to avoid the perspective distorsion on a 3D object in a scene with threejs?

I have a scene with some 3d Objects when you drag the scene objects look stretched. See the image
I know that this is the normal behavior But I have a client with this weird requirement, that the objects should move but without the distortion on the shape.
Is there way to do that?
That’s due to the camets fov. You can change it through the camera component

Is it possible to rotate an object with TrackballControls?

Is it possible to rotate an object – instead of the camera – with TrackballControls?
http://threejs.org/examples/js/controls/TrackballControls.js
Three.js introduced the Controls so you could easily maneuver with the camera around in the space. Controls are used for camera, like TrackballControls, FPSControls... They make moving with camera and pivoting a lot easier and they are almost automatically updated, so no need for hand-coded calculations.
If you wish to transform the object, then you should use rotation and position properties of the object, along with the lookAt(THREE.Vector3 point) and similar.
Hope this helps.

Working with Three.js

Context: trying to take THREE.js and use it to display conic sections.
Method: creating a mesh of vertices and then connect face4's to all of them. Used two faces to produce a front and back side so that when the conic section rotates it won't matter from which angle the camera views it.
Problems encountered: 1. Trying to find a good way to create a intuitive mouse rotation scheme. If you think in spherical coordinates, then it feels like just making up/down change phi and left/right change phi would work. But that requires that you can move the camera. As far as I can tell, there is no way to change actively change the rotation of anything besides the objects. Does anyone know how to change the rotation of the camera or scene? 2. Is there a way to graph functions that is better than creating a mesh? If the mesh has many points then it is too slow, and if the mesh has few points then you cannot easily make out the shape of the conic sections.
Any sort of help would be most excellent.
I'm still starting to learn Three.js, so I'm not sure about the second part of your question.
For the first part, to change the camera, there is a very good way, which could also include zooming and moving the scene: the trackball camera.
For the exact code and how to use it, you can view:
https://github.com/mrdoob/three.js/blob/master/examples/webgl_trackballcamera_earth.html
At the botton of this page (http://mrdoob.com/122/Threejs) you can see the example in action (the globe in the third row from the bottom).
There is an orbit control script for the three.js camera.
I'm not sure if I understand the rotation bit. You do want to rotate an object, but you are correct, the rotation is relative.
When you rotate or move your camera, a matrix is calculated for that position/rotation, and it does indeed rotate the scene while keeping the camera static.
This is irrelevant though, because you work in model/world space, and you position your camera in it, the engine takes care of the rotations under the hood.
What you probably want is to set up an object, hook up your rotation with spherical coordinates, and link your camera as a child to this object. The translation along the cameras Z axis relative to the object should mimic your dolly (zoom is FOV change).
You can rotate the camera by changing its position. See the code I pasted here: https://gamedev.stackexchange.com/questions/79219/three-js-camera-turning-leftside-right
As others are saying OrbitControls.js is an intuitive way for users to manage the camera.
I tackled many of the same issues when building formulatoy.net. I used Morphing Geometries since I found mapping 3d math functions to a UV surface to require v little code and it allowed an easy way to implement different coordinate systems (Cartesian, spherical, cylindrical).
You could use particles instead of a mesh I suppose but a mesh seems best. The lattice material is not too useful if you're trying to understand a surface mathematically. At this point I'm thinking of drawing my own X,Y lines on the surface (or phi, theta lines etc) to better demonstrate cross-sections.
Hope that helps.
You can use trackball controls by which you can zoom in and out of an object,rotate the object,pan it.In trackball controls you are moving the camera around the object.Object still rotates with respect to the screen or renderer centre (0,0,0).

Resources