comparison engine/core/view/renderers/lightrenderer.cpp @ 661:e3140f01749d

* Merged the light branch back into trunk. * Modified the demos so they work with the new loaders and setting.
author helios2000@33b003aa-7bff-0310-803a-e67f0ece8222
date Fri, 05 Nov 2010 15:21:10 +0000
parents
children 60621d858548
comparison
equal deleted inserted replaced
660:b0733d998d0f 661:e3140f01749d
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
51 namespace 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 }