comparison engine/core/view/camera.cpp @ 405:cfe2f6db4964

Reverting my last change to camera.cpp. It caused unexpected results with rotated tiles.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Fri, 29 Jan 2010 15:55:47 +0000
parents d98e398d3057
children f27880d4c08c
comparison
equal deleted inserted replaced
404:0ef7b088b3f8 405:cfe2f6db4964
51 51
52 52
53 namespace FIFE { 53 namespace FIFE {
54 static Logger _log(LM_CAMERA); 54 static Logger _log(LM_CAMERA);
55 55
56 Camera::Camera(const std::string& id, 56 Camera::Camera(const std::string& id,
57 Layer *layer, 57 Layer *layer,
58 Rect viewport, 58 Rect viewport,
59 ExactModelCoordinate emc, 59 ExactModelCoordinate emc,
60 RenderBackend* renderbackend, 60 RenderBackend* renderbackend,
61 ImagePool* ipool, 61 ImagePool* ipool,
62 AnimationPool* apool): 62 AnimationPool* apool):
63 m_id(id), 63 m_id(id),
145 if ((m_prev_origo == m_cur_origo) && (m_prev_origo == ScreenPoint(0,0,0))) { 145 if ((m_prev_origo == m_cur_origo) && (m_prev_origo == ScreenPoint(0,0,0))) {
146 m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0)); 146 m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0));
147 m_prev_origo = m_cur_origo; 147 m_prev_origo = m_cur_origo;
148 } 148 }
149 m_location = location; 149 m_location = location;
150 150
151 CellGrid* cg = NULL; 151 CellGrid* cg = NULL;
152 if (m_location.getLayer()) { 152 if (m_location.getLayer()) {
153 cg = m_location.getLayer()->getCellGrid(); 153 cg = m_location.getLayer()->getCellGrid();
154 } else { 154 } else {
155 throw Exception("Location without layer given to Camera::setLocation"); 155 throw Exception("Location without layer given to Camera::setLocation");
156 } 156 }
157 if (!cg) { 157 if (!cg) {
158 throw Exception("Camera layer has no cellgrid specified"); 158 throw Exception("Camera layer has no cellgrid specified");
159 } 159 }
160 160
161 updateMatrices(); 161 updateMatrices();
162 162
163 m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0)); 163 m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0));
164 } 164 }
165 165
166 Point Camera::getCellImageDimensions() { 166 Point Camera::getCellImageDimensions() {
167 return getCellImageDimensions(m_location.getLayer()); 167 return getCellImageDimensions(m_location.getLayer());
182 p.x = static_cast<int>(round(m_reference_scale * dimensions.x)); 182 p.x = static_cast<int>(round(m_reference_scale * dimensions.x));
183 p.y = static_cast<int>(round(m_reference_scale * dimensions.y)); 183 p.y = static_cast<int>(round(m_reference_scale * dimensions.y));
184 m_image_dimensions[layer] = p; 184 m_image_dimensions[layer] = p;
185 return p; 185 return p;
186 } 186 }
187 187
188 Location Camera::getLocation() const { 188 Location Camera::getLocation() const {
189 return m_location; 189 return m_location;
190 } 190 }
191 191
192 Location& Camera::getLocationRef() { 192 Location& Camera::getLocationRef() {
193 return m_location; 193 return m_location;
194 } 194 }
195 195
196 void Camera::setViewPort(const Rect& viewport) { 196 void Camera::setViewPort(const Rect& viewport) {
197 m_viewport = viewport; 197 m_viewport = viewport;
198 } 198 }
199 199
200 const Rect& Camera::getViewPort() const { 200 const Rect& Camera::getViewPort() const {
202 } 202 }
203 203
204 void Camera::setEnabled(bool enabled) { 204 void Camera::setEnabled(bool enabled) {
205 m_enabled = enabled; 205 m_enabled = enabled;
206 } 206 }
207 207
208 bool Camera::isEnabled() { 208 bool Camera::isEnabled() {
209 return m_enabled; 209 return m_enabled;
210 } 210 }
211 211
212 void Camera::updateMatrices() { 212 void Camera::updateMatrices() {
228 228
229 void Camera::calculateZValue(ScreenPoint& screen_coords) { 229 void Camera::calculateZValue(ScreenPoint& screen_coords) {
230 int dy = -(screen_coords.y - toScreenCoordinates(m_location.getMapCoordinates()).y); 230 int dy = -(screen_coords.y - toScreenCoordinates(m_location.getMapCoordinates()).y);
231 screen_coords.z = static_cast<int>(tan(m_tilt * (M_PI / 180.0)) * static_cast<double>(dy)); 231 screen_coords.z = static_cast<int>(tan(m_tilt * (M_PI / 180.0)) * static_cast<double>(dy));
232 } 232 }
233 233
234 ExactModelCoordinate Camera::toMapCoordinates(ScreenPoint screen_coords, bool z_calculated) { 234 ExactModelCoordinate Camera::toMapCoordinates(ScreenPoint screen_coords, bool z_calculated) {
235 if (!z_calculated) { 235 if (!z_calculated) {
236 calculateZValue(screen_coords); 236 calculateZValue(screen_coords);
237 } 237 }
238 screen_coords.x -= m_viewport.w / 2; 238 screen_coords.x -= m_viewport.w / 2;
286 286
287 FL_DBG(_log, "Updating reference scale"); 287 FL_DBG(_log, "Updating reference scale");
288 FL_DBG(_log, LMsg(" tilt=") << m_tilt << " rot=" << m_rotation); 288 FL_DBG(_log, LMsg(" tilt=") << m_tilt << " rot=" << m_rotation);
289 FL_DBG(_log, LMsg(" m_screen_cell_width=") << m_screen_cell_width); 289 FL_DBG(_log, LMsg(" m_screen_cell_width=") << m_screen_cell_width);
290 } 290 }
291 291
292 void Camera::getMatchingInstances(ScreenPoint screen_coords, Layer& layer, std::list<Instance*>& instances) { 292 void Camera::getMatchingInstances(ScreenPoint screen_coords, Layer& layer, std::list<Instance*>& instances) {
293 instances.clear(); 293 instances.clear();
294 const std::vector<Instance*>& layer_instances = m_layer_to_instances[&layer]; 294 const std::vector<Instance*>& layer_instances = m_layer_to_instances[&layer];
295 std::vector<Instance*>::const_iterator instance_it = layer_instances.end(); 295 std::vector<Instance*>::const_iterator instance_it = layer_instances.end();
296 while (instance_it != layer_instances.begin()) { 296 while (instance_it != layer_instances.begin()) {
319 instances.push_back(i); 319 instances.push_back(i);
320 } 320 }
321 } 321 }
322 } 322 }
323 } 323 }
324 324
325 void Camera::getMatchingInstances(Rect screen_rect, Layer& layer, std::list<Instance*>& instances) { 325 void Camera::getMatchingInstances(Rect screen_rect, Layer& layer, std::list<Instance*>& instances) {
326 instances.clear(); 326 instances.clear();
327 const std::vector<Instance*>& layer_instances = m_layer_to_instances[&layer]; 327 const std::vector<Instance*>& layer_instances = m_layer_to_instances[&layer];
328 std::vector<Instance*>::const_iterator instance_it = layer_instances.end(); 328 std::vector<Instance*>::const_iterator instance_it = layer_instances.end();
329 while (instance_it != layer_instances.begin()) { 329 while (instance_it != layer_instances.begin()) {
360 } 360 }
361 found_non_transparent_pixel:; 361 found_non_transparent_pixel:;
362 } 362 }
363 } 363 }
364 } 364 }
365 365
366 void Camera::getMatchingInstances(Location& loc, std::list<Instance*>& instances, bool use_exactcoordinates) { 366 void Camera::getMatchingInstances(Location& loc, std::list<Instance*>& instances, bool use_exactcoordinates) {
367 instances.clear(); 367 instances.clear();
368 const std::vector<Instance*>& layer_instances = m_layer_to_instances[loc.getLayer()]; 368 const std::vector<Instance*>& layer_instances = m_layer_to_instances[loc.getLayer()];
369 std::vector<Instance*>::const_iterator instance_it = layer_instances.end(); 369 std::vector<Instance*>::const_iterator instance_it = layer_instances.end();
370 while (instance_it != layer_instances.begin()) { 370 while (instance_it != layer_instances.begin()) {
402 Location loc(m_location); 402 Location loc(m_location);
403 loc.setExactLayerCoordinates( m_attachedto->getLocationRef().getExactLayerCoordinates(m_location.getLayer()) ); 403 loc.setExactLayerCoordinates( m_attachedto->getLocationRef().getExactLayerCoordinates(m_location.getLayer()) );
404 setLocation(loc); 404 setLocation(loc);
405 updateMatrices(); 405 updateMatrices();
406 } 406 }
407 407
408 void Camera::refresh() { 408 void Camera::refresh() {
409 updateMatrices(); 409 updateMatrices();
410 m_iswarped = true; 410 m_iswarped = true;
411 } 411 }
412 412
413 void Camera::resetUpdates() { 413 void Camera::resetUpdates() {
414 m_iswarped = false; 414 m_iswarped = false;
415 m_prev_origo = m_cur_origo; 415 m_prev_origo = m_cur_origo;
416 } 416 }
417 417
418 bool pipelineSort(const RendererBase* lhs, const RendererBase* rhs) { 418 bool pipelineSort(const RendererBase* lhs, const RendererBase* rhs) {
419 return (lhs->getPipelinePosition() < rhs->getPipelinePosition()); 419 return (lhs->getPipelinePosition() < rhs->getPipelinePosition());
420 } 420 }
421 421
422 void Camera::addRenderer(RendererBase* renderer) { 422 void Camera::addRenderer(RendererBase* renderer) {
423 renderer->setRendererListener(this); 423 renderer->setRendererListener(this);
424 m_renderers[renderer->getName()] = renderer; 424 m_renderers[renderer->getName()] = renderer;
425 if (renderer->isEnabled()) { 425 if (renderer->isEnabled()) {
426 m_pipeline.push_back(renderer); 426 m_pipeline.push_back(renderer);
427 } 427 }
428 m_pipeline.sort(pipelineSort); 428 m_pipeline.sort(pipelineSort);
429 } 429 }
430 430
431 void Camera::onRendererPipelinePositionChanged(RendererBase* renderer) { 431 void Camera::onRendererPipelinePositionChanged(RendererBase* renderer) {
432 m_pipeline.sort(pipelineSort); 432 m_pipeline.sort(pipelineSort);
433 } 433 }
434 434
435 void Camera::onRendererEnabledChanged(RendererBase* renderer) { 435 void Camera::onRendererEnabledChanged(RendererBase* renderer) {
436 assert(m_renderers[renderer->getName()]); 436 assert(m_renderers[renderer->getName()]);
437 if (renderer->isEnabled()) { 437 if (renderer->isEnabled()) {
438 FL_LOG(_log, LMsg("Enabling renderer ") << renderer->getName()); 438 FL_LOG(_log, LMsg("Enabling renderer ") << renderer->getName());
439 m_pipeline.push_back(renderer); 439 m_pipeline.push_back(renderer);
444 } 444 }
445 445
446 RendererBase* Camera::getRenderer(const std::string& name) { 446 RendererBase* Camera::getRenderer(const std::string& name) {
447 return m_renderers[name]; 447 return m_renderers[name];
448 } 448 }
449 449
450 class InstanceDistanceSort { 450 class InstanceDistanceSort {
451 public: 451 public:
452 Camera* cam; 452 Camera* cam;
453 inline bool operator()(const Instance* lhs, const Instance* rhs) { 453 inline bool operator()(const Instance* lhs, const Instance* rhs) {
454 InstanceVisual* liv = lhs->getVisual<InstanceVisual>(); 454 InstanceVisual* liv = lhs->getVisual<InstanceVisual>();
471 } 471 }
472 } 472 }
473 473
474 void Camera::render() { 474 void Camera::render() {
475 ScreenPoint cammove = m_prev_origo - m_cur_origo; 475 ScreenPoint cammove = m_prev_origo - m_cur_origo;
476 476
477 Map* map = m_location.getMap(); 477 Map* map = m_location.getMap();
478 if (!map) { 478 if (!map) {
479 FL_ERR(_log, "No map for camera found"); 479 FL_ERR(_log, "No map for camera found");
480 return; 480 return;
481 } 481 }
482 //if ((!map->isChanged()) && (!m_iswarped) && (cammove == ScreenPoint(0,0,0))) { 482 //if ((!map->isChanged()) && (!m_iswarped) && (cammove == ScreenPoint(0,0,0))) {
483 // return; 483 // return;
484 //} 484 //}
485 485
486 // update each layer 486 // update each layer
487 m_renderbackend->pushClipArea(getViewPort()); 487 m_renderbackend->pushClipArea(getViewPort());
488 488
489 m_layer_to_instances.clear(); 489 m_layer_to_instances.clear();
490 490
491 const std::list<Layer*>& layers = map->getLayers(); 491 const std::list<Layer*>& layers = map->getLayers();
492 std::list<Layer*>::const_iterator layer_it = layers.begin(); 492 std::list<Layer*>::const_iterator layer_it = layers.begin();
493 for (;layer_it != layers.end(); ++layer_it) { 493 for (;layer_it != layers.end(); ++layer_it) {
503 Instance* instance = *instance_it; 503 Instance* instance = *instance_it;
504 InstanceVisual* visual = instance->getVisual<InstanceVisual>(); 504 InstanceVisual* visual = instance->getVisual<InstanceVisual>();
505 if(!visual->isVisible()) 505 if(!visual->isVisible())
506 continue; 506 continue;
507 InstanceVisualCacheItem& vc = visual->getCacheItem(this); 507 InstanceVisualCacheItem& vc = visual->getCacheItem(this);
508 508
509 // use cached values if there is no need to do full recalculation 509 // use cached values if there is no need to do full recalculation
510 ScreenPoint drawpt; 510 ScreenPoint drawpt;
511 int angle = 0; 511 int angle = 0;
512 if (m_updated && (!m_iswarped) && (!(instance->getChangeInfo() & (ICHANGE_LOC | ICHANGE_ROTATION | ICHANGE_FACING_LOC))) && (vc.image)) { 512 if (m_updated && (!m_iswarped) && (!(instance->getChangeInfo() & (ICHANGE_LOC | ICHANGE_ROTATION | ICHANGE_FACING_LOC))) && (vc.image)) {
513 int pos_estimate_x = vc.screenpoint.x - cammove.x; 513 int pos_estimate_x = vc.screenpoint.x - cammove.x;
520 drawpt.y = pos_estimate_y; 520 drawpt.y = pos_estimate_y;
521 drawpt.z = pos_estimate_z; 521 drawpt.z = pos_estimate_z;
522 //drawpt.z = toScreenCoordinates( instance->getLocationRef().getMapCoordinates() ).z; 522 //drawpt.z = toScreenCoordinates( instance->getLocationRef().getMapCoordinates() ).z;
523 } else { 523 } else {
524 drawpt = toScreenCoordinates( instance->getLocationRef().getMapCoordinates() ); 524 drawpt = toScreenCoordinates( instance->getLocationRef().getMapCoordinates() );
525 vc.facing_angle = angle = getAngleBetween(instance->getLocationRef(), instance->getFacingLocation()); 525 vc.facing_angle = getAngleBetween(instance->getLocationRef(), instance->getFacingLocation());
526 } 526 angle = vc.facing_angle;
527 527 }
528 //This is to fix ticket #361. I would rather not have to put this here. 528
529 //It should be handled in a more appropriate spot like within Instance::setFacingLocation(). 529 angle += instance->getRotation();
530 //It ensures the instances rotation is in sync with it's facing direction.
531 if (angle < 0) {
532 angle = 360+angle;
533 }
534 instance->setRotation(angle);
535 530
536 Image* image = NULL; 531 Image* image = NULL;
537 Action* action = instance->getCurrentAction(); 532 Action* action = instance->getCurrentAction();
538 if (action) { 533 if (action) {
539 FL_DBG(_log, "Instance has action"); 534 FL_DBG(_log, "Instance has action");
559 } 554 }
560 } 555 }
561 if (image) { 556 if (image) {
562 vc.image = image; 557 vc.image = image;
563 vc.screenpoint = drawpt; 558 vc.screenpoint = drawpt;
564 559
565 int w = image->getWidth(); 560 int w = image->getWidth();
566 int h = image->getHeight(); 561 int h = image->getHeight();
567 drawpt.x -= w / 2; 562 drawpt.x -= w / 2;
568 drawpt.x += image->getXShift(); 563 drawpt.x += image->getXShift();
569 drawpt.y -= h / 2; 564 drawpt.y -= h / 2;
570 drawpt.y += image->getYShift(); 565 drawpt.y += image->getYShift();
571 Rect r = Rect(drawpt.x, drawpt.y, w, h); 566 Rect r = Rect(drawpt.x, drawpt.y, w, h);
572 567
573 vc.dimensions = r; 568 vc.dimensions = r;
574 if (m_zoom != 1.0) { 569 if (m_zoom != 1.0) {
575 // NOTE: Due to image alignment, there is additional additions and substractions on image dimensions 570 // NOTE: Due to image alignment, there is additional additions and substractions on image dimensions
576 // There's probabaly some better solution for this, but works "good enough" for now. 571 // There's probabaly some better solution for this, but works "good enough" for now.
577 // In case additions / substractions are removed, gaps appear between tiles. 572 // In case additions / substractions are removed, gaps appear between tiles.
581 int yo = static_cast<int>(ceil(static_cast<double>(vc.image->getYShift()) * m_zoom)) - vc.image->getYShift(); 576 int yo = static_cast<int>(ceil(static_cast<double>(vc.image->getYShift()) * m_zoom)) - vc.image->getYShift();
582 r.x = vc.dimensions.x - static_cast<unsigned int>(ceil(static_cast<double>(r.w - vc.dimensions.w) / 2)) + xo - 1; 577 r.x = vc.dimensions.x - static_cast<unsigned int>(ceil(static_cast<double>(r.w - vc.dimensions.w) / 2)) + xo - 1;
583 r.y = vc.dimensions.y - static_cast<unsigned int>(ceil(static_cast<double>(r.h - vc.dimensions.h) / 2)) + yo - 1; 578 r.y = vc.dimensions.y - static_cast<unsigned int>(ceil(static_cast<double>(r.h - vc.dimensions.h) / 2)) + yo - 1;
584 vc.dimensions = r; 579 vc.dimensions = r;
585 } 580 }
586 581
587 if (vc.dimensions.intersects(getViewPort())) { 582 if (vc.dimensions.intersects(getViewPort())) {
588 instances_to_render.push_back(instance); 583 instances_to_render.push_back(instance);
589 } 584 }
590 } 585 }
591 } 586 }