PhysicsInterface::JointObject Bullet::createHingeJoint(BodyObject firstBodyObject, BodyObject secondBodyObject, const Vec3& globalAnchor, const Vec3& globalAxis) { if (!firstBodyObject || !secondBodyObject || firstBodyObject == secondBodyObject) { LOG_ERROR << "Invalid bodies"; return nullptr; } auto firstBody = reinterpret_cast<Body*>(firstBodyObject); auto secondBody = reinterpret_cast<Body*>(secondBodyObject); auto firstBodyTransform = btTransform(); auto secondBodyTransform = btTransform(); firstBody->bulletBody->getMotionState()->getWorldTransform(firstBodyTransform); secondBody->bulletBody->getMotionState()->getWorldTransform(secondBodyTransform); auto btConstraint = new btHingeConstraint(*firstBody->bulletBody, *secondBody->bulletBody, firstBodyTransform.inverse() * toBullet(globalAnchor), secondBodyTransform.inverse() * toBullet(globalAnchor), firstBodyTransform.getBasis().inverse() * toBullet(globalAxis), secondBodyTransform.getBasis().inverse() * toBullet(globalAxis)); joints_.append(new Joint(firstBody, secondBody, btConstraint)); dynamicsWorld_->addConstraint(joints_.back()->bulletConstraint, true); return joints_.back(); }
void Context::init( const Format &format ) { mCollisionConfiguration = format.mConfiguration ? format.mConfiguration : !format.mCreateSoftRigidWorld ? new btDefaultCollisionConfiguration() : new btSoftBodyRigidBodyCollisionConfiguration(); mCollisionDispatcher = format.mCollisionDispatcher ? format.mCollisionDispatcher : new btCollisionDispatcher(mCollisionConfiguration); mBroadPhase = format.mBroadphase ? format.mBroadphase : new btDbvtBroadphase(); mSolver = format.mSolver ? format.mSolver : new btSequentialImpulseConstraintSolver(); mWorld = format.mWorld ? format.mWorld : !format.mCreateSoftRigidWorld ? new btDiscreteDynamicsWorld( mCollisionDispatcher, mBroadPhase, mSolver, mCollisionConfiguration ) : new btSoftRigidDynamicsWorld( mCollisionDispatcher, mBroadPhase, mSolver, mCollisionConfiguration, format.mSoftBodySolver ); // If we want to setup the debug renderer if( format.mCreateDebugRenderer ) { setupDebugRenderer( format.mDebugMode ); } // This initializes the static pointer to the bullet context sBulletContext = this; sBulletContextInitialized = true; mWorld->setWorldUserInfo( this ); mWorld->setGravity( toBullet( format.mGravity ) ); if( format.mCreateSoftRigidWorld ) { auto worldInfo = getSoftBodyWorldInfo(); worldInfo.m_gravity = toBullet( format.mGravity ); // Add other world_info settings here from format. } }
bool Context::closestRayCast( const ci::vec3 &startPosition, const ci::vec3 &direction, RayResult &result ) { if( ! world() ) return false; btVector3 rayTo = toBullet( direction * 1000.0f ); btVector3 rayFrom = toBullet( startPosition ); btCollisionWorld::ClosestRayResultCallback rayCallback( rayFrom, rayTo ); world()->rayTest( rayFrom, rayTo, rayCallback ); if( rayCallback.hasHit() ) { btRigidBody* pBody = (btRigidBody*) btRigidBody::upcast( rayCallback.m_collisionObject ); if(!pBody) return false; result.pBody = pBody; result.hitPoint = fromBullet( rayCallback.m_hitPointWorld ); result.hitNormal = fromBullet( rayCallback.m_hitNormalWorld ); return true; } return false; }
Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<const Resource::BulletShape> shape, btCollisionWorld* world) : mCanWaterWalk(false), mWalkingOnWater(false) , mCollisionObject(0), mForce(0.f, 0.f, 0.f), mOnGround(false) , mInternalCollisionMode(true) , mExternalCollisionMode(true) , mCollisionWorld(world) { mPtr = ptr; mHalfExtents = shape->mCollisionBoxHalfExtents; mMeshTranslation = shape->mCollisionBoxTranslate; // Use capsule shape only if base is square (nonuniform scaling apparently doesn't work on it) if (std::abs(mHalfExtents.x()-mHalfExtents.y())<mHalfExtents.x()*0.05 && mHalfExtents.z() >= mHalfExtents.x()) { // Could also be btCapsuleShapeZ, but the movement solver seems to have issues with it (jumping on slopes doesn't work) mShape.reset(new btCylinderShapeZ(toBullet(mHalfExtents))); } else mShape.reset(new btBoxShape(toBullet(mHalfExtents))); mCollisionObject.reset(new btCollisionObject); mCollisionObject->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT); mCollisionObject->setActivationState(DISABLE_DEACTIVATION); mCollisionObject->setCollisionShape(mShape.get()); mCollisionObject->setUserPointer(static_cast<PtrHolder*>(this)); updateRotation(); updateScale(); updatePosition(); updateCollisionMask(); }
void Bullet::applyForceToBody(BodyObject bodyObject, const Vec3& force, ForceMode mode) { if (!bodyObject) return; auto body = reinterpret_cast<Body*>(bodyObject); body->bulletBody->activate(true); if (mode == ForceStandard) body->bulletBody->applyCentralForce(toBullet(force * 100.0f)); else if (mode == ForceImpulse) body->bulletBody->applyCentralImpulse(toBullet(force)); }
void Bullet::applyTorqueToBody(BodyObject bodyObject, const Vec3& torque, ForceMode mode) { if (!bodyObject) return; auto body = reinterpret_cast<Body*>(bodyObject); body->bulletBody->activate(true); if (mode == ForceStandard) body->bulletBody->applyTorque(toBullet(torque)); else if (mode == ForceImpulse) body->bulletBody->applyTorqueImpulse(toBullet(torque)); }
bool Bullet::raycast(const Ray& ray, PhysicsIntersectResult& result) const { auto endPoint = ray.getPoint(MaxRayDistance); auto intersections = Vector<PhysicsIntersectResult>(); auto callback = RayResultCollector(ray, intersections); dynamicsWorld_->rayTest(toBullet(ray.getOrigin()), toBullet(endPoint), callback); if (intersections.empty()) return false; intersections.sort(); result = intersections[0]; return true; }
PhysicsInterface::BodyObject Bullet::createCapsuleBody(float height, float radius, float mass, bool fixed, const Entity* entity, const SimpleTransform& initialTransform) { auto collisionShape = new btCapsuleShape(radius, height); // Calculate inertia auto localInertia = btVector3(0.0f, 0.0f, 0.0f); if (!fixed) collisionShape->calculateLocalInertia(mass, localInertia); // Motion state for this body auto motionState = new btDefaultMotionState(toBullet(initialTransform)); // Create Bullet rigid body auto bulletBody = new btRigidBody( btRigidBody::btRigidBodyConstructionInfo(fixed ? 0.0f : mass, motionState, collisionShape, localInertia)); bulletBody->setDamping(DefaultLinearDamping, DefaultAngularDamping); bulletBody->setSleepingThresholds(DefaultLinearSleepingThreshold, DefaultAngularSleepingThreshold); bulletBody->setRestitution(0.0f); // Add body to the simulation dynamicsWorld_->addRigidBody(bulletBody); // Create local body auto body = new Body(bulletBody, entity, fixed); bodies_.append(body); body->ownedCollisionShape = collisionShape; bulletBody->setUserPointer(body); return body; }
void reEnemy::messageProcess( reMessageDispatcher* sender, reMessage* message ) { switch (message->id) { case reM_MOUSE_PRESS: { reMouseMessage* mouseMessage = (reMouseMessage*)message; reVec3 dir = glm::normalize(mouseMessage->dir); reVec3 p(0,1,0); target = mouseMessage->p + mouseMessage->dir*(glm::dot(p, mouseMessage->p)/glm::dot(p, -mouseMessage->dir)); reVec3 d = (mouseMessage->p.y / -dir.y) * dir + mouseMessage->p; assert(glm::length(d-target) < 0.1f); } break; case reM_TIMER: { reVec4 pos = worldTransform().matrix * reVec4(0,0,0,1); reVec3 dir = target - reVec3(pos); if (glm::length(dir)>.5f) { dir = glm::normalize(dir); body->btBody->applyCentralForce(toBullet(dir)*1000); } else { dir = -fromBullet(body->btBody->getLinearVelocity()); body->btBody->applyCentralForce(toBullet(dir)*100); } reVec3 v = fromBullet(body->btBody->getLinearVelocity()); reNode* node = (reNode*)children->objectByName("model"); reAnimator* animator = node->children->findObject<reAnimator>(); if (glm::length(v) > 0.001f) { float angle = atan2(v.x, v.z); node->transform(reTransform(glm::rotate(reMat4(), glm::degrees(angle), reVec3(0,1,0)))); animator->play((reSequence*)node->objectByName("walk"), .3); animator->stopAnimation("idle", .3); } else { animator->play((reSequence*)node->objectByName("idle"), .3); animator->stopAnimation("walk", .3); } } break; } }
void Actor::updateCollisionObjectPosition() { btTransform tr = mCollisionObject->getWorldTransform(); osg::Vec3f scaledTranslation = mRotation * osg::componentMultiply(mMeshTranslation, mScale); osg::Vec3f newPosition = scaledTranslation + mPosition; tr.setOrigin(toBullet(newPosition)); mCollisionObject->setWorldTransform(tr); }
void RigidBody::init( const Format &format ) { mType = getPhyObjType( format.mCollShape->getName() ); mCollGroup = format.mCollisionGroup; mCollMask = format.mCollisionMask; mCollisionShape = format.mCollShape; mCollisionShape->setLocalScaling( toBullet(format.mInitialScale) ); recalculateBoundingSphere(); btVector3 localInertia(0,0,0); if( format.mMass != 0.0f && ! format.mSetKinematic ) { mCollisionShape->calculateLocalInertia( format.mMass, localInertia ); } mMotionState = format.mMotionState; btRigidBody::btRigidBodyConstructionInfo cInfo( format.mMass, mMotionState.get(), mCollisionShape.get(), localInertia ); cInfo.m_friction = format.mFriction; cInfo.m_restitution = format.mRestitution; mRigidBody.reset( new btRigidBody(cInfo) ); if( format.mSetKinematic ) { mRigidBody->setCollisionFlags( mRigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT ); setActivationState( DISABLE_DEACTIVATION ); } if( format.mAddToWorld ) { Context()->addRigidBody( mRigidBody.get(), mCollGroup, mCollMask ); mAddedToWorld = true; } if( ! mMotionState ) { btTransform trans; trans.setOrigin( toBullet( format.mInitialPosition ) ); trans.setRotation( toBullet( format.mInitialRotation ) ); mRigidBody->setWorldTransform( trans ); } mRigidBody->setUserPointer( format.mRigidBodyUserPtr ? format.mRigidBodyUserPtr : this ); }
void Bullet::moveCharacterController(CharacterControllerObject characterControllerObject, const Vec3& move, float time) { if (!characterControllerObject) return; auto characterController = reinterpret_cast<CharacterController*>(characterControllerObject); characterController->bulletController->setVelocityForTimeInterval(toBullet(move / time), time); }
void Actor::updateRotation () { btTransform tr = mCollisionObject->getWorldTransform(); mRotation = mPtr.getRefData().getBaseNode()->getAttitude(); tr.setRotation(toBullet(mRotation)); mCollisionObject->setWorldTransform(tr); updateCollisionObjectPosition(); }
bool Context::allHitsRayResult( const ci::vec3 &startPosition, const ci::vec3 &direction, RayResult &result ) { btVector3 rayTo = toBullet( direction * 1000.0f ); btVector3 rayFrom = toBullet( startPosition ); btCollisionWorld::AllHitsRayResultCallback allHitsCallback( rayFrom, rayTo ); world()->rayTest( rayFrom, rayTo, allHitsCallback ); if( allHitsCallback.hasHit() ) { auto bodies = std::move( allHitsCallback.m_collisionObjects ); if( bodies.size() <= 0 ) return false; } return false; }
bool Bullet::setCharacterControllerPosition(CharacterControllerObject characterControllerObject, const Vec3& position) { if (!characterControllerObject) return false; auto characterController = reinterpret_cast<CharacterController*>(characterControllerObject); characterController->bulletController->setWorldPosition(toBullet(position)); return true; }
bool Bullet::setBodyAngularVelocity(BodyObject bodyObject, const Vec3& velocity) const { if (!bodyObject) return false; auto body = reinterpret_cast<Body*>(bodyObject); body->bulletBody->setAngularVelocity(toBullet(velocity)); body->bulletBody->activate(true); return true; }
void ActorTracer::doTrace(const btCollisionObject *actor, const osg::Vec3f& start, const osg::Vec3f& end, const btCollisionWorld* world) { const btVector3 btstart = toBullet(start); const btVector3 btend = toBullet(end); const btTransform &trans = actor->getWorldTransform(); btTransform from(trans); btTransform to(trans); from.setOrigin(btstart); to.setOrigin(btend); ClosestNotMeConvexResultCallback newTraceCallback(actor, btstart-btend, btScalar(0.0)); // Inherit the actor's collision group and mask newTraceCallback.m_collisionFilterGroup = actor->getBroadphaseHandle()->m_collisionFilterGroup; newTraceCallback.m_collisionFilterMask = actor->getBroadphaseHandle()->m_collisionFilterMask; const btCollisionShape *shape = actor->getCollisionShape(); assert(shape->isConvex()); world->convexSweepTest(static_cast<const btConvexShape*>(shape), from, to, newTraceCallback); // Copy the hit data over to our trace results struct: if(newTraceCallback.hasHit()) { const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; mFraction = newTraceCallback.m_closestHitFraction; mPlaneNormal = osg::Vec3f(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); mEndPos = (end-start)*mFraction + start; mHitPoint = toOsg(newTraceCallback.m_hitPointWorld); mHitObject = newTraceCallback.m_hitCollisionObject; } else { mEndPos = end; mPlaneNormal = osg::Vec3f(0.0f, 0.0f, 1.0f); mFraction = 1.0f; mHitPoint = end; mHitObject = nullptr; } }
PhysicsInterface::BodyTemplateObject Bullet::createBodyTemplateFromGeometry(const Vector<Vec3>& vertices, const Vector<RawIndexedTriangle>& triangles, bool deleteOnceUnused, float customCollisionMargin) { if (vertices.empty() || triangles.empty()) return nullptr; auto bodyTemplate = new BodyTemplate(deleteOnceUnused); bodyTemplates_.append(bodyTemplate); // Copy the geometry data bodyTemplate->vertices = vertices; bodyTemplate->triangles = triangles; // Create interface to the geometry data for Bullet to use auto mesh = btIndexedMesh(); mesh.m_numTriangles = bodyTemplate->triangles.size(); mesh.m_triangleIndexBase = reinterpret_cast<byte_t*>(bodyTemplate->triangles.getData()); mesh.m_triangleIndexStride = 3 * sizeof(unsigned int); mesh.m_numVertices = bodyTemplate->vertices.size(); mesh.m_vertexBase = bodyTemplate->vertices.as<byte_t>(); mesh.m_vertexStride = 3 * sizeof(float); auto meshInterface = new btTriangleIndexVertexArray(); meshInterface->addIndexedMesh(mesh); // Calculate an AABB around the geometry auto aabb = AABB(bodyTemplate->vertices); // Create the collision shape bodyTemplate->collisionShape = new btBvhTriangleMeshShape(meshInterface, true, toBullet(aabb.getMinimum()), toBullet(aabb.getMaximum())); if (customCollisionMargin > 0.0f) bodyTemplate->collisionShape->setMargin(customCollisionMargin); return bodyTemplate; }
PhysicsInterface::JointObject Bullet::createBallAndSocketJoint(BodyObject firstBodyObject, BodyObject secondBodyObject, const Vec3& globalAnchor, const Vec3& angularLimits) { if (!firstBodyObject || !secondBodyObject || firstBodyObject == secondBodyObject) { LOG_ERROR << "Invalid bodies"; return nullptr; } auto firstBody = reinterpret_cast<Body*>(firstBodyObject); auto secondBody = reinterpret_cast<Body*>(secondBodyObject); auto firstBodyTransform = btTransform(); auto secondBodyTransform = btTransform(); firstBody->bulletBody->getMotionState()->getWorldTransform(firstBodyTransform); secondBody->bulletBody->getMotionState()->getWorldTransform(secondBodyTransform); auto firstLocalAnchor = btTransform(btQuaternion::getIdentity(), firstBodyTransform.inverse() * toBullet(globalAnchor)); auto secondLocalAnchor = btTransform(btQuaternion::getIdentity(), secondBodyTransform.inverse() * toBullet(globalAnchor)); auto btConstraint = new btGeneric6DofConstraint(*firstBody->bulletBody, *secondBody->bulletBody, firstLocalAnchor, secondLocalAnchor, true); if (angularLimits != Vec3::Zero) { btConstraint->setAngularLowerLimit(toBullet(-angularLimits)); btConstraint->setAngularUpperLimit(toBullet(angularLimits)); } joints_.append(new Joint(firstBody, secondBody, btConstraint)); dynamicsWorld_->addConstraint(joints_.back()->bulletConstraint, true); return joints_.back(); }
void PhyObjTriggerVol::initObject( btCollisionShape *collShape, const ci::vec3 &position ) { mTrigger = new btCollisionObject(); mTrigger->setCollisionShape( collShape ); btTransform triggerTrans; triggerTrans.setIdentity(); triggerTrans.setOrigin( toBullet( position ) ); mTrigger->setWorldTransform( triggerTrans ); mTrigger->setCollisionFlags( btCollisionObject::CF_NO_CONTACT_RESPONSE ); Context()->world()->addCollisionObject( mTrigger ); }
void Actor::updateScale() { float scale = mPtr.getCellRef().getScale(); osg::Vec3f scaleVec(scale,scale,scale); mPtr.getClass().adjustScale(mPtr, scaleVec, false); mScale = scaleVec; mShape->setLocalScaling(toBullet(mScale)); scaleVec = osg::Vec3f(scale,scale,scale); mPtr.getClass().adjustScale(mPtr, scaleVec, true); mRenderingScale = scaleVec; updateCollisionObjectPosition(); }
PhysicsInterface::BodyObject Bullet::createBoundingBoxBody(const AABB& aabb, float mass, bool fixed, const Entity* entity, const SimpleTransform& initialTransform) { auto collisionShape = new btBoxShape(toBullet((aabb.getMaximum() - aabb.getMinimum()) * 0.5f)); // Calculate inertia auto localInertia = btVector3(0.0f, 0.0f, 0.0f); if (!fixed) collisionShape->calculateLocalInertia(mass, localInertia); // Motion state for this body auto motionState = new btDefaultMotionState(toBullet(initialTransform), btTransform(btQuaternion::getIdentity(), toBullet(aabb.getCenter()))); // Create Bullet rigid body auto bulletBody = new btRigidBody( btRigidBody::btRigidBodyConstructionInfo(fixed ? 0.0f : mass, motionState, collisionShape, localInertia)); bulletBody->setDamping(DefaultLinearDamping, DefaultAngularDamping); bulletBody->setSleepingThresholds(DefaultLinearSleepingThreshold, DefaultAngularSleepingThreshold); bulletBody->setRestitution(0.0f); // Add body to the simulation dynamicsWorld_->addRigidBody(bulletBody); // Create local body auto body = new Body(bulletBody, entity, fixed); bodies_.append(body); body->ownedCollisionShape = collisionShape; bulletBody->setUserPointer(body); return body; }
bool Bullet::setup() { broadphase_ = new btDbvtBroadphase; ghostPairCallback_ = new btGhostPairCallback; broadphase_->getOverlappingPairCache()->setInternalGhostPairCallback(ghostPairCallback_); collisionConfiguration_ = new btDefaultCollisionConfiguration; dispatcher_ = new btCollisionDispatcher(collisionConfiguration_); solver_ = new btSequentialImpulseConstraintSolver; dynamicsWorld_ = new btDiscreteDynamicsWorld(dispatcher_, broadphase_, solver_, collisionConfiguration_); dynamicsWorld_->setGravity(toBullet(getGravityVector())); LOG_INFO << "Initialized Bullet " << (btGetVersion() / 100) << "." << (btGetVersion() % 100); return true; }
PhysicsInterface::BodyObject Bullet::createGeometryBodyFromTemplate(BodyTemplateObject bodyTemplateObject, float mass, bool fixed, const Entity* entity, const SimpleTransform& initialTransform) { auto bodyTemplate = reinterpret_cast<BodyTemplate*>(bodyTemplateObject); if (!bodyTemplateObject || !bodyTemplate->collisionShape) { LOG_ERROR << "Invalid body template"; return nullptr; } // Calculate inertia auto localInertia = btVector3(0.0f, 0.0f, 0.0f); if (!fixed) bodyTemplate->collisionShape->calculateLocalInertia(mass, localInertia); // Motion state for this body auto motionState = new btDefaultMotionState(toBullet(initialTransform), btTransform(btQuaternion::getIdentity(), toBullet(Vec3::Zero))); // Create Bullet rigid body auto bulletBody = new btRigidBody( btRigidBody::btRigidBodyConstructionInfo((fixed ? 0.0f : mass), motionState, bodyTemplate->collisionShape, (fixed ? btVector3(0.0f, 0.0f, 0.0f) : localInertia))); bulletBody->setDamping(DefaultLinearDamping, DefaultAngularDamping); bulletBody->setSleepingThresholds(DefaultLinearSleepingThreshold, DefaultAngularSleepingThreshold); bulletBody->setRestitution(0.0f); // Add body to the simulation dynamicsWorld_->addRigidBody(bulletBody); // Create local body auto body = new Body(bulletBody, entity, fixed); bodies_.append(body); bulletBody->setUserPointer(body); return body; }
bool Bullet::setBodyTransform(BodyObject bodyObject, const SimpleTransform& transform) { if (!bodyObject) return false; auto body = reinterpret_cast<Body*>(bodyObject); if (body->isFixed) { LOG_ERROR << "Can't alter the physics transform of a fixed body"; return false; } // Set new transform on the body body->bulletBody->getWorldTransform() = toBullet(transform); // Put this body back in the active list since it's been manually reconfigured body->bulletBody->activate(true); return true; }
void ActorTracer::findGround(const Actor* actor, const osg::Vec3f& start, const osg::Vec3f& end, btCollisionWorld* world) { const btVector3 btstart(start.x(), start.y(), start.z()+1.0f); const btVector3 btend(end.x(), end.y(), end.z()+1.0f); const btTransform &trans = actor->getCollisionObject()->getWorldTransform(); btTransform from(trans.getBasis(), btstart); btTransform to(trans.getBasis(), btend); ClosestNotMeConvexResultCallback newTraceCallback(actor->getCollisionObject(), btstart-btend, btScalar(0.0)); // Inherit the actor's collision group and mask newTraceCallback.m_collisionFilterGroup = actor->getCollisionObject()->getBroadphaseHandle()->m_collisionFilterGroup; newTraceCallback.m_collisionFilterMask = actor->getCollisionObject()->getBroadphaseHandle()->m_collisionFilterMask; newTraceCallback.m_collisionFilterMask &= ~CollisionType_Actor; btVector3 halfExtents = toBullet(actor->getHalfExtents()); halfExtents[2] = 1.0f; btCylinderShapeZ base(halfExtents); world->convexSweepTest(&base, from, to, newTraceCallback); if(newTraceCallback.hasHit()) { const btVector3& tracehitnormal = newTraceCallback.m_hitNormalWorld; mFraction = newTraceCallback.m_closestHitFraction; mPlaneNormal = osg::Vec3f(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z()); mEndPos = (end-start)*mFraction + start; mEndPos[2] += 1.0f; } else { mEndPos = end; mPlaneNormal = osg::Vec3f(0.0f, 0.0f, 1.0f); mFraction = 1.0f; } }
void PhysicsEngine::RegisterObject(ModelNode *pItem){ /********************************************************************* *ADDING SHAPES **********************************************************************/ if (dynamic_cast<Shape*>(pItem) != NULL) { Shape* pNodeShape = (Shape*) pItem; /************************************ *ADDING A RAYCAST VEHICLE ************************************/ if(dynamic_cast<SimRaycastVehicle*>(pNodeShape)!=NULL){ bullet_vehicle btRayVehicle( pItem, dynamics_world_.get(), vehicle_raycaster_); CollisionShapePtr pShape( btRayVehicle.getBulletShapePtr() ); MotionStatePtr pMotionState( btRayVehicle.getBulletMotionStatePtr() ); RigidBodyPtr body( btRayVehicle.getBulletBodyPtr() ); VehiclePtr vehicle( btRayVehicle.getBulletRaycastVehicle() ); std::shared_ptr<Vehicle_Entity> pEntity( new Vehicle_Entity ); pEntity->m_pRigidBody = body; pEntity->m_pShape = pShape; pEntity->m_pMotionState = pMotionState; pEntity->m_pVehicle = vehicle; ray_vehicles_map_[pItem->GetName()] = pEntity; } //Box if (dynamic_cast<BoxShape*>( pNodeShape ) != NULL) { bullet_cube btBox(pItem); CollisionShapePtr pShape( btBox.getBulletShapePtr() ); MotionStatePtr pMotionState( btBox.getBulletMotionStatePtr() ); RigidBodyPtr body( btBox.getBulletBodyPtr() ); dynamics_world_->addRigidBody( body.get() ); //Save the object; easier deconstruction this way. std::shared_ptr<Entity> pEntity( new Entity ); pEntity->m_pRigidBody = body; pEntity->m_pShape = pShape; pEntity->m_pMotionState = pMotionState; shapes_map_[pItem->GetName()] = pEntity; } //Cylinder else if (dynamic_cast<CylinderShape*>( pNodeShape ) != NULL) { bullet_cylinder btCylinder(pItem); CollisionShapePtr pShape( btCylinder.getBulletShapePtr() ); MotionStatePtr pMotionState( btCylinder.getBulletMotionStatePtr() ); RigidBodyPtr body( btCylinder.getBulletBodyPtr() ); dynamics_world_->addRigidBody( body.get() ); //Save the object; easier deconstruction this way. std::shared_ptr<Entity> pEntity( new Entity ); pEntity->m_pRigidBody = body; pEntity->m_pShape = pShape; pEntity->m_pMotionState = pMotionState; shapes_map_[pItem->GetName()] = pEntity; } //Plane else if (dynamic_cast<PlaneShape*>( pNodeShape ) != NULL) { bullet_plane btPlane(pItem); CollisionShapePtr pShape( btPlane.getBulletShapePtr() ); MotionStatePtr pMotionState( btPlane.getBulletMotionStatePtr() ); RigidBodyPtr body( btPlane.getBulletBodyPtr() ); dynamics_world_->addRigidBody( body.get() ); //Save the object; easier deconstruction this way. std::shared_ptr<Entity> pEntity( new Entity ); pEntity->m_pRigidBody = body; pEntity->m_pShape = pShape; pEntity->m_pMotionState = pMotionState; shapes_map_[pItem->GetName()] = pEntity; } //Heightmap else if (dynamic_cast<HeightmapShape*>( pNodeShape ) != NULL) { bullet_heightmap btMap(pItem); CollisionShapePtr pShape( btMap.getBulletShapePtr() ); MotionStatePtr pMotionState( btMap.getBulletMotionStatePtr() ); RigidBodyPtr body( btMap.getBulletBodyPtr() ); dynamics_world_->addRigidBody( body.get() ); //Save the object; easier deconstruction this way. std::shared_ptr<Entity> pEntity( new Entity ); pEntity->m_pRigidBody = body; pEntity->m_pShape = pShape; pEntity->m_pMotionState = pMotionState; shapes_map_[pItem->GetName()] = pEntity; } //Mesh else if (dynamic_cast<MeshShape*>( pNodeShape ) != NULL){ bullet_mesh btMesh(pItem); CollisionShapePtr pShape( btMesh.getBulletShapePtr() ); MotionStatePtr pMotionState( btMesh.getBulletMotionStatePtr() ); RigidBodyPtr body( btMesh.getBulletBodyPtr() ); dynamics_world_->addRigidBody( body.get() ); //Save the object; easier deconstruction this way. std::shared_ptr<Entity> pEntity( new Entity ); pEntity->m_pRigidBody = body; pEntity->m_pShape = pShape; pEntity->m_pMotionState = pMotionState; shapes_map_[pItem->GetName()] = pEntity; } } /********************************************************************* *ADDING CONSTRAINTS **********************************************************************/ else if (dynamic_cast<Constraint*>(pItem) != NULL) { Constraint* pNodeCon = (Constraint*) pItem; // Point to Point if (dynamic_cast<PToPOne*>( pNodeCon ) != NULL) { PToPOne* pCon = (PToPOne*) pNodeCon; btRigidBody* RigidShape_A; if(isVehicle(pCon->m_Shape_A)){ std::shared_ptr<Vehicle_Entity> Shape_A = ray_vehicles_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_A = shapes_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } btVector3 pivot_A(pCon->m_pivot_in_A[0], pCon->m_pivot_in_A[1], pCon->m_pivot_in_A[2]); btPoint2PointConstraint* PToP = new btPoint2PointConstraint(*RigidShape_A, pivot_A); dynamics_world_->addConstraint(PToP); ptop_map_[pCon->GetName()] = PToP; } else if(dynamic_cast<PToPTwo*>( pNodeCon ) != NULL) { PToPTwo* pCon = (PToPTwo*) pNodeCon; btRigidBody* RigidShape_A; btRigidBody* RigidShape_B; if(isVehicle(pCon->m_Shape_A)){ std::shared_ptr<Vehicle_Entity> Shape_A = ray_vehicles_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_A = shapes_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } if(isVehicle(pCon->m_Shape_B)){ std::shared_ptr<Vehicle_Entity> Shape_B = ray_vehicles_map_.at(pCon->m_Shape_B); RigidShape_B = Shape_B->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_B = shapes_map_.at(pCon->m_Shape_B); RigidShape_B = Shape_B->m_pRigidBody.get(); } btVector3 pivot_A(pCon->m_pivot_in_A[0], pCon->m_pivot_in_A[1], pCon->m_pivot_in_A[2]); btVector3 pivot_B(pCon->m_pivot_in_B[0], pCon->m_pivot_in_B[1], pCon->m_pivot_in_B[2]); btPoint2PointConstraint* PToP = new btPoint2PointConstraint(*RigidShape_A, *RigidShape_B, pivot_A, pivot_B); dynamics_world_->addConstraint(PToP); ptop_map_[pCon->GetName()] = PToP; } //Hinge else if(dynamic_cast<HingeOnePivot*>( pNodeCon ) != NULL) { HingeOnePivot* pCon = (HingeOnePivot*) pNodeCon; btRigidBody* RigidShape_A; if(isVehicle(pCon->m_Shape_A)){ std::shared_ptr<Vehicle_Entity> Shape_A = ray_vehicles_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_A = shapes_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } btVector3 pivot_A(pCon->m_pivot_in_A[0], pCon->m_pivot_in_A[1], pCon->m_pivot_in_A[2]); btVector3 axis_A(pCon->m_axis_in_A[0], pCon->m_axis_in_A[1], pCon->m_axis_in_A[2]); btHingeConstraint* Hinge = new btHingeConstraint(*RigidShape_A, pivot_A, axis_A, true); Hinge->setLimit(pCon->m_low_limit, pCon->m_high_limit, pCon->m_softness, pCon->m_bias, pCon->m_relaxation); dynamics_world_->addConstraint(Hinge); hinge_map_[pCon->GetName()] = Hinge; } else if(dynamic_cast<HingeTwoPivot*>( pNodeCon ) != NULL) { HingeTwoPivot* pCon = (HingeTwoPivot*) pNodeCon; btRigidBody* RigidShape_A; btRigidBody* RigidShape_B; if(isVehicle(pCon->m_Shape_A)){ std::shared_ptr<Vehicle_Entity> Shape_A = ray_vehicles_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_A = shapes_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } if(isVehicle(pCon->m_Shape_B)){ std::shared_ptr<Vehicle_Entity> Shape_B = ray_vehicles_map_.at(pCon->m_Shape_B); RigidShape_B = Shape_B->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_B = shapes_map_.at(pCon->m_Shape_B); RigidShape_B = Shape_B->m_pRigidBody.get(); } btVector3 pivot_A(pCon->m_pivot_in_A[0], pCon->m_pivot_in_A[1], pCon->m_pivot_in_A[2]); btVector3 axis_A(pCon->m_axis_in_A[0], pCon->m_axis_in_A[1], pCon->m_axis_in_A[2]); btVector3 pivot_B(pCon->m_pivot_in_B[0], pCon->m_pivot_in_B[1], pCon->m_pivot_in_B[2]); btVector3 axis_B(pCon->m_axis_in_B[0], pCon->m_axis_in_B[1], pCon->m_axis_in_B[2]); btHingeConstraint* Hinge = new btHingeConstraint(*RigidShape_A, *RigidShape_B, pivot_A, pivot_B, axis_A, axis_B, true); Hinge->setLimit(pCon->m_low_limit, pCon->m_high_limit, pCon->m_softness, pCon->m_bias, pCon->m_relaxation); dynamics_world_->addConstraint(Hinge); hinge_map_[pCon->GetName()] = Hinge; } //Hinge2 else if(dynamic_cast<Hinge2*>( pNodeCon ) != NULL) { Hinge2* pCon = (Hinge2*) pNodeCon; btRigidBody* RigidShape_A; btRigidBody* RigidShape_B; if(isVehicle(pCon->m_Shape_A)){ std::shared_ptr<Vehicle_Entity> Shape_A = ray_vehicles_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_A = shapes_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } if(isVehicle(pCon->m_Shape_B)){ std::shared_ptr<Vehicle_Entity> Shape_B = ray_vehicles_map_.at(pCon->m_Shape_B); RigidShape_B = Shape_B->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_B = shapes_map_.at(pCon->m_Shape_B); RigidShape_B = Shape_B->m_pRigidBody.get(); } btVector3 btAnchor(pCon->m_Anchor[0], pCon->m_Anchor[1], pCon->m_Anchor[2]); btVector3 btAxis_1(pCon->m_Axis_1[0], pCon->m_Axis_1[1], pCon->m_Axis_1[2]); btVector3 btAxis_2(pCon->m_Axis_2[0], pCon->m_Axis_2[1], pCon->m_Axis_2[2]); btHinge2Constraint* Hinge = new btHinge2Constraint(*RigidShape_A, *RigidShape_B, btAnchor, btAxis_1, btAxis_2); Hinge->setAngularLowerLimit(toBulletVec3(pCon->m_LowerAngLimit)); Hinge->setAngularUpperLimit(toBulletVec3(pCon->m_UpperAngLimit)); Hinge->setLinearLowerLimit(toBulletVec3(pCon->m_LowerLinLimit)); Hinge->setLinearUpperLimit(toBulletVec3(pCon->m_UpperLinLimit)); Hinge->enableSpring(3, true); Hinge->setStiffness(3, pCon->m_stiffness); Hinge->setDamping(3, pCon->m_damping); dynamics_world_->addConstraint(Hinge); hinge2_map_[pCon->GetName()] = Hinge; } //SixDOF else if(dynamic_cast<SixDOFOne*>( pNodeCon ) != NULL) { SixDOFOne* pCon = (SixDOFOne*) pNodeCon; std::shared_ptr<Entity> Shape_A = shapes_map_.at(pCon->m_Shape_A); btTransform trans_A = toBullet(_Cart2T(pCon->m_Transform_A)); btGeneric6DofConstraint* SixDOF = new btGeneric6DofConstraint(*Shape_A->m_pRigidBody.get(), trans_A, true); SixDOF->setLinearLowerLimit(toBulletVec3(pCon->m_LowerLinLimit)); SixDOF->setLinearUpperLimit(toBulletVec3(pCon->m_UpperLinLimit)); SixDOF->setAngularLowerLimit(toBulletVec3(pCon->m_LowerAngLimit)); SixDOF->setAngularUpperLimit(toBulletVec3(pCon->m_UpperAngLimit)); dynamics_world_->addConstraint(SixDOF); sixdof_map_[pCon->GetName()] = SixDOF; } else if(dynamic_cast<SixDOFTwo*>( pNodeCon ) != NULL) { SixDOFTwo* pCon = (SixDOFTwo*) pNodeCon; btRigidBody* RigidShape_A; btRigidBody* RigidShape_B; if(isVehicle(pCon->m_Shape_A)){ std::shared_ptr<Vehicle_Entity> Shape_A = ray_vehicles_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_A = shapes_map_.at(pCon->m_Shape_A); RigidShape_A = Shape_A->m_pRigidBody.get(); } if(isVehicle(pCon->m_Shape_B)){ std::shared_ptr<Vehicle_Entity> Shape_B = ray_vehicles_map_.at(pCon->m_Shape_B); RigidShape_B = Shape_B->m_pRigidBody.get(); } else{ std::shared_ptr<Entity> Shape_B = shapes_map_.at(pCon->m_Shape_B); RigidShape_B = Shape_B->m_pRigidBody.get(); } btTransform trans_A = toBullet(_Cart2T(pCon->m_Transform_A)); btTransform trans_B = toBullet(_Cart2T(pCon->m_Transform_B)); btGeneric6DofConstraint* SixDOF = new btGeneric6DofConstraint(*RigidShape_A, *RigidShape_B, trans_A, trans_B, true); SixDOF->setLinearLowerLimit(toBulletVec3(pCon->m_LowerLinLimit)); SixDOF->setLinearUpperLimit(toBulletVec3(pCon->m_UpperLinLimit)); SixDOF->setAngularLowerLimit(toBulletVec3(pCon->m_LowerAngLimit)); SixDOF->setAngularUpperLimit(toBulletVec3(pCon->m_UpperAngLimit)); dynamics_world_->addConstraint(SixDOF); sixdof_map_[pCon->GetName()] = SixDOF; } } return; }
void rePlayer::messageProcess( reMessageDispatcher* sender, reMessage* message ) { reVec3 deltaAngle(0,0,0); float rs = .5f; switch (message->id) { case reM_TIMER: if (model()) { reVec3 dirZ = reVec3(model()->worldTransform().matrix * reVec4(0,0,-1, 0)); reVec3 dirX = reVec3(model()->worldTransform().matrix * reVec4(1,0,0, 0)); if (reRadial::shared()->input()->keyStates['W']) { body->btBody->applyCentralForce(toBullet(dirZ * 50.0f)); } if (reRadial::shared()->input()->keyStates['S']) { body->btBody->applyCentralForce(toBullet(dirZ * -50.0f)); } if (reRadial::shared()->input()->keyStates[' ']) { body->btBody->applyCentralForce(toBullet(dirX * 1.0f)); //reVec4 f = worldTransform().matrix * reVec4(0,-200,0,0); //btVector3 bf(f.x, f.y, f.z); //body->btBody->applyCentralForce(bf); } if (reRadial::shared()->input()->keyStates['A']) { reVec3 v = reVec3(glm::rotate(reMat4(), rs, reVec3(0,1,0)) * reVec4(fromBullet(body->btBody->getLinearVelocity()), 0)); body->btBody->setLinearVelocity(toBullet(v)); model()->transform(glm::rotate(reMat4(), rs, reVec3(0,1,0)) * model()->transform().matrix); //body->btBody->applyCentralForce(toBullet(f)); } if (reRadial::shared()->input()->keyStates['D']) { reVec3 v = reVec3(glm::rotate(reMat4(), -rs, reVec3(0,1,0)) * reVec4(fromBullet(body->btBody->getLinearVelocity()), 0)); body->btBody->setLinearVelocity(toBullet(v)); model()->transform(glm::rotate(reMat4(), -rs, reVec3(0,1,0)) * model()->transform().matrix); //deltaAngle += reVec3(0,-1,0); //model()->transform(glm::rotate(reMat4(), -1.0f, reVec3(0,1,0)) * model()->transform().matrix); } reVec3 pos = worldTransform().position(); camera->lookAt(pos); light->lookAt(pos); if (pos.y < calculateVertex(reVec4(pos,1)).y) { //__debugbreak(); } break; } } if (glm::length(fromBullet(body->btBody->getLinearVelocity()))) { reVec3 dir = glm::normalize(fromBullet(body->btBody->getLinearVelocity())); if (!dir.z) { return; } float yaw = dir.z < 0 ? glm::atan(dir.x / dir.z) : M_PI - glm::atan(dir.x / -dir.z); float pitch = glm::atan(dir.y / abs(dir.z)); reMat4 y(glm::rotate(reMat4(), glm::degrees(yaw), reVec3(0,1,0))); reMat4 p(glm::rotate(reMat4(), glm::degrees(pitch), reVec3(1,0,0))); model()->children->at(0)->transform(p); reVec3 da = reVec3(0, glm::degrees(yaw), 0) - camera->lookAngles(); camera->lookAngles(camera->lookAngles() + da / 5.0f ); } }
void Bullet::setGravityVector(const Vec3& gravity) { gravityVector_ = gravity; dynamicsWorld_->setGravity(toBullet(gravityVector_)); }
void compileProject(Path rootPath, irr::scene::ISceneManager* smgr) { pRoot = rootPath; FMain fMain; std::vector<FObject> fObjects; std::vector<FResource> fResources; // Main file { std::cout << "Loading main file..." << std::endl; Json::Value jrMain; // Read { std::ifstream rMain(pRoot + "/" + pMain); if(!rMain.is_open()) { std::cout << "Aborted! Could not read main file!" << std::endl; return; } rMain >> jrMain; } fMain.name = toString(jrMain["name"], "Unnamed Content Pack"); fMain.namesp = toString(jrMain["namespace"], "anon"); fMain.desc = toString(jrMain["description"], "No description available."); // Load authors { const Json::Value& jrMainObjects = jrMain["authors"]; if(jrMainObjects.isArray()) { for(Json::Value::iterator it = jrMainObjects.begin(); it != jrMainObjects.end(); ++ it) { fMain.authors.push_back(toString(*it)); } } else { fMain.authors.push_back(toString(jrMainObjects, "Anonymous")); } } // Load object reference list { const Json::Value& jrMainObjects = jrMain["objects"]; if(jrMainObjects.isArray()) { for(Json::Value::iterator it = jrMainObjects.begin(); it != jrMainObjects.end(); ++ it) { Path objPath = toString(*it); fMain.refObjects.push_back(Referen(objPath)); } } else if(jrMainObjects.isString()) { Path objPath = jrMainObjects.asString(); fMain.refObjects.push_back(Referen(objPath)); } else { std::cout << "Aborted! Cannot parse objects list!" << std::endl; return; } } } // Object files { std::cout << "Loading object files..."; for(std::vector<Referen>::iterator it = fMain.refObjects.begin(); it != fMain.refObjects.end(); ++ it) { const Referen& refObject = *it; Path refContext = getDirectory(refObject.absPath); FObject fObject; Json::Value jrObject; { std::ifstream rObject(pRoot + "/" + refObject.absPath); if(!rObject.is_open()) { std::cout << "Aborted! Could not read " + refObject.absPath + "!" << std::endl; return; } rObject >> jrObject; } fObject.id = toString(jrObject["id"]); Path pModel = toString(jrObject["model"]); fObject.refModel = Referen(pModel, refContext); FResource fModel; fModel.refSelf = fObject.refModel; fModel.type = MODEL; fResources.push_back(fModel); Path pPhysics = toString(jrObject["physics"]); fObject.refPhysics = Referen(pPhysics, refContext); FResource fPhys; fPhys.refSelf = fObject.refPhysics; fPhys.type = PHYSICS; fResources.push_back(fPhys); fObject.physOffset = toBullet(jrObject["physics-offset"]); fObject.refSelf = refObject; fObjects.push_back(fObject); } } std::cout << "Compiling entire project..." << std::endl; // Main file { std::cout << "Compiling main file..." << std::endl; // Construct new json file Json::Value jwMain; // Simple strings jwMain["name"] = fMain.name; jwMain["namespace"] = fMain.namesp; jwMain["description"] = fMain.desc; // Authors { Json::Value& jwMainAuthors = jwMain["authors"]; for(std::vector<std::string>::iterator it = fMain.authors.begin(); it != fMain.authors.end(); ++ it) { jwMainAuthors.append(*it); } } // Objects { Json::Value& jwMainAuthors = jwMain["objects"]; for(std::vector<Referen>::iterator it = fMain.refObjects.begin(); it != fMain.refObjects.end(); ++ it) { const Referen& referen = *it; jwMainAuthors.append(referen.qualifiedName); } } // Also clean the folder { std::string winCmd; winCmd = "del /q \"" + pOutputRoot + "\\" + fMain.name + "\\*.*\""; std::system(winCmd.c_str()); winCmd = "mkdir \"" + pOutputRoot + "/" + fMain.name + "\""; std::system(winCmd.c_str()); } std::ofstream wMain(pOutputRoot + "/" + fMain.name + "/content-pack.json"); if(!wMain.is_open()) { std::cout << "Aborted! Could not write to main file!" << std::endl; return; } wMain << jwMain; } // Object files { std::cout << "Compiling object definition files..." << std::endl; for(std::vector<FObject>::iterator it = fObjects.begin(); it != fObjects.end(); ++ it) { const FObject& fObject = *it; // Construct new json file Json::Value jwObject; // Simple strings jwObject["id"] = fObject.id; jwObject["model"] = fObject.refModel.qualifiedName; jwObject["physics"] = fObject.refPhysics.qualifiedName; jwObject["physics-offset"] = toJson(fObject.physOffset); std::ofstream wObject(pOutputRoot + "/" + fMain.name + "/" + fObject.refSelf.qualifiedName); if(!wObject.is_open()) { std::cout << "Aborted! Could not write to object file " << fObject.refSelf.qualifiedName << std::endl; return; } wObject << jwObject; } } // Resource files { std::cout << "Compiling resources" << std::endl; for(std::vector<FResource>::iterator it = fResources.begin(); it != fResources.end(); ++ it) { const FResource& fResource = *it; Path output = pOutputRoot + "/" + fMain.name + "/" + fResource.refSelf.qualifiedName; switch(fResource.type) { /* case MODEL: { } */ case PHYSICS: { std::ifstream rResource(pRoot + "/" + fResource.refSelf.absPath); if(!rResource.is_open()) { std::cout << "Aborted! Could not read " << fResource.refSelf.absPath << "!" << std::endl; return; } std::string extension = getExtension(fResource.refSelf.absPath); FPhysics physShape; if(extension == "json") { Json::Value jwPhysics; rResource >> jwPhysics; std::string strType = jwPhysics["type"].asString(); if(strType == "sphere") { physShape.type = SPHERE; physShape.radius = jwPhysics["radius"].asDouble(); } else if(strType == "box") { physShape.type = BOX; physShape.dimensions = toBullet(jwPhysics["size"]); } else if(strType == "cylinder") { physShape.type = CYLINDER; physShape.dimensions = toBullet(jwPhysics["size"]); } else if(strType == "capsule") { physShape.type = CAPSULE; physShape.radius = jwPhysics["radius"].asDouble(); physShape.height = jwPhysics["height"].asDouble(); } else if(strType == "cone") { physShape.type = CONE; physShape.radius = jwPhysics["radius"].asDouble(); physShape.height = jwPhysics["height"].asDouble(); } } else { } output = shaveExtension(output); ReiIO::savePhysics(output + ".physics", physShape); break; } case MODEL: { reia::ComplexMeshData* meshData = reia::loadUsingAssimp(smgr, pRoot + "/" + fResource.refSelf.absPath); reia::ComplexMeshSceneNode* meshNode = reia::addNodeFromMesh(smgr, meshData); delete meshNode; output = shaveExtension(output); ReiIO::saveComplexMesh(output + ".model", *meshData); delete meshData; break; } default: { } } }