Mercurial > fife-parpg
diff engine/core/view/camera.h @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children | 40a7c9618ade |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/view/camera.h Sun Jun 29 18:44:17 2008 +0000 @@ -0,0 +1,335 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_VIEW_CAMERA_H +#define FIFE_VIEW_CAMERA_H + +// Standard C++ library includes +#include <string> + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "model/structures/location.h" +#include "util/math/matrix.h" +#include "util/structures/rect.h" + +#include "rendererbase.h" + +namespace FIFE { + + typedef Point3D ScreenPoint; + class Layer; + class Instance; + class ImagePool; + class AnimationPool; + class RenderBackend; + typedef std::map<Layer*, std::vector<Instance*> > t_layer_to_instances; + + /** Camera describes properties of a view port shown in the main screen + * Main screen can have multiple cameras active simultanously + * Different cameras can have different properties, like location + * to shoot, zoom or tilt + */ + class Camera: public IRendererListener, public IRendererContainer { + public: + /** Constructor + * Camera needs to be added to the view. If not done so, it is not rendered. + * @param id identifier for the camera + * @param layer layer where camera is bind. Camera is bind to a layer for two reasons: + * * camera's scaling is done based on cell image dimensions. Cell image is layer based (@see setCellImageDimensions) + * * camera could be bind to a pather, which operates on layer + * @param viewport used viewport for the camera. Viewport is measured in pixels in relation to game main screen + * @param emc coordinate, where camera is focused on given layer + * @param renderbackend to use with rendering + * @param ipool to use with rendering + * @param apool to use with rendering + */ + Camera(const std::string& id, + Layer* layer, + Rect viewport, + ExactModelCoordinate emc, + RenderBackend* renderbackend, + ImagePool* ipool, + AnimationPool* apool); + + /** Destructor + */ + virtual ~Camera(); + + /** Gets the identifier for this camera. + */ + const std::string& getId() { return m_id; } + + /** Sets tilt for the camera. + * e.g. overhead camera has tilt 0, while traditional isometric camera has tilt 45 + * @param tilt tilt for the camera + */ + void setTilt(double tilt); + + /** Gets camera tilt + * @return tilt of camera + */ + double getTilt() const; + + /** Sets rotation for the camera. + * Rotation can be visualized by thinking camera that rotates around an object + * that it is rendering + * @param rotation rotation for the camera + */ + void setRotation(double rotation); + + /** Gets camera rotation + * @return rotation of the camera + */ + double getRotation() const; + + /** Sets zoom for the camera. + * @param zoom zoom for the camera + */ + void setZoom(double zoom); + + /** Gets camera zoom + * @return zoom of the camera + */ + double getZoom() const; + + /** Sets screen cell image dimensions. + * Cell image dimension is basically width and height of a bitmap, that covers + * one cell in the layer where camera is bind + * @return Point Point containing x=width and y=height + */ + void setCellImageDimensions(unsigned int width, unsigned int height); + + /** Gets screen cell image dimensions. + * @see setCellImageDimensions + * @return Point containing x=width and y=height + */ + Point getCellImageDimensions(); + + /** Gets screen cell image dimensions for given layer. + * @return Point Point containing x=width and y=height + */ + Point getCellImageDimensions(Layer* layer); + + /** Sets the location for camera + * @param location location (center point) to render + */ + void setLocation(const Location& location); + + /** Gets the location camera is rendering + * @return camera location + */ + Location getLocation() const; + + /** Gets a reference to the camera location + * @note if you change returned location without calling Camera::setLocation(...), + * remember to call Camera::refresh() (otherwise camera transforms are not updated) + * @return reference to the camera location + */ + Location& getLocationRef(); + + /** Attaches the camera to an instance. + * @param instance Instance to which the camera shall be attached + * @note The camera can only be attached to an instance at the same layer! + */ + void attach(Instance *instance); + + /** Detaches the camera from an instance. + */ + void detach(); + + /** Returns instance where camera is attached. NULL if not attached + */ + bool getAttached() const { return m_attachedto; } + + /** Sets the viewport for camera + * viewport is rectangle inside the view where camera renders + * @param viewport area for camera render + */ + void setViewPort(const Rect& viewport); + + /** Gets the viewport for camera + * @return camera viewport + */ + const Rect& getViewPort() const; + + /** Transforms given point from screen coordinates to map coordinates + * @param screen_coords screen coordinates to transform + * @param z_calculated if true, z-value (depth cut point) is pre-calculated. If false, camera calculates it + * @return point in map coordinates + */ + ExactModelCoordinate toMapCoordinates(ScreenPoint screen_coords, bool z_calculated=true); + + /** Transforms given point from map coordinates to screen coordinates + * @return point in screen coordinates + */ + ScreenPoint toScreenCoordinates(ExactModelCoordinate map_coords); + + /** Sets camera enabled / disabled + */ + void setEnabled(bool enabled); + + /** Gets if camera is enabled / disabled + */ + bool isEnabled(); + + /** Gets angle of vector defined by given locations and camera properties (e.g. rotation) + * @return angle in polar coordinates + */ + inline int getAngleBetween(const Location& loc1, const Location& loc2) { + static const double VECTOR_MULTIP = 100000.0; + ExactModelCoordinate c1 = loc1.getMapCoordinates(); + ExactModelCoordinate c2 = loc2.getMapCoordinates(); + ExactModelCoordinate cd((c2.x - c1.x) * VECTOR_MULTIP, (c2.y - c1.y) * VECTOR_MULTIP, 0); + c2.x = c1.x + cd.x; + c2.y = c1.y + cd.y; + ScreenPoint pt1 = this->toScreenCoordinates(c1); + ScreenPoint pt2 = this->toScreenCoordinates(c2); + double dy = (pt2.y - pt1.y); + double dx = (pt2.x - pt1.x); + int angle = static_cast<int>(atan2(-dy,dx)*(180.0/M_PI)); + return angle; + } + + /** Returns instances that match given screen coordinate + * @param screen_coords screen coordinates to be used for hit search + * @param layer layer to use for search + * @param instances list of instances that is filled based on hit test results + */ + void getMatchingInstances(ScreenPoint screen_coords, Layer& layer, std::list<Instance*>& instances); + + /** Returns instances that match given location. Instances are sorted based on camera view, so that "topmost" + * instance is first in returned list + * @param loc location where to fetch instances from + * @param instances list of instances that is filled based on hit test results + * @param use_exactcoordinates if true, comparison is done using exact coordinates. if not, cell coordinates are used + */ + void getMatchingInstances(Location& loc, std::list<Instance*>& instances, bool use_exactcoordinates=false); + + /** General update routine. + * In this function, the camera's position gets updated when its attached + * to another instance. + * @note call this only once in engine update cycle, so that tracking between + * current position and previous position keeps in sync. This information + * is used e.g. by view to fix the pixel wobbling problem + */ + void update(); + + /** Refreshes camera view in case e.g. location is updated directly (not via setLocation) + * @note calling this function marks camera as "warped", therefore it causes all instance + * positions to be recalculated. If you constantly call this, you end up with pixel wobbling + * effect when camera is moved. + */ + void refresh(); + + /** Returns latest camera movement in screen coordinates (dx, dy) + */ + inline ScreenPoint getLatestMovement() { + return m_prev_origo - m_cur_origo; + } + + /** Resets temporary values from last update round, like warped flag + */ + void resetUpdates(); + + /** Adds new renderer on the view. Ownership is transferred to the camera. + */ + void addRenderer(RendererBase* renderer); + + /** Gets renderer with given name + */ + RendererBase* getRenderer(const std::string& name); + + /** resets active layer information on all renderers. + */ + void resetRenderers(); + + /** calculates z-value for given screenpoint + */ + void calculateZValue(ScreenPoint& screen_coords); + + void onRendererPipelinePositionChanged(RendererBase* renderer); + void onRendererEnabledChanged(RendererBase* renderer); + + /** Renders camera + */ + void render(); + + private: + std::string m_id; + + /** Updates the camera transformation matrix T with requested values. + * The requests are done using these functions : + * - setLocation + * - setRotation + * - setTilt + */ + void updateMatrices(); + + /** Updates camera reference scale + * Reference scale is in a sense an internal zooming factor, + * which adjusts cell dimensions in logical space to ones shown on + * screen. Calculation is based on current camera properties (e.g. rotation) + * + given cell image dimensions for camera's layer + */ + void updateReferenceScale(); + + /** Gets logical cell image dimensions for given layer + */ + DoublePoint getLogicalCellDimensions(Layer* layer); + + DoubleMatrix m_matrix; + DoubleMatrix m_inverse_matrix; + double m_tilt; + double m_rotation; + double m_zoom; + Location m_location; + ScreenPoint m_prev_origo; + ScreenPoint m_cur_origo; + Rect m_viewport; + bool m_view_updated; + unsigned int m_screen_cell_width; + unsigned int m_screen_cell_height; + double m_reference_scale; + bool m_enabled; + Instance* m_attachedto; + // caches calculated image dimensions for already queried & calculated layers + std::map<Layer*, Point> m_image_dimensions; + bool m_iswarped; + + // list of renderers managed by the view + std::map<std::string, RendererBase*> m_renderers; + std::list<RendererBase*> m_pipeline; + bool m_updated; // false, if view has never been updated before + + RenderBackend* m_renderbackend; + ImagePool* m_ipool; + AnimationPool* m_apool; + + // caches layer -> instances structure between renders e.g. to fast query of mouse picking order + t_layer_to_instances m_layer_to_instances; + }; +} +#endif