float CPUElevationProducer::getHeight(ptr<TileProducer> producer, int level, float x, float y) { float levelTileSize = producer->getRootQuadSize() / (1 << level); float s = producer->getRootQuadSize() / 2.0f; if (x <= -s || x >= s || y <= -s || y >= s) { return 0; } x += s; y += s; int tx = (int) floor(x / levelTileSize); int ty = (int) floor(y / levelTileSize); int tileWidth = producer->getCache()->getStorage()->getTileSize(); int tileSize = tileWidth - 5; TileCache::Tile *t = producer->findTile(level, tx, ty);; if (t == NULL) { if (Logger::INFO_LOGGER != NULL) { Logger::INFO_LOGGER->logf("DEM", "Missing CPUElevation tile [%d:%d:%d] (coord %f:%f)", level, tx, ty, x, y); } return 0; } assert(t != NULL); CPUTileStorage<float>::CPUSlot *slot = dynamic_cast<CPUTileStorage<float>::CPUSlot*>(t->getData()); assert(slot != NULL); float *tile = slot->data; x = 2.0f + (fmod(x, levelTileSize) / levelTileSize) * tileSize; y = 2.0f + (fmod(y, levelTileSize) / levelTileSize) * tileSize; int sx = (int) floor(x); int sy = (int) floor(y); return tile[sx + sy * tileWidth]; }
virtual bool doCreateTile(int level, int tx, int ty, TileStorage::Slot *data) { if (Logger::DEBUG_LOGGER != NULL) { ostringstream oss; oss << "Contour tile " << getId() << " " << level << " " << tx << " " << ty; Logger::DEBUG_LOGGER->log("ORTHO", oss.str()); } GPUTileStorage::GPUSlot *gpuData = dynamic_cast<GPUTileStorage::GPUSlot*>(data); assert(gpuData != NULL); // don't forget this! getCache()->getStorage().cast<GPUTileStorage> ()->notifyChange(gpuData); int tileWidth = data->getOwner()->getTileSize(); ptr<Texture> storage = getCache()->getStorage().cast<GPUTileStorage>()->getTexture(0); TileCache::Tile *t = elevationTiles->findTile(level, tx, ty); assert(t != NULL); GPUTileStorage::GPUSlot *elevationGpuData = dynamic_cast<GPUTileStorage::GPUSlot*>(t->getData()); assert(elevationGpuData != NULL); int zTileWidth = elevationGpuData->getWidth(); float scale = ((zTileWidth - 5.0) / zTileWidth) * (tileWidth / (tileWidth - 4.0)); float offset = (1.0 - scale) / 2.0; elevationSamplerU->set(elevationGpuData->t); elevationOSLU->set(vec4f(offset, offset, scale, elevationGpuData->l)); frameBuffer->drawQuad(contourProgram); gpuData->copyPixels(frameBuffer, 0, 0, tileWidth, tileWidth); return true; }
bool ForestOrthoLayer::doCreateTile(int level, int tx, int ty, TileStorage::Slot *data) { if (Logger::DEBUG_LOGGER != NULL) { ostringstream oss; oss << "OrthoForest tile " << getProducerId() << " " << level << " " << tx << " " << ty; Logger::DEBUG_LOGGER->log("ORTHO", oss.str()); } if (level >= displayLevel) { ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer(); TileCache::Tile * t = graphProducer->findTile(level, tx, ty); assert(t != NULL); ObjectTileStorage::ObjectSlot *graphData = dynamic_cast<ObjectTileStorage::ObjectSlot*>(t->getData()); GraphPtr g = graphData->data.cast<Graph>(); if (g != NULL) { vec3d q = getTileCoords(level, tx, ty); float scale = 2.0f * (1.0f - getTileBorder() * 2.0f / getTileSize()) / q.z; vec3d tileOffset = vec3d(q.x + q.z / 2.0f, q.y + q.z / 2.0f, scale); //offsetU->set(vec3f(q.x + q.z / 2.0f, q.y + q.z / 2.0f, scale)); offsetU->set(vec3f(0.0, 0.0, 1.0)); colorU->set(vec4f(color.x, color.y, color.z, color.w)); mesh->setMode(TRIANGLES); mesh->clear(); ptr<Graph::AreaIterator> ai = g->getAreas(); while (ai->hasNext()) { AreaPtr a = ai->next(); tess->beginPolygon(mesh); drawArea(tileOffset, a, *tess); tess->endPolygon(); } fb->draw(layerProgram, *mesh); } else { if (Logger::DEBUG_LOGGER != NULL) { ostringstream oss; oss << "NULL Graph : " << level << " " << tx << " " << ty; Logger::DEBUG_LOGGER->log("GRAPH", oss.str()); } } } return true; }
bool OrthoGPUProducer::doCreateTile(int level, int tx, int ty, TileStorage::Slot *data) { if (Logger::DEBUG_LOGGER != NULL) { ostringstream oss; oss << "GPU tile " << getId() << " " << level << " " << tx << " " << ty; Logger::DEBUG_LOGGER->log("ORTHO", oss.str()); } GPUTileStorage::GPUSlot *gpuData = dynamic_cast<GPUTileStorage::GPUSlot*> (data); assert(gpuData != NULL); getCache()->getStorage().cast<GPUTileStorage> ()->notifyChange(gpuData); CPUTileStorage<unsigned char>::CPUSlot *cpuData = NULL; TileCache::Tile* coarseTile = NULL; GPUTileStorage::GPUSlot *coarseGpuData = NULL; if (orthoTiles != NULL) { if (hasLayers() && !orthoTiles->hasTile(level, tx, ty)) { int l = level; int x = tx; int y = ty; while (!coarseGpuTiles->hasTile(l, x, y)) { l -= 1; x /= 2; y /= 2; } coarseTile = coarseGpuTiles->findTile(l, x, y); assert(coarseTile != NULL); coarseGpuData = dynamic_cast<GPUTileStorage::GPUSlot*>(coarseTile->getData()); assert(coarseGpuData != NULL); } else { TileCache::Tile *t = orthoTiles->findTile(level, tx, ty); assert(t != NULL); cpuData = dynamic_cast<CPUTileStorage<unsigned char>::CPUSlot*>(t->getData()); assert(cpuData != NULL); } } TextureFormat f; switch (channels) { case 1: f = RED; break; case 2: f = RG; break; case 3: f = RGB; break; default: f = RGBA; break; } if (compressedTexture == NULL && !hasLayers()) { assert(cpuData != NULL); if (channels != 2 || tileSize%2 == 0) { gpuData->setSubImage(0, 0, tileSize, tileSize, f, UNSIGNED_BYTE, Buffer::Parameters(), CPUBuffer(cpuData->data)); } else { // TODO better way to fix this "OpenGL bug" (?) with odd texture sizes? unsigned char *tmp = new unsigned char[tileSize*tileSize*4]; for (int i = 0; i < tileSize*tileSize; ++i) { tmp[4*i] = cpuData->data[2*i]; tmp[4*i+1] = cpuData->data[2*i+1]; tmp[4*i+2] = 0; tmp[4*i+3] = 0; } gpuData->setSubImage(0, 0, tileSize, tileSize, RGBA, UNSIGNED_BYTE, Buffer::Parameters(), CPUBuffer(tmp)); delete[] tmp; } } else { if (cpuData != NULL) { if (compressedTexture != NULL) { compressedTexture->setCompressedSubImage(0, 0, 0, tileSize, tileSize, cpuData->size, CPUBuffer(cpuData->data)); uncompressSourceU->set(compressedTexture); frameBuffer->drawQuad(uncompress); } else { uncompressedTexture->setSubImage(0, 0, 0, tileSize, tileSize, f, UNSIGNED_BYTE, Buffer::Parameters(), CPUBuffer(cpuData->data)); } } if (coarseGpuData != NULL) { vec4f coords = coarseGpuTiles->getGpuTileCoords(level, tx, ty, &coarseTile); float b = float(getBorder()) / (1 << (level - coarseTile->level)); float s = (float) getCache()->getStorage()->getTileSize(); float S = s / (s - 2 * getBorder()); coords.x -= b / coarseGpuData->getWidth(); coords.y -= b / coarseGpuData->getHeight(); coords.w *= S; upsampleSourceU->set(coarseGpuData->t); tileU->set(coords); frameBuffer->drawQuad(upsample); } if (hasLayers()) { TileProducer::doCreateTile(level, tx, ty, data); } gpuData->copyPixels(frameBuffer, 0, 0, tileSize, tileSize); } return true; }
bool TextureLayer::doCreateTile(int level, int tx, int ty, TileStorage::Slot *data) { if (Logger::DEBUG_LOGGER != NULL) { ostringstream oss; oss << "Texture tile " << getProducerId() << " " << level << " " << tx << " " << ty; Logger::DEBUG_LOGGER->log("ORTHO", oss.str()); } if (level < minDisplayLevel) { return true; } int l = level; int x = tx; int y = ty; while (!tiles->hasTile(l, x, y)) { l -= 1; x /= 2; y /= 2; assert(l >= 0); } ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer(); TileCache::Tile *t = tiles->findTile(l, x, y); assert(t != NULL); GPUTileStorage::GPUSlot *gput = dynamic_cast<GPUTileStorage::GPUSlot*>(t->getData()); assert(gput != NULL); vec4f coords = tiles->getGpuTileCoords(level, tx, ty, &t); int s = tiles->getCache()->getStorage()->getTileSize(); float b = float(tiles->getBorder()) / (1 << (level - l)); float S = s / (s - 2.0f * tiles->getBorder()); // correct border vec4f coordsCorrected = coords; coordsCorrected.x -= b / gput->getWidth(); coordsCorrected.y -= b / gput->getHeight(); coordsCorrected.w *= S; samplerU->set(gput->t); coordsU->set(vec3f(coordsCorrected.x, coordsCorrected.y, coords.z)); sizeU->set(vec3f(coordsCorrected.w, coordsCorrected.w, (s / 2) * 2.0f - 2.0f * b)); if (blend.buffer != (BufferId) -1) { fb->setBlend(blend.buffer, true, blend.rgb, blend.srgb, blend.drgb, blend.alpha, blend.salpha, blend.dalpha); } else { fb->setBlend(true, blend.rgb, blend.srgb, blend.drgb, blend.alpha, blend.salpha, blend.dalpha); } fb->drawQuad(program); if (blend.buffer != (BufferId) -1) { fb->setBlend(blend.buffer, false); } else { fb->setBlend(false); } return true; }
bool CPUElevationProducer::doCreateTile(int level, int tx, int ty, TileStorage::Slot *data) { if (Logger::DEBUG_LOGGER != NULL) { ostringstream oss; oss << "CPUElevation tile " << getId() << " " << level << " " << tx << " " << ty; Logger::DEBUG_LOGGER->log("DEM", oss.str()); } CPUTileStorage<float>::CPUSlot *cpuData = dynamic_cast<CPUTileStorage<float>::CPUSlot*>(data); assert(cpuData != NULL); int tileWidth = data->getOwner()->getTileSize(); int tileSize = tileWidth - 5; CPUTileStorage<float>::CPUSlot *parentCpuData = NULL; if (level > 0) { TileCache::Tile *t = findTile(level - 1, tx / 2, ty / 2); assert(t != NULL); parentCpuData = dynamic_cast<CPUTileStorage<float>::CPUSlot*>(t->getData()); assert(parentCpuData != NULL); } int residualTileWidth = residualTiles->getCache()->getStorage()->getTileSize(); int mod = (residualTileWidth - 2 * residualTiles->getBorder() - 1) / tileSize; int rx = (tx % mod) * tileSize; // select the xy coord in residual int ry = (ty % mod) * tileSize; TileCache::Tile *t = residualTiles->findTile(level, tx / mod, ty / mod); CPUTileStorage<float>::CPUSlot *cpuTile = NULL; bool hasResidual = residualTiles->hasTile(level, tx / mod, ty / mod); if (hasResidual) { assert(t != NULL); cpuTile = dynamic_cast<CPUTileStorage<float>::CPUSlot*>(t->getData()); assert(cpuTile != NULL); } int px = 1 + (tx % 2) * tileSize / 2; //select the xy coord in the parent tile int py = 1 + (ty % 2) * tileSize / 2; float *parentTile = NULL; if (level > 0) { parentTile = parentCpuData->data; } for (int j = 0; j < tileWidth; ++j) { for (int i = 0; i < tileWidth; ++i) { float z; float r = 0.0f; if (level == 0) { z = 0.0f; } else { if (j % 2 == 0) { if (i % 2 == 0) { z = parentTile[i / 2 + px + (j / 2 + py) * tileWidth]; } else { float z0 = parentTile[i / 2 + px - 1 + (j / 2 + py) * tileWidth]; float z1 = parentTile[i / 2 + px + (j / 2 + py) * tileWidth]; float z2 = parentTile[i / 2 + px + 1 + (j / 2 + py) * tileWidth]; float z3 = parentTile[i / 2 + px + 2 + (j / 2 + py) * tileWidth]; z = ((z1 + z2) * 9 - (z0 + z3)) / 16; } } else { if (i % 2 == 0) { float z0 = parentTile[i / 2 + px + (j / 2 - 1 + py) * tileWidth]; float z1 = parentTile[i / 2 + px + (j / 2 + py) * tileWidth]; float z2 = parentTile[i / 2 + px + (j / 2 + 1 + py) * tileWidth]; float z3 = parentTile[i / 2 + px + (j / 2 + 2 + py) * tileWidth]; z = ((z1 + z2) * 9 - (z0 + z3)) / 16; } else { int di, dj; z = 0; for (dj = -1; dj <= 2; ++dj) { float f = dj == -1 || dj == 2 ? -1/16.0f : 9/16.0f; for (di = -1; di <= 2; ++di) { float g = di == -1 || di == 2 ? -1/16.0f : 9/16.0f; z += f * g * parentTile[i / 2 + di + px + (j / 2 + dj + py) * tileWidth]; } } } } } if (hasResidual) { r = cpuTile->data[(int)(i + rx + (j + ry) * residualTileWidth)]; } cpuData->data[i + j * tileWidth] = z + r; } } return true; }
bool WaterElevationLayer::doCreateTile(int level, int tx, int ty, TileStorage::Slot *data) { if (Logger::DEBUG_LOGGER != NULL) { ostringstream oss; oss << "ElevationRoad tile " << getProducerId() << " " << level << " " << tx << " " << ty; Logger::DEBUG_LOGGER->log("DEM", oss.str()); } if (level >= displayLevel) { TileCache::Tile *t = graphProducer->findTile(level, tx, ty); assert(t != NULL); ObjectTileStorage::ObjectSlot *graphData = dynamic_cast<ObjectTileStorage::ObjectSlot*>(t->getData()); GraphPtr g = graphData->data.cast<Graph>(); if (g->getCurveCount() == 0) { return false; } ptr<FrameBuffer> fb = SceneManager::getCurrentFrameBuffer(); vec3d q = getTileCoords(level, tx, ty); vec2d nx, ny, lx, ly; getDeformParameters(q, nx, ny, lx, ly); float scale = 2.0f * (getTileSize() - 1.0f - (2.0f * getTileBorder())) / q.z; vec3d tileOffset = vec3d(q.x + q.z / 2.0f, q.y + q.z / 2.0f, scale / getTileSize()); //tileOffsetU->set(vec3f(q.x + q.z / 2.0f, q.y + q.z / 2.0f, scale / getTileSize())); tileOffsetU->set(vec3f(0.0, 0.0, 1.0)); fb->clear(false, false, true); if (g->getAreaCount() > 0) { //fillOffsetU->set(vec3f(q.x + q.z / 2.0f, q.y + q.z / 2.0f, scale / getTileSize())); fillOffsetU->set(vec3f(0.0, 0.0, 1.0)); depthU->set(0.02f); colorU->set(vec4f(0.0f, 0.0f, 0.0f, 0.0f)); fb->setDepthTest(true, ALWAYS); fb->setColorMask(false, false, false, true); fb->setDepthMask(true); mesh->setMode(TRIANGLES); mesh->clear(); tess->beginPolygon(mesh); ptr<Graph::AreaIterator> ai = g->getAreas(); while (ai->hasNext()) { AreaPtr a = ai->next(); GraphLayer::drawArea(tileOffset, a, *tess); } tess->endPolygon(); fb->draw(fillProg, *mesh); riverU->set(1); ai = g->getAreas(); while (ai->hasNext()) { AreaPtr a = ai->next(); bool island = true; for (int j = 0; j < a->getCurveCount(); ++j) { int o; island &= (a->getCurve(j, o)->getType() == WaterElevationCurveData::ISLAND); if (!island) { break; } } for (int j = 0; j < a->getCurveCount(); ++j) { int orientation; CurvePtr p = a->getCurve(j, orientation); if (island) { orientation = 1 - orientation; } else { if (p->getType() == WaterElevationCurveData::ISLAND) { continue; } } if (orientation != 0) { GraphLayer::drawCurve(tileOffset, p, vec4f(0, 12, 1, 2), fb, layerProgram, *(meshuv), &nx, &ny, &lx, &ly); } else { GraphLayer::drawCurve(tileOffset, p, vec4f(0, -12, 1, 2), fb, layerProgram, *(meshuv), &nx, &ny, &lx, &ly); } } } fb->setDepthTest(true, NOTEQUAL); fb->setColorMask(false, false, true, false); fb->setDepthMask(false); riverU->set(2); ptr<Graph::CurveIterator> ci = g->getCurves(); while (ci->hasNext()) { CurvePtr c = ci->next(); float w = c->getWidth(); float tw = w; if (w * scale <= 1 || (c->getParent() == NULL && level != 0) || c->getType() == WaterElevationCurveData::LAKE || c->getType() == WaterElevationCurveData::RIVER || c->getArea1() != NULL) {//== WaterElevationCurveData::RIVER) { continue; } ElevationCurveData *cData = dynamic_cast<ElevationCurveData*>(findCurveData(c)); ElevationGraphLayer::drawCurveAltitude(tileOffset, c, cData, tw, tw / w, max(1.0f, 1.0f / scale), false, fb, layerProgram, *meshuv, &nx, &ny, &lx, &ly); } } fb->setColorMask(false, false, true, true); fb->setDepthTest(true, LESS); fb->setDepthMask(true); riverU->set(1); ptr<Graph::CurveIterator> ci = g->getCurves(); while (ci->hasNext()) { CurvePtr c = ci->next(); float cwidth = c->getWidth(); if (cwidth * scale <= 1 || c->getType() != WaterElevationCurveData::RIVER || (c->getParent() == NULL && level != 0)) { continue; } float w = BASEWIDTH(cwidth, scale); float tw = TOTALWIDTH(w); ElevationCurveData *cData = dynamic_cast<ElevationCurveData*>(findCurveData(c)); ElevationGraphLayer::drawCurveAltitude(tileOffset, c, cData, tw, tw / w, max(1.0f, 1.0f / scale), true, fb, layerProgram, *meshuv, &nx, &ny, &lx, &ly); } fb->setColorMask(true, true, true, true); } return true; }
bool HydroFlowProducer::doCreateTile(int level, int tx, int ty, TileStorage::Slot *data) { if (Logger::DEBUG_LOGGER != NULL) { ostringstream oss; oss << "Hydro tile " << getId() << " " << level << " " << tx << " " << ty; Logger::DEBUG_LOGGER->log("RIVER", oss.str()); } swHYDRODATA->start(); bool res = false; ObjectTileStorage::ObjectSlot *objectData = dynamic_cast<ObjectTileStorage::ObjectSlot*>(data); assert(objectData != NULL); TileCache::Tile::TId id = TileCache::Tile::getTId(getId(), level, tx, ty); TileCache::Tile *graphTile = graphs->findTile(level, tx, ty); assert(graphTile != NULL); ptr<Graph> graphData = dynamic_cast<ObjectTileStorage::ObjectSlot*>(graphTile->getData())->data.cast<Graph>(); float quadSize = getRootQuadSize() / (1 << level); bool diffVersion = false; if (objectData->data != NULL) { diffVersion = !objectData->data.cast<HydroFlowTile>()->equals(graphData->version, slipParameter, min((int) (quadSize / potentialDelta), displayTileSize), searchRadiusFactor);//objectData->data.cast<HydroFlowTile>()->version != graphData->version; } if (diffVersion || id != objectData->id || objectData->data == NULL ) { ptr<HydroFlowTile> hydroData; double ox = getRootQuadSize() * (double(tx) / (1 << level) - 0.5f); double oy = getRootQuadSize() * (double(ty) / (1 << level) - 0.5f); if (level >= minLevel) { if (graphData.cast<HydroGraph>() == NULL && graphData.cast<LazyHydroGraph>() == NULL) { // if the type of graph is wrong if (Logger::ERROR_LOGGER != NULL) { ostringstream oss; oss << "Bad Graph Type : Should be a [Lazy]HydroGraph."; Logger::ERROR_LOGGER->log("RIVER", oss.str()); } return false; } if (quadSize / potentialDelta < displayTileSize / 2 && level - 1 >=minLevel) { //maxLevel objectData->data = dynamic_cast<ObjectTileStorage::ObjectSlot*>(findTile(level - 1, tx / 2, ty / 2)->getData())->data; return true; } float scale = displayTileSize == -1 ? 1 : displayTileSize / quadSize; ptr<Graph::CurveIterator> ci = graphData->getCurves(); vector<ptr<HydroCurve> > banks; float width = 0.f; while(ci->hasNext()) { ptr<HydroCurve> c = ci->next().cast<HydroCurve>(); bool display = false; if (c->getType() != HydroCurve::BANK && c->getWidth() * scale > 1.0f) { display = true; if (width < c->getWidth()) { width = c->getWidth(); } } else if (c->getType() == HydroCurve::BANK && c->getRiver().id != NULL_ID) { if (c->getOwner()->getAncestor()->getCurve(c->getRiver()).cast<HydroCurve>()->getWidth() * scale > 1.0f) { display = true; } } if (display) { banks.push_back(c); } } hydroData = new HydroFlowTile(ox, oy, quadSize, slipParameter, min((int) (quadSize / potentialDelta), displayTileSize), searchRadiusFactor); hydroData->addBanks(banks, width); } else { hydroData = new HydroFlowTile(ox, oy, quadSize, slipParameter, min((int) (quadSize / potentialDelta), displayTileSize), searchRadiusFactor); } objectData->data = hydroData; hydroData->version = graphData->version; res = true; } swHYDRODATA->end(); TileProducer::doCreateTile(level, tx, ty, data); return res; }