Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

Odd problems with raycaster...please help!

Started by jakpandora 22 replies 2.9k views
Original Post
jakpandora
jakpandora
I have been wroking on a raycaster. there are a few bugs in it, however, and I need to know how to fix it. although there are mutltiple files to the project, the bugs occur in the following one:

#include "Q3DMath.h"
#include "QuickCG.h"
#include <cmath>

Vector3::Vector3(Scalar x, Scalar y, Scalar z)
{
    this->x = x;
    this->y = y;
    this->z = z;
}

Vector3::Vector3()
{
    x = 0.0;
    y = 0.0;
    z = 0.0;
} 

Scalar Vector3::length()
{
    return sqrt(x * x + y * y + z * z);
}

Scalar length(Vector3 v)
{
    return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}

void Vector3::normalize()
{
    Scalar l = length();
    if(l != 0)
    {
        x /= l;
        y /= l;
        z /= l;
    }    
}

Vector3 normalize(Vector3 v)
{
    v.normalize();
    return v;
}

Scalar Vector3::distance(Vector3 v)
{
    return sqrt((v.x - x) * (v.x - x) + (v.y - y) * (v.y - y) + (v.z - z) * (v.z - z));
}  

Scalar distance(Vector3 v, Vector3 w)
{
    return sqrt((v.x - w.x) * (v.x - w.x) + (v.y - w.y) * (v.y - w.y) + (v.z - w.z) * (v.z - w.z));
}

Scalar Vector3::dot(Vector3 v)
{
    return v.x * x + v.y * y + v.z * z;
}             

Scalar dot(Vector3 v, Vector3 w)
{
    return v.x * w.x + v.y * w.y + v.z * w.z;
}

Vector3 Vector3::cross(Vector3 v)
{
    Vector3 u;

	u.x = ((v.y * z) - (v.z * y));
	u.y = ((v.z * x) - (v.x * z));
	u.z = ((v.x * y) - (v.y * x));
    return u;    
} 

Vector3 cross(Vector3 v, Vector3 w)
{
    Vector3 u;

	u.x = ((v.y * w.z) - (v.z * w.y));
	u.y = ((v.z * w.x) - (v.x * w.z));
	u.z = ((v.x * w.y) - (v.y * w.x));
    return u;
}

//Subtract two vectors
Vector3 operator-(Vector3 v, Vector3 w)
{
    Vector3 u;
    u.x = v.x - w.x;
    u.y = v.y - w.y;
    u.z = v.z - w.z;
    return u;
}

//Return the negative of the vector
Vector3 operator-(Vector3 v)
{
    Vector3 u;
    u.x = -v.x;
    u.y = -v.y;
    u.z = -v.z;
    return u;
}

//Add two vectors
Vector3 operator+(Vector3 v, Vector3 w)
{
    Vector3 u;
    u.x = v.x + w.x;
    u.y = v.y + w.y;
    u.z = v.z + w.z;
    return u;
}

//Multiplies a vector by a scalar
Vector3 operator*(Vector3 v, Scalar a)
{
    Vector3 w;
    w.x = v.x * a;
    w.y = v.y * a;
    w.z = v.z * a;
    return w;
}

//Multiplies a vector by a scalar
Vector3 operator*(Scalar a, Vector3 v)
{
    Vector3 w;
    w.x = v.x * a;
    w.y = v.y * a;
    w.z = v.z * a;
    return w;
}

//Divides a vector through a scalar
Vector3 operator/(Vector3 v, Scalar a)
{
    Vector3 w;
    w.x = v.x / a;
    w.y = v.y / a;
    w.z = v.z / a;
    return w;
}

//Gives the angle between two 3D vectors (in radians)
Scalar vectorAngle(Vector3 v, Vector3 w)
{
    //dot product(v,w) = length(v)*length(w)*cos(angle) ==> angle = acos(dot/(length(v)*length(w))) = acos(dot(norm(v)*norm(w)));
    Scalar cosineOfAngle = dot(normalize(v), normalize(w));
    //for acos, the value has to be between -1.0 and 1.0, but due to numerical imprecisions it sometimes comes outside this range
    if(cosineOfAngle > 1.0) cosineOfAngle = 1.0;
    if(cosineOfAngle < -1.0) cosineOfAngle = -1.0;
    return -acos(cosineOfAngle);
}

//Rotate vector v around arbitrary axis axis for angle radians
//It can only rotate around an axis through our object, to rotate around another axis:
//first translate the object to the axis, then use this function, then translate back in the new direction.
Vector3 rotateAroundArbitrary(Vector3 v, Vector3 axis, Scalar angle)
{
    if((v.x == 0) && (v.y == 0) && (v.z == 0)) return Vector3();

    Vector3 w;
    Scalar c, s, t;

    axis.normalize();

    //calculate parameters of the rotation matrix
    c = cos(angle);
    s = sin(angle);
    t = 1 - c;

    //multiply v with rotation matrix
    w.x = (t * axis.x * axis.x +          c) * v.x 
        + (t * axis.x * axis.y + s * axis.z) * v.y 
        + (t * axis.x * axis.z - s * axis.y) * v.z;
        
    w.y = (t * axis.x * axis.y - s * axis.z) * v.x 
        + (t * axis.y * axis.y +          c) * v.y 
        + (t * axis.y * axis.z + s * axis.x) * v.z;
        
    w.z = (t * axis.x * axis.z + s * axis.y) * v.x 
        + (t * axis.y * axis.z - s * axis.x) * v.y 
        + (t * axis.z * axis.z +          c) * v.z;

    w.normalize();
    w = w * v.length();
    
    return w;
}



Matrix3::Matrix3(Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g, Scalar h, Scalar i)
{
    this->a = a;
    this->b = b;
    this->c = c;
    this->d = d;
    this->e = e;
    this->f = f;
    this->g = g;
    this->h = h;
    this->i = i;
}
    
Matrix3::Matrix3()
{
    a = 0.0;
    b = 0.0;
    c = 0.0;
    d = 0.0;
    e = 0.0;
    f = 0.0;
    g = 0.0;
    h = 0.0;
    i = 0.0;
}

////////////////////////////////////////////////////////////////////////////////
//Transpose:                                                                  //
//                                                                            //
// [ a b c ]T    [ a d g ]                                                    //
// [ d e f ]  =  [ b e h ]                                                    //
// [ g h i ]     [ c f i ]                                                    //
////////////////////////////////////////////////////////////////////////////////
void Matrix3::transpose()
{
    b += d; d = b - d; b -= d; //swap b and d
    c += g; g = c - g; c -= g; //swap c and g
    f += h; h = f - h; f -= h; //swap f and h
}  

Matrix3 transpose(Matrix3 A)
{
    A.transpose();
    return A;
} 

Scalar Matrix3::determinant()
{
    Scalar det = a * e * i 
               + b * f * g 
               + d * h * c 
               - g * e * c 
               - d * b * i 
               - h * f * a;
              
    return det;
}   

Scalar determinant(Matrix3 A)
{
    return A.determinant();
}     

//Inverse of a 3x3 matrix
void Matrix3::inverse()
{
    /*
    the inverse is the adjoint divided through the determinant
    find the matrix of minors (minor = determinant of 2x2 matrix of the 2 rows/colums current element is NOT in)
    turn them in cofactors (= change some of the signs)
    find the adjoint by transposing the matrix of cofactors
    divide this through the determinant to get the inverse
    */
    
    Scalar det = determinant();
    Matrix3 B;

    //included in these calculations: minor, cofactor (changed signs), transpose (by the order of "="), division through determinant
    B.a = ( e * i - h * f) / det;
    B.b = (-b * i + h * c) / det;
    B.c = ( b * f - e * c) / det;
    B.d = (-d * i + g * f) / det;
    B.e = ( a * i - g * c) / det;
    B.f = (-a * f + d * c) / det;
    B.g = ( d * h - g * e) / det;
    B.h = (-a * h + g * b) / det;
    B.i = ( a * e - d * b) / det;
    
    *this = B;
}

Matrix3 inverse(Matrix3 A)
{
    A.inverse();
    return A;
} 

//Add two matrices
Matrix3 operator+(Matrix3 A, Matrix3 B)
{
    A.a += B.a;
    A.b += B.b;
    A.c += B.c;
    A.d += B.d;
    A.e += B.e;
    A.f += B.f;
    A.g += B.g;
    A.h += B.h;
    A.i += B.i;
    return A;
}

//Subtract two matrices
Matrix3 operator-(Matrix3 A, Matrix3 B)
{
    A.a -= B.a;
    A.b -= B.b;
    A.c -= B.c;
    A.d -= B.d;
    A.e -= B.e;
    A.f -= B.f;
    A.g -= B.g;
    A.h -= B.h;
    A.i -= B.i;
    return A;
}

//Multiply a matrix with a scalar
Matrix3 operator*(Matrix3 A, Scalar a)
{
    A.a *= a;
    A.b *= a;
    A.c *= a;
    A.d *= a;
    A.e *= a;
    A.f *= a;
    A.g *= a;
    A.h *= a;
    A.i *= a;
    return A;
}

//Multiply a matrix with a scalar
Matrix3 operator*(Scalar a, Matrix3 A)
{
    A.a *= a;
    A.b *= a;
    A.c *= a;
    A.d *= a;
    A.e *= a;
    A.f *= a;
    A.g *= a;
    A.h *= a;
    A.i *= a;
    return A;
}

//Divide a matrix through a scalar
Matrix3 operator/(Matrix3 A, Scalar a)
{
    A.a /= a;
    A.b /= a;
    A.c /= a;
    A.d /= a;
    A.e /= a;
    A.f /= a;
    A.g /= a;
    A.h /= a;
    A.i /= a;
    return A;
}

//Multiply a matrix with a column vector, resulting in a column vector
Vector3 operator*(Matrix3 A, Vector3 v)
{
    Vector3 w;
    w.x = A.a * v.x + A.b * v.y + A.c * v.z;
    w.y = A.d * v.x + A.e * v.y + A.f * v.z;
    w.z = A.g * v.x + A.h * v.y + A.i * v.z;
    return w;
}  

//Multiply a vector with a row matrix, resulting in a row vector
Vector3 operator*(Vector3 v, Matrix3 A)
{
    Vector3 w;
    w.x = A.a * v.x + A.d * v.y + A.g * v.z;
    w.y = A.b * v.x + A.e * v.y + A.h * v.z;
    w.z = A.c * v.x + A.f * v.y + A.i * v.z;
    return w;
}

//Multiply a 3x3 matrix with a 3x3 matrix
Matrix3 operator*(Matrix3 A, Matrix3 B)
{
    Matrix3 C;
    C.a = A.a * B.a + A.b * B.d + A.c * B.g;
    C.b = A.a * B.b + A.b * B.e + A.c * B.h;
    C.c = A.a * B.c + A.b * B.h + A.c * B.i;
    C.d = A.d * B.a + A.e * B.d + A.f * B.g;
    C.e = A.d * B.b + A.e * B.e + A.f * B.h;
    C.f = A.d * B.c + A.e * B.h + A.f * B.i;
    C.g = A.g * B.a + A.h * B.d + A.i * B.g;
    C.h = A.g * B.b + A.h * B.e + A.i * B.h;
    C.i = A.g * B.c + A.h * B.h + A.i * B.i;
    return C;
}



//Camera functions

/*
Note: 
Every function that changes u, v or dir should use "generateMatrix();" at the end,
unless that function already calls another one that generates it, at the end.
*/
Camera::Camera(Scalar posx, Scalar posy, Scalar posz, Scalar ux, Scalar uy, Scalar uz, Scalar vx, Scalar vy, Scalar vz, Scalar dirx, Scalar diry, Scalar dirz, Scalar nearClip, Scalar farClip)
{
    pos.x = posx;
    pos.y = posy;
    pos.z = posz;
    u.x = ux;
    u.y = uy;
    u.z = uz;
    v.x = vx;
    v.y = vy;
    v.z = vz;
    dir.x = dirx;
    dir.y = diry;
    dir.z = dirz;
    this->nearClip = nearClip;
    this->farClip = farClip;
    generateMatrix();
}    

//Construct a camera with default parameters
Camera::Camera()
{
    pos.x = 0.0;
    pos.y = 0.0;
    pos.z = 0.0;
    u.x = 1.0;
    u.y = 0.0;
    u.z = 0.0;
    v.x = 0.0;
    v.y = 1.0;
    v.z = 0.0;
    dir.x = 0.0;
    dir.y = 0.0;
    dir.z = 1.0;
    nearClip = 0.1;
    farClip = 1000000.0;
    generateMatrix();        
}

Vector3 Camera::getU()
{
    return u;
}    
Vector3 Camera::getV()
{
    return v;
}    
Vector3 Camera::getDir()
{
    return dir;
}    
Vector3 Camera::getPos()
{
    return pos;
}

void Camera::setU(Vector3 newU)
{
    u = newU;
    generateMatrix();
}    
void Camera::setV(Vector3 newV)    
{
    v = newV;
    generateMatrix();
}

void Camera::setDir(Vector3 newDir)    
{
    dir = newDir;
    generateMatrix();
}    

void Camera::setPos(Vector3 newPos)
{
    pos = newPos;
} 

void Camera::move(Vector3 offset)
{
    pos = pos + offset;
}  

void Camera::rotate(Vector3 axis, Scalar angle)
{
    u = rotateAroundArbitrary(u, axis, angle);
    v = rotateAroundArbitrary(v, axis, angle);
    dir = rotateAroundArbitrary(dir, axis, angle);
    generateMatrix();
}   

//Look in a certain direction.
void Camera::setLookDir(Vector3 newDir)
{
    Vector3 axis = cross(dir, newDir);
    if(axis.length() == 0) return;
    
    Scalar angle = vectorAngle(dir, newDir);
    if(angle != 0) rotate(axis, angle);   
}

//Look at a certain point (the point will come in the center of the screen, if nothing's in front of it that is)
void Camera::lookAt(Vector3 lookAtMe)
{
    setLookDir(lookAtMe - pos);
}

Scalar Camera::getDist(Vector3 point)
{
    return distance(pos, point);
}

//Set the distance to a point
void Camera::setDist(Vector3 point, Scalar dist)
{
    Scalar currentDist = distance(pos, point);
    move(currentDist * normalize(point - pos));
}    

void Camera::zoom(Scalar a)
{
    //increasing length of dir or decreasing length of the plane (u and v) = zoom IN
    u = u / a;
    v = v / a;
    generateMatrix();
}

void Camera::zoomU(Scalar a)
{
    u = u / a;
    generateMatrix();
}

void Camera::zoomV(Scalar a)
{
    v = v / a;
    generateMatrix();
}

Scalar Camera::getZoomU()
{
   return(dir.length() / u.length());
}

Scalar Camera::getZoomV()
{
   return(dir.length() / v.length());
}

void Camera::setZoomU(Scalar a)
{
    u = u / (a / getZoomU());
    generateMatrix();
}

void Camera::setZoomV(Scalar a)
{
    v = v / (a / getZoomV());
    generateMatrix();
}    

Scalar Camera::getFOVU()
{
    return(2.0 * atan2(u.length(), dir.length()));
}

Scalar Camera::getFOVV()
{
    return(2.0 * atan2(v.length(), dir.length()));
}

void Camera::setFOVU(Scalar angle)
{
    setZoomU(1.0 / tan(angle / 2.0));
}

void Camera::setFOVV(Scalar angle)
{
    setZoomV(1.0 / tan(angle / 2.0));
}     

////////////////////////////////////////////////////////////////////////////////
//Functions to get Yaw, Pitch and Roll. Normally to do things with the camera, 
//you never need these angles, everything works with vectors!
//However, these can be useful if you want a compass in your game, or a weapon 
//that allows you to accurately change it's pitch
////////////////////////////////////////////////////////////////////////////////

/*
Yaw is the wind direction the camera is looking at if you'd be standing on planet earth, and the ground has vectors X and Z, while Y points to the sky
       N
       ^ 
       |z 
       |   x        Looking in the direction Z = North (0°, 0 rad)
W -----+-----> E    Looking in the direction X = East (+90°, +1.57 rad)
       |            Looking in negative Z = South (180°, 3.1415 rad, sign jump)
       |            Looking in negative X = West (-90°, -1.57 rad)
       |
       S
*/
Scalar Camera::getYaw()
{    
    //the atan2 function returns the angle of a 2D point (like from polar coordinates), so here it gives angle of dir projected on XZ plane, which is what we want for the yaw
    return(atan2(dir.x, dir.z));
}

//setYaw can be used to make you look at a certain wind direction (where the ground is the XZ plane)
void Camera::setYaw(Scalar angle)
{    
    Scalar currentAngle = getYaw();
    //to change yaw, you have to rotate around the "up" axis of the WORLD = the y axis
    rotate(Vector3(0,1,0), - angle + currentAngle);
}

//rotates camera around world Y-axis with given angle (in space this would make no sense since there isn't really an "up" or "down" of the world, instead you rotate around the "up" and "down" of your own spaceship there
//When rolled, yawPlanet will give very annoying rotation, so for a spacegame or flight simulator you'll want to use yawSpace instead.
void Camera::yawPlanet(Scalar angle)
{    
    rotate(Vector3(0,1,0), angle);
}

//rotates camera around camera v axis with given angle (this one makes sense in space, but not on a planet, on a planet your camera would start getting a "roll")
void Camera::yawSpace(Scalar angle)
{    
    rotate(v, angle);
}

/*
Pitch is only useful to define if you're standing on a plane or a planet, and there's a sky
The plane you're standing on is the XZ plane, and Y points to the sky
Pitch is 0° if you look forward (direction vector parallel to the XZ plane)
Pitch is +90° if you look to the sky (maximum "up")
Pitch is -90° if you look at the ground (maximum "down")
Pitches of more than 90° or less than -90° aren't defined, since these can also be made by having  yaw 180° rotated and having a pitch between -90° and +90°
*/
Scalar Camera::getPitch()
{
    //Project dir on the XZ plane
    //Then find angle between dir and projected dir   
    //With atan2: angle of the point (lengthof2Dvector(dir.x, dir.z), dir.y)
    return atan2(dir.y, sqrt(dir.x * dir.x + dir.z * dir.z));
}

/*
setPitch can be used to make you look to the sky or floor with certain angle without changing wind direction
NOT useful for spacecrafts etc... because there's no up or down in space and X, Y and Z axes have no physical meaning there
only useful for FPS games or other games where you walk on a planet surface
*/
void Camera::setPitch(Scalar angle)
{    
    Scalar currentAngle = getPitch();
    //to change pitch, you have to rotate around the horizontal vector of the camera
    rotate(u, angle - currentAngle);
}

//pitches the camera over a certain amount
void Camera::pitch(Scalar angle)
{    
    rotate(u, angle);
}

/*
Roll is only necessary for spacegames, flightsimulators or rare effects of FPS games
Roll 0° = cam.u parallel with XZ plane, cam.v points upwards
Roll +90° = cam.v parallel with XZ plane, cam.u points downwards
Roll +-180° = cam.u parallel with XZ plane, cam.v points downwards (= you're upside down)
Roll -90° = cam.v parallel with XZ plane, cam.u points upwards
In space games the angles have no physical meaning, but in the coordinate system this angle is an "Euler" angle.
*/
Scalar Camera::getRoll()
{
    //roll is the angle between the plane (world_up, camera_dir) and the plane (camera_up, camera_dir)
    //the angle between two planes is the angle between their normals
    //the normals are gotten with cross products
    //the vectorAngle function uses acos and dot product
    Scalar roll = vectorAngle(cross(Vector3(0, 1, 0), dir), cross(v, dir));
    if(u.y < 0) roll = -roll;
    return roll;
}

void Camera::setRoll(Scalar angle)
{    
    Scalar currentAngle = getRoll();
    //to change roll, you have to rotate around the direction vector of the camera
    rotate(dir, angle - currentAngle);
}

//rolls the camera by rotating it around the direction vector (only makes sense in space or for "shaking" effects)
void Camera::roll(Scalar angle)
{    
    rotate(dir, angle);
}

//makes u, v and dir perpendicular by using cross product, maintains exact direction and roll if only v was skewed
scalar Camera::resetSkewU()
{
    Scalar oldZoomU = getZoomU(); 
    Scalar oldZoomV = getZoomV();
    u = cross(dir, v);
    v = cross(dir, -u);
    setZoomU(oldZoomU);
    setZoomV(oldZoomV);
}

//makes u, v and dir perpendicular by using cross product, maintains exact direction and roll if only u was skewed
scalar Camera::resetSkewV()
{
    Scalar oldZoomU = getZoomU(); 
    Scalar oldZoomV = getZoomV();
    v = cross(dir, u);
    u = cross(dir, -v);
    setZoomU(oldZoomU);
    setZoomV(oldZoomV);
}

//get and set screen ratios of the camera (ratio of length of u and v, e.g. 4:3, 16:9, 640:480, ...)
Scalar Camera::getRatioUV()
{
    return u.length() / v.length();
}    

Scalar Camera::getRatioVU()
{
    return v.length() / u.length();
}

//changes V    
void Camera::setRatioUV(Scalar ratio)
{
    v.normalize();
    v = v * u.length() / ratio;
    generateMatrix();    
}    

//changes U
void Camera::setRatioVU(Scalar ratio)
{
    u.normalize();
    u = u * v.length() / ratio;
    generateMatrix();
} 

//scale U, V and Dir without changing what you see
Scalar Camera::getScale()
{
    return dir.length();
}    
void Camera::setScale(Scalar dirLength)
{
    scale(dir.length() / dirLength);
}
    
void Camera::scale(Scalar factor)    
{
    dir = dir * factor;
    u = u * factor;
    v = v * factor;
    generateMatrix();
}    

void Camera::generateMatrix()
{
    //the cameraMatrix is generated, this is the matrix with 3 column vectors: u, v and dir
    //it has to be generated everytime u, v or dir are changed  
    camMatrix.a = u.x;
    camMatrix.d = u.y;
    camMatrix.g = u.z;
    camMatrix.b = v.x;
    camMatrix.e = v.y;
    camMatrix.h = v.z;
    camMatrix.c = dir.x;
    camMatrix.f = dir.y;
    camMatrix.i = dir.z;

    //this is the inverse of the camMatrix, to use for transformations
    invCamMatrix = inverse(camMatrix);
}

Matrix3 Camera::getMatrix()
{
    return camMatrix;
}

Matrix3 Camera::getInvMatrix()
{
    return invCamMatrix;
}

void Camera::setMatrix(Matrix3 matrix)
{
    //to make sure the vectors and the matrix are according to each other, set the vectors to the given matrix 
    //and then use generateMatrix with these new vectors
    u.x = matrix.a;
    u.y = matrix.d;
    u.z = matrix.g;
    v.x = matrix.b;
    v.y = matrix.e;
    v.z = matrix.h;
    dir.x = matrix.c;
    dir.y = matrix.f;
    dir.z = matrix.i;
    generateMatrix();
} 

Vector3 Camera::transform(Vector3 v)
{
    /*
    Transformation from coordinate system 1 (base 1) to coordinate system 2 (base 2):
        
    vector v = coordinates of point p in base 1 (column vector)
    matrix A = the 3 vectors representing coordinates of unit vectors of base 2 in base 1 (3 column vectors in matrix)
    vector w = coordinates of point p in base 2(column vector)
    
    Then: v = A * w
          w = A^(-1) * v
    
    Now: base 1 = worldspace, base 2 = cameraspace
    v = coordinates of point in worldspace (the given v )
    A = the matrix from the camera: the coordinates of the camera vectors in worldspace
    w = coordinates of point in cameraspace
    
    So our transformation is w = A^(-1) * v, where v is the parameter given to the function, and A = perspective matrix of camera
    
    All this text to describe only one line of code...
    */
    
    return invCamMatrix * v;  
}

/*
uses the transform function of the camera, to project a point on screen, stores result in x and y (screen coordinates)
returns 1 if point is legal, 0 if point is behind camera, outside screen, ...
also stores z value of the point in camera coordinates in z
*/
bool Camera::projectOnScreen(Vector3 point, int & x, int & y, Scalar & z)
{
    //First transformation: position
    Vector3 a = point - pos;
    
    //Second transformation: rotation
    Vector3 b = transform(a);
    
    //Third transformation: Projection on screen
    //be warned: if b.z is too small, you get integer imprecisions, so don't make near clipping plane too small    
    int px = int(w / 2.0 + w * b.x / b.z);
    int py = int(h / 2.0 - h * b.y / b.z); //inversed: y should be "up", while in screen coordinates it's down
    if(onScreen(px, py) && b.z >= nearClip)
    {
        x = px;
        y = py;
        z = b.z;
        return 1;
    }
    else
    {
        x = px;
        y = py;
        z = b.z;
        return 0;
    }        
}

bool Camera::projectOnScreen(Vector3 point, int & x, int & y)
{
    Scalar z;
    return projectOnScreen(point, x, y, z);       
} 

bool Camera::camSpaceToScreen(Vector3 point, int & x, int & y)
{
    //be warned: if point.z is too small, you get integer imprecisions, so don't make near clipping plane too small
    int px = int(w / 2.0 + w * point.x / point.z);
    int py = int(h / 2.0 - h * point.y / point.z); //inversed: y should be "up", while in screen coordinates it's down
    if(onScreen(px, py) && point.z >= nearClip)
    {
        x = px;
        y = py;
        return 1;
    }
    else
    {
        x = px;
        y = py;
        return 0;
    }       
}    


//Auxiliary Functions


//Swap between radians and degrees
Scalar radToDeg(Scalar rad)
{
    return 360.0 * rad / (3.14159 * 2.0);
} 

Scalar degToRad(Scalar deg)
{
    return (3.14159 * 2.0) * deg / 360.0;
}    

//TO DO:
//Z-buffer
//drawLine and disk functions that use the zbuffer

I get the following errors: --------------------Configuration: Wolfenstein raycaster - Win32 Debug-------------------- Compiling... Q3DMath.cpp C:\Program Files\Microsoft Visual Studio\MyProjects\Wolfenstein raycaster\Q3DMath.cpp(736) : error C2143: syntax error : missing ';' before 'tag::id' C:\Program Files\Microsoft Visual Studio\MyProjects\Wolfenstein raycaster\Q3DMath.cpp(736) : error C2501: 'scalar' : missing storage-class or type specifiers C:\Program Files\Microsoft Visual Studio\MyProjects\Wolfenstein raycaster\Q3DMath.cpp(736) : fatal error C1004: unexpected end of file found Error executing cl.exe. Wolfenstein raycaster.exe - 3 error(s), 0 warning(s) could someone tell me whats wrong? also odd is the fact that last time I compiled the project, I was having different errors, something to do with scalar. could someone tell me if those are ok also?
______________________________My website: Quest Networks
nts
nts
all the errors occur on line 736, no body is going to count the lines to find where the error is. Maybe you can go into VS, go to the line with the error on it and post that line here. I'm sure you would get a lot more help.

btw how much of that is your code? maybe the original source may be of help.
stormrunner
stormrunner
indeed, friend. i plugged that into dev-c++, and on line 736 you have typed ' Scalar ' - however it seems you use it two different ways - ' Scalar ' & ' scalar ' in the preceeding function. perhaps double checking that would help - are they separate return types ?.
line 736 =
Scalar Camera::getRatioVU(){    return v.length() / u.length();} <-- line 736

hope that helps.
as compared to
scalar Camera::resetSkewV() { /* insert function here */ }
stormrunner
Eelco
Eelco
what do you need a 3d vector for in a wolfenstein like game anyway?
Kyle N
Kyle N
It looks like your return types for the functions resetSkewU and resetSkewV are wrong. It seems you need to change 'scalar' to 'Scalar' if you intend to return a scalar value. But it doesnt seem you even return anything at the moment in those functions, so perhaps they should just return void.

Kyle
jakpandora
jakpandora
all of the code I have posted is not mine, and got it off of a site as part of a tutorial. I was more interested in focusing on the content of the game instead of programming most of it, so I found a raycasting tutorial(I dont even remeber the site anymore, sorry) I will check out the scalar thing(though this is exaclty how I got it online. I cut and pasted it) is there any way to find line 736 without counting every single line?

*EDIT* there were only two places where SCALAR was lower case and not capital. when I changed them to capital, I got more errors:

--------------------Configuration: Wolfenstein raycaster - Win32 Debug--------------------
Compiling...
Q3DMath.cpp
C:\Program Files\Microsoft Visual Studio\MyProjects\Wolfenstein raycaster\Q3DMath.cpp(737) : error C2556: 'double __thiscall Camera::resetSkewU(void)' : overloaded function differs only by return type from 'class Vector3 __thiscall Camera::resetSkew
U(void)'
c:\program files\microsoft visual studio\myprojects\wolfenstein raycaster\q3dmath.h(174) : see declaration of 'resetSkewU'
C:\Program Files\Microsoft Visual Studio\MyProjects\Wolfenstein raycaster\Q3DMath.cpp(737) : error C2371: 'resetSkewU' : redefinition; different basic types
c:\program files\microsoft visual studio\myprojects\wolfenstein raycaster\q3dmath.h(174) : see declaration of 'resetSkewU'
C:\Program Files\Microsoft Visual Studio\MyProjects\Wolfenstein raycaster\Q3DMath.cpp(748) : error C2556: 'double __thiscall Camera::resetSkewV(void)' : overloaded function differs only by return type from 'class Vector3 __thiscall Camera::resetSkew
V(void)'
c:\program files\microsoft visual studio\myprojects\wolfenstein raycaster\q3dmath.h(175) : see declaration of 'resetSkewV'
C:\Program Files\Microsoft Visual Studio\MyProjects\Wolfenstein raycaster\Q3DMath.cpp(748) : error C2371: 'resetSkewV' : redefinition; different basic types
c:\program files\microsoft visual studio\myprojects\wolfenstein raycaster\q3dmath.h(175) : see declaration of 'resetSkewV'
Error executing cl.exe.

Wolfenstein raycaster.exe - 4 error(s), 0 warning(s)
______________________________My website: Quest Networks
nts
nts
Quote:
Original post by jakpandora
...though this is exaclty how I got it online. I cut and pasted it...


famous last words there buddy,

in VS.NET you can enable line numbers (at the left of the document), they are also displayed at the bottom of the document (Ln _ Col _ Ch _) and i believe there is also a goto line dialog somewhere in there.

The errors, random copying/pasting and random editing related. You changed the definition but didn't change the prototype/declaration.

btw by copying and pasting you are never going to learn how to do it yourself, and as you have just seen most of the time it doesn't work.
jakpandora
jakpandora
I know ill never learn, I never really wanted to learn the code in this file. it was never even taught in the tutorial. and it wasnt simply random copy and pasting. I copied the whole file and put everything where its supposed to go. and I use mscv C++ 6.0, not .NET. and from what I can see, there is only a prototyype.
______________________________My website: Quest Networks
jakpandora
jakpandora
come on! could someone please help!
______________________________My website: Quest Networks
stormrunner
stormrunner
well, since you aren't a coder i'm not sure what you can do. but i'll spare you the lecture.
Quote:
C:\Program Files\Microsoft Visual Studio\MyProjects\Wolfenstein raycaster\Q3DMath.cpp(737) : error C2556: 'double __thiscall Camera::resetSkewU(void)' : overloaded function differs only by return type from 'class Vector3 __thiscall Camera::resetSkew
U(void)'

this, and all the others that refer to the bold section, means that you (or whomever you got this from) attempted to overload an operator by return type only, without changing the parameters. because you are using VC6, it won't compile because VC6 doesn't support partial-variable specialization (or whatever its called). you can overload a function in VC6 by changing the return type and parameters, something you probably don't want to do. however, a simpler solution would be to find a different compiler that does support that. and check the function definitions of those referenced (i didn't go through it).
also, as an after thought, you might want to check the headers for exactly what 'scalar' and 'Scalar' actually reference, perhaps they are valid. i'm assuming they're typdef floats or something.
stormrunner
Axenation
Axenation
The author's name is Lode Vandevenne.

His GameDev.net username is Lode.

His website is http://www.student.kuleuven.ac.be/~m0216922/CG/
and it's full of great tutorials so i suggest you read more of the tutorials.

--------------------------------------------------------------

Quote:

I know ill never learn, I never really wanted to learn the code in this file. it was never even taught in the tutorial.


Perhaps you should read "all" of the tutorials on the site, maybe even the one on 3D Math.

this is what i changed to fix the errors using MSVC6.0

original code:
//makes u, v and dir perpendicular by using cross product, maintains exact direction and roll if only v was skewedscalar Camera::resetSkewU(){    Scalar oldZoomU = getZoomU();     Scalar oldZoomV = getZoomV();    u = cross(dir, v);    v = cross(dir, -u);    setZoomU(oldZoomU);    setZoomV(oldZoomV);}//makes u, v and dir perpendicular by using cross product, maintains exact direction and roll if only u was skewedscalar Camera::resetSkewV(){    Scalar oldZoomU = getZoomU();     Scalar oldZoomV = getZoomV();    v = cross(dir, u);    u = cross(dir, -v);    setZoomU(oldZoomU);    setZoomV(oldZoomV);}


my edit:
//makes u, v and dir perpendicular by using cross product, maintains exact direction and roll if only v was skewedVector3 Camera::resetSkewU(){    Scalar oldZoomU = getZoomU();     Scalar oldZoomV = getZoomV();    u = cross(dir, v);    v = cross(dir, -u);    setZoomU(oldZoomU);    setZoomV(oldZoomV);    // added due to error    return u;}//makes u, v and dir perpendicular by using cross product, maintains exact direction and roll if only u was skewedVector3 Camera::resetSkewV(){    Scalar oldZoomU = getZoomU();     Scalar oldZoomV = getZoomV();    v = cross(dir, u);    u = cross(dir, -v);    setZoomU(oldZoomU);    setZoomV(oldZoomV);    //added due to error    return v;}



Now I get a cookie!
jakpandora
jakpandora
Thank you very much! sorry if I annoyed anyone with this. ill rate you all up.
______________________________My website: Quest Networks
jakpandora
jakpandora
I got more errors when I changed my code to what axenation wrote.



--------------------Configuration: Wolfenstein raycaster - Win32 Debug--------------------
Compiling...
Q3DMath.cpp
Linking...
main.obj : error LNK2001: unresolved external symbol "unsigned char * inkeys" (?inkeys@@3PAEA)
main.obj : error LNK2001: unresolved external symbol "void __cdecl readKeys(void)" (?readKeys@@YAXXZ)
main.obj : error LNK2001: unresolved external symbol "void __cdecl cls(struct ColorRGB)" (?cls@@YAXUColorRGB@@@Z)
main.obj : error LNK2001: unresolved external symbol "void __cdecl redraw(void)" (?redraw@@YAXXZ)
main.obj : error LNK2001: unresolved external symbol "int __cdecl fprint(double,int,int,int,struct ColorRGB,bool,struct ColorRGB,bool,int)" (?fprint@@YAHNHHHUColorRGB@@_N01H@Z)
main.obj : error LNK2001: unresolved external symbol "float __cdecl getTime(void)" (?getTime@@YAMXZ)
main.obj : error LNK2001: unresolved external symbol "bool __cdecl verLine(int,int,int,struct ColorRGB)" (?verLine@@YA_NHHHUColorRGB@@@Z)
main.obj : error LNK2001: unresolved external symbol "struct ColorRGB __cdecl operator/(struct ColorRGB,int)" (??K@YA?AUColorRGB@@U0@H@Z)
main.obj : error LNK2001: unresolved external symbol "public: __thiscall ColorRGB::ColorRGB(unsigned char,unsigned char,unsigned char)" (??0ColorRGB@@QAE@EEE@Z)
main.obj : error LNK2001: unresolved external symbol "public: __thiscall ColorRGB::ColorRGB(void)" (??0ColorRGB@@QAE@XZ)
main.obj : error LNK2001: unresolved external symbol "int h" (?h@@3HA)
Q3DMath.obj : error LNK2001: unresolved external symbol "int h" (?h@@3HA)
main.obj : error LNK2001: unresolved external symbol "int w" (?w@@3HA)
Q3DMath.obj : error LNK2001: unresolved external symbol "int w" (?w@@3HA)
main.obj : error LNK2001: unresolved external symbol "bool __cdecl done(void)" (?done@@YA_NXZ)
main.obj : error LNK2001: unresolved external symbol "void
__cdecl screen(int,int,bool,char *)" (?screen@@YAXHH_NPAD@Z)
Q3DMath.obj : error LNK2001: unresolved external symbol "bool __cdecl onScreen(int,int)" (?onScreen@@YA_NHH@Z)
Debug/Wolfenstein raycaster.exe : fatal error LNK1120: 15 unresolved externals
Error executing link.exe.

Wolfenstein raycaster.exe - 18 error(s), 0 warning(s)



any help? also when I try to debug my project, I have to build it first. however, it wont build because there are errors in the code, so how am I supposed to debug?

______________________________My website: Quest Networks
Ajare
Ajare
Well, your program has compiled. It's the linking stage that it's failing at now. Basically, what is happening is that you have declared the functions prototypes, but the linker cannot find the actual code that these prototypes refer to. There's probably a library file that needs including into the project. QuickCG.lib or QuickCG.dll perhaps?

Could you give the list of all the files in the project?
jakpandora
jakpandora
sure. here are al the files and the code that goes with them.

main.cpp

#include <math.h>#include <stdio.h>#include <iostream>#include <SDL/SDL.h>#include "QuickCG.h"#pragma comment(lib, "SDL.lib")#pragma comment(lib, "SDLmain.lib")#define mapWidth 24#define mapHeight 24int worldMap[mapWidth][mapHeight]={	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1,	1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1,	1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};Scalar rayPosX = 22, rayPosY = 12;Scalar rayDirX = -1, rayDirY = 0;Scalar posX = 22, posY = 12;  //x and y start positionScalar dirX = -1, dirY = 0; //initial direction vectorScalar planeX = 0, planeY = 0.66; //the 2d raycaster version of camera planeScalar time = 0; //time of current frameScalar oldTime = 0; //time of previous frameint main(int argc, char *argv[]){	screen(640, 480, false, "Raycaster");	while(!done())	{		SDL_Delay(5); //sacrifice 5 milliseconds per frame to free some CPU time		for(int x = 0; x < w; x++)		{            			//calculate ray position and direction			Scalar cameraX = 2 * x / Scalar(w) - 1; //x-coordinate in camera space			Scalar rayPosX = posX;			Scalar rayPosY = posY;			Scalar rayDirX = dirX + planeX * cameraX;			Scalar rayDirY = dirY + planeY * cameraX;					//which box of the map we're in			int mapX = int(rayPosX);			int mapY = int(rayPosY);			//length of ray from current position to next x or y-side			Scalar sideDistX;			Scalar sideDistY;			//length of ray from one x or y-side to next x or y-side			Scalar deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));			Scalar deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));			Scalar perpWallDist;			//what direction to step in x or y-direction (either +1 or -1)			int stepX;			int stepY;   			int hit = 0; //was there a wall hit?			int side; //was a NS or a EW wall hit?			//calculate step and initial sideDist			if (rayDirX < 0)			{				stepX = -1;				sideDistX = (rayPosX - mapX) * deltaDistX;			}			else			{				stepX = 1;				sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;			}           			if (rayDirY < 0)			{				stepY = -1;				sideDistY = (rayPosY - mapY) * deltaDistY;			}			else			{				stepY = 1;				sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;			}			//perform DDA			while (hit == 0)			{                   				//jump to next map square, OR in x-direction, OR in y-direction				if (sideDistX < sideDistY)				{					sideDistX += deltaDistX;					mapX += stepX;					side = 0;				}				else				{					sideDistY += deltaDistY;					mapY += stepY;					side = 1;				}               				//Check if ray has hit a wall				if (worldMap[mapX][mapY] > 0) hit = 1;              			} 			//Calculate distance projected on camera direction (oblique distance will give fisheye effect!)			if (side == 0)				perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);			else				perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);			//Calculate height of line to draw on screen			int lineHeight = abs(int(h / perpWallDist));        			//calculate lowest and highest pixel to fill in current stripe			int drawStart = -lineHeight / 2 + h / 2;			if(drawStart < 0)drawStart = 0;			int drawEnd = lineHeight / 2 + h / 2;			if(drawEnd >= h)drawEnd = h - 1;     			//choose wall color			ColorRGB color;			switch(worldMap[mapX][mapY])			{			case 1:  color = RGB_Red;    break; //red			case 2:  color = RGB_Green;  break; //green			case 3:  color = RGB_Blue;   break; //blue			case 4:  color = RGB_White;  break; //white			default: color = RGB_Yellow; break; //yellow			}			//give x and y sides different brightness			if (side == 1) {color = color / 2;}            			//draw the pixels of the stripe as a vertical line			verLine(x, drawStart, drawEnd, color);		}		//timing for input and FPS counter		oldTime = time;		time = getTime();		Scalar frameTime = (time - oldTime) / 1000.0; //frameTime is the time this frame has taken, in seconds		fprint(1.0 / frameTime); //FPS counter		redraw();		cls();		//speed modifiers		Scalar moveSpeed = frameTime * 5.0; //the constant value is in squares/second		Scalar rotSpeed = frameTime * 3.0; //the constant value is in radians/second		readKeys();		//move forward if no wall in front of you		if (inkeys[SDLK_UP])		{			if(worldMap[int(posX + dirX * moveSpeed)][int(posY)] == false) posX += dirX * moveSpeed;			if(worldMap[int(posX)][int(posY + dirY * moveSpeed)] == false) posY += dirY * moveSpeed;		}		//move backwards if no wall behind you		if (inkeys[SDLK_DOWN])		{			if(worldMap[int(posX - dirX * moveSpeed)][int(posY)] == false) posX -= dirX * moveSpeed;			if(worldMap[int(posX)][int(posY - dirY * moveSpeed)] == false) posY -= dirY * moveSpeed;		}    		//rotate to the right		if (inkeys[SDLK_RIGHT])		{			//both camera direction and camera plane must be rotated			Scalar oldDirX = dirX;			dirX = dirX * cos(-rotSpeed) - dirY * sin(-rotSpeed);			dirY = oldDirX * sin(-rotSpeed) + dirY * cos(-rotSpeed);			Scalar oldPlaneX = planeX;			planeX = planeX * cos(-rotSpeed) - planeY * sin(-rotSpeed);			planeY = oldPlaneX * sin(-rotSpeed) + planeY * cos(-rotSpeed);		}		//rotate to the left		if (inkeys[SDLK_LEFT])		{			//both camera direction and camera plane must be rotated			Scalar oldDirX = dirX;			dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed);			dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed);			Scalar oldPlaneX = planeX;			planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed);			planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed);		}        	}	return 0;}



Q3DMath.cpp

#include "Q3DMath.h"#include "QuickCG.h"#include <cmath>Vector3::Vector3(Scalar x, Scalar y, Scalar z){    this->x = x;    this->y = y;    this->z = z;}Vector3::Vector3(){    x = 0.0;    y = 0.0;    z = 0.0;} Scalar Vector3::length(){    return sqrt(x * x + y * y + z * z);}Scalar length(Vector3 v){    return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);}void Vector3::normalize(){    Scalar l = length();    if(l != 0)    {        x /= l;        y /= l;        z /= l;    }    }Vector3 normalize(Vector3 v){    v.normalize();    return v;}Scalar Vector3::distance(Vector3 v){    return sqrt((v.x - x) * (v.x - x) + (v.y - y) * (v.y - y) + (v.z - z) * (v.z - z));}  Scalar distance(Vector3 v, Vector3 w){    return sqrt((v.x - w.x) * (v.x - w.x) + (v.y - w.y) * (v.y - w.y) + (v.z - w.z) * (v.z - w.z));}Scalar Vector3::dot(Vector3 v){    return v.x * x + v.y * y + v.z * z;}             Scalar dot(Vector3 v, Vector3 w){    return v.x * w.x + v.y * w.y + v.z * w.z;}Vector3 Vector3::cross(Vector3 v){    Vector3 u;	u.x = ((v.y * z) - (v.z * y));	u.y = ((v.z * x) - (v.x * z));	u.z = ((v.x * y) - (v.y * x));    return u;    } Vector3 cross(Vector3 v, Vector3 w){    Vector3 u;	u.x = ((v.y * w.z) - (v.z * w.y));	u.y = ((v.z * w.x) - (v.x * w.z));	u.z = ((v.x * w.y) - (v.y * w.x));    return u;}//Subtract two vectorsVector3 operator-(Vector3 v, Vector3 w){    Vector3 u;    u.x = v.x - w.x;    u.y = v.y - w.y;    u.z = v.z - w.z;    return u;}//Return the negative of the vectorVector3 operator-(Vector3 v){    Vector3 u;    u.x = -v.x;    u.y = -v.y;    u.z = -v.z;    return u;}//Add two vectorsVector3 operator+(Vector3 v, Vector3 w){    Vector3 u;    u.x = v.x + w.x;    u.y = v.y + w.y;    u.z = v.z + w.z;    return u;}//Multiplies a vector by a scalarVector3 operator*(Vector3 v, Scalar a){    Vector3 w;    w.x = v.x * a;    w.y = v.y * a;    w.z = v.z * a;    return w;}//Multiplies a vector by a scalarVector3 operator*(Scalar a, Vector3 v){    Vector3 w;    w.x = v.x * a;    w.y = v.y * a;    w.z = v.z * a;    return w;}//Divides a vector through a scalarVector3 operator/(Vector3 v, Scalar a){    Vector3 w;    w.x = v.x / a;    w.y = v.y / a;    w.z = v.z / a;    return w;}//Gives the angle between two 3D vectors (in radians)Scalar vectorAngle(Vector3 v, Vector3 w){    //dot product(v,w) = length(v)*length(w)*cos(angle) ==> angle = acos(dot/(length(v)*length(w))) = acos(dot(norm(v)*norm(w)));    Scalar cosineOfAngle = dot(normalize(v), normalize(w));    //for acos, the value has to be between -1.0 and 1.0, but due to numerical imprecisions it sometimes comes outside this range    if(cosineOfAngle > 1.0) cosineOfAngle = 1.0;    if(cosineOfAngle < -1.0) cosineOfAngle = -1.0;    return -acos(cosineOfAngle);}//Rotate vector v around arbitrary axis axis for angle radians//It can only rotate around an axis through our object, to rotate around another axis://first translate the object to the axis, then use this function, then translate back in the new direction.Vector3 rotateAroundArbitrary(Vector3 v, Vector3 axis, Scalar angle){    if((v.x == 0) && (v.y == 0) && (v.z == 0)) return Vector3();    Vector3 w;    Scalar c, s, t;    axis.normalize();    //calculate parameters of the rotation matrix    c = cos(angle);    s = sin(angle);    t = 1 - c;    //multiply v with rotation matrix    w.x = (t * axis.x * axis.x +          c) * v.x         + (t * axis.x * axis.y + s * axis.z) * v.y         + (t * axis.x * axis.z - s * axis.y) * v.z;            w.y = (t * axis.x * axis.y - s * axis.z) * v.x         + (t * axis.y * axis.y +          c) * v.y         + (t * axis.y * axis.z + s * axis.x) * v.z;            w.z = (t * axis.x * axis.z + s * axis.y) * v.x         + (t * axis.y * axis.z - s * axis.x) * v.y         + (t * axis.z * axis.z +          c) * v.z;    w.normalize();    w = w * v.length();        return w;}Matrix3::Matrix3(Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g, Scalar h, Scalar i){    this->a = a;    this->b = b;    this->c = c;    this->d = d;    this->e = e;    this->f = f;    this->g = g;    this->h = h;    this->i = i;}    Matrix3::Matrix3(){    a = 0.0;    b = 0.0;    c = 0.0;    d = 0.0;    e = 0.0;    f = 0.0;    g = 0.0;    h = 0.0;    i = 0.0;}//////////////////////////////////////////////////////////////////////////////////Transpose:                                                                  ////                                                                            //// [ a b c ]T    [ a d g ]                                                    //// [ d e f ]  =  [ b e h ]                                                    //// [ g h i ]     [ c f i ]                                                    //////////////////////////////////////////////////////////////////////////////////void Matrix3::transpose(){    b += d; d = b - d; b -= d; //swap b and d    c += g; g = c - g; c -= g; //swap c and g    f += h; h = f - h; f -= h; //swap f and h}  Matrix3 transpose(Matrix3 A){    A.transpose();    return A;} Scalar Matrix3::determinant(){    Scalar det = a * e * i                + b * f * g                + d * h * c                - g * e * c                - d * b * i                - h * f * a;                  return det;}   Scalar determinant(Matrix3 A){    return A.determinant();}     //Inverse of a 3x3 matrixvoid Matrix3::inverse(){    /*    the inverse is the adjoint divided through the determinant    find the matrix of minors (minor = determinant of 2x2 matrix of the 2 rows/colums current element is NOT in)    turn them in cofactors (= change some of the signs)    find the adjoint by transposing the matrix of cofactors    divide this through the determinant to get the inverse    */        Scalar det = determinant();    Matrix3 B;    //included in these calculations: minor, cofactor (changed signs), transpose (by the order of "="), division through determinant    B.a = ( e * i - h * f) / det;    B.b = (-b * i + h * c) / det;    B.c = ( b * f - e * c) / det;    B.d = (-d * i + g * f) / det;    B.e = ( a * i - g * c) / det;    B.f = (-a * f + d * c) / det;    B.g = ( d * h - g * e) / det;    B.h = (-a * h + g * b) / det;    B.i = ( a * e - d * b) / det;        *this = B;}Matrix3 inverse(Matrix3 A){    A.inverse();    return A;} //Add two matricesMatrix3 operator+(Matrix3 A, Matrix3 B){    A.a += B.a;    A.b += B.b;    A.c += B.c;    A.d += B.d;    A.e += B.e;    A.f += B.f;    A.g += B.g;    A.h += B.h;    A.i += B.i;    return A;}//Subtract two matricesMatrix3 operator-(Matrix3 A, Matrix3 B){    A.a -= B.a;    A.b -= B.b;    A.c -= B.c;    A.d -= B.d;    A.e -= B.e;    A.f -= B.f;    A.g -= B.g;    A.h -= B.h;    A.i -= B.i;    return A;}//Multiply a matrix with a scalarMatrix3 operator*(Matrix3 A, Scalar a){    A.a *= a;    A.b *= a;    A.c *= a;    A.d *= a;    A.e *= a;    A.f *= a;    A.g *= a;    A.h *= a;    A.i *= a;    return A;}//Multiply a matrix with a scalarMatrix3 operator*(Scalar a, Matrix3 A){    A.a *= a;    A.b *= a;    A.c *= a;    A.d *= a;    A.e *= a;    A.f *= a;    A.g *= a;    A.h *= a;    A.i *= a;    return A;}//Divide a matrix through a scalarMatrix3 operator/(Matrix3 A, Scalar a){    A.a /= a;    A.b /= a;    A.c /= a;    A.d /= a;    A.e /= a;    A.f /= a;    A.g /= a;    A.h /= a;    A.i /= a;    return A;}//Multiply a matrix with a column vector, resulting in a column vectorVector3 operator*(Matrix3 A, Vector3 v){    Vector3 w;    w.x = A.a * v.x + A.b * v.y + A.c * v.z;    w.y = A.d * v.x + A.e * v.y + A.f * v.z;    w.z = A.g * v.x + A.h * v.y + A.i * v.z;    return w;}  //Multiply a vector with a row matrix, resulting in a row vectorVector3 operator*(Vector3 v, Matrix3 A){    Vector3 w;    w.x = A.a * v.x + A.d * v.y + A.g * v.z;    w.y = A.b * v.x + A.e * v.y + A.h * v.z;    w.z = A.c * v.x + A.f * v.y + A.i * v.z;    return w;}//Multiply a 3x3 matrix with a 3x3 matrixMatrix3 operator*(Matrix3 A, Matrix3 B){    Matrix3 C;    C.a = A.a * B.a + A.b * B.d + A.c * B.g;    C.b = A.a * B.b + A.b * B.e + A.c * B.h;    C.c = A.a * B.c + A.b * B.h + A.c * B.i;    C.d = A.d * B.a + A.e * B.d + A.f * B.g;    C.e = A.d * B.b + A.e * B.e + A.f * B.h;    C.f = A.d * B.c + A.e * B.h + A.f * B.i;    C.g = A.g * B.a + A.h * B.d + A.i * B.g;    C.h = A.g * B.b + A.h * B.e + A.i * B.h;    C.i = A.g * B.c + A.h * B.h + A.i * B.i;    return C;}//Camera functions/*Note: Every function that changes u, v or dir should use "generateMatrix();" at the end,unless that function already calls another one that generates it, at the end.*/Camera::Camera(Scalar posx, Scalar posy, Scalar posz, Scalar ux, Scalar uy, Scalar uz, Scalar vx, Scalar vy, Scalar vz, Scalar dirx, Scalar diry, Scalar dirz, Scalar nearClip, Scalar farClip){    pos.x = posx;    pos.y = posy;    pos.z = posz;    u.x = ux;    u.y = uy;    u.z = uz;    v.x = vx;    v.y = vy;    v.z = vz;    dir.x = dirx;    dir.y = diry;    dir.z = dirz;    this->nearClip = nearClip;    this->farClip = farClip;    generateMatrix();}    //Construct a camera with default parametersCamera::Camera(){    pos.x = 0.0;    pos.y = 0.0;    pos.z = 0.0;    u.x = 1.0;    u.y = 0.0;    u.z = 0.0;    v.x = 0.0;    v.y = 1.0;    v.z = 0.0;    dir.x = 0.0;    dir.y = 0.0;    dir.z = 1.0;    nearClip = 0.1;    farClip = 1000000.0;    generateMatrix();        }Vector3 Camera::getU(){    return u;}    Vector3 Camera::getV(){    return v;}    Vector3 Camera::getDir(){    return dir;}    Vector3 Camera::getPos(){    return pos;}void Camera::setU(Vector3 newU){    u = newU;    generateMatrix();}    void Camera::setV(Vector3 newV)    {    v = newV;    generateMatrix();}void Camera::setDir(Vector3 newDir)    {    dir = newDir;    generateMatrix();}    void Camera::setPos(Vector3 newPos){    pos = newPos;} void Camera::move(Vector3 offset){    pos = pos + offset;}  void Camera::rotate(Vector3 axis, Scalar angle){    u = rotateAroundArbitrary(u, axis, angle);    v = rotateAroundArbitrary(v, axis, angle);    dir = rotateAroundArbitrary(dir, axis, angle);    generateMatrix();}   //Look in a certain direction.void Camera::setLookDir(Vector3 newDir){    Vector3 axis = cross(dir, newDir);    if(axis.length() == 0) return;        Scalar angle = vectorAngle(dir, newDir);    if(angle != 0) rotate(axis, angle);   }//Look at a certain point (the point will come in the center of the screen, if nothing's in front of it that is)void Camera::lookAt(Vector3 lookAtMe){    setLookDir(lookAtMe - pos);}Scalar Camera::getDist(Vector3 point){    return distance(pos, point);}//Set the distance to a pointvoid Camera::setDist(Vector3 point, Scalar dist){    Scalar currentDist = distance(pos, point);    move(currentDist * normalize(point - pos));}    void Camera::zoom(Scalar a){    //increasing length of dir or decreasing length of the plane (u and v) = zoom IN    u = u / a;    v = v / a;    generateMatrix();}void Camera::zoomU(Scalar a){    u = u / a;    generateMatrix();}void Camera::zoomV(Scalar a){    v = v / a;    generateMatrix();}Scalar Camera::getZoomU(){   return(dir.length() / u.length());}Scalar Camera::getZoomV(){   return(dir.length() / v.length());}void Camera::setZoomU(Scalar a){    u = u / (a / getZoomU());    generateMatrix();}void Camera::setZoomV(Scalar a){    v = v / (a / getZoomV());    generateMatrix();}    Scalar Camera::getFOVU(){    return(2.0 * atan2(u.length(), dir.length()));}Scalar Camera::getFOVV(){    return(2.0 * atan2(v.length(), dir.length()));}void Camera::setFOVU(Scalar angle){    setZoomU(1.0 / tan(angle / 2.0));}void Camera::setFOVV(Scalar angle){    setZoomV(1.0 / tan(angle / 2.0));}     //////////////////////////////////////////////////////////////////////////////////Functions to get Yaw, Pitch and Roll. Normally to do things with the camera, //you never need these angles, everything works with vectors!//However, these can be useful if you want a compass in your game, or a weapon //that allows you to accurately change it's pitch/////////////////////////////////////////////////////////////////////////////////*Yaw is the wind direction the camera is looking at if you'd be standing on planet earth, and the ground has vectors X and Z, while Y points to the sky       N       ^        |z        |   x        Looking in the direction Z = North (0°, 0 rad)W -----+-----> E    Looking in the direction X = East (+90°, +1.57 rad)       |            Looking in negative Z = South (180°, 3.1415 rad, sign jump)       |            Looking in negative X = West (-90°, -1.57 rad)       |       S*/Scalar Camera::getYaw(){        //the atan2 function returns the angle of a 2D point (like from polar coordinates), so here it gives angle of dir projected on XZ plane, which is what we want for the yaw    return(atan2(dir.x, dir.z));}//setYaw can be used to make you look at a certain wind direction (where the ground is the XZ plane)void Camera::setYaw(Scalar angle){        Scalar currentAngle = getYaw();    //to change yaw, you have to rotate around the "up" axis of the WORLD = the y axis    rotate(Vector3(0,1,0), - angle + currentAngle);}//rotates camera around world Y-axis with given angle (in space this would make no sense since there isn't really an "up" or "down" of the world, instead you rotate around the "up" and "down" of your own spaceship there//When rolled, yawPlanet will give very annoying rotation, so for a spacegame or flight simulator you'll want to use yawSpace instead.void Camera::yawPlanet(Scalar angle){        rotate(Vector3(0,1,0), angle);}//rotates camera around camera v axis with given angle (this one makes sense in space, but not on a planet, on a planet your camera would start getting a "roll")void Camera::yawSpace(Scalar angle){        rotate(v, angle);}/*Pitch is only useful to define if you're standing on a plane or a planet, and there's a skyThe plane you're standing on is the XZ plane, and Y points to the skyPitch is 0° if you look forward (direction vector parallel to the XZ plane)Pitch is +90° if you look to the sky (maximum "up")Pitch is -90° if you look at the ground (maximum "down")Pitches of more than 90° or less than -90° aren't defined, since these can also be made by having  yaw 180° rotated and having a pitch between -90° and +90°*/Scalar Camera::getPitch(){    //Project dir on the XZ plane    //Then find angle between dir and projected dir       //With atan2: angle of the point (lengthof2Dvector(dir.x, dir.z), dir.y)    return atan2(dir.y, sqrt(dir.x * dir.x + dir.z * dir.z));}/*setPitch can be used to make you look to the sky or floor with certain angle without changing wind directionNOT useful for spacecrafts etc... because there's no up or down in space and X, Y and Z axes have no physical meaning thereonly useful for FPS games or other games where you walk on a planet surface*/void Camera::setPitch(Scalar angle){        Scalar currentAngle = getPitch();    //to change pitch, you have to rotate around the horizontal vector of the camera    rotate(u, angle - currentAngle);}//pitches the camera over a certain amountvoid Camera::pitch(Scalar angle){        rotate(u, angle);}/*Roll is only necessary for spacegames, flightsimulators or rare effects of FPS gamesRoll 0° = cam.u parallel with XZ plane, cam.v points upwardsRoll +90° = cam.v parallel with XZ plane, cam.u points downwardsRoll +-180° = cam.u parallel with XZ plane, cam.v points downwards (= you're upside down)Roll -90° = cam.v parallel with XZ plane, cam.u points upwardsIn space games the angles have no physical meaning, but in the coordinate system this angle is an "Euler" angle.*/Scalar Camera::getRoll(){    //roll is the angle between the plane (world_up, camera_dir) and the plane (camera_up, camera_dir)    //the angle between two planes is the angle between their normals    //the normals are gotten with cross products    //the vectorAngle function uses acos and dot product    Scalar roll = vectorAngle(cross(Vector3(0, 1, 0), dir), cross(v, dir));    if(u.y < 0) roll = -roll;    return roll;}void Camera::setRoll(Scalar angle){        Scalar currentAngle = getRoll();    //to change roll, you have to rotate around the direction vector of the camera    rotate(dir, angle - currentAngle);}//rolls the camera by rotating it around the direction vector (only makes sense in space or for "shaking" effects)void Camera::roll(Scalar angle){        rotate(dir, angle);}//makes u, v and dir perpendicular by using cross product, maintains exact direction and roll if only v was skewedVector3 Camera::resetSkewU(){    Scalar oldZoomU = getZoomU();     Scalar oldZoomV = getZoomV();    u = cross(dir, v);    v = cross(dir, -u);    setZoomU(oldZoomU);    setZoomV(oldZoomV);    // added due to error    return u;}//makes u, v and dir perpendicular by using cross product, maintains exact direction and roll if only u was skewedVector3 Camera::resetSkewV(){    Scalar oldZoomU = getZoomU();     Scalar oldZoomV = getZoomV();    v = cross(dir, u);    u = cross(dir, -v);    setZoomU(oldZoomU);    setZoomV(oldZoomV);    //added due to error    return v;}//get and set screen ratios of the camera (ratio of length of u and v, e.g. 4:3, 16:9, 640:480, ...)Scalar Camera::getRatioUV(){    return u.length() / v.length();}    Scalar Camera::getRatioVU(){    return v.length() / u.length();}//changes V    void Camera::setRatioUV(Scalar ratio){    v.normalize();    v = v * u.length() / ratio;    generateMatrix();    }    //changes Uvoid Camera::setRatioVU(Scalar ratio){    u.normalize();    u = u * v.length() / ratio;    generateMatrix();} //scale U, V and Dir without changing what you seeScalar Camera::getScale(){    return dir.length();}    void Camera::setScale(Scalar dirLength){    scale(dir.length() / dirLength);}    void Camera::scale(Scalar factor)    {    dir = dir * factor;    u = u * factor;    v = v * factor;    generateMatrix();}    void Camera::generateMatrix(){    //the cameraMatrix is generated, this is the matrix with 3 column vectors: u, v and dir    //it has to be generated everytime u, v or dir are changed      camMatrix.a = u.x;    camMatrix.d = u.y;    camMatrix.g = u.z;    camMatrix.b = v.x;    camMatrix.e = v.y;    camMatrix.h = v.z;    camMatrix.c = dir.x;    camMatrix.f = dir.y;    camMatrix.i = dir.z;    //this is the inverse of the camMatrix, to use for transformations    invCamMatrix = inverse(camMatrix);}Matrix3 Camera::getMatrix(){    return camMatrix;}Matrix3 Camera::getInvMatrix(){    return invCamMatrix;}void Camera::setMatrix(Matrix3 matrix){    //to make sure the vectors and the matrix are according to each other, set the vectors to the given matrix     //and then use generateMatrix with these new vectors    u.x = matrix.a;    u.y = matrix.d;    u.z = matrix.g;    v.x = matrix.b;    v.y = matrix.e;    v.z = matrix.h;    dir.x = matrix.c;    dir.y = matrix.f;    dir.z = matrix.i;    generateMatrix();} Vector3 Camera::transform(Vector3 v){    /*    Transformation from coordinate system 1 (base 1) to coordinate system 2 (base 2):            vector v = coordinates of point p in base 1 (column vector)    matrix A = the 3 vectors representing coordinates of unit vectors of base 2 in base 1 (3 column vectors in matrix)    vector w = coordinates of point p in base 2(column vector)        Then: v = A * w          w = A^(-1) * v        Now: base 1 = worldspace, base 2 = cameraspace    v = coordinates of point in worldspace (the given v )    A = the matrix from the camera: the coordinates of the camera vectors in worldspace    w = coordinates of point in cameraspace        So our transformation is w = A^(-1) * v, where v is the parameter given to the function, and A = perspective matrix of camera        All this text to describe only one line of code...    */        return invCamMatrix * v;  }/*uses the transform function of the camera, to project a point on screen, stores result in x and y (screen coordinates)returns 1 if point is legal, 0 if point is behind camera, outside screen, ...also stores z value of the point in camera coordinates in z*/bool Camera::projectOnScreen(Vector3 point, int & x, int & y, Scalar & z){    //First transformation: position    Vector3 a = point - pos;        //Second transformation: rotation    Vector3 b = transform(a);        //Third transformation: Projection on screen    //be warned: if b.z is too small, you get integer imprecisions, so don't make near clipping plane too small        int px = int(w / 2.0 + w * b.x / b.z);    int py = int(h / 2.0 - h * b.y / b.z); //inversed: y should be "up", while in screen coordinates it's down    if(onScreen(px, py) && b.z >= nearClip)    {        x = px;        y = py;        z = b.z;        return 1;    }    else    {        x = px;        y = py;        z = b.z;        return 0;    }        }bool Camera::projectOnScreen(Vector3 point, int & x, int & y){    Scalar z;    return projectOnScreen(point, x, y, z);       } bool Camera::camSpaceToScreen(Vector3 point, int & x, int & y){    //be warned: if point.z is too small, you get integer imprecisions, so don't make near clipping plane too small    int px = int(w / 2.0 + w * point.x / point.z);    int py = int(h / 2.0 - h * point.y / point.z); //inversed: y should be "up", while in screen coordinates it's down    if(onScreen(px, py) && point.z >= nearClip)    {        x = px;        y = py;        return 1;    }    else    {        x = px;        y = py;        return 0;    }       }    //Auxiliary Functions//Swap between radians and degreesScalar radToDeg(Scalar rad){    return 360.0 * rad / (3.14159 * 2.0);} Scalar degToRad(Scalar deg){    return (3.14159 * 2.0) * deg / 360.0;}    //TO DO://Z-buffer//drawLine and disk functions that use the zbuffer


QuickCG.cpp

#ifndef _quickcg_h_#define _quickcg_h_#include <SDL/SDL.h>//////////////////////////////////////////////////////////////////////////////////MIN, MAX and Scalar/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////use with care: if a or b is a function, it's executed twice!#ifndef max#define max(a,b) ((a)>(b)?(a):(b))#endif#ifndef min#define min(a,b) ((a)<(b)?(a):(b))#endif//define Scalar either as float or as double, at your choice#define Scalar double//////////////////////////////////////////////////////////////////////////////////COLOR STRUCTS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////struct ColorRGB8bit;//a color with 3 components: r, g and bstruct ColorRGB{    int r;    int g;    int b;        ColorRGB(Uint8 r, Uint8 g, Uint8 b);    ColorRGB(ColorRGB8bit color);    ColorRGB();};  ColorRGB operator+(ColorRGB color, ColorRGB color2);ColorRGB operator-(ColorRGB color, ColorRGB color2);ColorRGB operator*(ColorRGB color, int a);ColorRGB operator*(int a, ColorRGB color);ColorRGB operator/(ColorRGB color, int a);bool operator==(ColorRGB color, ColorRGB color2);bool operator!=(ColorRGB color, ColorRGB color2);#define RGB_Black   ColorRGB(  0,   0,   0)#define RGB_Red     ColorRGB(255,   0,   0)#define RGB_Green   ColorRGB(  0, 255,   0)#define RGB_Blue    ColorRGB(  0,   0, 255)#define RGB_Cyan    ColorRGB(  0, 255, 255)#define RGB_Magenta ColorRGB(255,   0, 255)#define RGB_Yellow  ColorRGB(255, 255,   0)#define RGB_White   ColorRGB(255, 255, 255)   #define RGB_Gray    ColorRGB(128, 128, 128)#define RGB_Grey    ColorRGB(192, 192, 192)#define RGB_Maroon    ColorRGB(128,   0,   0)#define RGB_Darkgreen ColorRGB(  0, 128,   0)#define RGB_Navy      ColorRGB(  0,   0, 128)#define RGB_Teal      ColorRGB(  0, 128, 128)#define RGB_Purple    ColorRGB(128,   0, 128)#define RGB_Olive     ColorRGB(128, 128,   0)//a color with 3 components: r, g and bstruct ColorRGB8bit{    Uint8 r;    Uint8 g;    Uint8 b;        ColorRGB8bit(Uint8 r, Uint8 g, Uint8 b);    ColorRGB8bit(ColorRGB color);    ColorRGB8bit();};  //a color with 3 components: h, s and lstruct ColorHSL{    int h;    int s;    int l;        ColorHSL(Uint8 h, Uint8 s, Uint8 l);    ColorHSL();};    //a color with 3 components: h, s and vstruct ColorHSV{    int h;    int s;    int v;        ColorHSV(Uint8 h, Uint8 s, Uint8 v);    ColorHSV();};//////////////////////////////////////////////////////////////////////////////////GLOBAL VARIABLES//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////extern SDL_Surface *scr; //the single SDL surface usedextern int w;extern int h;extern Uint8 *inkeys;//////////////////////////////////////////////////////////////////////////////////BASIC SCREEN FUNCTIONS////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void screen(int width = 640, int height = 400, bool fullscreen = 0, char *text = " ");void lock();void unlock();void redraw();void cls(ColorRGB color = RGB_Black);void pset(int x, int y, ColorRGB color);ColorRGB pget(int x, int y);void drawBuffer(Uint32 *buffer);bool onScreen(int x, int y);//////////////////////////////////////////////////////////////////////////////////NON GRAPHICAL FUNCTIONS///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void sleep();void waitFrame(float oldTime, float mspf);bool done();void end();void readKeys();void getMouseState(int & mouseX, int & mouseY);void getMouseState(int & mouseX, int & mouseY, bool & LMB, bool & RMB);float getTime();//////////////////////////////////////////////////////////////////////////////////2D SHAPES/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////bool horLine(int y, int x1, int x2, ColorRGB color);bool verLine(int x, int y1, int y2, ColorRGB color);bool drawLine(int x1, int y1, int x2, int y2, ColorRGB color);bool drawCircle(int xc, int yc, int radius, ColorRGB color);bool drawDisk(int xc, int yc, int radius, ColorRGB color);bool drawRect(int x1, int y1, int x2, int y2, ColorRGB color);bool clipLine(int x1,int y1,int x2, int y2, int & x3, int & y3, int & x4, int & y4);//////////////////////////////////////////////////////////////////////////////////COLOR CONVERSIONS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ColorHSL RGBtoHSL(ColorRGB colorRGB);ColorRGB HSLtoRGB(ColorHSL colorHSL);ColorHSV RGBtoHSV(ColorRGB colorRGB);ColorRGB HSVtoRGB(ColorHSV colorHSV);Uint32 RGBtoINT(ColorRGB colorRGB);ColorRGB INTtoRGB(Uint32 colorINT);//////////////////////////////////////////////////////////////////////////////////BMP FUNCTIONS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////int loadBMP(char *filename, ColorRGB *image, int w, int h);int loadBMP(char *filename, Uint32 *image, int w, int h);//////////////////////////////////////////////////////////////////////////////////TEXT FUNCTIONS////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////extern const bool font[256][8][8];static void inline drawLetter(unsigned char n, int x, int y, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);int print(char *text, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black, int forceLength=0);int iprint(int a, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black, bool orderSigns=0, int forceLength=0);int iprint(Uint32 a, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black, bool orderSigns=0, int forceLength=0);int fprint(double a, int length = 0, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black, bool orderSigns=0, int forceLength=0);int cprint(unsigned char n, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);//////////////////////////////////////////////////////////////////////////////////TEXT INPUT FUNCTIONS//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Uint8 getChar(char * message = "", int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);void getString(char * text, int length, char * message = "", int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);Scalar getScalar(char * message = "", int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);#endif


Q3DMath.h

#ifndef __3DMATH_H__#define __3DMATH_H__#include "QuickCG.h"//////////////////////////////////////////////////////////////////////////////////               [ x ]                                                        //// Vector Class  [ y ]                                                        ////               [ z ]                                                        //////////////////////////////////////////////////////////////////////////////////class Vector3{    public:                   Scalar x;    Scalar y;    Scalar z;        Vector3(Scalar x, Scalar y, Scalar z);    Vector3();        Scalar length();    void normalize();    Scalar distance(Vector3 v);    Scalar dot(Vector3 v);    Vector3 cross(Vector3 v);};Scalar length(Vector3 v);Vector3 normalize(Vector3 v);Scalar distance(Vector3 v, Vector3 w);       Scalar dot(Vector3 v, Vector3 w);Vector3 cross(Vector3 v, Vector3 w);Vector3 operator-(Vector3 v, Vector3 w);Vector3 operator-(Vector3 v);Vector3 operator+(Vector3 v, Vector3 w);Vector3 operator*(Vector3 v, Scalar a);Vector3 operator*(Scalar a, Vector3 v);Vector3 operator/(Vector3 v, Scalar a);Scalar vectorAngle(Vector3 v, Vector3 w);Vector3 rotateAroundArbitrary(Vector3 v, Vector3 axis, Scalar angle);//////////////////////////////////////////////////////////////////////////////////               [ a b c ]                                                    //// Matrix Class  [ d e f ]                                                    ////               [ g h i ]                                                    //////////////////////////////////////////////////////////////////////////////////class Matrix3{    public:            Scalar a; Scalar b; Scalar c;    Scalar d; Scalar e; Scalar f;    Scalar g; Scalar h; Scalar i;        Matrix3(Scalar a, Scalar b, Scalar c, Scalar d, Scalar e, Scalar f, Scalar g, Scalar h, Scalar i);    Matrix3();        void transpose();    Scalar determinant();    void inverse();   };Matrix3 transpose(Matrix3 A);Scalar determinant(Matrix3 A);Matrix3 inverse(Matrix3 A);Matrix3 operator+(Matrix3 A, Matrix3 B);Matrix3 operator-(Matrix3 A, Matrix3 B);Matrix3 operator*(Matrix3 A, Scalar a);Matrix3 operator*(Scalar a, Matrix3 A);Matrix3 operator/(Matrix3 A, Scalar a);Vector3 operator*(Matrix3 A, Vector3 v);Vector3 operator*(Vector3 v, Matrix3 A);Matrix3 operator*(Matrix3 A, Matrix3 B);//////////////////////////////////////////////////////////////////////////////////               [ u.x v.x dir.x ]   [ pos.x ]                                //// Camera Class  [ u.y v.y dir.y ] + [ pos.y ]                                ////               [ u.z v.z dir.z ]   [ pos.z ]                                //////////////////////////////////////////////////////////////////////////////////class Camera{    public:    Scalar nearClip; //near clipping plane    Scalar farClip; //far clipping plane    Camera();    Camera(Scalar posx, Scalar posy, Scalar posz,           Scalar ux,   Scalar uy,   Scalar uz,           Scalar vx,   Scalar vy,   Scalar vz,           Scalar dirx, Scalar diry, Scalar dirz,           Scalar nearClip, Scalar farClip);                         //Get and Set the 4 important vectors     Vector3 getU(); //the "right" vector of the camera, x coordinate of screen    Vector3 getV(); //the "up" vector of the camera, y coordinate of screen    Vector3 getDir(); //the direction of the camera, vector that points into the screen (z direction)    Vector3 getPos(); //the position of the camera in world coordinates    void setDir(Vector3 newDir);    void setU(Vector3 newY);    void setV(Vector3 newV);        void setPos(Vector3 newPos);        //move and rotate with vectors    void move(Vector3 offset);    void rotate(Vector3 axis, Scalar angle);    void setLookDir(Vector3 newDir);    void lookAt(Vector3 lookAtMe);        //get and set distance to a certain point    Scalar getDist(Vector3 point);    void setDist(Vector3 point, Scalar dist);        //get and set zoom    Scalar getZoomU();    Scalar getZoomV();    void setZoomU(Scalar a);    void setZoomV(Scalar a);     void zoom(Scalar a);    void zoomU(Scalar a);    void zoomV(Scalar a);            //get and set FOV    Scalar getFOVU();    Scalar getFOVV();    void setFOVU(Scalar angle);    void setFOVV(Scalar angle);            //get and set pitch, yaw and roll (these are NOT native parameters of the camera and should normally never be needed!)       Scalar getYaw();    Scalar getPitch();    Scalar getRoll();          void setYaw(Scalar angle);    void setPitch(Scalar angle);        void setRoll(Scalar angle);    void yawPlanet(Scalar angle);    void yawSpace(Scalar angle);      void pitch(Scalar angle);    void roll(Scalar angle);         //make camera orthogonal (reset skewing)    Vector3 resetSkewU();    Vector3 resetSkewV();        //set screen ratio of the camera (ratio of length of u and v, e.g. 4:3, 16:9, 640:480, ...)    Scalar getRatioUV();    Scalar getRatioVU();    void setRatioUV(Scalar ratio);    void setRatioVU(Scalar ratio);        //scale U, V and Dir without changing what you see    Scalar getScale();    void setScale(Scalar dirLength);    void scale(Scalar factor);        //generate, get and use the camera matrix to transform points    void generateMatrix();    Matrix3 getMatrix();    Matrix3 getInvMatrix();    void setMatrix(Matrix3 matrix);   //sets the u, v and dir vector to given matrix (and generates the actual matrix too of course)    Vector3 transform(Vector3 v);    bool projectOnScreen(Vector3 point, int & x, int & y, Scalar & z);    bool projectOnScreen(Vector3 point, int & x, int & y);    bool camSpaceToScreen(Vector3 point, int & x, int & y);                                    private:    //the camera plane, described by the vectors u and v, is described by "z = 0" in camera space    Vector3 pos; //the location of the camera    Vector3 u; //horizontal vector, horizontal side of computer screen    Vector3 v; //vertical "up" vector, vertical side of computer screen    Vector3 dir; //direction of the camera, direction of the projection    Matrix3 camMatrix; //the camera matrix, is nothing more than the column vectors u, v and dir in one matrix    Matrix3 invCamMatrix; //the inverse of the camera matrix     };//Auxiliary functions//swap between radians and degreesScalar radToDeg(Scalar rad);Scalar degToRad(Scalar deg);#endif


QuickCG.h

#ifndef _quickcg_h_#define _quickcg_h_#include <SDL/SDL.h>//////////////////////////////////////////////////////////////////////////////////MIN, MAX and Scalar/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////use with care: if a or b is a function, it's executed twice!#ifndef max#define max(a,b) ((a)>(b)?(a):(b))#endif#ifndef min#define min(a,b) ((a)<(b)?(a):(b))#endif//define Scalar either as float or as double, at your choice#define Scalar double//////////////////////////////////////////////////////////////////////////////////COLOR STRUCTS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////struct ColorRGB8bit;//a color with 3 components: r, g and bstruct ColorRGB{    int r;    int g;    int b;        ColorRGB(Uint8 r, Uint8 g, Uint8 b);    ColorRGB(ColorRGB8bit color);    ColorRGB();};  ColorRGB operator+(ColorRGB color, ColorRGB color2);ColorRGB operator-(ColorRGB color, ColorRGB color2);ColorRGB operator*(ColorRGB color, int a);ColorRGB operator*(int a, ColorRGB color);ColorRGB operator/(ColorRGB color, int a);bool operator==(ColorRGB color, ColorRGB color2);bool operator!=(ColorRGB color, ColorRGB color2);#define RGB_Black   ColorRGB(  0,   0,   0)#define RGB_Red     ColorRGB(255,   0,   0)#define RGB_Green   ColorRGB(  0, 255,   0)#define RGB_Blue    ColorRGB(  0,   0, 255)#define RGB_Cyan    ColorRGB(  0, 255, 255)#define RGB_Magenta ColorRGB(255,   0, 255)#define RGB_Yellow  ColorRGB(255, 255,   0)#define RGB_White   ColorRGB(255, 255, 255)   #define RGB_Gray    ColorRGB(128, 128, 128)#define RGB_Grey    ColorRGB(192, 192, 192)#define RGB_Maroon    ColorRGB(128,   0,   0)#define RGB_Darkgreen ColorRGB(  0, 128,   0)#define RGB_Navy      ColorRGB(  0,   0, 128)#define RGB_Teal      ColorRGB(  0, 128, 128)#define RGB_Purple    ColorRGB(128,   0, 128)#define RGB_Olive     ColorRGB(128, 128,   0)//a color with 3 components: r, g and bstruct ColorRGB8bit{    Uint8 r;    Uint8 g;    Uint8 b;        ColorRGB8bit(Uint8 r, Uint8 g, Uint8 b);    ColorRGB8bit(ColorRGB color);    ColorRGB8bit();};  //a color with 3 components: h, s and lstruct ColorHSL{    int h;    int s;    int l;        ColorHSL(Uint8 h, Uint8 s, Uint8 l);    ColorHSL();};    //a color with 3 components: h, s and vstruct ColorHSV{    int h;    int s;    int v;        ColorHSV(Uint8 h, Uint8 s, Uint8 v);    ColorHSV();};//////////////////////////////////////////////////////////////////////////////////GLOBAL VARIABLES//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////extern SDL_Surface *scr; //the single SDL surface usedextern int w;extern int h;extern Uint8 *inkeys;//////////////////////////////////////////////////////////////////////////////////BASIC SCREEN FUNCTIONS////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void screen(int width = 640, int height = 400, bool fullscreen = 0, char *text = " ");void lock();void unlock();void redraw();void cls(ColorRGB color = RGB_Black);void pset(int x, int y, ColorRGB color);ColorRGB pget(int x, int y);void drawBuffer(Uint32 *buffer);bool onScreen(int x, int y);//////////////////////////////////////////////////////////////////////////////////NON GRAPHICAL FUNCTIONS///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void sleep();void waitFrame(float oldTime, float mspf);bool done();void end();void readKeys();void getMouseState(int & mouseX, int & mouseY);void getMouseState(int & mouseX, int & mouseY, bool & LMB, bool & RMB);float getTime();//////////////////////////////////////////////////////////////////////////////////2D SHAPES/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////bool horLine(int y, int x1, int x2, ColorRGB color);bool verLine(int x, int y1, int y2, ColorRGB color);bool drawLine(int x1, int y1, int x2, int y2, ColorRGB color);bool drawCircle(int xc, int yc, int radius, ColorRGB color);bool drawDisk(int xc, int yc, int radius, ColorRGB color);bool drawRect(int x1, int y1, int x2, int y2, ColorRGB color);bool clipLine(int x1,int y1,int x2, int y2, int & x3, int & y3, int & x4, int & y4);//////////////////////////////////////////////////////////////////////////////////COLOR CONVERSIONS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ColorHSL RGBtoHSL(ColorRGB colorRGB);ColorRGB HSLtoRGB(ColorHSL colorHSL);ColorHSV RGBtoHSV(ColorRGB colorRGB);ColorRGB HSVtoRGB(ColorHSV colorHSV);Uint32 RGBtoINT(ColorRGB colorRGB);ColorRGB INTtoRGB(Uint32 colorINT);//////////////////////////////////////////////////////////////////////////////////BMP FUNCTIONS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////int loadBMP(char *filename, ColorRGB *image, int w, int h);int loadBMP(char *filename, Uint32 *image, int w, int h);//////////////////////////////////////////////////////////////////////////////////TEXT FUNCTIONS////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////extern const bool font[256][8][8];static void inline drawLetter(unsigned char n, int x, int y, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);int print(char *text, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black, int forceLength=0);int iprint(int a, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black, bool orderSigns=0, int forceLength=0);int iprint(Uint32 a, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black, bool orderSigns=0, int forceLength=0);int fprint(double a, int length = 0, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black, bool orderSigns=0, int forceLength=0);int cprint(unsigned char n, int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);//////////////////////////////////////////////////////////////////////////////////TEXT INPUT FUNCTIONS//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Uint8 getChar(char * message = "", int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);void getString(char * text, int length, char * message = "", int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);Scalar getScalar(char * message = "", int x = 0, int y = 0, ColorRGB color = RGB_White, bool bg = 0, ColorRGB color2 = RGB_Black);#endif




also, before you ask, I do have sdl linked to my project properly.

______________________________My website: Quest Networks
Ajare
Ajare
That QuickCG.cpp file doesn't look right at all - in fact it looks just like QuickCG.h :)
Axenation
Axenation
Quote:
Original post by Ajare
That QuickCG.cpp file doesn't look right at all - in fact it looks just like QuickCG.h :)


Which would describe why he got those linkers errors. The compiler couldn't complain about have the same file twice because of the two preprocessor lines at the top of the file. i'm guessing you should go to Lode's website and download the QuickCG.cpp file again. Don't copy the one stormrunner posted above. It's not complete due to the forum cutting it off.
Now I get a cookie!
jakpandora
jakpandora
I didnt actually. I downloaded quickCg and then just put my own main in it. however, I seem to be linking it to SDL wrong, so ill have to check out lodes site to see how to do it.
______________________________My website: Quest Networks
jakpandora
jakpandora
I must have really bad luck with this. when I fix everything, I get more errors.(its not exactly the one stormrunner said, but it has something to do with time)

C:\Documents and Settings\Michael\Desktop\zip files\main.cpp
[Warning] In function int SDL_main(int, char**)':

166 C:\Documents and Settings\Michael\Desktop\zip files\main.cpp
_oldTime' undeclared (first use this function)



any help?
______________________________My website: Quest Networks

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.