MercuryDisplay.cpp

Go to the documentation of this file.
00001 #include "global.h"
00002 #include "MercuryDisplay.h"
00003 #include "MercuryLog.h"
00004 #include "MercuryUtil.h"
00005 #include "MercuryINI.h"
00006 #include "MercuryMath.h"
00007 #include "MercuryTexture.h"
00008 #include "BMPWriter.h"
00009 
00010 #if !defined(_EE)
00011 #if !defined(USE_FRAMEBUFFER)
00012 #include "MercuryOGL.h"
00013 #endif
00014 #include "MercuryDisplaySoftwareC.h"
00015 #else
00016 #include "MercuryDisplayEE.h"
00017 #endif
00018 
00019 
00020 #include "MercuryInput.h"
00021 
00022 #if defined (WIN32)
00023 #include "Win32Window.h"
00024 #if defined( USE_D3D )
00025 #include "MercuryDisplay_D3D.h"
00026 #endif
00027 #else
00028 #if !defined(_EE)
00029 #if !defined(USE_FRAMEBUFFER)
00030 #include "MercuryWindowSDL.h"
00031 #else
00032 #include "MercuryWindowFB.h"
00033 #endif
00034 #else
00035 #include "MercuryWindowEE.h"
00036 #endif
00037 #endif
00038 
00039 #if defined(_MSC_VER) && (_MSC_VER > 1100)
00040     #pragma warning (disable : 4786) //char truncation dealing with MStrings
00041 #endif
00042 
00043 MercuryMatrixStack WorldStack;
00044 //MercuryMatrixStack ViewStack;
00045 MercuryMatrixStack TextureStack;
00046 
00047 KeyMappingWithCode( print_scr, "0-316" );
00048 
00049 REGISTER_STATEMENT_TO_MESSAGE( quit, quit, DISPLAY->CloseNextCycle(); )
00050 REGISTER_STATEMENT_TO_COMMAND( quit, DISPLAY->CloseNextCycle(); )
00051 
00052 REGISTER_STATEMENT_TO_MESSAGE( screenshot, mappedinput,
00053                               InputMessageStruct c(args);
00054                             if (c.code == print_scr && c.type == IET_RELEASE )
00055                                 DISPLAY->TakeScreenShot();
00056 )
00057 
00058 MercuryDisplay::MercuryDisplay()
00059 :m_renderObjects(200)
00060 {
00061     m_framesDrawn = 0;
00062     m_verticesDrawn = 0;
00063     m_bCloseNextCycle = 0;
00064     m_maxTextures = 1;
00065     m_maxLights = 0;
00066     m_initalized = false;
00067     m_maxDrawBuffers = m_maxVertexAttributes = m_maxTextureCoordinates =
00068     m_maxShaderVertUniformComponents = m_maxShaderFragUniformComponents =
00069     m_shaderLanngVersion = 0;
00070     m_maxAnisotropy = 0;
00071 
00072     m_based_width = PREFSMAN->GetValueI( "Rendering", "BasedWidth", InitialDisplayProperties::InitialBasedWidth, true );
00073     m_based_height = PREFSMAN->GetValueI( "Rendering", "BasedHeight", InitialDisplayProperties::InitialBasedHeight, true );
00074     
00075     m_window = NULL;
00076 
00077     m_disableTextures = false;
00078     m_useMaterialColors = true;
00079 }
00080 
00081 MercuryDisplay::~MercuryDisplay()
00082 {
00083     SAFE_DELETE(m_window);
00084     m_globalState.pop_back(); //prevents crash
00085 }
00086 
00087 void* MercuryDisplay::ThreadCallback(void* display)
00088 {
00089     ((MercuryDisplay*)display)->ThreadLoop();
00090     return NULL;
00091 }
00092 
00093 void MercuryDisplay::CreateThread()
00094 {
00095 #if !defined( NO_THREADS )
00096     m_thread.Create(MercuryDisplay::ThreadCallback, this);
00097 #endif
00098 }
00099 
00100 void MercuryDisplay::ThreadLoop()
00101 {
00102     if ( !DISPLAY->Init(
00103         PREFSMAN->GetValueS( "Window", "Name", "Mercury Engine", true ).c_str(),
00104         PREFSMAN->GetValueI( "Window", "Width", 640, true ),
00105         PREFSMAN->GetValueI( "Window", "Height", 480, true ),
00106         PREFSMAN->GetValueI( "Window", "BPP", 32, true ),
00107         PREFSMAN->GetValueB( "Window", "Fullscreen", false, true )
00108         ) )
00109     {
00110         LOG.Warn("Failed to initalize display.");
00111         ASSERT(!"Failed to initalize display.");
00112     }
00113 
00114     while(true)
00115     {
00116     }
00117 }
00118 
00119 bool MercuryDisplay::Init(const MString& name, unsigned int width, unsigned int height, unsigned short bpp, bool fullscreen)
00120 {
00121     m_initalized = true;
00122     m_view.Identity();
00123 
00124 #if defined (WIN32)
00125     AttachWindow(new Win32Window);
00126 #else
00127 
00128 #if !defined(_EE)
00129 #if !defined(USE_FRAMEBUFFER)
00130     AttachWindow(new MercuryWindowSDL);
00131 #else
00132     AttachWindow(new MercuryWindowFB);
00133 #endif
00134 #else
00135     AttachWindow(new MercuryWindowEE);
00136 #endif
00137 
00138 #endif
00139     if ( !MakeWindow(name, width, height, bpp, fullscreen) )
00140     {
00141         LOG.Warn("Failed to make window.");
00142         return false;
00143     }
00144 
00145     MercuryGLState gls;
00146     gls.Enable(MGLS_ALL);
00147     m_globalState.push_front(gls);
00148     m_currentState = gls;
00149     gls.Disable(MGLS_ALL);
00150     SetStates(gls);
00151 
00152     return true;
00153 }
00154 
00155 bool MercuryDisplay::Update(const float dTime)
00156 {
00157     double age = m_timer.Age();
00158 
00159     if (m_window != NULL)
00160         if (!m_window->Update(dTime))
00161             return false;
00162 
00163     if ( m_window->HasFocus() != m_bLastHadFocus )
00164     {
00165         m_bLastHadFocus = m_window->HasFocus();
00166         MESSAGEMAN->BroadcastMessage( "changefocus", PStack( PSElement( m_bLastHadFocus ) ) );
00167     }
00168 
00169     if (age >= 0.5)
00170     {
00171         m_timer.Touch();
00172         PStack stats;
00173         stats.PushItemBack( PSElement ((float)(m_verticesDrawn/age)) ); //VPS
00174         stats.PushItemBack( PSElement ((float)(m_verticesDrawn/(float)m_framesDrawn)) ); //VPF
00175         stats.PushItemBack( PSElement ((float)(m_framesDrawn/age)) ); //FPS
00176 
00177         //Post this message and deal with it later
00178         MESSAGEMAN->PostSystemMessage( "RenderStats", stats, 0 );
00179 
00180         m_framesDrawn = 0;
00181         m_verticesDrawn = 0;
00182     }
00183 
00184     return !m_bCloseNextCycle;
00185 }
00186 
00187 void MercuryDisplay::Resize(int width, int height)
00188 {
00189     if (height <= 0)
00190         height = 1;
00191 
00192     if (width <= 0)
00193         width = 1;
00194 
00195     m_window->SetDemensions(width, height);
00196 
00198     Viewport(0, 0, width, height);
00199 
00200     //Don't do anything if we are minimizing.
00201     if ( !m_window->IsMinimized() )
00202     {
00203         if ((width > 1) && (height > 1))
00204         {
00205             DisplayDimensions dimensions = GetDimensions();
00206             MESSAGEMAN->BroadcastMessage( "DisplayResized", PStack( PSElement( dimensions.height ), PSElement( dimensions.width) ) );
00207         }
00208     }
00209 }
00210 
00211 void MercuryDisplay::SetProjection(const Projection& projection)
00212 {
00213     m_projection = projection;
00214     ResetFrustumClippingPlanes();
00215     SendProjectionMatrixData();
00216 }
00217 
00218 bool MercuryDisplay::AttachWindow(MercuryWindow* window)
00219 {
00220     SAFE_DELETE(m_window);
00221     m_window = window;
00222 
00223     return true;
00224 }
00225 
00226 bool MercuryDisplay::MakeWindow(const char* title, int width, int height, int bits, bool fullscreenflag)
00227 {
00228     RendererInfo();
00229     Resize(m_window->GetWidth(), m_window->GetHeight());
00230 
00231     return true;
00232 }
00233 
00234 DisplayDimensions MercuryDisplay::GetDimensions() const
00235 {
00236     DisplayDimensions dimensions;
00237     dimensions.width = (float)m_window->GetWidth();
00238     dimensions.height = (float)m_window->GetHeight();
00239     return dimensions;
00240 }
00241 
00242 DisplayDimensions MercuryDisplay::GetBasedDimensions() const
00243 {
00244     DisplayDimensions dimensions;
00245     dimensions.width = (float)m_based_width;
00246     dimensions.height = (float)m_based_height;
00247     return dimensions;
00248 }
00249 
00250 void MercuryDisplay::LookAt( float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ )
00251 {
00252     MercuryPoint eye(eyeX,eyeY,eyeZ);
00253     MercuryPoint center(centerX,centerY,centerZ);
00254     MercuryPoint up(upX,upY,upZ);
00255 
00256     LookAt(eye, center, up);
00257 }
00258 
00259 MercuryPoint MercuryDisplay::GetLastCameraPosition( )
00260 {
00261     return m_pLastCameraPos;
00262 }
00263 
00264 void MercuryDisplay::LookAt(const MercuryPoint& eye, const MercuryPoint& center,
00265                     const MercuryPoint& up)
00266 {
00267     LookAtInternals lai = CalculateLookAtMatrix(eye, center, up, m_view);
00268     m_pLastCameraPos = eye;
00269     SetupClippingPlanes( eye, lai.m_direction, lai.m_up, lai.m_x );
00270 }
00271 
00272 LookAtInternals CalculateLookAtMatrix(const MercuryPoint& eye, const MercuryPoint& center,
00273                     const MercuryPoint& up, MercuryMatrix& m)
00274 {
00275     MercuryPoint viewDirection = (center-eye).Normalize(); //direction vector
00276 
00277     MercuryPoint viewX = viewDirection.CrossProduct( up.Normalize() ); //x axis
00278     viewX.NormalizeSelf();
00279 
00280     MercuryPoint viewUp = viewX.CrossProduct( viewDirection ); //real up
00281     viewUp.NormalizeSelf();
00282 
00283     m.Identity();
00284 
00285     //row major
00286     m[0][0] = viewX.GetX();
00287     m[0][1] = viewX.GetY();
00288     m[0][2] = viewX.GetZ();
00289 
00290     m[1][0] = viewUp.GetX();
00291     m[1][1] = viewUp.GetY();
00292     m[1][2] = viewUp.GetZ();
00293 
00294     m[2][0] = -viewDirection.GetX();
00295     m[2][1] = -viewDirection.GetY();
00296     m[2][2] = -viewDirection.GetZ();
00297 
00298     m.Translate( -eye.GetX(), -eye.GetY(), -eye.GetZ() );
00299 
00300     return LookAtInternals(viewDirection, viewX, viewUp);
00301 }
00302 
00303 void MercuryDisplay::SetupClippingPlanes(const MercuryPoint& position, MercuryPoint F, MercuryPoint u, MercuryPoint s )
00304 {
00305     u.NormalizeSelf();
00306     F.NormalizeSelf();
00307     s.NormalizeSelf();
00308     //Set up the view planes.
00309     //NEAR
00310     m_nViewPlanes[0] = MercuryPoint(0,0,0)-F;   //SPECIAL: The eye does not lie on this plane
00311     //FAR
00312     m_nViewPlanes[1] = F;   //SPECIAL: The eye does not lie on this plane either.
00313 
00314     MercuryMatrix mNormalRot;
00315 
00316     //Sanity check code for RotateAngAxis
00317 /*  MercuryPoint pRight;
00318     MercuryPoint pOut;
00319     pRight = MercuryPoint( 0,0,1 );
00320     mNormalRot.RotateAngAxis( 45, 1,0,0 );
00321     VectorRotate( pRight, mNormalRot, pOut );*/
00322     
00323     mNormalRot.RotateAngAxis( -m_projection.m_frustumInfo.m_fov/2, s.x, s.y, s.z );
00324     VectorRotate( MercuryPoint()-u, mNormalRot, m_nViewPlanes[2] );
00325 
00326     mNormalRot.Identity();
00327     mNormalRot.RotateAngAxis( m_projection.m_frustumInfo.m_fov/2, s.x, s.y, s.z  );
00328     VectorRotate( u, mNormalRot, m_nViewPlanes[3] );
00329 
00330     mNormalRot.Identity();
00331     mNormalRot.RotateAngAxis( m_projection.m_frustumInfo.m_fov/2 * m_projection.m_frustumInfo.m_aspect, u.x, u.y, u.z );
00332     VectorRotate( MercuryPoint()-s, mNormalRot, m_nViewPlanes[4] );
00333 
00334     mNormalRot.Identity();
00335     mNormalRot.RotateAngAxis( -m_projection.m_frustumInfo.m_fov/2 * m_projection.m_frustumInfo.m_aspect, u.x, u.y, u.z );
00336     VectorRotate( s, mNormalRot, m_nViewPlanes[5] );
00337 
00338     m_pNearPoint = F * m_projection.m_frustumInfo.m_znear + position;
00339     m_pFarPoint = F * m_projection.m_frustumInfo.m_zfar + position;
00340 }
00341 
00342 void MercuryDisplay::LookAt(const MQuaternion& q, const MercuryPoint& eye)
00343 {
00344     MercuryMatrix& view = m_view;
00345 //  view.Identity();
00346     q.toMatrix4(view);
00347 
00348     view.Translate( -eye.GetX(), -eye.GetY(), -eye.GetZ() );
00349     m_pLastCameraPos = eye;
00350     SetupClippingPlanes( eye, MercuryPoint(0,0,0)-MercuryPoint(view[2]), view[1], view[0] );
00351 }
00352 
00353 void MercuryDisplay::ResetFrustumClippingPlanes()
00354 {
00355     m_pLastCameraPos = MercuryPoint(0,0,0);
00356     SetupClippingPlanes( MercuryPoint(0,0,0), MercuryPoint( 0,0,-1 ), MercuryPoint( 0,1, 0 ), MercuryPoint(1,0,0 ) );
00357 }
00358 
00359 bool MercuryDisplay::IsVisible( const MercuryPoint & pCenter, float fRadius, const MercuryMatrix& world )
00360 {
00361     if ( fRadius < 0 )
00362         return true;
00363 
00364     const float * f = world.Ptr();
00365     MercuryPoint pAdjustedCenter(f[3], f[7], f[11]);
00366 
00367     if ( (DotProduct(m_nViewPlanes[0],(pAdjustedCenter-m_pNearPoint))) > fRadius )
00368         return false;
00369     if ( (DotProduct(m_nViewPlanes[1],(pAdjustedCenter-m_pFarPoint))) > fRadius )
00370         return false;
00371     if ( (DotProduct(m_nViewPlanes[2],(pAdjustedCenter-m_pLastCameraPos))) > fRadius )
00372         return false;
00373     if ( (DotProduct(m_nViewPlanes[3],(pAdjustedCenter-m_pLastCameraPos))) > fRadius )
00374         return false;
00375     if ( (DotProduct(m_nViewPlanes[4],(pAdjustedCenter-m_pLastCameraPos))) > fRadius )
00376         return false;
00377     if ( (DotProduct(m_nViewPlanes[5],(pAdjustedCenter-m_pLastCameraPos))) > fRadius )
00378         return false;
00379 
00380     return true;
00381 }
00382 
00383 void MercuryDisplay::AddLight(MercuryLight* light)
00384 {
00385     ASSERT(light->IsInitalized());
00386     m_lights.push_back(light);
00387 }
00388 
00389 void MercuryDisplay::RemoveLight(MercuryLight* light)
00390 {
00391     for( unsigned int i = 0; i < m_lights.size(); ++i)
00392         if (m_lights[i] == light)
00393         {
00394             m_lights.remove(i);
00395             return;
00396         }
00397 }
00398 
00399 void MercuryDisplay::TakeScreenShot()
00400 {
00401     RawImageData image;
00402     DISPLAY->ReadFrameBuffer(image);
00403     int ssn = PREFSMAN->GetValueI("Data", "ScreenShotNum", 0, true);
00404     //XXX: put screenshots in a folder
00405     WriteBMP(ssprintf("screenshot%d.bmp", ssn), image);
00406     PREFSMAN->SetValue("Data", "ScreenShotNum", ssprintf("%d", ++ssn));
00407     SAFE_DELETE(image.data);
00408     LOG.Log("screen shot");
00409 }
00410 
00411 MercuryDisplay* MakeDisplayDriver()
00412 {
00413     MString sDisplayDriver = PREFSMAN->GetValueS( "Options", "DisplayDriver", "OGL", true );
00414 #if !defined(_EE) && !defined(USE_FRAMEBUFFER)
00415     if ( sDisplayDriver == "OGL" )
00416         return new MercuryOGL();
00417 #if defined( WIN32 )
00418 #if defined( USE_D3D )
00419     if ( sDisplayDriver == "D3D" )
00420         return new MercuryDisplay_D3D();
00421 #endif
00422 #endif
00423 #elif defined(_EE)
00424     return new MercuryDisplayEE();
00425 #endif
00426     if ( sDisplayDriver == "SWC" )
00427         return new MercuryDisplaySoftwareC();
00428 
00429     LOG.Warn( "Cannot make display driver.  Pick OGL." );
00430     mercury_crash( "Cannot make display driver.  Pick OGL." );
00431     return NULL;        //Not like we'll get here
00432 }
00433 
00434 void MercuryDisplay::AddTranslucentObject(MercuryObject* obj)
00435 {
00436     //sort furthest to nearest
00437     const MercuryMatrix& m = obj->GetFinalMatrix();
00438     TranslucentPair p;
00439     MercuryPoint gp(m[0][3], m[1][3], m[2][3]);
00440     p.dist = -(gp - GetLastCameraPosition()).Magnitude();
00441     p.obj = obj;
00442     m_translucentObjects.push_back(p);
00443 
00444     TSortDrawOrder(m_translucentObjects);
00445 }
00446 
00447 MercuryPoint PointToScreenCoord(const MercuryMatrix& proj, const MercuryMatrix& view, const MercuryPoint& p, const DisplayDimensions& bd)
00448 {
00449     float ip[4];
00450     float a[4];
00451     MercuryMatrix mFinal;
00452     MercuryPoint tmp;
00453 
00454     mFinal = proj * view;
00455 
00456     ip[0] = p.x;
00457     ip[1] = p.y;
00458     ip[2] = p.z;
00459     ip[3] = 1;
00460 
00461     VectorMultiply4f( mFinal.Ptr(), ip, a );
00462 
00463     //Divide-by-perspective step
00464     tmp.x = a[0]/a[3];
00465     tmp.y = a[1]/a[3];
00466     tmp.z = a[2]/fabs(a[3]);
00467 
00468     //we don't want real window coordinates, we only want the
00469     //coordinates for the base resolution we are in
00470 /*
00471     tmp.x *= (m_VPwidth - m_VPx)/2.0f;
00472     tmp.x += (m_VPwidth)/2.0f;
00473     tmp.y *= (m_VPy - m_VPheight)/2.0f;
00474     tmp.y += (m_VPheight)/2.0f;
00475 */
00476 
00477     tmp.x *= (bd.width)/2.0f;
00478     tmp.x += (bd.width)/2.0f;
00479     tmp.y *= (-bd.height)/2.0f;
00480     tmp.y += (bd.height)/2.0f;
00481 
00482     return tmp;
00483 }
00484 
00485 void MercuryDisplay::Viewport(int x, int y, int width, int height)
00486 {
00487     m_VPx = x;
00488     m_VPy = y;
00489     m_VPwidth = width;
00490     m_VPheight = height;
00491 }
00492 
00493 void MercuryDisplay::FindLights(const MercuryMatrix& world, float radius)
00494 {
00495     m_foundLights.clear();
00496 
00497     if ( radius < 0 )
00498         return;
00499 
00500     const float * f = world.Ptr();
00501     MercuryPoint objectPosition(f[3], f[7], f[11]);
00502 
00503     for (unsigned int i = 0; i < m_lights.size(); ++i)
00504     {
00505         float x = (objectPosition - m_lights[i]->GetPosition()).Magnitude();
00506         float y = m_lights[i]->GetRadius() + radius;
00507 
00508         if (m_lights[i]->GetLightType() == LT_DIRECTIONAL)
00509             m_foundLights.push_back(m_lights[i]);
00510         else if ( x < y )
00511             m_foundLights.push_back(m_lights[i]);
00512     }
00513 //  printf("picked:%d %d\n", m_foundLights.size(), m_lights.size());
00514 }
00515 
00516 int MercuryDisplay::Next3Lights(const MercuryLight* light[3], unsigned int& count)
00517 {
00518     unsigned int i;
00519     if (m_currentState.GetState(MGLS_LIGHTING))
00520     {
00521         for (i = 0; i < 3; ++i)
00522                 light[i] = NULL;
00523         for (i = 0; (i < 3) && (count+i < m_foundLights.size()); ++i)
00524                 light[i] = m_foundLights[count+i];
00525         count += i;
00526         return m_foundLights.size() - count;
00527     }
00528     return 0;
00529 }
00530 
00531 MercuryGLState MercuryDisplay::SetStates(MercuryGLState states)
00532 {
00533     MercuryGLState newstate = m_globalState.back()&states;
00534     MercuryGLState changedStates = m_currentState^newstate;
00535     m_currentState = newstate;
00536     return changedStates;
00537 }
00538 
00539 void MercuryDisplay::SetView(const MercuryPoint& position, const MercuryMatrix& m, const LookAtInternals& lai)
00540 {
00541     m_view = m;
00542     m_pLastCameraPos = position;
00543     SetupClippingPlanes(position, lai.m_direction, lai.m_up, lai.m_x);
00544 }
00545 
00546 void MercuryDisplay::EnqueueObject(const RenderPacket& rp)
00547 {
00548     m_renderObjects.push_back(rp);
00549 }
00550 
00551 Projection Perspective( float fov, float aspect, float znear, float zfar )
00552 {
00553     Projection p;
00554     p.m_frustumInfo.m_fov = fov;
00555     p.m_frustumInfo.m_aspect = aspect;
00556     p.m_frustumInfo.m_znear = znear;
00557     p.m_frustumInfo.m_zfar = zfar;
00558 
00559     float xmin, xmax, ymin, ymax;
00560 
00561     ymax = znear * TAN(fov * Q_PI / 360.0);
00562     ymin = -ymax;
00563     xmin = ymin * aspect;
00564     xmax = ymax * aspect;
00565 
00566     p.m_matrix = Frustum(xmin, xmax, ymin, ymax, znear, zfar);
00567     return p;
00568 }
00569 
00570 Projection Ortho(float left, float right, float bottom, float top, float zNear, float zFar)
00571 {
00572     Projection p;
00573     MercuryMatrix& PERSP = p.m_matrix;
00574 
00575     //row major
00576     PERSP[0][0] = 2/(right-left);
00577     PERSP[0][3] = -(right+left)/(right-left);
00578     PERSP[1][1] = 2/(top-bottom);
00579     PERSP[1][3] = -(top+bottom)/(top-bottom);
00580     PERSP[2][2] = -2/(zFar-zNear);
00581     PERSP[2][3] = (zFar + zNear)/(zFar-zNear);
00582     PERSP[3][3] = 1;
00583 
00584     return p;
00585 }
00586 
00587 MercuryMatrix Frustum(float left, float right, float bottom, float top, float zNear, float zFar)
00588 {
00589     //http://pyopengl.sourceforge.net/documentation/manual/glFrustum.3G.html
00590 
00591     MercuryMatrix frustum;
00592 
00593     float near2 = 2*zNear;
00594     float rml = right-left;
00595     float tmb = top - bottom;
00596     float fmn = zFar - zNear;
00597 
00598     float A = (right+left)/rml;
00599     float B = (top+bottom)/tmb;
00600     float C = -(zFar+zNear)/fmn;
00601     float D = -(near2*zFar)/fmn;
00602 
00603     frustum.Zero();
00604 
00605     //row major
00606     frustum[0][0] = near2/rml;
00607     frustum[0][2] = A;
00608     frustum[1][1] = near2/tmb;
00609     frustum[1][2] = B;
00610     frustum[2][2] = C;
00611     frustum[2][3] = D;
00612     frustum[3][2] = -1;
00613 
00614     return frustum;
00615 }
00616 
00617 MercuryDisplay * GetDisplay()
00618 {
00619     return DISPLAY;
00620 }
00621 
00622 /* 
00623  * Copyright (c) 2005-2006 Joshua Allen
00624  * All rights reserved.
00625  *
00626  * Redistribution and use in source and binary forms, with or
00627  * without modification, are permitted provided that the following
00628  * conditions are met:
00629  *  -   Redistributions of source code must retain the above
00630  *      copyright notice, this list of conditions and the following disclaimer.
00631  *  -   Redistributions in binary form must reproduce the above copyright
00632  *      notice, this list of conditions and the following disclaimer in
00633  *      the documentation and/or other materials provided with the distribution.
00634  *  -   Neither the name of the Mercury Engine nor the names of its
00635  *      contributors may be used to endorse or promote products derived from
00636  *      this software without specific prior written permission.
00637  *
00638  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00639  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00640  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00641  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00642  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00643  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00644  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00645  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00646  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00647  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00648  */

Hosted by SourceForge.net Logo