void PlaypenApp::createObject(const std::string& material, ObjectType type) { switch(type) { case OBJECT_TYPE_BOX: { Ogre::Vector3 boxDim(5, 5, 5); opal::Solid* s = mSimulator->createSolid(); s->setPosition(mCreationPoint); opal::BoxShapeData data; data.dimensions.set(boxDim[0], boxDim[1], boxDim[2]); s->addShape(data); createPhysicalEntityBox("", material, boxDim, s); break; } case OBJECT_TYPE_SPHERE: { Ogre::Real radius = 3; // testing opal::Solid* s = mSimulator->createSolid(); s->setPosition(mCreationPoint); opal::SphereShapeData data; data.radius = radius; data.material.density = 1; // testing s->addShape(data); createPhysicalEntitySphere("", material, radius, s); break; } case OBJECT_TYPE_WALL: { opal::Matrix44r m; m.rotate(45, 0, 1, 0); m.translate(0, 0, -23); createWall(6, 8, opal::Vec3r(3, 1.5, 1.5), m, material); break; } case OBJECT_TYPE_TOWER: { createTower(2, 2, 15, opal::Vec3r(3, 1.5, 1.5), opal::Matrix44r(), material); break; } case OBJECT_TYPE_RAGDOLL: { opal::Blueprint ragdollBP; opal::loadFile(ragdollBP, "../../data/blueprints/ragdoll.xml"); opal::Matrix44r transform; transform.translate(mCreationPoint[0], mCreationPoint[1] - 5, mCreationPoint[2]); // Instantiate the Blueprint. opal::BlueprintInstance instance; mSimulator->instantiateBlueprint(instance, ragdollBP, transform, 16); unsigned int i=0; for (i=0; i<instance.getNumSolids(); ++i) { opal::Solid* s = instance.getSolid(i); const opal::SolidData& data = s->getData(); unsigned int j=0; for (j=0; j<data.getNumShapes(); ++j) { opal::ShapeData* shapeData = data.getShapeData(j); switch(shapeData->getType()) { case opal::BOX_SHAPE: { opal::Vec3r dim = ((opal::BoxShapeData*)shapeData)->dimensions; Ogre::Vector3 boxDim(dim[0], dim[1], dim[2]); createPhysicalEntityBox("", material, boxDim, s); break; } case opal::SPHERE_SHAPE: { opal::real r = ((opal::SphereShapeData*)shapeData)->radius; createPhysicalEntitySphere("", material, r, s); break; } case opal::CAPSULE_SHAPE: { opal::real r = ((opal::CapsuleShapeData*)shapeData)->radius; opal::real l = ((opal::CapsuleShapeData*)shapeData)->length; createPhysicalEntityCapsule("", material, r, l, s); break; } default: assert(false); } } } break; } default: assert(false); break; } }
void PlaypenApp::setupInitialPhysicalEntities() { opal::Matrix44r m; // Create a static box for a ground plane. Ogre::Vector3 boxDim(70, 16, 70); opal::Solid* s = mSimulator->createSolid(); s->setStatic(true); s->setPosition(0, -8, 0); opal::BoxShapeData data; data.dimensions.set(boxDim[0], boxDim[1], boxDim[2]); s->addShape(data); createPhysicalEntityBox("ground", "Plastic/Gray", boxDim, s); // Setup the "object creation tube". boxDim.x = 1; boxDim.y = 20; boxDim.z = 10; data.dimensions.set(boxDim[0], boxDim[1], boxDim[2]); s = mSimulator->createSolid(); s->setStatic(true); m.makeTranslation(mCreationPoint[0] + 0.5 * boxDim.z, mCreationPoint[1], mCreationPoint[2] + 0.5 * boxDim.x); s->setTransform(m); s->addShape(data); createPhysicalEntityBox("tube0", "Plastic/LightGray", boxDim, s); s = mSimulator->createSolid(); s->setStatic(true); m.makeTranslation(mCreationPoint[0] - 0.5 * boxDim.z, mCreationPoint[1], mCreationPoint[2] - 0.5 * boxDim.x); s->setTransform(m); s->addShape(data); createPhysicalEntityBox("tube1", "Plastic/LightGray", boxDim, s); s = mSimulator->createSolid(); s->setStatic(true); m.makeRotation(90, 0, 1, 0); m.translate(-mCreationPoint[2] + 0.5 * boxDim.z, mCreationPoint[1], mCreationPoint[0] + 0.5 * boxDim.x); s->setTransform(m); s->addShape(data); createPhysicalEntityBox("tube2", "Plastic/LightGray", boxDim, s); s = mSimulator->createSolid(); s->setStatic(true); m.makeRotation(90, 0, 1, 0); m.translate(-mCreationPoint[2] - 0.5 * boxDim.z, mCreationPoint[1], mCreationPoint[0] - 0.5 * boxDim.x); s->setTransform(m); s->addShape(data); createPhysicalEntityBox("tube3", "Plastic/LightGray", boxDim, s); // Make a slide under the object creation tube. boxDim.x = 60; boxDim.y = 1; boxDim.z = 15; data.dimensions.set(boxDim[0], boxDim[1], boxDim[2]); data.material.friction = 0.00001; s = mSimulator->createSolid(); s->setStatic(true); m.makeTranslation(mCreationPoint[0], mCreationPoint[1] - 33, mCreationPoint[2]); m.rotate(-45, 0, 1, 0); m.translate(0.3 * boxDim.x, 0, 0); m.rotate(-30, 0, 0, 1); s->setTransform(m); s->addShape(data); createPhysicalEntityBox("slide", "Plastic/DarkGray", boxDim, s); }
void Update(float elapsed) { float maxTime = GetPortFloat(&m_actInfo, EIP_Duration); float percent = maxTime > FLT_EPSILON ? elapsed / maxTime : 1.0f; if(percent >= 1.0f) { m_actInfo.pGraph->SetRegularlyUpdated(m_actInfo.myID, false); m_triggered = false; return; } Vec3 N = GetPortVec3(&m_actInfo, EIP_Normal); float rangeMin = GetPortFloat(&m_actInfo, EIP_RangeMin); float rangeMax = GetPortFloat(&m_actInfo, EIP_RangeMax); const float range = rangeMax - rangeMin; Vec3 boxDim(rangeMax, rangeMax, rangeMax); Vec3 ptmin = m_effectCenter - boxDim; Vec3 ptmax = m_effectCenter + boxDim; float speed = GetPortFloat(&m_actInfo, EIP_Speed); float waveFront = elapsed * speed; float decay = GetPortFloat(&m_actInfo, EIP_Decay); if(decay > FLT_EPSILON) decay = 1.0f / decay; float force = GetPortFloat(&m_actInfo, EIP_Force); force = pow_tpl(force * (1-percent), decay); float amplitude = GetPortFloat(&m_actInfo, EIP_Amplitude); amplitude = pow_tpl(amplitude * (1-percent), decay); if (gEnv->bMultiplayer) // Turned off for performance and network issues { return; } IPhysicalEntity** pEntityList = NULL; static const int iObjTypes = ent_rigid | ent_sleeping_rigid | ent_living;// | ent_allocate_list; int numEntities = gEnv->pPhysicalWorld->GetEntitiesInBox(ptmin, ptmax, pEntityList, iObjTypes); AABB bounds; for(int i=0; i<numEntities; ++i) { IPhysicalEntity* pPhysicalEntity = pEntityList[i]; IEntity* pEntity = static_cast<IEntity*>(pPhysicalEntity->GetForeignData(PHYS_FOREIGN_ID_ENTITY)); // Has the entity already been affected? if(pEntity) { bool affected = stl::find(m_entitiesAffected, pEntity->GetId()); if(!affected) { IEntityPhysicalProxy* pPhysicalProxy = static_cast<IEntityPhysicalProxy*>(pEntity->GetProxy(ENTITY_PROXY_PHYSICS)); if(pPhysicalProxy) { pPhysicalProxy->GetWorldBounds(bounds); Vec3 p = bounds.GetCenter(); Vec3 v = p - m_effectCenter; float distFromCenter = v.GetLength() + FLT_EPSILON; if(distFromCenter < rangeMax) { if(waveFront > distFromCenter) // has the wavefront passed the entity? { //pPhysicalEntity->GetStatus(&dyn); // normalize v, cheaper than another sqrt v /= distFromCenter; Vec3 dir = N + v * force; static bool usePos = false; float impulse = 1.0f - (max(0.0f, distFromCenter - rangeMin) / range); impulse = impulse * amplitude;// / dyn.mass; if(impulse > FLT_EPSILON) { pPhysicalProxy->AddImpulse(-1, p, dir * impulse, usePos, 1.0f); m_entitiesAffected.push_back(pEntity->GetId()); } } } } } } } }
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; }
bool PlaypenApp::processUnbufferedKeyInput(Ogre::Real dt) { // Check if we should quit looping. if(mKeyboard->isKeyDown(OIS::KC_ESCAPE) || mKeyboard->isKeyDown(OIS::KC_Q)) { return false; } // Check if we should pause physics. if(mKeyboard->isKeyDown(OIS::KC_P) && mTimeUntilNextToggle <= 0) { mPaused = !mPaused; // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.5; } // Reset the scene. if(mKeyboard->isKeyDown(OIS::KC_R)) { // Make sure the PhysicalCamera isn't grabbing anything. mPhysicalCamera->release(); destroyAllPhysicalEntities(); setupInitialPhysicalEntities(); } // Create various types of objects when the number keys are // pressed. // Create a box. if(mKeyboard->isKeyDown(OIS::KC_1) && mTimeUntilNextToggle <= 0) { Ogre::Vector3 boxDim(3, 3, 3); opal::Solid* s = mSimulator->createSolid(); s->setPosition(mCreationPoint); opal::BoxShapeData data; data.dimensions.set(boxDim[0], boxDim[1], boxDim[2]); s->addShape(data); createPhysicalEntityBox("", "Plastic/Yellow", boxDim, s); // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.3; } // Create a sphere. if(mKeyboard->isKeyDown(OIS::KC_2) && mTimeUntilNextToggle <= 0) { Ogre::Real radius = 2; opal::Solid* s = mSimulator->createSolid(); s->setPosition(mCreationPoint); opal::SphereShapeData data; data.radius = radius; s->addShape(data); createPhysicalEntitySphere("", "Plastic/Purple", radius, s); // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.3; } // Create a capsule. if(mKeyboard->isKeyDown(OIS::KC_3) && mTimeUntilNextToggle <= 0) { Ogre::Real radius = 2; Ogre::Real length = 5; opal::Solid* s = mSimulator->createSolid(); s->setPosition(mCreationPoint); opal::CapsuleShapeData data; data.radius = radius; data.length = length; s->addShape(data); createPhysicalEntityCapsule("", "Plastic/Red", radius, length, s); // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.3; } // Create a cylinder. if(mKeyboard->isKeyDown(OIS::KC_4) && mTimeUntilNextToggle <= 0) { Ogre::Real radius = 3; Ogre::Real length = 5; opal::Solid* s = mSimulator->createSolid(); s->setPosition(mCreationPoint); opal::CylinderShapeData data; data.radius = radius; data.length = length; s->addShape(data); createPhysicalEntityCylinder("", "Plastic/Blue", radius, length, s); // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.3; } // Create a long box. if(mKeyboard->isKeyDown(OIS::KC_5) && mTimeUntilNextToggle <= 0) { Ogre::Vector3 boxDim(2, 10, 3); opal::Solid* s = mSimulator->createSolid(); s->setPosition(mCreationPoint); opal::BoxShapeData data; data.dimensions.set(boxDim[0], boxDim[1], boxDim[2]); data.material.density = 10; s->addShape(data); createPhysicalEntityBox("", "Plastic/Green", boxDim, s); // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.3; } //// Create a log. //if(mKeyboard->isKeyDown(OIS::KC_6) && mTimeUntilNextToggle <= 0) //{ // Ogre::Real logScale = 9; // Ogre::Vector3 boxDim(0.4243, 0.4243, 2); // boxDim *= logScale; // opal::Solid* s = mSimulator->createSolid(); // opal::Matrix44r m; // m.rotate(90, 1, 0, 0); // s->setTransform(m); // s->setPosition(mCreationPoint); // opal::BoxShapeData data; // data.dimensions.set(boxDim[0], boxDim[1], boxDim[2]); // s->addShape(data); // std::string name = generateUniqueName(); // Ogre::SceneNode* sn = mSceneMgr->getRootSceneNode()-> // createChildSceneNode(name); // sn->scale(logScale, logScale, logScale); // Entity* e = mSceneMgr->createEntity(name, "log.mesh"); // e->setNormaliseNormals(true); // e->setMaterialName("Textured/Wood"); // sn->attachObject(e); // createPhysicalEntity(name, sn, s); // // Reset the timer for toggle keys. // mTimeUntilNextToggle = 0.3; //} // Create a knot. if(mKeyboard->isKeyDown(OIS::KC_6) && mTimeUntilNextToggle <= 0) { opalSamples::PhysicalEntity* pe = createPhysicalEntityMesh("", "knot.mesh", "Textured/RustedMetal", false, 0.1); pe->getSolid()->setPosition(opal::Point3r(0, 40, 0)); // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.3; } // Create a wall. if(mKeyboard->isKeyDown(OIS::KC_7) && mTimeUntilNextToggle <= 0) { opal::Matrix44r m; m.rotate(45, 0, 1, 0); m.translate(0, 0, -23); createWall(6, 8, opal::Vec3r(3, 1.5, 1.5), m); // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.3; } // Create a tower. if(mKeyboard->isKeyDown(OIS::KC_8) && mTimeUntilNextToggle <= 0) { createTower(2, 2, 15, opal::Vec3r(3, 1.5, 1.5)); // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.3; } // Create a ragdoll. if(mKeyboard->isKeyDown(OIS::KC_9) && mTimeUntilNextToggle <= 0) { opal::Blueprint ragdollBP; opal::loadFile(ragdollBP, "../data/blueprints/ragdoll.xml"); opal::Matrix44r transform; transform.translate(mCreationPoint[0], mCreationPoint[1] - 5, mCreationPoint[2]); // Instantiate the Blueprint. opal::BlueprintInstance instance; mSimulator->instantiateBlueprint(instance, ragdollBP, transform, 16); unsigned int i=0; for (i=0; i<instance.getNumSolids(); ++i) { opal::Solid* s = instance.getSolid(i); const opal::SolidData& data = s->getData(); unsigned int j=0; for (j=0; j<data.getNumShapes(); ++j) { opal::ShapeData* shapeData = data.getShapeData(j); switch(shapeData->getType()) { case opal::BOX_SHAPE: { opal::Vec3r dim = ((opal::BoxShapeData*)shapeData)->dimensions; Ogre::Vector3 boxDim(dim[0], dim[1], dim[2]); createPhysicalEntityBox("", "Plastic/LightBlue", boxDim, s); break; } case opal::SPHERE_SHAPE: { opal::real r = ((opal::SphereShapeData*)shapeData)->radius; createPhysicalEntitySphere("", "Plastic/LightBlue", r, s); break; } case opal::CAPSULE_SHAPE: { opal::real r = ((opal::CapsuleShapeData*)shapeData)->radius; opal::real l = ((opal::CapsuleShapeData*)shapeData)->length; createPhysicalEntityCapsule("", "Plastic/LightBlue", r, l, s); break; } default: assert(false); } } } // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.5; } // The following code updates the camera's position. opal::Vec3r cameraDir(0, 0, 0); bool cameraMoved = false; if (mKeyboard->isKeyDown(OIS::KC_LEFT) || mKeyboard->isKeyDown(OIS::KC_A)) { // Move camera left. cameraDir[0] -= (dt * mMoveSpeed); cameraMoved = true; } if (mKeyboard->isKeyDown(OIS::KC_RIGHT) || mKeyboard->isKeyDown(OIS::KC_D)) { // Move camera right. cameraDir[0] += (dt * mMoveSpeed); cameraMoved = true; } if (mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W)) { // Move camera forward. cameraDir[2] -= (dt * mMoveSpeed); cameraMoved = true; } if (mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S)) { // Move camera backward. cameraDir[2] += (dt * mMoveSpeed); cameraMoved = true; } if (!cameraMoved) { // Slow physical camera motion if necessary. } // Use the camera dir vector to translate the camera. mPhysicalCamera->moveRelative(cameraDir); // Toggle shadows. if(mKeyboard->isKeyDown(OIS::KC_H) && mTimeUntilNextToggle <= 0) { mUseShadows = !mUseShadows; if (mUseShadows) { mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE); } else { mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE); } // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.5; } // Toggle second light source. if(mKeyboard->isKeyDown(OIS::KC_L) && mTimeUntilNextToggle <= 0) { Ogre::Light* light1 = mSceneMgr->getLight("light1"); if (light1->isVisible()) { light1->setVisible(false); } else { light1->setVisible(true); } // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.5; } // Toggle GUI. if (mKeyboard->isKeyDown(OIS::KC_G) && mTimeUntilNextToggle <= 0) { mStatsOn = !mStatsOn; showDebugOverlay(mStatsOn); mTimeUntilNextToggle = 1; } // Handy screenshot saving procedure. if (mKeyboard->isKeyDown(OIS::KC_SYSRQ) && mTimeUntilNextToggle <= 0) { char tmp[20]; sprintf(tmp, "screenshot_%d.png", ++mNumScreenShots); ExampleApplication::mWindow->writeContentsToFile(tmp); mDebugText = String("Wrote ") + tmp; // Reset the timer for toggle keys. mTimeUntilNextToggle = 0.5; } // Return true to continue looping. return true; }
NxActor* CreateLander(NxVec3 position) { NxActor* actor=NULL; switch (gLanderType) { case CAPSULE_LANDER: actor = CreateCapsuleGrain(position,gLanderMass/pow(gLanderSize.x,3.0f),gLanderSize.x); break; case SPHERE_LANDER: actor = CreateSphericalGrain(position,gLanderMass/pow(gLanderSize.x,3.0f),gLanderSize.x); break; case ROLY_POLY: {// Two slightly offset spheres, one heavy, one slightly smaller, and hollow NxActorDesc actorDesc; NxBodyDesc bodyDesc; NxReal radius=gLanderSize.x; // The bottom "roly" NxSphereShapeDesc rolyDesc; rolyDesc.radius=radius*gLanderSize.z; // relative to top hemisphere rolyDesc.localPose.t=NxVec3(0.0f,radius,0.0f); rolyDesc.materialIndex=gLanderDownMaterial->getMaterialIndex(); // note: both hemispheres use "down" material rolyDesc.mass=1; // relative to top hemisphere rolyDesc.skinWidth=radius/60; rolyDesc.name="downside"; actorDesc.shapes.pushBack(&rolyDesc); // The top "poly" NxSphereShapeDesc polyDesc; polyDesc.radius=radius; polyDesc.localPose.t=NxVec3(0.0f,radius+gLanderSize.y,0.0f); polyDesc.materialIndex=gLanderDownMaterial->getMaterialIndex(); // note: both hemispheres use "down" material polyDesc.mass=1; polyDesc.skinWidth=radius/60; polyDesc.name="upside"; actorDesc.shapes.pushBack(&polyDesc); // The weight NxSphereShapeDesc wDesc; wDesc.radius=radius/10; wDesc.localPose.t=NxVec3(0.0f,wDesc.radius,0.0f); wDesc.materialIndex=gLanderDownMaterial->getMaterialIndex(); // note: this is irrelevant wDesc.mass=gRPWeight; // relative to top hemisphere wDesc.skinWidth=radius/120; wDesc.name="weight"; actorDesc.shapes.pushBack(&wDesc); // the lander bodyDesc.mass=gLanderMass; actorDesc.body=&bodyDesc; actorDesc.globalPose.t=position; assert(actorDesc.isValid()); actor=gScene->createActor(actorDesc); assert(actor); actor->setName("~lander"); //actor->raiseBodyFlag(NX_BF_KINEMATIC); break; } case SHAPED_CHARGE: {// Two flat plates, like a two-layer ruler, one heavy and absorbing, one hollow and elastic NxActorDesc actorDesc; NxBodyDesc bodyDesc; NxVec3 boxDim=gLanderSize/2; // remember NxShapeDesc.dimension is the "radius" boxDim.y/=2; // remember we're going to stack two of these // The down side NxBoxShapeDesc downsideDesc; downsideDesc.dimensions.set(boxDim); downsideDesc.localPose.t=NxVec3(0.0f,boxDim.y,0.0f); downsideDesc.materialIndex=gLanderDownMaterial->getMaterialIndex(); downsideDesc.density=gLanderMassRatio; downsideDesc.skinWidth=boxDim.y/60; downsideDesc.name="downside"; actorDesc.shapes.pushBack(&downsideDesc); // The up side NxBoxShapeDesc upsideDesc; upsideDesc.dimensions.set(boxDim); upsideDesc.localPose.t=NxVec3(0.0f,3.0*boxDim.y,0.0f); upsideDesc.materialIndex=gLanderUpMaterial->getMaterialIndex(); upsideDesc.density=1; upsideDesc.skinWidth=boxDim.y/60; upsideDesc.name="upside"; actorDesc.shapes.pushBack(&upsideDesc); // The Lander bodyDesc.mass=gLanderMass; actorDesc.body = &bodyDesc; actorDesc.globalPose.t = position; assert(actorDesc.isValid()); actor = gScene->createActor(actorDesc); assert(actor); actor->setName("~lander"); break; } case CUBESAT: {// JPL's new fad, comes in units of 10x10x10 cm NxActorDesc actorDesc; NxBodyDesc bodyDesc; NxVec3 boxDim(0.05); // remember NxShapeDesc.dimension is the "radius" // U1 - the dead weight NxBoxShapeDesc U1Desc; U1Desc.dimensions.set(boxDim); U1Desc.localPose.t=NxVec3(0.0f,boxDim.y,0.0f); U1Desc.materialIndex=gLanderDownMaterial->getMaterialIndex(); U1Desc.mass=10*gLanderMass; U1Desc.skinWidth=boxDim.y/60; U1Desc.name="U1"; actorDesc.shapes.pushBack(&U1Desc); // U2 NxBoxShapeDesc U2Desc; U2Desc.dimensions.set(boxDim); U2Desc.localPose.t=NxVec3(0.0f,3.0*boxDim.y,0.0f); U2Desc.materialIndex=gLanderUpMaterial->getMaterialIndex(); U2Desc.mass=gLanderMass; U2Desc.skinWidth=boxDim.y/60; U2Desc.name="U2"; actorDesc.shapes.pushBack(&U2Desc); // U3 NxBoxShapeDesc U3Desc; U3Desc.dimensions.set(boxDim); U3Desc.localPose.t=NxVec3(0.0f,5.0*boxDim.y,0.0f); U3Desc.materialIndex=gLanderUpMaterial->getMaterialIndex(); U3Desc.mass=gLanderMass; U3Desc.skinWidth=boxDim.y/60; U3Desc.name="U3"; actorDesc.shapes.pushBack(&U3Desc); // The Cubesat bodyDesc.mass=gLanderMass; actorDesc.body = &bodyDesc; actorDesc.globalPose.t = position; assert(actorDesc.isValid()); actor = gScene->createActor(actorDesc); assert(actor); actor->setName("~lander"); break; } default: printf("Error: unknown lander type\n"); break; } return actor; }