FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
lightrenderer.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2011 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/animation.h"
33 #include "video/fonts/ifont.h"
34 #include "video/imagemanager.h"
35 #include "video/image.h"
36 #include "video/opengl/glimage.h"
37 #include "video/opengle/gleimage.h"
38 #include "video/opengl/renderbackendopengl.h"
39 #include "video/opengle/renderbackendopengle.h"
40 #include "util/math/fife_math.h"
41 #include "util/log/logger.h"
42 #include "util/time/timemanager.h"
43 #include "model/metamodel/grids/cellgrid.h"
44 #include "model/metamodel/timeprovider.h"
45 #include "model/structures/instance.h"
46 #include "model/structures/layer.h"
47 #include "model/structures/location.h"
48 
49 #include "view/camera.h"
50 #include "lightrenderer.h"
51 
52 
53 namespace FIFE {
54  static Logger _log(LM_VIEWVIEW);
55 
56  LightRendererElementInfo::LightRendererElementInfo(RendererNode n, int32_t src, int32_t dst):
57  m_anchor(n),
58  m_src(src),
59  m_dst(dst),
60  m_stencil(false),
61  m_stencil_ref(0) {
62  }
63  void LightRendererElementInfo::setStencil(uint8_t stencil_ref) {
64  m_stencil = true;
65  m_stencil_ref = stencil_ref;
66  }
67  int32_t LightRendererElementInfo::getStencil() {
68  if(!m_stencil) {
69  return -1;
70  }
71  return m_stencil_ref;
72  }
73  void LightRendererElementInfo::removeStencil() {
74  m_stencil = false;
75  m_stencil_ref = 0;
76  }
77  LightRendererImageInfo::LightRendererImageInfo(RendererNode anchor, ImagePtr image, int32_t src, int32_t dst):
78  LightRendererElementInfo(anchor, src, dst),
79  m_image(image){
80  }
81  void LightRendererImageInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
82  Point p = m_anchor.getCalculatedPoint(cam, layer);
83  if(m_anchor.getLayer() == layer) {
84  Rect r;
85  Rect viewport = cam->getViewPort();
86  uint32_t width = static_cast<uint32_t>(round(m_image->getWidth() * cam->getZoom()));
87  uint32_t height = static_cast<uint32_t>(round(m_image->getHeight() * cam->getZoom()));
88  r.x = p.x-width/2;
89  r.y = p.y-height/2;
90  r.w = width;
91  r.h = height;
92 
93  if(r.intersects(viewport)) {
94  uint8_t lm = renderbackend->getLightingModel();
95  m_image->render(r);
96  if (m_stencil) {
97  renderbackend->changeRenderInfos(1, m_src, m_dst, false, true, m_stencil_ref, INCR, GEQUAL);
98  } else if (lm == 1) {
99  renderbackend->changeRenderInfos(1, m_src, m_dst, false, true, 255, KEEP, NOTEQUAL);
100  }
101  }
102  }
103  }
104  LightRendererAnimationInfo::LightRendererAnimationInfo(RendererNode anchor, AnimationPtr animation, int32_t src, int32_t dst):
105  LightRendererElementInfo(anchor, src, dst),
106  m_animation(animation),
107  m_start_time(TimeManager::instance()->getTime()),
108  m_time_scale(1.0){
109  }
110  void LightRendererAnimationInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
111  Point p = m_anchor.getCalculatedPoint(cam, layer);
112  if(m_anchor.getLayer() == layer) {
113  int32_t animtime = scaleTime(m_time_scale, TimeManager::instance()->getTime() - m_start_time) % m_animation->getDuration();
114  ImagePtr img = m_animation->getFrameByTimestamp(animtime);
115  Rect r;
116  Rect viewport = cam->getViewPort();
117  uint32_t width = static_cast<uint32_t>(round(img->getWidth() * cam->getZoom()));
118  uint32_t height = static_cast<uint32_t>(round(img->getHeight() * cam->getZoom()));
119  r.x = p.x-width/2;
120  r.y = p.y-height/2;
121  r.w = width;
122  r.h = height;
123 
124  if(r.intersects(viewport)) {
125  uint8_t lm = renderbackend->getLightingModel();
126  img->render(r);
127  if (m_stencil) {
128  renderbackend->changeRenderInfos(1, m_src, m_dst, false, true, m_stencil_ref, INCR, GEQUAL);
129  } else if (lm == 1) {
130  renderbackend->changeRenderInfos(1, m_src, m_dst, false, true, 255, KEEP, NOTEQUAL);
131  }
132  }
133  }
134  }
135  LightRendererResizeInfo::LightRendererResizeInfo(RendererNode anchor, ImagePtr image, int32_t width, int32_t height, int32_t src, int32_t dst):
136  LightRendererElementInfo(anchor, src, dst),
137  m_image(image),
138  m_width(width),
139  m_height(height) {
140  }
141  void LightRendererResizeInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
142  Point p = m_anchor.getCalculatedPoint(cam, layer);
143  if(m_anchor.getLayer() == layer) {
144  Rect r;
145  Rect viewport = cam->getViewPort();
146  uint32_t width = static_cast<uint32_t>(round(m_width * cam->getZoom()));
147  uint32_t height = static_cast<uint32_t>(round(m_height * cam->getZoom()));
148  r.x = p.x-width/2;
149  r.y = p.y-height/2;
150  r.w = width;
151  r.h = height;
152 
153  if(r.intersects(viewport)) {
154  uint8_t lm = renderbackend->getLightingModel();
155  m_image->render(r);
156  if (m_stencil) {
157  renderbackend->changeRenderInfos(1, m_src, m_dst, false, true, m_stencil_ref, INCR, GEQUAL);
158  } else if (lm == 1) {
159  renderbackend->changeRenderInfos(1, m_src, m_dst, false, true, 255, KEEP, NOTEQUAL);
160  }
161  }
162  }
163  }
164  LightRendererSimpleLightInfo::LightRendererSimpleLightInfo(RendererNode anchor, uint8_t intensity, float radius, int32_t subdivisions, float xstretch, float ystretch, uint8_t r, uint8_t g, uint8_t b, int32_t src, int32_t dst):
165  LightRendererElementInfo(anchor, src, dst),
166  m_intensity(intensity),
167  m_radius(radius),
168  m_subdivisions(subdivisions),
169  m_xstretch(xstretch),
170  m_ystretch(ystretch),
171  m_red(r),
172  m_green(g),
173  m_blue(b){
174  }
175  void LightRendererSimpleLightInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
176  Point p = m_anchor.getCalculatedPoint(cam, layer);
177  if(m_anchor.getLayer() == layer) {
178  double zoom = cam->getZoom();
179 
180  uint8_t lm = renderbackend->getLightingModel();
181  renderbackend->drawLightPrimitive(p, m_intensity, m_radius, m_subdivisions,
182  static_cast<float>(m_xstretch * zoom), static_cast<float>(m_ystretch * zoom),
183  m_red, m_green, m_blue);
184 
185  if (m_stencil) {
186  renderbackend->changeRenderInfos(m_subdivisions, m_src, m_dst, false, true, m_stencil_ref, INCR, GEQUAL);
187  } else if (lm == 1) {
188  renderbackend->changeRenderInfos(m_subdivisions, m_src, m_dst, false, true, 255, KEEP, NOTEQUAL);
189  }
190  }
191  }
192  std::vector<uint8_t> LightRendererSimpleLightInfo::getColor() {
193  std::vector<uint8_t> colors;
194  colors.push_back(m_red);
195  colors.push_back(m_green);
196  colors.push_back(m_blue);
197  colors.push_back(m_intensity);
198  return colors;
199  }
200  LightRenderer* LightRenderer::getInstance(IRendererContainer* cnt) {
201  return dynamic_cast<LightRenderer*>(cnt->getRenderer("LightRenderer"));
202  }
203  LightRenderer::LightRenderer(RenderBackend* renderbackend, int32_t position):
204  RendererBase(renderbackend, position),
205  m_groups() {
206  setEnabled(false);
207  }
208  LightRenderer::LightRenderer(const LightRenderer& old):
209  RendererBase(old),
210  m_groups() {
211  setEnabled(false);
212  }
213  RendererBase* LightRenderer::clone() {
214  return new LightRenderer(*this);
215  }
216  LightRenderer::~LightRenderer() {
217  }
218  // Add a static lightmap
219  void LightRenderer::addImage(const std::string &group, RendererNode n, ImagePtr image, int32_t src, int32_t dst) {
220  LightRendererElementInfo* info = new LightRendererImageInfo(n, image, src, dst);
221  m_groups[group].push_back(info);
222  }
223  // Add a animation lightmap
224  void LightRenderer::addAnimation(const std::string &group, RendererNode n, AnimationPtr animation, int32_t src, int32_t dst) {
225  LightRendererElementInfo* info = new LightRendererAnimationInfo(n, animation, src, dst);
226  m_groups[group].push_back(info);
227  }
228  // Add a simple light
229  void LightRenderer::addSimpleLight(const std::string &group, RendererNode n, uint8_t intensity, float radius, int32_t subdivisions, float xstretch, float ystretch, uint8_t r, uint8_t g, uint8_t b, int32_t src, int32_t dst) {
230  LightRendererElementInfo* info = new LightRendererSimpleLightInfo(n, intensity, radius, subdivisions, xstretch, ystretch, r, g, b, src, dst);
231  m_groups[group].push_back(info);
232  }
233  // Resize an Image
234  void LightRenderer::resizeImage(const std::string &group, RendererNode n, ImagePtr image, int32_t width, int32_t height, int32_t src, int32_t dst) {
235  LightRendererElementInfo* info = new LightRendererResizeInfo(n, image, width, height, src, dst);
236  m_groups[group].push_back(info);
237  }
238  // Enable stencil test for the group
239  void LightRenderer::addStencilTest(const std::string &group, uint8_t stencil_ref) {
240  std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
241  for (;info_it != m_groups[group].end(); ++info_it) {
242  (*info_it)->setStencil(stencil_ref);
243  }
244  }
245  // Disable stencil test for the group
246  void LightRenderer::removeStencilTest(const std::string &group) {
247  std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
248  for (;info_it != m_groups[group].end(); ++info_it) {
249  (*info_it)->removeStencil();
250  }
251  }
252  // Return a list of all groups
253  std::list<std::string> LightRenderer::getGroups() {
254  std::list<std::string> groups;
255  std::map<std::string, std::vector<LightRendererElementInfo*> >::iterator group_it = m_groups.begin();
256  for(; group_it != m_groups.end(); ++group_it) {
257  groups.push_back(group_it->first);
258  }
259  groups.sort();
260  groups.unique();
261  return groups;
262  }
263  // Return a vector of all LightElementInfos
264  std::vector<LightRendererElementInfo*> LightRenderer::getLightInfo(const std::string &group) {
265  std::vector<LightRendererElementInfo*> info;
266  std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
267  for (;info_it != m_groups[group].end(); ++info_it) {
268  info.push_back(*info_it);
269  }
270  return info;
271  }
272  // Remove the group
273  void LightRenderer::removeAll(const std::string &group) {
274  std::vector<LightRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
275  for (;info_it != m_groups[group].end(); ++info_it) {
276  delete *info_it;
277  }
278  m_groups[group].clear();
279  m_groups.erase(group);
280  }
281  // Remove all groups
282  void LightRenderer::removeAll() {
283  m_groups.clear();
284  }
285  // Clear all groups
286  void LightRenderer::reset() {
287  removeAll();
288  }
289  // Render
290  void LightRenderer::render(Camera* cam, Layer* layer, RenderList& instances) {
291  uint8_t lm = m_renderbackend->getLightingModel();
292 
293  if (!layer->areInstancesVisible()) {
294  return;
295  }
296 
297  std::map<std::string, std::vector<LightRendererElementInfo*> >::iterator group_it = m_groups.begin();
298  for (; group_it != m_groups.end(); ++group_it) {
299  std::vector<LightRendererElementInfo*>::const_iterator info_it = group_it->second.begin();
300  for (;info_it != group_it->second.end(); ++info_it) {
301  if (lm != 0) {
302  if ((*info_it)->getStencil() != -1 && (*info_it)->getStencil() < 255) {
303  if(info_it != group_it->second.begin()) {
304  (*info_it)->setStencil((*info_it)->getStencil()+1);
305  }
306  }
307  }
308  (*info_it)->render(cam, layer, instances, m_renderbackend);
309  }
310  }
311  }
312 
313 }
virtual void setEnabled(bool enabled)
uint32_t scaleTime(float multiplier, uint32_t ticks)