//-----------------------------------------------------------------------------
//  Constructor
//-----------------------------------------------------------------------------
CPhysicEngine::CPhysicEngine (void)
{
    // Creacion e inicializacion del objeto principal de PhysX
    int nVersion = NX_PHYSICS_SDK_VERSION;
    NxSDKCreateError errorCode;
    m_pPhysicsSDK = NxCreatePhysicsSDK (NX_PHYSICS_SDK_VERSION, Globals::g_pUserAllocator, this, NxPhysicsSDKDesc(), &errorCode);
    if (!m_pPhysicsSDK)  return;

#ifdef _DEBUG
    m_pPhysicsSDK->getFoundationSDK().getRemoteDebugger()->connect ("localhost", 5425);
#endif

    // Set the physics parameters
    m_pPhysicsSDK->setParameter (NX_SKIN_WIDTH, 0.001f);

    // Set the debug visualization parameters
    m_pPhysicsSDK->setParameter (NX_VISUALIZATION_SCALE, 1);
    m_pPhysicsSDK->setParameter (NX_VISUALIZE_COLLISION_SHAPES, 1);
    m_pPhysicsSDK->setParameter (NX_VISUALIZE_ACTOR_AXES, 1);

    // Inicializacion del motor de cooking para procesamiento de triangleMeshes
    NxInitCooking();

    // Creacion del gestor de controllers
    m_pControllerMgr = NxCreateControllerManager ( Globals::g_pUserAllocator );
}
Exemple #2
0
Menge::GeometryInterface * NovodexPhysicSystem::cookConcave( const float * _verts, int _vertexSize, const int * _indecies, int _indexSize )
{
	NxTriangleMeshDesc triMeshDesc;

	triMeshDesc.numVertices			= _vertexSize;
	triMeshDesc.pointStrideBytes	= 3 * sizeof(float);
	triMeshDesc.points				= _verts;
	triMeshDesc.numTriangles		= _indexSize;
	triMeshDesc.triangles			= _indecies;
	triMeshDesc.triangleStrideBytes	= 3 * sizeof(int);
	triMeshDesc.flags				= 0;

	NxTriangleMeshShapeDesc * nxTriShape = new NxTriangleMeshShapeDesc();

	NxInitCooking();
	MemoryWriteBuffer buf;

	//bool status = NxCookTriangleMesh(triMeshDesc, UserStream("c:\\cooked.bin", false));

	bool status = NxCookTriangleMesh(triMeshDesc, buf);
	assert(status);

	nxTriShape->meshData = m_physicsSDK->createTriangleMesh(MemoryReadBuffer(buf.data));
	nxTriShape->group = GROUP_COLLIDABLE_NON_PUSHABLE;

	NovodexGeometry * novodexGeometry = new NovodexGeometry(nxTriShape);
	return novodexGeometry;
}
Exemple #3
0
bool plSimulationMgr::InitSimulation()
{
    fSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION, NULL, &gErrorStream);
    if (!fSDK) {
        fLog->AddLine("Phailed to init PhysX SDK");
        return false; // client will handle this and ask user to install
    }

    fLog = plStatusLogMgr::GetInstance().CreateStatusLog(40, "Simulation.log", plStatusLog::kFilledBackground | plStatusLog::kAlignToTop);
    fLog->AddLine("Initialized PhysX SDK");

    if (!NxInitCooking(nullptr, &gErrorStream)) {
        fLog->AddLine("Phailed to init NxCooking");
        fSDK->release();
        fSDK = nullptr;
        return false;
    }

#ifndef PLASMA_EXTERNAL_RELEASE
    // If this is an internal build, enable the PhysX debugger
    fSDK->getFoundationSDK().getRemoteDebugger()->connect("localhost", 5425);
#endif

    return true;
}
Exemple #4
0
Menge::GeometryInterface * NovodexPhysicSystem::cookConvex( const float * _verts, int _vertexSize, const int * _indecies, int _indexSize )
{
	NxConvexMeshDesc m_convexMesh;

	m_convexMesh.numVertices			= _vertexSize;
	m_convexMesh.pointStrideBytes		= 3 * sizeof(float);
	m_convexMesh.points					= _verts;
	m_convexMesh.numTriangles			= _indexSize;
	m_convexMesh.triangles				= _indecies;
	m_convexMesh.triangleStrideBytes	= 3 * sizeof(int);
	m_convexMesh.flags					= 0;

	NxConvexShapeDesc * nxConvexShape = new NxConvexShapeDesc();

	NxInitCooking();
	MemoryWriteBuffer buf;

	bool status = NxCookConvexMesh(m_convexMesh, buf);
	assert(status);

	nxConvexShape->meshData = m_physicsSDK->createConvexMesh(MemoryReadBuffer(buf.data));
	nxConvexShape->group = GROUP_COLLIDABLE_PUSHABLE;

	NovodexGeometry * novodexGeometry = new NovodexGeometry(nxConvexShape);
	return novodexGeometry;
}
void plPhysXCooking::Init()
{
    NxInitCooking();
    NxUtilLib* fUtilLib=NxGetUtilLib();
    NxCookingParams parms=NxGetCookingParams();
    parms.skinWidth=.05;
    NxSetCookingParams(parms);

}
Exemple #6
0
bool InitCooking(NxUserAllocator* allocator, NxUserOutputStream* outputStream)
{
#ifdef COOKING_INTERFACE
  hasCookingLibrary();
  if ( !gCooking ) return false;
  return gCooking->NxInitCooking(allocator, outputStream);
#else
  return NxInitCooking(allocator, outputStream);
#endif
}
bool InitCooking(void)
{
	#ifdef COOKING_INTERFACE
	hasCookingLibrary();
	if (!gCooking)
	{
		return false;
	}
	return gCooking->NxInitCooking();
	#else
	return NxInitCooking();
	#endif
}
//-------------------------------------------------------------------------------------------------
bool sdPhysXCookUtility::InitCooking(NxUserAllocator* pkAllocator, NxUserOutputStream* pkOutputStream)
{
#ifdef COOKING_INTERFACE
	if (!ms_pkCooking)
		ms_pkCooking = NxGetCookingLib(NX_PHYSICS_SDK_VERSION);

	if (!ms_pkCooking)
		return false;

	ms_pkCooking->NxInitCooking(pkAllocator, pkOutputStream);
	return true;
#else
	return NxInitCooking(pkAllocator, pkOutputStream);
#endif
}
Exemple #9
0
// -----------------------------------------------------------------------
void MyCloth::init(NxScene *scene, NxClothDesc &desc, NxClothMeshDesc &meshDesc)
{
	mScene = scene;

	// if we want tearing we must tell the cooker
	// this way it will generate some space for particles that will be generated during tearing
	if (desc.flags & NX_CLF_TEARABLE)
		meshDesc.flags |= NX_CLOTH_MESH_TEARABLE;

	NxInitCooking();
	cookMesh(meshDesc);
	NxCloseCooking();

	releaseMeshDescBuffers(meshDesc);

	allocateReceiveBuffers(meshDesc.numVertices, meshDesc.numTriangles);

	desc.clothMesh = mClothMesh;
	desc.meshData = mReceiveBuffers;
	mCloth = scene->createCloth(desc);
	mInitDone = true;
}
void PhysCreateStaticRigidBodyMesh ( int iObject )
{
	sObject* pObject = dbGetObject ( iObject );

	if ( !pObject )
		return;

	int iCount = 0;
	
	for ( int iMesh = 0; iMesh < pObject->iMeshCount; iMesh++ )
	{
		NxVec3* pVertices		= new NxVec3 [ pObject->ppMeshList [ iMesh ]->dwVertexCount ];
		int		iVertexCount	= pObject->ppMeshList [ iMesh ]->dwVertexCount;
		int*	iTriangles		= new int [ pObject->ppMeshList [ iMesh ]->dwIndexCount ];
		int		iTriangleCount	= pObject->ppMeshList [ iMesh ]->dwIndexCount;

		sOffsetMap offsetMap;
		GetFVFOffsetMap ( pObject->ppMeshList [ iMesh ], &offsetMap );

		for ( int i = 0; i < iVertexCount; i++ )
		{
			pVertices [ i ].x = *( ( float* ) pObject->ppMeshList [ iMesh ]->pVertexData + offsetMap.dwX + ( offsetMap.dwSize * i ) );
			pVertices [ i ].y = *( ( float* ) pObject->ppMeshList [ iMesh ]->pVertexData + offsetMap.dwY + ( offsetMap.dwSize * i ) );
			pVertices [ i ].z = *( ( float* ) pObject->ppMeshList [ iMesh ]->pVertexData + offsetMap.dwZ + ( offsetMap.dwSize * i ) );
		}

		for ( i = 0; i < iTriangleCount; i++ )
			iTriangles [ i ] = pObject->ppMeshList [ iMesh ]->pIndices [ i ];
		
		NxTriangleMeshDesc levelDesc;
		levelDesc.numVertices			= iVertexCount;
		levelDesc.numTriangles			= iTriangleCount / 3;
		levelDesc.pointStrideBytes		= sizeof ( NxVec3 );
		levelDesc.triangleStrideBytes   = 3 * sizeof ( int );
		levelDesc.points				= pVertices;
		levelDesc.triangles				= iTriangles;
		levelDesc.flags					= NX_CF_COMPUTE_CONVEX;

		NxTriangleMeshShapeDesc levelShapeDesc;
		NxInitCooking ( );
		
		MemoryWriteBuffer buf;
		bool status = NxCookTriangleMesh ( levelDesc, buf );
		
		if ( status )
		{
			levelShapeDesc.meshData = gPhysicsSDK->createTriangleMesh ( MemoryReadBuffer ( buf.data ) );
		
			NxActor* actor = NULL;

			NxActorDesc actorDesc;
			actorDesc.shapes.pushBack ( &levelShapeDesc );

			actor = gScene->createActor ( actorDesc );
			
			sPhysObject* pPhys = new sPhysObject;
			pPhys->iID      = iObject;
			actor->userData = ( void* )pPhys;

			SetActorCollisionGroup ( actor, GROUP_COLLIDABLE_NON_PUSHABLE );
		}
	}
}
void plGenericPhysical::IWritePXPhysical(hsStream* S, plResManager* mgr) {
    S->writeFloat(fMass);
    S->writeFloat(fFriction);
    S->writeFloat(fRestitution);
    S->writeByte(fBounds);
    S->writeByte(plPXSimDefs::toGroup(fMemberGroup, fCollideGroup));
    S->writeInt(plPXSimDefs::setReportsOn(fReportGroup));
    S->writeShort(fLOSDBs);
    mgr->writeKey(S, fObjectKey);
    mgr->writeKey(S, fSceneNode);
    mgr->writeKey(S, fSubWorld);

    mgr->writeKey(S, fSoundGroup);
    fPos.write(S);
    fRot.write(S);
    fProps.write(S);

    if (fBounds == plSimDefs::kSphereBounds) {
        S->writeFloat(fRadius);
        fOffset.write(S);
    } else if (fBounds == plSimDefs::kBoxBounds) {
        fDimensions.write(S);
        fOffset.write(S);
    } else if (fBounds == plSimDefs::kHullBounds) {
#ifdef HAVE_PX_SDK
        if (!sPhysxWasInit) {
            NxInitCooking();
            sPhysxWasInit = true;
        }
        NxConvexMeshDesc convexDesc;
        convexDesc.numVertices = fVerts.size();
        convexDesc.pointStrideBytes = sizeof(hsVector3);
        convexDesc.points = &fVerts[0];
        convexDesc.flags = NX_CF_COMPUTE_CONVEX;

        plPXStream buf(S);
        if (!NxCookConvexMesh(convexDesc, buf))
            throw hsBadParamException(__FILE__, __LINE__, "Incorrect data for PhysX Hull Bake");
#else
        throw hsNotImplementedException(__FILE__, __LINE__, "PhysX HullBounds");
#endif
    } else {    // Proxy or Explicit
#ifdef HAVE_PX_SDK
        if (!sPhysxWasInit) {
            NxInitCooking();
            sPhysxWasInit = true;
        }
        NxTriangleMeshDesc triDesc;
        triDesc.numVertices = fVerts.size();
        triDesc.pointStrideBytes = sizeof(hsVector3);
        triDesc.points = &fVerts[0];
        triDesc.numTriangles = fIndices.size() / 3;
        triDesc.triangleStrideBytes = sizeof(unsigned int) * 3;
        triDesc.triangles = &fIndices[0];
        triDesc.flags = 0; // 32-bit appears to be the default for index size

        plPXStream buf(S);
        if (!NxCookTriangleMesh(triDesc, buf))
            throw hsBadParamException(__FILE__, __LINE__, "Incorrect data for a PhysX Trimesh Bake");
#else
        throw hsNotImplementedException(__FILE__, __LINE__, "PhysX TriangleMesh");
#endif
    }
}
Exemple #12
0
NxActor* CreatePyramid(const NxVec3& pos, const NxVec3& boxDim, const NxReal density)
{
	// Add a single-shape actor to the scene
    NxActorDesc actorDesc;
    NxBodyDesc bodyDesc;

    // Pyramid
    NxVec3 verts[8] = { NxVec3(boxDim.x,-boxDim.y,-boxDim.z), NxVec3(-boxDim.x,-boxDim.y,-boxDim.z), NxVec3(-boxDim.x,-boxDim.y,boxDim.z), NxVec3(boxDim.x,-boxDim.y,boxDim.z), 
                        NxVec3(boxDim.x*0.5,boxDim.y,-boxDim.z*0.5), NxVec3(-boxDim.x*0.5,boxDim.y,-boxDim.z*0.5), NxVec3(-boxDim.x*0.5,boxDim.y,boxDim.z*0.5), NxVec3(boxDim.x*0.5,boxDim.y,boxDim.z*0.5) };

    // Create descriptor for convex mesh
    NxConvexMeshDesc convexDesc;
    convexDesc.numVertices			= 8;
    convexDesc.pointStrideBytes		= sizeof(NxVec3);
    convexDesc.points				= verts;
    convexDesc.flags				= NX_CF_COMPUTE_CONVEX | NX_CF_USE_LEGACY_COOKER;

	// The actor has one shape, a convex mesh
    NxConvexShapeDesc convexShapeDesc;
	convexShapeDesc.localPose.t		= NxVec3(0,boxDim.y,0);
 
	NxInitCooking();
    if (0)
    {
        // Cooking from file
#ifndef LINUX
        bool status = NxCookConvexMesh(convexDesc, UserStream("c:\\tmp.bin", false));
        convexShapeDesc.meshData = gPhysicsSDK->createConvexMesh(UserStream("c:\\tmp.bin", true));
#else
		printf("Linux does not behave well with UserStreams, use Memorybuffers instead\n");
#endif
    }
    else
    {
        // Cooking from memory
        MemoryWriteBuffer buf;
        bool status = NxCookConvexMesh(convexDesc, buf);
        convexShapeDesc.meshData = gPhysicsSDK->createConvexMesh(MemoryReadBuffer(buf.data));
    }

    if (convexShapeDesc.meshData)
    {
        NxActorDesc actorDesc;
        actorDesc.shapes.pushBack(&convexShapeDesc);
	    if (density)
	    {
		    actorDesc.body = &bodyDesc;
		    actorDesc.density = density;
	    }
	    else
	    {
		    actorDesc.body = NULL;
	    }
        actorDesc.globalPose.t  = pos;
		NxActor* actor = gScene->createActor(actorDesc);

		return actor;
//      gPhysicsSDK->releaseConvexMesh(*convexShapeDesc.meshData);
    }

    return NULL;
}
void InitNx()
{
	// Create a memory allocator
    gAllocator = new UserAllocator;

	// Initialize physics SDK
	gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION, gAllocator);
	if (!gPhysicsSDK)  return;

	gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.05);
	gPhysicsSDK->setParameter(NX_VISUALIZATION_SCALE, 10);
	//gPhysicsSDK->setParameter(NX_VISUALIZE_FLUID_POSITION, 1);
	//gPhysicsSDK->setParameter(NX_VISUALIZE_FLUID_VELOCITY, 1);
	gPhysicsSDK->setParameter(NX_VISUALIZE_FLUID_PACKETS, 1);
	gPhysicsSDK->setParameter(NX_VISUALIZE_FLUID_DRAINS, 1);

	// Create a scene
	NxSceneDesc sceneDesc;
	sceneDesc.simType				= NX_SIMULATION_SW;
	sceneDesc.gravity				= gDefaultGravity;
	gScene = gPhysicsSDK->createScene(sceneDesc);	

	// Create the default material
	NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0); 
	defaultMaterial->setRestitution(0.5);
	defaultMaterial->setStaticFriction(0.5);
	defaultMaterial->setDynamicFriction(0.5);

	// Initialize cooking
    NxInitCooking(NULL, &gErrorStream);

	// Load ASE files
    int set = 0;

#ifdef WIN32
	set = SetCurrentDirectory(&fname[0]);
	if (!set) set = SetCurrentDirectory(&fname1[0]);
	if (!set) set = SetCurrentDirectory(&fname2[0]);
	if (!set) set = SetCurrentDirectory(&fname3[0]);
	if (!set) { 
		char basePath[256];
		GetModuleFileName(NULL, basePath, 256);
		char* pTmp = strrchr(basePath, '\\');
		basePath[pTmp-basePath+1] = 0;
		SetCurrentDirectory(basePath);//for running from start menu

		set = SetCurrentDirectory(&fname2[0]);
	}
#elif LINUX
	set = chdir(&fname[0]);
	if (set != 0) set = chdir(&fname2[0]);
	if (set != 0) set = chdir(&fname3[0]);
#endif

	bowl = CookASE("fluidSample.ase", gScene, NxVec3(1,0,0));
	flume = CookASE("coolFlow.ase", gScene, NxVec3(1,-4,-0), NxVec3(1,0.2,1));

	box = CreateBox(NxVec3(2,5-0.75,7), NxVec3(0.75,0.75,0.75), 1);
	sphere = CreateSphere(NxVec3(0,4-0.4,1), 0.4, 1);
	capsule = CreateCapsule(NxVec3(3,0-(1+0.5),8), 1, 1, 1);

	CreateBox(NxVec3(0,-10-1,0), NxVec3(40,1,40), 0);

	fluid = CreateFluid(NxVec3(0,1.5,0), 19, 0.1, gScene);

    AddUserDataToActors(gScene);
	//((ActorUserData*)(drain->userData))->flags |= UD_IS_DRAIN;

	// Page in the hardware meshes
	if(bHardwareScene)
		PageInHardwareMeshes(gScene);

	gSelectedActor = box;

	// Initialize HUD
	InitializeHUD();

	// Get the current time
	getElapsedTime();

	// Start the first frame of the simulation
	if (gScene)  StartPhysics();
}
NxActor* CreateConvex(const NxVec3 &pos, int flag)
{
   NxActorDesc actorDesc;
    NxBodyDesc bodyDesc;
	
	NxVec3 boxDim(1,0.8,1.5);
    // Pyramid
     NxVec3 verts[8] =	{	NxVec3(boxDim.x,      -boxDim.y, -boxDim.z), 
							NxVec3(-boxDim.x,     -boxDim.y, -boxDim.z), 
							NxVec3(-boxDim.x,     -boxDim.y, boxDim.z),
							NxVec3(boxDim.x,      -boxDim.y, boxDim.z), 
							NxVec3(boxDim.x*0.5,  boxDim.y,  -boxDim.z*0.5), 
							NxVec3(-boxDim.x*0.5, boxDim.y,  -boxDim.z*0.5),
							NxVec3(-boxDim.x*0.5, boxDim.y,  boxDim.z*0.5), 
							NxVec3(boxDim.x*0.5,  boxDim.y,  boxDim.z*0.5)
						};


	// Create descriptor for convex mesh
	 if (!convexDesc)
	 {
		convexDesc = new  NxConvexMeshDesc();
		assert(convexDesc);
	 }

    convexDesc->numVertices			= 8;
    convexDesc->pointStrideBytes	= sizeof(NxVec3);
    convexDesc->points				= verts;
	convexDesc->flags				= NX_CF_COMPUTE_CONVEX;

	NxConvexShapeDesc convexShapeDesc;
	convexShapeDesc.localPose.t		= NxVec3(0, 2.0f, boxDim.z * 0.4);
	convexShapeDesc.userData		= convexDesc;
 
	NxInitCooking();
	// Cooking from memory
    MemoryWriteBuffer buf;
    bool status = NxCookConvexMesh(*convexDesc, buf);
	//
	// Please note about the created Convex Mesh, user needs to release it when no one uses it to save memory. It can be detected
	// by API "meshData->getReferenceCount() == 0". And, the release API is "gPhysicsSDK->releaseConvexMesh(*convexShapeDesc.meshData);"
	//
	NxConvexMesh *pMesh			= gPhysicsSDK->createConvexMesh(MemoryReadBuffer(buf.data));
	assert(pMesh);
    convexShapeDesc.meshData	= pMesh;
	NxCloseCooking();

    if (pMesh)
    {
        // Save mesh in userData for drawing.
		pMesh->saveToDesc(*convexDesc);
		//
		NxActorDesc actorDesc;
		assert(convexShapeDesc.isValid());
		actorDesc.shapes.pushBack(&convexShapeDesc);
		if (0 == flag)
		{	//Dynamic actor
			bodyDesc.flags	   |= NX_BF_DISABLE_GRAVITY;
			actorDesc.body		= &bodyDesc;
			actorDesc.density	= 1.0f;
		}
		else if (1 == flag)
		{	//Static actor
			actorDesc.body		= NULL;
			actorDesc.density	= 1.0f;
		}
		else if (2 == flag)
		{	// Kinematic actor
			bodyDesc.flags	   |= NX_BF_KINEMATIC;
			actorDesc.body		= &bodyDesc;
			actorDesc.density	= 1.0f;
		}

		actorDesc.globalPose.t  = pos; //NxVec3(6.5f, 0.0f, 0.0f);
		assert(actorDesc.isValid());
		NxActor* actor = gScene->createActor(actorDesc);
		assert(actor);	
		return actor;
    }

    return NULL;
}
void FPxScene::CreateLevel( ULevel* level )
{
	pxguard(FPxScene::CreateLevel);
	PX_LOG( PX_NAME, TEXT("%s >> %s ::"), PX_LOGP );

	if( !level )
	{
		PX_ERR( PX_NAME, TEXT("%s !! %s :: No level provided"), PX_LOGP );
		return;
	}

	if( mLevel )
	{
		PX_ERR( PX_NAME, TEXT("%s !! %s :: Level already loaded"), PX_LOGP );
		return;
	}

	mLevel = level;

	// Triangulate level mesh
	PX_LOG( PX_NAME, TEXT("%s .. %s :: Triangulating Level"), PX_LOGP );
	FPxTriangulator tor;
	tor.Triangulate(mLevel->Model);
	TArray<INT>& tris = tor.Triangles;
	TArray<NxVec3> verts;
	for( TArray<FVector>::TIterator it_point(tor.Points); it_point; ++it_point )
	{
		verts.AddItem( ToNVS(*it_point) );
	}

    // Build physical model
    NxTriangleMeshDesc levelDesc;
    levelDesc.numVertices = verts.Num();
    levelDesc.numTriangles = tris.Num() / 3;
    levelDesc.pointStrideBytes = sizeof(NxVec3);
    levelDesc.triangleStrideBytes = 3*sizeof(INT);
    levelDesc.points = verts.GetData();
    levelDesc.triangles = tris.GetData();
    levelDesc.flags = NX_MF_FLIPNORMALS;

    // Cooking
	PX_LOG( PX_NAME, TEXT("%s .. %s :: Cooking Level"), PX_LOGP );
    NxInitCooking();
    FPxMemWriteBuffer buf;
    bool status = NxCookTriangleMesh(levelDesc, buf);
    NxTriangleMeshShapeDesc levelShapeDesc;
    levelShapeDesc.meshData = GPxPhysics.GetSDK().createTriangleMesh(FPxMemReadBuffer(buf.data));
	NxCloseCooking();

	// Calc level bounding box
	NxVec3 bmin, bmax;
	NxComputeBounds( bmin, bmax, verts.Num(), static_cast<NxVec3*>(verts.GetData()) );
	mBounds.set(bmin,bmax);

	// Update scene limits
	mSceneLimits.maxNbActors = 1;
	mSceneLimits.maxNbBodies = 1;
	mSceneLimits.maxNbStaticShapes = 1;
	mSceneLimits.maxNbDynamicShapes = 0;
	mSceneLimits.maxNbJoints = 0;

	// Update scene descriptor
	mSceneDesc.limits = &mSceneLimits;
	mSceneDesc.maxBounds = &mBounds;
	mSceneDesc.upAxis = 1; // Y
	mSceneDesc.staticStructure = NX_PRUNING_STATIC_AABB_TREE;
	mSceneDesc.dynamicStructure = NX_PRUNING_NONE; //NX_PRUNING_DYNAMIC_AABB_TREE;
	
	// create scene
	if( !mScene )
	{
		CreateScene();
	}
	if( !mScene )
	{
		PX_ERR( PX_NAME, TEXT("%s !! %s :: Scene could not be created"), PX_LOGP );
		return;
	}

	// default material
	NxMaterial* defaultMaterial = mScene->getMaterialFromIndex(0); 
	defaultMaterial->setRestitution(0.1f);
	defaultMaterial->setStaticFriction(0.9f);
	defaultMaterial->setDynamicFriction(0.85f);

	// Create static level actor
	PX_LOG( PX_NAME, TEXT("%s .. %s :: Creating level mesh"), PX_LOGP );
    NxActorDesc actorDesc;
    actorDesc.shapes.pushBack(&levelShapeDesc);

	// Add level actor to the scene
	PX_LOG( PX_NAME, TEXT("%s .. %s :: Creating level actor"), PX_LOGP );
    NxActor* actor = mScene->createActor(actorDesc);
    actor->userData = (void*)level->GetLevelInfo();

	PX_LOG( PX_NAME, TEXT("%s << %s ::"), PX_LOGP );
	unguard;
}