Ogre::TexturePtr Simple::updateShadowTexture(Ogre::MaterialPtr material, const TerrainPageShadow* terrainPageShadow, std::set<std::string>& managedTextures) const { auto shadowTextureName = getShadowTextureName(material); Ogre::TexturePtr texture = static_cast<Ogre::TexturePtr>(Ogre::Root::getSingletonPtr()->getTextureManager()->getByName(shadowTextureName)); if (texture.isNull()) { texture = Ogre::Root::getSingletonPtr()->getTextureManager()->createManual(shadowTextureName, "General", Ogre::TEX_TYPE_2D, mPage.getBlendMapSize(), mPage.getBlendMapSize(), 1, Ogre::PF_L8, Ogre::TU_DYNAMIC_WRITE_ONLY); managedTextures.insert(texture->getName()); } Ogre::Image ogreImage; terrainPageShadow->loadIntoImage(ogreImage); texture->loadImage(ogreImage); //blit the whole image to the hardware buffer Ogre::PixelBox sourceBox(ogreImage.getPixelBox()); //blit for each mipmap for (unsigned int i = 0; i <= texture->getNumMipmaps(); ++i) { Ogre::HardwarePixelBufferSharedPtr hardwareBuffer(texture->getBuffer(0, i)); hardwareBuffer->blitFromMemory(sourceBox); } return texture; }
void SnowTerrain::initBlendMaps(Terrain* terrain) { TextureLayerFileList blendImages = mSnowConfig->terrainSettings.textureBlendFileList; // load those blendmaps into the layers for(int j = 0;j < terrain->getLayerCount();j++) { // skip first layer if(j==0) continue; // no blend map for this layer if(blendImages.size() >= j && blendImages[j].length() == 0) continue; Ogre::TerrainLayerBlendMap *blendmap = terrain->getLayerBlendMap(j); Ogre::Image img; img.load(blendImages[j],"General"); int blendmapsize = terrain->getLayerBlendMapSize(); if(img.getWidth() != blendmapsize) img.resize(blendmapsize, blendmapsize); float *ptr = blendmap->getBlendPointer(); Ogre::uint8 *data = static_cast<Ogre::uint8*>(img.getPixelBox().data); for(int bp = 0;bp < blendmapsize * blendmapsize;bp++) ptr[bp] = static_cast<float>(data[bp]) / 255.0f; blendmap->dirty(); blendmap->update(); } }
bool ShadowUpdateTask::executeTaskInMainThread() { if (!mPageGeometries.empty()) { auto pageGeometry = mPageGeometries.back(); mPageGeometries.pop_back(); auto& page = pageGeometry->getPage(); if (page.getSurface()) { auto shadow = page.getSurface()->getShadow(); if (shadow) { auto& shadowTextureName = shadow->getShadowTextureName(); if (!shadowTextureName.empty()) { Ogre::TexturePtr texture = Ogre::Root::getSingletonPtr()->getTextureManager()->getByName(shadowTextureName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); if (texture) { Ogre::Image ogreImage; shadow->loadIntoImage(ogreImage); texture->loadImage(ogreImage); //blit the whole image to the hardware buffer Ogre::PixelBox sourceBox(ogreImage.getPixelBox()); //blit for each mipmap for (unsigned int i = 0; i <= texture->getNumMipmaps(); ++i) { Ogre::HardwarePixelBufferSharedPtr hardwareBuffer(texture->getBuffer(0, i)); hardwareBuffer->blitFromMemory(sourceBox); } } } } } } return mPageGeometries.empty(); }
Ogre::TexturePtr Simple::updateShadowTexture(Ogre::MaterialPtr material, const TerrainPageShadow* terrainPageShadow) { //we need an unique name for our alpha texture std::stringstream shadowTextureNameSS; shadowTextureNameSS << material->getName() << "_shadow"; const Ogre::String shadowTextureName(shadowTextureNameSS.str()); Ogre::TexturePtr texture = static_cast<Ogre::TexturePtr> (Ogre::Root::getSingletonPtr()->getTextureManager()->getByName(shadowTextureName)); if (texture.isNull()) { texture = Ogre::Root::getSingletonPtr()->getTextureManager()->createManual(shadowTextureName, "General", Ogre::TEX_TYPE_2D, mPage.getAlphaTextureSize(), mPage.getAlphaTextureSize(), 1, Ogre::PF_L8, Ogre::TU_DYNAMIC_WRITE_ONLY); } Ogre::Image ogreImage; terrainPageShadow->loadIntoImage(ogreImage); texture->loadImage(ogreImage); //blit the whole image to the hardware buffer Ogre::PixelBox sourceBox(ogreImage.getPixelBox()); //blit for each mipmap for (unsigned int i = 0; i <= texture->getNumMipmaps(); ++i) { Ogre::HardwarePixelBufferSharedPtr hardwareBuffer(texture->getBuffer(0, i)); hardwareBuffer->blitFromMemory(sourceBox); } return texture; }
//----------------------------------------------------------------------------------------- void CTerrainGroupEditor::importFullTerrainFromHeightMap() { UTFStringVector extlist; extlist.push_back(OTR("PNG Grayscale")); extlist.push_back("*.png"); extlist.push_back(OTR("Raw 32bit Float File")); extlist.push_back("*.raw;*.ohm;*.f32;*.r32"); Ogre::UTFString defaultPath = mSystem->GetSetting("system", "ExportTerrainPath", ""); Ogre::String filename = mSystem->DisplayOpenDialog(OTR("Import Heightmap"), extlist, defaultPath); if(filename == "") return; mSystem->SetSetting("system", "ExportTerrainPath", OgitorsUtils::ExtractFilePath(filename)); Ogre::NameValuePairList params; if(!mSystem->DisplayImportHeightMapDialog(params)) return; Ogre::Real fScale = Ogre::StringConverter::parseReal(params["scale"]); Ogre::Real fBias = Ogre::StringConverter::parseReal(params["bias"]); Ogre::String normal = params["normal"]; Ogre::String diffuse = params["diffuse"]; bool flipV = Ogre::StringConverter::parseBool(params["inverted"]); float *data = 0; float *flipBV = 0; Ogre::String namePart = OgitorsUtils::ExtractFileName(filename); namePart.erase(0, namePart.find(".")); int imgW = 0; int imgH = 0; if(namePart == ".png") { std::fstream fstr(filename.c_str(), std::ios::in|std::ios::binary); Ogre::DataStreamPtr stream = Ogre::DataStreamPtr(OGRE_NEW Ogre::FileStreamDataStream(&fstr, false)); Ogre::Image img; img.load(stream); data = OGRE_ALLOC_T(float, img.getWidth() * img.getHeight(), Ogre::MEMCATEGORY_GEOMETRY); Ogre::PixelBox pb(img.getWidth(), img.getHeight(), 1, Ogre::PF_FLOAT32_R, data); Ogre::PixelUtil::bulkPixelConversion(img.getPixelBox(), pb); imgW = img.getWidth(); imgH = img.getHeight(); img.freeMemory(); stream.setNull(); }
/**************************************************************************** ** ** Copyright (C) 2016 - 2017 ** ** This file is part of the Magus toolkit ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ #include "constants.h" #include "texturelayer.h" #include "OgreHlmsPbs.h" #include "OgreHlmsManager.h" #include "OgreLogManager.h" #include "OgreStringConverter.h" #include <fstream> #include <ctime> //****************************************************************************/ TextureLayer::TextureLayer(void) : mTextureOnWhichIsPaintedWidth(0), mTextureOnWhichIsPaintedHeight(0), mTextureOnWhichIsPaintedHasAlpha(false), mNumMipMaps(0), mTextureTypeDefined(false), mMaxSequence(0) { mTextureType = Ogre::PBSM_DIFFUSE; mDatablockId = ""; mTextureFileName = ""; } //****************************************************************************/ TextureLayer::~TextureLayer(void) { } //****************************************************************************/ void TextureLayer::setDatablockIdAndTexture (const Ogre::IdString& datablockId, Ogre::PbsTextureTypes textureType, const Ogre::String& textureFileName) { mDatablockId = datablockId; mTextureType = textureType; mTextureFileName = textureFileName; mTextureTypeDefined = true; // Load the texture as image; assume it can be loaded, because it was already loaded as part of the material setFirstTextureGeneration(); // Create the pixelbox of the original texture; this MUST be a separate image mOriginalTexture.load(textureFileName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mPixelboxOriginalTexture = mOriginalTexture.getPixelBox(0, 0); // Debug texture //Ogre::LogManager::getSingleton().logMessage("Debug texture: " + textureFileName); //Ogre::LogManager::getSingleton().logMessage("Depth: " + Ogre::StringConverter::toString(mOriginalTexture.getDepth())); //Ogre::LogManager::getSingleton().logMessage("Pixel format: " + Ogre::StringConverter::toString(mOriginalTexture.getFormat())); //Ogre::LogManager::getSingleton().logMessage("Alpha: " + Ogre::StringConverter::toString(mOriginalTexture.getHasAlpha())); //Ogre::LogManager::getSingleton().logMessage("Height: " + Ogre::StringConverter::toString(mOriginalTexture.getHeight())); //Ogre::LogManager::getSingleton().logMessage("Number of faces: " + Ogre::StringConverter::toString(mOriginalTexture.getNumFaces())); //Ogre::LogManager::getSingleton().logMessage("Number of mipmaps: " + Ogre::StringConverter::toString(mOriginalTexture.getNumMipmaps())); //Ogre::LogManager::getSingleton().logMessage("Width: " + Ogre::StringConverter::toString(mOriginalTexture.getWidth())); } //****************************************************************************/ void TextureLayer::blitTexture (void) { /* Always get the actual pointers, because they may change. That is the reason why the datablock pointer cannot be cached. * The same seems to apply to the texture pointer. */ Ogre::HlmsDatablock* datablock; Ogre::HlmsPbsDatablock* datablockPbs; Ogre::TexturePtr texture; Ogre::HlmsManager* hlmsManager = Ogre::Root::getSingletonPtr()->getHlmsManager(); Ogre::HlmsPbs* hlmsPbs = static_cast<Ogre::HlmsPbs*>(hlmsManager->getHlms(Ogre::HLMS_PBS)); datablock = hlmsPbs->getDatablock(mDatablockId); if (!datablock) return; datablockPbs = static_cast<Ogre::HlmsPbsDatablock*>(datablock); try { // Get texture on GPU if (!datablockPbs->getTexture(mTextureType).isNull()) { texture = datablockPbs->getTexture(mTextureType); // TextureType MUST exist, otherwise the application crashes mNumMipMaps = texture->getNumMipmaps(); } } catch (Ogre::Exception e){} if (texture.isNull()) return; Ogre::uint8 maxMipMaps = mNumMipMaps + 1; // Increase with one, because there is always one image to blit maxMipMaps = maxMipMaps > PAINT_MAX_MIP_MAPS ? PAINT_MAX_MIP_MAPS : maxMipMaps; // Just paint a few mipmaps (not all) Ogre::Image textureOnWhichIsPaintedScaled = mTextureOnWhichIsPainted; // Temporary image must be used, otherwise painting doesn't work size_t w = mTextureOnWhichIsPaintedWidth; size_t h = mTextureOnWhichIsPaintedHeight; Ogre::v1::HardwarePixelBuffer* buffer; for (Ogre::uint8 i = 0; i < maxMipMaps; ++i) { buffer = texture->getBuffer(0, i).getPointer(); buffer->blitFromMemory(textureOnWhichIsPaintedScaled.getPixelBox(0, 0), Ogre::Box(0, 0, 0, w, h, 1)); w*=0.5f; // Mipmaps always are half of the previous one h*=0.5f; if (w < 1.0f || h < 1.0f) break; // Stop when the mipmaps are too small textureOnWhichIsPaintedScaled.resize(w, h); } textureOnWhichIsPaintedScaled.freeMemory(); }
/// _Tool_ tex .......................... // (remove alpha channel for ter tex prv img) void App::ToolTexAlpha() { Ogre::Image im; im.load("jungle_5d.png", "General"); PixelBox pb = im.getPixelBox(); int w = pb.getWidth(), h = pb.getHeight(); for(int j=0; j < h; ++j) for(int i=0; i < w; ++i) { ColourValue c = pb.getColourAt(i,j,0); c.a = 1.f; pb.setColourAt(c,i,j,0); } im.save(PATHMANAGER::Data()+"/prv.png"); }
//----------------------------------------------------------------------------------------- void CTerrainGroupEditor::setBrushName(const std::string& brush) { mBrushName = brush; if(!mDecalTexture.isNull()) { Ogre::Image img; img.load(brush,"Brushes"); unsigned char *dataptr = OGRE_ALLOC_T(unsigned char, img.getWidth() * img.getHeight() * 3, Ogre::MEMCATEGORY_GEOMETRY); Ogre::PixelBox resultbox(img.getWidth(),img.getHeight(),1,Ogre::PF_B8G8R8,dataptr); Ogre::PixelUtil::bulkPixelConversion(img.getPixelBox(), resultbox); resultbox.setConsecutive(); int pos = 0; Ogre::ColourValue colval; for(unsigned int x = 0;x < img.getHeight() * img.getWidth();x++) { dataptr[pos] = 0; dataptr[pos + 1] = 0; dataptr[pos + 2] *= 0.8f; pos += 3; } mDecalTexture->setHeight(img.getHeight()); mDecalTexture->setWidth(img.getWidth()); Ogre::HardwarePixelBufferSharedPtr ptr = mDecalTexture->getBuffer(); ptr->blitFromMemory(resultbox); OGRE_FREE(dataptr, Ogre::MEMCATEGORY_GEOMETRY); img.resize(mBrushSize, mBrushSize); img.resize(BRUSH_DATA_SIZE, BRUSH_DATA_SIZE); pos = 0; Ogre::ColourValue cval; for(unsigned int y = 0;y < BRUSH_DATA_SIZE ;y++) { pos = ((BRUSH_DATA_SIZE - 1) - y) * BRUSH_DATA_SIZE; for(unsigned int x = 0;x < BRUSH_DATA_SIZE ;x++) { cval = img.getColourAt(x,y,0); mBrushData[pos] = cval.r; pos++; } } }
void DotSceneLoader::processBlendmaps(rapidxml::xml_node<>* XMLNode) { int pageX = Ogre::StringConverter::parseInt(XMLNode->first_attribute("pageX")->value()); int pageY = Ogre::StringConverter::parseInt(XMLNode->first_attribute("pageY")->value()); Ogre::String filename = mTerrainGroup->generateFilename(pageX, pageY); // skip this is terrain page has been saved already if (!Ogre::ResourceGroupManager::getSingleton().resourceExists(mTerrainGroup->getResourceGroup(), filename)) { rapidxml::xml_node<>* pElement; // Process blendmaps (*) std::vector<Ogre::String> blendMaps; rapidxml::xml_node<>* pBlendmap; pElement = XMLNode->first_node("blendMaps"); pBlendmap = pElement->first_node("blendMap"); while(pBlendmap) { blendMaps.push_back(getAttrib(pBlendmap, "texture","")); pBlendmap = pBlendmap->next_sibling("blendMap"); } for(int j = 1;j < mTerrainGroup->getTerrain(pageX, pageY)->getLayerCount();j++) { Ogre::TerrainLayerBlendMap *blendmap = mTerrainGroup->getTerrain(pageX, pageY)->getLayerBlendMap(j); Ogre::Image img; img.load(blendMaps[j-1],"General"); int blendmapsize = mTerrainGroup->getTerrain(pageX, pageY)->getLayerBlendMapSize(); if(img.getWidth() != blendmapsize) img.resize(blendmapsize, blendmapsize); float *ptr = blendmap->getBlendPointer(); Ogre::uint8 *data = static_cast<Ogre::uint8*>(img.getPixelBox().data); for(int bp = 0;bp < blendmapsize * blendmapsize;bp++) ptr[bp] = static_cast<float>(data[bp]) / 255.0f; blendmap->dirty(); blendmap->update(); } } }
//---------------------------------------------------------------------------------------- QImage ImageConverter::fromOgreImage(const Ogre::Image& image) { if (!Ogre::PixelUtil::isAccessible(image.getFormat())) return _imageFromRenderTarget(image); size_t size = Ogre::PixelUtil::getMemorySize(mWidth, mHeight, 1, Ogre::PF_A8R8G8B8); unsigned char *dataptr = OGRE_ALLOC_T(unsigned char, size, Ogre::MEMCATEGORY_GENERAL); Ogre::PixelBox pixbox(mWidth, mHeight, 1, Ogre::PF_A8R8G8B8, dataptr); Ogre::Image::scale(image.getPixelBox(), pixbox); pixbox.setConsecutive(); QImage shallowImg(dataptr, pixbox.getWidth(), pixbox.getHeight(), QImage::Format_ARGB32); // perform deep copy otherwise data lost upon freeing dataptr QImage deepImg = shallowImg.copy(); OGRE_FREE(dataptr, Ogre::MEMCATEGORY_GENERAL); return deepImg; }
void Simple::addLightingPass(Ogre::Technique* technique, std::set<std::string>& managedTextures) const { Ogre::Pass* lightingPass = technique->createPass(); lightingPass->setSceneBlending(Ogre::SBT_MODULATE); lightingPass->setLightingEnabled(false); Ogre::TextureUnitState * textureUnitStateSplat = lightingPass->createTextureUnitState(); //we need an unique name for our alpha texture std::stringstream lightingTextureNameSS; lightingTextureNameSS << technique->getParent()->getName() << "_lighting"; const Ogre::String lightingTextureName(lightingTextureNameSS.str()); Ogre::TexturePtr texture = static_cast<Ogre::TexturePtr>(Ogre::Root::getSingletonPtr()->getTextureManager()->getByName(lightingTextureName)); if (texture.isNull()) { texture = Ogre::Root::getSingletonPtr()->getTextureManager()->createManual(lightingTextureName, "General", Ogre::TEX_TYPE_2D, mPage.getBlendMapSize(), mPage.getBlendMapSize(), 1, Ogre::PF_L8, Ogre::TU_DYNAMIC_WRITE_ONLY); managedTextures.insert(texture->getName()); } Ogre::Image ogreImage; ogreImage.loadDynamicImage(const_cast<unsigned char*>(mLightingImage->getData()), mLightingImage->getResolution(), mLightingImage->getResolution(), 1, Ogre::PF_L8); texture->loadImage(ogreImage); //blit the whole image to the hardware buffer Ogre::PixelBox sourceBox(ogreImage.getPixelBox()); //blit for each mipmap for (unsigned int i = 0; i <= texture->getNumMipmaps(); ++i) { Ogre::HardwarePixelBufferSharedPtr hardwareBuffer(texture->getBuffer(0, i)); hardwareBuffer->blitFromMemory(sourceBox); } textureUnitStateSplat->setTextureName(texture->getName()); textureUnitStateSplat->setTextureCoordSet(0); textureUnitStateSplat->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); textureUnitStateSplat->setTextureFiltering(Ogre::TFO_ANISOTROPIC); }
Vector4* SnowTerrain::getTerrainNormalData() { PixelBox* terrainNormals; // load from normals file if(mSnowConfig->terrainSettings.normalsDataFile.length() > 0) { // get terrain normal data using image Ogre::Image img; img.load(mSnowConfig->terrainSettings.normalsDataFile, "General"); //img.flipAroundY(); //img.flipAroundX(); size_t size = img.getWidth(); assert(img.getWidth() == img.getHeight()); if (img.getWidth() != mTerrainSize || img.getHeight() != mTerrainSize) img.resize(mTerrainSize, mTerrainSize); terrainNormals = &img.getPixelBox(); Vector4* floats = convertNormalsToFloats(terrainNormals, true); //OGRE_FREE(terrainNormals->data, Ogre::MEMCATEGORY_GENERAL); // need to swap z and y vector due to different vertical axis in normal map and world space! for(size_t i = 0;i<mTerrainSize*mTerrainSize;i++) { Vector4 v = floats[i]; floats[i].z = v.y; floats[i].y = v.z; } return floats; } else { // need to wait until terrain is loaded while (getTerrain()->isDerivedDataUpdateInProgress()) { // we need to wait for this to finish OGRE_THREAD_SLEEP(50); Root::getSingleton().getWorkQueue()->processResponses(); } // Get terrain normal data using official method //terrainNormals = getTerrain()->calculateNormals(Ogre::Rect(0,0,mTerrainSize,mTerrainSize),Rect(0,0,mTerrainSize,mTerrainSize)); Ogre::Image img; getTerrain()->getTerrainNormalMap()->convertToImage(img); //img.flipAroundY(); img.flipAroundX(); //img.save("test_normals.bmp"); terrainNormals = &img.getPixelBox(); Vector4* floats = convertNormalsToFloats(terrainNormals, true); //OGRE_FREE(terrainNormals->data, Ogre::MEMCATEGORY_GENERAL); return floats; } }
int _tmain(int argc, _TCHAR* argv[]) { // ------------------------- Check for command line argument ------------------------------------------- if (! argv[1]) { printf("\n"); printf("Missing argument.\nExample: \"Converter.exe job1.cfg\""); return 0; } // ------------------------- Basic Ogre Engine initialization ------------------------------------------- Ogre::Root* root = new Ogre::Root; Ogre::RenderSystem* rendersys = root->getRenderSystemByName("Direct3D9 Rendering Subsystem"); rendersys->setConfigOption("Full Screen", "No"); rendersys->setConfigOption("Video Mode", "800 x 600 @ 32-bit colour"); root->setRenderSystem(rendersys); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("resource", "FileSystem", "General"); Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); root->initialise(false); Ogre::RenderWindow* window = root->createRenderWindow("RAW2OGT", 800, 600, false); Ogre::SceneManager* scenemgr = root->createSceneManager(Ogre::SceneType::ST_GENERIC); Ogre::Camera* camera = scenemgr->createCamera("camera"); Ogre::Viewport* viewport = window->addViewport(camera); /*Ogre::Vector3 lightdir(0, -0.3, 0.75); lightdir.normalise(); Ogre::Light* l = scenemgr->createLight("tstLight"); l->setType(Ogre::Light::LT_DIRECTIONAL); l->setDirection(lightdir); l->setDiffuseColour(Ogre::ColourValue(1.0, 1.0, 1.0)); l->setSpecularColour(Ogre::ColourValue(0.4, 0.4, 0.4));*/ scenemgr->setAmbientLight(Ogre::ColourValue(0.7, 0.7, 0.7)); // --------------------------------- Start convert ---------------------------------------------------- // Load job config Ogre::ConfigFile* terrainconfig = OGRE_NEW Ogre::ConfigFile(); terrainconfig->loadDirect(argv[1]); // Load info from [general] block Ogre::String heightmapfile = terrainconfig->getSetting("heightmap", "general"); Ogre::Real heightmapscale = Ogre::StringConverter::parseReal(terrainconfig->getSetting("heightmapscale", "general")); Ogre::Real heightmapoffset = Ogre::StringConverter::parseReal(terrainconfig->getSetting("heightmapoffset", "general")); Ogre::uint16 terrainsize = Ogre::StringConverter::parseUnsignedInt(terrainconfig->getSetting("terrainsize", "general")); Ogre::Real worldsize = Ogre::StringConverter::parseReal(terrainconfig->getSetting("worldsize", "general")); Ogre::uint16 layercount = Ogre::StringConverter::parseUnsignedInt(terrainconfig->getSetting("layercount", "general")); // initialise stream to heightmapfile Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(heightmapfile, "General"); size_t size = stream.get()->size(); // verify size if(size != terrainsize * terrainsize * 4) OGRE_EXCEPT( Ogre::Exception::ERR_INTERNAL_ERROR, "Size of stream does not match terrainsize!", "TerrainPage" ); // load to buffer float* buffer = OGRE_ALLOC_T(float, size, Ogre::MEMCATEGORY_GENERAL); stream->read(buffer, size); // apply scale and offset for(int i=0;i<terrainsize*terrainsize;i++) { buffer[i] = (buffer[i] + heightmapoffset) * heightmapscale; } // Terrain initialization Ogre::TerrainGlobalOptions* terrainglobals = OGRE_NEW Ogre::TerrainGlobalOptions(); terrainglobals->setMaxPixelError(1); //terrainglobals->setCompositeMapDistance(30000); //terrainglobals->setLightMapDirection(lightdir); //terrainglobals->setCompositeMapAmbient(scenemgr->getAmbientLight()); //terrainglobals->setCompositeMapDiffuse(l->getDiffuseColour()); Ogre::TerrainMaterialGeneratorA::SM2Profile* pMatProfile = static_cast<Ogre::TerrainMaterialGeneratorA::SM2Profile*>(terrainglobals->getDefaultMaterialGenerator()->getActiveProfile()); pMatProfile->setLightmapEnabled(false); pMatProfile->setCompositeMapEnabled(false); Ogre::TerrainGroup* terraingroup = OGRE_NEW Ogre::TerrainGroup(scenemgr, Ogre::Terrain::ALIGN_X_Z, terrainsize, worldsize); terraingroup->setFilenameConvention(Ogre::String("terrain"), Ogre::String("ogt")); terraingroup->setOrigin(Ogre::Vector3::ZERO); Ogre::Terrain* terrain = OGRE_NEW Ogre::Terrain(scenemgr); // terrainsettings Ogre::Terrain::ImportData& imp = terraingroup->getDefaultImportSettings(); imp.terrainSize = terrainsize; imp.worldSize = worldsize; imp.minBatchSize = 33; imp.maxBatchSize = 65; // use float RAW heightmap as input imp.inputFloat = buffer; // process texture layers imp.layerList.resize(layercount); Ogre::StringVector blendmaps(layercount); for(int i=0;i<layercount;i++) { // load layer info Ogre::String sectionStr = Ogre::StringConverter::toString(i); Ogre::Real layerworldsize = Ogre::StringConverter::parseReal(terrainconfig->getSetting("worldsize", sectionStr)); if (i==0) { // no blendmap at layer 0 (baselayer) Ogre::String specular = terrainconfig->getSetting("specular", sectionStr); Ogre::String normal = terrainconfig->getSetting("normal", sectionStr); // add layer imp.layerList[i].textureNames.push_back(specular); imp.layerList[i].textureNames.push_back(normal); imp.layerList[i].worldSize = layerworldsize; } else { Ogre::String specular = terrainconfig->getSetting("specular", sectionStr); Ogre::String normal = terrainconfig->getSetting("normal", sectionStr); Ogre::String blend = terrainconfig->getSetting("blend", sectionStr); // add layer imp.layerList[i].textureNames.push_back(specular); imp.layerList[i].textureNames.push_back(normal); imp.layerList[i].worldSize = layerworldsize; blendmaps[i] = blend; } } // load the terrain terrain->prepare(imp); terrain->load(); // load those blendmaps into the layers for(int j = 1;j < terrain->getLayerCount();j++) { Ogre::TerrainLayerBlendMap *blendmap = terrain->getLayerBlendMap(j); Ogre::Image img; img.load(blendmaps[j],"General"); int blendmapsize = terrain->getLayerBlendMapSize(); if(img.getWidth() != blendmapsize) img.resize(blendmapsize, blendmapsize); float *ptr = blendmap->getBlendPointer(); Ogre::uint8 *data = static_cast<Ogre::uint8*>(img.getPixelBox().data); for(int bp = 0;bp < blendmapsize * blendmapsize;bp++) ptr[bp] = static_cast<float>(data[bp]) / 255.0f; blendmap->dirty(); blendmap->update(); } // create filename for writing int pos = heightmapfile.find_last_of('.'); if (pos < 0) heightmapfile = heightmapfile + ".ogt"; else heightmapfile = heightmapfile.substr(0, pos) + ".ogt"; // save as Ogre .OGT terrain->save(heightmapfile); Ogre::LogManager::getSingletonPtr()->logMessage(Ogre::LogMessageLevel::LML_NORMAL, heightmapfile + " successfully written."); // debug viewing (exit with CTRL+C) camera->setPosition(-terrainsize, 7000, -terrainsize); camera->lookAt(terrainsize/2,0,terrainsize/2); root->startRendering(); return 0; }
// void TerrainPageSurfaceCompiler::addTextureUnitsToPass(Ogre::Pass* pass, const Ogre::String& splatTextureName) { // // if (getMaxTextureUnits() - pass->getNumTextureUnitStates() < 2 || pass->getParent()->getNumPasses() > 1) { // addPassToTechnique(pass->getParent(), splatTextureName); // // S_LOG_WARNING("Trying to add texture units to pass with too few available texture unit states."); // return; // } // // S_LOG_VERBOSE("Adding new texture unit (detailtexture: " << mTextureName << " alphatexture: " << splatTextureName << ") to pass nr " << pass->getIndex() << " in technique for material " << pass->getParent()->getParent()->getName()); // // /* pass->setSelfIllumination(Ogre::ColourValue(1,1,1)); // pass->setAmbient(Ogre::ColourValue(1,1,1)); // pass->setDiffuse(Ogre::ColourValue(1,1,1)); // pass->setLightingEnabled(true);*/ // Ogre::TextureUnitState * textureUnitStateSplat = pass->createTextureUnitState(); // textureUnitStateSplat->setTextureName(splatTextureName); // // textureUnitStateSplat->setTextureCoordSet(0); // textureUnitStateSplat->setTextureFiltering(Ogre::TFO_ANISOTROPIC); // textureUnitStateSplat->setAlphaOperation(Ogre::LBX_SOURCE1, Ogre::LBS_TEXTURE, Ogre::LBS_TEXTURE); // textureUnitStateSplat->setColourOperationEx(Ogre::LBX_SOURCE1, Ogre::LBS_CURRENT, Ogre::LBS_CURRENT); // textureUnitStateSplat->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // // textureUnitStateSplat->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, Ogre::LBS_CURRENT, Ogre::LBS_TEXTURE); // // textureUnitStateSplat->setColourOperationEx(Ogre::LBX_BLEND_TEXTURE_ALPHA, Ogre::LBS_CURRENT, Ogre::LBS_TEXTURE); // // Ogre::TextureUnitState * textureUnitState = pass->createTextureUnitState(); // textureUnitState->setTextureName(mTextureName); // textureUnitState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); // /* textureUnitState->setTextureCoordSet(0);*/ // textureUnitState->setTextureScale(0.025, 0.025); // textureUnitState->setColourOperationEx(Ogre::LBX_BLEND_CURRENT_ALPHA, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT); // // /* Ogre::TextureUnitState * alphaTextureState= pass->createTextureUnitState(); // alphaTextureState->setTextureName(mTextureName); // // alphaTextureState->setTextureName(splatTextureName); // alphaTextureState->setTextureCoordSet(0); // alphaTextureState->setTextureFiltering(Ogre::TFO_ANISOTROPIC); // alphaTextureState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // alphaTextureState->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, Ogre::LBS_CURRENT, Ogre::LBS_TEXTURE); // // // // // detailTextureState->setAlphaOperation(Ogre::LBX_SOURCE1, Ogre::LBS_TEXTURE, Ogre::LBS_TEXTURE); // // detailTextureState->setColourOperationEx(Ogre::LBX_SOURCE1, Ogre::LBS_CURRENT, Ogre::LBS_CURRENT); // // Ogre::TextureUnitState * detailTextureState = pass->createTextureUnitState(); // detailTextureState ->setTextureName(splatTextureName); // // detailTextureState ->setTextureName(mTextureName); // detailTextureState ->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); // detailTextureState ->setTextureCoordSet(0); // detailTextureState ->setTextureScale(0.01, 0.01); // //detailTextureState ->setColourOperationEx(Ogre::LBX_BLEND_CURRENT_ALPHA, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT);*/ // // } // Ogre::Pass* Simple::addPassToTechnique(const TerrainPageGeometry& geometry, Ogre::Technique* technique, const Layer& layer, std::set<std::string>& managedTextures) const { //check if we instead can reuse the existing pass // if (technique->getNumPasses() != 0) { // Ogre::Pass* pass = technique->getPass(technique->getNumPasses() - 1); // if (4 - pass->getNumTextureUnitStates() >= 2) { // //there's more than two texture units available, use those instead of creating a new pass // S_LOG_VERBOSE("Reusing existing pass. ("<< pass->getNumTextureUnitStates() << " of "<< mNumberOfTextureUnitsOnCard << " texture unit used)"); // addTextureUnitsToPass(pass, splatTextureName); // return pass; // } // // } const OgreImage& ogreImage = *layer.blendMap; Ogre::Image image; image.loadDynamicImage(const_cast<unsigned char*>(ogreImage.getData()), ogreImage.getResolution(), ogreImage.getResolution(), 1, Ogre::PF_A8); std::stringstream splatTextureNameSS; splatTextureNameSS << "terrain_" << mPage.getWFPosition().x() << "_" << mPage.getWFPosition().y() << "_" << technique->getNumPasses(); const Ogre::String splatTextureName(splatTextureNameSS.str()); Ogre::TexturePtr blendMapTexture; if (Ogre::Root::getSingletonPtr()->getTextureManager()->resourceExists(splatTextureName)) { blendMapTexture = static_cast<Ogre::TexturePtr>(Ogre::Root::getSingletonPtr()->getTextureManager()->getByName(splatTextureName)); blendMapTexture->loadImage(image); Ogre::HardwarePixelBufferSharedPtr hardwareBuffer(blendMapTexture->getBuffer()); //blit the whole image to the hardware buffer Ogre::PixelBox sourceBox(image.getPixelBox()); hardwareBuffer->blitFromMemory(sourceBox); } else { blendMapTexture = Ogre::Root::getSingletonPtr()->getTextureManager()->loadImage(splatTextureName, "General", image, Ogre::TEX_TYPE_2D, 0); managedTextures.insert(blendMapTexture->getName()); } //we need to create the image, update it and then destroy it again (to keep the memory usage down) // if (layer->getBlendMapTextureName() == "") { // //no texture yet; let's create one // layer->createBlendMapImage(); // layer->updateBlendMapImage(geometry); // layer->createTexture(); // } else { // //a texture exists, so we just need to update the image // layer->updateBlendMapImage(geometry); //calling this will also update the texture since the method will blit the image onto it // } Ogre::Pass* pass = technique->createPass(); pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); pass->setAmbient(1, 1, 1); pass->setDiffuse(1, 1, 1, 1); pass->setLightingEnabled(false); Ogre::TextureUnitState * textureUnitState = pass->createTextureUnitState(); textureUnitState->setTextureName(layer.surfaceLayer.getDiffuseTextureName()); textureUnitState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP); textureUnitState->setTextureCoordSet(0); textureUnitState->setTextureScale(1.0f / layer.surfaceLayer.getScale(), 1.0f / layer.surfaceLayer.getScale()); Ogre::TextureUnitState * textureUnitStateSplat = pass->createTextureUnitState(); textureUnitStateSplat->setTextureName(blendMapTexture->getName()); textureUnitStateSplat->setTextureCoordSet(0); textureUnitStateSplat->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); textureUnitStateSplat->setTextureFiltering(Ogre::TFO_ANISOTROPIC); // textureUnitStateSplat->setAlphaOperation(Ogre::LBX_SOURCE1, Ogre::LBS_TEXTURE, Ogre::LBS_TEXTURE); textureUnitStateSplat->setAlphaOperation(Ogre::LBX_BLEND_DIFFUSE_COLOUR, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT); textureUnitStateSplat->setColourOperationEx(Ogre::LBX_SOURCE1, Ogre::LBS_CURRENT, Ogre::LBS_CURRENT); return pass; }
//------------------------------------------------------ void TextureAtlas::build() { if (!mIsDirty) return; bool fitted; size_t area = 0; // build the fonts (if this didn't happen already) // so we'll be sure the glyphs are there to be atlassed FontSet::iterator fit = mMyFonts.begin(); while (fit != mMyFonts.end()) { FontDrawSource* fdsp = *fit++; if (!fdsp->isBuilt()) fdsp->build(); } // First, we sort by size of the DrawSource mMyDrawSources.sort(DrawSourceLess()); // now try to allocate all the draw sources. If we fail, grow and try again do { fitted = true; area = 0; // try to fit DrawSourceList::iterator it = mMyDrawSources.begin(); while (it != mMyDrawSources.end()) { const DrawSourcePtr& ds = *it++; const PixelSize& ps = ds->getPixelSize(); area += ps.getPixelArea(); LOG_VERBOSE("TextureAtlas: (%s) Trying to place %d x %d (%d -> %d)", mAtlasName.c_str(), ps.width, ps.height, ps.getPixelArea(), area); // try to allocate FreeSpaceInfo* fsi = mAtlasAllocation->allocate(ps.width, ps.height); if (fsi) { ds->setPlacementPtr(fsi); } else { fitted = false; break; } } // fitted? if (!fitted) // nope - Enlarge! enlarge(area); } while (!fitted); LOG_INFO("TextureAtlas: (%s) Creating atlas with dimensions %d x %d", mAtlasName.c_str(), mAtlasSize.width, mAtlasSize.height); if (mTexture.isNull()) prepareResources(); // TODO: Reallocate the texture here if needed! Ogre::HardwarePixelBufferSharedPtr pixelBuffer = mTexture->getBuffer(); pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); const Ogre::PixelBox& targetBox = pixelBuffer->getCurrentLock(); size_t pixelsize = Ogre::PixelUtil::getNumElemBytes(targetBox.format); size_t rowsize = targetBox.rowPitch * pixelsize; Ogre::uint8* dstData = static_cast<Ogre::uint8*>(targetBox.data); // We'll iterate over all draw sources, painting the pixels onto the allocated space DrawSourceList::iterator it = mMyDrawSources.begin(); while (it != mMyDrawSources.end()) { const DrawSourcePtr& ds = *it++; // render all pixels into the right place FreeSpaceInfo* fsi = reinterpret_cast<FreeSpaceInfo*>(ds->getPlacementPtr()); assert(fsi); // render into the specified place unsigned char* conversionBuf = NULL; const PixelSize& dps = ds->getPixelSize(); Ogre::Image* img = ds->getImage(); Ogre::PixelBox srcPixels = img->getPixelBox(); // convert if the source data don't match if(img->getFormat() != Ogre::PF_BYTE_BGRA) { conversionBuf = new unsigned char[img->getWidth() * img->getHeight() * pixelsize]; Ogre::PixelBox convPixels(Ogre::Box(0, 0, dps.width, dps.height), Ogre::PF_BYTE_BGRA, conversionBuf); Ogre::PixelUtil::bulkPixelConversion(srcPixels, convPixels); srcPixels = convPixels; } size_t srcrowsize = srcPixels.rowPitch * pixelsize; Ogre::uint8* srcData = static_cast<Ogre::uint8*>(srcPixels.data); // TODO: we're always handling 32bit data, so we could as well transfer 4 bytes each iteration instead of one (speedup) for(size_t row = 0; row < dps.height; row++) { for(size_t col = 0; col < srcrowsize; col++) { dstData[((row + fsi->y) * rowsize) + (fsi->x * pixelsize) + col] = srcData[(row * srcrowsize) + col]; } } delete[] conversionBuf; // Convert the full draw source pixel coordinates to the atlas contained ones (initializes the texturing coordinates transform) ds->atlas(mMaterial, fsi->x, fsi->y, mAtlasSize.width, mAtlasSize.height); } // for debug, write the texture to a file /*unsigned char *readrefdata = static_cast<unsigned char*>(targetBox.data); Ogre::Image img; img = img.loadDynamicImage (readrefdata, mTexture->getWidth(), mTexture->getHeight(), mTexture->getFormat()); img.save(mAtlasName + ".png");*/ // and close the pixel buffer of the atlas at the end pixelBuffer->unlock(); mIsDirty = false; }
void GlobalMap::exploreCell(int cellX, int cellY) { float originX = static_cast<float>((cellX - mMinX) * mCellSize); // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is float originY = static_cast<float>(mHeight - (cellY + 1 - mMinY) * mCellSize); if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) return; Ogre::TexturePtr localMapTexture = Ogre::TextureManager::getSingleton().getByName("Cell_" + boost::lexical_cast<std::string>(cellX) + "_" + boost::lexical_cast<std::string>(cellY)); if (!localMapTexture.isNull()) { int mapWidth = localMapTexture->getWidth(); int mapHeight = localMapTexture->getHeight(); mOverlayTexture->load(); mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,mapWidth,mapHeight), Ogre::Image::Box(static_cast<Ogre::uint32>(originX), static_cast<Ogre::uint32>(originY), static_cast<Ogre::uint32>(originX + mCellSize), static_cast<Ogre::uint32>(originY + mCellSize))); Ogre::Image backup; std::vector<Ogre::uchar> data; data.resize(mCellSize*mCellSize*4, 0); backup.loadDynamicImage(&data[0], mCellSize, mCellSize, Ogre::PF_A8B8G8R8); localMapTexture->getBuffer()->blitToMemory(Ogre::Image::Box(0,0,mapWidth,mapHeight), backup.getPixelBox()); for (int x=0; x<mCellSize; ++x) for (int y=0; y<mCellSize; ++y) { assert (originX+x < mOverlayImage.getWidth()); assert (originY+y < mOverlayImage.getHeight()); assert (x < int(backup.getWidth())); assert (y < int(backup.getHeight())); mOverlayImage.setColourAt(backup.getColourAt(x, y, 0), static_cast<size_t>(originX + x), static_cast<size_t>(originY + y), 0); } } }
void Terrain::_createAtlasPixmap(size_t pixmapId) { const TerrainData::Pixmap& pixmap = mData->mPixmaps[pixmapId]; size_t textureId = pixmap.textureId; assert(textureId < mData->mTextures.size()); const Ogre::String& textureName = mData->mTextures[textureId]; // If the atlas texture already exist, use it. AtlasArray::const_iterator it; for (it = mAtlases.begin(); it != mAtlases.end(); ++it) { if (it->texture->getName() == textureName) break; } if (it != mAtlases.end()) { // Fill up atlas pixmap info size_t atlasId = it - mAtlases.begin() + 1; mAtlasPixmaps[pixmapId].atlasId = atlasId; mAtlasPixmaps[pixmapId].left = pixmap.left; mAtlasPixmaps[pixmapId].top = pixmap.top; mAtlasPixmaps[pixmapId].right = pixmap.right; mAtlasPixmaps[pixmapId].bottom = pixmap.bottom; return; } // If texture already loaded and is composited, use it without any modify. Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName(textureName); if (!texture.isNull() && (texture->getWidth() > mAtlasPixmapSize || texture->getHeight() > mAtlasPixmapSize)) { mAtlases.push_back(Atlas()); Atlas& atlas = mAtlases.back(); atlas.texture = texture; // Fill up atlas pixmap info size_t atlasId = mAtlases.size(); mAtlasPixmaps[pixmapId].atlasId = atlasId; mAtlasPixmaps[pixmapId].left = pixmap.left; mAtlasPixmaps[pixmapId].top = pixmap.top; mAtlasPixmaps[pixmapId].right = pixmap.right; mAtlasPixmaps[pixmapId].bottom = pixmap.bottom; return; } // Load the image Ogre::Image image; image.load(textureName, BRUSH_RESOURCE_GROUP_NAME); // If the image is composited, use it without any modify. if (image.getWidth() > mAtlasPixmapSize || image.getHeight() > mAtlasPixmapSize) { mAtlases.push_back(Atlas()); Atlas& atlas = mAtlases.back(); // re-use the loaded image avoid load it again atlas.texture = Ogre::TextureManager::getSingleton() .loadImage(textureName, BRUSH_RESOURCE_GROUP_NAME, image); // Fill up atlas pixmap info size_t atlasId = mAtlases.size(); mAtlasPixmaps[pixmapId].atlasId = atlasId; mAtlasPixmaps[pixmapId].left = pixmap.left; mAtlasPixmaps[pixmapId].top = pixmap.top; mAtlasPixmaps[pixmapId].right = pixmap.right; mAtlasPixmaps[pixmapId].bottom = pixmap.bottom; return; } // Composite into the atlas texture. bool isTransparent = image.getHasAlpha(); AtlasAllocInfo& allocInfo = isTransparent ? mTransparentAtlasAllocInfo : mSolidAtlasAllocInfo; if (allocInfo.blockId >= mMaxAtlasBlockId) { // Use special name to avoid confuse with other reference with this texture Ogre::String atlasName = "<Terrain/Atlas>:" + Ogre::StringConverter::toString(mAtlases.size()); mAtlases.push_back(Atlas()); Atlas& atlas = mAtlases.back(); Ogre::PixelFormat pixelFormat = isTransparent ? Ogre::PF_A8R8G8B8 : Ogre::PF_X8R8G8B8; atlas.image.bind(new Ogre::Image); atlas.image->loadDynamicImage(0, mAtlasTextureSize, mAtlasTextureSize, 1, pixelFormat, true, 1, mAtlasNumMipMaps); memset(atlas.image->getData(), 0, atlas.image->getSize()); atlas.texture = Ogre::TextureManager::getSingleton().createManual(atlasName, BRUSH_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, atlas.image->getWidth(), atlas.image->getHeight(), mAtlasNumMipMaps, atlas.image->getFormat(), Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE, this); allocInfo.atlasId = mAtlases.size(); allocInfo.blockId = 0; } // Copy origin pixmap to atlas image Atlas& atlas = mAtlases[allocInfo.atlasId - 1]; int blockX = allocInfo.blockId % mAtlasBlockSize; int blockY = allocInfo.blockId / mAtlasBlockSize; Ogre::PixelBox dst = atlas.image->getPixelBox().getSubVolume(Ogre::Box( blockX * mAtlasPixmapSize, blockY * mAtlasPixmapSize, blockX * mAtlasPixmapSize + mAtlasPixmapSize, blockY * mAtlasPixmapSize + mAtlasPixmapSize)); Ogre::PixelBox src = image.getPixelBox().getSubVolume(Ogre::Box( fast_ifloor(pixmap.left * image.getWidth() + 0.5f), fast_ifloor(pixmap.top * image.getHeight() + 0.5f), fast_ifloor(pixmap.right * image.getWidth() + 0.5f), fast_ifloor(pixmap.bottom * image.getHeight() + 0.5f))); if (src.getWidth() == mAtlasPixmapSize && src.getHeight() == mAtlasPixmapSize) Ogre::PixelUtil::bulkPixelConversion(src, dst); else Ogre::Image::scale(src, dst); // Generate mipmaps manual for (size_t mipmap = 1; mipmap <= mAtlasNumMipMaps; ++mipmap) { src = dst; size_t pixmapSize = mAtlasPixmapSize >> mipmap; dst = atlas.image->getPixelBox(0, mipmap).getSubVolume(Ogre::Box( blockX * pixmapSize, blockY * pixmapSize, blockX * pixmapSize + pixmapSize, blockY * pixmapSize + pixmapSize)); Ogre::Image::scale(src, dst); } // Notify that the atlas texture need to reload if (atlas.texture->isLoaded()) atlas.texture->unload(); ++allocInfo.blockId; // Fill up atlas pixmap info mAtlasPixmaps[pixmapId].atlasId = allocInfo.atlasId; mAtlasPixmaps[pixmapId].left = blockX * mAtlasBlockTexCoordInc + 0.5f / mAtlasTextureSize; mAtlasPixmaps[pixmapId].top = blockY * mAtlasBlockTexCoordInc + 0.5f / mAtlasTextureSize; mAtlasPixmaps[pixmapId].right = mAtlasPixmaps[pixmapId].left + mAtlasBlockTexCoordInc - 1.0f / mAtlasTextureSize; mAtlasPixmaps[pixmapId].bottom = mAtlasPixmaps[pixmapId].top + mAtlasBlockTexCoordInc - 1.0f / mAtlasTextureSize; }