source: trunk/engine/core/view/renderers/lightrenderer.cpp @ 3491

Revision 3491, 19.4 KB checked in by helios2000, 8 years ago (diff)
  • Merged the light branch back into trunk.
  • Modified the demos so they work with the new loaders and setting.
Line 
1/***************************************************************************
2 *   Copyright (C) 2005-2008 by the FIFE team                              *
3 *   http://www.fifengine.de                                               *
4 *   This file is part of FIFE.                                            *
5 *                                                                         *
6 *   FIFE is free software; you can redistribute it and/or                 *
7 *   modify it under the terms of the GNU Lesser General Public            *
8 *   License as published by the Free Software Foundation; either          *
9 *   version 2.1 of the License, or (at your option) any later version.    *
10 *                                                                         *
11 *   This library is distributed in the hope that it will be useful,       *
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14 *   Lesser General Public License for more details.                       *
15 *                                                                         *
16 *   You should have received a copy of the GNU Lesser General Public      *
17 *   License along with this library; if not, write to the                 *
18 *   Free Software Foundation, Inc.,                                       *
19 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
20 ***************************************************************************/
21
22// Standard C++ library includes
23#include <SDL.h>
24
25// 3rd party library includes
26
27// FIFE includes
28// These includes are split up in two parts, separated by one empty line
29// First block: files included from the FIFE root src directory
30// Second block: files included from the same folder
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"
46
47#include "view/camera.h"
48#include "lightrenderer.h"
49
50
51namespace FIFE {
52   static Logger _log(LM_VIEWVIEW);
53
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) {
59   }
60   LightRendererNode::LightRendererNode(Instance* attached_instance, const Location &relative_location, const Point &relative_point):
61      m_instance(attached_instance),
62      m_location(relative_location),
63      m_layer(NULL),
64      m_point(relative_point) {
65   }
66   LightRendererNode::LightRendererNode(Instance* attached_instance, Layer* relative_layer, const Point &relative_point):
67      m_instance(attached_instance),
68      m_location(NULL),
69      m_layer(relative_layer),
70      m_point(relative_point) {
71   }
72   LightRendererNode::LightRendererNode(Instance* attached_instance, const Point &relative_point):
73      m_instance(attached_instance),
74      m_location(NULL),
75      m_layer(NULL),
76      m_point(relative_point) {
77   }
78   LightRendererNode::LightRendererNode(const Location &attached_location, Layer* relative_layer, const Point &relative_point):
79      m_instance(NULL),
80      m_location(attached_location),
81      m_layer(relative_layer),
82      m_point(relative_point) {
83   }
84   LightRendererNode::LightRendererNode(const Location &attached_location, const Point &relative_point):
85      m_instance(NULL),
86      m_location(attached_location),
87      m_layer(NULL),
88      m_point(relative_point) {
89   }
90   LightRendererNode::LightRendererNode(Layer* attached_layer, const Point &relative_point):
91      m_instance(NULL),
92      m_location(NULL),
93      m_layer(attached_layer),
94      m_point(relative_point) {
95   }
96   LightRendererNode::LightRendererNode(const Point &attached_point):
97      m_instance(NULL),
98      m_location(NULL),
99      m_layer(NULL),
100      m_point(attached_point) {
101   }
102   LightRendererNode::~LightRendererNode() {
103   }
104
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;
109   }
110   void LightRendererNode::setAttached(Instance* attached_instance, const Location &relative_location) {
111      m_instance = attached_instance;
112      m_location = relative_location;
113   }
114   void LightRendererNode::setAttached(Instance* attached_instance, const Point &relative_point) {
115      m_instance = attached_instance;
116      m_point = relative_point;
117   }
118   void LightRendererNode::setAttached(Instance* attached_instance) {
119      m_instance = attached_instance;
120   }
121   void LightRendererNode::setAttached(const Location &attached_location, const Point &relative_point) {
122      m_instance = NULL;
123      m_location = attached_location;
124      m_point = relative_point;
125   }
126   void LightRendererNode::setAttached(const Location &attached_location) {
127      m_instance = NULL;
128      m_location = attached_location;
129   }
130   void LightRendererNode::setAttached(Layer* attached_layer) {
131      m_layer = attached_layer;
132   }
133   void LightRendererNode::setAttached(const Point &attached_point) {
134      m_instance = NULL;
135      m_location = NULL;
136      m_point = attached_point;
137   }
138
139   void LightRendererNode::setRelative(const Location &relative_location) {
140      if(m_instance == NULL) {
141         throw NotSupported("No instance attached.");
142      }
143      m_location = relative_location;
144   }
145   void LightRendererNode::setRelative(const Location &relative_location, Point relative_point) {
146      if(m_instance == NULL) {
147         throw NotSupported("No instance attached.");
148      }
149      m_location = relative_location;
150      m_point = relative_point;
151   }
152   void LightRendererNode::setRelative(const Point &relative_point) {
153      if(m_instance == NULL || m_location == NULL) {
154         throw NotSupported("No instance or location attached.");
155      }
156      m_point = relative_point;
157   }
158
159   Instance* LightRendererNode::getAttachedInstance() {
160      if(m_instance == NULL) {
161         throw NotSupported("No instance attached.");
162      }
163      return m_instance;
164   }
165   Location LightRendererNode::getAttachedLocation() {
166      if(m_instance != NULL || m_location == NULL) {
167         throw NotSupported("No location attached.");
168      }
169      return m_location;
170   }
171   Layer* LightRendererNode::getAttachedLayer() {
172      if(m_layer == NULL) {
173         throw NotSupported("No layer attached.");
174      }
175      return m_layer;
176   }
177   Point LightRendererNode::getAttachedPoint() {
178      if(m_instance != NULL || m_location != NULL) {
179         throw NotSupported("No point attached.");
180      }
181      return m_point;
182   }
183
184   Location LightRendererNode::getOffsetLocation() {
185      if(m_instance == NULL || m_location == NULL) {
186         throw NotSupported("No location as offset used.");
187      }
188      return m_location;
189   }
190   Point LightRendererNode::getOffsetPoint() {
191      if(m_instance == NULL && m_location == NULL) {
192         throw NotSupported("No point as offset used.");
193      }
194      return m_point;
195   }
196
197   Instance* LightRendererNode::getInstance() {
198      return m_instance;
199   }
200   Location LightRendererNode::getLocation() {
201      return m_location;
202   }
203   Layer* LightRendererNode::getLayer() {
204      return m_layer;
205   }
206   Point LightRendererNode::getPoint() {
207      return m_point;
208   }
209
210   Point LightRendererNode::getCalculatedPoint(Camera* cam, Layer* layer) {
211      ScreenPoint p;
212      if(m_instance != NULL) {
213         if(m_layer == NULL) {
214            m_layer = m_instance->getLocation().getLayer();
215         }
216         if(m_location != NULL) {
217            p = cam->toScreenCoordinates(m_instance->getLocationRef().getMapCoordinates() + m_location.getMapCoordinates());
218         } else {
219            p = cam->toScreenCoordinates(m_instance->getLocation().getMapCoordinates());
220         }
221      } else if(m_location != NULL) {
222         if(m_layer == NULL) {
223            m_layer = m_location.getLayer();
224         }
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);
230      }
231      return Point(m_point.x + p.x, m_point.y + p.y);
232   }
233
234   LightRendererImageInfo::LightRendererImageInfo(LightRendererNode anchor, int image, int src, int dst):
235      LightRendererElementInfo(),
236      m_anchor(anchor),
237      m_image(image),
238      m_src(src),
239      m_dst(dst),
240      m_stencil(false),
241      m_stencil_ref(0),
242      m_alpha_ref(0.0) {
243   }
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);
248         Rect r;
249         Rect viewport = cam->getViewPort();
250         r.x = p.x-img->getWidth()/2;
251         r.y = p.y-img->getHeight()/2;
252         r.w = img->getWidth();
253         r.h = img->getHeight();
254         renderbackend->changeBlending(m_src, m_dst);
255         if(r.intersects(viewport))
256            img->render(r);
257      }
258   }
259   void LightRendererImageInfo::setStencil(uint8_t stencil_ref, float alpha_ref) {
260      m_stencil = true;
261      m_stencil_ref = stencil_ref;
262      m_alpha_ref = alpha_ref;
263   }
264   int LightRendererImageInfo::getStencil() {
265      if(!m_stencil) {
266         return -1;
267      }
268      return m_stencil_ref;
269   }
270   float LightRendererImageInfo::getAlpha() {
271      return m_alpha_ref;
272   }
273   void LightRendererImageInfo::removeStencil() {
274      m_stencil = false;
275      m_stencil_ref = 0;
276      m_alpha_ref = 0.0;
277   }
278   
279   LightRendererAnimationInfo::LightRendererAnimationInfo(LightRendererNode anchor, int animation, int src, int dst):
280      LightRendererElementInfo(),
281      m_anchor(anchor),
282      m_animation(animation),
283      m_src(src),
284      m_dst(dst),
285      m_start_time(TimeManager::instance()->getTime()),
286      m_time_scale(1.0),
287      m_stencil(false),
288      m_stencil_ref(0),
289      m_alpha_ref(0.0) {
290   }
291   void LightRendererAnimationInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) { 
292      Point p = m_anchor.getCalculatedPoint(cam, layer);
293      if(m_anchor.getLayer() == layer) {
294         Animation& animation = animpool->getAnimation(m_animation);
295         int animtime = scaleTime(m_time_scale, TimeManager::instance()->getTime() - m_start_time) % animation.getDuration();
296         Image* img = animation.getFrameByTimestamp(animtime);
297         Rect r;
298         Rect viewport = cam->getViewPort();
299         r.x = p.x-img->getWidth()/2;
300         r.y = p.y-img->getHeight()/2;
301         r.w = img->getWidth();
302         r.h = img->getHeight();
303         renderbackend->changeBlending(m_src, m_dst);
304         if(r.intersects(viewport))
305            img->render(r);
306      }
307   }
308   void LightRendererAnimationInfo::setStencil(uint8_t stencil_ref, float alpha_ref) {
309      m_stencil = true;
310      m_stencil_ref = stencil_ref;
311      m_alpha_ref = alpha_ref;
312   }
313   int LightRendererAnimationInfo::getStencil() {
314      if(!m_stencil) {
315         return -1;
316      }
317      return m_stencil_ref;
318   }
319   float LightRendererAnimationInfo::getAlpha() {
320      return m_alpha_ref;
321   }
322   void LightRendererAnimationInfo::removeStencil() {
323      m_stencil = false;
324      m_stencil_ref = 0;
325      m_alpha_ref = 0.0;
326   }
327
328   LightRendererResizeInfo::LightRendererResizeInfo(LightRendererNode anchor, int image, int width, int height, int src, int dst):
329      LightRendererElementInfo(),
330      m_anchor(anchor),
331      m_image(image),
332      m_width(width),
333      m_height(height),
334      m_src(src),
335      m_dst(dst),
336      m_stencil(false),
337      m_stencil_ref(0),
338      m_alpha_ref(0.0) {
339   }
340   void LightRendererResizeInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
341      Point p = m_anchor.getCalculatedPoint(cam, layer);
342      if(m_anchor.getLayer() == layer) {
343         Image* img = &imagepool->getImage(m_image);
344         Rect r;
345         Rect viewport = cam->getViewPort();
346         r.x = p.x-m_width/2;
347         r.y = p.y-m_height/2;
348         r.w = m_width;
349         r.h = m_height;
350         renderbackend->changeBlending(m_src, m_dst);
351         if(r.intersects(viewport))
352            img->render(r);
353      }
354   }
355   void LightRendererResizeInfo::setStencil(uint8_t stencil_ref, float alpha_ref) {
356      m_stencil = true;
357      m_stencil_ref = stencil_ref;
358      m_alpha_ref = alpha_ref;
359   }
360   int LightRendererResizeInfo::getStencil() {
361      if(!m_stencil) {
362         return -1;
363      }
364      return m_stencil_ref;
365   }
366   float LightRendererResizeInfo::getAlpha() {
367      return m_alpha_ref;
368   }
369   void LightRendererResizeInfo::removeStencil() {
370      m_stencil = false;
371      m_stencil_ref = 0;
372      m_alpha_ref = 0.0;
373   }
374
375   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):
376      LightRendererElementInfo(),
377      m_anchor(anchor),
378      m_intensity(intensity),
379      m_radius(radius),
380      m_subdivisions(subdivisions),
381      m_xstretch(xstretch),
382      m_ystretch(ystretch),
383      m_red(r),
384      m_green(g),
385      m_blue(b),
386      m_src(src),
387      m_dst(dst),
388      m_stencil(false),
389      m_stencil_ref(0),
390      m_alpha_ref(0.0) {
391   }
392   void LightRendererSimpleLightInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {
393      Point p = m_anchor.getCalculatedPoint(cam, layer);
394      if(m_anchor.getLayer() == layer) {
395         renderbackend->changeBlending(m_src, m_dst);
396         renderbackend->drawLightPrimitive(p, m_intensity, m_radius, m_subdivisions, m_xstretch, m_ystretch, m_red, m_green, m_blue);
397      }
398   }
399   void LightRendererSimpleLightInfo::setStencil(uint8_t stencil_ref, float alpha_ref) {
400      m_stencil = true;
401      m_stencil_ref = stencil_ref;
402      m_alpha_ref = alpha_ref;
403   }
404   int LightRendererSimpleLightInfo::getStencil() {
405      if(!m_stencil) {
406         return -1;
407      }
408      return m_stencil_ref;
409   }
410   float LightRendererSimpleLightInfo::getAlpha() {
411      return m_alpha_ref;
412   }
413   void LightRendererSimpleLightInfo::removeStencil() {
414      m_stencil = false;
415      m_stencil_ref = 0;
416      m_alpha_ref = 0.0;
417   }
418   std::vector<uint8_t> LightRendererSimpleLightInfo::getColor() {
419      std::vector<uint8_t> colors;
420      colors.push_back(m_red);
421      colors.push_back(m_green);
422      colors.push_back(m_blue);
423      colors.push_back(m_intensity);
424      return colors;
425   }
426
427   LightRenderer* LightRenderer::getInstance(IRendererContainer* cnt) {
428      return dynamic_cast<LightRenderer*>(cnt->getRenderer("LightRenderer"));
429   }
430   
431   LightRenderer::LightRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool):
432      RendererBase(renderbackend, position),
433      m_imagepool(imagepool),
434      m_animationpool(animpool),
435      m_groups() {
436      setEnabled(false);
437   }
438
439   LightRenderer::LightRenderer(const LightRenderer& old):
440      RendererBase(old),
441      m_imagepool(old.m_imagepool),
442      m_animationpool(old.m_animationpool),
443      m_groups() {
444      setEnabled(false);
445   }
446
447   RendererBase* LightRenderer::clone() {
448      return new LightRenderer(*this);
449   }
450
451   LightRenderer::~LightRenderer() {
452   }
453   // Add a static lightmap
454   void LightRenderer::addImage(const std::string &group, LightRendererNode n, int image, int src, int dst) {
455      LightRendererElementInfo* info = new LightRendererImageInfo(n, image, src, dst);
456      m_groups[group].push_back(info);
457   }
458   // Add a animation lightmap
459   void LightRenderer::addAnimation(const std::string &group, LightRendererNode n, int animation, int src, int dst) {
460      LightRendererElementInfo* info = new LightRendererAnimationInfo(n, animation, src, dst);
461      m_groups[group].push_back(info);
462   }
463   // Add a simple light
464   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) {
465      LightRendererElementInfo* info = new LightRendererSimpleLightInfo(n, intensity, radius, subdivisions, xstretch, ystretch, r, g, b, src, dst);
466      m_groups[group].push_back(info);
467   }
468   // Resize an Image
469   void LightRenderer::resizeImage(const std::string &group, LightRendererNode n, int image, int width, int height, int src, int dst) {
470      LightRendererElementInfo* info = new LightRendererResizeInfo(n, image, width, height, src, dst);
471      m_groups[group].push_back(info);
472   }
473   // Enable stencil test for the group
474   void LightRenderer::addStencilTest(const std::string &group, uint8_t stencil_ref, float alpha_ref) {
475      std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
476      for (;info_it != m_groups[group].end(); ++info_it) {
477         (*info_it)->setStencil(stencil_ref, alpha_ref);
478      }
479   }
480   // Disable stencil test for the group
481   void LightRenderer::removeStencilTest(const std::string &group) {
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)->removeStencil();
485      }
486   }
487   // Return a list of all groups
488   std::list<std::string> LightRenderer::getGroups() {
489      std::list<std::string> groups;
490      std::map<std::string, std::vector<LightRendererElementInfo*> >::iterator group_it = m_groups.begin();
491      for(; group_it != m_groups.end(); ++group_it) {
492         groups.push_back(group_it->first);
493      }
494      groups.sort();
495      groups.unique();
496      return groups;
497   }
498   // Return a vector of all LightElementInfos
499   std::vector<LightRendererElementInfo*> LightRenderer::getLightInfo(const std::string &group) {
500      std::vector<LightRendererElementInfo*> info;
501      std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
502      for (;info_it != m_groups[group].end(); ++info_it) {
503         info.push_back(*info_it);
504      }
505      return info;
506   }
507   // Remove the group
508   void LightRenderer::removeAll(const std::string &group) {
509      std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
510      for (;info_it != m_groups[group].end(); ++info_it) {
511         delete *info_it;
512      }
513      m_groups[group].clear();
514      m_groups.erase(group);
515   }
516   // Render
517   void LightRenderer::render(Camera* cam, Layer* layer, RenderList& instances) {
518      uint8_t lm = m_renderbackend->getLightingModel();
519     
520      if (!layer->areInstancesVisible()) {
521         return;
522      }
523      m_renderbackend->disableLighting();
524      std::map<std::string, std::vector<LightRendererElementInfo*> >::iterator group_it = m_groups.begin();
525      for (; group_it != m_groups.end(); ++group_it) {
526         std::vector<LightRendererElementInfo*>::const_iterator info_it = group_it->second.begin();
527         for (;info_it != group_it->second.end(); ++info_it) {
528            if (lm != 0) {
529               if ((*info_it)->getStencil() != -1) {
530                  uint8_t sref = (*info_it)->getStencil();
531                  float aref = (*info_it)->getAlpha();
532                  if(info_it != group_it->second.begin())
533                     sref += 1;
534                  m_renderbackend->setStencilTest(sref, 3, 4);
535                  m_renderbackend->setAlphaTest(aref);
536               } else if(lm == 1) {
537                  m_renderbackend->setStencilTest(255, 0, 6);
538                  m_renderbackend->setAlphaTest(0);
539               } else if(lm == 2) {
540                  m_renderbackend->setStencilTest(1, 2, 4);
541                  m_renderbackend->setAlphaTest(0);
542               }
543               (*info_it)->render(cam, layer, instances, m_renderbackend, m_imagepool, m_animationpool);
544               m_renderbackend->disableAlphaTest();
545               m_renderbackend->disableStencilTest();
546            } else {
547               (*info_it)->render(cam, layer, instances, m_renderbackend, m_imagepool, m_animationpool);
548            }
549         }
550      }
551      m_renderbackend->changeBlending(4, 5);
552      m_renderbackend->enableLighting();
553   }
554
555}
Note: See TracBrowser for help on using the repository browser.