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 "visual.h"
00052 
00053 
00054 namespace FIFE {
00055     static Logger _log(LM_CAMERA);
00056 
00057     Camera::Camera(const std::string& id,
00058         Layer *layer,
00059         const Rect& viewport,
00060         const ExactModelCoordinate& emc,
00061         RenderBackend* renderbackend,
00062         ImagePool* ipool,
00063         AnimationPool* apool):
00064             m_id(id),
00065             m_matrix(),
00066             m_inverse_matrix(),
00067             m_tilt(0),
00068             m_rotation(0),
00069             m_zoom(1),
00070             m_location(),
00071             m_prev_origo(ScreenPoint(0,0,0)),
00072             m_cur_origo(ScreenPoint(0,0,0)),
00073             m_viewport(),
00074             m_screen_cell_width(1),
00075             m_screen_cell_height(1),
00076             m_reference_scale(1),
00077             m_enabled(true),
00078             m_attachedto(NULL),
00079             m_image_dimensions(),
00080             m_iswarped(false),
00081             m_renderers(),
00082             m_pipeline(),
00083             m_updated(false),
00084             m_renderbackend(renderbackend),
00085             m_ipool(ipool),
00086             m_apool(apool),
00087             m_layer_to_instances() {
00088         m_location.setLayer(layer);
00089         m_location.setExactLayerCoordinates(emc);
00090         m_viewport = viewport;
00091     }
00092 
00093     Camera::~Camera() {
00094         std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
00095         for(; r_it != m_renderers.end(); ++r_it) {
00096             delete r_it->second;
00097         }
00098         m_renderers.clear();
00099     }
00100 
00101     void Camera::setTilt(double tilt) {
00102         m_tilt = tilt;
00103         updateReferenceScale();
00104         updateMatrices();
00105         m_iswarped = true;
00106     }
00107 
00108     double Camera::getTilt() const {
00109         return m_tilt;
00110     }
00111 
00112     void Camera::setRotation(double rotation) {
00113         m_rotation = rotation;
00114         updateReferenceScale();
00115         updateMatrices();
00116         m_iswarped = true;
00117     }
00118 
00119     double Camera::getRotation() const {
00120         return m_rotation;
00121     }
00122 
00123     void Camera::setZoom(double zoom) {
00124         m_zoom = zoom;
00125         if (m_zoom < 0.001) {
00126             m_zoom = 0.001;
00127         }
00128         updateMatrices();
00129         m_iswarped = true;
00130     }
00131 
00132     double Camera::getZoom() const {
00133         return m_zoom;
00134     }
00135 
00136     void Camera::setCellImageDimensions(unsigned int width, unsigned int height) {
00137         m_screen_cell_width = width;
00138         m_screen_cell_height = height;
00139         updateReferenceScale();
00140         updateMatrices();
00141         m_iswarped = true;
00142     }
00143 
00144     void Camera::setLocation(const Location& location) {
00145         // initialize first set properly
00146         if ((m_prev_origo == m_cur_origo) && (m_prev_origo == ScreenPoint(0,0,0))) {
00147             m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0));
00148             m_prev_origo = m_cur_origo;
00149         }
00150         m_location = location;
00151 
00152         CellGrid* cg = NULL;
00153         if (m_location.getLayer()) {
00154             cg = m_location.getLayer()->getCellGrid();
00155         } else {
00156             throw Exception("Location without layer given to Camera::setLocation");
00157         }
00158         if (!cg) {
00159             throw Exception("Camera layer has no cellgrid specified");
00160         }
00161 
00162         updateMatrices();
00163 
00164         m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0));
00165     }
00166 
00167     Point Camera::getCellImageDimensions() {
00168         return getCellImageDimensions(m_location.getLayer());
00169     }
00170 
00171     Point Camera::getCellImageDimensions(Layer* layer) {
00172         if (layer == m_location.getLayer()) {
00173             return Point( m_screen_cell_width, m_screen_cell_height );
00174         }
00175         std::map<Layer*, Point>::iterator it = m_image_dimensions.find(layer);
00176         if (it != m_image_dimensions.end()) {
00177             return it->second;
00178         }
00179         Point p;
00180         CellGrid* cg = layer->getCellGrid();
00181         assert(cg);
00182         DoublePoint dimensions = getLogicalCellDimensions(layer);
00183         p.x = static_cast<int>(round(m_reference_scale * dimensions.x));
00184         p.y = static_cast<int>(round(m_reference_scale * dimensions.y));
00185         m_image_dimensions[layer] = p;
00186         return p;
00187     }
00188 
00189     Location Camera::getLocation() const {
00190         return m_location;
00191     }
00192 
00193     Location& Camera::getLocationRef() {
00194         return m_location;
00195     }
00196 
00197     void Camera::setViewPort(const Rect& viewport) {
00198         m_viewport = viewport;
00199     }
00200 
00201     const Rect& Camera::getViewPort() const {
00202         return m_viewport;
00203     }
00204 
00205     void Camera::setEnabled(bool enabled) {
00206         m_enabled = enabled;
00207     }
00208 
00209     bool Camera::isEnabled() {
00210         return m_enabled;
00211     }
00212 
00213     void Camera::updateMatrices() {
00214         double scale = m_reference_scale;
00215         m_matrix.loadScale(scale, scale, scale);
00216         if (m_location.getLayer()) {
00217             CellGrid* cg = m_location.getLayer()->getCellGrid();
00218             if (cg) {
00219                 ExactModelCoordinate pt = m_location.getMapCoordinates();
00220                 m_matrix.applyTranslate( -pt.x *m_reference_scale,-pt.y *m_reference_scale, 0);
00221             }
00222         }
00223         scale = m_zoom;
00224         m_matrix.applyScale(scale, scale, scale);
00225         m_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
00226         m_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
00227         m_inverse_matrix = m_matrix.inverse();
00228     }
00229 
00230     void Camera::calculateZValue(ScreenPoint& screen_coords) {
00231         int dy = -(screen_coords.y - toScreenCoordinates(m_location.getMapCoordinates()).y);
00232         screen_coords.z = static_cast<int>(tan(m_tilt * (M_PI / 180.0)) * static_cast<double>(dy));
00233     }
00234 
00235     ExactModelCoordinate Camera::toMapCoordinates(ScreenPoint screen_coords, bool z_calculated) {
00236         if (!z_calculated) {
00237             calculateZValue(screen_coords);
00238         }
00239         screen_coords.x -= m_viewport.w / 2;
00240         screen_coords.y -= m_viewport.h / 2;
00241 
00242         return m_inverse_matrix  * intPt2doublePt(screen_coords);
00243     }
00244 
00245     ScreenPoint Camera::toScreenCoordinates(ExactModelCoordinate elevation_coords) {
00246         ExactModelCoordinate p = elevation_coords;
00247         ScreenPoint pt = doublePt2intPt( m_matrix* p  );
00248         pt.x += m_viewport.w / 2;
00249         pt.y += m_viewport.h / 2;
00250         return pt;
00251     }
00252 
00253     DoublePoint Camera::getLogicalCellDimensions(Layer* layer) {
00254         CellGrid* cg = NULL;
00255         if (layer) {
00256             cg = layer->getCellGrid();
00257         }
00258         assert(cg);
00259 
00260         ModelCoordinate cell(0,0);
00261         std::vector<ExactModelCoordinate> vertices;
00262         cg->getVertices(vertices, cell);
00263 
00264         DoubleMatrix mtx;
00265         mtx.loadRotate(m_rotation, 0.0, 0.0, 1.0);
00266         mtx.applyRotate(m_tilt, 1.0, 0.0, 0.0);
00267         double x1, x2, y1, y2;
00268         for (unsigned int i = 0; i < vertices.size(); i++) {
00269             vertices[i] = cg->toMapCoordinates(vertices[i]);
00270             vertices[i] = mtx * vertices[i];
00271             if (i == 0) {
00272                 x1 = x2 = vertices[0].x;
00273                 y1 = y2 = vertices[0].y;
00274             } else {
00275                 x1 = std::min(vertices[i].x, x1);
00276                 x2 = std::max(vertices[i].x, x2);
00277                 y1 = std::min(vertices[i].y, y1);
00278                 y2 = std::max(vertices[i].y, y2);
00279             }
00280         }
00281         return DoublePoint( x2 - x1, y2 - y1 );
00282     }
00283 
00284     void Camera::updateReferenceScale() {
00285         DoublePoint dim = getLogicalCellDimensions(m_location.getLayer());
00286         m_reference_scale = static_cast<double>(m_screen_cell_width) / dim.x;
00287 
00288         FL_DBG(_log, "Updating reference scale");
00289         FL_DBG(_log, LMsg("   tilt=") << m_tilt << " rot=" << m_rotation);
00290         FL_DBG(_log, LMsg("   m_screen_cell_width=") << m_screen_cell_width);
00291     }
00292 
00293     void Camera::getMatchingInstances(ScreenPoint screen_coords, Layer& layer, std::list<Instance*>& instances) {
00294         instances.clear();
00295         const std::vector<Instance*>& layer_instances = m_layer_to_instances[&layer];
00296         std::vector<Instance*>::const_iterator instance_it = layer_instances.end();
00297         while (instance_it != layer_instances.begin()) {
00298             --instance_it;
00299             Instance* i = (*instance_it);
00300             InstanceVisual* visual = i->getVisual<InstanceVisual>();
00301             InstanceVisualCacheItem& vc = visual->getCacheItem(this);
00302             if ((vc.dimensions.contains(Point(screen_coords.x, screen_coords.y)))) {
00303                 assert(vc.image);
00304                 Uint8 r, g, b, a;
00305                 int x = screen_coords.x - vc.dimensions.x;
00306                 int y = screen_coords.y - vc.dimensions.y;
00307                 if (m_zoom != 1.0) {
00308                     double fx = static_cast<double>(x);
00309                     double fy = static_cast<double>(y);
00310                     double fow = static_cast<double>(vc.image->getWidth());
00311                     double foh = static_cast<double>(vc.image->getHeight());
00312                     double fsw = static_cast<double>(vc.dimensions.w);
00313                     double fsh = static_cast<double>(vc.dimensions.h);
00314                     x = static_cast<int>(round(fx / fsw * fow));
00315                     y = static_cast<int>(round(fy / fsh * foh));
00316                 }
00317                 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00318                 // instance is hit with mouse if not totally transparent
00319                 if (a != 0) {
00320                     instances.push_back(i);
00321                 }
00322             }
00323         }
00324     }
00325 
00326     void Camera::getMatchingInstances(Rect screen_rect, Layer& layer, std::list<Instance*>& instances) {
00327         instances.clear();
00328         const std::vector<Instance*>& layer_instances = m_layer_to_instances[&layer];
00329         std::vector<Instance*>::const_iterator instance_it = layer_instances.end();
00330         while (instance_it != layer_instances.begin()) {
00331             --instance_it;
00332             Instance* i = (*instance_it);
00333             InstanceVisual* visual = i->getVisual<InstanceVisual>();
00334             InstanceVisualCacheItem& vc = visual->getCacheItem(this);
00335             if ((vc.dimensions.intersects(screen_rect))) {
00336                 assert(vc.image);
00337                 Uint8 r, g, b, a;
00338                 for(int xx = screen_rect.x; xx < screen_rect.x + screen_rect.w; xx++) {
00339                     for(int yy = screen_rect.y; yy < screen_rect.y + screen_rect.h; yy++) {
00340                         if ((vc.dimensions.contains(Point(xx, yy)))) {
00341                             int x = xx - vc.dimensions.x;
00342                             int y = yy - vc.dimensions.y;
00343                             if (m_zoom != 1.0) {
00344                                 double fx = static_cast<double>(x);
00345                                 double fy = static_cast<double>(y);
00346                                 double fow = static_cast<double>(vc.image->getWidth());
00347                                 double foh = static_cast<double>(vc.image->getHeight());
00348                                 double fsw = static_cast<double>(vc.dimensions.w);
00349                                 double fsh = static_cast<double>(vc.dimensions.h);
00350                                 x = static_cast<int>(round(fx / fsw * fow));
00351                                 y = static_cast<int>(round(fy / fsh * foh));
00352                             }
00353                             vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00354                             // instance is hit with mouse if not totally transparent
00355                             if (a != 0) {
00356                                 instances.push_back(i);
00357                                 goto found_non_transparent_pixel;
00358                             }
00359                         }
00360                     }
00361                 }
00362                 found_non_transparent_pixel:;
00363             }
00364         }
00365     }
00366 
00367     void Camera::getMatchingInstances(Location& loc, std::list<Instance*>& instances, bool use_exactcoordinates) {
00368         instances.clear();
00369         const std::vector<Instance*>& layer_instances = m_layer_to_instances[loc.getLayer()];
00370         std::vector<Instance*>::const_iterator instance_it = layer_instances.end();
00371         while (instance_it != layer_instances.begin()) {
00372             --instance_it;
00373             Instance* i = (*instance_it);
00374             if (use_exactcoordinates) {
00375                 if (i->getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
00376                     instances.push_back(i);
00377                 }
00378             } else {
00379                 if (i->getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
00380                     instances.push_back(i);
00381                 }
00382             }
00383         }
00384     }
00385 
00386     void Camera::attach(Instance *instance) {
00387         // fail if the layers aren't the same
00388         if (m_location.getLayer()->getId() != instance->getLocation().getLayer()->getId()) {
00389             FL_WARN(_log, "Tried to attach camera to instance on different layer.");
00390             return ;
00391         }
00392         m_attachedto = instance;
00393     }
00394 
00395     void Camera::detach() {
00396         m_attachedto = NULL;
00397     }
00398 
00399     void Camera::update() {
00400         if( !m_attachedto ) {
00401             return;
00402         }
00403         Location loc(m_location);
00404         loc.setExactLayerCoordinates( m_attachedto->getLocationRef().getExactLayerCoordinates(m_location.getLayer()) );
00405         setLocation(loc);
00406         updateMatrices();
00407     }
00408 
00409     void Camera::refresh() {
00410         updateMatrices();
00411         m_iswarped = true;
00412     }
00413 
00414     void Camera::resetUpdates() {
00415         m_iswarped = false;
00416         m_prev_origo = m_cur_origo;
00417     }
00418 
00419     bool pipelineSort(const RendererBase* lhs, const RendererBase* rhs) {
00420         return (lhs->getPipelinePosition() < rhs->getPipelinePosition());
00421     }
00422 
00423     void Camera::addRenderer(RendererBase* renderer) {
00424         renderer->setRendererListener(this);
00425         m_renderers[renderer->getName()] = renderer;
00426         if (renderer->isEnabled()) {
00427             m_pipeline.push_back(renderer);
00428         }
00429         m_pipeline.sort(pipelineSort);
00430     }
00431 
00432     void Camera::onRendererPipelinePositionChanged(RendererBase* renderer) {
00433         m_pipeline.sort(pipelineSort);
00434     }
00435 
00436     void Camera::onRendererEnabledChanged(RendererBase* renderer) {
00437         assert(m_renderers[renderer->getName()]);
00438         if (renderer->isEnabled()) {
00439             FL_LOG(_log, LMsg("Enabling renderer ") << renderer->getName());
00440             m_pipeline.push_back(renderer);
00441             m_pipeline.sort(pipelineSort);
00442         } else {
00443             m_pipeline.remove(renderer);
00444         }
00445     }
00446 
00447     RendererBase* Camera::getRenderer(const std::string& name) {
00448         return m_renderers[name];
00449     }
00450 
00451     class InstanceDistanceSort {
00452     public:
00453         Camera* cam;
00454         inline bool operator()(const Instance* lhs, const Instance* rhs) {
00455             InstanceVisual* liv = lhs->getVisual<InstanceVisual>();
00456             InstanceVisual* riv = rhs->getVisual<InstanceVisual>();
00457             InstanceVisualCacheItem& lic = liv->getCacheItem(cam);
00458             InstanceVisualCacheItem& ric = riv->getCacheItem(cam);
00459             if (lic.screenpoint.z == ric.screenpoint.z) {
00460                 return liv->getStackPosition() < riv->getStackPosition();
00461             }
00462             return lic.screenpoint.z < ric.screenpoint.z;
00463         }
00464     };
00465 
00466     void Camera::resetRenderers() {
00467         std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
00468         for (; r_it != m_renderers.end(); ++r_it) {
00469             Map* map = m_location.getMap();
00470             r_it->second->reset();
00471         }
00472     }
00473 
00474     void Camera::render() {
00475         ScreenPoint cammove = m_prev_origo - m_cur_origo;
00476 
00477         Map* map = m_location.getMap();
00478         if (!map) {
00479             FL_ERR(_log, "No map for camera found");
00480             return;
00481         }
00482         //if ((!map->isChanged()) && (!m_iswarped) && (cammove == ScreenPoint(0,0,0))) {
00483         //  return;
00484         //}
00485 
00486         // update each layer
00487         m_renderbackend->pushClipArea(getViewPort());
00488 
00489         m_layer_to_instances.clear();
00490 
00491         const std::list<Layer*>& layers = map->getLayers();
00492         std::list<Layer*>::const_iterator layer_it = layers.begin();
00493         for (;layer_it != layers.end(); ++layer_it) {
00494 
00495             // sort instances on layer based on stack position + camera distance. done only once
00496             //  here instead passing it to each renderer.
00497             // instances are checked first if their image intersects with the viewport.
00498             // this reduces processing load during sorting later
00499             const std::vector<Instance*>& allinstances = (*layer_it)->getInstances();
00500             std::vector<Instance*>::const_iterator instance_it = allinstances.begin();
00501             std::vector<Instance*>& instances_to_render = m_layer_to_instances[*layer_it];
00502             for (;instance_it != allinstances.end(); ++instance_it) {
00503                 Instance* instance = *instance_it;
00504                 InstanceVisual* visual = instance->getVisual<InstanceVisual>();
00505                 if(!visual->isVisible())
00506                     continue;
00507                 InstanceVisualCacheItem& vc = visual->getCacheItem(this);
00508 
00509                 // use cached values if there is no need to do full recalculation
00510                 ScreenPoint drawpt;
00511                 int angle = 0;
00512                 if (m_updated && (!m_iswarped) && (!(instance->getChangeInfo() & (ICHANGE_LOC | ICHANGE_ROTATION | ICHANGE_FACING_LOC))) && (vc.image)) {
00513                     int pos_estimate_x = vc.screenpoint.x - cammove.x;
00514                     int pos_estimate_y = vc.screenpoint.y - cammove.y;
00515                     int pos_estimate_z = vc.screenpoint.z - cammove.z;
00516                     angle = vc.facing_angle;
00517                     //std::cout << "orig x = " << drawpt.x << ", est x = " << pos_estimate_x << "\n";
00518                     //std::cout << "orig y = " << drawpt.y << ", est y = " << pos_estimate_y << "\n";
00519                     drawpt.x = pos_estimate_x;
00520                     drawpt.y = pos_estimate_y;
00521                     drawpt.z = pos_estimate_z;
00522                     //drawpt.z = toScreenCoordinates( instance->getLocationRef().getMapCoordinates() ).z;
00523                 } else {
00524                     drawpt = toScreenCoordinates( instance->getLocationRef().getMapCoordinates() );
00525                     vc.facing_angle = getAngleBetween(instance->getLocationRef(), instance->getFacingLocation());
00526                     angle = vc.facing_angle;
00527                 }
00528 
00529                 //generate angle based on camera rotation and instance rotation
00530                 angle = angle + m_rotation + instance->getRotation();
00531 
00532                 Image* image = NULL;
00533                 Action* action = instance->getCurrentAction();
00534                 if (action) {
00535                     FL_DBG(_log, "Instance has action");
00536                     int animation_id = action->getVisual<ActionVisual>()->getAnimationIndexByAngle(vc.facing_angle + m_rotation);
00537 
00538                     int facing_angle = vc.facing_angle;
00539                     if (facing_angle < 0){
00540                         facing_angle = 360+facing_angle; //make it a positive angle
00541                     }
00542                     facing_angle %= 360;
00543                     instance->setRotation(facing_angle);  //update so the animation has correct rotation
00544 
00545                     Animation& animation = m_apool->getAnimation(animation_id);
00546                     unsigned int animtime = instance->getActionRuntime() % animation.getDuration();
00547                     image = animation.getFrameByTimestamp(animtime);
00548                 } else {
00549                     FL_DBG(_log, "No action");
00550                     int imageid = vc.getStaticImageIndexByAngle(angle, instance);
00551                     FL_DBG(_log, LMsg("Instance does not have action, using static image with id ") << imageid);
00552                     if (imageid >= 0) {
00553                         image = &m_ipool->getImage(imageid);
00554                     } else {
00555                         // there was no static image for instance, trying default action
00556                         action = instance->getObject()->getDefaultAction();
00557                         if (action) {
00558                             int animation_id = action->getVisual<ActionVisual>()->getAnimationIndexByAngle(angle);
00559                             Animation& animation = m_apool->getAnimation(animation_id);
00560                             unsigned int animtime = instance->getActionRuntime() % animation.getDuration();
00561                             image = animation.getFrameByTimestamp(animtime);
00562                         }
00563                     }
00564                 }
00565                 if (image) {
00566                     vc.image = image;
00567                     vc.screenpoint = drawpt;
00568 
00569                     int w = image->getWidth();
00570                     int h = image->getHeight();
00571                     drawpt.x -= w / 2;
00572                     drawpt.x += image->getXShift();
00573                     drawpt.y -= h / 2;
00574                     drawpt.y += image->getYShift();
00575                     Rect r = Rect(drawpt.x, drawpt.y, w, h);
00576 
00577                     vc.dimensions = r;
00578                     if (m_zoom != 1.0) {
00579                         // NOTE: Due to image alignment, there is additional additions and substractions on image dimensions
00580                         //       There's probabaly some better solution for this, but works "good enough" for now.
00581                         //       In case additions / substractions are removed, gaps appear between tiles.
00582                         r.w = static_cast<unsigned int>(ceil(static_cast<double>(vc.dimensions.w) * m_zoom)) + 2;
00583                         r.h = static_cast<unsigned int>(ceil(static_cast<double>(vc.dimensions.h) * m_zoom)) + 2;
00584                         int xo = static_cast<int>(ceil(static_cast<double>(vc.image->getXShift()) * m_zoom)) - vc.image->getXShift();
00585                         int yo = static_cast<int>(ceil(static_cast<double>(vc.image->getYShift()) * m_zoom)) - vc.image->getYShift();
00586                         r.x = vc.dimensions.x - static_cast<unsigned int>(ceil(static_cast<double>(r.w - vc.dimensions.w) / 2)) + xo - 1;
00587                         r.y = vc.dimensions.y - static_cast<unsigned int>(ceil(static_cast<double>(r.h - vc.dimensions.h) / 2)) + yo - 1;
00588                         vc.dimensions = r;
00589                     }
00590 
00591                     if (vc.dimensions.intersects(getViewPort())) {
00592                         instances_to_render.push_back(instance);
00593                     }
00594                 }
00595             }
00596 
00597             InstanceDistanceSort ids;
00598             ids.cam = this;
00599             std::stable_sort(instances_to_render.begin(), instances_to_render.end(), ids);
00600 
00601             std::list<RendererBase*>::iterator r_it = m_pipeline.begin();
00602             for (; r_it != m_pipeline.end(); ++r_it) {
00603                 if ((*r_it)->isActivedLayer(*layer_it)) {
00604                     (*r_it)->render(this, *layer_it, instances_to_render);
00605                 }
00606             }
00607         }
00608         m_renderbackend->popClipArea();
00609         resetUpdates();
00610         m_updated = true;
00611     }
00612 
00613 }
Generated by  doxygen 1.6.2-20100208