I'm not sure if I am posting this in the right section or not but I figured sense I'm a total noob I'd start here.
A few months ago I tested a ChaseCamera class for the XNA framework, and it compiled and worked well out of the box. It had some nice dampening effects as well as smooth transitions.
Now, I've switched from XNA to Irrlicht and I am trying to convert this class to Irrlicht as there doesn't seem to be many working examples of a chase camera (3Rd person and CockpitClass don't count as they are not able to fly in 3D space correctly). XNA has many of the same concepts and methods which made it pretty easy for my to switch too. I was/am also in no way an experienced XNA or 3D developer as well.
So here is my conversion so far. It compiles just fine but I think some of my transformations are off. XNA uses transform.Up(Vect3D) and transform.Right(Vect3d) but my understanding of transformation is still rusty.
Would anyone be so kind to assist me?
C#/XNA Class:
Taken from here: http://creators.xna.com/en-US/sample/chasecamera
Code: Select all
#region File Description
//-----------------------------------------------------------------------------
// ChaseCamera.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
#endregion
namespace ChaseCameraSample
{
public class ChaseCamera
{
#region Chased object properties (set externally each frame)
/// <summary>
/// Position of object being chased.
/// </summary>
public Vector3 ChasePosition
{
get { return chasePosition; }
set { chasePosition = value; }
}
private Vector3 chasePosition;
/// <summary>
/// Direction the chased object is facing.
/// </summary>
public Vector3 ChaseDirection
{
get { return chaseDirection; }
set { chaseDirection = value; }
}
private Vector3 chaseDirection;
/// <summary>
/// Chased object's Up vector.
/// </summary>
public Vector3 Up
{
get { return up; }
set { up = value; }
}
private Vector3 up = Vector3.Up;
#endregion
#region Desired camera positioning (set when creating camera or changing view)
/// <summary>
/// Desired camera position in the chased object's coordinate system.
/// </summary>
public Vector3 DesiredPositionOffset
{
get { return desiredPositionOffset; }
set { desiredPositionOffset = value; }
}
private Vector3 desiredPositionOffset = new Vector3(0, 2.0f, 2.0f);
/// <summary>
/// Desired camera position in world space.
/// </summary>
public Vector3 DesiredPosition
{
get
{
// Ensure correct value even if update has not been called this frame
UpdateWorldPositions();
return desiredPosition;
}
}
private Vector3 desiredPosition;
/// <summary>
/// Look at point in the chased object's coordinate system.
/// </summary>
public Vector3 LookAtOffset
{
get { return lookAtOffset; }
set { lookAtOffset = value; }
}
private Vector3 lookAtOffset = new Vector3(0, 2.8f, 0);
/// <summary>
/// Look at point in world space.
/// </summary>
public Vector3 LookAt
{
get
{
// Ensure correct value even if update has not been called this frame
UpdateWorldPositions();
return lookAt;
}
}
private Vector3 lookAt;
#endregion
#region Camera physics (typically set when creating camera)
/// <summary>
/// Physics coefficient which controls the influence of the camera's position
/// over the spring force. The stiffer the spring, the closer it will stay to
/// the chased object.
/// </summary>
public float Stiffness
{
get { return stiffness; }
set { stiffness = value; }
}
private float stiffness = 1800.0f;
/// <summary>
/// Physics coefficient which approximates internal friction of the spring.
/// Sufficient damping will prevent the spring from oscillating infinitely.
/// </summary>
public float Damping
{
get { return damping; }
set { damping = value; }
}
private float damping = 600.0f;
/// <summary>
/// Mass of the camera body. Heaver objects require stiffer springs with less
/// damping to move at the same rate as lighter objects.
/// </summary>
public float Mass
{
get { return mass; }
set { mass = value; }
}
private float mass = 50.0f;
#endregion
#region Current camera properties (updated by camera physics)
/// <summary>
/// Position of camera in world space.
/// </summary>
public Vector3 Position
{
get { return position; }
}
private Vector3 position;
/// <summary>
/// Velocity of camera.
/// </summary>
public Vector3 Velocity
{
get { return velocity; }
}
private Vector3 velocity;
#endregion
#region Perspective properties
/// <summary>
/// Perspective aspect ratio. Default value should be overriden by application.
/// </summary>
public float AspectRatio
{
get { return aspectRatio; }
set { aspectRatio = value; }
}
private float aspectRatio = 4.0f / 3.0f;
/// <summary>
/// Perspective field of view.
/// </summary>
public float FieldOfView
{
get { return fieldOfView; }
set { fieldOfView = value; }
}
private float fieldOfView = MathHelper.ToRadians(45.0f);
/// <summary>
/// Distance to the near clipping plane.
/// </summary>
public float NearPlaneDistance
{
get { return nearPlaneDistance; }
set { nearPlaneDistance = value; }
}
private float nearPlaneDistance = 1.0f;
/// <summary>
/// Distance to the far clipping plane.
/// </summary>
public float FarPlaneDistance
{
get { return farPlaneDistance; }
set { farPlaneDistance = value; }
}
private float farPlaneDistance = 100000.0f;
#endregion
#region Matrix properties
/// <summary>
/// View transform matrix.
/// </summary>
public Matrix View
{
get { return view; }
}
private Matrix view;
/// <summary>
/// Projecton transform matrix.
/// </summary>
public Matrix Projection
{
get { return projection; }
}
private Matrix projection;
#endregion
#region Methods
/// <summary>
/// Rebuilds object space values in world space. Invoke before publicly
/// returning or privately accessing world space values.
/// </summary>
private void UpdateWorldPositions()
{
// Construct a matrix to transform from object space to worldspace
Matrix transform = Matrix.Identity;
transform.Forward = ChaseDirection;
transform.Up = Up;
transform.Right = Vector3.Cross(Up, ChaseDirection);
// Calculate desired camera properties in world space
desiredPosition = ChasePosition +
Vector3.TransformNormal(DesiredPositionOffset, transform);
lookAt = ChasePosition +
Vector3.TransformNormal(LookAtOffset, transform);
}
/// <summary>
/// Rebuilds camera's view and projection matricies.
/// </summary>
private void UpdateMatrices()
{
view = Matrix.CreateLookAt(this.Position, this.LookAt, this.Up);
projection = Matrix.CreatePerspectiveFieldOfView(FieldOfView,
AspectRatio, NearPlaneDistance, FarPlaneDistance);
}
/// <summary>
/// Forces camera to be at desired position and to stop moving. The is useful
/// when the chased object is first created or after it has been teleported.
/// Failing to call this after a large change to the chased object's position
/// will result in the camera quickly flying across the world.
/// </summary>
public void Reset()
{
UpdateWorldPositions();
// Stop motion
velocity = Vector3.Zero;
// Force desired position
position = desiredPosition;
UpdateMatrices();
}
/// <summary>
/// Animates the camera from its current position towards the desired offset
/// behind the chased object. The camera's animation is controlled by a simple
/// physical spring attached to the camera and anchored to the desired position.
/// </summary>
public void Update(GameTime gameTime)
{
if (gameTime == null)
throw new ArgumentNullException("gameTime");
UpdateWorldPositions();
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
// Calculate spring force
Vector3 stretch = position - desiredPosition;
Vector3 force = -stiffness * stretch - damping * velocity;
// Apply acceleration
Vector3 acceleration = force / mass;
velocity += acceleration * elapsed;
// Apply velocity
position += velocity * elapsed;
UpdateMatrices();
}
#endregion
}
}
Code: Select all
/*
* ChaseCamera.cpp
*
* Created on: Sep 3, 2010
* Author: jim
*/
#include "ChaseCamera.h"
//ChaseCamera::~ChaseCamera() {
// TODO Auto-generated destructor stub
//}
float stiffness = 1800.0f;
float damping = 600.0f;
float mass = 50.0f;
float fieldOfView = irr::core::degToRad(45.0f);
irr::core::matrix4 view;
irr::core::matrix4 projection;
irr::core::vector3df desiredPositionOffset = irr::core::vector3df(0, 2.0f, 2.0f);
core::vector3df ChaseCamera::lookAtVector3df()
{
UpdateWorldPositions();
return lookAt;
}
void ChaseCamera::UpdateWorldPositions()
{
irr::core::matrix4 transform = irr::core::IdentityMatrix;
//irr::core::vector3df forward = ChasePosition;
transform.transformVect(ChasePosition);
transform.transformVect(Up);
irr::core::vector3df Right = Up.crossProduct(ChasePosition);
transform.transformVect(Right);
//from C# desiredPosition = ChasePosition + Vector3.TransformNormal(DesiredPositionOffset, transform);
desiredPositionOffset.normalize();
desiredPosition = ChasePosition + desiredPositionOffset;
}
void ChaseCamera::UpdateMatrices()
{
irr::core::matrix4 m;
view = m.buildCameraLookAtMatrixRH(position,lookAtVector3df(),Up);
projection = m.buildProjectionMatrixPerspectiveFovRH(fieldOfView,aspectRatio,nearPlaneDistance,farPlaneDistance);
}
void ChaseCamera::Reset()
{
UpdateWorldPositions();
velocity = irr::core::vector3df(0,0,0);
UpdateMatrices();
}
//elapsed is in seconds.
void ChaseCamera::Update(float elapsed)
{
UpdateWorldPositions();
irr::core::vector3df stretch = position - desiredPosition;
irr::core::vector3df force = -stiffness * stretch - damping * velocity;
irr::core::vector3df acceleration = force / mass;
velocity == acceleration * elapsed;
UpdateMatrices();
}
ChaseCamera::ChaseCamera() {
// TODO Auto-generated constructor stub
desiredPositionOffset = core::vector3df(0, 2.0f, 2.0f);
lookAtOffset = core::vector3df(0, 2.8f, 0);
nearPlaneDistance = 1.0f;
farPlaneDistance = 10000.0f;
aspectRatio = 4.0f / 3.0f;
}Code: Select all
/*
* ChaseCamera.h
*
* Created on: Sep 3, 2010
* Author: jim
*/
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifndef CHASECAMERA_H_
#define CHASECAMERA_H_
class ChaseCamera {
public:
core::vector3df ChasePosition;
core::vector3df ChaseDirection;
core::vector3df desiredPosition;
core::vector3df lookAtOffset;
core::vector3df position;
core::vector3df velocity;
core::vector3df Up;
core::vector3df Right;
core::vector3df desiredPositionOffset;
core::vector3df lookAt;
float nearPlaneDistance;
float farPlaneDistance;
float aspectRatio;
void UpdateWorldPositions();
void UpdateMatrices();
void Reset();
void Update(float elapsed);
irr::core::vector3df lookAtVector3df();
ChaseCamera();
};
#endif /* CHASECAMERA_H_ */