00001 #include "ODEProjectile.h"
00002 #include "MercuryLog.h"
00003
00004 REGISTER_ODE_OBJECT_CLASS( Projectile )
00005
00006 Projectile::~Projectile()
00007 {
00008 Disable();
00009 }
00010
00011 void Projectile::Init()
00012 {
00013 MercuryODEObject::Init();
00014
00015 m_pRay = 0;
00016 m_pToNotify = 0;
00017
00018
00019 m_shpTracer.SetName("Tracer");
00020 m_shpTracer.Init();
00021 m_shpTracer.MakeBox();
00022 m_shpTracer.SetDiffuse( MercuryColor( 1,1,1,0.5 ) );
00023
00024 m_shpTracer.LoadImage( "GRAPHIC:MoltenMetal.bmp" );
00025 m_shpTracer.SetScale( MercuryPoint( .3f,.3f,500 ) );
00026 m_shpTracer.SetHide( true );
00027 AddObject( &m_shpTracer );
00028 }
00029
00030 void Projectile::Update( const float dTime )
00031 {
00032 MercuryODEObject::Update( dTime );
00033 }
00034
00035 bool Projectile::Collide( MercuryODEObject * pHit, dContact & pContact, MercuryODEWorld * pWorld )
00036 {
00037 if( m_pToNotify )
00038 {
00039 PStack pRet;
00040 PStack pArgs;
00041 pArgs.PushItemBack( PSElement( MString( pHit->GetName() ) ) );
00042 pArgs.PushItemBack( PSElement( (void*)pHit ) );
00043 pArgs.PushItemBack( PSElement( pContact.geom.pos[0] ) );
00044 pArgs.PushItemBack( PSElement( pContact.geom.pos[1] ) );
00045 pArgs.PushItemBack( PSElement( pContact.geom.pos[2] ) );
00046 pArgs.PushItemBack( PSElement( pContact.geom.normal[0] ) );
00047 pArgs.PushItemBack( PSElement( pContact.geom.normal[1] ) );
00048 pArgs.PushItemBack( PSElement( pContact.geom.normal[2] ) );
00049 m_pToNotify->Command( pRet, m_sMessage.c_str(), pArgs );
00050 }
00051
00052 return false;
00053 }
00054
00055 void Projectile::Message( int Message, PStack & data, const MString & name )
00056 {
00057 MercuryODEObject::Message( Message, data, name );
00058 }
00059
00060 void Projectile::EnableForShot( dSpaceID sID, float fLength, const MercuryPoint & pCenter, const MercuryPoint & pDirection )
00061 {
00062
00063
00064
00065 m_pRay = dCreateRay( sID, fLength );
00066 dGeomSetPosition( m_pRay, pCenter.x, pCenter.y, pCenter.z );
00067 dGeomSetData( m_pRay, this );
00068
00069 MQuaternion Q;
00070 MercuryPoint pFlatOrient = pDirection;
00071 pFlatOrient.z = 0;
00072 pFlatOrient.Normalize();
00073 MercuryPoint pAxis = MercuryPoint( 0,0,1 ).CrossProduct( pFlatOrient );
00074 if( pAxis.Magnitude() < 0.00001f )
00075 pAxis = MercuryPoint( 1,0,0 );
00076 pAxis.NormalizeSelf();
00077
00078 Q.CreateFromAxisAngle(pAxis, Q_PI/2 - ATAN2( pDirection.z,SQRT(1-pDirection.z*pDirection.z)));
00079 Q.normalize();
00080 dGeomSetQuaternion( m_pRay, &Q.w );
00081
00082 m_shpTracer.SetPosition( pCenter );
00083 m_shpTracer.SetRotationMode( RM_MATRIX );
00084 MercuryMatrix M;
00085 Q.toMatrix4( M );
00086 M.Translate(0,0,250);
00087 m_shpTracer.Tweening.AddCommand( "SetHide,0;diffuse,1,1,1,.7;linear,0.25;diffuse,1,1,1,.2;sleep,0;SetHide,1;" );
00088 m_shpTracer.SetAfterMatrix( M.Ptr() );
00089 }
00090
00091 void Projectile::Disable()
00092 {
00093 if( m_pRay )
00094 dGeomDestroy( m_pRay );
00095 m_pRay = 0;
00096 }
00097
00099
00100 void VirtualProjectile::Init()
00101 {
00102 MercuryODEObject::Init();
00103
00104 m_pRay = 0;
00105 m_pToNotify = 0;
00106 }
00107
00108 void VirtualProjectile::Disable()
00109 {
00110 if( m_pRay )
00111 dGeomDestroy( m_pRay );
00112 m_pRay = 0;
00113 }
00114
00115 void VirtualProjectile::EnableForShot( dSpaceID sID, float fLength, const MercuryPoint & pCenter, const MercuryPoint & pDirection )
00116 {
00117
00118
00119
00120 m_pRay = dCreateRay( sID, fLength );
00121 dGeomSetPosition( m_pRay, pCenter.x, pCenter.y, pCenter.z );
00122 dGeomSetData( m_pRay, this );
00123
00124 MQuaternion Q;
00125 MercuryPoint pFlatOrient = pDirection;
00126 pFlatOrient.z = 0;
00127 pFlatOrient.Normalize();
00128 MercuryPoint pAxis = MercuryPoint( 0,0,1 ).CrossProduct( pFlatOrient );
00129 if( pAxis.Magnitude() < 0.00001f )
00130 pAxis = MercuryPoint( 1,0,0 );
00131 pAxis.NormalizeSelf();
00132
00133 Q.CreateFromAxisAngle(pAxis, Q_PI/2 - ATAN2( pDirection.z,SQRT(1-pDirection.z*pDirection.z)));
00134 Q.normalize();
00135 dGeomSetQuaternion( m_pRay, &Q.w );
00136 }
00137
00138 bool VirtualProjectile::Collide( MercuryODEObject * pHit, dContact & pContact, MercuryODEWorld * pWorld )
00139 {
00140 if( m_pToNotify )
00141 {
00142 PStack pRet;
00143 PStack pArgs;
00144 pArgs.PushItemBack( PSElement( MString( pHit->GetName() ) ) );
00145 pArgs.PushItemBack( PSElement( (void*)pHit ) );
00146 pArgs.PushItemBack( PSElement( pContact.geom.pos[0] ) );
00147 pArgs.PushItemBack( PSElement( pContact.geom.pos[1] ) );
00148 pArgs.PushItemBack( PSElement( pContact.geom.pos[2] ) );
00149 pArgs.PushItemBack( PSElement( pContact.geom.normal[0] ) );
00150 pArgs.PushItemBack( PSElement( pContact.geom.normal[1] ) );
00151 pArgs.PushItemBack( PSElement( pContact.geom.normal[2] ) );
00152 m_pToNotify->Command( pRet, m_sMessage.c_str(), pArgs );
00153 }
00154
00155 return false;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186