Mercurial > fife-parpg
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 } |