FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator
camera.cpp
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 
00024 // 3rd party library includes
00025 #include <SDL.h>
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 
00032 #include "model/metamodel/grids/cellgrid.h"
00033 #include "model/metamodel/action.h"
00034 #include "model/metamodel/timeprovider.h"
00035 #include "model/structures/map.h"
00036 #include "model/structures/layer.h"
00037 #include "model/structures/instancetree.h"
00038 #include "model/structures/instance.h"
00039 #include "model/structures/location.h"
00040 #include "util/log/logger.h"
00041 #include "util/math/fife_math.h"
00042 #include "util/math/angles.h"
00043 #include "util/time/timemanager.h"
00044 #include "video/renderbackend.h"
00045 #include "video/image.h"
00046 #include "video/imagepool.h"
00047 #include "video/animation.h"
00048 #include "video/animationpool.h"
00049 
00050 #include "camera.h"
00051 #include "layercache.h"
00052 #include "visual.h"
00053 
00054 
00055 namespace FIFE {
00056     static Logger _log(LM_CAMERA);
00057 
00058     class MapObserver : public MapChangeListener {
00059         Camera* m_camera;
00060 
00061     public:
00062         MapObserver(Camera* camera) {
00063             m_camera = camera;
00064         }
00065         virtual ~MapObserver() {}
00066 
00067         virtual void onMapChanged(Map* map, std::vector<Layer*>& changedLayers) {
00068         }
00069 
00070         virtual void onLayerCreate(Map* map, Layer* layer) {
00071             m_camera->addLayer(layer);
00072         }
00073 
00074         virtual void onLayerDelete(Map* map, Layer* layer) {
00075             m_camera->removeLayer(layer);
00076         }
00077     };
00078 
00079     Camera::Camera(const std::string& id,
00080         Layer *layer,
00081         const Rect& viewport,
00082         RenderBackend* renderbackend,
00083         ImagePool* ipool,
00084         AnimationPool* apool):
00085             m_id(id),
00086             m_matrix(),
00087             m_inverse_matrix(),
00088             m_tilt(0),
00089             m_rotation(0),
00090             m_zoom(1),
00091             m_location(),
00092             m_prev_origo(ScreenPoint(0,0,0)),
00093             m_cur_origo(ScreenPoint(0,0,0)),
00094             m_viewport(),
00095             m_screen_cell_width(1),
00096             m_screen_cell_height(1),
00097             m_reference_scale(1),
00098             m_enabled(true),
00099             m_attachedto(NULL),
00100             m_image_dimensions(),
00101             m_iswarped(false),
00102             m_renderers(),
00103             m_pipeline(),
00104             m_updated(false),
00105             m_renderbackend(renderbackend),
00106             m_ipool(ipool),
00107             m_apool(apool),
00108             m_layer_to_instances(),
00109             m_lighting(false),
00110             m_light_colors() {
00111 
00112         m_viewport = viewport;
00113         m_map_observer = new MapObserver(this);
00114         m_map = 0;
00115         Location location;
00116         location.setLayer(layer);
00117         setLocation(location);
00118         if(m_renderbackend->getName() == "SDL") {
00119             m_backendSDL = true;
00120         } else {
00121             m_backendSDL = false;
00122         }
00123     }
00124 
00125     Camera::~Camera() {
00126         // Trigger removal of LayerCaches and MapObserver
00127         updateMap(NULL);
00128 
00129         std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
00130         for(; r_it != m_renderers.end(); ++r_it) {
00131             delete r_it->second;
00132         }
00133         m_renderers.clear();
00134         delete m_map_observer;
00135     }
00136 
00137     void Camera::setTilt(double tilt) {
00138         if(m_tilt != tilt) {
00139             m_tilt = tilt;
00140             updateReferenceScale();
00141             updateMatrices();
00142             m_iswarped = true;
00143         }
00144     }
00145 
00146     double Camera::getTilt() const {
00147         return m_tilt;
00148     }
00149 
00150     void Camera::setRotation(double rotation) {
00151         if(m_rotation != rotation) {
00152             m_rotation = rotation;
00153             updateReferenceScale();
00154             updateMatrices();
00155             m_iswarped = true;
00156         }
00157     }
00158 
00159     double Camera::getRotation() const {
00160         return m_rotation;
00161     }
00162 
00163     void Camera::setZoom(double zoom) {
00164         if(m_zoom!=zoom) {
00165             m_zoom = zoom;
00166             if (m_zoom < 0.001) {
00167                 m_zoom = 0.001;
00168             }
00169             updateMatrices();
00170         }
00171     }
00172 
00173     double Camera::getZoom() const {
00174         return m_zoom;
00175     }
00176 
00177     void Camera::setCellImageDimensions(unsigned int width, unsigned int height) {
00178         m_screen_cell_width = width;
00179         m_screen_cell_height = height;
00180         updateReferenceScale();
00181         updateMatrices();
00182         m_iswarped = true;
00183     }
00184 
00185     void Camera::setLocation(const Location& location) {
00186         // initialize first set properly
00187         if ((m_prev_origo == m_cur_origo) && (m_prev_origo == ScreenPoint(0,0,0))) {
00188             m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0));
00189             m_prev_origo = m_cur_origo;
00190         }
00191 
00192         CellGrid* cell_grid = NULL;
00193         if (location.getLayer()) {
00194             cell_grid = location.getLayer()->getCellGrid();
00195         } else {
00196             throw Exception("Location without layer given to Camera::setLocation");
00197         }
00198         if (!cell_grid) {
00199             throw Exception("Camera layer has no cellgrid specified");
00200         }
00201 
00202         m_location = location;
00203         updateMatrices();
00204 
00205         // WARNING
00206         // It is important that m_location is already set,
00207         // as the updates which are triggered here
00208         // need to calculate screen-coordinates
00209         // which depend on m_location.
00210         updateMap(location.getMap());
00211 
00212         m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0));
00213     }
00214 
00215     void Camera::updateMap(Map* map)
00216     {
00217         if(m_map == map)
00218         {
00219             return;
00220         }
00221         if(m_map) {
00222             m_map->removeChangeListener(m_map_observer);
00223             const std::list<Layer*>& layers = m_map->getLayers();
00224             for(std::list<Layer*>::const_iterator i = layers.begin(); i !=layers.end(); ++i) {
00225                 removeLayer(*i);
00226             }
00227         }
00228         if(map) {
00229             map->addChangeListener(m_map_observer);
00230             const std::list<Layer*>& layers = map->getLayers();
00231             for(std::list<Layer*>::const_iterator i = layers.begin(); i !=layers.end(); ++i)
00232                 addLayer(*i);
00233         }
00234         m_map = map;
00235     }
00236 
00237     Point Camera::getCellImageDimensions() {
00238         return getCellImageDimensions(m_location.getLayer());
00239     }
00240 
00241     Point Camera::getCellImageDimensions(Layer* layer) {
00242         if (layer == m_location.getLayer()) {
00243             return Point( m_screen_cell_width, m_screen_cell_height );
00244         }
00245         std::map<Layer*, Point>::iterator it = m_image_dimensions.find(layer);
00246         if (it != m_image_dimensions.end()) {
00247             return it->second;
00248         }
00249         Point p;
00250         CellGrid* cg = layer->getCellGrid();
00251         assert(cg);
00252         DoublePoint dimensions = getLogicalCellDimensions(layer);
00253         p.x = static_cast<int>(round(m_reference_scale * dimensions.x));
00254         p.y = static_cast<int>(round(m_reference_scale * dimensions.y));
00255         m_image_dimensions[layer] = p;
00256         return p;
00257     }
00258 
00259     Location Camera::getLocation() const {
00260         return m_location;
00261     }
00262 
00263     Location& Camera::getLocationRef() {
00264         return m_location;
00265     }
00266 
00267     void Camera::setViewPort(const Rect& viewport) {
00268         m_viewport = viewport;
00269     }
00270 
00271     const Rect& Camera::getViewPort() const {
00272         return m_viewport;
00273     }
00274 
00275     void Camera::setEnabled(bool enabled) {
00276         m_enabled = enabled;
00277     }
00278 
00279     bool Camera::isEnabled() {
00280         return m_enabled;
00281     }
00282 
00283     Point3D Camera::getOrigin() const {
00284         return m_cur_origo;
00285     }
00286 
00287     void Camera::updateMatrices() {
00288         double scale = m_reference_scale;
00289         m_matrix.loadScale(scale, scale, scale);
00290         m_vs_matrix.loadScale(scale,scale,scale);
00291         if (m_location.getLayer()) {
00292             CellGrid* cg = m_location.getLayer()->getCellGrid();
00293             if (cg) {
00294                 ExactModelCoordinate pt = m_location.getMapCoordinates();
00295                 m_matrix.applyTranslate( -pt.x *m_reference_scale,-pt.y *m_reference_scale, 0);
00296             }
00297         }
00298         scale = m_zoom;
00299         m_matrix.applyScale(scale, scale, scale);
00300         m_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
00301         m_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
00302         m_matrix.applyTranslate(+m_viewport.x+m_viewport.w/2, +m_viewport.y+m_viewport.h/2, 0);
00303         m_inverse_matrix = m_matrix.inverse();
00304 
00305 
00306         m_vs_matrix.applyTranslate(0,0,0);
00307         m_vs_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
00308         m_vs_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
00309         m_vs_inverse_matrix = m_vs_matrix.inverse();
00310 
00311         // calculate the screen<->virtual screen transformation
00312         // this explicitly ignores the z-value.
00313         m_vscreen_2_screen = m_matrix;
00314         // NOTE: mult4by4 is an in-place modification.
00315         m_vscreen_2_screen.mult4by4(m_vs_inverse_matrix);
00316         // set the z transformation to unity
00317         const int N=4;
00318         for(int i=0; i!=N; ++i) {
00319               m_vscreen_2_screen[2*N + i] = 0;
00320               m_vscreen_2_screen[i*N + 2] = 0;
00321         }
00322         m_vscreen_2_screen[2*N + 2] = 1;
00323         m_screen_2_vscreen = m_vscreen_2_screen.inverse();
00324 
00325         // FL_WARN(_log, LMsg("matrix: ") << m_matrix << " 1: " << m_matrix.inverse().mult4by4(m_matrix));
00326 //      FL_WARN(_log, LMsg("vs2s matrix: ") << m_vscreen_2_screen << " s2vs matrix: " << m_screen_2_vscreen);
00327     }
00328 
00329     void Camera::calculateZValue(ScreenPoint& screen_coords) {
00330         int dy = -(screen_coords.y - toScreenCoordinates(m_location.getMapCoordinates()).y);
00331         screen_coords.z = static_cast<int>(Mathd::Tan(m_tilt * (Mathd::pi() / 180.0)) * static_cast<double>(dy));
00332     }
00333 
00334     ExactModelCoordinate Camera::toMapCoordinates(ScreenPoint screen_coords, bool z_calculated) {
00335         if (!z_calculated) {
00336             calculateZValue(screen_coords);
00337         }
00338         return m_inverse_matrix  * intPt2doublePt(screen_coords);
00339     }
00340 
00341     ScreenPoint Camera::toScreenCoordinates(ExactModelCoordinate elevation_coords) {
00342         ExactModelCoordinate p = elevation_coords;
00343         ScreenPoint pt = doublePt2intPt( m_matrix* p  );
00344         return pt;
00345     }
00346 
00347     DoublePoint3D  Camera::toVirtualScreenCoordinates(ExactModelCoordinate elevation_coords) {
00348         ExactModelCoordinate p = elevation_coords;
00349         DoublePoint3D  pt = (m_vs_matrix * p);
00350         return pt;
00351     }
00352 
00353     ScreenPoint Camera::virtualScreenToScreen(const DoublePoint3D& p) {
00354         return doublePt2intPt(m_vscreen_2_screen * p);
00355     }
00356 
00357     DoublePoint3D Camera::screenToVirtualScreen(const ScreenPoint& p) {
00358         return m_screen_2_vscreen * intPt2doublePt(p);
00359     }
00360 
00361     DoublePoint Camera::getLogicalCellDimensions(Layer* layer) {
00362         CellGrid* cg = NULL;
00363         if (layer) {
00364             cg = layer->getCellGrid();
00365         }
00366         assert(cg);
00367 
00368         ModelCoordinate cell(0,0);
00369         std::vector<ExactModelCoordinate> vertices;
00370         cg->getVertices(vertices, cell);
00371 
00372         DoubleMatrix mtx;
00373         mtx.loadRotate(m_rotation, 0.0, 0.0, 1.0);
00374         mtx.applyRotate(m_tilt, 1.0, 0.0, 0.0);
00375 
00376         double x1 = 0;
00377         double x2 = 0;
00378         double y1 = 0;
00379         double y2 = 0;
00380 
00381         for (unsigned int i = 0; i < vertices.size(); i++) {
00382             vertices[i] = cg->toMapCoordinates(vertices[i]);
00383             vertices[i] = mtx * vertices[i];
00384             if (i == 0) {
00385                 x1 = x2 = vertices[0].x;
00386                 y1 = y2 = vertices[0].y;
00387             } else {
00388                 x1 = std::min(vertices[i].x, x1);
00389                 x2 = std::max(vertices[i].x, x2);
00390                 y1 = std::min(vertices[i].y, y1);
00391                 y2 = std::max(vertices[i].y, y2);
00392             }
00393         }
00394         return DoublePoint( x2 - x1, y2 - y1 );
00395     }
00396 
00397     void Camera::updateReferenceScale() {
00398         DoublePoint dim = getLogicalCellDimensions(m_location.getLayer());
00399         m_reference_scale = static_cast<double>(m_screen_cell_width) / dim.x;
00400 
00401         FL_DBG(_log, "Updating reference scale");
00402         FL_DBG(_log, LMsg("   tilt=") << m_tilt << " rot=" << m_rotation);
00403         FL_DBG(_log, LMsg("   m_screen_cell_width=") << m_screen_cell_width);
00404     }
00405 
00406     bool Camera::testRenderedViewPort() {
00407         Map* map = m_location.getMap();
00408         Rect cv = m_viewport;
00409         int cv2x = cv.x+cv.w;
00410         int cv2y = cv.y+cv.h;
00411         bool trec1 = false, trec2 = false, trec3 = false, trec4 = false;
00412         Rect rec1 = Rect(cv.x, cv.y, 1, 1);
00413         Rect rec2 = Rect(cv.x, cv2y, 1, 1);
00414         Rect rec3 = Rect(cv2x, cv.y, 1, 1);
00415         Rect rec4 = Rect(cv2x, cv2y, 1, 1);
00416 
00417         const std::list<Layer*>& layers = map->getLayers();
00418         std::list<Layer*>::const_iterator layer_it = layers.begin();
00419         m_layer_to_instances.clear();
00420         const RenderList& layer_instances = m_layer_to_instances[*layer_it];
00421         RenderList::const_iterator instance_it = layer_instances.begin();
00422         for(; instance_it != layer_instances.end(); ++instance_it) {
00423             const RenderItem& vc = **instance_it;
00424             if(vc.dimensions.intersects(rec1) && !trec1) {
00425                 trec1 = true;
00426             }
00427             if(vc.dimensions.intersects(rec2) && !trec2) {
00428                 trec2 = true;
00429             }
00430             if(trec1 && trec2) {
00431                 break;
00432             }
00433         }
00434         if(trec1 && trec2) {
00435             RenderList::const_reverse_iterator instance_itr = layer_instances.rbegin();
00436             for(; instance_itr != layer_instances.rend(); ++instance_itr) {
00437                 const RenderItem& vc = **instance_itr;
00438                 if(vc.dimensions.intersects(rec3) && !trec3) {
00439                     trec3 = true;
00440                 }
00441                 if(vc.dimensions.intersects(rec4) && !trec4) {
00442                     trec4 = true;
00443                 }
00444                 if(trec3 && trec4) {
00445                     break;
00446                 }
00447             }
00448         }
00449 
00450         if(trec1 && trec2 && trec3 && trec4) {
00451             return false;
00452         }
00453         return true;
00454     }
00455 
00456     void Camera::getMatchingInstances(ScreenPoint screen_coords, Layer& layer, std::list<Instance*>& instances) {
00457         instances.clear();
00458         const RenderList& layer_instances = m_layer_to_instances[&layer];
00459         RenderList::const_iterator instance_it = layer_instances.end();
00460         while (instance_it != layer_instances.begin()) {
00461             --instance_it;
00462             Instance* i = (*instance_it)->instance;
00463             const RenderItem& vc = **instance_it;
00464             if ((vc.dimensions.contains(Point(screen_coords.x, screen_coords.y)))) {
00465                 assert(vc.image);
00466                 Uint8 r, g, b, a;
00467                 int x = screen_coords.x - vc.dimensions.x;
00468                 int y = screen_coords.y - vc.dimensions.y;
00469                 if (m_zoom != 1.0) {
00470                     double fx = static_cast<double>(x);
00471                     double fy = static_cast<double>(y);
00472                     double fow = static_cast<double>(vc.image->getWidth());
00473                     double foh = static_cast<double>(vc.image->getHeight());
00474                     double fsw = static_cast<double>(vc.dimensions.w);
00475                     double fsh = static_cast<double>(vc.dimensions.h);
00476                     x = static_cast<int>(round(fx / fsw * fow));
00477                     y = static_cast<int>(round(fy / fsh * foh));
00478                 }
00479                 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00480                 // instance is hit with mouse if not totally transparent
00481                 if (a != 0) {
00482                     instances.push_back(i);
00483                 }
00484             }
00485         }
00486     }
00487 
00488     void Camera::getMatchingInstances(Rect screen_rect, Layer& layer, std::list<Instance*>& instances) {
00489         instances.clear();
00490         const RenderList& layer_instances = m_layer_to_instances[&layer];
00491         RenderList::const_iterator instance_it = layer_instances.end();
00492         while (instance_it != layer_instances.begin()) {
00493             --instance_it;
00494             Instance* i = (*instance_it)->instance;;
00495             const RenderItem& vc = **instance_it;
00496             if ((vc.dimensions.intersects(screen_rect))) {
00497                 assert(vc.image);
00498                 Uint8 r, g, b, a;
00499                 for(int xx = screen_rect.x; xx < screen_rect.x + screen_rect.w; xx++) {
00500                     for(int yy = screen_rect.y; yy < screen_rect.y + screen_rect.h; yy++) {
00501                         if ((vc.dimensions.contains(Point(xx, yy)))) {
00502                             int x = xx - vc.dimensions.x;
00503                             int y = yy - vc.dimensions.y;
00504                             if (m_zoom != 1.0) {
00505                                 double fx = static_cast<double>(x);
00506                                 double fy = static_cast<double>(y);
00507                                 double fow = static_cast<double>(vc.image->getWidth());
00508                                 double foh = static_cast<double>(vc.image->getHeight());
00509                                 double fsw = static_cast<double>(vc.dimensions.w);
00510                                 double fsh = static_cast<double>(vc.dimensions.h);
00511                                 x = static_cast<int>(round(fx / fsw * fow));
00512                                 y = static_cast<int>(round(fy / fsh * foh));
00513                             }
00514                             vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00515                             // instance is hit with mouse if not totally transparent
00516                             if (a != 0) {
00517                                 instances.push_back(i);
00518                                 goto found_non_transparent_pixel;
00519                             }
00520                         }
00521                     }
00522                 }
00523                 found_non_transparent_pixel:;
00524             }
00525         }
00526     }
00527 
00528     void Camera::getMatchingInstances(Location& loc, std::list<Instance*>& instances, bool use_exactcoordinates) {
00529         instances.clear();
00530         const RenderList& layer_instances = m_layer_to_instances[loc.getLayer()];
00531         RenderList::const_iterator instance_it = layer_instances.end();
00532         while (instance_it != layer_instances.begin()) {
00533             --instance_it;
00534             Instance* i = (*instance_it)->instance;
00535             if (use_exactcoordinates) {
00536                 if (i->getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
00537                     instances.push_back(i);
00538                 }
00539             } else {
00540                 if (i->getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
00541                     instances.push_back(i);
00542                 }
00543             }
00544         }
00545     }
00546 
00547     void Camera::attach(Instance *instance) {
00548         // fail if the layers aren't the same
00549         if (m_location.getLayer()->getId() != instance->getLocation().getLayer()->getId()) {
00550             FL_WARN(_log, "Tried to attach camera to instance on different layer.");
00551             return ;
00552         }
00553         m_attachedto = instance;
00554     }
00555 
00556     void Camera::detach() {
00557         m_attachedto = NULL;
00558     }
00559 
00560     void Camera::update() {
00561         if( !m_attachedto ) {
00562             return;
00563         }
00564         Location loc(m_location);
00565         loc.setExactLayerCoordinates( m_attachedto->getLocationRef().getExactLayerCoordinates(m_location.getLayer()) );
00566         setLocation(loc);
00567         updateMatrices();
00568     }
00569 
00570     void Camera::refresh() {
00571         updateMatrices();
00572         m_iswarped = true;
00573     }
00574 
00575     void Camera::resetUpdates() {
00576         m_iswarped = false;
00577         m_prev_origo = m_cur_origo;
00578     }
00579 
00580     bool pipelineSort(const RendererBase* lhs, const RendererBase* rhs) {
00581         return (lhs->getPipelinePosition() < rhs->getPipelinePosition());
00582     }
00583 
00584     void Camera::addRenderer(RendererBase* renderer) {
00585         renderer->setRendererListener(this);
00586         m_renderers[renderer->getName()] = renderer;
00587         if (renderer->isEnabled()) {
00588             m_pipeline.push_back(renderer);
00589         }
00590         m_pipeline.sort(pipelineSort);
00591     }
00592 
00593     void Camera::onRendererPipelinePositionChanged(RendererBase* renderer) {
00594         m_pipeline.sort(pipelineSort);
00595     }
00596 
00597     void Camera::onRendererEnabledChanged(RendererBase* renderer) {
00598         assert(m_renderers[renderer->getName()]);
00599         if (renderer->isEnabled()) {
00600             FL_LOG(_log, LMsg("Enabling renderer ") << renderer->getName());
00601             m_pipeline.push_back(renderer);
00602             m_pipeline.sort(pipelineSort);
00603         } else {
00604             m_pipeline.remove(renderer);
00605         }
00606     }
00607 
00608     RendererBase* Camera::getRenderer(const std::string& name) {
00609         return m_renderers[name];
00610     }
00611 
00612     void Camera::resetRenderers() {
00613         std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
00614         for (; r_it != m_renderers.end(); ++r_it) {
00615             Map* map = m_location.getMap();
00616             r_it->second->reset();
00617         }
00618     }
00619 
00620     void Camera::addLayer(Layer* layer) {
00621         m_cache[layer] = new LayerCache(this, m_ipool, m_apool);
00622         m_cache[layer]->setLayer(layer);
00623         m_layer_to_instances[layer] = RenderList();
00624     }
00625 
00626     void Camera::removeLayer(Layer* layer) {
00627         delete m_cache[layer];
00628         m_cache.erase(layer);
00629         m_layer_to_instances.erase(layer);
00630     }
00631 
00632     void Camera::setLightingColor(float red, float green, float blue, float alpha) {
00633         m_lighting = true;
00634         m_light_colors.clear();
00635         m_light_colors.push_back(red);
00636         m_light_colors.push_back(green);
00637         m_light_colors.push_back(blue);
00638         m_light_colors.push_back(alpha);
00639     }
00640 
00641     std::vector<float> Camera::getLightingColor() {
00642         if(m_light_colors.empty()) {
00643             for(int colors = 0; colors != 4; ++colors) {
00644                 m_light_colors.push_back(1.0f);
00645             }
00646         }
00647         return m_light_colors;
00648     }
00649 
00650     void Camera::resetLightingColor() {
00651         m_lighting = false;
00652         m_renderbackend->resetLighting();
00653     }
00654 
00655     void Camera::render() {
00656         Transform transform = NormalTransform;
00657         if(m_iswarped)
00658               transform = WarpedTransform;
00659         m_iswarped = false;
00660 
00661         Map* map = m_location.getMap();
00662         if (!map) {
00663             FL_ERR(_log, "No map for camera found");
00664             return;
00665         }
00666         //if ((!map->isChanged()) && (!m_iswarped) && (cammove == ScreenPoint(0,0,0))) {
00667         //  return;
00668         //}
00669 
00670         if (m_renderbackend->getLightingModel() != 0) {
00671             m_renderbackend->resetStencilBuffer(0);
00672             if (m_lighting) {
00673                 m_renderbackend->setLighting(m_light_colors[0], m_light_colors[1], m_light_colors[2], m_light_colors[3]);
00674             }
00675         }
00676 
00677         if(m_backendSDL) {
00678             m_renderbackend->pushClipArea(getViewPort());
00679         } else {
00680             m_renderbackend->pushClipArea(getViewPort(), testRenderedViewPort());
00681         }
00682 
00683         // update each layer
00684 //      m_layer_to_instances.clear();
00685 
00686         const std::list<Layer*>& layers = map->getLayers();
00687         std::list<Layer*>::const_iterator layer_it = layers.begin();
00688         for (;layer_it != layers.end(); ++layer_it) {
00689             LayerCache* cache = m_cache[*layer_it];
00690             if(!cache) {
00691                 addLayer(*layer_it);
00692                 cache = m_cache[*layer_it];
00693                 FL_ERR(_log, LMsg("Layer Cache miss! (This shouldn't happen!)") << (*layer_it)->getId());
00694             }
00695             RenderList& instances_to_render = m_layer_to_instances[*layer_it];
00696             cache->update(transform, instances_to_render);
00697 
00698             std::list<RendererBase*>::iterator r_it = m_pipeline.begin();
00699             for (; r_it != m_pipeline.end(); ++r_it) {
00700                 if ((*r_it)->isActivedLayer(*layer_it)) {
00701                     (*r_it)->render(this, *layer_it, instances_to_render);
00702                 }
00703             }
00704         }
00705 
00706         if (m_lighting) {
00707             m_renderbackend->resetLighting();
00708         }
00709 
00710         m_renderbackend->popClipArea();
00711         resetUpdates();
00712         m_updated = true;
00713     }
00714 
00715 }