const char* HK_CALL hkDemoFileSystem::removeDemoBasePath( const char* pathIn, hkArray<char>& buffer ) { hkString path( pathIn ); path.makeLowerCase(); // strip everything up to the demo root folder hkString root("/demos/"); root.makeLowerCase(); const char* str = path.cString(); const char* start = hkString::strStr(str, root.cString()); if ( start != HK_NULL ) { int pos = static_cast<int>(start - str) + root.getLength(); buffer.setSize( path.getLength() - pos + 1 ); // copy the part of the string that follows the demo prefix hkString::memCpy( buffer.begin(), pathIn+pos, buffer.getSize()-1 ); buffer[ buffer.getSize()-1 ] = 0; // null terminate return buffer.begin(); } else { // nothing to do return pathIn; } }
// // Test function to make sure that the hits from the kd-tree are identical to the ones from the broadphase. // static hkBool compareHitArrays(const hkAabb& aabb, const hkPrimitiveId* kdHits, int numKdHits, const hkArray<hkpBroadPhaseHandlePair>& sapHits) { hkLocalArray<const hkpCollidable*> sapCollidables(sapHits.getSize()); for (int i=0; i<sapHits.getSize(); i++) { const hkpTypedBroadPhaseHandle* tp = static_cast<const hkpTypedBroadPhaseHandle*>( sapHits[i].m_b ); const hkpCollidable* collB = static_cast<hkpCollidable*>(tp->getOwner()); // Make sure no spurious hits from the broadphase hkAabb colAabb; hkpRigidBody* rb = hkGetRigidBody(collB); if (rb) { collB->getShape()->getAabb(rb->getTransform(), 0.0f, colAabb); hkBool aabbOverlap = colAabb.overlaps(aabb); if (aabbOverlap) sapCollidables.pushBack(collB); } } // Make sure that the contents of the arrays at the same // It would be faster to sort and do a string compare, but this is just as easy. hkBool isOk = true; for (int i=0; i<numKdHits; i++) { const hkpCollidable* kdCollidable = reinterpret_cast<const hkpCollidable*> (kdHits[i]); int idx = sapCollidables.indexOf(kdCollidable); if(idx < 0) { // There's a hit in the kd-tree's list but not the 3AxisSweep's list // It's possible that 3AxisSweep skipped something. So get the AABB of the body in the kd-tree list. hkAabb colAabb; hkpRigidBody* rb = hkGetRigidBody(kdCollidable); kdCollidable->getShape()->getAabb(rb->getTransform(), rb->getWorld()->getCollisionInput()->getTolerance(), colAabb); hkBool aabbOverlap = colAabb.overlaps(aabb); if (!aabbOverlap) { // Something in the list doesn't overlap with the query's aabb isOk = false; } continue; } sapCollidables.removeAt(idx); } // If we made it this far, they must agree. return isOk && sapCollidables.isEmpty(); }
void HK_CALL SlidingWorldDemo::removeDuplicatesFromArray(hkArray<hkpBroadPhaseHandle*>& objectsEnteringBroadphaseBorder ) { hkArray<hkpBroadPhaseHandle*> noDups; noDups.reserve( objectsEnteringBroadphaseBorder.getSize() ); for (int i = 0; i < objectsEnteringBroadphaseBorder.getSize(); i++) { if( noDups.indexOf( objectsEnteringBroadphaseBorder[i] ) == -1) { noDups.pushBack( objectsEnteringBroadphaseBorder[i] ); } } objectsEnteringBroadphaseBorder.swap( noDups ); }
void ShapeQueryDemo::worldGetPenetrations( hkpWorld* world, hkReal time, hkArray<QueryObject>& queryObjects ) { hkpAllCdBodyPairCollector collector[10]; // Next we batch query the system (that is ask for the penetrations N times before processing the results). // This follows our usual core loop: 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->getPenetrations( qo.m_collidable, *world->getCollisionInput(), collector[i] ); MY_TIMER_END(); } } // Next up is the display update, first we highlight any overlapping triangles or objects: { for ( int i = 0; i < queryObjects.getSize(); i++ ) { // iterate over each individual hit for (int j = 0; j < collector[i].getHits().getSize(); j++ ) { displayRootCdBody( world, collector[i].getHits()[j].m_rootCollidableB, collector[i].getHits()[j].m_shapeKeyB ); } } } // Followed by a geometry update for our QO: { for ( int i = 0; i < queryObjects.getSize(); i++ ) { QueryObject& qo = queryObjects[i]; hkDebugDisplay::getInstance().updateGeometry( qo.m_collidable->getTransform(), (hkUlong)qo.m_collidable, 0); } } }
static void FillTransforms( hkArray<hkQsTransform>& transforms, int boneIdx, int numTracks , const hkQsTransform& localTransform, PosRotScale prs = prsDefault , int from=0, int to=-1) { int n = transforms.getSize() / numTracks; if (n == 0) return; if (to == -1 || to >= n) to = n-1; if ((prs & prsDefault) == prsDefault) { for (int idx = from; idx <= to; ++idx) { hkQsTransform& transform = transforms[idx*numTracks + boneIdx]; transform = localTransform; } } else { for (int idx = from; idx <= to; ++idx) { hkQsTransform& transform = transforms[idx*numTracks + boneIdx]; if ((prs & prsPos) != 0) transform.setTranslation(localTransform.getTranslation()); if ((prs & prsRot) != 0) transform.setRotation(localTransform.getRotation()); if ((prs & prsScale) != 0) transform.setScale(localTransform.getScale()); } } }
void WorldLinearCastMultithreadedDemo::buildQueryObects( hkArray<hkpShape*>& shapes, hkArray<QueryObject>& objects ) { hkpShapeDisplayBuilder::hkpShapeDisplayBuilderEnvironment env; hkpShapeDisplayBuilder builder(env); for (int i = 0; i < shapes.getSize(); i++) { QueryObject qo; qo.m_transform = new hkTransform(); qo.m_transform->setIdentity(); qo.m_collidable = new hkpCollidable( shapes[i], qo.m_transform ); objects.pushBack( qo ); hkArray<hkDisplayGeometry*> displayGeometries; builder.buildDisplayGeometries( shapes[i], displayGeometries ); hkDebugDisplay::getInstance().addGeometry( displayGeometries, hkTransform::getIdentity(), (hkUlong)qo.m_collidable, 0, 0 ); while( displayGeometries.getSize() ) { delete displayGeometries[0]; displayGeometries.removeAt(0); } // Set green color HK_SET_OBJECT_COLOR((hkUlong)qo.m_collidable, hkColor::rgbFromChars(0,255,0,120)); } }
void HK_CALL VehicleApiUtils::syncDisplayWheels(hkDemoEnvironment* environment, hkpVehicleInstance& vehicle, const hkArray<int>& wheels, int tag) { // // Sync wheels. This is necessary only because they do not "exist" as bodies in simulation, // and so are not automatically updated by the current display. We must explicity tell the // display that some other "display obects" (objects which are drawn but are not physical) // have moved. // for (int i = 0; i < wheels.getSize(); i++) { hkVector4 pos; hkQuaternion rot; // // XXX Check if this is the same value as the m_hardPointWS in wheelsInfo // // vehicle.calcCurrentPositionAndRotation( vehicle.getChassis(), vehicle.m_suspension, i, pos, rot ); hkTransform trans(rot, pos); environment->m_displayHandler->updateGeometry(trans, wheels[i], tag); } }
void hkvImageFileProperties::setProperty(const hkvProperty& prop, const hkArray<hkStringPtr>& path, hkUint32 stackIndex, hkvProperty::Purpose purpose) { int stackSize = (path.getSize() - stackIndex); if ((stackSize != 0)) return; if (hkvStringHelper::safeCompare(prop.getName(), "FileFormat") == 0) { if (m_imageFormatInstance.setByString(prop.getString()) != HK_SUCCESS) { m_imageFormatInstance.setByDefinitionId(HKV_IMAGE_FILE_FORMAT_INVALID); } } else if (hkvStringHelper::safeCompare(prop.getName(), "Width") == 0) { m_width = prop.getUint(); } else if (hkvStringHelper::safeCompare(prop.getName(), "Height") == 0) { m_height = prop.getUint(); } else if (hkvStringHelper::safeCompare(prop.getName(), "HasAlpha") == 0) { m_hasAlpha = prop.getBool(); } }
void hkvTextureAsset::setSpecificProperty(const hkvProperty& prop, const hkArray<hkStringPtr>& path, unsigned int stackIndex, hkvProperty::Purpose purpose) { int stackSize = (path.getSize() - stackIndex); if ((stackSize == 1) && (hkvStringHelper::safeCompare(path.back(), "Texture") == 0)) { m_imageProperties.setProperty(prop, path, stackIndex + 1, purpose); // Usage is still present here for backwards compatibility to convert older asset libraries, but has now moved to the texture transform rule instead. if (hkvStringHelper::safeCompare(prop.getName(), "Usage") == 0) { if (purpose == hkvProperty::PURPOSE_SERIALIZATION) { if (m_usageInstance.setByString(prop.getString()) != HK_SUCCESS) { m_usageInstance.setByAvailableElementsId(0); } } } else if (hkvStringHelper::safeCompare(prop.getName(), "sRGB") == 0) { m_sRgb = prop.getBool(); } } }
void hkvTextureAsset::setSpecificProperty(const hkvProperty& prop, const hkArray<hkStringPtr>& path, unsigned int stackIndex, hkvProperty::Purpose purpose) { int stackSize = (path.getSize() - stackIndex); if ((stackSize == 1) && (hkvStringHelper::safeCompare(path.back(), "Texture") == 0)) { m_imageProperties.setProperty(prop, path, stackIndex + 1, purpose); if (hkvStringHelper::safeCompare(prop.getName(), "Usage") == 0) { if (purpose == hkvProperty::PURPOSE_SERIALIZATION) { if (m_usageInstance.setByString(prop.getString()) != HK_SUCCESS) { m_usageInstance.setByAvailableElementsId(0); } } else { m_usageInstance.setByAvailableElementsId(prop.getEnumValue()); } } else if (hkvStringHelper::safeCompare(prop.getName(), "sRGB") == 0) { m_sRgb = prop.getBool(); } } }
hkString findCommonRootPath( const hkArray< hkDemoEntry* >& demos ) { hkString prefix = ""; // // Find the common root, be careful if there is only one demo // special: if we see "*/Demo/" means <toplevel>/Demo { int i = 0; while( i < demos.getSize() && prefix.getLength() == 0 ) { if(demos[i]->m_menuPath[0] != '*') // get a regular path. { int lastSlash = demos[i]->m_menuPath.lastIndexOf('/'); if(lastSlash >= 0) { prefix = demos[i]->m_menuPath.substr(0, lastSlash + 1); prefix.makeLowerCase(); } } ++i; } } for(int i = 0; i < demos.getSize() && prefix.getLength() != 0; ++i) { if( demos[i]->m_menuPath[0] != '*') { hkString gp = demos[i]->m_menuPath.asLowerCase(); while( !gp.beginsWith(prefix) ) { // commonRoot is foo/bar/ we want the second last / int lastSlash = prefix.lastIndexOf('/', 0, prefix.getLength() - 1 ); if(lastSlash >= 0) { // want the trailing / in the commonRoot prefix.setAsSubstr(0, lastSlash + 1); } else { prefix = ""; } } } // if != * } // for return prefix; }
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); } } }
void hkvTagfileAsset::setInternalProperty(const hkvProperty& prop, const hkArray<hkStringPtr>& path, unsigned int stackIndex, hkvProperty::Purpose purpose) { int stackSize = (path.getSize() - stackIndex); if ((stackSize >= 1) && (hkvStringHelper::safeCompare(path[stackIndex + 0], "Tagfile") == 0)) { setTagfileArrayProperty(prop, path, stackIndex, purpose); } }
void hkvTextureTransformationRule::setProperty(const hkvProperty& prop, const hkArray<hkStringPtr>& path, unsigned int iStackIndex, hkvProperty::Purpose purpose) { int iStackSize = (path.getSize() - iStackIndex); if (iStackSize == 0) { if (hkvStringHelper::safeCompare(prop.getName(), "Compression") == 0) { if (purpose == hkvProperty::PURPOSE_SERIALIZATION) { if (m_compressionInstance.setByString(prop.getString()) != HK_SUCCESS) { m_compressionInstance.setByAvailableElementsId(0); } } else { m_compressionInstance.setByAvailableElementsId(prop.getEnumValue()); } } else if (hkvStringHelper::safeCompare(prop.getName(), "Usage") == 0) { if (purpose == hkvProperty::PURPOSE_SERIALIZATION) { if (m_usageInstance.setByString(prop.getString()) != HK_SUCCESS) { m_usageInstance.setByAvailableElementsId(0); } } else { m_usageInstance.setByAvailableElementsId(prop.getEnumValue()); } } else if (hkvStringHelper::safeCompare(prop.getName(), "RemoveAlphaChannel") == 0) { m_removeAlphaChannel = prop.getBool(); } else if (hkvStringHelper::safeCompare(prop.getName(), "CreateMipMaps") == 0) { m_createMipMaps = prop.getBool(); } else if (hkvStringHelper::safeCompare(prop.getName(), "DownscaleLevel") == 0) { m_downscaleLevel = prop.getUint(); } else if (hkvStringHelper::safeCompare(prop.getName(), "MinimumSize") == 0) { m_minSize = prop.getUint(); } else if (hkvStringHelper::safeCompare(prop.getName(), "MaximumSize") == 0) { m_maxSize = prop.getUint(); } } }
static void SetTransformScaleRange( hkArray<hkQsTransform>& transforms, int numTracks, int boneIdx , float ¤tTime, float lastTime, int &frame , FloatKey &first, FloatKey &last) { int n = transforms.getSize()/numTracks; for ( ; COMPARE(currentTime, lastTime) <= 0 && frame < n; currentTime += FramesIncrement, ++frame) { hkQsTransform& transform = transforms[frame*numTracks + boneIdx]; SetTransformScale(transform, first.data); } }
/*---------------------------------------------------------------------------*/ void NifCollisionUtility::reorderTriangles(hkArray<hkGeometry::Triangle>& srcAry) { int length (srcAry.getSize() - 1); short idxGroup(0); // for each triangle in list for (int idx(0); idx < length; ++idx) { hkGeometry::Triangle& dstTri(srcAry[idx]); hkGeometry::Triangle& srcTri(srcAry[idx+1]); int vertsDst[3] = {dstTri.m_a, dstTri.m_b, dstTri.m_c}; int vertsSrc[3] = {srcTri.m_a, srcTri.m_b, srcTri.m_c}; short idxDst(0); short idxSrc(0); short cntPts(0); // find common edge for (; idxDst < 3; ++idxDst) { for (idxSrc=0; idxSrc < 3; ++idxSrc) { if (vertsSrc[idxSrc] == vertsDst[idxDst]) break; } if (idxSrc > 2) { vertsDst[idxDst] = -1; } } for (idxDst=0; idxDst < 3; ++idxDst) { if (vertsDst[idxDst] != -1) ++cntPts; } // swap two vertices in case of uneven triangle in group having common edge with precessor if ((cntPts == 2) && ((idxGroup % 2) == 1)) { int tmp(srcTri.m_a); srcTri.m_a = srcTri.m_c; srcTri.m_c = tmp; } // no common edge => start new group else if (cntPts != 2) { idxGroup = 0; } // increase index in group ++idxGroup; } // for (int idxRes(0); idxRes < length; ++idxRes) }
void hkDefaultPhysicsDemo::addTimersToVdb( const hkArray<hkTimerData>& threadStreams, const hkArray<hkTimerData>& spuStreams ) { // reset our VDB stats list if (m_physicsViewersContext) { m_physicsViewersContext->m_monitorStreamBegins.setSize(0); m_physicsViewersContext->m_monitorStreamEnds.setSize(0); } for ( int i = 0; i < threadStreams.getSize(); ++i ) { m_physicsViewersContext->m_monitorStreamBegins.pushBack(threadStreams[i].m_streamBegin); m_physicsViewersContext->m_monitorStreamEnds.pushBack(threadStreams[i].m_streamEnd); } for ( int ii = 0; ii < spuStreams.getSize(); ++ii ) { m_physicsViewersContext->m_monitorStreamBegins.pushBack(spuStreams[ii].m_streamBegin); m_physicsViewersContext->m_monitorStreamEnds.pushBack(spuStreams[ii].m_streamEnd); } }
static void phantomGetPenetrations( ShapeQueryDemo* demo, hkArray<T*>& phantoms, hkReal offset ) { hkpAllCdBodyPairCollector collector[10]; // Perform all queries in one go (do not interleave with examining the results, // as this is bad for code and data cache. { for ( int i = 0; i < phantoms.getSize(); i++ ) { // create a new position: all objects move in a circle hkReal t = demo->m_time + HK_REAL_PI * 2 * i / phantoms.getSize() + offset; hkVector4 pos( hkMath::sin( t ) * 10.0f, 0.0f, hkMath::cos( t ) * 10.0f ); phantoms[i]->setPosition(pos); // Query for intersecting objects for (int j = 0; j < NUM_ITER; j++ ) { MY_TIMER_BEGIN(i); collector[i].reset(); phantoms[i]->getPenetrations( collector[i] ); MY_TIMER_END(); } } } // Batch display our hits { for ( int i = 0; i < phantoms.getSize(); i++ ) { // iterate over each individual hit for (int j = 0; j < collector[i].getHits().getSize(); j++ ) { demo->displayRootCdBody( demo->m_world, collector[i].getHits()[j].m_rootCollidableB, collector[i].getHits()[j].m_shapeKeyB ); } } } // Finally no need to update the phantoms, as the graphics engine picks up phantoms automatically. }
static void SetTransformPositionRange( hkArray<hkQsTransform>& transforms, int numTracks, int boneIdx , float ¤tTime, float lastTime, int &frame , Vector3Key &first, Vector3Key &last) { int n = transforms.getSize()/numTracks; hkVector4 p = TOVECTOR4(first.data); for ( ; COMPARE(currentTime, lastTime) <= 0 && frame < n; currentTime += FramesIncrement, ++frame) { hkQsTransform& transform = transforms[frame*numTracks + boneIdx]; SetTransformPosition(transform, p); } }
static void SetTransformRotationRange( hkArray<hkQsTransform>& transforms, int numTracks, int boneIdx , float ¤tTime, float lastTime, int &frame , QuatKey &first, QuatKey &last) { int n = transforms.getSize()/numTracks; hkQuaternion q = TOQUAT(first.data); for ( ; COMPARE(currentTime, lastTime) <= 0&& frame < n; currentTime += FramesIncrement, ++frame) { hkQsTransform& transform = transforms[frame*numTracks + boneIdx]; SetTransformRotation(transform, q); } }
void hkvStaticMeshAsset::setSpecificProperty(const hkvProperty& prop, const hkArray<hkStringPtr>& path, unsigned int stackIndex, hkvProperty::Purpose purpose) { int stackSize = (path.getSize() - stackIndex); if ((stackSize == 1) && (hkvStringHelper::safeCompare(path.back(), "Model") == 0)) { if (hkvStringHelper::safeCompare(prop.getName(), "LODSwitchDistances") == 0) { m_lodDistances = prop.getArray(); } } }
static void _mergeCompoundNodes(hkgDisplayObject* dispObj, hkxNode* node, hkgArray<hkgAssetConverter::Mapping>& meshes, const hkArray<hkpRigidBody*>& rbs ) { // See if it is in itself an rb or not. If it is then return. int gi; for (gi=0; gi < node->m_numAttributeGroups; ++gi) { hkxAttributeGroup* group = &node->m_attributeGroups[gi]; if ( (group->m_numAttributes > 0) && (hkString::strCmp( group->m_name, "hkpRigidBody") == 0) ) return; // it is an rb, not a shape or ramdom mesh } // could be an old style export scene, so will not have attributes // check for rbs of the same name.. if (node->m_name) { for (int rbl = 0; rbl < rbs.getSize(); ++rbl) { if (rbs[rbl]->getName() && (hkString::strCmp( rbs[rbl]->getName(), node->m_name) == 0) ) return; // rb by the same name as this node so can assume it is this one } } // merge the mesh (if it is a mesh) into the rb, transforming it as required. if ( hkString::strCmp( node->m_object.m_class->getName(), hkxMeshClass.getName()) == 0 ) { hkxMesh* theMesh = (hkxMesh*)node->m_object.m_object; hkgDisplayObject* toBeMerged = _findDisplayObject( theMesh, meshes ); const float* tA = toBeMerged->getTransform(); const float* tB = dispObj->getTransform(); float bInv[16]; float geomT[16]; hkgMat4Invert(bInv, tB); hkgMat4Mult(geomT, bInv, tA); int numGeom = toBeMerged->getNumGeometry(); for (gi=numGeom-1; gi >= 0; --gi) { hkgGeometry* geom = toBeMerged->removeGeometry(gi); geom->transform(geomT); // bake in relative transform dispObj->addGeometry(geom); geom->removeReference(); // remove ref given back by previous remove } } // recurse for (int ci=0; ci < node->m_numChildren; ++ci) { _mergeCompoundNodes(dispObj, node->m_children[ci], meshes, rbs ); } }
HavokDataHolder(hkDisplayGeometry* displayGeometry, const hkArray<hkGeometry::Triangle>& triangles) { m_pDisplayGeometry = displayGeometry; displayGeometry->addReference(); m_indices.reserve(triangles.getSize() * 3); for(auto& triangle : triangles) { m_indices.append(triangle.m_a); m_indices.append(triangle.m_b); m_indices.append(triangle.m_c); } }
static void phantomGetClosestPoints( ShapeQueryDemo* demo, hkArray<T*>& phantoms, hkReal offset ) { hkpAllCdPointCollector collector[10]; // Perform all queries in one go (do not interleave with examining the results, // as this is bad for code and data cache. { for ( int i = 0; i < phantoms.getSize(); i++ ) { // create a new position: all objects move in a circle hkReal t = demo->m_time + HK_REAL_PI * 2 * i / phantoms.getSize() + offset; hkVector4 pos( hkMath::sin( t ) * 10.0f, 0.0f, hkMath::cos( t ) * 10.0f ); phantoms[i]->setPosition(pos); // Query for intersecting objects for (int j = 0; j < NUM_ITER; j++ ) { MY_TIMER_BEGIN(i); collector[i].reset(); phantoms[i]->getClosestPoints( collector[i] ); MY_TIMER_END(); } } } // Batch update our display { for ( int i = 0; i < phantoms.getSize(); i++ ) { // iterate over each individual hit for (int j = 0; j < collector[i].getHits().getSize(); j++ ) { demo->displayRootCdPoint( demo->m_world, collector[i].getHits()[j] ); } } } }
void hkDefaultDemo::getVDBViewersByName( const char* name, hkArray<hkProcess*>& processes ) { if (m_vdb) { int tag = hkProcessFactory::getInstance().getProcessId( name ); m_vdb->getCurrentProcesses( processes ); int np = processes.getSize(); for (int pi = np -1; pi >= 0; --pi) { if (processes[pi]->getProcessTag() != tag) processes.removeAt(pi); } } }
void ShapeQueryDemo::buildCachingPhantoms( hkpWorld* world, hkArray<hkpShape*>& shapes, hkArray<hkpCachingShapePhantom*>& phantoms, hkPseudoRandomGenerator& generator ) { for (int i = 0; i < shapes.getSize(); i++) { // create a random position. This is important, otherwise all the phantoms will start in the // center of the level and will overlap, causing an N squared worst case problem hkTransform t; t.getRotation().setIdentity(); t.getTranslation().set( i * 10.f, 10.f, generator.getRandRange( -20.f, 20.f )); hkpCachingShapePhantom* phantom = new hkpCachingShapePhantom( shapes[i], t ); phantoms.pushBack( phantom ); world->addPhantom( phantom ); // Set red color HK_SET_OBJECT_COLOR((hkUlong)phantom->getCollidable( ), hkColor::rgbFromChars(255,0,0,120)); } }
void SlidingWorldDemo::removeBodiesLeavingBroadphaseFromSimulation(const hkArray<hkpBroadPhaseHandle*>& objectsEnteringBroadphaseBorder) { for (int i = 0; i < objectsEnteringBroadphaseBorder.getSize(); i++) { hkpBroadPhaseHandle* handle = objectsEnteringBroadphaseBorder[i]; hkpCollidable* collidable = static_cast<hkpCollidable*>(static_cast<hkpTypedBroadPhaseHandle*>(handle)->getOwner()); // It might be a rigid body, or a phantom, so check both possibilities hkpRigidBody* rigidBody = hkGetRigidBody(collidable); if(rigidBody) { m_world->removeEntity( rigidBody ); } hkpPhantom* phantom = hkGetPhantom(collidable); if(phantom) { m_world->removePhantom( phantom ); } } }
void loadEntireFileIntoBuffer(const char* filepath, hkArray<char>& outBuf) { // Load the entire file // Open a stream to read the file hkIstream infile( filepath ); HK_ASSERT( 0x215d080c, infile.isOk() ); if( infile.getStreamReader()->seekTellSupported() ) { infile.getStreamReader()->seek(0, hkStreamReader::STREAM_END); outBuf.reserve( infile.getStreamReader()->tell() ); infile.getStreamReader()->seek(0, hkStreamReader::STREAM_SET); } // read entire file into local buffer int nread = 1; while( nread ) { const int CSIZE = 8192; char* b = outBuf.expandBy( CSIZE ); // outBuf.reserve( outBuf.getSize() + CSIZE ); b = outBuf.begin() + outBuf.getSize(); nread = infile.read( b, CSIZE ); outBuf.setSize( outBuf.getSize() + nread - CSIZE ); } }
void hkvFbxAsset::setInternalProperty(const hkvProperty& prop, const hkArray<hkStringPtr>& path, unsigned int stackIndex, hkvProperty::Purpose purpose) { int stackSize = (path.getSize() - stackIndex); if ((stackSize >= 1) && (hkvStringHelper::safeCompare(path[stackIndex + 0], "FBX") == 0)) { if (stackSize == 1) { if (purpose == hkvProperty::PURPOSE_SERIALIZATION) { if (hkvStringHelper::safeCompare(prop.getName(), "FBX Target") == 0) { if (m_fbxTarget.setByString(prop.getString()) != HK_SUCCESS) { m_fbxTarget.setByAvailableElementsId(0); } } } else { if (hkvStringHelper::safeCompare(prop.getName(), "FBX Target") == 0) { if (m_fbxTarget.getAvailableElementsId() != prop.getEnumValue()) { hkvFbxTarget oldTarget = (hkvFbxTarget)m_fbxTarget.getDefinitionId(); m_fbxTarget.setByAvailableElementsId(prop.getEnumValue()); m_tagfiles.clear(); } } } } setTagfileArrayProperty(prop, path, stackIndex + 1, purpose); } hkvFilterManagerTransformableAsset::setInternalProperty(prop, path, stackIndex, purpose); }
void DestructibleHierarchy::breakOffNode(int nodeIdx, hkArray<DestructibleHierarchyCollisionEvent>& collisionEvents) { Node* node = &m_nodes[nodeIdx]; int immediateParent = node->m_parentIdx; HK_ASSERT2(0xad78d9dd, immediateParent != INVALID_NODE_INDEX, "where's the parent?"); // detach from parent Node* immediateParentNode = &m_nodes[immediateParent]; HK_ON_DEBUG( int initChildCount = immediateParentNode->m_childrenIdx.getSize() ); for (int c = 0; c < immediateParentNode->m_childrenIdx.getSize(); c++) { if (immediateParentNode->m_childrenIdx[c] == nodeIdx) { immediateParentNode->m_childrenIdx.removeAtAndCopy(c); break; } } HK_ASSERT2(0xad78ddaa, initChildCount-1 == immediateParentNode->m_childrenIdx.getSize(), "child not detached!" ); hkTransform accumulatedTransform = immediateParentNode->m_transform; // Find parent rigid body.. int parentIdx = immediateParent; Node* parentNode = immediateParentNode; while(parentNode->m_body == HK_NULL) { parentIdx = parentNode->m_parentIdx; parentNode = &m_nodes[parentIdx]; hkTransform tmp; tmp.setMul(parentNode->m_transform, accumulatedTransform); accumulatedTransform = tmp; HK_ASSERT2(0xad678daa, parentNode, "No parent rigid body found!"); } // Create new body hkpRigidBody* newBody; { hkpShape* shape = buildShape(nodeIdx); hkpShape* flatShape = hkFlattenShapeHierarchyUtil::flattenHierarchy(shape); shape->removeReference(); newBody = DestructibleHierarchy::buildRigidBody(flatShape, this, nodeIdx); flatShape->removeReference(); const hkSmallArray< hkpCollisionListener* >& listeners = parentNode->m_body->getCollisionListeners(); for (int i = 0; i < listeners.getSize(); i++) { newBody->addCollisionListener(listeners[i]); } } // init velocites for new body { // reposition the body hkTransform parentTransform; if (parentNode->m_initialTransformOfHierarchy) { parentTransform = *parentNode->m_initialTransformOfHierarchy; } else { parentTransform = parentNode->m_body->getTransform(); } hkTransform newBodyTransform; newBodyTransform.setMul( parentTransform, accumulatedTransform ); newBody->setTransform(newBodyTransform); // compute velocities hkVector4 linVel = parentNode->m_body->getLinearVelocity(); hkVector4 angVel = parentNode->m_body->getAngularVelocity(); hkVector4 relCm; relCm.setSub4(newBody->getCenterOfMassInWorld(), parentNode->m_body->getCenterOfMassInWorld()); hkVector4 extraLin; extraLin.setCross(angVel, relCm); linVel.add4(extraLin); newBody->setLinearVelocity( linVel ); newBody->setAngularVelocity( angVel ); } // set newBody position parentNode->m_body->getWorld()->addEntity(newBody); newBody->removeReference(); newBody = HK_NULL; // Update shape of parent body if (!parentNode->m_body->isFixed()) { hkpShape* shape = buildShape(parentIdx); if (shape) { hkVector4 oldCm = parentNode->m_body->getCenterOfMassInWorld(); hkpShape* flatShape = hkFlattenShapeHierarchyUtil::flattenHierarchy(shape); updateShapeOfRigidBody(flatShape, parentNode->m_body); shape->removeReference(); flatShape->removeReference(); hkVector4 relCm; relCm.setSub4(parentNode->m_body->getCenterOfMassInWorld(), oldCm); hkVector4 extraLin; extraLin.setCross(parentNode->m_body->getAngularVelocity(), relCm); hkVector4 linVel; linVel.setAdd4(parentNode->m_body->getLinearVelocity(), extraLin); parentNode->m_body->setLinearVelocity(linVel); } else { parentNode->m_body->getWorld()->removeEntity(parentNode->m_body); parentNode->m_body->removeReference(); parentNode->m_body = HK_NULL; } } else // if (!parentNode->m_body->isFixed()) { // if we're breaking off of a fixed shape -- this must be the one fixed mopp shape const hkpShape* shape = parentNode->m_body->getCollidable()->getShape(); HK_ASSERT2(0xad1788dd, shape->getType() == HK_SHAPE_MOPP, "The fixed body must have a mopp."); const hkpMoppBvTreeShape* mopp = static_cast<const hkpMoppBvTreeShape*>(shape); // Remove shapeKeys from mopp HK_ACCESS_CHECK_OBJECT(parentNode->m_body->getWorld(), HK_ACCESS_RW ); hkArray<hkpShapeKey> brokenOffShapeKeys; collectShapeKeys(nodeIdx, brokenOffShapeKeys); for (int i = brokenOffShapeKeys.getSize()-1; i >=0; i--) { if(brokenOffShapeKeys[i] == HK_INVALID_SHAPE_KEY) { brokenOffShapeKeys.removeAt(i); } else { const hkpMoppBvTreeShape* moppShape = static_cast<const hkpMoppBvTreeShape*>( parentNode->m_body->getCollidable()->getShape() ); removeSubShapeFromDisplay(parentNode->m_body, const_cast<hkpMoppBvTreeShape*>(moppShape), brokenOffShapeKeys[i]); } } hkpRemoveTerminalsMoppModifier modifier(mopp->getMoppCode(), mopp->getShapeCollection(), brokenOffShapeKeys); modifier.applyRemoveTerminals( const_cast<hkpMoppCode*>(mopp->getMoppCode()) ); // disable contact points for the removed shapes.. hkPointerMap<hkpShapeKey, int> shapeKeyMap; shapeKeyMap.reserve(brokenOffShapeKeys.getSize()); for (int k = 0; k < brokenOffShapeKeys.getSize(); k++) { shapeKeyMap.insert(brokenOffShapeKeys[k], 0); } for (int e = 0; e < collisionEvents.getSize(); e++) { if (collisionEvents[e].m_contactMgr) { hkpShapeKey key = collisionEvents[e].m_shapeKey; hkPointerMap<hkpShapeKey, int>::Iterator it = shapeKeyMap.findKey(key); if (shapeKeyMap.isValid(it) && collisionEvents[e].m_body == parentNode->m_body) { static_cast<hkpDynamicsContactMgr*>(collisionEvents[e].m_contactMgr)->getContactPoint(collisionEvents[e].m_contactPointId)->setDistance(100000.0f); collisionEvents.removeAt(e); e--; } } else { collisionEvents.removeAt(e); e--; } } } }