Game Development Community

dev|Pro Game Development Curriculum

PhysX in TGE Version 0.3 (Work-In-Progress)

by Shannon "ScarWars" Scarvaci · 07/03/2006 (11:35 am) · 269 comments

Outline
1. License
2. Get SDK from Ageia
3. Implementation
4. Scripts
5. Know Issues
6. Need your supports!

License:
The license of PhysX is following:
Free:
  * Commercial & non-commercial use on PC
       Must keep registration information currect
       Must agree to the EULA at the time of download (pops up, but is copied below)
       Available for Windows & Linux (soon)
       No PhysX HW support requirement
  * PS3 platform (through Sony pre-purchase)
  * All platforms through some of our middleware partnerships, such as UE3, Gamebryo 2.2,
     and others
k per platform:
  * Xbox 360
  * Fee may be waived at our discretion for multi-platform developers providing PC HW support
  * Fee may be waived at our discretion for some Tools & Middleware providers

Get SDK from Ageiq
You can obtain the SDK from www.ageia.com website, my currently version for this physics is 2.7.0.

If you are using Visual Studio then you need to add "include" and "library" in the project configuration.
(If you using linux or mac, then i don't know where to setup because I dont have linux or mac with me)
Directory for include files:
C:\Program Files\AGEIA PhysX SDK\v2.6.4\SDKs\Physics\include
C:\Program Files\AGEIA PhysX SDK\v2.6.4\SDKs\Foundation\include
C:\Program Files\AGEIA PhysX SDK\v2.6.4\SDKs\PhysXLoader\include
C:\Program Files\AGEIA PhysX SDK\v2.6.4\SDKs\Cooking\include
Directory for library files:
C:\Program Files\AGEIA PhysX SDK\v2.6.4\SDKs\lib\win32
Note: These files' path's are relative to my hard drive, your files may be in different directory depending on how you installed the PhysX SDK.

Please install AGEIA PhysX Runtime in your PC (prefered lastest version)
Also put two dll file (PhysXLoader.dll and NxCooking.dll from AGEIA PhysX SDK\v2.7.0\SDKs\Bin\win32) in the example folder.


Implementation
Copy the 17 files from "PhysX" folder into engine/PhysX and modify some TGE's source code files.

Player
in game/player.h in bold
//----------------------------------------------------------------------------

[b]struct sNxActor;[/b]
class Player: public ShapeBase
{
  typedef ShapeBase Parent;
  [b]sNxActor *mActor;[/b]
protected:
  /// Bit masks for different types of events
  enum MaskBits {

game/player.cc at the top in bold
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
[b]#include "physX/PhysX.h"
#include "physX/PhysXWorld.h"[/b]
#include "game/player.h"

game/player.cc in Player::Player() function
mMountPending = 0;

   [b]mActor = NULL;[/b]
}

game/player.cc in Player::onAdd() function
gCamFXMgr.clear();
        }

	 [b]PhysXWorld *PxWorld = PhysXWorld::getWorld(isServerObject());
	 if (PxWorld) {
		 mActor = PxWorld->AddShapeBase(this);
	 }[/b]

   return true;

game/player.cc in Player::setPosition(...)
else {
      mat.set(EulerF(0, 0, rot.z));
      mat.setColumn(3,pos);
   }
   [b]if (mActor) {
      QuatF q(mat);
      Point3F pos;
      mat.getColumn(3,&pos);
      NxQuat quat;
      quat.setXYZW(q.x,q.y,q.z,q.w);
      mActor->actor->setGlobalOrientationQuat(quat);
      mActor->actor->setGlobalPosition(NxVec3(pos.x,pos.y,pos.z));
   }[/b]
   Parent::setTransform(mat);
   mRot = rot;
}

Terrain
in terrain/terrData.cc
at the top of the file
#include "terrain/terrRender.h"
#include "terrain/blender.h"

[b]#include "physX/PhysXWorld.h"[/b]

extern bool gDGLRender;

terrain/terrData.cc in TerrainBlock::onAdd function near the end
if(!unpackEmptySquares())
                 return(false);

	[b]PhysXWorld *PxWorld = PhysXWorld::getWorld(isServerObject());
	if (PxWorld) {
		PxWorld->SetupTerrainCollision(); // old style
	}[/b]

   return true;
}

Interior
in interior/interior.h
class Interior
{
   ...
   friend class EditInteriorResource;
   [b]friend class PhysXInterior;[/b]

in interior/interiorInstance.h
class InteriorInstance : public SceneObject
{
   ...
   friend class FloorPlan;
   [b]friend class PhysXInterior;
   friend class PhysXWorld;[/b]

in interior/interiorInstance.cc
#include "platform/profiler.h"
[b]#include "physX/PhysXWorld.h"[/b]

...

bool InteriorInstance::onAdd()
{
   ...
   
   addToScene();

   [b]PhysXWorld *PxWorld = PhysXWorld::getWorld(isServerObject());
   if (PxWorld) {
      PxWorld->SetupInterior(*this);
   }[/b]
   return true;
}

TSStatic
in ts/tsShapeInstance.h
class TSShapeInstance
{
   ...
   friend class TSPartInstance;
   [b]friend class PhysXTSStatic;
   friend class PhysXActor;[/b]

in game/tsStatic.h
class TSStatic : public SceneObject
{
   ...
   friend class TSStaticConvex; 
   [b]friend class PhysXTSStatic;[/b]

in game/tsStatic.cc
#include "sim/netConnection.h"
[b]#include "physX/PhysXWorld.h"[/b]

...

bool TSStatic::onAdd()
{
   ...
   
   addToScene();

   [b]PhysXWorld *PxWorld = PhysXWorld::getWorld(isServerObject());
   if (PxWorld) {
      PxWorld->SetupTSStatic(*this);
   }[/b]
   return true;
}

ShapeBase
in game\shapeBase.h
class ShapeBase : public GameBase
{
   typedef GameBase Parent;
   friend class ShapeBaseConvex;
   friend class ShapeBaseImageData;
   [b]friend class PhysXWorld;[/b]

Material in GameBase
in game\gameBase.h
[b]struct PhysXMaterialData;[/b]
struct GameBaseData : public SimDataBlock {
   ...
   void unpackData(BitStream* stream);
   [b]// PhysX
   PhysXMaterialData* mMaterialBlock;[/b]
};
...
class GameBase : public SceneObject
{
   ...
   enum GameBaseMasks {
      InitialUpdateMask =     Parent::NextFreeMask,
      DataBlockMask =         InitialUpdateMask << 1,
      ExtendedInfoMask =      DataBlockMask << 1,
      ControlMask =           ExtendedInfoMask << 1,
      [b]//NextFreeMask =        ControlMask << 1
      // PhysX
      MaterialDataBlockMask = ControlMask << 1,
      NextFreeMask =          MaterialDataBlockMask << 1[/b]
   };
   ...

   [b]// PhysX
   bool setMaterialDataBlock(PhysXMaterialData* dptr);
   bool onNewMaterialDataBlock(PhysXMaterialData* dptr);[/b]

};
...
in game\gameBase.cc
[b]#include "physX/PhysX.h"
#include "physX/PhysXActor.h"[/b]
#include "platform/platform.h"
...
GameBaseData::GameBaseData()
{
   ...
   [b]mMaterialBlock = 0;[/b]
}
...
[b]IMPLEMENT_CONSOLETYPE(PhysXMaterialData)
IMPLEMENT_GETDATATYPE(PhysXMaterialData)
IMPLEMENT_SETDATATYPE(PhysXMaterialData)[/b]

void GameBaseData::initPersistFields()
{
   Parent::initPersistFields();
   ...
   [b]addField("materialBlock", TypePhysXMaterialDataPtr, Offset(mMaterialBlock, GameBaseData));[/b]
}
...
bool GameBase::onNewDataBlock(GameBaseData* dptr)
{
   ...
   [b]onNewMaterialDataBlock(mDataBlock->mMaterialBlock);[/b]

   setMaskBits(DataBlockMask);
   return true;
}
...
bool GameBase::setDataBlock(GameBaseData* dptr)
{
   ...
}

[b]bool GameBase::setMaterialDataBlock(PhysXMaterialData* dptr)
{
   if (isGhost() || isProperlyAdded()) {
      if (mDataBlock->mMaterialBlock != dptr)
         return onNewMaterialDataBlock(dptr);
   }
   else
      mDataBlock->mMaterialBlock = dptr;
   return true;
}

bool GameBase::onNewMaterialDataBlock(PhysXMaterialData* dptr)
{
   mDataBlock->mMaterialBlock = dptr;

   if (!mDataBlock->mMaterialBlock)
      return false;

   setMaskBits(MaterialDataBlockMask);
   return true;
}[/b]
...
U32 GameBase::packUpdate(NetConnection *, U32 mask, BitStream *stream)
{
   ...
   [b]if (stream->writeFlag((mask & MaterialDataBlockMask) && mDataBlock->mMaterialBlock != NULL)) {
      stream->writeRangedU32(mDataBlock->mMaterialBlock->getId(),
                             DataBlockObjectIdFirst,
                             DataBlockObjectIdLast);
   }[/b]

   // cafTODO: ControlMask
   return 0;
}

void GameBase::unpackUpdate(NetConnection *con, BitStream *stream)
{
   ...
   [b]if (stream->readFlag()) {
      PhysXMaterialData* dptrMD = 0;
      SimObjectId id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);

      if (!Sim::findObject(id,dptrMD) || !setMaterialDataBlock(dptrMD))
         con->setLastError("Invalid packet GameBase::unpackUpdate()");
   }[/b]
}

Scripts
Copy three script files (PhysX.cs, physXActorBox.cs and physXActorSphere.cs) in starter.fps/server/scripts and add three lines of code in starter.fps/server/scripts/games.cs

// PhysX
	 exec("./physX.cs");
	 exec("./physXActorBox.cs");
	 exec("./physXActorSphere.cs");
	 exec("./physXJoints.cs");

add one line of code in common/client/mission.cs
function clientCmdMissionStart(%seq)
{
   // The client recieves a mission start right before
   // being dropped into the game.
	[b]startPhysX();[/b]
}

and in every mission file need to add PhysXWorld as show in bold:
new SimGroup(MissionGroup) {

	 [b]new PhysXWorld() {
		errorReport = false; // set to true if you want error report from PhysX
	 };[/b]
	
	 new ScriptObject(MissionInfo) {
	 ...

If you want to testing around by droping the object in the free-look camera, then use default.bind.cs script
function addCrate(%val)
{
	if (%val)
		commandToServer('pxcrate');
}
function addBox(%val)
{
	if (%val)
		commandToServer('pxbox');
}
function addRock(%val)
{
	if (%val)
		commandToServer('pxsphere');
}

moveMap.bind( keyboard, "alt r", addCrate);
moveMap.bind( keyboard, "alt t", addBox);
moveMap.bind( keyboard, "alt y", addRock);

Know Issues
Terrain is the problem here because PhysX can accept 256x256 collision mesh in their engine which is mean squareSize equal to one! So the TGE's default squareSize is 8 and you see object will miss the collision in some area of the terrain. Possible solution is to create chunks, for example if you use squareSize of 8 then use 64 chunks of 256x256 collision mesh.

Loading the mesh of 256x256 collision will very slow but there possible solution is to write the mesh to file create by PhysX engine and read the file from PhysX will be lots faster, similar to lighting system which is used in TGE.

I've tried number of way to use Terrain collision in PhysX such as split in four section, NxHeightfield which make it very slow but I haven't tried this in PPU yet. So I have to stick with 256x256 collision mesh for a while.

Player/ShapeBase collision with PhysX's object is not complete.

Networking:
Loading objects from the begin in the remote client sometime not showing but if object appear during the gameplay will work ok. That something i need to be working on. (There may be some problem because of improved speed, but didn't test it yet)

Improved PhysX Speed
Big thank to decryptoid for helping us in PhysX, esp. for speed improvement.

Need your supports!
Now you can play with PhysX in your TGE game! If you find any improvement for this Physics in coding or script or anything please post here and I'll happy to update in here.
Also please use TDNfor any info to advise for our community

In the future:
- Run in PPU.
- Player collision.
- ShapeBase, (TSStatic and Interior - Completed) collision.
- Use advance physics such as joints, clothes and fluid. Done two type of joints

Enjoy your Physics!

Check out the video.
First Video
Second Video
Joints Video (4MB, prefer download before watch)

This is my first resource, please be kind to me :)

Due to file limit please download from here Updated 13th Apirl 2006

Here TGEA PhysX Resource here
#161
11/03/2006 (8:46 am)
ok.. so no changes needed... cool gonna test it tonight
#162
11/10/2006 (12:02 pm)
Is this the version that requires Physx card acceleration? Because it lags quite bad on my computer (800Mhz [Yes I know, slow processor, but with the Geforce6200 in it, it plays half-life 2 at max fine {And runs Garry's Mod with lots of exploding watermelons ok}])
#163
11/11/2006 (1:00 am)
Alex, this only uses the HW is its available. The lag (isn't that networking?) would be caused by your CPU. Physics calculations are very CPU intense and im surprised your pc supports HL2.
#164
11/14/2006 (1:26 pm)
Im having problems with the 2.6 SDK, anyone else getting the same crash?

The only way to resolve it is, unfortunately, to add this to PhysXWorld::onAdd()
// cant continue without gPhysicsSDK
		if (!gPhysicsSDK){ 
			Con::errorf("PhysX did not initialize properly!");
			return false;
		}

But that doesnt really fix the problem does it?

The crash comes from gScene = gPhysicsSDK->createScene(sceneDesc);
probably beacuse gPhysicsSDK isnt getting created for some reason. But why???

EDIT: I was using the wrong systemsoftware exe LOL, ignore this :(
#165
11/22/2006 (9:00 am)
Quote:
AGEIA TECHNOLOGIES has announced an End User Licence Agreement (EULA), which will allow its physics engine, the PhysX SDK to be used and its runtime components distributed commercially and otherwise, royalty free.

The EULA means that game developers, be they big name developers or working on smaller projects, will be able to use the PhysX engine with a no-fee licence.

:)
#166
11/22/2006 (11:24 am)
No. Fucking. Way.
#167
11/26/2006 (3:20 pm)
Will this [In the future releases] have the advanced features in PhysX? (For example that awesome cloth simulation with the carpet that you can tear up [The one you get in the SDK]) or will it only have the basic necessities (Gravity, collision detection, round stuff rolls, etc)?

If you havn't seen the example I'm talking about it's in SampleCloth, when you run that hit 6, right click and drag to Pinch and tear an area of the carpet, sure it doesn't behave exactly like a carpet (Little too elastic) But it sure shows potential.

-edit- forgot question marks
#168
11/26/2006 (6:26 pm)
First, excellent work -- this is the best physics implementation in Torque I've seen to date.

So, I got this working with minimal effort, and it's impressively smooth. The objects don't blip or react in any odd ways, except the physics timescale seems to be way off -- objects clearly move accurately, but they do so on a completely different scale.

Basically, objects fall at a rate at least 2x, if not more, the actual rate of gravity. They react in the same manner when pushed or impacting with each other -- it's very smooth and accurate, but clearly the physics timescale is far too high. Anyone have an idea of how to adjust this?

***UPDATE***

Okay, so I found the place where this is handled, but I'm having trouble figuring out what value is appropriate here. The current value, 32, creates a physics sim which is leaps and bounds faster than Torque's (which seems to be relatively physically accurate -- compare TGE's sim to ODE, for example -- even based on many explorations of the code. It's also consistant with behaviors seen in other physics sims, like HL2 and Oblivion's Havok.

I tried changing the value to TickSec, thinking it was possible the sim had been accidentally written for seconds and then called using MS, and the result was actually more realistic, but about 30% slower than TGE physics. In case you're curious, I'm testing vs. items, vehicles, and players, all of which fall at about the same rate (excepting the Player's speed cap while falling).

I'm continuing to tweak this value to find the actual appropriate level for the sim, but I'm curious what's causing it to be off scale in the first place.

Line 219 in PhysXWorld.cpp is where you can change the scale, by changing the amount of time in each tick. A value of TickSec * 1.4 results in objects which react in sync with TGE objects, and everything is still smooth as silk.
#169
11/27/2006 (7:53 am)
Quote:
but I'm curious what's causing it to be off scale in the first place

Maybe you're not looking in the right place?

EDIT: Just read the rest of your post :)
#170
11/29/2006 (9:45 pm)
Good news for Linux/GCC devs:

Version 2.6.2
* Software Runtime for SuSE Enterprise Linux 10.0 (alpha release; 32bit and 64bit editions; Pentium III / Athlon XP and higher only)
* Software Runtime for Red Hat Enterprise Linux WS 4.0 (alpha release; 32bit and 64bit editions; Pentium III / Athlon XP and higher only)


According to Ageia, PhysX 2.6.0 will be available for Debian linux sometime late next week
#171
12/05/2006 (10:47 am)
I'm trying to get PhysX 2.6.2 to work in my TGE 1.5 Visual Studio 2005 project.

I'm getting the following error:

Error 1 fatal error C1189: #error : custom definition of NX_CALL_CONV for your OS needed! c:\program files\ageia technologies\ageia physx sdk\v2.6.2\sdks\foundation\include\nx.h 34


It looks like the solution is to include WIN32 in the Preprocessor Definitions, is this correct?

Current Preprocessor Definitions for TGE 1.5 Debug(Win32): UNICODE;TORQUE_DEBUG;_CRT_SECURE_NO_DEPRECATE

Will adding WIN32 cause problems with TGE?
#172
12/05/2006 (11:01 am)
NxCreatePhysicsSDK is returning NULL with error code NXCE_PHYSX_NOT_FOUND.
I can't figure out what I'm doing wrong. Any help would be appreciated.
#173
12/14/2006 (3:40 pm)
I installed the wrong system software version. I needed to install 6.11.01. Now that I have the correct version, I expect to have PhysX integrated into my TGE game by jan 2007.
#174
12/15/2006 (4:57 pm)
thank you for your nice job ,Shannon


i am using Microsoft Visual Studio .NET 2003, but i have problem with this error .can you help me?


'NxPhysics.h': No such file or directory

Physx.h:
#include

regards
#175
12/17/2006 (1:17 pm)
... posting problems.
#176
12/17/2006 (1:21 pm)
.... finally got it to load. (freaked out on strange characters!)
#177
12/17/2006 (1:27 pm)
First off let me give much thanks to Shannon for starting this resource. Ageia Physx the by far the best physics systems EVER and I am glad to finally be able to implement it in TSE!

This resource is great, however there are many changes that will help to utilize it to its full potential. Just to give you an example, check out these shots of Physx on Atlas2 (and keep in mind I DO NOT have a Physx Card!):

www.decryptoid.com/downloads/physx.jpg
The balls are actually rolling... and look at the framerate! This is a 16km Atlas2 terrain with a treedepth of 5 and about 2.2 million total vertices. After atlas loads I cook each of the collision chunks into an actor (with mesh paging set to auto) and load in their appropriate locations. So far I have not been able to make an atlas terrain that wont cook and I am talking some sick terrains! I cannot just upload the code for you guys because this requires many other changes to the Physx implementation to allow it to work. (this entire terrain cooked in 4 seconds)



AND, entire Orc Base cooked into a physx object...
www.decryptoid.com/downloads/physx2.jpg
Something is wacky in the resource implementation for interiors (sometimes they wont cook.. others were missing hulls, positions were wacky) so I rewrote some of it so it does the transforms and positions for the interiors correctly and never misses and interior or hull. (Orc Base cooks in about 0.5 seconds)

What I am using The newest PhysX SDK on a Dual Opteron with an ATI X800 and 2GB of memory.. nothing amazing.

Helpful hints:
* MOST IMPORTANT Run the Physx engine asynchronously!! If you dont then you will never understand the true power of Physx. Run serially like in this resource you will be waiting for the physx to finish for each cycle and that makes it seems clunky. The Physx engine will stall the game if you try to get the results before you have run an iteration so you should set a flag for the first cycle.

* Timing is wrong: Physx is based on fractions of a second, NOT milliseconds. Physx is also an iterative processor. Meaning it tries to as many iterations as possible in the time you give it per cycle. Torque and TSE are already process-ticked so we dont need to use this function either. So.. on your scene set:
sceneDesc.maxIter = 1;
sceneDesc.timeStepMethod = NX_TIMESTEP_FIXED;
sceneDesc.maxTimestep = 0.03125;
AND use StartPhysx(0.03125)

This will force 1 iteration per processtick with every timestep = 0.03125.

*Using density is confusing: Everything should use mass not density. By using mass the physx engine will make all other calulations for you automatically and you wont get thos wacky collisions with objects flying off into space. Also, this will make the sim seem faster @ 0.03125. (thats why it seems slow at the correct timing using desnities makes object masses HUGE!)

* Remove Server/client check from PhysXWrold::Processtick: You are losing cycles here. The physx engine HAS to run to matter were it is so let it. You will immediately notice the speed increase here. This is directly connected with the timing issues (again, why it seems slow and chunky)

*Everything needs a physx material: If you dont implement a physx material for EVERY object then it defaults to the stock one which is lame. Objects wont act like you expect.

*The scripts for adding and defining objects are confusing. You have to write a script to add every object because you assign the material in the OnCreate routine instead of the objects datablock. Heres another way to try. (shadow stuff is for TSE)

//*************************************************************************
// This file is for PhysX based prop objects....
//*************************************************************************

// generic spawn function for testing
function pxCreateItem(%objDataBlock) {
  
    %pos = LocalClientConnection.Camera.getPosition();
  
    new PhysXActor() {
                position = %pos;
                rotation = "1 0 0 0";
                dataBlock = %objDataBlock;
                materialBlock = %objDataBlock.matdata;
    };
}


moveMap.bindCmd( keyboard, "p", "", "pxCreateItem(pxBoulder);");


//*************************************************************************
// creation routine for physx props
// this is for ALL physx objects...
// You need to set the material in a
// "matData" variable in the datablock
//*************************************************************************
function PhysXActorData::create(%data)
{
                 %obj = new PhysXActor() {
                      dataBlock = %data;
                      materialBlock = %data.matdata;
                 };
                return %obj;
}

//*************************************************************************
//PhysX Materials
//*************************************************************************
datablock PhysXMaterialData(pxBouncyMaterial) {
                //The ratio of speed of separation to speed of approach in a collision
                pxRestitution = 0.7;
                //Friction while still
                pxStaticFriction = 0.9;
                //Friction in motion
                pxDynamicFriction = 0.9;
};

//***********************************
// boulder - with physics
//***********************************
datablock PhysXActorData(pxBoulder)
{
    
    category = "Props - PhysX enabled";
    shapeFile = "~/data/shapes/boulder/boulder.dts";
    emap = true;

    // details for shadows... (for TSE only)
    shadowEnable = true;
    shadowCanMove = true;
    shadowCanAnimate = true;
    //shadowSelfShadow = true;
    shadowSize = 512;
    shadowAnimationFrameSkip = 5;
    shadowMaxVisibleDistance = 200;
    //shadowProjectionDistance = 20;
    shadowSphereAdjust = 5.0;
    //shadowBias = 0.5;

    //physx details...
    pxShape = "sphere";
    pxRadius = "2.0";

    //friction = 0;
    mass = 500.0;
    //elasticity = 0;

    // HERE is where you set the physx material datablock!
    matdata = pxBouncyMaterial;
    
};

In summation... After messing with this realized that we can TOTALLY Physx enable Torque/TSE without any real problems. All that is really necessary is that users have a machine with either dual processors, dual cores, or a single processor with the Physx Card (obviously the card would be best though).

Shannon, let me know if you are still maintaining this and I will start sending you my code posting here will take up a ton of space (especially the atlas2 stuff whoah!)

Sorry about the wacky posting... pasting from "Word" inserts strange characters!
#178
12/17/2006 (1:47 pm)
Oh... and heres the code to make bullets effect physx objects.

Right after this in Projectile::onCollision:
Con::executef(mDataBlock, 6, "onCollision",
         scriptThis(),
         Con::getIntArg(hitObject->getId()),\
         Con::getFloatArg(mFadeValue),
         posArg,
         normalArg);

You need to add this:
// Only run this if we collide with a PhysX Object
if (!dStrcmp(hitObject->getClassName(), "PhysXActor"))
   {
   // force is calculated as (0.5 * (Speed^2 * Mass))/Time^2
   // speed = muzzlevelocity (m/sec)
   // mass = bullet mass (kg)
   // time = 4 for now (4 millisecond impact)
   F32 impactDuration = 4;
 
   // * using kinetic energy values like this will cause the
   // impulse value to be squared as speed doubles which
   // "feels" most realistic
   F32 impulseVal = ( 0.5 * ((mDataBlock->muzzleVelocity * mDataBlock->muzzleVelocity) * mDataBlock->massVal))/(impactDuration*impactDuration);
 		  
   // convert the hitposition (world coordinates) to Nx Vector
   NxVec3 nvHitPosition = hitPosition;
 		
   // create a hitforce vector out of the hitnormal.
   // the normal is the opposite direction
   // so reverse it as well...
   NxVec3 nvHitNormalForce = -hitNormal * impulseVal;
 
   // get the physx actor out of the hitobject
   PhysXActor * act = dynamic_cast<PhysXActor*>(hitObject);
 
   // apply the impulse
   act->mActor->actor->addForceAtPos(nvHitNormalForce,nvHitPosition,NX_IMPULSE,true);
 
}

It will only work if you make a new datablock variable called massVal or just replace mDataBlock->massVal with a real number in kilograms. Experiment!
#179
12/17/2006 (2:04 pm)
More goodies.... Ever wonder how the h*ll to get face indexes for a triangle mesh that isn't square? This was really p*ssing me off when I was implementing various triangle meshes of strange shaped objects. I am sure most of you have already noticed that the Ageia examples only cover square stuff for this (size, xsize, ysize... blah blah blah).

For almost everything you can just use this for your face indexing:

//******************** build fake face array **************************
// since there is no consistancy for this object type we just
// make up a triangle index... otherwise it wont cook
 
     NxU32 k = 0;
     int countFace = 0;
     for(NxU32 i=0;i<nbFaces;i++)
     {
            // create first triangle
            faces[k++] = countFace;		
            faces[k++] = countFace+1;	
            faces[k++] = countFace+2;	
 
            countFace = countFace +3;
 	
      }

The sweet part is it will make a face index for a triangle mesh with an odd number of faces... praise the lord! You may have to set the mesh flag to switch normals, but thats about it.
#180
12/18/2006 (10:39 pm)
Hi, can you explain how do you want to implement multiplayer support ? In the normal way everytging is calculating by the server and this is not really good if you want to play with 32 or 64 players ^^

THX for the great work !