// Creates a Box object, including the associated Bullet rigid // body, and sets its collision shape to a bullet box shape. // If the object is specified to be kinematic, then the appropriate setup // is done to the rigid body to make it kinematic within Bullet. // position: where to create the box. // dimensions: the dimensions of the box // density: the density of the box (which, with the dimensions, determines its mass) // isKinematic: flag to determine if this object will be kinematic or not Box::Box(double position[3], double dimensions[3], double density, bool isKinematic) { x = dimensions[0]; y = dimensions[1]; z = dimensions[2]; double mass = x * y * z * density; btCollisionShape* boxCollision = new btBoxShape(btVector3(x * 0.5, y * 0.5, z * 0.5)); btDefaultMotionState* boxState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(position[0], position[1], position[2]))); btVector3 boxInertia(0, 0, 0); boxCollision->calculateLocalInertia(mass, boxInertia); btRigidBody::btRigidBodyConstructionInfo boxInfo(mass, boxState, boxCollision, boxInertia); btRigidBody* rb = new btRigidBody(boxInfo); // set the kinematic flag and set up the rigid body as kinematic if necessary setKinematic(isKinematic); if (isKinematic) { rb->setCollisionFlags(rb->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); rb->setActivationState(DISABLE_DEACTIVATION); } // set the rigid body associated with this SceneObject. setRigidBody(rb); }
PhysicsRigidBody::PhysicsRigidBody(Node* node, const PhysicsCollisionShape::Definition& shape, const Parameters& parameters, int group, int mask) : PhysicsCollisionObject(node, group, mask), _body(NULL), _mass(parameters.mass), _constraints(NULL), _inDestructor(false) { GP_ASSERT(Game::getInstance()->getPhysicsController()); GP_ASSERT(_node); // Create our collision shape. kmVec3 centerOfMassOffset = vec3Zero; _collisionShape = Game::getInstance()->getPhysicsController()->createShape(node, shape, ¢erOfMassOffset, parameters.mass != 0.0f); GP_ASSERT(_collisionShape && _collisionShape->getShape()); // Create motion state object. _motionState = new PhysicsMotionState(node, this, (kmVec3LengthSq(¢erOfMassOffset) > MATH_EPSILON) ? ¢erOfMassOffset : NULL); // If the mass is non-zero, then the object is dynamic so we calculate the local // inertia. However, if the collision shape is a triangle mesh, we don't calculate // inertia since Bullet doesn't currently support this. btVector3 localInertia(0.0, 0.0, 0.0); if (parameters.mass != 0.0) _collisionShape->getShape()->calculateLocalInertia(parameters.mass, localInertia); // Create the Bullet physics rigid body object. btRigidBody::btRigidBodyConstructionInfo rbInfo(parameters.mass, NULL, _collisionShape->getShape(), localInertia); rbInfo.m_friction = parameters.friction; rbInfo.m_restitution = parameters.restitution; rbInfo.m_linearDamping = parameters.linearDamping; rbInfo.m_angularDamping = parameters.angularDamping; // Create + assign the new bullet rigid body object. _body = bullet_new<btRigidBody>(rbInfo); // Set motion state after rigid body assignment, since bullet will callback on the motion state interface to query // the initial transform and it will need to access to rigid body (_body). _body->setMotionState(_motionState); // Set other initially defined properties. setKinematic(parameters.kinematic); setAnisotropicFriction(parameters.anisotropicFriction); setAngularFactor(parameters.angularFactor); setLinearFactor(parameters.linearFactor); // Add ourself to the physics world. Game::getInstance()->getPhysicsController()->addCollisionObject(this); if (_collisionShape->getType() == PhysicsCollisionShape::SHAPE_HEIGHTFIELD) { // Add a listener on the node's transform so we can track dirty changes to calculate // an inverse kmMat4 for transforming heightfield points between world and local space. _node->addListener(this); } }
PhysicsRigidBody::PhysicsRigidBody(Node* node, const PhysicsCollisionShape::Definition& shape, const Parameters& parameters) : PhysicsCollisionObject(node), _body(NULL), _mass(parameters.mass), _constraints(NULL), _inDestructor(false) { GP_ASSERT(Game::getInstance()->getPhysicsController()); GP_ASSERT(_node); // Create our collision shape. Vector3 centerOfMassOffset; _collisionShape = Game::getInstance()->getPhysicsController()->createShape(node, shape, ¢erOfMassOffset); GP_ASSERT(_collisionShape && _collisionShape->getShape()); // Create motion state object. _motionState = new PhysicsMotionState(node, (centerOfMassOffset.lengthSquared() > MATH_EPSILON) ? ¢erOfMassOffset : NULL); // If the mass is non-zero, then the object is dynamic so we calculate the local // inertia. However, if the collision shape is a triangle mesh, we don't calculate // inertia since Bullet doesn't currently support this. btVector3 localInertia(0.0, 0.0, 0.0); if (parameters.mass != 0.0 && _collisionShape->getType() != PhysicsCollisionShape::SHAPE_MESH) _collisionShape->getShape()->calculateLocalInertia(parameters.mass, localInertia); // Create the Bullet physics rigid body object. btRigidBody::btRigidBodyConstructionInfo rbInfo(parameters.mass, _motionState, _collisionShape->getShape(), localInertia); rbInfo.m_friction = parameters.friction; rbInfo.m_restitution = parameters.restitution; rbInfo.m_linearDamping = parameters.linearDamping; rbInfo.m_angularDamping = parameters.angularDamping; // Create + assign the new bullet rigid body object. _body = bullet_new<btRigidBody>(rbInfo); // Set other initially defined properties. setKinematic(parameters.kinematic); setAnisotropicFriction(parameters.anisotropicFriction); setGravity(parameters.gravity); // Add ourself to the physics world. Game::getInstance()->getPhysicsController()->addCollisionObject(this); if (_collisionShape->getType() == PhysicsCollisionShape::SHAPE_HEIGHTFIELD) { // Add a listener on the node's transform so we can track dirty changes to calculate // an inverse matrix for transforming heightfield points between world and local space. _node->addListener(this); } }
void EntityMotionState::updateKinematicState(uint32_t substep) { setKinematic(_entity->isMoving(), substep); }
bool Physics3DKinematicDemo::init() { if (!Physics3DTestDemo::init()) return false; //create floor Physics3DRigidBodyDes rbDes; rbDes.mass = 0.0f; rbDes.shape = Physics3DShape::createBox(Vec3(60.0f, 1.0f, 60.0f)); auto floor = PhysicsSprite3D::create("Sprite3DTest/box.c3t", &rbDes); floor->setTexture("Sprite3DTest/plane.png"); floor->setScaleX(60); floor->setScaleZ(60); floor->setPosition3D(Vec3(0.f, -1.f, 0.f)); this->addChild(floor); floor->setCameraMask((unsigned short)CameraFlag::USER1); floor->syncNodeToPhysics(); //static object sync is not needed floor->setSyncFlag(Physics3DComponent::PhysicsSyncFlag::NONE); //create Kinematics for (unsigned int i = 0; i < 3; ++i) { rbDes.mass = 0.f; //kinematic objects. zero mass so that it can not be affected by other dynamic objects rbDes.shape = Physics3DShape::createBox(Vec3(2.0f, 2.0f, 2.0f)); auto sprite = PhysicsSprite3D::create("Sprite3DTest/box.c3t", &rbDes); sprite->setTexture("Images/CyanSquare.png"); sprite->setCameraMask((unsigned short)CameraFlag::USER1); auto rigidBody = static_cast<Physics3DRigidBody*>(sprite->getPhysicsObj()); rigidBody->setKinematic(true); this->addChild(sprite); sprite->setScale(2.0f); sprite->setPosition3D(Vec3(-15.0f, 0.0f, 15.0f - 15.0f * i)); auto moveby = MoveBy::create(2.0f + i, Vec3(30.0f, 0.0f, 0.0f)); sprite->runAction(RepeatForever::create(Sequence::create(moveby, moveby->reverse(), nullptr))); } //create Dynamic { //create several spheres rbDes.mass = 1.f; rbDes.shape = Physics3DShape::createSphere(0.5f); float start_x = START_POS_X - ARRAY_SIZE_X/2; float start_y = START_POS_Y + 5.0f; float start_z = START_POS_Z - ARRAY_SIZE_Z/2; for (int k=0;k<ARRAY_SIZE_Y;k++) { for (int i=0;i<ARRAY_SIZE_X;i++) { for(int j = 0;j<ARRAY_SIZE_Z;j++) { float x = 1.0*i + start_x; float y = 5.0+1.0*k + start_y; float z = 1.0*j + start_z; rbDes.originalTransform.setIdentity(); rbDes.originalTransform.translate(x, y, z); auto sprite = PhysicsSprite3D::create("Sprite3DTest/sphere.c3b", &rbDes); sprite->setTexture("Sprite3DTest/plane.png"); sprite->setCameraMask((unsigned short)CameraFlag::USER1); sprite->setScale(1.0f / sprite->getContentSize().width); this->addChild(sprite); sprite->setPosition3D(Vec3(x, y, z)); sprite->syncNodeToPhysics(); sprite->setSyncFlag(Physics3DComponent::PhysicsSyncFlag::PHYSICS_TO_NODE); } } } } physicsScene->setPhysics3DDebugCamera(_camera); return true; }
bool Physics3DColliderDemo::init() { if (!Physics3DTestDemo::init()) return false; Physics3DRigidBodyDes rbDes; rbDes.mass = 1.0f; rbDes.shape = Physics3DShape::createBox(Vec3(3.0f, 3.0f, 3.f)); auto playerBody = Physics3DRigidBody::create(&rbDes); auto component = Physics3DComponent::create(playerBody); playerBody->setKinematic(true); auto sprite = Sprite3D::create("Sprite3DTest/box.c3t"); sprite->setTexture("Sprite3DTest/plane.png"); sprite->setScale(3.f); sprite->setPosition3D(Vec3(0.0f, 0.f, 30.f)); sprite->addComponent(component); sprite->setCameraMask((unsigned short)CameraFlag::USER1); auto moveby = MoveBy::create(5.0f, Vec3(0.0f, 0.0f, -60.0f)); sprite->runAction(RepeatForever::create(Sequence::create(moveby, moveby->reverse(), nullptr))); this->addChild(sprite); { Physics3DColliderDes colliderDes; colliderDes.shape = Physics3DShape::createSphere(10.0f); colliderDes.isTrigger = true; auto collider = Physics3DCollider::create(&colliderDes); auto component = Physics3DComponent::create(collider); auto node = Node::create(); node->addComponent(component); node->setCameraMask((unsigned short)CameraFlag::USER1); this->addChild(node); Physics3DRigidBodyDes rbDes; rbDes.mass = 1.0f; rbDes.shape = Physics3DShape::createBox(Vec3(10.0f, 10.0f, 1.f)); auto rigidBody = Physics3DRigidBody::create(&rbDes); component = Physics3DComponent::create(rigidBody); rigidBody->setKinematic(true); auto doorLeft = Sprite3D::create("Sprite3DTest/box.c3t"); doorLeft->setTexture("Sprite3DTest/plane.png"); doorLeft->setScaleX(10.0f); doorLeft->setScaleY(10.0f); doorLeft->setScaleZ(1.0f); doorLeft->setPosition3D(Vec3(-5.0f, 0.0f, 0.0f)); doorLeft->addComponent(component); doorLeft->setCameraMask((unsigned short)CameraFlag::USER1); node->addChild(doorLeft); rbDes.mass = 1.0f; rbDes.shape = Physics3DShape::createBox(Vec3(10.0f, 10.0f, 1.f)); rigidBody = Physics3DRigidBody::create(&rbDes); component = Physics3DComponent::create(rigidBody); rigidBody->setKinematic(true); auto doorRight = Sprite3D::create("Sprite3DTest/box.c3t"); doorRight->setTexture("Sprite3DTest/plane.png"); doorRight->setScaleX(10.0f); doorRight->setScaleY(10.0f); doorRight->setScaleZ(1.0f); doorRight->setPosition3D(Vec3(5.0f, 0.0f, 0.0f)); doorRight->addComponent(component); doorRight->setCameraMask((unsigned short)CameraFlag::USER1); node->addChild(doorRight); collider->onTriggerEnter = [=](Physics3DObject *otherObject){ if (otherObject == playerBody){ auto moveby = MoveBy::create(1.0f, Vec3(-5.0f, 0.0f, 0.0f)); doorLeft->runAction(moveby); doorRight->runAction(moveby->reverse()); } }; collider->onTriggerExit = [=](Physics3DObject *otherObject){ if (otherObject == playerBody){ auto moveby = MoveBy::create(1.0f, Vec3(5.0f, 0.0f, 0.0f)); doorLeft->runAction(moveby); doorRight->runAction(moveby->reverse()); } }; } physicsScene->setPhysics3DDebugCamera(_camera); return true; }