DirectX + PhysX (English)

This is a lesson for English-speaking people and it`s just a copy of the same lesson on Russian language. First of all — sorry for my bad English, but as I think, it is better to read this than text on Russian or text from Google translator.
I’ve wrote this translation in a cause of interest from other counties.

This lesson is about how to setup and work with PhysX with your DirectX based application and what problems you need to solve on this way. Also I’ll give you information about how to create NxConvexMesh and NxTriangleMesh from DirectX mesh (.x) file data.

Introduction.

логотипо First of all read this. For this time everybody know physics engine named Nvidia PhysX (also Ageia PhysX some time ago), so Ill cut away briefing about it. One thing that you really need to understand — PhysX is a free for you! But sources of it is not. If you don’t want to change PhysX core you can use it for free. All that you need is to insert some Nvidia logos in your product if it is commercial. More about licenses. Go here to download latest PhysX sdk.

About lesson.

There are some difficults for DirectX developers because there is no examples for DirectX in sdk (there is only one and bad example with dxut). Google can help you to find some few examples but they are for Ageia PhysX, and there are some troubles for newbie.
People in forums ofen answering like “Examples for DirectX and OpenGL are the same!”, but I say NO! They are wrong!)
What do you need? I am using MSVS C++ 2005 for coding, so you can try it too.

With what to start?

Try to run examples in sdk, to look how the magic makes -) Below you can see code of scene update.

RenderCallback() {
...
gScene->simulate(1.0f/60.0f);
...
}

Simply order of it looks like: making of scene object, making of physic object, translate objects to scene, then calling update in step.

одна из демок физикса

Problems. Matrices.

First of all some words about VRD — Visual Remote Debugger (also there is better program PVD — PhysX Visual Debuger). With this utillites you can catch bugs in your program “on fly” and manipulate PhysX objects. It is really cool.
In VRD you can find some diffuculties because it`s using RHCS — Right Hand Coordinate System, but in DX we are using LHCS, don’t forget it!
How to transform NxMat34 to D3DXMATRIX ? I`ve searched answer for a long time -) But its really simple:

//NxMat34 a;
a.getColumnMajor44( d3dMat );

And how to draw our graphic object at the right place, where PhysX object is? That’s simple too (if you know it!)):

//NxActor* object; LPD3DXMESH* g_pObjectMesh;
D3DXMATRIX d3dMat;
taburet_object->getGlobalPose().getColumnMajor44( d3dMat );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
g_pObjectMesh->DrawSubset(0);

долго с этим мучился

On this screenshots something wrong with matrices -)
так уже лучше
VRD and your program, look for differences! ^_^

Problems. Meshes..

How to create mesh from model file? For newbies it is very strong problem cause many of them don’t really know how its works, many of them using DirecX meshes to forget about buffers\indexes\triangles so do I -) Thanks to Chillypacman, from Nvidia forum for help in understanding how it works and functions that are really work!)
In example we will use type vector (из namespace std).

So the magic functions are:
1. Function for getting array of vertices from LPD3DXMESH

vector<float> GetVertices(LPD3DXMESH    *g_pMesh )
{
	vector<float> vertices;
	DWORD stride =  D3DXGetFVFVertexSize((*g_pMesh)->GetFVF());
	BYTE* vbptr = NULL;
	(*g_pMesh)->LockVertexBuffer(0, (LPVOID*)&vbptr);
	int ii = -1;
	for(int i = 0; i < (*g_pMesh)->GetNumVertices(); i++)
	{
		ii++;
		D3DXVECTOR3* pos = (D3DXVECTOR3*)vbptr;
		vertices.push_back(pos->x);
		vertices.push_back(pos->y);
		vertices.push_back(pos->z);
		vbptr += stride;
	}
	(*g_pMesh)->UnlockVertexBuffer();
	return vertices;
}

2. Function for getting array of indices:

vector<short> GetIndices(LPD3DXMESH     *g_pMesh)
{
	LPVOID * ppData;
	DWORD stride = sizeof(short);
	BYTE* ibptr = NULL;
	short* indices = new short[(*g_pMesh)->GetNumFaces() * 3];
	vector<short> copy;
	(*g_pMesh)->LockIndexBuffer(0, (LPVOID*)&indices);

	for(int i = 0; i < (*g_pMesh)->GetNumFaces() * 3; i++)
	{
		copy.push_back(indices[i]);
	}
	(*g_pMesh)->UnlockIndexBuffer();
	return copy;
}

Before we continue lets speak about what Triangle Mesh and Convex Mesh is.
First object used only for static geometry and you cane use it for walls in your engine, but you need to know that Nvidia advice is to avoid of using it, its better to use simple objects like box everywhere you can.
Second object type is simple rounded mesh with maximum of 256 vertices that can be used for both static and dynamic objects. Its can be generated automatically ore loaded from file formats like Collada.

Now we can return to magic functions:

2. Function for generation of NxTriangleMesh:

NxActor* GenTriangleMesh(NxVec3 pos, vector<short> indices, vector<float> vertices )
{
	int NumVerticies = vertices.size() / 3;
	int NumTriangles = indices.size() / 3;
	//Create pointer for vertices
	NxVec3* verts = new NxVec3[NumVerticies];
	int ii = -1;
	
	for(int i = 0; i < NumVerticies; i++)
	{
		++ii;
		verts[i].x = vertices[ii];
		verts[i].y = vertices[++ii];
		verts[i].z = vertices[++ii];
	}

	//Create pointer for indices
	NxU16 *tris = new NxU16[indices.size()];
	for(int i = indices.size() - 1; i >= 0; i--)
	tris[i] = i;

	// Build physical model
	NxTriangleMeshDesc TriMeshDesc;
	TriMeshDesc.numVertices = NumVerticies;
	TriMeshDesc.numTriangles = NumTriangles;
	TriMeshDesc.pointStrideBytes = sizeof(NxVec3);
	TriMeshDesc.triangleStrideBytes = 3*sizeof(NxU16);
	TriMeshDesc.points = verts;
	TriMeshDesc.triangles = tris;
	TriMeshDesc.flags = NX_MF_16_BIT_INDICES ;//| NX_MF_FLIPNORMALS  ;
	NxTriangleMeshShapeDesc ShapeDesc;
	NxInitCooking();

	// Cooking from memory
	MemoryWriteBuffer buf;
	bool status = NxCookTriangleMesh(TriMeshDesc, buf);
	ShapeDesc.meshData = g_pPhysicsSDK->createTriangleMesh(MemoryReadBuffer(buf.data));
	NxActorDesc actorDesc;
	actorDesc.shapes.pushBack(&ShapeDesc);
	actorDesc.globalPose.t = pos;
	NxActor* act = g_pScene->createActor(actorDesc);
	delete[] verts;
	delete[] tris;
	return act;
}

3. Function for generation of NxConvexMesh:

NxActor* GenConvexMesh(const NxVec3& pos, vector<float> vertices, const NxReal density)
{
	int i = 0;
	NxActorDesc actorDesc;
	NxBodyDesc bodyDesc;
	int numVertices = vertices.size() / 3;
	NxVec3* verts = new NxVec3[numVertices];
	int ii = -1;
	
	for(int i = 0; i < numVertices; i++)
	{
		++ii;
		verts[i].x = vertices[ii];
		verts[i].y = vertices[++ii];
		verts[i].z = vertices[++ii];
	}
	
	// Create descriptor for convex mesh
	NxConvexMeshDesc convexDesc;
	convexDesc.numVertices         = numVertices;
	convexDesc.pointStrideBytes    = sizeof(NxVec3);
	convexDesc.points                   = verts;
	convexDesc.flags                     = NX_CF_COMPUTE_CONVEX;
	NxActorDesc actorDesc;
	NxInitCooking();
	MemoryWriteBuffer buf;
	bool status = NxCookConvexMesh(convexDesc, buf);
	NxConvexShapeDesc* convexShapeDesc    =    new NxConvexShapeDesc();
	convexShapeDesc->localPose.t          =    NxVec3(0,0,0);
	convexShapeDesc->materialIndex        =    0;
	convexShapeDesc->meshData = g_pPhysicsSDK->createConvexMesh(MemoryReadBuffer(buf.data));
	actorDesc.shapes.pushBack(convexShapeDesc);
	NxBodyDesc bodyDesc;
	if(!stat)
	{
		actorDesc.body = &bodyDesc;
		actorDesc.density = 1;
	}
	else
		actorDesc.body = NULL;

	actorDesc.globalPose.t  = NxVec3(0, 0, 0);
	actorDesc.name = "boo";
	NxActor* actor = g_pScene->createActor(actorDesc);
	return actor;
}

Looks like this functions are the most common searched functions.

Problems with Cooking.h and Stream.h

Those headers are using in PhysX examples, but they are in different versions, and there are same problems with them, so I am giving you header (CookingStream.h) modified by my friend ASD (asddev.3dn.ru), his file is a mix of those two files and works pretty good.
You can find it in archive to lesson.

Additional:

How to use VRD (or PVD) in your program? Its simple indeed, copy this code in header where your PhysX initializing:

#define SAMPLES_VRD_HOST "localhost"
#define SAMPLES_VRD_PORT NX_DBG_DEFAULT_PORT
#define SAMPLES_VRD_EVENTMASK NX_DBG_EVENTMASK_EVERYTHING
int    gAppData;
void vrd_init()
{
  NxRemoteDebugger* pRemDeb = g_pPhysicsSDK->getFoundationSDK().getRemoteDebugger();
  
  pRemDeb->connect(SAMPLES_VRD_HOST,   SAMPLES_VRD_PORT,   SAMPLES_VRD_EVENTMASK);

  if (pRemDeb->isConnected())
  {
      pRemDeb->createObject(&gAppData,  NX_DBG_OBJECTTYPE_GENERIC,"AppData",   NX_DBG_EVENTMASK_EVERYTHING);
      pRemDeb->writeParameter("Info text",   &gAppData,   true,"Info",     NX_DBG_EVENTMASK_EVERYTHING);
      pRemDeb->createObject(&gAppData+1,   NX_DBG_OBJECTTYPE_VECTOR,"AVector",   NX_DBG_EVENTMASK_EVERYTHING);
      pRemDeb->writeParameter(NxVec3(0, 0, 0),  &gAppData+1,   true,"Origin",  NX_DBG_EVENTMASK_EVERYTHING);
      pRemDeb->writeParameter(NxVec3(1, 1, 1),  &gAppData+1,  true,"Extent",  NX_DBG_EVENTMASK_EVERYTHING);
      pRemDeb->addChild(&gAppData, &gAppData+1,  NX_DBG_EVENTMASK_EVERYTHING);
      // Tells our application that we have created the VRD object
      // and that it is ok to set information in it
      gAppData = 1; 
  }
}

After PhysX initialization call vrd_init();. Now if you ran VRD before your program starts, your program will automatically be connected to VRD.

What is in the archive?

My sample based on example for Ageia NovodeX (first name of PhysX) from CodeSampler.com, there are few things that you need to change in their lesson:
1. from project properties you must remove Physics.lib. Also you need to copy PhysXLoader.lib,nxcooking.lib,NxCharacter.lib to project folder and too connect library’s use:

#pragma comment(lib, "physxloader.lib")
#pragma comment(lib, "nxcooking.lib")
#pragma comment(lib, "NxCharacter.lib")
2. In compilation you may see error in function initNovodeX() where you need to remove those lines:
sceneDesc.broadPhase = NX_BROADPHASE_COHERENT;
sceneDesc.collisionDetection = true;

So everything will run now!

Screenshot from my example.

кууубики

P.S.

So there is a point where my lesson ends -) Enjoy it!
Thanks to ASD and Chillypacman for their help again. You can also see Chillypacman`s solution HERE
Thanks to Nvidia for free PhysX!

And… sorry for my bad English again)

Wow, and archive!! -> dx9_novodex_simple_derivedbycrol

Реклама

6 Responses to “DirectX + PhysX (English)”


  1. 1 ASD 18/08/2009 в 07:12

    ow, nice translation :) at least it could be really useful.

  2. 2 mr 29/12/2009 в 06:29

    Thanks, friend! Just what I needed :D

  3. 3 lanks 05/07/2011 в 13:33

    oi amigo o codigo fonte do seu tutorial esta com o link off sera que teria como voce colocar on pra gente poder entender melhor?????

  4. 4 pvns 14/06/2012 в 13:00

    Link to dx9_novodex_simple_derivedbycrol is dead. Please make it alive.
    Thanks in advance

  5. 5 CharlesDido 06/04/2016 в 14:38

    любопытно выслушать потомков,которые сейчас знают, чем мочь изумить транссексуалы Москвы. Я по собственной личности исследователь. Уже сигал с парашютом, с эстакады на резинке, каботажничал на лодке по горному хребту. И вообще интим постоянно не терпится перепробовать в бытии. смотри и пришла ко мне идея попробовать такого типа вид интим услуги. для какой цели собственно необходимо оказаться подготовленным? Как себя корчить с такими? Проститутки Москвы, с которыми мне приходилось водиться, нисколько о трансах дельного известить не в силах. Может они какое-нибудь собственное каста, недоступное от сторонних взоров. Я просто не знаю где их можно встретить, исключая как не в интернете.

  6. 6 Stevenbuh 16/05/2016 в 11:32

    Недурно бы рассказать своими эмоциями насчет вояжа по Европе.чувства не о достопримечательностях и тому подобном, а о древнейшей профессии и еёвидах.ведомо на территорий государств пребывавшего совка, а тоже на Балканах, путанство полностью запрещена и гоняется законом. этого не скажешь сравнительно про державы Западной и Центральной Европы. В том ракурсе государства дробятся на 2 типов- где абсолютно легальна путанство и сексуальные услуги в всяких формах индивидуалки, и где древнейшая профессия легальна однако воспрещены бордели и сутенерство. к первой части относятся Германия и Чехия. к следующему типу — Франция. первый вид — среди авторов секс-туризма, и прямо в те страны лучше всего идеально лететь ради такого авантюры .


Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s




Twitter

Рубрики

Топ записей

Онлайн игра в которую я играю.

Страницы

Май 2009
Пн Вт Ср Чт Пт Сб Вс
     
 123
45678910
11121314151617
18192021222324
25262728293031

%d такие блоггеры, как: