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);
	}
}
Exemple #6
0
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 );
	}
}
Exemple #7
0
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
}
Exemple #10
0
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);
}
Exemple #12
0
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..)
}
Exemple #17
0
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);
		}
	}
}