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(); } }
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(); } } }
//----------------------------------------------------------------------------------------- void CTerrainGroupEditor::_splat(CTerrainPageEditor *handle, Ogre::Vector3 &editpos, float timePassed) { Ogre::Rect brushrect, maprect; Ogre::Terrain *terrain = static_cast<Ogre::Terrain*>(handle->getHandle()); int mBlendMapSize = terrain->getLayerBlendMapSize(); editpos.x *= (float)mBlendMapSize; editpos.y = (1.0f - editpos.y) * (float)mBlendMapSize; if(!_getEditRect(editpos, brushrect, maprect, mBlendMapSize)) return; int mLayer = 0; mLayer = handle->_getLayerID(mTextureDiffuse, mTextureNormal, mEditDirection); if(mLayer == -1) { Ogre::String msg = handle->getName() + " already has the maximum number of supported texture layers."; mSystem->DisplayMessageDialog(OTR(msg), DLGTYPE_OK); return; } else if(mLayer == 0) { Ogre::TerrainLayerBlendMap *mBlendMaps[128]; float *mBlendDatas[128]; int mLayerMax = terrain->getLayerCount(); for(int l = 1;l < mLayerMax;l++) { mBlendMaps[l] = terrain->getLayerBlendMap(l); mBlendDatas[l] = mBlendMaps[l]->getBlendPointer(); } float maxVal; int u; int num; for(u = mLayerMax-1;u > 0;u--) { mLayer = u; maxVal = 0.0f; for(int j = maprect.top;j < maprect.bottom;j++) { int mapPos = (j * mBlendMapSize) + maprect.left; for(int i = maprect.left;i < maprect.right;i++) { maxVal += mBlendDatas[u][mapPos]; } } num = (maprect.top*mBlendMapSize); num = (num+maprect.right)-(num+maprect.left); if (maxVal > num) break; } if (mLayer == 0) return; mEditDirection = true; } handle->_notifyModification(mLayer, maprect); int mLayerMax = terrain->getLayerCount(); Ogre::TerrainLayerBlendMap *mBlendMaps[128]; float *mBlendDatas[128]; Ogre::TerrainLayerBlendMap *mCurrentBlendMap = terrain->getLayerBlendMap(mLayer); float *mCurrentBlendData = mCurrentBlendMap->getBlendPointer(); for(int l = mLayer;l < mLayerMax;l++) { mBlendMaps[l] = terrain->getLayerBlendMap(l); mBlendDatas[l] = mBlendMaps[l]->getBlendPointer(); } float mRatio = (float)BRUSH_DATA_SIZE / (float)mBrushSize; float brushPos; int mapPos; int right = brushrect.right; brushrect.right = BRUSH_DATA_SIZE - brushrect.left; brushrect.left = BRUSH_DATA_SIZE - right; float factor = mBrushIntensity * timePassed * 0.2f; if(!mEditDirection) { int u; float sum; for(int j = maprect.top;j < maprect.bottom;j++) { brushPos = (brushrect.top + (int)((j - maprect.top) * mRatio)) * BRUSH_DATA_SIZE; brushPos += brushrect.right; mapPos = (j * mBlendMapSize) + maprect.left; for(int i = maprect.left;i < maprect.right;i++) { brushPos -= mRatio; assert(mapPos < (mBlendMapSize * mBlendMapSize) && mapPos >= 0); assert((int)brushPos < (BRUSH_DATA_SIZE * BRUSH_DATA_SIZE) && (int)brushPos >= 0); sum = 0.0f; for(u = mLayer + 1;u < mLayerMax;u++) sum += mBlendDatas[u][mapPos]; float val = mCurrentBlendData[mapPos] + (mBrushData[(int)brushPos] * factor); sum += val; if(sum > 1.0f) { float normfactor = 1.0f / (float)sum; mCurrentBlendData[mapPos] = val * normfactor; for(u = mLayer + 1;u < mLayerMax;u++) mBlendDatas[u][mapPos] *= normfactor; } else mCurrentBlendData[mapPos] = val; ++mapPos; } } for(u = mLayer;u < mLayerMax;u++) { mBlendMaps[u]->dirtyRect(maprect); mBlendMaps[u]->update(); } } else { for(int j = maprect.top;j < maprect.bottom;j++) { brushPos = (brushrect.top + (int)((j - maprect.top) * mRatio)) * BRUSH_DATA_SIZE; brushPos += brushrect.right; mapPos = (j * mBlendMapSize) + maprect.left; for(int i = maprect.left;i < maprect.right;i++) { brushPos -= mRatio; assert(mapPos < (mBlendMapSize * mBlendMapSize) && mapPos >= 0); assert((int)brushPos < (BRUSH_DATA_SIZE * BRUSH_DATA_SIZE) && (int)brushPos >= 0); float val = mCurrentBlendData[mapPos] - (mBrushData[(int)brushPos] * factor); if(val < 0.0f) val = 0.0f; mCurrentBlendData[mapPos] = val; ++mapPos; } } mCurrentBlendMap->dirtyRect(maprect); mCurrentBlendMap->update(); } }
void ManipulatorTerrain::OnEdit( float dt ) { assert(m_curEditMode != eTerrainEditMode_None); //第0层不能编辑BlendMap,应该从第1层开始 if(m_curEditMode == eTerrainEditMode_Splat && m_curEditLayer == 0) return; Ogre::Terrain* pTerrain = ManipulatorSystem.GetScene()->GetTerrain(); const Vector3 brushPos = m_brush[m_curBrushIndex]->GetPosition(); Vector3 tsPos; pTerrain->getTerrainPosition(brushPos, &tsPos); float brushSizeW, brushSizeH; m_brush[m_curBrushIndex]->GetDimension(brushSizeW, brushSizeH); float worldSize = GetWorldSize(); brushSizeW /= worldSize; brushSizeH /= worldSize; int multiplier; Ogre::TerrainLayerBlendMap* layer = nullptr; if(m_curEditMode == eTerrainEditMode_Deform) { multiplier = pTerrain->getSize() - 1; } else { multiplier = pTerrain->getLayerBlendMapSize(); layer = pTerrain->getLayerBlendMap(m_curEditLayer); } long startx = (long)((tsPos.x - brushSizeW / 2) * multiplier); long starty = (long)((tsPos.y - brushSizeH / 2) * multiplier); long endx = (long)((tsPos.x + brushSizeW / 2) * multiplier); long endy= (long)((tsPos.y + brushSizeH / 2) * multiplier); startx = max(startx, 0L); starty = max(starty, 0L); endx = min(endx, (long)multiplier); endy = min(endy, (long)multiplier); for (long y = starty; y <= endy; ++y) { for (long x = startx; x <= endx; ++x) { float tsXdist = (x / multiplier) - tsPos.x; float tsYdist = (y / multiplier) - tsPos.y; if(m_curEditMode == eTerrainEditMode_Deform) { float* pData = pTerrain->getHeightData(); pData[y*GetMapSize()+x] += 100.0f * dt; } else { float* pData = layer->getBlendPointer(); size_t imgY = multiplier - y; float newValue = pData[imgY*multiplier+x] + dt; newValue = Ogre::Math::Clamp(newValue, 0.0f, 1.0f); pData[imgY*multiplier+x] = newValue; } } } if(m_curEditMode == eTerrainEditMode_Deform) { Ogre::Rect rect(startx, starty, endx, endy); pTerrain->dirtyRect(rect); pTerrain->update(); } else { size_t imgStartY = multiplier - starty; size_t imgEndY = multiplier - endy; Ogre::Rect rect(startx, min(imgStartY,imgEndY), endx, max(imgStartY,imgEndY)); layer->dirtyRect(rect); layer->update(); } }
//----------------------------------------------------------------------------------------- void CTerrainGroupEditor::_splat(CTerrainPageEditor *handle, Ogre::Vector3 &editpos, float timePassed) { Ogre::Rect brushrect, maprect; Ogre::Terrain *terrain = static_cast<Ogre::Terrain*>(handle->getHandle()); int mBlendMapSize = terrain->getLayerBlendMapSize(); editpos.x *= (float)mBlendMapSize; editpos.y = (1.0f - editpos.y) * (float)mBlendMapSize; if(!_getEditRect(editpos, brushrect, maprect, mBlendMapSize)) return; int mLayer = 0; mLayer = handle->_getLayerID(mTextureDiffuse, mTextureNormal, mEditDirection); if(mLayer < 1) return; handle->_notifyModification(mLayer, maprect); int mLayerMax = terrain->getLayerCount(); Ogre::TerrainLayerBlendMap *mBlendMaps[128]; float *mBlendDatas[128]; Ogre::TerrainLayerBlendMap *mCurrentBlendMap = terrain->getLayerBlendMap(mLayer); float *mCurrentBlendData = mCurrentBlendMap->getBlendPointer(); for(int l = mLayer;l < mLayerMax;l++) { mBlendMaps[l] = terrain->getLayerBlendMap(l); mBlendDatas[l] = mBlendMaps[l]->getBlendPointer(); } float mRatio = (float)BRUSH_DATA_SIZE / (float)mBrushSize; float brushPos; int mapPos; int right = brushrect.right; brushrect.right = BRUSH_DATA_SIZE - brushrect.left; brushrect.left = BRUSH_DATA_SIZE - right; float factor = mBrushIntensity * timePassed * 0.2f; if(!mEditDirection) { int u; float sum; for(int j = maprect.top;j < maprect.bottom;j++) { brushPos = (brushrect.top + (int)((j - maprect.top) * mRatio)) * BRUSH_DATA_SIZE; brushPos += brushrect.right; mapPos = (j * mBlendMapSize) + maprect.left; for(int i = maprect.left;i < maprect.right;i++) { brushPos -= mRatio; assert(mapPos < (mBlendMapSize * mBlendMapSize) && mapPos >= 0); assert((int)brushPos < (BRUSH_DATA_SIZE * BRUSH_DATA_SIZE) && (int)brushPos >= 0); sum = 0.0f; for(u = mLayer + 1;u < mLayerMax;u++) sum += mBlendDatas[u][mapPos]; float val = mCurrentBlendData[mapPos] + (mBrushData[(int)brushPos] * factor); sum += val; if(sum > 1.0f) { float normfactor = 1.0f / (float)sum; mCurrentBlendData[mapPos] = val * normfactor; for(u = mLayer + 1;u < mLayerMax;u++) mBlendDatas[u][mapPos] *= normfactor; } else mCurrentBlendData[mapPos] = val; ++mapPos; } } for(u = mLayer;u < mLayerMax;u++) { mBlendMaps[u]->dirtyRect(maprect); mBlendMaps[u]->update(); } } else { for(int j = maprect.top;j < maprect.bottom;j++) { brushPos = (brushrect.top + (int)((j - maprect.top) * mRatio)) * BRUSH_DATA_SIZE; brushPos += brushrect.right; mapPos = (j * mBlendMapSize) + maprect.left; for(int i = maprect.left;i < maprect.right;i++) { brushPos -= mRatio; assert(mapPos < (mBlendMapSize * mBlendMapSize) && mapPos >= 0); assert((int)brushPos < (BRUSH_DATA_SIZE * BRUSH_DATA_SIZE) && (int)brushPos >= 0); float val = mCurrentBlendData[mapPos] - (mBrushData[(int)brushPos] * factor); if(val < 0.0f) val = 0.0f; mCurrentBlendData[mapPos] = val; ++mapPos; } } mCurrentBlendMap->dirtyRect(maprect); mCurrentBlendMap->update(); } }
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; }