void DestructibleBridgeUtil::createConvexTranslateShapeAndAddToArray(hkpBoxShape* shape, hkReal posX, hkReal posY, hkReal posZ, hkReal scale, hkArray<hkpShape*>& shapes) { hkVector4 position(posX, posY, posZ); position.mul4(scale); hkpConvexTranslateShape* translatedShape = new hkpConvexTranslateShape(shape, position); shapes.pushBack(translatedShape); }
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)); } }
bool hkvTextureTransformationSettings::checkFormatCompatibility( hkArray<hkvAssetLogMessage>& out_messages) { // Check if the file and data formats are compatible if (!hkvTextureFileToDataFormatMapping::getInstance().isMapped(m_targetFileFormat, m_targetDataFormat)) { hkStringBuf msg; msg.printf("The target file format (%s) is not compatible with the target data format (%s)", hkvTextureFileFormatNames[m_targetFileFormat], hkvTextureDataFormatNames[m_targetDataFormat]); out_messages.pushBack(hkvAssetLogMessage(HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, msg)); } // Check if the platform can handle the target data format if (m_platform != HKV_TARGET_PLATFORM_ANY) { if (!hkvPlatformToTextureDataFormatMapping::getInstance().isMapped(m_platform, m_targetDataFormat)) { const char* platformName = ""; hkvGetTargetPlatformDefinition().idToString(m_platform, platformName); hkStringBuf msg; msg.printf("The target data format (%s) is not compatible with the target platform (%s)", hkvTextureDataFormatNames[m_targetDataFormat], platformName); out_messages.pushBack(hkvAssetLogMessage(HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, msg)); } } // Check if the platform can handle the target file format if (m_platform != HKV_TARGET_PLATFORM_ANY) { if (!hkvPlatformToTextureFileFormatMapping::getInstance().isMapped(m_platform, m_targetFileFormat)) { const char* platformName = ""; hkvGetTargetPlatformDefinition().idToString(m_platform, platformName); hkStringBuf msg; msg.printf("The target file format (%s) is not compatible with the target platform (%s)", hkvTextureFileFormatNames[m_targetFileFormat], platformName); out_messages.pushBack(hkvAssetLogMessage(HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, msg)); } } return true; }
void DestructibleHierarchy::collectShapeKeys(int nodeIdx, hkArray<hkpShapeKey>& shapeKeys) { Node* node = &m_nodes[nodeIdx]; if (node->m_shapeKey) { shapeKeys.pushBack(node->m_shapeKey); } for (int c = 0; c < node->m_childrenIdx.getSize(); c++) { collectShapeKeys(node->m_childrenIdx[c], shapeKeys); } }
void FbxToHkxConverter::findChildren(FbxNode* root, hkArray<FbxNode*>& children, FbxNodeAttribute::EType type) { for (int childIndex = 0; childIndex < root->GetChildCount(); childIndex++) { FbxNode *node = root->GetChild(childIndex); if (node->GetNodeAttribute() != NULL && node->GetNodeAttribute()->GetAttributeType() == type) { children.pushBack(node); } findChildren(node, children, type); } }
void ShapeQueryDemo::buildAabbPhantoms( hkpWorld* world, int numPhantoms, hkArray<hkpAabbPhantom*>& phantoms, hkPseudoRandomGenerator& generator ) { for (int i = 0; i < numPhantoms; i++) { hkAabb aabb; // 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 aabb.m_min.set( i * 10.f, 10.f, generator.getRandRange( -20.f, 20.f )); aabb.m_max = aabb.m_min; hkpAabbPhantom* phantom = new hkpAabbPhantom( aabb ); phantoms.pushBack( phantom ); world->addPhantom( phantom ); } }
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 hkDefaultPhysicsDemo::setupContexts(hkArray<hkProcessContext*>& contexts) { if ( m_world ) { m_world->markForWrite(); if ( (m_physicsViewersContext->findWorld(m_world) < 0) ) { m_physicsViewersContext->addWorld(m_world); } m_world->unmarkForWrite(); } contexts.pushBack( m_physicsViewersContext ); // Add viewers to the demo display. // Uncomment these to use them. // m_debugViewerNames.pushBack( hkpBroadphaseViewer::getName() ); //m_debugViewerNames.pushBack( hkpConstraintViewer::getName() ); // m_debugViewerNames.pushBack( hkpActiveContactPointViewer::getName() ); // m_debugViewerNames.pushBack( hkpInactiveContactPointViewer::getName() ); // m_debugViewerNames.pushBack( hkpRigidBodyCentreOfMassViewer::getName() ); // m_debugViewerNames.pushBack( hkpRigidBodyInertiaViewer::getName() ); // m_debugViewerNames.pushBack( hkpSimulationIslandViewer::getName() ); // m_debugViewerNames.pushBack( hkpVehicleViewer::getName() ); // m_debugViewerNames.pushBack( hkStatisticsProcess::getName() ); // m_debugViewerNames.pushBack( hkpSweptTransformDisplayViewer::getName() ); // m_debugViewerNames.pushBack( hkpToiContactPointViewer::getName() ); // A viewer to look at the collision radius of convex objects. // m_debugViewerNames.pushBack( hkpConvexRadiusViewer::getName() ); // These are the three "default" viewers which display shapes, // phantoms and debug lines. m_debugViewerNames.pushBack( hkpShapeDisplayViewer::getName() ); m_debugViewerNames.pushBack( hkpPhantomDisplayViewer::getName() ); m_debugViewerNames.pushBack( hkDebugDisplayProcess::getName() ); // register all our classes we know about with the vdb for tweaking if (m_vdbClassReg) { m_vdbClassReg->registerList(hkBuiltinTypeRegistry::StaticLinkedTypeInfos, hkBuiltinTypeRegistry::StaticLinkedClasses); } }
void hkDefaultDemo::getTimerStreamInfo( hkArray<hkTimerData>& threadStreams, hkArray<hkTimerData>& spuStreams, int maxThreads ) { hkTimerData info; info.m_streamBegin = hkMonitorStream::getInstance().getStart(); info.m_streamEnd = hkMonitorStream::getInstance().getEnd(); threadStreams.pushBack(info); #if defined HK_PLATFORM_PS3_PPU if ( m_jobThreadPool != HK_NULL ) { m_jobThreadPool->appendTimerData( spuStreams ); } #else if ( m_jobThreadPool != HK_NULL ) { m_jobThreadPool->appendTimerData( threadStreams ); } #endif }
void displayChunks(const hkpMoppCode* code, hkgDisplayHandler* handler, hkArray<hkReferencedObject*>& delayedCleanup ) { const int numChunks = code->getCodeSize() / HK_MOPP_CHUNK_SIZE; hkGeometry* geom = new hkGeometry(); for (int chunkId = 0; chunkId < numChunks; ++chunkId) { const unsigned char *offsetCmd = code->m_data.begin() + ( HK_MOPP_CHUNK_SIZE * chunkId ); // HK_ASSERT2( 0x43234564, *offsetCmd == HK_MOPP_DATA_OFFSET, "Can't find offset command"); int offsetIntoChunk = (offsetCmd[1] << 8) | offsetCmd[2]; int numTerminalsInChunk = (offsetCmd[3] << 8) | offsetCmd[4]; for (int terminalId=0; terminalId < numTerminalsInChunk; terminalId++) { hkpShapeCollection::ShapeBuffer buffer; // Decompress into the buffer const void* data = offsetCmd + offsetIntoChunk; hkpTriangleShape* triangleShape = new(buffer)hkpTriangleShape; hkpTriangleCompressor::getTriangleShape( *triangleShape, terminalId, data ); hkGeometry::Triangle triangle; triangle.m_a = geom->m_vertices.getSize(); triangle.m_b = geom->m_vertices.getSize() + 1; triangle.m_c = geom->m_vertices.getSize() + 2; geom->m_vertices.pushBack(triangleShape->getVertex(0)); geom->m_vertices.pushBack(triangleShape->getVertex(1)); geom->m_vertices.pushBack(triangleShape->getVertex(2)); geom->m_triangles.pushBack(triangle); } } hkDisplayGeometry* displayGeom = new hkDisplayConvex( geom ); delayedCleanup.pushBack(displayGeom); hkArray<hkDisplayGeometry*> displayGeometries( &displayGeom, 1, 1 ); handler->addGeometry( displayGeometries, hkTransform::getIdentity(), 12345, 0, 0); hkgDisplayObject* obj = handler->findDisplayObject( 12345 ); hkgVertexSet* verts = obj->getGeometry(0)->getMaterialFaceSet(0)->getFaceSet(0)->getVertexSet(); verts->lock(HKG_LOCK_READONLY); // Copy vertices hkgFaceSet* faceSet = hkgFaceSet::create( handler->getContext() ); hkgVertexSet* copyVerts = hkgVertexSet::create( handler->getContext() ); faceSet->setVertexSet(copyVerts); copyVerts->removeReference(); { copyVerts->setNumVerts( verts->getNumVerts(), verts->getVertexFormat()); copyVerts->lock(HKG_LOCK_WRITEDISCARD); for (int i=0; i < verts->getNumVerts(); i++) { copyVerts->copyExistingVertex(i,i,verts); } } verts->unlock(); verts->setNumVerts( verts->getNumVerts(), verts->getVertexFormat() | HKG_VERTEX_FORMAT_COLOR); verts->lock(HKG_LOCK_WRITEDISCARD); int vertIdx = 0; for (int chunkId = 0; chunkId < numChunks; ++chunkId) { const unsigned char *offsetCmd = code->m_data.begin() + ( HK_MOPP_CHUNK_SIZE * chunkId ); // HK_ASSERT2( 0x43234564, *offsetCmd == HK_MOPP_DATA_OFFSET, "Can't find offset command"); int numTerminalsInChunk = (offsetCmd[3] << 8) | offsetCmd[4]; int col = hkColor::getRandomColor(); for (int terminalId=0; terminalId < numTerminalsInChunk; terminalId++) { verts->copyExistingVertex( vertIdx, vertIdx, copyVerts); verts->setVertexComponentData( HKG_VERTEX_COMPONENT_COLOR, vertIdx, &col); vertIdx++; verts->copyExistingVertex( vertIdx, vertIdx, copyVerts); verts->setVertexComponentData( HKG_VERTEX_COMPONENT_COLOR, vertIdx, &col); vertIdx++; verts->copyExistingVertex( vertIdx, vertIdx, copyVerts); verts->setVertexComponentData( HKG_VERTEX_COMPONENT_COLOR, vertIdx, &col); vertIdx++; } } copyVerts->unlock(); verts->unlock(); //Destroy tmp data faceSet->removeReference(); }
void DestructibleBridgeUtil::createSingleBoardOrBeam(const hkpConvexShape* shape, const hkVector4& position, hkArray<hkpConvexShape*>& shapeArray) { hkpConvexTranslateShape* translatedShape = new hkpConvexTranslateShape(shape, position); shapeArray.pushBack(translatedShape); }
void ShapeQueryDemo::createShapes(hkArray<hkpShape*>& shapesOut) { const hkReal s = 1.25f; // Create Sphere body { hkpConvexShape* shape = new hkpSphereShape(s); shapesOut.pushBack(shape ); } // Create Capsule body { hkVector4 a(-s * .5f, 0.f, 0.f); hkVector4 b( s * .5f, 0.f, 0.f); hkpCapsuleShape* shape = new hkpCapsuleShape(a, b, s); shapesOut.pushBack(shape ); } // Create Box body { hkVector4 halfExtents; halfExtents.setAll3( s ); hkpBoxShape* shape = new hkpBoxShape(halfExtents, 0 ); shapesOut.pushBack(shape ); } // Create ConvexVertices body { int numVertices = 12; // 3 for x,y,z (size of float) int stride = 3 * sizeof(float); const hkReal t = s * 0.7f; const hkReal o = 0.0f; float vertices[] = { // 4 vertices -s, o, -s, -s, o, s, s, o, -s, s, o, s, o, s, -t, o, s, t, t, s, o, -t, s, o, o, -s, -t, o, -s, t, t, -s, o, -t, -s, o, }; hkpConvexVerticesShape* shape; { hkStridedVertices stridedVerts; { stridedVerts.m_numVertices = numVertices; stridedVerts.m_striding = stride; stridedVerts.m_vertices = vertices; } shape = new hkpConvexVerticesShape(stridedVerts); } shapesOut.pushBack( shape ); } }
void WorldLinearCastMultithreadedDemo::createShapes(hkArray<hkpShape*>& shapesOut) { const hkReal s = 1.25f; // Create Sphere body { hkpConvexShape* shape = new hkpSphereShape(s); shapesOut.pushBack(shape ); } // Create Capsule body { hkVector4 a(-s * .5f, 0.f, 0.f); hkVector4 b( s * .5f, 0.f, 0.f); hkpCapsuleShape* shape = new hkpCapsuleShape(a, b, s); shapesOut.pushBack(shape ); } // Create Box body { hkVector4 halfExtents; halfExtents.setAll3( s ); hkpBoxShape* shape = new hkpBoxShape(halfExtents, 0 ); shapesOut.pushBack(shape ); } // Create ConvexVertices body { int numVertices = 12; // 3 for x,y,z (size of float) int stride = 3 * sizeof(float); const hkReal t = s * 0.7f; const hkReal o = 0.0f; float vertices[] = { // 4 vertices -s, o, -s, -s, o, s, s, o, -s, s, o, s, o, s, -t, o, s, t, t, s, o, -t, s, o, o, -s, -t, o, -s, t, t, -s, o, -t, -s, o, }; hkpConvexVerticesShape* shape; hkArray<hkVector4> planeEquations; hkGeometry geom; { hkStridedVertices stridedVerts; { stridedVerts.m_numVertices = numVertices; stridedVerts.m_striding = stride; stridedVerts.m_vertices = vertices; } hkGeometryUtility::createConvexGeometry( stridedVerts, geom, planeEquations ); { stridedVerts.m_numVertices = geom.m_vertices.getSize(); stridedVerts.m_striding = sizeof(hkVector4); stridedVerts.m_vertices = &(geom.m_vertices[0](0)); } shape = new hkpConvexVerticesShape(stridedVerts, planeEquations); } shapesOut.pushBack( shape ); } }
bool hkvTextureTransformationSettings::ensureDimensionIntegrity(hkArray<hkvAssetLogMessage>& out_messages) { if (m_sourceWidth == 0 || m_sourceHeight == 0) { out_messages.pushBack(hkvAssetLogMessage(HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, "Size of source texture is invalid; cannot continue!")); return false; } // Perform sanity checks if (m_validationNeedsPowerOfTwo && m_validationNeedsMultipleOf > 1) { if (hkvMath::isPowerOf2(m_validationNeedsMultipleOf)) { // Both Power-of-Two and Multiple-of restrictions are given. However, multiple-of is a power of two, // so we can drop the multiple-of constraint as long as we limit the minimum size. m_validationMinSize = hkvMath::Max(m_validationMinSize, m_validationNeedsMultipleOf); } else { VASSERT_MSG(false, "Both Power-of-Two and Multiple-of restrictions are specified, but Multiple-of is not a power of two. Ignoring Multiple-of."); } m_validationNeedsMultipleOf = 1; } if (m_validationNeedsPowerOfTwo) { if (m_validationMinSize > 0 && !hkvMath::isPowerOf2(m_validationMinSize)) { VASSERT_MSG(false, "According to set restrictions, system minimum size needs to be Power-of-Two. Adjusting."); m_validationMinSize = hkvMath::powerOf2_ceil(m_validationMinSize); } if (m_userMinSize > 0) { m_userMinSize = adjustToNearestPowerOfTwo(m_userMinSize); } if (m_validationMaxSize > 0 && !hkvMath::isPowerOf2(m_validationMaxSize)) { VASSERT_MSG(false, "According to set restrictions, system maximum size needs to be Power-of-Two. Adjusting."); m_validationMaxSize = hkvMath::powerOf2_floor(m_validationMaxSize); } if (m_userMaxSize > 0) { m_userMaxSize = adjustToNearestPowerOfTwo(m_userMaxSize); } } if (m_validationNeedsMultipleOf > 1) { if ((m_validationMinSize % m_validationNeedsMultipleOf) != 0) { VASSERT_MSG(false, "According to set restrictions, system minimum size needs to be Multiple-of. Adjusting."); m_validationMinSize = ((m_validationMinSize + m_validationNeedsMultipleOf - 1) / m_validationNeedsMultipleOf) * m_validationNeedsMultipleOf; } m_userMinSize = ((m_userMinSize + m_validationNeedsMultipleOf - 1) / m_validationNeedsMultipleOf) * m_validationNeedsMultipleOf; if (m_validationMaxSize % m_validationNeedsMultipleOf != 0) { VASSERT_MSG(false, "According to set restrictions, system maximum size needs to be Multiple-of. Adjusting."); m_validationMaxSize = (m_validationMaxSize / m_validationNeedsMultipleOf) * m_validationNeedsMultipleOf; } m_userMaxSize = (m_userMaxSize / m_validationNeedsMultipleOf) * m_validationNeedsMultipleOf; } if ((m_validationMinSize > 0) && (m_validationMaxSize > 0) && (m_validationMaxSize < m_validationMinSize)) { VASSERT_MSG(false, "System maximum size less than system minimum size; adjusting."); m_validationMinSize = m_validationMaxSize; } if ((m_userMinSize > 0) && (m_userMaxSize > 0) && (m_userMaxSize < m_userMinSize)) { m_userMinSize = m_userMaxSize; } if ((m_validationMinSize > 0) && (m_userMinSize > 0) && (m_userMinSize < m_validationMinSize)) { m_userMinSize = m_validationMinSize; } if ((m_validationMaxSize > 0) && (m_userMaxSize > 0) && (m_userMaxSize > m_validationMaxSize)) { m_userMaxSize = m_validationMaxSize; } return true; }
hkResult BreakOffPartsDemo::breakOffSubPart( const ContactImpulseLimitBreachedEvent& event, hkArray<hkpShapeKey>& keysBrokenOffOut, hkpPhysicsSystem& systemOut ) { const BreakOffPartsVariant& variant = g_variants[m_variantId]; // // Remove the broken pieces from the car or landscape // hkpRigidBody* breakingBody = event.m_breakingBody; for (int p = 0; p < event.m_points.getSize(); p++) { const ContactImpulseLimitBreachedEvent::PointInfo& pointInfo = event.m_points[p]; hkpShapeKey brokenPieceKey = pointInfo.m_brokenShapeKey; const hkpShape* newShape = HK_NULL; { hkpShape* shape = const_cast<hkpShape*>(breakingBody->getCollidable()->getShape()); switch (shape->m_type ) { case HK_SHAPE_LIST: { hkpListShape* list = static_cast<hkpListShape*>(shape); newShape = list->m_childInfo[brokenPieceKey].m_shape; hkpBreakOffPartsUtil::removeKeysFromListShape( breakingBody, &brokenPieceKey, 1 ); removeSubShapeFromDisplay( event.m_breakingBody, list, brokenPieceKey ); keysBrokenOffOut.pushBack( brokenPieceKey ); break; } case HK_SHAPE_MOPP: { hkpMoppBvTreeShape* moppTree = static_cast<hkpMoppBvTreeShape*>(shape); hkpShapeCollection* collection = const_cast<hkpShapeCollection*>(moppTree->getShapeCollection()); HK_ASSERT2(0xad875a22, collection->getType() == HK_SHAPE_LIST, "The container must be a list shape.."); hkpListShape* list = static_cast<hkpListShape*>(collection); newShape = list->m_childInfo[brokenPieceKey].m_shape; hkpBreakOffPartsUtil::removeKeysFromListShape( breakingBody, &brokenPieceKey, 1 ); removeSubShapeFromDisplay( event.m_breakingBody, list, brokenPieceKey ); keysBrokenOffOut.pushBack( brokenPieceKey ); break; } default: HK_ASSERT2( 0xf03df569, 0, "This shape is not implemented yet" ); return HK_FAILURE; } } // // Create the new broken off piece // hkpRigidBodyCinfo rigidBodyCinfo; { rigidBodyCinfo.m_shape = newShape; rigidBodyCinfo.m_position = breakingBody->getPosition(); rigidBodyCinfo.m_rotation = breakingBody->getRotation(); rigidBodyCinfo.m_linearVelocity = breakingBody->getLinearVelocity(); rigidBodyCinfo.m_angularVelocity = breakingBody->getAngularVelocity(); rigidBodyCinfo.m_mass = 10.0f; rigidBodyCinfo.m_qualityType = (variant.m_type == BREAK_OFF_PARTS_DEMO_TOI) ? HK_COLLIDABLE_QUALITY_MOVING : HK_COLLIDABLE_QUALITY_DEBRIS; hkpInertiaTensorComputer::setShapeVolumeMassProperties( newShape, rigidBodyCinfo.m_mass, rigidBodyCinfo ); } hkReferencedObject::lockAll(); hkpRigidBody* newBody = new hkpRigidBody( rigidBodyCinfo ); systemOut.addRigidBody( newBody ); newBody->removeReference(); hkReferencedObject::unlockAll(); // if the original unbroken body was fixed, the colliding impulse is lost, simply apply the impulse to the new piece if ( breakingBody->isFixedOrKeyframed() ) { hkReal maxImpulse = pointInfo.m_properties->m_maxImpulse; hkVector4 impulse; impulse.setMul4( -maxImpulse, pointInfo.m_contactPoint->getNormal() ); newBody->applyPointImpulse( impulse, pointInfo.m_contactPoint->getPosition() ); } } return HK_SUCCESS; }
void BrickWallBuilder::buildBrickWall(const BrickwallBuilderDescriptor& bwDescriptor, hkArray<hkpRigidBody*>& bricksOut, hkArray<hkpConstraintInstance*>& constraintsOut ) { hkVector4 halfExtents( bwDescriptor.m_brickShape->getHalfExtents() ); // move start point depending on wall size hkVector4 posX( hkVector4::getZero() ); posX(0) = -bwDescriptor.m_width * halfExtents(0); posX(0) += halfExtents(0); posX(1) = -halfExtents(1); // reserve space for all bricks and constraints bricksOut.reserve(bwDescriptor.m_height * bwDescriptor.m_width * 2); constraintsOut.reserve( (2 * bwDescriptor.m_height - 1) * (2 * bwDescriptor.m_width - 1) + bwDescriptor.m_width - 1); hkReal thresholdDelta = (bwDescriptor.m_strength > bwDescriptor.m_lowerThreshold)? (bwDescriptor.m_strength - bwDescriptor.m_lowerThreshold) /(bwDescriptor.m_height*2-1) : 0.0f; // set brick properties, used for all the bricks hkpRigidBodyCinfo boxInfo; computeBrickInfo(bwDescriptor.m_brickShape, bwDescriptor.m_brickMass, boxInfo); // QUI int colOffset=bwDescriptor.m_height; for(int x=0;x<bwDescriptor.m_width;x++) // along the ground, left to right { hkVector4 pos(posX); // breaking threshold for this row hkReal rowThreshold = bwDescriptor.m_strength; for(int y=0; y<bwDescriptor.m_height; y++) // bottom to top { pos(1) += (halfExtents(1) + bwDescriptor.m_brickShape->getRadius()) * 2.0f; // build rigid body for brick int brickIndOne; { brickIndOne=bricksOut.getSize(); boxInfo.m_position.setRotatedDir( bwDescriptor.m_transform.getRotation() /*bwDescriptor.m_orientation*/,pos); boxInfo.m_position.add4( bwDescriptor.m_transform.getTranslation() /*bwDescriptor.m_position*/); boxInfo.m_rotation.set( bwDescriptor.m_transform.getRotation() ); //bwDescriptor.m_orientation; bricksOut.pushBack(new hkpRigidBody(boxInfo)); } // At each step 2 constraints are built: hkBool constraintsAdded[] = {false, false}; // 1 - A constraint to the ground OR a constraint to the brick below the one just built if( y == 0 ) { // attach the first row to the ground (if requested) if(bwDescriptor.m_attachToGround) constraintsOut.pushBack(buildBreakableConstraintInstance(bricksOut[brickIndOne], bwDescriptor.m_theGround, rowThreshold*1000)); } else { // create a breakable constraint from the brick and the one below constraintsOut.pushBack(buildBreakableConstraintInstance(bricksOut[brickIndOne], bricksOut[brickIndOne - 1], rowThreshold)); constraintsAdded[0]=true; } // 2 - a constraint to the brick to the left if( x > 0 ) // check if there is a previous column { // create a constraint from the new brick and the corresponding brick from the previous column // the first row is made of unbreakable constraints if(y==0 && bwDescriptor.m_attachToGround) constraintsOut.pushBack(buildConstraintInstance(bricksOut[brickIndOne], bricksOut[brickIndOne - colOffset])); else constraintsOut.pushBack(buildBreakableConstraintInstance(bricksOut[brickIndOne], bricksOut[brickIndOne - colOffset], rowThreshold)); constraintsAdded[1]=true; } if(bwDescriptor.m_setCollisionFilter) { // Set filter info bool b = constraintsAdded[0]; bool l = constraintsAdded[1]; hkUint32 filterInfo = BrickFilter::calcFilterInfo(y, x, bwDescriptor.m_wallID, l, b); bricksOut[brickIndOne]->setCollisionFilterInfo(filterInfo); } rowThreshold -= thresholdDelta; } // end of for(..y..) // advance to next col posX(0) += bwDescriptor.m_gapWidth + halfExtents(0)*2.0f; } // end of for(..x..) }
void hkFlattenShapeHierarchyUtil::getLeafShapesFromShape(const hkpShape* shape, const hkTransform& transform, const hkBool isFixedBody, hkArray<hkpExtendedMeshShape::TrianglesSubpart>& trianglePartsOut, hkArray<hkpConvexShape*>& convexShapesOut, hkArray<hkpShape*>& otherShapesOut) { const hkpShapeType type = shape->getType(); hkTransform newTransform; const hkpShape* childShape = HK_NULL; hkUlong userData = HK_NULL; switch(type) { case HK_SHAPE_LIST: case HK_SHAPE_CONVEX_LIST: { const hkpShapeContainer* container = shape->getContainer(); hkpShapeContainer::ShapeBuffer buffer; HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(shape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); hkUint16 materialId = hkUint16(0xffff & hkUlong(shape->getUserData())); for (hkpShapeKey key = container->getFirstKey(); key != HK_INVALID_SHAPE_KEY; key = container->getNextKey(key)) { const hkpShape* child = container->getChildShape(key, buffer); if (materialId && 0 == (0xffff & hkUlong(child->getUserData())) ) { // no material id for the child -- copy it hkUlong childData = hkUlong(child->getUserData()) | materialId; // Warning: modifying the const input hkpShape* const_cast<hkpShape*>(child)->setUserData(childData); } //HK_ASSERT2(0xad6777dd, isFixedBody || !isLeafShape(child), "A child of a list shape cannot be a terminal node. You must use a transform shape in between." ); getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } break; case HK_SHAPE_TRANSFORM: { const hkpTransformShape* transformShape = static_cast<const hkpTransformShape*>(shape); newTransform.setMul(transform, transformShape->getTransform()); childShape = transformShape->getChildShape(); userData = hkUlong(transformShape->getUserData()); } break; case HK_SHAPE_CONVEX_TRANSFORM: { const hkpConvexTransformShape* convexTransformShape = static_cast<const hkpConvexTransformShape*>(shape); newTransform.setMul(transform, convexTransformShape->getTransform()); childShape = convexTransformShape->getChildShape(); userData = hkUlong(convexTransformShape->getUserData()); } break; case HK_SHAPE_CONVEX_TRANSLATE: { const hkpConvexTranslateShape* convexTranslateShape = static_cast<const hkpConvexTranslateShape*>(shape); hkTransform localTransform( static_cast<const hkRotation&>(hkRotation::getIdentity()), convexTranslateShape->getTranslation() ); newTransform.setMul(transform, localTransform); childShape = convexTranslateShape->getChildShape(); userData = hkUlong(convexTranslateShape->getUserData()); } break; case HK_SHAPE_BV_TREE: { const hkpBvTreeShape* bvTreeshape = static_cast<const hkpBvTreeShape*>(shape); HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); const hkpShapeContainer* container = bvTreeshape->getContainer(); for (hkpShapeKey key = container->getFirstKey(); key!= HK_INVALID_SHAPE_KEY; key = container->getNextKey(key)) { hkpShapeContainer::ShapeBuffer buffer; const hkpShape* child = container->getChildShape(key, buffer); const hkpShapeType childType = child->getType(); if ((childType == HK_SHAPE_LIST) || (childType == HK_SHAPE_CONVEX_LIST)) { getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } break; } case HK_SHAPE_MOPP: { const hkpMoppBvTreeShape* bvTreeshape = static_cast<const hkpMoppBvTreeShape*>(shape); // HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data."); getLeafShapesFromShape(bvTreeshape->getShapeCollection(), transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); break; } default: { //HK_ASSERT2(0xad67ddaa, isFixedBody, "A child of a list was attached without an intermediate transform shape. This is not handled."); // We can get simple shapes without transforms when processing fixed bodies. We do add a hkpConvexTransformShape as usual then ... childShape = shape; newTransform = transform; userData = hkUlong(shape->getUserData()); //HK_ASSERT2(0XAD678D8D, 0 == (userData & 0xffff0000), "Userdata of a fixed body (other than the one fixed uber body) has a non-zero destructible info index."); } break; } if (HK_NULL != childShape) { hkBool leafDone = false; if (hkOneFixedMoppUtil::isTerminalConvexShape(childShape)) { // Create new transform shape to wrap the child terminal shape hkpConvexTransformShape* newConvexTransformShape = new hkpConvexTransformShape(static_cast<const hkpConvexShape*>(childShape), newTransform); newConvexTransformShape->setUserData( userData ); HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); // put this transform on the shapesOut list convexShapesOut.pushBack(newConvexTransformShape); leafDone = true; } else if (isLeafShape(childShape)) { // It's not a terminal(leaf?) convex shape, but it might be a mesh, or indeed a simplemesh. // It's most likely to be a storagemesh, but we can't assume that, so check vtable: const hkClass* childShapeClass = hkBuiltinTypeRegistry::getInstance().getVtableClassRegistry()->getClassFromVirtualInstance(childShape); if( hkpMeshShapeClass.isSuperClass(*childShapeClass) ) { const hkpMeshShape* mesh = static_cast<const hkpMeshShape*>(childShape); // Confirm vertex data not shared, see below #if defined(HK_DEBUG) { for(int i = 0; i < mesh->getNumSubparts(); i++) { const hkpMeshShape::Subpart& meshSubPartI = mesh->getSubpartAt(i); for(int j = i+1; j < mesh->getNumSubparts(); j++) { const hkpMeshShape::Subpart& meshSubPartJ = mesh->getSubpartAt(j); HK_ASSERT2(0x0, meshSubPartI.m_vertexBase != meshSubPartJ.m_vertexBase, "This method can't (currently) collapse chared meshs data as it collpases the transform into the verts\n"); } } } #endif for(int i = 0; i < mesh->getNumSubparts(); i++) { const hkpMeshShape::Subpart& meshSubPart = mesh->getSubpartAt(i); // Now we have the subpart. We can't know if the data pointed to is 'owned' by the mesh (eg. subclass hkpStorageMeshShape) // or 'pointed to' (base class hkpMeshShape) // // We'll just assume here we can 'share' the data by grabbing the pointers... hkpExtendedMeshShape::TrianglesSubpart extendedMeshSubPart; extendedMeshSubPart.m_vertexBase = meshSubPart.m_vertexBase; extendedMeshSubPart.m_vertexStriding = meshSubPart.m_vertexStriding; extendedMeshSubPart.m_numVertices = meshSubPart.m_numVertices; extendedMeshSubPart.m_triangleOffset = meshSubPart.m_triangleOffset; // .. but we'll have to multiply in the transform! This assumes the vertex data is not shared! { for(int j = 0; j < extendedMeshSubPart.m_numVertices ; j++) { hkVector4 v; v(0) = extendedMeshSubPart.m_vertexBase[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v(1) = extendedMeshSubPart.m_vertexBase[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v(2) = extendedMeshSubPart.m_vertexBase[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j]; v.setTransformedPos(transform, v); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(0); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(1); const_cast<float*>(extendedMeshSubPart.m_vertexBase)[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(2); } } extendedMeshSubPart.m_indexBase = meshSubPart.m_indexBase; extendedMeshSubPart.m_indexStriding = meshSubPart.m_indexStriding; extendedMeshSubPart.m_numTriangleShapes = meshSubPart.m_numTriangles; extendedMeshSubPart.m_stridingType = (meshSubPart.m_stridingType == hkpMeshShape::INDICES_INT16) ? hkpExtendedMeshShape::INDICES_INT16 : hkpExtendedMeshShape::INDICES_INT32; trianglePartsOut.pushBack(extendedMeshSubPart); leafDone = true; } } } if(!leafDone) { HK_WARN(0xad678dda, "An extra hkTransform shape has been inserted into the hierarchy. This might be suboptimal."); // Create new transform shape to wrap the child terminal shape hkpTransformShape* newTransformShape = new hkpTransformShape(childShape, newTransform); newTransformShape->setUserData( userData ); HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); // put this transform on the shapesOut list otherShapesOut.pushBack(newTransformShape); leafDone = true; } if(!leafDone) { //HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & shape->getUserData()), "We're dropping a non-zero user data."); if ( 0xffff0000 & hkUlong(shape->getUserData()) ) { // copy the destruction info index downwards.. HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data."); HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & hkUlong(shape->getUserData())) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape."); //HK_WORLD_ACCESS_CHECK(parentBody->getWorld(), HK_ACCESS_RW ); // Warning: we're actually modifying the const hkpShape* passed as an input parameter const_cast<hkpShape*>(childShape)->setUserData( shape->getUserData() ); } getLeafShapesFromShape(childShape, newTransform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut); } } }