mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-26 08:56:37 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			114 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "cellborder.hpp"
 | |
| 
 | |
| #include <osg/Geometry>
 | |
| #include <osg/Material>
 | |
| #include <osg/PolygonMode>
 | |
| 
 | |
| #include "world.hpp"
 | |
| 
 | |
| #include <components/esm/util.hpp>
 | |
| #include <components/esm3/loadland.hpp>
 | |
| #include <components/resource/scenemanager.hpp>
 | |
| #include <components/terrain/storage.hpp>
 | |
| 
 | |
| namespace Terrain
 | |
| {
 | |
| 
 | |
|     CellBorder::CellBorder(
 | |
|         Terrain::World* world, osg::Group* root, int borderMask, Resource::SceneManager* sceneManager)
 | |
|         : mWorld(world)
 | |
|         , mSceneManager(sceneManager)
 | |
|         , mRoot(root)
 | |
|         , mBorderMask(borderMask)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     osg::ref_ptr<osg::Group> CellBorder::createBorderGeometry(float x, float y, float size, Terrain::Storage* terrain,
 | |
|         Resource::SceneManager* sceneManager, int mask, ESM::RefId worldspace, float offset, osg::Vec4f color)
 | |
|     {
 | |
|         const int cellSize = ESM::getCellSize(worldspace);
 | |
|         const int borderSegments = 40;
 | |
| 
 | |
|         osg::Vec3 cellCorner = osg::Vec3(x * cellSize, y * cellSize, 0);
 | |
|         size *= cellSize;
 | |
| 
 | |
|         osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
 | |
|         osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
 | |
|         osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
 | |
| 
 | |
|         normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
 | |
| 
 | |
|         float borderStep = size / ((float)borderSegments);
 | |
| 
 | |
|         for (int i = 0; i <= 2 * borderSegments; ++i)
 | |
|         {
 | |
|             osg::Vec3f pos = i < borderSegments ? osg::Vec3(i * borderStep, 0.0f, 0.0f)
 | |
|                                                 : osg::Vec3(size, (i - borderSegments) * borderStep, 0.0f);
 | |
| 
 | |
|             pos += cellCorner;
 | |
|             pos += osg::Vec3f(0, 0, terrain->getHeightAt(pos, worldspace) + offset);
 | |
| 
 | |
|             vertices->push_back(pos);
 | |
| 
 | |
|             osg::Vec4f col = i % 2 == 0 ? osg::Vec4f(0, 0, 0, 1) : color;
 | |
| 
 | |
|             colors->push_back(col);
 | |
|         }
 | |
| 
 | |
|         osg::ref_ptr<osg::Geometry> border = new osg::Geometry;
 | |
|         border->setVertexArray(vertices.get());
 | |
|         border->setNormalArray(normals.get());
 | |
|         border->setNormalBinding(osg::Geometry::BIND_OVERALL);
 | |
|         border->setColorArray(colors.get());
 | |
|         border->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
 | |
| 
 | |
|         border->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, vertices->size()));
 | |
| 
 | |
|         osg::ref_ptr<osg::Group> borderGroup = new osg::Group;
 | |
|         borderGroup->addChild(border.get());
 | |
| 
 | |
|         osg::StateSet* stateSet = borderGroup->getOrCreateStateSet();
 | |
|         osg::ref_ptr<osg::Material> material(new osg::Material);
 | |
|         material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
 | |
|         stateSet->setAttribute(material);
 | |
| 
 | |
|         osg::PolygonMode* polygonmode = new osg::PolygonMode;
 | |
|         polygonmode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
 | |
|         stateSet->setAttributeAndModes(polygonmode, osg::StateAttribute::ON);
 | |
| 
 | |
|         sceneManager->recreateShaders(borderGroup, "debug");
 | |
|         borderGroup->setNodeMask(mask);
 | |
| 
 | |
|         return borderGroup;
 | |
|     }
 | |
| 
 | |
|     void CellBorder::createCellBorderGeometry(int x, int y)
 | |
|     {
 | |
|         auto borderGroup = createBorderGeometry(
 | |
|             x, y, 1.f, mWorld->getStorage(), mSceneManager, mBorderMask, mWorld->getWorldspace());
 | |
|         mRoot->addChild(borderGroup);
 | |
| 
 | |
|         mCellBorderNodes[std::make_pair(x, y)] = borderGroup;
 | |
|     }
 | |
| 
 | |
|     void CellBorder::destroyCellBorderGeometry(int x, int y)
 | |
|     {
 | |
|         CellGrid::iterator it = mCellBorderNodes.find(std::make_pair(x, y));
 | |
| 
 | |
|         if (it == mCellBorderNodes.end())
 | |
|             return;
 | |
| 
 | |
|         osg::ref_ptr<osg::Node> borderNode = it->second;
 | |
|         mRoot->removeChild(borderNode);
 | |
| 
 | |
|         mCellBorderNodes.erase(it);
 | |
|     }
 | |
| 
 | |
|     void CellBorder::destroyCellBorderGeometry()
 | |
|     {
 | |
|         for (const auto& v : mCellBorderNodes)
 | |
|             mRoot->removeChild(v.second);
 | |
|         mCellBorderNodes.clear();
 | |
|     }
 | |
| 
 | |
| }
 |