pRigidBody*pFactory::createRigidBody(CK3dEntity *referenceObject,pObjectDescr& oDescr) { CK3dEntity *worldReferenceObject = (CK3dEntity*)GetPMan()->GetContext()->GetObject(oDescr.worlReference); pWorld *world=getManager()->getWorld(worldReferenceObject,referenceObject); if (!world) { xLogger::xLog(XL_START,ELOGWARNING,E_LI_MANAGER,"world object invalid, setting to default world"); world = GetPMan()->getDefaultWorld(); } pRigidBody*result = world->getBody(referenceObject); // create minimum object result = createBody(referenceObject,worldReferenceObject); if (!result) { xLogger::xLog(XL_START,ELOGERROR,E_LI_MANAGER,"failed"); return NULL; } result->setWorld(world); result->setFlags(oDescr.flags); result->setHullType(oDescr.hullType); if (oDescr.density <= 0.001f) oDescr.density = 1.0f; if (oDescr.skinWidth <= 0.001f) oDescr.skinWidth = 0.025f; result->setDensity(oDescr.density); bool hierarchy = (oDescr.flags & BF_Hierarchy); bool isDeformable = oDescr.flags & BF_Deformable; bool trigger = oDescr.flags & BF_TriggerShape; //################################################################ // // Deformable ? // pCloth *cloth = NULL; pClothDesc cDescr; if (isDeformable) { xLogger::xLog(XL_START,ELOGERROR,E_LI_MANAGER,"deformable feature disabled in this release"); return NULL; cDescr.setToDefault(); cDescr.worldReference = worldReferenceObject->GetID(); if ( result->getFlags() & BF_Gravity ) { cDescr.flags |= PCF_Gravity; } if ( result->getFlags() & BF_Collision ) { } if (!cloth) { cloth = pFactory::Instance()->createCloth(referenceObject,cDescr); if (!cloth) { xLogger::xLog(XL_START,ELOGERROR,E_LI_MANAGER,"Cannot create cloth : factory object failed !"); } } } float density = oDescr.density; VxVector box_s= BoxGetZero(referenceObject); VxMatrix v_matrix ; VxVector position,scale; VxQuaternion quat; v_matrix = referenceObject->GetWorldMatrix(); Vx3DDecomposeMatrix(v_matrix,quat,position,scale); NxVec3 pos = pMath::getFrom(position); NxQuat rot = pMath::getFrom(quat); //---------------------------------------------------------------- // // Fill NxActorDescr // NxActorDesc actorDesc;actorDesc.setToDefault(); NxBodyDesc bodyDesc;bodyDesc.setToDefault(); // // Fix parameters to default values actorDesc.density = oDescr.density; //skin width if (oDescr.skinWidth<=0.0001f) oDescr.skinWidth=0.025f; float radius = result->GetVT3DObject()->GetRadius(); //---------------------------------------------------------------- // // Create the physic mesh. Externalizing this procedure will corrupt the // actor description object. // switch(oDescr.hullType) { ////////////////////////////////////////////////////////////////////////// case HT_Box: { NxBoxShapeDesc shape; if (! (oDescr.flags & BF_Deformable) ) { shape.dimensions = pMath::getFrom(box_s)*0.5f; } shape.density = density; shape.skinWidth = oDescr.skinWidth; actorDesc.shapes.pushBack(&shape); break; } ////////////////////////////////////////////////////////////////////////// case HT_Sphere: { NxSphereShapeDesc shape; if (! (oDescr.flags & BF_Deformable) ) { shape.radius = radius; } shape.density = density; shape.skinWidth = oDescr.skinWidth; actorDesc.shapes.pushBack(&shape); break; } ////////////////////////////////////////////////////////////////////////// case HT_Mesh: { NxTriangleMeshDesc myMesh; myMesh.setToDefault(); pFactory::Instance()->createMesh(result->getWorld()->getScene(),result->GetVT3DObject()->GetCurrentMesh(),myMesh); NxTriangleMeshShapeDesc shape; bool status = InitCooking(); if (!status) { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Couldn't initiate cooking lib!"); return false; } MemoryWriteBuffer buf; status = CookTriangleMesh(myMesh, buf); if (!status) { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Couldn't cook mesh!"); return false; } shape.meshData = GetPMan()->getPhysicsSDK()->createTriangleMesh(MemoryReadBuffer(buf.data)); shape.density = density; shape.group = oDescr.collisionGroup; actorDesc.shapes.pushBack(&shape); shape.skinWidth = oDescr.skinWidth; CloseCooking(); if (myMesh.points) { delete [] myMesh.points; } if (myMesh.triangles) { delete []myMesh.triangles; } break; } ////////////////////////////////////////////////////////////////////////// case HT_ConvexMesh: { if (result->GetVT3DObject()->GetCurrentMesh()) { if (result->GetVT3DObject()->GetCurrentMesh()->GetVertexCount()>=256 ) { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Only 256 vertices for convex meshes allowed, by Ageia!"); return false; } }else { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Object has no mesh!"); return false; } NxConvexMeshDesc myMesh; myMesh.setToDefault(); pFactory::Instance()->createConvexMesh(result->getWorld()->getScene(),result->GetVT3DObject()->GetCurrentMesh(),myMesh); NxConvexShapeDesc shape; bool status = InitCooking(); if (!status) { xLogger::xLog(XL_START,ELOGERROR,E_LI_AGEIA,"Couldn't initiate cooking lib!"); return false; } MemoryWriteBuffer buf; status = CookConvexMesh(myMesh, buf); if (!status) { xLogger::xLog(XL_START,ELOGERROR,E_LI_AGEIA,"Couldn't cook convex mesh!"); return false; } shape.meshData = GetPMan()->getPhysicsSDK()->createConvexMesh(MemoryReadBuffer(buf.data)); shape.density = density; actorDesc.shapes.pushBack(&shape); if (oDescr.skinWidth!=-1.0f) shape.skinWidth = oDescr.skinWidth; int h = shape.isValid(); CloseCooking(); if (myMesh.points) { delete [] myMesh.points; } if (myMesh.triangles) { delete []myMesh.triangles; } break; } ////////////////////////////////////////////////////////////////////////// case HT_ConvexCylinder: { NxConvexShapeDesc shape; pConvexCylinderSettings &cSettings = oDescr.convexCylinder; iAssertW( (oDescr.mask & OD_ConvexCylinder),pFactory::Instance()->findSettings(cSettings,result->GetVT3DObject()), "Hull type has been set to convex cylinder but there is no descriptions passed or activated in the pObjectDescr::mask.Trying object attributes...."); if (cSettings.radius.reference) cSettings.radius.evaluate(cSettings.radius.reference); if (cSettings.height.reference) cSettings.height.evaluate(cSettings.height.reference); iAssertW( cSettings.isValid() , cSettings.setToDefault(),""); cSettings.radius.value = cSettings.radius.value > 0.0f ? (cSettings.radius.value*0.5) : (box_s.v[cSettings.radius.referenceAxis] * 0.5f); cSettings.height.value = cSettings.height.value > 0.0f ? cSettings.height.value : (box_s.v[cSettings.height.referenceAxis] * 0.5f); bool resultAssert = true; iAssertWR( pFactory::Instance()->_createConvexCylinderMesh(&shape,cSettings,result->GetVT3DObject()),"",resultAssert); shape.density = density; shape.skinWidth = oDescr.skinWidth; actorDesc.shapes.pushBack(&shape); break; } ////////////////////////////////////////////////////////////////////////// case HT_Capsule: { NxCapsuleShapeDesc shape; pCapsuleSettingsEx &cSettings = oDescr.capsule; if (!( oDescr.mask & OD_Capsule) ) { // try over attribute : pFactory::Instance()->findSettings(cSettings,result->GetVT3DObject()); } bool resultAssert = true; if (cSettings.radius.reference) cSettings.radius.evaluate(cSettings.radius.reference); if (cSettings.height.reference) cSettings.height.evaluate(cSettings.height.reference); iAssertWR(cSettings.isValid(),cSettings.setToDefault(),resultAssert); shape.radius = cSettings.radius.value > 0.0f ? (cSettings.radius.value*0.5) : (box_s.v[cSettings.radius.referenceAxis] * 0.5f); shape.height = cSettings.height.value > 0.0f ? (cSettings.height.value-( 2*shape.radius)) : (box_s.v[cSettings.height.referenceAxis] - ( 2*shape.radius)) ; shape.density = density; shape.skinWidth = oDescr.skinWidth; actorDesc.shapes.pushBack(&shape); break; } case HT_Wheel: { xLogger::xLog(XL_START,ELOGERROR,E_LI_AGEIA,"Wheel shape can be sub shape only!"); return false; } } if ( !isDeformable) { actorDesc.globalPose.t = pos; actorDesc.globalPose.M = rot; } //---------------------------------------------------------------- // // Create the final NxActor // if (oDescr.flags & BF_Moving) actorDesc.body = &bodyDesc; NxActor *actor = world->getScene()->createActor(actorDesc); if (!actor) { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Couldn't create actor"); delete result; return NULL; } //---------------------------------------------------------------- // // // result->setActor(actor); actor->setName(referenceObject->GetName()); result->SetVT3DObject(referenceObject); actor->userData= result; ////////////////////////////////////////////////////////////////////////// //Deformable : if (isDeformable && cloth) { pDeformableSettings dSettings; dSettings.ImpulsThresold = 50.0f; dSettings.PenetrationDepth= 0.1f ; dSettings.MaxDeform = 2.0f; CKParameterOut *poutDS = referenceObject->GetAttributeParameter(GetPMan()->att_deformable); if (poutDS) { pFactory::Instance()->copyTo(dSettings,poutDS); } cloth->attachToCore(referenceObject,dSettings.ImpulsThresold,dSettings.PenetrationDepth,dSettings.MaxDeform); result->setCloth(cloth); } ////////////////////////////////////////////////////////////////////////// // // Extra settings : // if (result->getFlags() & BF_Moving) { VxVector massOffsetOut;referenceObject->Transform(&massOffsetOut,&oDescr.massOffsetLinear); actor->setCMassOffsetGlobalPosition(pMath::getFrom(massOffsetOut)); } if (result->getFlags() & BF_Kinematic) { result->setKinematic(true); } if (result->getFlags() & BF_Moving ) { result->enableGravity(result->getFlags() & BF_Gravity); } if (result->getFlags() & BF_Sleep ) { result->setSleeping(true); } if (oDescr.worlReference == 0) { if (GetPMan()->getDefaultWorld()) { oDescr.worlReference = GetPMan()->getDefaultWorld()->getReference()->GetID(); } } //---------------------------------------------------------------- // // store mesh meta info in the first main mesh // NxShape *shape = result->getShapeByIndex(); if (shape) { pSubMeshInfo *sInfo = new pSubMeshInfo(); sInfo->entID = referenceObject->GetID(); sInfo->refObject = (CKBeObject*)referenceObject; shape->userData = (void*)sInfo; result->setMainShape(shape); shape->setName(referenceObject->GetName()); } result->enableCollision( (result->getFlags() & BF_Collision), referenceObject ); //---------------------------------------------------------------- // // Adjust pivot // if ( (oDescr.mask & OD_Pivot) ) { iAssertW1( oDescr.pivot.isValid(),oDescr.pivot.setToDefault()); result->updatePivotSettings(oDescr.pivot,referenceObject); }else if(pFactory::Instance()->findSettings(oDescr.collision,referenceObject)) result->updatePivotSettings(oDescr.pivot,referenceObject); //---------------------------------------------------------------- // // Optimization // if ((oDescr.mask & OD_Optimization )) { iAssertW1( oDescr.optimization.isValid(),oDescr.optimization.setToDefault()); result->updateOptimizationSettings(oDescr.optimization); } else{ if(pFactory::Instance()->findSettings(oDescr.optimization,referenceObject)) { iAssertW1( oDescr.optimization.isValid(),oDescr.optimization.setToDefault()); result->updateOptimizationSettings(oDescr.optimization); } } //---------------------------------------------------------------- // // Collision // if ((oDescr.mask & OD_Collision)) result->updateCollisionSettings(oDescr.collision,referenceObject); else if(pFactory::Instance()->findSettings(oDescr.collision,referenceObject)) result->updateCollisionSettings(oDescr.collision,referenceObject); //---------------------------------------------------------------- // // Material // NxMaterialDesc *materialDescr = NULL; NxMaterial *material = NULL; pMaterial &bMaterial = oDescr.material; if (oDescr.mask & OD_Material) { result->updateMaterialSettings(bMaterial,referenceObject); }else { bool hasMaterial = pFactory::Instance()->findSettings(bMaterial,referenceObject); if (!hasMaterial) { if (world->getDefaultMaterial()) { int z = (int)world->getDefaultMaterial()->userData; shape->setMaterial(world->getDefaultMaterial()->getMaterialIndex()); } }else{ iAssertW( bMaterial.isValid(),bMaterial.setToDefault(), "Material settings were still invalid : "); NxMaterialDesc nxMatDescr; pFactory::Instance()->copyTo(nxMatDescr,bMaterial); NxMaterial *nxMaterial = world->getScene()->createMaterial(nxMatDescr); if (nxMaterial) { shape->setMaterial(nxMaterial->getMaterialIndex()); } } } xLogger::xLog(ELOGINFO,E_LI_MANAGER,"Rigid body creation successful : %s",referenceObject->GetName()); result->setInitialDescription(&oDescr); //---------------------------------------------------------------- // // Hierarchy mode fix : // if ( (oDescr.flags & BF_Hierarchy) ) oDescr.hirarchy = true; if ( oDescr.hirarchy ) oDescr.flags << BF_Hierarchy; if ( (!oDescr.hirarchy) || !(oDescr.flags & BF_Hierarchy) ) return result; //---------------------------------------------------------------- // // Parse hirarchy // CK3dEntity* subEntity = NULL; while (subEntity= referenceObject->HierarchyParser(subEntity) ) { pObjectDescr *subDescr = NULL; int attTypePBSetup = GetPMan()->getAttributeTypeByGuid(VTS_PHYSIC_ACTOR); if (subEntity->HasAttribute(attTypePBSetup)) { subDescr = new pObjectDescr(); CKParameterOut *par = subEntity->GetAttributeParameter(attTypePBSetup); IParameter::Instance()->copyTo(subDescr,par); subDescr->version = pObjectDescr::E_OD_VERSION::OD_DECR_V1; } if (!subDescr) continue; if (subDescr->flags & BF_SubShape) { ////////////////////////////////////////////////////////////////////////// // // Regular Mesh : // if (subDescr->hullType != HT_Cloth) { //result->addSubShape(NULL,*subDescr,subEntity); VxQuaternion refQuad;subEntity->GetQuaternion(&refQuad,referenceObject); VxVector relPos;subEntity->GetPosition(&relPos,referenceObject); shape = pFactory::Instance()->createShape(referenceObject,*subDescr,subEntity,subEntity->GetCurrentMesh(),relPos,refQuad); //NxShape *shape = result->getSubShape(subEntity); if (shape) { //---------------------------------------------------------------- // // check for collision setup // //try to get get from child attributes first /* if(pFactory::Instance()->findSettings(subDescr->collision,subEntity)) { result->updateCollisionSettings(subDescr->collision,subEntity); continue; } if ( (subDescr->mask & OD_Optimization) ) { //if (pFactory::Instance()->findSettings(subDescr->collision,subEntity)) result->updateCollisionSettings(subDescr->collision,subEntity); } else if ( (oDescr.mask & OD_Optimization) ) { result->updateCollisionSettings(oDescr.collision,subEntity); }else if(pFactory::Instance()->findSettings(subDescr->collision,subEntity)) { result->updateCollisionSettings(subDescr->collision,subEntity); } */ } } ////////////////////////////////////////////////////////////////////////// // // Cloth Mesh : // if (subDescr->hullType == HT_Cloth) { //pClothDesc *cloth = pFactory::Instance()->createPObjectDescrFromParameter(subEntity->GetAttributeParameter(GetPMan()->GetPAttribute())); } } } //---------------------------------------------------------------- // // Adjust mass // //---------------------------------------------------------------- // // Collision // if ((oDescr.mask & OD_Mass)) result->updateMassSettings(oDescr.mass); else if(pFactory::Instance()->findSettings(oDescr.mass,referenceObject)) result->updateMassSettings(oDescr.mass); return result; nothing: return result; }
bool plPXPhysical::Init(PhysRecipe& recipe) { bool startAsleep = false; fBoundsType = recipe.bounds; fGroup = recipe.group; fReportsOn = recipe.reportsOn; fObjectKey = recipe.objectKey; fSceneNode = recipe.sceneNode; fWorldKey = recipe.worldKey; NxActorDesc actorDesc; NxSphereShapeDesc sphereDesc; NxConvexShapeDesc convexShapeDesc; NxTriangleMeshShapeDesc trimeshShapeDesc; NxBoxShapeDesc boxDesc; plPXConvert::Matrix(recipe.l2s, actorDesc.globalPose); switch (fBoundsType) { case plSimDefs::kSphereBounds: { hsMatrix44 sphereL2W; sphereL2W.Reset(); sphereL2W.SetTranslate(&recipe.offset); sphereDesc.radius = recipe.radius; plPXConvert::Matrix(sphereL2W, sphereDesc.localPose); sphereDesc.group = fGroup; actorDesc.shapes.pushBack(&sphereDesc); } break; case plSimDefs::kHullBounds: // FIXME PHYSX - Remove when hull detection is fixed // If this is read time (ie, meshStream is nil), turn the convex hull // into a box. That way the data won't have to change when convex hulls // actually work right. if (fGroup == plSimDefs::kGroupDetector && recipe.meshStream == nil) { #ifdef USE_BOXES_FOR_DETECTOR_HULLS MakeBoxFromHull(recipe.convexMesh, boxDesc); plSimulationMgr::GetInstance()->GetSDK()->releaseConvexMesh(*recipe.convexMesh); boxDesc.group = fGroup; actorDesc.shapes.push_back(&boxDesc); #else #ifdef USE_PHYSX_CONVEXHULL_WORKAROUND // make a hull of planes for testing IsInside IMakeHull(recipe.convexMesh,recipe.l2s); #endif // USE_PHYSX_CONVEXHULL_WORKAROUND convexShapeDesc.meshData = recipe.convexMesh; convexShapeDesc.userData = recipe.meshStream; convexShapeDesc.group = fGroup; actorDesc.shapes.pushBack(&convexShapeDesc); #endif // USE_BOXES_FOR_DETECTOR_HULLS } else { convexShapeDesc.meshData = recipe.convexMesh; convexShapeDesc.userData = recipe.meshStream; convexShapeDesc.group = fGroup; actorDesc.shapes.pushBack(&convexShapeDesc); } break; case plSimDefs::kBoxBounds: { boxDesc.dimensions = plPXConvert::Point(recipe.bDimensions); hsMatrix44 boxL2W; boxL2W.Reset(); boxL2W.SetTranslate(&recipe.bOffset); plPXConvert::Matrix(boxL2W, boxDesc.localPose); boxDesc.group = fGroup; actorDesc.shapes.push_back(&boxDesc); } break; case plSimDefs::kExplicitBounds: case plSimDefs::kProxyBounds: if (fGroup == plSimDefs::kGroupDetector) { SimLog("Someone using an Exact on a detector region: %s", GetKeyName().c_str()); } trimeshShapeDesc.meshData = recipe.triMesh; trimeshShapeDesc.userData = recipe.meshStream; trimeshShapeDesc.group = fGroup; actorDesc.shapes.pushBack(&trimeshShapeDesc); break; default: hsAssert(false, "Unknown geometry type during read."); return false; break; } // Now fill out the body, or dynamic part of the physical NxBodyDesc bodyDesc; fMass = recipe.mass; if (recipe.mass != 0) { bodyDesc.mass = recipe.mass; actorDesc.body = &bodyDesc; if (GetProperty(plSimulationInterface::kPinned)) { bodyDesc.flags |= NX_BF_FROZEN; startAsleep = true; // put it to sleep if they are going to be frozen } if (fGroup != plSimDefs::kGroupDynamic || GetProperty(plSimulationInterface::kPhysAnim)) { SetProperty(plSimulationInterface::kPassive, true); // Even though the code for animated physicals and animated activators are the same // keep these code snippets separated for fine tuning. Thanks. if (fGroup == plSimDefs::kGroupDynamic) { // handle the animated physicals.... make kinematic for now. fNumberAnimatedPhysicals++; bodyDesc.flags |= NX_BF_KINEMATIC; startAsleep = true; } else { // handle the animated activators.... fNumberAnimatedActivators++; bodyDesc.flags |= NX_BF_KINEMATIC; startAsleep = true; } } } else { if ( GetProperty(plSimulationInterface::kPhysAnim) ) SimLog("An animated physical that has no mass: %s", GetKeyName().c_str()); } actorDesc.userData = this; actorDesc.name = GetKeyName().c_str(); // Put the dynamics into actor group 1. The actor groups are only used for // deciding who we get contact reports for. if (fGroup == plSimDefs::kGroupDynamic) actorDesc.group = 1; NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey); try { fActor = scene->createActor(actorDesc); } catch (...) { hsAssert(false, "Actor creation crashed"); return false; } hsAssert(fActor, "Actor creation failed"); if (!fActor) return false; NxShape* shape = fActor->getShapes()[0]; shape->setMaterial(plSimulationMgr::GetInstance()->GetMaterialIdx(scene, recipe.friction, recipe.restitution)); // Turn on the trigger flags for any detectors. // // Normally, we'd set these flags on the shape before it's created. However, // in the case where the detector is going to be animated, it'll have a rigid // body too, and that will cause problems at creation. According to Ageia, // a detector shape doesn't actually count as a shape, so the SDK will have // problems trying to calculate an intertial tensor. By letting it be // created as a normal dynamic first, then setting the flags, we work around // that problem. if (fGroup == plSimDefs::kGroupDetector) { shape->setFlag(NX_TRIGGER_ON_ENTER, true); shape->setFlag(NX_TRIGGER_ON_LEAVE, true); } if (GetProperty(plSimulationInterface::kStartInactive) || startAsleep) { if (!fActor->isSleeping()) { if (plSimulationMgr::fExtraProfile) SimLog("Deactivating %s in SetPositionAndRotationSim", GetKeyName().c_str()); fActor->putToSleep(); } } if (GetProperty(plSimulationInterface::kDisable)) IEnable(false); if (GetProperty(plSimulationInterface::kSuppressed_DEAD)) IEnable(false); plNodeRefMsg* refMsg = new plNodeRefMsg(fSceneNode, plRefMsg::kOnCreate, -1, plNodeRefMsg::kPhysical); hsgResMgr::ResMgr()->AddViaNotify(GetKey(), refMsg, plRefFlags::kActiveRef); if (fWorldKey) { plGenRefMsg* ref = new plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPhysRefWorld); hsgResMgr::ResMgr()->AddViaNotify(fWorldKey, ref, plRefFlags::kActiveRef); } // only dynamic physicals without noSync need SDLs if ( fGroup == plSimDefs::kGroupDynamic && !fProps.IsBitSet(plSimulationInterface::kNoSynchronize) ) { // add SDL modifier plSceneObject* sceneObj = plSceneObject::ConvertNoRef(fObjectKey->ObjectIsLoaded()); hsAssert(sceneObj, "nil sceneObject, failed to create and attach SDL modifier"); delete fSDLMod; fSDLMod = new plPhysicalSDLModifier; sceneObj->AddModifier(fSDLMod); } return true; }
pRigidBody*pFactory::createRigidBodyFull(CK3dEntity *referenceObject, CK3dEntity *worldReferenceObject) { //################################################################ // // Sanity checks // pWorld *world=getManager()->getWorld(worldReferenceObject,referenceObject); pRigidBody*result = world->getBody(referenceObject); if(result) { result->destroy(); delete result; result = NULL; } //################################################################ // // Construct the result // result = createBody(referenceObject,worldReferenceObject); if (result) { result->setWorld(world); //---------------------------------------------------------------- // // Handle different attribute types (Object or pBSetup) // int attTypeOld = GetPMan()->GetPAttribute(); int attTypeNew = GetPMan()->getAttributeTypeByGuid(VTS_PHYSIC_ACTOR); pObjectDescr *oDescr = NULL; //---------------------------------------------------------------- // // the old way : // if (referenceObject->HasAttribute(attTypeOld)) { result->retrieveSettingsFromAttribute(); oDescr = pFactory::Instance()->createPObjectDescrFromParameter(referenceObject->GetAttributeParameter(GetPMan()->GetPAttribute())); } bool hierarchy = result->getFlags() & BF_Hierarchy; bool isDeformable = result->getFlags() & BF_Deformable; bool trigger = (result->getFlags() & BF_TriggerShape); //---------------------------------------------------------------- // // the new way // if (referenceObject->HasAttribute(attTypeNew)) { oDescr = new pObjectDescr(); } result->checkDataFlags(); /* pObjectDescr *oDescr = if (!oDescr) return result; */ //################################################################ // // Older versions have the hierarchy mode settings not the body flags // We migrate it : // if (oDescr->hirarchy) { result->setFlags( (result->getFlags() | BF_Hierarchy )); } if (hierarchy) { oDescr->hirarchy = hierarchy; } //################################################################ // // Deformable ? // pCloth *cloth = NULL; pClothDesc cDescr; if (isDeformable) { cDescr.setToDefault(); cDescr.worldReference = worldReferenceObject->GetID(); if ( result->getFlags() & BF_Gravity ) { cDescr.flags |= PCF_Gravity; } if ( result->getFlags() & BF_Collision ) { } if (!cloth) { cloth = pFactory::Instance()->createCloth(referenceObject,cDescr); if (!cloth) { xLogger::xLog(XL_START,ELOGERROR,E_LI_MANAGER,"Cannot create cloth : factory object failed !"); } } } //################################################################ // // Some settings // if (result->getSkinWidth()==-1.0f) { result->setSkinWidth(0.01f); } float radius = referenceObject->GetRadius(); if (referenceObject->GetRadius() < 0.001f ) { radius = 1.0f; } float density = result->getDensity(); VxVector box_s= BoxGetZero(referenceObject); //################################################################ // // Calculate destination matrix // VxMatrix v_matrix ; VxVector position,scale; VxQuaternion quat; v_matrix = referenceObject->GetWorldMatrix(); Vx3DDecomposeMatrix(v_matrix,quat,position,scale); NxVec3 pos = pMath::getFrom(position); NxQuat rot = pMath::getFrom(quat); ////////////////////////////////////////////////////////////////////////// //create actors description NxActorDesc actorDesc;actorDesc.setToDefault(); NxBodyDesc bodyDesc;bodyDesc.setToDefault(); NxMaterialDesc *materialDescr = NULL; NxMaterial *material = NULL; switch(result->getHullType()) { ////////////////////////////////////////////////////////////////////////// case HT_Box: { NxBoxShapeDesc shape; if (! isDeformable ) { shape.dimensions = pMath::getFrom(box_s)*0.5f; } shape.density = density; //shape.localPose.t = pMath::getFrom(shapeOffset); if (result->getSkinWidth()!=-1.0f) shape.skinWidth = result->getSkinWidth(); actorDesc.shapes.pushBack(&shape); break; } ////////////////////////////////////////////////////////////////////////// case HT_Sphere: { NxSphereShapeDesc shape; if (! isDeformable ) { shape.radius = radius; } shape.density = density; //shape.localPose.t = pMath::getFrom(shapeOffset); if (result->getSkinWidth()!=-1.0f) shape.skinWidth = result->getSkinWidth(); actorDesc.shapes.pushBack(&shape); break; } ////////////////////////////////////////////////////////////////////////// case HT_Mesh: { if (! (result->getFlags() & BF_Deformable) ) { //xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Can not use a mesh as de"); //return NULL; } NxTriangleMeshDesc myMesh; myMesh.setToDefault(); createMesh(world->getScene(),referenceObject->GetCurrentMesh(),myMesh); NxTriangleMeshShapeDesc shape; bool status = InitCooking(); if (!status) { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Couldn't initiate cooking lib!"); return NULL; } MemoryWriteBuffer buf; status = CookTriangleMesh(myMesh, buf); if (!status) { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Couldn't cook mesh!"); return NULL; } shape.meshData = getManager()->getPhysicsSDK()->createTriangleMesh(MemoryReadBuffer(buf.data)); shape.density = density; // shape.materialIndex = result->getMaterial()->getMaterialIndex(); actorDesc.shapes.pushBack(&shape); //shape.localPose.t = pMath::getFrom(shapeOffset); if (result->getSkinWidth()!=-1.0f) shape.skinWidth = result->getSkinWidth(); CloseCooking(); if (myMesh.points) { delete [] myMesh.points; } if (myMesh.triangles) { delete []myMesh.triangles; } break; } ////////////////////////////////////////////////////////////////////////// case HT_ConvexMesh: { if (referenceObject->GetCurrentMesh()) { if (referenceObject->GetCurrentMesh()->GetVertexCount()>=256 ) { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Only 256 vertices for convex meshs allowed, by Ageia!"); goto nothing; } }else { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Object has no mesh!"); goto nothing; } NxConvexMeshDesc myMesh; myMesh.setToDefault(); createConvexMesh(world->getScene(),referenceObject->GetCurrentMesh(),myMesh); NxConvexShapeDesc shape; bool status = InitCooking(); if (!status) { xLogger::xLog(XL_START,ELOGERROR,E_LI_AGEIA,"Couldn't initiate cooking lib!"); goto nothing; } MemoryWriteBuffer buf; status = CookConvexMesh(myMesh, buf); if (!status) { xLogger::xLog(XL_START,ELOGERROR,E_LI_AGEIA,"Couldn't cook convex mesh!"); goto nothing; } shape.meshData = getManager()->getPhysicsSDK()->createConvexMesh(MemoryReadBuffer(buf.data)); shape.density = density; // shape.materialIndex = result->getMaterial()->getMaterialIndex(); actorDesc.shapes.pushBack(&shape); //shape.localPose.t = pMath::getFrom(shapeOffset); if (result->getSkinWidth()!=-1.0f) shape.skinWidth = result->getSkinWidth(); int h = shape.isValid(); CloseCooking(); if (myMesh.points) { delete [] myMesh.points; } if (myMesh.triangles) { delete []myMesh.triangles; } break; } ////////////////////////////////////////////////////////////////////////// case HT_ConvexCylinder: { NxConvexShapeDesc shape; if (!_createConvexCylinder(&shape,referenceObject)) xLogger::xLog(XL_START,ELOGERROR,E_LI_AGEIA,"Couldn't create convex cylinder mesh"); shape.density = density; if (result->getSkinWidth()!=-1.0f) shape.skinWidth = result->getSkinWidth(); actorDesc.shapes.pushBack(&shape); break; } ////////////////////////////////////////////////////////////////////////// case HT_Capsule: { NxCapsuleShapeDesc shape; if ( !isDeformable ) { pCapsuleSettings cSettings; pFactory::Instance()->findSettings(cSettings,referenceObject); shape.radius = cSettings.radius > 0.0f ? cSettings.radius : box_s.v[cSettings.localRadiusAxis] * 0.5f; shape.height = cSettings.height > 0.0f ? cSettings.height : box_s.v[cSettings.localLengthAxis] - ( 2*shape.radius) ; } shape.density = density; // shape.materialIndex = result->getMaterial()->getMaterialIndex(); // shape.localPose.t = pMath::getFrom(shapeOffset); if (result->getSkinWidth()!=-1.0f) shape.skinWidth = result->getSkinWidth(); actorDesc.shapes.pushBack(&shape); break; } case HT_Wheel: { // xLogger::xLog(XL_START,ELOGERROR,E_LI_AGEIA,"Couldn't create convex cylinder mesh"); /* NxWheelShapeDesc shape; shape.radius = box_s.z*0.5f; shape.density = density; if (result->getSkinWidth()!=-1.0f) shape.skinWidth = result->getSkinWidth(); if (referenceObject && referenceObject->HasAttribute(GetPMan()->att_wheelDescr )) { CKParameter *par = referenceObject->GetAttributeParameter(GetPMan()->att_wheelDescr ); if (par) { pWheelDescr *wheelDescr = pFactory::Instance()->copyTo(par); if (wheelDescr) { float heightModifier = (wheelDescr->wheelSuspension + radius ) / wheelDescr->wheelSuspension; shape.suspension.damper = wheelDescr->springDamping * heightModifier; shape.suspension.targetValue = wheelDescr->springBias * heightModifier; shape.suspensionTravel = wheelDescr->wheelSuspension; shape.lateralTireForceFunction.stiffnessFactor *= wheelDescr->frictionToSide; shape.longitudalTireForceFunction.stiffnessFactor*=wheelDescr->frictionToFront; shape.inverseWheelMass = 0.1; int isValid = shape.isValid(); actorDesc.shapes.pushBack(&shape); } }else { XString name = result->GetVT3DObject()->GetName(); name << " needs to have an additional wheel attribute attached ! "; xLogger::xLog(XL_START,ELOGERROR,E_LI_AGEIA,name.CStr()); } } */ break; } } ////////////////////////////////////////////////////////////////////////// //dynamic object ? if (result->getFlags() & BF_Moving){ actorDesc.body = &bodyDesc; } else actorDesc.body = NULL; ////////////////////////////////////////////////////////////////////////// //set transformations actorDesc.density = result->getDensity(); if ( !isDeformable) { actorDesc.globalPose.t = pos; actorDesc.globalPose.M = rot; } ////////////////////////////////////////////////////////////////////////// //create the actor int v = actorDesc.isValid(); NxActor *actor = world->getScene()->createActor(actorDesc); if (!actor) { xLogger::xLog(ELOGERROR,E_LI_AGEIA,"Couldn't create actor"); delete result; return NULL; } ////////////////////////////////////////////////////////////////////////// //set additional settings : result->setActor(actor); actor->setName(referenceObject->GetName()); actor->userData= result; ////////////////////////////////////////////////////////////////////////// //Deformable : if (isDeformable && cloth) { pDeformableSettings dSettings; dSettings.ImpulsThresold = 50.0f; dSettings.PenetrationDepth= 0.1f ; dSettings.MaxDeform = 2.0f; CKParameterOut *poutDS = referenceObject->GetAttributeParameter(GetPMan()->att_deformable); if (poutDS) { pFactory::Instance()->copyTo(dSettings,poutDS); } cloth->attachToCore(referenceObject,dSettings.ImpulsThresold,dSettings.PenetrationDepth,dSettings.MaxDeform); result->setCloth(cloth); } ////////////////////////////////////////////////////////////////////////// // // Extra settings : // if (result->getFlags() & BF_Moving) { VxVector massOffsetOut;referenceObject->Transform(&massOffsetOut,&result->getMassOffset()); actor->setCMassOffsetGlobalPosition(pMath::getFrom(massOffsetOut)); } if (result->getFlags() & BF_Kinematic) { result->setKinematic(true); } if (result->getFlags() & BF_Moving ) { result->enableGravity(result->getFlags() & BF_Gravity); } //---------------------------------------------------------------- // // Special Parameters // //- look for optimization attribute : result->checkForOptimization(); //---------------------------------------------------------------- // // store mesh meta info in the first main mesh // NxShape *shape = result->getShapeByIndex(); if (shape) { pSubMeshInfo *sInfo = new pSubMeshInfo(); sInfo->entID = referenceObject->GetID(); sInfo->refObject = (CKBeObject*)referenceObject; shape->userData = (void*)sInfo; result->setMainShape(shape); shape->setName(referenceObject->GetName()); pMaterial bMaterial; bool hasMaterial = pFactory::Instance()->findSettings(bMaterial,referenceObject); if (!hasMaterial) { if (world->getDefaultMaterial()) { int z = (int)world->getDefaultMaterial()->userData; shape->setMaterial(world->getDefaultMaterial()->getMaterialIndex()); //pFactory::Instance()->copyTo(bMaterial,world->getDefaultMaterial()); } }else{ NxMaterialDesc nxMatDescr; pFactory::Instance()->copyTo(nxMatDescr,bMaterial); NxMaterial *nxMaterial = world->getScene()->createMaterial(nxMatDescr); if (nxMaterial) { shape->setMaterial(nxMaterial->getMaterialIndex()); } } } result->enableCollision( (result->getFlags() & BF_Collision), referenceObject ); //- handle collisions setup if (oDescr->version == pObjectDescr::E_OD_VERSION::OD_DECR_V1) result->updateCollisionSettings(*oDescr,referenceObject); xLogger::xLog(ELOGINFO,E_LI_MANAGER,"Rigid body creation successful : %s",referenceObject->GetName()); //---------------------------------------------------------------- // // Parse hierarchy // if (!oDescr->hirarchy) return result; CK3dEntity* subEntity = NULL; while (subEntity= referenceObject->HierarchyParser(subEntity) ) { if (subEntity->HasAttribute(GetPMan()->GetPAttribute())) { pObjectDescr *subDescr = pFactory::Instance()->createPObjectDescrFromParameter(subEntity->GetAttributeParameter(GetPMan()->GetPAttribute())); if (subDescr->flags & BF_SubShape) { ////////////////////////////////////////////////////////////////////////// // // Regular Mesh : // if (subDescr->hullType != HT_Cloth) { result->addSubShape(NULL,*oDescr,subEntity); } ////////////////////////////////////////////////////////////////////////// // // Cloth Mesh : // if (subDescr->hullType == HT_Cloth) { //pClothDesc *cloth = pFactory::Instance()->createPObjectDescrFromParameter(subEntity->GetAttributeParameter(GetPMan()->GetPAttribute())); } } } } if (oDescr->hirarchy) { if (oDescr->newDensity!=0.0f || oDescr->totalMass!=0.0f ) { result->updateMassFromShapes(oDescr->newDensity,oDescr->totalMass); } } return result; } nothing: return result; }