void KeyframingDemo::createBodies() { // Each body needs at least one shape const hkVector4 halfExtents(1.0f, 0.75f, 1.0f); hkpShape* shape = new hkpBoxShape(halfExtents, 0 ); // Compute the inertia tensor from the shape hkpMassProperties massProperties; hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape, 5.0f, massProperties); // Assign the rigid body properties hkpRigidBodyCinfo bodyInfo; bodyInfo.m_mass = massProperties.m_mass; bodyInfo.m_centerOfMass = massProperties.m_centerOfMass; bodyInfo.m_inertiaTensor = massProperties.m_inertiaTensor; bodyInfo.m_shape = shape; bodyInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA; bodyInfo.m_friction = 0.1f; for(int i = 0; i < m_numBodies; i++) { bodyInfo.m_position.set( hkMath::cos(hkReal(i)) - 2.0f, i * 2.0f, hkMath::sin(hkReal(i))); hkpRigidBody* body = new hkpRigidBody(bodyInfo); m_world->addEntity(body); body->removeReference(); } shape->removeReference(); }
void SpiderDemo::moveSpider( SpiderLayout& sl, hkReal time, hkReal leftVel, hkReal rightVel ) { int legId = 0; for (int posId = 0; posId < sl.m_numLegs; posId++ ) { hkReal xf = posId/hkReal(sl.m_numLegs-1)*2.0f - 1.0f; hkReal vel = leftVel; for (int z = -1; z <= 1; z+=2 ) { Leg& leg = m_legs[legId++]; moveLeg( sl, leg, hkReal(z), xf, time, vel ); vel = rightVel; } } }
// Raycast from the bottom (Y is up) to make sure that raycasting against the scaled mopp works void MoppInstancingDemo::checkRayCasts(const hkpMoppBvTreeShape* mopp, const hkTransform& t) { hkAabb aabb; mopp->getAabb(hkTransform::getIdentity(), 1.0f, aabb); hkVector4 extents; extents.setSub4(aabb.m_max, aabb.m_min); const int numX=10, numZ = 10; const hkReal deltaX = extents(0) / hkReal(numX-1); const hkReal deltaZ = extents(2) / hkReal(numZ-1); for (int x=0; x<numX; x++) { for (int z=0; z<numZ; z++) { hkpShapeRayCastInput input; hkpShapeRayCastOutput output; input.m_from(0) = aabb.m_min(0) + hkReal(x)*deltaX; input.m_from(1) = aabb.m_min(1) ; input.m_from(2) = aabb.m_min(2) + hkReal(z)*deltaZ; input.m_to = input.m_from; input.m_to(1) = aabb.m_max(1); input.m_rayShapeCollectionFilter = HK_NULL; mopp->castRay(input, output); hkVector4 worldFrom, worldTo; worldFrom.setTransformedPos(t, input.m_from); worldTo.setTransformedPos(t, input.m_to); if (output.hasHit()) { hkVector4 hitpoint; hitpoint.setInterpolate4(worldFrom, worldTo, output.m_hitFraction); HK_DISPLAY_LINE(worldFrom, hitpoint, hkColor::GREEN); } // Check that the naive raycast gives the same results hkpShapeRayCastOutput testOutput; mopp->getShapeCollection()->castRay(input, testOutput); HK_ASSERT(0x793171a3, hkMath::equal(testOutput.m_hitFraction, output.m_hitFraction) ); if ( !hkMath::equal(testOutput.m_hitFraction, 1.0f) ) { HK_ASSERT(0x793171a3, testOutput.m_normal.equals3(output.m_normal) ); } } } }
void CompressionDemo::AddAnimation(const char* name, hkaAnimation* anim, hkaAnimationBinding* binding, int skipOffset ) { TestRecord* rec = new TestRecord; rec->m_name = name; rec->m_bytes = 0; // Set up the binding rec->m_binding = new hkaAnimationBinding(); hkString::memCpy(rec->m_binding, binding, sizeof(hkaAnimationBinding) ); rec->m_binding->m_animation = anim; // Create an animation control hkaDefaultAnimationControl* ac = new hkaDefaultAnimationControl(rec->m_binding); // Create a new animated skeleton rec->m_animatedSkeleton = new hkaAnimatedSkeleton( m_skeleton ); rec->m_animatedSkeleton->setReferencePoseWeightThreshold(0.001f); // Bind the control to the skeleton rec->m_animatedSkeleton->addAnimationControl( ac ); // The animated skeleton now owns the control ac->removeReference(); rec->m_offset = OFFSET; rec->m_offset.mul4( hkReal(m_animationRecords.getSize() + skipOffset) ); m_animationRecords.pushBack(rec); }
void DemoKeeper::createBodies( void ) { // Each body needs at least one shape const hkVector4 halfExtents(1.0f, 0.75f, 1.0f); hkpShape* shape = new hkpBoxShape(halfExtents, 0 ); // Compute the inertia tensor from the shape hkMassProperties massProperties; hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape, 5.0f, massProperties); // Assign the rigid body properties hkpRigidBodyCinfo bodyInfo; bodyInfo.m_mass = massProperties.m_mass; bodyInfo.m_centerOfMass = massProperties.m_centerOfMass; bodyInfo.m_inertiaTensor = massProperties.m_inertiaTensor; bodyInfo.m_shape = shape; bodyInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA; bodyInfo.m_friction = 0.1f; for(int i = 0; i < m_numBodies; i++) { bodyInfo.m_position.set( hkMath::cos(hkReal(i)) - 2.0f, i * 2.0f + 10, hkMath::sin(hkReal(i))); hkpRigidBody* body = new hkpRigidBody(bodyInfo); mWorld->addEntity(body); body->removeReference(); //render it with Ogre Ogre::SceneNode* boxNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); //scale boxNode->scale(2, 1.5, 2); //display and sync Ogre::Entity *ent = mSceneMgr->createEntity(Ogre::StringConverter::toString(mLabMgr->getEntityCount()),"defCube.mesh"); mLabMgr->setColor(ent, Ogre::Vector3(rand()/(double)RAND_MAX,rand()/(double)RAND_MAX,rand()/(double)RAND_MAX)); HkOgre::Renderable* rend = new HkOgre::Renderable(boxNode, body,mWorld); boxNode->attachObject(ent); //register to lab manager mLabMgr->registerEnity( boxNode, body); } shape->removeReference(); }
void VehicleManagerDemo::buildLandscape() { if (1) { // // Create the ground we'll drive on. // { hkpRigidBodyCinfo groundInfo; // // Set the if condition to 0 if you want to test the heightfield // if ( 1 ) { FlatLand* fl = new FlatLand(); m_track = fl; groundInfo.m_shape = fl->createMoppShapeForSpu(); groundInfo.m_position.set(5.0f, -2.0f, 5.0f); groundInfo.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo( GROUND_LAYER, 0 ); } { groundInfo.m_motionType = hkpMotion::MOTION_FIXED; groundInfo.m_friction = 0.5f; hkpRigidBody* groundbody = new hkpRigidBody(groundInfo); m_world->addEntity(groundbody); groundbody->removeReference(); } groundInfo.m_shape->removeReference(); } } if (1) { hkVector4 halfExtents(10.0f, 0.1f, 10.0f); hkVector4 startPos(-240.0f, -7.8f, 0.0f); hkVector4 diffPos (30.0f, 0.0f, 0.0f); createDodgeBoxes(5, halfExtents, startPos, diffPos); } if (1) { hkVector4 halfExtents(10.0f, 0.05f, 10.0f); hkVector4 startPos(-240.0f, -7.85f, 30.0f); hkVector4 diffPos (30.0f, 0.0f, 0.0f); createDodgeBoxes(5, halfExtents, startPos, diffPos); } if (1) { int gridSize = 1 + int(hkMath::sqrt( hkReal(m_env->m_cpuMhz/100) )); createRagdollGrid( m_world, gridSize, gridSize, 4.0f, 4.0f, m_ragdolls ); } }
static void CreateListGrid( hkpWorld* world, hkReal bound, int numPerCubeSide, int numPerList ) { // Add List Shapes { hkPseudoRandomGenerator gen(123); for (int i = 0; i < numPerCubeSide; i++) { for (int j = 0; j < numPerCubeSide; j++) { for (int k = 0; k < numPerCubeSide; k++) { hkArray<hkpShape*> listElems; for (int e = 0; e < numPerList; e++) { // Make a random convex vertex shape hkVector4 cen; gen.getRandomVector11( cen ); cen.mul4( bound / (numPerCubeSide * 4.0f) ); hkVector4 extent; extent.setAll3( bound / (numPerCubeSide * 4) ); listElems.pushBack( GameUtils::createConvexVerticesBoxShape( cen, extent, hkConvexShapeDefaultRadius ) ); } hkpShape* listShape = new hkpListShape( listElems.begin(), listElems.getSize() ); for (int s=0; s < listElems.getSize(); s++) { listElems[s]->removeReference(); } hkpRigidBodyCinfo ci; ci.m_motionType = hkpMotion::MOTION_BOX_INERTIA; ci.m_shape = listShape; ci.m_mass = 1.f; ci.m_position.set( hkReal(i - numPerCubeSide / 2), hkReal(j + 1), hkReal(k - numPerCubeSide / 2) ); ci.m_position.mul4( bound / numPerCubeSide ); hkpRigidBody* body = new hkpRigidBody( ci ); world->addEntity(body); body->removeReference(); listShape->removeReference(); } } } } }
void SpiderDemo::createSpider( hkpWorld* world, SpiderLayout& sl ) { hkVector4 center( 0, 1, 0 ); // center body hkpRigidBody* rootBody; { hkpRigidBodyCinfo ci; ci.m_shape = new hkpBoxShape( sl.m_bodyHalfExtents, 0.0f ); ci.m_friction = 2.0f; ci.m_restitution = 0.0f; ci.m_collisionFilterInfo = sl.m_filterInfo; ci.m_motionType = hkpMotion::MOTION_BOX_INERTIA; ci.m_position = center; ci.m_angularDamping = 1.0f; hkReal mass = 30.0f; hkReal inertiaFactor = 1.0f; hkpMassProperties mp; hkpInertiaTensorComputer::computeBoxVolumeMassProperties( sl.m_legHalfExtents, mass * inertiaFactor, mp ); ci.m_mass = mass; ci.m_inertiaTensor = mp.m_inertiaTensor; rootBody = new hkpRigidBody( ci ); world->addEntity( rootBody ); rootBody->removeReference(); ci.m_shape->removeReference(); } // legs { for (int leg = 0; leg < sl.m_numLegs; leg++ ) { hkReal xf = leg/hkReal(sl.m_numLegs-1)*2.0f - 1.0f; for (int z = -1; z <= 1; z+=2 ) { SpiderDemo::calcLegMatrizesIn m; m.m_from = center; m.m_from(0) += xf * sl.m_bodyHalfExtents(0); m.m_from(2) += z * sl.m_bodyHalfExtents(2); m.m_to = center; m.m_to(0) += xf * sl.m_legHalfExtents(0); m.m_to(1) -= sl.m_legHalfExtents(1); m.m_to(2) += z * sl.m_legHalfExtents(2); m.m_up.set(0,1,0); hkVector4 diff; diff.setSub4( m.m_to, m.m_from ); hkReal len = diff.length3(); m.m_lenA = 0.6f * len; m.m_lenB = 0.8f * len; buildLeg( world, rootBody, m, sl.m_filterInfo, m_legs.expandOne() ); } } } }
KdTreeVsBroadphaseDemo::KdTreeVsBroadphaseDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env), m_flattenRays(false), m_rand(1337) { { m_worldSizeX = 2.0f * hkMath::sqrt(hkReal(m_env->m_cpuMhz)); m_worldSizeY = 3; m_worldSizeZ = m_worldSizeX; } // Setup the camera and graphics { // setup the camera hkVector4 from(0.0f, m_worldSizeZ*2.f, -m_worldSizeZ); hkVector4 to (0.0f, 0.0f, 0.0f); hkVector4 up (0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up, 1.0f, 5000.0f ); } { hkpWorldCinfo cinfo; cinfo.m_gravity.setAll(0); cinfo.m_broadPhaseWorldAabb.m_max.set( m_worldSizeX, 10.0f*m_worldSizeY, m_worldSizeZ); cinfo.m_broadPhaseWorldAabb.m_min.setNeg4( cinfo.m_broadPhaseWorldAabb.m_max ); cinfo.m_useKdTree = true; m_world = new hkpWorld(cinfo); m_world->lock(); } { hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); } // // Add a lot of rigid bodies to the world // { hkAabb worldAabb; worldAabb.m_max.set( m_worldSizeX, 10.0f*m_worldSizeY, m_worldSizeZ); worldAabb.m_min.setNeg4( worldAabb.m_max ); hkpMotion::MotionType motionType = hkpMotion::MOTION_FIXED; KdTreeDemoUtils::createRandomBodies(m_world, worldAabb, numBodies, motionType, &m_rand, m_collidables); } setupGraphics(); m_world->unlock(); }
hkReal BridgeLand::getHeight( int x, int y ) { hkReal percentageX = hkReal(x) / hkReal(m_side); // flatten terrain if we are outside of canyon area if ( percentageX < (0.5f - m_halfCanyonWidthRatio) || percentageX > (0.5f + m_halfCanyonWidthRatio) ) { return 0.0f; } // smoothen out slope if flag is set if ( m_smoothBreak ) { percentageX = (percentageX - (0.5f - m_halfCanyonWidthRatio)) / (m_halfCanyonWidthRatio*2.0f); } hkReal adjustedCosinus = (hkMath::cos(percentageX*2.0f*HK_REAL_PI) - 1.0f) * 0.5f; return adjustedCosinus * m_maxHeight; }
void vHavokVisualDebugger::Step() { // Get the local timers to feed to the stats viewer // reset our VDB stats list if (m_physicsContext) { m_physicsContext->syncTimers(vHavokPhysicsModule::GetInstance()->GetThreadPool()); } hkReal dt = Vision::GetTimer()->GetTimeDifference(); // Step the debugger m_pVisualDebugger->step(dt*hkReal(1000)); // Update camera hkVector4 pos; vHavokConversionUtils::VisVecToPhysVecWorld(Vision::Camera.GetMainCamera()->GetPosition(),pos); hkVector4 dir; vHavokConversionUtils::VisVecToPhysVec_noscale(Vision::Camera.GetMainCamera()->GetDirection(),dir); hkVector4 up; vHavokConversionUtils::VisVecToPhysVec_noscale(Vision::Camera.GetMainCamera()->GetObjDir_Up(), up); hkVector4 lookat; lookat.setAdd(pos,dir); // Havok visual debugger defaults float nearPlane = 0.1f; float farPlane = 500.f; float fovX = 0.f; float fovY = 45.f; VisRenderContext_cl::GetMainRenderContext()->GetClipPlanes(nearPlane, farPlane); VisRenderContext_cl::GetMainRenderContext()->GetFinalFOV(fovX, fovY); // Scale them to Havok space nearPlane = float(VIS2HK_FLOAT_SCALED(nearPlane)); farPlane = float(VIS2HK_FLOAT_SCALED(farPlane)); HK_UPDATE_CAMERA(pos, lookat, up, nearPlane, farPlane, fovY, "Vision"); // Reset internal profiling info for next frame hkMonitorStream::getInstance().reset(); }
void vHavokTerrain::CreateHkRigidBody() { // Create the Havok shape hkpShape *pShape = vHavokShapeFactory::CreateShapeFromTerrain(*m_terrainSector); // Create the Havok rigid body hkpRigidBodyCinfo rci; rci.m_motionType = hkpMotion::MOTION_FIXED; rci.m_shape = pShape; //subtract the y sample spacing from the original position to make sure that the physical representation and the visible terrain match hkvVec3 vSpacing(0, m_terrainSector->m_Config.m_vSampleSpacing.y, 0); vHavokConversionUtils::VisVecToPhysVecWorld(hkvVec3(m_terrainSector->GetSectorOrigin() - vSpacing),rci.m_position); rci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(vHavokPhysicsModule::HK_LAYER_COLLIDABLE_TERRAIN); // We have two choices here. Heightfields in Havok are on the X,Z local plane, but in Vision they are // X,Y, so some transform is required. We could rotate by -90 and invert the heights but that results // in normals that are the opposite to what you would expect (which is fine though as double sided, but not ideal). // The second option is to rotate the opposite way and invert the lookup on Y (Havok local Z) // This second option of course shifts the direction of the extends, so we need to also include the translation for that: // y, but take into account the single sample edge overlap in the terrain hkSimdReal yvOffset; yvOffset.setFromFloat( m_terrainSector->m_Config.m_vSectorSize.y + m_terrainSector->m_Config.m_vSampleSpacing.y ); yvOffset.mul(vHavokConversionUtils::GetVision2HavokScaleSIMD()); // Counter act the shift the extent dir rci.m_position.addMul( hkVector4::getConstant<HK_QUADREAL_0100>(), yvOffset ); rci.m_rotation.setAxisAngle(hkVector4::getConstant<HK_QUADREAL_1000>(),hkSimdReal_PiOver2); // Basis change rci.m_friction = hkReal(0.2f); m_pRigidBody = new hkpRigidBody( rci ); // Set user data to identify this terrain during collision detection (raycast etc) m_pRigidBody->setUserData((hkUlong)vHavokUserDataPointerPair_t::CombineTypeAndPointer(this, V_USERDATA_TERRAIN)); // Add our instance to the module m_module.AddTerrain(this); // Remove reference pShape->removeReference(); }
void Vehicle::SetInput(float steering, float acceleration, bool brake, bool reverse, bool fixedControl) { if (m_instance == HK_NULL) return; if(!this->automated) Vision::Message.Print (1, 10, Vision::Video.GetYRes() - 100, "%f %f %d", acceleration,GetMPH(), brake); // Drive the car with our input hkpVehicleDriverInputAnalogStatus* deviceStatus = (hkpVehicleDriverInputAnalogStatus*)m_instance->m_deviceStatus; deviceStatus->m_handbrakeButtonPressed = brake; deviceStatus->m_reverseButtonPressed = reverse; deviceStatus->m_positionY = acceleration; if (fixedControl) { deviceStatus->m_positionX = hkMath::clamp(steering, -1.f, 1.f); } else { const hkReal delta = Vision::GetTimer()->GetTimeDifference(); deviceStatus->m_positionX = hkMath::clamp(deviceStatus->m_positionX + steering * delta, hkReal(-1.0f), hkReal(1.0f)); if (hkMath::equal(steering, 0.f)) { float difference = 2.0f * delta; deviceStatus->m_positionX += difference * (deviceStatus->m_positionX > 0 ? -1 : 1); if (hkMath::equal(deviceStatus->m_positionX, 0.f, difference * 1.5f)) { deviceStatus->m_positionX = 0.f; } } } }
AsymetricCharacterRbDemo::AsymetricCharacterRbDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // Create the world { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 350.0f ); info.m_gravity.set(0, -9.8f, 0); info.m_collisionTolerance = 0.01f; info.m_contactPointGeneration = hkpWorldCinfo::CONTACT_POINT_ACCEPT_ALWAYS; m_world = new hkpWorld( info ); m_world->lock(); hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // Create a terrain (more bumpy as in the classical character proxy demo) TerrainHeightFieldShape* heightFieldShape; { hkpSampledHeightFieldBaseCinfo ci; ci.m_xRes = 64; ci.m_zRes = 64; ci.m_scale.set(1.6f, 0.2f, 1.6f); // Fill in a data array m_data = hkAllocate<hkReal>((ci.m_xRes * ci.m_zRes), HK_MEMORY_CLASS_DEMO); for (int x = 0; x < ci.m_xRes; x++) { for (int z = 0; z < ci.m_zRes; z++) { hkReal dx,dz,height = 0; int octave = 1; // Add together a few sine and cose waves for (int i=0; i< 3; i++) { dx = hkReal(x * octave) / ci.m_xRes; dz = hkReal(z * octave) / ci.m_zRes; height += 4 * i * hkMath::cos(dx * HK_REAL_PI) * hkMath::sin(dz * HK_REAL_PI); height -= 2.5f; octave *= 2; } m_data[x*ci.m_zRes + z] = height; } } heightFieldShape = new TerrainHeightFieldShape( ci , m_data ); // Create terrain as a fixed rigid body { hkpRigidBodyCinfo rci; rci.m_motionType = hkpMotion::MOTION_FIXED; rci.m_position.setMul4( -0.5f, heightFieldShape->m_extents ); // center the heighfield rci.m_shape = heightFieldShape; rci.m_friction = 0.5f; hkpRigidBody* terrain = new hkpRigidBody( rci ); m_world->addEntity(terrain); terrain->removeReference(); } heightFieldShape->removeReference(); } // Create some random static pilars (green) and smaller dynamic boxes (blue) { hkPseudoRandomGenerator randgen(12345); for (int i=0; i < 80; i++) { if (i%2) { // Dynamic boxes of random size hkVector4 size; randgen.getRandomVector11(size); size.setAbs4( size ); size.mul4(0.5f); hkVector4 minSize; minSize.setAll3(0.25f); size.add4(minSize); // Random position hkVector4 position; randgen.getRandomVector11( position ); position(0) *= 25; position(2) *= 25; position(1) = 4; { // To illustrate using the shape, create a rigid body by first defining a template. hkpRigidBodyCinfo rci; rci.m_shape = new hkpBoxShape( size ); rci.m_position = position; rci.m_friction = 0.5f; rci.m_restitution = 0.0f; // Density of concrete const hkReal density = 2000.0f; rci.m_mass = size(0)*size(1)*size(2)*density; hkVector4 halfExtents(size(0) * 0.5f, size(1) * 0.5f, size(2) * 0.5f); hkpMassProperties massProperties; hkpInertiaTensorComputer::computeBoxVolumeMassProperties(halfExtents, rci.m_mass, massProperties); rci.m_inertiaTensor = massProperties.m_inertiaTensor; rci.m_motionType = hkpMotion::MOTION_BOX_INERTIA; // Create a rigid body (using the template above). hkpRigidBody* box = new hkpRigidBody(rci); // Remove reference since the body now "owns" the Shape. rci.m_shape->removeReference(); box->addProperty(HK_PROPERTY_DEBUG_DISPLAY_COLOR, int(hkColor::DARKBLUE)); // Finally add body so we can see it, and remove reference since the world now "owns" it. m_world->addEntity(box)->removeReference(); } } else { // Fixed pilars of random size hkVector4 size; randgen.getRandomVector11(size); size.setAbs4( size ); hkVector4 minSize; minSize.setAll3(0.5f); size.add4(minSize); size(1) = 2.5f; // Random position hkVector4 position; randgen.getRandomVector11( position ); position(0) *= 25; position(2) *= 25; position(1) = 0; { // To illustrate using the shape, create a rigid body by first defining a template. hkpRigidBodyCinfo rci; rci.m_shape = new hkpBoxShape( size ); rci.m_position = position; rci.m_friction = 0.1f; rci.m_motionType = hkpMotion::MOTION_FIXED; // Create a rigid body (using the template above). hkpRigidBody* pilar = new hkpRigidBody(rci); // Remove reference since the body now "owns" the shape. rci.m_shape->removeReference(); pilar->addProperty(HK_PROPERTY_DEBUG_DISPLAY_COLOR, int(hkColor::DARKGREEN)); // Finally add body so we can see it, and remove reference since the world now "owns" it. m_world->addEntity(pilar); pilar->removeReference(); } } } } // Create a character rigid body { // Construct a shape hkVector4 vertexA(0.4f,0,0); hkVector4 vertexB(-0.4f,0,0); // Create a capsule to represent the character standing hkpShape* capsule = new hkpCapsuleShape(vertexA, vertexB, 0.6f); // Construct a character rigid body hkpCharacterRigidBodyCinfo info; info.m_mass = 100.0f; info.m_shape = capsule; info.m_maxForce = 1000.0f; info.m_up = UP; info.m_position.set(32.0f, 3.0f, 10.0f); info.m_maxSlope = HK_REAL_PI/2.0f; // Only vertical plane is too steep m_characterRigidBody = new hkpCharacterRigidBody( info ); m_world->addEntity( m_characterRigidBody->getRigidBody() ); capsule->removeReference(); } // Create the character state machine and context { 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_IN_AIR); manager->removeReference(); // Set new filter parameters for final output velocity filtering // Smoother interactions with small dynamic boxes m_characterContext->setCharacterType(hkpCharacterContext::HK_CHARACTER_RIGIDBODY); m_characterContext->setFilterParameters(0.9f,12.0f,200.0f); } // Initialize hkpSurfaceInfo of ground from previous frame // Specific case (character is in the air, UP is Y) m_previousGround = new hkpSurfaceInfo(UP,hkVector4::getZero(),hkpSurfaceInfo::UNSUPPORTED); m_framesInAir = 0; // Current camera angle about up m_currentAngle = 0.0f; // Init actual time m_time = 0.0f; // Init rigid body normal m_rigidBodyNormal = UP; m_world->unlock(); }
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 TractorSetup::setupVehicleData( const hkpWorld* world, hkpVehicleData& data ) { data.m_gravity = world->getGravity(); // // The vehicleData contains information about the chassis. // // The mass is set in the rigid body. // The coordinates of the chassis system, used for steering the vehicle. // up forward right data.m_chassisOrientation.setCols( hkVector4(0, 1, 0), hkVector4(1, 0, 0), hkVector4(0, 0, 1)); data.m_frictionEqualizer = 0.5f; data.m_torqueRollFactor = 0.5f; data.m_torquePitchFactor = 1.25f; data.m_torqueYawFactor = 0.5f; data.m_chassisUnitInertiaYaw = 1.0f; data.m_chassisUnitInertiaRoll = 1.0f; data.m_chassisUnitInertiaPitch = 1.0f; data.m_extraTorqueFactor = -1.0f; data.m_maxVelocityForPositionalFriction = 10.0f; // // Wheel specifications // data.m_numWheels = 6; data.m_wheelParams.setSize( data.m_numWheels ); data.m_wheelParams[0].m_axle = 0; data.m_wheelParams[1].m_axle = 0; data.m_wheelParams[2].m_axle = 1; data.m_wheelParams[3].m_axle = 1; data.m_wheelParams[4].m_axle = 1; data.m_wheelParams[5].m_axle = 1; data.m_wheelParams[0].m_friction = 2.3f; data.m_wheelParams[1].m_friction = 2.3f; data.m_wheelParams[2].m_friction = 4.0f; data.m_wheelParams[3].m_friction = 4.0f; data.m_wheelParams[4].m_friction = 4.0f; data.m_wheelParams[5].m_friction = 4.0f; for ( int i = 0 ; i < data.m_numWheels ; i++ ) { // This value is also used to calculate the m_primaryTransmissionRatio. data.m_wheelParams[i].m_radius = 0.5f; data.m_wheelParams[i].m_width = 0.2f; data.m_wheelParams[i].m_mass = 80.0f; data.m_wheelParams[i].m_viscosityFriction = 0.2f; data.m_wheelParams[i].m_slipAngle = 0.0f; data.m_wheelParams[i].m_maxFriction = 2.0f * data.m_wheelParams[i].m_friction; data.m_wheelParams[i].m_forceFeedbackMultiplier = 10.0f; data.m_wheelParams[i].m_maxContactBodyAcceleration = hkReal(data.m_gravity.length3()) * 2; } }
hkDemo::Result UnevenTerrainVsDemo::stepDemo() { HK_TIMER_BEGIN( "simulate multiply characters", HK_NULL ); m_world->lock(); hkVector4 up; up.setNeg4( m_world->getGravity() ); up.normalize3(); m_tick++; hkpCharacterInput inputRb; hkpCharacterInput inputProxy; // Fill in the state machine input structure for character rigid body { inputRb.m_atLadder = false; inputRb.m_up = up; // Steer the characters inputRb.m_inputLR = 0.0f; inputRb.m_inputUD = 1.0f; { // The factor 70.0f gives a turning circle which fits in the level // for the default walk speed of 10.0f. hkReal walkSpeedFactor = m_options.m_characterWalkSpeed / 70.0f; hkReal time = hkReal(m_tick) * walkSpeedFactor / 60.0f; const hkReal x = hkMath::sin(time); const hkReal z = hkMath::cos(time); inputRb.m_forward.set( x, 0, z ); inputRb.m_forward.normalize3(); } inputRb.m_wantJump = false; hkStepInfo stepInfo; stepInfo.m_deltaTime = m_timestep; stepInfo.m_invDeltaTime = 1.0f/m_timestep; inputRb.m_stepInfo = stepInfo; inputRb.m_characterGravity.set( 0.0f, m_options.m_characterGravity, 0.0f ); inputProxy = inputRb; // character rigid body specific code inputRb.m_velocity = m_characterRigidBody->getLinearVelocity(); inputRb.m_position = m_characterRigidBody->getPosition(); m_characterRigidBody->checkSupport(stepInfo, inputRb.m_surfaceInfo); filterStates( m_filterRigidBody, inputRb.m_surfaceInfo ); m_supportHistoryRb <<= 1; if ( inputRb.m_surfaceInfo.m_supportedState == hkpSurfaceInfo::SUPPORTED ) { ++m_supportHistoryRb; } else { ++m_unsupportedFramesCountRb; } // character proxy specific code inputProxy.m_velocity = m_characterProxy->getLinearVelocity(); inputProxy.m_position = m_characterProxy->getPosition(); hkVector4 down; down.setNeg4(UP); m_characterProxy->checkSupport(down, inputProxy.m_surfaceInfo); filterStates( m_filterProxy, inputProxy.m_surfaceInfo ); m_supportHistoryProxy <<= 1; if ( inputProxy.m_surfaceInfo.m_supportedState == hkpSurfaceInfo::SUPPORTED ) { ++m_supportHistoryProxy; } else { ++m_unsupportedFramesCountProxy; } } hkpCharacterOutput outputRb; hkpCharacterOutput outputProxy; // Apply the character state machine { HK_TIMER_BEGIN( "update character state", HK_NULL ); m_characterContext->update(inputRb, outputRb); m_characterProxyContext->update(inputProxy, outputProxy); HK_TIMER_END(); } //Apply the character controllers { HK_TIMER_BEGIN( "simulate character", HK_NULL ); // Feed the output velocity from state machine into character rigid body m_characterRigidBody->setLinearVelocity(outputRb.m_velocity, m_timestep); m_characterProxy->setLinearVelocity(outputProxy.m_velocity ); hkStepInfo si; si.m_deltaTime = m_timestep; si.m_invDeltaTime = 1.0f/m_timestep; m_characterProxy->integrate( si, m_world->getGravity() ); HK_TIMER_END(); } { // If the character has fallen off the world we reposition them if ( ( m_characterProxy->getPosition()(1) < -10.0f ) || ( m_characterRigidBody->getPosition()(1) < -10.0f ) ) { m_characterProxy->setPosition( characterStart ); m_characterProxy->setLinearVelocity( hkVector4::getZero() ); m_characterRigidBody->getRigidBody()->setPosition(characterStart); m_characterRigidBody->setLinearVelocity( hkVector4::getZero(), m_timestep ); m_tick = 0; } } m_world->unlock(); // Display state { char historyRb[33]; char historyProxy[33]; char buffer[255]; for ( int i = 0; i < 32; ++i ) { historyRb[i] = m_supportHistoryRb & ( 1 << i ) ? '#' : '_'; historyProxy[i] = m_supportHistoryProxy & ( 1 << i ) ? '#' : '_'; } historyRb[32] = '\0'; historyProxy[32] = '\0'; hkString::sprintf( buffer, "Rigid body unsupported frames: %d\n" "Proxy unsupported frames: %d\n\n" "Rigid body support history: %s\n" "Proxy support history: %s\n", m_unsupportedFramesCountRb, m_unsupportedFramesCountProxy, historyRb, historyProxy ); m_env->m_textDisplay->outputText( buffer, 20, 200, 0xffffffff ); } // Step the world { hkDefaultPhysicsDemo::stepDemo(); } HK_TIMER_END(); return hkDemo::DEMO_OK; }
BenchmarkSuiteDemo::BenchmarkSuiteDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { const BenchmarkSuiteVariant& variant = g_variants[m_variantId]; // Disable warnings: hkError::getInstance().setEnabled(0x7dd65995, false); //'The system has requested a heap allocation on stack overflow.' hkError::getInstance().setEnabled(0xaf55adde, false); //'No runtime block of size 637136 currently available. Allocating new block from unmanaged memory.' // // Setup the camera // { hkVector4 from(55.0f, 50.0f, 55.0f); hkVector4 to ( 0.0f, 0.0f, 0.0f); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras(env, from, to, up, 0.1f, 20000.0f); } // // Create the world // { hkpWorldCinfo worldInfo; { worldInfo.m_gravity.set(-0.0f, -9.81f, -0.0f); worldInfo.setBroadPhaseWorldSize(500.0f); worldInfo.setupSolverInfo( hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM ); if (variant.m_type == TYPE_3000_BODY_PILE) { worldInfo.m_enableSimulationIslands = false; } worldInfo.m_enableDeactivation = false; } m_world = new hkpWorld(worldInfo); m_world->lock(); // Register ALL agents (though some may not be necessary) hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); // enable instancing (if present on platform). Call this after setup graphics (as it makes the local viewers..) hkpShapeDisplayViewer* shapeViewer = (hkpShapeDisplayViewer*)getLocalViewerByName( hkpShapeDisplayViewer::getName() ); if (shapeViewer) { shapeViewer->setInstancingEnabled( true ); } } // // Setup the camera // { hkVector4 from(15.0f, 15.0f, 15.0f); hkVector4 to (0.0f, 0.0f, 0.0f); hkVector4 up (0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up ); } switch (variant.m_type) { case TYPE_10x10x1_ON_BOX: { CreateGroundPlane( m_world ); CreateStack(m_world, 10); break; } case TYPE_5x5x5_ON_BOX: { CreateGroundPlane(m_world); for (int q = -3; q <= 2; q++ ) { CreateStack(m_world,5, q * 10.0f); } break; } case TYPE_300_BODY_PILE: { CreateGroundPlane(m_world); CreateFall(m_world, 5); break; } case TYPE_OBJECTS_ON_MOPP_SMALL: { CreatePhysicsTerrain(m_world, 16, 1.0f); CreateFlatCubeGrid(m_world,8); break; } case TYPE_LIST_PILE_SMALL: { int side = 16; CreatePhysicsTerrain(m_world, side, 1.0f); CreateListGrid(m_world, hkReal(side), 3, 3); break; } case TYPE_30x30x1_ON_BOX: { CreateGroundPlane( m_world ); CreateStack(m_world, 30); break; } case TYPE_20x20x5_ON_BOX: { CreateGroundPlane(m_world); for (int q = -3; q <= 2; q++ ) { CreateStack(m_world,20, q * 10.0f); } break; } case TYPE_12x12x10_ON_BOX: { CreateGroundPlane(m_world); for (int q = -5; q <= 4; q++ ) { CreateStack(m_world,12, q * 2.5f); } break; } case TYPE_3000_BODY_PILE: { CreateGroundPlane(m_world); CreateFall(m_world, 50); break; } case TYPE_OBJECTS_ON_MOPP_LARGE: { CreatePhysicsTerrain(m_world, 64, 1.0f); CreateFlatCubeGrid(m_world,30); break; } case TYPE_LIST_PILE_LARGE: { int side = 16; CreatePhysicsTerrain(m_world, side, 1.0f); CreateListGrid(m_world, hkReal(side), 5, 5); break; } default: { CreateGroundPlane(m_world); CreateStack(m_world, 20); break; } } // // Some values // m_world->unlock(); }
void VehicleSetup::setupVehicleData( const hkpWorld* world, hkpVehicleData& data ) { data.m_gravity = world->getGravity(); // // The vehicleData contains information about the chassis. // // The coordinates of the chassis system, used for steering the vehicle. data.m_chassisOrientation.setCols( m_up, m_forward, m_right); data.m_frictionEqualizer = 0.5f; // Inertia tensor for each axis is calculated by using : // (1 / chassis_mass) * (torque(axis)Factor / chassisUnitInertia) data.m_torqueRollFactor = 0.525f; data.m_torquePitchFactor = 0.6f; data.m_torqueYawFactor = 0.55f; data.m_chassisUnitInertiaYaw = 1.0f; data.m_chassisUnitInertiaRoll = 1.0f; data.m_chassisUnitInertiaPitch = 1.0f; // Adds or removes torque around the yaw axis // based on the current steering angle. This will // affect steering. data.m_extraTorqueFactor = -40000.0f; data.m_maxVelocityForPositionalFriction = 10.0f; // // Wheel specifications // data.m_numWheels = 4; m_wheelRadius = 0.36479f; data.m_wheelParams.setSize( data.m_numWheels ); data.m_wheelParams[0].m_axle = 0; data.m_wheelParams[1].m_axle = 0; data.m_wheelParams[2].m_axle = 1; data.m_wheelParams[3].m_axle = 1; data.m_wheelParams[0].m_friction = 2.1f; data.m_wheelParams[1].m_friction = 2.1f; data.m_wheelParams[2].m_friction = 2.05f; data.m_wheelParams[3].m_friction = 2.05f; data.m_wheelParams[0].m_slipAngle = 0.1f; data.m_wheelParams[1].m_slipAngle = 0.1f; data.m_wheelParams[2].m_slipAngle = 0.0f; data.m_wheelParams[3].m_slipAngle = 0.0f; for ( int i = 0 ; i < data.m_numWheels ; i++ ) { // This value is also used to calculate the m_primaryTransmissionRatio. data.m_wheelParams[i].m_radius = m_wheelRadius; data.m_wheelParams[i].m_width = 0.2f; data.m_wheelParams[i].m_mass = 10.0f; data.m_wheelParams[i].m_viscosityFriction = 0.0f; data.m_wheelParams[i].m_maxFriction = 2.0f * data.m_wheelParams[i].m_friction; data.m_wheelParams[i].m_forceFeedbackMultiplier = 0.1f; data.m_wheelParams[i].m_maxContactBodyAcceleration = hkReal(data.m_gravity.length3()) * 2; } }
LowFrequencyCharactersDemo::LowFrequencyCharactersDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // // Setup the camera // { hkVector4 from( 0.0f, 20.0f, -80.0f); hkVector4 to ( 0.0f, 0.0f, 0.0f); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up ); forceShadowState(false); } // // Create the world // { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 350.0f ); info.m_gravity.set(0, -9.8f, 0); info.m_collisionTolerance = 0.1f; m_world = new hkpWorld( info ); m_world->lock(); hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // // Create a terrain // TerrainHeightFieldShape* heightFieldShape; { hkpSampledHeightFieldBaseCinfo ci; ci.m_xRes = 64; ci.m_zRes = 64; ci.m_scale.set(4,1,4); // // Fill in a data array // m_data = hkAllocate<hkReal>(ci.m_xRes * ci.m_zRes, HK_MEMORY_CLASS_DEMO); for (int x = 0; x < ci.m_xRes; x++) { for (int z = 0; z < ci.m_xRes; z++) { hkReal dx,dz,height = 0; int octave = 1; // Add togther a few sine and cose waves for (int i=0; i< 3; i++) { dx = hkReal(x * octave) / ci.m_xRes; dz = hkReal(z * octave) / ci.m_zRes; height += (5 - (i * 2)) * hkMath::cos(dx * HK_REAL_PI) * hkMath::sin(dz * HK_REAL_PI); octave *= 4; } m_data[x*ci.m_zRes + z] = height; } } heightFieldShape = new TerrainHeightFieldShape( ci , m_data ); // // Create a fixed rigid body // { hkpRigidBodyCinfo rci; rci.m_motionType = hkpMotion::MOTION_FIXED; rci.m_position.setMul4( -0.5f, heightFieldShape->m_extents ); // center the heightfield rci.m_shape = heightFieldShape; rci.m_friction = 0.05f; hkpRigidBody* body = new hkpRigidBody( rci ); m_world->addEntity(body)->removeReference(); } heightFieldShape->removeReference(); } // // Create a character proxy object // { m_numBoxes = 0; m_numCapsules = 0; m_numSpheres = 0; // We'll store the simulation frequency in this hkpPropertyValue val; // Construct shape phantoms for the characters hkPseudoRandomGenerator random(123); for (int i=0; i < NUM_CHARACTERS; i++) { // Create a random shape to represent the character hkpConvexShape* shape = HK_NULL; { hkReal scale = random.getRandReal01() * 0.25f + 0.75f; //Set the simulation frequency val.setInt( random.getRand32() % 3 ); switch (val.getInt()) { case 0: { hkVector4 top(0, scale * 0.4f, 0); hkVector4 bottom(0, -scale * 0.4f, 0); shape = new hkpCapsuleShape(top, bottom, scale * 0.6f); m_numCapsules++; } break; case 1: { hkVector4 size(scale * 0.5f, scale , scale * 0.5f); shape = new hkpBoxShape(size); m_numBoxes++; } break; default: { shape = new hkpSphereShape(scale); m_numSpheres++; } break; } } hkpShapePhantom* phantom = new hkpSimpleShapePhantom( shape, hkTransform::getIdentity() ); shape->removeReference(); // Add the phantom to the world m_world->addPhantom(phantom); phantom->removeReference(); HK_SET_OBJECT_COLOR( (hkUlong)phantom->getCollidable(), 0x7fffffff & hkColor::getRandomColor() ); // Construct a character proxy hkpCharacterProxyCinfo cpci; random.getRandomVector11( cpci.m_position ); cpci.m_position.mul4(32); cpci.m_position(1) = 10; cpci.m_up.setNeg4( m_world->getGravity() ); cpci.m_up.normalize3(); cpci.m_shapePhantom = phantom; m_characterProxy[i] = new hkpCharacterProxy( cpci ); // Player is simulated at full frequency if (i==0) { val.setInt(0); } // Add the schedule property phantom->addProperty(HK_SCHEDULE_FREQUENCY, val); } } // // Create the Character state machine and context // hkpCharacterStateManager* manager; { hkpCharacterState* state; 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(); } // Create a context for each character { for (int i=0; i < NUM_CHARACTERS; i++) { m_characterContext[i] = new hkpCharacterContext(manager, HK_CHARACTER_ON_GROUND); } manager->removeReference(); } // Current camera angle about up m_currentAngle = 0.0f; //Initialised the round robin counter m_tick = 0; m_world->unlock(); }
hkDemo::Result MirroredMotionDemo::stepDemo() { // Check user input { if (m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_1 )) { for ( int i = 0; i < 2; i++ ) { if (( m_control[i]->getEaseStatus() == hkaDefaultAnimationControl::EASING_IN ) || ( m_control[i]->getEaseStatus() == hkaDefaultAnimationControl::EASED_IN )) { m_control[i]->easeOut( .5f ); } else { m_control[i]->easeIn( .5f ); } } } if (m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_2 )) { m_wireframe = !m_wireframe; setGraphicsState( HKG_ENABLED_WIREFRAME, m_wireframe ); } if (m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_3 )) { m_drawSkin = !m_drawSkin; } if ( m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_0 ) ) { m_useExtractedMotion = !m_useExtractedMotion; } if ( m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_L1 ) ) { m_accumulatedMotion[0].setIdentity(); m_accumulatedMotion[1].setIdentity(); } if ( m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_R1 ) ) { m_paused = !m_paused; if ( m_paused ) { m_timestep = 0; } else { m_timestep = 1.0f / 60.0f; } } } const int boneCount = m_skeleton->m_numBones; for ( int j = 0; j < 2; j++ ) { // Grab accumulated motion { hkQsTransform deltaMotion; deltaMotion.setIdentity(); m_skeletonInstance[j]->getDeltaReferenceFrame( m_timestep, deltaMotion ); m_accumulatedMotion[j].setMulEq( deltaMotion ); } // Advance the active animations m_skeletonInstance[j]->stepDeltaTime( m_timestep ); // Sample the active animations and combine into a single pose hkaPose pose (m_skeleton); m_skeletonInstance[j]->sampleAndCombineAnimations( pose.accessUnsyncedPoseLocalSpace().begin(), pose.getFloatSlotValues().begin() ); hkReal separation = m_separation * hkReal( 2*j-1 ); hkQsTransform Q( hkQsTransform::IDENTITY ); Q.m_translation.set( separation, 0, 0 ); if ( m_useExtractedMotion ) { Q.setMulEq( m_accumulatedMotion[j] ); } pose.syncModelSpace(); AnimationUtils::drawPose( pose, Q ); // Test if the skin is to be drawn if ( !m_drawSkin ) { Q.m_translation( 2 ) -= 2.0f * m_separation; } // Construct the composite world transform hkLocalArray<hkTransform> compositeWorldInverse( boneCount ); compositeWorldInverse.setSize( boneCount ); const hkArray<hkQsTransform>& poseModelSpace = pose.getSyncedPoseModelSpace(); // Skin the meshes for (int i=0; i < m_numSkinBindings[j]; i++) { // assumes either a straight map (null map) or a single one (1 palette) hkInt16* usedBones = m_skinBindings[j][i]->m_mappings? m_skinBindings[j][i]->m_mappings[0].m_mapping : HK_NULL; int numUsedBones = usedBones? m_skinBindings[j][i]->m_mappings[0].m_numMapping : boneCount; // Multiply through by the bind pose inverse world inverse matrices for (int p=0; p < numUsedBones; p++) { int boneIndex = usedBones? usedBones[p] : p; hkTransform tWorld; poseModelSpace[ boneIndex ].copyToTransform(tWorld); compositeWorldInverse[p].setMul( tWorld, m_skinBindings[j][i]->m_boneFromSkinMeshTransforms[ boneIndex ] ); } AnimationUtils::skinMesh( *m_skinBindings[j][i]->m_mesh, hkTransform( Q.m_rotation, hkVector4( Q.m_translation(0), Q.m_translation(1), Q.m_translation(2), 1 ) ), compositeWorldInverse.begin(), *m_env->m_sceneConverter ); } // Move the attachments { HK_ALIGN(float f[16], 16); for (int a=0; a < m_numAttachments[j]; a++) { if (m_attachmentObjects[j][a]) { hkaBoneAttachment* ba = m_attachments[j][a]; hkQsTransform modelFromBone = pose.getBoneModelSpace( ba->m_boneIndex ); hkQsTransform worldFromBoneQs; worldFromBoneQs.setMul( Q, modelFromBone ); worldFromBoneQs.get4x4ColumnMajor(f); hkMatrix4 worldFromBone; worldFromBone.set4x4ColumnMajor(f); hkMatrix4 worldFromAttachment; worldFromAttachment.setMul(worldFromBone, ba->m_boneFromAttachment); m_env->m_sceneConverter->updateAttachment(m_attachmentObjects[j][a], worldFromAttachment); } } } } return hkDemo::DEMO_OK; }
ActivationCallbacksDemo::ActivationCallbacksDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // // Setup the camera // { hkVector4 from(0.0f, 7.0f, 30.0f); hkVector4 to (0.0f, 3.0f, 0.0f); hkVector4 up (0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up ); } // // Create the world // { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 100.0f ); m_world = new hkpWorld( info ); m_world->lock(); m_debugViewerNames.pushBack( hkpSimulationIslandViewer::getName() ); setupGraphics(); } // // Register the agents // { hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); } // // Create the fixed box // { // Position of the box hkVector4 boxPosition(0.0f, 0.0f, 0.0f); // Set up the construction info parameters for the box hkpRigidBodyCinfo info; info.m_motionType = hkpMotion::MOTION_FIXED; info.m_friction = 1.0f; info.m_shape = new hkpBoxShape( hkVector4(60.0f, 0.2f, 60.0f), 0.05f ); info.m_position = boxPosition; // Create fixed box hkpRigidBody* box = new hkpRigidBody(info); m_world->addEntity(box); box->removeReference(); info.m_shape->removeReference(); } // // Create the moving boxes // for (int i = 0; i < 20; i++) { // Create some object hkpRigidBodyCinfo info; info.m_friction = 1.0f; info.m_shape = new hkpBoxShape( hkVector4(0.5f, 0.5f, 0.5f), 0.0f ); hkpInertiaTensorComputer::setShapeVolumeMassProperties( info.m_shape, 1.0f, info ); info.m_motionType = hkpMotion::MOTION_BOX_INERTIA; // Position of the box info.m_position.setZero4(); info.m_position(0) = - hkReal(i) * 1.5f + 2.0f; //left info.m_position(1) = 1.0f; info.m_position(2) = hkMath::sin( hkReal(i) / 3.0f ) * 0.7f; if (i == 0) { info.m_motionType = hkpMotion::MOTION_KEYFRAMED; info.m_linearVelocity = hkVector4( -1.0f, 0.0f, 0.0f ); } // Create a box hkpRigidBody* box = new hkpRigidBody(info); info.m_shape->removeReference(); // Create a listener and attach it to the box // NOTE: The listener attaches itself to the body as an hkpEntityListener // and deletes itself automatically when the entity is deleted. ActivationCallbacksDemoEntityActivationListener* listener = new ActivationCallbacksDemoEntityActivationListener(); box->addEntityActivationListener(listener); box->addEntityListener(listener); // Insert the box into the world m_world->addEntity(box); box->removeReference(); } m_world->unlock(); }
hkDemo::Result MultipleCharacterRbsDemo::stepDemo() { HK_TIMER_BEGIN( "simulate multiply characters", HK_NULL ); m_world->lock(); hkVector4 up; up.setNeg4( m_world->getGravity() ); up.normalize3(); int numCharacters = m_characterRigidBodies.getSize(); m_tick++; hkLocalArray<hkpCharacterInput> input( numCharacters ) ; input.setSize(numCharacters); // Fill in the state machine input structure { for (int i=0; i < numCharacters; i++) { input[i].m_atLadder = false; input[i].m_up = up; // Steer the characters hkReal time = hkReal(m_tick) / 60.0f; input[i].m_inputLR = hkMath::sin(time + i); input[i].m_inputUD = hkMath::cos(time + i); input[i].m_wantJump = false; input[i].m_forward.set(1,0,0); hkStepInfo stepInfo; stepInfo.m_deltaTime = m_timestep; stepInfo.m_invDeltaTime = 1.0f/m_timestep; input[i].m_stepInfo = stepInfo; input[i].m_characterGravity = m_world->getGravity(); input[i].m_velocity = m_characterRigidBodies[i]->getLinearVelocity(); input[i].m_position = m_characterRigidBodies[i]->getPosition(); hkpSurfaceInfo ground; m_characterRigidBodies[i]->checkSupport(stepInfo, ground); input[i].m_isSupported = (ground.m_supportedState == hkpSurfaceInfo::SUPPORTED); input[i].m_surfaceNormal = ground.m_surfaceNormal; input[i].m_surfaceVelocity = ground.m_surfaceVelocity; } } hkLocalArray<hkpCharacterOutput> output( numCharacters); output.setSize(numCharacters); // Apply the character state machine { HK_TIMER_BEGIN( "update character state", HK_NULL ); for (int i=0; i < numCharacters; i++) { m_characterContexts[i]->update(input[i], output[i]); } HK_TIMER_END(); } //Apply the character controllers { HK_TIMER_BEGIN( "simulate character", HK_NULL ); for (int i=0; i < numCharacters; i++) { // Feed the output velocity from state machine into character rigid body m_characterRigidBodies[i]->setLinearVelocity(output[i].m_velocity, m_timestep); // If the character has fallen off the world we reposition them hkVector4 pos = m_characterRigidBodies[i]->getRigidBody()->getPosition(); if (pos(1) < -10.0f) { pos.setZero4(); pos(1) = 5; m_characterRigidBodies[i]->getRigidBody()->setPosition(pos); } } HK_TIMER_END(); m_world->unlock(); } // Step the world { hkDefaultPhysicsDemo::stepDemo(); } HK_TIMER_END(); return hkDemo::DEMO_OK; }
TriSampledHeightFieldDemo::TriSampledHeightFieldDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env, DEMO_FLAGS_NO_SERIALIZE) { // Disable face culling setGraphicsState(HKG_ENABLED_CULLFACE, false); // Setup a camera in the right place to see our demo. { hkVector4 from( -3.7f, 5, 17.6f ); hkVector4 to (-1.5f, 1, 1.1f ); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras(env, from, to, up); } { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 100.0f ); info.m_collisionTolerance = 0.03f; m_world = new hkpWorld(info); m_world->lock(); setupGraphics(); } hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() ); // // Create two movable rigid bodies to fall on the two heightfields. // { hkVector4 halfExtents(1.f, .25f, 1.f ); hkpShape* shape = new hkpBoxShape( halfExtents , 0 ); for (int i = 0; i < 2; i++ ) { hkpRigidBodyCinfo ci; ci.m_motionType = hkpMotion::MOTION_SPHERE_INERTIA; ci.m_shape = shape; ci.m_mass = 4.f; hkpMassProperties m; hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape,4, m); ci.m_inertiaTensor = m.m_inertiaTensor; ci.m_position.set( hkReal(i * 7) - 5 , 4, 3 ); hkpRigidBody* body = new hkpRigidBody( ci ); m_world->addEntity(body); body->removeReference(); } shape->removeReference(); } { // Create our heightfield hkpSampledHeightFieldBaseCinfo ci; ci.m_xRes = 7; ci.m_zRes = 7; SimpleSampledHeightFieldShape* heightFieldShape = new SimpleSampledHeightFieldShape( ci ); { // // Create the first fixed rigid body, using the standard heightfield as the shape // hkpRigidBodyCinfo rci; rci.m_motionType = hkpMotion::MOTION_FIXED; rci.m_position.set(-8, 0, 0); rci.m_shape = heightFieldShape; rci.m_friction = 0.2f; hkpRigidBody* bodyA = new hkpRigidBody( rci ); m_world->addEntity(bodyA); bodyA->removeReference(); // // Create the second fixed rigid body, using the triSampledHeightfield // // Wrap the heightfield in a hkpTriSampledHeightFieldCollection: hkpTriSampledHeightFieldCollection* collection = new hkpTriSampledHeightFieldCollection( heightFieldShape ); // Now wrap the hkpTriSampledHeightFieldCollection in a hkpTriSampledHeightFieldBvTreeShape hkpTriSampledHeightFieldBvTreeShape* bvTree = new hkpTriSampledHeightFieldBvTreeShape( collection ); // Finally, assign the new hkpTriSampledHeightFieldBvTreeShape to be the rigid body's shape rci.m_shape = bvTree; rci.m_position.set(-1,0,0); hkpRigidBody* bodyB = new hkpRigidBody( rci ); m_world->addEntity(bodyB); bodyB->removeReference(); heightFieldShape->removeReference(); collection->removeReference(); bvTree->removeReference(); } hkString left("Standard heightfield."); m_env->m_textDisplay->outputText3D(left, -7, -.2f, 7, 0xffffffff, 2000); hkString right("Triangle heightfield."); m_env->m_textDisplay->outputText3D(right, -1, -.2f, 7, 0xffffffff, 2000); } m_world->unlock(); }
void Havok::TestNewFeature() { const float Altitude = 100.0f; const SwingingRopeVariant& variant = g_variants[2]; // const SwingingRopeVariant& variant = g_variants[7]; // const SwingingRopeVariant& variant = g_variants[1]; // const SwingingRopeVariant& variant = g_variants[3]; // Horizontal distance between the attachment points of the strings. const hkReal offset = 50.0f; // // Create the world // { /* hkpWorldCinfo info; info.setBroadPhaseWorldSize( 100000.0f ); info.m_gravity.set(0.0f, 0.0f, -variant.m_gravity); info.m_solverTau = variant.m_tau; mPhysicsWorld = new hkpWorld( info );*/ mPhysicsWorld->lock(); // mPhysicsWorld->m_wantDeactivation = false; } const float Radius = 1.0f; { hkpRigidBodyCinfo info; info.m_shape = new hkpSphereShape(Radius); // info.m_shape = new hkpBoxShape( hkVector4(0.5, 0.5f, 0.5f), 0.01f ); // hkpInertiaTensorComputer::setShapeVolumeMassProperties(info.m_shape, 10.0f, info); hkpInertiaTensorComputer::setShapeVolumeMassProperties(info.m_shape, 1.0f, info); info.m_mass = 1.0f; // info.m_linearVelocity(2) = -10.0f; // // Construct string of independent bilateral constraints // if(0) { hkpConstraintData* data; { hkpBallAndSocketConstraintData* bsData = new hkpBallAndSocketConstraintData(); // bsData->setInBodySpace(hkVector4::getZero(), hkVector4( -1.5f, 0.0f, -0.3f)); bsData->setInBodySpace(hkVector4::getZero(), hkVector4( -1.5f, -0.3f, 0.0f)); data = bsData; } hkpRigidBody* prevBody = HK_NULL; for (int b = 0; b < variant.m_numBodies; b++) { info.m_position.set(1.5f * hkReal(b) - offset / 2.0f, Altitude + 0.3f * hkReal(b), 0.0f); info.m_motionType = b ? hkpMotion::MOTION_DYNAMIC : hkpMotion::MOTION_FIXED; hkpRigidBody* body = new hkpRigidBody(info); mPhysicsWorld->addEntity(body); // HK_SET_OBJECT_COLOR( hkUlong(body->getCollidable()), 0xffff0000 ); mRigidBodies.Add(udword(body)); if (prevBody) { // add constraint hkpConstraintInstance* instance = new hkpConstraintInstance(prevBody, body, data); mPhysicsWorld->addConstraint( instance ); instance->removeReference(); } prevBody = body; // we remove reference, but we know one is still kept by mPhysicsWorld body->removeReference(); } data->removeReference(); } // // Construct constraint chain // { hkArray<hkpEntity*> entities; for (int b = 0; b < variant.m_numBodies; b++) { // info.m_position.set(1.5f * hkReal(b) + offset / 2.0f, Altitude + 0.3f * hkReal(b), 2.0f); info.m_position.set(float(b)*(Radius+0.5f)*2.0f, 0.0f, 0.0f); info.m_motionType = b ? hkpMotion::MOTION_DYNAMIC : hkpMotion::MOTION_FIXED; hkpRigidBody* body = new hkpRigidBody(info); mPhysicsWorld->addEntity(body); // HK_SET_OBJECT_COLOR( hkUlong(body->getCollidable()), 0xff00ff00 ); mRigidBodies.Add(udword(body)); entities.pushBack(body); // we know, a reference is kept by the world body->removeReference(); } { hkpConstraintChainInstance* chainInstance = HK_NULL; if (variant.m_type == BALL_AND_SOCKET) { hkpBallSocketChainData* chainData = new hkpBallSocketChainData(); chainInstance = new hkpConstraintChainInstance( chainData ); chainInstance->addEntity( entities[0] ); for (int e = 1; e < entities.getSize(); e++) { // chainData->addConstraintInfoInBodySpace( hkVector4::getZero(), hkVector4( -1.5f, 0.0f, -0.3f) ); // chainData->addConstraintInfoInBodySpace( hkVector4::getZero(), hkVector4( -1.5f, -0.3f, 0.0f) ); chainData->addConstraintInfoInBodySpace( hkVector4( Radius+0.5f, 0.0f, 0.0f), hkVector4( -Radius-0.5f, 0.0f, 0.0f) ); chainInstance->addEntity( entities[e] ); } chainData->m_tau = variant.m_tau; chainData->removeReference(); } else if(variant.m_type == STIFF_SPRING) { hkpStiffSpringChainData* chainData = new hkpStiffSpringChainData(); chainInstance = new hkpConstraintChainInstance( chainData ); chainInstance->addEntity( entities[0] ); for (int e = 1; e < entities.getSize(); e++) { // chainData->addConstraintInfoInBodySpace( hkVector4::getZero(), hkVector4( -1.0f, 0.0f, -0.2f), 0.55f ); chainData->addConstraintInfoInBodySpace( hkVector4::getZero(), hkVector4( -1.0f, -0.2f, 0.0f), 0.55f ); chainInstance->addEntity( entities[e] ); } chainData->m_tau = variant.m_tau; chainData->removeReference(); } mPhysicsWorld->addConstraint( chainInstance ); chainInstance->removeReference(); } } info.m_shape->removeReference(); } mPhysicsWorld->unlock(); }
OptimizedWorldRaycastDemo::OptimizedWorldRaycastDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { { m_numRigidBodies = int(m_env->m_cpuMhz); m_numBroadphaseMarkers = 64; m_rayLength = 5; m_worldSizeX = 2.0f * hkMath::sqrt(hkReal(m_env->m_cpuMhz)); m_worldSizeY = 3; m_worldSizeZ = m_worldSizeX; } // // Setup the camera. // { hkVector4 from(30.0f, 8.0f, 25.0f); hkVector4 to ( 4.0f, 0.0f, -3.0f); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras(env, from, to, up); // Demo is slow graphicaly as it without shadows forceShadowState(false); } // // Create the world. // { hkpWorldCinfo info; // Set gravity to zero so body floats. info.m_gravity.setZero4(); // make the world big enough to hold all our objects // make y larger so that our raycasts stay within the world aabb info.m_broadPhaseWorldAabb.m_max.set( m_worldSizeX + 10, 10*m_worldSizeY + 10, m_worldSizeZ + 10 ); info.m_broadPhaseWorldAabb.m_min.setNeg4( info.m_broadPhaseWorldAabb.m_max ); // Subdivide the broadphase space into equal sections along the x-axis // NOTE: Disabling this until the marker crash issue is fixed. //info.m_broadPhaseNumMarkers = m_numBroadphaseMarkers; m_world = new hkpWorld(info); m_world->lock(); setupGraphics(); } // register all agents(however, we put all objects into the some group, // so no collision will be detected hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() ); // Add a collision filter to the world to allow the bodies interpenetrate { hkpGroupFilter* filter = new hkpGroupFilter(); filter->disableCollisionsBetween( hkpGroupFilterSetup::LAYER_DEBRIS, hkpGroupFilterSetup::LAYER_DEBRIS ); m_world->setCollisionFilter( filter ); filter->removeReference(); } // // Set the simulation time to 0 // m_time = 0; // // Create our phantom at our origin. // This is a bad hack, we should really create our phantom at it's final position, // but let's keep the demo simple. // If you actually create many phantoms all at the origin, you get a massive CPU spike // as every phantom will collide with every other phantom. // { hkAabb aabb; aabb.m_min.setZero4(); aabb.m_max.setZero4(); m_phantom = new hkpAabbPhantom( aabb ); m_world->addPhantom( m_phantom ); m_phantomUseCache = new hkpAabbPhantom( aabb ); m_world->addPhantom( m_phantomUseCache ); } // // Create some bodies (reuse the ShapeRaycastApi demo) // createBodies(); m_world->unlock(); }
WorldLinearCastMultithreadingApiDemo::WorldLinearCastMultithreadingApiDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env, DEMO_FLAGS_NO_SERIALIZE), m_time(0.0f) { const WorldLinearCastMultithreadingApiDemoVariant& variant = g_WorldLinearCastMultithreadingApiDemoVariants[m_variantId]; // // Setup the camera. // { hkVector4 from(0.0f, 30.0f, 45.0f); hkVector4 to(0.0f, 0.0f, 5.0f); hkVector4 up(0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up ); } // // Create the world. // { hkpWorldCinfo info; { info.setBroadPhaseWorldSize( 1000.0f ); info.m_gravity.setZero4(); } m_world = new hkpWorld( info ); m_world->lock(); // Register ALL agents (though some may not be necessary) hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // // Create a simple list shape. // hkpListShape* listShape; { hkVector4 boxSize1(1,2,1); hkpBoxShape* box1 = new hkpBoxShape(boxSize1); hkVector4 boxSize2(2,1,1); hkpBoxShape* box2 = new hkpBoxShape(boxSize2); hkpShape* list[2] = {box1, box2}; listShape = new hkpListShape(list, 2); box1->removeReference(); box2->removeReference(); } { hkVector4 position(0.0f, 0.0f, 0.0f); m_castBody = GameUtils::createRigidBody(listShape, 0.0f, position); m_world->addEntity(m_castBody); m_castBody->removeReference(); } // // Create a circle of simple list shapes. // { int numBoxesInCircle = 10; hkReal angleStep = (2.0f * HK_REAL_PI) / hkReal(numBoxesInCircle); hkReal radius = 15.0f; for (float angle = 0.0f; angle < 2.0f * HK_REAL_PI; angle += angleStep) { hkVector4 position(radius * hkMath::sin(angle), 0.0f, radius * hkMath::cos(angle)); hkVector4 size(3.0f, 3.0f, 3.0f); hkpRigidBody* body = GameUtils::createRigidBody(listShape, 0.0f, position); m_world->addEntity(body); body->removeReference(); } listShape->removeReference(); } { hkpGroupFilter* filter = new hkpGroupFilter(); m_world->setCollisionFilter(filter); filter->removeReference(); } // // Some magic to create a second graphical representation of the cast body. // { hkArray<hkDisplayGeometry*> geom; hkpShapeDisplayBuilder::hkpShapeDisplayBuilderEnvironment sdbe; hkpShapeDisplayBuilder builder(sdbe); builder.buildShapeDisplay( m_castBody->getCollidable()->getShape(), hkTransform::getIdentity(), geom ); m_env->m_displayHandler->addGeometry(geom, m_castBody->getCollidable()->getTransform(), 1 , 0, 0 ); hkReferencedObject::removeReferences(geom.begin(), geom.getSize()); } m_world->unlock(); // Special case for this demo variant: we do not allow the # of active SPUs to drop to zero as this can cause a deadlock. if ( variant.m_demoType == WorldLinearCastMultithreadingApiDemoVariant::MULTITHREADED_ON_SPU ) m_allowZeroActiveSpus = false; // Register the collision query functions hkpCollisionQueryJobQueueUtils::registerWithJobQueue(m_jobQueue); hkpRayCastQueryJobQueueUtils::registerWithJobQueue(m_jobQueue); // register the default addCdPoint() function; you are free to register your own implementation here though hkpFixedBufferCdPointCollector::registerDefaultAddCdPointFunction(); }
CenterOfMassChangerDemo::CenterOfMassChangerDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // Disable warnings: hkError::getInstance().setEnabled(0xf0de4356, false); // 'Your m_contactRestingVelocity seems to be too small' // // Setup the camera // { hkVector4 from(0.0f, 8.0f, 24.0f); hkVector4 to (0.0f, 0.0f, 0.0f); hkVector4 up (0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up ); } // // Create the world // { hkpWorldCinfo info; info.m_gravity.set(0.0f, -9.8f, 0.0f); info.setupSolverInfo(hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM); info.m_solverIterations = 1; info.m_collisionTolerance = 0.01f; info.m_contactRestingVelocity = 0.01f; // simple response //info.m_contactRestingVelocity = 10000.01f; // solver-only response info.m_enableSimulationIslands = false; info.m_gravity.setZero4(); m_world = new hkpWorld( info ); m_world->lock(); // Register ALL agents (though some may not be necessary) hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // // Create the base // { hkVector4 baseSize( 30.0f, 0.5f, 30.0f); hkpConvexShape* shape = new hkpBoxShape( baseSize , 0 ); hkpRigidBodyCinfo ci; ci.m_shape = shape; ci.m_motionType = hkpMotion::MOTION_FIXED; ci.m_position.set(0.0f, -0.5f, 0.0f); ci.m_friction = 0.0f; //m_world->addEntity( new hkpRigidBody( ci ) )->removeReference(); shape->removeReference(); } hkVector4 rowPositionOffset(0.0f, 0.0f, 2.0f); const int numRows = 10; for (int p = 0; p < numRows; p++) { // // Create 3 boxes // { hkpRigidBody* body; hkpRigidBodyCinfo boxInfo; //boxInfo.m_shape = new hkpCylinderShape(hkVector4::getZero(), hkVector4(0.0f, 0.3f, 0.0f), 0.6f, 0.0f); boxInfo.m_shape = new hkpSphereShape(0.6f); hkpInertiaTensorComputer::setShapeVolumeMassProperties(boxInfo.m_shape, 1.0f, boxInfo); boxInfo.m_qualityType = HK_COLLIDABLE_QUALITY_DEBRIS; boxInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA; boxInfo.m_friction = 0.0f; boxInfo.m_restitution = 1.0f;//hkReal(p)/hkReal(numRows-1); // box 0 // boxInfo.m_restitution = 0.0f; boxInfo.m_position.set(-5.0f, 0.0f, 0.0f); boxInfo.m_position.addMul4(hkReal(p), rowPositionOffset); boxInfo.m_rotation.setAxisAngle(hkVector4(0.0f, 0.0f, 1.0f), 180.0f * HK_REAL_DEG_TO_RAD); hkpRigidBody* hitBody = body = new hkpRigidBody(boxInfo); m_world->addEntity(body)->removeReference(); boxInfo.m_restitution = 1.0f;//hkReal(p)/hkReal(numRows-1); boxInfo.m_rotation.setIdentity(); // box 1 // boxInfo.m_position.set(0.0f, 0.0f, 0.0f); boxInfo.m_position.addMul4(hkReal(p), rowPositionOffset); hkpRigidBody* hittingBody = body = new hkpRigidBody(boxInfo); m_world->addEntity(body)->removeReference(); // box 2 // boxInfo.m_position.set( 10.0f, 0.0f, 0.0f); boxInfo.m_position.addMul4(hkReal(p), rowPositionOffset); boxInfo.m_linearVelocity.set(-10.0f, 0.0f, 0.0f); body = new hkpRigidBody(boxInfo); m_world->addEntity(body)->removeReference(); //hkVector4 comDisplacement(0.0f, 1.5f, 1.5f); hkVector4 comDisplacement(0.0f, 0.0f + 0.5f * hkReal(p), 0.0f); hkpCenterOfMassChangerUtil* cmcu = new hkpCenterOfMassChangerUtil( hittingBody, hitBody, hkVector4::getZero(), comDisplacement ); m_utils.pushBack(cmcu); boxInfo.m_shape->removeReference(); } } m_world->unlock(); }
virtual int read(void* buf, int nbytes) { m_bytesRead += nbytes; m_demo->progressSet(hkReal(m_bytesRead) / m_fileSize); return m_child->read(buf, nbytes); }
void DetailedTimersDemo::timeDemo( hkDemo* demo, int iterations, const char* fileName ) { // // Time the demo // hkMonitorStreamFrameInfo frameInfo; # ifdef HK_PS2 frameInfo.m_indexOfTimer0 = 1; frameInfo.m_indexOfTimer1 = 0; // Assume that each instruction cache miss cost around 35 cycles. // So we can see how much of our overall time is spent waiting for the // memory system frameInfo.m_timerFactor0 = 35.0f / 300.f; frameInfo.m_timerFactor1 = 1.0f / 300.f; frameInfo.m_heading = "usec: IcachePenalty (assuming 35 cycle penalty)"; # else frameInfo.m_indexOfTimer0 = 0; frameInfo.m_indexOfTimer1 = -1; frameInfo.m_heading = "usecs"; frameInfo.m_timerFactor0 = 1e6f / hkReal(hkStopwatch::getTicksPerSecond()); # endif int demoIdx = hkDemoDatabase::getInstance().findDemo( TEST_DEMO_FULLPATH ); HK_ASSERT2(0x654e432e, demoIdx != -1, "Demo does not exist" ); const bool isPhysicsDemo = (HK_DEMO_TYPE_PHYSICS == hkDemoDatabase::getInstance().getDemos()[ demoIdx ].m_demoTypeFlags); // // Setup some memory to store all the timer information // for all frames // int numThreads = 1; if( isPhysicsDemo ) { hkCpuJobThreadPool* mtUtil = (hkCpuJobThreadPool*)static_cast<hkDefaultPhysicsDemo*>(demo)->m_jobThreadPool; if (mtUtil) { numThreads += mtUtil->getNumThreads(); } } hkMonitorStreamAnalyzer streamAnalyzer( 10000000, numThreads ); for (int i = 0; i < iterations; i++ ) { // // Setup the timerinfo and memory on a per frame bases // hkMonitorStream& stream = hkMonitorStream::getInstance(); stream.resize( 2 * 1024 * 1024 ); // 2 meg for timer info per frame stream.reset(); // // Start timers // # ifdef HK_PS2 scePcStart( SCE_PC_CTE | SCE_PC_U0 | SCE_PC_U1 | SCE_PC0_ICACHE_MISS | SCE_PC1_CPU_CYCLE, 0 ,0 ); # endif // // Step the demo // demo->stepDemo(); // // Stop timers. This is necessary as a timer overflow on PlayStation(R)2 causes an exception // # ifdef HK_PS2 scePcStop() ; # endif // // Analyze the per frame info and copy the data over to the multi frame buffer // if( numThreads > 1 ) { hkCpuJobThreadPool* mtUtil = (hkCpuJobThreadPool*)static_cast<hkDefaultPhysicsDemo*>(demo)->m_jobThreadPool; // Loop through each thread. Capture the frame details from the local // stream analyzer in each thread. for (int t = 0; t < mtUtil->getNumThreads(); ++t) { hkCpuJobThreadPool::WorkerThreadData& data = mtUtil->m_workerThreads[t]; if (data.m_monitorStreamBegin != data.m_monitorStreamEnd ) { frameInfo.m_threadId = t + 1; streamAnalyzer.captureFrameDetails( data.m_monitorStreamBegin,data.m_monitorStreamEnd, frameInfo ); } } } frameInfo.m_threadId = 0; streamAnalyzer.captureFrameDetails(stream.getStart(), stream.getEnd(), frameInfo ); } // // Write the results to a file // { // Disable double conversion check - we know this will fail pushDoubleConversionCheck(false); hkReferencedObject::lockAll(); hkOstream ostr (fileName); ostr << TEST_DEMO_NAME " Timers: \n"; streamAnalyzer.writeStatistics( ostr ); hkReferencedObject::unlockAll(); popDoubleConversionCheck(); } }