// // Test a line against a mesh // Selects the closest front-facing triangle // int CMesh::LineSelect( const CVec3 &LP1, const CVec3 &LP2 ) { CVec3 HitP; int nbHits = 0; int nSelTri = -1; float fDistance = 1000000000.0f; for (int nTri = 0; nTri < m_nbTris; nTri++ ) { if ( m_pTriFlags[ nTri ] & TF_BACKFACING ) continue; // Check only front facing triangles int nV = nTri*3; bool bHit = CheckLineTri( LP2, LP1, m_pVerts[ m_pTris[nV] ], m_pVerts[ m_pTris[nV+1] ], m_pVerts[ m_pTris[nV+2] ], HitP ); if ( bHit ) { if ( HitP.Distance( LP1 ) < fDistance ) { fDistance = HitP.Distance( LP1 ); nSelTri = nTri; } nbHits++; } } SelectTriangle( nSelTri ); return nbHits; }
void CControl::GetCorner( ECornerPosition type, float& x, float& y ) { CVec3 corner; switch ( type ) { case eCP_BottomLeft: corner = m_quadp.bl; break; case eCP_BottomRight: corner = m_quadp.br; break; case eCP_TopLeft: corner = m_quadp.tl; break; case eCP_TopRight: corner = m_quadp.tr; break; default: BEATS_ASSERT( false, _T("the error ECornerPosition") ); break; } corner.Transform( GetWorldTM()); x = corner.x; y = corner.y; }
CVertMeshViewer::CVertMeshViewer(UVertMesh* Mesh, CApplication* Window) : CMeshViewer(Mesh, Window) , AnimIndex(-1) { CVertMeshInstance *VertInst = new CVertMeshInstance(); VertInst->SetMesh(Mesh); Inst = VertInst; CVertMeshInstance *MeshInst = static_cast<CVertMeshInstance*>(Inst); // compute model center by Z-axis (vertical) CVec3 offset; const FBox &B = Mesh->BoundingBox; #if 1 VectorAdd(CVT(B.Min), CVT(B.Max), offset); offset.Scale(0.5f); MeshInst->BaseTransformScaled.TransformPointSlow(offset, offset); #else // scale/translate origin float z = (B.Max.Z + B.Min.Z) / 2; z = (z - Mesh->MeshOrigin.Z) * Mesh->MeshScale.Z; //!! bad formula offset.Set(0, 0, z); #endif offset[2] += Mesh->BoundingSphere.R / 20; // offset a bit up // offset view SetViewOffset(offset); // automatically scale view distance depending on model size float Radius = Mesh->BoundingSphere.R; if (Radius < 10) Radius = 10; SetDistScale(Mesh->MeshScale.X * Radius / 150); }
int main() { CVec3 a(.2,.5,.7); CVec3 b(-.2,-.2,.8); CVec3 c; c = a + b; a.print("a= "); b.print("b= "); c.print("a+b"); c = a - b; c.print("a-b"); c = b - a; c.print("b-a"); (a-b).print("inline a-b: "); CVec3 d = c + b - 3*c; (a^b).print("a^b" ); CVec3 dd = CVec3(.2,.6,.9) + a; testvec(CVec3(.2,.2,.2)+CVec3(.1,.1,.1)); testvec(dd^CVec3(.2,.3,.5)); testvec(dd += CVec3(.3, .7. .2)); return 0; }
void CShapeModule::InitParticleForCone(CVec3& localPos, CVec3& direction, float fParticleScale) const { CVec3 finalPos, finalDirection; float fClipAngle = m_fAngle; BEATS_CLIP_VALUE(fClipAngle, 0, 89.99f); float fRadius = m_fRadius * fParticleScale; float fConeLength = m_fConeLength * fParticleScale; float fTopRadius = fRadius + fConeLength * tanf(DegreesToRadians(fClipAngle)); CVec3 randomDirection(PARTICLE_RAND_RANGE(-1, 1), PARTICLE_RAND_RANGE(-1, 1), 0); randomDirection.Normalize(); float fRadiusOnBase = m_bEmitFromShell ? fRadius : PARTICLE_RAND_RANGE(0, fRadius); finalPos = randomDirection * fRadiusOnBase; BEATS_ASSERT(!BEATS_FLOAT_EQUAL(fRadius, 0)); fTopRadius *= (fRadiusOnBase / fRadius); CVec3 topPos = (m_bRandomDirection ? GetRandomDirection() : randomDirection) * fTopRadius; topPos.Z() = fConeLength; finalDirection = topPos - finalPos; if (!m_bEmitFromBaseOrVolume) { finalPos += (finalDirection * PARTICLE_RAND_RANGE(0, 1)); if (m_bRandomDirection) { finalDirection = GetRandomDirection(); } } finalDirection.Normalize(); localPos = finalPos; direction = finalDirection; }
void S4r::Simulation::GetFields(const Vec3 &r, CVec3 &E, CVec3 &H){ if(0 == layers.size()){ // no layers E.setZero(); H.setZero(); } size_t ilayer = 0; double dz = r[2]; { double z = 0; double t = layers[ilayer]->description.thickness; while(r[2] > z + t){ z += t; dz -= t; if(ilayer+1 >= layers.size()){ break; } ilayer++; t = layers[ilayer]->description.thickness; } } //fprintf(stderr, "(%f,%f,%f) in %s: dz = %f\n", r[0], r[1], r[2], L->name, dz); SolveLayer(ilayer); CVec2 phi = GetBlochPhaseFactors(); layers[ilayer]->GetFields(omega, mesh, phi, Vec3(r[0], r[1], dz), E, H); }
CVec3 CVec3::interpolateTo(const CVec3 &other, float fraction) const { static CVec3 dir; dir.set(other); dir -= *(this); return (*this) + dir * fraction; }
CVec3 CVec3::project(CVec3 normal) const { float inv_denom = 1.0f / normal.dot(normal); float d = normal.dot((*this)) * inv_denom; CVec3 vec = normal * inv_denom; return (*this) - vec * d; }
// // returns true if line (L1, L2) intersects with triangle( PV1, PV2, PV3 ) // The point of intersection is returned in HitP // bool CheckLineTri( const CVec3 &L1, const CVec3 &L2, const CVec3 &PV1, const CVec3 &PV2, const CVec3 &PV3, CVec3 &HitP ) { CVec3 VIntersect; // Find Triangle Normal, would be quicker to have these computed already CVec3 VNorm; VNorm = ( PV2 - PV1 ).CrossProduct( PV3 - PV1 ); VNorm.Normalize(); // Find distance from L1 and L2 to the plane defined by the triangle float fDst1 = (L1-PV1).Dot( VNorm ); float fDst2 = (L2-PV1).Dot( VNorm ); if ( (fDst1 * fDst2) >= 0.0f) return false; // line doesn't cross the triangle. if ( fDst1 == fDst2) {return false;} // line and plane are parallel // Find point on the line that intersects with the plane VIntersect = L1 + (L2-L1) * ( -fDst1/(fDst2-fDst1) ); // Find if the interesection point lies inside the triangle by testing it against all edges CVec3 VTest; VTest = VNorm.CrossProduct( PV2-PV1 ); if ( VTest.Dot( VIntersect-PV1 ) < 0.0f ) return false; VTest = VNorm.CrossProduct( PV3-PV2 ); if ( VTest.Dot( VIntersect-PV2 ) < 0.0f ) return false; VTest = VNorm.CrossProduct( PV1-PV3 ); if ( VTest.Dot( VIntersect-PV1 ) < 0.0f ) return false; HitP = VIntersect; return true; }
/////////////////////////////////////////////////////////////////////////////// // _Indirect_irradiance // Estimate the in-direction irradiance (diffuse) /////////////////////////////////////////////////////////////////////////////// CCol4 CMcBspTR::_Indirect_irradiance (const TBspCross &crs, int nPID, int nDepth) { CCol4 cAccu = COLOR_BLACK; CBspMaterial *pm = &m_pMaterials[m_pTriangles[nPID].GetMaterialID()]; if (m_nDistrRayNum <= 0) return cAccu; //------------------------------------------------------------------------- // If it is the first hit, we would need to estimate the indirect // illumination accurately. //------------------------------------------------------------------------- if (nDepth == 0) { int nAccu = 0; BOOL bHitLig; TBspRay ray; // The local frame CVec3 vZ = crs.vNml.Normalized(); CVec3 vY = RANDOM_VEC; CVec3 vX = (vY.Cross(vZ)).Normalized(); vY = vZ.Cross(vX); // The inclination and azimuth resolution int m = (int) sqrt((double)(m_nDistrRayNum>>2)); int n = m_nDistrRayNum / m; // Evenly distribute the sampling ray on the hemi-sphere according to // the inclination angle for (int i = 1; i <= n; i ++) { for (int j = 1; j <= m; j ++) { float fTheta = (float)asin(sqrt((j-RANDOM_0_1)/m)); float fPhi = 2 * PI * (i-RANDOM_0_1)/n; ray.vDir = vY * sin (fPhi) + vX * cos (fPhi); ray.vDir = vZ * sin (fTheta) + ray.vDir * cos (fTheta); ray.vOrg = crs.vPos; ray.vEnd = ray.vOrg + ray.vDir * m_fSceneSize; CCol4 cTemp = _PM_radiance_along_the_ray (ray, nPID, bHitLig); if (!bHitLig) { cAccu += cTemp; nAccu ++; } } } cAccu = cAccu * PI / nAccu; // cAccu = cAccu / nAccu; }
//////////////////////////////////////////////////////////////////////////////////// // Update - Changes wind when current target velocity expires //////////////////////////////////////////////////////////////////////////////////// void Update() { if (mTargetVelocityTimeRemaining==0) { if (FloatRand()<mChanceOfDeadTime) { mRDeadTime.Pick(mTargetVelocityTimeRemaining); mTargetVelocity.Clear(); } else { mRDuration.Pick(mTargetVelocityTimeRemaining); mRVelocity.Pick(mTargetVelocity); } } else if (mTargetVelocityTimeRemaining!=-1) { mTargetVelocityTimeRemaining--; CVec3 DeltaVelocity(mTargetVelocity - mCurrentVelocity); float DeltaVelocityLen = VectorNormalize(DeltaVelocity.v); if (DeltaVelocityLen > mMaxDeltaVelocityPerUpdate) { DeltaVelocityLen = mMaxDeltaVelocityPerUpdate; } DeltaVelocity *= (DeltaVelocityLen); mCurrentVelocity += DeltaVelocity; } }
void CShapeModule::InitParticleForBox(CVec3& localPos, CVec3& direction, float fParticleScale) const { CVec3 halfSize = m_boxSize * 0.5f * fParticleScale; localPos.Fill(RANGR_RANDOM_FLOAT(-halfSize.X(), halfSize.X()), RANGR_RANDOM_FLOAT(-halfSize.Y(), halfSize.Y()), RANGR_RANDOM_FLOAT(-halfSize.Z(), halfSize.Z())); direction = CVec3(0, 0, 1); if (m_bRandomDirection) { direction = GetRandomDirection(); } }
//////////////////////////////////////////////////////////////////////////////////// // Initialize - Will setup default values for all data //////////////////////////////////////////////////////////////////////////////////// void Initialize() { mRBounds.Clear(); mGlobal = true; mRVelocity.mMins = -1500.0f; mRVelocity.mMins[2] = -10.0f; mRVelocity.mMaxs = 1500.0f; mRVelocity.mMaxs[2] = 10.0f; mMaxDeltaVelocityPerUpdate = 10.0f; mRDuration.mMin = 1000; mRDuration.mMax = 2000; mChanceOfDeadTime = 0.3f; mRDeadTime.mMin = 1000; mRDeadTime.mMax = 3000; mCurrentVelocity.Clear(); mTargetVelocity.Clear(); mTargetVelocityTimeRemaining = 0; }
//////////////////////////////////////////////////////////////////////////////////////// // Line Intersects Circle (True/False) // // r - Radius Of The Circle // A - Start Of Line Segment // B - End Of Line Segment // // P - Projected Position Of Origin Onto Line AB // // // B // / // / // P // / \ \ // / this-r->| // / / // A // //////////////////////////////////////////////////////////////////////////////////////// bool CVec3::LineInCircle(const CVec3 &A, const CVec3 &B, float r, CVec3 &P) { P = (*this); float Scale = P.ProjectToLine(A, B); // If The Projected Position Is Not On The Line Segment, // Check If It Is Within Radius Of Endpoints A and B. //------------------------------------------------------- if (Scale<0 || Scale>1) { return (PtInCircle(A, r) || PtInCircle(B, r)); } // Otherwise, Check To See If P Is Within The Radius Of This Circle //------------------------------------------------------------------ return (PtInCircle(P, r)); }
float CVec3::distanceSquared(const CVec3 &other) const { CVec3 d = other - *this; return d.lengthSquared(); }
CVec4::CVec4(const CVec3& vec3, float w) { Fill(vec3.X(), vec3.Y(), vec3.Z(), w); }
CVec3::CVec3(CVec3& vec) { this->vec[0] = vec.x(); this->vec[1] = vec.y(); this->vec[2] = vec.z(); }
void USkeleton::ConvertAnims(UAnimSequence4* Seq) { guard(USkeleton::ConvertAnims); CAnimSet* AnimSet = ConvertedAnim; if (!AnimSet) { AnimSet = new CAnimSet(this); ConvertedAnim = AnimSet; // Copy bone names AnimSet->TrackBoneNames.Empty(ReferenceSkeleton.RefBoneInfo.Num()); for (int i = 0; i < ReferenceSkeleton.RefBoneInfo.Num(); i++) { AnimSet->TrackBoneNames.Add(ReferenceSkeleton.RefBoneInfo[i].Name); } //TODO: verify if UE4 has AnimRotationOnly stuff AnimSet->AnimRotationOnly = false; } if (!Seq) return; // allow calling ConvertAnims(NULL) to create empty AnimSet // DBG("----------- Skeleton %s: %d seq, %d bones -----------\n", Name, Anims.Num(), ReferenceSkeleton.RefBoneInfo.Num()); int NumTracks = Seq->GetNumTracks(); #if DEBUG_DECOMPRESS appPrintf("Sequence %s: %d bones, %d offsets (%g per bone), %d frames, %d compressed data\n" " trans %s, rot %s, scale %s, key %s\n", Seq->Name, NumTracks, Seq->CompressedTrackOffsets.Num(), Seq->CompressedTrackOffsets.Num() / (float)NumTracks, Seq->NumFrames, Seq->CompressedByteStream.Num(), EnumToName(Seq->TranslationCompressionFormat), EnumToName(Seq->RotationCompressionFormat), EnumToName(Seq->ScaleCompressionFormat), EnumToName(Seq->KeyEncodingFormat) ); for (int i2 = 0; i2 < Seq->CompressedTrackOffsets.Num(); /*empty*/) { if (Seq->KeyEncodingFormat != AKF_PerTrackCompression) { FName BoneName = ReferenceSkeleton.RefBoneInfo[Seq->GetTrackBoneIndex(i2/4)].Name; int TransOffset = Seq->CompressedTrackOffsets[i2 ]; int TransKeys = Seq->CompressedTrackOffsets[i2+1]; int RotOffset = Seq->CompressedTrackOffsets[i2+2]; int RotKeys = Seq->CompressedTrackOffsets[i2+3]; appPrintf(" [%d] = trans %d[%d] rot %d[%d] - %s\n", i2/4, TransOffset, TransKeys, RotOffset, RotKeys, *BoneName); i2 += 4; } else { FName BoneName = ReferenceSkeleton.RefBoneInfo[Seq->GetTrackBoneIndex(i2/2)].Name; int TransOffset = Seq->CompressedTrackOffsets[i2 ]; int RotOffset = Seq->CompressedTrackOffsets[i2+1]; appPrintf(" [%d] = trans %d rot %d - %s\n", i2/2, TransOffset, RotOffset, *BoneName); i2 += 2; } } #endif // DEBUG_DECOMPRESS // some checks int offsetsPerBone = 4; if (Seq->KeyEncodingFormat == AKF_PerTrackCompression) offsetsPerBone = 2; if (Seq->CompressedTrackOffsets.Num() != NumTracks * offsetsPerBone && !Seq->RawAnimationData.Num()) { appNotify("AnimSequence %s has wrong CompressedTrackOffsets size (has %d, expected %d), removing track", Seq->Name, Seq->CompressedTrackOffsets.Num(), NumTracks * offsetsPerBone); return; } // create CAnimSequence CAnimSequence *Dst = new CAnimSequence; AnimSet->Sequences.Add(Dst); Dst->Name = Seq->Name; Dst->NumFrames = Seq->NumFrames; Dst->Rate = Seq->NumFrames / Seq->SequenceLength * Seq->RateScale; // bone tracks ... Dst->Tracks.Empty(NumTracks); FMemReader Reader(Seq->CompressedByteStream.GetData(), Seq->CompressedByteStream.Num()); Reader.SetupFrom(*Package); bool HasTimeTracks = (Seq->KeyEncodingFormat == AKF_VariableKeyLerp); for (int BoneIndex = 0; BoneIndex < ReferenceSkeleton.RefBoneInfo.Num(); BoneIndex++) { CAnimTrack *A = new (Dst->Tracks) CAnimTrack; int TrackIndex = Seq->FindTrackForBoneIndex(BoneIndex); if (TrackIndex < 0) { // this track has no animation, use static pose from ReferenceSkeleton const FTransform& RefPose = ReferenceSkeleton.RefBonePose[BoneIndex]; A->KeyPos.Add(CVT(RefPose.Translation)); A->KeyQuat.Add(CVT(RefPose.Rotation)); //!! RefPose.Scale3D continue; } int k; if (!Seq->CompressedTrackOffsets.Num()) //?? or if RawAnimData.Num() != 0 { // using RawAnimData array assert(Seq->RawAnimationData.Num() == NumTracks); CopyArray(A->KeyPos, CVT(Seq->RawAnimationData[TrackIndex].PosKeys)); CopyArray(A->KeyQuat, CVT(Seq->RawAnimationData[TrackIndex].RotKeys)); CopyArray(A->KeyTime, Seq->RawAnimationData[TrackIndex].KeyTimes); // may be empty for (int k = 0; k < A->KeyTime.Num(); k++) A->KeyTime[k] *= Dst->Rate; continue; } FVector Mins, Ranges; // common ... static const CVec3 nullVec = { 0, 0, 0 }; static const CQuat nullQuat = { 0, 0, 0, 1 }; int offsetIndex = TrackIndex * offsetsPerBone; // PARAGON has invalid data inside some animation tracks. Not sure if game engine ignores them // or trying to process (this game has holes in data due to wrong pointers in CompressedTrackOffsets). // This causes garbage data to appear instead of real animation track header, with wrong compression // method etc. We're going to skip such tracks with displaying a warning message. if (0) // this is just a placeholder for error handler - it should be located somewhere { track_error: AnimSet->Sequences.RemoveSingle(Dst); delete Dst; return; } //---------------------------------------------- // decode AKF_PerTrackCompression data //---------------------------------------------- if (Seq->KeyEncodingFormat == AKF_PerTrackCompression) { // this format uses different key storage guard(PerTrackCompression); assert(Seq->TranslationCompressionFormat == ACF_Identity); assert(Seq->RotationCompressionFormat == ACF_Identity); int TransOffset = Seq->CompressedTrackOffsets[offsetIndex ]; int RotOffset = Seq->CompressedTrackOffsets[offsetIndex+1]; uint32 PackedInfo; AnimationCompressionFormat KeyFormat; int ComponentMask; int NumKeys; #define DECODE_PER_TRACK_INFO(info) \ KeyFormat = (AnimationCompressionFormat)(info >> 28); \ ComponentMask = (info >> 24) & 0xF; \ NumKeys = info & 0xFFFFFF; \ HasTimeTracks = (ComponentMask & 8) != 0; guard(TransKeys); // read translation keys if (TransOffset == -1) { A->KeyPos.Add(nullVec); DBG(" [%d] no translation data\n", TrackIndex); } else { Reader.Seek(TransOffset); Reader << PackedInfo; DECODE_PER_TRACK_INFO(PackedInfo); A->KeyPos.Empty(NumKeys); DBG(" [%d] trans: fmt=%d (%s), %d keys, mask %d\n", TrackIndex, KeyFormat, EnumToName(KeyFormat), NumKeys, ComponentMask ); if (KeyFormat == ACF_IntervalFixed32NoW) { // read mins/maxs Mins.Set(0, 0, 0); Ranges.Set(0, 0, 0); if (ComponentMask & 1) Reader << Mins.X << Ranges.X; if (ComponentMask & 2) Reader << Mins.Y << Ranges.Y; if (ComponentMask & 4) Reader << Mins.Z << Ranges.Z; } for (k = 0; k < NumKeys; k++) { switch (KeyFormat) { // case ACF_None: case ACF_Float96NoW: { FVector v; if (ComponentMask & 7) { v.Set(0, 0, 0); if (ComponentMask & 1) Reader << v.X; if (ComponentMask & 2) Reader << v.Y; if (ComponentMask & 4) Reader << v.Z; } else { // ACF_Float96NoW has a special case for ((ComponentMask & 7) == 0) Reader << v; } A->KeyPos.Add(CVT(v)); } break; TPR(ACF_IntervalFixed32NoW, FVectorIntervalFixed32) case ACF_Fixed48NoW: { uint16 X, Y, Z; CVec3 v; v.Set(0, 0, 0); if (ComponentMask & 1) { Reader << X; v[0] = DecodeFixed48_PerTrackComponent<7>(X); } if (ComponentMask & 2) { Reader << Y; v[1] = DecodeFixed48_PerTrackComponent<7>(Y); } if (ComponentMask & 4) { Reader << Z; v[2] = DecodeFixed48_PerTrackComponent<7>(Z); } A->KeyPos.Add(v); } break; case ACF_Identity: A->KeyPos.Add(nullVec); break; default: { char buf[1024]; Seq->GetFullName(buf, 1024); appNotify("%s: unknown translation compression method: %d (%s) - dropping track", buf, KeyFormat, EnumToName(KeyFormat)); goto track_error; } } } // align to 4 bytes Reader.Seek(Align(Reader.Tell(), 4)); if (HasTimeTracks) ReadTimeArray(Reader, NumKeys, A->KeyPosTime, Seq->NumFrames); } unguard; guard(RotKeys); // read rotation keys if (RotOffset == -1) { A->KeyQuat.Add(nullQuat); DBG(" [%d] no rotation data\n", TrackIndex); } else { Reader.Seek(RotOffset); Reader << PackedInfo; DECODE_PER_TRACK_INFO(PackedInfo); A->KeyQuat.Empty(NumKeys); DBG(" [%d] rot : fmt=%d (%s), %d keys, mask %d\n", TrackIndex, KeyFormat, EnumToName(KeyFormat), NumKeys, ComponentMask ); if (KeyFormat == ACF_IntervalFixed32NoW) { // read mins/maxs Mins.Set(0, 0, 0); Ranges.Set(0, 0, 0); if (ComponentMask & 1) Reader << Mins.X << Ranges.X; if (ComponentMask & 2) Reader << Mins.Y << Ranges.Y; if (ComponentMask & 4) Reader << Mins.Z << Ranges.Z; } for (k = 0; k < NumKeys; k++) { switch (KeyFormat) { // TR (ACF_None, FQuat) case ACF_Float96NoW: { FQuatFloat96NoW q; Reader << q; FQuat q2 = q; // convert A->KeyQuat.Add(CVT(q2)); } break; case ACF_Fixed48NoW: { FQuatFixed48NoW q; q.X = q.Y = q.Z = 32767; // corresponds to 0 if (ComponentMask & 1) Reader << q.X; if (ComponentMask & 2) Reader << q.Y; if (ComponentMask & 4) Reader << q.Z; FQuat q2 = q; // convert A->KeyQuat.Add(CVT(q2)); } break; TR (ACF_Fixed32NoW, FQuatFixed32NoW) TRR(ACF_IntervalFixed32NoW, FQuatIntervalFixed32NoW) TR (ACF_Float32NoW, FQuatFloat32NoW) case ACF_Identity: A->KeyQuat.Add(nullQuat); break; default: { char buf[1024]; Seq->GetFullName(buf, 1024); appNotify("%s: unknown rotation compression method: %d (%s) - dropping track", buf, KeyFormat, EnumToName(KeyFormat)); goto track_error; } } } // align to 4 bytes Reader.Seek(Align(Reader.Tell(), 4)); if (HasTimeTracks) ReadTimeArray(Reader, NumKeys, A->KeyQuatTime, Seq->NumFrames); } unguard; unguard; continue; // end of AKF_PerTrackCompression block ... } //---------------------------------------------- // end of AKF_PerTrackCompression decoder //---------------------------------------------- // read animations int TransOffset = Seq->CompressedTrackOffsets[offsetIndex ]; int TransKeys = Seq->CompressedTrackOffsets[offsetIndex+1]; int RotOffset = Seq->CompressedTrackOffsets[offsetIndex+2]; int RotKeys = Seq->CompressedTrackOffsets[offsetIndex+3]; // appPrintf("[%d:%d:%d] : %d[%d] %d[%d] %d[%d]\n", j, Seq->RotationCompressionFormat, Seq->TranslationCompressionFormat, TransOffset, TransKeys, RotOffset, RotKeys, ScaleOffset, ScaleKeys); A->KeyPos.Empty(TransKeys); A->KeyQuat.Empty(RotKeys); // read translation keys if (TransKeys) { Reader.Seek(TransOffset); AnimationCompressionFormat TranslationCompressionFormat = Seq->TranslationCompressionFormat; if (TransKeys == 1) TranslationCompressionFormat = ACF_None; // single key is stored without compression // read mins/ranges if (TranslationCompressionFormat == ACF_IntervalFixed32NoW) { Reader << Mins << Ranges; } for (k = 0; k < TransKeys; k++) { switch (TranslationCompressionFormat) { TP (ACF_None, FVector) TP (ACF_Float96NoW, FVector) TPR(ACF_IntervalFixed32NoW, FVectorIntervalFixed32) TP (ACF_Fixed48NoW, FVectorFixed48) case ACF_Identity: A->KeyPos.Add(nullVec); break; default: appError("Unknown translation compression method: %d (%s)", TranslationCompressionFormat, EnumToName(TranslationCompressionFormat)); } } // align to 4 bytes Reader.Seek(Align(Reader.Tell(), 4)); if (HasTimeTracks) ReadTimeArray(Reader, TransKeys, A->KeyPosTime, Seq->NumFrames); } else { // A->KeyPos.Add(nullVec); // appNotify("No translation keys!"); }
//void testvec(CVec3& a) //{ //a.print("inside testvec CVec3&, a= "); //} void testvec(CVec3 a) { a.print("inside testvec CVec3, a= "); }
inline void TransformPosition(CVec3& pos) { Exchange(pos[1], pos[2]); pos.Scale(0.01f); }
static void SV_ClipMoveToEntities(trace_t &trace, const CVec3 &start, const CVec3 &end, const CBox &bounds, edict_t *passedict, int contentmask) { guard(SV_ClipMoveToEntities); if (trace.allsolid) return; int i; CVec3 amins, amaxs; for (i = 0; i < 3; i++) { if (start[i] < end[i]) { amins[i] = bounds.mins[i] + start[i]; amaxs[i] = bounds.maxs[i] + end[i]; } else { amins[i] = bounds.mins[i] + end[i]; amaxs[i] = bounds.maxs[i] + start[i]; } } edict_t *list[MAX_EDICTS]; int num = SV_AreaEdicts(amins, amaxs, ARRAY_ARG(list), AREA_SOLID); if (!num) return; float b1 = dot(bounds.mins, bounds.mins); float b2 = dot(bounds.maxs, bounds.maxs); float t = max(b1, b2); float traceWidth = SQRTFAST(t); CVec3 traceDir; VectorSubtract(end, start, traceDir); float traceLen = traceDir.Normalize() + traceWidth; for (i = 0; i < num; i++) { edict_t *edict = list[i]; entityHull_t &ent = ents[NUM_FOR_EDICT(edict)]; // if (!ent->linked) continue; if (edict->solid == SOLID_NOT || edict == passedict) continue; if (passedict) { if (edict->owner == passedict) continue; // don't clip against own missiles if (passedict->owner == edict) continue; // don't clip against owner } if (!(contentmask & CONTENTS_DEADMONSTER) && (edict->svflags & SVF_DEADMONSTER)) continue; CVec3 eCenter; VectorSubtract(ent.center, start, eCenter); // check position of point projection on line float entPos = dot(eCenter, traceDir); if (entPos < -traceWidth - ent.radius || entPos > traceLen + ent.radius) continue; // too near / too far // check distance between point and line CVec3 tmp; VectorMA(eCenter, -entPos, traceDir, tmp); float dist2 = dot(tmp, tmp); float dist0 = ent.radius + traceWidth; if (dist2 >= dist0 * dist0) continue; trace_t tr; if (ent.model) CM_TransformedBoxTrace(tr, start, end, bounds, ent.model->headnode, contentmask, edict->s.origin, ent.axis); else CM_TransformedBoxTrace(tr, start, end, bounds, CM_HeadnodeForBox(ent.bounds), contentmask, edict->s.origin, nullVec3); if (CM_CombineTrace(trace, tr)) trace.ent = edict; if (trace.allsolid) return; } unguard; }
inline void Clear() { mMins.Clear(); mMaxs.Clear(); }
/////////////////////////////////////////////////////////////////////////////// // _Create_caustic_photonmap // Build the caustic photon map after the creation of global photon map /////////////////////////////////////////////////////////////////////////////// void CMcBspTR::_Create_caustic_photonmap(void) { int i, j; CCol4 cCurrPow; int nStored = 0; TBspRay ray; float fLen; printf("\nBuilding caustic photon map ...\n"); TCausDir *p = m_tCausDir.next; for (i = 0; i < m_nCausDir; i ++) { printf ("."); CCol4 cPow = m_tpLigPatches[p->nLID].cPhotonPow / m_nCauPhoSubd * 5; if (m_bDirectionalLight) { CBspTriangle *tri = &m_pTriangles[m_tpLigPatches[p->nLID].nTID]; fLen = sqrt(tri->Calc_area() / m_tpLigPatches[p->nLID].nPhotonNum); CVec3 vZ = tri->Calc_normal(); CVec3 vY = RANDOM_VEC; CVec3 vX = vY.Cross(vZ); vX.Normalize(); vY = vZ.Cross(vX); vX *= fLen; vY *= fLen; for (j = 0; j < m_nCauPhoSubd; j ++) { ray.vOrg = p->vPos + vX * RANDOM_N1_P1 + vY * RANDOM_N1_P1; ray.vDir = p->vDir; ray.vEnd = ray.vOrg + ray.vDir * m_fSceneSize; _Trace_caustic_photon (ray, cPow, m_tpLigPatches[p->nLID].nTID, nStored); } } else { double fCos = cos(PI/sqrt(m_tpLigPatches[p->nLID].nPhotonNum*4.)); fLen = 2.f * (float) tan( acos(fCos) ); for (j = 0; j < m_nCauPhoSubd; j ++) { ray.vOrg = p->vPos; ray.vDir = p->vDir + (RANDOM_VEC * fLen); ray.vDir.Normalize(); ray.vEnd = ray.vOrg + ray.vDir * m_fSceneSize; _Trace_caustic_photon (ray, cPow, m_tpLigPatches[p->nLID].nTID, nStored); } } m_tCausDir.next = p->next; delete p; p = m_tCausDir.next; } m_tCausDir.next = NULL; // Balance photon map kd-tree printf("\n Balance KD tree"); m_pCausticPhotonMap->balance(); printf("\nFinish building caustic photon map, %d photons stored\n", nStored); }
sizebuf_t *SV_MulticastHook(sizebuf_t *original, sizebuf_t *ext) { CVec3 v1, v2; const char *s; guard(SV_MulticastHook); original->BeginReading(); // check for interesting messages if (MSG_ReadByte(original) != svc_temp_entity) return original; ext->Clear(); byte cmd = MSG_ReadByte(original); switch (cmd) { case TE_RAILTRAIL: { MSG_ReadPos(original, v1); // start MSG_ReadPos(original, v2); // end client_t *cl = FindClient(v1, 18*18); int rType = 1; int rColor = 0; if (cl) { if (s = Info_ValueForKey(cl->Userinfo, "railcolor")) { rColor = atoi(s); rColor = bound(rColor, 0, 7); } if (s = Info_ValueForKey(cl->Userinfo, "railtype")) { rType = atoi(s); rType = bound(rType, 0, 3); } } if (!rType) return original; // type==0 -> original rail trail MSG_WriteByte(ext, svc_temp_entity); MSG_WriteByte(ext, TE_RAILTRAIL_EXT); MSG_WritePos(ext, v1); MSG_WritePos(ext, v2); MSG_WriteByte(ext, rColor); MSG_WriteByte(ext, rType); } return ext; case TE_GUNSHOT: case TE_SPARKS: case TE_BULLET_SPARKS: { if (shotLevel != 2) return original; MSG_ReadPos(original, v1); MSG_ReadDir(original, v2); // compute reflection vector // appPrintf("sp: (%g %g %g) -> (%g %g %g)\n",VECTOR_ARG(v1),VECTOR_ARG(v2));//!! CVec3 d; VectorSubtract(shotStart, shotEnd, d); d.NormalizeFast(); float back = dot(d, v2); for (int i = 0; i < 3; i++) v2[i] = d[i] - 2 * (d[i] - back * v2[i]); MSG_WriteByte(ext, svc_temp_entity); MSG_WriteByte(ext, cmd); MSG_WritePos(ext, v1); MSG_WriteDir(ext, v2); } return ext; case TE_SPLASH: { int count = MSG_ReadByte(original); MSG_ReadPos(original, v1); // pos int tmp = MSG_ReadByte(original); // dir int type = MSG_ReadByte(original); if (type != SPLASH_BLUE_WATER && type != SPLASH_BROWN_WATER) return original; // not bullet effect // find splash origin in static map splashes to avoid bullethit sounds for waterfalls etc. for (const originInfo_t *spl = bspfile.splashes; spl; spl = spl->next) { if (fabs(spl->origin[0] - v1[0]) < 1 && fabs(spl->origin[1] - v1[1]) < 1 && fabs(spl->origin[2] - v1[2]) < 1) // dir is quantized, so - make inprecisious compare return original; } //?? can add ripple effect on water, water smoke MSG_WriteByte(ext, svc_temp_entity); MSG_WriteByte(ext, TE_SPLASH); MSG_WriteByte(ext, count); MSG_WritePos(ext, v1); MSG_WriteByte(ext, tmp); MSG_WriteByte(ext, type - SPLASH_BLUE_WATER + SPLASH_BULLET_BLUE_WATER); } return ext; } return original; unguard; }
void UVertMesh::BuildNormals() { // UE1 meshes have no stored normals, should build them // This function is similar to BuildNormals() from SkelMeshInstance.cpp int numVerts = Verts.Num(); int i; Normals.Empty(numVerts); Normals.AddZeroed(numVerts); TArray<CVec3> tmpVerts, tmpNormals; tmpVerts.AddZeroed(numVerts); tmpNormals.AddZeroed(numVerts); // convert verts for (i = 0; i < numVerts; i++) { const FMeshVert &SV = Verts[i]; CVec3 &DV = tmpVerts[i]; DV[0] = SV.X * MeshScale.X; DV[1] = SV.Y * MeshScale.Y; DV[2] = SV.Z * MeshScale.Z; } // iterate faces for (i = 0; i < Faces.Num(); i++) { const FMeshFace &F = Faces[i]; // get vertex indices int i1 = Wedges[F.iWedge[0]].iVertex; int i2 = Wedges[F.iWedge[2]].iVertex; // note: reverse order in comparison with SkeletalMesh int i3 = Wedges[F.iWedge[1]].iVertex; // iterate all frames for (int j = 0; j < FrameCount; j++) { int base = VertexCount * j; // compute edges const CVec3 &V1 = tmpVerts[base + i1]; const CVec3 &V2 = tmpVerts[base + i2]; const CVec3 &V3 = tmpVerts[base + i3]; CVec3 D1, D2, D3; VectorSubtract(V2, V1, D1); VectorSubtract(V3, V2, D2); VectorSubtract(V1, V3, D3); // compute normal CVec3 norm; cross(D2, D1, norm); norm.Normalize(); // compute angles D1.Normalize(); D2.Normalize(); D3.Normalize(); float angle1 = acos(-dot(D1, D3)); float angle2 = acos(-dot(D1, D2)); float angle3 = acos(-dot(D2, D3)); // add normals for triangle verts VectorMA(tmpNormals[base + i1], angle1, norm); VectorMA(tmpNormals[base + i2], angle2, norm); VectorMA(tmpNormals[base + i3], angle3, norm); } } // normalize and convert computed normals for (i = 0; i < numVerts; i++) { CVec3 &SN = tmpNormals[i]; FMeshNorm &DN = Normals[i]; SN.Normalize(); DN.X = appRound(SN[0] * 511 + 512); DN.Y = appRound(SN[1] * 511 + 512); DN.Z = appRound(SN[2] * 511 + 512); } }
/////////////////////////////////////////////////////////////////////////////// // _Direct_lighting // Calculate the radiance directly come from light sources /////////////////////////////////////////////////////////////////////////////// CCol4 CMcBspTR::_Direct_lighting (const CVec3 &vPos, const CVec3 &vNml, const CVec3 &vView, const CVec3 &vTex, int PID) { int l; TBspRay ray; TBspCross crs; CBspMaterial *pm; CCol4 cRsl = COLOR_BLACK; pm = &m_pMaterials[m_pTriangles[PID].GetMaterialID()]; if (m_bDirectionalLight) { ray.vOrg = vPos; ray.vDir = m_vLightDir; ray.vEnd = ray.vOrg + ray.vDir * m_fSceneSize; if (ray.vDir.Dot(vNml) < 0.f) return cRsl; int PID2 = PID; if (_RayTreeIntersect (ray, crs, PID2)) { if (!_Is_light_patch(PID2)) return cRsl; cRsl = G_theSahder.PhongShading (m_cLightColor, ray.vDir, vView*(-1), vPos, vNml, vTex.at(0), vTex.at(1), pm); } return cRsl; } for (l = 0; l < m_nLigPatches; l ++) { //--------------------------------------------------------------------- // construct a ray point to a random point on the selected light patch //--------------------------------------------------------------------- CBspTriangle *tri = &m_pTriangles[m_tpLigPatches[l].nTID]; ray.vEnd = tri->Random_point_on_the_triangle(); ray.vOrg = vPos; ray.vDir = ray.vEnd - vPos; ray.vDir.Normalize(); ray.vEnd += ray.vDir; // extend the ray a little bit //--------------------------------------------------------------------- // If the patch does not facing the light patch or the light patch dose // not facing the patch, return black; //--------------------------------------------------------------------- if (ray.vDir.Dot(vNml) < 0.f) continue; float fDirectionalScale = m_tpLigPatches[l].vNml.Dot(ray.vDir); if (fDirectionalScale > 0.f) continue; else fDirectionalScale = -fDirectionalScale; //--------------------------------------------------------------------- // Check if the light is occluded by another patch // Calculate the shading by phong model if is lit //--------------------------------------------------------------------- int PID2 = PID; if (_RayTreeIntersect (ray, crs, PID2)) { if (PID2 == m_tpLigPatches[l].nTID) { // Calculate the lighting intensity according to the the // distance and the intensity of the light patch. CVec3 vTemp = crs.vPos - vPos; //float fTemp = vTemp.Dot(vTemp) * 4 * PI; float fTemp = vTemp.Dot(vTemp) * PI; CCol4 cIntensity = m_tpLigPatches[l].cEnergy * fDirectionalScale / fTemp; // Shading computation by Phong model. cRsl += G_theSahder.PhongShading (cIntensity, ray.vDir, vView*(-1), vPos, vNml, vTex[0], vTex[1], pm); } } } return cRsl; }
void Pilot_Steer_Vehicle() { if (!NPC->enemy || !NPC->enemy->client) { return; } // SETUP //======= // Setup Actor Data //------------------ CVec3 ActorPos(NPC->currentOrigin); CVec3 ActorAngles(NPC->currentAngles); ActorAngles[2] = 0; Vehicle_t* ActorVeh = NPCInfo->greetEnt->m_pVehicle; bool ActorInTurbo = (ActorVeh->m_iTurboTime>level.time); float ActorSpeed = (ActorVeh)?(VectorLength(ActorVeh->m_pParentEntity->client->ps.velocity)):(NPC->client->ps.speed); // If my vehicle is spinning out of control, just hold on, we're going to die!!!!! //--------------------------------------------------------------------------------- if (ActorVeh && (ActorVeh->m_ulFlags & VEH_OUTOFCONTROL)) { if (NPC->client->ps.weapon!=WP_NONE) { NPC_ChangeWeapon(WP_NONE); } ucmd.buttons &=~BUTTON_ATTACK; ucmd.buttons &=~BUTTON_ALT_ATTACK; return; } CVec3 ActorDirection; AngleVectors(ActorAngles.v, ActorDirection.v, 0, 0); CVec3 ActorFuturePos(ActorPos); ActorFuturePos.ScaleAdd(ActorDirection, FUTURE_PRED_DIST); bool ActorDoTurbo = false; bool ActorAccelerate = false; bool ActorAimAtTarget= true; float ActorYawOffset = 0.0f; // Setup Enemy Data //------------------ CVec3 EnemyPos(NPC->enemy->currentOrigin); CVec3 EnemyAngles(NPC->enemy->currentAngles); EnemyAngles[2] = 0; Vehicle_t* EnemyVeh = (NPC->enemy->s.m_iVehicleNum)?(g_entities[NPC->enemy->s.m_iVehicleNum].m_pVehicle):(0); bool EnemyInTurbo = (EnemyVeh && EnemyVeh->m_iTurboTime>level.time); float EnemySpeed = (EnemyVeh)?(EnemyVeh->m_pParentEntity->client->ps.speed):(NPC->enemy->resultspeed); bool EnemySlideBreak = (EnemyVeh && (EnemyVeh->m_ulFlags&VEH_SLIDEBREAKING || EnemyVeh->m_ulFlags&VEH_STRAFERAM)); bool EnemyDead = (NPC->enemy->health<=0); bool ActorFlank = (NPCInfo->lastAvoidSteerSideDebouncer>level.time && EnemyVeh && EnemySpeed>10.0f); CVec3 EnemyDirection; CVec3 EnemyRight; AngleVectors(EnemyAngles.v, EnemyDirection.v, EnemyRight.v, 0); CVec3 EnemyFuturePos(EnemyPos); EnemyFuturePos.ScaleAdd(EnemyDirection, FUTURE_PRED_DIST); ESide EnemySide = ActorPos.LRTest(EnemyPos, EnemyFuturePos); CVec3 EnemyFlankPos(EnemyFuturePos); EnemyFlankPos.ScaleAdd(EnemyRight, (EnemySide==Side_Right)?(FUTURE_SIDE_DIST):(-FUTURE_SIDE_DIST)); // Debug Draw Enemy Data //----------------------- if (false) { CG_DrawEdge(EnemyPos.v, EnemyFuturePos.v, EDGE_IMPACT_SAFE); CG_DrawEdge(EnemyFuturePos.v, EnemyFlankPos.v, EDGE_IMPACT_SAFE); } // Setup Move And Aim Directions //------------------------------- CVec3 MoveDirection((ActorFlank)?(EnemyFlankPos):(EnemyFuturePos)); MoveDirection -= ActorPos; float MoveDistance = MoveDirection.SafeNorm(); float MoveAccuracy = MoveDirection.Dot(ActorDirection); CVec3 AimDirection(EnemyPos); AimDirection -= ActorPos; float AimDistance = AimDirection.SafeNorm(); float AimAccuracy = AimDirection.Dot(ActorDirection); if (!ActorFlank && TIMER_Done(NPC, "FlankAttackCheck")) { TIMER_Set(NPC, "FlankAttackCheck", Q_irand(1000, 3000)); if (MoveDistance<4000 && Q_irand(0, 1)==0) { NPCInfo->lastAvoidSteerSideDebouncer = level.time + Q_irand(8000, 14000); } } // Fly By Sounds //--------------- if ((ActorVeh->m_pVehicleInfo->soundFlyBy || ActorVeh->m_pVehicleInfo->soundFlyBy2) && EnemyVeh && MoveDistance<800 && ActorSpeed>500.0f && TIMER_Done(NPC, "FlybySoundDebouncer") ) { if (EnemySpeed<100.0f || (ActorDirection.Dot(EnemyDirection)*(MoveDistance/800.0f))<-0.5f) { TIMER_Set(NPC, "FlybySoundDebouncer", 2000); int soundFlyBy = ActorVeh->m_pVehicleInfo->soundFlyBy; if (ActorVeh->m_pVehicleInfo->soundFlyBy2 && (!soundFlyBy || !Q_irand(0,1))) { soundFlyBy = ActorVeh->m_pVehicleInfo->soundFlyBy2; } G_Sound(ActorVeh->m_pParentEntity, soundFlyBy); } } // FLY PAST BEHAVIOR //=================== if (EnemySlideBreak || !TIMER_Done(NPC, "MinHoldDirectionTime")) { if (TIMER_Done(NPC, "MinHoldDirectionTime")) { TIMER_Set(NPC, "MinHoldDirectionTime", 500); // Hold For At Least 500 ms } ActorAccelerate = true; // Go ActorAimAtTarget = false; // Don't Alter Our Aim Direction ucmd.buttons &=~BUTTON_VEH_SPEED; // Let Normal Vehicle Controls Go } // FLANKING BEHAVIOR //=================== else if (ActorFlank) { ActorAccelerate = true; ActorDoTurbo = (MoveDistance>2500 || EnemyInTurbo); ucmd.buttons |= BUTTON_VEH_SPEED; // Tells PMove to use the ps.speed we calculate here, not the one from g_vehicles.c // For Flanking, We Calculate The Speed By Hand, Rather Than Using Pure Accelerate / No Accelerate Functionality //--------------------------------------------------------------------------------------------------------------- NPC->client->ps.speed = ActorVeh->m_pVehicleInfo->speedMax * ((ActorInTurbo)?(1.35f):(1.15f)); // If In Slowing Distance, Scale Down The Speed As We Approach Our Move Target //----------------------------------------------------------------------------- if (MoveDistance<ATTACK_FLANK_SLOWING) { NPC->client->ps.speed *= (MoveDistance/ATTACK_FLANK_SLOWING); NPC->client->ps.speed += EnemySpeed; // Match Enemy Speed //------------------- if (NPC->client->ps.speed<5.0f && EnemySpeed<5.0f) { NPC->client->ps.speed = EnemySpeed; } // Extra Slow Down When Out In Front //----------------------------------- if (MoveAccuracy<0.0f) { NPC->client->ps.speed *= (MoveAccuracy + 1.0f); } MoveDirection *= (MoveDistance/ATTACK_FLANK_SLOWING); EnemyDirection *= 1.0f - (MoveDistance/ATTACK_FLANK_SLOWING); MoveDirection += EnemyDirection; if (TIMER_Done(NPC, "RamCheck")) { TIMER_Set(NPC, "RamCheck", Q_irand(1000, 3000)); if (MoveDistance<RAM_DIST && Q_irand(0, 2)==0) { VEH_StartStrafeRam(ActorVeh, (EnemySide==Side_Left)); } } } } // NORMAL CHASE BEHAVIOR //======================= else { if (!EnemyVeh && AimAccuracy>0.99f && MoveDistance<500 && !EnemyDead) { ActorAccelerate = true; ActorDoTurbo = false; } else { ActorAccelerate = ((MoveDistance>500 && EnemySpeed>20.0f) || MoveDistance>1000); ActorDoTurbo = (MoveDistance>3000 && EnemySpeed>20.0f); } ucmd.buttons &=~BUTTON_VEH_SPEED; } // APPLY RESULTS //======================= // Decide Turbo //-------------- if (ActorDoTurbo || ActorInTurbo) { ucmd.buttons |= BUTTON_ALT_ATTACK; } else { ucmd.buttons &=~BUTTON_ALT_ATTACK; } // Decide Acceleration //--------------------- ucmd.forwardmove = (ActorAccelerate)?(127):(0); // Decide To Shoot //----------------- ucmd.buttons &=~BUTTON_ATTACK; ucmd.rightmove = 0; if (AimDistance<2000 && !EnemyDead) { // If Doing A Ram Attack //----------------------- if (ActorYawOffset!=0) { if (NPC->client->ps.weapon!=WP_NONE) { NPC_ChangeWeapon(WP_NONE); } ucmd.buttons &=~BUTTON_ATTACK; } else if (AimAccuracy>ATTACK_FWD) { if (NPC->client->ps.weapon!=WP_NONE) { NPC_ChangeWeapon(WP_NONE); } ucmd.buttons |= BUTTON_ATTACK; } else if (AimAccuracy<AIM_SIDE && AimAccuracy>-AIM_SIDE) { if (NPC->client->ps.weapon!=WP_BLASTER) { NPC_ChangeWeapon(WP_BLASTER); } if (AimAccuracy<ATTACK_SIDE && AimAccuracy>-ATTACK_SIDE) { //if (!TIMER_Done(NPC, "RiderAltAttack")) //{ // ucmd.buttons |= BUTTON_ALT_ATTACK; //} //else //{ ucmd.buttons |= BUTTON_ATTACK; /* if (TIMER_Done(NPC, "RiderAltAttackCheck")) { TIMER_Set(NPC, "RiderAltAttackCheck", Q_irand(1000, 3000)); if (Q_irand(0, 2)==0) { TIMER_Set(NPC, "RiderAltAttack", 300); } }*/ //} WeaponThink(true); } ucmd.rightmove = (EnemySide==Side_Left)?( 127):(-127); } else { if (NPC->client->ps.weapon!=WP_NONE) { NPC_ChangeWeapon(WP_NONE); } } } else { if (NPC->client->ps.weapon!=WP_NONE) { NPC_ChangeWeapon(WP_NONE); } } // Aim At Target //--------------- if (ActorAimAtTarget) { MoveDirection.VecToAng(); NPCInfo->desiredPitch = AngleNormalize360(MoveDirection[PITCH]); NPCInfo->desiredYaw = AngleNormalize360(MoveDirection[YAW] + ActorYawOffset); } NPC_UpdateAngles(qtrue, qtrue); }
void CShapeRenderer::DrawAABB(const CAABBBox& aabb, CColor color) { CVec3 tmin = aabb.m_minPos; CVec3 tmax = aabb.m_maxPos; CVec3 sub = tmax - tmin; CVertexPC startPos, endPos; startPos.color = color; endPos.color = color; startPos.position = tmin; endPos.position = CVec3(tmin.X(), tmin.Y(), tmin.Z() + sub.Z() * 0.2F);// Min CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmin.X(), tmin.Y() + sub.Y() * 0.2F, tmin.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmin.X() + sub.X() * 0.2F, tmin.Y(), tmin.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); startPos.position = tmax; endPos.position = CVec3(tmax.X(), tmax.Y(), tmax.Z() - sub.Z() * 0.2F);// Max CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmax.X(), tmax.Y() - sub.Y() * 0.2F, tmax.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmax.X() - sub.X() * 0.2F, tmax.Y(), tmax.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); startPos.position = CVec3(tmin.X(), tmin.Y(), tmax.Z());// x min, y min, z max endPos.position = CVec3(tmin.X(), tmin.Y(), tmax.Z() - sub.Z() * 0.2F); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmin.X(), tmin.Y() + sub.Y() * 0.2F, tmax.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmin.X() + sub.X() * 0.2F, tmin.Y(), tmax.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); startPos.position = CVec3(tmin.X(), tmax.Y(), tmin.Z());// x min, y max, z min endPos.position = CVec3(tmin.X(), tmax.Y(), tmin.Z() + sub.Z() * 0.2F); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmin.X(), tmax.Y() - sub.Y() * 0.2F, tmin.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmin.X() + sub.X() * 0.2F, tmax.Y(), tmin.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); startPos.position = CVec3(tmax.X(), tmin.Y(), tmin.Z());// x max, y min, z min endPos.position = CVec3(tmax.X(), tmin.Y(), tmin.Z() + sub.Z() * 0.2F); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmax.X(), tmin.Y() + sub.Y() * 0.2F, tmin.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmax.X() - sub.X() * 0.2F, tmin.Y(), tmin.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); startPos.position = CVec3(tmin.X(), tmax.Y(), tmax.Z());// x min, y max, z max endPos.position = CVec3(tmin.X(), tmax.Y(), tmax.Z() - sub.Z() * 0.2F); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmin.X(), tmax.Y() - sub.Y() * 0.2F, tmax.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmin.X() + sub.X() * 0.2F, tmax.Y(), tmax.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); startPos.position = CVec3(tmax.X(), tmax.Y(), tmin.Z());// x min, y max, z max endPos.position = CVec3(tmax.X(), tmax.Y(), tmin.Z() + sub.Z() * 0.2F); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmax.X(), tmax.Y() - sub.Y() * 0.2F, tmin.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmax.X() - sub.X() * 0.2F, tmax.Y(), tmin.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); startPos.position = CVec3(tmax.X(), tmin.Y(), tmax.Z());// x max, y min, z max endPos.position = CVec3(tmax.X(), tmin.Y(), tmax.Z() - sub.Z() * 0.2F); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmax.X(), tmin.Y() + sub.Y() * 0.2F, tmax.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); endPos.position = CVec3(tmax.X() - sub.X() * 0.2F, tmin.Y(), tmax.Z()); CRenderManager::GetInstance()->RenderLine(startPos, endPos, 1.0f, true); }