Example #1
0
btScalar TRACK::RayTestProcessor::addSingleResult(
	btCollisionWorld::LocalRayResult & rayResult,
	bool normalInWorldSpace)
{
	// We only support static mesh collision shapes
	if (!(rayResult.m_collisionObject->getCollisionFlags() & btCollisionObject::CF_STATIC_OBJECT) &&
		(rayResult.m_collisionObject->getCollisionShape()->getShapeType() != TRIANGLE_MESH_SHAPE_PROXYTYPE))
	{
		return 1.0;
	}
	//std::cerr << rayResult.m_hitFraction << "    ";

	// Road bezier patch ray test
	assert(m_ray);
	btVector3 rayFrom = m_ray->m_rayFrom;
	btVector3 rayTo = m_ray->m_rayTo;
	btScalar rayLen = m_ray->m_rayLen;
	btVector3 rayVec = rayTo - rayFrom;

	// patch space
	MATHVECTOR<float, 3> from(rayFrom[1], rayFrom[2], rayFrom[0]);
	MATHVECTOR<float, 3> to(rayTo[1], rayTo[2], rayTo[0]);
	MATHVECTOR<float, 3> dir(rayVec[1], rayVec[2], rayVec[0]);
	dir = dir / rayLen;

	int patchId = m_ray->m_patchid;
	const BEZIER * colBez = 0;
	MATHVECTOR<float, 3> colPoint;
	MATHVECTOR<float, 3> colNormal;
	for (std::list<ROADSTRIP>::const_iterator i = m_data.roads.begin(); i != m_data.roads.end(); ++i)
	{
		const BEZIER * bez(0);
		MATHVECTOR<float, 3> norm;
		MATHVECTOR<float, 3> point(to);
		if (i->Collide(from, dir, rayLen, patchId, point, bez, norm) &&
			((point - from).MagnitudeSquared() < (colPoint - from).MagnitudeSquared()))
		{
			colPoint = point;
			colNormal = norm;
			colBez = bez;
		}
	}

	if (colBez)
	{
		btVector3 hitPoint(colPoint[2], colPoint[0], colPoint[1]);
		btVector3 hitNormal(colNormal[2], colNormal[0], colNormal[1]);
		btScalar dist_p = hitNormal.dot(hitPoint);
		btScalar dist_a = hitNormal.dot(rayFrom);
		btScalar dist_b = hitNormal.dot(rayTo);
		btScalar fraction = (dist_a - dist_p) / (dist_a - dist_b);
		rayResult.m_hitFraction = fraction;
		rayResult.m_hitNormalLocal = hitNormal;
		m_ray->m_patch = colBez;
		m_ray->m_patchid = patchId;
	}
	//std::cerr << rayResult.m_hitFraction << "    ";

	return m_ray->addSingleResult(rayResult, true);
}
Example #2
0
void pxBroadphase_Simple::TraceBox( const TraceBoxInput& input, TraceBoxOutput &output )
{
	if( input.start == input.end )
	{
		output.hitPosition = input.start;
		output.hitNormal.SetZero();
		output.hitFraction = 0.0f;
		return;
	}

	ShapePMTraceInput		shapeTraceInput;
	{
	shapeTraceInput.start = input.start;
	shapeTraceInput.end = input.end;
	shapeTraceInput.size = input.size;

	shapeTraceInput.UpdateCachedData();
	}

	F4	minHitFraction = 1.0f;
	UINT hitObjectId = INDEX_NONE;
	Vec3D	hitNormal(0);

	for( UINT i=0; i < mHandles.Num(); i++ )
	{
		pxSimpleBroadphaseProxy& proxy = mHandles[i];

		if( !proxy.bounds.IntersectsBounds( shapeTraceInput.fullTraceBounds ) )
		{
			continue;
		}

		ShapePMTraceOutput	shapeTraceOutput;
		proxy.o->GetShape()->TraceBox( shapeTraceInput, shapeTraceOutput );

		if( shapeTraceOutput.fraction < minHitFraction )
		{
			minHitFraction = shapeTraceOutput.fraction;
			hitObjectId = i;
			hitNormal = shapeTraceOutput.normal;
		}
	}
//DBGOUT("fraction = %f\n",minHitFraction);
	output.hitPosition = input.start + (input.end - input.start) * minHitFraction;
	output.hitNormal = hitNormal;
	output.hitFraction = minHitFraction;
}
	// return true if position ok and decal should be added
	//        false, if position NOT ok and decal should NOT be added
	bool DecalPositionCalculator::calculateDecalPosition(
		game::GameScene *gameScene,
		const VC3 &origin, const VC3 &velocity, 
		DECAL_POSITIONING positioning, int positionRandom,
		VC3 *resultPosition, QUAT *resultRotation)
	{
		assert(positioning != DecalPositionCalculator::DECAL_POSITIONING_INVALID);

		game::GameMap *gameMap = gameScene->getGameMap();

		bool hitWall = false;

		*resultPosition = origin;
		*resultRotation = QUAT((-3.1415926f / 2.0f),0,0);

		// if velocity positioning...
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_VELOCITY)
		{
			VC3 velocityRandomized;
			if (positionRandom > 0)
			{
				velocityRandomized = velocity * GAME_TICKS_PER_SECOND;

	// TEMP
	//char buf[64];
	//sprintf(buf, "%f,%f,%f", velocity.x, velocity.y, velocity.z);
	//Logger::getInstance()->error(buf);

				// TODO: add positionRandom to velocity _angle_...
				// (or maybe just do a quick hack and add it to xz-coordinates?)
				velocityRandomized.x += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				velocityRandomized.z += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				
				// add to y too? maybe should add downward only? 
				// NOTE: biased downward
				velocityRandomized.y += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				velocityRandomized.y -= float(positionRandom) / 100.0f * 0.5f;

			} else {
				velocityRandomized = velocity;
			}

			velocityRandomized *= 2.0f;

			IStorm3D_Scene *scene = gameScene->getStormScene();

			VC3 dir = velocityRandomized.GetNormalized();			
			VC3 rayOrigin = origin;
			float rayLen = velocityRandomized.GetLength();

			Storm3D_CollisionInfo sceneColl;
			sceneColl.includeTerrainObjects = false;
			scene->RayTrace(rayOrigin, dir, rayLen, sceneColl, true);

			/*
			if (sceneColl.hit)
			{
				VC3 hitNormal = sceneColl.plane_normal;
				// make a "wall" hit if normal-y is not nearly 1
				//if (fabs(hitNormal.y) < 0.8f)
				{
					hitWall = true;

					VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
					x.Normalize();
					x -= hitNormal * x.GetDotWith(hitNormal);
					VC3 y = -x.GetCrossWith(hitNormal);

					assert(fabsf(x.GetDotWith(y)) < 0.0001f);
					assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

					MAT tm;
					tm.Set(0, x.x);
					tm.Set(1, x.y);
					tm.Set(2, x.z);
					tm.Set(4, y.x);
					tm.Set(5, y.y);
					tm.Set(6, y.z);
					tm.Set(8, hitNormal.x);
					tm.Set(9, hitNormal.y);
					tm.Set(10, hitNormal.z);

					*resultRotation = tm.GetRotation();
				}
				*resultPosition = sceneColl.position;
			} else {
				*resultPosition += velocityRandomized;
			}
			*/

			// New version
			{
				VC3 hitNormal(0, 1.f, 0);
				if(sceneColl.hit)
				{
					hitNormal = sceneColl.plane_normal;
					*resultPosition = sceneColl.position;
				}
				else
				{
					*resultPosition += velocityRandomized;
					VC2 p2(resultPosition->x, resultPosition->z);
					hitNormal = gameScene->getTerrain()->getFaceNormal(p2);
				}

				{
					if(sceneColl.hit)
						hitWall = true;

		/*
		VC3 y = dir;
		VC3 z = hitNormal;
		y -= hitNormal * y.GetDotWith(hitNormal);
		VC3 x = z.GetCrossWith(y);
		*/

		VC3 x = dir;
		x.y = 0.f;
		x.Normalize();
		x -= hitNormal * x.GetDotWith(hitNormal);
		VC3 y = -x.GetCrossWith(hitNormal);
		VC3 z = hitNormal;

		MAT tm;
		tm.Set(0, x.x);
		tm.Set(1, x.y);
		tm.Set(2, x.z);
		tm.Set(4, y.x);
		tm.Set(5, y.y);
		tm.Set(6, y.z);
		tm.Set(8, z.x);
		tm.Set(9, z.y);
		tm.Set(10, z.z);

		resultRotation->MakeFromAngles(0.f, 0.f, -PI*0.5f);
		*resultRotation = (*resultRotation) * tm.GetRotation();

					/*
					VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
					x.Normalize();
					x -= hitNormal * x.GetDotWith(hitNormal);
					VC3 y = -x.GetCrossWith(hitNormal);

					assert(fabsf(x.GetDotWith(y)) < 0.0001f);
					assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

					MAT tm;
					tm.Set(0, x.x);
					tm.Set(1, x.y);
					tm.Set(2, x.z);
					tm.Set(4, y.x);
					tm.Set(5, y.y);
					tm.Set(6, y.z);
					tm.Set(8, hitNormal.x);
					tm.Set(9, hitNormal.y);
					tm.Set(10, hitNormal.z);

					*resultRotation = tm.GetRotation();
					*/
				}
			}


			// TODO: some kind of terrain raytrace maybe...?
			// should collide to walls, etc.
		}

		// if downward positioning...
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_DOWNWARD)
		{
			if (positionRandom > 0)
			{
				// TODO: add a random xz-offset to result position
				//*resultPosition += randomizedOffset;
				resultPosition->x += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				resultPosition->z += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
			}			

			/*
			// psd
			{
				VC2 p2(resultPosition->x, resultPosition->z);
				VC3 hitNormal = gameScene->getTerrain()->getFaceNormal(p2);

				VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
				x.Normalize();
				x -= hitNormal * x.GetDotWith(hitNormal);
				VC3 y = -x.GetCrossWith(hitNormal);

				assert(fabsf(x.GetDotWith(y)) < 0.0001f);
				assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

				MAT tm;
				tm.Set(0, x.x);
				tm.Set(1, x.y);
				tm.Set(2, x.z);
				tm.Set(4, y.x);
				tm.Set(5, y.y);
				tm.Set(6, y.z);
				tm.Set(8, hitNormal.x);
				tm.Set(9, hitNormal.y);
				tm.Set(10, hitNormal.z);

				*resultRotation = tm.GetRotation();
			}
			*/
			VC3 fooNormal;
			calculateDecalRotation(gameScene, *resultPosition, *resultRotation, 0.f, fooNormal);
		}

		// now check that we're still inside map boundaries
		if (!gameMap->isWellInScaledBoundaries(resultPosition->x, resultPosition->z))
		{
			// out of map.
			return false;
		}

		// then fix decal height to ground height
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_DOWNWARD
			|| positioning == DecalPositionCalculator::DECAL_POSITIONING_VELOCITY)
		{
			if (!hitWall)
			{
				resultPosition->y = gameMap->getScaledHeightAt(resultPosition->x, resultPosition->z);
			}
		}

		// check that not on top of metal grid area...
		if (game::MaterialManager::isMaterialUnderPosition(gameMap, 
			*resultPosition, MATERIAL_METAL_GRATE))
		{
			// on top of grid, no decal here.
			return false;
		}

		// TODO: check that not inside a wall, terrainobject, etc.
		// if so, return false

		return true;
	}