This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  GL_Export For 3DS Max Users
  Submitted by



If you are a 3DS Max user and want your Max scene to appear in your OpenGL project, this smart utility does just that. Please read the provided readme.html.


Currently browsing [GL_Export1.zip] (104,965 bytes) - [BlankProject/Main.cpp] - (4,182 bytes)


#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glaux.lib")

#include "main.h" #include <math.h> #include "Camera.h"

// Include Your Header File Here // Then Call Function CreateMaterialLib() // Don't forget Create<YourObj/s>() // in RenderScene() Call glCallList Function to Call your Objects ObjectID #define INC 3.0 #define R_180 3.142857142 #define R_90 1.571428571

bool g_bFullScreen = 1; // Set full screen as default HWND g_hWnd; // This is the handle for the window RECT g_rRect; // This holds the window dimensions HDC g_hDC; // General HDC - (handle to device context) HGLRC g_hRC; // General OpenGL_DC - Our Rendering Context for OpenGL HINSTANCE g_hInstance; // This holds the global hInstance for UnregisterClass() in DeInit() float rotationH,rotationV; Point3 CamPos, CamTar; float thetha,thethaV=0; float focullength=2; float step=5;

GLfloat Vertex[] = { -75.0000, -50.0000, 0.0000, 75.0000, -50.0000, 0.0000, -75.0000, 50.0000, 0.0000, 75.0000, 50.0000, 0.0000 };

GLfloat TVertex[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, }; CCamera g_Camera;

UINT g_Texture[MAX_TEXTURES];

void Init(HWND hWnd) { g_hWnd = hWnd; // Assign the window handle to a global window handle GetClientRect(g_hWnd, &g_rRect); // Assign the windows rectangle to a global RECT InitializeOpenGL(g_rRect.right, g_rRect.bottom); // Init OpenGL with the global rect // CreateMaterialLib() here and // Object's Create Functions

g_Camera.PositionCamera( 10,150,12, 9,150,12, 0,1,0 ); g_Camera.SetCameraRadius(1);

}

WPARAM MainLoop() { MSG msg; while(1) // Do our infinate loop { // Check if there was a message if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(msg.message == WM_QUIT) // If the message wasnt to quit break; TranslateMessage(&msg); // Find out what the message does DispatchMessage(&msg); // Execute the message } else // if there wasn't a message { g_Camera.Update(); RenderScene(); // Redraw the scene every frame } }

DeInit(); // Free all the app's memory allocated return(msg.wParam); // Return from the program }

void RenderScene() { CamTar.x = CamPos.x+focullength*cos( thetha ); CamTar.z = CamPos.z+focullength*sin( thetha ); CamPos.y = 100; CamTar.y = 100;

glVertexPointer( 3, GL_FLOAT, 0, Vertex ); glTexCoordPointer(2, GL_FLOAT, 0, TVertex );

glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); g_Camera.Look(); glPushMatrix();

// Call Your Object Lists Here by // glCallList() // Like glCallList( BOX01 ) if BOX01 is defined. glPopMatrix(); SwapBuffers(g_hDC); // Swap the backbuffers to the foreground }



LRESULT CALLBACK WinProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { LONG lRet = 0; PAINTSTRUCT ps; static int lxPos,lyPos; static int xPos, yPos;

POINT mpos; switch (uMsg) { case WM_SIZE: // If the window is resized if(!g_bFullScreen) // Do this only if we are NOT in full screen { SizeOpenGLScreen(LOWORD(lParam),HIWORD(lParam));// LoWord=Width, HiWord=Height GetClientRect(hWnd, &g_rRect); } break; case WM_PAINT: // If we need to repaint the scene BeginPaint(hWnd, &ps); // Init the paint struct EndPaint(hWnd, &ps); // EndPaint, Clean up break; case WM_CLOSE: // If the window is being closes PostQuitMessage(0); // Send a QUIT Message to the window break; default: // Return by default lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); break; } return lRet; // Return by default }

Currently browsing [GL_Export1.zip] (104,965 bytes) - [BlankProject/3DMath.h] - (4,395 bytes)

#ifndef _3DMATH_H
#define _3DMATH_H

#define PI 3.1415926535897932 // This is our famous PI #define BEHIND 0 #define INTERSECTS 1 #define FRONT 2

// This is our basic 3D point/vector class struct CVector3 { public: // A default constructor CVector3() {} CVector3( CVector3 *vPos ) { x = vPos->x; y = vPos->y; z = vPos->z; } // This is our constructor that allows us to initialize our data upon creating an instance CVector3(float X, float Y, float Z) { x = X; y = Y; z = Z; }

// Here we overload the + operator so we can add vectors together CVector3 operator+(CVector3 vVector) { // Return the added vectors result. return CVector3(vVector.x + x, vVector.y + y, vVector.z + z); }

// Here we overload the - operator so we can subtract vectors CVector3 operator-(CVector3 vVector) { // Return the subtracted vectors result return CVector3(x - vVector.x, y - vVector.y, z - vVector.z); } // Here we overload the * operator so we can multiply by scalars CVector3 operator*(float num) { // Return the scaled vector return CVector3(x * num, y * num, z * num); }

// Here we overload the / operator so we can divide by a scalar CVector3 operator/(float num) { // Return the scale vector return CVector3(x / num, y / num, z / num); }

float x, y, z; };

// This returns the absolute value of "num" float Absolute(float num);

// This returns a perpendicular vector from 2 given vectors by taking the cross product. CVector3 Cross(CVector3 vVector1, CVector3 vVector2);

// This returns the magnitude of a normal (or any other vector) float Magnitude(CVector3 vNormal);

// This returns a normalize vector (A vector exactly of length 1) CVector3 Normalize(CVector3 vNormal);

// This returns the normal of a polygon (The direction the polygon is facing) CVector3 Normal(CVector3 vPolygon[]);

// This returns the distance between 2 3D points float Distance(CVector3 vPoint1, CVector3 vPoint2);

// This returns the point on the line segment vA_vB that is closest to point vPoint CVector3 ClosestPointOnLine(CVector3 vA, CVector3 vB, CVector3 vPoint);

// This returns the distance the plane is from the origin (0, 0, 0) // It takes the normal to the plane, along with ANY point that lies on the plane (any corner) float PlaneDistance(CVector3 Normal, CVector3 Point);

// This takes a triangle (plane) and line and returns true if they intersected bool IntersectedPlane(CVector3 vPoly[], CVector3 vLine[], CVector3 &vNormal, float &originDistance);

// This returns the dot product between 2 vectors float Dot(CVector3 vVector1, CVector3 vVector2);

// This returns the angle between 2 vectors double AngleBetweenVectors(CVector3 Vector1, CVector3 Vector2);

// This returns an intersection point of a polygon and a line (assuming intersects the plane) CVector3 IntersectionPoint(CVector3 vNormal, CVector3 vLine[], double distance);

// This returns true if the intersection point is inside of the polygon bool InsidePolygon(CVector3 vIntersection, CVector3 Poly[], long verticeCount);

// Use this function to test collision between a line and polygon bool IntersectedPolygon(CVector3 vPoly[], CVector3 vLine[], int verticeCount);

// This function classifies a sphere according to a plane. (BEHIND, in FRONT, or INTERSECTS) int ClassifySphere(CVector3 &vCenter, CVector3 &vNormal, CVector3 &vPoint, float radius, float &distance);

// This takes in the sphere center, radius, polygon vertices and vertex count. // This function is only called if the intersection point failed. The sphere // could still possibly be intersecting the polygon, but on it's edges. bool EdgeSphereCollision(CVector3 &vCenter, CVector3 vPolygon[], int vertexCount, float radius);

// This returns true if the sphere is intersecting with the polygon. bool SpherePolygonCollision(CVector3 vPolygon[], CVector3 &vCenter, int vertexCount, float radius);

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // This returns the offset the sphere needs to move in order to not intersect the plane CVector3 GetCollisionOffset(CVector3 &vNormal, float radius, float distance);

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * #endif


Currently browsing [GL_Export1.zip] (104,965 bytes) - [BlankProject/Camera.cpp] - (13,155 bytes)

//***********************************************************************//
//																		 //
//		- "Talk to me like I'm a 3 year old!" Programming Lessons -		 //
//                                                                       //
//		$Author:		DigiBen		DigiBen@GameTutorials.com			 //
//																		 //
//		$Program:		BSP Loader										 //
//																		 //
//		$Description:	Loads faces and textures from a Quake3 BSP file  //
//																		 //
//		$Date:			5/9/02											 //
//																		 //
//***********************************************************************//


#include "main.h" #include "Camera.h"

// We increased the speed a bit from the Camera Strafing Tutorial // This is how fast our camera moves #define kSpeed 190.0f

// Our global float that stores the elapsed time between the current and last frame float g_FrameInterval = 0.0f;

///////////////////////////////// CALCULATE FRAME RATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This function calculates the frame rate and time intervals between frames ///// ///////////////////////////////// CALCULATE FRAME RATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* void CalculateFrameRate() { static float framesPerSecond = 0.0f; // This will store our fps static float lastTime = 0.0f; // This will hold the time from the last frame static char strFrameRate[50] = {0}; // We will store the string here for the window title static float frameTime = 0.0f; // This stores the last frame's time // Get the current time in seconds float currentTime = timeGetTime() * 0.001f;

// Here we store the elapsed time between the current and last frame, // then keep the current frame in our static variable for the next frame. g_FrameInterval = currentTime - frameTime; frameTime = currentTime;

// Increase the frame counter ++framesPerSecond;

// Now we want to subtract the current time by the last time that was stored // to see if the time elapsed has been over a second, which means we found our FPS. if( currentTime - lastTime > 1.0f ) { // Here we set the lastTime to the currentTime lastTime = currentTime; // Copy the frames per second into a string to display in the window title bar sprintf(strFrameRate, "Current Frames Per Second: %d", int(framesPerSecond));

// Set the window title bar to our string SetWindowText(g_hWnd, strFrameRate);

// Reset the frames per second framesPerSecond = 0; } }

///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This is the class constructor ///// ///////////////////////////////// CCAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* CCamera::CCamera() { CVector3 vZero = CVector3(0.0, 0.0, 0.0); // Init a vVector to 0 0 0 for our position CVector3 vView = CVector3(0.0, 1.0, 0.5); // Init a starting view vVector (looking up and out the screen) CVector3 vUp = CVector3(0.0, 0.0, 1.0); // Init a standard up vVector (Rarely ever changes) m_vPosition = vZero; // Init the position to zero m_vView = vView; // Init the view to a std starting view m_vUpVector = vUp; // Init the UpVector for( int i=0; i<10 ; i++ ) { for( int j=0 ; j<10 ; j++ ) { if( i==0 || j==0 || i==9 || j==9 ) Map[i][j] = 1; else Map[i][j] = 0;

} } }

///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This function sets the camera's position and view and up vVector. ///// ///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* void CCamera::PositionCamera(float positionX, float positionY, float positionZ, float viewX, float viewY, float viewZ, float upVectorX, float upVectorY, float upVectorZ) { CVector3 vPosition = CVector3(positionX, positionY, positionZ); CVector3 vView = CVector3(viewX, viewY, viewZ); CVector3 vUpVector = CVector3(upVectorX, upVectorY, upVectorZ);

// The code above just makes it cleaner to set the variables. // Otherwise we would have to set each variable x y and z. m_vPosition = vPosition; // Assign the position m_vView = vView; // Assign the view m_vUpVector = vUpVector; // Assign the up vector }

///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This allows us to look around using the mouse, like in most first person games. ///// ///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* void CCamera::SetViewByMouse() { POINT mousePos; // This is a window structure that holds an X and Y int middleX = SCREEN_WIDTH >> 1; // This is a binary shift to get half the width int middleY = SCREEN_HEIGHT >> 1; // This is a binary shift to get half the height float angleY = 0.0f; // This is the direction for looking up or down float angleZ = 0.0f; // This will be the value we need to rotate around the Y axis (Left and Right) static float currentRotX = 0.0f; // Get the mouse's current X,Y position GetCursorPos(&mousePos); // If our cursor is still in the middle, we never moved... so don't update the screen if( (mousePos.x == middleX) && (mousePos.y == middleY) ) return;

// Set the mouse position to the middle of our window SetCursorPos(middleX, middleY);

// Get the direction the mouse moved in, but bring the number down to a reasonable amount angleY = (float)( (middleX - mousePos.x) ) / 500.0f; angleZ = (float)( (middleY - mousePos.y) ) / 500.0f;

// Here we keep track of the current rotation (for up and down) so that // we can restrict the camera from doing a full 360 loop. currentRotX -= angleZ;

/* Kapil This is desable because it restricts the viewing angle // If the current rotation (in radians) is greater than 1.0, we want to cap it. if(currentRotX > 1.0f) currentRotX = 1.0f; // Check if the rotation is below -1.0, if so we want to make sure it doesn't continue else if(currentRotX < -1.0f) currentRotX = -1.0f; // Otherwise, we can rotate the view around our position else {*/ // To find the axis we need to rotate around for up and down // movements, we need to get a perpendicular vector from the // camera's view vector and up vector. This will be the axis. CVector3 vAxis = Cross(m_vView - m_vPosition, m_vUpVector); vAxis = Normalize(vAxis);

// Rotate around our perpendicular axis and along the y-axis RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z); RotateView(angleY, 0, 1, 0); //} }

///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This rotates the view around the position using an axis-angle rotation ///// ///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* void CCamera::RotateView(float angle, float x, float y, float z) { CVector3 vNewView;

// Get the view vector (The direction we are facing) CVector3 vView = m_vView - m_vPosition;

// Calculate the sine and cosine of the angle once float cosTheta = (float)cos(angle); float sinTheta = (float)sin(angle);

// Find the new x position for the new rotated point vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x; vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y; vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;

// Find the new y position for the new rotated point vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x; vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y; vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;

// Find the new z position for the new rotated point vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x; vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y; vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;

// Now we just add the newly rotated vector to our position to set // our new rotated view of our camera. m_vView = m_vPosition + vNewView; }

///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This strafes the camera left and right depending on the speed (-/+) ///// ///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* void CCamera::StrafeCamera(float speed) { // Add the strafe vector to our position CVector3 m_vPosition1 ( &m_vPosition ),m_vView1( &m_vView ); m_vPosition1.x += m_vStrafe.x * speed; m_vPosition1.z += m_vStrafe.z * speed;

// Add the strafe vector to our view m_vView1.x += m_vStrafe.x * speed; m_vView1.z += m_vStrafe.z * speed; if( m_vPosition1.x > -800 && m_vPosition1.x < 230 && m_vPosition1.z > -190 && m_vPosition1.z < 770 ) { m_vPosition.x = m_vPosition1.x; m_vPosition.z = m_vPosition1.z;

m_vView.x = m_vView1.x; m_vView.z = m_vView1.z; } }

///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This will move the camera forward or backward depending on the speed ///// ///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* void CCamera::MoveCamera(float speed) { // Get the current view vector (the direction we are looking) CVector3 m_vPosition1 ( &m_vPosition ),m_vView1( &m_vView ); CVector3 vVector = m_vView - m_vPosition; vVector = Normalize(vVector); m_vPosition1.x += vVector.x * speed; // Add our acceleration to our position's X m_vPosition1.y += vVector.y * speed; // Add our acceleration to our position's Y m_vPosition1.z += vVector.z * speed; // Add our acceleration to our position's Z m_vView1.x += vVector.x * speed; // Add our acceleration to our view's X m_vView1.y += vVector.y * speed; // Add our acceleration to our view's Y m_vView1.z += vVector.z * speed; // Add our acceleration to our view's Z // Here should be the collision testing condition..... if( m_vPosition1.x > -800 && m_vPosition1.x < 230 && m_vPosition1.z > -190 && m_vPosition1.z < 770 ) { m_vPosition.x = m_vPosition1.x; m_vPosition.y = m_vPosition1.y; m_vPosition.z = m_vPosition1.z;

m_vView.x = m_vView1.x; m_vView.y = m_vView1.y; m_vView.z = m_vView1.z; } }

//////////// *** NEW *** ////////// *** NEW *** ///////////// *** NEW *** //////////////////// ///////////////////////////////// CHECK CAMERA COLLISION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This checks all the polygons in our list and offsets the camera if collided ///// ///////////////////////////////// CHECK CAMERA COLLISION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* void CCamera::CheckCameraCollision(CVector3 *pVertices, int numOfVerts) { for(int i = 0; i < numOfVerts; i += 3) {

CVector3 vTriangle[3] = { pVertices[i], pVertices[i+1], pVertices[i+2] }; CVector3 vNormal = Normal(vTriangle); float distance = 0.0f; int classification = ClassifySphere(m_vPosition, vNormal, vTriangle[0], m_radius, distance); if(classification == INTERSECTS) {

CVector3 vOffset = vNormal * distance; CVector3 vIntersection = m_vPosition - vOffset; if(InsidePolygon(vIntersection, vTriangle, 3) || EdgeSphereCollision(m_vPosition, vTriangle, 3, m_radius / 2)) { vOffset = GetCollisionOffset(vNormal, m_radius, distance); m_vPosition = m_vPosition + vOffset; m_vView = m_vView + vOffset; } } } }

void CCamera::CheckForMovement() { float speed = kSpeed * g_FrameInterval;

x = (m_vView.x + 750 )/100; y = (m_vView.z + 180 )/100; if(GetKeyState(VK_UP) & 0x80 || GetKeyState('W') & 0x80) {

MoveCamera(speed); }

if(GetKeyState(VK_DOWN) & 0x80 || GetKeyState('S') & 0x80) { MoveCamera(-speed); }

if(GetKeyState(VK_LEFT) & 0x80 || GetKeyState('A') & 0x80) { StrafeCamera(-speed); }

// Check if we hit the Right arrow or the 'd' key if(GetKeyState(VK_RIGHT) & 0x80 || GetKeyState('D') & 0x80) {

// Strafe the camera right StrafeCamera(speed); } }

void CCamera::Update() { // Initialize a variable for the cross product result CVector3 vCross = Cross(m_vView - m_vPosition, m_vUpVector);

// Normalize the strafe vector m_vStrafe = Normalize(vCross);

// Move the camera's view by the mouse SetViewByMouse();

// This checks to see if the keyboard was pressed CheckForMovement(); // Calculate our frame rate and set our frame interval for time based movement CalculateFrameRate(); }

void CCamera::Look() {

gluLookAt(m_vPosition.x, m_vPosition.y, m_vPosition.z, m_vView.x, m_vView.y, m_vView.z, m_vUpVector.x, m_vUpVector.y, m_vUpVector.z); }

///////////////////////////////////////////////////////////////////////////////// // // * QUICK NOTES * // // // // Ben Humphrey (DigiBen) // Game Programmer // DigiBen@GameTutorials.com // Co-Web Host of www.GameTutorials.com // //

Currently browsing [GL_Export1.zip] (104,965 bytes) - [BlankProject/Camera.h] - (2,740 bytes)

#ifndef _CAMERA_H
#define _CAMERA_H

#include <mmsystem.h>

class CCamera {

public: int x, y; int Map[10][10];

// Our camera constructor CCamera();

// These are are data access functions for our camera's private data CVector3 Position() { return m_vPosition; } CVector3 View() { return m_vView; } CVector3 UpVector() { return m_vUpVector; } CVector3 Strafe() { return m_vStrafe; }

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // This intializes the camera's sphere radius void SetCameraRadius(float radius) { m_radius = radius; };

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *

// This changes the position, view, and up vector of the camera. // This is primarily used for initialization void PositionCamera(float positionX, float positionY, float positionZ, float viewX, float viewY, float viewZ, float upVectorX, float upVectorY, float upVectorZ);

// This rotates the camera's view around the position depending on the values passed in. void RotateView(float angle, float X, float Y, float Z);

// This moves the camera's view by the mouse movements (First person view) void SetViewByMouse();

// This rotates the camera around a point (I.E. your character). void RotateAroundPoint(CVector3 vCenter, float X, float Y, float Z);

// This strafes the camera left or right depending on the speed (+/-) void StrafeCamera(float speed);

// This will move the camera forward or backward depending on the speed void MoveCamera(float speed);

// This checks for keyboard movement void CheckForMovement();

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // This takes a list of vertices and the vertex count to determine if the camera's // shere has collided with them. void CheckCameraCollision(CVector3 *pVertices, int numOfVerts);

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *

// This updates the camera's view and other data (Should be called each frame) void Update();

// This uses gluLookAt() to tell OpenGL where to look void Look();

private:

// The camera's position CVector3 m_vPosition;

// The camera's view CVector3 m_vView;

// The camera's up vector CVector3 m_vUpVector; // The camera's strafe vector CVector3 m_vStrafe;

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // The camera's collision radius float m_radius;

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * };

#endif


Currently browsing [GL_Export1.zip] (104,965 bytes) - [BlankProject/Init.cpp] - (7,758 bytes)



#include "main.h"

void CreateTexture(UINT textureArray[], LPSTR strFileName, int textureID) { AUX_RGBImageRec *pBitmap = NULL; if(!strFileName) return; pBitmap = auxDIBImageLoad( strFileName );

if(pBitmap == NULL) exit(0);

glGenTextures(1, &textureArray[textureID]); glBindTexture(GL_TEXTURE_2D, textureArray[textureID]);

gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pBitmap->sizeX, pBitmap->sizeY, GL_RGB, GL_UNSIGNED_BYTE, pBitmap->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);//GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);//GL_NEAREST); //GL_NEAREST if (pBitmap) // If we loaded the bitmap { if (pBitmap->data) // If there is texture data { free(pBitmap->data); // Free the texture data, we don't need it anymore }

free(pBitmap); // Free the bitmap structure } }

void ChangeToFullScreen() { DEVMODE dmSettings; // Device Mode variable memset(&dmSettings,0,sizeof(dmSettings)); // Makes Sure Memory's Cleared if(!EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dmSettings)) { MessageBox(NULL, "Could No t Enum Display Settings", "Error", MB_OK); return; }

dmSettings.dmPelsWidth = SCREEN_WIDTH; // Selected Screen Width dmSettings.dmPelsHeight = SCREEN_HEIGHT; // Selected Screen Height int result = ChangeDisplaySettings(&dmSettings,CDS_FULLSCREEN);

if(result != DISP_CHANGE_SUCCESSFUL) { MessageBox(NULL, "Display Mode Not Compatible", "Error", MB_OK); PostQuitMessage(0); } }

HWND CreateMyWindow(LPSTR strWindowName, int width, int height, DWORD dwStyle, bool bFullScreen, HINSTANCE hInstance) { HWND hWnd; WNDCLASS wndclass; memset(&wndclass, 0, sizeof(WNDCLASS)); // Init the size of the class wndclass.style = CS_HREDRAW | CS_VREDRAW; // Regular drawing capabilities wndclass.lpfnWndProc = WinProc; // Pass our function pointer as the window procedure wndclass.hInstance = hInstance; // Assign our hInstance wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // General icon wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); // An arrow for the cursor wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW+1); // A white window wndclass.lpszClassName = "GameTutorials"; // Assign the class name RegisterClass(&wndclass); // Register the class if(bFullScreen && !dwStyle) // Check if we wanted full screen mode { // Set the window properties for full screen mode dwStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; ChangeToFullScreen(); // Go to full screen ShowCursor(FALSE); // Hide the cursor } else if(!dwStyle) // Assign styles to the window depending on the choice dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; g_hInstance = hInstance; // Assign our global hInstance to the window's hInstance RECT rWindow; rWindow.left = 0; // Set Left Value To 0 rWindow.right = width; // Set Right Value To Requested Width rWindow.top = 0; // Set Top Value To 0 rWindow.bottom = height; // Set Bottom Value To Requested Height AdjustWindowRect( &rWindow, dwStyle, false); // Adjust Window To True Requested Size // Create the window hWnd = CreateWindow("GameTutorials", strWindowName, dwStyle, 0, 0, rWindow.right - rWindow.left, rWindow.bottom - rWindow.top, NULL, NULL, hInstance, NULL);

if(!hWnd) return NULL; // If we could get a handle, return NULL ShowWindow(hWnd, SW_SHOWNORMAL); // Show the window UpdateWindow(hWnd); // Draw the window SetFocus(hWnd); // Sets Keyboard Focus To The Window return hWnd; }

bool bSetupPixelFormat(HDC hdc) { PIXELFORMATDESCRIPTOR pfd; int pixelformat; pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); // Set the size of the structure pfd.nVersion = 1; // Always set this to 1 // Pass in the appropriate OpenGL flags pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.dwLayerMask = PFD_MAIN_PLANE; // We want the standard mask (this is ignored anyway) pfd.iPixelType = PFD_TYPE_RGBA; // We want RGB and Alpha pixel type pfd.cColorBits = SCREEN_DEPTH; // Here we use our #define for the color bits pfd.cDepthBits = SCREEN_DEPTH; // Depthbits is ignored for RGBA, but we do it anyway pfd.cAccumBits = 0; // No special bitplanes needed pfd.cStencilBits = 0; // We desire no stencil bits if ( (pixelformat = ChoosePixelFormat(hdc, &pfd)) == FALSE ) { MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK); return FALSE; } if (SetPixelFormat(hdc, pixelformat, &pfd) == FALSE) { MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK); return FALSE; } return TRUE; // Return a success! }

void SizeOpenGLScreen(int width, int height) // Initialize The GL Window { if (height==0) // Prevent A Divide By Zero error { height=1; // Make the Height Equal One }

glClearIndex( 0.0f ); glClearDepth( 1.0f ); glEnable( GL_DEPTH_TEST );

glViewport(0,0,width,height); // Make our viewport the whole window glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix gluPerspective(45.0f,(GLfloat)width/(GLfloat)height, 10.0f ,2000.0f);

glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix glLoadIdentity(); // Reset The Modelview Matrix glEnable( GL_LIGHTING ); glEnable( GL_LIGHT0 );

}

void InitializeOpenGL(int width, int height) { g_hDC = GetDC(g_hWnd); // This sets our global HDC // We don't free this hdc until the end of our program if (!bSetupPixelFormat(g_hDC)) // This sets our pixel format/information PostQuitMessage (0); // If there's an error, quit g_hRC = wglCreateContext(g_hDC); // This creates a rendering context from our hdc wglMakeCurrent(g_hDC, g_hRC); // This makes the rendering context we just created the one we want to use glEnable(GL_TEXTURE_2D); glCullFace( GL_FRONT ); glEnable( GL_CULL_FACE ); GLfloat Amb[] ={ 2,2,2,1 }; glLightModelfv( GL_LIGHT_MODEL_AMBIENT, Amb ); SizeOpenGLScreen(width, height); // Setup the screen translations and viewport }



void DeInit() { if (g_hRC) { wglMakeCurrent(NULL, NULL); // This frees our rendering memory and sets everything back to normal wglDeleteContext(g_hRC); // Delete our OpenGL Rendering Context } if (g_hDC) ReleaseDC(g_hWnd, g_hDC); // Release our HDC from memory if(g_bFullScreen) // If we were in full screen { ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop ShowCursor(TRUE); // Show Mouse Pointer }

UnregisterClass("GameTutorials", g_hInstance); // Free the window class PostQuitMessage (0); // Post a QUIT message to the window }



int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprev, PSTR cmdline, int ishow) { HWND hWnd;

hWnd = CreateMyWindow("Hotel", SCREEN_WIDTH, SCREEN_HEIGHT, 0, g_bFullScreen, hInstance);

// If we never got a valid window handle, quit the program if(hWnd == NULL) return TRUE;

// INIT OpenGL Init(hWnd);

// Run our message loop and after it's done, return the result return MainLoop(); }


Currently browsing [GL_Export1.zip] (104,965 bytes) - [BlankProject/3DMath.cpp] - (24,351 bytes)

//***********************************************************************//
//																		 //
//		- "Talk to me like I'm a 3 year old!" Programming Lessons -		 //
//                                                                       //
//		$Author:		DigiBen		digiben@gametutorials.com			 //
//																		 //
//		$Program:		CameraWorldCollision							 //
//																		 //
//		$Description:	Shows how to check if camera and world collide	 //
//																		 //
//		$Date:			1/23/02											 //
//																		 //
//***********************************************************************//

#include "main.h"
#include <math.h>	// We include math.h so we can use the sqrt() function
#include <float.h>	// This is so we can use _isnan() for acos()

/////////////////////////////////////// ABSOLUTE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
/////	This returns the absolute value of the number passed in
/////
/////////////////////////////////////// ABSOLUTE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

float Absolute(float num)
{
	// If num is less than zero, we want to return the absolute value of num.
	// This is simple, either we times num by -1 or subtract it from 0.
	if(num < 0)
		return (0 - num);

// Return the original number because it was already positive return num; }

/////////////////////////////////////// CROSS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns a perpendicular vector from 2 given vectors by taking the cross product. ///// /////////////////////////////////////// CROSS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* CVector3 Cross(CVector3 vVector1, CVector3 vVector2) { CVector3 vNormal; // The vector to hold the cross product // The X value for the vector is: (V1.y * V2.z) - (V1.z * V2.y) // Get the X value vNormal.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y)); // The Y value for the vector is: (V1.z * V2.x) - (V1.x * V2.z) vNormal.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z)); // The Z value for the vector is: (V1.x * V2.y) - (V1.y * V2.x) vNormal.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));

return vNormal; // Return the cross product (Direction the polygon is facing - Normal) }

/////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns the magnitude of a normal (or any other vector) ///// /////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* float Magnitude(CVector3 vNormal) { // This will give us the magnitude or "Norm" as some say, of our normal. // Here is the equation: magnitude = sqrt(V.x^2 + V.y^2 + V.z^2) Where V is the vector return (float)sqrt( (vNormal.x * vNormal.x) + (vNormal.y * vNormal.y) + (vNormal.z * vNormal.z) ); }

/////////////////////////////////////// NORMALIZE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns a normalize vector (A vector exactly of length 1) ///// /////////////////////////////////////// NORMALIZE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* CVector3 Normalize(CVector3 vNormal) { float magnitude = Magnitude(vNormal); // Get the magnitude of our normal // Now that we have the magnitude, we can divide our normal by that magnitude. // That will make our normal a total length of 1. This makes it easier to work with too. vNormal.x /= magnitude; // Divide the X value of our normal by it's magnitude vNormal.y /= magnitude; // Divide the Y value of our normal by it's magnitude vNormal.z /= magnitude; // Divide the Z value of our normal by it's magnitude // Finally, return our normalized normal. return vNormal; // Return the new normal of length 1. }

/////////////////////////////////////// NORMAL \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns the normal of a polygon (The direction the polygon is facing) ///// /////////////////////////////////////// NORMAL \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* CVector3 Normal(CVector3 vPolygon[]) { // Get 2 vectors from the polygon (2 sides), Remember the order! CVector3 vVector1 = vPolygon[2] - vPolygon[0]; CVector3 vVector2 = vPolygon[1] - vPolygon[0];

CVector3 vNormal = Cross(vVector1, vVector2); // Take the cross product of our 2 vectors to get a perpendicular vector // Now we have a normal, but it's at a strange length, so let's make it length 1. vNormal = Normalize(vNormal); // Use our function we created to normalize the normal (Makes it a length of one) return vNormal; // Return our normal at our desired length }

/////////////////////////////////// DISTANCE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns the distance between 2 3D points ///// /////////////////////////////////// DISTANCE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* float Distance(CVector3 vPoint1, CVector3 vPoint2) { // This is the classic formula used in beginning algebra to return the // distance between 2 points. Since it's 3D, we just add the z dimension: // // Distance = sqrt( (P2.x - P1.x)^2 + (P2.y - P1.y)^2 + (P2.z - P1.z)^2 ) // double distance = sqrt( (vPoint2.x - vPoint1.x) * (vPoint2.x - vPoint1.x) + (vPoint2.y - vPoint1.y) * (vPoint2.y - vPoint1.y) + (vPoint2.z - vPoint1.z) * (vPoint2.z - vPoint1.z) );

// Return the distance between the 2 points return (float)distance; }

////////////////////////////// CLOSEST POINT ON LINE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns the point on the line vA_vB that is closest to the point vPoint ///// ////////////////////////////// CLOSEST POINT ON LINE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* CVector3 ClosestPointOnLine(CVector3 vA, CVector3 vB, CVector3 vPoint) { // Create the vector from end point vA to our point vPoint. CVector3 vVector1 = vPoint - vA;

// Create a normalized direction vector from end point vA to end point vB CVector3 vVector2 = Normalize(vB - vA);

// Use the distance formula to find the distance of the line segment (or magnitude) float d = Distance(vA, vB);

// Using the dot product, we project the vVector1 onto the vector vVector2. // This essentially gives us the distance from our projected vector from vA. float t = Dot(vVector2, vVector1);

// If our projected distance from vA, "t", is less than or equal to 0, it must // be closest to the end point vA. We want to return this end point. if (t <= 0) return vA;

// If our projected distance from vA, "t", is greater than or equal to the magnitude // or distance of the line segment, it must be closest to the end point vB. So, return vB. if (t >= d) return vB; // Here we create a vector that is of length t and in the direction of vVector2 CVector3 vVector3 = vVector2 * t;

// To find the closest point on the line segment, we just add vVector3 to the original // end point vA. CVector3 vClosestPoint = vA + vVector3;

// Return the closest point on the line segment return vClosestPoint; }

/////////////////////////////////// PLANE DISTANCE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns the distance between a plane and the origin ///// /////////////////////////////////// PLANE DISTANCE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* float PlaneDistance(CVector3 Normal, CVector3 Point) { float distance = 0; // This variable holds the distance from the plane tot he origin // Use the plane equation to find the distance (Ax + By + Cz + D = 0) We want to find D. // So, we come up with D = -(Ax + By + Cz) // Basically, the negated dot product of the normal of the plane and the point. (More about the dot product in another tutorial) distance = - ((Normal.x * Point.x) + (Normal.y * Point.y) + (Normal.z * Point.z));

return distance; // Return the distance }

/////////////////////////////////// INTERSECTED PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This checks to see if a line intersects a plane ///// /////////////////////////////////// INTERSECTED PLANE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* bool IntersectedPlane(CVector3 vPoly[], CVector3 vLine[], CVector3 &vNormal, float &originDistance) { float distance1=0, distance2=0; // The distances from the 2 points of the line from the plane vNormal = Normal(vPoly); // We need to get the normal of our plane to go any further // Let's find the distance our plane is from the origin. We can find this value // from the normal to the plane (polygon) and any point that lies on that plane (Any vertex) originDistance = PlaneDistance(vNormal, vPoly[0]);

// Get the distance from point1 from the plane using: Ax + By + Cz + D = (The distance from the plane) distance1 = ((vNormal.x * vLine[0].x) + // Ax + (vNormal.y * vLine[0].y) + // Bx + (vNormal.z * vLine[0].z)) + originDistance; // Cz + D // Get the distance from point2 from the plane using Ax + By + Cz + D = (The distance from the plane) distance2 = ((vNormal.x * vLine[1].x) + // Ax + (vNormal.y * vLine[1].y) + // Bx + (vNormal.z * vLine[1].z)) + originDistance; // Cz + D // Now that we have 2 distances from the plane, if we times them together we either // get a positive or negative number. If it's a negative number, that means we collided! // This is because the 2 points must be on either side of the plane (IE. -1 * 1 = -1). if(distance1 * distance2 >= 0) // Check to see if both point's distances are both negative or both positive return false; // Return false if each point has the same sign. -1 and 1 would mean each point is on either side of the plane. -1 -2 or 3 4 wouldn't... return true; // The line intersected the plane, Return TRUE }

/////////////////////////////////// DOT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This computers the dot product of 2 vectors ///// /////////////////////////////////// DOT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* float Dot(CVector3 vVector1, CVector3 vVector2) { // The dot product is this equation: V1.V2 = (V1.x * V2.x + V1.y * V2.y + V1.z * V2.z) // In math terms, it looks like this: V1.V2 = ||V1|| ||V2|| cos(theta) // (V1.x * V2.x + V1.y * V2.y + V1.z * V2.z) return ( (vVector1.x * vVector2.x) + (vVector1.y * vVector2.y) + (vVector1.z * vVector2.z) ); }

/////////////////////////////////// ANGLE BETWEEN VECTORS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This checks to see if a point is inside the ranges of a polygon ///// /////////////////////////////////// ANGLE BETWEEN VECTORS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* double AngleBetweenVectors(CVector3 Vector1, CVector3 Vector2) { // Get the dot product of the vectors float dotProduct = Dot(Vector1, Vector2);

// Get the product of both of the vectors magnitudes float vectorsMagnitude = Magnitude(Vector1) * Magnitude(Vector2) ;

// Get the angle in radians between the 2 vectors double angle = acos( dotProduct / vectorsMagnitude );

// Here we make sure that the angle is not a -1.#IND0000000 number, which means indefinate if(_isnan(angle)) return 0; // Return the angle in radians return( angle ); }

/////////////////////////////////// INTERSECTION POINT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns the intersection point of the line that intersects the plane ///// /////////////////////////////////// INTERSECTION POINT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* CVector3 IntersectionPoint(CVector3 vNormal, CVector3 vLine[], double distance) { CVector3 vPoint, vLineDir; // Variables to hold the point and the line's direction double Numerator = 0.0, Denominator = 0.0, dist = 0.0;

// 1) First we need to get the vector of our line, Then normalize it so it's a length of 1 vLineDir = vLine[1] - vLine[0]; // Get the Vector of the line vLineDir = Normalize(vLineDir); // Normalize the lines vector

// 2) Use the plane equation (distance = Ax + By + Cz + D) to find the // distance from one of our points to the plane. Numerator = - (vNormal.x * vLine[0].x + // Use the plane equation with the normal and the line vNormal.y * vLine[0].y + vNormal.z * vLine[0].z + distance);

// 3) If we take the dot product between our line vector and the normal of the polygon, Denominator = Dot(vNormal, vLineDir); // Get the dot product of the line's vector and the normal of the plane // Since we are using division, we need to make sure we don't get a divide by zero error // If we do get a 0, that means that there are INFINATE points because the the line is // on the plane (the normal is perpendicular to the line - (Normal.Vector = 0)). // In this case, we should just return any point on the line. if( Denominator == 0.0) // Check so we don't divide by zero return vLine[0]; // Return an arbitrary point on the line dist = Numerator / Denominator; // Divide to get the multiplying (percentage) factor // Now, like we said above, we times the dist by the vector, then add our arbitrary point. vPoint.x = (float)(vLine[0].x + (vLineDir.x * dist)); vPoint.y = (float)(vLine[0].y + (vLineDir.y * dist)); vPoint.z = (float)(vLine[0].z + (vLineDir.z * dist));

return vPoint; // Return the intersection point }

/////////////////////////////////// INSIDE POLYGON \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This checks to see if a point is inside the ranges of a polygon ///// /////////////////////////////////// INSIDE POLYGON \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* bool InsidePolygon(CVector3 vIntersection, CVector3 Poly[], long verticeCount) { const double MATCH_FACTOR = 0.99; // Used to cover up the error in floating point double Angle = 0.0; // Initialize the angle CVector3 vA, vB; // Create temp vectors for (int i = 0; i < verticeCount; i++) // Go in a circle to each vertex and get the angle between { vA = Poly[i] - vIntersection; // Subtract the intersection point from the current vertex // Subtract the point from the next vertex vB = Poly[(i + 1) % verticeCount] - vIntersection; Angle += AngleBetweenVectors(vA, vB); // Find the angle between the 2 vectors and add them all up as we go along } if(Angle >= (MATCH_FACTOR * (2.0 * PI)) ) // If the angle is greater than 2 PI, (360 degrees) return true; // The point is inside of the polygon return false; // If you get here, it obviously wasn't inside the polygon, so Return FALSE }

/////////////////////////////////// INTERSECTED POLYGON \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This checks if a line is intersecting a polygon ///// /////////////////////////////////// INTERSECTED POLYGON \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* bool IntersectedPolygon(CVector3 vPoly[], CVector3 vLine[], int verticeCount) { CVector3 vNormal; float originDistance = 0;

// First, make sure our line intersects the plane // Reference // Reference if(!IntersectedPlane(vPoly, vLine, vNormal, originDistance)) return false;

// Now that we have our normal and distance passed back from IntersectedPlane(), // we can use it to calculate the intersection point. CVector3 vIntersection = IntersectionPoint(vNormal, vLine, originDistance);

// Now that we have the intersection point, we need to test if it's inside the polygon. if(InsidePolygon(vIntersection, vPoly, verticeCount)) return true; // We collided! Return success return false; // There was no collision, so return false }

///////////////////////////////// CLASSIFY SPHERE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This tells if a sphere is BEHIND, in FRONT, or INTERSECTS a plane, also it's distance ///// ///////////////////////////////// CLASSIFY SPHERE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* int ClassifySphere(CVector3 &vCenter, CVector3 &vNormal, CVector3 &vPoint, float radius, float &distance) { // First we need to find the distance our polygon plane is from the origin. float d = (float)PlaneDistance(vNormal, vPoint);

// Here we use the famous distance formula to find the distance the center point // of the sphere is from the polygon's plane. distance = (vNormal.x * vCenter.x + vNormal.y * vCenter.y + vNormal.z * vCenter.z + d);

// If the absolute value of the distance we just found is less than the radius, // the sphere intersected the plane. if(Absolute(distance) < radius) return INTERSECTS; // Else, if the distance is greater than or equal to the radius, the sphere is // completely in FRONT of the plane. else if(distance >= radius) return FRONT; // If the sphere isn't intersecting or in FRONT of the plane, it must be BEHIND return BEHIND; }

///////////////////////////////// EDGE SPHERE COLLSIION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns true if the sphere is intersecting any of the edges of the polygon ///// ///////////////////////////////// EDGE SPHERE COLLSIION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* bool EdgeSphereCollision(CVector3 &vCenter, CVector3 vPolygon[], int vertexCount, float radius) { CVector3 vPoint;

// This function takes in the sphere's center, the polygon's vertices, the vertex count // and the radius of the sphere. We will return true from this function if the sphere // is intersecting any of the edges of the polygon. // Go through all of the vertices in the polygon for(int i = 0; i < vertexCount; i++) { // This returns the closest point on the current edge to the center of the sphere. vPoint = ClosestPointOnLine(vPolygon[i], vPolygon[(i + 1) % vertexCount], vCenter); // Now, we want to calculate the distance between the closest point and the center float distance = Distance(vPoint, vCenter);

// If the distance is less than the radius, there must be a collision so return true if(distance < radius) return true; }

// The was no intersection of the sphere and the edges of the polygon return false; }

////////////////////////////// SPHERE POLYGON COLLISION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns true if our sphere collides with the polygon passed in ///// ////////////////////////////// SPHERE POLYGON COLLISION \\\\\\\\\\\\\\\\\\\\\\\\\\\\\* bool SpherePolygonCollision(CVector3 vPolygon[], CVector3 &vCenter, int vertexCount, float radius) { // 1) STEP ONE - Finding the sphere's classification // Let's use our Normal() function to return us the normal to this polygon CVector3 vNormal = Normal(vPolygon);

// This will store the distance our sphere is from the plane float distance = 0.0f;

// This is where we determine if the sphere is in FRONT, BEHIND, or INTERSECTS the plane int classification = ClassifySphere(vCenter, vNormal, vPolygon[0], radius, distance);

// If the sphere intersects the polygon's plane, then we need to check further if(classification == INTERSECTS) { // 2) STEP TWO - Finding the psuedo intersection point on the plane // Now we want to project the sphere's center onto the polygon's plane CVector3 vOffset = vNormal * distance;

// Once we have the offset to the plane, we just subtract it from the center // of the sphere. "vPosition" now a point that lies on the plane of the polygon. CVector3 vPosition = vCenter - vOffset;

// 3) STEP THREE - Check if the intersection point is inside the polygons perimeter // If the intersection point is inside the perimeter of the polygon, it returns true. // We pass in the intersection point, the list of vertices and vertex count of the poly. if(InsidePolygon(vPosition, vPolygon, 3)) return true; // We collided! else { // 4) STEP FOUR - Check the sphere intersects any of the polygon's edges // If we get here, we didn't find an intersection point in the perimeter. // We now need to check collision against the edges of the polygon. if(EdgeSphereCollision(vCenter, vPolygon, vertexCount, radius)) { return true; // We collided! } } }

// If we get here, there is obviously no collision return false; }

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * ///////////////////////////////// GET COLLISION OFFSET \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* ///// ///// This returns the offset to move the center of the sphere off the collided polygon ///// ///////////////////////////////// GET COLLISION OFFSET \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\* CVector3 GetCollisionOffset(CVector3 &vNormal, float radius, float distance) { CVector3 vOffset = CVector3(0, 0, 0);

// Once we find if a collision has taken place, we need make sure the sphere // doesn't move into the wall. In our app, the position will actually move into // the wall, but we check our collision detection before we render the scene, which // eliminates the bounce back effect it would cause. The question is, how do we // know which direction to move the sphere back? In our collision detection, we // account for collisions on both sides of the polygon. Usually, you just need // to worry about the side with the normal vector and positive distance. If // you don't want to back face cull and have 2 sided planes, I check for both sides. // // Let me explain the math that is going on here. First, we have the normal to // the plane, the radius of the sphere, as well as the distance the center of the // sphere is from the plane. In the case of the sphere colliding in the front of // the polygon, we can just subtract the distance from the radius, then multiply // that new distance by the normal of the plane. This projects that leftover // distance along the normal vector. For instance, say we have these values: // // vNormal = (1, 0, 0) radius = 5 distance = 3 // // If we subtract the distance from the radius we get: (5 - 3 = 2) // The number 2 tells us that our sphere is over the plane by a distance of 2. // So basically, we need to move the sphere back 2 units. How do we know which // direction though? This part is easy, we have a normal vector that tells us the // direction of the plane. // If we multiply the normal by the left over distance we get: (2, 0, 0) // This new offset vectors tells us which direction and how much to move back. // We then subtract this offset from the sphere's position, giving is the new // position that is lying right on top of the plane. Ba da bing! // If we are colliding from behind the polygon (not usual), we do the opposite // signs as seen below: // If our distance is greater than zero, we are in front of the polygon if(distance > 0) { // Find the distance that our sphere is overlapping the plane, then // find the direction vector to move our sphere. float distanceOver = radius - distance; vOffset = vNormal * distanceOver; } else // Else colliding from behind the polygon { // Find the distance that our sphere is overlapping the plane, then // find the direction vector to move our sphere. float distanceOver = radius + distance; vOffset = vNormal * -distanceOver; }

// There is one problem with check for collisions behind the polygon, and that // is if you are moving really fast and your center goes past the front of the // polygon, it will then assume you were colliding from behind and not let // you back in. Most likely you will take out the if / else check, but I // figured I would show both ways in case someone didn't want to back face cull. // Return the offset we need to move back to not be intersecting the polygon. return vOffset; }

Currently browsing [GL_Export1.zip] (104,965 bytes) - [BlankProject/MAIN.H] - (3,151 bytes)

#ifndef _MAIN_H
#define _MAIN_H

#include <windows.h> #include <stdio.h> #include <stdlib.h> #include <gl\gl.h> // Header File For The OpenGL32 Library #include <gl\glu.h> // Header File For The GLu32 Library #include <gl\glaux.h>

#include <float.h> #include <math.h> #include "3DMath.h" #include "Camera.h"



#define SCREEN_WIDTH 640 // We want our screen width 800 pixels #define SCREEN_HEIGHT 480 // We want our screen height 600 pixels #define SCREEN_DEPTH 8 // We want 16 bits per pixel /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * #define MAX_TEXTURES 1 // This says how many texture we will be using /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * extern bool g_bFullScreen; // Set full screen as default extern HWND g_hWnd; // This is the handle for the window extern RECT g_rRect; // This holds the window dimensions extern HDC g_hDC; // General HDC - (handle to device context) extern HGLRC g_hRC; // General OpenGL_DC - Our Rendering Context for OpenGL extern HINSTANCE g_hInstance;

struct Point3 { float x; float y; float z; };

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * extern UINT g_Texture[MAX_TEXTURES]; // This is our texture data array /////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// * // This is our MAIN() for windows int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprev, PSTR cmdline, int ishow);

// The window proc which handles all of window's messages. LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

// This controls our main program loop WPARAM MainLoop();

// This loads a texture into openGL from a file (IE, "bitmap.bmp") void CreateTexture(UINT textureArray[], LPSTR strFileName, int textureID);

// This changes the screen to full screen mode void ChangeToFullScreen();

// This is our own function that makes creating a window modular and easy HWND CreateMyWindow(LPSTR strWindowName, int width, int height, DWORD dwStyle, bool bFullScreen, HINSTANCE hInstance);

// This allows us to configure our window for OpenGL and backbuffered bool bSetupPixelFormat(HDC hdc);

// This inits our screen translations and projections void SizeOpenGLScreen(int width, int height);

// This sets up OpenGL void InitializeOpenGL(int width, int height);

// This initializes the whole program void Init(HWND hWnd);

// This draws everything to the screen void RenderScene();

// This frees all our memory in our program void DeInit();

#endif

///////////////////////////////////////////////////////////////////////////////// // // * QUICK NOTES * // // We added MAX_TEXTURES to this header file. This define is the size of the g_Texture[] // array, which we also extern here so init.cpp can free it's data. // // // Ben Humphrey (DigiBen) // Game Programmer // DigiBen@GameTutorials.com // Co-Web Host of www.GameTutorials.com // //

Currently browsing [GL_Export1.zip] (104,965 bytes) - [BlankProject/resource.h] - (456 bytes)

//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Script1.rc
//
#define IDB_BITMAP1                     101

// Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

 

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.