예제 #1
0
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;
	}
}
예제 #2
0
//
// 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();
}
예제 #3
0
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 );
	
}
예제 #4
0
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);
		}
	}
}
예제 #5
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));
	}
}
예제 #7
0
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();
  }
}
예제 #9
0
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();
    }
  }
}
예제 #10
0
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();
        }
    }
}
예제 #11
0
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;
}
예제 #12
0
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);
		}
	}
}
예제 #13
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();
    }
  }
}
예제 #15
0
static void SetTransformScaleRange( hkArray<hkQsTransform>& transforms, int numTracks, int boneIdx
                                    , float &currentTime, 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);
    }
}
예제 #16
0
/*---------------------------------------------------------------------------*/
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);
	}
}
예제 #18
0
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.
}
예제 #19
0
static void SetTransformPositionRange( hkArray<hkQsTransform>& transforms, int numTracks, int boneIdx
                                       , float &currentTime, 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);
    }
}
예제 #20
0
static void SetTransformRotationRange( hkArray<hkQsTransform>& transforms, int numTracks, int boneIdx
                                       , float &currentTime, 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 );
	}
}
예제 #23
0
        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);
            }

        }
예제 #24
0
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] );
			}
		}
	}
}
예제 #25
0
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);
		}
	}
}
예제 #26
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));
	}
}
예제 #27
0
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 );
	}
}
예제 #29
0
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--;
			}
		}

	}



}