00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <SDL.h>
00024
00025
00026
00027
00028
00029
00030
00031 #include "video/renderbackend.h"
00032 #include "video/imagepool.h"
00033 #include "video/animation.h"
00034 #include "video/animationpool.h"
00035 #include "video/fonts/abstractfont.h"
00036 #include "video/image.h"
00037 #include "video/opengl/glimage.h"
00038 #include "util/math/fife_math.h"
00039 #include "util/log/logger.h"
00040 #include "util/time/timemanager.h"
00041 #include "model/metamodel/grids/cellgrid.h"
00042 #include "model/metamodel/timeprovider.h"
00043 #include "model/structures/instance.h"
00044 #include "model/structures/layer.h"
00045 #include "model/structures/location.h"
00046
00047 #include "view/camera.h"
00048 #include "lightrenderer.h"
00049
00050
00051 namespace FIFE {
00052 static Logger _log(LM_VIEWVIEW);
00053
00054 LightRendererNode::LightRendererNode(Instance* attached_instance, const Location &relative_location, Layer* relative_layer, const Point &relative_point):
00055 m_instance(attached_instance),
00056 m_location(relative_location),
00057 m_layer(relative_layer),
00058 m_point(relative_point) {
00059 }
00060 LightRendererNode::LightRendererNode(Instance* attached_instance, const Location &relative_location, const Point &relative_point):
00061 m_instance(attached_instance),
00062 m_location(relative_location),
00063 m_layer(NULL),
00064 m_point(relative_point) {
00065 }
00066 LightRendererNode::LightRendererNode(Instance* attached_instance, Layer* relative_layer, const Point &relative_point):
00067 m_instance(attached_instance),
00068 m_location(NULL),
00069 m_layer(relative_layer),
00070 m_point(relative_point) {
00071 }
00072 LightRendererNode::LightRendererNode(Instance* attached_instance, const Point &relative_point):
00073 m_instance(attached_instance),
00074 m_location(NULL),
00075 m_layer(NULL),
00076 m_point(relative_point) {
00077 }
00078 LightRendererNode::LightRendererNode(const Location &attached_location, Layer* relative_layer, const Point &relative_point):
00079 m_instance(NULL),
00080 m_location(attached_location),
00081 m_layer(relative_layer),
00082 m_point(relative_point) {
00083 }
00084 LightRendererNode::LightRendererNode(const Location &attached_location, const Point &relative_point):
00085 m_instance(NULL),
00086 m_location(attached_location),
00087 m_layer(NULL),
00088 m_point(relative_point) {
00089 }
00090 LightRendererNode::LightRendererNode(Layer* attached_layer, const Point &relative_point):
00091 m_instance(NULL),
00092 m_location(NULL),
00093 m_layer(attached_layer),
00094 m_point(relative_point) {
00095 }
00096 LightRendererNode::LightRendererNode(const Point &attached_point):
00097 m_instance(NULL),
00098 m_location(NULL),
00099 m_layer(NULL),
00100 m_point(attached_point) {
00101 }
00102 LightRendererNode::~LightRendererNode() {
00103 }
00104
00105 void LightRendererNode::setAttached(Instance* attached_instance, const Location &relative_location, const Point &relative_point) {
00106 m_instance = attached_instance;
00107 m_location = relative_location;
00108 m_point = relative_point;
00109 }
00110 void LightRendererNode::setAttached(Instance* attached_instance, const Location &relative_location) {
00111 m_instance = attached_instance;
00112 m_location = relative_location;
00113 }
00114 void LightRendererNode::setAttached(Instance* attached_instance, const Point &relative_point) {
00115 m_instance = attached_instance;
00116 m_point = relative_point;
00117 }
00118 void LightRendererNode::setAttached(Instance* attached_instance) {
00119 m_instance = attached_instance;
00120 }
00121 void LightRendererNode::setAttached(const Location &attached_location, const Point &relative_point) {
00122 m_instance = NULL;
00123 m_location = attached_location;
00124 m_point = relative_point;
00125 }
00126 void LightRendererNode::setAttached(const Location &attached_location) {
00127 m_instance = NULL;
00128 m_location = attached_location;
00129 }
00130 void LightRendererNode::setAttached(Layer* attached_layer) {
00131 m_layer = attached_layer;
00132 }
00133 void LightRendererNode::setAttached(const Point &attached_point) {
00134 m_instance = NULL;
00135 m_location = NULL;
00136 m_point = attached_point;
00137 }
00138
00139 void LightRendererNode::setRelative(const Location &relative_location) {
00140 if(m_instance == NULL) {
00141 throw NotSupported("No instance attached.");
00142 }
00143 m_location = relative_location;
00144 }
00145 void LightRendererNode::setRelative(const Location &relative_location, Point relative_point) {
00146 if(m_instance == NULL) {
00147 throw NotSupported("No instance attached.");
00148 }
00149 m_location = relative_location;
00150 m_point = relative_point;
00151 }
00152 void LightRendererNode::setRelative(const Point &relative_point) {
00153 if(m_instance == NULL || m_location == NULL) {
00154 throw NotSupported("No instance or location attached.");
00155 }
00156 m_point = relative_point;
00157 }
00158
00159 Instance* LightRendererNode::getAttachedInstance() {
00160 if(m_instance == NULL) {
00161 throw NotSupported("No instance attached.");
00162 }
00163 return m_instance;
00164 }
00165 Location LightRendererNode::getAttachedLocation() {
00166 if(m_instance != NULL || m_location == NULL) {
00167 throw NotSupported("No location attached.");
00168 }
00169 return m_location;
00170 }
00171 Layer* LightRendererNode::getAttachedLayer() {
00172 if(m_layer == NULL) {
00173 throw NotSupported("No layer attached.");
00174 }
00175 return m_layer;
00176 }
00177 Point LightRendererNode::getAttachedPoint() {
00178 if(m_instance != NULL || m_location != NULL) {
00179 throw NotSupported("No point attached.");
00180 }
00181 return m_point;
00182 }
00183
00184 Location LightRendererNode::getOffsetLocation() {
00185 if(m_instance == NULL || m_location == NULL) {
00186 throw NotSupported("No location as offset used.");
00187 }
00188 return m_location;
00189 }
00190 Point LightRendererNode::getOffsetPoint() {
00191 if(m_instance == NULL && m_location == NULL) {
00192 throw NotSupported("No point as offset used.");
00193 }
00194 return m_point;
00195 }
00196
00197 Instance* LightRendererNode::getInstance() {
00198 return m_instance;
00199 }
00200 Location LightRendererNode::getLocation() {
00201 return m_location;
00202 }
00203 Layer* LightRendererNode::getLayer() {
00204 return m_layer;
00205 }
00206 Point LightRendererNode::getPoint() {
00207 return m_point;
00208 }
00209
00210 Point LightRendererNode::getCalculatedPoint(Camera* cam, Layer* layer) {
00211 ScreenPoint p;
00212 if(m_instance != NULL) {
00213 if(m_layer == NULL) {
00214 m_layer = m_instance->getLocation().getLayer();
00215 }
00216 if(m_location != NULL) {
00217 p = cam->toScreenCoordinates(m_instance->getLocationRef().getMapCoordinates() + m_location.getMapCoordinates());
00218 } else {
00219 p = cam->toScreenCoordinates(m_instance->getLocation().getMapCoordinates());
00220 }
00221 } else if(m_location != NULL) {
00222 if(m_layer == NULL) {
00223 m_layer = m_location.getLayer();
00224 }
00225 p = cam->toScreenCoordinates(m_location.getMapCoordinates());
00226 } else if(m_layer == NULL) {
00227 const std::list<Layer*>& layers = cam->getRenderer("LightRenderer")->getActiveLayers();
00228 std::list<Layer*>::const_reverse_iterator layer_it = layers.rbegin();
00229 setAttached(*layer_it);
00230 }
00231 return Point(m_point.x + p.x, m_point.y + p.y);
00232 }
00233
00234 LightRendererImageInfo::LightRendererImageInfo(LightRendererNode anchor, int image, int src, int dst):
00235 LightRendererElementInfo(),
00236 m_anchor(anchor),
00237 m_image(image),
00238 m_src(src),
00239 m_dst(dst),
00240 m_stencil(false),
00241 m_stencil_ref(0),
00242 m_alpha_ref(0.0) {
00243 }
00244 void LightRendererImageInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
00245 Point p = m_anchor.getCalculatedPoint(cam, layer);
00246 if(m_anchor.getLayer() == layer) {
00247 Image* img = &imagepool->getImage(m_image);
00248 Rect r;
00249 Rect viewport = cam->getViewPort();
00250 unsigned int widtht = round(img->getWidth() * cam->getZoom());
00251 unsigned int height = round(img->getHeight() * cam->getZoom());
00252 r.x = p.x-widtht/2;
00253 r.y = p.y-height/2;
00254 r.w = widtht;
00255 r.h = height;
00256 renderbackend->changeBlending(m_src, m_dst);
00257 if(r.intersects(viewport))
00258 img->render(r);
00259 }
00260 }
00261 void LightRendererImageInfo::setStencil(uint8_t stencil_ref, float alpha_ref) {
00262 m_stencil = true;
00263 m_stencil_ref = stencil_ref;
00264 m_alpha_ref = alpha_ref;
00265 }
00266 int LightRendererImageInfo::getStencil() {
00267 if(!m_stencil) {
00268 return -1;
00269 }
00270 return m_stencil_ref;
00271 }
00272 float LightRendererImageInfo::getAlpha() {
00273 return m_alpha_ref;
00274 }
00275 void LightRendererImageInfo::removeStencil() {
00276 m_stencil = false;
00277 m_stencil_ref = 0;
00278 m_alpha_ref = 0.0;
00279 }
00280
00281 LightRendererAnimationInfo::LightRendererAnimationInfo(LightRendererNode anchor, int animation, int src, int dst):
00282 LightRendererElementInfo(),
00283 m_anchor(anchor),
00284 m_animation(animation),
00285 m_src(src),
00286 m_dst(dst),
00287 m_start_time(TimeManager::instance()->getTime()),
00288 m_time_scale(1.0),
00289 m_stencil(false),
00290 m_stencil_ref(0),
00291 m_alpha_ref(0.0) {
00292 }
00293 void LightRendererAnimationInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
00294 Point p = m_anchor.getCalculatedPoint(cam, layer);
00295 if(m_anchor.getLayer() == layer) {
00296 Animation& animation = animpool->getAnimation(m_animation);
00297 int animtime = scaleTime(m_time_scale, TimeManager::instance()->getTime() - m_start_time) % animation.getDuration();
00298 Image* img = animation.getFrameByTimestamp(animtime);
00299 Rect r;
00300 Rect viewport = cam->getViewPort();
00301 unsigned int widtht = round(img->getWidth() * cam->getZoom());
00302 unsigned int height = round(img->getHeight() * cam->getZoom());
00303 r.x = p.x-widtht/2;
00304 r.y = p.y-height/2;
00305 r.w = widtht;
00306 r.h = height;
00307 renderbackend->changeBlending(m_src, m_dst);
00308 if(r.intersects(viewport))
00309 img->render(r);
00310 }
00311 }
00312 void LightRendererAnimationInfo::setStencil(uint8_t stencil_ref, float alpha_ref) {
00313 m_stencil = true;
00314 m_stencil_ref = stencil_ref;
00315 m_alpha_ref = alpha_ref;
00316 }
00317 int LightRendererAnimationInfo::getStencil() {
00318 if(!m_stencil) {
00319 return -1;
00320 }
00321 return m_stencil_ref;
00322 }
00323 float LightRendererAnimationInfo::getAlpha() {
00324 return m_alpha_ref;
00325 }
00326 void LightRendererAnimationInfo::removeStencil() {
00327 m_stencil = false;
00328 m_stencil_ref = 0;
00329 m_alpha_ref = 0.0;
00330 }
00331
00332 LightRendererResizeInfo::LightRendererResizeInfo(LightRendererNode anchor, int image, int width, int height, int src, int dst):
00333 LightRendererElementInfo(),
00334 m_anchor(anchor),
00335 m_image(image),
00336 m_width(width),
00337 m_height(height),
00338 m_src(src),
00339 m_dst(dst),
00340 m_stencil(false),
00341 m_stencil_ref(0),
00342 m_alpha_ref(0.0) {
00343 }
00344 void LightRendererResizeInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
00345 Point p = m_anchor.getCalculatedPoint(cam, layer);
00346 if(m_anchor.getLayer() == layer) {
00347 Image* img = &imagepool->getImage(m_image);
00348 Rect r;
00349 Rect viewport = cam->getViewPort();
00350 unsigned int widtht = round(m_width * cam->getZoom());
00351 unsigned int height = round(m_height * cam->getZoom());
00352 r.x = p.x-widtht/2;
00353 r.y = p.y-height/2;
00354 r.w = widtht;
00355 r.h = height;
00356 renderbackend->changeBlending(m_src, m_dst);
00357 if(r.intersects(viewport))
00358 img->render(r);
00359 }
00360 }
00361 void LightRendererResizeInfo::setStencil(uint8_t stencil_ref, float alpha_ref) {
00362 m_stencil = true;
00363 m_stencil_ref = stencil_ref;
00364 m_alpha_ref = alpha_ref;
00365 }
00366 int LightRendererResizeInfo::getStencil() {
00367 if(!m_stencil) {
00368 return -1;
00369 }
00370 return m_stencil_ref;
00371 }
00372 float LightRendererResizeInfo::getAlpha() {
00373 return m_alpha_ref;
00374 }
00375 void LightRendererResizeInfo::removeStencil() {
00376 m_stencil = false;
00377 m_stencil_ref = 0;
00378 m_alpha_ref = 0.0;
00379 }
00380
00381 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):
00382 LightRendererElementInfo(),
00383 m_anchor(anchor),
00384 m_intensity(intensity),
00385 m_radius(radius),
00386 m_subdivisions(subdivisions),
00387 m_xstretch(xstretch),
00388 m_ystretch(ystretch),
00389 m_red(r),
00390 m_green(g),
00391 m_blue(b),
00392 m_src(src),
00393 m_dst(dst),
00394 m_stencil(false),
00395 m_stencil_ref(0),
00396 m_alpha_ref(0.0) {
00397 }
00398 void LightRendererSimpleLightInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
00399 Point p = m_anchor.getCalculatedPoint(cam, layer);
00400 if(m_anchor.getLayer() == layer) {
00401 double zoom = cam->getZoom();
00402 renderbackend->changeBlending(m_src, m_dst);
00403 renderbackend->drawLightPrimitive(p, m_intensity, m_radius, m_subdivisions, m_xstretch * zoom, m_ystretch * zoom, m_red, m_green, m_blue);
00404 }
00405 }
00406 void LightRendererSimpleLightInfo::setStencil(uint8_t stencil_ref, float alpha_ref) {
00407 m_stencil = true;
00408 m_stencil_ref = stencil_ref;
00409 m_alpha_ref = alpha_ref;
00410 }
00411 int LightRendererSimpleLightInfo::getStencil() {
00412 if(!m_stencil) {
00413 return -1;
00414 }
00415 return m_stencil_ref;
00416 }
00417 float LightRendererSimpleLightInfo::getAlpha() {
00418 return m_alpha_ref;
00419 }
00420 void LightRendererSimpleLightInfo::removeStencil() {
00421 m_stencil = false;
00422 m_stencil_ref = 0;
00423 m_alpha_ref = 0.0;
00424 }
00425 std::vector<uint8_t> LightRendererSimpleLightInfo::getColor() {
00426 std::vector<uint8_t> colors;
00427 colors.push_back(m_red);
00428 colors.push_back(m_green);
00429 colors.push_back(m_blue);
00430 colors.push_back(m_intensity);
00431 return colors;
00432 }
00433
00434 LightRenderer* LightRenderer::getInstance(IRendererContainer* cnt) {
00435 return dynamic_cast<LightRenderer*>(cnt->getRenderer("LightRenderer"));
00436 }
00437
00438 LightRenderer::LightRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool):
00439 RendererBase(renderbackend, position),
00440 m_imagepool(imagepool),
00441 m_animationpool(animpool),
00442 m_groups() {
00443 setEnabled(false);
00444 }
00445
00446 LightRenderer::LightRenderer(const LightRenderer& old):
00447 RendererBase(old),
00448 m_imagepool(old.m_imagepool),
00449 m_animationpool(old.m_animationpool),
00450 m_groups() {
00451 setEnabled(false);
00452 }
00453
00454 RendererBase* LightRenderer::clone() {
00455 return new LightRenderer(*this);
00456 }
00457
00458 LightRenderer::~LightRenderer() {
00459 }
00460
00461 void LightRenderer::addImage(const std::string &group, LightRendererNode n, int image, int src, int dst) {
00462 LightRendererElementInfo* info = new LightRendererImageInfo(n, image, src, dst);
00463 m_groups[group].push_back(info);
00464 }
00465
00466 void LightRenderer::addAnimation(const std::string &group, LightRendererNode n, int animation, int src, int dst) {
00467 LightRendererElementInfo* info = new LightRendererAnimationInfo(n, animation, src, dst);
00468 m_groups[group].push_back(info);
00469 }
00470
00471 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) {
00472 LightRendererElementInfo* info = new LightRendererSimpleLightInfo(n, intensity, radius, subdivisions, xstretch, ystretch, r, g, b, src, dst);
00473 m_groups[group].push_back(info);
00474 }
00475
00476 void LightRenderer::resizeImage(const std::string &group, LightRendererNode n, int image, int width, int height, int src, int dst) {
00477 LightRendererElementInfo* info = new LightRendererResizeInfo(n, image, width, height, src, dst);
00478 m_groups[group].push_back(info);
00479 }
00480
00481 void LightRenderer::addStencilTest(const std::string &group, uint8_t stencil_ref, float alpha_ref) {
00482 std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
00483 for (;info_it != m_groups[group].end(); ++info_it) {
00484 (*info_it)->setStencil(stencil_ref, alpha_ref);
00485 }
00486 }
00487
00488 void LightRenderer::removeStencilTest(const std::string &group) {
00489 std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
00490 for (;info_it != m_groups[group].end(); ++info_it) {
00491 (*info_it)->removeStencil();
00492 }
00493 }
00494
00495 std::list<std::string> LightRenderer::getGroups() {
00496 std::list<std::string> groups;
00497 std::map<std::string, std::vector<LightRendererElementInfo*> >::iterator group_it = m_groups.begin();
00498 for(; group_it != m_groups.end(); ++group_it) {
00499 groups.push_back(group_it->first);
00500 }
00501 groups.sort();
00502 groups.unique();
00503 return groups;
00504 }
00505
00506 std::vector<LightRendererElementInfo*> LightRenderer::getLightInfo(const std::string &group) {
00507 std::vector<LightRendererElementInfo*> info;
00508 std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
00509 for (;info_it != m_groups[group].end(); ++info_it) {
00510 info.push_back(*info_it);
00511 }
00512 return info;
00513 }
00514
00515 void LightRenderer::removeAll(const std::string &group) {
00516 std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
00517 for (;info_it != m_groups[group].end(); ++info_it) {
00518 delete *info_it;
00519 }
00520 m_groups[group].clear();
00521 m_groups.erase(group);
00522 }
00523
00524 void LightRenderer::render(Camera* cam, Layer* layer, RenderList& instances) {
00525 uint8_t lm = m_renderbackend->getLightingModel();
00526
00527 if (!layer->areInstancesVisible()) {
00528 return;
00529 }
00530 m_renderbackend->disableLighting();
00531 std::map<std::string, std::vector<LightRendererElementInfo*> >::iterator group_it = m_groups.begin();
00532 for (; group_it != m_groups.end(); ++group_it) {
00533 std::vector<LightRendererElementInfo*>::const_iterator info_it = group_it->second.begin();
00534 for (;info_it != group_it->second.end(); ++info_it) {
00535 if (lm != 0) {
00536 if ((*info_it)->getStencil() != -1) {
00537 uint8_t sref = (*info_it)->getStencil();
00538 float aref = (*info_it)->getAlpha();
00539 if(info_it != group_it->second.begin())
00540 sref += 1;
00541 m_renderbackend->setStencilTest(sref, 3, 4);
00542 m_renderbackend->setAlphaTest(aref);
00543 } else if(lm == 1) {
00544 m_renderbackend->setStencilTest(255, 0, 6);
00545 m_renderbackend->setAlphaTest(0);
00546 } else if(lm == 2) {
00547 m_renderbackend->setStencilTest(1, 2, 4);
00548 m_renderbackend->setAlphaTest(0);
00549 }
00550 (*info_it)->render(cam, layer, instances, m_renderbackend, m_imagepool, m_animationpool);
00551 m_renderbackend->disableAlphaTest();
00552 m_renderbackend->disableStencilTest();
00553 } else {
00554 (*info_it)->render(cam, layer, instances, m_renderbackend, m_imagepool, m_animationpool);
00555 }
00556 }
00557 }
00558 m_renderbackend->changeBlending(4, 5);
00559 m_renderbackend->enableLighting();
00560 }
00561
00562 }