Camera Rotations / Scene Rotations

Irrlicht.Net is no longer developed or supported, Irrlicht.Net Cross Platform is a much more complete wrapper. Please ask your C# related questions on their forums first.
Locked
Gibbo
Posts: 8
Joined: Thu Aug 10, 2006 1:17 pm

Camera Rotations / Scene Rotations

Post 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!!! :cry:

Anybody got any ideas?

Thanks
Shoarc
Posts: 7
Joined: Tue Aug 08, 2006 9:26 pm

Post 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.
Saku
Posts: 158
Joined: Wed Jan 05, 2005 8:48 am
Location: Denmark

Post by Saku »

If you want to simply rotate your camera around a point, you should have a look at scenenode animators.

good luck
Call me Wice, Miami Wice!
shurijo
Posts: 148
Joined: Sat Feb 21, 2004 3:04 am

Post 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.
Locked