I have given up trying to orbit a camera around my scene in Three.js and have now decided to revert to doing what I used to do in XNA, just rotate everything except the camera.
The reason I have given up is because I cannot get the camera to orbit properly 360 degrees in all the axis, it starts inverting after going over the top or under the bottom. Using THREE.OrbitControls does not solve this because it merely restricts rotation in the problematic axis instead of fixing the problem.
My problem is now getting this other rotation story working. What I have done is put all objects except the camera in another object "rotSection" and I am now just rotating that object. This is working but rotation is always performed according to the relative (0, 0, 0) position of the rotation object which seems to always stay in the one corner but I would like to rotate around the centre of my world on not around the edge. I have tried to centre the rotSection relative to the scene but it still rotates around its corner and not its centre. Any idea how I can get rotation of an Object3D around a certain point?
The engines don’t move the ship at all. The ship stays where it is and
the engines move the universe around it.
Futurama
The camera in 3d technically never rotates, everything else is rotated and move in order to bring it to camera's local space. You don't have to do any tricks in order to do this, this should be the core of the 3d engine, setting the matrices, setting up the shaders, and doing the correct transforms. Three.js does this for you.
Perhaps you should look into quaternions? Specifically the axisAngle conversion to quats. THREE.OrbitControls won't do what you want.
Related
Is it possible to turn off sizeAttenuation for an Object3D in THREE.js?
I ask because I'm drawing a trajectory on a very large scale using arrow helper to indicate the direction of motion, and I want the heads of the arrows to stay oriented correctly (unlike using a pointcloud w/ sprite points), but also not shrink/grow as you zoom the camera.
Any other ideas? Can I achieve the same effect using a pointcloud/lines?
sizeAttenuation is just rescaling the sprite based on it's position to give a sense of a "virtual size". Object3D's have an actual size so they scale with perspective.
Outside of switching to an Orthographic Camera (might not be ideal for everything else you're doing), the only things that come to mind are
position the arrow closer to the camera always, so it doesn't change size
constantly adjust the scale of the arrow to make it larger/smaller in the scene, so it appears to be the same size on the screen.
I have a scene with many Object3D objects containing blocks, cylinders and meshes. I also have a perspective camera and use trackballcontrols. What I need is a way to set the camera position without modifying the FOV or the camera angle and insure that all objects in the scene are visible on screen. I have successfully done this with preset top, bottom, left and right views using the bounding box of the entire scene, but I need this to work from any camera angle since the user can rotate the view using trackball controls into any position.
If there were a way to get a 2d bounding rectangle based on the camera position, target and the list of objects, I think I could get it to work, but I am having trouble finding how to do this.
The functionality would work like this: With a scene containing many objects, the user rotates the camera with the mouse to some arbitrary position and then clicks a "Zoom All" button. Then, the camera is zoomed(moved) out or in(keeping FOV constant) to make all objects fit to the screen.
How about rotate and translate the whole szene, so that the camera lies on an axis looking at the origin.
From there get the bounding box, calculate the needed distance for the camera and translate the camera.
Then rotate and translate the whole szene back.
Say I have a nice spaceship rendered in my scene. I then zoom out and the ship becomes smaller. This is all quite simple to achieve. Now at some point I want to replace the spaceship object with a simple triangle representing the ship. At this stage the icon for the ship should be rendered instead of the ship. Obviously the triangle should move based on the ship's movement and my camera movements. The triangle should not change orientation, so even if I rotate the camera or have the ship roll the triangle should stay the same orientation. So on a canvas this would be very simple to do. I would just take the x and y components of the 3d object and draw my triangle at the coordinates. My problem is that I do not know how to draw on the WebGL canvas directly? Is it possible? If not do anybody have any pointers to strategies to get this done? I would be happy if I could get nudged in the right direction :) Thanks in advance.
Update : What I eventually decided to do was to use the orthographic camera overlay approach suggested below and in a couple of other places.
Use Sprite object for icon. Then place icon right between spaceship and camera in a specific distance from the camera (using Raycaster or just calculation).
Use of orthographic overlay as mentioned by #WestLangley is also possible. Since you would have to calculate ship's position relative to your canvas in this case, maybe you could even create pure HTML overlay using DIV and place your icon in it as IMG object.
I have a simple Three.js scene with a camera that orbits around a cube, always looking directly at it. I need to figure out the percentage of the side that is currently most visible by the camera as it orbits around the cube.
So if I'm looking straight on then side 1 (the "front") can be seeing 100% and all other 5 sides are at 0%. If I rotate the camera slightly to the right right then part of side 2 (the "right side") can now be seen -- perhaps 20%, while side one can now be seen at %80. If I then rotate slightly up then perhaps side 3 (the top) is 10% visible, etc.
How can I go about figuring this out? Remember, the cube itself does not rotate -- only the camera. Three.js or JavaScript would be great, but I can deal with pretty much any programming language. I'm mostly interested in ideas for how to achieve this.
As another option, you could calculate the dot product of the camera's view vector and the cubes face normals, maybe? Then calculate the angle in degrees from the dot product and you know the angle of each face normal relative to the cameras view vector. I am not quite sure if this works, was just an idea. So everything above 90 degrees is not visible at all and 0 degrees is completely facing the camera.
Well, not quite sure about the percentages but i don't know your use case. Just thought about saving the screenspace operations proposed by Gero3 somehow.... by only using the angles from the face normals. FOr example if you would be looking at the edge of the cube and have 2 faces in 45 degrees from the camera view direction, you know that you are 50% for each of the two faces?
First calculate the position of the vertexes in screen space.
HOW TO:
var screenspaceVertexPosition = vertex.position.applyProjection(
this.projectionMatrix.multiplyMatrices(object.matrixWorld))
Do this for all 8 vertexes.
Then figure out which planes are visible by checking the planes normals.
Calculate then the area used by each face in screenspace. From there you can calculate the complete visible area and the percentage.
I am working on a 3D model of a building using Three.JS and Collada loader.
I'm improving my system interactivity, but I have two main issues:
1- When I rotate the model in the scene, it rotates in 3 axis and it makes it upside down! I want to keep the model fixed in horizontal axis and only rotate it along Y axis (Up).
A live sample How I can rotate this cube only around Y Axis (Up)?
2-How I can have a smooth control on the system using mouse movements? For example in big models, it is not easy to zoom to a specific small object smoothly. How I can configure the camera to zoom, pan and rotate smoothly?
Thanks
You are not rotating the model. You are rotating the camera.
Use OrbitControls instead of TrackballControls -- it will keep the camera right-side-up.
OrbitControls should be smooth. If it is not, then there may be something wrong with your model. That can only be handled on a case-by-case basis.
You are using a version of the library that is a year old. It is wise to update to the current version.
three.js r.57.
Add the following in your script:
controls.getMouseProjectionOnBall2 = controls.getMouseProjectionOnBall;
controls.getMouseProjectionOnBall = function(x, y){
return controls.getMouseProjectionOnBall2.call(controls, x, controls.screen.height/2);
}
Regarding the jerky movements, I see you're doing everything possible already (often people omit requestAnimationFrame). I don't think there's anything you can do to reduce jerkiness other than reduce the complexity of your building.