void ShapeQueryDemo::worldGetClosestPoints( hkpWorld* world, hkReal time, hkArray<QueryObject>& queryObjects ) { hkpAllCdPointCollector collector[10]; // We setup the usual loop and call the getClosestPoints(...) method: { for ( int i = 0; i < queryObjects.getSize(); i++ ) { QueryObject& qo = queryObjects[i]; // create a new position: all objects move in a circle hkReal t = time + HK_REAL_PI * 2 * i / queryObjects.getSize(); hkVector4 pos( hkMath::sin( t ) * 10.0f, 0.0f, hkMath::cos( t ) * 10.0f ); qo.m_transform->setTranslation(pos); // Query for intersecting objects for (int j = 0; j < NUM_ITER; j++ ) { MY_TIMER_BEGIN(i); collector[i].reset(); world->getClosestPoints( qo.m_collidable, *world->getCollisionInput(), collector[i] ); MY_TIMER_END(); } } } // Updating our display is carried out in the usual manner: { for ( int i = 0; i < queryObjects.getSize(); i++ ) { // iterate over each individual hit for (int j = 0; j < collector[i].getHits().getSize(); j++ ) { displayRootCdPoint( world, collector[i].getHits()[j] ); } } } { for ( int i = 0; i < queryObjects.getSize(); i++ ) { QueryObject& qo = queryObjects[i]; hkDebugDisplay::getInstance().updateGeometry( qo.m_collidable->getTransform(), (hkUlong)qo.m_collidable, 0); } } }
hkDemo::Result WorldLinearCastMultithreadedDemo::stepDemo() { if (m_jobThreadPool->getNumThreads() == 0) { HK_WARN(0x34561f23, "This demo does not run with only one thread"); return DEMO_STOP; } // const WorldLinearCastMultithreadedDemoVariant& variant = g_WorldLinearCastMultithreadedDemoVariants[m_variantId]; m_world->lock(); // Reset all object colors { for (int i = 0; i < m_rocksOnTheFloor.getSize(); i++) { HK_SET_OBJECT_COLOR((hkUlong)m_rocksOnTheFloor[i]->getCollidable(), hkColor::rgbFromChars(70,70,70)); } } // For this cast we use a hkpClosestCdPointCollector to gather the results: hkpClosestCdPointCollector collectors[10]; // Since we're not too concerned with perfect accuracy, we can set the early out // distance to give the algorithm a chance to exit more quickly: m_world->getCollisionInput()->m_config->m_iterativeLinearCastEarlyOutDistance = 0.1f; m_world->unlock(); // Cast direction & length. hkVector4 castVector( 0.0f, -30.0f, 0.0f ); int numQueryObjects = m_queryObjects.getSize(); // // Setup the output array where the resulting collision points will be returned. // hkpRootCdPoint* collisionPoints = hkAllocateChunk<hkpRootCdPoint>(numQueryObjects, HK_MEMORY_CLASS_DEMO); // // Setup commands: one command for each query object. // hkArray<hkpWorldLinearCastCommand> commands; { for ( int i = 0; i < numQueryObjects; i++ ) { QueryObject& queryObject = m_queryObjects[i]; // // Let QueryObjects move in circles. // hkVector4 position; { hkReal t = m_time + HK_REAL_PI * 2 * i / m_queryObjects.getSize(); position.set( hkMath::sin( t ) * 10.0f, 10.0f, hkMath::cos( t ) * 10.0f ); } queryObject.m_transform->setTranslation(position); hkpWorldLinearCastCommand& command = commands.expandOne(); { // Init input data. { command.m_input.m_to . setAdd4( position, castVector ); command.m_input.m_maxExtraPenetration = HK_REAL_EPSILON; command.m_input.m_startPointTolerance = HK_REAL_EPSILON; command.m_collidable = queryObject.m_collidable; } // Init output data. { command.m_results = &collisionPoints[i]; command.m_resultsCapacity = 1; command.m_numResultsOut = 0; } } } } // // Create the job header. // hkpCollisionQueryJobHeader* jobHeader; { jobHeader = hkAllocateChunk<hkpCollisionQueryJobHeader>(1, HK_MEMORY_CLASS_DEMO); } // // Setup hkpWorldLinearCastJob. // m_world->markForRead(); hkpWorldLinearCastJob worldLinearCastJob(m_world->getCollisionInput(), jobHeader, commands.begin(), commands.getSize(), m_world->m_broadPhase, &m_semaphore); m_world->unmarkForRead(); // // Put the job on the queue, kick-off the PPU/SPU threads and wait for everything to finish. // { m_world->lockReadOnly(); // // Put the raycast job on the job queue. // worldLinearCastJob.setRunsOnSpuOrPpu(); m_jobQueue->addJob( worldLinearCastJob, hkJobQueue::JOB_LOW_PRIORITY ); m_jobThreadPool->processAllJobs( m_jobQueue ); m_jobThreadPool->waitForCompletion(); // // Wait for the one single job we started to finish. // m_semaphore.acquire(); m_world->unlockReadOnly(); } // // Display results. // { m_world->lock(); { for (int i = 0; i < commands.getSize(); i++) { QueryObject& queryObject = m_queryObjects[i]; hkpWorldLinearCastCommand& command = commands[i]; if ( command.m_numResultsOut > 0 ) { // move our position to the hit and draw a line along the cast direction hkVector4& pos = queryObject.m_transform->getTranslation(); hkVector4 to; to.setAdd4( pos, castVector ); hkVector4 newPos; newPos.setInterpolate4( pos, to, command.m_results->m_contact.getDistance() ); HK_DISPLAY_LINE(pos, newPos, hkColor::GREEN); // Update our QO queryObject.m_transform->setTranslation( newPos ); hkDebugDisplay::getInstance().updateGeometry( queryObject.m_collidable->getTransform(), (hkUlong)queryObject.m_collidable, 0); // call a function to display the details displayRootCdPoint( m_world, *command.m_results ); } else { // only draw a line along the cast direction hkVector4& pos = queryObject.m_transform->getTranslation(); hkVector4 to; to.setAdd4( pos, castVector ); HK_DISPLAY_LINE(pos, to, hkColor::GREEN); // Update our QO hkVector4 nirvana(10000.0f, 10000.0f, 10000.0f); queryObject.m_transform->setTranslation( nirvana ); hkDebugDisplay::getInstance().updateGeometry( queryObject.m_collidable->getTransform(), (hkUlong)queryObject.m_collidable, 0); } } } m_world->unlock(); } // // Free temporarily allocated memory. // hkDeallocateChunk( jobHeader, 1, HK_MEMORY_CLASS_DEMO ); hkDeallocateChunk(collisionPoints, numQueryObjects, HK_MEMORY_CLASS_DEMO); m_time += 0.005f; return hkDefaultPhysicsDemo::stepDemo(); }
void ShapeQueryDemo::worldLinearCast( hkpWorld* world, hkReal time, hkArray<QueryObject>& queryObjects ) { // For this cast we use a hkpClosestCdPointCollector to gather the results: hkpClosestCdPointCollector collector[10]; // Since we're not too concerned with perfect accuracy, we can set the early out // distance to give the algorithm a chance to exit more quickly: world->getCollisionInput()->m_config->m_iterativeLinearCastEarlyOutDistance = 0.1f; // Cast direction hkVector4 displacement( 0.0f, -30.0f, 0.0f ); // Perform all queries in one go (do not interleave with examining the results, // as this is bad for code and data cache. // The core loop is very similar to the one we described for the world ray cast, // with several casts being performed forming a circular pattern. The only // real difference this time is that we get the shape to cast (and the 'from' // position) from our collection of 'QueryObjects'. { for ( int i = 0; i < queryObjects.getSize(); i++ ) { QueryObject& qo = queryObjects[i]; // Create a new position: all objects move in a circle hkReal t = time + HK_REAL_PI * 2 * i / queryObjects.getSize(); hkVector4 pos( hkMath::sin( t ) * 10.0f, 10.0f, hkMath::cos( t ) * 10.0f ); // Set our position in our motion state qo.m_transform->setTranslation(pos); // // Query for intersecting objects // for (int k = 0; k < NUM_ITER ; k++ ) { MY_TIMER_BEGIN(i); { // Input hkpLinearCastInput input; input.m_to.setAdd4( pos, displacement ); // Output hkpClosestCdPointCollector& coll = collector[i]; coll.reset(); // Call the engine world->linearCast( qo.m_collidable, input, coll ); } MY_TIMER_END(); } } } // // Batch examine the results // // All that remains to do now is to display the results and update the position of our 'QueryObjects' (QO). We use the updateGeometry(...) // method from hkDebugDisplay to do the QO updates and once again we draw everything in GREEN: { for ( int i = 0; i < queryObjects.getSize(); i++ ) { QueryObject& qo = queryObjects[i]; // update our display if ( collector[i].hasHit() ) { // move our position to the hit and draw a line along the cast direction hkVector4& pos = qo.m_transform->getTranslation(); hkVector4 to; to.setAdd4( pos, displacement ); hkVector4 newPos; newPos.setInterpolate4( pos, to, collector[i].getHitContact().getDistance() ); HK_DISPLAY_LINE(pos, newPos, hkColor::GREEN); // Update our QO qo.m_transform->setTranslation( newPos ); hkDebugDisplay::getInstance().updateGeometry( qo.m_collidable->getTransform(), (hkUlong)qo.m_collidable, 0); // call a function to display the details displayRootCdPoint( world, collector[i].getHit() ); } } } }