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 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 }