31 #include "video/renderbackend.h"
32 #include "video/imagepool.h"
33 #include "video/animation.h"
34 #include "video/animationpool.h"
35 #include "video/fonts/abstractfont.h"
36 #include "video/image.h"
37 #include "video/opengl/glimage.h"
38 #include "util/math/fife_math.h"
39 #include "util/log/logger.h"
40 #include "util/time/timemanager.h"
41 #include "model/metamodel/grids/cellgrid.h"
42 #include "model/metamodel/timeprovider.h"
43 #include "model/structures/instance.h"
44 #include "model/structures/layer.h"
45 #include "model/structures/location.h"
47 #include "view/camera.h"
48 #include "lightrenderer.h"
52 static Logger _log(LM_VIEWVIEW);
54 LightRendererNode::LightRendererNode(Instance* attached_instance,
const Location &relative_location, Layer* relative_layer,
const Point &relative_point):
55 m_instance(attached_instance),
56 m_location(relative_location),
57 m_layer(relative_layer),
58 m_point(relative_point) {
60 LightRendererNode::LightRendererNode(Instance* attached_instance,
const Location &relative_location,
const Point &relative_point):
61 m_instance(attached_instance),
62 m_location(relative_location),
64 m_point(relative_point) {
66 LightRendererNode::LightRendererNode(Instance* attached_instance, Layer* relative_layer,
const Point &relative_point):
67 m_instance(attached_instance),
69 m_layer(relative_layer),
70 m_point(relative_point) {
72 LightRendererNode::LightRendererNode(Instance* attached_instance,
const Point &relative_point):
73 m_instance(attached_instance),
76 m_point(relative_point) {
78 LightRendererNode::LightRendererNode(
const Location &attached_location, Layer* relative_layer,
const Point &relative_point):
80 m_location(attached_location),
81 m_layer(relative_layer),
82 m_point(relative_point) {
84 LightRendererNode::LightRendererNode(
const Location &attached_location,
const Point &relative_point):
86 m_location(attached_location),
88 m_point(relative_point) {
90 LightRendererNode::LightRendererNode(Layer* attached_layer,
const Point &relative_point):
93 m_layer(attached_layer),
94 m_point(relative_point) {
96 LightRendererNode::LightRendererNode(
const Point &attached_point):
100 m_point(attached_point) {
102 LightRendererNode::~LightRendererNode() {
105 void LightRendererNode::setAttached(Instance* attached_instance,
const Location &relative_location,
const Point &relative_point) {
106 m_instance = attached_instance;
107 m_location = relative_location;
108 m_point = relative_point;
110 void LightRendererNode::setAttached(Instance* attached_instance,
const Location &relative_location) {
111 m_instance = attached_instance;
112 m_location = relative_location;
114 void LightRendererNode::setAttached(Instance* attached_instance,
const Point &relative_point) {
115 m_instance = attached_instance;
116 m_point = relative_point;
118 void LightRendererNode::setAttached(Instance* attached_instance) {
119 m_instance = attached_instance;
121 void LightRendererNode::setAttached(
const Location &attached_location,
const Point &relative_point) {
123 m_location = attached_location;
124 m_point = relative_point;
126 void LightRendererNode::setAttached(
const Location &attached_location) {
128 m_location = attached_location;
130 void LightRendererNode::setAttached(Layer* attached_layer) {
131 m_layer = attached_layer;
133 void LightRendererNode::setAttached(
const Point &attached_point) {
136 m_point = attached_point;
139 void LightRendererNode::setRelative(
const Location &relative_location) {
140 if(m_instance == NULL) {
141 throw NotSupported(
"No instance attached.");
143 m_location = relative_location;
145 void LightRendererNode::setRelative(
const Location &relative_location, Point relative_point) {
146 if(m_instance == NULL) {
147 throw NotSupported(
"No instance attached.");
149 m_location = relative_location;
150 m_point = relative_point;
152 void LightRendererNode::setRelative(
const Point &relative_point) {
153 if(m_instance == NULL || m_location == NULL) {
154 throw NotSupported(
"No instance or location attached.");
156 m_point = relative_point;
159 Instance* LightRendererNode::getAttachedInstance() {
160 if(m_instance == NULL) {
161 throw NotSupported(
"No instance attached.");
165 Location LightRendererNode::getAttachedLocation() {
166 if(m_instance != NULL || m_location == NULL) {
167 throw NotSupported(
"No location attached.");
171 Layer* LightRendererNode::getAttachedLayer() {
172 if(m_layer == NULL) {
173 throw NotSupported(
"No layer attached.");
177 Point LightRendererNode::getAttachedPoint() {
178 if(m_instance != NULL || m_location != NULL) {
179 throw NotSupported(
"No point attached.");
184 Location LightRendererNode::getOffsetLocation() {
185 if(m_instance == NULL || m_location == NULL) {
186 throw NotSupported(
"No location as offset used.");
190 Point LightRendererNode::getOffsetPoint() {
191 if(m_instance == NULL && m_location == NULL) {
192 throw NotSupported(
"No point as offset used.");
197 Instance* LightRendererNode::getInstance() {
200 Location LightRendererNode::getLocation() {
203 Layer* LightRendererNode::getLayer() {
206 Point LightRendererNode::getPoint() {
210 Point LightRendererNode::getCalculatedPoint(Camera* cam, Layer* layer) {
212 if(m_instance != NULL) {
213 if(m_layer == NULL) {
214 m_layer = m_instance->getLocation().getLayer();
216 if(m_location != NULL) {
217 p = cam->toScreenCoordinates(m_instance->getLocationRef().getMapCoordinates() + m_location.getMapCoordinates());
219 p = cam->toScreenCoordinates(m_instance->getLocation().getMapCoordinates());
221 }
else if(m_location != NULL) {
222 if(m_layer == NULL) {
223 m_layer = m_location.getLayer();
225 p = cam->toScreenCoordinates(m_location.getMapCoordinates());
226 }
else if(m_layer == NULL) {
227 const std::list<Layer*>& layers = cam->getRenderer(
"LightRenderer")->getActiveLayers();
228 std::list<Layer*>::const_reverse_iterator layer_it = layers.rbegin();
229 setAttached(*layer_it);
231 return Point(m_point.x + p.x, m_point.y + p.y);
234 LightRendererImageInfo::LightRendererImageInfo(LightRendererNode anchor,
int image,
int src,
int dst):
235 LightRendererElementInfo(),
244 void LightRendererImageInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
245 Point p = m_anchor.getCalculatedPoint(cam, layer);
246 if(m_anchor.getLayer() == layer) {
247 Image* img = &imagepool->getImage(m_image);
249 Rect viewport = cam->getViewPort();
250 unsigned int widtht = round(img->getWidth() * cam->getZoom());
251 unsigned int height = round(img->getHeight() * cam->getZoom());
256 renderbackend->changeBlending(m_src, m_dst);
257 if(r.intersects(viewport))
261 void LightRendererImageInfo::setStencil(uint8_t stencil_ref,
float alpha_ref) {
263 m_stencil_ref = stencil_ref;
264 m_alpha_ref = alpha_ref;
266 int LightRendererImageInfo::getStencil() {
270 return m_stencil_ref;
272 float LightRendererImageInfo::getAlpha() {
275 void LightRendererImageInfo::removeStencil() {
281 LightRendererAnimationInfo::LightRendererAnimationInfo(LightRendererNode anchor,
int animation,
int src,
int dst):
282 LightRendererElementInfo(),
284 m_animation(animation),
287 m_start_time(TimeManager::instance()->getTime()),
293 void LightRendererAnimationInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
294 Point p = m_anchor.getCalculatedPoint(cam, layer);
295 if(m_anchor.getLayer() == layer) {
296 Animation& animation = animpool->getAnimation(m_animation);
297 int animtime =
scaleTime(m_time_scale, TimeManager::instance()->getTime() - m_start_time) % animation.getDuration();
298 Image* img = animation.getFrameByTimestamp(animtime);
300 Rect viewport = cam->getViewPort();
301 unsigned int widtht = round(img->getWidth() * cam->getZoom());
302 unsigned int height = round(img->getHeight() * cam->getZoom());
307 renderbackend->changeBlending(m_src, m_dst);
308 if(r.intersects(viewport))
312 void LightRendererAnimationInfo::setStencil(uint8_t stencil_ref,
float alpha_ref) {
314 m_stencil_ref = stencil_ref;
315 m_alpha_ref = alpha_ref;
317 int LightRendererAnimationInfo::getStencil() {
321 return m_stencil_ref;
323 float LightRendererAnimationInfo::getAlpha() {
326 void LightRendererAnimationInfo::removeStencil() {
332 LightRendererResizeInfo::LightRendererResizeInfo(LightRendererNode anchor,
int image,
int width,
int height,
int src,
int dst):
333 LightRendererElementInfo(),
344 void LightRendererResizeInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
345 Point p = m_anchor.getCalculatedPoint(cam, layer);
346 if(m_anchor.getLayer() == layer) {
347 Image* img = &imagepool->getImage(m_image);
349 Rect viewport = cam->getViewPort();
350 unsigned int widtht = round(m_width * cam->getZoom());
351 unsigned int height = round(m_height * cam->getZoom());
356 renderbackend->changeBlending(m_src, m_dst);
357 if(r.intersects(viewport))
361 void LightRendererResizeInfo::setStencil(uint8_t stencil_ref,
float alpha_ref) {
363 m_stencil_ref = stencil_ref;
364 m_alpha_ref = alpha_ref;
366 int LightRendererResizeInfo::getStencil() {
370 return m_stencil_ref;
372 float LightRendererResizeInfo::getAlpha() {
375 void LightRendererResizeInfo::removeStencil() {
381 LightRendererSimpleLightInfo::LightRendererSimpleLightInfo(LightRendererNode anchor, uint8_t intensity,
float radius,
int subdivisions,
float xstretch,
float ystretch, uint8_t r, uint8_t g, uint8_t b,
int src,
int dst):
382 LightRendererElementInfo(),
384 m_intensity(intensity),
386 m_subdivisions(subdivisions),
387 m_xstretch(xstretch),
388 m_ystretch(ystretch),
398 void LightRendererSimpleLightInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
399 Point p = m_anchor.getCalculatedPoint(cam, layer);
400 if(m_anchor.getLayer() == layer) {
401 double zoom = cam->getZoom();
402 renderbackend->changeBlending(m_src, m_dst);
403 renderbackend->drawLightPrimitive(p, m_intensity, m_radius, m_subdivisions, m_xstretch * zoom, m_ystretch * zoom, m_red, m_green, m_blue);
406 void LightRendererSimpleLightInfo::setStencil(uint8_t stencil_ref,
float alpha_ref) {
408 m_stencil_ref = stencil_ref;
409 m_alpha_ref = alpha_ref;
411 int LightRendererSimpleLightInfo::getStencil() {
415 return m_stencil_ref;
417 float LightRendererSimpleLightInfo::getAlpha() {
420 void LightRendererSimpleLightInfo::removeStencil() {
425 std::vector<uint8_t> LightRendererSimpleLightInfo::getColor() {
426 std::vector<uint8_t> colors;
427 colors.push_back(m_red);
428 colors.push_back(m_green);
429 colors.push_back(m_blue);
430 colors.push_back(m_intensity);
434 LightRenderer* LightRenderer::getInstance(IRendererContainer* cnt) {
435 return dynamic_cast<LightRenderer*
>(cnt->getRenderer(
"LightRenderer"));
438 LightRenderer::LightRenderer(RenderBackend* renderbackend,
int position, ImagePool* imagepool, AnimationPool* animpool):
439 RendererBase(renderbackend, position),
440 m_imagepool(imagepool),
441 m_animationpool(animpool),
446 LightRenderer::LightRenderer(
const LightRenderer& old):
448 m_imagepool(old.m_imagepool),
449 m_animationpool(old.m_animationpool),
454 RendererBase* LightRenderer::clone() {
455 return new LightRenderer(*
this);
458 LightRenderer::~LightRenderer() {
461 void LightRenderer::addImage(
const std::string &group, LightRendererNode n,
int image,
int src,
int dst) {
462 LightRendererElementInfo* info =
new LightRendererImageInfo(n, image, src, dst);
463 m_groups[group].push_back(info);
466 void LightRenderer::addAnimation(
const std::string &group, LightRendererNode n,
int animation,
int src,
int dst) {
467 LightRendererElementInfo* info =
new LightRendererAnimationInfo(n, animation, src, dst);
468 m_groups[group].push_back(info);
471 void LightRenderer::addSimpleLight(
const std::string &group, LightRendererNode n, uint8_t intensity,
float radius,
int subdivisions,
float xstretch,
float ystretch, uint8_t r, uint8_t g, uint8_t b,
int src,
int dst) {
472 LightRendererElementInfo* info =
new LightRendererSimpleLightInfo(n, intensity, radius, subdivisions, xstretch, ystretch, r, g, b, src, dst);
473 m_groups[group].push_back(info);
476 void LightRenderer::resizeImage(
const std::string &group, LightRendererNode n,
int image,
int width,
int height,
int src,
int dst) {
477 LightRendererElementInfo* info =
new LightRendererResizeInfo(n, image, width, height, src, dst);
478 m_groups[group].push_back(info);
481 void LightRenderer::addStencilTest(
const std::string &group, uint8_t stencil_ref,
float alpha_ref) {
482 std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
483 for (;info_it != m_groups[group].end(); ++info_it) {
484 (*info_it)->setStencil(stencil_ref, alpha_ref);
488 void LightRenderer::removeStencilTest(
const std::string &group) {
489 std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
490 for (;info_it != m_groups[group].end(); ++info_it) {
491 (*info_it)->removeStencil();
495 std::list<std::string> LightRenderer::getGroups() {
496 std::list<std::string> groups;
497 std::map<std::string, std::vector<LightRendererElementInfo*> >::iterator group_it = m_groups.begin();
498 for(; group_it != m_groups.end(); ++group_it) {
499 groups.push_back(group_it->first);
506 std::vector<LightRendererElementInfo*> LightRenderer::getLightInfo(
const std::string &group) {
507 std::vector<LightRendererElementInfo*> info;
508 std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
509 for (;info_it != m_groups[group].end(); ++info_it) {
510 info.push_back(*info_it);
515 void LightRenderer::removeAll(
const std::string &group) {
516 std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
517 for (;info_it != m_groups[group].end(); ++info_it) {
520 m_groups[group].clear();
521 m_groups.erase(group);
524 void LightRenderer::render(Camera* cam, Layer* layer, RenderList& instances) {
525 uint8_t lm = m_renderbackend->getLightingModel();
527 if (!layer->areInstancesVisible()) {
530 m_renderbackend->disableLighting();
531 std::map<std::string, std::vector<LightRendererElementInfo*> >::iterator group_it = m_groups.begin();
532 for (; group_it != m_groups.end(); ++group_it) {
533 std::vector<LightRendererElementInfo*>::const_iterator info_it = group_it->second.begin();
534 for (;info_it != group_it->second.end(); ++info_it) {
536 if ((*info_it)->getStencil() != -1) {
537 uint8_t sref = (*info_it)->getStencil();
538 float aref = (*info_it)->getAlpha();
539 if(info_it != group_it->second.begin())
541 m_renderbackend->setStencilTest(sref, 3, 4);
542 m_renderbackend->setAlphaTest(aref);
544 m_renderbackend->setStencilTest(255, 0, 6);
545 m_renderbackend->setAlphaTest(0);
547 m_renderbackend->setStencilTest(1, 2, 4);
548 m_renderbackend->setAlphaTest(0);
550 (*info_it)->render(cam, layer, instances, m_renderbackend, m_imagepool, m_animationpool);
551 m_renderbackend->disableAlphaTest();
552 m_renderbackend->disableStencilTest();
554 (*info_it)->render(cam, layer, instances, m_renderbackend, m_imagepool, m_animationpool);
558 m_renderbackend->changeBlending(4, 5);
559 m_renderbackend->enableLighting();