MercuryTexture.cpp

Go to the documentation of this file.
00001 #include "global.h"
00002 #include "MercuryTexture.h"
00003 #include "MercuryLog.h"
00004 #include "MercuryFiles.h"
00005 #include "MercuryLog.h"
00006 #include "MercuryMath.h"
00007 #include "MercuryDisplay.h"
00008 
00009 //for PNG Loading
00010 #if defined(WIN32)
00011 #  include <png.h>
00012 #  if defined(_MSC_VER)
00013 #    pragma comment(lib, "libpng.lib")
00014 #  endif
00015 #  pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
00016 #else
00017 #  include <png.h>
00018 #endif
00019 
00020 //Add supported image formats to the loade along with their finger print.
00021 //ADDIMAGELOADER( LoadBMP, (*"BM8") );
00022 //ADDIMAGELOADER( LoadPNG, (*"‰PN") );
00023 
00024 #define     MC_TEXTUREID        1
00025 
00026 int ColorBytesToSize(ColorBytes cb)
00027 {
00028     switch (cb)
00029     {
00030     case LUMINANCE_ALPHA:
00031         return 2;
00032     case RGB:
00033         return 3;
00034     case DEPTH_COMPONENT24:
00035         return 3;
00036     case RGBA:
00037         return 4;
00038     case RGBA_FLOAT:
00039         return 16;
00040     default:
00041         ASSERT(!"Invalid Color Byte")
00042     };
00043     return 0;
00044 }
00045 
00046 MercuryTexture::MercuryTexture()
00047 :MercuryObject()
00048 {
00049     Init();
00050 }
00051 
00052 MercuryTexture::MercuryTexture(const MercuryTexture& texture)
00053 :MercuryObject()
00054 {
00055     Init();
00056     *this = texture;
00057 }
00058 
00059 MercuryTexture::~MercuryTexture()
00060 {
00061     SendRemoveMessage();
00062 }
00063 
00064 void MercuryTexture::Message( int Message, PStack & data, const MString & name )
00065 {
00066     switch ( Message ) 
00067     {
00068     case MC_TEXTUREID:
00069         {
00070             const MercuryTexture* t = (const MercuryTexture*)data.PeekItem(0).GetValueV();
00071             const ImageAttrs* imageAttrs = (const ImageAttrs*)data.PeekItem(1).GetValueV();
00072             if(this == t)
00073             {
00074                 m_imageAttrs = *imageAttrs;
00075                 SetMatrixTainted(true);
00076                 MercuryMessageHandler::UnregisterMessage( MC_TEXTUREID, "GetTextureID" );
00077                 m_state = LOADED;
00078             }
00079         }
00080         break;
00081     }
00082 }
00083 
00084 void MercuryTexture::AutoDestroy()
00085 {
00086     SendRemoveMessage();
00087     if (GetID() > 0)
00088         m_imageAttrs.m_ID = 0;
00089 }
00090 
00091 void MercuryTexture::SendRemoveMessage()
00092 {
00093     PStack stack;
00094     stack.PushItemBack(PSElement(GetPath()));
00095     stack.PushItemBack(PSElement((void*)this));
00096     MESSAGEMAN->PostSystemMessage("UnregisterTexture", stack, 0);
00097     m_state = UNLOADED;
00098 }
00099 
00100 void MercuryTexture::SendLoadMessage()
00101 {
00102     PStack stack;
00103     stack.PushItemBack(PSElement(GetPath()));
00104     stack.PushItemBack(PSElement((void*)this));
00105     MercuryMessageHandler::RegisterMessage( MC_TEXTUREID, "GetTextureID" );
00106     MESSAGEMAN->PostSystemMessage("LoadTexture", stack, 0);
00107     m_state = UNLOADED;
00108 }
00109 
00110 void MercuryTexture::SendLoadFromRaw(RawImageData* data)
00111 {
00112     PStack stack;
00113     stack.PushItemBack(PSElement(GetPath()));
00114     stack.PushItemBack(PSElement((void*)this));
00115     stack.PushItemBack(PSElement((void*)data));
00116     MercuryMessageHandler::RegisterMessage( MC_TEXTUREID, "GetTextureID" );
00117     MESSAGEMAN->PostSystemMessage("LoadTextureRaw", stack, 0);
00118     m_state = UNLOADED;
00119 }
00120 
00121 void MercuryTexture::operator=(const MercuryTexture& texture)
00122 {
00123     if (!texture.m_path.empty())
00124     {
00125         //If we have an ID we should unregister
00126         if (GetID() > 0)
00127             SendRemoveMessage();
00128     
00129         m_attrs = texture.m_attrs;
00130         m_imageAttrs = texture.m_imageAttrs;
00131 
00132         //We need to register this texture incase the previous one is destroyed
00133         SendLoadMessage();
00134     }
00135 }
00136 
00137 void RawImageData::CorrectSize()
00138 {
00139     attrs.m_width_original = attrs.m_width;
00140     attrs.m_height_original = attrs.m_height;
00141 
00142     //cube maps have 6 times as much shit in the data as everything else
00143     if (attrs.m_cube)
00144     {
00145         printf ("*******CorrectSize:\npdata = %lu\nwidth = %lu\nheight = %lu\ncolorbytes = %lu\nCorrectSize\n", data, attrs.m_width, attrs.m_height, (unsigned int)(ColorBytesToSize(attrs.m_ColorByteType)));
00146         return;
00147     }
00148     
00149     attrs.m_height = makePow2(attrs.m_height);
00150     attrs.m_width = makePow2(attrs.m_width);
00151 
00152     attrs.m_resizeFactor.SetX( (float)attrs.m_width_original / attrs.m_width );
00153     attrs.m_resizeFactor.SetY( (float)attrs.m_height_original / attrs.m_height );
00154 
00155     unsigned char* resized;
00156     int chunk = attrs.m_width_original * ColorBytesToSize(attrs.m_ColorByteType);
00157     int newchunk = attrs.m_width * ColorBytesToSize(attrs.m_ColorByteType);
00158     int newsize = attrs.m_height * attrs.m_width * ColorBytesToSize(attrs.m_ColorByteType);
00159 
00160     if ((attrs.m_height_original != attrs.m_height) || (attrs.m_width_original != attrs.m_width))
00161     {
00162         resized = new unsigned char[newsize];
00163 
00164         memset(resized, 0, newsize);
00165         for (unsigned int i = 0; i < (unsigned)attrs.m_height_original; i++)
00166         {
00167             memcpy(&resized[i * newchunk], &data[i * chunk], chunk); 
00168         }
00169         SAFE_DELETE(data);
00170         data = new unsigned char[newsize];
00171         memcpy(data, resized, newsize);
00172         SAFE_DELETE(resized);
00173     }
00174 }
00175 
00176 void RawImageData::ToRGBA()
00177 {
00178     if (data == NULL)   
00179     {
00180         LOG.Warn("Texture data null, not converting to RGBA.");
00181         return;
00182     }
00183 
00184     const unsigned int size = attrs.m_width*attrs.m_height*ColorBytesToSize(RGBA);
00185     unsigned char* tmpdata = new unsigned char[size];
00186     switch(attrs.m_ColorByteType)
00187     {
00188     case RGB:
00189         {
00190 //          unsigned int osize = GetWidth()*GetHeight()*RGB;
00191             unsigned int opos = 0;
00192             for (unsigned int i = 0; i < size; i++)
00193             {
00194                 if(((i+1)%4) == 0)
00195                 {
00196                     tmpdata[i] = 255; //alpha
00197                 }
00198                 else
00199                 {
00200                     tmpdata[i] = data[opos++];
00201                 }
00202             }
00203             SAFE_DELETE(data);
00204             attrs.m_ColorByteType = RGBA;
00205             data = new unsigned char[size];
00206             memcpy(data, tmpdata, size);
00207         }
00208         break;
00209     default:
00210         break;
00211     }
00212     SAFE_DELETE(tmpdata);
00213 }
00214 
00215 void MercuryTexture::CalculateMatrices()
00216 {
00217     if ( IsMatrixTainted() )
00218     {
00219         m_localMatrix.Identity();
00220 
00221         MercuryPoint scale = GetScale()*m_imageAttrs.m_resizeFactor;
00222         const MercuryPoint& position = GetPosition();
00223         const MercuryPoint& rotation = GetRot();
00224 
00225         if( GetRotMode() == RM_NORMAL )
00226         {
00227             m_localMatrix.Transotale( position.x, position.y, position.z,
00228                                         rotation.x, rotation.y, rotation.z,
00229                                         scale.x, scale.y, scale.z );
00230             SetMatrixTainted(false);
00231         }
00232         else
00233         {
00234 
00235             m_localMatrix.Translate(position.x, position.y, position.z);
00236 
00237             switch ( GetRotMode() )
00238             {
00239             case RM_OFF:
00240                 break;
00241             case RM_BILLBOARD:
00242                 {
00243                     static const MercuryPoint look(0,0,1);
00244                     static MercuryPoint directionProj;
00245                     static float angle;
00246                     static MercuryPoint axis;
00247                     static MercuryMatrix world;
00248 
00249                     //http://www.lighthouse3d.com/opengl/billboarding/index.php?billCyl
00250                     directionProj = GetGlobalPosition() - DISPLAY->GetLastCameraPosition();
00251                     directionProj.NormalizeSelf();
00252 
00253                     axis = look.CrossProduct(directionProj);
00254                     angle = ACOS(DotProduct(look, directionProj));
00255 
00256                     //The destroys the previous matrix
00257                     world.RotateAngAxis(angle*RADDEG, axis.x, axis.y, axis.z);
00258 
00259                     m_localMatrix *= world;
00260                 }
00261                 break;
00262             case RM_MATRIX:
00263                 m_localMatrix *= GetAfterMatrix();
00264                 break;
00265             case RM_QUATERNION:
00266                 {
00267                     MercuryMatrix m;
00268                     GetRotationQuaternion().toMatrix4(m);
00269                     m_localMatrix *= m;
00270                 }
00271                 break;
00272             default:
00273                 break;
00274             };
00275 
00276             m_localMatrix.Scale(scale.x, scale.y, scale.z);
00277             SetMatrixTainted(false);
00278         }
00279     }
00280 
00281     m_finalMatrix = TextureStack.GetTop() *= m_localMatrix;
00282 }
00283 
00284 void MercuryTexture::Prerender()
00285 {
00286     TextureStack.Push();
00287     CalculateMatrices();
00288     TextureStack.Pop();
00289 }
00290 
00291 
00292 void CaclulateDiv2Texture( const RawImageData & riIn, RawImageData & riOut )
00293 {
00294     riOut.attrs.m_ColorByteType = riIn.attrs.m_ColorByteType;
00295     unsigned cbsize = ColorBytesToSize( riIn.attrs.m_ColorByteType );
00296 
00297     if( riIn.attrs.m_height != 1 && riIn.attrs.m_width != 1 )
00298     {
00299         unsigned oHeight = riOut.attrs.m_height = riIn.attrs.m_height / 2;
00300         unsigned oWidth = riOut.attrs.m_width = riIn.attrs.m_width / 2;
00301         riOut.data = new unsigned char[riOut.attrs.m_width * riOut.attrs.m_height * cbsize];
00302 
00303         for( unsigned y = 0; y < riOut.attrs.m_height; ++y )
00304             for( unsigned x = 0; x < riOut.attrs.m_width; ++x )
00305                 for( unsigned b = 0; b < cbsize; ++b )
00306                 {
00307                     riOut.data[(x+y*oWidth)*cbsize + b] = (
00308                         (unsigned)riIn.data[((x*2+y*2*riIn.attrs.m_width))*cbsize + b] +
00309                         (unsigned)riIn.data[((x*2)+1+y*2*riIn.attrs.m_width)*cbsize + b] +
00310                         (unsigned)riIn.data[(x*2+(y*2+1)*riIn.attrs.m_width)*cbsize + b] +
00311                         (unsigned)riIn.data[((x*2)+1+(y*2+1)*riIn.attrs.m_width)*cbsize + b] ) / 4;
00312                 }
00313     } else if( riIn.attrs.m_height != 1 )
00314     {
00315         unsigned oHeight = riOut.attrs.m_height = riIn.attrs.m_height / 2;
00316         unsigned oWidth = riOut.attrs.m_width = riIn.attrs.m_width;
00317         riOut.data = new unsigned char[riOut.attrs.m_width * riOut.attrs.m_height * cbsize];
00318 
00319         for( unsigned y = 0; y < riOut.attrs.m_height; ++y )
00320             for( unsigned x = 0; x < riOut.attrs.m_width; ++x )
00321                 for( unsigned b = 0; b < cbsize; ++b )
00322                 {
00323                     riOut.data[(x+y*oWidth)*cbsize + b] = (
00324                         (unsigned)riIn.data[(x*2+y*2*riIn.attrs.m_width)*cbsize + b] +
00325                         (unsigned)riIn.data[(x*2+(y+1)*2*riIn.attrs.m_width)*cbsize + b] ) / 2;
00326                 }
00327     } else if( riIn.attrs.m_width != 1 )
00328     {
00329         unsigned oHeight = riOut.attrs.m_height = riIn.attrs.m_height;
00330         unsigned oWidth = riOut.attrs.m_width = riIn.attrs.m_width / 2;
00331         riOut.data = new unsigned char[riOut.attrs.m_width * riOut.attrs.m_height * cbsize];
00332 
00333         for( unsigned y = 0; y < riOut.attrs.m_height; ++y )
00334             for( unsigned x = 0; x < riOut.attrs.m_width; ++x )
00335                 for( unsigned b = 0; b < cbsize; ++b )
00336                 {
00337                     riOut.data[(x+y*oWidth)*cbsize + b] = (
00338                         (unsigned)riIn.data[(x*2+y*2*riIn.attrs.m_width)*cbsize + b] +
00339                         (unsigned)riIn.data[((x+1)*2+y*2*riIn.attrs.m_width)*cbsize + b] ) / 2;
00340                 }
00341     }
00342 }
00343 
00344 /* (c) 2005 Joshua Allen
00345  * (c) 2006 Charles Lohr
00346  * All rights reserved.
00347  * 
00348  * Permission is hereby granted, free of charge, to any person obtaining a
00349  * copy of this software and associated documentation files (the
00350  * "Software"), to deal in the Software without restriction, including
00351  * without limitation the rights to use, copy, modify, merge, publish,
00352  * distribute, and/or sell copies of the Software, and to permit persons to
00353  * whom the Software is furnished to do so, provided that the above
00354  * copyright notice(s) and this permission notice appear in all copies of
00355  * the Software and that both the above copyright notice(s) and this
00356  * permission notice appear in supporting documentation.
00357  * 
00358  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00359  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00360  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
00361  * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
00362  * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
00363  * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
00364  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
00365  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00366  * PERFORMANCE OF THIS SOFTWARE.
00367  */

Hosted by SourceForge.net Logo