Camera as child of Object3D positioning issues - camera

Setup a simple scene here:
http://jsfiddle.net/majman/Sps3c/
I was initially trying to demonstrate a problem I was having with rotating a parent container while having the camera maintain it's relative offset position, but when setting up this example I couldn't even adjust the camera's initial position.
Current Problem:
// camera
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 5, 150);
camera.position.z = 50; // this doesn't work?
// object to contain camera & helper
cameraContainer = new THREE.Object3D();
cameraContainer.rotation.order = "YXZ"; // maybe not necessary
// add to container
cameraContainer.add(camera);
scene.add(cameraContainer);
Now when rotating the cameraContainer, the camera's rotation follows - but I'd like the camera's position to be offset from the cameraContainer. I'm unable to modify any position properties for some reason.

Your code is working fine. You are confused because the CameraHelper is not displaying the camera in its actual position. You need to add the CameraHelper as a child of the scene.
// camera helper
cameraHelper = new THREE.CameraHelper( camera2 );
scene.add( cameraHelper );
updated fiddle: http://jsfiddle.net/Sps3c/1/
Tip: I added an OrbitController to your demo for a better view of the situation.
three.js r.66

Related

Cesium: Having the camera in an entity's first person view

I would like to have my camera follow the first-person view of a moving entity. I do not believe that trackedEntity will work for this use case because I don't want to look at the entity, but I want to look out from it. I would also like the user to be able to use the mouse to turn the camera with respect to the moving entity (for example, to look out the left window of a moving plane).
In a traditional game engine, I would do this by attaching the camera to the entity, so it would move with it, but retain its own local transform with respect to the entity so that it was free to move with respect to the entity.
The only way I can think of right now is to keep track of the "user-controlled" transform separately and multiply it with the entity transform at every clock tick. Is there a better way?
Have a look at Cesium's Cardboard sandcastle example. Here you are on board of a hot-air balloon and perceive the world from there. After scrolling out, you can pan with the mouse to look around. Since the calculations are quite complicated, I cannot give any details how it works, but it seems that the camera view is aligned to the moving direction of the entity. The essential part of the script is:
// Set initial camera position and orientation to be when in the model's reference frame.
var camera = viewer.camera;
camera.position = new Cesium.Cartesian3(0.25, 0.0, 0.0);
camera.direction = new Cesium.Cartesian3(1.0, 0.0, 0.0);
camera.up = new Cesium.Cartesian3(0.0, 0.0, 1.0);
camera.right = new Cesium.Cartesian3(0.0, -1.0, 0.0);
viewer.scene.postUpdate.addEventListener(function (scene, time) {
var position = entity.position.getValue(time);
if (!Cesium.defined(position)) {
return;
}
var transform;
if (!Cesium.defined(entity.orientation)) {
transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
} else {
var orientation = entity.orientation.getValue(time);
if (!Cesium.defined(orientation)) {
return;
}
transform = Cesium.Matrix4.fromRotationTranslation(
Cesium.Matrix3.fromQuaternion(orientation),
position
);
}
// Save camera state
var offset = Cesium.Cartesian3.clone(camera.position);
var direction = Cesium.Cartesian3.clone(camera.direction);
var up = Cesium.Cartesian3.clone(camera.up);
// Set camera to be in model's reference frame.
camera.lookAtTransform(transform);
// Reset the camera state to the saved state so it appears fixed in the model's frame.
Cesium.Cartesian3.clone(offset, camera.position);
Cesium.Cartesian3.clone(direction, camera.direction);
Cesium.Cartesian3.clone(up, camera.up);
Cesium.Cartesian3.cross(direction, up, camera.right);
});
Maybe you can try to modify the camera vectors or multiply the transform with another rotation matrix to simulate turning one's head (to look left/right/back) while being in the initial perspective. For instance, you can try to combine the example above with code from a repository called Cesium First Person Camera Controller.
Had to figure this out myself as well.
Camera.setView and self-defined utility functions are your friend.
E.g. Here is a naive implementation of rotation (does not work well when the pitch of the camera is too "birds-eye-view" like):
Cesium.Camera.prototype.rotateView = function(rotation) {
let { heading, pitch, roll } = rotation;
heading = this.heading + (heading || 0);
pitch = this.pitch + (pitch || 0);
roll = this.roll + (roll || 0);
const destination = this.position;
this.setView({
destination,
orientation: {
heading,
pitch,
roll
}
});
};
Similarly you can update the position with the position of the entity by providing destination.

SceneKit follow camera?

I am trying to make a follow camera in scenekit. I have just started, so try to bear with me. I have a node (robotNode) and am trying to have the camera follow the robot. I have partially achived this by doing adding the camera as a child node of the robot:
cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
[robotNode addChildNode:cameraNode];
// place the camera
cameraNode.position = SCNVector3Make(0, 0, 10);
But the problem is when I start to rotate the camera, it doesn't follow the node anymore. See here:
How can I get it to continue to follow the node?
What you've written will create a camera node a fixed distance from the robot, but you've done nothing to control where the camera points.
Create an SCNLookAtConstraint whose target is the robot node. Attach that to the camera node.
// warning, written in browser, untested
SCNLookAtConstraint *robotStare = [SCNLookAtConstraint lookAtConstraintWithTarget:robotNode];
// and maybe also
robotStare.gimbalLockEnabled = YES;
cameraNode.constraints = #[robotStare];
// OP added this, to make camera follow node. I'm skeptical.
cameraNode.camera.usesOrthographicProjection = YES;

Setting UI Button width and height in cocos2d js android application

In my Cocos2d js android app i have a UI button as
var button=new ccui.Button();
button.loadTextures(res.play_png,res.play_png);
button.setAnchorPoint(cc.p(0,0));
button.x=size.width/2;
button.y=size.height/2;
this.addChild(button);
The button loads and i am able to set it at any position on the screen.
But i am unable to change its width and height to specified number of pixels.
I want something like
button.width=100;
button.height=100;
I did not find any method to do that...
Any help how to accomplish this would be greatful.
Thanks.
The buttons i use are options like play,how to play,share etc..
So i have to position them in such a way that they dont overlap or get distorted for various screen resolutions...
How can i use the setScale method in this context???
We can make a call to a function that can scale the size of the UIButton by performing an action. In this case, the following code might help:
performScaleAction : function()
{
var duration = 0; // duration in seconds for performing this action
var scaleX = 0.5; // scale factor for X-axis
var scaleY = 0.5; // scale factor for Y-axis
var scaleAction = new cc.ScaleTo(duration , scaleX , scaleY );
this.runAction(scaleAction);
}
Now, call the above function in the following way:
this.performScaleAction();
this.addChild(button);
So, if the actual height of the image used for creating the UIButton is h, in this case, the new size as displayed on the screen would be h times scaleX . Same for the width of the UIButton.
Hope this helps!

How to get the real position of a sub node in SceneKit after rotation?

I am developing a scene with SceneKit. I have a main node with a subnode:
// Main node
SCNNode* planet = [SCNNode node];
planet.geometry = [SCNSphere sphereWithRadius:2];
planet.position = SCNVector3Make(0, -3, 5);
// sub-node
SCNNode* satellite = [SCNNode node];
satellite.geometry = [SCNSphere sphereWithRadius:0.4];
satellite.position = SCNVector3Make(4, 0, 0);
[planet addChildNode:satellite];
[scene.rootNode addChildNode:planet];
I use a NSTimer to make some actions and some animations. In the timer event I do that:
planetRotation += 0.1;
planet.rotation = SCNVector4Make(0,1,0, planetRotation);
But if i try to get the position of the satellite node I always get the same value.
I tried to get the positionnode to know the real position of the satellite node but nothing changes.
How can I get the real position of a sub-node when I change the rotation of the parent node?
Thanks in advance
the position of a node is expressed in its parent coordinate system. Just like for views in UIKIt/AppKit. If you change the frame of a view, the frame of its subviews does not change.
What you want is what we call the world transform of the subnode (i.e. its transform expressed in the coordinate system of the scene's root node).
You can have a look at worldTransform and -convertPosition:toNode:.
The node's position won't change due to physics, that is why you aren't seeing it change. You need to call the node's presentationNode to get the position of the node as it is presented onscreen:
node.presentationNode.position

THREE.js rotating camera around an object using orbit path

I am struggling in solving this problem.
On my scene, I have a camera which looks at the center of mass of an object. I have a some buttons that enable to set camera position on particular view (front view, back view,...) along a invisible sphere that surroung the object (constant radius).
When I click on the button, i would like the camera to move from its start position to the end position along the sphere surface. When camera moves I would like it to keep fixing center of mass of the object.
Has anyone have a clue on how to achieve this?
Thanks for help!
If you are happy/prefer to use basic trigonometry then in your initialisation section you could do this:
var cameraAngle = 0;
var orbitRange = 100;
var orbitSpeed = 2 * Math.PI/180;
var desiredAngle = 90 * Math.PI/180;
...
camera.position.set(orbitRange,0,0);
camera.lookAt(myObject.position);
Then in your render/animate section you could do this:
if (cameraAngle == desiredAngle) { orbitSpeed = 0; }
else {
cameraAngle += orbitSpeed;
camera.position.x = Math.cos(cameraAngle) * orbitRange;
camera.position.y = Math.sin(cameraAngle) * orbitRange;
}
Of course, your buttons would modify what the desiredAngle was (0°, 90°, 180° or 270° presumably), you need to rotate around the correct plane (I am rotating around the XY plane above), and you can play with the orbitRange and orbitSpeed until you hare happy.
You can also modify orbitSpeed as it moves along the orbit path, speeding up and slowing down at various cameraAngles for a smoother ride. This process is called 'tweening' and you could search on 'tween' or 'tweening' if you want to know more. I think Three.js has tweening support but have never looked into it.
Oh, also remember to set your camera's far property to be greater than orbitRadius or you will only see the front half of your object and, depending on what it is, that might look weird.