32 #include "model/metamodel/grids/cellgrid.h"
33 #include "model/metamodel/action.h"
34 #include "model/metamodel/timeprovider.h"
35 #include "model/structures/map.h"
36 #include "model/structures/layer.h"
37 #include "model/structures/instancetree.h"
38 #include "model/structures/instance.h"
39 #include "model/structures/location.h"
40 #include "util/log/logger.h"
41 #include "util/math/fife_math.h"
42 #include "util/math/angles.h"
43 #include "util/time/timemanager.h"
44 #include "video/renderbackend.h"
45 #include "video/image.h"
46 #include "video/imagepool.h"
47 #include "video/animation.h"
48 #include "video/animationpool.h"
51 #include "layercache.h"
56 static Logger _log(LM_CAMERA);
58 class MapObserver :
public MapChangeListener {
62 MapObserver(Camera* camera) {
65 virtual ~MapObserver() {}
67 virtual void onMapChanged(Map* map, std::vector<Layer*>& changedLayers) {
70 virtual void onLayerCreate(Map* map, Layer* layer) {
71 m_camera->addLayer(layer);
74 virtual void onLayerDelete(Map* map, Layer* layer) {
75 m_camera->removeLayer(layer);
95 m_screen_cell_width(1),
96 m_screen_cell_height(1),
100 m_image_dimensions(),
105 m_renderbackend(renderbackend),
108 m_layer_to_instances(),
112 m_viewport = viewport;
113 m_map_observer =
new MapObserver(
this);
116 location.setLayer(layer);
118 if(m_renderbackend->
getName() ==
"SDL") {
121 m_backendSDL =
false;
129 std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
130 for(; r_it != m_renderers.end(); ++r_it) {
134 delete m_map_observer;
140 updateReferenceScale();
151 if(m_rotation != rotation) {
152 m_rotation = rotation;
153 updateReferenceScale();
166 if (m_zoom < 0.001) {
178 m_screen_cell_width = width;
179 m_screen_cell_height = height;
180 updateReferenceScale();
187 if ((m_prev_origo == m_cur_origo) && (m_prev_origo ==
ScreenPoint(0,0,0))) {
189 m_prev_origo = m_cur_origo;
192 CellGrid* cell_grid = NULL;
193 if (location.getLayer()) {
194 cell_grid = location.getLayer()->getCellGrid();
196 throw Exception(
"Location without layer given to Camera::setLocation");
199 throw Exception(
"Camera layer has no cellgrid specified");
202 m_location = location;
210 updateMap(location.getMap());
215 void Camera::updateMap(
Map* map)
223 const std::list<Layer*>& layers = m_map->
getLayers();
224 for(std::list<Layer*>::const_iterator i = layers.begin(); i !=layers.end(); ++i) {
230 const std::list<Layer*>& layers = map->
getLayers();
231 for(std::list<Layer*>::const_iterator i = layers.begin(); i !=layers.end(); ++i)
242 if (layer == m_location.getLayer()) {
243 return Point( m_screen_cell_width, m_screen_cell_height );
245 std::map<Layer*, Point>::iterator it = m_image_dimensions.find(layer);
246 if (it != m_image_dimensions.end()) {
252 DoublePoint dimensions = getLogicalCellDimensions(layer);
253 p.x =
static_cast<int>(round(m_reference_scale * dimensions.x));
254 p.y =
static_cast<int>(round(m_reference_scale * dimensions.y));
255 m_image_dimensions[layer] = p;
268 m_viewport = viewport;
283 Point3D Camera::getOrigin()
const {
287 void Camera::updateMatrices() {
288 double scale = m_reference_scale;
290 m_vs_matrix.
loadScale(scale,scale,scale);
291 if (m_location.getLayer()) {
292 CellGrid* cg = m_location.getLayer()->getCellGrid();
294 ExactModelCoordinate pt = m_location.getMapCoordinates();
295 m_matrix.
applyTranslate( -pt.x *m_reference_scale,-pt.y *m_reference_scale, 0);
300 m_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
301 m_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
302 m_matrix.
applyTranslate(+m_viewport.
x+m_viewport.
w/2, +m_viewport.
y+m_viewport.
h/2, 0);
303 m_inverse_matrix = m_matrix.
inverse();
307 m_vs_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
308 m_vs_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
309 m_vs_inverse_matrix = m_vs_matrix.
inverse();
313 m_vscreen_2_screen = m_matrix;
315 m_vscreen_2_screen.mult4by4(m_vs_inverse_matrix);
318 for(
int i=0; i!=N; ++i) {
319 m_vscreen_2_screen[2*N + i] = 0;
320 m_vscreen_2_screen[i*N + 2] = 0;
322 m_vscreen_2_screen[2*N + 2] = 1;
323 m_screen_2_vscreen = m_vscreen_2_screen.
inverse();
331 screen_coords.z =
static_cast<int>(Mathd::Tan(m_tilt * (Mathd::pi() / 180.0)) *
static_cast<double>(dy));
357 DoublePoint3D Camera::screenToVirtualScreen(
const ScreenPoint& p) {
361 DoublePoint Camera::getLogicalCellDimensions(Layer* layer) {
364 cg = layer->getCellGrid();
368 ModelCoordinate cell(0,0);
369 std::vector<ExactModelCoordinate> vertices;
370 cg->getVertices(vertices, cell);
374 mtx.applyRotate(m_tilt, 1.0, 0.0, 0.0);
381 for (
unsigned int i = 0; i < vertices.size(); i++) {
382 vertices[i] = cg->toMapCoordinates(vertices[i]);
383 vertices[i] = mtx * vertices[i];
385 x1 = x2 = vertices[0].x;
386 y1 = y2 = vertices[0].y;
388 x1 = std::min(vertices[i].x, x1);
389 x2 = std::max(vertices[i].x, x2);
390 y1 = std::min(vertices[i].y, y1);
391 y2 = std::max(vertices[i].y, y2);
394 return DoublePoint( x2 - x1, y2 - y1 );
397 void Camera::updateReferenceScale() {
398 DoublePoint dim = getLogicalCellDimensions(m_location.getLayer());
399 m_reference_scale =
static_cast<double>(m_screen_cell_width) / dim.x;
401 FL_DBG(_log,
"Updating reference scale");
402 FL_DBG(_log, LMsg(
" tilt=") << m_tilt <<
" rot=" << m_rotation);
403 FL_DBG(_log, LMsg(
" m_screen_cell_width=") << m_screen_cell_width);
407 Map* map = m_location.getMap();
408 Rect cv = m_viewport;
409 int cv2x = cv.
x+cv.
w;
410 int cv2y = cv.
y+cv.
h;
411 bool trec1 =
false, trec2 =
false, trec3 =
false, trec4 =
false;
417 const std::list<Layer*>& layers = map->
getLayers();
418 std::list<Layer*>::const_iterator layer_it = layers.begin();
419 m_layer_to_instances.clear();
420 const RenderList& layer_instances = m_layer_to_instances[*layer_it];
421 RenderList::const_iterator instance_it = layer_instances.begin();
422 for(; instance_it != layer_instances.end(); ++instance_it) {
423 const RenderItem& vc = **instance_it;
424 if(vc.dimensions.intersects(rec1) && !trec1) {
427 if(vc.dimensions.intersects(rec2) && !trec2) {
435 RenderList::const_reverse_iterator instance_itr = layer_instances.rbegin();
436 for(; instance_itr != layer_instances.rend(); ++instance_itr) {
437 const RenderItem& vc = **instance_itr;
438 if(vc.dimensions.intersects(rec3) && !trec3) {
441 if(vc.dimensions.intersects(rec4) && !trec4) {
450 if(trec1 && trec2 && trec3 && trec4) {
458 const RenderList& layer_instances = m_layer_to_instances[&layer];
459 RenderList::const_iterator instance_it = layer_instances.end();
460 while (instance_it != layer_instances.begin()) {
462 Instance* i = (*instance_it)->instance;
463 const RenderItem& vc = **instance_it;
464 if ((vc.dimensions.contains(
Point(screen_coords.x, screen_coords.y)))) {
467 int x = screen_coords.x - vc.dimensions.x;
468 int y = screen_coords.y - vc.dimensions.y;
470 double fx =
static_cast<double>(x);
471 double fy =
static_cast<double>(y);
472 double fow =
static_cast<double>(vc.image->getWidth());
473 double foh =
static_cast<double>(vc.image->getHeight());
474 double fsw =
static_cast<double>(vc.dimensions.w);
475 double fsh =
static_cast<double>(vc.dimensions.h);
476 x =
static_cast<int>(round(fx / fsw * fow));
477 y =
static_cast<int>(round(fy / fsh * foh));
479 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
482 instances.push_back(i);
490 const RenderList& layer_instances = m_layer_to_instances[&layer];
491 RenderList::const_iterator instance_it = layer_instances.end();
492 while (instance_it != layer_instances.begin()) {
494 Instance* i = (*instance_it)->instance;;
495 const RenderItem& vc = **instance_it;
496 if ((vc.dimensions.intersects(screen_rect))) {
499 for(
int xx = screen_rect.
x; xx < screen_rect.
x + screen_rect.
w; xx++) {
500 for(
int yy = screen_rect.
y; yy < screen_rect.
y + screen_rect.
h; yy++) {
501 if ((vc.dimensions.contains(
Point(xx, yy)))) {
502 int x = xx - vc.dimensions.x;
503 int y = yy - vc.dimensions.y;
505 double fx =
static_cast<double>(x);
506 double fy =
static_cast<double>(y);
507 double fow =
static_cast<double>(vc.image->getWidth());
508 double foh =
static_cast<double>(vc.image->getHeight());
509 double fsw =
static_cast<double>(vc.dimensions.w);
510 double fsh =
static_cast<double>(vc.dimensions.h);
511 x =
static_cast<int>(round(fx / fsw * fow));
512 y =
static_cast<int>(round(fy / fsh * foh));
514 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
517 instances.push_back(i);
518 goto found_non_transparent_pixel;
523 found_non_transparent_pixel:;
530 const RenderList& layer_instances = m_layer_to_instances[loc.getLayer()];
531 RenderList::const_iterator instance_it = layer_instances.end();
532 while (instance_it != layer_instances.begin()) {
534 Instance* i = (*instance_it)->instance;
535 if (use_exactcoordinates) {
536 if (i->
getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
537 instances.push_back(i);
540 if (i->
getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
541 instances.push_back(i);
549 if (m_location.getLayer()->getId() != instance->
getLocation().getLayer()->getId()) {
550 FL_WARN(_log,
"Tried to attach camera to instance on different layer.");
553 m_attachedto = instance;
561 if( !m_attachedto ) {
564 Location loc(m_location);
565 loc.setExactLayerCoordinates( m_attachedto->
getLocationRef().getExactLayerCoordinates(m_location.getLayer()) );
577 m_prev_origo = m_cur_origo;
586 m_renderers[renderer->
getName()] = renderer;
588 m_pipeline.push_back(renderer);
590 m_pipeline.sort(pipelineSort);
594 m_pipeline.sort(pipelineSort);
598 assert(m_renderers[renderer->
getName()]);
600 FL_LOG(_log,
LMsg(
"Enabling renderer ") << renderer->
getName());
601 m_pipeline.push_back(renderer);
602 m_pipeline.sort(pipelineSort);
604 m_pipeline.remove(renderer);
609 return m_renderers[name];
613 std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
614 for (; r_it != m_renderers.end(); ++r_it) {
615 Map* map = m_location.getMap();
616 r_it->second->reset();
620 void Camera::addLayer(
Layer* layer) {
621 m_cache[layer] =
new LayerCache(
this, m_ipool, m_apool);
622 m_cache[layer]->setLayer(layer);
623 m_layer_to_instances[layer] = RenderList();
626 void Camera::removeLayer(Layer* layer) {
627 delete m_cache[layer];
628 m_cache.erase(layer);
629 m_layer_to_instances.erase(layer);
632 void Camera::setLightingColor(
float red,
float green,
float blue,
float alpha) {
634 m_light_colors.clear();
635 m_light_colors.push_back(red);
636 m_light_colors.push_back(green);
637 m_light_colors.push_back(blue);
638 m_light_colors.push_back(alpha);
641 std::vector<float> Camera::getLightingColor() {
642 if(m_light_colors.empty()) {
643 for(
int colors = 0; colors != 4; ++colors) {
644 m_light_colors.push_back(1.0f);
647 return m_light_colors;
650 void Camera::resetLightingColor() {
656 Transform transform = NormalTransform;
658 transform = WarpedTransform;
661 Map* map = m_location.getMap();
663 FL_ERR(_log,
"No map for camera found");
673 m_renderbackend->
setLighting(m_light_colors[0], m_light_colors[1], m_light_colors[2], m_light_colors[3]);
686 const std::list<Layer*>& layers = map->
getLayers();
687 std::list<Layer*>::const_iterator layer_it = layers.begin();
688 for (;layer_it != layers.end(); ++layer_it) {
689 LayerCache* cache = m_cache[*layer_it];
692 cache = m_cache[*layer_it];
693 FL_ERR(_log,
LMsg(
"Layer Cache miss! (This shouldn't happen!)") << (*layer_it)->getId());
695 RenderList& instances_to_render = m_layer_to_instances[*layer_it];
696 cache->update(transform, instances_to_render);
698 std::list<RendererBase*>::iterator r_it = m_pipeline.begin();
699 for (; r_it != m_pipeline.end(); ++r_it) {
700 if ((*r_it)->isActivedLayer(*layer_it)) {
701 (*r_it)->render(
this, *layer_it, instances_to_render);
710 m_renderbackend->popClipArea();