31 #include "model/metamodel/grids/cellgrid.h"
32 #include "model/metamodel/action.h"
33 #include "model/metamodel/timeprovider.h"
34 #include "model/structures/map.h"
35 #include "model/structures/layer.h"
36 #include "model/structures/instancetree.h"
37 #include "model/structures/instance.h"
38 #include "model/structures/location.h"
39 #include "util/log/logger.h"
40 #include "util/math/fife_math.h"
41 #include "util/math/angles.h"
42 #include "util/time/timemanager.h"
43 #include "video/renderbackend.h"
44 #include "video/image.h"
45 #include "video/animation.h"
46 #include "video/imagemanager.h"
49 #include "layercache.h"
54 static Logger _log(LM_CAMERA);
56 class MapObserver :
public MapChangeListener {
60 MapObserver(Camera* camera) {
63 virtual ~MapObserver() {}
65 virtual void onMapChanged(Map* map, std::vector<Layer*>& changedLayers) {
68 virtual void onLayerCreate(Map* map, Layer* layer) {
69 m_camera->addLayer(layer);
72 virtual void onLayerDelete(Map* map, Layer* layer) {
73 m_camera->removeLayer(layer);
90 m_screen_cell_width(1),
91 m_screen_cell_height(1),
100 m_renderbackend(renderbackend),
101 m_layer_to_instances(),
104 m_col_overlay(false),
105 m_img_overlay(false),
106 m_ani_overlay(false) {
107 m_viewport = viewport;
108 m_map_observer =
new MapObserver(
this);
111 location.setLayer(layer);
119 std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
120 for(; r_it != m_renderers.end(); ++r_it) {
121 r_it->second->reset();
125 delete m_map_observer;
129 if (!Mathd::Equal(m_tilt, tilt)) {
131 updateReferenceScale();
142 if (!Mathd::Equal(m_rotation, rotation)) {
143 m_rotation = rotation;
144 updateReferenceScale();
155 if (!Mathd::Equal(m_zoom, zoom)) {
157 if (m_zoom < 0.001) {
170 m_screen_cell_width = width;
171 m_screen_cell_height = height;
172 updateReferenceScale();
178 if (m_location == location ) {
182 CellGrid* cell_grid = NULL;
183 if (location.getLayer()) {
184 cell_grid = location.getLayer()->getCellGrid();
186 throw Exception(
"Location without layer given to Camera::setLocation");
189 throw Exception(
"Camera layer has no cellgrid specified");
192 m_location = location;
203 updateMap(m_location.getMap());
208 void Camera::updateMap(
Map* map) {
214 const std::list<Layer*>& layers = m_map->
getLayers();
215 for(std::list<Layer*>::const_iterator i = layers.begin(); i !=layers.end(); ++i) {
221 const std::list<Layer*>& layers = map->
getLayers();
222 for(std::list<Layer*>::const_iterator i = layers.begin(); i !=layers.end(); ++i) {
234 if (layer == m_location.getLayer()) {
235 return Point( m_screen_cell_width, m_screen_cell_height );
237 std::map<Layer*, Point>::iterator it = m_image_dimensions.find(layer);
238 if (it != m_image_dimensions.end()) {
244 DoublePoint dimensions = getLogicalCellDimensions(layer);
245 p.x =
static_cast<int32_t
>(round(m_reference_scale * dimensions.x));
246 p.y =
static_cast<int32_t
>(round(m_reference_scale * dimensions.y));
247 m_image_dimensions[layer] = p;
260 m_viewport = viewport;
279 void Camera::updateMatrices() {
280 double scale = m_reference_scale;
282 m_vs_matrix.
loadScale(scale,scale,scale);
283 if (m_location.getLayer()) {
284 CellGrid* cg = m_location.getLayer()->getCellGrid();
287 m_matrix.
applyTranslate( -pt.x *m_reference_scale,-pt.y *m_reference_scale, -pt.z*m_reference_scale);
292 m_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
293 m_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
294 m_matrix.
applyTranslate(+m_viewport.
x+m_viewport.
w/2, +m_viewport.
y+m_viewport.
h/2, 0);
295 m_inverse_matrix = m_matrix.
inverse();
297 m_vs_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
298 m_vs_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
299 m_vs_inverse_matrix = m_vs_matrix.
inverse();
303 m_vscreen_2_screen = m_matrix;
305 m_vscreen_2_screen.mult4by4(m_vs_inverse_matrix);
308 for(int32_t i=0; i!=N; ++i) {
309 m_vscreen_2_screen[2*N + i] = 0;
310 m_vscreen_2_screen[i*N + 2] = 0;
312 m_vscreen_2_screen[2*N + 2] = 1;
313 m_screen_2_vscreen = m_vscreen_2_screen.
inverse();
321 screen_coords.z =
static_cast<int32_t
>(Mathd::Tan(m_tilt * (Mathd::pi() / 180.0)) *
static_cast<double>(dy));
345 DoublePoint3D Camera::screenToVirtualScreen(
const ScreenPoint& p) {
349 DoublePoint Camera::getLogicalCellDimensions(Layer* layer) {
352 cg = layer->getCellGrid();
356 ModelCoordinate cell(0,0);
357 std::vector<ExactModelCoordinate> vertices;
358 cg->getVertices(vertices, cell);
362 mtx.applyRotate(m_tilt, 1.0, 0.0, 0.0);
369 for (uint32_t i = 0; i < vertices.size(); i++) {
370 vertices[i] = cg->toMapCoordinates(vertices[i]);
371 vertices[i] = mtx * vertices[i];
373 x1 = x2 = vertices[0].x;
374 y1 = y2 = vertices[0].y;
376 x1 = std::min(vertices[i].x, x1);
377 x2 = std::max(vertices[i].x, x2);
378 y1 = std::min(vertices[i].y, y1);
379 y2 = std::max(vertices[i].y, y2);
382 return DoublePoint( x2 - x1, y2 - y1 );
385 Point Camera::getRealCellDimensions(Layer* layer) {
388 cg = layer->getCellGrid();
393 ModelCoordinate cell(0,0);
394 loc.setLayerCoordinates(cell);
397 loc.setLayerCoordinates(cell);
400 Point p(ABS(sp2.x - sp1.x), ABS(sp2.y - sp1.y));
419 loc.setLayerCoordinates(cell);
422 loc.setLayerCoordinates(cell);
425 return Point3D(sp2.x - sp1.x, sp2.y - sp1.y, sp2.z - sp1.z);
428 void Camera::updateReferenceScale() {
429 DoublePoint dim = getLogicalCellDimensions(m_location.getLayer());
430 m_reference_scale =
static_cast<double>(m_screen_cell_width) / dim.x;
432 FL_DBG(_log,
"Updating reference scale");
433 FL_DBG(_log,
LMsg(
" tilt=") << m_tilt <<
" rot=" << m_rotation);
434 FL_DBG(_log,
LMsg(
" m_screen_cell_width=") << m_screen_cell_width);
437 void Camera::cacheUpdate(Layer* layer) {
438 Map* map = m_location.getMap();
440 FL_ERR(_log,
"No map for camera found");
444 if (m_iswarped || !m_updated) {
447 LayerCache* cache = m_cache[layer];
450 cache = m_cache[layer];
451 FL_ERR(_log, LMsg(
"Layer Cache miss! (This shouldn't happen!)") << layer->getId());
454 if (cache->needUpdate()) {
455 Transform transform = NormalTransform;
457 transform = WarpedTransform;
459 RenderList& instances_to_render = m_layer_to_instances[layer];
460 cache->update(transform, instances_to_render);
467 bool zoomed = !Mathd::Equal(m_zoom, 1.0);
468 bool special_alpha = alpha != 0;
470 const RenderList& layer_instances = m_layer_to_instances[&layer];
471 RenderList::const_iterator instance_it = layer_instances.end();
472 while (instance_it != layer_instances.begin()) {
474 Instance* i = (*instance_it)->instance;
475 const RenderItem& vc = **instance_it;
476 if ((vc.dimensions.contains(
Point(screen_coords.x, screen_coords.y)))) {
477 if(vc.image->isSharedImage()) {
478 vc.image->forceLoadInternal();
480 uint8_t r, g, b, a = 0;
481 int32_t x = screen_coords.x - vc.dimensions.x;
482 int32_t y = screen_coords.y - vc.dimensions.y;
484 double fx =
static_cast<double>(x);
485 double fy =
static_cast<double>(y);
486 double fow =
static_cast<double>(vc.image->getWidth());
487 double foh =
static_cast<double>(vc.image->getHeight());
488 double fsw =
static_cast<double>(vc.dimensions.w);
489 double fsh =
static_cast<double>(vc.dimensions.h);
490 x =
static_cast<int32_t
>(round(fx / fsw * fow));
491 y =
static_cast<int32_t
>(round(fy / fsh * foh));
493 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
495 if (a == 0 || (special_alpha && a < alpha)) {
498 instances.push_back(i);
505 bool zoomed = !Mathd::Equal(m_zoom, 1.0);
506 bool special_alpha = alpha != 0;
509 const RenderList& layer_instances = m_layer_to_instances[&layer];
510 RenderList::const_iterator instance_it = layer_instances.end();
511 while (instance_it != layer_instances.begin()) {
513 Instance* i = (*instance_it)->instance;;
514 const RenderItem& vc = **instance_it;
515 if ((vc.dimensions.intersects(screen_rect))) {
516 if(vc.image->isSharedImage()) {
517 vc.image->forceLoadInternal();
519 uint8_t r, g, b, a = 0;
520 for(int32_t xx = screen_rect.
x; xx < screen_rect.
x + screen_rect.
w; xx++) {
521 for(int32_t yy = screen_rect.
y; yy < screen_rect.
y + screen_rect.
h; yy++) {
522 if ((vc.dimensions.contains(
Point(xx, yy)))) {
523 int32_t x = xx - vc.dimensions.x;
524 int32_t y = yy - vc.dimensions.y;
526 double fx =
static_cast<double>(x);
527 double fy =
static_cast<double>(y);
528 double fow =
static_cast<double>(vc.image->getWidth());
529 double foh =
static_cast<double>(vc.image->getHeight());
530 double fsw =
static_cast<double>(vc.dimensions.w);
531 double fsh =
static_cast<double>(vc.dimensions.h);
532 x =
static_cast<int32_t
>(round(fx / fsw * fow));
533 y =
static_cast<int32_t
>(round(fy / fsh * foh));
535 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
537 if (a == 0 || (special_alpha && a < alpha)) {
541 instances.push_back(i);
542 goto found_non_transparent_pixel;
546 found_non_transparent_pixel:;
553 Layer* layer = loc.getLayer();
559 const RenderList& layer_instances = m_layer_to_instances[layer];
560 RenderList::const_iterator instance_it = layer_instances.end();
561 while (instance_it != layer_instances.begin()) {
563 Instance* i = (*instance_it)->instance;
564 if (use_exactcoordinates) {
565 if (i->
getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
566 instances.push_back(i);
569 if (i->
getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
570 instances.push_back(i);
578 if (m_location.getLayer()->getId() != instance->
getLocation().getLayer()->getId()) {
579 FL_WARN(_log,
"Tried to attach camera to instance on different layer.");
582 m_attachedto = instance;
590 if( !m_attachedto ) {
593 Location loc(m_location);
594 loc.setExactLayerCoordinates( m_attachedto->
getLocationRef().getExactLayerCoordinates(m_location.getLayer()) );
615 m_renderers[renderer->
getName()] = renderer;
617 m_pipeline.push_back(renderer);
619 m_pipeline.sort(pipelineSort);
623 m_pipeline.sort(pipelineSort);
627 assert(m_renderers[renderer->
getName()]);
629 FL_LOG(_log,
LMsg(
"Enabling renderer ") << renderer->
getName());
630 m_pipeline.push_back(renderer);
631 m_pipeline.sort(pipelineSort);
633 m_pipeline.remove(renderer);
638 return m_renderers[name];
642 std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
643 for (; r_it != m_renderers.end(); ++r_it) {
644 r_it->second->reset();
648 void Camera::addLayer(
Layer* layer) {
649 m_cache[layer] =
new LayerCache(
this);
650 m_cache[layer]->setLayer(layer);
651 m_layer_to_instances[layer] = RenderList();
654 void Camera::removeLayer(Layer* layer) {
655 delete m_cache[layer];
656 m_cache.erase(layer);
657 m_layer_to_instances.erase(layer);
662 m_light_colors.clear();
663 m_light_colors.push_back(red);
664 m_light_colors.push_back(green);
665 m_light_colors.push_back(blue);
669 if(m_light_colors.empty()) {
670 for(int32_t colors = 0; colors != 3; ++colors) {
671 m_light_colors.push_back(1.0f);
674 return m_light_colors;
683 m_col_overlay =
true;
684 m_overlay_color.r = red;
685 m_overlay_color.g = green;
686 m_overlay_color.b = blue;
687 m_overlay_color.unused = alpha;
691 std::vector<uint8_t> colors;
693 colors.push_back(m_overlay_color.r);
694 colors.push_back(m_overlay_color.g);
695 colors.push_back(m_overlay_color.b);
696 colors.push_back(m_overlay_color.unused);
698 for(uint8_t cc = 0; cc != 4; ++cc) {
699 colors.push_back(255);
706 m_col_overlay =
false;
710 m_img_overlay =
true;
724 m_img_overlay =
false;
729 m_ani_overlay =
true;
740 m_ani_overlay =
false;
744 void Camera::renderOverlay() {
745 if (!m_col_overlay && !m_img_overlay && !m_ani_overlay) {
748 uint16_t width = m_viewport.
w;
749 uint16_t height = m_viewport.
h;
750 Point pm = Point(m_viewport.
x + width/2, m_viewport.
y + height/2);
755 Point p = Point(m_viewport.
x, m_viewport.
y);
756 m_renderbackend->
fillRectangle(p, width, height, m_overlay_color.r, m_overlay_color.g, m_overlay_color.b, m_overlay_color.unused);
760 ImagePtr resptr = ImageManager::instance()->get(m_img_id);
761 Image* img = resptr.get();
767 r.w = img->getWidth();
768 r.h = img->getHeight();
777 assert(m_ani_ptr != 0);
779 if (m_start_time == 0) {
780 m_start_time = TimeManager::instance()->getTime();
782 uint32_t animtime =
scaleTime(1.0, TimeManager::instance()->getTime() - m_start_time) % m_ani_ptr->
getDuration();
789 r.w = img->getWidth();
790 r.h = img->getHeight();
799 void Camera::updateRenderLists() {
800 Map* map = m_location.getMap();
802 FL_ERR(_log,
"No map for camera found");
806 Transform transform = NormalTransform;
808 transform = WarpedTransform;
810 const std::list<Layer*>& layers = map->getLayers();
811 std::list<Layer*>::const_iterator layer_it = layers.begin();
812 for (;layer_it != layers.end(); ++layer_it) {
813 LayerCache* cache = m_cache[*layer_it];
816 cache = m_cache[*layer_it];
817 FL_ERR(_log, LMsg(
"Layer Cache miss! (This shouldn't happen!)") << (*layer_it)->getId());
819 RenderList& instances_to_render = m_layer_to_instances[*layer_it];
820 if (m_iswarped || !m_updated || cache->needUpdate()) {
821 cache->update(transform, instances_to_render);
828 static bool renderbackendOpenGLe = (m_renderbackend->
getName() ==
"OpenGLe");
830 Map* map = m_location.getMap();
839 m_renderbackend->
setLighting(m_light_colors[0], m_light_colors[1], m_light_colors[2]);
845 const std::list<Layer*>& layers = map->
getLayers();
846 std::list<Layer*>::const_iterator layer_it = layers.begin();
847 for ( ; layer_it != layers.end(); ++layer_it) {
848 RenderList& instances_to_render = m_layer_to_instances[*layer_it];
849 std::list<RendererBase*>::iterator r_it = m_pipeline.begin();
850 for (; r_it != m_pipeline.end(); ++r_it) {
851 if ((*r_it)->isActivedLayer(*layer_it)) {
852 (*r_it)->render(
this, *layer_it, instances_to_render);
855 if (renderbackendOpenGLe) {
862 if (m_lighting && lm != 0) {
virtual void setLighting(float red, float green, float blue)=0
int32_t getOverlayImage()
void setOverlayImage(int32_t id, bool fill=false)
void removeChangeListener(MapChangeListener *listener)
void setOverlayColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
virtual const std::string & getName() const =0
DoublePoint3D toVirtualScreenCoordinates(const ExactModelCoordinate &map_coords)
void resetLightingColor()
void setTilt(double tilt)
uint32_t getDuration() const
void resetOverlayAnimation()
void addChangeListener(MapChangeListener *listener)
void attach(Instance *instance)
Point3D getZOffset(Layer *layer)
Matrix & applyScale(T x, T y, T z)
std::vector< uint8_t > getOverlayColor()
void setRotation(double rotation)
void onRendererEnabledChanged(RendererBase *renderer)
Camera(const std::string &id, Layer *layer, const Rect &viewport, RenderBackend *renderbackend)
RendererBase * getRenderer(const std::string &name)
virtual uint32_t getLightingModel() const =0
void addRenderer(RendererBase *renderer)
const Rect & getViewPort() const
void onRendererPipelinePositionChanged(RendererBase *renderer)
ImagePtr getFrameByTimestamp(uint32_t timestamp)
void setLocation(const Location &location)
void pushClipArea(const Rect &cliparea, bool clear=true)
CellGrid * getCellGrid() const
Point doublePt2intPt(DoublePoint pt)
Location & getLocationRef()
Location getLocation() const
void setLightingColor(float red, float green, float blue)
Location & getLocationRef()
AnimationPtr getOverlayAnimation()
void setRendererListener(IRendererListener *listener)
virtual std::string getName()=0
Point getCellImageDimensions()
Matrix & loadRotate(T angle, T x, T y, T z)
Matrix & loadScale(T x, T y, T z=1)
ScreenPoint toScreenCoordinates(const ExactModelCoordinate &map_coords)
void getMatchingInstances(ScreenPoint screen_coords, Layer &layer, std::list< Instance * > &instances, uint8_t alpha=0)
Location getLocation() const
void calculateZValue(ScreenPoint &screen_coords)
DoublePoint intPt2doublePt(Point pt)
const std::list< Layer * > & getLayers() const
ExactModelCoordinate toMapCoordinates(ScreenPoint screen_coords, bool z_calculated=true)
void setOverlayAnimation(AnimationPtr anim, bool fill=false)
Point3D getOrigin() const
virtual void renderVertexArrays()=0
virtual void fillRectangle(const Point &p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)=0
uint32_t scaleTime(float multiplier, uint32_t ticks)
void setCellImageDimensions(uint32_t width, uint32_t height)
void setViewPort(const Rect &viewport)
virtual void resetLighting()=0
virtual void resetStencilBuffer(uint8_t buffer)=0
void setEnabled(bool enabled)
int32_t getPipelinePosition() const
Matrix & applyTranslate(T x, T y, T z)
std::vector< float > getLightingColor()
double getRotation() const
void setZoom(double zoom)