plPXPhysical::~plPXPhysical() { SpamMsg(plSimulationMgr::Log("Destroying physical %s", GetKeyName().c_str())); if (fActor) { // Grab any mesh we may have (they need to be released manually) NxConvexMesh* convexMesh = nil; NxTriangleMesh* triMesh = nil; NxShape* shape = fActor->getShapes()[0]; if (NxConvexShape* convexShape = shape->isConvexMesh()) convexMesh = &convexShape->getConvexMesh(); else if (NxTriangleMeshShape* trimeshShape = shape->isTriangleMesh()) triMesh = &trimeshShape->getTriangleMesh(); if (!fActor->isDynamic()) plPXPhysicalControllerCore::RebuildCache(); if (fActor->isDynamic() && fActor->readBodyFlag(NX_BF_KINEMATIC)) { if (fGroup == plSimDefs::kGroupDynamic) fNumberAnimatedPhysicals--; else fNumberAnimatedActivators--; } // Release the actor NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey); scene->releaseActor(*fActor); fActor = nil; // Now that the actor is freed, release the mesh if (convexMesh) plSimulationMgr::GetInstance()->GetSDK()->releaseConvexMesh(*convexMesh); if (triMesh) plSimulationMgr::GetInstance()->GetSDK()->releaseTriangleMesh(*triMesh); // Release the scene, so it can be cleaned up if no one else is using it plSimulationMgr::GetInstance()->ReleaseScene(fWorldKey); } if (fWorldHull) delete [] fWorldHull; if (fSaveTriangles) delete [] fSaveTriangles; delete fProxyGen; // remove sdl modifier plSceneObject* sceneObj = plSceneObject::ConvertNoRef(fObjectKey->ObjectIsLoaded()); if (sceneObj && fSDLMod) { sceneObj->RemoveModifier(fSDLMod); } delete fSDLMod; }
void AddUserDataToShapes(NxActor* actor) { NxU32 i = 0; NxShape*const* shapes = actor->getShapes(); NxU32 nbShapes = actor->getNbShapes(); while (nbShapes--) { NxShape* shape = shapes[nbShapes]; shape->userData = new ShapeUserData; ShapeUserData* sud = (ShapeUserData*)(shape->userData); sud->id = i++; if (shape->getType() == NX_SHAPE_CONVEX) { sud->mesh = new NxConvexMeshDesc; shape->isConvexMesh()->getConvexMesh().saveToDesc(*(NxConvexMeshDesc*)sud->mesh); } if (shape->getType() == NX_SHAPE_MESH) { sud->mesh = new NxTriangleMeshDesc; shape->isTriangleMesh()->getTriangleMesh().saveToDesc(*(NxTriangleMeshDesc*)sud->mesh); } } }
// Make a visible object that can be viewed by users for debugging purposes. plDrawableSpans* plPXPhysical::CreateProxy(hsGMaterial* mat, hsTArray<uint32_t>& idx, plDrawableSpans* addTo) { plDrawableSpans* myDraw = addTo; hsMatrix44 l2w, unused; GetTransform(l2w, unused); bool blended = ((mat->GetLayer(0)->GetBlendFlags() & hsGMatState::kBlendMask)); NxShape* shape = fActor->getShapes()[0]; NxTriangleMeshShape* trimeshShape = shape->isTriangleMesh(); if (trimeshShape) { NxTriangleMeshDesc desc; trimeshShape->getTriangleMesh().saveToDesc(desc); hsTArray<hsPoint3> pos; hsTArray<uint16_t> tris; const int kMaxTris = 10000; const int kMaxVerts = 32000; if ((desc.numVertices < kMaxVerts) && (desc.numTriangles < kMaxTris)) { pos.SetCount(desc.numVertices); tris.SetCount(desc.numTriangles * 3); for (int i = 0; i < desc.numVertices; i++ ) pos[i] = GetTrimeshVert(desc, i); for (int i = 0; i < desc.numTriangles; i++) GetTrimeshTri(desc, i, &tris[i*3]); myDraw = plDrawableGenerator::GenerateDrawable(pos.GetCount(), pos.AcquireArray(), nil, // normals - def to avg (smooth) norm nil, // uvws 0, // uvws per vertex nil, // colors - def to white true, // do a quick fake shade nil, // optional color modulation tris.GetCount(), tris.AcquireArray(), mat, l2w, blended, &idx, myDraw); } else { int curTri = 0; int trisToDo = desc.numTriangles; while (trisToDo > 0) { int trisThisRound = trisToDo > kMaxTris ? kMaxTris : trisToDo; trisToDo -= trisThisRound; pos.SetCount(trisThisRound * 3); tris.SetCount(trisThisRound * 3); for (int i = 0; i < trisThisRound; i++) { GetTrimeshTri(desc, curTri, &tris[i*3]); pos[i*3 + 0] = GetTrimeshVert(desc, tris[i*3+0]); pos[i*3 + 1] = GetTrimeshVert(desc, tris[i*3+1]); pos[i*3 + 2] = GetTrimeshVert(desc, tris[i*3+2]); curTri++; } myDraw = plDrawableGenerator::GenerateDrawable(pos.GetCount(), pos.AcquireArray(), nil, // normals - def to avg (smooth) norm nil, // uvws 0, // uvws per vertex nil, // colors - def to white true, // do a quick fake shade nil, // optional color modulation tris.GetCount(), tris.AcquireArray(), mat, l2w, blended, &idx, myDraw); } } } NxConvexShape* convexShape = shape->isConvexMesh(); if (convexShape) { NxConvexMeshDesc desc; convexShape->getConvexMesh().saveToDesc(desc); hsTArray<hsPoint3> pos; hsTArray<uint16_t> tris; pos.SetCount(desc.numVertices); tris.SetCount(desc.numTriangles * 3); for (int i = 0; i < desc.numVertices; i++ ) pos[i] = GetConvexVert(desc, i); for (int i = 0; i < desc.numTriangles; i++) GetConvexTri(desc, i, &tris[i*3]); myDraw = plDrawableGenerator::GenerateDrawable(pos.GetCount(), pos.AcquireArray(), nil, // normals - def to avg (smooth) norm nil, // uvws 0, // uvws per vertex nil, // colors - def to white true, // do a quick fake shade nil, // optional color modulation tris.GetCount(), tris.AcquireArray(), mat, l2w, blended, &idx, myDraw); } NxSphereShape* sphere = shape->isSphere(); if (sphere) { float radius = sphere->getRadius(); hsPoint3 offset = plPXConvert::Point(sphere->getLocalPosition()); myDraw = plDrawableGenerator::GenerateSphericalDrawable(offset, radius, mat, l2w, blended, nil, &idx, myDraw); } NxBoxShape* box = shape->isBox(); if (box) { hsPoint3 dim = plPXConvert::Point(box->getDimensions()); myDraw = plDrawableGenerator::GenerateBoxDrawable(dim.fX*2.f, dim.fY*2.f, dim.fZ*2.f, mat,l2w,blended, nil,&idx,myDraw); } return myDraw; }
void plPXPhysical::Write(hsStream* stream, hsResMgr* mgr) { plPhysical::Write(stream, mgr); hsAssert(fActor, "nil actor"); hsAssert(fActor->getNbShapes() == 1, "Can only write actors with one shape. Writing first only."); NxShape* shape = fActor->getShapes()[0]; NxMaterialIndex matIdx = shape->getMaterial(); NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey); NxMaterial* mat = scene->getMaterialFromIndex(matIdx); float friction = mat->getStaticFriction(); float restitution = mat->getRestitution(); stream->WriteLEScalar(fActor->getMass()); stream->WriteLEScalar(friction); stream->WriteLEScalar(restitution); stream->WriteByte(fBoundsType); stream->WriteByte(fGroup); stream->WriteLE32(fReportsOn); stream->WriteLE16(fLOSDBs); mgr->WriteKey(stream, fObjectKey); mgr->WriteKey(stream, fSceneNode); mgr->WriteKey(stream, fWorldKey); mgr->WriteKey(stream, fSndGroup); hsPoint3 pos; hsQuat rot; IGetPositionSim(pos); IGetRotationSim(rot); pos.Write(stream); rot.Write(stream); fProps.Write(stream); if (fBoundsType == plSimDefs::kSphereBounds) { const NxSphereShape* sphereShape = shape->isSphere(); stream->WriteLEScalar(sphereShape->getRadius()); hsPoint3 localPos = plPXConvert::Point(sphereShape->getLocalPosition()); localPos.Write(stream); } else if (fBoundsType == plSimDefs::kBoxBounds) { const NxBoxShape* boxShape = shape->isBox(); hsPoint3 dim = plPXConvert::Point(boxShape->getDimensions()); dim.Write(stream); hsPoint3 localPos = plPXConvert::Point(boxShape->getLocalPosition()); localPos.Write(stream); } else { if (fBoundsType == plSimDefs::kHullBounds) hsAssert(shape->isConvexMesh(), "Hull shape isn't a convex mesh"); else hsAssert(shape->isTriangleMesh(), "Exact shape isn't a trimesh"); // We hide the stream we used to create this mesh away in the shape user data. // Pull it out and write it to disk. hsVectorStream* vecStream = (hsVectorStream*)shape->userData; stream->Write(vecStream->GetEOF(), vecStream->GetData()); delete vecStream; } }
void CPhysicsActor::AddVisualization() { // get the CPhysicsObject's name PHYSICSUSERDATA* userData = (PHYSICSUSERDATA*)m_Actor->userData; if( userData == NULL ) return; CPhysicsObject* physObj = userData->physObj; IHashString* cpoName = physObj->GetParentName(); // Loop through shapes in the actor unsigned int numShapes = m_Actor->getNbShapes(); NxShape*const* shapes = m_Actor->getShapes(); NxShape* shape; // we need to unscale before feeding it to the shape objects since they // get the scale from the parent Vec3 invScale; invScale.x = 1.0f / m_CurrentScale.x; invScale.y = 1.0f / m_CurrentScale.y; invScale.z = 1.0f / m_CurrentScale.z; // Add visualizations for each shape while( numShapes-- ) { shape = shapes[numShapes]; // Add shape to be rendered if( shape->isBox() ) { NxBoxShape* boxShape = (NxBoxShape*)shape; Matrix4x4 localTransform; localTransform.SetIdentity(); float tempRot[9]; boxShape->getLocalOrientation().getColumnMajor( tempRot ); localTransform.SetFrom3x3( tempRot ); NxVec3 tempPos = boxShape->getLocalPosition(); tempPos.x *= invScale.x; tempPos.y *= invScale.y; tempPos.z *= invScale.z; localTransform.SetTranslation( Vec3(tempPos.x, tempPos.y, tempPos.z) ); NxVec3 boxDimensions = boxShape->getDimensions(); float halfXDimension = boxDimensions.x * invScale.x; float halfYDimension = boxDimensions.y * invScale.y; float halfZDimension = boxDimensions.z * invScale.z; // Add a debug render object to visualize the object ADDOBJECTORIENTEDBOXPARAMS oobbParams; oobbParams.name = cpoName; oobbParams.min = Vec3( -halfXDimension, -halfYDimension, -halfZDimension ); oobbParams.max = Vec3( halfXDimension, halfYDimension, halfZDimension ); oobbParams.localTransform = localTransform; static DWORD msgHash_AddObjectOrientedBox = CHashString(_T("AddObjectOrientedBox")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_AddObjectOrientedBox, sizeof(ADDOBJECTORIENTEDBOXPARAMS), &oobbParams ); } if( shape->isSphere() ) { NxSphereShape* sphereShape = (NxSphereShape*)shape; float radius = sphereShape->getRadius(); // Add a debug render object to visualize the object ADDSPHEREPARAMS sphereParams; sphereParams.name = cpoName; sphereParams.radius = radius * invScale.x; sphereParams.red = 0; sphereParams.green = 255; // making the sphere green to distinguish it from AABBs sphereParams.blue = 0; static DWORD msgHash_AddSphere = CHashString(_T("AddSphere")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_AddSphere, sizeof(ADDSPHEREPARAMS), &sphereParams ); } if( shape->isCapsule() ) { // Draw as a red box for now NxCapsuleShape* capsuleShape = (NxCapsuleShape*)shape; Matrix4x4 localTransform; localTransform.SetIdentity(); float tempRot[9]; capsuleShape->getLocalOrientation().getColumnMajor( tempRot ); localTransform.SetFrom3x3( tempRot ); NxVec3 tempPos = capsuleShape->getLocalPosition(); tempPos.x *= invScale.x; tempPos.y *= invScale.y; tempPos.z *= invScale.z; localTransform.SetTranslation( Vec3(tempPos.x, tempPos.y, tempPos.z) ); float halfXDimension = capsuleShape->getRadius(); float halfYDimension = capsuleShape->getHeight() - capsuleShape->getRadius(); float halfZDimension = capsuleShape->getRadius(); // Add a debug render object to visualize the object ADDOBJECTORIENTEDBOXPARAMS oobbParams; oobbParams.name = cpoName; oobbParams.min = Vec3( -halfXDimension, -halfYDimension, -halfZDimension ); oobbParams.max = Vec3( halfXDimension, halfYDimension, halfZDimension ); oobbParams.localTransform = localTransform; oobbParams.red = 255; oobbParams.green = 0; oobbParams.blue = 0; static DWORD msgHash_AddObjectOrientedBox = CHashString(_T("AddObjectOrientedBox")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_AddObjectOrientedBox, sizeof(ADDOBJECTORIENTEDBOXPARAMS), &oobbParams ); } if( shape->isConvexMesh() ) { // not yet implemented } } }