// 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; }
int pWorld::overlapOBBShapes(const VxBbox& worldBounds, CK3dEntity*shapeReference, pShapesType shapeType,CKGroup *shapes,int activeGroups/* =0xffffffff */, const pGroupsMask* groupsMask/* =NULL */, bool accurateCollision/* =false */) { int result=0; NxBox box; if (shapeReference) { NxShape *shape = getShapeByEntityID(shapeReference->GetID()); if (shape) { //shape->checkOverlapAABB() NxBoxShape*boxShape = static_cast<NxBoxShape*>(shape->isBox()); if (boxShape) { boxShape->getWorldOBB(box); } } }else{ box.center = getFrom(worldBounds.GetCenter()); box.extents = getFrom(worldBounds.GetSize()); } int total = 0; if (shapeType & ST_Dynamic ) { total+=getScene()->getNbDynamicShapes(); } if (shapeType & ST_Static) { total+=getScene()->getNbStaticShapes(); } NxShape** _shapes = (NxShape**)NxAlloca(total*sizeof(NxShape*)); for (NxU32 i = 0; i < total; i++) _shapes[i] = NULL; NxGroupsMask mask; if (groupsMask) { mask.bits0 = groupsMask->bits0; mask.bits1 = groupsMask->bits1; mask.bits2 = groupsMask->bits2; mask.bits3 = groupsMask->bits3; }else{ mask.bits0 = 0; mask.bits1 = 0; mask.bits2 = 0; mask.bits3 = 0; } result = getScene()->overlapOBBShapes(box,(NxShapesType)shapeType,total,_shapes,NULL,activeGroups,&mask,accurateCollision); if (_shapes && shapes ) { for (int i = 0 ; i < result ; i++) { NxShape *s = _shapes[i]; if (s) { const char* name =s->getName(); pSubMeshInfo *sInfo = static_cast<pSubMeshInfo*>(s->userData); if (sInfo->entID) { CKObject *obj = (CKObject*)GetPMan()->m_Context->GetObject(sInfo->entID); if (obj) { shapes->AddObject((CKBeObject*)obj); } } } } } int op=2; return result; }
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 } } }