Collision coordinate junk!?!? (full main source code)

Started by
10 comments, last by theo2005 11 years, 8 months ago
I've been fighting with this for a few months now and nothing worked...

Please help me out. I do not know what is causing this, but my hunch is that it has something to do with world transforms and vector coordinate transforms. I really am on the verge of giving up on 3D programming because of this..

Don't mind the collision checks.
The problem basically is that what I'm getting for my bounding box coordinates is junk.
Junk like...

Object 0: 8.83098e-042 0 0
Object 3: 5 14.3369 1.17549e-038


#include <windows.h>
#include <windowsx.h> //has something to do with the window class << EX >> (newer window class)
#include <d3d9.h>
#include <d3dx9.h> //matrix stuff
#include <dinput.h> //directInput
#include <sstream>
#include <iostream>
#include <fstream>
#include "XAnimator_lib.h"
// include the Direct3D Library files
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
//directInput stuff
#pragma comment (lib, "dinput8.lib") //why 8? Because 9 had no significant changes
#pragma comment (lib, "dxguid.lib")
// define the screen resolution
#define SCREEN_WIDTH 800 // in CCamera as well
#define SCREEN_HEIGHT 600
#define WALL 2
#define FLOOR 1
#define SKELE 0
// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL; // the pointer to the vertex buffer
LPDIRECT3DINDEXBUFFER9 i_buffer; //create the index buffer
//directInput stuff
LPDIRECTINPUT8 din; // the pointer to our DirectInput interface
LPDIRECTINPUTDEVICE8 dinkeyboard; // the pointer to the keyboard device
LPDIRECTINPUTDEVICE8 dinmouse; // the pointer to the mouse device
BYTE keystate[256]; // the storage for the key-information
DIMOUSESTATE mousestate; // the storage for the mouse-information
void cleanD3D()
{
v_buffer->Release(); // close and release the vertex buffer
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
}
// this is the function that closes DirectInput
void cleanDInput()
{
dinkeyboard->Unacquire(); // make sure the keyboard is unacquired
dinmouse->Unacquire(); // make sure the mouse in unacquired
din->Release(); // close DirectInput before exiting
}

//function prototypes
void FileWrite (float PosX, float PosY, float PosZ, float LookX, float LookY, float LookZ);
void CleanDynamicVariables ();
void render_frame(); // renders a single frame
void init_graphics(); // 3D declarations
void init_light ();
//directinput stuff
void initDInput(HINSTANCE hInstance, HWND hWnd); // sets up and initializes DirectInput
void detect_input(); // gets the current input state
bool LoadModel(const std::string &filename);
void ProcessInput( long xDelta, long yDelta, long zDelta, float elapsedTime );
inline void SetObjectCoords ();
void RenderOOBB(D3DXVECTOR3 *corners, int ObjNum);
void RenderBoundingBoxes(int ObjNum);

//checks n' bools
bool IsFullscreen = FALSE; //fullscreen, here we come!
bool FirstTime = TRUE;
bool Movement = TRUE;
IXAnimator * XAnimator=0;
VOID* pVoid; // a void pointer
int ObjectQuantity = 0; //we find out later
static int countZ = 0;
int * ModelID = new int [ObjectQuantity];
int * NumAnimationSets= new int[ObjectQuantity];
int * CurrentAnimationSet = new int[ObjectQuantity];
DWORD * lastTimeAnimationChanged = new DWORD [ObjectQuantity];
DWORD * lastUpdateTime = new DWORD [ObjectQuantity];
DWORD * timeElapsedSinceAnimationChange = new DWORD[ObjectQuantity];
DWORD * timeElapsedSinceLastUpdate = new DWORD[ObjectQuantity];
// Transition time between animation sets in ms
float TransitionTime=2500;
// Time before we switch to the next animation in ms
DWORD TimeBeforeNextAnimation=4000;
float * TranslateX = new float[ObjectQuantity];
float * TranslateY = new float[ObjectQuantity];
float * TranslateZ = new float[ObjectQuantity];
D3DXMATRIX IdentityMatrix;

//headerfiles (mostly functions) --....
#include "CenterScreen.h"
#include "InitD3D.h"
#include "CCamera.h"
#include "CTimer.h"
void Pause( BOOL rendering, BOOL timer ); //needs to be h ere because of CTimer.h
struct CUSTOMVERTEX {FLOAT X, Y, Z; DWORD COLOR;}; //D3DVECTOR NORMAL DWORD COLOR
//#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL)
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)

LRESULT CALLBACK WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);

CCamera Camera;
CTimer Timer;
//CMovement Movement;
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//------------------------------------------------------------ WINDOW STUFF ------------------------------------------------------//
HWND hWnd;
WNDCLASSEX wc;
// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW; //redraw the window when moved
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
//wc.hbrBackground = (HBRUSH)COLOR_WINDOW; //(important to comment out to make the game look professinal in full screen)
wc.lpszClassName = L"WindowClass1";
// register the window class
RegisterClassEx(&wc);
// create the window and use the result as the handle
DWORD style;
if (IsFullscreen == TRUE)
{
style = WS_EX_TOPMOST | WS_POPUP;
}
else
{
style = WS_OVERLAPPEDWINDOW;
}
hWnd = CreateWindowEx(NULL,
L"WindowClass1", // name of the window class
L"My first 3D program", // title of the window
style, // window style (buttons)
0, // x-position of the window LEFT RIGHT currently FC value
0, // y-position of the window UP DOWN currently FC value
SCREEN_WIDTH, // width of the window
SCREEN_HEIGHT, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
if (IsFullscreen == FALSE)
{
HWND TempWnd = NULL;
TempWnd = GetDesktopWindow ();
CenterWindow(hWnd, TempWnd); //center window relative to desktop
}
// display the window on the screen
nCmdShow = SW_SHOWNORMAL; //just in case..
ShowWindow(hWnd, nCmdShow);
//-------------------------------------------------------- WINDOW STUFF ----------------------------------------------------------------------//
initD3D(hWnd);
initDInput(hInstance, hWnd); // initialize DirectInput
Pause( FALSE, FALSE ); //Timer start
XAnimator=CreateXAnimator(d3ddev);
if (!XAnimator)
{
return 0;
}
if (!LoadModel ("Data\\bones_all.x"))
{
return 0;
}
if (!LoadModel("Data\\floor.x"))
{
return 0;
}
if (!LoadModel("Data\\wall.x"))
{
return 0;
}
if (!LoadModel("Data\\BOX.x"))
{
return 0;
}
// this struct holds Windows event messages
MSG msg;
// Enter the infinite message loop
while(TRUE)
{
// Check to see if any messages are waiting in the queue
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) //PM_REMOVE removes messages after processing
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
}

if(msg.message == WM_QUIT) // exits the while loop
{
break;
}
detect_input(); // update the input data before rendering
//if the while loop still goes on, then draw the frame (see the function below)
render_frame();
if(keystate[DIK_ESCAPE] & 0x80) //0x80 is for the last bit of information about the keystroke that we need
{
PostMessage(hWnd, WM_DESTROY, 0, 0);
}
}
cleanD3D(); //cleans up DirectX and COM
cleanDInput(); // release DirectInput
//CleanDynamicVariables ();
return msg.wParam; // return this part of the WM_QUIT message to Windows
}

// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) //as much as I understand, windows can CALLBACK this func. when it needs to anytime
{
// sort through and find what code to run for the message given
switch(message)
{

case WM_DESTROY: //if the user closed the window
{
PostQuitMessage(0); //send the WM_QUIT message which will trigger the if statement which break;'s the while loop
return 0; //important to return 0 so that DefwindowProc knows that this case was handled
}
break;
}
// Handle any messages the switch statement didn't
return DefWindowProc (hWnd, message, wParam, lParam);
}

// this is the function used to render a single frame
void render_frame()
{
// clear the window to a deep blue
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); //clear the z-buffer to black
d3ddev->BeginScene(); // begins the 3D scene
//---------------------------------------------------------- SET UP THE PIPELINE <start> ---------------------------------------------------------------------//

static D3DXMATRIX * matTranslate = new D3DXMATRIX[ObjectQuantity];
static D3DXMATRIX * matRotateX = new D3DXMATRIX[ObjectQuantity];
static D3DXMATRIX * matRotateY = new D3DXMATRIX[ObjectQuantity];
static float Index = 0.0f;
if (FirstTime == TRUE)
{
for (int TimeCount = 0; TimeCount < ObjectQuantity; ++ TimeCount)
{
lastTimeAnimationChanged[TimeCount]=timeGetTime();
lastUpdateTime[TimeCount]=timeGetTime();
D3DXMatrixIdentity(&matRotateY[TimeCount]);
D3DXMatrixIdentity(&matRotateX[TimeCount]);
D3DXMatrixIdentity(&matTranslate[TimeCount]);

}
D3DXMatrixIdentity(&IdentityMatrix);
SetObjectCoords ();
FirstTime = FALSE;
}
Timer.Update();
float elapsedTime = Timer.GetElapsedTime ();
float MovementSpeed = 4.0f;
if (Movement == TRUE)
{
if(keystate[DIK_UP] & 0x80)
{

TranslateZ[SKELE] -= (cos(Index) * MovementSpeed * elapsedTime );
//Camera.MoveForward(-cos(Index) * MovementSpeed * elapsedTime );
TranslateX[SKELE] -= (sin(Index) * MovementSpeed * elapsedTime );
//Camera.Strafe(-sin(Index) * MovementSpeed * elapsedTime );
if (timeElapsedSinceAnimationChange[SKELE] > TimeBeforeNextAnimation)
{
XAnimator->ChangeAnimationSet(ModelID[SKELE],1 ,200); //TransitionTime = 200
lastTimeAnimationChanged[SKELE] = timeGetTime();
} //animationsets not in the right order? 0 seems to be running
}
if(keystate[DIK_LEFT] & 0x80)
{
Index -= 3.0f * elapsedTime;
D3DXMatrixRotationY(&matRotateY[SKELE], Index);
//Camera.Yaw(D3DXToRadian(-Index));
}
if(keystate[DIK_DOWN] & 0x80)
{
//TranslateZ[SKELE] += ( -MovementSpeed * elapsedTime );
TranslateZ[SKELE] += (cos(Index) * MovementSpeed * elapsedTime );
TranslateX[SKELE] += (sin(Index) * MovementSpeed * elapsedTime );
//Camera.MoveForward(cos(Index) * MovementSpeed * elapsedTime );
//Camera.Strafe(sin(Index) * MovementSpeed * elapsedTime );
}
if(keystate[DIK_RIGHT] & 0x80)
{
Index +=3.0f * elapsedTime;
D3DXMatrixRotationY(&matRotateY[SKELE], Index);
//Camera.Yaw(D3DXToRadian(-Index));
}
}


for (int CountTime = 0;CountTime < ObjectQuantity; ++CountTime) //do time calculations for all objects
{
timeElapsedSinceAnimationChange[CountTime] = timeGetTime()-lastTimeAnimationChanged[CountTime];
// Periodically advance to the next animation set
if (timeElapsedSinceAnimationChange[CountTime] > TimeBeforeNextAnimation) //TimeBefireNextAnimation = 4000ms
{
if(!(keystate[DIK_UP] & 0x80))
{
CurrentAnimationSet[CountTime]+=1;
if (CurrentAnimationSet[CountTime] >= NumAnimationSets[CountTime]) //currentanimationset must not be bigger than total animationsets
{
CurrentAnimationSet[CountTime]=0; //reset back to start
}
XAnimator->ChangeAnimationSet(ModelID[CountTime],CurrentAnimationSet[CountTime],TransitionTime); //change the animation set
}
lastTimeAnimationChanged[CountTime] = timeGetTime();
}


timeElapsedSinceLastUpdate[CountTime] = timeGetTime() - lastUpdateTime[CountTime];
}


for (int CountRender = 0;CountRender < ObjectQuantity; ++ CountRender) //draw all the objects despite of which object time calculation is executing
{

D3DXMatrixTranslation(&matTranslate[CountRender], TranslateX[CountRender], TranslateY[CountRender], TranslateZ[CountRender]);
XAnimator->Render(ModelID[CountRender], matRotateY[CountRender] * matTranslate[CountRender] ,(float)timeElapsedSinceLastUpdate[CountRender]);
}
for (int CountTime = 0; CountTime < ObjectQuantity; ++ CountTime)
{
lastUpdateTime[CountTime]=timeGetTime();
}
//---------------------------------------------------------- CAMERA SETUP <start> ----------------------------------------------------------------------------//
//float elapsedTime = Timer.GetElapsedTime();
long xDelta; xDelta = mousestate.lX;
long yDelta; yDelta = mousestate.lY;
long zDelta; zDelta = mousestate.lZ;
//Timer.Update();
//FileWrite(xDelta);
static D3DXVECTOR3 * cameraPosition;
static D3DXVECTOR3 cameraTarget( 0.0f, 1.0f, 0.0f );
static D3DXVECTOR3 cameraUp( 0.0f, 1.0f, 0.0f );
ProcessInput( xDelta, yDelta, zDelta, Timer.GetElapsedTime() );
Camera.Update ();
d3ddev->SetTransform( D3DTS_VIEW, Camera.GetViewMatrix () );
D3DXVECTOR3 * Position = Camera.GetPosition ();
D3DXVECTOR3 * LookAt = Camera.GetLookAt ();
float PosX = Position -> x;
float PosY = Position -> y;
float PosZ = Position -> z;
float LookX = LookAt -> x;
float LookY = LookAt -> y;
float LookZ = LookAt -> z;


// Set the projection matrix
D3DXMATRIX projection;
float aspect = (float)SCREEN_WIDTH / (float)SCREEN_HEIGHT;
D3DXMatrixPerspectiveFovLH( &projection, D3DXToRadian (45), aspect, 0.1f, 1000.0f );
d3ddev->SetTransform( D3DTS_PROJECTION, &projection );
// select which vertex format we are using. Global variable: #define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)
d3ddev->SetFVF(CUSTOMFVF);
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
d3ddev->SetIndices(i_buffer);
//render the object collision boxes for every object
for (int count = 0; count < ObjectQuantity; ++count)
{
D3DXMatrixMultiply(&IdentityMatrix, &matRotateY[count], &matTranslate[count]);
// d3ddev->SetTransform(D3DTS_WORLD, &IdentityMatrix); // set the world transform
D3DXVECTOR3 minBoundsModelSpace,maxBoundsModelSpace; // Model min max values in object space
D3DXVECTOR3 sphereCentreModelSpace; // Sphere centre in model space
float sphereRadius; // Sphere radius in model space
int numMesh; // Number of individual mesh bounds returned by the function
TMeshBounds *indMeshBoundsModelSpace=XAnimator->GetBoundingShapes(ModelID[count],&minBoundsModelSpace,&maxBoundsModelSpace,&sphereCentreModelSpace,&sphereRadius,&numMesh);
// We have min and max values, use these to get the 8 corners of the boundingbox
D3DXVECTOR3 cornersInModelSpace[8];
//float * TranslateZ = new float[ObjectQuantity];
cornersInModelSpace[0] = D3DXVECTOR3( minBoundsModelSpace.x, minBoundsModelSpace.y, minBoundsModelSpace.z ); // xyz
cornersInModelSpace[1] = D3DXVECTOR3( maxBoundsModelSpace.x, minBoundsModelSpace.y, minBoundsModelSpace.z ); // Xyz
cornersInModelSpace[2] = D3DXVECTOR3( minBoundsModelSpace.x, maxBoundsModelSpace.y, minBoundsModelSpace.z ); // xYz
cornersInModelSpace[3] = D3DXVECTOR3( maxBoundsModelSpace.x, maxBoundsModelSpace.y, minBoundsModelSpace.z ); // XYz
cornersInModelSpace[4] = D3DXVECTOR3( minBoundsModelSpace.x, minBoundsModelSpace.y, maxBoundsModelSpace.z ); // xyZ
cornersInModelSpace[5] = D3DXVECTOR3( maxBoundsModelSpace.x, minBoundsModelSpace.y, maxBoundsModelSpace.z ); // XyZ
cornersInModelSpace[6] = D3DXVECTOR3( minBoundsModelSpace.x, maxBoundsModelSpace.y, maxBoundsModelSpace.z ); // xYZ
cornersInModelSpace[7] = D3DXVECTOR3( maxBoundsModelSpace.x, maxBoundsModelSpace.y, maxBoundsModelSpace.z ); // XYZ
// Now we transform each corner by the world matrix
static bool DoOnce = true;
static D3DXVECTOR3 ** cornersInWorldSpace = 0;
if (DoOnce == true)
{
cornersInWorldSpace = new D3DXVECTOR3 *[8];
for( int i = 0 ; i < 8 ; i++ )
cornersInWorldSpace = new D3DXVECTOR3[ObjectQuantity];
DoOnce = false;
}
for( int i = 0; i < 8; i++ )
{
D3DXVec3TransformCoord( &cornersInWorldSpace[count], &cornersInModelSpace, &IdentityMatrix);
}
D3DXVECTOR3 * minBoundsWorldSpace = new D3DXVECTOR3[ObjectQuantity];
minBoundsWorldSpace[count] = cornersInWorldSpace[0][count];
D3DXVECTOR3 * maxBoundsWorldSpace = new D3DXVECTOR3[ObjectQuantity];
maxBoundsWorldSpace[count] = cornersInWorldSpace[0][count];
for (int i=1;i<8;i++)
{
minBoundsWorldSpace[count].x= min(minBoundsWorldSpace[count].x,cornersInWorldSpace[count].x);
minBoundsWorldSpace[count].y= min(minBoundsWorldSpace[count].y,cornersInWorldSpace[count].y);
minBoundsWorldSpace[count].z= min(minBoundsWorldSpace[count].z,cornersInWorldSpace[count].z);
maxBoundsWorldSpace[count].x= max(maxBoundsWorldSpace[count].x,cornersInWorldSpace[count].x);
maxBoundsWorldSpace[count].y= max(maxBoundsWorldSpace[count].y,cornersInWorldSpace[count].y);
maxBoundsWorldSpace[count].z= max(maxBoundsWorldSpace[count].z,cornersInWorldSpace[count].z);
}
if (count == 3) //array starts from 0 not 1, that's why -1 ;; that was wrong..
{
if (maxBoundsWorldSpace[0].x > minBoundsWorldSpace[3].x)
{
Movement = FALSE;
}
/*for (int count = 1; count < ObjectQuantity; ++ count) //count 1+ because 0 is skeleton, other objects wont collide
{
for (int CountCorner = 0; CountCorner < 4; ++ CountCorner)
{
if (FrontX[SKELE][0] / BackX[3][0] > 0.98 && FrontX[SKELE][0] / BackX[3][0] < 1)
{
Movement = FALSE;
}
/* else
{
Movement = TRUE;
}*/
//}
//}
FileWrite(maxBoundsWorldSpace[0].x, maxBoundsWorldSpace[0].y, maxBoundsWorldSpace[0].z,maxBoundsWorldSpace[3].x, maxBoundsWorldSpace[3].y, maxBoundsWorldSpace[3].z);
}
}


// ----------------------------------------------------------- CAMERA SETUP <END> --------------------------------------------------------------------------//
//---------------------------------------------------------- SET UP THE PIPELINE <END> ---------------------------------------------------------------------//
d3ddev->EndScene(); // ends the 3D scene
d3ddev->Present(NULL, NULL, NULL, NULL); // displays the created frame on the screen
}
// this is the function that puts the 3D models into video RAM
void init_graphics()
{
// create the vertices using the CUSTOMVERTEX struct
// create a vertex buffer interface called v_buffer
d3ddev->CreateVertexBuffer(8*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);
// create the indices using an int array
short indices[] =
{
0, 1, 2, // side 1
2, 1, 3,
4, 0, 6, // side 2
6, 0, 2,
7, 5, 6, // side 3
6, 5, 4,
3, 1, 7, // side 4
7, 1, 5,
4, 5, 0, // side 5
0, 5, 1,
3, 7, 2, // side 6
2, 7, 6,
};
// create an index buffer interface called i_buffer
d3ddev->CreateIndexBuffer(36*sizeof(short),
0,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&i_buffer,
NULL);
// lock i_buffer and load the indices into it
i_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, indices, sizeof(indices));
i_buffer->Unlock();
}
// this is the function that initializes DirectInput
void initDInput(HINSTANCE hInstance, HWND hWnd)
{
// create the DirectInput interface
DirectInput8Create(hInstance, // the handle to the application
DIRECTINPUT_VERSION, // the compatible version
IID_IDirectInput8, // the DirectInput interface version
(void**)&din, // the pointer to the interface
NULL); // COM stuff, so we'll set it to NULL
// create the keyboard device
din->CreateDevice(GUID_SysKeyboard, // the default keyboard ID being used
&dinkeyboard, // the pointer to the device interface
NULL); // COM stuff, so we'll set it to NULL
din->CreateDevice(GUID_SysMouse,
&dinmouse,
NULL);
// set the data format to keyboard format (or mouse format below)
dinkeyboard->SetDataFormat(&c_dfDIKeyboard);
dinmouse->SetDataFormat(&c_dfDIMouse);
// set the control you will have over the keyboard (or mouse below)
dinkeyboard->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
dinmouse->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND); //exclusive to ditch windows with it's mouse pointer
}
// this is the function that gets the latest input data
void detect_input()
{
// get access if we don't have it already
dinkeyboard->Acquire();
dinmouse->Acquire();
// get the input data
dinkeyboard->GetDeviceState(256, (LPVOID)keystate);
dinmouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mousestate); //mousestate is a DIMOUSESTATE struct type
}
void init_light(void)
{
D3DLIGHT9 light; // create the light struct
D3DMATERIAL9 material; // create the material struct
ZeroMemory(&light, sizeof(light)); // clear out the light struct for use
light.Type = D3DLIGHT_DIRECTIONAL; // make the light type 'directional light'
light.Diffuse = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f); // set the light's color
light.Direction = D3DXVECTOR3(-1.0f, -0.3f, -1.0f);
d3ddev->SetLight(0, &light); // send the light struct properties to light #0
d3ddev->LightEnable(0, TRUE); // turn on light #0
ZeroMemory(&material, sizeof(D3DMATERIAL9)); // clear out the struct for use
material.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // set diffuse color to white
material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // set ambient color to white
d3ddev->SetMaterial(&material); // set the globably-used material to &material
}
bool LoadModel(const std::string &filename)
{
if (!XAnimator->LoadXFile(filename,&ModelID[ObjectQuantity]))
{
return false;
}
ObjectQuantity ++;
if(countZ < ObjectQuantity) //increases count after loop is run
{
NumAnimationSets[countZ]=XAnimator->GetNumberOfAnimationSets(ModelID[countZ]);
CurrentAnimationSet[countZ] = 0;
// First animation set to start with - note: v.small transition time as it is the first
XAnimator->ChangeAnimationSet(ModelID[countZ],CurrentAnimationSet[countZ],500); //500 transition time in ms
}
countZ++;
return true;
}
inline void CleanDynamicVariables () //not used because crashes the program if more than two objects
{
delete[] NumAnimationSets;
delete[] CurrentAnimationSet;
delete[] lastTimeAnimationChanged;
delete[] lastUpdateTime;
delete[] timeElapsedSinceLastUpdate;
delete[] timeElapsedSinceAnimationChange;
delete XAnimator;
delete[] TranslateX;
delete[] TranslateY;
delete[] TranslateZ;
}
void FileWrite (float PosX, float PosY, float PosZ, float LookX, float LookY, float LookZ)
{
using namespace std;
ofstream File("FileInput.txt");
if (File)
{
// read stuff from FileInputZ and print into file
File << PosX << " " << PosY << " " << PosZ << endl
<< LookX << " " << LookY << " " << LookZ << endl;
}

}
void ProcessInput( long xDelta, long yDelta, long zDelta, float elapsedTime )
{
float cameraSpeed = 10.0f;

static bool pressedButtons[4];
for ( int i = 0; i < 4; i++ )
{
if ( mousestate.rgbButtons & 0x80 )
{
pressedButtons = TRUE;
}
else
{
pressedButtons = FALSE;
}

}
//if ( pressedButtons[0] ) //if left mouse click
//{
Camera.Yaw( xDelta * elapsedTime * 0.2f);
Camera.Pitch( yDelta * elapsedTime * 0.2f );
//}

if(keystate[DIK_W] & 0x80)
{
Camera.MoveForward( cameraSpeed * elapsedTime );
}
if(keystate[DIK_A] & 0x80)
{
Camera.Strafe( -cameraSpeed * elapsedTime );
}
if(keystate[DIK_S] & 0x80)
{
Camera.MoveForward( -cameraSpeed * elapsedTime );
}
if(keystate[DIK_D] & 0x80)
{
Camera.Strafe( cameraSpeed * elapsedTime );
}

}
void Pause( BOOL rendering, BOOL timer )
{
Timer.m_renderingPauseCount += rendering ? 1 : -1;
Timer.m_renderingPauseCount = (Timer.m_renderingPauseCount < 0) ? 0 :Timer.m_renderingPauseCount;
Timer.m_timerPauseCount += timer ? 1 : -1;
Timer.m_timerPauseCount = (Timer.m_timerPauseCount < 0) ? 0 : Timer.m_timerPauseCount;
Timer.m_renderingPaused = (Timer.m_renderingPauseCount > 0);
Timer.m_timerPaused = (Timer.m_timerPauseCount > 0);
if (Timer.m_timerPaused)
{
Timer.Stop();
}
else if (!Timer.m_timerPaused)
{
Timer.Start();
}
}
void SetObjectCoords ()
{
TranslateX[SKELE] = 4.0f;
TranslateY[SKELE] = 0.2f;
TranslateZ[SKELE] = 3.0f;
TranslateX[FLOOR] = 0.0f;
TranslateY[FLOOR] = 0.0f;
TranslateZ[FLOOR] = 0.0f;
TranslateX[WALL] = 0.0f;
TranslateY[WALL] = 0.0f;
TranslateZ[WALL] = 0.0f;
TranslateX[3] = 5.0f;
TranslateY[3] = 0.0f;
TranslateZ[3] = 0.0f;
}
//boundingboxes stuff starts here
void RenderBoundingBoxes(int ObjNum)
{
/*
Get bounding shape information from XAnimator
The GetBoundingShapes call allows you to get bounding shapes for the whole model and for each mesh within the model
The call has default parameters so you can just extract the min, max bounds of the whole model or, by providing sphere
variables you can also extract the sphere bounds. Finally by providing a variable for numMesh you can also extract
boudning data for each mesh within the model.
Note that the bounding data depends on the current animation of the model (from the last time it was animated)
*/
D3DXVECTOR3 minBoundsModelSpace,maxBoundsModelSpace; // Model min max values in object space
D3DXVECTOR3 sphereCentreModelSpace; // Sphere centre in model space
float sphereRadius; // Sphere radius in model space
int numMesh; // Number of individual mesh bounds returned by the function
// Get all the bounds information from XAnimator
TMeshBounds *indMeshBoundsModelSpace=XAnimator->GetBoundingShapes(ModelID[ObjNum],&minBoundsModelSpace,&maxBoundsModelSpace,&sphereCentreModelSpace,&sphereRadius,&numMesh);
/*
Model Oriented Bounding Box (OBB)
XAnimator returns all bounds values in model space. We need to convert these to world space
We do this by using the same world matrix we used to draw the model
When transforming from object space to world space we will lose the axis-aligned nature of the bounds
Meaning we cannot just store min and max values but must store all 8 corners of the box
Therefore the first step is to create the 8 corners
*/
// We have min and max values, use these to get the 8 corners of the boundingbox
D3DXVECTOR3 cornersInModelSpace[8];
cornersInModelSpace[0] = D3DXVECTOR3( minBoundsModelSpace.x, minBoundsModelSpace.y, minBoundsModelSpace.z ); // xyz
cornersInModelSpace[1] = D3DXVECTOR3( maxBoundsModelSpace.x, minBoundsModelSpace.y, minBoundsModelSpace.z ); // Xyz
cornersInModelSpace[2] = D3DXVECTOR3( minBoundsModelSpace.x, maxBoundsModelSpace.y, minBoundsModelSpace.z ); // xYz
cornersInModelSpace[3] = D3DXVECTOR3( maxBoundsModelSpace.x, maxBoundsModelSpace.y, minBoundsModelSpace.z ); // XYz
cornersInModelSpace[4] = D3DXVECTOR3( minBoundsModelSpace.x, minBoundsModelSpace.y, maxBoundsModelSpace.z ); // xyZ
cornersInModelSpace[5] = D3DXVECTOR3( maxBoundsModelSpace.x, minBoundsModelSpace.y, maxBoundsModelSpace.z ); // XyZ
cornersInModelSpace[6] = D3DXVECTOR3( minBoundsModelSpace.x, maxBoundsModelSpace.y, maxBoundsModelSpace.z ); // xYZ
cornersInModelSpace[7] = D3DXVECTOR3( maxBoundsModelSpace.x, maxBoundsModelSpace.y, maxBoundsModelSpace.z ); // XYZ
// Now we transform each corner by the world matrix
D3DXVECTOR3 cornersInWorldSpace[8];
for( int i = 0; i < 8; i++ )
{
D3DXVec3TransformCoord( &cornersInWorldSpace, &cornersInModelSpace, &IdentityMatrix);
}
// We now have an oriented bounding box in world space
//RenderOOBB(cornersInWorldSpace, ObjNum);
/*
Model Axis Aligned Bounding Box (OBB)
We could, at a loss in accuracy, convert our OBB in world space to an axis-alinged one in world space
This would make collision detection far easier
To convert we find the min and max values of the 8 corners in world space
*/
D3DXVECTOR3 minBoundsWorldSpace=cornersInWorldSpace[0];
D3DXVECTOR3 maxBoundsWorldSpace=cornersInWorldSpace[0];
for (int i=1;i<8;i++)
{
minBoundsWorldSpace.x=min(minBoundsWorldSpace.x,cornersInWorldSpace.x);
minBoundsWorldSpace.y=min(minBoundsWorldSpace.y,cornersInWorldSpace.y);
minBoundsWorldSpace.z=min(minBoundsWorldSpace.z,cornersInWorldSpace.z);
maxBoundsWorldSpace.x=max(maxBoundsWorldSpace.x,cornersInWorldSpace.x);
maxBoundsWorldSpace.y=max(maxBoundsWorldSpace.y,cornersInWorldSpace.y);
maxBoundsWorldSpace.z=max(maxBoundsWorldSpace.z,cornersInWorldSpace.z);
}

//RenderAABBox(minBoundsWorldSpace,maxBoundsWorldSpace,D3DCOLOR_XRGB(255,0,0));

/* Model individual mesh
XAnimator also returns an array of boundign boxes for each individual mesh in the model. These can be used for
very accurate collisions e.g. just with a foot or a hand.
*/
/*for (int i=0;i<numMesh;i++)
{
// Again we need to transform each one into world space
D3DXVECTOR3 indMeshOBBWorldSpace[8];
// Transform the 8 corners of our object space bounding box into world space
for( int j = 0; j < 8; j++ )
{
D3DXVec3TransformCoord( &indMeshOBBWorldSpace[j], &indMeshBoundsModelSpace.corners[j], &IdentityMatrix );
}
// And render
//RenderOOBB(indMeshOBBWorldSpace);
}*/
}
//loads the vertices
void RenderOOBB(D3DXVECTOR3 *cornersInWorldSpace, int ObjNum)
{
D3DXVECTOR3 front[4],back[4];
front[0] = cornersInWorldSpace[0];
front[1] = cornersInWorldSpace[2];
back[2] = cornersInWorldSpace[3];
back[3] = cornersInWorldSpace[1];
front[3] = cornersInWorldSpace[4];
front[2] = cornersInWorldSpace[6];
back[1] = cornersInWorldSpace[7];
back[0] = cornersInWorldSpace[5];
static float (* FrontX)[4] = new float[ObjectQuantity][4];
static float (* FrontY)[4] = new float[ObjectQuantity][4];
static float (* FrontZ)[4] = new float[ObjectQuantity][4];
static float (* BackX)[4] = new float[ObjectQuantity][4];
static float (* BackY)[4] = new float[ObjectQuantity][4];
static float (* BackZ)[4] = new float[ObjectQuantity][4];
for (int count = 0; count < 4; ++ count)
{
FrontX[ObjNum][count] = front[count].x;
FrontY[ObjNum][count] = front[count].y;
FrontZ[ObjNum][count] = front[count].z;
BackX[ObjNum][count] = back[count].x;
BackY[ObjNum][count] = back[count].y;
BackZ[ObjNum][count] = back[count].z;
}

CUSTOMVERTEX vertices[] =
{
{ FrontX[ObjNum][0], FrontY[ObjNum][0], FrontZ[ObjNum][0], D3DCOLOR_XRGB(0, 0, 255), },
{ FrontX[ObjNum][1], FrontY[ObjNum][1], FrontZ[ObjNum][1], D3DCOLOR_XRGB(0, 0, 255), },
{ FrontX[ObjNum][2], FrontY[ObjNum][2], FrontZ[ObjNum][2], D3DCOLOR_XRGB(0, 0, 255), },
{ FrontX[ObjNum][3], FrontY[ObjNum][3], FrontZ[ObjNum][3], D3DCOLOR_XRGB(0, 0, 255), },
{ BackX[ObjNum][0], BackY[ObjNum][0], BackZ[ObjNum][0], D3DCOLOR_XRGB(0, 0, 255), },
{ BackX[ObjNum][1], BackY[ObjNum][1], BackZ[ObjNum][1], D3DCOLOR_XRGB(0, 0, 255), },
{ BackX[ObjNum][2], BackY[ObjNum][2], BackZ[ObjNum][2], D3DCOLOR_XRGB(0, 0, 255), },
{ BackX[ObjNum][3], BackY[ObjNum][3], BackZ[ObjNum][3], D3DCOLOR_XRGB(0, 0, 255), },
};
// lock v_buffer and load the vertices into it
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();

//if the last object has been called
if (ObjNum == 3) //array starts from 0 not 1, that's why -1 ;; that was wrong..
{
for (int count = 1; count < ObjectQuantity; ++ count) //count 1+ because 0 is skeleton, other objects wont collide
{
for (int CountCorner = 0; CountCorner < 4; ++ CountCorner)
{
if (FrontX[SKELE][0] / BackX[3][0] > 0.98 && FrontX[SKELE][0] / BackX[3][0] < 1)
{
Movement = FALSE;
}
else
{
Movement = TRUE;
}
}
}
FileWrite(FrontX[0][0], FrontX[0][1], FrontX[0][2], FrontX[0][3], FrontX[SKELE][0], FrontX[SKELE][1]);
}
}
Advertisement

Don't mind the collision checks.
The problem basically is that what I'm getting for my bounding box coordinates is junk.
Junk like...
Object 0: 8.83098e-042 0 0
Object 3: 5 14.3369 1.17549e-038
[/quote]

So:


TMeshBounds *indMeshBoundsModelSpace=XAnimator->GetBoundingShapes(ModelID[ObjNum],&minBoundsModelSpace,&maxBoundsModelSpace,&sphereCentreModelSpace,&sphereRadius,&numMesh);


Is returning junk? If not, could you paste particular pieces of code you may think are faulty and why? This is an awful lot to parse through...
What makes you say these numbers are "junk"?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]


What makes you say these numbers are "junk"?


If my objects are positioned at:

void SetObjectCoords ()
{
TranslateX[SKELE] = 4.0f;
TranslateY[SKELE] = 0.2f;
TranslateZ[SKELE] = 3.0f;
TranslateX[FLOOR] = 0.0f;
TranslateY[FLOOR] = 0.0f;
TranslateZ[FLOOR] = 0.0f;
TranslateX[WALL] = 0.0f;
TranslateY[WALL] = 0.0f;
TranslateZ[WALL] = 0.0f;
TranslateX[3] = 5.0f;
TranslateY[3] = 0.0f;
TranslateZ[3] = 0.0f;
}


It makes no sense for their max bounds (as the numbers above) to have such values. At least makes no sense for me.

@greenvertex:

These are the parts I think may be faulty:

for (int count = 0; count < ObjectQuantity; ++count)
{
D3DXMatrixMultiply(&IdentityMatrix, &matRotateY[count], &matTranslate[count]);
// d3ddev->SetTransform(D3DTS_WORLD, &IdentityMatrix); // set the world transform
TMeshBounds *indMeshBoundsModelSpace=XAnimator->GetBoundingShapes(ModelID[count],&minBoundsModelSpace,&maxBoundsModelSpace,&sphereCentreModelSpace,&sphereRadius,&numMesh);

There I figured, to get the world matrix, I'd multiply those two matrices like I do when I draw each object:

for (int CountRender = 0;CountRender < ObjectQuantity; ++ CountRender) //draw all the objects despite of which object time calculation is executing
{

D3DXMatrixTranslation(&matTranslate[CountRender], TranslateX[CountRender], TranslateY[CountRender], TranslateZ[CountRender]);
XAnimator->Render(ModelID[CountRender], matRotateY[CountRender] * matTranslate[CountRender] ,(float)timeElapsedSinceLastUpdate[CountRender]);
}


The so called world matrix I got after multiplying, I then use here (which is the most suspicious place imho):

for( int i = 0; i < 8; i++ )
{
D3DXVec3TransformCoord( &cornersInWorldSpace[count], &cornersInModelSpace, &IdentityMatrix);
}


I hope that helps..
You might want to look at:


for (int count = 0; count < ObjectQuantity; ++count)
{
D3DXMatrixMultiply(&IdentityMatrix, &matRotateY[count], &matTranslate[count]);
//...


From what I can gather, IdentityMatrix seems to be the combination of all linear transforms of all models' rotation and translation up to that point. Is that actually what you wanted? Especially considering the call here:


for (int CountRender = 0;CountRender < ObjectQuantity; ++ CountRender) //draw all the objects despite of which object time calculation is executing
{
D3DXMatrixTranslation(&matTranslate[CountRender], TranslateX[CountRender], TranslateY[CountRender], TranslateZ[CountRender]);
XAnimator->Render(ModelID[CountRender], matRotateY[CountRender] * matTranslate[CountRender] ,(float)timeElapsedSinceLastUpdate[CountRender]);
}


Doesn't appear to be exhibiting that behavior. There it looks as if each world transform is the linear combination of one translation and one rotation matrix.

From what I can gather, IdentityMatrix seems to be the combination of all linear transforms of all models' rotation and translation up to that point. Is that actually what you wanted? Especially considering the call here:


I changed the code above to:

for (int count = 0; count < ObjectQuantity; ++count)
{
D3DXMatrixIdentity(&IdentityMatrix);
D3DXMatrixMultiply(&IdentityMatrix, &matRotateY[count], &matTranslate[count]);


And the only thing that happened was..

max bound values for two objects (x,y,z) changed from


1.77825e-042 0 0
5 14.3369 1.17549e-038


to...


2.83763e-042 0 0
5 14.3369 1.17549e-038


I hope I addressed the problem you pointed out the correct way. Even though it didn't seemingly contribute to much of an anything except different junk values.
Yea that would make IdentityMatrix represent the same combinations as above...

I'll keep looking when I get a chance, hopefully something will turn up.

Yea that would make IdentityMatrix represent the same combinations as above...

I'll keep looking when I get a chance, hopefully something will turn up.


Thank you
Try outputting the value of IdentityMatrix in:


FileWrite(maxBoundsWorldSpace[0].x, maxBoundsWorldSpace[0].y, maxBoundsWorldSpace[0].z,maxBoundsWorldSpace[3].x, maxBoundsWorldSpace[3].y, maxBoundsWorldSpace[3].z);


And post the first set of results. I can't see any problems in that loop with the math. Maybe the matrix is not what it appears. If everything's rendering correctly though via:


XAnimator->Render(ModelID[CountRender], matRotateY[CountRender] * matTranslate[CountRender] ,(float)timeElapsedSinceLastUpdate[CountRender]);


The IdentityMatrix should also be correct...
I'm not sure how to output a matrix but since it doesn't seem to let me as a multidimensional array.. I guess something like this.


if (count == 0)
{
FileWrite(IdentityMatrix[0], IdentityMatrix[1], IdentityMatrix[2],IdentityMatrix[3], 0, 0);
}


Result: 1 0 0 0

It is the same for every object (0 - 3)

This topic is closed to new replies.

Advertisement