00001 #include "lugre_prefix.h"
00002 #include "lugre_ogrewrapper.h"
00003 #include "lugre_spritelist.h"
00004
00005 #include <Ogre.h>
00006 #define SPRITELIST_DEBUG 0
00007 #define SPRITELIST_DEBUG_GEO 0
00008
00009 using namespace Ogre;
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 namespace Lugre {
00024
00025
00026
00027
00028 inline void RectAdd (Ogre::Rectangle& a,const float l,const float t,const float r,const float b) {
00029 a.left = mymin(a.left ,l);
00030 a.top = mymin(a.top ,t);
00031 a.right = mymax(a.right ,r);
00032 a.bottom = mymax(a.bottom,b);
00033 }
00034
00035 inline void RectAdd (Ogre::Rectangle& a,const Ogre::Rectangle& b) { RectAdd(a,b.left,b.top,b.right,b.bottom); }
00036 inline void RectAddWithOffset (Ogre::Rectangle& a,const Ogre::Rectangle& b,const Ogre::Vector3& off) {
00037 RectAdd(a,off.x+b.left,off.y+b.top,off.x+b.right,off.y+b.bottom);
00038 }
00039 inline void RectSetWithOffset (Ogre::Rectangle& a,const Ogre::Rectangle& b,const Ogre::Vector3& off) {
00040 a.left = off.x+b.left;
00041 a.top = off.y+b.top;
00042 a.right = off.x+b.right;
00043 a.bottom = off.y+b.bottom;
00044 }
00045
00046 inline Ogre::Rectangle MakeRectLTRB (const float left,const float top,const float right,const float bottom) {
00047 Ogre::Rectangle r;
00048 r.left = left;
00049 r.top = top;
00050 r.right = right;
00051 r.bottom = bottom;
00052 return r;
00053 }
00054
00055 inline Ogre::Rectangle OffsetRect (const Ogre::Rectangle& rIn,const Ogre::Vector3& vAdd) {
00056 return MakeRectLTRB(rIn.left + vAdd.x, rIn.top + vAdd.y,
00057 rIn.right + vAdd.x, rIn.bottom + vAdd.y);
00058 }
00059
00060
00061
00062
00063 cRenderGroup2D::cRenderGroup2D () : mpParent(0), miForcedMinW(0), miForcedMinH(0), mbRelBoundsDirty(true), mbRelBoundsEmpty(true), mbAddBoundsToParent(true), mbClipActive(false), mbTmpClipActive(false), mbVisible(true), miChildListRevision(0), mvPos(0,0,0) {}
00064
00065 cRenderGroup2D::~cRenderGroup2D () {
00066 if (mpParent && GetAddBoundsToParent()) mpParent->MarkRelBoundsAsDirty();
00067 _RemoveFromParent_NoClipUpdate();
00068 for (tChildListItor itor=mlChilds.begin();itor!=mlChilds.end();++itor) { (*itor)->mpParent = 0; delete *itor; }
00069 mlChilds.clear();
00070 }
00071
00072 void cRenderGroup2D::UpdateRelBounds () {
00073 mbRelBoundsDirty = false;
00074 mbRelBoundsEmpty = (miForcedMinW > 0 && miForcedMinH > 0) ? false : true;
00075 mrRelBounds.left = 0;
00076 mrRelBounds.top = 0;
00077 mrRelBounds.right = miForcedMinW;
00078 mrRelBounds.bottom = miForcedMinH;
00079
00080
00081 for (tChildListItor itor=mlChilds.begin();itor!=mlChilds.end();++itor) {
00082 cRenderGroup2D& child = *(*itor);
00083
00084 if (child.GetAddBoundsToParent()) _BoundsAddRectWithOffset(child.GetRelBounds(),child.GetPos());
00085 }
00086 }
00087
00088 void cRenderGroup2D::CalcAbsBounds (Ogre::Rectangle& r) {
00089 Ogre::Rectangle& a = GetRelBounds();
00090 Ogre::Vector3 p = GetDerivedPos();
00091 r.left = a.left + p.x;
00092 r.top = a.top + p.y;
00093 r.right = a.right + p.x;
00094 r.bottom = a.bottom + p.y;
00095 }
00096
00097
00098 void cRenderGroup2D::UpdateClip () {
00099 if (SPRITELIST_DEBUG) printf("cRenderGroup2D::UpdateClip childlistsize=%d parentclip=%d ownclip=%d\n",mlChilds.size(),_ParentClipActive()?1:0,mbClipActive?1:0);
00100 if (_ParentClipActive()) {
00101
00102 mrTmpClip = mbClipActive ? intersect(OffsetRect(mrClip,GetDerivedPos()),mpParent->mrTmpClip) : mpParent->mrTmpClip;
00103 mbTmpClipActive = true;
00104 } else {
00105
00106 mbTmpClipActive = mbClipActive;
00107 if (mbTmpClipActive) mrTmpClip = OffsetRect(mrClip,GetDerivedPos());
00108 }
00109 if (mbTmpClipActive) mrTmpClipRel = OffsetRect(mrTmpClip,-GetDerivedPos());
00110 if (SPRITELIST_DEBUG) printf("abs l=%0.0f,t=%0.0f,r=%0.0f,b=%0.0f\n",mrTmpClip.left,mrTmpClip.top,mrTmpClip.right,mrTmpClip.bottom);
00111 if (SPRITELIST_DEBUG) printf("rel l=%0.0f,t=%0.0f,r=%0.0f,b=%0.0f\n",mrTmpClipRel.left,mrTmpClipRel.top,mrTmpClipRel.right,mrTmpClipRel.bottom);
00112
00113
00114 for (tChildListItor itor=mlChilds.begin();itor!=mlChilds.end();++itor) (*itor)->UpdateClip();
00115 }
00116
00117 void cRenderGroup2D::Render (cRenderManager2D& pRenderManager2D,const Ogre::Vector3& vPos) {
00118 if (!mbVisible) return;
00119
00120
00121 for (tChildListItor itor=mlChilds.begin();itor!=mlChilds.end();++itor) (*itor)->Render(pRenderManager2D,GetPos() + vPos);
00122 }
00123
00124
00125
00126
00127
00128 cSpriteList::cSpriteList(const bool bVertexBufferDynamic,const bool bVertexCol)
00129 : iMaxInitializedSprite(0), mRobRenderOp(&mRenderOp), mpPass(0), mbVertexBufferDynamic(bVertexBufferDynamic), mbGeometryClipped(false), mbGeometryDirty(false), mbVertexCol(bVertexCol), mpTexTransformMatrix(0) {
00130 mRenderOp.vertexData = new Ogre::VertexData();
00131 mRenderOp.indexData = new Ogre::IndexData();
00132 if (SPRITELIST_DEBUG) printf("cSpriteList::cSpriteList mbVertexBufferDynamic=%d mbVertexCol=%d\n",mbVertexBufferDynamic?1:0,mbVertexCol?1:0);
00133 }
00134
00135 cSpriteList::~cSpriteList() {
00136 delete mRenderOp.vertexData; mRenderOp.vertexData = 0;
00137 delete mRenderOp.indexData; mRenderOp.indexData = 0;
00138 if (mpTexTransformMatrix) delete mpTexTransformMatrix; mpTexTransformMatrix = 0;
00139 }
00140
00141 void cSpriteList::UpdateRelBounds () {
00142 cRenderGroup2D::UpdateRelBounds();
00143 int c = mlSprites.size();
00144 for (int i=0;i<c;++i) {
00145 cSprite& o = mlSprites[i];
00146 _BoundsAddRect(o.p.x,o.p.y,o.p.x + o.w,o.p.y + o.h);
00147 }
00148 }
00149
00150 void cSpriteList::UpdateGeometry () {
00151 int c = mlSprites.size();
00152 mbGeometryDirty = false;
00153 mbGeometryClipped = false;
00154 if (SPRITELIST_DEBUG) printf("cSpriteList::UpdateGeometry size=%d\n",c);
00155 mRobRenderOp.Begin(4*c,6*c,mbVertexBufferDynamic);
00156 for (int i=0,vc=0;i<c;++i,vc+=4) {
00157 mlSprites[i].WriteGeometry(mRobRenderOp,mbVertexCol);
00158 mRobRenderOp.Index(vc+0,vc+1,vc+2);
00159 mRobRenderOp.Index(vc+2,vc+1,vc+3);
00160 }
00161 mRobRenderOp.End();
00162 }
00163
00164 void cSpriteList::UpdateGeometryClipped (const Ogre::Rectangle& rClip) {
00165 int c = mlSprites.size();
00166 mbGeometryDirty = false;
00167 mbGeometryClipped = true;
00168 if (SPRITELIST_DEBUG) printf("cSpriteList::UpdateGeometryClipped size=%d\n",c);
00169 mRobRenderOp.Begin(4*c,6*c,mbVertexBufferDynamic);
00170 for (int i=0,vc=0;i<c;++i) {
00171 if (mlSprites[i].WriteGeometryClipped(mRobRenderOp,mbVertexCol,rClip)) {
00172 mRobRenderOp.Index(vc+0,vc+1,vc+2);
00173 mRobRenderOp.Index(vc+2,vc+1,vc+3);
00174 vc += 4;
00175 } else {
00176
00177 mRobRenderOp.SkipVertices(4);
00178 mRobRenderOp.SkipIndices(6);
00179 }
00180 }
00181 mRobRenderOp.End();
00182 }
00183
00184 void cSpriteList::UpdateClip () {
00185 if (SPRITELIST_DEBUG) printf("cSpriteList::UpdateClip childlistsize=%d\n",mlChilds.size());
00186
00187
00188 cRenderGroup2D::UpdateClip();
00189
00190
00191 if (mbTmpClipActive) {
00192 UpdateGeometryClipped(mrTmpClipRel);
00193 } else {
00194
00195 if (mbGeometryClipped || mbGeometryDirty) UpdateGeometry();
00196 }
00197 }
00198
00199 void cSpriteList::Render (cRenderManager2D& pRenderManager2D,const Ogre::Vector3& vPos) {
00200 if (!mbVisible) return;
00201
00202
00203
00204 static Ogre::Matrix4 myTrans = Ogre::Matrix4::IDENTITY;
00205
00206 if (mRenderOp.indexData && mRenderOp.indexData->indexCount > 0) {
00207 Ogre::RenderSystem& pRenderSys = *pRenderManager2D.GetRenderSystem();
00208 myTrans.setTrans(GetPos() + vPos);
00209 pRenderSys._setWorldMatrix(myTrans);
00210 pRenderManager2D.GetSceneMan()->_setPass(GetMatPass(),true,false);
00211 if (mpTexTransformMatrix) pRenderSys._setTextureMatrix(0,*mpTexTransformMatrix);
00212 pRenderSys._render(mRenderOp);
00213 } else {
00214
00215 }
00216
00217
00218 cRenderGroup2D::Render(pRenderManager2D,vPos);
00219
00220
00221 }
00222
00223 void cSpriteList::SetMaterial (Ogre::MaterialPtr mat) { mpMat = mat; if (!mat->isLoaded()) mat->load(); mpPass = mat.isNull()?0:mat->getTechnique(0)->getPass(0); }
00224 void cSpriteList::SetMaterial (const char* szMatName) {
00225 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(szMatName);
00226 if (mat.isNull()) printf("warning : cSpriteList::SetMaterial : failed to load material '%s'\n",szMatName);
00227 SetMaterial(mat);
00228 }
00229
00230
00231
00232
00233 #define SPRITE_VERTEX_AUX( geom,x,y,z,u,v) geom.Vertex(Ogre::Vector3(x,y,z),u,v); if (SPRITELIST_DEBUG_GEO) printf("SPRITE_VERTEX %f,%f,%f %f,%f\n",x,y,z,u,v);
00234 #define SPRITE_VERTEX_AUX_C(geom,x,y,z,u,v,c) geom.Vertex(Ogre::Vector3(x,y,z),u,v,c); if (SPRITELIST_DEBUG_GEO) printf("SPRITE_VERTEXc %f,%f,%f %f,%f %f,%f,%f,%f\n",x,y,z,u,v,c.r,c.g,c.b,c.a);
00235
00236 #define SPRITE_VERTEX(geom,fx,fy) SPRITE_VERTEX_AUX(geom, p.x + w * fx, \
00237 p.y + h * fy, \
00238 p.z , \
00239 mvTexCoord0.x + mvTexCoordX.x * fx + mvTexCoordY.x * fy, \
00240 mvTexCoord0.y + mvTexCoordX.y * fx + mvTexCoordY.y * fy );
00241 #define SPRITE_VERTEX_COL(geom,fx,fy) SPRITE_VERTEX_AUX_C(geom, p.x + w * fx, \
00242 p.y + h * fy, \
00243 p.z , \
00244 mvTexCoord0.x + mvTexCoordX.x * fx + mvTexCoordY.x * fy, \
00245 mvTexCoord0.y + mvTexCoordX.y * fx + mvTexCoordY.y * fy, mvCol );
00246
00247
00248 void cSpriteList::cSprite::WriteGeometry (cRobRenderOp& pGeometry,const bool bVertexCol) {
00249 if (bVertexCol) {
00250 SPRITE_VERTEX_COL(pGeometry,0,0)
00251 SPRITE_VERTEX_COL(pGeometry,1,0)
00252 SPRITE_VERTEX_COL(pGeometry,0,1)
00253 SPRITE_VERTEX_COL(pGeometry,1,1)
00254 } else {
00255 SPRITE_VERTEX(pGeometry,0,0)
00256 SPRITE_VERTEX(pGeometry,1,0)
00257 SPRITE_VERTEX(pGeometry,0,1)
00258 SPRITE_VERTEX(pGeometry,1,1)
00259 }
00260 }
00261
00262 bool cSpriteList::cSprite::WriteGeometryClipped (cRobRenderOp& pGeometry,const bool bVertexCol,const Ogre::Rectangle& rClip) {
00263 if (w <= 0.0 ) return false;
00264 if (h <= 0.0 ) return false;
00265 if (p.x >= rClip.right ) return false;
00266 if (p.y >= rClip.bottom ) return false;
00267 if (p.x+w < rClip.left ) return false;
00268 if (p.y+h < rClip.top ) return false;
00269 float fx0 = (mymax(rClip.left,mymin(rClip.right ,p.x ))-p.x)/w;
00270 float fx1 = (mymax(rClip.left,mymin(rClip.right ,p.x+w))-p.x)/w;
00271 float fy0 = (mymax(rClip.top ,mymin(rClip.bottom,p.y ))-p.y)/h;
00272 float fy1 = (mymax(rClip.top ,mymin(rClip.bottom,p.y+h))-p.y)/h;
00273 if (bVertexCol) {
00274 SPRITE_VERTEX_COL(pGeometry,fx0,fy0)
00275 SPRITE_VERTEX_COL(pGeometry,fx1,fy0)
00276 SPRITE_VERTEX_COL(pGeometry,fx0,fy1)
00277 SPRITE_VERTEX_COL(pGeometry,fx1,fy1)
00278 } else {
00279 SPRITE_VERTEX(pGeometry,fx0,fy0)
00280 SPRITE_VERTEX(pGeometry,fx1,fy0)
00281 SPRITE_VERTEX(pGeometry,fx0,fy1)
00282 SPRITE_VERTEX(pGeometry,fx1,fy1)
00283 }
00284 return true;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 cRobRenderable2D::cRobRenderable2D()
00294 : mRobRenderOp(&mRenderOp), mpPass(0), mpTexTransformMatrix(0) {
00295 mRenderOp.vertexData = new Ogre::VertexData();
00296 mRenderOp.indexData = new Ogre::IndexData();
00297 }
00298
00299 cRobRenderable2D::~cRobRenderable2D() {
00300 delete mRenderOp.vertexData; mRenderOp.vertexData = 0;
00301 delete mRenderOp.indexData; mRenderOp.indexData = 0;
00302 if (mpTexTransformMatrix) delete mpTexTransformMatrix; mpTexTransformMatrix = 0;
00303 }
00304
00305 void cRobRenderable2D::UpdateRelBounds () {
00306 cRenderGroup2D::UpdateRelBounds();
00307 _BoundsAddRect( mRobRenderOp.mvAABMin.x,
00308 mRobRenderOp.mvAABMin.y,
00309 mRobRenderOp.mvAABMax.x,
00310 mRobRenderOp.mvAABMax.y);
00311 }
00312
00313 void cRobRenderable2D::Render (cRenderManager2D& pRenderManager2D,const Ogre::Vector3& vPos) {
00314 if (!mbVisible) return;
00315
00316 static Ogre::Matrix4 myTrans = Ogre::Matrix4::IDENTITY;
00317
00318 if (mRenderOp.indexData && mRenderOp.indexData->indexCount > 0) {
00319 Ogre::RenderSystem& pRenderSys = *pRenderManager2D.GetRenderSystem();
00320 myTrans.setTrans(GetPos() + vPos);
00321 pRenderSys._setWorldMatrix(myTrans);
00322 pRenderManager2D.GetSceneMan()->_setPass(GetMatPass(),true,false);
00323 if (mpTexTransformMatrix) pRenderSys._setTextureMatrix(0,*mpTexTransformMatrix);
00324 pRenderSys._render(mRenderOp);
00325 } else {
00326 printf("cRobRenderable2D::Render : ERROR: no index data %p %d\n",mRenderOp.indexData,(mRenderOp.indexData?mRenderOp.indexData->indexCount:0));
00327 }
00328
00329
00330 cRenderGroup2D::Render(pRenderManager2D,vPos);
00331
00332
00333 }
00334
00335
00336 void cRobRenderable2D::SetMaterial (Ogre::MaterialPtr mat) { mpMat = mat; if (!mat->isLoaded()) mat->load(); mpPass = mat.isNull()?0:mat->getTechnique(0)->getPass(0); }
00337 void cRobRenderable2D::SetMaterial (const char* szMatName) {
00338 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(szMatName);
00339 if (mat.isNull()) printf("warning : cRobRenderable2D::SetMaterial : failed to load material '%s'\n",szMatName);
00340 SetMaterial(mat);
00341 }
00342
00343
00344
00345
00346 void cRenderManager2D::SetRenderEvenIfOverlaysDisabled (bool render) {
00347 mbRenderEvenIfOverlaysDisabled = render;
00348 }
00349
00350 cRenderManager2D::cRenderManager2D (Ogre::SceneManager* pSceneMan,Ogre::uint8 iQueueGroupID) : mpSceneMan(pSceneMan), miQueueGroupID(iQueueGroupID), mbRenderEvenIfOverlaysDisabled(false) {
00351 if (SPRITELIST_DEBUG) printf("cRenderManager2D::cRenderManager2D mpSceneMan=%x\n",(int)(long)mpSceneMan);
00352 mpRenderSys = Ogre::Root::getSingleton().getRenderSystem();
00353 if (mpSceneMan) mpSceneMan->addRenderQueueListener(this);
00354 }
00355
00356 cRenderManager2D::~cRenderManager2D () {
00357 if (mpSceneMan) mpSceneMan->removeRenderQueueListener(this);
00358 mpSceneMan = 0;
00359 }
00360
00361 void cRenderManager2D::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) {
00362 if (queueGroupId != miQueueGroupID) return;
00363 if (invocation != Ogre::StringUtil::BLANK) return;
00364
00365
00366 if (mpRenderSys) {
00367 if (mbRenderEvenIfOverlaysDisabled || mpRenderSys->_getViewport()->getOverlaysEnabled()){
00368 SetRenderState(*mpRenderSys);
00369 Render(*this,Ogre::Vector3::ZERO);
00370 }
00371 }
00372 }
00373
00374 void cRenderManager2D::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) {
00375 }
00376
00377 void cRenderManager2D::SetRenderState (Ogre::RenderSystem& pRenderSys) {
00378
00379 Ogre::Viewport& pViewport = *pRenderSys._getViewport();
00380 int w = pViewport.getActualWidth();
00381 int h = pViewport.getActualHeight();
00382
00383
00384 if (1) {
00385
00386 Ogre::Matrix4 m_view = Ogre::Matrix4::IDENTITY;
00387 m_view.setTrans(Ogre::Vector3(-(w-0.5)/2.0, -(h-0.5)/2.0,0.0));
00388
00389 Ogre::Matrix4 m_proj = Ogre::Matrix4::getScale( 2.0/w, -2.0/h, 1.0 );
00390
00391 pRenderSys._setViewMatrix( m_view );
00392 pRenderSys._setProjectionMatrix( m_proj );
00393 pRenderSys._setWorldMatrix( Ogre::Matrix4::IDENTITY );
00394 pRenderSys._setTextureMatrix( 0, Ogre::Matrix4::IDENTITY );
00395
00396 } else if (1) {
00397
00398 Ogre::Real left = 0;
00399 Ogre::Real top = 0;
00400 Ogre::Real right = w;
00401 Ogre::Real bottom = h;
00402 Ogre::Real mFarDist = 1;
00403 Ogre::Real mNearDist = 0;
00404
00405 Ogre::Real inv_w = 1 / (right - left);
00406 Ogre::Real inv_h = 1 / (top - bottom);
00407 Ogre::Real inv_d = 1 / (mFarDist - mNearDist);
00408
00409
00410 Ogre::Real A = 2 * inv_w;
00411 Ogre::Real B = 2 * inv_h;
00412 Ogre::Real C = - (right + left) * inv_w;
00413 Ogre::Real D = - (top + bottom) * inv_h;
00414 Ogre::Real q, qn;
00415 if (mFarDist == 0)
00416 {
00417
00418 q = - Ogre::Frustum::INFINITE_FAR_PLANE_ADJUST / mNearDist;
00419 qn = - Ogre::Frustum::INFINITE_FAR_PLANE_ADJUST - 1;
00420 }
00421 else
00422 {
00423 q = - 2 * inv_d;
00424 qn = - (mFarDist + mNearDist) * inv_d;
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 static Ogre::Matrix4 mProjMatrix = Matrix4::ZERO;
00443 mProjMatrix[0][0] = A;
00444 mProjMatrix[0][3] = C;
00445 mProjMatrix[1][1] = B;
00446 mProjMatrix[1][3] = D;
00447 mProjMatrix[2][2] = q;
00448 mProjMatrix[2][3] = qn;
00449 mProjMatrix[3][3] = 1;
00450 static Ogre::Matrix4 mProjMatrixRS = Matrix4::ZERO;
00451
00452
00453
00454 pRenderSys._convertProjectionMatrix(mProjMatrix, mProjMatrixRS);
00455
00456
00457
00458 Ogre::Matrix4 ViewportMatrix = Ogre::Matrix4::IDENTITY;
00459 ViewportMatrix.setTrans(Ogre::Vector3(-1.0, +1.0,0.0));
00460
00461 pRenderSys._setViewMatrix( Ogre::Matrix4::IDENTITY );
00462 pRenderSys._setProjectionMatrix( mProjMatrixRS );
00463 pRenderSys._setWorldMatrix( Ogre::Matrix4::IDENTITY );
00464 pRenderSys._setTextureMatrix( 0, Ogre::Matrix4::IDENTITY );
00465 } else {
00466
00467
00468
00469 Ogre::Matrix4 ViewportMatrix = Ogre::Matrix4::getScale( 2.0/w, -2.0/h, 1.0 );
00470 ViewportMatrix.setTrans(Ogre::Vector3(-1.0, +1.0,0.0));
00471 pRenderSys._setViewMatrix( ViewportMatrix );
00472 pRenderSys._setProjectionMatrix( Ogre::Matrix4::IDENTITY );
00473 pRenderSys._setWorldMatrix( Ogre::Matrix4::IDENTITY );
00474 pRenderSys._setTextureMatrix( 0, Ogre::Matrix4::IDENTITY );
00475
00476 }
00477
00478
00479
00480
00481
00482
00483 }
00484
00485
00486
00487 };