void CSTransform::RotateOrigin(const double vector[3], double angle, bool concatenate) { double XYZ_A[4]={vector[0],vector[1],vector[2],angle}; double matrix[16]; if (RotateOriginMatrix(matrix, XYZ_A)==false) return; ApplyMatrix(matrix,concatenate); AppendList(ROTATE_ORIGIN,XYZ_A,4); }
void Planet::Draw(Renderer & renderer) { if (!m_attr->active) return; Matrix tmp = m_matrix; m_matrix = m2; ApplyMatrix(renderer); renderer.SetBlending(false); renderer.SetColor(Color(0.0f, 0.0f, 0.0f)); renderer.DrawShape(m_planetBkgnd); renderer.SetBlending(true); m_matrix = tmp; ApplyMatrix(renderer); renderer.SetTexturing(false); renderer.SetColor(m_color); renderer.DrawWireSphere(42.5f, 14, 14); }
void Quaternion::rotate_vector(Vector in,Vector &out) { float inv[4]={float(in.x),float(in.y),float(in.z),0},outv[4]={float(out.x),float(out.y),float(out.z),0}; float matrix[16]; normalize(); to_matrix(matrix); ApplyMatrix(inv,matrix,outv); out.x=outv[0]; out.y=outv[1]; out.z=outv[2]; } /* Quaternion::rotate_vector */
void BaseMesh::CreateClosedCylinder(float radius, const Vec3f &pt1, const Vec3f &pt2, UINT slices, UINT stacks) { float height = (pt2 - pt1).Length(); CreateClosedCylinder(radius, height, slices, stacks); //create a basic cylinder of the appropriate height Matrix4 T1 = Matrix4::Translation(Vec3f(0.0f,0.0f,height / 2.0f)); //translate so it goes from Origin to eZ*height Matrix4 Face = Matrix4::Face(Vec3f::eZ, pt2 - pt1); //make it face the direction pt2 - pt1 instead of eZ Matrix4 T2 = Matrix4::Translation(pt1); //translate it so it goes from pt1 -> pt2 as requested ApplyMatrix(T1 * Face * T2); //apply the constructed Matrix4 GenerateNormals(); }
/*------------------------------------------------------------------- Procedure : Create Quat from dir vector and up vector Input : VECTOR * Direction Vector : VECTOR * Up Vector : QUAT * Destin Quaternion Output : Nothing -------------------------------------------------------------------*/ void QuatFromDirAndUp( VECTOR * Dir, VECTOR * Up, QUAT * Quat ) { MATRIX TempMat; VECTOR TempUp; QUAT RotQuat; QuatFrom2Vectors( Quat, &Forward, Dir ); QuatToMatrix( Quat, &TempMat ); ApplyMatrix( &TempMat, &SlideUp, &TempUp ); QuatFrom2Vectors( &RotQuat, &TempUp, Up ); QuatMultiply( &RotQuat, Quat, Quat ); }
int FB_Jolt( void ) { static float checktime = 0.0F; //static float jolt_time = 0.0F; GLOBALSHIP *s; OBJECT *obj; VECTOR jolt; float magnitude, duration; float attack_level, attack_time; float fade_level, fade_time; MATRIX InvMat; if ( !FF_Supported( FB_Joystick ) ) return 0; s = &Ships[ WhoIAm ]; obj = &s->Object; if ( framelag ) magnitude = VectorLength( &JoltForce ) / framelag; else magnitude = 0.0F; magnitude /= MAXTURBOSPEED; if ( magnitude > 0.01F ) { MatrixTranspose( &obj->Mat, &InvMat ); ApplyMatrix( &InvMat, &JoltForce, &jolt ); duration = 0.25F; attack_level = (float) sqrt( magnitude ); attack_time = 0.1F; fade_level = 0.0F; fade_time = 0.15F; if ( magnitude > MAX_MAGNITUDE ) magnitude = MAX_MAGNITUDE; if ( attack_level > MAX_MAGNITUDE ) attack_level = MAX_MAGNITUDE; FF_UpdateConstantEffect( FB_Joystick, FF_EFFECT_Jolt, magnitude, duration, attack_level, attack_time, fade_level, fade_time, &jolt, DIEP_START ); checktime -= framelag; if ( checktime < 0.0F ) { checktime = JOLT_CHECK_INTERVAL; FF_CheckEffectPlaying( FB_Joystick, FF_EFFECT_Jolt ); } } JoltForce.x = 0.0F; JoltForce.y = 0.0F; JoltForce.z = 0.0F; return 1; }
FX_BOOL CFDE_GdiDevice::FillPolygon(IFDE_Brush* pBrush, const CFX_PointsF& points, const CFX_Matrix* pMatrix) { Gdiplus::Brush* pGdiBrush = CreateGdiBrush(pBrush); if (pGdiBrush == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->FillPolygon( pGdiBrush, (const Gdiplus::PointF*)points.GetData(), points.GetSize()); RestoreMatrix(pMatrix); ReleaseGdiBrush(pGdiBrush); return ret == Gdiplus::Ok; }
FX_BOOL CFDE_GdiDevice::FillRectangle(IFDE_Brush* pBrush, const CFX_RectF& rect, const CFX_Matrix* pMatrix) { Gdiplus::Brush* pGdiBrush = CreateGdiBrush(pBrush); if (pGdiBrush == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->FillRectangle( pGdiBrush, rect.left, rect.top, rect.width, rect.height); RestoreMatrix(pMatrix); ReleaseGdiBrush(pGdiBrush); return ret == Gdiplus::Ok; }
void matrixstack::Rotate(const double phi) { Matrix m(3,3); m.UnitMatrix(); const double s = sin(phi); const double c = cos(phi); m(0,0) = c; m(0,1) = -s; m(1,0) = s; m(1,1) = c; ApplyMatrix( m ); }
/*------------------------------------------------------------------- Procedure : Exogenon Move Down Input : ENEMY * Enemy Output : Nothing -------------------------------------------------------------------*/ void AI_EXOGENON_MOVEDOWN( register ENEMY * Enemy ) { VECTOR TempUpVector; VECTOR FireDir; BOOL ClearLos = TRUE; VECTOR TempOffset = { 0.0F, 0.0F, 180.0F }; ExogenonAim( Enemy ); Enemy->Object.AnimSpeed = 1.5F; if( Enemy->Object.Animating ) { return; } if( !(ClearLos = AI_ClearLOSNonZeroNonObject( &Enemy->Object.Pos,Enemy->Object.Group, &Ships[WhoIAm].Object.Pos , SHIP_RADIUS)) || (Random_Range(10) > 5 ) ) { Enemy->Object.AI_Mode = AIMODE_EXOGENON_MOVEUP; SetCurAnimSeq( EXOGENONSEQ_Move_Up, &Enemy->Object ); if( ClearLos ) { ApplyMatrix( &Enemy->Object.Mat, &SlideUp, &TempUpVector ); ApplyMatrix( &Enemy->Object.Mat, &Forward, &FireDir ); // Fire a homing missile Forward... InitOneSecBull( OWNER_ENEMY, Enemy->Index, ++Enemy->BulletID, Enemy->Object.Group, &Enemy->Object.Pos, &TempOffset, &FireDir, &TempUpVector, &TempOffset, ENEMYBLUEHOMINGMISSILE, FALSE ); } ExogenonFireLeftRight( Enemy ); }else{ Enemy->Object.AI_Mode = AIMODE_EXOGENON_SCAN; SetCurAnimSeq( EXOGENONSEQ_Idle, &Enemy->Object ); } }
FX_BOOL CFDE_GdiDevice::DrawRectangle(IFDE_Pen* pPen, FX_FLOAT fPenWidth, const CFX_RectF& rect, const CFX_Matrix* pMatrix) { Gdiplus::Pen* pGdiPen = CreateGdiPen(pPen, fPenWidth); if (pGdiPen == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->DrawRectangle(pGdiPen, rect.left, rect.top, rect.width, rect.height); RestoreMatrix(pMatrix); ReleaseGdiPen(pGdiPen); return ret == Gdiplus::Ok; }
FX_BOOL CFDE_GdiDevice::DrawPolygon(IFDE_Pen* pPen, FX_FLOAT fPenWidth, const CFX_PointsF& points, const CFX_Matrix* pMatrix) { Gdiplus::Pen* pGdiPen = CreateGdiPen(pPen, fPenWidth); if (pGdiPen == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->DrawPolygon( pGdiPen, (const Gdiplus::PointF*)points.GetData(), points.GetSize()); RestoreMatrix(pMatrix); ReleaseGdiPen(pGdiPen); return ret == Gdiplus::Ok; }
void CSTransform::RotateXYZ(int dir, double angle, bool concatenate) { if ((dir<0) || (dir>3)) return; double vec[4]={0,0,0,angle}; vec[dir] = 1; double matrix[16]; if (RotateOriginMatrix(matrix, vec)==false) return; ApplyMatrix(matrix,concatenate); TransformType type = (TransformType)((int)ROTATE_X + dir); AppendList(type,&angle,1); }
FX_BOOL CFDE_GdiDevice::FillClosedCurve(IFDE_Brush* pBrush, const CFX_PointsF& points, FX_FLOAT fTension, const CFX_Matrix* pMatrix) { Gdiplus::Brush* pGdiBrush = CreateGdiBrush(pBrush); if (pGdiBrush == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->FillClosedCurve( pGdiBrush, (const Gdiplus::PointF*)points.GetData(), points.GetSize(), Gdiplus::FillModeAlternate, fTension); RestoreMatrix(pMatrix); ReleaseGdiBrush(pGdiBrush); return ret == Gdiplus::Ok; }
FX_BOOL CFDE_GdiDevice::DrawLine(IFDE_Pen* pPen, FX_FLOAT fPenWidth, const CFX_PointF& pt1, const CFX_PointF& pt2, const CFX_Matrix* pMatrix) { Gdiplus::Pen* pGdiPen = CreateGdiPen(pPen, fPenWidth); if (pGdiPen == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->DrawLine(pGdiPen, pt1.x, pt1.y, pt2.x, pt2.y); RestoreMatrix(pMatrix); ReleaseGdiPen(pGdiPen); return ret == Gdiplus::Ok; }
FX_BOOL CFDE_GdiDevice::FillPath(IFDE_Brush* pBrush, const IFDE_Path* pPath, const CFX_Matrix* pMatrix) { CFDE_GdiPath* pGdiPath = (CFDE_GdiPath*)pPath; if (pGdiPath == NULL) { return FALSE; } Gdiplus::Brush* pGdiBrush = CreateGdiBrush(pBrush); if (pGdiBrush == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->FillPath(pGdiBrush, &pGdiPath->m_Path); RestoreMatrix(pMatrix); ReleaseGdiBrush(pGdiBrush); return ret == Gdiplus::Ok; }
void BaseMesh::ReCreateLozenge(float Radius, const Vec3f &Start, const Vec3f &End, UINT slices, UINT stacks) { //this is just like CreateCylinder(radius, pt1, pt2, slices, stacks) except the radius function isn't fixed; //towards the ends it rounds off into a sphere. MeshVertex *V = Vertices(); float Theta,CurZ,SqrtValue; float PI2_Slices = 2.0f * Math::PIf / float(slices), Height, LocalRadius; Vec3f Diff = End - Start; Height = Diff.Length(); for(UINT i=0; i <= stacks; i++) { for(UINT i2 = 0; i2 < slices; i2++) { Theta = float(i2) * PI2_Slices; CurZ = float(Math::LinearMap(0.0f, float(stacks), -Radius, Height+Radius, float(i))); if(CurZ < 0.0f) //if we need to round the cylinder, { LocalRadius = float(Math::LinearMap(-Radius, 0.0f, 1.0f, 0.0f, CurZ)); SqrtValue = 1.0f - LocalRadius*LocalRadius; if(SqrtValue < 0.0f) SqrtValue = 0.0f; LocalRadius = sqrtf(SqrtValue) * Radius; //compute the appropriate radius } else if(CurZ > Height) //if we're on the other end of the cylinder and need to round, { LocalRadius = float(Math::LinearMap(Height, Height+Radius, 0.0f, 1.0f, CurZ)); SqrtValue = 1.0f - LocalRadius*LocalRadius; if(SqrtValue < 0.0f) SqrtValue = 0.0f; LocalRadius = sqrtf(SqrtValue) * Radius; //do the same thing if(LocalRadius < 0.0f || LocalRadius > Radius + 1e-5f) LocalRadius = 0.0f; } else { LocalRadius = Radius; //otherwise we're in the middle and our radius is fixed like a cylinder } V[i*slices+i2].Pos = Vec3f(LocalRadius * cosf(Theta), LocalRadius * sinf(Theta), CurZ); //load the appropriate position } } Vec3f UpVec(0.0f, 0.0f, 1.0f); ApplyMatrix(Matrix4::Face(UpVec, Diff) * Matrix4::Translation(Start)); //make it face the right direction and translate it to the right position }
FX_BOOL CFDE_GdiDevice::DrawPath(IFDE_Pen* pPen, FX_FLOAT fPenWidth, const IFDE_Path* pPath, const CFX_Matrix* pMatrix) { CFDE_GdiPath* pGdiPath = (CFDE_GdiPath*)pPath; if (pGdiPath == NULL) { return FALSE; } Gdiplus::Pen* pGdiPen = CreateGdiPen(pPen, fPenWidth); if (pGdiPen == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->DrawPath(pGdiPen, &pGdiPath->m_Path); RestoreMatrix(pMatrix); ReleaseGdiPen(pGdiPen); return ret == Gdiplus::Ok; }
FX_BOOL CFDE_GdiDevice::FillPie(IFDE_Brush* pBrush, const CFX_RectF& rect, FX_FLOAT startAngle, FX_FLOAT sweepAngle, const CFX_Matrix* pMatrix) { startAngle = FX_RAD2DEG(startAngle); sweepAngle = FX_RAD2DEG(sweepAngle); Gdiplus::Brush* pGdiBrush = CreateGdiBrush(pBrush); if (pGdiBrush == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->FillPie(pGdiBrush, rect.left, rect.top, rect.width, rect.height, startAngle, sweepAngle); RestoreMatrix(pMatrix); ReleaseGdiBrush(pGdiBrush); return ret == Gdiplus::Ok; }
MF_API void MFView_TransformPoint2DTo3D(const MFVector& point, MFVector *pResult, MFVector *pResultRayDir) { MFMatrix proj, viewProj, view; // get the perspective projection matrix proj.SetPerspective(pCurrentView->fov, pCurrentView->nearPlane, pCurrentView->farPlane, pCurrentView->aspectRatio); // in this special case, we'll make the projection matrix produce a 0-1 value in z across all platforms (some platforms project into different 'z' spaces) float zn = pCurrentView->nearPlane; float zf = pCurrentView->farPlane; float zd = zf-zn; float zs = zf/zd; proj.m[10] = zs; proj.m[14] = -zn*zs; // get the view matrix (which we will need to calculate if we are in ortho mode) if(!MFView_IsOrtho()) view = MFView_GetWorldToViewMatrix(); else view.Inverse(MFView_GetCameraMatrix()); viewProj.Multiply4x4(view, proj); // inverse projection viewProj.Inverse(); // which the point from ortho space back into homogeneous space *pResult = point; *pResult -= MakeVector(pCurrentView->orthoRect.x, pCurrentView->orthoRect.y); *pResult *= MakeVector(MFRcp(pCurrentView->orthoRect.width*0.5f), MFRcp(pCurrentView->orthoRect.height*0.5f)); pResult->x -= 1.0f; pResult->y = -pResult->y + 1.0f; // and un-project // TODO: undo the perspective divide (f**k) *pResult = ApplyMatrix(*pResult, viewProj); if(pResultRayDir) { // calculate the pixels rays direction.. } }
float BOTAI_DistanceToWall( bool u, bool d, bool l, bool r, bool f, bool b ) { float dist; VECTOR temp; NORMAL FaceNormal; VECTOR Pos_New; VECTOR ImpactPoint; u_int16_t ImpactGroup; VECTOR Slide; // calculate the desired vector Slide.x = 0.0F; Slide.y = 0.0F; Slide.z = 0.0F; if(r) Slide.x = 1.0F; else if(l) Slide.x = -1.0F; if(u) Slide.y = 1.0F; else if(d) Slide.y = -1.0F; if(f) Slide.z = 1.0F; else if(b) Slide.z = -1.0F; ApplyMatrix( &Ships[WhoIAm].Object.FinalMat, &Slide, &temp ); temp.x *= MaxColDistance; temp.y *= MaxColDistance; temp.z *= MaxColDistance; // get collision details BackgroundCollide( &MCloadheadert0, &Mloadheader, &Ships[WhoIAm].Object.Pos, Ships[WhoIAm].Object.Group, &temp, &ImpactPoint, &ImpactGroup, &FaceNormal, &Pos_New, false, NULL ); // return the distance dist = DistanceVector2Vector(&Ships[WhoIAm].Object.Pos, &ImpactPoint); // if movement will put me in a gravgon we want to avoid this Pos_New = Ships[WhoIAm].Object.Pos; BOTAI_LookAheadPos( 10.0F, &Pos_New, Slide ); if( BOTAI_CheckForGravgons( &Pos_New ) ) dist = 1.0F; return dist; }
FX_BOOL CFDE_GdiDevice::DrawPie(IFDE_Pen* pPen, FX_FLOAT fPenWidth, const CFX_RectF& rect, FX_FLOAT startAngle, FX_FLOAT sweepAngle, const CFX_Matrix* pMatrix) { startAngle = FX_RAD2DEG(startAngle); sweepAngle = FX_RAD2DEG(sweepAngle); Gdiplus::Pen* pGdiPen = CreateGdiPen(pPen, fPenWidth); if (pGdiPen == NULL) { return FALSE; } ApplyMatrix(pMatrix); Gdiplus::Status ret = m_pGraphics->DrawPie(pGdiPen, rect.left, rect.top, rect.width, rect.height, startAngle, sweepAngle); RestoreMatrix(pMatrix); ReleaseGdiPen(pGdiPen); return ret == Gdiplus::Ok; }
void BaseMesh::CreatePlane(const Vec3f &_start, const Vec3f &_end, UINT slicesX, UINT slicesY) { Vec3f start = _start, end = _end; CreatePlane(1.0f, slicesX, slicesY); if(start.x > end.x) { Utility::Swap(start.x, end.x); } if(start.y > end.y) { Utility::Swap(start.y, end.y); } Matrix4 T1 = Matrix4::Translation(Vec3f(0.5f,0.5f,0.0f)); Matrix4 Scale = Matrix4::Scaling(Vec3f((end.x-start.x),(end.y-start.y),1.0f)); Matrix4 T2 = Matrix4::Translation(start); ApplyMatrix(T1 * Scale * T2); }
/*=================================================================== Procedure : AIR Formation Flying Input : ENEMY * Enemy Output : Nothing ===================================================================*/ void AI_LITTLEGEEK_FORMATION( register ENEMY * Enemy ) { OBJECT * SObject; VECTOR Offset; VECTOR TargetPos; ENEMY * LinkEnemy; SObject = &Enemy->Object; // Is it time to think??? AI_THINK( Enemy , false ,false); LinkEnemy = Enemy->FormationLink; if( !LinkEnemy || ( LinkEnemy->Object.Shield <= (EnemyTypes[LinkEnemy->Type].Shield * 0.5F ) ) ) { Enemy->Object.ControlType = ENEMY_CONTROLTYPE_FLY_AI; EnemyTypes[ENEMY_Boss_LittleGeek].Radius = 800 * GLOBAL_SCALE; EnemyTypes[ENEMY_Boss_BigGeek].Radius = 900.0F * GLOBAL_SCALE; AI_SetDOGFIGHT( Enemy ); SetCurAnimSeq( LITTLEGEEKSEQ_Open, &Enemy->Object ); Enemy->FormationLink = NULL; return; } SetCurAnimSeq( LITTLEGEEKSEQ_Stop, &Enemy->Object ); Offset = Enemy->FormationOffset; ApplyMatrix( &LinkEnemy->Object.Mat, &Offset, &TargetPos ); TargetPos.x += LinkEnemy->Object.Pos.x; TargetPos.y += LinkEnemy->Object.Pos.y; TargetPos.z += LinkEnemy->Object.Pos.z; Enemy->Object.Pos = TargetPos; Enemy->Object.Quat = LinkEnemy->Object.Quat; Enemy->Object.Mat = LinkEnemy->Object.Mat; Enemy->Object.InvMat = LinkEnemy->Object.InvMat; Enemy->Object.FinalMat = LinkEnemy->Object.FinalMat; Enemy->Object.FinalInvMat = LinkEnemy->Object.FinalInvMat; EnemyTypes[ENEMY_Boss_LittleGeek].Radius = 0.0F; }
bool CSTransform::RotateXYZ(int dir, std::string angle, bool concatenate) { if ((dir<0) || (dir>3)) return false; ParameterScalar ps_angle(m_ParaSet, angle); int EC = ps_angle.Evaluate(); if (EC!=0) return false; double vec[4]={0,0,0,ps_angle.GetValue()}; vec[dir] = 1; double matrix[16]; if (RotateOriginMatrix(matrix, vec)==false) return false; ApplyMatrix(matrix,concatenate); TransformType type = (TransformType)((int)ROTATE_X + dir); AppendList(type,&ps_angle,1); return true; }
bool BOTAI_InViewCone( VECTOR * Pos, MATRIX * Mat, VECTOR * TPos, float ViewConeCos ) { float Cos; VECTOR NormVector; VECTOR Dir; if( ViewConeCos == 1.0F ) return true; Dir.x = TPos->x - Pos->x; Dir.y = TPos->y - Pos->y; Dir.z = TPos->z - Pos->z; NormVector = Dir; NormaliseVector( &NormVector ); ApplyMatrix( Mat, &Forward, &Dir ); Cos = DotProduct( &NormVector, &Dir ); if( Cos > ViewConeCos ) return true; return false; }
/*=================================================================== Procedure : Update an Enemies Guns... Input : ENEMY * Enemy Output : Nothing ===================================================================*/ void AI_UPDATEGUNS( register ENEMY * Enemy ) { OBJECT * TObject; GUNOBJECT * GObject; VECTOR TempVector; VECTOR TempUpVector; VECTOR TempOffset = { 0.0F, 0.0F, 0.0F }; VECTOR NewPos; VECTOR FireOffset; FIREPOS * FirePosPnt; VECTOR AimOffset; u_int16_t i; BYTE Weapon; TObject = (OBJECT*) Enemy->TShip; if( !TObject || TObject->Mode != NORMAL_MODE ) return; GObject = Enemy->Object.FirstGun; while( GObject ) { // if( TObject && ( (Enemy->AIFlags & AI_ICANSEEPLAYER) || (Enemy->Object.ControlType == ENEMY_CONTROLTYPE_TURRET_AI) || (Enemy->Object.ControlType == ENEMY_CONTROLTYPE_SPLINE) ) ) if( TObject && ( (Enemy->AIFlags & AI_ICANSEEPLAYER) || (Enemy->Object.ControlType == ENEMY_CONTROLTYPE_SPLINE) ) ) { FirePosPnt = EnemyTypes[Enemy->Type].GunFirePoints[GObject->GunNum>>1]; ApplyMatrix( &GObject->Mat , &FirePosPnt->Points[GObject->FirePosCount] , &FireOffset ); FireOffset.x += GObject->FirePos.x; FireOffset.y += GObject->FirePos.y; FireOffset.z += GObject->FirePos.z; FireOffset.x -= Enemy->Object.Pos.x; FireOffset.y -= Enemy->Object.Pos.y; FireOffset.z -= Enemy->Object.Pos.z; ApplyMatrix( &GObject->Mat, EnemyTypes[ Enemy->Type ].GunAimPos[GObject->GunNum>>1], &AimOffset ); AimOffset.x += Enemy->Object.Pos.x; AimOffset.y += Enemy->Object.Pos.y; AimOffset.z += Enemy->Object.Pos.z; if( !GunTypes[GObject->Type].BurstMasterCount ) { // Normal gun that just fires when it can.. if( GunTypes[GObject->Type].PrimarySecondary ) { AI_LookAhead( EnemyTypes[Enemy->Type].Behave.Anticipate_Move ,&AimOffset, TObject , &NewPos , SecondaryWeaponAttribs[GunTypes[GObject->Type].WeaponType].Speed); }else{ AI_LookAhead( EnemyTypes[Enemy->Type].Behave.Anticipate_Move ,&AimOffset, TObject , &NewPos , PrimaryWeaponAttribs[GunTypes[GObject->Type].WeaponType].Speed[GunTypes[GObject->Type].PowerLevel]); } AI_AimAtTarget( &GObject->InvMat , &AimOffset, &NewPos ); GObject->AIMoveFlags |= AimData.Flags; GObject->AI_Angle = AimData.Angle; if( GObject->Type == GUN_MetaTankMain ) { if( (GObject->ReloadTime <= (0.5F*60.0F) ) && !Enemy->Object.Animating ) { SetCurAnimSeq( 0, &Enemy->Object ); } } if( GObject->ReloadTime <= 0.0F && ( (( ( GObject->AI_Angle.x < GunTypes[GObject->Type].BurstAngle && GObject->AI_Angle.x > -GunTypes[GObject->Type].BurstAngle ) && ( GObject->AI_Angle.y < GunTypes[GObject->Type].BurstAngle && GObject->AI_Angle.y > -GunTypes[GObject->Type].BurstAngle ) ) ) || GObject->Type == GUN_MetaTankMain ) ) { ApplyMatrix( &GObject->Mat, &Forward, &TempVector ); ApplyMatrix( &GObject->Mat, &SlideUp, &TempUpVector ); if( !(Enemy->Object.Flags & SHIP_Scattered ) && (!GunTypes[GObject->Type].Range || ( DistanceVector2Vector( &TObject->Pos , &Enemy->Object.Pos) < GunTypes[GObject->Type].Range ) )) { if(Enemy->Object.ControlType == ENEMY_CONTROLTYPE_TURRET_AI) { if( !Enemy->Object.Animating && (Enemy->Type != ENEMY_MissileTurret) ) { SetCurAnimSeq( TURRETSEQ_Fire, &Enemy->Object ); } } if( GunTypes[GObject->Type].PrimarySecondary ) { InitOneSecBull( OWNER_ENEMY, Enemy->Index, ++Enemy->BulletID, Enemy->Object.Group, &Enemy->Object.Pos, &FireOffset, &TempVector, &TempUpVector, &TempOffset, GunTypes[GObject->Type].WeaponType, false ); }else{ Weapon = BodgePrimaryWeapon( GunTypes[GObject->Type].WeaponType, Enemy->PickupHeld ); i = EnemyFirePrimary( OWNER_ENEMY, Enemy->Index, ++Enemy->BulletID, Weapon, Enemy->Object.Group, &Enemy->Object.Pos, &FireOffset, &TempVector, &TempUpVector, GunTypes[GObject->Type].PowerLevel, (GunTypes[GObject->Type].PowerLevel +1) * 33.0F, false, GObject ); if( i != (u_int16_t) -1 ) { PrimBulls[i].FirePoint = GObject->FirePosCount; } } GObject->FirePosCount++; if( GObject->FirePosCount >= FirePosPnt->NumPoints ) GObject->FirePosCount = 0; GObject->ReloadTime =GunTypes[GObject->Type].ReloadTime; } } }else{ // A Gun That Does a Burst... if( GObject->BurstCount ) { if( GunTypes[GObject->Type].PrimarySecondary ) { AI_LookAhead( EnemyTypes[Enemy->Type].Behave.Anticipate_Move ,&AimOffset, TObject , &NewPos , SecondaryWeaponAttribs[GunTypes[GObject->Type].WeaponType].Speed); }else{ AI_LookAhead( EnemyTypes[Enemy->Type].Behave.Anticipate_Move ,&AimOffset, TObject , &NewPos , PrimaryWeaponAttribs[GunTypes[GObject->Type].WeaponType].Speed[GunTypes[GObject->Type].PowerLevel]); } AI_AimAtTarget( &GObject->InvMat , &AimOffset, &NewPos ); GObject->AIMoveFlags |= AimData.Flags; GObject->AIMoveFlags &= ~(AI_CONTROL_TURNLEFT + AI_CONTROL_TURNRIGHT ); GObject->AI_Angle = AimData.Angle; if( GObject->BurstStartSign < 0.0F ) { GObject->AIMoveFlags |= AI_CONTROL_TURNLEFT; }else{ GObject->AIMoveFlags |= AI_CONTROL_TURNRIGHT; } if( !(Enemy->Object.Flags & SHIP_Scattered ) &&GObject->ReloadTime <= 0.0F ) { ApplyMatrix( &GObject->Mat, &Forward, &TempVector ); ApplyMatrix( &GObject->Mat, &SlideUp, &TempUpVector ); if(Enemy->Object.ControlType == ENEMY_CONTROLTYPE_TURRET_AI) { if( !Enemy->Object.Animating && (Enemy->Type != ENEMY_MissileTurret) ) { SetCurAnimSeq( TURRETSEQ_Fire, &Enemy->Object ); } } if( GunTypes[GObject->Type].PrimarySecondary ) { InitOneSecBull( OWNER_ENEMY, Enemy->Index, ++Enemy->BulletID, Enemy->Object.Group, &Enemy->Object.Pos, &FireOffset, &TempVector, &TempUpVector, &TempOffset, GunTypes[GObject->Type].WeaponType, false ); }else{ Weapon = BodgePrimaryWeapon( GunTypes[GObject->Type].WeaponType, Enemy->PickupHeld ); i = EnemyFirePrimary( OWNER_ENEMY, Enemy->Index, ++Enemy->BulletID, Weapon, Enemy->Object.Group, &Enemy->Object.Pos, &FireOffset, &TempVector, &TempUpVector, GunTypes[GObject->Type].PowerLevel, (GunTypes[GObject->Type].PowerLevel +1) * 33.0F, false, GObject ); if( i != (u_int16_t) -1 ) { PrimBulls[i].FirePoint = GObject->FirePosCount; } } GObject->FirePosCount++; if( GObject->FirePosCount >= FirePosPnt->NumPoints ) GObject->FirePosCount = 0; GObject->ReloadTime = GunTypes[GObject->Type].ReloadTime; GObject->BurstCount--; } } if( !GObject->BurstCount && GunTypes[GObject->Type].BurstMasterCount ) { if( GunTypes[GObject->Type].PrimarySecondary ) { AI_LookAhead( EnemyTypes[Enemy->Type].Behave.Anticipate_Move ,&AimOffset, TObject , &NewPos , SecondaryWeaponAttribs[GunTypes[GObject->Type].WeaponType].Speed); }else{ AI_LookAhead( EnemyTypes[Enemy->Type].Behave.Anticipate_Move ,&AimOffset, TObject , &NewPos , PrimaryWeaponAttribs[GunTypes[GObject->Type].WeaponType].Speed[GunTypes[GObject->Type].PowerLevel]); } AI_AimAtTarget( &GObject->InvMat , &AimOffset, &NewPos ); GObject->AIMoveFlags |= AimData.Flags; GObject->AI_Angle = AimData.Angle; if( GObject->BurstTime == 0.0F ) { if( (GObject->AI_Angle.y <= GunTypes[GObject->Type].BurstAngle) && (GObject->AI_Angle.y >= -GunTypes[GObject->Type].BurstAngle) ) { GObject->BurstCount = GunTypes[GObject->Type].BurstMasterCount; GObject->BurstTime = GunTypes[GObject->Type].BurstMasterTime; GObject->BurstStartSign = GObject->AI_Angle.y; } } } } } GObject = GObject->Next; }
o3d::Primitive* Primitives::CreateSphere( o3d::Pack* pack, float radius, int subdivisionsAxis, int subdivisionsHeight, o3d::Matrix4* matrix) { DCHECK(subdivisionsAxis >= 1); DCHECK(subdivisionsHeight >= 1); std::vector<o3d::Point3> positions; std::vector<o3d::Vector3> normals; std::vector<Vector2> tex_coords; std::vector<Triangle> indices; const float kPI = 3.14159265f; for (int y = 0; y <= subdivisionsHeight; ++y) { for (int x = 0; x <= subdivisionsAxis; ++x) { // Generate a vertex based on its spherical coordinates float u = static_cast<float>(x) / static_cast<float>(subdivisionsAxis); float v = static_cast<float>(y) / static_cast<float>(subdivisionsHeight); float theta = 2.0f * kPI * u; float phi = kPI * v; float sinTheta = sinf(theta); float cosTheta = cosf(theta); float sinPhi = sinf(phi); float cosPhi = cosf(phi); float ux = cosTheta * sinPhi; float uy = cosPhi; float uz = sinTheta * sinPhi; positions.push_back(o3d::Point3(radius * ux, radius * uy, radius * uz)); normals.push_back(o3d::Vector3(ux, uy, uz)); tex_coords.push_back(Vector2(1 - u, 1 - v)); } } int numVertsAround = subdivisionsAxis + 1; for (int x = 0; x < subdivisionsAxis; ++x) { for (int y = 0; y < subdivisionsHeight; ++y) { // Make triangle 1 of quad. indices.push_back(Triangle( (y + 0) * numVertsAround + x, (y + 0) * numVertsAround + x + 1, (y + 1) * numVertsAround + x)); // Make triangle 2 of quad. indices.push_back(Triangle( (y + 1) * numVertsAround + x, (y + 0) * numVertsAround + x + 1, (y + 1) * numVertsAround + x + 1)); } } if (matrix) { ApplyMatrix(*matrix, &positions); ApplyMatrix(*matrix, &normals); } return CreatePrimitive( pack, &positions, &normals, &tex_coords, &indices, o3d::Primitive::TRIANGLELIST); }
void ParseMD2File(char *pFile, size_t length) { int a, b; MD2Header *pHeader = (MD2Header*)pFile; MFDebug_Assert(pHeader->ident == (('2'<<24) | ('P'<<16) | ('D'<<8) | 'I'), "Invalid MD2 header."); MFDebug_Assert(pHeader->version == 8, "Invalid MD2 version."); // md2_skin_t *skins = (md2_skin_t*)(pFile + pHeader->offset_skins); md2_texCoord_t *st = (md2_texCoord_t*)(pFile + pHeader->offset_st); md2_triangle_t *tris = (md2_triangle_t*)(pFile + pHeader->offset_tris); md2_frame_t *frames = (md2_frame_t*)(pFile + pHeader->offset_frames); MFMatrix md2Mat; md2Mat.SetIdentity(); md2Mat.SetXAxis3(MakeVector(1,0,0)); md2Mat.SetYAxis3(MakeVector(0,0,1)); md2Mat.SetZAxis3(MakeVector(0,1,0)); // material F3DMaterialChunk *pMatChunk = pModel->GetMaterialChunk(); F3DMaterial &mat = pMatChunk->materials.push(); mat.name = pModel->name; mat.maps[0] = pModel->name; // mesh data F3DMeshChunk *pMC = pModel->GetMeshChunk(); F3DSubObject &sub = pMC->subObjects.push(); // copy name (TODO: remove file extension) sub.name = pModel->name; // colours sub.colours.resize(1); sub.colours[0] = MFVector::one; // tex coords sub.uvs.resize(pHeader->num_st); for(a=0; a<pHeader->num_st; a++) { sub.uvs[a].x = (float)st[a].s / (float)pHeader->skinwidth; sub.uvs[a].y = (float)st[a].t / (float)pHeader->skinheight; sub.uvs[a].z = 0.0f; } // normals sub.normals.resize(numNormals); for(a=0; a<numNormals; a++) { sub.normals[a].x = normalTable[a][0]; sub.normals[a].y = normalTable[a][1]; sub.normals[a].z = normalTable[a][2]; sub.normals[a] = ApplyMatrix(sub.normals[a], md2Mat); } // for(a=0; a<pHeader->num_frames; a++) // { // read frame data // (char*&)pHeader->frames += pHeader->framesize; // } // vertices sub.positions.resize(pHeader->num_vertices); MFVector scale = MakeVector(frames->scale[0], frames->scale[1], frames->scale[2], 0.0f); MFVector translate = MakeVector(frames->translate[0], frames->translate[1], frames->translate[2]); for(b=0; b<pHeader->num_vertices; b++) { // verts sub.positions[b] = MakeVector((float)frames->verts[b].v[0], (float)frames->verts[b].v[1], (float)frames->verts[b].v[2]); sub.positions[b] = sub.positions[b]*scale + translate; sub.positions[b] = ApplyMatrix(sub.positions[b], md2Mat); } // trnangles F3DMaterialSubobject &matSub = sub.matSubobjects.push(); matSub.materialIndex = 0; matSub.vertices.resize(pHeader->num_tris * 3); for(a=0; a<pHeader->num_tris; a++) { matSub.vertices[a*3 + 0].colour = 0; matSub.vertices[a*3 + 1].colour = 0; matSub.vertices[a*3 + 2].colour = 0; matSub.vertices[a*3 + 0].position = tris[a].vertex[0]; matSub.vertices[a*3 + 0].uv[0] = tris[a].st[0]; matSub.vertices[a*3 + 0].normal = frames->verts[tris[a].vertex[0]].normalIndex; matSub.vertices[a*3 + 1].position = tris[a].vertex[1]; matSub.vertices[a*3 + 1].uv[0] = tris[a].st[1]; matSub.vertices[a*3 + 1].normal = frames->verts[tris[a].vertex[1]].normalIndex; matSub.vertices[a*3 + 2].position = tris[a].vertex[2]; matSub.vertices[a*3 + 2].uv[0] = tris[a].st[2]; matSub.vertices[a*3 + 2].normal = frames->verts[tris[a].vertex[2]].normalIndex; } matSub.triangles.resize(pHeader->num_tris); for(a=0; a<pHeader->num_tris; a++) { matSub.triangles[a].v[0] = a*3 + 0; matSub.triangles[a].v[1] = a*3 + 1; matSub.triangles[a].v[2] = a*3 + 2; // TODO: generate face normal } }
/*=================================================================== Procedure : AIR Formation Flying Input : ENEMY * Enemy Output : Nothing ===================================================================*/ void AI_AIR_FORMATION( register ENEMY * Enemy ) { float Dist; OBJECT * TObject; OBJECT * SObject; VECTOR NewPos; VECTOR TempVector; VECTOR TempUpVector; VECTOR TempOffset = { 0.0F, 0.0F, 0.0F }; VECTOR Offset; VECTOR TargetPos; VECTOR TempDir; ENEMY * LinkEnemy; SObject = &Enemy->Object; // Is it time to think??? AI_THINK( Enemy , false ,false); LinkEnemy = Enemy->FormationLink; if( !LinkEnemy || ( LinkEnemy->Object.AI_Mode == AIMODE_RETREAT ) ) { if( Enemy->AIFlags & ( AI_ICANSEEPLAYER + AI_ICANHEARPLAYER ) ) { AI_SetDOGFIGHT( Enemy ); return; }else{ AI_SetFOLLOWPATH( Enemy ); return; } } TObject = (OBJECT*) Enemy->TShip; Enemy->Timer -= framelag; if( Enemy->Timer < 0.0F ) Enemy->Timer = 0.0F; Enemy->PrimaryFireTimer -= framelag; if( Enemy->PrimaryFireTimer < 0.0F ) Enemy->PrimaryFireTimer = 0.0F; Enemy->SecondaryFireTimer -= framelag; if( Enemy->SecondaryFireTimer < 0.0F ) Enemy->SecondaryFireTimer = 0.0F; if( Enemy->AIFlags & ( AI_ICANSEEPLAYER + AI_ICANHEARPLAYER ) ) { Enemy->TNode = NULL; if( !(Enemy->Object.Flags & SHIP_Scattered ) && (Enemy->AIFlags & AI_ICANSEEPLAYER) && !(Enemy->AIFlags & AI_FRIENDLYFIRE) ) { ApplyMatrix( &SObject->Mat, &Forward, &TempVector ); ApplyMatrix( &SObject->Mat, &SlideUp, &TempUpVector ); if( (Enemy->PrimaryFireTimer == 0.0F) && ( EnemyTypes[Enemy->Type].PrimaryWeaponType != NO_PRIMARY ) ) { Enemy->PrimaryFireTimer = EnemyTypes[Enemy->Type].PrimaryFireRate + (float) Random_Range( (u_int16_t) EnemyTypes[Enemy->Type].PrimaryFireRate ); EnemyFirePrimary( OWNER_ENEMY, Enemy->Index, ++Enemy->BulletID, EnemyTypes[Enemy->Type].PrimaryWeaponType, Enemy->Object.Group, &Enemy->Object.Pos, &TempOffset, &TempVector, &TempUpVector, EnemyTypes[Enemy->Type].PowerLevel, 0.0F, false, NULL ); } } } if( (Enemy->Object.Flags & SHIP_Scattered ) || ( (EnemyTypes[Enemy->Type].Behave.Flags & AI_BEHAVIOUR_RETREAT) && ( Enemy->Object.Shield <= (EnemyTypes[Enemy->Type].Shield * 0.15 ) ) ) ) { // we should get out of hear.. Enemy->FormationLink = NULL; AI_SetRETREAT( Enemy ); return; } AI_UPDATEGUNS( Enemy ); // Aim at target if( TObject && ( Enemy->AIFlags & AI_ICANSEEPLAYER ) ) { if( EnemyTypes[Enemy->Type].PrimaryWeaponType != NO_PRIMARY ) { AI_LookAhead( EnemyTypes[Enemy->Type].Behave.Anticipate_Move , &Enemy->Object.Pos , TObject , &NewPos , PrimaryWeaponAttribs[EnemyTypes[Enemy->Type].PrimaryWeaponType].Speed[0] ); }else{ NewPos = TObject->Pos; } AI_AimAtTarget( &Enemy->Object.InvMat , &Enemy->Object.Pos, &NewPos ); if( !( EnemyTypes[Enemy->Type].Behave.Flags & AI_BEHAVIOUR_ICANTPITCH ) ) { Enemy->AIMoveFlags |= AimData.Flags; }else{ //This enemy cant look up or down so it has to move up and down to compensate.... Enemy->AIMoveFlags |= ( AimData.Flags & ( AI_CONTROL_TURNLEFT + AI_CONTROL_TURNRIGHT ) ); if( AimData.Flags & AI_CONTROL_TURNUP ) { Enemy->AIMoveFlags |= AI_CONTROL_UP; }else if( AimData.Flags & AI_CONTROL_TURNDOWN ) { Enemy->AIMoveFlags |= AI_CONTROL_DOWN; } } Enemy->AI_Angle = AimData.Angle; }else{ ApplyMatrix( &LinkEnemy->Object.Mat, &Forward, &TempDir ); TempDir.x *= 1024.0F * GLOBAL_SCALE * 5.0F; TempDir.y *= 1024.0F * GLOBAL_SCALE * 5.0F; TempDir.z *= 1024.0F * GLOBAL_SCALE * 5.0F; NewPos.x = LinkEnemy->Object.Pos.x + TempDir.x; NewPos.y = LinkEnemy->Object.Pos.y + TempDir.y; NewPos.z = LinkEnemy->Object.Pos.z + TempDir.z; AI_AimAtTarget( &Enemy->Object.InvMat , &Enemy->Object.Pos, &NewPos ); if( !( EnemyTypes[Enemy->Type].Behave.Flags & AI_BEHAVIOUR_ICANTPITCH ) ) { Enemy->AIMoveFlags |= AimData.Flags; }else{ //This enemy cant look up or down so it has to move up and down to compensate.... Enemy->AIMoveFlags |= ( AimData.Flags & ( AI_CONTROL_TURNLEFT + AI_CONTROL_TURNRIGHT ) ); if( AimData.Flags & AI_CONTROL_TURNUP ) { Enemy->AIMoveFlags |= AI_CONTROL_UP; }else if( AimData.Flags & AI_CONTROL_TURNDOWN ) { Enemy->AIMoveFlags |= AI_CONTROL_DOWN; } } Enemy->AI_Angle = AimData.Angle; } if( Enemy->AvoidTimer ) { Enemy->AIMoveFlags = Enemy->AvoidType; }else{ Offset = Enemy->FormationOffset; ApplyMatrix( &LinkEnemy->Object.Mat, &Offset, &TargetPos ); TargetPos.x += LinkEnemy->Object.Pos.x; TargetPos.y += LinkEnemy->Object.Pos.y; TargetPos.z += LinkEnemy->Object.Pos.z; Dist = DistanceVector2Vector( &TargetPos , &Enemy->Object.Pos); if( Dist > (EnemyTypes[Enemy->Type].Radius * 0.75F) ) { Offset.x = TargetPos.x - Enemy->Object.Pos.x; Offset.y = TargetPos.y - Enemy->Object.Pos.y; Offset.z = TargetPos.z - Enemy->Object.Pos.z; ApplyMatrix( &Enemy->Object.InvMat, &Offset, &TargetPos ); if( TargetPos.x < -(EnemyTypes[Enemy->Type].Radius * 0.25F) ) { Enemy->AIMoveFlags |= AI_CONTROL_LEFT; } if( TargetPos.x > (EnemyTypes[Enemy->Type].Radius * 0.25F) ) { Enemy->AIMoveFlags |= AI_CONTROL_RIGHT; } if( TargetPos.y < -(EnemyTypes[Enemy->Type].Radius * 0.25F) ) { Enemy->AIMoveFlags |= AI_CONTROL_DOWN; } if( TargetPos.y > (EnemyTypes[Enemy->Type].Radius * 0.25F) ) { Enemy->AIMoveFlags |= AI_CONTROL_UP; } if( TargetPos.z < -(EnemyTypes[Enemy->Type].Radius * 0.25F) ) { Enemy->AIMoveFlags |= AI_CONTROL_BACK; } if( TargetPos.z > (EnemyTypes[Enemy->Type].Radius * 0.25F) ) { Enemy->AIMoveFlags |= AI_CONTROL_FORWARD; } } } }