FIFE
2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2008 by the FIFE team * 00003 * http://www.fifengine.de * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 #include <SDL.h> 00024 00025 // 3rd party library includes 00026 00027 // FIFE includes 00028 // These includes are split up in two parts, separated by one empty line 00029 // First block: files included from the FIFE root src directory 00030 // Second block: files included from the same folder 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 // Add a static lightmap 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 // Add a animation lightmap 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 // Add a simple light 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 // Resize an Image 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 // Enable stencil test for the group 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 // Disable stencil test for the group 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 // Return a list of all groups 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 // Return a vector of all LightElementInfos 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 // Remove the group 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 // Render 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 }