hkpConvexVerticesShape* FindConvexShape(bool share_shapes, std::vector<hkpConvexVerticesShape*>& shapes, const PINT_CONVEX_CREATE& convex_create, const hkStridedVertices& strided_verts) { if(share_shapes && convex_create.mRenderer) { const int size = shapes.size(); for(int i=0;i<size;i++) { hkpConvexVerticesShape* CurrentShape = shapes[i]; if(CurrentShape->getUserData()==hkUlong(convex_create.mRenderer)) { CurrentShape->addReference(); return CurrentShape; } } } hkpConvexVerticesShape* shape = new hkpConvexVerticesShape(strided_verts); ASSERT(shape); shapes.push_back(shape); if(convex_create.mRenderer) shape->setUserData(hkUlong(convex_create.mRenderer)); return shape; }
hkpBoxShape* FindBoxShape(bool share_shapes, std::vector<hkpBoxShape*>& shapes, const PINT_BOX_CREATE& box_create) { const hkVector4 halfExtents = ToHkVector4(box_create.mExtents); if(share_shapes) { const int size = shapes.size(); for(int i=0;i<size;i++) { hkpBoxShape* CurrentShape = shapes[i]; const hkVector4& CurrentExtents = CurrentShape->getHalfExtents(); if( CurrentExtents(0)==halfExtents(0) && CurrentExtents(1)==halfExtents(1) && CurrentExtents(2)==halfExtents(2)) { CurrentShape->addReference(); return CurrentShape; } } } hkpBoxShape* shape = new hkpBoxShape(halfExtents, 0); ASSERT(shape); shapes.push_back(shape); if(box_create.mRenderer) shape->setUserData(hkUlong(box_create.mRenderer)); return shape; }
hkpCapsuleShape* FindCapsuleShape(bool share_shapes, std::vector<InternalCapsuleShape>& shapes, const PINT_CAPSULE_CREATE& capsule_create) { const float Radius = capsule_create.mRadius; const float HalfHeight = capsule_create.mHalfHeight; if(share_shapes) { const int size = shapes.size(); for(int i=0;i<size;i++) { const InternalCapsuleShape& CurrentShape = shapes[i]; if(CurrentShape.mRadius==Radius && CurrentShape.mHalfHeight==HalfHeight) { CurrentShape.mShape->addReference(); return CurrentShape.mShape; } } } const hkVector4 vertexA(0.0f, HalfHeight, 0.0f); const hkVector4 vertexB(0.0f, -HalfHeight, 0.0f); hkpCapsuleShape* shape = new hkpCapsuleShape(vertexA, vertexB, capsule_create.mRadius); ASSERT(shape); InternalCapsuleShape ICS; ICS.mShape = shape; ICS.mRadius = Radius; ICS.mHalfHeight = HalfHeight; shapes.push_back(ICS); if(capsule_create.mRenderer) shape->setUserData(hkUlong(capsule_create.mRenderer)); return shape; }
hkpSphereShape* FindSphereShape(bool share_shapes, std::vector<hkpSphereShape*>& shapes, const PINT_SPHERE_CREATE& sphere_create) { const float Radius = sphere_create.mRadius; if(share_shapes) { const int size = shapes.size(); for(int i=0;i<size;i++) { hkpSphereShape* CurrentShape = shapes[i]; if(CurrentShape->getRadius()==Radius) { CurrentShape->addReference(); return CurrentShape; } } } hkpSphereShape* shape = new hkpSphereShape(Radius); ASSERT(shape); shapes.push_back(shape); if(sphere_create.mRenderer) shape->setUserData(hkUlong(sphere_create.mRenderer)); return shape; }
udword Havok::CreateConvexObject(const PINT_CONVEX_DATA_CREATE& desc) { hkStridedVertices StridedVerts; StridedVerts.m_numVertices = desc.mNbVerts; StridedVerts.m_striding = sizeof(Point); StridedVerts.m_vertices = &desc.mVerts->x; // hkpConvexVerticesShape* shape = FindConvexShape(gShareShapes, mConvexShapes, *ConvexCreate, StridedVerts); hkpConvexVerticesShape* shape = new hkpConvexVerticesShape(StridedVerts); ASSERT(shape); if(desc.mRenderer) shape->setUserData(hkUlong(desc.mRenderer)); const udword CurrentSize = mConvexObjects.size(); mConvexObjects.push_back(shape); return CurrentSize; /* btConvexHullShape* shape = new btConvexHullShape(&desc.mVerts->x, desc.mNbVerts, sizeof(Point)); ASSERT(shape); if(desc.mRenderer) shape->setUserPointer(desc.mRenderer); const udword CurrentSize = mConvexObjects.size(); mConvexObjects.push_back(shape); return CurrentSize;*/ }
void SlidingWorldDemo::addBodiesNewlyInsideSimulationAreaToSimulation() { m_world->lock(); hkpBroadPhase* bp = m_world->getBroadPhase(); hkAabb broadphaseAabb; bp->getExtents( broadphaseAabb.m_min, broadphaseAabb.m_max); for (int i = 0; i < m_boxes.getSize(); i++) { hkpRigidBody* rb = m_boxes[i]; // If we're not in simulation, check if we're now inside the simulation area/broadphase if( rb->getWorld() == HK_NULL ) { // In general you'd have some world object management code here. In our case, we'll just check if the current // aabb of the body would be fully contained inside the new broadphase location. hkAabb rbAabb; rb->getCollidable()->getShape()->getAabb(rb->getTransform(), 0, rbAabb); if (broadphaseAabb.contains(rbAabb)) { m_world->addEntity( rb ); // Color them slightly green so they are clearly marked as newly added HK_SET_OBJECT_COLOR(hkUlong(rb->getCollidable()), hkColor::rgbFromChars(200, 255, 200)); } } } m_world->unlock(); }
void BreakOffPartsDemo::removeSubShapeFromDisplay(hkpRigidBody* body, hkpListShape* listShape, int shapeKey) { // get the vertex set hkgVertexSet* vertexSet; { int geometryIndex = shapeKey; const hkpCollidable* collidable = body->getCollidable(); hkgDisplayObject* displayObject = m_env->m_displayHandler->findDisplayObject(hkUlong(collidable)); hkgGeometry* geometry = displayObject->getGeometry(geometryIndex); hkgFaceSet* faceSet = geometry->getMaterialFaceSet(0)->getFaceSet(0); vertexSet = faceSet->getVertexSet(); } // Simply zero-out all vertices. This will degenerate the triangles but that should be ok. { m_env->m_window->getContext()->lock(); vertexSet->lock(HKG_LOCK_WRITEDISCARD); hkVector4 newPos(0,0,0); for (int i = 0; i < vertexSet->getNumVerts(); i++) { vertexSet->setVertexComponentData(HKG_VERTEX_COMPONENT_POS, i, &newPos(0)); } vertexSet->unlock(); m_env->m_window->getContext()->unlock(); } }
InteractiveFloor::InteractiveFloor(Ogre::Vector3 Pos, Ogre::Vector3 size, Physics * physics, Ogre::SceneManager * manager) :Floor(Pos, size, physics, manager) { Body->setUserData(hkUlong(this)); }
void PlatformsCharacterRbDemo::cameraHandling() { const hkReal height = .7f; hkVector4 forward; forward.set(1,0,0); forward.setRotatedDir( m_currentOrient, forward ); hkVector4 from, to; to = m_characterRigidBody->getPosition(); to.addMul4(height, UP ); hkVector4 dir; dir.setMul4( height, UP ); dir.addMul4( -8.f, forward); from.setAdd4(to, dir); // Make object in line of sight transparent { // Cast down to landscape to get an accurate position hkpWorldRayCastInput raycastIn; // Reverse direction for collision detection raycastIn.m_from = to; raycastIn.m_to = from; raycastIn.m_filterInfo = hkpGroupFilter::calcFilterInfo(0); hkpAllRayHitCollector collector; m_world->castRay( raycastIn, collector); hkLocalArray<hkUlong> transp(5); // Loop over all collected objects for(int i=0; i < collector.getHits().getSize();i++) { hkpWorldRayCastOutput raycastOut = collector.getHits()[i]; transp.pushBack(hkUlong(raycastOut.m_rootCollidable)); } // loop over display ids for(int i=0; i < m_objectIds.getSize();i++) { if(transp.indexOf(m_objectIds[i]) != -1) { HK_SET_OBJECT_COLOR(m_objectIds[i], TRANSPARENT_GREY); } else { HK_SET_OBJECT_COLOR(m_objectIds[i],NORMAL_GRAY); } } } setupDefaultCameras(m_env, from , to, UP, 1.0f); }
InteractiveWall::InteractiveWall(Ogre::Vector3 Pos, Ogre::Vector3 size,Physics * physics, Ogre::SceneManager * manager, float rotation) : Wall(Pos, size, physics, manager, rotation) { Body->setUserData(hkUlong(this)); }
Wall::Wall(Ogre::Vector3 Pos, Ogre::Vector3 size,Physics * physics, Ogre::SceneManager * manager, float rotation) : StaticObject(Pos, Ogre::Vector3(size.x, size.y, 20.0f), "cube.mesh", physics, manager) { mOrintation = Ogre::Quaternion(Ogre::Radian(Ogre::Degree(rotation)), Ogre::Vector3(0,1,0)); hkVector4 HalfSize( mSize.x / 2.0, mSize.y / 2.0, mSize.z / 2.0); hkpBoxShape* Hbox = new hkpBoxShape(HalfSize,0); Hbox->setRadius(0.0f); hkpRigidBodyCinfo WallInfo; WallInfo.m_mass = 100.0f; hkMassProperties massProperties; hkpInertiaTensorComputer::computeBoxVolumeMassProperties( HalfSize, WallInfo.m_mass, massProperties); WallInfo.m_mass = massProperties.m_mass; WallInfo.m_centerOfMass = massProperties.m_centerOfMass; WallInfo.m_inertiaTensor = massProperties.m_inertiaTensor; WallInfo.m_solverDeactivation = WallInfo.SOLVER_DEACTIVATION_MEDIUM; WallInfo.m_shape = Hbox; WallInfo.m_restitution = 0.0f; WallInfo.m_qualityType = HK_COLLIDABLE_QUALITY_FIXED; WallInfo.m_motionType = hkpMotion::MOTION_FIXED; WallInfo.m_rotation = hkQuaternion(mOrintation.x, mOrintation.y, mOrintation.z, mOrintation.w); WallInfo.m_position = hkVector4(mPosition.x,mPosition.y,mPosition.z); Body = new hkpRigidBody(WallInfo); Body->setUserData(hkUlong(this)); mPhysicsManager->GetPhysicsWorld()->addEntity(Body); ObjectNode->setScale(mSize.x / ObjectEnt->getBoundingBox().getSize().x, mSize.y / ObjectEnt->getBoundingBox().getSize().y, mSize.z / ObjectEnt->getBoundingBox().getSize().z); ObjectNode->setPosition(Ogre::Vector3(Body->getPosition()(0), Body->getPosition()(1),Body->getPosition()(2))); ObjectEnt->setMaterialName("Examples/RustySteel"); hkQuaternion GetBodyAngle = Body->getRotation(); hkVector4 GetrotationAxis(0,0,0); if(GetBodyAngle.hasValidAxis()) { GetBodyAngle.getAxis(GetrotationAxis); } Ogre::Quaternion UpdateOrintation(Ogre::Radian(GetBodyAngle.getAngle()), Ogre::Vector3(GetrotationAxis(0),GetrotationAxis(1),GetrotationAxis(2))); ObjectNode->setOrientation(UpdateOrintation); }
Turret::Turret(Ogre::Vector3 Pos, Ogre::SceneManager* manager, Physics* physicsManager) : DynamicObject( Pos, "cube.mesh", Ogre::Vector3(20.0,50.0,20.0), Ogre::Quaternion( Ogre::Radian(0), Ogre::Vector3(0,1,0)), manager, physicsManager ) ,mRotateValue(0) ,mChangeInRotation(0.001) ,mKillTimer(0) ,mShutdown(false) { hkVector4 HalfSize( mSize.x / 2.0, mSize.y / 2.0, mSize.z / 2.0); hkpBoxShape* Hbox = new hkpBoxShape(HalfSize,0); Hbox->setRadius(0.0f); hkpRigidBodyCinfo TurretInfo; TurretInfo.m_mass = 5000.0f; hkMassProperties massProperties; hkpInertiaTensorComputer::computeBoxVolumeMassProperties( HalfSize, TurretInfo.m_mass, massProperties); TurretInfo.m_mass = massProperties.m_mass; TurretInfo.m_centerOfMass = hkVector4(massProperties.m_centerOfMass(0),massProperties.m_centerOfMass(1) - 20,massProperties.m_centerOfMass(2)); TurretInfo.m_inertiaTensor = massProperties.m_inertiaTensor; TurretInfo.m_solverDeactivation = TurretInfo.SOLVER_DEACTIVATION_MEDIUM; TurretInfo.m_shape = Hbox; TurretInfo.m_restitution = 0.0f; TurretInfo.m_qualityType = HK_COLLIDABLE_QUALITY_MOVING; TurretInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA; TurretInfo.m_rotation = hkQuaternion(mOrintation.x, mOrintation.y, mOrintation.z, mOrintation.w); TurretInfo.m_position = hkVector4(mPosition.x,mPosition.y,mPosition.z); Body = new hkpRigidBody(TurretInfo); Body->setUserData(hkUlong(this)); mPhysicsManager->GetPhysicsWorld()->addEntity(Body); ObjectNode->setScale(mSize.x / ObjectEnt->getBoundingBox().getSize().x, mSize.y / ObjectEnt->getBoundingBox().getSize().y, mSize.z / ObjectEnt->getBoundingBox().getSize().z); ObjectNode->setPosition(Ogre::Vector3(Body->getPosition()(0), Body->getPosition()(1),Body->getPosition()(2))); }
hkpShape* CreateMeshShape(const PINT_MESH_CREATE& create, HavokMeshFormat format, std::vector<HavokMeshRender>& meshes, PintShapeRenderer* renderer) { if(/*gShareMeshData &&*/renderer) { const udword Size = meshes.size(); for(udword i=0;i<Size;i++) { const HavokMeshRender& CurrentMesh = meshes[i]; if(CurrentMesh.mRenderer==renderer) { return CurrentMesh.mTriangleMesh; } } } hkpShape* S = CreateMeshShape(create, format); meshes.push_back(HavokMeshRender(S, renderer)); if(create.mRenderer) S->setUserData(hkUlong(create.mRenderer)); return S; }
Create::Create(Ogre::Vector3 Pos, Ogre::SceneManager* manager, Physics* physicsManager) : DynamicObject( Pos, "cube.mesh", Ogre::Vector3(34.0,34.0,34.0), Ogre::Quaternion( Ogre::Radian(0), Ogre::Vector3(0,1,0)), manager, physicsManager ) ,Hit(false) { hkVector4 HalfSize( mSize.x / 2.0, mSize.y / 2.0, mSize.z / 2.0); hkpBoxShape* Hbox = new hkpBoxShape(HalfSize,0); Hbox->setRadius(0.0f); hkpRigidBodyCinfo CreateInfo; CreateInfo.m_mass = 100.0f; hkMassProperties massProperties; hkpInertiaTensorComputer::computeBoxVolumeMassProperties( HalfSize, CreateInfo.m_mass, massProperties); CreateInfo.m_mass = massProperties.m_mass; CreateInfo.m_centerOfMass = massProperties.m_centerOfMass; CreateInfo.m_inertiaTensor = massProperties.m_inertiaTensor; CreateInfo.m_solverDeactivation = CreateInfo.SOLVER_DEACTIVATION_MEDIUM; CreateInfo.m_shape = Hbox; CreateInfo.m_restitution = 0.0f; CreateInfo.m_qualityType = HK_COLLIDABLE_QUALITY_MOVING; CreateInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA; CreateInfo.m_rotation = hkQuaternion(mOrintation.x, mOrintation.y, mOrintation.z, mOrintation.w); CreateInfo.m_position = hkVector4(mPosition.x,mPosition.y,mPosition.z); Body = new hkpRigidBody(CreateInfo); Body->setUserData(hkUlong(this)); RecptorFront = mOrintation * Ogre::Vector3::UNIT_X; RecptorSide = mOrintation * Ogre::Vector3::UNIT_Z; mPhysicsManager->GetPhysicsWorld()->addEntity(Body); ObjectNode->setScale(mSize.x / ObjectEnt->getBoundingBox().getSize().x, mSize.y / ObjectEnt->getBoundingBox().getSize().y, mSize.z / ObjectEnt->getBoundingBox().getSize().z); ObjectNode->setPosition(Ogre::Vector3(Body->getPosition()(0), Body->getPosition()(1),Body->getPosition()(2))); }
BallAndSocketRopeDemo::BallAndSocketRopeDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env, DEMO_FLAGS_NO_SERIALIZE) { const BallAndSocketRopeVariant& variant = g_variants[env->m_variantId]; // // Setup the camera // { hkVector4 from(0.0f, -10.0f, 6.0f); hkVector4 to (0.0f, 0.0f, 1.0f); hkVector4 up (0.0f, 0.0f, 1.0f); setupDefaultCameras( env, from, to, up, 0.1f, 500.0f ); } // // Create the world // { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 1000.0f ); info.m_gravity.set(0.0f, 0.0f, -9.81f); m_world = new hkpWorld( info ); m_world->lock(); m_world->m_wantDeactivation = false; setupGraphics(); // // Create a group filter to avoid intra-collision for the rope // { hkpGroupFilter* filter = new hkpGroupFilter(); m_world->setCollisionFilter( filter ); filter->removeReference(); } } hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() ); // // Create debris // { int numDebris = 40; hkPseudoRandomGenerator generator(0xF14); hkpRigidBodyCinfo info; hkVector4 top; top.set(0.0f, 0.0f, 0.50f); hkVector4 bottom; bottom.set(0.f, 0.f, -0.50f); info.m_shape = new hkpCapsuleShape( top, bottom, 0.3f ); hkpInertiaTensorComputer::setShapeVolumeMassProperties( info.m_shape, 5.0f, info ); for (int d = 0; d < numDebris; d++) { hkReal xPos = generator.getRandRange(-10.0f, 10.0f); hkReal yPos = generator.getRandRange(-10.0f, 10.0f); hkBool isDynamic = (generator.getRand32() % 4) != 0; info.m_position.set( xPos, yPos, isDynamic ? 0.8f : 0.5f ); info.m_motionType = isDynamic ? hkpMotion::MOTION_DYNAMIC : hkpMotion::MOTION_FIXED; hkpRigidBody* debris = new hkpRigidBody(info); m_world->addEntity(debris); debris->removeReference(); } info.m_shape->removeReference(); } // // Create ground box // { hkpRigidBodyCinfo info; info.m_motionType = hkpMotion::MOTION_FIXED; info.m_shape = new hkpBoxShape( hkVector4(100.0f, 100.0f, 0.1f) ); info.m_position(2) = - 0.1f; hkpRigidBody* ground = new hkpRigidBody(info); info.m_shape->removeReference(); m_world->addEntity(ground); ground->removeReference(); HK_SET_OBJECT_COLOR( hkUlong(ground->getCollidable()), 0xff339933); } // // Create fixed peg over the ground // { hkpRigidBodyCinfo info; info.m_motionType = hkpMotion::MOTION_FIXED; info.m_shape = new hkpCapsuleShape( hkVector4(0.0f, 1.0f, 0.0f), hkVector4( 0,-1.0f, 0), 0.3f ); info.m_position.set(0.0f, 0.0f, 3.0f); hkpRigidBody* peg = new hkpRigidBody(info); info.m_shape->removeReference(); m_world->addEntity(peg); peg->removeReference(); } // // Create chain // { hkReal elemHalfSize = 0.075f; hkpShape* sphereShape = new hkpSphereShape(0.3f); hkpShape* capsuleShape = new hkpCapsuleShape( hkVector4(elemHalfSize, 0.0f, 0.0f), hkVector4(-elemHalfSize, 0.0f, 0.0f), 0.03f ); hkpRigidBodyCinfo info; info.m_linearDamping = 0.0f; info.m_angularDamping = 0.3f; info.m_friction = 0.0f; //info.m_qualityType = HK_COLLIDABLE_QUALITY_MOVING; info.m_motionType = hkpMotion::MOTION_SPHERE_INERTIA; info.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(1, 1); { hkArray<hkpRigidBody*> entities; for (int b = 0; b < variant.m_numBodies; b++) { info.m_position.set(elemHalfSize * 2.0f * (b - hkReal(variant.m_numBodies-1) / 2.0f), 0.0f, 4.0f); hkReal mass; hkReal inertiaMultiplier; if (0 == b || variant.m_numBodies-1 == b) { info.m_shape = sphereShape; mass = 10.0f; inertiaMultiplier = 1.0f; } else { info.m_shape = capsuleShape; mass = 1.0f; inertiaMultiplier = 50.0f; } hkpInertiaTensorComputer::setShapeVolumeMassProperties(info.m_shape, inertiaMultiplier * mass, info); info.m_mass = mass; { hkpRigidBody* body = new hkpRigidBody(info); m_world->addEntity(body); entities.pushBack(body); } } { // connect all the bodies hkpConstraintChainInstance* chainInstance; { hkpBallSocketChainData* chainData = new hkpBallSocketChainData(); chainInstance = new hkpConstraintChainInstance( chainData ); chainInstance->addEntity( entities[0] ); for (int e = 1; e < entities.getSize(); e++) { chainData->addConstraintInfoInBodySpace( hkVector4(elemHalfSize, 0.0f, 0.0f), hkVector4( -elemHalfSize, 0.0f, 0.0f) ); chainInstance->addEntity( entities[e] ); } chainData->removeReference(); } m_world->addConstraint(chainInstance); chainInstance->removeReference(); } for (int i = 0; i < entities.getSize(); i++) { entities[i]->removeReference(); } } sphereShape->removeReference(); capsuleShape->removeReference(); } m_world->unlock(); }
void ConcreteFractureCollisionListener::contactPointConfirmedCallback( hkpContactPointConfirmedEvent& event) { m_randomSeed++; // Check whether our velocity is strong enough to fracture the body. // You might also want to check the type of object, the mass, volume and the material // (soft ball hardly fractures a piece of glass) if (event.m_projectedVelocity < -m_fractureVelocity ) { // // get and fix the direction of the normal; // hkContactPoint cp = *event.m_contactPoint; if (event.m_callbackFiredFrom->getCollidable() == event.m_collidableA) { hkVector4 tmp; tmp.setNeg4(cp.getSeparatingNormal()); cp.setSeparatingNormal(tmp); } // get the hitting body, e.g. the bullet hkpRigidBody* otherBody = reinterpret_cast<hkpRigidBody*>(hkUlong(event.m_callbackFiredFrom) ^ hkUlong(event.m_collidableA->getOwner()) ^ hkUlong(event.m_collidableB->getOwner())); // Remember the bullets velocity so we can revert the bullet body back to its original velocity. // // The reasons is: // - that this callback is called just before the bullet's velocities are updated // (either in the PSI-integrate step or in a TOI-event-handling function), // - and at the world is locked at the time of this callback, so the bullet still interacts with the old/original // unfractured body (instead of with the intended fractured pieces), // // So, to have a 'more' proper fracturing interaction we do: // - reset the velocity of the fracturing bullet once the fractured body is replaced by // its resulting pieces and the world is unlocked, // - reintegrate and re-collide the bullet body, so that it collides with the fractured pieces // hkVector4 linearVel = otherBody->getLinearVelocity(); hkVector4 angularVel = otherBody->getAngularVelocity(); SetBodyVelocityAsCriticalOperation* callback = new SetBodyVelocityAsCriticalOperation(otherBody, linearVel, angularVel, true); // // Fracture the piece // hkpRigidBody* originalBody = static_cast<hkpRigidBody*>(event.m_callbackFiredFrom); HK_ASSERT2(0xad23eb33, originalBody, "This listener must be attached as a hkpEntity-CollisonListener."); originalBody->removeCollisionListener(this); hkpWorld* world = otherBody->getWorld(); hkInplaceArray<hkpRigidBody*, 32> newBodies; createFracturedRigidBodyPieces(world, originalBody, cp, newBodies); // // Replace the body with fractured pieces. // world->removeEntity(originalBody); world->addEntityBatch(reinterpret_cast<hkpEntity**>(newBodies.begin()), newBodies.getSize()); // // Add our undo velocities to the delayed operation queue. It will be executed as // soon as all our fractured pieces are all added to the world. // if (!otherBody->isFixedOrKeyframed() ) { if (!event.m_callbackFiredFrom->isFixedOrKeyframed()) { // Warning: this can cause multiple TOI events. It is not safe with fixedOrKeyframed bodies. world->queueCallback(callback); } } callback->removeReferenceLockUnchecked(); // // If an external hkArray<hkpRigidBody*> is supplied then export the references to new bodies. // if (m_fracturedBodies) { m_fracturedBodies->insertAt(m_fracturedBodies->getSize(), newBodies.begin(), newBodies.getSize() ); } else { for (int i = 0; i < newBodies.getSize(); i++) { newBodies[i]->removeReference(); } } } }
void hkFlattenShapeHierarchyUtil::getLeafShapesFromShape(const hkpShape* shape, const hkTransform& transform, const hkBool isFixedBody, hkArray<hkpExtendedMeshShape::TrianglesSubpart>& trianglePartsOut, hkArray<hkpConvexShape*>& convexShapesOut, hkArray<hkpShape*>& otherShapesOut) { const hkpShapeType type = shape->getType(); hkTransform newTransform; const hkpShape* childShape = HK_NULL; hkUlong userData = HK_NULL; switch(type) { case HK_SHAPE_LIST: case HK_SHAPE_CONVEX_LIST: { const hkpShapeContainer* container = shape->getContainer(); hkpShapeContainer::ShapeBuffer buffer; HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(shape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); hkUint16 materialId = hkUint16(0xffff & hkUlong(shape->getUserData())); for (hkpShapeKey key = container->getFirstKey(); key != HK_INVALID_SHAPE_KEY; key = container->getNextKey(key)) { const hkpShape* child = container->getChildShape(key, buffer); if (materialId && 0 == (0xffff & hkUlong(child->getUserData())) ) { // no material id for the child -- copy it hkUlong childData = hkUlong(child->getUserData()) | materialId; // Warning: modifying the const input hkpShape* const_cast<hkpShape*>(child)->setUserData(childData); } //HK_ASSERT2(0xad6777dd, isFixedBody || !isLeafShape(child), "A child of a list shape cannot be a terminal node. You must use a transform shape in between." ); getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } break; case HK_SHAPE_TRANSFORM: { const hkpTransformShape* transformShape = static_cast<const hkpTransformShape*>(shape); newTransform.setMul(transform, transformShape->getTransform()); childShape = transformShape->getChildShape(); userData = hkUlong(transformShape->getUserData()); } break; case HK_SHAPE_CONVEX_TRANSFORM: { const hkpConvexTransformShape* convexTransformShape = static_cast<const hkpConvexTransformShape*>(shape); newTransform.setMul(transform, convexTransformShape->getTransform()); childShape = convexTransformShape->getChildShape(); userData = hkUlong(convexTransformShape->getUserData()); } break; case HK_SHAPE_CONVEX_TRANSLATE: { const hkpConvexTranslateShape* convexTranslateShape = static_cast<const hkpConvexTranslateShape*>(shape); hkTransform localTransform( static_cast<const hkRotation&>(hkRotation::getIdentity()), convexTranslateShape->getTranslation() ); newTransform.setMul(transform, localTransform); childShape = convexTranslateShape->getChildShape(); userData = hkUlong(convexTranslateShape->getUserData()); } break; case HK_SHAPE_BV_TREE: { const hkpBvTreeShape* bvTreeshape = static_cast<const hkpBvTreeShape*>(shape); HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); const hkpShapeContainer* container = bvTreeshape->getContainer(); for (hkpShapeKey key = container->getFirstKey(); key!= HK_INVALID_SHAPE_KEY; key = container->getNextKey(key)) { hkpShapeContainer::ShapeBuffer buffer; const hkpShape* child = container->getChildShape(key, buffer); const hkpShapeType childType = child->getType(); if ((childType == HK_SHAPE_LIST) || (childType == HK_SHAPE_CONVEX_LIST)) { getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } break; } case HK_SHAPE_MOPP: { const hkpMoppBvTreeShape* bvTreeshape = static_cast<const hkpMoppBvTreeShape*>(shape); // HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); getLeafShapesFromShape(bvTreeshape->getShapeCollection(), transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); break; } default: { //HK_ASSERT2(0xad67ddaa, isFixedBody, "A child of a list was attached without an intermediate transform shape. This is not handled."); // We can get simple shapes without transforms when processing fixed bodies. We do add a hkpConvexTransformShape as usual then ... childShape = shape; newTransform = transform; userData = hkUlong(shape->getUserData()); //HK_ASSERT2(0XAD678D8D, 0 == (userData & 0xffff0000), "Userdata of a fixed body (other than the one fixed uber body) has a non-zero destructible info index."); } break; } if (HK_NULL != childShape) { hkBool leafDone = false; if (hkOneFixedMoppUtil::isTerminalConvexShape(childShape)) { // Create new transform shape to wrap the child terminal shape hkpConvexTransformShape* newConvexTransformShape = new hkpConvexTransformShape(static_cast<const hkpConvexShape*>(childShape), newTransform); newConvexTransformShape->setUserData( userData ); HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); // put this transform on the shapesOut list convexShapesOut.pushBack(newConvexTransformShape); leafDone = true; } else if (isLeafShape(childShape)) { // It's not a terminal(leaf?) convex shape, but it might be a mesh, or indeed a simplemesh. // It's most likely to be a storagemesh, but we can't assume that, so check vtable: const hkClass* childShapeClass = hkBuiltinTypeRegistry::getInstance().getVtableClassRegistry()->getClassFromVirtualInstance(childShape); if( hkpMeshShapeClass.isSuperClass(*childShapeClass) ) { const hkpMeshShape* mesh = static_cast<const hkpMeshShape*>(childShape); // Confirm vertex data not shared, see below #if defined(HK_DEBUG) { for(int i = 0; i < mesh->getNumSubparts(); i++) { const hkpMeshShape::Subpart& meshSubPartI = mesh->getSubpartAt(i); for(int j = i+1; j < mesh->getNumSubparts(); j++) { const hkpMeshShape::Subpart& meshSubPartJ = mesh->getSubpartAt(j); HK_ASSERT2(0x0, meshSubPartI.m_vertexBase != meshSubPartJ.m_vertexBase, "This method can't (currently) collapse chared meshs data as it collpases the transform into the verts\n"); } } } #endif for(int i = 0; i < mesh->getNumSubparts(); i++) { const hkpMeshShape::Subpart& meshSubPart = mesh->getSubpartAt(i); // Now we have the subpart. We can't know if the data pointed to is 'owned' by the mesh (eg. subclass hkpStorageMeshShape) // or 'pointed to' (base class hkpMeshShape) // // We'll just assume here we can 'share' the data by grabbing the pointers... hkpExtendedMeshShape::TrianglesSubpart extendedMeshSubPart; extendedMeshSubPart.m_vertexBase = meshSubPart.m_vertexBase; extendedMeshSubPart.m_vertexStriding = meshSubPart.m_vertexStriding; extendedMeshSubPart.m_numVertices = meshSubPart.m_numVertices; extendedMeshSubPart.m_triangleOffset = meshSubPart.m_triangleOffset; // .. but we'll have to multiply in the transform! This assumes the vertex data is not shared! { for(int j = 0; j < extendedMeshSubPart.m_numVertices ; j++) { hkVector4 v; v(0) = extendedMeshSubPart.m_vertexBase[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v(1) = extendedMeshSubPart.m_vertexBase[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v(2) = extendedMeshSubPart.m_vertexBase[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v.setTransformedPos(transform, v); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(0); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(1); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(2); } } extendedMeshSubPart.m_indexBase = meshSubPart.m_indexBase; extendedMeshSubPart.m_indexStriding = meshSubPart.m_indexStriding; extendedMeshSubPart.m_numTriangleShapes = meshSubPart.m_numTriangles; extendedMeshSubPart.m_stridingType = (meshSubPart.m_stridingType == hkpMeshShape::INDICES_INT16) ? hkpExtendedMeshShape::INDICES_INT16 : hkpExtendedMeshShape::INDICES_INT32; trianglePartsOut.pushBack(extendedMeshSubPart); leafDone = true; } } } if(!leafDone) { HK_WARN(0xad678dda, "An extra hkTransform shape has been inserted into the hierarchy. This might be suboptimal."); // Create new transform shape to wrap the child terminal shape hkpTransformShape* newTransformShape = new hkpTransformShape(childShape, newTransform); newTransformShape->setUserData( userData ); HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); // put this transform on the shapesOut list otherShapesOut.pushBack(newTransformShape); leafDone = true; } if(!leafDone) { //HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & shape->getUserData()), "We're dropping a non-zero user data."); if ( 0xffff0000 & hkUlong(shape->getUserData()) ) { // copy the destruction info index downwards.. HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & hkUlong(shape->getUserData())) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); //HK_WORLD_ACCESS_CHECK(parentBody->getWorld(), HK_ACCESS_RW ); // Warning: we're actually modifying the const hkpShape* passed as an input parameter const_cast<hkpShape*>(childShape)->setUserData( shape->getUserData() ); } getLeafShapesFromShape(childShape, newTransform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } }
CrashTestDummiesDemo::CrashTestDummiesDemo(hkDemoEnvironment* env): hkDefaultPhysicsDemo( env ) { // Disable warnings: hkError::getInstance().setEnabled(0xafe97523, false); //'This utility is intended primarily for Havok demo use. If you wish to step the world asynchronously,...' // XXX remove once async stepping fixed hkpWorld::IgnoreForceMultithreadedSimulation ignoreForceMultithreaded; enableDisplayingToiInformation(true); m_ragdoll = HK_NULL; // // Create the world // { hkpWorldCinfo info; info.m_gravity.set( 0.0f, 0.0f, -10.0f ); //info.m_enableDeactivation = false; info.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_CONTINUOUS; //info.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_BACKSTEP_SIMPLE; m_world = new hkpWorld( info ); m_world->lock(); // Register ALL agents (though some may not be necessary) hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); } // // Collision Filter // { m_filter = new hkpGroupFilter(); hkpGroupFilterSetup::setupGroupFilter( m_filter ); m_world->setCollisionFilter(m_filter); } // // Setup the camera // { hkVector4 from(0.0f, 8.0f, 3.0f); hkVector4 to(0.0f, 0.0f, 1.0f); hkVector4 up(0.0f, 0.0f, 1.0f); setupDefaultCameras( env, from, to, up, 1.f, 1000.0f ); setupGraphics(); } m_car = createSimpleCarHull(); m_world->addEntity( m_car )->removeReference(); HK_SET_OBJECT_COLOR(hkUlong(m_car->getCollidable()), hkColor::rgbFromChars(255, 255, 255, 50)); fitRagdollsIn(hkVector4::getZero()); //hkVector4 pos(3.0f, 1.0f, 0.8f); //putBoxesIn( pos ); //putBoxesIn(hkVector4(4.1f, 1.0f, 0.8f)); createGroundBox(); createFastObject(); m_world->unlock(); }
PlatformsCharacterRbDemo::PlatformsCharacterRbDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // Setup the graphics { // Disable back face culling setGraphicsState(HKG_ENABLED_CULLFACE, false); // don't really want shadows as makes it too dark forceShadowState(false); setupLights(m_env); // so that the extra lights are added // allow color change on precreated objects m_env->m_displayHandler->setAllowColorChangeOnPrecreated(true); } // Create the world { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 350.0f ); info.m_gravity.set(0,0,-9.8f); info.m_collisionTolerance = 0.01f; m_world = new hkpWorld( info ); m_world->lock(); hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // Load the level { m_loader = new hkLoader(); hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Physics/levels/test_platform.hkx"); hkRootLevelContainer* container = m_loader->load( assetFile.cString() ); HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset"); hkxScene* scene = reinterpret_cast<hkxScene*>( container->findObjectByType( hkxSceneClass.getName() )); HK_ASSERT2(0x27343635, scene, "No scene loaded"); env->m_sceneConverter->convert( scene, hkgAssetConverter::CONVERT_ALL ); hkpPhysicsData* physics = reinterpret_cast<hkpPhysicsData*>( container->findObjectByType( hkpPhysicsDataClass.getName() )); HK_ASSERT2(0x27343635, physics, "No physics loaded"); // Physics if (physics) { const hkArray<hkpPhysicsSystem*>& psys = physics->getPhysicsSystems(); // Tie the two together for (int i=0; i<psys.getSize(); i++) { hkpPhysicsSystem* system = psys[i]; // Change the layer of the rigid bodies for (int rb=0; rb < system->getRigidBodies().getSize(); rb++) { const hkUlong id = hkUlong(system->getRigidBodies()[rb]->getCollidable()); HK_SET_OBJECT_COLOR(id,NORMAL_GRAY); m_objectIds.pushBack(id); } // Associate the display and physics (by name) if (scene) { addPrecreatedDisplayObjectsByName( psys[i]->getRigidBodies(), scene ); } // add the lot to the world m_world->addPhysicsSystem(system); } } } // Add horizontal keyframed platform { hkpShape* platform = new hkpBoxShape(hkVector4(1.5,2.5,0.25)); hkpRigidBodyCinfo rbci; rbci.m_shape = platform; rbci.m_motionType = hkpMotion::MOTION_KEYFRAMED; rbci.m_position.set(2.5f, 0.0f, 0.25f); rbci.m_friction = 1.0f; rbci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(hkpGroupFilter::calcFilterInfo(1)); m_horPlatform = new hkpRigidBody(rbci); platform->removeReference(); m_world->addEntity(m_horPlatform); m_horPlatform->removeReference(); } // Add vertical keyframed platform { hkpShape* platform = new hkpBoxShape(hkVector4(1.5,2.5,0.25)); hkpRigidBodyCinfo rbci; rbci.m_shape = platform; rbci.m_motionType = hkpMotion::MOTION_KEYFRAMED; rbci.m_position.set(-3.5f, 0.0f, 3.25f); rbci.m_friction = 1.0f; rbci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(hkpGroupFilter::calcFilterInfo(1)); m_verPlatform = new hkpRigidBody(rbci); platform->removeReference(); m_world->addEntity(m_verPlatform); m_verPlatform->removeReference(); } // Create a character rigid body { // Create a capsule to represent the character standing hkVector4 vertexA(0,0, 0.4f); hkVector4 vertexB(0,0,-0.4f); m_standShape = new hkpCapsuleShape(vertexA, vertexB, .6f); // Construct a character rigid body hkpCharacterRigidBodyCinfo info; info.m_mass = 100.0f; info.m_shape = m_standShape; info.m_maxForce = 1000.0f; info.m_up = UP; info.m_position.set(0.0f, 5.0f, 1.5f); info.m_maxSlope = HK_REAL_PI/2.0f; m_characterRigidBody = new hkpCharacterRigidBody( info ); m_world->addEntity( m_characterRigidBody->getRigidBody() ); } // Create the character state machine { hkpCharacterState* state; hkpCharacterStateManager* manager = new hkpCharacterStateManager(); state = new hkpCharacterStateOnGround(); manager->registerState( state, HK_CHARACTER_ON_GROUND); state->removeReference(); state = new hkpCharacterStateInAir(); manager->registerState( state, HK_CHARACTER_IN_AIR); state->removeReference(); state = new hkpCharacterStateJumping(); manager->registerState( state, HK_CHARACTER_JUMPING); state->removeReference(); state = new hkpCharacterStateClimbing(); manager->registerState( state, HK_CHARACTER_CLIMBING); state->removeReference(); m_characterContext = new hkpCharacterContext(manager, HK_CHARACTER_ON_GROUND); m_characterContext->setCharacterType(hkpCharacterContext::HK_CHARACTER_RIGIDBODY); manager->removeReference(); } // Set colors of platforms HK_SET_OBJECT_COLOR(hkUlong(m_verPlatform->getCollidable()),hkColor::BLUE); HK_SET_OBJECT_COLOR(hkUlong(m_horPlatform->getCollidable()),hkColor::GREEN); // Set global time m_time = 0.0f; // Initialize hkpSurfaceInfo for previous ground m_previousGround = new hkpSurfaceInfo(); m_framesInAir = 0; // Current camera angle about up m_currentAngle = HK_REAL_PI * 0.5f; m_world->unlock(); }
hkDemo::Result SlidingWorldDemo::stepDemo() { makeFakeInput(); hkBool doShift = false; hkVector4 newCenter; handleKeys(doShift, newCenter); m_world->lock(); if(doShift) { // reset the box colors to a light grey for (int i = 0; i < m_boxes.getSize(); i++) { HK_SET_OBJECT_COLOR(hkUlong(m_boxes[i]->getCollidable()), hkColor::LIGHTGREY); } { //hkVector4 currentCenter = m_centers[((m_ticks / delay) + (numCenters-1)) % numCenters]; //HK_DISPLAY_STAR(currentCenter, 2.5f, 0xFF00FF00); //HK_DISPLAY_LINE(nextCenter, m_currentCenter, 0xFF00FF00); } hkVector4 diff; diff.setSub4(newCenter, m_currentCenter); hkArray<hkpBroadPhaseHandle*> objectsEnteringBroadphaseBorder; hkVector4 effectiveShift; if( g_variants[m_variantId].m_mode == SlidingWorldDemoVariant::RECENTER_BROAD_PHASE_ONLY ) { recenterBroadPhaseVariant(diff, objectsEnteringBroadphaseBorder, effectiveShift); } else // SlidingWorldDemoVariant::SHIFT_COORDINATE_SPACE) { shiftCoordinateSystemVariant(diff, objectsEnteringBroadphaseBorder, effectiveShift); } removeDuplicatesFromArray(objectsEnteringBroadphaseBorder); // Some bodies may have to be removed from simulation, some may need to be added. { removeBodiesLeavingBroadphaseFromSimulation(objectsEnteringBroadphaseBorder); addBodiesNewlyInsideSimulationAreaToSimulation(); } m_currentCenter = newCenter; } // draw the grid in cyan { hkVector4 minOffset; minOffset.set(-5, 1, -5); hkVector4 maxOffset; maxOffset.set(5,1,5); hkVector4 min, max; for (int i = -2; i <= 2; i++) for (int j = -2; j <= 2; j++) { min.set((hkReal)10*i, 0, (hkReal)10*j); max = min; min.add4(minOffset); max.add4(maxOffset); drawAabb(min, max, hkColor::CYAN ); } } // draw the broadphase extents in red displayCurrentBroadPhaseAabb(m_world, hkColor::RED ); // draw locations of all 'unsimulated' bodies drawUnsimulatedBodies(); if( m_currentMode == AUTOMATIC_SHIFT) { m_ticks++; } m_world->unlock(); return hkDefaultPhysicsDemo::stepDemo(); }
void DestructibleHierarchy::removeSubShapeFromDisplay(hkpRigidBody* moppRigidBody, hkpMoppBvTreeShape* moppShape, int subShapeKey) { if (!m_env) { return; } // // calculate the shape's index in the hkgDisplayObject's geometry array // int geometryIndex; { hkpShapeCollection::ShapeBuffer buffer; const hkpExtendedMeshShape* meshShape = static_cast<const hkpExtendedMeshShape*>( moppShape->getContainer()->getChildShape(0, buffer) ); hkpExtendedMeshShape::SubpartType type = meshShape->getSubpartType(subShapeKey); int subpartIndex = meshShape->getSubPartIndex(subShapeKey); geometryIndex = 0; if ( type == hkpExtendedMeshShape::SUBPART_TRIANGLES ) { geometryIndex = subpartIndex; } else // type == hkpExtendedMeshShape::SUBPART_SHAPE { // skip all triangle subparts geometryIndex += meshShape->getNumTrianglesSubparts(); // loop over all previous shape subparts { for (int i=0; i<subpartIndex; i++) { geometryIndex += meshShape->getShapesSubpartAt(i).m_numChildShapes; } } geometryIndex += meshShape->getTerminalIndexInSubPart(subShapeKey); } } // // get the terrain's vertex set // hkgVertexSet* vertexSet; { const hkpCollidable* collidable = moppRigidBody->getCollidable(); hkgDisplayObject* displayObject = m_env->m_displayHandler->findDisplayObject(hkUlong(collidable)); hkgGeometry* geometry = displayObject->getGeometry(geometryIndex); hkgFaceSet* faceSet = geometry->getMaterialFaceSet(0)->getFaceSet(0); vertexSet = faceSet->getVertexSet(); } m_env->m_window->getContext()->lock(); // vertex set has to be locked before any vertices can be manipulated vertexSet->lock(HKG_LOCK_WRITEDISCARD); { // // Simply zero-out all vertices. This will degenerate the triangles but that should be ok. // hkVector4 newPos(0,0,0); for (int i = 0; i < vertexSet->getNumVerts(); i++) { vertexSet->setVertexComponentData(HKG_VERTEX_COMPONENT_POS, i, &newPos(0)); } } // unlock the vertex set again vertexSet->unlock(); m_env->m_window->getContext()->unlock(); return; }
virtual void entityActivatedCallback(hkpEntity* entity) { HK_SET_OBJECT_COLOR( hkUlong(entity->getCollidable()), 0xff55ff55 ); }