geBoolean TestEdge_r(geFloat Start, geFloat End, int32 p1, int32 p2, int32 StartVert)
{
	int32	j, k;
	geFloat	Dist;
	geVec3d	Delta;
	geVec3d	Exact;
	geVec3d	Off;
	geFloat	Error;
	geVec3d	p;

	if (p1 == p2)
	{
		//GHook.Printf("TestEdge_r:  Degenerate Edge.\n");
		return GE_TRUE;		// degenerate edge
	}

	for (k=StartVert ; k<NumEdgeVerts ; k++)
	{
		j = EdgeVerts[k];

		if (j==p1 || j == p2)
			continue;

		p = WeldedVerts[j];

		geVec3d_Subtract(&p, &EdgeStart, &Delta);
		Dist = geVec3d_DotProduct(&Delta, &EdgeDir);
		
		if (Dist <= Start || Dist >= End)
			continue;	
		
		geVec3d_AddScaled(&EdgeStart, &EdgeDir, Dist, &Exact);
		geVec3d_Subtract(&p, &Exact, &Off);
		Error = geVec3d_Length(&Off);

		if (fabs(Error) > OFF_EPSILON)
			continue;		

		// break the edge
		NumTJunctions++;

		TestEdge_r (Start, Dist, p1, j, k+1);
		TestEdge_r (Dist, End, j, p2, k+1);

		return GE_TRUE;
	}

	if (NumTempIndexVerts >= MAX_TEMP_INDEX_VERTS)
	{
		GHook.Error("Max Temp Index Verts.\n");
		return GE_FALSE;
	}

	TempIndexVerts[NumTempIndexVerts] = p1;
	NumTempIndexVerts++;

	return GE_TRUE;
}
Example #2
0
//================================================================================
//	CalcPortalInfo
//================================================================================
geBoolean CalcPortalInfo(VIS_Portal *Portal)
{
	geFloat		BestDist, Dist;
	GBSP_Poly	*Poly;
	geVec3d		Vect;
	int32			i;

	Poly = Portal->Poly;

	PolyCenter(Poly, &Portal->Center);	

	BestDist = 0.0f;

	for (i=0; i< Poly->NumVerts; i++)
	{
		geVec3d_Subtract(&Poly->Verts[i], &Portal->Center, &Vect);

		Dist = geVec3d_Length(&Vect);

		if (Dist > BestDist)
			BestDist = Dist;
	}

	Portal->Radius = BestDist;

	return GE_TRUE;
}
Example #3
0
void GENESISCC geExtBox_GetScaling( const geExtBox *B, geVec3d *pScale )
{
	assert (geExtBox_IsValid (B) != GE_FALSE );
	assert (pScale != NULL);

	geVec3d_Subtract( &(B->Max), &(B->Min), pScale );
}
//=====================================================================================
//	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;
}
/* ------------------------------------------------------------------------------------ */
CDSpotLight::CDSpotLight()
{
	geEntity_EntitySet *pSet;
	geEntity *pEntity;

	pSet = geWorld_GetEntitySet(CCD->World(), "DSpotLight");

	if(!pSet)
		return;						// None there.

	// Ok, we have dynamic lights somewhere.  Dig through 'em all.
	for(pEntity=geEntity_EntitySetGetNextEntity(pSet, NULL); pEntity;
	    pEntity=geEntity_EntitySetGetNextEntity(pSet, pEntity))
	{
		DSpotLight *pLight = (DSpotLight*)geEntity_GetUserData(pEntity);
		pLight->RadiusSpeed *= 1000.0f;			// From SECONDS to MILLISECONDS

		if(EffectC_IsStringNull(pLight->szEntityName))
		{
			char szName[128];
			geEntity_GetName(pEntity, szName, 128);
			pLight->szEntityName = szName;
		}

		// Ok, put this entity into the Global Entity Registry
		CCD->EntityRegistry()->AddEntity(pLight->szEntityName, "DSpotLight");

		// "negative light" shadow
		if(pLight->Shadow)
		{
			pLight->Color.r = -pLight->Color.r;
			pLight->Color.g = -pLight->Color.g;
			pLight->Color.b = -pLight->Color.b;
		}

		pLight->OriginOffset = pLight->origin;
		geVec3d_Scale(&(pLight->angles), GE_PIOVER180, &(pLight->RealAngle));

        if(pLight->Model)
		{
            geVec3d ModelOrigin;
	    	geWorld_GetModelRotationalCenter(CCD->World(), pLight->Model, &ModelOrigin);
            geVec3d_Subtract(&(pLight->origin), &ModelOrigin, &(pLight->OriginOffset));
  		}

		pLight->active = GE_FALSE;
		pLight->NumFunctionValues = strlen(pLight->RadiusFunction);

		if(pLight->NumFunctionValues == 0)
		{
			CCD->ReportError("[WARNING] DSpotLight has no RadiusFunction string\n", false);
			continue;
		}

		pLight->IntervalWidth = pLight->RadiusSpeed / (geFloat)pLight->NumFunctionValues;
	}
}
Example #7
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;
}
/* ------------------------------------------------------------------------------------ */
void CAudioStream::Tick(geFloat dwTicks)
{
	geEntity_EntitySet *pSet;
	geEntity *pEntity;
	geVec3d PlayerPos;

	if(m_nStreamerCount == 0)
		return;										// No streamers in world, bail early

	// Now scan for StreamingAudioProxy entities
	pSet = geWorld_GetEntitySet(CCD->World(), "StreamingAudioProxy");

	if(!pSet)
		return;										// Don't waste CPU time.

	// Clean up any non-playing streams
	Sweep();

	// Ok, go through and see if we need to trigger playback.
	PlayerPos = CCD->Player()->Position();			// Get player position

	for(pEntity=geEntity_EntitySetGetNextEntity(pSet, NULL); pEntity;
	    pEntity=geEntity_EntitySetGetNextEntity(pSet, pEntity))
	{
		StreamingAudioProxy *pProxy = (StreamingAudioProxy*)geEntity_GetUserData(pEntity);

		if(pProxy->bActive == false)
			continue;								// Not active, ignore it

		// changed QD 12/15/05
		//if(geVec3d_DistanceBetween(&pProxy->origin, &PlayerPos) > pProxy->Range)
		//	continue;	// Too far away
		geVec3d temp;
		geVec3d_Subtract(&pProxy->origin, &PlayerPos, &temp);

		if(geVec3d_DotProduct(&temp, &temp) > pProxy->Range*pProxy->Range)
			continue;	// Too far away
		// end change

		// Check to see if we've waited long enough before triggering this
		// ..from the last time.
		if(CCD->FreeRunningCounter() < (DWORD)(pProxy->LastTimeTriggered + (pProxy->SleepTime*1000)))
			continue;								// No more often than every <n> seconds.

		// Ok, we're close enough and it's time.  Trigger it!
		Play(pProxy->szStreamFile, pProxy->bLoops, true);

		// If this is a one-shot, kill any hope of reactivation.
		if(pProxy->bOneShot == GE_TRUE)
			pProxy->bActive = false;				// Turn it off!
	}

	return;
}
/* ------------------------------------------------------------------------------------ */
CDynalite::CDynalite()
{
	geEntity_EntitySet *pSet;
	geEntity *pEntity;

	pSet = geWorld_GetEntitySet(CCD->World(), "DynamicLight");

	if(!pSet)
		return;						// None there.

	// Ok, we have dynamic lights somewhere.  Dig through 'em all.
	for(pEntity=geEntity_EntitySetGetNextEntity(pSet, NULL); pEntity;
	    pEntity=geEntity_EntitySetGetNextEntity(pSet, pEntity))
	{
		DynamicLight *pLight = (DynamicLight*)geEntity_GetUserData(pEntity);
		pLight->RadiusSpeed *= 1000.0f;			// From SECONDS to MILLISECONDS

		if(EffectC_IsStringNull(pLight->szEntityName))
		{
			char szName[128];
			geEntity_GetName(pEntity, szName, 128);
			pLight->szEntityName = szName;
		}

		// Ok, put this entity into the Global Entity Registry
		CCD->EntityRegistry()->AddEntity(pLight->szEntityName, "DynamicLight");
		//MOD010124 - Added next if block to calculate the Origin offset.  We pass it to
        //            SetOrigin later in the tick function so that the light will stay in
        //            the same position relative to the model.  The offset is just the
        //            difference of the Dynamic Light's origin vector and the Model's
        //            origin vector.
		pLight->OriginOffset = pLight->origin;

		if(pLight->Model)
		{
            geVec3d ModelOrigin;
	    	geWorld_GetModelRotationalCenter(CCD->World(), pLight->Model, &ModelOrigin);
            geVec3d_Subtract(&(pLight->origin), &ModelOrigin, &(pLight->OriginOffset));
  		}

		pLight->active = GE_FALSE;
		pLight->NumFunctionValues = strlen(pLight->RadiusFunction);

		if(pLight->NumFunctionValues == 0)
		{
			CCD->ReportError("[WARNING] DynamicLight has no RadiusFunction string\n", false);
			continue;
		}

		pLight->IntervalWidth = pLight->RadiusSpeed / (geFloat)pLight->NumFunctionValues;
	}

	return;
}
Example #10
0
/* ------------------------------------------------------------------------------------ */
CRain::CRain()
{
	geEntity_EntitySet *pSet;
	geEntity *pEntity;

	pSet = geWorld_GetEntitySet(CCD->World(), "Rain");

	if(!pSet)
		return;

	for(pEntity=geEntity_EntitySetGetNextEntity(pSet, NULL); pEntity;
		pEntity=geEntity_EntitySetGetNextEntity(pSet, pEntity))
	{
		Rain *R = (Rain*)geEntity_GetUserData(pEntity);

		if(EffectC_IsStringNull(R->szEntityName))
		{
			char szName[128];
			geEntity_GetName(pEntity, szName, 128);
			R->szEntityName = szName;
		}

		// Ok, put this entity into the Global Entity Registry
		CCD->EntityRegistry()->AddEntity(R->szEntityName, "Rain");
		R->OriginOffset = R->origin;

		if(R->Model)
		{
			geVec3d ModelOrigin;
			geWorld_GetModelRotationalCenter(CCD->World(), R->Model, &ModelOrigin);
			geVec3d_Subtract(&(R->origin), &ModelOrigin, &(R->OriginOffset));
  		}

		// calculate number of Sprays needed
		R->EffectCount = (int)R->Radius / RAINM_RADIUSTOEFFECTRATIO;

		// create dynamic array to hold effect indexes
		R->EffectList = (int*)malloc(sizeof(int)*R->EffectCount);

		// make sure data is valid
		if(R->Severity < 0.0f)
			R->Severity = 0.0f;
		else if(R->Severity > 1.0f)
			R->Severity = 1.0f;

		if(R->DropLife <= 0.0f)
			R->DropLife = 0.1f;

		R->active = GE_FALSE;

		TPool_Bitmap("rain.bmp", "a_rain.bmp", R->BmpName, R->AlphaName);
	}
}
Example #11
0
void GENESISCC geExtBox_SetTranslation( geExtBox *B, const geVec3d *pCenter )
{
	geVec3d Center,Translation;

	assert (geExtBox_IsValid (B) != GE_FALSE);
	assert (pCenter != NULL);
	assert( geVec3d_IsValid(pCenter) != GE_FALSE );

	geExtBox_GetTranslation( B, &Center );
	geVec3d_Subtract( pCenter, &Center, &Translation);

	geExtBox_Translate( B, Translation.X, Translation.Y, Translation.Z );
}
/* ------------------------------------------------------------------------------------ */
int CPathFollower::Tick(geFloat dwTicks)
{
	geEntity_EntitySet *pSet;
	geEntity *pEntity;
	geVec3d PlayerPos;

	// 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

	PlayerPos = CCD->Player()->Position();

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

		if(pFollower->bReady == GE_FALSE)
			continue;												// Disabled entity

		if(pFollower->bMoving == GE_TRUE)
			continue;												// Already moving, don't re-trigger

		if(pFollower->RangeTrigger == 0.0f)
			continue;												// Not range trigger, keep moving

		// changed QD 12/15/05
		//if(geVec3d_DistanceBetween(&(pFollower->origin), &PlayerPos) > pFollower->RangeTrigger)
		//	continue;	// Too far away
		geVec3d temp;
		geVec3d_Subtract(&(pFollower->origin), &PlayerPos, &temp);

		if(geVec3d_DotProduct(&temp, &temp) > pFollower->RangeTrigger*pFollower->RangeTrigger)
			continue;
		// end change

		// In range, trigger it!
		pFollower->bTriggered = GE_TRUE;							// Triggered...
		pFollower->bMoving = GE_TRUE;								// We're moving!
		pFollower->TimeInMotion = 0.0f;								// Clear time in motion
		pFollower->LastMotionTick = CCD->FreeRunningCounter_F();	// Prime the time
	}

	return RGF_SUCCESS;
}
Example #13
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;
}
/* ------------------------------------------------------------------------------------ */
int CPathFollower::GetRotationToFacePoint(const geVec3d &LookFrom, const geVec3d &LookAt,
										  geVec3d *LookRotation)
{
	geFloat x, l;

	geVec3d_Subtract(&LookAt, &LookFrom, LookRotation);

	l = geVec3d_Length(LookRotation);

	// protect from Div by Zero
	if(l > 0.0f)
	{
		x = LookRotation->X;

		// changed QD 12/15/05
		// LookRotation->X = (geFloat)(GE_PI*0.5f) - (geFloat)acos(LookRotation->Y / l);
		LookRotation->X = GE_PIOVER2 - (geFloat)acos(LookRotation->Y / l);
		LookRotation->Y = (geFloat)atan2(x, LookRotation->Z) + GE_PI;
		LookRotation->Z = 0.0f;	// roll is zero - always!!?
	}

	return RGF_SUCCESS;
}
/* ------------------------------------------------------------------------------------ */
void CCameraManager::DoThirdPersonTracking()
{
	geXForm3d theViewPoint;
	geVec3d Pos;
	GE_Collision Collision;
	geVec3d Front, Back;
	geVec3d Direction;
	geFloat CurrentDistance;
	geExtBox ActorExtBox;
	geFloat ActorScale;
	geVec3d Orient;
	geFloat x;
// changed QD 01/2004
	geFloat PlayerScale = CCD->Player()->GetScale();
// end change

	CCD->ActorManager()->GetScale(theActor, &ActorScale);		// Get actor scale
	CCD->ActorManager()->GetBoundingBox(theActor, &ActorExtBox);
	CurrentDistance = m_defaultdistance * ActorScale;

	geVec3d ActorPosition, ActorRotation;
	CCD->ActorManager()->GetPosition(theActor, &ActorPosition);
	ActorPosition.Y += CameraOffsetTranslation.Y;
	CCD->ActorManager()->GetRotation(theActor, &ActorRotation);
// Start Nov2003DCS
	geVec3d_Add(&ActorRotation, &CameraOffsetRotation, &ActorRotation);
// End Nov2003DCS
	ActorRotation.X = 0.0f;

// changed QD 12/15/05
	//geXForm3d_SetIdentity(&theViewPoint);
	//geXForm3d_RotateZ(&theViewPoint, ActorRotation.Z+CameraOffsetRotation.Z);
	geXForm3d_SetZRotation(&theViewPoint, ActorRotation.Z+CameraOffsetRotation.Z);
// end change
	geXForm3d_RotateX(&theViewPoint, ActorRotation.X+CameraOffsetRotation.X+GE_PIOVER180*(m_cameraX));
	geXForm3d_RotateY(&theViewPoint, ActorRotation.Y+CameraOffsetRotation.Y+GE_PIOVER180*(m_cameraY));
	geXForm3d_Translate(&theViewPoint, ActorPosition.X, ActorPosition.Y, ActorPosition.Z);

	Pos = theViewPoint.Translation;
	geXForm3d_GetIn(&theViewPoint, &Direction);
	geVec3d_AddScaled(&Pos, &Direction, CurrentDistance, &Back);
// changed QD 12/15/05
	// geVec3d_AddScaled(&Pos, &Direction, 0.0f, &Front);
	geVec3d_Copy(&Pos, &Front);
// end change

	if(geWorld_Collision(CCD->World(), &CameraExtBox.Min, &CameraExtBox.Max, &Front,
		&Back, /*GE_VISIBLE_CONTENTS*/GE_CONTENTS_SOLID_CLIP, GE_COLLIDE_ALL, 0, NULL, NULL, &Collision))
    {
// changed QD 01/2004
		// can't be negative (sqrt!)
		// CurrentDistance = (geFloat)fabs(geVec3d_DistanceBetween(&Collision.Impact, &Front));
		// if(CurrentDistance < 0.0f)
		//	CurrentDistance = 0.0f;
		CurrentDistance = geVec3d_DistanceBetween(&Collision.Impact, &Front);
// end change

		if(CurrentDistance > (m_defaultdistance*ActorScale))
			CurrentDistance = m_defaultdistance*ActorScale;

		geVec3d_AddScaled(&Pos, &Direction, CurrentDistance, &Back);
	}

// changed QD 01/2004
	geVec3d_AddScaled(&Pos, &Direction, playermindistance*ActorScale, &Front);

	if(CCD->Meshes()->CollisionCheck(&CameraExtBox.Min, &CameraExtBox.Max, Front, Back, &Collision))
	{
// changed QD distance can't be negative
	//	geFloat CurrentDistance2 = (geFloat)fabs(geVec3d_DistanceBetween(&Collision.Impact, &Front));//-4.0f;
		geFloat CurrentDistance2 = geVec3d_DistanceBetween(&Collision.Impact, &Front);

		CurrentDistance2 += playermindistance*ActorScale;

		if(theActor == CCD->Player()->GetActor())
		{
			if(CurrentDistance2 < (playermindistance*ActorScale))
				CurrentDistance2 = playermindistance*ActorScale;
			if(CurrentDistance2 > (playermaxdistance*ActorScale))
				CurrentDistance2 = playermaxdistance*ActorScale;
		}
		else
		{
			if(CurrentDistance2 > (m_defaultdistance*ActorScale))
				CurrentDistance2 = m_defaultdistance*ActorScale;
		}

		if(CurrentDistance2 < CurrentDistance)
		{
			CurrentDistance = CurrentDistance2;
			geVec3d_AddScaled(&Pos, &Direction, CurrentDistance2, &Back);
		}
	}
// end change

	m_currentdistance = CurrentDistance/ActorScale;

	// Ok, here's the implementation of Ralph Deane's too-cool
	// ..third-person Actor Fading code. As the camera approaches
	// ..the player avatar, the AVATAR IS FADED OUT until finally
	// ..it's rendering is shut down. This is one Way Cool Effect.
	// 03/22/2000 eaa3 Added Ralph Deane's scaling fixes.

	geFloat fAlpha = 255.0f;

	if(CurrentDistance < (40.0f*ActorScale))
	{
		fAlpha = (10.0f*((CurrentDistance-((geFloat)fabs(ActorExtBox.Min.Z)+1.0f))/ActorScale))+30.0f;

		if(fAlpha < (15.0f*ActorScale))
			fAlpha = 0.0f;

		if(fAlpha > 255.0f)
			fAlpha = 255.0f;
	}

	CCD->ActorManager()->SetAlpha(theActor, fAlpha);			// Adjust actor alpha

	geVec3d_Subtract( &Pos, &Back, &Orient );

	// protect from Div by Zero
	if(CurrentDistance > 0.0f)
	{
		x = Orient.X;
		// changed QD 12/15/05
		// Orient.X = (geFloat)( GE_PI*0.5 ) - (geFloat)acos(Orient.Y / CurrentDistance);
		Orient.X = GE_PIOVER2 - (geFloat)acos(Orient.Y / CurrentDistance);
		Orient.Y = (geFloat)atan2(x, Orient.Z) + GE_PI;
		Orient.Z = 0.0f;	// roll is zero - always!!?
	}

	Rotation = Orient;										// Set camera orientation
	Translation = Back;										// Set camera translation

	return;
}
/* ------------------------------------------------------------------------------------ */
void Particle_SystemFrame(Particle_System *ps, geFloat DeltaTime)
{
	geVec3d	AnchorDelta;

	// the quick fix to the particle no-draw problem
	ps->psQuantumSeconds = DeltaTime;

	{
		Particle *ptcl;

		ptcl = ps->psParticles;

		while(ptcl)
		{
			ptcl->ptclTime -= ps->psQuantumSeconds;

			if(ptcl->ptclTime <= 0.0f)
			{
				Particle *temp;

				temp = ptcl->ptclNext;
				UnlinkParticle(ps, ptcl);
				DestroyParticle(ps, ptcl);
				ptcl = temp;
				continue;
			}
			else
			{
				// locals
				geVec3d	DeltaPos = {0.0f, 0.0f, 0.0f};

				// apply velocity
				if(ptcl->ptclFlags & PARTICLE_HASVELOCITY)
				{
					geVec3d_Scale(&(ptcl->ptclVelocity), ps->psQuantumSeconds, &DeltaPos);
				}

				// apply gravity
				if(ptcl->ptclFlags & PARTICLE_HASGRAVITY)
				{
					// locals
					geVec3d	Gravity;

					// make gravity vector
					geVec3d_Scale(&(ptcl->Gravity), ps->psQuantumSeconds, &Gravity);

					// apply gravity to built in velocity and DeltaPos
					geVec3d_Add(&(ptcl->ptclVelocity), &Gravity, &(ptcl->ptclVelocity));
					geVec3d_Add(&DeltaPos, &Gravity, &DeltaPos);
				}

				//apply wind
				if(ptcl->ptclFlags & PARTICLE_HASWIND)
				{
					geVec3d Wind = CCD->Player()->GetWind();

					//make wind vector
					geVec3d_Scale(&Wind, ps->psQuantumSeconds, &Wind);

					//add wind to delta pos
					geVec3d_Add(&DeltaPos, &Wind, &DeltaPos);
				}

				// apply DeltaPos to particle position
				if((ptcl->ptclFlags & PARTICLE_HASVELOCITY) || (ptcl->ptclFlags & PARTICLE_HASGRAVITY) || (ptcl->ptclFlags & PARTICLE_HASWIND))
				{
					geVec3d temppos, temppos1;
					GE_Collision Collision;
					geVec3d_Copy((geVec3d*)&(ptcl->ptclVertex.X), &temppos);
					geVec3d_Add(&temppos, &DeltaPos, &temppos1);

					if(ptcl->Bounce)
					{
						float totalTravelled = 1.0f;// keeps track of fraction of path travelled (1.0=complete)
						float margin = 0.001f;		// margin to be satisfied with (1.0 - margin == 1.0)
						int loopCounter = 0;		// safety valve for endless collisions in tight corners
						const int maxLoops = 10;

						while(geWorld_Collision(CCD->World(), NULL, NULL, &temppos,
							&temppos1, GE_VISIBLE_CONTENTS, GE_COLLIDE_ALL, 0, NULL, NULL, &Collision))
						{
							float ratio ;
							float elasticity = 1.3f ;
							float friction = 0.9f ; // loses (1 minus friction) of speed

							CollisionCalcRatio(Collision, temppos, temppos1, &ratio);
							CollisionCalcImpactPoint(Collision, temppos, temppos1, 1.0f, ratio, &temppos1);
							CollisionCalcVelocityImpact(Collision, ptcl->ptclVelocity, elasticity,
														friction, &(ptcl->ptclVelocity));

							if(ratio >= 0)
								totalTravelled += (1.0f - totalTravelled) * ratio ;

							if(totalTravelled >= 1.0f - margin)
								break ;

							if(++loopCounter >= maxLoops) // safety check
								break ;
						}
					}
					else
					{
						if(geWorld_Collision(CCD->World(), NULL, NULL, &temppos,
							&temppos1, GE_VISIBLE_CONTENTS, GE_COLLIDE_ALL, 0, NULL, NULL, &Collision))
						{
							Particle *temp;
							temp = ptcl->ptclNext;
							UnlinkParticle(ps, ptcl);
							DestroyParticle(ps, ptcl);
							ptcl = temp;
							continue;
						}
					}

					geVec3d_Copy(&temppos1, (geVec3d *)&(ptcl->ptclVertex.X));
				}

				// make the particle follow its anchor point if it has one
				if(ptcl->AnchorPoint != (const geVec3d*)NULL)
				{
					geVec3d_Subtract(ptcl->AnchorPoint, &(ptcl->CurrentAnchorPoint), &AnchorDelta);
					geVec3d_Add((geVec3d*)&(ptcl->ptclVertex.X), &AnchorDelta, (geVec3d*)&(ptcl->ptclVertex.X));
					geVec3d_Copy(ptcl->AnchorPoint, &(ptcl->CurrentAnchorPoint));
				}
			}

#ifndef	POLYQ
			// set particle alpha
			ptcl->ptclVertex.a = ptcl->Alpha * (ptcl->ptclTime / ptcl->ptclTotalTime);

			geWorld_AddPolyOnce(ps->psWorld,
								&(ptcl->ptclVertex),
								1,
								ptcl->ptclTexture,
								GE_TEXTURED_POINT,
								PARTICLE_RENDERSTYLE,
								ptcl->Scale);
#else
			// set particle alpha
			ptcl->ptclVertex.a = ptcl->Alpha * (ptcl->ptclTime / ptcl->ptclTotalTime);

			if(ptcl->ptclPoly)
				gePoly_SetLVertex(ptcl->ptclPoly, 0, &(ptcl->ptclVertex));
#endif

			ptcl = ptcl->ptclNext;
		}

		DeltaTime -= QUANTUMSIZE;
	}

	ps->psLastTime += DeltaTime;
}
Example #17
0
geBoolean GENESISCC geExtBox_RayCollision( const geExtBox *B, const geVec3d *Start, const geVec3d *End, 
								geFloat *T, geVec3d *Normal )
{
	// only detects rays going 'in' to the box
	geFloat t;
	geVec3d Delta;
	geVec3d LocalNormal;
	geFloat LocalT;

	assert( B != NULL );
	assert( Start != NULL );
	assert( End != NULL );
	assert (geVec3d_IsValid( Start )!= GE_FALSE);
	assert (geVec3d_IsValid( End   )!= GE_FALSE);
	assert (geExtBox_IsValid( B )!= GE_FALSE );

	geVec3d_Subtract(End,Start,&Delta);
	
	if (Normal == NULL)
		Normal = &LocalNormal;
	if (T == NULL)
		T = &LocalT;
	
	// test x end of box, facing away from ray direction.
	if (Delta.X > 0.0f)
		{
			if ( (Start->X <= B->Min.X) && (B->Min.X <= End->X) &&
				 (geExtBox_XFaceDist(  Start ,&Delta, B, &t, B->Min.X ) != GE_FALSE) )
					{
						geVec3d_Set( Normal,  -1.0f, 0.0f, 0.0f );
						*T = t;
						return GE_TRUE;
					}
		}
	else if (Delta.X < 0.0f)
		{
			if ( (End->X <= B->Max.X) && (B->Max.X <= Start->X) &&
				 (geExtBox_XFaceDist(  Start ,&Delta, B, &t, B->Max.X ) != GE_FALSE) )
					{
						geVec3d_Set( Normal,  1.0f, 0.0f, 0.0f );
						*T = t;
						return GE_TRUE;
					}
		}
	
	// test y end of box, facing away from ray direction.
	if (Delta.Y > 0.0f)
		{	
			if ( (Start->Y <= B->Min.Y) && (B->Min.Y <= End->Y) &&
				 (geExtBox_YFaceDist(  Start ,&Delta, B, &t, B->Min.Y ) != GE_FALSE) )
				{
					geVec3d_Set( Normal,  0.0f, -1.0f, 0.0f );
					*T = t;
					return GE_TRUE;
				}
		}
	else if (Delta.Y < 0.0f)
		{
			if ( (End->Y <= B->Max.Y) && (B->Max.Y <= Start->Y) &&
				 (geExtBox_YFaceDist(  Start ,&Delta, B, &t, B->Max.Y ) != GE_FALSE) )
				{
					geVec3d_Set( Normal,  0.0f, 1.0f, 0.0f );
					*T = t;
					return GE_TRUE;
				}
		}
	
	// test z end of box, facing away from ray direction.
	if (Delta.Z > 0.0f)
		{	
			if ( (Start->Z <= B->Min.Z) && (B->Min.Z <= End->Z) &&
			     (geExtBox_ZFaceDist(  Start ,&Delta, B, &t, B->Min.Z ) != GE_FALSE) )
				{
					geVec3d_Set( Normal,  0.0f, 0.0f, -1.0f );
					*T = t;
					return GE_TRUE;
				}
		}
	else if (Delta.Z < 0.0f)
		{			
			if ( (End->Z <= B->Max.Z) && (B->Max.Z <= Start->Z) &&
				 (geExtBox_ZFaceDist(  Start ,&Delta, B, &t, B->Max.Z ) != GE_FALSE) )
				{
					geVec3d_Set( Normal,  0.0f, 0.0f, 1.0f );
					*T = t;
					return GE_TRUE;
				}
		}
	return GE_FALSE;	
}
/* ------------------------------------------------------------------------------------ */
void CCameraManager::DoIsoTracking()
{
	geXForm3d theViewPoint;
	geVec3d Pos;
	GE_Collision Collision;
	geVec3d Front, Back;
	geVec3d Direction;
	geFloat CurrentDistance;
	geExtBox ActorExtBox;
	geFloat ActorScale;
	geVec3d Orient;
	geFloat x;

	CCD->ActorManager()->GetScale(theActor, &ActorScale);		// Get actor scale
	CCD->ActorManager()->GetBoundingBox(theActor, &ActorExtBox);
	CurrentDistance = m_defaultdistance * ActorScale;

	geVec3d ActorPosition, ActorRotation;
	CCD->ActorManager()->GetPosition(theActor, &ActorPosition);
	ActorPosition.Y += CameraOffsetTranslation.Y;
	CCD->ActorManager()->GetRotation(theActor, &ActorRotation);
	ActorRotation.X = 0.0f;

// changed QD 12/15/05
	//geXForm3d_SetIdentity(&theViewPoint);
	//geXForm3d_RotateZ(&theViewPoint, CameraOffsetRotation.Z);
	geXForm3d_SetZRotation(&theViewPoint, CameraOffsetRotation.Z);
// end change
	geXForm3d_RotateX(&theViewPoint, CameraOffsetRotation.X+GE_PIOVER180*(m_cameraX));
	geXForm3d_RotateY(&theViewPoint, CameraOffsetRotation.Y+GE_PIOVER180*(m_cameraY));
	geXForm3d_Translate(&theViewPoint, ActorPosition.X, ActorPosition.Y, ActorPosition.Z);

	Pos = theViewPoint.Translation;
	geXForm3d_GetIn(&theViewPoint, &Direction);
	geVec3d_AddScaled(&Pos, &Direction, CurrentDistance, &Back);
// changed QD 12/15/05
	// geVec3d_AddScaled(&Pos, &Direction, 0.0f, &Front);
	geVec3d_Copy(&Pos, &Front);
// end change

	if(IsoCollFlag)
	{
		if(geWorld_Collision(CCD->World(), &CameraExtBox.Min, &CameraExtBox.Max, &Front,
		&Back, /*GE_VISIBLE_CONTENTS*/GE_CONTENTS_SOLID_CLIP, GE_COLLIDE_ALL, 0, NULL, NULL, &Collision))
		{
// changed QD 01/2004
			// can't be negative (sqrt)
			// CurrentDistance = (geFloat)fabs(geVec3d_DistanceBetween(&Collision.Impact, &Front));
			// if(CurrentDistance < 0.0f)
			//	CurrentDistance = 0.0f;
			CurrentDistance = geVec3d_DistanceBetween(&Collision.Impact, &Front);
// end change

			if(CurrentDistance > (m_defaultdistance*ActorScale))
				CurrentDistance = m_defaultdistance*ActorScale;

			geVec3d_AddScaled(&Pos, &Direction, CurrentDistance, &Back);
		}

// changed QD 01/2004
		if(CCD->Meshes()->CollisionCheck(&CameraExtBox.Min, &CameraExtBox.Max, Front, Back, &Collision))
		{
			geFloat CurrentDistance2 = geVec3d_DistanceBetween(&Collision.Impact, &Front);

			if(CurrentDistance2 > (m_defaultdistance*ActorScale))
				CurrentDistance2 = m_defaultdistance*ActorScale;

			if(CurrentDistance2<CurrentDistance)
			{
				CurrentDistance = CurrentDistance2;
				geVec3d_AddScaled(&Pos, &Direction, CurrentDistance2, &Back);
			}
		}
// end change
	}

	m_currentdistance = CurrentDistance/ActorScale;

	if(IsoCollFlag)
	{
		geFloat fAlpha = 255.0f;

		if(CurrentDistance < (40.0f*ActorScale))
		{
			fAlpha = (10.0f*((CurrentDistance-((geFloat)fabs(ActorExtBox.Min.Z)+1.0f))/ActorScale))+30.0f;

			if(fAlpha < (15.0f*ActorScale))
				fAlpha = 0.0f;

			if(fAlpha > 255.0f)
				fAlpha = 255.0f;
		}

		CCD->ActorManager()->SetAlpha(theActor, fAlpha);			// Adjust actor alpha
	}

	geVec3d_Subtract( &Pos, &Back, &Orient );

	// protect from Div by Zero
	if(CurrentDistance > 0.0f)
	{
		x = Orient.X;
		// changed QD 12/15/05
		// Orient.X = GE_PI*0.5f - (geFloat)acos(Orient.Y / CurrentDistance);
		Orient.X = GE_PIOVER2 - (geFloat)acos(Orient.Y / CurrentDistance);
		Orient.Y = (geFloat)atan2(x, Orient.Z) + GE_PI;
		Orient.Z = 0.0f;	// roll is zero - always!!?

	}

	Rotation = Orient;										// Set camera orientation
	Translation = Back;										// Set camera translation

	return;
}
/* ------------------------------------------------------------------------------------ */
int CCameraManager::RenderView()
{
	geXForm3d theViewPoint;

// changed QD 12/15/05
	//geXForm3d_SetIdentity(&theViewPoint); // Clear the matrix
	//geXForm3d_RotateZ(&theViewPoint, Rotation.Z); // Rotate then translate
	geXForm3d_SetZRotation(&theViewPoint, Rotation.Z);
// end change
	geXForm3d_RotateX(&theViewPoint, Rotation.X);
	geXForm3d_RotateY(&theViewPoint, Rotation.Y);

	geXForm3d_Translate(&theViewPoint, Translation.X+shakex, Translation.Y+shakey, Translation.Z);

// changed RF063
	GE_Contents ZoneContents;
	geExtBox ExtBox;
	geVec3d Direction, Pos;
	GE_LVertex	Vertex;

	ExtBox.Min.X = ExtBox.Min.Z = -1.0f;
	ExtBox.Min.Y = 0.0f;
	ExtBox.Max.Y = 1.0f;
	ExtBox.Max.X = ExtBox.Max.Z = 1.0f;

	if(CCD->Collision()->GetContentsOf(Translation, &ExtBox, &ZoneContents) == RGF_SUCCESS)
	//if(geWorld_GetContents(CCD->World(), &Translation, &ExtBox.Min,
		//&ExtBox.Max, GE_COLLIDE_MODELS, 0, NULL, NULL, &ZoneContents) == GE_TRUE)
	{
		Liquid * LQ = CCD->Liquids()->IsLiquid(ZoneContents.Model);

		if(LQ)
		{
			geXForm3d_GetIn(&theViewPoint, &Direction);
			geVec3d_AddScaled(&Translation, &Direction, OverlayDist, &Pos);

			Vertex.r = LQ->TintColor.r;
			Vertex.g = LQ->TintColor.g;
			Vertex.b = LQ->TintColor.b;
			Vertex.a = LQ->Transparency;

			Vertex.u = 0.0f;
			Vertex.v = 0.0f;

			Vertex.X = Pos.X;
			Vertex.Y = Pos.Y;
			Vertex.Z = Pos.Z;

			geWorld_AddPolyOnce(CCD->World(), &Vertex, 1,
				LQ->Texture,
				GE_TEXTURED_POINT  , GE_RENDER_DO_NOT_OCCLUDE_SELF, 2.0f );
		}
// changed RF064
		else
		{
			Overlay * OL = CCD->Overlays()->IsOverlay(ZoneContents.Model);

			if(OL)
			{
				geXForm3d_GetIn(&theViewPoint, &Direction);
				geVec3d_AddScaled(&Translation, &Direction, OverlayDist, &Pos);

				Vertex.r = OL->TintColor.r;
				Vertex.g = OL->TintColor.g;
				Vertex.b = OL->TintColor.b;
				Vertex.a = OL->Transparency;

				Vertex.u = 0.0f;
				Vertex.v = 0.0f;

				Vertex.X = Pos.X;
				Vertex.Y = Pos.Y;
				Vertex.Z = Pos.Z;

				geWorld_AddPolyOnce(CCD->World(), &Vertex, 1, OL->Texture,
					GE_TEXTURED_POINT  , GE_RENDER_DO_NOT_OCCLUDE_SELF, 2.0f);
			}
		}
// end change RF064
	}

	if(jerk)
	{
		geVec3d Direction;
		geXForm3d_GetIn(&theViewPoint, &Direction);
		geVec3d_AddScaled(&theViewPoint.Translation, &Direction, -jerkamt, &theViewPoint.Translation);
	}

// end change RF063
	//	Set up camera attributes just prior to rendering the world.

	geRect Rect;
	geCamera_SetWorldSpaceXForm(EngineCamera, &theViewPoint);
	geCamera_GetClippingRect(EngineCamera, &Rect);
	geCamera_SetAttributes(EngineCamera, FOV, &Rect);
// changed RF064
	geVec3d_Subtract(&m_OldXForm.Translation, &theViewPoint.Translation, &m_vMoveDif );
	m_bPositionMoved = !geVec3d_IsZero(&m_vMoveDif);

	if( m_bPositionMoved  ||
		m_OldXForm.AX != theViewPoint.AX || m_OldXForm.AY != theViewPoint.AY || m_OldXForm.AZ != theViewPoint.AZ ||
		m_OldXForm.BX != theViewPoint.BX || m_OldXForm.BY != theViewPoint.BY || m_OldXForm.BZ != theViewPoint.BZ ||
		m_OldXForm.CX != theViewPoint.CX || m_OldXForm.CY != theViewPoint.CY || m_OldXForm.CZ != theViewPoint.CZ)
	{
		m_bViewChanged = true;
		m_OldXForm = theViewPoint;
	}
// end change RF064

	return RGF_SUCCESS;
}
/* ------------------------------------------------------------------------------------ */
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;
}
Example #21
0
GENESISAPI gePhysicsJoint * GENESISCC gePhysicsJoint_Create(gePhysicsJoint_Kind Kind, const geVec3d *Location, 
	geFloat assemblyRate, gePhysicsObject *PS1, gePhysicsObject *PS2, geFloat physicsScale)
{
	gePhysicsJoint*	pPhysjnt;
	geVec3d		POLocation;
	geVec3d		physicsSpaceLocation;

	pPhysjnt = NULL;
	pPhysjnt = GE_RAM_ALLOCATE_STRUCT(gePhysicsJoint);
	if (pPhysjnt == NULL)
	{
		return NULL;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// make sure the joint makes sense

	pPhysjnt->Type = Kind;
	pPhysjnt->assemblyRate = assemblyRate * JOINT_ASSEMBLY_RATE_MULTIPLIER;
	pPhysjnt->Object1 = PS1;
	pPhysjnt->Object2 = PS2;

	geVec3d_Scale(Location, physicsScale, &physicsSpaceLocation);

	switch (Kind)
	{
		case JT_WORLD:
			if (PS1 == NULL)
			{
				/*
				GenVSI_Error(VSI, 
					GE_FALSE, 
					"Joint_Spawn: World joint needs non-NULL gePhysicsObject1 field.\n");
				*/
				return NULL;
			}
			#if 0
			if (pJoint->Next == pJoint)
			{
				/*
				GenVSI_Error(VSI, 
					GE_FALSE, 
					"Joint_Spawn: Next field points to parent.\n");
				*/
				return NULL;
			}
			#endif
			
			gePhysicsObject_GetLocation(PS1, &POLocation, 0);

			geVec3d_Subtract(&physicsSpaceLocation,
				&POLocation,
				&pPhysjnt->locationA);
			geVec3d_Copy(&physicsSpaceLocation, &pPhysjnt->locationB);
			break;

		case JT_SPHERICAL:
			if (PS1 == NULL || PS2 == NULL)
			{
				/*
				GenVSI_Error(VSI, 
					GE_FALSE, 
					"Joint_Spawn: Spherical joint needs 2 non-NULL gePhysicsObjects.\n");
				*/
				return NULL;
			}
			#if 0
			if (pJoint->Next == pJoint)
			{
				/*
				GenVSI_Error(VSI, 
					GE_FALSE, 
					"Joint_Spawn: Next field points to parent.\n");
				*/
			}
			#endif
			if (PS1 == PS2)
			{
				/*
				GenVSI_Error(VSI, 
					GE_FALSE, 
					"Joint_Spawn: Spherical joint: need 2 distinct gePhysicsObjects.\n");
				*/
				return NULL;
			}

			gePhysicsObject_GetLocation(PS1, &POLocation, 0);
			geVec3d_Subtract(&physicsSpaceLocation,
				&POLocation,
				&pPhysjnt->locationA);

			gePhysicsObject_GetLocation(PS2, &POLocation, 0);
			geVec3d_Subtract(&physicsSpaceLocation,
				&POLocation,
				&pPhysjnt->locationB);
			break;

		default:
			/*
			GenVSI_Error(VSI, 
				GE_FALSE, 
				"Joint_Spawn: unsupported joint type %d.\n", ij->jointType);
			*/
			return NULL;
	}

	return pPhysjnt;
}
/* ------------------------------------------------------------------------------------ */
static void Particles_MoveParticles(Procedural *Proc, geFloat time)
{
	int cnt;
	Particle *pP;

	pP = Proc->Particles;

	for(cnt=0; cnt<Proc->NumActiveParticles; cnt++, pP++)
	{
		geFloat mul, vsqr;

		pP->CurDeathTime += time;

		if(pP->CurDeathTime > pP->DeathTime)
		{
			pP->shade -= (Proc->NumShades + 15)>>4;
			pP->CurDeathTime -= pP->DeathTime;
		}

		if(pP->shade < 0)
		{
			Particles_DeleteParticle(Proc,pP);

			if(cnt >= Proc->NumActiveParticles)
				break;
		}

		pP->p[0] += pP->v[0] * time;
		Proc->Capper(pP->p + 0, pP->v + 0, Proc->SizeX);

		pP->p[1] += pP->v[1] * time;
		Proc->Capper(pP->p + 1, pP->v + 1, Proc->SizeY);

		pP->p[2] += pP->v[2] * time;
		Proc->Capper(pP->p + 2, pP->v + 2, Proc->SizeZ);

		vsqr = geVec3d_LengthSquared((geVec3d*)pP->v);

		if(vsqr > 100.0f)
			vsqr = 100.0f;

		mul = vsqr * pP->Drag;

		if(mul > 0.05f)
			mul = 0.05f;

		pP->v[0] -= pP->v[0] * mul;
		pP->v[1] -= pP->v[1] * mul;
		pP->v[2] -= pP->v[2] * mul;

		// change velocity based on some forces
		if(Proc->DoMagnetic)
		{
			geVec3d A;

			geVec3d_CrossProduct((geVec3d*)(pP->v) , &(Proc->MagneticField), &A);
			pP->v[0] += time * A.X;
			pP->v[1] += time * A.Y;
			pP->v[2] += time * A.Z;
		}

		if(Proc->DoAttractor)
		{
			geFloat ax, ay, az, q;

			if(Proc->AttractorIsAxis)
			{
				geVec3d Diff;

				geVec3d_Subtract((geVec3d*)pP->p , &(Proc->AttractorPos), &Diff);
				q = geVec3d_DotProduct(&(Proc->AttractorAxis), &Diff);
				ax = q * Proc->AttractorAxis.X - Diff.X;
				ay = q * Proc->AttractorAxis.Y - Diff.Y;
				az = q * Proc->AttractorAxis.Z - Diff.Z;
			}
			else
			{
				ax = Proc->AttractorPos.X - pP->p[0];
				ay = Proc->AttractorPos.Y - pP->p[1];
				az = Proc->AttractorPos.Z - pP->p[2];
			}

			q = Proc->AttractorStrength * time;
			ax *= q;
			ay *= q;
			az *= q;

			pP->v[0] += ax;
			pP->v[1] += ay;
			pP->v[2] += az;
		}
	}