30 #include "video/renderbackend.h"
31 #include "video/image.h"
32 #include "video/sdl/sdlimage.h"
33 #include "video/imagepool.h"
34 #include "video/animation.h"
35 #include "video/animationpool.h"
36 #include "util/math/fife_math.h"
37 #include "util/log/logger.h"
38 #include "model/metamodel/grids/cellgrid.h"
39 #include "model/metamodel/action.h"
40 #include "model/structures/instance.h"
41 #include "model/structures/layer.h"
42 #include "model/structures/location.h"
43 #include "video/opengl/fife_opengl.h"
45 #include "view/camera.h"
46 #include "view/visual.h"
47 #include "instancerenderer.h"
51 unsigned int scale(
unsigned int val,
double factor) {
52 return static_cast<unsigned int>(ceil(static_cast<double>(val) * factor));
57 static Logger _log(LM_VIEWVIEW);
59 InstanceRenderer::OutlineInfo::OutlineInfo():
68 InstanceRenderer::ColoringInfo::ColoringInfo():
77 InstanceRenderer::AreaInfo::AreaInfo():
87 InstanceRenderer::OutlineInfo::~OutlineInfo() {
91 InstanceRenderer::ColoringInfo::~ColoringInfo() {
95 InstanceRenderer::AreaInfo::~AreaInfo() {
98 InstanceRenderer* InstanceRenderer::getInstance(IRendererContainer* cnt) {
99 return dynamic_cast<InstanceRenderer*
>(cnt->getRenderer(
"InstanceRenderer"));
102 InstanceRenderer::InstanceRenderer(RenderBackend* renderbackend,
int position, ImagePool* imagepool, AnimationPool* animpool):
103 RendererBase(renderbackend, position),
104 m_imagepool(imagepool),
105 m_animationpool(animpool),
106 m_area_layer(false) {
110 InstanceRenderer::InstanceRenderer(
const InstanceRenderer& old):
112 m_imagepool(old.m_imagepool),
113 m_animationpool(old.m_animationpool),
114 m_area_layer(old.m_area_layer) {
118 RendererBase* InstanceRenderer::clone() {
119 return new InstanceRenderer(*
this);
122 InstanceRenderer::~InstanceRenderer() {
125 void InstanceRenderer::render(Camera* cam, Layer* layer, RenderList& instances) {
126 FL_DBG(_log,
"Iterating layer...");
127 CellGrid* cg = layer->getCellGrid();
129 FL_WARN(_log,
"No cellgrid assigned to layer, cannot draw instances");
133 const bool any_effects = !(m_instance_outlines.empty() && m_instance_colorings.empty());
134 const bool unlit = !m_unlit_groups.empty();
135 unsigned int lm = m_renderbackend->getLightingModel();
137 m_area_layer =
false;
138 if(!m_instance_areas.empty()) {
139 InstanceToAreas_t::iterator area_it = m_instance_areas.begin();
140 for(;area_it != m_instance_areas.end(); area_it++) {
141 AreaInfo& info = area_it->second;
142 if(info.instance->getLocation().getLayer() == layer) {
144 DoublePoint3D instance_posv = cam->toVirtualScreenCoordinates(info.instance->getLocation().getMapCoordinates());
145 info.z = instance_posv.z;
152 RenderList::iterator instance_it = instances.begin();
153 for (;instance_it != instances.end(); ++instance_it) {
154 FL_DBG(_log,
"Iterating instances...");
155 Instance* instance = (*instance_it)->instance;
156 RenderItem& vc = **instance_it;
159 InstanceToAreas_t::iterator areas_it = m_instance_areas.begin();
160 for(;areas_it != m_instance_areas.end(); areas_it++) {
161 AreaInfo& infoa = areas_it->second;
163 if(infoa.z >= vc.screenpoint.z) {
168 std::string str_name = instance->getObject()->getNamespace();
169 std::list<std::string>::iterator group_it = infoa.groups.begin();
170 for(;group_it != infoa.groups.end(); ++group_it) {
171 if(str_name.find((*group_it)) != std::string::npos) {
174 p = cam->toScreenCoordinates(infoa.instance->getLocation().getMapCoordinates());
175 rec.
x = p.x - infoa.w / 2;
176 rec.y = p.y - infoa.h / 2;
179 if(infoa.instance != instance && vc.dimensions.intersects(rec)) {
180 vc.transparency = 255 - infoa.trans;
187 FL_DBG(_log, LMsg(
"Instance layer coordinates = ") << instance->getLocationRef().getLayerCoordinates());
190 InstanceToOutlines_t::iterator outline_it = m_instance_outlines.find(instance);
191 if (outline_it != m_instance_outlines.end()) {
193 m_renderbackend->disableLighting();
194 m_renderbackend->setStencilTest(255, 2, 7);
195 m_renderbackend->setAlphaTest(0.0);
196 bindOutline(outline_it->second, vc, cam)->render(vc.dimensions, vc.transparency);
197 m_renderbackend->enableLighting();
198 m_renderbackend->setStencilTest(0, 2, 7);
199 vc.image->render(vc.dimensions, vc.transparency);
200 m_renderbackend->disableAlphaTest();
201 m_renderbackend->disableStencilTest();
204 bindOutline(outline_it->second, vc, cam)->render(vc.dimensions, vc.transparency);
207 InstanceToColoring_t::iterator coloring_it = m_instance_colorings.find(instance);
208 if (coloring_it != m_instance_colorings.end()) {
209 m_renderbackend->disableLighting();
210 bindColoring(coloring_it->second, vc, cam)->render(vc.dimensions, vc.transparency);
211 m_renderbackend->enableLighting();
218 std::string lit_name = instance->getObject()->getNamespace();
219 std::list<std::string>::iterator unlit_it = m_unlit_groups.begin();
220 for(;unlit_it != m_unlit_groups.end(); ++unlit_it) {
221 if(lit_name.find(*unlit_it) != std::string::npos) {
222 m_renderbackend->setStencilTest(255, 2, 7);
229 m_renderbackend->setStencilTest(0, 1, 7);
231 m_renderbackend->setAlphaTest(0.0);
232 vc.image->render(vc.dimensions, vc.transparency);
236 vc.image->render(vc.dimensions, vc.transparency);
240 m_renderbackend->disableAlphaTest();
241 m_renderbackend->disableStencilTest();
245 Image* InstanceRenderer::bindOutline(OutlineInfo& info, RenderItem& vc, Camera* cam) {
246 if (!info.dirty && info.curimg == vc.image) {
250 info.curimg = vc.image;
257 SDL_Surface* surface = vc.image->getSurface();
258 SDL_Surface* outline_surface = SDL_ConvertSurface(surface, surface->format, surface->flags);
261 SDLImage* img =
new SDLImage(outline_surface);
264 uint8_t r, g, b, a = 0;
267 for (
unsigned int x = 0; x < img->getWidth(); x ++) {
269 for (
unsigned int y = 0; y < img->getHeight(); y ++) {
270 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
271 if ((a == 0 || prev_a == 0) && (a != prev_a)) {
273 for (
unsigned int yy = y; yy < y + info.width; yy++) {
274 img->putPixel(x, yy, info.r, info.g, info.b);
277 for (
unsigned int yy = y - info.width; yy < y; yy++) {
278 img->putPixel(x, yy, info.r, info.g, info.b);
286 for (
unsigned int y = 0; y < img->getHeight(); y ++) {
288 for (
unsigned int x = 0; x < img->getWidth(); x ++) {
289 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
290 if ((a == 0 || prev_a == 0) && (a != prev_a)) {
292 for (
unsigned int xx = x; xx < x + info.width; xx++) {
293 img->putPixel(xx, y, info.r, info.g, info.b);
296 for (
unsigned int xx = x - info.width; xx < x; xx++) {
297 img->putPixel(xx, y, info.r, info.g, info.b);
306 info.outline = m_renderbackend->createImage(img->detachSurface());
317 Image* InstanceRenderer::bindColoring(ColoringInfo& info, RenderItem& vc, Camera* cam) {
318 if (!info.dirty && info.curimg == vc.image) {
323 info.curimg = vc.image;
331 SDL_Surface* surface = vc.image->getSurface();
332 SDL_Surface* overlay_surface = SDL_ConvertSurface(surface, surface->format, surface->flags);
335 SDLImage* img =
new SDLImage(overlay_surface);
337 uint8_t r, g, b, a = 0;
339 for (
unsigned int x = 0; x < img->getWidth(); x ++) {
340 for (
unsigned int y = 0; y < img->getHeight(); y ++) {
341 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
343 img->putPixel(x, y, (r + info.r) >> 1, (g + info.g) >> 1, (b + info.b) >> 1);
349 info.overlay = m_renderbackend->createImage(img->detachSurface());
360 void InstanceRenderer::addOutlined(Instance* instance,
int r,
int g,
int b,
int width) {
365 newinfo.width = width;
366 newinfo.dirty =
true;
372 std::pair<InstanceToOutlines_t::iterator, bool> insertiter = m_instance_outlines.insert(std::make_pair(instance, newinfo));
374 if (insertiter.second ==
false) {
377 OutlineInfo& info = insertiter.first->second;
379 if (info.r != r || info.g != g || info.b != b || info.width != width) {
391 void InstanceRenderer::addColored(Instance* instance,
int r,
int g,
int b) {
392 ColoringInfo newinfo;
396 newinfo.dirty =
true;
402 std::pair<InstanceToColoring_t::iterator, bool> insertiter = m_instance_colorings.insert(std::make_pair(instance, newinfo));
404 if (insertiter.second ==
false) {
407 ColoringInfo& info = insertiter.first->second;
409 if (info.r != r || info.g != g || info.b != b) {
420 void InstanceRenderer::addTransparentArea(Instance* instance,
const std::list<std::string> &groups,
unsigned int w,
unsigned int h,
unsigned char trans,
bool front) {
422 newinfo.instance = instance;
423 newinfo.groups = groups;
427 newinfo.trans = trans;
428 newinfo.front = front;
435 std::pair<InstanceToAreas_t::iterator, bool> insertiter = m_instance_areas.insert(std::make_pair(instance, newinfo));
437 if (insertiter.second ==
false) {
440 AreaInfo& info = insertiter.first->second;
444 void InstanceRenderer::removeOutlined(Instance* instance) {
445 m_instance_outlines.erase(instance);
448 void InstanceRenderer::removeColored(Instance* instance) {
449 m_instance_colorings.erase(instance);
452 void InstanceRenderer::removeTransparentArea(Instance* instance) {
453 m_instance_areas.erase(instance);
456 void InstanceRenderer::removeAllOutlines() {
457 m_instance_outlines.clear();
460 void InstanceRenderer::removeAllColored() {
461 m_instance_colorings.clear();
464 void InstanceRenderer::removeAllTransparentAreas() {
465 m_instance_areas.clear();
468 void InstanceRenderer::addIgnoreLight(
const std::list<std::string> &groups) {
469 std::list<std::string>::const_iterator group_it = groups.begin();
470 for(;group_it != groups.end(); ++group_it) {
471 m_unlit_groups.push_back(*group_it);
473 m_unlit_groups.sort();
474 m_unlit_groups.unique();
477 void InstanceRenderer::removeIgnoreLight(
const std::list<std::string> &groups) {
478 std::list<std::string>::const_iterator group_it = groups.begin();
479 for(;group_it != groups.end(); ++group_it) {
480 std::list<std::string>::iterator unlit_it = m_unlit_groups.begin();
481 for(;unlit_it != m_unlit_groups.end(); ++unlit_it) {
482 if((*group_it).find(*unlit_it) != std::string::npos) {
483 m_unlit_groups.remove(*unlit_it);
490 void InstanceRenderer::removeAllIgnoreLight() {
491 m_unlit_groups.clear();
494 void InstanceRenderer::reset() {
497 removeAllTransparentAreas();
498 removeAllIgnoreLight();