示例#1
0
//========================================================================================
//	geCamera_ScreenPointToWorld
//========================================================================================
GENESISAPI void GENESISCC geCamera_ScreenPointToWorld (	const geCamera	*Camera,
														int32			 ScreenX,
														int32			 ScreenY,
														geVec3d			*Vector)
// Takes a screen X and Y pair, and a camera and generates a vector pointing
// in the direction from the camera position to the screen point.
{
	geVec3d In,Left,Up;
	geVec3d ScaledIn,ScaledLeft,ScaledUp ;
	geFloat	XCenter ;
	geFloat	YCenter ;
	geFloat	Scale ;
	const geXForm3d *pM;

	pM = &(Camera->TransposeXForm);
	XCenter = Camera->XCenter ;
	YCenter = Camera->YCenter ;
	Scale   = Camera->Scale ;

	geXForm3d_GetIn( pM, &In ) ;
	geXForm3d_GetLeft( pM, &Left ) ;
	geXForm3d_GetUp( pM, &Up ) ;
	
	geVec3d_Scale(&In,   Scale, &ScaledIn);
	geVec3d_Scale(&Left, XCenter - ((geFloat)ScreenX), &ScaledLeft );
	geVec3d_Scale(&Up,   YCenter - ((geFloat)ScreenY), &ScaledUp   );

	geVec3d_Copy(&ScaledIn, Vector);
	geVec3d_Add(Vector,		&ScaledLeft,	Vector );
	geVec3d_Add(Vector,		&ScaledUp,		Vector );
	geVec3d_Normalize(Vector);
}
示例#2
0
//=====================================================================================
//	FixFaceTJunctions
//=====================================================================================
geBoolean FixFaceTJunctions(GBSP_Node *Node, GBSP_Face *Face)
{
	int32	i, P1, P2;
	int32	Start[MAX_TEMP_INDEX_VERTS];
	int32	Count[MAX_TEMP_INDEX_VERTS];
	geVec3d	Edge2;
	geFloat	Len;
	int32	Base;

	NumTempIndexVerts = 0;
	
	for (i=0; i< Face->NumIndexVerts; i++)
	{
		P1 = Face->IndexVerts[i];
		P2 = Face->IndexVerts[(i+1)%Face->NumIndexVerts];

		EdgeStart = WeldedVerts[P1];
		Edge2 = WeldedVerts[P2];

		FindEdgeVerts(&EdgeStart, &Edge2);

		geVec3d_Subtract(&Edge2, &EdgeStart, &EdgeDir);
		Len = geVec3d_Normalize(&EdgeDir);

		Start[i] = NumTempIndexVerts;

		TestEdge_r(0.0f, Len, P1, P2, 0);

		Count[i] = NumTempIndexVerts - Start[i];
	}

	if (NumTempIndexVerts < 3)
	{
		Face->NumIndexVerts = 0;

		//GHook.Printf("FixFaceTJunctions:  Face collapsed.\n");
		return GE_TRUE;
	}

	for (i=0 ; i<Face->NumIndexVerts; i++)
	{
		if (Count[i] == 1 && Count[(i+Face->NumIndexVerts-1)%Face->NumIndexVerts] == 1)
			break;
	}

	if (i == Face->NumIndexVerts)
	{
		Base = 0;
	}
	else
	{	// rotate the vertex order
		Base = Start[i];
	}

	if (!FinalizeFace(Face, Base))
		return GE_FALSE;

	return GE_TRUE;
}
/* ------------------------------------------------------------------------------------ */
int CPathFollower::GetDirectionVector(const geVec3d &LookFrom, const geVec3d &LookAt,
									  geVec3d *theDirectionVector)
{
	geVec3d_Subtract(&LookAt, &LookFrom, theDirectionVector);

	geVec3d_Normalize(theDirectionVector);

	return RGF_SUCCESS;
}
示例#4
0
//================================================================================
//	Frustum_SetFromPoly
//	Create a frustum looking through a poly (from the origin)
//================================================================================
geBoolean Frustum_SetFromPoly(Frustum_Info *Info, geVec3d *Verts, int32 NumVerts, geBoolean Flip)
{
	int32		NextVert;
	geVec3d		*pVert1, *pVert2, Vect;
	GFX_Plane	*Planes;
	int32		i;

	if (NumVerts >= MAX_FCP)
		return GE_FALSE;		// Too many planes!!!
	
	Planes = Info->Planes;

	Info->NumPlanes = 0;

	for (i=0; i< NumVerts; i++)
	{
		NextVert = ((i+1) < NumVerts) ? (i+1) : 0;

		pVert1 = &Verts[i];
		pVert2 = &Verts[NextVert];

		if (geVec3d_Compare(pVert1, pVert2, 0.1f))	// Coplanar edge...
			continue;	// Coplanar edges will cause a plane to be duplicated, skip it or it will screw up 
						// the clipping stage of the frustum created from this poly...

		geVec3d_Subtract(pVert1, pVert2, &Vect);
		
		if (Flip)
			geVec3d_CrossProduct(pVert2, &Vect, &Planes->Normal);
		else
			geVec3d_CrossProduct(&Vect, pVert2, &Planes->Normal);

		geVec3d_Normalize(&Planes->Normal);

		Planes->Dist = 0.0f;
		Planes->Type = PLANE_ANY;

		Planes++;
		Info->NumPlanes++;
	}

	// Get BBox info for fast BBox rejection against frustum...
	SetUpFrustumBBox(Info);
return GE_TRUE;
}
示例#5
0
//====================================================================================
//	gePlane_SetFromVerts
//====================================================================================
void gePlane_SetFromVerts(GFX_Plane *Plane, const geVec3d *V1, const geVec3d *V2, const geVec3d *V3)
{
	geVec3d		Vect1, Vect2;
	
	// Get the 2 vectors to derive the normal
	geVec3d_Subtract(V1, V2, &Vect1);
	geVec3d_Subtract(V3, V2, &Vect2);
	
	// The normal is the cross between these 2 vectors
	geVec3d_CrossProduct(&Vect1, &Vect2, &Plane->Normal);
	geVec3d_Normalize(&Plane->Normal);

	// Get the planes distance from the origin, by projecting a vert on the plane
	// along the plane normal, to the origin...
	Plane->Dist = geVec3d_DotProduct(V1, &Plane->Normal);

	// Finally, get the plane type
	Plane->Type = PLANE_ANY;
}
示例#6
0
//================================================================================
//	Frustum_SetFromCamera
//================================================================================
void Frustum_SetFromCamera(Frustum_Info *Info, geCamera *Camera)
{
    geFloat		s, c, ZFar;
	geBoolean	ZFarEnable;
    geVec3d		Normal;
	int32		i;
// changed QD Clipping
	geFloat		ZScale; 

    geCamera_GetViewAngleXSinCos(Camera,&s,&c);

    // Left clip plane
    Normal.X = s;
    Normal.Y = 0.0f;
    Normal.Z = -c;
	geVec3d_Normalize(&Normal);
	Info->Planes[0].Normal = Normal;

    // Right clip plane
    Normal.X = -s;
	geVec3d_Normalize(&Normal);
	Info->Planes[1].Normal = Normal;

    geCamera_GetViewAngleYSinCos(Camera,&s,&c);

    // Bottom clip plane
    Normal.X = 0.0f;
    Normal.Y = s;
    Normal.Z = -c;
	geVec3d_Normalize(&Normal);
	Info->Planes[2].Normal = Normal;

    // Top clip plane
    Normal.Y = -s;
	geVec3d_Normalize(&Normal);
	Info->Planes[3].Normal = Normal;

// changed QD Clipping
	
/*	Info->NumPlanes = 4;

	// Clear all distances
	for (i=0; i<Info->NumPlanes; i++)
	{
		Info->Planes[i].Dist = 0.0f;
		Info->Planes[i].Type = PLANE_ANY;
	}

    // Check to see if we need to use a far clip plane
	geCamera_GetFarClipPlane(Camera, &ZFarEnable, &ZFar);

	if (ZFarEnable)
	{
		geFloat		ZScale;

		ZScale = geCamera_GetZScale(Camera);

		// Far clip plane
		Normal.X = 0.0f;
		Normal.Y = 0.0f;
		Normal.Z = 1.0f;
		geVec3d_Normalize(&Normal);
		Info->Planes[4].Normal = Normal;

		Info->Planes[4].Dist = -(ZFar/ZScale);
		Info->Planes[4].Type = PLANE_ANY;

		Info->NumPlanes = 5;
	}
/**/
	Normal.X = 0.0f;
	Normal.Y = 0.0f;
	Normal.Z = -1.0f;
	Info->Planes[4].Normal = Normal;

	Info->NumPlanes = 5;

	// Clear all distances
	for (i=0; i<Info->NumPlanes; i++)
	{
		Info->Planes[i].Dist = 0.0f;
		Info->Planes[i].Type = PLANE_ANY;
	}

	ZScale = geCamera_GetZScale(Camera);
	Info->Planes[4].Dist = (2.0f/ZScale);

    // Check to see if we need to use a far clip plane
	geCamera_GetFarClipPlane(Camera, &ZFarEnable, &ZFar);

	if(ZFarEnable)
	{
		// Far clip plane
		Normal.X = 0.0f;
		Normal.Y = 0.0f;
		Normal.Z = 1.0f;
		geVec3d_Normalize(&Normal);
		Info->Planes[5].Normal = Normal;

		Info->Planes[5].Dist = -(ZFar/ZScale);
		Info->Planes[5].Type = PLANE_ANY;

		Info->NumPlanes = 6;
	}

// end change

	// Get BBox info for fast BBox rejection against frustum...
	SetUpFrustumBBox(Info);
}
/* ------------------------------------------------------------------------------------ */
int CPathFollower::GetNextPosition(const char *szEntityName, geVec3d *NextPosition,
								   bool YLocked)
{
	geEntity_EntitySet *pSet;
	geEntity *pEntity;
	int nResult;
	geVec3d thePos, temp, DirectionVector;

	// Ok, check to see if there are path followers in this world
	pSet = geWorld_GetEntitySet(CCD->World(), "PathFollower");

	if(!pSet)
		return RGF_FAILURE;									// No path followers

	// Ok, dig through 'em all.
	for(pEntity=geEntity_EntitySetGetNextEntity(pSet, NULL); pEntity;
		pEntity=geEntity_EntitySetGetNextEntity(pSet, pEntity))
	{
		PathFollower *pFollower = (PathFollower*)geEntity_GetUserData(pEntity);

		if(strcmp(pFollower->EntityName, szEntityName) != 0)
			continue;										// Keep looking

		// Ok, it's this entity.  Let's set the return position to the
		// ..current position in case we aren't moving
		*NextPosition = pFollower->CurrentPosition;

		// Compute the # of milliseconds since we last moved, then use that
		// ..to compute the distance we've travelled in that period
		geFloat nMotionTime = (CCD->FreeRunningCounter_F() - pFollower->LastMotionTick);

		if(nMotionTime > 100.0f)
			nMotionTime = 100.0f;							// In case of stalls elsewhere

		geFloat fDistance = nMotionTime * (pFollower->Speed * 0.001f); // / 1000.0f);
		pFollower->TimeInMotion += nMotionTime;
		pFollower->LastMotionTick = CCD->FreeRunningCounter_F();

		if(pFollower->bMoving == GE_FALSE)
			return RGF_SUCCESS;								// Current position is good

		if(pFollower->bReady == GE_FALSE)
			return RGF_SUCCESS;								// Disabled, use current position

		switch(pFollower->CurrentNodeType)
		{
		// For both start and waypoints, we're going to compute the new
		// position the same way (since they're both target-based motion).
		case RGF_POINT_TYPE_START:
		case RGF_POINT_TYPE_WAY:
			// Ok, we're moving.  What we need to do is perform a new position
			// ..computation based on the entities speed on the path and the
			// ..vector towards the current target, if not a ranged point.  First,
			// ..compute the direction vector towards the current target
			geVec3d_Subtract(&pFollower->CurrentTarget, &pFollower->CurrentPosition, &DirectionVector);
			geVec3d_Normalize(&DirectionVector);
			geVec3d_Scale(&DirectionVector, fDistance, &DirectionVector);
			// Fine, DirectionVector now contains a displacement from the current
			// ..position of the bound entity towards the target node.
			if(YLocked)
				DirectionVector.Y = 0.0f;			// Stomp on Y vector value
			temp.X = pFollower->CurrentPosition.X + DirectionVector.X;
			temp.Y = pFollower->CurrentPosition.Y + DirectionVector.Y;
			temp.Z = pFollower->CurrentPosition.Z + DirectionVector.Z;
			break;
		case RGF_POINT_TYPE_RANGED:
			// Ranged points are somewhat different.  We're basically constraining
			// ..random motion to a sphere (if not YLocked) of space in which the
			// ..bound entity randomly moves about.  What we'll do is randomly
			// ..pick a target point in the range sphere every <n> seconds and
			// ..have the entity move towards that point.
			if(pFollower->TimeInMotion > pFollower->RandomRollTime)
			{
				// Compute a new random target in the range sphere.
				srand(CCD->FreeRunningCounter());
				geVec3d RandomPosition;
				RandomPosition.X = (geFloat)(rand() % (int)pFollower->PointRange);
				if(rand()%2 == 1)
					RandomPosition.X = -(RandomPosition.X);

				RandomPosition.Y = (geFloat)(rand() % (int)pFollower->PointRange);
				if(rand()%2 == 1)
					RandomPosition.Y = -(RandomPosition.Y);

				RandomPosition.Z = (geFloat)(rand() % (int)pFollower->PointRange);
				if(rand()%2 == 1)
					RandomPosition.Z = -(RandomPosition.Z);

				RandomPosition.X += pFollower->PathOrigin.X;
				RandomPosition.Y += pFollower->PathOrigin.Y;
				RandomPosition.Z += pFollower->PathOrigin.Z;

				pFollower->CurrentTarget = RandomPosition;
				pFollower->TimeInMotion = 0.0f;				// Clear re-seek time
			}
			// From here on in, the code is identical to the target-seeking
			// ..computations performed for way an start points.
			geVec3d_Subtract(&pFollower->CurrentTarget, &pFollower->CurrentPosition, &DirectionVector);
			geVec3d_Normalize(&DirectionVector);
			geVec3d_Scale(&DirectionVector, fDistance, &DirectionVector);
			// Fine, DirectionVector now contains a displacement from the current
			// ..position of the bound entity towards the target node.
			if(YLocked)
				DirectionVector.Y = 0.0f;			// Stomp on Y vector value
			temp.X = pFollower->CurrentPosition.X + DirectionVector.X;
			temp.Y = pFollower->CurrentPosition.Y + DirectionVector.Y;
			temp.Z = pFollower->CurrentPosition.Z + DirectionVector.Z;
			break;
		}

		// Ok, we have a new point to move to!  Let's do a basic ray
		// ..collision test so we can first-level cull any motion
		if(pFollower->CollisionTest == GE_TRUE)
		{
			nResult = CCD->Collision()->CheckForCollision(NULL, NULL,
									pFollower->CurrentPosition,	temp);

			if(nResult)
				return RGF_SUCCESS;						// Don't move, we collided.
		}

		// Fine, no collisions.  Let's check to see if (a) we're not on a
		// ..ranged point and (b) if we're within 1 world unit of the target
		// ..point.  If we pass those tests, we will reset the target to the
		// ..next target point.
		*NextPosition = temp;						// Copy out for use
		pFollower->CurrentPosition = *NextPosition;

		if(pFollower->CurrentNodeType == RGF_POINT_TYPE_RANGED)
			return RGF_SUCCESS;						// Done all we need to do, bail this.

		if(geVec3d_DistanceBetween(&pFollower->CurrentPosition, &pFollower->CurrentTarget) <= pFollower->Speed)
		{
			// Move to the NEXT path point, based on our direction
			if(pFollower->bForward == GE_TRUE)
			{
				// Get next pathpoint
				nResult = CCD->PathDatabase()->NextPoint(pFollower->PathHandle, &thePos);

				if(nResult == RGF_NO_NEXT)
				{
					// No next point is END OF PATH.  Fine, if looping motion, let's
					// ..switch directions - otherwise shut down the motion.
					if(pFollower->MotionLoops)
					{
						if(pFollower->Reverse)
							pFollower->bForward = GE_FALSE;			// Switch direction
						else
						{
							CCD->PathDatabase()->Rewind(pFollower->PathHandle, &thePos);
							pFollower->CurrentTarget = thePos;
						}
					}
					else
					{
						pFollower->bReady = GE_FALSE;				// End of motion
						pFollower->bMoving = GE_FALSE;				// Don't move any more!
					}
				}
				else
				{
					// All be cool, set our target tot he new point
					pFollower->CurrentTarget = thePos;
				}
			}
			else
			{
				// Get previous pathpoint
				nResult = CCD->PathDatabase()->PreviousPoint(pFollower->PathHandle, &thePos);

				if(nResult == RGF_NO_PREVIOUS)
				{
					// No previous point is START OF PATH.  Fine, if looping motion, let's
					// ..switch directions - otherwise shut down the motion.
					if(pFollower->MotionLoops)
						pFollower->bForward = GE_TRUE;				// Switch direction
					else
					{
						pFollower->bReady = GE_FALSE;				// End of motion
						pFollower->bMoving = GE_FALSE;				// Don't move any more!
					}
				}
				else
				{
					// All be cool, set our target tot he new point
					pFollower->CurrentTarget = thePos;
				}
			}
		}

		// All done, new point back to caller
		return RGF_SUCCESS;
	}

	// Entity not bound, return failure.
	return RGF_FAILURE;
}
/* ------------------------------------------------------------------------------------ */
Procedural* Particles_Create(char *TextureName, geWorld *World, const char *InputParams)
{
    Procedural *Proc;
    int i;
    char ParamWork[8192],*pstr;
    geBitmap	*ppBitmap;

	Proc = GE_RAM_ALLOCATE_STRUCT(Procedural);

	if(!Proc)
		return (Procedural*)NULL;

	memset(Proc, 0, sizeof(Procedural));

	ppBitmap = geWorld_GetBitmapByName(World, TextureName);

	/**** read Params *****/

// changed RF064 by QD
	if(!strcmp(InputParams, "Params_Oil"))
	{
		strcpy(ParamWork, Params_Oil);
	}
	else if(!strcmp(InputParams, "Params_Jet"))
	{
		strcpy(ParamWork,Params_Jet);
	}
	else if(!strcmp(InputParams, "Params_Steam"))
	{
		strcpy(ParamWork,Params_Steam);
	}
	else if(!strcmp(InputParams, "Params_Explosion") || strlen(InputParams) < 20 )
	{
		strcpy(ParamWork,DefaultParams);
	}
// end change RF064 by QD
	else
	{
		strcpy(ParamWork,InputParams);
	}

	pstr = strtok(ParamWork,strbreakers);

	Proc->NumParticles = getint(pstr);
	Proc->NumSources = getint(pstr);

	/**** make Bitmap *****/

	if(!Particles_InitBitmap(ppBitmap))
		goto fail;

	Proc->Bitmap = ppBitmap;

	Proc->SizeX  = geBitmap_Width(Proc->Bitmap);
	Proc->SizeY = geBitmap_Height(Proc->Bitmap);
	geBitmap_GetInfo(Proc->Bitmap, &(Proc->BmInfo), (geBitmap_Info*)NULL);
	Proc->SizeZ = min(Proc->SizeX, Proc->SizeY);

	/**** make Particles *****/

	Proc->Particles = (Particle*)geRam_AllocateClear(Proc->NumParticles * sizeof(Particle));

	if(!(Proc->Particles))
		goto fail;

	for(i=0; i<Proc->NumParticles; i++)
	{
		Proc->Particles[i].shade = -1;
	}

	Proc->NumActiveParticles = 0;

	/**** make Sources *****/

	Proc->Sources = (ParticleSource*)geRam_AllocateClear(Proc->NumSources * sizeof(ParticleSource));

	if(!(Proc->Sources))
		goto fail;

	/**** More Params *****/

	// <> for stock schemes, take a few colors as parameters

	if(matchstr(pstr, "oil"))
	{
		nextparam(pstr);
		Proc->NumColors = Proc->NumShades = 16;
		Proc->PixelRGBA = PixelRGBA_OilColor;
	}
	else if(matchstr(pstr, "fire"))
	{
		nextparam(pstr);
		Proc->NumColors = 1;
		Proc->NumShades = 256;
		Proc->PixelRGBA = PixelRGBA_FireColor;
	}
	else if(matchstr(pstr, "opaquefire"))
	{
		nextparam(pstr);
		Proc->NumColors = 1;
		Proc->NumShades = 256;
		Proc->PixelRGBA = PixelRGBA_OpaqueFireColor;
	}
	else if(matchstr(pstr, "steam"))
	{
		nextparam(pstr);
		Proc->NumColors = 1;
		Proc->NumShades = 256;
		Proc->PixelRGBA = PixelRGBA_SteamColor;
	}
	else
	{
		Proc->NumColors = getint(pstr);
		Proc->NumShades = getint(pstr);
		Proc->PixelRGBA = PixelRGBA_OilColor;
		// <>
		// way to read in general spline of colors ?
	}

	if((Proc->NumColors * Proc->NumShades) < 256)
	{
		Proc->NumColors = min(Proc->NumColors, 256);
		Proc->NumShades = 256 / Proc->NumColors;
	}

	Proc->NumSmoothes	= getint(pstr);
	Proc->SmoothRadius	= getint(pstr);

	if(matchstr(pstr, "bounce"))
	{
		Proc->Capper = Capper_Bounce;
		Proc->SmoothWrap = GE_FALSE;
	}
	else if(matchstr(pstr,"wrap"))
	{
		Proc->Capper = Capper_Wrap;
		Proc->SmoothWrap = GE_TRUE;
	}
	else if(matchstr(pstr,"hard"))
	{
		Proc->Capper = Capper_Hard;
		Proc->SmoothWrap = GE_FALSE;
	}
	else
	{
		goto fail;
	}

	nextparam(pstr);

	Proc->DoMagnetic = getbool(pstr);

	if(Proc->DoMagnetic)
	{
		getvec(pstr, &(Proc->MagneticField));
	}

	Proc->DoAttractor = getbool(pstr);

	if(Proc->DoAttractor)
	{
		Proc->AttractorStrength = getfloat(pstr); // negative for repulsive
		Proc->AttractorIsAxis = getbool(pstr);

		if(Proc->AttractorIsAxis)
		{
			getvec(pstr, &(Proc->AttractorAxis));
			geVec3d_Normalize(&(Proc->AttractorAxis));
		}

		getvec(pstr, &(Proc->AttractorPos));
		scalevec(&(Proc->AttractorPos));
	}

	/**** LUT's *****/

	if(!Particles_InitPalette(Proc))
		goto fail;

	for(i=0; i<Proc->NumSources; i++)
	{
		ParticleSource *pSource;
		Particle *pParticle;

		pSource = Proc->Sources + i;

		// base
		pParticle = &(pSource->Base);

		getvec(pstr, pParticle->p);
		getvec(pstr, pParticle->v);

		scalevec(pParticle->p);
		scalevec(pParticle->v);

		pParticle->DeathTime = getfloat(pstr);
		pParticle->color = getint(pstr);
		pParticle->shade = Proc->NumShades - 1;
		pParticle->CurDeathTime = 0.0f;

		// random
		pParticle = &(pSource->Random);

		getvec(pstr,pParticle->p);
		getvec(pstr,pParticle->v);

		scalevec(pParticle->p);
		scalevec(pParticle->v);

		absvec(pParticle->p);
		absvec(pParticle->v);

		pParticle->DeathTime = getfloat(pstr);
		pParticle->color = getint(pstr);
		pParticle->shade = getint(pstr);
		pParticle->CurDeathTime = 0.0f;

		pSource->RandomVMagnitude = geVec3d_Normalize((geVec3d*)(pParticle->v));

		pSource->Delay = getfloat(pstr); // seconds
		pSource->Base.Drag = getfloat(pstr);
		pSource->CurTime = pSource->Delay;
	}

	return Proc;

fail:

	Particles_Destroy(Proc);
	return (Procedural*)NULL;
}