/* ** All the three given vectors span only a 2D space, and this finds ** the normal to that plane. Simply sums up all the pair-wise ** cross-products to get a good estimate. Trick is getting the cross ** products to line up before summing. */ void nullspace1(double ret[3], const double r0[3], const double r1[3], const double r2[3]) { double crs[3]; /* ret = r0 x r1 */ VEC_CROSS(ret, r0, r1); /* crs = r1 x r2 */ VEC_CROSS(crs, r1, r2); /* ret += crs or ret -= crs; whichever makes ret longer */ if (VEC_DOT(ret, crs) > 0) { VEC_ADD(ret, crs); } else { VEC_SUB(ret, crs); } /* crs = r0 x r2 */ VEC_CROSS(crs, r0, r2); /* ret += crs or ret -= crs; whichever makes ret longer */ if (VEC_DOT(ret, crs) > 0) { VEC_ADD(ret, crs); } else { VEC_SUB(ret, crs); } return; }
BOOL hit_geo_sphere (GEO *Generic, RAY *Ray, HIT *Hit, PAIR *Bound, void *Info) { GEO_SPHERE *Geo; VECTOR Point; REAL a, b, Distance, Delta; Geo = (GEO_SPHERE *) Generic; VEC_SUB (Point, Ray->Point, Geo->Point); a = - VEC_DOT (Point, Ray->Vector); b = VEC_DOT (Point, Point); Delta = a * a - b + Geo->Radius * Geo->Radius; if (Delta < 0.0) return (FALSE); Delta = sqrt (Delta); Distance = a - Delta; /* - Epsilon;*/ if (Distance < Bound->u || Distance > Bound->v) return (FALSE); if (Hit) { Ray->Distance = Distance; VEC_LIN (Point, Ray->Point, Distance, Ray->Vector); VEC_SUB (Hit->Normal, Point, Geo->Point); if (VEC_DOT (Ray->Vector, Hit->Normal) > 0.0) VEC_NEG (Hit->Normal); VEC_UNIT (Hit->Normal, Distance); VEC_LIN (Hit->Point, Point, Epsilon, Hit->Normal); xyz2uv_geo_sphere (Geo, Hit); } return (TRUE); }
/***************************************** * Read nappe characterization in a file * *****************************************/ GEO * file_geo_nappe (BYTE Type, FILE *File) { GEO_NAPPE *Geo; PNT *Pnt, *PntA, *PntB, *PntC, *PntD; FCT *Fct; VECTOR U, V; REAL Real; INDEX Index; INIT_MEM (Geo, 1, GEO_NAPPE); Geo->Type = Type; GET_INDEX (Geo->NbrPnt); INIT_MEM (Geo->TabPnt, Geo->NbrPnt, PNT); GET_INDEX (Geo->NbrFct); INIT_MEM (Geo->TabFct, Geo->NbrFct, FCT); Geo->Min.x = Geo->Min.y = Geo->Min.z = INFINITY; Geo->Max.x = Geo->Max.y = Geo->Max.z = -INFINITY; for (Index = 0, Pnt = Geo->TabPnt; Index < Geo->NbrPnt; Index++, Pnt++) { GET_VECTOR (Pnt->Point); VEC_MIN (Geo->Min, Pnt->Point); VEC_MAX (Geo->Max, Pnt->Point); } for (Index = 0, Fct = Geo->TabFct; Index < Geo->NbrFct; Index++, Fct++) { if (fscanf (File, " ( %d %d %d %d )", &Fct->i, &Fct->j, &Fct->k, &Fct->l) < 4) return (FALSE); Fct->NumFct = Index; PntA = Geo->TabPnt + Fct->i; PntB = Geo->TabPnt + Fct->j; PntC = Geo->TabPnt + Fct->k; PntD = Geo->TabPnt + Fct->l; VEC_SUB (U, PntC->Point, PntA->Point); VEC_SUB (V, PntD->Point, PntB->Point); VEC_CROSS (Fct->Normal, U, V); VEC_UNIT (Fct->Normal, Real); VEC_INC (PntA->Normal, Fct->Normal); VEC_INC (PntB->Normal, Fct->Normal); VEC_INC (PntC->Normal, Fct->Normal); VEC_INC (PntD->Normal, Fct->Normal); } for (Index = 0, Pnt = Geo->TabPnt; Index < Geo->NbrPnt; Index++, Pnt++) VEC_UNIT (Pnt->Normal, Real); return ((GEO *) Geo); }
/************************************************* * Transform uv-coordinates into xyz-coordinates * *************************************************/ static void uv2xyz_geo_nappe (GEO *Generic, REAL U, REAL V, VECTOR *Point, VECTOR * Normal, VECTOR *Tangent) { GEO_NAPPE *Geo; INDEX Num; PNT *A, *B, *C, *D; REAL Real; Geo = (GEO_NAPPE *) Generic; Num = (INDEX) (U * Geo->NbrFct); if (Num == Geo->NbrFct) Num -= 1; A = &(Geo->TabPnt[(Geo->TabFct[Num]).i]); B = &(Geo->TabPnt[(Geo->TabFct[Num]).j]); C = &(Geo->TabPnt[(Geo->TabFct[Num]).k]); D = &(Geo->TabPnt[(Geo->TabFct[Num]).l]); VEC_UV (*Point, U, V, A->Point, B->Point, C->Point, D->Point); if (Normal != NULL) { VEC_UV (*Normal, U, V, A->Normal, B->Normal, C->Normal, D->Normal); /* or *Normal = (Geo->TabFct[Num]).Normal without any interpolation */ VEC_UNIT (*Normal, Real); } if (Tangent != NULL) { VEC_SUB (*Tangent, (*C).Point, (*A).Point); VEC_UNIT (*Tangent, Real); } }
void Body::FacePos(const LTVector& vTargetPos) { if (!g_pLTServer || !m_hObject) return; LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); LTVector vDir; VEC_SUB(vDir, vTargetPos, vPos); if ( vDir.MagSqr() == 0.0f ) { // Facing the same position... this would be a divide by zero case // when we normalize. So just return. return; } vDir.y = 0.0f; // Don't look up/down VEC_NORM(vDir); LTRotation rRot; LTVector temp(0,1,0); g_pMathLT->AlignRotation(rRot, vDir, temp); g_pLTServer->SetObjectRotation(m_hObject, &rRot); }
BOOL IsPolyInsideSurface(CTempSurface *pSurface, CPrePoly *pPoly) { DWORD i, j; CEditPoly *pEditPoly; CPrePlane edgePlane; PVector vTemp, testPt; pEditPoly = pSurface->m_pPoly; for(i=0; i < pEditPoly->NumVerts(); i++) { VEC_SUB(vTemp, pEditPoly->NextPt(i), pEditPoly->Pt(i)); VEC_CROSS(edgePlane.m_Normal, vTemp, pEditPoly->Normal()); edgePlane.m_Normal.Norm(); edgePlane.m_Dist = VEC_DOT(edgePlane.m_Normal, pEditPoly->Pt(i)); for(j=0; j < pPoly->NumVerts(); j++) { testPt = pPoly->Pt(j); if(DIST_TO_PLANE(testPt, edgePlane) < -0.1f) { return FALSE; } } } return TRUE; }
/************************************************* * Transform uv-coordinates into xyz-coordinates * *************************************************/ static void uv2xyz_geo_sphere (GEO *Generic, REAL U, REAL V, VECTOR *Point, VECTOR * Normal, VECTOR *Tangent) { GEO_SPHERE *Geo; REAL CosPnt, SinPnt; REAL r, Real; Geo = (GEO_SPHERE *) Generic; CosPnt = cos(2.0*PI*U); SinPnt = sin(2.0*PI*U); r = 2.0 * Geo->Radius * sqrt(V*(1.0-V)); Point->x = Geo->Point.x + r * CosPnt; Point->y = Geo->Point.y + r * SinPnt; Point->z = Geo->Point.z + Geo->Radius * (2.0*V-1); if (Normal != NULL) { VEC_SUB (*Normal, *Point, Geo->Point); VEC_UNIT (*Normal, Real); } if (Tangent != NULL) { VEC_MAKE (*Tangent, -SinPnt, CosPnt, 0.0); } }
void CPlayerCamera::PointAtPosition(DVector pos, DRotation rRot, DVector pointFrom) { if (!m_pClientDE) return; // m_pServerDE->GetObjectPos(m_hObject, &vPos); // vTargetPos.y = vPos.y; // Don't look up/down. DVector vDir; VEC_SUB(vDir, pos, pointFrom); VEC_NORM(vDir); m_pClientDE->AlignRotation(&m_rRotation, &vDir, NULL); //m_Angles.Copy(m_Target.m_Angles); //m_Angles.z = angles.z; //m_Angles.x = angles.x; /* DVector vAngles; VEC_INIT(vAngles); m_rRotation = rRot; DFLOAT diffX = pos.x - m_vPos.x; DFLOAT diffY = pos.z - m_vPos.z; vAngles.y = (DFLOAT)atan2(diffX, diffY); DVector target, copy; DVector up, right, forward; m_pClientDE->GetRotationVectors(&m_rRotation, &up, &right, &forward); VEC_SUB(copy, pos, pointFrom); target = Apply(right, up, forward, copy); diffX = target.z; diffY = target.y; //DFLOAT temp = -ATan2(diffY,diffX); //if(Abs(temp - m_Angles.x) < .5) vAngles.x = (DFLOAT)-atan2(diffY, diffX); //PrintVector(pos); //GetClientShell().CPrint("X = " + RealStr(m_Angles.x)); DRotation rOldRot; ROT_COPY(rOldRot, m_rRotation); m_pClientDE->SetupEuler(&m_rRotation, vAngles.x, vAngles.y, vAngles.z); // Make sure rotation is valid... m_pClientDE->GetRotationVectors(&m_rRotation, &up, &right, &forward); if (up.y < 0) ROT_COPY(m_rRotation, rOldRot); */ }
/* ** assign Epsilon */ void assign_epsilon (void) { VECTOR Vector; VEC_SUB (Vector, MainBnd->Max, MainBnd->Min); Epsilon = MINMIN (Vector.x, Vector.y, Vector.z) * EPSILON/3.0; /*Epsilon = EPSILON;*/ }
/* ** All vectors are in the same 1D space, we have to find two ** mutually vectors perpendicular to that span */ void nullspace2(double reta[3], double retb[3], const double r0[3], const double r1[3], const double r2[3]) { double sqr[3], sum[3]; int idx; VEC_COPY(sum, r0); if (VEC_DOT(sum, r1) > 0) { VEC_ADD(sum, r1); } else { VEC_SUB(sum, r1); } if (VEC_DOT(sum, r2) > 0) { VEC_ADD(sum, r2); } else { VEC_SUB(sum, r2); } /* find largest component, to get most stable expression for a perpendicular vector */ sqr[0] = sum[0]*sum[0]; sqr[1] = sum[1]*sum[1]; sqr[2] = sum[2]*sum[2]; idx = 0; if (sqr[0] < sqr[1]) idx = 1; if (sqr[idx] < sqr[2]) idx = 2; /* reta will be perpendicular to sum */ if (0 == idx) { VEC_SET(reta, sum[1] - sum[2], -sum[0], sum[0]); } else if (1 == idx) { VEC_SET(reta, -sum[1], sum[0] - sum[2], sum[1]); } else { VEC_SET(reta, -sum[2], sum[2], sum[0] - sum[1]); } /* and now retb will be perpendicular to both reta and sum */ VEC_CROSS(retb, reta, sum); return; }
DBOOL Naga::Fire(DBOOL bAltFire) { DVector vPos, vDir; DRotation rRot; // Sanity check (GK 9/18/98) if (!m_InventoryMgr.GetCurrentWeapon()) return DFALSE; switch(m_InventoryMgr.GetCurrentWeapon()->GetType()) { case WEAP_NAGA_EYEBEAM: { m_pServerDE->GetModelNodeTransform(m_hObject,"head_gun",&vPos,&rRot); VEC_SUB(vDir, m_vTargetPos, vPos); break; } case WEAP_NAGA_SPIKE: { m_pServerDE->GetModelNodeTransform(m_hObject,"l_gun",&vPos,&rRot); VEC_SUB(vDir, m_vTargetPos, vPos); break; } default: { m_pServerDE->GetObjectPos(m_hObject,&vPos); VEC_SUB(vDir, m_vTargetPos, vPos); break; } } VEC_NORM(vDir); m_pServerDE->AlignRotation(&rRot, &vDir, DNULL); m_InventoryMgr.FireCurrentWeapon(&vPos, &rRot, bAltFire); return DTRUE; }
inline bool d3d_ClipSprite(SpriteInstance *pInstance, HPOLY hPoly, T **ppPoints, uint32 *pnPoints, T *pOut) { LTPlane thePlane; float dot, d1, d2; SPolyVertex *pPrevPoint, *pCurPoint, *pEndPoint; LTVector vecTo; T *pVerts; uint32 nVerts; WorldPoly *pPoly; if(g_have_world == false) return false; // Get the correct poly. pPoly = world_bsp_client->GetPolyFromHPoly(hPoly); if(!pPoly) return false; // First see if the viewer is on the frontside of the poly. dot = pPoly->GetPlane()->DistTo(g_ViewParams.m_Pos); if(dot <= 0.01f) return false; pVerts = *ppPoints; nVerts = *pnPoints; // Clip on each edge plane. pEndPoint = &pPoly->GetVertices()[pPoly->GetNumVertices()]; pPrevPoint = pEndPoint - 1; for(pCurPoint=pPoly->GetVertices(); pCurPoint != pEndPoint; ) { VEC_SUB(vecTo, pCurPoint->m_Vertex->m_Vec, pPrevPoint->m_Vertex->m_Vec); VEC_CROSS(thePlane.m_Normal, vecTo, pPoly->GetPlane()->m_Normal); VEC_NORM(thePlane.m_Normal); thePlane.m_Dist = VEC_DOT(thePlane.m_Normal, pCurPoint->m_Vertex->m_Vec); #define CLIPTEST PLANETEST #define DOCLIP DOPLANECLIP #include "polyclip.h" #undef CLIPTEST #undef DOCLIP pPrevPoint = pCurPoint; ++pCurPoint; } *ppPoints = pVerts; *pnPoints = nVerts; return true; }
DBOOL CameraObj::Update() { if (!g_pServerDE) return DFALSE; g_pServerDE->SetNextUpdate(m_hObject, 0.01f); // Need to check if Camera has Moved... // If so, we need to change the Line... // and Send new camera position // // Might have to send a pan up, pan down, pan direction, because of client/server slow down. // That way all the updates are done on the client. // if (g_pServerDE->GetVarValueFloat(g_pServerDE->GetGameConVar("DebugCutScene")) == 1.0f) // { // DisplayRay(); // } // If we are linked then check to make sure the Link has not moved... if (m_hLinkObject) { DVector vPos, vMyPos; VEC_INIT(vPos); VEC_INIT(vMyPos); // From this Point g_pServerDE->GetObjectPos(m_hObject, &vMyPos); // To this Point g_pServerDE->GetObjectPos(m_hLinkObject, &vPos); DVector vF, vU; VEC_SUB(vF, vPos, vMyPos); VEC_SET(vU, 0, 1, 0); DRotation rMyNewRot; g_pServerDE->AlignRotation(&rMyNewRot, &vF, &vU); g_pServerDE->SetObjectRotation(m_hObject, &rMyNewRot); } // Deactivate if the active time has expired. if (m_fActiveTime > 0 && g_pServerDE->GetTime() > m_fDeactivateTime) SetActive(DFALSE); return DTRUE; }
DBOOL CMovement::ClearToPoint(DVector vStart, DVector vDestPos, DVector vDims, IntersectInfo* IInfo) { GlobalFilterFnData globalFilterFnData; CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return DFALSE; DFLOAT fDim = (DFLOAT)sqrt((vDims.x * vDims.x) + (vDims.z * vDims.z)) + 0.1f; IntersectQuery IQuery; IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; IQuery.m_FilterFn = GlobalFilterFn; globalFilterFnData.m_dwFlags = IGNORE_CHARACTER; globalFilterFnData.m_nIgnoreObjects = 1; globalFilterFnData.m_hIgnoreObjects = &m_hObject; IQuery.m_pUserData = &globalFilterFnData; DVector vDir; DRotation rRot; VEC_SUB(vDir, vDestPos, vStart); VEC_NORM(vDir); pServerDE->AlignRotation(&rRot, &vDir, &m_vUp); DVector vU,vR,vF; pServerDE->GetRotationVectors(&rRot,&vU,&vR,&vF); //check the right side VEC_ADDSCALED(IQuery.m_From, vStart, vR, fDim); VEC_ADDSCALED(IQuery.m_To, vDestPos, vR, fDim); if(pServerDE->IntersectSegment(&IQuery, IInfo)) { return DFALSE; } //check the left side VEC_ADDSCALED(IQuery.m_From, vStart, vR, (fDim * -1.0f)); VEC_ADDSCALED(IQuery.m_To,vDestPos, vR, (fDim * -1.0f)); if(pServerDE->IntersectSegment(&IQuery, IInfo)) { return DFALSE; } return DTRUE; }
GEO * file_geo_sphere (BYTE Type, FILE *File) { GEO_SPHERE *Geo; VECTOR Vector; INIT_MEM (Geo, 1, GEO_SPHERE); Geo->Type = Type; GET_VECTOR (Geo->Point); GET_REAL (Geo->Radius); Vector.x = Vector.y = Vector.z = Geo->Radius; VEC_SUB (Geo->Min, Geo->Point, Vector); VEC_ADD (Geo->Max, Geo->Point, Vector); return ((GEO *) Geo); }
DBOOL CLaserBeamFX::UpdateBeam() { if(!m_pClientDE) return DFALSE; DVector vDist, vUp; DRotation rRot; VEC_SET(vUp, 0.0f, 1.0f, 0.0f); VEC_SUB(vDist, m_vDest, m_vSource); m_pClientDE->AlignRotation(&rRot, &vDist, &vUp); m_pClientDE->SetObjectPos(m_hObject, &m_vSource); m_pClientDE->SetObjectRotation(m_hObject, &rRot); VEC_SET(m_vScale, m_fMinScale, m_fMinScale, VEC_MAG(vDist)); return DTRUE; }
BOOL point_geo_sphere (GEO *Generic, HIT *Hit, RAY *NewRay) { VECTOR Point; if (NewRay == NULL) { uv2xyz_geo_sphere (Generic, Hit->u, Hit->v, &(Hit->Point), &(Hit->Normal), NULL); } else { uv2xyz_geo_sphere (Generic, Hit->u, Hit->v, &Point, NULL, NULL); NewRay->Point = Hit->Point; VEC_SUB (NewRay->Vector, Point, NewRay->Point); VEC_UNIT (NewRay->Vector, NewRay->Distance); } return (TRUE); }
DBOOL UndeadGideon::Fire(DBOOL bAltFire) { DVector vPos, vDir; DRotation rRot; // Sanity check (GK 9/18/98) if (!m_InventoryMgr.GetCurrentWeapon()) return DFALSE; m_pServerDE->GetModelNodeTransform(m_hObject,"head",&vPos,&rRot); VEC_SUB(vDir, m_vTargetPos, vPos); VEC_NORM(vDir); vDir.x = m_MoveObj.GetForwardVector().x; vDir.z = m_MoveObj.GetForwardVector().z; m_pServerDE->AlignRotation(&rRot, &vDir, DNULL); DDWORD m_nFiredWeapon = m_InventoryMgr.FireCurrentWeapon(&vPos, &rRot, bAltFire); return DTRUE; }
LTBOOL CGibFX::OkToRemoveGib(HLOCALOBJ hGib) { if (!m_pClientDE || !g_pGameClientShell || !hGib) return LTTRUE; // The only constraint is that the client isn't currently looking // at the model... HLOCALOBJ hCamera = g_pGameClientShell->GetCamera(); if (!hCamera) return LTTRUE; LTVector vPos, vCamPos; m_pClientDE->GetObjectPos(hGib, &vPos); m_pClientDE->GetObjectPos(hCamera, &vCamPos); // Determine if the client can see us... LTVector vDir; VEC_SUB(vDir, vPos, vCamPos); LTRotation rRot; LTVector vU, vR, vF; m_pClientDE->GetObjectRotation(hCamera, &rRot); m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF); VEC_NORM(vDir); VEC_NORM(vF); LTFLOAT fMul = VEC_DOT(vDir, vF); if (fMul <= 0.0f) return LTTRUE; // Client is looking our way, don't remove it yet... return LTFALSE; }
DBOOL Equal(DVector & v1, DVector & v2) { DVector v; VEC_SUB(v, v1, v2); return DBOOL(VEC_MAG(v) < 1.0f); }
void CPlayerCamera::MoveCameraToPosition(DVector pos, DVector vStartPos, DFLOAT deltaTime) { if (!m_pClientDE || !m_hTarget) return; DFLOAT nCurrentTime = m_pClientDE->GetTime(); // Handle transition if (m_eCameraMode == GOINGFIRSTPERSON || m_eCameraMode == GOINGCHASE || m_eCameraMode == DEATH) { if (nCurrentTime > m_fTransitionStart + m_fTransitionTime) { switch (m_eCameraMode) { case GOINGFIRSTPERSON: m_eCameraMode = FIRSTPERSON; break; case GOINGCHASE: m_eCameraMode = CHASE; break; } } else { // vStartPos is starting pos, pos is the position we want DFLOAT percentage = (nCurrentTime - m_fTransitionStart) / (m_fTransitionTime); DVector vMagnitude; VEC_SUB (vMagnitude, pos, vStartPos); VEC_MULSCALAR (vMagnitude, vMagnitude, percentage); VEC_ADD (pos, vStartPos, vMagnitude); } } DVector dir; VEC_SUB(dir, pos, m_vPos); DFLOAT multiplier = 1.0f; // 0.5f; DVector toMove; VEC_MULSCALAR(toMove, dir, multiplier); DFLOAT moveMag; if(m_bSlide) { moveMag = VEC_MAG(toMove); if(moveMag > VEC_MAG(dir)) moveMag = VEC_MAG(dir); if (toMove.x != 0.0f || toMove.y != 0.0f || toMove.z != 0.0f) { VEC_NORM(toMove); } VEC_MULSCALAR(toMove, toMove, moveMag); VEC_ADD(m_vPos, m_vPos, toMove); } else { VEC_COPY(m_vPos, pos); } }
void CProjectileFX::Detonate(CollisionInfo* pInfo) { if (!m_pClientDE || m_bDetonated) return; m_bDetonated = LTTRUE; SurfaceType eType = ST_UNKNOWN; LTVector vPos; g_pLTClient->GetObjectPos(m_hServerObject, &vPos); // Determine the normal of the surface we are impacting on... LTVector vNormal; VEC_SET(vNormal, 0.0f, 1.0f, 0.0f); if (pInfo) { if (pInfo->m_hObject) { eType = GetSurfaceType(pInfo->m_hObject); } else if (pInfo->m_hPoly != INVALID_HPOLY) { eType = GetSurfaceType(pInfo->m_hPoly); VEC_COPY(vNormal, pInfo->m_Plane.m_Normal); LTRotation rRot(vNormal, LTVector(0.0f, 1.0f, 0.0f)); m_pClientDE->SetObjectRotation(m_hServerObject, &rRot); // Calculate where we really hit the plane... LTVector vVel, vP0, vP1; g_pPhysicsLT->GetVelocity(m_hServerObject, &vVel); VEC_COPY(vP1, vPos); VEC_MULSCALAR(vVel, vVel, g_pGameClientShell->GetFrameTime()); VEC_SUB(vP0, vP1, vVel); LTFLOAT fDot1 = VEC_DOT(pInfo->m_Plane.m_Normal, vP0) - pInfo->m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT(pInfo->m_Plane.m_Normal, vP1) - pInfo->m_Plane.m_Dist; if (fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f) { VEC_COPY(vPos, vP1); } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP(vPos, vP0, vP1, fPercent); } } } else { // Since pInfo was null, this means the projectile's lifetime was up, // so we just blow-up in the air. eType = ST_AIR; } HOBJECT hObj = !!pInfo ? pInfo->m_hObject : LTNULL; ::AddLocalImpactFX(hObj, m_vFirePos, vPos, vNormal, eType, m_vPath, m_nWeaponId, m_nAmmoId, 0); m_bWantRemove = LTTRUE; }
DBOOL CFlashlightFX::Update() { if (!m_pClientDE || m_bWantRemove || !m_hServerObject || !m_hObject) return DFALSE; DDWORD dwUsrFlags; m_pClientDE->GetObjectUserFlags(m_hServerObject, &dwUsrFlags); // Hidden if (!(dwUsrFlags & USRFLG_VISIBLE)) { m_pClientDE->SetObjectFlags(m_hObject, 0); } else { DRotation rRot; DVector vPos, vF, vR, vU; m_pClientDE->GetObjectRotation(m_hServerObject, &rRot); m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF); m_pClientDE->GetObjectPos(m_hServerObject, &vPos); // Cast a line to see where to put the light.. ClientIntersectQuery iQuery; ClientIntersectInfo iInfo; VEC_COPY(iQuery.m_From, vPos); VEC_COPY(iQuery.m_Direction, vF); iQuery.m_Flags = INTERSECT_OBJECTS; DFLOAT fDistance = 1000.0f; // Far, far, away... if (m_pClientDE->CastRay(&iQuery, &iInfo)) { // Place the light m_pClientDE->SetObjectPos(m_hObject, &iInfo.m_Point); // Calculate the distance VEC_SUB(vPos, vPos, iInfo.m_Point); fDistance = VEC_MAG(vPos); if (fDistance < 10.0f) fDistance = 10.0f; // The farther away, the brighter and bigger the light DFLOAT fRadius = fDistance * 0.40f; m_pClientDE->SetLightRadius(m_hObject, fRadius); // Determine the minimum intensity based on the current light level // (so we don't end up casting a dark light instead). DFLOAT fMinIntensity = 100.0f; DVector vColor; if (m_pClientDE->Common()->GetPointShade(&vPos, &vColor)) { if (vColor.x > fMinIntensity) fMinIntensity = vColor.x; if (vColor.y > fMinIntensity) fMinIntensity = vColor.y; if (vColor.z > fMinIntensity) fMinIntensity = vColor.z; } fMinIntensity = DCLAMP((fMinIntensity + 32), 0, 255); fMinIntensity /= 255.0f; DFLOAT fIntensity = (1000.0f - (fDistance/2.0f)) / 1000.0f; if (fIntensity < fMinIntensity) fIntensity = fMinIntensity; m_pClientDE->SetLightColor(m_hObject, fIntensity, fIntensity, fIntensity); m_pClientDE->SetObjectFlags(m_hObject, FLAG_VISIBLE); } else { m_pClientDE->SetObjectFlags(m_hObject, 0); } } return DTRUE; }
static DDWORD DemoSky_EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData) { DemoSkyWorldModel *pModel; SkyDef def; DVector pos, temp; ObjectCreateStruct *pStruct; HOBJECT hObject; pModel = (DemoSkyWorldModel*)pObject; switch(messageID) { case MID_PRECREATE: { pStruct = (ObjectCreateStruct*)pData; pStruct->m_ObjectType = OT_WORLDMODEL; if( lData == 1.0f ) { g_pServerDE->GetPropVector("SkyDims", &pModel->SkyDims); g_pServerDE->GetPropString("Name", pStruct->m_Filename, MAX_CS_FILENAME_LEN); g_pServerDE->GetPropReal("InnerPercentX", &pModel->InnerPercentX); g_pServerDE->GetPropReal("InnerPercentY", &pModel->InnerPercentY); g_pServerDE->GetPropReal("InnerPercentZ", &pModel->InnerPercentZ); g_pServerDE->GetPropLongInt("Index", &pModel->Index); } else { VEC_INIT( pModel->SkyDims ); pModel->InnerPercentX = 0.1f; pModel->InnerPercentY = 0.1f; pModel->InnerPercentZ = 0.1f; pModel->Index = 0; } break; } case MID_INITIALUPDATE: { // Set the sky box? if(pModel->SkyDims.x != 0.0f && pModel->SkyDims.y != 0.0f && pModel->SkyDims.z != 0.0f) { g_pServerDE->GetObjectPos(pModel->BaseClass.m_hObject, &pos); VEC_SUB(def.m_Min, pos, pModel->SkyDims); VEC_ADD(def.m_Max, pos, pModel->SkyDims); temp.x = pModel->SkyDims.x * pModel->InnerPercentX; temp.y = pModel->SkyDims.y * pModel->InnerPercentY; temp.z = pModel->SkyDims.z * pModel->InnerPercentZ; VEC_SUB(def.m_ViewMin, pos, temp); VEC_ADD(def.m_ViewMax, pos, temp); g_pServerDE->SetSkyDef(&def); } hObject = pModel->BaseClass.m_hObject; g_pServerDE->SetObjectFlags(hObject, g_pServerDE->GetObjectFlags(hObject) | (FLAG_SKYOBJECT|FLAG_FORCEOPTIMIZEOBJECT)); g_pServerDE->AddObjectToSky(pModel->BaseClass.m_hObject, pModel->Index); break; } } return bc_EngineMessageFn(pObject, messageID, pData, lData); }
DVector CPlayerCamera::FindOptimalCameraPosition() { DVector pos; VEC_INIT(pos); if (!m_pClientDE || !m_hTarget) return pos; DVector up, right, forward, dir; DFLOAT distToOptimal; DVector TargetPlusOffset; DVector vTargetPos; m_pClientDE->GetObjectPos(m_hTarget, &vTargetPos); DRotation rRot; m_pClientDE->GetObjectRotation(m_hTarget, &rRot); if (Equal(vTargetPos, m_vLastTargetPos) && Equal(rRot, m_rLastTargetRot) && m_eCameraMode != DEATH) { return m_vLastOptPos; } else { VEC_COPY(m_vLastTargetPos, vTargetPos); ROT_COPY(m_rLastTargetRot, rRot); } DVector vTemp; if (m_eCameraMode == DEATH) { VEC_COPY(vTemp, m_TargetDeathOffset); } else { VEC_COPY(vTemp, m_TargetChaseOffset); } VEC_ADD(vTemp, vTargetPos, vTemp); VEC_COPY(TargetPlusOffset, vTemp); m_pClientDE->GetRotationVectors(&rRot, &up, &right, &forward); // pos = TargetPlusOffset + right*m_OptX + up*m_OptY + forward*m_OptZ; DVector vTemp1, vTemp2; if (m_eCameraMode == DEATH) { VEC_MULSCALAR(vTemp, right, m_DeathOptX); VEC_MULSCALAR(vTemp2, forward, m_DeathOptZ); } else { VEC_MULSCALAR(vTemp, right, m_OptX); VEC_MULSCALAR(vTemp2, forward, m_OptZ); } VEC_MULSCALAR(vTemp1, up, m_OptY); ClientIntersectQuery iQuery; ClientIntersectInfo iInfo; VEC_ADD(vTemp, vTemp, vTemp1); VEC_ADD(vTemp, vTemp, vTemp2); VEC_ADD(pos, TargetPlusOffset, vTemp); VEC_SUB(vTemp, TargetPlusOffset, pos); distToOptimal = VEC_MAG(vTemp); VEC_SUB(dir, pos, TargetPlusOffset); VEC_NORM(dir); VEC_COPY(iQuery.m_From, TargetPlusOffset); VEC_COPY(iQuery.m_To, pos); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, TargetPlusOffset); // If there was something in the way, move in front of that thing. if (VEC_MAG(vTemp) < distToOptimal) { VEC_ADD(pos, iInfo.m_Point, iInfo.m_Plane.m_Normal); } } #ifdef DOING_EXTRA_CHECKS // Make sure we aren't clipping into walls... DFLOAT fClipDistance = 100.0f; // 15.0f; DBOOL bClipRightIssues = DTRUE; DBOOL bClipUpIssues = DTRUE; // Check for walls to the right... VEC_MULSCALAR(vTemp, right, fClipDistance); VEC_ADD(vTemp, pos, vTemp); VEC_COPY(iQuery.m_From, pos); VEC_COPY(iQuery.m_To, vTemp); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, pos); DFLOAT fDist = (fClipDistance - VEC_MAG(vTemp)); VEC_MULSCALAR(vTemp, right, -fDist) VEC_ADD(pos, pos, vTemp); } else { bClipRightIssues = DFALSE; } // If we didn't adjust for a wall to the right, check walls to the left... if (!bClipRightIssues) { VEC_MULSCALAR(vTemp, right, -fClipDistance); VEC_ADD(vTemp, pos, vTemp); VEC_COPY(iQuery.m_From, pos); VEC_COPY(iQuery.m_To, vTemp); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, pos); DFLOAT fDist = (fClipDistance - VEC_MAG(vTemp)); VEC_MULSCALAR(vTemp, right, fDist) VEC_ADD(pos, pos, vTemp); } } // Check for ceilings... VEC_MULSCALAR(vTemp, up, fClipDistance); VEC_ADD(vTemp, pos, vTemp); VEC_COPY(iQuery.m_From, pos); VEC_COPY(iQuery.m_To, vTemp); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, pos); DFLOAT fDist = (fClipDistance - VEC_MAG(vTemp)); VEC_MULSCALAR(vTemp, up, -fDist) VEC_ADD(pos, pos, vTemp); } else { bClipUpIssues = DFALSE; } // If we didn't hit any ceilings, check for floors... if (!bClipUpIssues) { VEC_MULSCALAR(vTemp, up, -fClipDistance); VEC_ADD(vTemp, pos, vTemp); VEC_COPY(iQuery.m_From, pos); VEC_COPY(iQuery.m_To, vTemp); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vTemp, iInfo.m_Point, pos); DFLOAT fDist = (fClipDistance - VEC_MAG(vTemp)); VEC_MULSCALAR(vTemp, up, fDist) VEC_ADD(pos, pos, vTemp); } } #endif // DOING_EXTRA_CHECKS VEC_COPY(m_vLastOptPos, pos); return pos; }
LTBOOL CBulletTrailFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { // See if we can figure out what color bubbles to make, based on the // container we start in... HLOCALOBJ objList[1]; uint32 dwNum = m_pClientDE->GetPointContainers(&m_vStartPos, objList, 1); if (dwNum > 0 && objList[0]) { uint32 dwUserFlags; m_pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags); if (dwUserFlags & USRFLG_VISIBLE) { uint16 dwCode; if (m_pClientDE->GetContainerCode(objList[0], &dwCode)) { GetLiquidColorRange((ContainerCode)dwCode, &m_vColor1, &m_vColor2); } } } // Move the particle system to the correct position... m_pClientDE->SetObjectPos(m_hObject, &m_vStartPos); m_bFirstUpdate = LTFALSE; m_fStartTime = fTime; m_fLastTime = fTime; VEC_INIT(m_vLastPos); // Find the end position... ClientIntersectQuery iQuery; ClientIntersectInfo iInfo; LTVector vTemp, vEndPoint; VEC_MULSCALAR(vTemp, m_vDir, MAX_TRAIL_LENGTH); VEC_ADD(vEndPoint, m_vStartPos, vTemp); VEC_COPY(iQuery.m_From, m_vStartPos); VEC_COPY(iQuery.m_To, vEndPoint); if (m_pClientDE->IntersectSegment(&iQuery, &iInfo)) { VEC_SUB(vEndPoint, iInfo.m_Point, m_vStartPos); m_fDistance = VEC_MAG(vEndPoint); } if (m_fDistance <= 0.0f || m_fFadeTime <= 0.0f) return LTFALSE; // Calculate the trail velocity... m_fTrailVel = m_fDistance / m_fFadeTime; VEC_MULSCALAR(m_vDir, m_vDir, m_fTrailVel); } // Check to see if we should just wait for last bubble to go away... if (fTime > m_fStartTime + m_fFadeTime) { if (fTime > m_fLastTime + m_fLifeTime) { return LTFALSE; } LTFLOAT fScale = (m_fLifeTime - (fTime - m_fLastTime)) / m_fLifeTime; // m_pClientDE->SetParticleSystemColorScale(m_hObject, fScale); LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale); return LTTRUE; } // Create the necessary particles... LTFLOAT fTimeOffset = g_pGameClientShell->GetFrameTime(); // Calculate distance traveled this frame... LTFLOAT fDist = m_fTrailVel * fTimeOffset; if (fDist > m_fDistance) fDist = m_fDistance; m_fDistTraveled += fDist; if (m_fDistTraveled > m_fDistance) { fDist = m_fDistance - (m_fDistTraveled - fDist); if (fDist <= 0.0f) return LTTRUE; } // Calculate number of particles to create... LTFLOAT fNumParticles = fDist * m_fNumParticles / m_fDistance; // Calculate starting bubble position... LTVector vCurPos, vPos, vDelta, vTemp, vDriftVel, vColor; VEC_MULSCALAR(vTemp, m_vDir, fTimeOffset); VEC_ADD(vCurPos, m_vLastPos, vTemp); // What is the range of colors? LTFLOAT fRange = m_vColor2.x - m_vColor1.x; // Fill the distance between the last projectile position, and it's // current position with bubbles... VEC_SUB(vTemp, vCurPos, m_vLastPos); VEC_MULSCALAR(vDelta, vTemp, 1.0f/fNumParticles); VEC_COPY(vPos, m_vLastPos); LTFLOAT fLifeTime = 100.0f; LTFLOAT fOffset = 0.0f; LTVector vDriftOffset; VEC_SET(vDriftOffset, 0.0f, 0.0f, 0.0f); int nNumParticles = GetNumParticles((int)fNumParticles); for (int i=0; i < nNumParticles; i++) { // Build the individual bubbless... for (int j=0; j < 1; j++) { VEC_COPY(vTemp, vPos); VEC_SET(vDriftVel, 0.0f, GetRandom(5.0f, 6.0f), 0.0f); vTemp.x += GetRandom(-fOffset, fOffset); vTemp.y += GetRandom(-fOffset, fOffset); vTemp.z += GetRandom(-fOffset, fOffset); GetRandomColorInRange(vColor); m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fLifeTime); } VEC_ADD(vPos, vPos, vDelta); } VEC_COPY(m_vLastPos, vCurPos); m_fLastTime = fTime; return LTTRUE; }
static DDWORD SkyPointer_EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData) { SkyPointer *pModel; SkyDef def; DVector pos, temp; ObjectCreateStruct *pStruct; ObjectList *pList; HOBJECT hObject; pModel = (SkyPointer*)pObject; switch(messageID) { case MID_PRECREATE: { pStruct = (ObjectCreateStruct*)pData; pStruct->m_ObjectType = OT_NORMAL; pModel->m_hObject = 0; if( lData == 1.0f ) { g_pServerDE->GetPropVector("SkyDims", &pModel->SkyDims); g_pServerDE->GetPropString("Name", pStruct->m_Filename, MAX_CS_FILENAME_LEN); g_pServerDE->GetPropString("SkyObjectName", pModel->m_ObjectName, sizeof(pModel->m_ObjectName)-1); g_pServerDE->GetPropReal("InnerPercentX", &pModel->InnerPercentX); g_pServerDE->GetPropReal("InnerPercentY", &pModel->InnerPercentY); g_pServerDE->GetPropReal("InnerPercentZ", &pModel->InnerPercentZ); g_pServerDE->GetPropLongInt("Index", &pModel->Index); } else { pModel->m_ObjectName[0] = 0; VEC_INIT( pModel->SkyDims ); pModel->InnerPercentX = 0.1f; pModel->InnerPercentY = 0.1f; pModel->InnerPercentZ = 0.1f; pModel->Index = 0; } break; } case MID_INITIALUPDATE: { // Set the sky box? if(pModel->SkyDims.x != 0.0f && pModel->SkyDims.y != 0.0f && pModel->SkyDims.z != 0.0f) { g_pServerDE->GetObjectPos(pModel->BaseClass.m_hObject, &pos); VEC_SUB(def.m_Min, pos, pModel->SkyDims); VEC_ADD(def.m_Max, pos, pModel->SkyDims); temp.x = pModel->SkyDims.x * pModel->InnerPercentX; temp.y = pModel->SkyDims.y * pModel->InnerPercentY; temp.z = pModel->SkyDims.z * pModel->InnerPercentZ; VEC_SUB(def.m_ViewMin, pos, temp); VEC_ADD(def.m_ViewMax, pos, temp); g_pServerDE->SetSkyDef(&def); } g_pServerDE->SetNextUpdate(pModel->BaseClass.m_hObject, 0.001f); break; } case MID_UPDATE: { // Add the first object to the sky. pList = g_pServerDE->FindNamedObjects(pModel->m_ObjectName); if(pList && pList->m_pFirstLink) { hObject = pList->m_pFirstLink->m_hObject; g_pServerDE->AddObjectToSky(hObject, pModel->Index); g_pServerDE->SetObjectFlags(hObject, g_pServerDE->GetObjectFlags(hObject) | (FLAG_SKYOBJECT|FLAG_FORCEOPTIMIZEOBJECT)); g_pServerDE->RelinquishList(pList); } g_pServerDE->RemoveObject(pModel->BaseClass.m_hObject); break; } } return bc_EngineMessageFn(pObject, messageID, pData, lData); }
void CParticleExplosionFX::AddParticles(MovingObject* pObject) { if (!m_hObject || !m_pClientDE || !pObject || pObject->m_PhysicsFlags & MO_RESTING) return; LTFLOAT fTime = m_pClientDE->GetTime(); LTVector vCurPos, vLastPos, vPos, vDelta, vTemp, vDriftVel, vColor; VEC_COPY(vCurPos, pObject->m_Pos); VEC_COPY(vLastPos, pObject->m_LastPos); // Calculate Particle puff positions... // Current position is relative to the particle system's postion (i.e., // each puff of Particle is some distance away from the particle system's // position)... VEC_SUB(vCurPos, vCurPos, m_vPos); VEC_SUB(vLastPos, vLastPos, m_vPos); // How long has it been since the last Particle puff? LTFLOAT fTimeOffset = fTime - m_fLastTime; // Fill the distance between the last projectile position, and it's // current position with Particle puffs... VEC_SUB(vTemp, vCurPos, vLastPos); VEC_MULSCALAR(vDelta, vTemp, 1.0f/LTFLOAT(m_nNumSteps)); VEC_COPY(vPos, vLastPos); LTFLOAT fCurLifeTime = 10.0f; LTFLOAT fLifeTimeOffset = fTimeOffset / LTFLOAT(m_nNumSteps); LTFLOAT fOffset = 0.5f; if (m_bSmall) { fOffset /= 2.0f; } for (int i=0; i < m_nNumSteps; i++) { // Build the individual Particle puffs... for (int j=0; j < m_nNumPerPuff; j++) { VEC_COPY(vTemp, vPos); VEC_SET(vDriftVel, GetRandom(m_vMinDriftOffset.x, m_vMaxDriftOffset.x), GetRandom(m_vMinDriftOffset.y, m_vMaxDriftOffset.y), GetRandom(m_vMinDriftOffset.z, m_vMaxDriftOffset.z)); if (!m_bIgnoreWind) { vDriftVel.x += g_vWorldWindVel.x; vDriftVel.y += g_vWorldWindVel.y; vDriftVel.z += g_vWorldWindVel.z; } vTemp.x += GetRandom(-fOffset, fOffset); vTemp.y += GetRandom(-fOffset, fOffset); vTemp.z += GetRandom(-fOffset, fOffset); GetRandomColorInRange(vColor); m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fCurLifeTime); } VEC_ADD(vPos, vPos, vDelta); fCurLifeTime += fLifeTimeOffset; } }
/******************************************************** * Search for an intersection between a nappe and a ray * *******************************************************/ BOOL hit_geo_nappe (GEO *Generic, RAY *Ray, HIT *Hit, PAIR *Bound, void *Info) { GEO_NAPPE *Geo; FCT *Fct; PNT *Pnt, *PntA, *PntB; VECTOR Normal; VECTOR Point; REAL a, b, c, u, v, uA, vA, uB, vB, Distance, Real; Geo = (GEO_NAPPE *) Generic; Fct = (FCT *) Info; Distance = VEC_DOT (Ray->Vector, Fct->Normal); if (ABS(Distance) < EPSILON) return (FALSE); Pnt = Geo->TabPnt + Fct->i; VEC_SUB (Point, Pnt->Point, Ray->Point); Distance = VEC_DOT (Point, Fct->Normal) / Distance ; /*-Epsilon est vire*/ if (Distance < Bound->u || Distance > Bound->v) return (FALSE); VEC_LIN (Point, Ray->Point, Distance, Ray->Vector); if ((ABS(Fct->Normal.z) > ABS(Fct->Normal.x)) && (ABS(Fct->Normal.z) > ABS(Fct->Normal.y))) { u = Point.x - Pnt->Point.x; v = Point.y - Pnt->Point.y; PntA = Geo->TabPnt + Fct->j; PntB = Geo->TabPnt + Fct->k; uA = PntA->Point.x - Pnt->Point.x; vA = PntA->Point.y - Pnt->Point.y; uB = PntB->Point.x - Pnt->Point.x; vB = PntB->Point.y - Pnt->Point.y; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA-u*vA) / a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } if (Fct->l == Fct->i) return (FALSE); PntA = Geo->TabPnt + Fct->l; uA = PntA->Point.x - Pnt->Point.x; vA = PntA->Point.y - Pnt->Point.y; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } return (FALSE); } else if (ABS(Fct->Normal.y) > ABS(Fct->Normal.x)) { u = Point.z - Pnt->Point.z; v = Point.x - Pnt->Point.x; PntA = Geo->TabPnt + Fct->j; PntB = Geo->TabPnt + Fct->k; uA = PntA->Point.z - Pnt->Point.z; vA = PntA->Point.x - Pnt->Point.x; uB = PntB->Point.z - Pnt->Point.z; vB = PntB->Point.x - Pnt->Point.x; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } if (Fct->l == Fct->i) return (FALSE); PntA = Geo->TabPnt + Fct->l; uA = PntA->Point.z - Pnt->Point.z; vA = PntA->Point.x - Pnt->Point.x; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } return (FALSE); } else if (ABS(Fct->Normal.x) > EPSILON) { u = Point.y - Pnt->Point.y; v = Point.z - Pnt->Point.z; PntA = Geo->TabPnt + Fct->j; PntB = Geo->TabPnt + Fct->k; uA = PntA->Point.y - Pnt->Point.y; vA = PntA->Point.z - Pnt->Point.z; uB = PntB->Point.y - Pnt->Point.y; vB = PntB->Point.z - Pnt->Point.z; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } if (Fct->l == Fct->i) return (FALSE); PntA = Geo->TabPnt + Fct->l; uA = PntA->Point.y - Pnt->Point.y; vA = PntA->Point.z - Pnt->Point.z; a = uA*vB - vA*uB; b = (u*vB - v*uB)/a; c = (v*uA - u*vA)/a; a = 1.0-b-c; if (a > -EPSILON && b > -EPSILON && c > -EPSILON) { VEC_INTER (Normal, a, Pnt->Normal, b, PntA->Normal, c, PntB->Normal); Real = VEC_DOT (Ray->Vector, Normal); if (Real > 0.0) return (FALSE); if (Hit) { Real = VEC_LEN (Normal); VEC_UNIT (Normal, Real); Ray->Distance = Distance; Hit->Point = Point; Hit->Normal = Normal; xyz2uv_geo_nappe (Geo, Hit, Fct); } return (TRUE); } return (FALSE); } return (FALSE); }
LTBOOL CParticleTrailSegmentFX::Update() { if (!m_hObject || !m_pClientDE) return LTFALSE; if (!CBaseParticleSystemFX::Update()) return LTFALSE; CGameSettings* pSettings = g_pInterfaceMgr->GetSettings(); if (!pSettings) return LTFALSE; uint8 nDetailLevel = pSettings->SpecialFXSetting(); LTFLOAT fTime = m_pClientDE->GetTime(); if (m_bFirstUpdate) { if (!m_hServerObject) return LTFALSE; m_bFirstUpdate = LTFALSE; m_fStartTime = fTime; m_fLastTime = fTime; // Where is the server (moving) object... LTVector vPos, vTemp; m_pClientDE->GetObjectPos(m_hServerObject, &vPos); // Current position is relative to the particle system's postion (i.e., // each puff of Particle is some distance away from the particle system's /// position)... m_pClientDE->GetObjectPos(m_hObject, &vTemp); VEC_SUB(vPos, vPos, vTemp); VEC_COPY(m_vLastPos, vPos); } // Check to see if we should just wait for last Particle puff to go away... if (m_bWantRemove || (fTime > m_fStartTime + m_fFadeTime)) { if (fTime > m_fLastTime + m_fLifeTime) { return LTFALSE; } LTFLOAT fScale = (m_fLifeTime - (fTime - m_fLastTime)) / m_fLifeTime; LTFLOAT r, g, b, a; m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a); m_pClientDE->SetObjectColor(m_hObject, r, g, b, fScale); return LTTRUE; } // See if it is time to create a new Particle puff... if ((fTime > m_fLastTime + m_fOffsetTime) && m_hServerObject) { LTVector vCurPos, vPos, vDelta, vTemp, vDriftVel, vColor; // Calculate Particle puff position... // Where is the server (moving) object... m_pClientDE->GetObjectPos(m_hServerObject, &vCurPos); // Current position is relative to the particle system's postion (i.e., // each puff of Particle is some distance away from the particle system's /// position)... m_pClientDE->GetObjectPos(m_hObject, &vTemp); VEC_SUB(vCurPos, vCurPos, vTemp); // How long has it been since the last Particle puff? LTFLOAT fTimeOffset = fTime - m_fLastTime; // What is the range of colors? LTFLOAT fRange = m_vColor2.x - m_vColor1.x; // Fill the distance between the last projectile position, and it's // current position with Particle puffs... int nNumSteps = (m_fLastTime > 0) ? (((m_nType & PT_BLOOD) || (m_nType & PT_GIBSMOKE)) ? 20 : 5): 1; if (nDetailLevel != RS_HIGH) { nNumSteps /= 2; } VEC_SUB(vTemp, vCurPos, m_vLastPos); VEC_MULSCALAR(vDelta, vTemp, 1.0f/float(nNumSteps)); VEC_COPY(vPos, m_vLastPos); LTFLOAT fCurLifeTime = 10.0f; if (nDetailLevel == RS_HIGH) { fCurLifeTime /= 2; } LTFLOAT fLifeTimeOffset = fTimeOffset / float(nNumSteps); LTFLOAT fOffset = 0.5f; int nNumPerPuff = GetNumParticles(m_nNumPerPuff); for (int i=0; i < nNumSteps; i++) { // Build the individual Particle puffs... for (int j=0; j < nNumPerPuff; j++) { VEC_COPY(vTemp, vPos); if (m_bIgnoreWind) { VEC_SET(vDriftVel, GetRandom(-m_vDriftOffset.x*2.0f, -m_vDriftOffset.x), GetRandom(5.0f, 6.0f), GetRandom(-m_vDriftOffset.z, m_vDriftOffset.z)); } else { VEC_SET(vDriftVel, g_vWorldWindVel.x + GetRandom(-m_vDriftOffset.x*2.0f, -m_vDriftOffset.x), g_vWorldWindVel.y + GetRandom(5.0f, 6.0f), g_vWorldWindVel.z + GetRandom(-m_vDriftOffset.z, m_vDriftOffset.z)); } vTemp.x += GetRandom(-fOffset, fOffset); vTemp.y += GetRandom(-fOffset, fOffset); vTemp.z += GetRandom(-fOffset, fOffset); GetRandomColorInRange(vColor); m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &vColor, fCurLifeTime); } VEC_ADD(vPos, vPos, vDelta); fCurLifeTime += fLifeTimeOffset; } m_fLastTime = fTime; VEC_COPY(m_vLastPos, vCurPos); } return LTTRUE; }