Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Lucas

« Newer Snippets
Older Snippets »
Showing 1-6 of 6 total  RSS 

Simple camera class in FTS - lookAt function.

// Camera class for FTS

/// Makes the camera look at a certain point.
/** This function makes the camera look at a certain point. If that point is the same as its
 *  current position, the camera moves back the (current) distance |camera-target|.
 *
 * \param in_vTgt The position where the camera should look at.
 *
 * \return If successfull: ERR_OK
 * \return If failed:      An error code < 0
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::lookAt(const CFTSVector & in_vTgt)
{
    // Calculate the new front vector that points to the target.
    CFTSVector vNewFront = (in_vTgt - m_vPos).normalize();

    // The two vectors are in one plane. This gives us the cosine of the angle between
    // these two vectors.
    float fDotProd = vNewFront.dot(m_vFront);
    if(fDotProd > 1.0f || fDotProd < -1.0f)
        return this;

    // By getting the arc cosine of this, we get the angle in radians between the two
    // vectors. But we only get an angle between 0 and pi, that will be a problem.
    float fAlpha = acosf(fDotProd);

    // Here we get the normal to these two vectors, we will need to rotate our front
    // vector around this normal.
    CFTSVector vNormal = vNewFront.cross(m_vFront).normalize();

    // As I said, we have a problem: as we only get an angle between 0 and pi,
    // we don't know if we need to rotate clockwise or counterclockwise ...
    // We solve this problem by just trying it out.
    CFTSVector vFrontTest = m_vFront.rotate(vNormal, fAlpha);

    // If the dot product is near to one, it means we were right. with our guess
    // rotating counterclockwise.
    // Else, we must rotate clockwise.
    fDotProd = vFrontTest.dot(vNewFront);
    if(fabs(fDotProd) > (1.0f - D_FTS_DELTA)) {
            m_vFront = vFrontTest;
            m_vUp = m_vUp.rotate(vNormal, fAlpha);
            m_vRight = m_vRight.rotate(vNormal, fAlpha);
    } else {
            m_vFront = m_vFront.rotate(vNormal, -fAlpha);
            m_vUp = m_vUp.rotate(vNormal, -fAlpha);
            m_vRight = m_vRight.rotate(vNormal, -fAlpha);
    }

    // If the dot product is near to -1, it means we look the wrong way.
    // To correct this, we just rotate pi radians (a half circle).
    if(fDotProd < -(1.0f - D_FTS_DELTA))
        this->rotateYRadians(M_PI);

    return this;
}

Simple camera class in FTS

// Simple camera class in FTS

/**
 * \file camera.cpp
 * \author Pompei2
 * \date 15 July 2006
 * \brief This file contains the camera class implementation.
 **/

#include "3d/camera.h"

#include <GL/gl.h>

#ifdef DEBUG
#  define new new(__FILE__,__LINE__)
#endif

/// Constructor
CFTSCamera::CFTSCamera( void )
{
    m_vRight = CFTSVector(1.0f,0.0f,0.0f);
    m_vUp    = CFTSVector(0.0f,1.0f,0.0f);
    m_vFront = CFTSVector(0.0f,0.0f,-1.0f);
}

/// Destructor
CFTSCamera::~CFTSCamera( void )
{
}

/// Places the camera at a certain point.
/** This function places the camera at a certain point in space.
 *
 * \param in_vPos The new position of the camera.
 *
 * \return If successfull: ERR_OK
 * \return If failed:      An error code < 0
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::pos(const CFTSVector & in_vPos)
{
    m_vPos = in_vPos;
    return this;
}

/// Moves the camera to the right.
/** This moves the camera to the right. The right is relative to the
 *  camera's orientation ! To move to the left, put a negative value here.
 *
 * \param in_fAmount The amount of units to move to the right.
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::moveRight(float in_fAmount)
{
    // We have a vector pointing to the right,
    // so moving to the right is an easy thing:
    // Just add a multiple of this vector to the current position.
    m_vPos = m_vPos + m_vRight.scalar(in_fAmount);

    return this;
}

/// Moves the camera to the front.
/** This moves the camera to the front. The right is relative to the
 *  camera's orientation and to be exact, it is where the camera looks at.
 *  Moving to the front is a bit like zooming in.
 *  To move back (like zoom out), put a negative value here.
 *
 * \param in_fAmount The amount of units to move to the front.
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::moveFront(float in_fAmount)
{
    // Same as for moveRight.
    m_vPos = m_vPos + m_vFront.scalar(in_fAmount);

    return this;
}

/// Moves the camera upwards.
/** This moves the camera upwards. Upwards is the direction that is perpendicular
 *  To your right and to your front, and shows up :) It is like the top of your head.
 *  To move downwards (to your feets), put a negative value here.
 *
 * \param in_fAmount The amount of units to move up.
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::moveUp(float in_fAmount)
{
    // Same as for moveRight.
    m_vPos = m_vPos + m_vUp.scalar(in_fAmount);

    return this;
}

/// Rotates the camera around ITS x axis.
/** This rotates the camera around THE CAMERA's x axis.
 *  This basically means it looks up or down. As seen from the right,
 *  a positive value rotates counterclockwise (look up) and a negative
 *  value rotates clockwise (look down).
 *
 * \param in_fAmount The amount of degrees to rotate.
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::rotateX(float in_fAmount)
{
    Lib3dsMatrix mRotation;
    Lib3dsQuat qRotation;

    // First, clean the matrix.
    lib3ds_matrix_identity(mRotation);

    // Create the quaternion to rotate, we need the angle in radians.
    lib3ds_quat_axis_angle(qRotation, m_vRight.lib3ds(), -RADIANS(in_fAmount));

    // Apply the rotation to the identity matrix, creating a transformation matrix.
    lib3ds_matrix_rotate(mRotation, qRotation);

    // Rotate our front and up vectors, this makes the camera rotate.
    m_vFront = m_vFront.transform(mRotation).normalize();
    m_vUp = m_vUp.transform(mRotation).normalize();

    return this;
}

/// Rotates the camera around ITS y axis.
/** This rotates the camera around THE CAMERA's y axis.
 *  This basically means it looks left or right. As seen from the top,
 *  a positive value rotates counterclockwise (look left) and a negative
 *  value rotates clockwise (look right).
 *
 * \param in_fAmount The amount of degrees to rotate.
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::rotateY(float in_fAmount)
{
    Lib3dsMatrix mRotation;
    Lib3dsQuat qRotation;

    // First, clean the matrix.
    lib3ds_matrix_identity(mRotation);

    // Create the quaternion to rotate, we need the angle in radians.
    lib3ds_quat_axis_angle(qRotation, m_vUp.lib3ds(), -RADIANS(in_fAmount));

    // Apply the rotation to the identity matrix, creating a transformation matrix.
    lib3ds_matrix_rotate(mRotation, qRotation);

    // Rotate our front and up vectors, this makes the camera rotate.
    m_vFront = m_vFront.transform(mRotation).normalize();
    m_vRight = m_vRight.transform(mRotation).normalize();

    return this;
}

/// Rotates the camera around ITS z axis.
/** This rotates the camera around THE CAMERA's z axis.
 *  This is the same effect as if you rotate your head to bring an ear
 *  close to the shoulder. A positive value rotates counterclockwise (left shoulder)
 *  and a negative value rotates clockwise (right shoulder).
 *
 * \param in_fAmount The amount of degrees to rotate.
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::rotateZ(float in_fAmount)
{
    Lib3dsMatrix mRotation;
    Lib3dsQuat qRotation;

    // First, clean the matrix.
    lib3ds_matrix_identity(mRotation);

    // Create the quaternion to rotate, we need the angle in radians.
    lib3ds_quat_axis_angle(qRotation, m_vFront.lib3ds(), -RADIANS(in_fAmount));

    // Apply the rotation to the identity matrix, creating a transformation matrix.
    lib3ds_matrix_rotate(mRotation, qRotation);

    // Rotate our front and up vectors, this makes the camera rotate.
    m_vUp = m_vUp.transform(mRotation).normalize();
    m_vRight = m_vRight.transform(mRotation).normalize();

    return this;
}

/// Renders the camera.
/** This function applies all transformations to the current matrix
 *  that are needed to place the camera.
 *
 * \author Pompei2
 */
CFTSCamera *CFTSCamera::render(void)
{
    // gluLookAt wants a point in space to look at, not just a direction.
    // Calculate this point.
    CFTSVector vLookAt = m_vPos + m_vFront;

    // Let gluLookAt do all the matrix calculation stuff.
    gluLookAt(m_vPos.x(), m_vPos.y(), m_vPos.z(),
              vLookAt.x(), vLookAt.y(), vLookAt.z(),
              m_vUp.x(), m_vUp.y(), m_vUp.z());

    return this;
}

Multiply a point by a transformation matrix

// Multiply a point by a transformation matrix.

/*!
 * Multiply a point by a transformation matrix.
 *
 * Applies the given transformation matrix to the given point.  With some
 * transformation matrices, a vector may also be transformed.
 *
 * \param c Result. (just a float[3])
 * \param m Transformation matrix. (just a float[4][4])
 * \param a Input point. (just a float[3])
 */
void
lib3ds_vector_transform(Lib3dsVector c, Lib3dsMatrix m, Lib3dsVector a) {
    c[0] = m[0][0] * a[0] + m[1][0] * a[1] + m[2][0] * a[2] + m[3][0];
    c[1] = m[0][1] * a[0] + m[1][1] * a[1] + m[2][1] * a[2] + m[3][1];
    c[2] = m[0][2] * a[0] + m[1][2] * a[1] + m[2][2] * a[2] + m[3][2];
}

Multiply two matrices

// Multiply two matrices

/*!
* Multiplies a matrix by a second one (m = m * n).
*/
void lib3ds_matrix_mult(Lib3dsMatrix m, Lib3dsMatrix n) {
    Lib3dsMatrix tmp;
    int i, j, k;
    float ab;

    memcpy(tmp, m, sizeof(Lib3dsMatrix));
    for (j = 0; j &lt; 4; j++) {
        for (i = 0; i &lt; 4; i++) {
            ab = 0.0f;
            for (k = 0; k &lt; 4; k++)
                ab += tmp[k][i] * n[j][k];
            m[j][i] = ab;
        }
    }
}

Apply a rotation about an arbitrary axis to a matrix.

// Apply a rotation about an arbitrary axis to a matrix.

/*!
* Apply a rotation about an arbitrary axis to a matrix.
* m is just a float[4][4], q is just a float[4]
*/
void lib3ds_matrix_rotate(Lib3dsMatrix m, Lib3dsQuat q) {
    float s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz, l;
    Lib3dsMatrix R;

    l = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
    s = 2.0f / l;

    xs = q[0] * s;
    ys = q[1] * s;
    zs = q[2] * s;
    wx = q[3] * xs;
    wy = q[3] * ys;
    wz = q[3] * zs;
    xx = q[0] * xs;
    xy = q[0] * ys;
    xz = q[0] * zs;
    yy = q[1] * ys;
    yz = q[1] * zs;
    zz = q[2] * zs;

    R[0][0] = 1.0f - (yy + zz);
    R[1][0] = xy - wz;
    R[2][0] = xz + wy;
    R[0][1] = xy + wz;
    R[1][1] = 1.0f - (xx + zz);
    R[2][1] = yz - wx;
    R[0][2] = xz - wy;
    R[1][2] = yz + wx;
    R[2][2] = 1.0f - (xx + yy);
    R[3][0] = R[3][1] = R[3][2] = R[0][3] = R[1][3] = R[2][3] = 0.0f;
    R[3][3] = 1.0f;

    lib3ds_matrix_mult(m, R);
}

Build a quaternion from a rotation about an arbitrary axis

// Build a quaternion from a rotation about an arbitrary axis

/*!
* Compute a quaternion from axis and angle.
*
* \param c Computed quaternion (this is just a float[4])
* \param axis Rotation axis (this is just a float[3])
* \param angle Angle of rotation, radians.
*/
void lib3ds_quat_axis_angle(Lib3dsQuat c, Lib3dsVector axis, float angle)
{
    double omega, s;
    double l = sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);

    omega = -0.5 * angle;
    s = sin(omega) / l;

    c[0] = (float)s * axis[0];
    c[1] = (float)s * axis[1];
    c[2] = (float)s * axis[2];
    c[3] = (float)cos(omega);
}
« Newer Snippets
Older Snippets »
Showing 1-6 of 6 total  RSS