home *** CD-ROM | disk | FTP | other *** search
- #ifdef WIN32
- #include <windows.h>
- #endif
- #include <GL/gl.h>
- #include <GL/glu.h>
-
- #include <math.h>
-
- #include "Camera.h"
- //#include "render.h"
- #include "collision.h"
-
- #include "log.h"
- #include "Game.h"
- #include "Network.h"
-
-
- Camera::Camera(){
- mode=CAMERA_MODE_FREE;
- noclip=true;
- moveSpeed=20.0;
- turnSpeed=2.0;
-
- lastProcessMillis = SDL_GetTicks();
- lastMoveMillis = SDL_GetTicks();
-
- vectorInit3d(-0.2f, -0.2f, -0.2f, moveAABB.min);
- vectorInit3d(+0.2f, +0.2f, +0.2f, moveAABB.max);
- /*
- vectorInit3d(0.0, 0.0, 0.0, pos);
- vectorInit3d(0.0, 0.0, 0.0, vel);
- vectorInit3d(0.0, 0.0, 1.0, dir);
- vectorInit3d(0.0, 1.0, 0.0, up);
- vectorInit3d(1.0, 0.0, 0.0, left);
- */
- target = NULL;
- reset();
- }
-
- void Camera::setMode(int mode){
- if(mode>=0 && mode<NUM_CAMERA_MODES){
- this->mode=mode;
- Game::info.cvar.game_camera_mode->setVal(mode); // to be consistent...
- }
- }
-
- void Camera::setTarget(Vehicle* newTarget){
- this->target = newTarget;
- }
-
- void Camera::setPositionAndOrientation(vec3_t pos, vec3_t dir, vec3_t up){
- vectorCopy3d(pos, this->pos);
- vectorCopy3d(dir, this->dir);
- vectorCopy3d(up, this->up);
-
- vectorCrossP3d(up, dir, left);
- vectorCrossP3d(dir, left, up); // THINKABOUTME: sicher ist sicher...
-
- vectorNormalize3d(dir, dir);
- vectorNormalize3d(up, up);
- vectorNormalize3d(left, left);
- }
-
- void Camera::setPositionAndOrientation(float posx,float posy,float posz, float dirx, float diry, float dirz, float upx,float upy,float upz){
- vectorInit3d(posx, posy, posz, pos);
- vectorInit3d(dirx, diry, dirz, dir);
- vectorInit3d(upx, upy, upz, up);
-
- vectorCrossP3d(up, dir, left);
- vectorCrossP3d(dir, left, up); // THINKABOUTME: sicher ist sicher...
-
- vectorNormalize3d(dir, dir);
- vectorNormalize3d(up, up);
- vectorNormalize3d(left, left);
- }
-
-
- void Camera::lookAtScene(){
- vec3_t at;
-
- vectorAdd3d(pos, dir, at);
-
- gluLookAt(pos[0], pos[1], pos[2],
- at[0], at[1], at[2],
- up[0], up[1], up[2]);
-
- calculateFrustum();
- }
-
- void Camera::processInputArray(inputArray_t inputArray){
- unsigned int currentMillis = SDL_GetTicks();
-
- // if( lastProcessMillis >= currentMillis ) // sanity check
- // return;
-
- float deltaT = (currentMillis - lastProcessMillis)/1000.0f;
- lastProcessMillis = currentMillis;
-
- // printf("deltaT: %i\n", deltaT);
-
-
- vectorInit3d(0.0f, 0.0f, 0.0f, vel);
-
- if( mode==CAMERA_MODE_FIRST_PERSON && target != NULL ){
- }else if( mode==CAMERA_MODE_THIRD_PERSON && target != NULL ){
- if(inputArray[CAMERA_ZOOM_IN].pressed){
- zoomIn(deltaT);
- }
- if(inputArray[CAMERA_ZOOM_OUT].pressed){
- zoomOut(deltaT);
- }
- if(inputArray[CAMERA_ROTATE_LEFT].pressed){
- rotateLeft(deltaT);
- }
- if(inputArray[CAMERA_ROTATE_RIGHT].pressed){
- rotateRight(deltaT);
- }
- if(inputArray[CAMERA_ROTATE_UP].pressed){
- rotateUp(deltaT);
- }
- if(inputArray[CAMERA_ROTATE_DOWN].pressed){
- rotateDown(deltaT);
- }
- if(inputArray[CAMERA_RESET].pressed){
- reset();
- }
-
- }else/* if( mode==CAMERA_MODE_FREE )*/{
- if(inputArray[TURN_UP].pressed){
- turnUp(deltaT);
- }
- if(inputArray[TURN_DOWN].pressed){
- turnDown(deltaT);
- }
- if(inputArray[TURN_LEFT].pressed){
- turnLeft(deltaT);
- }
- if(inputArray[TURN_RIGHT].pressed){
- turnRight(deltaT);
- }
-
- if(inputArray[MOVE_FORWARD].pressed){
- moveForward(deltaT);
- }
- if(inputArray[MOVE_BACKWARD].pressed){
- moveBackward(deltaT);
- }
- if(inputArray[MOVE_LEFT].pressed){
- moveLeft(deltaT);
- }
- if(inputArray[MOVE_RIGHT].pressed){
- moveRight(deltaT);
- }
- if(inputArray[MOVE_UP].pressed){
- moveUp(deltaT);
- }
- if(inputArray[MOVE_DOWN].pressed){
- moveDown(deltaT);
- }
- }
-
- vectorsFromAngles();
- }
-
- void Camera::turnLeft(float deltaT){
- yaw = (float)fmod( yaw-(turnSpeed * deltaT), (2*PI));
- if(yaw<0.0f)
- yaw=yaw+(2*PI);
- }
-
- void Camera::turnRight(float deltaT){
- yaw = (float)fmod( yaw+(turnSpeed * deltaT), (2*PI));
- }
-
- void Camera::turnUp(float deltaT){
- pitch -= (turnSpeed * deltaT);
- if(pitch<GAME_OBJECT_MIN_PITCH)
- pitch=GAME_OBJECT_MIN_PITCH;
- }
-
- void Camera::turnDown(float deltaT){
- pitch += (turnSpeed * deltaT);
- if(pitch>GAME_OBJECT_MAX_PITCH)
- pitch=GAME_OBJECT_MAX_PITCH;
- }
-
- void Camera::moveForward(float deltaT){
- vectorMA3d(vel, deltaT*moveSpeed, dir, vel);
- }
- void Camera::moveBackward(float deltaT){
- vectorMA3d(vel, -deltaT*moveSpeed, dir, vel);
- }
- void Camera::moveLeft(float deltaT){
- vectorMA3d(vel, deltaT*moveSpeed, left, vel);
- }
- void Camera::moveRight(float deltaT){
- vectorMA3d(vel, -deltaT*moveSpeed, left, vel);
- }
- void Camera::moveUp(float deltaT){
- vectorMA3d(vel, deltaT*moveSpeed, e2, vel);
- }
- void Camera::moveDown(float deltaT){
- vectorMA3d(vel, -deltaT*moveSpeed, e2, vel);
- }
-
- void Camera::rotateLeft(float deltaT){
- azimutAngle -= deltaT * turnSpeed;
- if( azimutAngle < 0.0f*PI )
- azimutAngle += 2.0f*PI;
- }
- void Camera::rotateRight(float deltaT){
- azimutAngle += deltaT * turnSpeed;
- if( azimutAngle > 2.0f*PI )
- azimutAngle -= 2.0f*PI;
- }
- void Camera::rotateUp(float deltaT){
- elevationAngle += deltaT * turnSpeed;
- if( elevationAngle > 2.0f*PI )
- elevationAngle -= 2.0f*PI;
- }
- void Camera::rotateDown(float deltaT){
- elevationAngle -= deltaT * turnSpeed;
- if( elevationAngle < 0.0f*PI )
- elevationAngle += 2.0f*PI;
- }
-
- void Camera::move(){
- unsigned int currentMillis = SDL_GetTicks();
- float deltaT = (currentMillis - lastMoveMillis)/1000.0f;
- lastMoveMillis = currentMillis;
-
- // reconstructVectors(); // make sure local COSystem is orthonormal
-
- if( mode == CAMERA_MODE_FIRST_PERSON && target != NULL ){
- setPositionAndOrientation(target->pos, target->dir, target->up);
- }else if( mode == CAMERA_MODE_THIRD_PERSON && target != NULL ){
- // vec3_t pos, dir, up, left;
-
- vectorRotateAroundNormal3d(target->dir, target->up, azimutAngle, dir);
- vectorCrossP3d(target->up, dir, left);
- vectorRotateAroundNormal3d(dir, left, elevationAngle, dir);
- vectorCrossP3d(dir, left, up);
-
- vectorMA3d( target->pos, -zoom, dir, pos);
- // setPositionAndOrientation(pos, dir, up);
- anglesFromVectors();
-
- // yaw = target->yaw + azimutAngle;
- // pitch = elevationAngle;
- // vectorsFromAngles();
- // vectorMA3d( target->pos, -zoom, dir, pos);
- }else{ // free or no target
-
- if(vectorLengthSquared3d(vel)<0.0001f)
- return;
-
- // vectorNormalize3d(vel, vel);
- // vectorScale3d(deltaT*moveSpeed, vel, vel);
- if(noclip || collisionDetection(vel)) // check if move is save
- vectorAdd3d(pos, vel, pos); // ...and move
- }
- }
-
- bool Camera::collisionDetection(vec3_t displacement){
- Face* f;
- int numIterations = 0;
- vec3_t testPos;
- float t;
- trace_t trace;
- // trace.ignoreBackfaces=true; // collide only with front-facing faces
- // trace.ignoreNonSolids=true; // ...and solid faces
- trace.ignoreFlags = 0 | COLLISION_FLAG_BACKFACES | COLLISION_FLAG_WALK_THROUGH | COLLISION_FLAG_VEHICLES;
-
- do{
- vectorAdd3d(pos, displacement, testPos);
-
- // check if pos is save inside arena
- //trace.hits.clear();
- //Game::arena->sptree->traceAABB(pos, testPos, min, max, &trace);
- traceAABB(pos, testPos, moveAABB, &trace);
- if( !trace.hits.empty() ){ // collision! -> change displ.
- // printf("Collided with %i faces!\n", trace.hitFaces.size() );
- for(unsigned int i=0;i<trace.hits.size();i++){
- f = trace.hits[i].face; // only first face is of interest
- t = vectorDotP3d(f->normal, displacement);
- vectorMA3d(displacement, -t, f->normal, displacement);
- }
- }
-
-
- // count iterations
- numIterations++;
- if(numIterations>5 ){
- warn("(in Camera::collisionDetection()): Too many iterations. Aborting move.\n\n");
- vectorInit3d(0.0f, 0.0f, 0.0f, displacement);
- return false;
- }
-
- }while( !trace.hits.empty() );
-
- // check if pos is in arenas box
- if(testPos[0]+moveAABB.min[0] < Game::arena->min[0] && displacement[0] < 0.0f
- || testPos[0]+moveAABB.max[0] > Game::arena->max[0] && displacement[0] > 0.0f){
- displacement[0] = 0.0f;
- }
- if(testPos[1]+moveAABB.min[1] < Game::arena->min[1] && displacement[1] < 0.0f
- || testPos[1]+moveAABB.max[1] > Game::arena->max[1] && displacement[1] > 0.0f){
- displacement[1] = 0.0f;
- }
- if(testPos[2]+moveAABB.min[2] < Game::arena->min[2] && displacement[2] < 0.0f
- || testPos[2]+moveAABB.max[2] > Game::arena->max[2] && displacement[2] > 0.0f){
- displacement[2] = 0.0f;
- }
-
-
- return true;
- }
-
-
- void Camera::chaseNext(){
- int i;
- int startSlot = 0;
- if( Game::cam.target == NULL ){
- startSlot = 0;
- }else{
- for(i=0;i<GAME_MAX_VEHICLES;i++){
- if( Game::vehicles[i] != NULL && Game::vehicles[i] == Game::cam.target ){
- startSlot = i;
- break;
- }
- }
- }
-
- for(i=startSlot+1;i<GAME_MAX_VEHICLES;i++){
- if( Game::vehicles[i] != NULL ){
- Game::cam.setTarget(Game::vehicles[i]);
- return;
- }
- }
- for(i=0;i<=startSlot;i++){
- if( Game::vehicles[i] != NULL ){
- Game::cam.setTarget(Game::vehicles[i]);
- return;
- }
- }
-
- Game::cam.setTarget(NULL);
- }
-
- void Camera::chasePrevious(){
- int i;
- int startSlot = 0;
- if( Game::cam.target == NULL ){
- startSlot = 0;
- }else{
- for(i=0; i<GAME_MAX_VEHICLES; i++){
- if( Game::vehicles[i] != NULL && Game::vehicles[i] == Game::cam.target ){
- startSlot = i;
- break;
- }
- }
- }
-
- for(i=startSlot-1; i>=0; i--){
- if( Game::vehicles[i] != NULL ){
- Game::cam.setTarget(Game::vehicles[i]);
- return;
- }
- }
- for(i=Network::server->si.maxClients-1; i>=startSlot; i--){
- if( Game::vehicles[i] != NULL ){
- Game::cam.setTarget(Game::vehicles[i]);
- return;
- }
- }
-
- Game::cam.setTarget(NULL);
- }
-
-
- void Camera::zoomIn(float deltaT){
- zoom -= deltaT * moveSpeed;
- if( zoom < 1.5f )
- zoom = 1.5f;
- }
- void Camera::zoomOut(float deltaT){
- zoom += deltaT * moveSpeed;
- if( zoom > 100.0f )
- zoom = 100.0f;
- }
-
-
- void Camera::reset(){
- elevationAngle = 0.0f;
- azimutAngle = 0.0f;
- zoom = 5.0f;
- }
-
-
-
-
-
-
-
-
-
-
-
- // We create an enum of the sides so we don't have to call each side 0 or 1.
- // This way it makes it more understandable and readable when dealing with frustum sides.
- enum FrustumSide
- {
- RIGHT = 0, // The RIGHT side of the frustum
- LEFT = 1, // The LEFT side of the frustum
- BOTTOM = 2, // The BOTTOM side of the frustum
- TOP = 3, // The TOP side of the frustum
- BACK = 4, // The BACK side of the frustum
- FRONT = 5 // The FRONT side of the frustum
- };
-
- // Like above, instead of saying a number for the ABC and D of the plane, we
- // want to be more descriptive.
- enum PlaneData
- {
- A = 0, // The X value of the plane's normal
- B = 1, // The Y value of the plane's normal
- C = 2, // The Z value of the plane's normal
- D = 3 // The distance the plane is from the origin
- };
-
- ///////////////////////////////// NORMALIZE PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
- /////
- ///// This normalizes a plane (A side) from a given frustum.
- /////
- ///////////////////////////////// NORMALIZE PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
-
- static void normalizePlane(float frustum[6][4], int side)
- {
- // Here we calculate the magnitude of the normal to the plane (point A B C)
- // Remember that (A, B, C) is that same thing as the normal's (X, Y, Z).
- // To calculate magnitude you use the equation: magnitude = sqrt( x^2 + y^2 + z^2)
- float magnitude = (float)sqrt( frustum[side][A] * frustum[side][A] +
- frustum[side][B] * frustum[side][B] +
- frustum[side][C] * frustum[side][C] );
-
- // Then we divide the plane's values by it's magnitude.
- // This makes it easier to work with.
- frustum[side][A] /= magnitude;
- frustum[side][B] /= magnitude;
- frustum[side][C] /= magnitude;
- frustum[side][D] /= magnitude;
- }
-
-
- ///////////////////////////////// CALCULATE FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
- /////
- ///// This extracts our frustum from the projection and modelview matrix.
- /////
- ///////////////////////////////// CALCULATE FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
-
- void Camera::calculateFrustum()
- {
- float proj[16]; // This will hold our projection matrix
- float modl[16]; // This will hold our modelview matrix
- float clip[16]; // This will hold the clipping planes
-
- // glGetFloatv() is used to extract information about our OpenGL world.
- // Below, we pass in GL_PROJECTION_MATRIX to abstract our projection matrix.
- // It then stores the matrix into an array of [16].
- glGetFloatv( GL_PROJECTION_MATRIX, proj );
-
- // By passing in GL_MODELVIEW_MATRIX, we can abstract our model view matrix.
- // This also stores it in an array of [16].
- glGetFloatv( GL_MODELVIEW_MATRIX, modl );
-
- // Now that we have our modelview and projection matrix, if we combine these 2 matrices,
- // it will give us our clipping planes. To combine 2 matrices, we multiply them.
-
- clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
- clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
- clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
- clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
-
- clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
- clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
- clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
- clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
-
- clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
- clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
- clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
- clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
-
- clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
- clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
- clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
- clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
-
- // Now we actually want to get the sides of the frustum. To do this we take
- // the clipping planes we received above and extract the sides from them.
-
- // This will extract the RIGHT side of the frustum
- frustum[RIGHT][A] = clip[ 3] - clip[ 0];
- frustum[RIGHT][B] = clip[ 7] - clip[ 4];
- frustum[RIGHT][C] = clip[11] - clip[ 8];
- frustum[RIGHT][D] = clip[15] - clip[12];
-
- // Now that we have a normal (A,B,C) and a distance (D) to the plane,
- // we want to normalize that normal and distance.
-
- // Normalize the RIGHT side
- normalizePlane(frustum, RIGHT);
-
- // This will extract the LEFT side of the frustum
- frustum[LEFT][A] = clip[ 3] + clip[ 0];
- frustum[LEFT][B] = clip[ 7] + clip[ 4];
- frustum[LEFT][C] = clip[11] + clip[ 8];
- frustum[LEFT][D] = clip[15] + clip[12];
-
- // Normalize the LEFT side
- normalizePlane(frustum, LEFT);
-
- // This will extract the BOTTOM side of the frustum
- frustum[BOTTOM][A] = clip[ 3] + clip[ 1];
- frustum[BOTTOM][B] = clip[ 7] + clip[ 5];
- frustum[BOTTOM][C] = clip[11] + clip[ 9];
- frustum[BOTTOM][D] = clip[15] + clip[13];
-
- // Normalize the BOTTOM side
- normalizePlane(frustum, BOTTOM);
-
- // This will extract the TOP side of the frustum
- frustum[TOP][A] = clip[ 3] - clip[ 1];
- frustum[TOP][B] = clip[ 7] - clip[ 5];
- frustum[TOP][C] = clip[11] - clip[ 9];
- frustum[TOP][D] = clip[15] - clip[13];
-
- // Normalize the TOP side
- normalizePlane(frustum, TOP);
-
- // This will extract the BACK side of the frustum
- frustum[BACK][A] = clip[ 3] - clip[ 2];
- frustum[BACK][B] = clip[ 7] - clip[ 6];
- frustum[BACK][C] = clip[11] - clip[10];
- frustum[BACK][D] = clip[15] - clip[14];
-
- // Normalize the BACK side
- normalizePlane(frustum, BACK);
-
- // This will extract the FRONT side of the frustum
- frustum[FRONT][A] = clip[ 3] + clip[ 2];
- frustum[FRONT][B] = clip[ 7] + clip[ 6];
- frustum[FRONT][C] = clip[11] + clip[10];
- frustum[FRONT][D] = clip[15] + clip[14];
-
- // Normalize the FRONT side
- normalizePlane(frustum, FRONT);
- }
-
- // The code below will allow us to make checks within the frustum. For example,
- // if we want to see if a point, a sphere, or a cube lies inside of the frustum.
- // Because all of our planes point INWARDS (The normals are all pointing inside the frustum)
- // we then can assume that if a point is in FRONT of all of the planes, it's inside.
-
- ///////////////////////////////// POINT IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
- /////
- ///// This determines if a point is inside of the frustum
- /////
- ///////////////////////////////// POINT IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
-
- bool Camera::pointInFrustum( float x, float y, float z )
- {
- // If you remember the plane equation (A*x + B*y + C*z + D = 0), then the rest
- // of this code should be quite obvious and easy to figure out yourself.
- // In case don't know the plane equation, it might be a good idea to look
- // at our Plane Collision tutorial at www.GameTutorials.com in OpenGL Tutorials.
- // I will briefly go over it here. (A,B,C) is the (X,Y,Z) of the normal to the plane.
- // They are the same thing... but just called ABC because you don't want to say:
- // (x*x + y*y + z*z + d = 0). That would be wrong, so they substitute them.
- // the (x, y, z) in the equation is the point that you are testing. The D is
- // The distance the plane is from the origin. The equation ends with "= 0" because
- // that is true when the point (x, y, z) is ON the plane. When the point is NOT on
- // the plane, it is either a negative number (the point is behind the plane) or a
- // positive number (the point is in front of the plane). We want to check if the point
- // is in front of the plane, so all we have to do is go through each point and make
- // sure the plane equation goes out to a positive number on each side of the frustum.
- // The result (be it positive or negative) is the distance the point is front the plane.
-
- // Go through all the sides of the frustum
- for(int i = 0; i < 6; i++ )
- {
- // Calculate the plane equation and check if the point is behind a side of the frustum
- if(frustum[i][A] * x + frustum[i][B] * y + frustum[i][C] * z + frustum[i][D] <= 0)
- {
- // The point was behind a side, so it ISN'T in the frustum
- return false;
- }
- }
-
- // The point was inside of the frustum (In front of ALL the sides of the frustum)
- return true;
- }
-
-
- ///////////////////////////////// SPHERE IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
- /////
- ///// This determines if a sphere is inside of our frustum by it's center and radius.
- /////
- ///////////////////////////////// SPHERE IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
-
- bool Camera::sphereInFrustum( float x, float y, float z, float radius )
- {
- // Now this function is almost identical to the PointInFrustum(), except we
- // now have to deal with a radius around the point. The point is the center of
- // the radius. So, the point might be outside of the frustum, but it doesn't
- // mean that the rest of the sphere is. It could be half and half. So instead of
- // checking if it's less than 0, we need to add on the radius to that. Say the
- // equation produced -2, which means the center of the sphere is the distance of
- // 2 behind the plane. Well, what if the radius was 5? The sphere is still inside,
- // so we would say, if(-2 < -5) then we are outside. In that case it's false,
- // so we are inside of the frustum, but a distance of 3. This is reflected below.
-
- // Go through all the sides of the frustum
- for(int i = 0; i < 6; i++ )
- {
- // If the center of the sphere is farther away from the plane than the radius
- if( frustum[i][A] * x + frustum[i][B] * y + frustum[i][C] * z + frustum[i][D] <= -radius )
- {
- // The distance was greater than the radius so the sphere is outside of the frustum
- return false;
- }
- }
-
- // The sphere was inside of the frustum!
- return true;
- }
-
- bool Camera::sphereInFrustum( vec3_t pos, float radius )
- {
-
- // Go through all the sides of the frustum
- for(int i = 0; i < 6; i++ )
- {
- // If the center of the sphere is farther away from the plane than the radius
- if( frustum[i][A] * pos[0] + frustum[i][B] * pos[1] + frustum[i][C] * pos[2] + frustum[i][D] <= -radius )
- {
- // The distance was greater than the radius so the sphere is outside of the frustum
- return false;
- }
- }
-
- // The sphere was inside of the frustum!
- return true;
- }
-
-
- ///////////////////////////////// CUBE IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
- /////
- ///// This determines if a cube is in or around our frustum by it's center and 1/2 it's length
- /////
- ///////////////////////////////// CUBE IN FRUSTUM \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
-
- bool Camera::cubeInFrustum( float x, float y, float z, float size )
- {
- // This test is a bit more work, but not too much more complicated.
- // Basically, what is going on is, that we are given the center of the cube,
- // and half the length. Think of it like a radius. Then we checking each point
- // in the cube and seeing if it is inside the frustum. If a point is found in front
- // of a side, then we skip to the next side. If we get to a plane that does NOT have
- // a point in front of it, then it will return false.
-
- // *Note* - This will sometimes say that a cube is inside the frustum when it isn't.
- // This happens when all the corners of the bounding box are not behind any one plane.
- // This is rare and shouldn't effect the overall rendering speed.
-
- for(int i = 0; i < 6; i++ )
- {
- if(frustum[i][A] * (x - size) + frustum[i][B] * (y - size) + frustum[i][C] * (z - size) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x + size) + frustum[i][B] * (y - size) + frustum[i][C] * (z - size) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x - size) + frustum[i][B] * (y + size) + frustum[i][C] * (z - size) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x + size) + frustum[i][B] * (y + size) + frustum[i][C] * (z - size) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x - size) + frustum[i][B] * (y - size) + frustum[i][C] * (z + size) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x + size) + frustum[i][B] * (y - size) + frustum[i][C] * (z + size) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x - size) + frustum[i][B] * (y + size) + frustum[i][C] * (z + size) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x + size) + frustum[i][B] * (y + size) + frustum[i][C] * (z + size) + frustum[i][D] > 0)
- continue;
-
- // If we get here, it isn't in the frustum
- return false;
- }
-
- return true;
- }
-
- bool Camera::AABBInFrustum(vec3_t min, vec3_t max)
- {
- float x=(min[0]+max[0])*0.5f;
- float y=(min[1]+max[1])*0.5f;
- float z=(min[2]+max[2])*0.5f;
-
- vec3_t size;
- vectorInit3d(max[0]-min[0], max[1]-min[1], max[2]-min[2], size);
-
- for(int i = 0; i < 6; i++ )
- {
- if(frustum[i][A] * (x - size[0]) + frustum[i][B] * (y - size[1]) + frustum[i][C] * (z - size[2]) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x + size[0]) + frustum[i][B] * (y - size[1]) + frustum[i][C] * (z - size[2]) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x - size[0]) + frustum[i][B] * (y + size[1]) + frustum[i][C] * (z - size[2]) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x + size[0]) + frustum[i][B] * (y + size[1]) + frustum[i][C] * (z - size[2]) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x - size[0]) + frustum[i][B] * (y - size[1]) + frustum[i][C] * (z + size[2]) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x + size[0]) + frustum[i][B] * (y - size[1]) + frustum[i][C] * (z + size[2]) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x - size[0]) + frustum[i][B] * (y + size[1]) + frustum[i][C] * (z + size[2]) + frustum[i][D] > 0)
- continue;
- if(frustum[i][A] * (x + size[0]) + frustum[i][B] * (y + size[1]) + frustum[i][C] * (z + size[2]) + frustum[i][D] > 0)
- continue;
-
- // If we get here, it isn't in the frustum
- return false;
- }
-
- return true;
- }
-