void World::updateNaviMap(bool full_recompute) { FWK_PROFILE("updateNaviMap"); //TODO: what about static entities that are added during the game? if(full_recompute) { vector<IBox> bboxes, blockers; bboxes.reserve(m_tile_map.size() + m_entity_map.size()); for(int n = 0; n < m_tile_map.size(); n++) { const Tile *tile = m_tile_map[n].ptr; if(!tile || !Flags::test(tile->flags(), Flags::all | Flags::colliding)) continue; bool is_walkable = Flags::test(tile->flags(), Flags::walkable_tile | Flags::wall_tile); (is_walkable? bboxes : blockers).push_back((IBox)m_tile_map[n].bbox); } for(int n = 0; n < m_entity_map.size(); n++) if(m_entity_map[n].ptr && Flags::test(m_entity_map[n].flags, Flags::static_entity | Flags::colliding)) blockers.push_back(enclosingIBox(m_entity_map[n].ptr->boundingBox())); NaviHeightmap heightmap(m_tile_map.dimensions()); heightmap.update(bboxes, blockers); //heightmap.saveLevels(); //heightmap.printInfo(); for(int m = 0; m < (int)m_navi_maps.size(); m++) { m_navi_maps[m].update(heightmap); //m_navi_maps[m].printInfo(); } } for(int m = 0; m < (int)m_navi_maps.size(); m++) { NaviMap &navi_map = m_navi_maps[m]; navi_map.removeColliders(); for(int n = 0; n < m_entity_map.size(); n++) { auto &object = m_entity_map[n]; if(!object.ptr) continue; if(Flags::test(object.flags, Flags::dynamic_entity | Flags::colliding)) { const IBox &box = enclosingIBox(object.ptr->boundingBox()); navi_map.addCollider(box, n); } } navi_map.updateReachability(); } }
void WorldViewer::update(double time_diff) { FWK_PROFILE("WorldViewer::update"); Actor *spectator = m_world->refEntity<Actor>(m_spectator); if((int)m_entities.size() != m_world->entityCount()) m_entities.resize(m_world->entityCount()); if(!m_spectator) { for(int n = 0; n < (int)m_entities.size(); n++) { Entity *entity = m_world->refEntity(n); VisEntity &vis_entity = m_entities[n]; vis_entity.ref = entity? entity->ref() : EntityRef(); vis_entity.mode = entity? VisEntity::visible : VisEntity::invisible; vis_entity.occluder_id = -1; } return; } if(!spectator) return; FBox bbox = spectator->boundingBox(); m_cur_pos = bbox.center(); m_eye_pos = asXZY(m_cur_pos.xz(), bbox.min.y + bbox.height() * 0.75f); for(int n = 0; n < (int)m_entities.size(); n++) { Entity *entity = m_world->refEntity(n); VisEntity &vis_entity = m_entities[n]; if(!entity) { vis_entity = VisEntity(); continue; } const auto *desc = m_world->refEntityDesc(n); DASSERT(desc); bool is_visible = m_see_all || spectator == entity || spectator->canSee(entity->ref(), !isMovable(*entity)); if(vis_entity.ref != entity->ref()) { vis_entity = VisEntity(); vis_entity.ref = entity->ref(); vis_entity.mode = is_visible? VisEntity::visible : VisEntity::invisible; } if(is_visible) { vis_entity.occluder_id = desc->occluder_id; if(vis_entity.mode == VisEntity::visible) continue; if(vis_entity.mode == VisEntity::shadowed || vis_entity.mode == VisEntity::pre_blending_out) { vis_entity.shadow.reset(); vis_entity.mode = VisEntity::visible; } else { float blend_value = 0.0; if(vis_entity.mode == VisEntity::blending_in) blend_value = vis_entity.blend_value; else if(vis_entity.mode == VisEntity::blending_out) blend_value = blend_time - vis_entity.blend_value; blend_value += time_diff; vis_entity.mode = blend_value > blend_time? VisEntity::visible : VisEntity::blending_in; vis_entity.blend_value = blend_value; } } else { if(vis_entity.mode == VisEntity::shadowed || vis_entity.mode == VisEntity::invisible) continue; if(vis_entity.mode == VisEntity::visible) { vis_entity.blend_value = 0.0f; vis_entity.mode = VisEntity::pre_blending_out; } if(vis_entity.mode == VisEntity::pre_blending_out) { vis_entity.blend_value += time_diff; if(vis_entity.blend_value > blend_time) { if(isMovable(*entity)) { vis_entity.mode = VisEntity::blending_out; vis_entity.blend_value = vis_entity.blend_value - blend_time; } else { vis_entity.mode = VisEntity::shadowed; vis_entity.occluder_id = desc->occluder_id; vis_entity.shadow.reset(entity->clone()); } } } else { float blend_value = 0.0f; if(vis_entity.mode == VisEntity::blending_in) blend_value = blend_time - vis_entity.blend_value; else if(vis_entity.mode == VisEntity::blending_out) blend_value = vis_entity.blend_value; vis_entity.blend_value = blend_value + time_diff; vis_entity.mode = VisEntity::blending_out; if(vis_entity.blend_value > blend_time) vis_entity.mode = VisEntity::invisible; } } } if(m_occluder_config.update(spectator->boundingBox())) m_world->tileMap().updateVisibility(m_occluder_config); }