00001 #include "lugre_prefix.h"
00002 #include "lugre_texatlas.h"
00003 #include <stdlib.h>
00004 #include <Ogre.h>
00005
00006
00007
00008 namespace Lugre {
00009
00010
00011
00012
00013
00014 cTexAtlas::cTexAtlas (const int iW,const int iH, const int iMaxSubW, const int iMaxSubH)
00015 : miW(iW), miH(iH), miMaxSubW(iMaxSubW), miMaxSubH(iMaxSubH), miMinFreeSpaceSize(8) {
00016
00017 miFormat = Ogre::PF_BYTE_RGBA;
00018
00019 mData.resize(miW*miH,0);
00020
00021 miCurrentLineH = -1;
00022 miBrushX = 0;
00023 miBrushY = 0;
00024
00025
00026 }
00027
00028 bool cTexAtlas::AddImage (Ogre::Image& pSrc,Ogre::Rectangle& pOutTexCoords,const int iBorderPixels,const bool bWrap) {
00029
00030 int w = pSrc.getWidth();
00031 int h = pSrc.getHeight();
00032 int e = iBorderPixels;
00033 int wb = e + w + e;
00034 int hb = e + h + e;
00035 int l,r,t,b;
00036 bool bOk = RequestArea(wb,hb,l,r,t,b);
00037
00038
00039
00040 if (!bOk) return false;
00041
00042
00043 for (int y=t;y<b;++y)
00044 for (int x=l;x<r;++x) {
00045 int src_x = x-l-e;
00046 int src_y = y-t-e;
00047 if (bWrap) {
00048 while (src_x < 0) src_x += w;
00049 while (src_y < 0) src_y += h;
00050 src_x = src_x % w;
00051 src_y = src_y % h;
00052 } else {
00053 src_x = mymax(0,mymin(w-1,src_x));
00054 src_y = mymax(0,mymin(h-1,src_y));
00055 }
00056 Ogre::ColourValue src_col = pSrc.getColourAt(src_x,src_y,0);
00057 Ogre::PixelUtil::packColour(src_col,miFormat,GetPixelPointer(x,y));
00058 }
00059
00060
00061 pOutTexCoords.left = (l +e) / float(miW);
00062 pOutTexCoords.right = (l+w+e) / float(miW);
00063 pOutTexCoords.top = (t +e) / float(miH);
00064 pOutTexCoords.bottom = (t+h+e) / float(miH);
00065 return true;
00066 }
00067
00068
00069 void cTexAtlas::FillRect(const int x, const int y, const int w, const int h, const float r, const float g, const float b, const float a){
00070 Ogre::ColourValue c(r,g,b,a);
00071
00072 for (int yy=y;yy<y+h;++yy)
00073 for (int xx=x;xx<x+w;++xx) {
00074 int d_x = mymax(0,mymin(miW-1,xx));
00075 int d_y = mymax(0,mymin(miH-1,yy));
00076 Ogre::PixelUtil::packColour(c,miFormat,GetPixelPointer(d_x,d_y));
00077 }
00078
00079 }
00080
00081
00082 Ogre::TexturePtr cTexAtlas::MakeTexture (const Ogre::String &name, const Ogre::String &group) {
00083 Ogre::DataStreamPtr buf;
00084 buf.bind(new Ogre::MemoryDataStream(GetBasePointer(),Ogre::PixelUtil::getMemorySize(miW,miH,1,miFormat)));
00085 return Ogre::TextureManager::getSingleton().loadRawData(name,group,buf,miW,miH,miFormat);
00086 }
00087
00088 void cTexAtlas::MakeImage (Ogre::Image& pDest) {
00089
00090 Ogre::uchar* buf = (Ogre::uchar*)OGRE_MALLOC(GetBufferSize(), Ogre::MEMCATEGORY_GENERAL);
00091 memcpy(buf,GetBasePointer(),GetBufferSize());
00092
00093 pDest.loadDynamicImage(buf,miW,miH,1,miFormat,true);
00094 }
00095
00096
00097 void cTexAtlas::MarkAsFreeSpace(const int x,const int y,const int w,const int h){
00098
00099 if(w < miMinFreeSpaceSize || h < miMinFreeSpaceSize)return;
00100
00101
00102
00103 cFreeSpaceCell c(x,y,w,h);
00104 mlFreeSpace.push_back(c);
00105
00106
00107
00108 }
00109
00110 bool cTexAtlas::RequestArea (const int w,const int h,int& l,int& r,int& t,int& b) {
00111
00112
00113
00114 for (std::list<cFreeSpaceCell>::iterator itor=mlFreeSpace.begin();itor!=mlFreeSpace.end();++itor){
00115 if((*itor).w >= w && (*itor).h >= h){
00116
00117
00118
00119
00120 l = (*itor).x;
00121 t = (*itor).y;
00122 r = l+w;
00123 b = t+h;
00124
00125
00126
00127
00128 MarkAsFreeSpace(l,b,w,(*itor).h-h);
00129 MarkAsFreeSpace(r,t,(*itor).w-w,(*itor).h);
00130
00131
00132 mlFreeSpace.erase(itor);
00133
00134 return true;
00135 }
00136 }
00137
00138
00139
00140
00141
00142 int restw = miW - miBrushX;
00143 int resth = miH - miBrushY;
00144
00145
00146
00147
00148 if(h > resth){
00149
00150
00151 return false;
00152 }
00153
00154
00155 if(w <= restw && ((miCurrentLineH < 0) || (h <= miCurrentLineH))){
00156
00157
00158
00159
00160
00161 if(miCurrentLineH < 0){
00162
00163 miCurrentLineH = h;
00164 }
00165
00166
00167 l = miBrushX;
00168 t = miBrushY;
00169 r = l+w;
00170 b = t+h;
00171
00172
00173 MarkAsFreeSpace(miBrushX,miBrushY+h,w,miCurrentLineH-h);
00174
00175
00176 miBrushX += w;
00177
00178 return true;
00179 } else {
00180
00181
00182
00183 MarkAsFreeSpace(miBrushX,miBrushY,restw,miCurrentLineH);
00184
00185
00186 miBrushX = 0;
00187 miBrushY += miCurrentLineH;
00188 miCurrentLineH = -1;
00189
00190
00191 if( miBrushY >= miH){
00192
00193
00194 return false;
00195 } else {
00196
00197
00198 return RequestArea(w,h,l,r,t,b);
00199 }
00200 }
00201 }
00202
00203 };