Exemplo n.º 1
0
hkDemo::Result BreakOffPartsAndSpuDemo::stepDemo()
{
	hkpListShape* lists[] = {m_list0, m_list1};
	hkpRigidBody* bodies[] = {m_body0, m_body1};
	for (int i = 0; i < 2; i++)
	{
		hkpListShape* list = lists[i];
		if (list)// && list->getNumChildShapes() > 1)
		{
			hkpShapeKey key = list->getFirstKey();
			if (i)
			{
				key = list->getNextKey(key); // leave the first key in. on one shape -- for testing.
			}
			if (key < hkpListShape::MAX_DISABLED_CHILDREN)
			{
				list->disableChild(key);
				if (bodies[i]->isFixed())
				{
					
					// update aabbs this way:
					//
					   bodies[i]->markForWrite();
					   hkpBreakOffPartsUtil::removeKeysFromListShape( bodies[i], &key, 1 );
					   bodies[i]->unmarkForWrite();
					//
					// or this way:
					//
					//   m_world->markForWrite();
					//   hkpEntityAabbUtil::entityBatchRecalcAabb(m_world->getCollisionInput(), (hkpEntity**)bodies+i, 1);
					//   m_world->unmarkForWrite();
				}

				// remove child from graphics
				bodies[i]->markForWrite();
				removeSubShapeFromDisplay( bodies[i], list, key );
				bodies[i]->unmarkForWrite();
			}
		}
	}

	return hkDefaultPhysicsDemo::stepDemo();
}
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--;
			}
		}

	}



}
Exemplo n.º 3
0
hkResult DestructibleBridgeDemo::breakOffSubPart( const ContactImpulseLimitBreachedEvent& event, hkArray<hkpShapeKey>& keysBrokenOffOut, hkpPhysicsSystem& systemOut ) 
{
		// get the MOPP shape
	hkpRigidBody* body = event.m_breakingBody;
	hkpMoppBvTreeShape* moppShape;
	{
		const hkpShape* shape = body->getCollidable()->getShape();
		HK_ASSERT2(0xafef4321, shape->getType() == HK_SHAPE_MOPP, "DestructibleMoppUtility can only be attached to MOPPs.");
		moppShape = const_cast<hkpMoppBvTreeShape*>(static_cast<const hkpMoppBvTreeShape*>(shape));
	}

	//	for (int p = 0; p < event.m_points.getSize(); p++)
    for (int p = 0; p < 1; p++)     // use only one point ignore the others
	{
		const ContactImpulseLimitBreachedEvent::PointInfo& pointInfo = event.m_points[p];

			// calc impact position in mopp space
		hkVector4 impactPosMoppSpace; impactPosMoppSpace.setTransformedInversePos( body->getTransform(), pointInfo.m_contactPoint->getPosition() );
		hkReal impactRadius= 5.0f;


		hkBool keyAlreadyBrokenOff = false;
		for ( int keyIt = 0; keyIt < keysBrokenOffOut.getSize(); keyIt++ )
		{
			if ( keysBrokenOffOut[keyIt] == pointInfo.m_brokenShapeKey )
			{
				keyAlreadyBrokenOff = true;
				break;
			}
		}
		if ( keyAlreadyBrokenOff == true )
		{		
			//TODO: apply impulse from collision to the rigid body
			continue;
		}
			//
			// grep objects within a given impact sphere
			//
		hkArray<hkpShapeKey>& keys = keysBrokenOffOut;
		hkInplaceArray<DestructibleMoppUtility::ConvexShapeData,64> shapes;
		{
			DestructibleMoppUtility::collectAllConvexChildShapesWithinRadius( moppShape, impactPosMoppSpace, impactRadius, *m_world->getCollisionInput(), shapes, keys );
		}

			//
			// remove those objects from mopp and display
			//
		{
			for (int i =0; i < keys.getSize();i++){ removeSubShapeFromDisplay( body, moppShape, keys[i] ); }
			DestructibleMoppUtility::removeKeysFromMopp( moppShape, impactPosMoppSpace, impactRadius, keys );
		}


			// merge shapes which are further away to make things more interesting
		DestructibleMoppUtility::ShapeData mergedShape;
		{
			hkInplaceArray<DestructibleMoppUtility::ConvexShapeData,32> mergedShapes;
				// decide which shapes to merge
			for (int i = shapes.getSize()-1; i>=0; i-- )
			{
				DestructibleMoppUtility::ConvexShapeData& data = shapes[i];
				if ( data.m_contactDetails.getDistance() > 0.8f )
				{
					mergedShapes.pushBack( data );
					shapes.removeAt( i );
				}
			}
			DestructibleMoppUtility::mergeShapes( mergedShapes, mergedShape );
		}


			//
			// create new pieces from single and merged shape
			//
		for (int i = shapes.getSize()-1; i>=-1; i-- )
		{
			const hkpShape* shape;
			hkReal massFactor = 1.0f;
			const hkTransform* transform;
			{
				if ( i >=0 )
				{
					DestructibleMoppUtility::ConvexShapeData& data = shapes[i];
					transform = &data.m_transform;
					shape     = data.m_shape;
				}
				else
				{
					transform = &mergedShape.m_transform;
					shape     = mergedShape.m_shape;
					if (!shape)	{	continue;		}
					massFactor = 5.0f;
				}
			}

			hkTransform transformWorldSpace;	transformWorldSpace.setMul(body->getTransform(), *transform);

			hkpRigidBodyCinfo info;
			{
				info.m_shape				= shape;
				info.m_position				= transformWorldSpace.getTranslation();
				info.m_rotation				. set(transformWorldSpace.getRotation());
				info.m_motionType			= hkpMotion::MOTION_DYNAMIC;
				info.m_qualityType			= HK_COLLIDABLE_QUALITY_MOVING;
				info.m_restitution			= 0.0f;
				info.m_angularDamping		= 0.7f;
				info.m_maxAngularVelocity	= 3.0f;
				hkpInertiaTensorComputer::setShapeVolumeMassProperties(info.m_shape, massFactor * 5.0f, info);
				hkpInertiaTensorComputer::clipInertia( 20.0f, info );
			}

			hkReferencedObject::lockAll();		
			hkpRigidBody* newBody = new hkpRigidBody(info);
			hkpPropertyValue shapeKeyProperty;
			shapeKeyProperty.setInt( pointInfo.m_brokenShapeKey );
			newBody->addProperty( HK_BROKEN_OFF_SHAPEKEY_PROP, shapeKeyProperty );
			systemOut.addRigidBody(newBody);
			newBody->removeReference();
			if ( i < 0 )
			{
				// only remove reference to our newly created shape
				info.m_shape->removeReference();
			}
			hkReferencedObject::unlockAll();
		}
	}

	return HK_SUCCESS;
}
Exemplo n.º 4
0
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;
}