Jump to content
  • Advertisement
Sign in to follow this  
Azzazelus_13

PhysX triangle mesh

This topic is 3814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I downloaded a sample from this site http://www.equalmeans.net/~chriss/EQM/index.html with some PhysX stuff. I managed to use physX in my project with no problem except TRIANGLE MESH COOKING. Convex mesh works perfectly fine but I dont know actually how to make the Triangle Mesh work so I downloaded the sample but it CRASHES.
//////////////////////////////////////////////////////////////////////////////////////////////////
// File: PhysXTriangleMesh.cpp
// Author: Chris Smith
// Date Created: 2/15/07
// Description: Demonstrates how to create a triangle mesh physics object from a DX mesh in PhysX
// Copyright: Use this however you want, but I am not responsible for anything
//////////////////////////////////////////////////////////////////////////////////////////////////

#define STRICT
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX

float ScreenWidth  = 640;
float ScreenHeight = 480;

#include <windows.h>
#include <mmsystem.h>
#include <d3d9.h>
#include <d3dx9.h>
#include "NxPhysics.h"
#include "cooking.h"
#include "Stream.h"

// Win32
HWND hwnd = NULL;

//DirectX
IDirect3DDevice9* D3DDevice = NULL;
ID3DXMesh* LevelMesh;
ID3DXMesh* BallMesh;

//PhysX Objects
static NxPhysicsSDK* gPhysicsSDK = NULL;
static NxScene*	gScene = NULL;
NxActor* PhysXLevel;
NxActor* PhysXBall;

//Timer
DWORD CurrentTime;
DWORD LastTime;
double DeltaTime;

// Prototypes
void GenerateTriangleMeshFromDXMesh(ID3DXMesh* Mesh, NxActor* &PhysXActor, NxVec3 pos);
bool LoadXFile(char* MeshFilename, ID3DXMesh* &Mesh);
void UpdateDeltaTime(void);
void InitPhysics(void);
void Setup(void);
void Cleanup(void);
void Render(void);
void InitializeDirect3D(void);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

///////////////////////////////////////////////////////
// Generate a convex physics object from a DX mesh
///////////////////////////////////////////////////////
void GenerateTriangleMeshFromDXMesh(ID3DXMesh* Mesh, NxActor* &PhysXActor, NxVec3 pos)
{

	typedef struct {
		D3DXVECTOR3 VertexPos;
		D3DXVECTOR3 Normal;
		D3DXVECTOR2 TexCoord;
	} Mesh_FVF;

	//Used to copy indices
	typedef struct {
		short IBNumber[3];
	} IndexBufferStruct;

	int NumVerticies = Mesh->GetNumVertices();
	int NumTriangles = Mesh->GetNumFaces();
	DWORD FVFSize = D3DXGetFVFVertexSize(Mesh->GetFVF());

	//Create pointer for vertices
	NxVec3* verts = new NxVec3[NumVerticies];

	char *DXMeshPtr;
	Mesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&DXMeshPtr);
	for(int i = 0; i < NumVerticies; i++)
	{
		Mesh_FVF *DXMeshFVF = (Mesh_FVF*)DXMeshPtr;
		verts = NxVec3(DXMeshFVF->VertexPos.x, DXMeshFVF->VertexPos.y, DXMeshFVF->VertexPos.z);
		DXMeshPtr += FVFSize;
	}
	Mesh->UnlockVertexBuffer();

	//Create pointer for indices
	IndexBufferStruct *tris = new IndexBufferStruct[NumTriangles];

	IndexBufferStruct *DXMeshIBPtr;
	Mesh->LockIndexBuffer(D3DLOCK_READONLY, (void**)&DXMeshIBPtr);
	for(int NumInd = 0; NumInd < NumTriangles; NumInd++)
	{
		tris[NumInd].IBNumber[0] = DXMeshIBPtr[NumInd].IBNumber[0];
		tris[NumInd].IBNumber[1] = DXMeshIBPtr[NumInd].IBNumber[1];
		tris[NumInd].IBNumber[2] = DXMeshIBPtr[NumInd].IBNumber[2];
	}

	Mesh->UnlockIndexBuffer();




	// Build physical model
	NxTriangleMeshDesc TriMeshDesc;
	TriMeshDesc.numVertices = NumVerticies;
	TriMeshDesc.numTriangles = NumTriangles;
	TriMeshDesc.pointStrideBytes = sizeof(NxVec3);
	TriMeshDesc.triangleStrideBytes = 3*sizeof(NxU32);
	TriMeshDesc.points = verts;
	TriMeshDesc.triangles = tris;
	TriMeshDesc.flags = NX_MF_16_BIT_INDICES;




	NxTriangleMeshShapeDesc ShapeDesc;
	if(0)
	{
		// Cooking from file
		bool status = NxCookTriangleMesh(TriMeshDesc, UserStream("c:\\tmp.bin", false));
		ShapeDesc.meshData = gPhysicsSDK->createTriangleMesh(UserStream("c:\\tmp.bin", true));
	}
	else
	{
		// Cooking from memory
		MemoryWriteBuffer buf;
		bool status = NxCookTriangleMesh(TriMeshDesc, buf);
		ShapeDesc.meshData = gPhysicsSDK->createTriangleMesh(MemoryReadBuffer(buf.data));
	}



	NxActorDesc actorDesc;
	actorDesc.shapes.pushBack(&ShapeDesc);
	actorDesc.globalPose.t = pos;
	PhysXActor = gScene->createActor(actorDesc);
	PhysXActor->userData = (void*)1;

	delete[] verts;
	delete[] tris;
}

///////////////////////////////////////////////////////
// Load a .X file
///////////////////////////////////////////////////////
bool LoadXFile(char* MeshFilename, ID3DXMesh* &Mesh)
{
	//Zero Mesh and create buffer
	Mesh = 0;
	ID3DXBuffer* MeshBuffer  = 0;

	//Load and optimize the mesh
	if(FAILED(D3DXLoadMeshFromX( MeshFilename, D3DXMESH_MANAGED, D3DDevice, &MeshBuffer, 0, 0, 0, &Mesh)))
		return false;

	Mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)MeshBuffer->GetBufferPointer(), 0, 0, 0);

	//Release and zero the buffer
	MeshBuffer->Release();

	return true;
}

///////////////////////////////////////////////////////
// UpdateDeltaTime
///////////////////////////////////////////////////////
void UpdateDeltaTime()
{
	CurrentTime = timeGetTime();
	DeltaTime = ((double)CurrentTime - (double)LastTime) * 0.001f;
	LastTime = timeGetTime();
}

///////////////////////////////////////////////////////
// Initialize the physics
///////////////////////////////////////////////////////
void InitPhysics( void )
{
	//Initialize PhysicsSDK
	gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION, NULL, NULL);
	gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.05f);

	//Initialize cooking
	bool status = NxInitCooking();

	//Create a scene
	NxSceneDesc sceneDesc;
	sceneDesc.gravity = NxVec3(0.0f, -20.0f, 0.0f);
	gScene = gPhysicsSDK->createScene(sceneDesc);

	//Set default material
	NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0);
	defaultMaterial->setRestitution(0.0f);
	defaultMaterial->setStaticFriction(0.5f);
	defaultMaterial->setDynamicFriction(0.5f);

	//Create the sphere
	{
		//Define sphere physics object
		NxBodyDesc SphereBodyDesc;
		SphereBodyDesc.angularDamping = 0.5f;
		SphereBodyDesc.linearVelocity = NxVec3(0.0f, 0.0f, 0.0f);

		NxSphereShapeDesc SphereDesc;
		SphereDesc.radius = 1.0f;

		NxActorDesc SphereActorDesc;
		SphereActorDesc.shapes.pushBack(&SphereDesc);
		SphereActorDesc.body = &SphereBodyDesc;
		SphereActorDesc.density	= 10.0f;
		SphereActorDesc.globalPose.t = NxVec3(-10.0f, 25.0f, 7.0f);

		//Add new sphere object to physics scene
		PhysXBall = gScene->createActor(SphereActorDesc);
	}
}

///////////////////////////////////////////////////////
// Setup
///////////////////////////////////////////////////////
void Setup(void)
{
	//Start the timer
	UpdateDeltaTime();

	//Initialize the Physics
	InitPhysics();

	//Load the level mesh before making the physics object with it
	LoadXFile("level.X", LevelMesh);

	//Create level physics object
	GenerateTriangleMeshFromDXMesh(LevelMesh, PhysXLevel, NxVec3(0,0,0));

	//Make level physics object static
	PhysXLevel->raiseBodyFlag(NX_BF_KINEMATIC);

	//Create the ball mesh
	D3DXCreateSphere(D3DDevice, 1.0f, 20, 20, &BallMesh, 0);

	//Set the View matrix
	D3DXMATRIX View;
	D3DXVECTOR3 Position(0.0f, 50.0f, -50.0f);
	D3DXVECTOR3 Target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
	D3DXMatrixLookAtLH(&View, &Position, &Target, &Up);
	D3DDevice->SetTransform(D3DTS_VIEW, &View);

	//Set the Projection matrix
	D3DXMATRIX Proj;
	D3DXMatrixPerspectiveFovLH( &Proj, D3DX_PI /4, ScreenWidth / ScreenHeight, 1.0f, 1000.0f );
	D3DDevice->SetTransform(D3DTS_PROJECTION, &Proj);

    //Turn on lighting and set an ambient value
    D3DDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
    D3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( 0.2f, 0.2f, 0.2f, 1.0f ) );

	//Create a simple DX directional light
    D3DLIGHT9 light0;
    ZeroMemory( &light0, sizeof(D3DLIGHT9) );
    light0.Type = D3DLIGHT_DIRECTIONAL;
    light0.Direction = D3DXVECTOR3( 0.5f, -0.8f, 0.7f );
    light0.Diffuse.r = 1.0f;
    light0.Diffuse.g = 1.0f;
    light0.Diffuse.b = 1.0f;
    light0.Diffuse.a = 1.0f;

	//Set the light
    D3DDevice->SetLight(0, &light0);
    D3DDevice->LightEnable(0, TRUE);

	//Create a white material
	D3DMATERIAL9 WhiteMtrl;
    ZeroMemory( &WhiteMtrl, sizeof(D3DMATERIAL9) );

    WhiteMtrl.Diffuse.r = 1.0f;
    WhiteMtrl.Diffuse.g = 1.0f;
    WhiteMtrl.Diffuse.b = 1.0f;
    WhiteMtrl.Diffuse.a = 1.0f;
    WhiteMtrl.Ambient.r = 1.0f;
    WhiteMtrl.Ambient.g = 1.0f;
    WhiteMtrl.Ambient.b = 1.0f;
    WhiteMtrl.Ambient.a = 1.0f;

	D3DDevice->SetMaterial(&WhiteMtrl);
}

///////////////////////////////////////////////////////
// Cleanup
///////////////////////////////////////////////////////
void Cleanup( void )
{
	//Destroy the physics
	if(gPhysicsSDK != NULL)
	{
		if(gScene != NULL)
			gPhysicsSDK->releaseScene(*gScene);

		gPhysicsSDK->release();
	}

	//Release the DX Meshes
	LevelMesh->Release();
	BallMesh->Release();

	//Release the Direct3D device
	D3DDevice->Release();
}

///////////////////////////////////////////////////////
// Render
///////////////////////////////////////////////////////
void Render(void)
{
	//Update the delta time 
	UpdateDeltaTime();
	
	//Update the physics
	gScene->simulate(DeltaTime);

    D3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0 );
    D3DDevice->BeginScene();

	//Set the world matrix
	D3DXMATRIX World;
	D3DXMatrixIdentity(&World);
	D3DDevice->SetTransform(D3DTS_WORLD, &World);

	//Render the level
	LevelMesh->DrawSubset(0);

	//Get ball matrix and render it
	PhysXBall->getGlobalPose().getColumnMajor44(World);
	D3DDevice->SetTransform(D3DTS_WORLD, &World);
	BallMesh->DrawSubset(0);

    D3DDevice->EndScene();
    D3DDevice->Present( NULL, NULL, NULL, NULL );

	//Fetch simulation results
	gScene->flushStream();
	gScene->fetchResults(NX_RIGID_BODY_FINISHED, true);
}

///////////////////////////////////////////////////////
// WindowProc
///////////////////////////////////////////////////////
LRESULT CALLBACK WindowProc( HWND hWnd, UINT msg,  WPARAM wParam, LPARAM lParam )
{
    switch( msg )
	{
        case WM_KEYDOWN:
		{
			if( wParam == VK_ESCAPE )
			{
				PostQuitMessage(0);
				break;
			}
		}
        break;

		case WM_CLOSE:
		{
			PostQuitMessage(0);
		}
		
        case WM_DESTROY:
		{
            PostQuitMessage(0);
		}
        break;

		default:
		{
			return DefWindowProc( hWnd, msg, wParam, lParam );
		}
		break;
	}
	return 0;
}

///////////////////////////////////////////////////////
// InitializeDirect3D
///////////////////////////////////////////////////////
void InitializeDirect3D( void )
{
	IDirect3D9* D3D = NULL;

    D3D = Direct3DCreate9( D3D_SDK_VERSION );

	if( !D3D )
	{
		if( D3D != NULL )
			D3D->Release();

		::MessageBox(0, "Direct3DCreate9() - Failed", 0, 0);
		return;
	}

    D3DDISPLAYMODE d3ddm;

    if( FAILED( D3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
	{
		if( D3D != NULL )
			D3D->Release();

		::MessageBox(0, "GetAdapterDisplayMode() - Failed", 0, 0);
		return;
	}

	HRESULT hr;

	if( FAILED( hr = D3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 
												d3ddm.Format, D3DUSAGE_DEPTHSTENCIL,
												D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
	{
		if( hr == D3DERR_NOTAVAILABLE )
		{
			if( D3D != NULL )
				D3D->Release();

			::MessageBox(0, "CheckDeviceFormat() - Failed", 0, 0);
			return;
		}
	}

	D3DCAPS9 d3dCaps;

	if( FAILED( D3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps ) ) )
	{
		if( D3D != NULL )
			D3D->Release();

		::MessageBox(0, "GetDeviceCaps() - Failed", 0, 0);
		return;
	}

	DWORD dwBehaviorFlags = 0;

	// Use hardware vertex processing if supported, otherwise default to software 
	if( d3dCaps.VertexProcessingCaps != 0 )
		dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
	else
		dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

	// All system checks passed, create the device

	D3DPRESENT_PARAMETERS d3dpp;
	memset(&d3dpp, 0, sizeof(d3dpp));

    d3dpp.BackBufferFormat       = d3ddm.Format;
	d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
	d3dpp.Windowed               = TRUE;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_ONE;

    if( FAILED( D3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
                                      dwBehaviorFlags, &d3dpp, &D3DDevice ) ) )
	{
		if( D3D != NULL )
			D3D->Release();

		::MessageBox(0, "CreateDevice() - Failed", 0, 0);
		return;
	}

	// No longer needed, release it
	 if( D3D != NULL )
        D3D->Release();
}

///////////////////////////////////////////////////////
// WinMain
///////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	WNDCLASSEX winClass;
	MSG        uMsg;

    memset(&uMsg,0,sizeof(uMsg));

	winClass.lpszClassName = "MainWindow";
	winClass.cbSize        = sizeof(WNDCLASSEX);
	winClass.style         = CS_HREDRAW | CS_VREDRAW;
	winClass.lpfnWndProc   = WindowProc;
	winClass.hInstance     = hInstance;
	winClass.hIcon	       = ::LoadIcon(0, IDI_APPLICATION);
    winClass.hIconSm	   = ::LoadIcon(0, IDI_APPLICATION);
	winClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	winClass.lpszMenuName  = NULL;
	winClass.cbClsExtra    = 0;
	winClass.cbWndExtra    = 0;

	if( !RegisterClassEx(&winClass) )
		return E_FAIL;

	hwnd = CreateWindowEx( NULL, "MainWindow", 
                             "PhysX Triangle Mesh - by Chris Smith",
						     WS_OVERLAPPEDWINDOW,
					         0, 0, ScreenWidth, ScreenHeight, NULL, NULL, hInstance, NULL );

	if( hwnd == NULL )
		return E_FAIL;

    ShowWindow( hwnd, nCmdShow );
    UpdateWindow( hwnd );

	InitializeDirect3D();
	Setup();

	while( uMsg.message != WM_QUIT )
	{
		if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
		{ 
			TranslateMessage( &uMsg );
			DispatchMessage( &uMsg );
		}
        else
		    Render();
	}

	Cleanup();

    UnregisterClass( "MY_WINDOWS_CLASS", winClass.hInstance );

	return uMsg.wParam;
}

The .X file is Ok, i really dont know where is the problem as I didnt touched the sample. The crash: http://img262.imageshack.us/img262/5226/wx1nq0.jpg

Share this post


Link to post
Share on other sites
Advertisement
Since the access violation is reading address 0x00000008, it's likely that the problem is a NULL pointer that's being used somewhere it shouldn't be (offset by +8, very likely because it's supposed to be a pointer to a struct or object with something at this offset).

Can you 'break' and get a call stack from Visual Studio?

Failing that, try to isolate which code is causing the problem, perhaps by commenting out bits of it until the crash no longer occurs.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!