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(); }
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(); }