コード例 #1
0
ファイル: KX_RayCast.cpp プロジェクト: OldBrunet/BGERTPS
bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback)
{
	if(physics_environment==NULL) return false; /* prevents crashing in some cases */
	
	// Loops over all physics objects between frompoint and topoint,
	// calling callback.RayHit for each one.
	//
	// callback.RayHit should return true to stop looking, or false to continue.
	//
	// returns true if an object was found, false if not.
	
	MT_Point3 frompoint(_frompoint);
	const MT_Vector3 todir( (topoint - frompoint).safe_normalized() );
	MT_Point3 prevpoint(_frompoint+todir*(-1.f));
	
	PHY_IPhysicsController* hit_controller;

	while((hit_controller = physics_environment->rayTest(callback,
			frompoint.x(),frompoint.y(),frompoint.z(),
			topoint.x(),topoint.y(),topoint.z())) != NULL) 
	{
		KX_ClientObjectInfo* info = static_cast<KX_ClientObjectInfo*>(hit_controller->getNewClientInfo());
		
		if (!info)
		{
			printf("no info!\n");
			MT_assert(info && "Physics controller with no client object info");
			break;
		}
		
		// The biggest danger to endless loop, prevent this by checking that the
		// hit point always progresses along the ray direction..
		prevpoint -= callback.m_hitPoint;
		if (prevpoint.length2() < MT_EPSILON)
			break;

		if (callback.RayHit(info))
			// caller may decide to stop the loop and still cancel the hit
			return callback.m_hitFound;

		// Skip past the object and keep tracing.
		// Note that retrieving in a single shot multiple hit points would be possible 
		// but it would require some change in Bullet.
		prevpoint = callback.m_hitPoint;
		/* We add 0.001 of fudge, so that if the margin && radius == 0., we don't endless loop. */
		MT_Scalar marg = 0.001 + hit_controller->GetMargin();
		marg *= 2.f;
		/* Calculate the other side of this object */
		MT_Scalar h = MT_abs(todir.dot(callback.m_hitNormal));
		if (h <= 0.01)
			// the normal is almost orthogonal to the ray direction, cannot compute the other side
			break;
		marg /= h; 
		frompoint = callback.m_hitPoint + marg * todir;
		// verify that we are not passed the to point
		if ((topoint - frompoint).dot(todir) < 0.f)
			break;
	}
	return false;
}
コード例 #2
0
void RAS_OpenGLRasterizer::applyTransform(double* oglmatrix,int objectdrawmode )
{
	/* FIXME:
	blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const
	MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed.

	Program received signal SIGABRT, Aborted.
	[Switching to Thread 16384 (LWP 1519)]
	0x40477571 in kill () from /lib/libc.so.6
	(gdb) bt
	#7  0x08334368 in MT_Vector3::normalized() const ()
	#8  0x0833e6ec in RAS_OpenGLRasterizer::applyTransform(RAS_IRasterizer*, double*, int) ()
	*/

	if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED ||
		objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED)
	{
		// rotate the billboard/halo
		//page 360/361 3D Game Engine Design, David Eberly for a discussion
		// on screen aligned and axis aligned billboards
		// assumed is that the preprocessor transformed all billboard polygons
		// so that their normal points into the positive x direction (1.0, 0.0, 0.0)
		// when new parenting for objects is done, this rotation
		// will be moved into the object

		MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]);
		MT_Point3 campos = GetCameraPosition();
		MT_Vector3 dir = (campos - objpos).safe_normalized();
		MT_Vector3 up(0,0,1.0);

		KX_GameObject* gameobj = (KX_GameObject*)m_clientobject;
		// get scaling of halo object
		MT_Vector3  size = gameobj->GetSGNode()->GetWorldScaling();

		bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned
		if (screenaligned)
		{
			up = (up - up.dot(dir) * dir).safe_normalized();
		} else
		{
			dir = (dir - up.dot(dir)*up).safe_normalized();
		}

		MT_Vector3 left = dir.normalized();
		dir = (up.cross(left)).normalized();

		// we have calculated the row vectors, now we keep
		// local scaling into account:

		left *= size[0];
		dir  *= size[1];
		up   *= size[2];

		double maat[16] = {left[0], left[1], left[2], 0,
		                   dir[0],  dir[1],  dir[2],  0,
		                   up[0],   up[1],   up[2],   0,
		                   0,       0,       0,       1};

		glTranslated(objpos[0],objpos[1],objpos[2]);
		glMultMatrixd(maat);

	}
	else {
		if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
		{
			// shadow must be cast to the ground, physics system needed here!
			MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
			KX_GameObject *gameobj = (KX_GameObject*)m_clientobject;
			MT_Vector3 direction = MT_Vector3(0,0,-1);

			direction.normalize();
			direction *= 100000;

			MT_Point3 topoint = frompoint + direction;

			KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo;
			PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment();
			PHY_IPhysicsController* physics_controller = gameobj->GetPhysicsController();

			KX_GameObject *parent = gameobj->GetParent();
			if (!physics_controller && parent)
				physics_controller = parent->GetPhysicsController();
			if (parent)
				parent->Release();

			KX_RayCast::Callback<RAS_OpenGLRasterizer> callback(this, physics_controller, oglmatrix);
			if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback))
			{
				// couldn't find something to cast the shadow on...
				glMultMatrixd(oglmatrix);
			}
			else
			{ // we found the "ground", but the cast matrix doesn't take
			  // scaling in consideration, so we must apply the object scale
				MT_Vector3  size = gameobj->GetSGNode()->GetLocalScale();
				glScalef(size[0], size[1], size[2]);
			}
		} else
		{

			// 'normal' object
			glMultMatrixd(oglmatrix);
		}
	}
}