void TiledLayerChromium::reserveTextures() { updateBounds(); const IntRect& layerRect = visibleLayerRect(); if (layerRect.isEmpty() || !m_tiler->numTiles()) return; int left, top, right, bottom; m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom); createTextureUpdaterIfNeeded(); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) tile->m_dirtyRect = m_tiler->tileRect(tile); if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) return; } } }
void CCTiledLayerImpl::pushTileProperties(int i, int j, CCResourceProvider::ResourceId resourceId, const IntRect& opaqueRect) { DrawableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); tile->setResourceId(resourceId); tile->setOpaqueRect(opaqueRect); }
void CCTiledLayerImpl::pushInvalidTile(int i, int j) { DrawableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); tile->setResourceId(0); tile->setOpaqueRect(IntRect()); }
void TiledLayerChromium::updateCompositorResources(GraphicsContext3D* context) { // Painting could cause compositing to get turned off, which may cause the tiler to become invalidated mid-update. if (m_skipsDraw || m_updateRect.isEmpty() || !m_tiler->numTiles()) return; int left, top, right, bottom; m_tiler->contentRectToTileIndices(m_updateRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); else if (!tile->dirty()) continue; // Calculate page-space rectangle to copy from. IntRect sourceRect = m_tiler->tileContentRect(tile); const IntPoint anchor = sourceRect.location(); sourceRect.intersect(m_tiler->layerRectToContentRect(tile->m_dirtyLayerRect)); // Paint rect not guaranteed to line up on tile boundaries, so // make sure that sourceRect doesn't extend outside of it. sourceRect.intersect(m_paintRect); if (sourceRect.isEmpty()) continue; ASSERT(tile->texture()->isReserved()); // Calculate tile-space rectangle to upload into. IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()), sourceRect.size()); if (destRect.x() < 0) CRASH(); if (destRect.y() < 0) CRASH(); // Offset from paint rectangle to this tile's dirty rectangle. IntPoint paintOffset(sourceRect.x() - m_paintRect.x(), sourceRect.y() - m_paintRect.y()); if (paintOffset.x() < 0) CRASH(); if (paintOffset.y() < 0) CRASH(); if (paintOffset.x() + destRect.width() > m_paintRect.width()) CRASH(); if (paintOffset.y() + destRect.height() > m_paintRect.height()) CRASH(); tile->texture()->bindTexture(context); const GC3Dint filter = m_tiler->hasBorderTexels() ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST; GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, filter)); GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, filter)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0)); textureUpdater()->updateTextureRect(context, tile->texture(), sourceRect, destRect); tile->clearDirty(); } } }
void TiledLayerChromium::prepareToUpdate(const IntRect& contentRect) { ASSERT(m_tiler); m_skipsDraw = false; if (contentRect.isEmpty()) { m_updateRect = IntRect(); return; } // Invalidate old tiles that were previously used but aren't in use this // frame so that they can get reused for new tiles. invalidateTiles(contentRect); m_tiler->growLayerToContain(contentRect); if (!m_tiler->numTiles()) { m_updateRect = IntRect(); return; } // Create tiles as needed, expanding a dirty rect to contain all // the dirty regions currently being drawn. IntRect dirtyLayerRect; int left, top, right, bottom; m_tiler->contentRectToTileIndices(contentRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); if (!tile->texture()->isValid(m_tiler->tileSize(), m_textureFormat)) tile->m_dirtyLayerRect = m_tiler->tileLayerRect(tile); if (!tile->texture()->reserve(m_tiler->tileSize(), m_textureFormat)) { m_skipsDraw = true; cleanupResources(); return; } dirtyLayerRect.unite(tile->m_dirtyLayerRect); } } // Due to borders, when the paint rect is extended to tile boundaries, it // may end up overlapping more tiles than the original content rect. Record // that original rect so we don't upload more tiles than necessary. m_updateRect = contentRect; m_paintRect = m_tiler->layerRectToContentRect(dirtyLayerRect); if (dirtyLayerRect.isEmpty()) return; textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels()); }
void FeedWidget::addEntry( QSharedPointer<Entry> entry ) { Tile *tile = createTile( mPlayer, nullptr, entry ); if( tile ) { mLayout->addWidget( tile ); mTiles.push_back( tile ); connect( tile, SIGNAL(openUrl(QString)), SIGNAL(openUrl(QString)) ); } }
TiledMap::TiledMap(std::string mapFilename, Level* level) { _level = level; mapData = new Tmx::Map(); mapData->ParseFile(mapFilename); int sizeX = mapData->GetWidth(); int sizeY = mapData->GetHeight(); tileWidth = mapData->GetTileWidth(); tileHeight = mapData->GetTileHeight(); int numLayers = mapData->GetNumLayers(); int numObjectGroups = mapData->GetNumObjectGroups(); std::string imageFilename = mapData->GetTileset(0)->GetImage()->GetSource(); osg::Image* image = osgDB::readImageFile(imageFilename); if (!image) logError("Could not load tileset image."); geode = new osg::Geode(); // Set up the StateSet for this map. state = new osg::StateSet; osg::Texture2D* texture = new osg::Texture2D; texture->setImage(image); texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); state->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); // Apply the texture state->setRenderBinDetails(1, "transparent"); // Use a different rendering bin that gets rendered after the default one state->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); // Tell OpenGL that this is a transparent bin, and thus everything should be rendered back-to-front for(int i = 0; i < numLayers; ++i) for(int y = 0; y < sizeY; ++y) for(int x = 0; x < sizeX; ++x) { int gid = mapData->GetLayer(i)->GetTileId(x, y); if(gid > 0) // Don't create a tile for blank ones (gid 0). geode->addDrawable( createTile(osg::Vec3(x, -y - 1, i), 1.0f, 1.0f, gid)); } for(int i = 0; i < numObjectGroups; ++i) { if(mapData->GetObjectGroup(i)->GetName() == "Collision") loadCollisionLayer(mapData->GetObjectGroup(i)); else if(mapData->GetObjectGroup(i)->GetName() == "Entities") loadEntityLayer(mapData->GetObjectGroup(i)); else { std::ostringstream stream; stream << "Unable to determine function of object layer \"" << mapData->GetObjectGroup(i)->GetName() << "\"."; logWarning(stream.str()); } } transformNode = new osg::PositionAttitudeTransform(); transformNode->addChild(geode); addToSceneGraph(transformNode); }
void WorldMap::loadMap(std::string filename,tripleVector& objectVector){ std::ifstream in; std::string line; std::vector<std::string> strs; vectorXindex = 0; vectorYindex = 0; lastWorldXIndex = 0; lastWorldYIndex = 0; in.open(filename); int elementCount = 0; int currentIndex; std::string idString; int minSubstring; int parsedId; int counter; if (in.fail()) std::cout << "Failed To open:" + filename<<std::endl; while (!in.eof()){ lastWorldXIndex = 0; minSubstring = 0; currentIndex = 0; counter = 0; idString = ""; std::getline(in, line, '\n'); bool isRunning = true; while (isRunning){ while (currentIndex<line.size() && line.at(currentIndex) != ','){ currentIndex++; counter++; } idString = line.substr(minSubstring, counter); currentIndex++;//pass over , char minSubstring = currentIndex; if (minSubstring >= line.size()) isRunning = false; counter = 0; parsedId = atoi(idString.c_str()); elementCount++; createTile(lastWorldXIndex, lastWorldYIndex, parsedId, objectVector); lastWorldXIndex++; if (lastWorldXIndex % 16 == 0){ vectorYindex++; if (vectorYindex == Global::WorldRoomWidth) vectorYindex = 0; } } lastWorldYIndex++; if (lastWorldYIndex % 16 == 0){ vectorXindex++; } } in.close(); }
bool FonRegionMap::init() { if ( !Layer::init() ) { return false; } //draw fon region for(int i = -20; i < 20; i++) for(int j = -20; j < 20; j++) createTile(100.5*i ,100.5*j,"herb"); return true; }
QRect QQuickContext2DTexture::createTiles(const QRect& window) { QList<QQuickContext2DTile*> oldTiles = m_tiles; m_tiles.clear(); if (window.isEmpty()) { return QRect(); } QRect r = tiledRect(window, adjustedTileSize(m_tileSize)); const int tw = m_tileSize.width(); const int th = m_tileSize.height(); const int h1 = window.left() / tw; const int v1 = window.top() / th; const int htiles = r.width() / tw; const int vtiles = r.height() / th; for (int yy = 0; yy < vtiles; ++yy) { for (int xx = 0; xx < htiles; ++xx) { int ht = xx + h1; int vt = yy + v1; QQuickContext2DTile* tile = 0; QPoint pos(ht * tw, vt * th); QRect rect(pos, m_tileSize); for (int i = 0; i < oldTiles.size(); i++) { if (oldTiles[i]->rect() == rect) { tile = oldTiles.takeAt(i); break; } } if (!tile) tile = createTile(); tile->setRect(rect); m_tiles.append(tile); } } qDeleteAll(oldTiles); return r; }
void Purity::Layer::processTiles() { Tmx::MapTile tmxTile; int layerHeight = mTmxLayer->GetHeight(); int layerWidth = mTmxLayer->GetWidth(); for (int y = 0; y < layerHeight; ++y) { for (int x = 0; x < layerWidth; ++x) { tmxTile = mTmxLayer->GetTile(x, y); if (tmxTile.tilesetId != -1) { std::string tilesetPathStr = mTmxMap->GetTileset(tmxTile.tilesetId)->GetImage()->GetSource(); std::string texturePathStr = mSceneDir + tilesetPathStr; createTile(x, y, texturePathStr, tmxTile.id); } } } }
void TiledDrawingAreaProxy::createTiles() { IntRect visibleRect = mapFromContents(webViewVisibleRect()); m_previousVisibleRect = visibleRect; if (visibleRect.isEmpty()) return; // Resize tiles on edges in case the contents size has changed. bool didResizeTiles = resizeEdgeTiles(); // Remove tiles outside out current maximum keep rect. dropTilesOutsideRect(calculateKeepRect(visibleRect)); // Cover the cover rect with tiles. IntRect coverRect = calculateCoverRect(visibleRect); // Search for the tile position closest to the viewport center that does not yet contain a tile. // Which position is considered the closest depends on the tileDistance function. double shortestDistance = std::numeric_limits<double>::infinity(); Vector<TiledDrawingAreaTile::Coordinate> tilesToCreate; unsigned requiredTileCount = 0; bool hasVisibleCheckers = false; TiledDrawingAreaTile::Coordinate topLeft = tileCoordinateForPoint(coverRect.topLeft()); TiledDrawingAreaTile::Coordinate bottomRight = tileCoordinateForPoint(coverRect.bottomRight()); for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { TiledDrawingAreaTile::Coordinate currentCoordinate(xCoordinate, yCoordinate); // Distance is 0 for all currently visible tiles. double distance = tileDistance(visibleRect, currentCoordinate); RefPtr<TiledDrawingAreaTile> tile = tileAt(currentCoordinate); if (!distance && (!tile || !tile->isReadyToPaint())) hasVisibleCheckers = true; if (tile) continue; ++requiredTileCount; if (distance > shortestDistance) continue; if (distance < shortestDistance) { tilesToCreate.clear(); shortestDistance = distance; } tilesToCreate.append(currentCoordinate); } } if (hasVisibleCheckers && shortestDistance > 0) return; // Now construct the tile(s). unsigned tilesToCreateCount = tilesToCreate.size(); for (unsigned n = 0; n < tilesToCreateCount; ++n) createTile(tilesToCreate[n]); requiredTileCount -= tilesToCreateCount; // Paint the content of the newly created tiles. if (tilesToCreateCount || didResizeTiles) updateTileBuffers(); // Keep creating tiles until the whole coverRect is covered. if (requiredTileCount) m_tileCreationTimer.startOneShot(m_tileCreationDelay); }
bool IOMap::loadMap(Map* map, const std::string& identifier) { FileLoader f; if(!f.openFile(identifier.c_str(), false, true)) { std::stringstream ss; ss << "Could not open the file " << identifier << "."; setLastErrorString(ss.str()); return false; } uint32_t type = 0; NODE root = f.getChildNode((NODE)NULL, type); PropStream propStream; if(!f.getProps(root, propStream)) { setLastErrorString("Could not read root property."); return false; } OTBM_root_header* rootHeader; if(!propStream.GET_STRUCT(rootHeader)) { setLastErrorString("Could not read header."); return false; } uint32_t headerVersion = rootHeader->version; if(headerVersion <= 0) { //In otbm version 1 the count variable after splashes/fluidcontainers and stackables //are saved as attributes instead, this solves alot of problems with items //that is changed (stackable/charges/fluidcontainer/splash) during an update. setLastErrorString("This map needs to be upgraded by using the latest map editor version to be able to load correctly."); return false; } if(headerVersion > 2) { setLastErrorString("Unknown OTBM version detected."); return false; } uint32_t headerMajorItems = rootHeader->majorVersionItems; if(headerMajorItems < 3) { setLastErrorString("This map needs to be upgraded by using the latest map editor version to be able to load correctly."); return false; } if(headerMajorItems > (uint32_t)Items::dwMajorVersion) { setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required."); return false; } uint32_t headerMinorItems = rootHeader->minorVersionItems; if(headerMinorItems < CLIENT_VERSION_810) { setLastErrorString("This map needs an updated items.otb."); return false; } if(headerMinorItems > (uint32_t)Items::dwMinorVersion) setLastErrorString("This map needs an updated items.otb."); std::cout << "> Map size: " << rootHeader->width << "x" << rootHeader->height << "." << std::endl; map->mapWidth = rootHeader->width; map->mapHeight = rootHeader->height; NODE nodeMap = f.getChildNode(root, type); if(type != OTBM_MAP_DATA) { setLastErrorString("Could not read data node."); return false; } if(!f.getProps(nodeMap, propStream)) { setLastErrorString("Could not read map data attributes."); return false; } std::string tmp; uint8_t attribute; while(propStream.GET_UCHAR(attribute)) { switch(attribute) { case OTBM_ATTR_DESCRIPTION: { if(!propStream.GET_STRING(tmp)) { setLastErrorString("Invalid description tag."); return false; } map->descriptions.push_back(tmp); break; } case OTBM_ATTR_EXT_SPAWN_FILE: { if(!propStream.GET_STRING(tmp)) { setLastErrorString("Invalid spawnfile tag."); return false; } map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1); map->spawnfile += tmp; break; } case OTBM_ATTR_EXT_HOUSE_FILE: { if(!propStream.GET_STRING(tmp)) { setLastErrorString("Invalid housefile tag."); return false; } map->housefile = identifier.substr(0, identifier.rfind('/') + 1); map->housefile += tmp; break; } default: { setLastErrorString("Unknown header node."); return false; } } } std::cout << "> Map descriptions: " << std::endl; for(StringVec::iterator it = map->descriptions.begin(); it != map->descriptions.end(); ++it) std::cout << (*it) << std::endl; NODE nodeMapData = f.getChildNode(nodeMap, type); while(nodeMapData != NO_NODE) { if(f.getError() != ERROR_NONE) { setLastErrorString("Invalid map node."); return false; } if(type == OTBM_TILE_AREA) { if(!f.getProps(nodeMapData, propStream)) { setLastErrorString("Invalid map node."); return false; } OTBM_Destination_coords* area_coord; if(!propStream.GET_STRUCT(area_coord)) { setLastErrorString("Invalid map node."); return false; } int32_t base_x = area_coord->_x, base_y = area_coord->_y, base_z = area_coord->_z; NODE nodeTile = f.getChildNode(nodeMapData, type); while(nodeTile != NO_NODE) { if(f.getError() != ERROR_NONE) { setLastErrorString("Could not read node data."); return false; } if(type == OTBM_TILE || type == OTBM_HOUSETILE) { if(!f.getProps(nodeTile, propStream)) { setLastErrorString("Could not read node data."); return false; } OTBM_Tile_coords* tileCoord; if(!propStream.GET_STRUCT(tileCoord)) { setLastErrorString("Could not read tile position."); return false; } Tile* tile = NULL; Item* groundItem = NULL; uint32_t tileflags = 0; uint16_t px = base_x + tileCoord->_x, py = base_y + tileCoord->_y, pz = base_z; House* house = NULL; if(type == OTBM_HOUSETILE) { uint32_t _houseid; if(!propStream.GET_ULONG(_houseid)) { std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not read house id."; setLastErrorString(ss.str()); return false; } house = Houses::getInstance().getHouse(_houseid, true); if(!house) { std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not create house id: " << _houseid; setLastErrorString(ss.str()); return false; } tile = new HouseTile(px, py, pz, house); house->addTile(static_cast<HouseTile*>(tile)); } //read tile attributes uint8_t attribute; while(propStream.GET_UCHAR(attribute)) { switch(attribute) { case OTBM_ATTR_TILE_FLAGS: { uint32_t flags; if(!propStream.GET_ULONG(flags)) { std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to read tile flags."; setLastErrorString(ss.str()); return false; } if((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) tileflags |= TILESTATE_PROTECTIONZONE; else if((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE) tileflags |= TILESTATE_NOPVPZONE; else if((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE) tileflags |= TILESTATE_PVPZONE; if((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT) tileflags |= TILESTATE_NOLOGOUT; if((flags & TILESTATE_REFRESH) == TILESTATE_REFRESH) { if(house) std::cout << "[x:" << px << ", y:" << py << ", z:" << pz << "] House tile flagged as refreshing!"; tileflags |= TILESTATE_REFRESH; } break; } case OTBM_ATTR_ITEM: { Item* item = Item::CreateItem(propStream); if(!item) { std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item."; setLastErrorString(ss.str()); return false; } if(house && item->isMoveable()) { std::cout << "[Warning - IOMap::loadMap] Movable item in house: " << house->getHouseId(); std::cout << ", item type: " << item->getID() << ", at position " << px << "/" << py << "/"; std::cout << pz << std::endl; delete item; item = NULL; } else if(tile) { tile->__internalAddThing(item); item->__startDecaying(); item->setLoadedFromMap(true); } else if(item->isGroundTile()) { if(groundItem) delete groundItem; groundItem = item; } else { tile = createTile(groundItem, item, px, py, pz); tile->__internalAddThing(item); item->__startDecaying(); item->setLoadedFromMap(true); } break; } default: { std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown tile attribute."; setLastErrorString(ss.str()); return false; } } } NODE nodeItem = f.getChildNode(nodeTile, type); while(nodeItem) { if(type == OTBM_ITEM) { PropStream propStream; f.getProps(nodeItem, propStream); Item* item = Item::CreateItem(propStream); if(!item) { std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item."; setLastErrorString(ss.str()); return false; } if(item->unserializeItemNode(f, nodeItem, propStream)) { if(house && item->isMoveable()) { std::cout << "[Warning - IOMap::loadMap] Movable item in house: "; std::cout << house->getHouseId() << ", item type: " << item->getID(); std::cout << ", pos " << px << "/" << py << "/" << pz << std::endl; delete item; item = NULL; } else if(tile) { tile->__internalAddThing(item); item->__startDecaying(); item->setLoadedFromMap(true); } else if(item->isGroundTile()) { if(groundItem) delete groundItem; groundItem = item; } else { tile = createTile(groundItem, item, px, py, pz); tile->__internalAddThing(item); item->__startDecaying(); item->setLoadedFromMap(true); } } else { std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to load item " << item->getID() << "."; setLastErrorString(ss.str()); delete item; item = NULL; return false; } } else { std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown node type."; setLastErrorString(ss.str()); } nodeItem = f.getNextNode(nodeItem, type); } if(!tile) tile = createTile(groundItem, NULL, px, py, pz); tile->setFlag((tileflags_t)tileflags); map->setTile(px, py, pz, tile); } else { setLastErrorString("Unknown tile node."); return false; } nodeTile = f.getNextNode(nodeTile, type); } } else if(type == OTBM_TOWNS) { NODE nodeTown = f.getChildNode(nodeMapData, type); while(nodeTown != NO_NODE) { if(type == OTBM_TOWN) { if(!f.getProps(nodeTown, propStream)) { setLastErrorString("Could not read town data."); return false; } uint32_t townId = 0; if(!propStream.GET_ULONG(townId)) { setLastErrorString("Could not read town id."); return false; } Town* town = Towns::getInstance().getTown(townId); if(!town) { town = new Town(townId); Towns::getInstance().addTown(townId, town); } std::string townName = ""; if(!propStream.GET_STRING(townName)) { setLastErrorString("Could not read town name."); return false; } town->setName(townName); OTBM_Destination_coords *town_coords; if(!propStream.GET_STRUCT(town_coords)) { setLastErrorString("Could not read town coordinates."); return false; } town->setTemplePos(Position(town_coords->_x, town_coords->_y, town_coords->_z)); } else { setLastErrorString("Unknown town node."); return false; } nodeTown = f.getNextNode(nodeTown, type); } } else if(type == OTBM_WAYPOINTS && headerVersion > 1) { NODE nodeWaypoint = f.getChildNode(nodeMapData, type); while(nodeWaypoint != NO_NODE) { if(type == OTBM_WAYPOINT) { if(!f.getProps(nodeWaypoint, propStream)) { setLastErrorString("Could not read waypoint data."); return false; } std::string name; if(!propStream.GET_STRING(name)) { setLastErrorString("Could not read waypoint name."); return false; } OTBM_Destination_coords* waypoint_coords; if(!propStream.GET_STRUCT(waypoint_coords)) { setLastErrorString("Could not read waypoint coordinates."); return false; } map->waypoints.addWaypoint(WaypointPtr(new Waypoint(name, Position(waypoint_coords->_x, waypoint_coords->_y, waypoint_coords->_z)))); } else { setLastErrorString("Unknown waypoint node."); return false; } nodeWaypoint = f.getNextNode(nodeWaypoint, type); } } else { setLastErrorString("Unknown map node."); return false; } nodeMapData = f.getNextNode(nodeMapData, type); } return true; }
bool IOMap::loadMap(Map* map, const std::string& identifier) { int64_t start = OTSYS_TIME(); FileLoader f; if (!f.openFile(identifier.c_str(), "OTBM")) { std::ostringstream ss; ss << "Could not open the file " << identifier << '.'; setLastErrorString(ss.str()); return false; } uint32_t type; PropStream propStream; NODE root = f.getChildNode(nullptr, type); if (!f.getProps(root, propStream)) { setLastErrorString("Could not read root property."); return false; } const OTBM_root_header* root_header; if (!propStream.readStruct(root_header)) { setLastErrorString("Could not read header."); return false; } uint32_t headerVersion = root_header->version; if (headerVersion <= 0) { //In otbm version 1 the count variable after splashes/fluidcontainers and stackables //are saved as attributes instead, this solves alot of problems with items //that is changed (stackable/charges/fluidcontainer/splash) during an update. setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly."); return false; } if (headerVersion > 2) { setLastErrorString("Unknown OTBM version detected."); return false; } if (root_header->majorVersionItems < 3) { setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly."); return false; } if (root_header->majorVersionItems > Items::dwMajorVersion) { setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required."); return false; } if (root_header->minorVersionItems < CLIENT_VERSION_810) { setLastErrorString("This map needs to be updated."); return false; } if (root_header->minorVersionItems > Items::dwMinorVersion) { std::cout << "[Warning - IOMap::loadMap] This map needs an updated items.otb." << std::endl; } std::cout << "> Map size: " << root_header->width << "x" << root_header->height << '.' << std::endl; map->width = root_header->width; map->height = root_header->height; NODE nodeMap = f.getChildNode(root, type); if (type != OTBM_MAP_DATA) { setLastErrorString("Could not read data node."); return false; } if (!f.getProps(nodeMap, propStream)) { setLastErrorString("Could not read map data attributes."); return false; } std::string mapDescription; std::string tmp; uint8_t attribute; while (propStream.read<uint8_t>(attribute)) { switch (attribute) { case OTBM_ATTR_DESCRIPTION: if (!propStream.readString(mapDescription)) { setLastErrorString("Invalid description tag."); return false; } break; case OTBM_ATTR_EXT_SPAWN_FILE: if (!propStream.readString(tmp)) { setLastErrorString("Invalid spawn tag."); return false; } map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1); map->spawnfile += tmp; break; case OTBM_ATTR_EXT_HOUSE_FILE: if (!propStream.readString(tmp)) { setLastErrorString("Invalid house tag."); return false; } map->housefile = identifier.substr(0, identifier.rfind('/') + 1); map->housefile += tmp; break; default: setLastErrorString("Unknown header node."); return false; } } NODE nodeMapData = f.getChildNode(nodeMap, type); while (nodeMapData != NO_NODE) { if (f.getError() != ERROR_NONE) { setLastErrorString("Invalid map node."); return false; } if (type == OTBM_TILE_AREA) { if (!f.getProps(nodeMapData, propStream)) { setLastErrorString("Invalid map node."); return false; } const OTBM_Destination_coords* area_coord; if (!propStream.readStruct(area_coord)) { setLastErrorString("Invalid map node."); return false; } int32_t base_x = area_coord->x; int32_t base_y = area_coord->y; int32_t base_z = area_coord->z; NODE nodeTile = f.getChildNode(nodeMapData, type); while (nodeTile != NO_NODE) { if (f.getError() != ERROR_NONE) { setLastErrorString("Could not read node data."); return false; } if (type != OTBM_TILE && type != OTBM_HOUSETILE) { setLastErrorString("Unknown tile node."); return false; } if (!f.getProps(nodeTile, propStream)) { setLastErrorString("Could not read node data."); return false; } const OTBM_Tile_coords* tile_coord; if (!propStream.readStruct(tile_coord)) { setLastErrorString("Could not read tile position."); return false; } uint16_t px = base_x + tile_coord->x; uint16_t py = base_y + tile_coord->y; uint16_t pz = base_z; bool isHouseTile = false; House* house = nullptr; Tile* tile = nullptr; Item* ground_item = nullptr; uint32_t tileflags = TILESTATE_NONE; if (type == OTBM_HOUSETILE) { uint32_t houseId; if (!propStream.read<uint32_t>(houseId)) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not read house id."; setLastErrorString(ss.str()); return false; } house = map->houses.addHouse(houseId); if (!house) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not create house id: " << houseId; setLastErrorString(ss.str()); return false; } tile = new HouseTile(px, py, pz, house); house->addTile(reinterpret_cast<HouseTile*>(tile)); isHouseTile = true; } //read tile attributes while (propStream.read<uint8_t>(attribute)) { switch (attribute) { case OTBM_ATTR_TILE_FLAGS: { uint32_t flags; if (!propStream.read<uint32_t>(flags)) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to read tile flags."; setLastErrorString(ss.str()); return false; } if ((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) { tileflags |= TILESTATE_PROTECTIONZONE; } else if ((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE) { tileflags |= TILESTATE_NOPVPZONE; } else if ((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE) { tileflags |= TILESTATE_PVPZONE; } if ((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT) { tileflags |= TILESTATE_NOLOGOUT; } break; } case OTBM_ATTR_ITEM: { Item* item = Item::CreateItem(propStream); if (!item) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item."; setLastErrorString(ss.str()); return false; } if (isHouseTile && item->isMoveable()) { std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << px << ", y: " << py << ", z: " << pz << "]." << std::endl; delete item; } else { if (item->getItemCount() <= 0) { item->setItemCount(1); } if (tile) { tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } else if (item->isGroundTile()) { delete ground_item; ground_item = item; } else { tile = createTile(ground_item, item, px, py, pz); tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } } break; } default: std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown tile attribute."; setLastErrorString(ss.str()); return false; } } NODE nodeItem = f.getChildNode(nodeTile, type); while (nodeItem) { if (type != OTBM_ITEM) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown node type."; setLastErrorString(ss.str()); return false; } PropStream stream; if (!f.getProps(nodeItem, stream)) { setLastErrorString("Invalid item node."); return false; } Item* item = Item::CreateItem(stream); if (!item) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item."; setLastErrorString(ss.str()); return false; } if (!item->unserializeItemNode(f, nodeItem, stream)) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to load item " << item->getID() << '.'; setLastErrorString(ss.str()); delete item; return false; } if (isHouseTile && item->isMoveable()) { std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << px << ", y: " << py << ", z: " << pz << "]." << std::endl; delete item; } else { if (item->getItemCount() <= 0) { item->setItemCount(1); } if (tile) { tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } else if (item->isGroundTile()) { delete ground_item; ground_item = item; } else { tile = createTile(ground_item, item, px, py, pz); tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } } nodeItem = f.getNextNode(nodeItem, type); } if (!tile) { tile = createTile(ground_item, nullptr, px, py, pz); } tile->setFlag(static_cast<tileflags_t>(tileflags)); map->setTile(px, py, pz, tile); nodeTile = f.getNextNode(nodeTile, type); } } else if (type == OTBM_TOWNS) { NODE nodeTown = f.getChildNode(nodeMapData, type); while (nodeTown != NO_NODE) { if (type != OTBM_TOWN) { setLastErrorString("Unknown town node."); return false; } if (!f.getProps(nodeTown, propStream)) { setLastErrorString("Could not read town data."); return false; } uint32_t townId; if (!propStream.read<uint32_t>(townId)) { setLastErrorString("Could not read town id."); return false; } Town* town = map->towns.getTown(townId); if (!town) { town = new Town(townId); map->towns.addTown(townId, town); } std::string townName; if (!propStream.readString(townName)) { setLastErrorString("Could not read town name."); return false; } town->setName(townName); const OTBM_Destination_coords* town_coords; if (!propStream.readStruct(town_coords)) { setLastErrorString("Could not read town coordinates."); return false; } town->setTemplePos(Position(town_coords->x, town_coords->y, town_coords->z)); nodeTown = f.getNextNode(nodeTown, type); } } else if (type == OTBM_WAYPOINTS && headerVersion > 1) { NODE nodeWaypoint = f.getChildNode(nodeMapData, type); while (nodeWaypoint != NO_NODE) { if (type != OTBM_WAYPOINT) { setLastErrorString("Unknown waypoint node."); return false; } if (!f.getProps(nodeWaypoint, propStream)) { setLastErrorString("Could not read waypoint data."); return false; } std::string name; if (!propStream.readString(name)) { setLastErrorString("Could not read waypoint name."); return false; } const OTBM_Destination_coords* waypoint_coords; if (!propStream.readStruct(waypoint_coords)) { setLastErrorString("Could not read waypoint coordinates."); return false; } map->waypoints[name] = Position(waypoint_coords->x, waypoint_coords->y, waypoint_coords->z); nodeWaypoint = f.getNextNode(nodeWaypoint, type); } } else { setLastErrorString("Unknown map node."); return false; } nodeMapData = f.getNextNode(nodeMapData, type); } std::cout << "> Map loading time: " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl; return true; }
bool IOMapOTBM::loadMap(Map* map, const std::string& identifier) { int64_t start = OTSYS_TIME(); FileLoader f; if(!f.openFile(identifier.c_str(), "OTBM", false, true)){ std::stringstream ss; ss << "Could not open the file " << identifier << "."; setLastErrorString(ss.str()); return false; } unsigned long type; PropStream propStream; NODE root = f.getChildNode((NODE)NULL, type); if(!f.getProps(root, propStream)){ setLastErrorString("Could not read root property."); return false; } OTBM_root_header root_header; if( !propStream.GET_UINT32(root_header.version) || !propStream.GET_UINT16(root_header.width) || !propStream.GET_UINT16(root_header.height) || !propStream.GET_UINT32(root_header.majorVersionItems) || !propStream.GET_UINT32(root_header.minorVersionItems)) { setLastErrorString("Could not read header."); return false; } int header_version = root_header.version; if(header_version <= 0){ //In otbm version 1 the count variable after splashes/fluidcontainers and stackables //are saved as attributes instead, this solves alot of problems with items //that is changed (stackable/charges/fluidcontainer/splash) during an update. setLastErrorString("This map needs to be upgraded by using the latest map editor version to be able to load correctly."); return false; } if(header_version > 2){ setLastErrorString("Unknown OTBM version detected, please update your server."); return false; } if(root_header.majorVersionItems < 3){ setLastErrorString("This map needs to be upgraded by using the latest map editor version to be able to load correctly."); return false; } if(root_header.majorVersionItems > (unsigned long)Items::dwMajorVersion){ setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required."); return false; } // Prevent load maps saved with items.otb previous to // version 800, because of the change to stackable of // itemid 3965 if(root_header.minorVersionItems < CLIENT_VERSION_810){ setLastErrorString("This map needs to be updated."); return false; } if(root_header.minorVersionItems > (unsigned long)Items::dwMinorVersion){ std::cout << "Warning: [OTBM loader] This map needs an updated items.otb." <<std::endl; } if(root_header.minorVersionItems == CLIENT_VERSION_854_BAD){ std::cout << "Warning: [OTBM loader] This map needs uses an incorrect version of items.otb." <<std::endl; } std::cout << "Map size: " << root_header.width << "x" << root_header.height << std::endl; map->mapWidth = root_header.width; map->mapHeight = root_header.height; NODE nodeMap = f.getChildNode(root, type); if(type != OTBM_MAP_DATA){ setLastErrorString("Could not read data node."); return false; } if(!f.getProps(nodeMap, propStream)){ setLastErrorString("Could not read map data attributes."); return false; } unsigned char attribute; std::string mapDescription; std::string tmp; while(propStream.GET_UINT8(attribute)){ switch(attribute){ case OTBM_ATTR_DESCRIPTION: if(!propStream.GET_STRING(mapDescription)){ setLastErrorString("Invalid description tag."); return false; } std::cout << "Map description: " << mapDescription << std::endl; break; case OTBM_ATTR_EXT_SPAWN_FILE: if(!propStream.GET_STRING(tmp)){ setLastErrorString("Invalid spawn tag."); return false; } map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1); map->spawnfile += tmp; break; case OTBM_ATTR_EXT_HOUSE_FILE: if(!propStream.GET_STRING(tmp)){ setLastErrorString("Invalid house tag."); return false; } map->housefile = identifier.substr(0, identifier.rfind('/') + 1); map->housefile += tmp; break; default: setLastErrorString("Unknown header node."); return false; break; } } NODE nodeMapData = f.getChildNode(nodeMap, type); while(nodeMapData != NO_NODE){ if(f.getError() != ERROR_NONE){ setLastErrorString("Invalid map node."); return false; } if(type == OTBM_TILE_AREA){ if(!f.getProps(nodeMapData, propStream)){ setLastErrorString("Invalid map node."); return false; } OTBM_Tile_area_coords area_coord; if( !propStream.GET_UINT16(area_coord._x) || !propStream.GET_UINT16(area_coord._y) || !propStream.GET_UINT8(area_coord._z)) { setLastErrorString("Invalid map node."); return false; } int32_t base_x, base_y, base_z; base_x = area_coord._x; base_y = area_coord._y; base_z = area_coord._z; NODE nodeTile = f.getChildNode(nodeMapData, type); while(nodeTile != NO_NODE){ if(f.getError() != ERROR_NONE){ setLastErrorString("Could not read node data."); return false; } if(type == OTBM_TILE || type == OTBM_HOUSETILE){ if(!f.getProps(nodeTile, propStream)){ setLastErrorString("Could not read node data."); return false; } unsigned short px, py, pz; OTBM_Tile_coords tile_coord; if( !propStream.GET_UINT8(tile_coord._x) || !propStream.GET_UINT8(tile_coord._y)) { setLastErrorString("Could not read tile position."); return false; } px = base_x + tile_coord._x; py = base_y + tile_coord._y; pz = base_z; bool isHouseTile = false; House* house = NULL; Tile* tile = NULL; Item* ground_item = NULL; uint32_t tileflags = TILESTATE_NONE; if(type == OTBM_HOUSETILE){ uint32_t _houseid; if(!propStream.GET_UINT32(_houseid)){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Could not read house id."; setLastErrorString(ss.str()); return false; } house = Houses::getInstance().getHouse(_houseid, true); if(!house){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Could not create house id: " << _houseid; setLastErrorString(ss.str()); return false; } tile = new HouseTile(px, py, pz, house); house->addTile(static_cast<HouseTile*>(tile)); isHouseTile = true; } //read tile attributes unsigned char attribute; while(propStream.GET_UINT8(attribute)){ switch(attribute){ case OTBM_ATTR_TILE_FLAGS: { uint32_t flags; if(!propStream.GET_UINT32(flags)){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to read tile flags."; setLastErrorString(ss.str()); return false; } if((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE){ tileflags |= TILESTATE_PROTECTIONZONE; } else if((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE){ tileflags |= TILESTATE_NOPVPZONE; } else if((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE){ tileflags |= TILESTATE_PVPZONE; } if((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT){ tileflags |= TILESTATE_NOLOGOUT; } if((flags & TILESTATE_REFRESH) == TILESTATE_REFRESH){ if(house){ std::cout << "Warning [x:" << px << ", y:" << py << ", z:" << pz << "] " << " House tile flagged as refreshing!"; } tileflags |= TILESTATE_REFRESH; } break; } case OTBM_ATTR_ITEM: { Item* item = Item::CreateItem(propStream); if(!item){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to create item."; setLastErrorString(ss.str()); return false; } if(isHouseTile && !item->isNotMoveable()){ std::cout << "Warning: [OTBM loader] Moveable item in house id = " << house->getId() << " Item type = " << item->getID() << std::endl; delete item; item = NULL; } else{ if(tile){ tile->__internalAddThing(item); item->__startDecaying(); } else if(item->isGroundTile()){ if(ground_item) delete ground_item; ground_item = item; } else{ // !tile tile = createTile(ground_item, item, px, py, pz); tile->__internalAddThing(item); item->__startDecaying(); } } break; } default: std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Unknown tile attribute."; setLastErrorString(ss.str()); return false; break; } } NODE nodeItem = f.getChildNode(nodeTile, type); while(nodeItem){ if(type == OTBM_ITEM){ PropStream propStream; f.getProps(nodeItem, propStream); Item* item = Item::CreateItem(propStream); if(!item){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to create item."; setLastErrorString(ss.str()); return false; } if(item->unserializeItemNode(f, nodeItem, propStream)){ if(isHouseTile && !item->isNotMoveable()){ std::cout << "Warning: [OTBM loader] Moveable item in house id = " << house->getId() << " Item type = " << item->getID() << std::endl; delete item; } else{ if(tile){ tile->__internalAddThing(item); item->__startDecaying(); } else if(item->isGroundTile()){ if(ground_item) delete ground_item; ground_item = item; } else{ // !tile tile = createTile(ground_item, item, px, py, pz); tile->__internalAddThing(item); item->__startDecaying(); } } } else{ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to load item " << item->getID() << "."; setLastErrorString(ss.str()); delete item; return false; } } else{ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Unknown node type."; setLastErrorString(ss.str()); } nodeItem = f.getNextNode(nodeItem, type); } if(!tile) tile = createTile(ground_item, NULL, px, py, pz); tile->setFlag((tileflags_t)tileflags); map->setTile(px, py, pz, tile); } else{ setLastErrorString("Unknown tile node."); return false; } nodeTile = f.getNextNode(nodeTile, type); } } else if(type == OTBM_TOWNS){ NODE nodeTown = f.getChildNode(nodeMapData, type); while(nodeTown != NO_NODE){ if(type == OTBM_TOWN){ if(!f.getProps(nodeTown, propStream)){ setLastErrorString("Could not read town data."); return false; } uint32_t townid = 0; if(!propStream.GET_UINT32(townid)){ setLastErrorString("Could not read town id."); return false; } Town* town = Towns::getInstance().getTown(townid); if(!town){ town = new Town(townid); Towns::getInstance().addTown(townid, town); } std::string townName = ""; if(!propStream.GET_STRING(townName)){ setLastErrorString("Could not read town name."); return false; } town->setName(townName); OTBM_TownTemple_coords town_coords; if( !propStream.GET_UINT16(town_coords._x) || !propStream.GET_UINT16(town_coords._y) || !propStream.GET_UINT8(town_coords._z)) { setLastErrorString("Could not read town coordinates."); return false; } Position pos; pos.x = town_coords._x; pos.y = town_coords._y; pos.z = town_coords._z; town->setTemplePos(pos); } else{ setLastErrorString("Unknown town node."); return false; } nodeTown = f.getNextNode(nodeTown, type); } } else if(type == OTBM_WAYPOINTS && header_version >= 2){ NODE nodeWaypoint = f.getChildNode(nodeMapData, type); while(nodeWaypoint != NO_NODE){ if(type == OTBM_WAYPOINT){ if(!f.getProps(nodeWaypoint, propStream)){ setLastErrorString("Could not read waypoint data."); return false; } std::string name; Position pos; if(!propStream.GET_STRING(name)){ setLastErrorString("Could not read waypoint name."); return false; } OTBM_TownTemple_coords wp_coords; if( !propStream.GET_UINT16(wp_coords._x) || !propStream.GET_UINT16(wp_coords._y) || !propStream.GET_UINT8(wp_coords._z)) { setLastErrorString("Could not read waypoint coordinates."); return false; } pos.x = wp_coords._x; pos.y = wp_coords._y; pos.z = wp_coords._z; Waypoint_ptr wp(new Waypoint(name, pos)); map->waypoints.addWaypoint(wp); } else{ setLastErrorString("Unknown waypoint node."); return false; } nodeWaypoint = f.getNextNode(nodeWaypoint, type); } } else{ setLastErrorString("Unknown map node."); return false; } nodeMapData = f.getNextNode(nodeMapData, type); } std::cout << "Notice: [OTBM Loader] Loading time : " << (OTSYS_TIME() - start)/(1000.) << " s" << std::endl; return true; }
void Source::Impl::updateTiles(const UpdateParameters& parameters) { if (!loaded) { return; } const uint16_t tileSize = getTileSize(); const Range<uint8_t> zoomRange = getZoomRange(); // Determine the overzooming/underzooming amounts and required tiles. int32_t overscaledZoom = util::coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize); int32_t tileZoom = overscaledZoom; std::vector<UnwrappedTileID> idealTiles; if (overscaledZoom >= zoomRange.min) { int32_t idealZoom = std::min<int32_t>(zoomRange.max, overscaledZoom); // Make sure we're not reparsing overzoomed raster tiles. if (type == SourceType::Raster) { tileZoom = idealZoom; } idealTiles = util::tileCover(parameters.transformState, idealZoom); } // Stores a list of all the tiles that we're definitely going to retain. There are two // kinds of tiles we need: the ideal tiles determined by the tile cover. They may not yet be in // use because they're still loading. In addition to that, we also need to retain all tiles that // we're actively using, e.g. as a replacement for tile that aren't loaded yet. std::set<OverscaledTileID> retain; auto retainTileFn = [&retain](Tile& tile, Resource::Necessity necessity) -> void { retain.emplace(tile.id); tile.setNecessity(necessity); }; auto getTileFn = [this](const OverscaledTileID& tileID) -> Tile* { auto it = tiles.find(tileID); return it == tiles.end() ? nullptr : it->second.get(); }; auto createTileFn = [this, ¶meters](const OverscaledTileID& tileID) -> Tile* { std::unique_ptr<Tile> tile = cache.get(tileID); if (!tile) { tile = createTile(tileID, parameters); if (tile) { tile->setObserver(this); } } if (!tile) { return nullptr; } return tiles.emplace(tileID, std::move(tile)).first->second.get(); }; auto renderTileFn = [this](const UnwrappedTileID& tileID, Tile& tile) { renderTiles.emplace(tileID, RenderTile{ tileID, tile }); }; renderTiles.clear(); algorithm::updateRenderables(getTileFn, createTileFn, retainTileFn, renderTileFn, idealTiles, zoomRange, tileZoom); if (type != SourceType::Annotations && cache.getSize() == 0) { size_t conservativeCacheSize = std::max((float)parameters.transformState.getSize().width / util::tileSize, 1.0f) * std::max((float)parameters.transformState.getSize().height / util::tileSize, 1.0f) * (parameters.transformState.getMaxZoom() - parameters.transformState.getMinZoom() + 1) * 0.5; cache.setSize(conservativeCacheSize); } removeStaleTiles(retain); const PlacementConfig config { parameters.transformState.getAngle(), parameters.transformState.getPitch(), parameters.debugOptions & MapDebugOptions::Collision }; for (auto& pair : tiles) { pair.second->setPlacementConfig(config); } }
bool IOMap::parseTileArea(OTB::Loader& loader, const OTB::Node& tileAreaNode, Map& map) { PropStream propStream; if (!loader.getProps(tileAreaNode, propStream)) { setLastErrorString("Invalid map node."); return false; } OTBM_Destination_coords area_coord; if (!propStream.read(area_coord)) { setLastErrorString("Invalid map node."); return false; } uint16_t base_x = area_coord.x; uint16_t base_y = area_coord.y; uint16_t z = area_coord.z; for (auto& tileNode : tileAreaNode.children) { if (tileNode.type != OTBM_TILE && tileNode.type != OTBM_HOUSETILE) { setLastErrorString("Unknown tile node."); return false; } if (!loader.getProps(tileNode, propStream)) { setLastErrorString("Could not read node data."); return false; } OTBM_Tile_coords tile_coord; if (!propStream.read(tile_coord)) { setLastErrorString("Could not read tile position."); return false; } uint16_t x = base_x + tile_coord.x; uint16_t y = base_y + tile_coord.y; bool isHouseTile = false; House* house = nullptr; Tile* tile = nullptr; Item* ground_item = nullptr; uint32_t tileflags = TILESTATE_NONE; if (tileNode.type == OTBM_HOUSETILE) { uint32_t houseId; if (!propStream.read<uint32_t>(houseId)) { std::ostringstream ss; ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Could not read house id."; setLastErrorString(ss.str()); return false; } house = map.houses.addHouse(houseId); if (!house) { std::ostringstream ss; ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Could not create house id: " << houseId; setLastErrorString(ss.str()); return false; } tile = new HouseTile(x, y, z, house); house->addTile(static_cast<HouseTile*>(tile)); isHouseTile = true; } uint8_t attribute; //read tile attributes while (propStream.read<uint8_t>(attribute)) { switch (attribute) { case OTBM_ATTR_TILE_FLAGS: { uint32_t flags; if (!propStream.read<uint32_t>(flags)) { std::ostringstream ss; ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Failed to read tile flags."; setLastErrorString(ss.str()); return false; } if ((flags & OTBM_TILEFLAG_PROTECTIONZONE) != 0) { tileflags |= TILESTATE_PROTECTIONZONE; } else if ((flags & OTBM_TILEFLAG_NOPVPZONE) != 0) { tileflags |= TILESTATE_NOPVPZONE; } else if ((flags & OTBM_TILEFLAG_PVPZONE) != 0) { tileflags |= TILESTATE_PVPZONE; } if ((flags & OTBM_TILEFLAG_NOLOGOUT) != 0) { tileflags |= TILESTATE_NOLOGOUT; } break; } case OTBM_ATTR_ITEM: { Item* item = Item::CreateItem(propStream); if (!item) { std::ostringstream ss; ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Failed to create item."; setLastErrorString(ss.str()); return false; } if (isHouseTile && item->isMoveable()) { std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << x << ", y: " << y << ", z: " << z << "]." << std::endl; delete item; } else { if (item->getItemCount() <= 0) { item->setItemCount(1); } if (tile) { tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } else if (item->isGroundTile()) { delete ground_item; ground_item = item; } else { tile = createTile(ground_item, item, x, y, z); tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } } break; } default: std::ostringstream ss; ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Unknown tile attribute."; setLastErrorString(ss.str()); return false; } } for (auto& itemNode : tileNode.children) { if (itemNode.type != OTBM_ITEM) { std::ostringstream ss; ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Unknown node type."; setLastErrorString(ss.str()); return false; } PropStream stream; if (!loader.getProps(itemNode, stream)) { setLastErrorString("Invalid item node."); return false; } Item* item = Item::CreateItem(stream); if (!item) { std::ostringstream ss; ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Failed to create item."; setLastErrorString(ss.str()); return false; } if (!item->unserializeItemNode(loader, itemNode, stream)) { std::ostringstream ss; ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Failed to load item " << item->getID() << '.'; setLastErrorString(ss.str()); delete item; return false; } if (isHouseTile && item->isMoveable()) { std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << x << ", y: " << y << ", z: " << z << "]." << std::endl; delete item; } else { if (item->getItemCount() <= 0) { item->setItemCount(1); } if (tile) { tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } else if (item->isGroundTile()) { delete ground_item; ground_item = item; } else { tile = createTile(ground_item, item, x, y, z); tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } } } if (!tile) { tile = createTile(ground_item, nullptr, x, y, z); } tile->setFlag(static_cast<tileflags_t>(tileflags)); map.setTile(x, y, z, tile); } return true; }
void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom, const CCOcclusionTracker* occlusion) { createTextureUpdaterIfNeeded(); // Create tiles as needed, expanding a dirty rect to contain all // the dirty regions currently being drawn. All dirty tiles that are to be painted // get their m_updateRect set to m_dirtyRect and m_dirtyRect cleared. This way if // invalidateRect is invoked during prepareToUpdate we don't lose the request. IntRect dirtyLayerRect; for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); // When not idle painting, if the visible region of the tile is occluded, don't reserve a texture or mark it for update. // If any part of the tile is visible, then we need to paint it so the tile is pushed to the impl thread. // This will also avoid painting the tile in the next loop, below. if (!idle && occlusion) { IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j), visibleLayerRect()); if (occlusion->occluded(this, visibleTileRect)) continue; } // FIXME: Decide if partial update should be allowed based on cost // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost() && layerTreeHost()->requestPartialTextureUpdate()) tile->m_partialUpdate = true; else if (tileNeedsBufferedUpdate(tile) && layerTreeHost()) layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal()); if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) { // Sets the dirty rect to a full-sized tile with border texels. tile->m_dirtyRect = m_tiler->tileRect(tile); } if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) { m_skipsIdlePaint = true; if (!idle) { // If the background covers the viewport, always draw this // layer so that checkerboarded tiles will still draw. if (!backgroundCoversViewport()) m_skipsDraw = true; m_tiler->reset(); m_paintRect = IntRect(); m_requestedUpdateTilesRect = IntRect(); } return; } dirtyLayerRect.unite(tile->m_dirtyRect); tile->copyAndClearDirty(); } } m_paintRect = dirtyLayerRect; if (dirtyLayerRect.isEmpty()) return; // Due to borders, when the paint rect is extended to tile boundaries, it // may end up overlapping more tiles than the original content rect. Record // the original tiles so we don't upload more tiles than necessary. if (!m_paintRect.isEmpty()) m_requestedUpdateTilesRect = IntRect(left, top, right - left + 1, bottom - top + 1); // Calling prepareToUpdate() calls into WebKit to paint, which may have the side // effect of disabling compositing, which causes our reference to the texture updater to be deleted. // However, we can't free the memory backing the GraphicsContext until the paint finishes, // so we grab a local reference here to hold the updater alive until the paint completes. RefPtr<LayerTextureUpdater> protector(textureUpdater()); IntRect paintedOpaqueRect; textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels(), contentsScale(), &paintedOpaqueRect); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); // Tiles are created before prepareToUpdate() is called. if (!tile) CRASH(); IntRect tileRect = m_tiler->tileBounds(i, j); // Use m_updateRect as copyAndClearDirty above moved the existing dirty rect to m_updateRect if the tile isn't culled. const IntRect& dirtyRect = tile->m_updateRect; if (dirtyRect.isEmpty()) continue; // Save what was painted opaque in the tile. Keep the old area if the paint didn't touch it, and didn't paint some // other part of the tile opaque. IntRect tilePaintedRect = intersection(tileRect, m_paintRect); IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaqueRect); if (!tilePaintedRect.isEmpty()) { IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRect(), tilePaintedRect); bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRect.contains(paintInsideTileOpaqueRect); bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect.isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect); if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInsideTileOpaqueRect) tile->setOpaqueRect(tilePaintedOpaqueRect); } // sourceRect starts as a full-sized tile with border texels included. IntRect sourceRect = m_tiler->tileRect(tile); sourceRect.intersect(dirtyRect); // Paint rect not guaranteed to line up on tile boundaries, so // make sure that sourceRect doesn't extend outside of it. sourceRect.intersect(m_paintRect); tile->m_updateRect = sourceRect; if (sourceRect.isEmpty()) continue; tile->texture()->prepareRect(sourceRect); } } }
bool VectorDataCache::load(const VectorTileIdentity &p) { if (!_inited) _init(); if(!_style) { return false; } AmigoApplicationData &appData = AmigoApplication::instance().getData(); auto project = appData.getUser().projects.findProject(_projectId); if(!project) { return false; } std::shared_ptr<APIv1::Dataset> ds = std::dynamic_pointer_cast<APIv1::Dataset>(project->datasets.findDataset(_datasetId)); if(!ds) { return false; } Globe::instance()->enableSpinner(true); APIv1::Generalization *gen = NULL; if(ds->generalize) gen = ds->generalizations.findGeneralization(p.level); auto tile = std::make_shared<VectorTile>(p, _projectId, _datasetId); bool tileCreated = true; for(auto sd : _style->getData()) { if(!sd) continue; // Check level if(p.level < sd->zoom_level_min || p.level > sd->zoom_level_max) continue; // For text tile skip non label styles if(p._textTile && sd->type != StyleData::LABEL) { continue; } if(!p._textTile && sd->type == StyleData::LABEL) { continue; } std::vector<geos::geom::Geometry*> geoms; std::vector<GeoLabel> labels; Timestamp t2; _getGeometries(p, gen, project, ds, geoms, labels, sd); Timestamp t3; tileCreated = createTile(tile, p, geoms, labels, sd) && tileCreated; Timestamp t4; for(int i=0; i<geoms.size(); i++) { delete geoms[i]; } } if(tileCreated) { if(tile->getSize() < MAX_VERTEX_CACHE_SIZE) { _cache.putWithSize(p, tile, tile->getSize()); } else { AMIGO_LOG_W(TAG, "::createTile() Geometries is too big to render: %d vertises\n", tile->getSize()); } } Globe::instance()->enableSpinner(false); return true; }
void MapManager::loadMap(char *file) { cout << "Opening map: " << file << endl; objective = false; ifstream map (file); if(map.is_open()) { int y = 0; while(!map.eof()) { string line; getline(map, line); if(y<ConstManager::getInt("map_size")) { // Read in map tile information for(int x=0;x<ConstManager::getInt("map_size");x++) { std::vector<int> connections = std::vector<int>(); int chosenPiece; if(line[x]=='.') { mts[x][y] = new MapTile(); } else if(line[x]=='|') { connections.push_back(1); connections.push_back(3); chosenPiece = pieceChoices->getNextChoice(); sort(connections.begin(),connections.end()); // Sort to make sure nto the wrong way around createTile("strai/",connections,x,y,chosenPiece); } else if(line[x]=='-') { connections.push_back(2); connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("strai/",connections,x,y,chosenPiece); } else if(line[x]=='l') { connections.push_back(1); connections.push_back(2); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='r') { connections.push_back(2); connections.push_back(3); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='<') { connections.push_back(3); connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='j') { connections.push_back(1); connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='t') { connections.push_back(1); connections.push_back(2); connections.push_back(3); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='=') { connections.push_back(1); connections.push_back(3); connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='+') { connections.push_back(1); connections.push_back(2); connections.push_back(3); connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='/') { connections.push_back(1); connections.push_back(2); connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='\\') { connections.push_back(2); connections.push_back(3); connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("junct/",connections,x,y,chosenPiece); } else if(line[x]=='1') { connections.push_back(1); chosenPiece = pieceChoices->getNextChoice(); createTile("ends/",connections,x,y,chosenPiece); } else if(line[x]=='2') { connections.push_back(2); chosenPiece = pieceChoices->getNextChoice(); createTile("ends/",connections,x,y,chosenPiece); } else if(line[x]=='3') { connections.push_back(3); chosenPiece = pieceChoices->getNextChoice(); createTile("ends/",connections,x,y,chosenPiece); } else if(line[x]=='4') { connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("ends/",connections,x,y,chosenPiece); } else if(line[x]=='0') { objx=x; objy=y; connections.push_back(1); connections.push_back(2); connections.push_back(3); connections.push_back(4); chosenPiece = pieceChoices->getNextChoice(); createTile("objec/",connections,x,y,chosenPiece); } else if(line[x]=='S') { connections.push_back(2); chosenPiece = pieceChoices->getNextChoice(); createTile("start/",connections,x,y,chosenPiece); } } } else { // Read in waypoint information if((line[0]=='w')&&(line[1]=='p')) { istringstream liness(line); int x; int y; string temp; string rubbish; liness >> rubbish; liness >> x; liness >> y; liness >> temp; string *name = new string(temp); cout << x << " " << y << " " << name << endl; Waypoint *w = new Waypoint(name,x,y); waypoints.push_back(w); mts[x][y]->assignWaypoint(w); if(*w->getName()=="wp_start") { startx = x; starty = y; mts[x][y]->setStart(); } if(*w->getName()=="wp_end") { mts[x][y]->setEnd(); } } } y++; }
void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom) { // Reset m_updateRect for all tiles. for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); tile->m_updateRect = IntRect(); } // Create tiles as needed, expanding a dirty rect to contain all // the dirty regions currently being drawn. All dirty tiles that are to be painted // get their m_updateRect set to m_dirtyRect and m_dirtyRect cleared. This way if // invalidateRect is invoked during prepareToUpdate we don't lose the request. IntRect dirtyLayerRect; for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); if (!tile) tile = createTile(i, j); // Do post commit deletion of current texture when partial texture // updates are not used. if (tile->isDirty() && layerTreeHost() && !layerTreeHost()->settings().partialTextureUpdates) layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal()); if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) tile->m_dirtyRect = m_tiler->tileRect(tile); if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat)) { m_skipsIdlePaint = true; if (!idle) { m_skipsDraw = true; cleanupResources(); } return; } dirtyLayerRect.unite(tile->m_dirtyRect); tile->copyAndClearDirty(); } } m_paintRect = dirtyLayerRect; if (dirtyLayerRect.isEmpty()) return; // Due to borders, when the paint rect is extended to tile boundaries, it // may end up overlapping more tiles than the original content rect. Record // the original tiles so we don't upload more tiles than necessary. if (!m_paintRect.isEmpty()) m_requestedUpdateTilesRect = IntRect(left, top, right - left + 1, bottom - top + 1); // Calling prepareToUpdate() calls into WebKit to paint, which may have the side // effect of disabling compositing, which causes our reference to the texture updater to be deleted. // However, we can't free the memory backing the GraphicsContext until the paint finishes, // so we grab a local reference here to hold the updater alive until the paint completes. RefPtr<LayerTextureUpdater> protector(textureUpdater()); IntRect opaqueRect; // FIXME: unused. remove this and store in the layer to pass to impl for draw culling textureUpdater()->prepareToUpdate(m_paintRect, m_tiler->tileSize(), m_tiler->hasBorderTexels(), contentsScale(), &opaqueRect); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); // Tiles are created before prepareToUpdate() is called. if (!tile) CRASH(); // Use m_updateRect as copyAndClearDirty above moved the existing dirty rect to m_updateRect. const IntRect& dirtyRect = tile->m_updateRect; if (dirtyRect.isEmpty()) continue; IntRect sourceRect = m_tiler->tileRect(tile); sourceRect.intersect(dirtyRect); // Paint rect not guaranteed to line up on tile boundaries, so // make sure that sourceRect doesn't extend outside of it. sourceRect.intersect(m_paintRect); tile->m_updateRect = sourceRect; if (sourceRect.isEmpty()) continue; tile->texture()->prepareRect(sourceRect); } } }
void LayerTreeHostProxy::syncRemoteContent() { // We enqueue messages and execute them during paint, as they require an active GL context. ensureRootLayer(); while (OwnPtr<LayerTreeMessageToRenderer> nextMessage = m_messagesToRenderer.tryGetMessage()) { switch (nextMessage->type()) { case LayerTreeMessageToRenderer::SetRootLayer: { const SetRootLayerMessageData& data = static_cast<SetRootLayerMessage*>(nextMessage.get())->data(); setRootLayerID(data.layerID); break; } case LayerTreeMessageToRenderer::DeleteLayer: { const DeleteLayerMessageData& data = static_cast<DeleteLayerMessage*>(nextMessage.get())->data(); deleteLayer(data.layerID); break; } case LayerTreeMessageToRenderer::SyncLayerParameters: { const SyncLayerParametersMessageData& data = static_cast<SyncLayerParametersMessage*>(nextMessage.get())->data(); syncLayerParameters(data.layerInfo); break; } case LayerTreeMessageToRenderer::CreateTile: { const CreateTileMessageData& data = static_cast<CreateTileMessage*>(nextMessage.get())->data(); createTile(data.layerID, data.remoteTileID, data.scale); break; } case LayerTreeMessageToRenderer::RemoveTile: { const RemoveTileMessageData& data = static_cast<RemoveTileMessage*>(nextMessage.get())->data(); removeTile(data.layerID, data.remoteTileID); break; } case LayerTreeMessageToRenderer::UpdateTile: { const UpdateTileMessageData& data = static_cast<UpdateTileMessage*>(nextMessage.get())->data(); updateTile(data.layerID, data.remoteTileID, data.sourceRect, data.targetRect, data.image); break; } case LayerTreeMessageToRenderer::CreateImage: { const CreateImageMessageData& data = static_cast<CreateImageMessage*>(nextMessage.get())->data(); createImage(data.imageID, data.image); break; } case LayerTreeMessageToRenderer::DestroyImage: { const CreateImageMessageData& data = static_cast<CreateImageMessage*>(nextMessage.get())->data(); destroyImage(data.imageID); break; } case LayerTreeMessageToRenderer::FlushLayerChanges: flushLayerChanges(); break; } } }
bool Terrain::createTerrain() { if(mMainViewport == NULL) mMainViewport = Core::getSingleton().mCamera->getViewport(); Ogre::CompositorManager::getSingleton().addCompositor(mMainViewport, "DemoCompositor"); Ogre::CompositorManager::getSingleton().setCompositorEnabled(mMainViewport, "DemoCompositor", true); mMapData = MapDataManager::getSingletonPtr(); DataLibrary* datalib = DataLibrary::getSingletonPtr(); int terrainszie = mMapData->getMapSize() + 2 * MAPBOLDER + 1; Core::getSingleton().mSceneMgr->setSkyBox(true, "SkyBox",200); Ogre::GpuSharedParametersPtr sharedparams = Ogre::GpuProgramManager::getSingleton().getSharedParameters("TestSharedParamsName"); float border = mMapData->getMapSize() * 12.0f; sharedparams->setNamedConstant("border", border); //创建灯光 Core::getSingleton().mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f)); mLight = Core::getSingleton().mSceneMgr->createLight("TerrainLight"); mLight->setType(Ogre::Light::LT_DIRECTIONAL); mLight->setPosition(-500.0f,500.0f, 500.0f); mLight->setDirection(1.0f, -1.0f, -1.0f); mLight->setDiffuseColour(Ogre::ColourValue(0.5f, 0.5f,0.5f)); mLight->setSpecularColour(Ogre::ColourValue(0.8f, 0.8f,0.8f)); //设置深度图投影 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName("shadowdepthmap"); if(tex.isNull()) tex = Ogre::TextureManager::getSingleton().createManual("shadowdepthmap", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 2048, 2048, 0, Ogre::PF_FLOAT16_R, Ogre::TU_RENDERTARGET); mShadowDepthMapTarget = tex->getBuffer()->getRenderTarget(); Ogre::Viewport* vp = mShadowDepthMapTarget->addViewport(CameraContral::getSingleton().getShadowMapCamera()); vp->setSkiesEnabled(false); vp->setOverlaysEnabled(false); vp->setVisibilityMask(VISMASK_OPAQUE); vp->setMaterialScheme("WriteDepthMap"); vp->setBackgroundColour(Ogre::ColourValue(1.0f,1.0f,1.0f)); mShadowDepthMapTarget->addListener(this); //弱爆了…… Ogre::MaterialPtr mat; mat = Ogre::MaterialManager::getSingleton().getByName("TerrainTile"); Ogre::AliasTextureNamePairList texAliasList; std::string texname; datalib->getData("GameData/BattleData/MapData/Ground/G0Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); datalib->getData("GameData/BattleData/MapData/Ground/G1Tex",texname); texAliasList.insert(std::make_pair("Diffuse1",texname)); datalib->getData("GameData/BattleData/MapData/Ground/G2Tex",texname); texAliasList.insert(std::make_pair("Diffuse2",texname)); datalib->getData("GameData/BattleData/MapData/Ground/G3Tex",texname); texAliasList.insert(std::make_pair("Diffuse3",texname)); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("CliffMat1"); datalib->getData("GameData/BattleData/MapData/Ground/G0Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("CliffMat2"); datalib->getData("GameData/BattleData/MapData/Ground/G1Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("CliffMat3"); datalib->getData("GameData/BattleData/MapData/Ground/G2Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("CliffMat4"); datalib->getData("GameData/BattleData/MapData/Ground/G3Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("BankMat1"); datalib->getData("GameData/BattleData/MapData/Ground/G0Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("BankMat2"); datalib->getData("GameData/BattleData/MapData/Ground/G1Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("BankMat3"); datalib->getData("GameData/BattleData/MapData/Ground/G2Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("BankMat4"); datalib->getData("GameData/BattleData/MapData/Ground/G3Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); //创建地面Mesh mTerrainNode = Core::getSingleton().mSceneMgr->getRootSceneNode()->createChildSceneNode("TerrainNode"); int numVertices = terrainszie * terrainszie * VERTEX_QUAD; int numIndex = terrainszie * terrainszie * VERTEX_PREQUAD; Ogre::MeshPtr mTerrainMesh = Ogre::MeshManager::getSingleton().createManual("TerrianMesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); Ogre::SubMesh* subMesh = mTerrainMesh->createSubMesh(); subMesh->useSharedVertices=false; subMesh->setMaterialName("TerrainTile"); // 创建顶点数据结构 subMesh->vertexData = new Ogre::VertexData(); subMesh->vertexData->vertexStart = 0; subMesh->vertexData->vertexCount = numVertices; //顶点声明与缓冲区绑定 Ogre::VertexDeclaration* vdecl = subMesh->vertexData->vertexDeclaration; Ogre::VertexBufferBinding* vbind = subMesh->vertexData->vertexBufferBinding; //设置顶点数据结构 size_t offsetUV = 0; vdecl->addElement(VERTEX_POS_BINDING, 0, Ogre::VET_FLOAT3,Ogre::VES_POSITION);//向顶点添加一个位置元素 vdecl->addElement(VERTEX_NOM_BINDING, 0, Ogre::VET_FLOAT3,Ogre::VES_NORMAL); for(int i = 0 ; i < TEXTURE_COUNT ; i ++) { offsetUV += vdecl->addElement (VERTEX_UV_BINDING, offsetUV, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES , i).getSize(); } // 创建世界坐标顶点缓冲区 Ogre::HardwareVertexBufferSharedPtr vbufPos = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vdecl->getVertexSize(VERTEX_POS_BINDING), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); vbind->setBinding(VERTEX_POS_BINDING, vbufPos); Ogre::HardwareVertexBufferSharedPtr vbufNOM = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vdecl->getVertexSize(VERTEX_NOM_BINDING), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); vbind->setBinding(VERTEX_NOM_BINDING, vbufNOM); // 创建纹理坐标顶点缓冲区 Ogre::HardwareVertexBufferSharedPtr vbufUV = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vdecl->getVertexSize(VERTEX_UV_BINDING), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); vbind->setBinding(VERTEX_UV_BINDING, vbufUV); // 创建索引缓冲区 Ogre::HardwareIndexBufferSharedPtr indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT , numIndex, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); //创建地形 float* pBufferPos = (float*)vbufPos->lock(Ogre::HardwareBuffer::HBL_DISCARD); float* pBufferUV = (float*)vbufUV->lock(Ogre::HardwareBuffer::HBL_DISCARD); float* pBufferNom = (float*)vbufNOM->lock(Ogre::HardwareBuffer::HBL_DISCARD); float startpos = - terrainszie * TILESIZE / 2; for(int y = 0 ; y < terrainszie; y ++) { for(int x = 0 ; x < terrainszie; x ++) { createTile(x, y, startpos + x * TILESIZE, startpos + y * TILESIZE, pBufferPos, pBufferUV, pBufferNom); pBufferPos += 3 * VERTEX_QUAD ; pBufferNom += 3 * VERTEX_QUAD ; pBufferUV += 2 * VERTEX_QUAD * 4; } } vbufNOM->unlock(); vbufUV->unlock(); vbufPos->unlock(); //写入索引信息 // 锁定索引缓冲区 Ogre::ushort* pIdx = (Ogre::ushort*)indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); for(int y = 0 ; y < terrainszie ; y ++) { for(int x = 0 ; x < terrainszie ; x ++) { Ogre::ushort iIndexTopLeft = (x + y * terrainszie) * VERTEX_QUAD; Ogre::ushort iIndexTopRight = iIndexTopLeft + 1; Ogre::ushort iIndexBottomLeft = iIndexTopLeft + 2; Ogre::ushort iIndexBottomRight = iIndexTopLeft + 3; *pIdx++ = iIndexBottomLeft; *pIdx++ = iIndexBottomRight; *pIdx++ = iIndexTopLeft; *pIdx++ = iIndexBottomRight; *pIdx++ = iIndexTopRight; *pIdx++ = iIndexTopLeft; } } indexBuffer->unlock(); //设置模型的的索引数据 subMesh->indexData->indexBuffer = indexBuffer; subMesh->indexData->indexStart = 0; subMesh->indexData->indexCount =numIndex; Ogre::AxisAlignedBox meshBounds(startpos,0,startpos, -startpos,5,-startpos); mTerrainMesh->_setBounds(meshBounds); mTerrainEntity = Core::getSingleton().mSceneMgr->createEntity("TerrianMesh"); mTerrainNode->attachObject(mTerrainEntity); mTerrainEntity->setQueryFlags(QUERYMASK_TERRAIN); mTerrainNode->setPosition(0,0,0); //创建水面 tex = Ogre::TextureManager::getSingleton().getByName("reflection"); if(tex.isNull()) tex = Ogre::TextureManager::getSingleton().createManual("reflection", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); mReflectionTarget = tex->getBuffer()->getRenderTarget(); mReflectionTarget->addViewport(Core::getSingleton().mCamera)->setOverlaysEnabled(false); mReflectionTarget->addListener(this); // mat = Ogre::MaterialManager::getSingleton().getByName("ReflectionWater"); // tech = mat->getTechnique(0); // pass = tech->getPass(0); // tu = pass->getTextureUnitState(1); // tu->setTextureName(tex->getName()); mWaterPlane = Ogre::Plane(Ogre::Vector3::UNIT_Y, WATERHEIGHT); mWaterNode = Core::getSingleton().mSceneMgr->getRootSceneNode()->createChildSceneNode("WaterNode"); mWaterObject = Core::getSingleton().mSceneMgr->createManualObject("WaterObject"); mWaterObject->begin("DemoWater",Ogre::RenderOperation::OT_TRIANGLE_LIST); startpos += TILESIZE/2; for(int y = 0; y < terrainszie; y++) for(int x = 0; x < terrainszie; x++) { if(mMapData->getTerrainType(x -MAPBOLDER, y -MAPBOLDER ) == Water) { mWaterObject->position(startpos + x * TILESIZE, 0.0f, startpos + y * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(0.0f,0.0f); mWaterObject->position(startpos + (x+1) * TILESIZE, 0.0f, startpos + (y+1) * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(1.0f,1.0f); mWaterObject->position(startpos + (x+1) * TILESIZE, 0.0f, startpos + y * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(1.0f,0.0f); mWaterObject->position(startpos + (x+1) * TILESIZE, 0.0f, startpos + (y+1) * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(1.0f,1.0f); mWaterObject->position(startpos + x * TILESIZE, 0.0f, startpos + y * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(0.0f,0.0f); mWaterObject->position(startpos + x * TILESIZE, 0.0f, startpos + (y+1) * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(0.0f,1.0f); } } mWaterObject->end(); mWaterNode->attachObject(mWaterObject); mWaterNode->setPosition(0,WATERHEIGHT,0); //设置摄像机移动范围 float minx = 0.0f;// = ( - (float)(terrainszie - 2 * MAPBOLDER) / 2.0f - 1.0f) * TILESIZE ; getWorldCoords(0,0,minx,minx); minx -= TILESIZE/2; CameraContral::getSingleton().setMoveRect(minx, minx); CameraContral::getSingleton().resetCamera(); //深度投影测试 // Ogre::MeshManager::getSingleton().createPlane("testplane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, // mWaterPlane, 64, 64, 1, 1, true, 1, 1, 1, Ogre::Vector3::UNIT_Z); // Ogre::Entity* testent = Core::getSingleton().mSceneMgr->createEntity("testplaneent", "testplane"); // testent->setMaterialName("DepthTest"); // Ogre::SceneNode* testnode = Core::getSingleton().mSceneMgr->getRootSceneNode()->createChildSceneNode(); // testnode->attachObject(testent); // testnode->setPosition(0.0f,10.0f,0.0f); return true; }