Page 1 of 1
Camera Rotations / Scene Rotations
Posted: Wed Aug 16, 2006 1:29 pm
by Gibbo
Hi,
I'm new to Irrlicht.. I'm trying to use the Irrlicht.Net with C#..
I'm trying to make the camera orbit the target point, but wasn't havening much luck. So thought I'd rotate the root node instead.. But that didn't seem to be working either..
Code: Select all
Irrlicht.Core.Vector3D Degrees = model.RelativeTransformation;
.GetRotationDegrees();
Degrees.Y += value;
model.RelativeTransformation;
.SetRotationDegrees(Degrees);
But this had no effect. So I did the following to check that it was being set.
Code: Select all
Degrees = model.RelativeTransformation;
.GetRotationDegrees();
And it was being reset back!!!
Anybody got any ideas?
Thanks
Posted: Fri Aug 18, 2006 5:52 pm
by Shoarc
I also wanted to make a camera orbit around a specific point also and MayaCameraSceneNode did not give me the mouse controls that I wanted. I decided to just wrap code(not sure if this is good programming) around a normal CameraSceneNode, since I didn't know enough c++ programming to make my own node and add it to the engine.
Here is my OrbitCamera. However, this uses IrrlichtNETCP, not Irrlict.Net.
Also this code is still a bit messy since this was based on the MayaCameraNode code and there are some stuff that arn't needed that I forgot to remove.
The camera orbits around a point through middle mouse click and zooms by the mouse wheel. Hope this helps:
Code: Select all
public class OrbitCamera
{
#region Members
private bool[] MouseKeys;
private bool zooming, rotating, moving;
private float zoomSpeed;
private float translateSpeed;
private float rotateSpeed;
private float rotateStartX, rotateStartY;
private float currentZoom;
private float rotX, rotY;
private Position2Df MousePos;
private Vector3D Pos;
private SceneManager scene;
private CameraSceneNode camera;
private float totalRotX;
private float totalRotY;
private Vector3D rotAdd;
private float delta;
//Limits on zoom and rotation
private float maxZoom = 400;
private float minZoom = 100;
private float maxYRot = 85;
//-5
private float minYRot = -5;
private AnimatedMeshSceneNode targetNode;
private bool handled;
private float totalTransZ;
private float totalTransY;
private float totalTransX;
private Vector3D center;
#endregion
#region Constructor
public OrbitCamera(SceneManager mgr,
float rs, float zs, float ts)
{
scene = mgr;
camera = scene.AddCameraSceneNode(null);
rotAdd = new Vector3D();
zooming = false;
rotating = false;
moving = false;
zoomSpeed = zs;
rotateSpeed = rs;
currentZoom = 70.0f;
//Pos.set(0.0f, 70.0f, 0.0f);
camera.Target = new Vector3D(0, 70, 0);
rotX = 0;
rotY = 0;
MouseKeys = new bool[3];
targetNode = null;
handled = false;
allKeysUp();
//RecalculateViewArea();
}
#endregion
#region Methods
public void setMoved(bool moved)
{
moving = moved;
}
public bool handleMouseEvents(Event e)
{
if (e.Type == EventType.MouseInputEvent)
{
switch (e.MouseInputEvent)
{
case MouseInputEvent.MMousePressedDown:
{
handled = true;
MouseKeys[0] = true;
}
break;
case MouseInputEvent.MMouseLeftUp:
{
handled = true;
MouseKeys[0] = false;
}
break;
case MouseInputEvent.MouseMoved:
{
if (scene.VideoDriver != null)
{
Dimension2D ssize = (Dimension2D)scene.VideoDriver.ScreenSize;
MousePos.X = (e.MousePosition.X / (float)ssize.Width);
MousePos.Y = (e.MousePosition.Y / (float)ssize.Height);
moving = true;
handled = true;
}
}
break;
case MouseInputEvent.MouseWheel:
{
delta = e.MouseWheelDelta;
MouseKeys[2] = true;
handled = true;
break;
}
}
if (handled)
{
handled = false;
return true;
}
}
return false;
}
// Updates the rotation
public Vector3D update()
{
//Update camera translation to move with
// a scene node
//updateTarget();
// Update Pos camera rotation and zoom
// Pos stores the new position of the camera
animate();
// Sets the camera position
camera.Position = Pos;
//camera.UpdateAbsolutePosition();
return camera.Position;
}
// Helper method
private bool isMouseKeyDown(int key)
{
return MouseKeys[key];
}
// Updates camera
public void animate()
{
//ViewFrustrum va = ViewFrustrum;
float nRotX = rotX;
float nRotY = rotY;
float nZoom = currentZoom;
if (isMouseKeyDown(2))
{
zooming = true;
if (delta > 0)
{
currentZoom = currentZoom + (delta * zoomSpeed);
}
else
{
currentZoom = currentZoom - (delta * -zoomSpeed);
}
if (currentZoom > maxZoom)
currentZoom = maxZoom;
else if (currentZoom < minZoom)
currentZoom = minZoom;
/*if (!zooming)
{
zoomStartX = MousePos.X;
zoomStartY = MousePos.Y;
zooming = true;
nZoom = currentZoom;
}
else
{
float old = nZoom;
nZoom += (zoomStartX - MousePos.X) * zoomSpeed;
float targetMinDistance = 0.1f;
if (nZoom < targetMinDistance)
nZoom = targetMinDistance;
if (nZoom < 0)
nZoom = old;
}*/
}
/*else
{
if (zooming)
{
float old = currentZoom;
currentZoom = currentZoom + (zoomStartX - MousePos.X) * zoomSpeed;
nZoom = currentZoom;
if (nZoom < 0)
nZoom = currentZoom = old;
}
zooming = false;
}*/
// Translation ---------------------------------
//core::vector3df translate(oldTarget);
/* Vector3Df translate = oldTarget;
Vector3Df tvectX = Pos - Target;
tvectX = tvectX.CrossProduct(UpVector);
tvectX.Normalize();
Vector3Df tvectY = (va.GetFarLeftDown() - va.GetFarRightDown());
tvectY = tvectY.CrossProduct(UpVector.Y > 0 ? Pos - Target : Target - Pos);
tvectY.Normalize();
if (isMouseKeyDown(2) && !zooming)
{
if (!translating)
{
translateStartX = MousePos.X;
translateStartY = MousePos.Y;
translating = true;
}
else
{
translate += tvectX * (translateStartX - MousePos.X) * translateSpeed +
tvectY * (translateStartY - MousePos.Y) * translateSpeed;
}
}
else
{
if (translating)
{
translate += tvectX * (translateStartX - MousePos.X) * translateSpeed +
tvectY * (translateStartY - MousePos.Y) * translateSpeed;
oldTarget = translate;
}
translating = false;
}*/
// Rotation ------------------------------------
if (isMouseKeyDown(0) && !zooming)
{
if (!moving)
{
rotateStartX = MousePos.X;
rotateStartY = MousePos.Y;
}
else
moving = false;
if (!rotating)
{
rotateStartX = MousePos.X;
rotateStartY = MousePos.Y;
rotating = true;
nRotX = rotX;
nRotY = rotY;
}
else
{
nRotX += (rotateStartX - MousePos.X) * rotateSpeed;
nRotY += (rotateStartY - MousePos.Y) * rotateSpeed;
}
}
else
{
if (rotating)
{
rotX = rotX + (rotateStartX - MousePos.X) * rotateSpeed;
rotY = rotY + (rotateStartY - MousePos.Y) * rotateSpeed;
nRotX = rotX;
nRotY = rotY;
}
rotating = false;
}
//Console.WriteLine("currentZoom: " + currentZoom);
// Set Pos ------------------------------------
// Sets the rotation of the camera around the target
if (isMouseKeyDown(0) || isMouseKeyDown(2))
{
MouseKeys[2] = false;
zooming = false;
// Rotate up and down first then
// rotate left to right
totalRotX += -nRotX;
totalRotY += nRotY;
if (totalRotY > maxYRot)
totalRotY = maxYRot;
else if (totalRotY < minYRot)
totalRotY = minYRot;
rotAdd.Set(0, 0, -currentZoom);
rotAdd.RotateYZBy(totalRotY, center);
rotAdd.RotateXZBy(-totalRotX, center);
//rotAdd.X = rotAdd.X + Pos.X;
//rotAdd.Y = rotAdd.Y + Pos.Y;
Pos = rotAdd;
updateTranslation();
}
else
{
nRotY = 0;
nRotX = 0;
rotX = 0;
rotY = 0;
}
// Rotation Error ----------------------------
// jox: fixed bug: jitter when rotating to the top and bottom of y
Vector3D upVec = camera.UpVector;
upVec.X = 0;
upVec.Y = 1;
upVec.Z = 0;
camera.UpVector = upVec;
camera.UpVector.RotateXYBy(-nRotY, camera.Target);
camera.UpVector.RotateXZBy(-nRotX + 180f, camera.Target);
}
private void updateTranslation()
{
Pos.X += totalTransX;
Pos.Y += totalTransY;
Pos.Z += totalTransZ;
}
// Initiate all keys
private void allKeysUp()
{
for (int i=0; i<3; ++i)
MouseKeys[i] = false;
}
// function added by jox: fix setPosition()
// Sets the position of the camera
public void setPosition(Vector3D pos)
{
Pos = pos;
updateAnimationState();
//camera.Position = pos;
}
// function added by jox: fix setTarget()
// Sets the target to look at
public void setTarget(Vector3D pos)
{
camera.Target = pos;
center = pos;
updateAnimationState();
}
// Sets which node to follow
public void setTargetNode(AnimatedMeshSceneNode node)
{
targetNode = node;
}
// Updates the camera position to follow a target
// This is based on the most recent target that
// was set by 'setTarget()'
public void updateTarget()
{
if (targetNode != null)
{
float zdiff = Math.Abs(camera.Target.Z) - Math.Abs(targetNode.Position.Z);
float ydiff = Math.Abs(camera.Target.Y) - Math.Abs(targetNode.Position.Y);
float xdiff = Math.Abs(camera.Target.X) - Math.Abs(targetNode.Position.X);
Vector3D camPos = camera.Position;
if (zdiff < 0)
camPos.Z = camPos.Z - zdiff;
else
camPos.Z = camPos.Z + zdiff;
if (ydiff < 0)
camPos.Y = camPos.Y - ydiff;
else
camPos.Y = camPos.Y + ydiff;
if (xdiff < 0)
camPos.X = camPos.X - xdiff;
else
camPos.X = camPos.X + xdiff;
camera.Position = camPos;
Pos = camera.Position;
camera.Target = targetNode.Position;
/*currentZoom = (float)Pos.DistanceFrom(camera.Target);
if (currentZoom > maxZoom)
currentZoom = maxZoom;
else if (currentZoom < minZoom)
currentZoom = minZoom;*/
}
}
public void updateTarget(float zdiff, float ydiff, float xdiff)
{
if (targetNode != null)
{
//float zdiff = Math.Abs(camera.Target.Z) - Math.Abs(targetNode.Position.Z);
//float ydiff = Math.Abs(camera.Target.Y) - Math.Abs(targetNode.Position.Y);
//float xdiff = Math.Abs(camera.Target.X) - Math.Abs(targetNode.Position.X);
Vector3D camPos = camera.Position;
//Z
/*if (zdiff < 0)
{
camPos.Z = camPos.Z - zdiff;
totalTransZ -= zdiff;
}
else
{
camPos.Z = camPos.Z + zdiff;
totalTransZ += zdiff;
}
//Y
if (ydiff < 0)
{
camPos.Y = camPos.Y - ydiff;
totalTransY -= ydiff;
}
else
{
camPos.Y = camPos.Y + ydiff;
totalTransY += ydiff;
}
//X
if (xdiff < 0)
{
camPos.X = camPos.X - xdiff;
totalTransX -= xdiff;
}
else
{
camPos.X = camPos.X + xdiff;
totalTransX += xdiff;
}*/
camPos.Z += + zdiff;
totalTransZ += zdiff;
camPos.Y += ydiff;
totalTransY += ydiff;
camPos.X += xdiff;
totalTransX += xdiff;
camera.Position = camPos;
Pos = camera.Position;
camera.Target = targetNode.Position;
/*currentZoom = (float)Pos.DistanceFrom(camera.Target);
if (currentZoom > maxZoom)
currentZoom = maxZoom;
else if (currentZoom < minZoom)
currentZoom = minZoom;*/
}
}
// function added by jox
// Determines the angle from the position to the target
// and sets them to 'totalRot' variables
private void updateAnimationState()
{
float zLen = Math.Abs(Pos.Z) - Math.Abs(camera.Target.Z);
float yLen = Math.Abs(Pos.Y) - Math.Abs(camera.Target.Y);
float xLen = Math.Abs(Pos.X) - Math.Abs(camera.Target.X);
// X rotation
rotY = (float)((Math.Atan(yLen / zLen) * 360) / (2 * Math.PI));
rotX = (float)((Math.Atan(xLen / zLen) * 360) / (2 * Math.PI));
totalRotY = rotY;
totalRotX = rotX;
// Zoom
currentZoom = (float)Pos.DistanceFrom(camera.Target);
rotAdd.Set(0, 0, -currentZoom);
rotAdd.RotateYZBy(totalRotY, center);
rotAdd.RotateXZBy(-totalRotX, center);
Pos = rotAdd;
camera.Position = rotAdd;
}
public CameraSceneNode getCamera()
{
return camera;
}
#endregion
}
The tranlation from IrrlichtNETCP to Irrlicht.Net shouldn't be too hard. Anyway, if u have any questions about my code, feel free to ask.
Posted: Fri Aug 18, 2006 6:24 pm
by Saku
If you want to simply rotate your camera around a point, you should have a look at scenenode animators.
good luck
Posted: Fri Aug 18, 2006 8:49 pm
by shurijo
I typically just add an emptySceneNode and use that as the parent of my other nodes. Then I rotate the emptySceneNode. Works fine for me. I don't think you can rotate the root node, since everything (even the camera) is tied to it, so it would have any affect, etc.