Sprite: Perform CPU visibility culling

This commit is contained in:
Jonas Kulla 2013-12-06 03:24:53 +01:00
parent 6e3b1d9466
commit 8ac70b7879
1 changed files with 50 additions and 7 deletions

View File

@ -33,6 +33,8 @@
#include "shader.h" #include "shader.h"
#include "glstate.h" #include "glstate.h"
#include <SDL_rect.h>
#include <sigc++/connection.h> #include <sigc++/connection.h>
#include <QDebug> #include <QDebug>
@ -54,6 +56,12 @@ struct SpritePrivate
NormValue opacity; NormValue opacity;
BlendType blendType; BlendType blendType;
SDL_Rect sceneRect;
/* Would this sprite be visible on
* the screen if drawn? */
bool isVisible;
Color *color; Color *color;
Tone *tone; Tone *tone;
@ -70,10 +78,13 @@ struct SpritePrivate
bushOpacity(128), bushOpacity(128),
opacity(255), opacity(255),
blendType(BlendNormal), blendType(BlendNormal),
isVisible(false),
color(&tmp.color), color(&tmp.color),
tone(&tmp.tone) tone(&tmp.tone)
{ {
sceneRect.x = sceneRect.y = 0;
updateSrcRectCon(); updateSrcRectCon();
prepareCon = shState->prepareDraw.connect prepareCon = shState->prepareDraw.connect
@ -119,10 +130,45 @@ struct SpritePrivate
(sigc::mem_fun(this, &SpritePrivate::onSrcRectChange)); (sigc::mem_fun(this, &SpritePrivate::onSrcRectChange));
} }
void updateVisibility()
{
isVisible = false;
if (!bitmap)
return;
if (bitmap->isDisposed())
return;
if (!opacity)
return;
/* Compare sprite bounding box against the scene */
/* If sprite is zoomed/rotated, just opt out for now
* for simplicity's sake */
const Vec2 &scale = trans.getScale();
if (scale.x != 1 || scale.y != 1 || trans.getRotation() != 0)
{
isVisible = true;
return;
}
SDL_Rect self;
self.x = trans.getPosition().x - trans.getOrigin().x;
self.y = trans.getPosition().y - trans.getOrigin().y;
self.w = bitmap->width();
self.h = bitmap->height();
isVisible = SDL_HasIntersection(&self, &sceneRect);
}
void prepare() void prepare()
{ {
if (bitmap) if (bitmap)
bitmap->flush(); bitmap->flush();
updateVisibility();
} }
}; };
@ -316,13 +362,7 @@ void Sprite::releaseResources()
/* SceneElement */ /* SceneElement */
void Sprite::draw() void Sprite::draw()
{ {
if (!p->bitmap) if (!p->isVisible)
return;
if (p->bitmap->isDisposed())
return;
if (!p->opacity)
return; return;
if (emptyFlashFlag) if (emptyFlashFlag)
@ -385,4 +425,7 @@ void Sprite::onGeometryChange(const Scene::Geometry &geo)
int yOffset = geo.rect.y - geo.yOrigin; int yOffset = geo.rect.y - geo.yOrigin;
p->trans.setGlobalOffset(xOffset, yOffset); p->trans.setGlobalOffset(xOffset, yOffset);
p->sceneRect.w = geo.rect.w;
p->sceneRect.h = geo.rect.h;
} }