Odd problems with raycaster...please help!

Started by
22 comments, last by jakpandora 19 years, 6 months ago
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 ]  =                                                      //</span>
<span class="cpp-comment">// [ g h i ]     [ c f i ]                                                    //</span>
<span class="cpp-comment">////////////////////////////////////////////////////////////////////////////////</span>
<span class="cpp-keyword">void</span> Matrix3::transpose()
{
    b += d; d = b - d; b -= d; <span class="cpp-comment">//swap b and d</span>
    c += g; g = c - g; c -= g; <span class="cpp-comment">//swap c and g</span>
    f += h; h = f - h; f -= h; <span class="cpp-comment">//swap f and h</span>
}  

Matrix3 transpose(Matrix3 A)
{
    A.transpose();
    <span class="cpp-keyword">return</span> A;
} 

Scalar Matrix3::determinant()
{
    Scalar det = a * e * i 
               + b * f * g 
               + d * h * c 
               - g * e * c 
               - d * b * i 
               - h * f * a;
              
    <span class="cpp-keyword">return</span> det;
}   

Scalar determinant(Matrix3 A)
{
    <span class="cpp-keyword">return</span> A.determinant();
}     

<span class="cpp-comment">//Inverse of a 3x3 matrix</span>
<span class="cpp-keyword">void</span> Matrix3::inverse()
{
    <span class="cpp-comment">/*
    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
    */</span>
    
    Scalar det = determinant();
    Matrix3 B;

    <span class="cpp-comment">//included in these calculations: minor, cofactor (changed signs), transpose (by the order of "="), division through determinant</span>
    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;
    
    *<span class="cpp-keyword">this</span> = B;
}

Matrix3 inverse(Matrix3 A)
{
    A.inverse();
    <span class="cpp-keyword">return</span> A;
} 

<span class="cpp-comment">//Add two matrices</span>
Matrix3 <span class="cpp-keyword">operator</span>+(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;
    <span class="cpp-keyword">return</span> A;
}

<span class="cpp-comment">//Subtract two matrices</span>
Matrix3 <span class="cpp-keyword">operator</span>-(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;
    <span class="cpp-keyword">return</span> A;
}

<span class="cpp-comment">//Multiply a matrix with a scalar</span>
Matrix3 <span class="cpp-keyword">operator</span>*(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;
    <span class="cpp-keyword">return</span> A;
}

<span class="cpp-comment">//Multiply a matrix with a scalar</span>
Matrix3 <span class="cpp-keyword">operator</span>*(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;
    <span class="cpp-keyword">return</span> A;
}

<span class="cpp-comment">//Divide a matrix through a scalar</span>
Matrix3 <span class="cpp-keyword">operator</span>/(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;
    <span class="cpp-keyword">return</span> A;
}

<span class="cpp-comment">//Multiply a matrix with a column vector, resulting in a column vector</span>
Vector3 <span class="cpp-keyword">operator</span>*(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;
    <span class="cpp-keyword">return</span> w;
}  

<span class="cpp-comment">//Multiply a vector with a row matrix, resulting in a row vector</span>
Vector3 <span class="cpp-keyword">operator</span>*(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;
    <span class="cpp-keyword">return</span> w;
}

<span class="cpp-comment">//Multiply a 3x3 matrix with a 3x3 matrix</span>
Matrix3 <span class="cpp-keyword">operator</span>*(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;
    <span class="cpp-keyword">return</span> C;
}



<span class="cpp-comment">//Camera functions</span>

<span class="cpp-comment">/*
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.
*/</span>
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;
    <span class="cpp-keyword">this</span>-&gt;nearClip = nearClip;
    <span class="cpp-keyword">this</span>-&gt;farClip = farClip;
    generateMatrix();
}    

<span class="cpp-comment">//Construct a camera with default parameters</span>
Camera::Camera()
{
    pos.x = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    pos.y = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    pos.z = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    u.x = <span class="cpp-number">1</span>.<span class="cpp-number">0</span>;
    u.y = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    u.z = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    v.x = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    v.y = <span class="cpp-number">1</span>.<span class="cpp-number">0</span>;
    v.z = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    dir.x = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    dir.y = <span class="cpp-number">0</span>.<span class="cpp-number">0</span>;
    dir.z = <span class="cpp-number">1</span>.<span class="cpp-number">0</span>;
    nearClip = <span class="cpp-number">0</span>.<span class="cpp-number">1</span>;
    farClip = <span class="cpp-number">1000000</span>.<span class="cpp-number">0</span>;
    generateMatrix();        
}

Vector3 Camera::getU()
{
    <span class="cpp-keyword">return</span> u;
}    
Vector3 Camera::getV()
{
    <span class="cpp-keyword">return</span> v;
}    
Vector3 Camera::getDir()
{
    <span class="cpp-keyword">return</span> dir;
}    
Vector3 Camera::getPos()
{
    <span class="cpp-keyword">return</span> pos;
}

<span class="cpp-keyword">void</span> Camera::setU(Vector3 newU)
{
    u = newU;
    generateMatrix();
}    
<span class="cpp-keyword">void</span> Camera::setV(Vector3 newV)    
{
    v = newV;
    generateMatrix();
}

<span class="cpp-keyword">void</span> Camera::setDir(Vector3 newDir)    
{
    dir = newDir;
    generateMatrix();
}    

<span class="cpp-keyword">void</span> Camera::setPos(Vector3 newPos)
{
    pos = newPos;
} 

<span class="cpp-keyword">void</span> Camera::move(Vector3 offset)
{
    pos = pos + offset;
}  

<span class="cpp-keyword">void</span> Camera::rotate(Vector3 axis, Scalar angle)
{
    u = rotateAroundArbitrary(u, axis, angle);
    v = rotateAroundArbitrary(v, axis, angle);
    dir = rotateAroundArbitrary(dir, axis, angle);
    generateMatrix();
}   

<span class="cpp-comment">//Look in a certain direction.</span>
<span class="cpp-keyword">void</span> Camera::setLookDir(Vector3 newDir)
{
    Vector3 axis = cross(dir, newDir);
    <span class="cpp-keyword">if</span>(axis.length() == <span class="cpp-number">0</span>) <span class="cpp-keyword">return</span>;
    
    Scalar angle = vectorAngle(dir, newDir);
    <span class="cpp-keyword">if</span>(angle != <span class="cpp-number">0</span>) rotate(axis, angle);   
}

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

Scalar Camera::getDist(Vector3 point)
{
    <span class="cpp-keyword">return</span> distance(pos, point);
}

<span class="cpp-comment">//Set the distance to a point</span>
<span class="cpp-keyword">void</span> Camera::setDist(Vector3 point, Scalar dist)
{
    Scalar currentDist = distance(pos, point);
    move(currentDist * normalize(point - pos));
}    

<span class="cpp-keyword">void</span> Camera::zoom(Scalar a)
{
    <span class="cpp-comment">//increasing length of dir or decreasing length of the plane (u and v) = zoom IN</span>
    u = u / a;
    v = v / a;
    generateMatrix();
}

<span class="cpp-keyword">void</span> Camera::zoomU(Scalar a)
{
    u = u / a;
    generateMatrix();
}

<span class="cpp-keyword">void</span> Camera::zoomV(Scalar a)
{
    v = v / a;
    generateMatrix();
}

Scalar Camera::getZoomU()
{
   <span class="cpp-keyword">return</span>(dir.length() / u.length());
}

Scalar Camera::getZoomV()
{
   <span class="cpp-keyword">return</span>(dir.length() / v.length());
}

<span class="cpp-keyword">void</span> Camera::setZoomU(Scalar a)
{
    u = u / (a / getZoomU());
    generateMatrix();
}

<span class="cpp-keyword">void</span> Camera::setZoomV(Scalar a)
{
    v = v / (a / getZoomV());
    generateMatrix();
}    

Scalar Camera::getFOVU()
{
    <span class="cpp-keyword">return</span>(<span class="cpp-number">2</span>.<span class="cpp-number">0</span> * atan2(u.length(), dir.length()));
}

Scalar Camera::getFOVV()
{
    <span class="cpp-keyword">return</span>(<span class="cpp-number">2</span>.<span class="cpp-number">0</span> * atan2(v.length(), dir.length()));
}

<span class="cpp-keyword">void</span> Camera::setFOVU(Scalar angle)
{
    setZoomU(<span class="cpp-number">1</span>.<span class="cpp-number">0</span> / tan(angle / <span class="cpp-number">2</span>.<span class="cpp-number">0</span>));
}

<span class="cpp-keyword">void</span> Camera::setFOVV(Scalar angle)
{
    setZoomV(<span class="cpp-number">1</span>.<span class="cpp-number">0</span> / tan(angle / <span class="cpp-number">2</span>.<span class="cpp-number">0</span>));
}     

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

<span class="cpp-comment">/*
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 —–+—–&gt; 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
*/</span>
Scalar Camera::getYaw()
{    
    <span class="cpp-comment">//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</span>
    <span class="cpp-keyword">return</span>(atan2(dir.x, dir.z));
}

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

<span class="cpp-comment">//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</span>
<span class="cpp-comment">//When rolled, yawPlanet will give very annoying rotation, so for a spacegame or flight simulator you'll want to use yawSpace instead.</span>
<span class="cpp-keyword">void</span> Camera::yawPlanet(Scalar angle)
{    
    rotate(Vector3(<span class="cpp-number">0</span>,<span class="cpp-number">1</span>,<span class="cpp-number">0</span>), angle);
}

<span class="cpp-comment">//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")</span>
<span class="cpp-keyword">void</span> Camera::yawSpace(Scalar angle)
{    
    rotate(v, angle);
}

<span class="cpp-comment">/*
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°
*/</span>
Scalar Camera::getPitch()
{
    <span class="cpp-comment">//Project dir on the XZ plane</span>
    <span class="cpp-comment">//Then find angle between dir and projected dir   </span>
    <span class="cpp-comment">//With atan2: angle of the point (lengthof2Dvector(dir.x, dir.z), dir.y)</span>
    <span class="cpp-keyword">return</span> atan2(dir.y, sqrt(dir.x * dir.x + dir.z * dir.z));
}

<span class="cpp-comment">/*
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
*/</span>
<span class="cpp-keyword">void</span> Camera::setPitch(Scalar angle)
{    
    Scalar currentAngle = getPitch();
    <span class="cpp-comment">//to change pitch, you have to rotate around the horizontal vector of the camera</span>
    rotate(u, angle - currentAngle);
}

<span class="cpp-comment">//pitches the camera over a certain amount</span>
<span class="cpp-keyword">void</span> Camera::pitch(Scalar angle)
{    
    rotate(u, angle);
}

<span class="cpp-comment">/*
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.
*/</span>
Scalar Camera::getRoll()
{
    <span class="cpp-comment">//roll is the angle between the plane (world_up, camera_dir) and the plane (camera_up, camera_dir)</span>
    <span class="cpp-comment">//the angle between two planes is the angle between their normals</span>
    <span class="cpp-comment">//the normals are gotten with cross products</span>
    <span class="cpp-comment">//the vectorAngle function uses acos and dot product</span>
    Scalar roll = vectorAngle(cross(Vector3(<span class="cpp-number">0</span>, <span class="cpp-number">1</span>, <span class="cpp-number">0</span>), dir), cross(v, dir));
    <span class="cpp-keyword">if</span>(u.y &lt; <span class="cpp-number">0</span>) roll = -roll;
    <span class="cpp-keyword">return</span> roll;
}

<span class="cpp-keyword">void</span> Camera::setRoll(Scalar angle)
{    
    Scalar currentAngle = getRoll();
    <span class="cpp-comment">//to change roll, you have to rotate around the direction vector of the camera</span>
    rotate(dir, angle - currentAngle);
}

<span class="cpp-comment">//rolls the camera by rotating it around the direction vector (only makes sense in space or for "shaking" effects)</span>
<span class="cpp-keyword">void</span> Camera::roll(Scalar angle)
{    
    rotate(dir, angle);
}

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

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

<span class="cpp-comment">//get and set screen ratios of the camera (ratio of length of u and v, e.g. 4:3, 16:9, 640:480, …)</span>
Scalar Camera::getRatioUV()
{
    <span class="cpp-keyword">return</span> u.length() / v.length();
}    

Scalar Camera::getRatioVU()
{
    <span class="cpp-keyword">return</span> v.length() / u.length();
}

<span class="cpp-comment">//changes V    </span>
<span class="cpp-keyword">void</span> Camera::setRatioUV(Scalar ratio)
{
    v.normalize();
    v = v * u.length() / ratio;
    generateMatrix();    
}    

<span class="cpp-comment">//changes U</span>
<span class="cpp-keyword">void</span> Camera::setRatioVU(Scalar ratio)
{
    u.normalize();
    u = u * v.length() / ratio;
    generateMatrix();
} 

<span class="cpp-comment">//scale U, V and Dir without changing what you see</span>
Scalar Camera::getScale()
{
    <span class="cpp-keyword">return</span> dir.length();
}    
<span class="cpp-keyword">void</span> Camera::setScale(Scalar dirLength)
{
    scale(dir.length() / dirLength);
}
    
<span class="cpp-keyword">void</span> Camera::scale(Scalar factor)    
{
    dir = dir * factor;
    u = u * factor;
    v = v * factor;
    generateMatrix();
}    

<span class="cpp-keyword">void</span> Camera::generateMatrix()
{
    <span class="cpp-comment">//the cameraMatrix is generated, this is the matrix with 3 column vectors: u, v and dir</span>
    <span class="cpp-comment">//it has to be generated everytime u, v or dir are changed  </span>
    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;

    <span class="cpp-comment">//this is the inverse of the camMatrix, to use for transformations</span>
    invCamMatrix = inverse(camMatrix);
}

Matrix3 Camera::getMatrix()
{
    <span class="cpp-keyword">return</span> camMatrix;
}

Matrix3 Camera::getInvMatrix()
{
    <span class="cpp-keyword">return</span> invCamMatrix;
}

<span class="cpp-keyword">void</span> Camera::setMatrix(Matrix3 matrix)
{
    <span class="cpp-comment">//to make sure the vectors and the matrix are according to each other, set the vectors to the given matrix </span>
    <span class="cpp-comment">//and then use generateMatrix with these new vectors</span>
    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)
{
    <span class="cpp-comment">/*
    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…
    */</span>
    
    <span class="cpp-keyword">return</span> invCamMatrix * v;  
}

<span class="cpp-comment">/*
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
*/</span>
<span class="cpp-keyword">bool</span> Camera::projectOnScreen(Vector3 point, <span class="cpp-keyword">int</span> &amp; x, <span class="cpp-keyword">int</span> &amp; y, Scalar &amp; z)
{
    <span class="cpp-comment">//First transformation: position</span>
    Vector3 a = point - pos;
    
    <span class="cpp-comment">//Second transformation: rotation</span>
    Vector3 b = transform(a);
    
    <span class="cpp-comment">//Third transformation: Projection on screen</span>
    <span class="cpp-comment">//be warned: if b.z is too small, you get integer imprecisions, so don't make near clipping plane too small    </span>
    <span class="cpp-keyword">int</span> px = <span class="cpp-keyword">int</span>(w / <span class="cpp-number">2</span>.<span class="cpp-number">0</span> + w * b.x / b.z);
    <span class="cpp-keyword">int</span> py = <span class="cpp-keyword">int</span>(h / <span class="cpp-number">2</span>.<span class="cpp-number">0</span> - h * b.y / b.z); <span class="cpp-comment">//inversed: y should be "up", while in screen coordinates it's down</span>
    <span class="cpp-keyword">if</span>(onScreen(px, py) &amp;&amp; b.z &gt;= nearClip)
    {
        x = px;
        y = py;
        z = b.z;
        <span class="cpp-keyword">return</span> <span class="cpp-number">1</span>;
    }
    <span class="cpp-keyword">else</span>
    {
        x = px;
        y = py;
        z = b.z;
        <span class="cpp-keyword">return</span> <span class="cpp-number">0</span>;
    }        
}

<span class="cpp-keyword">bool</span> Camera::projectOnScreen(Vector3 point, <span class="cpp-keyword">int</span> &amp; x, <span class="cpp-keyword">int</span> &amp; y)
{
    Scalar z;
    <span class="cpp-keyword">return</span> projectOnScreen(point, x, y, z);       
} 

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


<span class="cpp-comment">//Auxiliary Functions</span>


<span class="cpp-comment">//Swap between radians and degrees</span>
Scalar radToDeg(Scalar rad)
{
    <span class="cpp-keyword">return</span> <span class="cpp-number">360</span>.<span class="cpp-number">0</span> * rad / (<span class="cpp-number">3</span>.<span class="cpp-number">14159</span> * <span class="cpp-number">2</span>.<span class="cpp-number">0</span>);
} 

Scalar degToRad(Scalar deg)
{
    <span class="cpp-keyword">return</span> (<span class="cpp-number">3</span>.<span class="cpp-number">14159</span> * <span class="cpp-number">2</span>.<span class="cpp-number">0</span>) * deg / <span class="cpp-number">360</span>.<span class="cpp-number">0</span>;
}    

<span class="cpp-comment">//TO DO:</span>
<span class="cpp-comment">//Z-buffer</span>
<span class="cpp-comment">//drawLine and disk functions that use the zbuffer</span>

</pre></div><!–ENDSCRIPT–>


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
Advertisement
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.
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.
<edit::> as compared to
scalar Camera::resetSkewV() { /* insert function here */ }
- stormrunner
what do you need a 3d vector for in a wolfenstein like game anyway?
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
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
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.
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
come on! could someone please help!
______________________________My website: Quest Networks
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

This topic is closed to new replies.

Advertisement