diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 74f311c5f..f78c411d2 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -90,7 +90,7 @@ opencs_units (view/render opencs_units_noqt (view/render lighting lightingday lightingnight - lightingbright object cell terrainstorage tagbase cellarrow cellmarker + lightingbright object cell terrainstorage tagbase cellarrow cellmarker cellborder ) opencs_hdrs_noqt (view/render diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index 641aeb088..5348f4683 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -93,6 +93,9 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st mTerrain.reset(new Terrain::TerrainGrid(mCellNode, data.getResourceSystem().get(), NULL, new TerrainStorage(mData), Mask_Terrain)); mTerrain->loadCell(esmLand.mX, esmLand.mY); + + mCellBorder.reset(new CellBorder(mCellNode, mCoordinates)); + mCellBorder->buildShape(esmLand); } } } diff --git a/apps/opencs/view/render/cell.hpp b/apps/opencs/view/render/cell.hpp index 22f9872e3..54f5bea1e 100644 --- a/apps/opencs/view/render/cell.hpp +++ b/apps/opencs/view/render/cell.hpp @@ -16,6 +16,7 @@ #include "object.hpp" #include "cellarrow.hpp" #include "cellmarker.hpp" +#include "cellborder.hpp" class QModelIndex; @@ -44,6 +45,7 @@ namespace CSVRender CSMWorld::CellCoordinates mCoordinates; std::auto_ptr mCellArrows[4]; std::auto_ptr mCellMarker; + std::auto_ptr mCellBorder; bool mDeleted; /// Ignored if cell does not have an object with the given ID. diff --git a/apps/opencs/view/render/cellborder.cpp b/apps/opencs/view/render/cellborder.cpp new file mode 100644 index 000000000..fd0492e5d --- /dev/null +++ b/apps/opencs/view/render/cellborder.cpp @@ -0,0 +1,97 @@ +#include "cellborder.hpp" + +#include +#include +#include +#include +#include + +#include + +#include "mask.hpp" + +#include "../../model/world/cellcoordinates.hpp" + +const int CSVRender::CellBorder::CellSize = ESM::Land::REAL_SIZE; +const int CSVRender::CellBorder::VertexCount = (ESM::Land::LAND_SIZE * 4) - 3; + + +CSVRender::CellBorder::CellBorder(osg::Group* cellNode, const CSMWorld::CellCoordinates& coords) + : mParentNode(cellNode) +{ + mBaseNode = new osg::PositionAttitudeTransform(); + mBaseNode->setNodeMask(Mask_CellBorder); + mBaseNode->setPosition(osg::Vec3f(coords.getX() * CellSize, coords.getY() * CellSize, 10)); + + mParentNode->addChild(mBaseNode); +} + +CSVRender::CellBorder::~CellBorder() +{ + mParentNode->removeChild(mBaseNode); +} + +void CSVRender::CellBorder::buildShape(const ESM::Land& esmLand) +{ + const ESM::Land::LandData* landData = esmLand.getLandData(ESM::Land::DATA_VHGT); + + if (!landData) + return; + + osg::ref_ptr geometry = new osg::Geometry(); + + // Vertices + osg::ref_ptr vertices = new osg::Vec3Array(); + + int x = 0, y = 0; + for (; x < ESM::Land::LAND_SIZE; ++x) + vertices->push_back(osg::Vec3f(scaleToWorld(x), scaleToWorld(y), landData->mHeights[landIndex(x, y)])); + + x = ESM::Land::LAND_SIZE - 1; + for (; y < ESM::Land::LAND_SIZE; ++y) + vertices->push_back(osg::Vec3f(scaleToWorld(x), scaleToWorld(y), landData->mHeights[landIndex(x, y)])); + + y = ESM::Land::LAND_SIZE - 1; + for (; x >= 0; --x) + vertices->push_back(osg::Vec3f(scaleToWorld(x), scaleToWorld(y), landData->mHeights[landIndex(x, y)])); + + x = 0; + for (; y >= 0; --y) + vertices->push_back(osg::Vec3f(scaleToWorld(x), scaleToWorld(y), landData->mHeights[landIndex(x, y)])); + + geometry->setVertexArray(vertices); + + // Color + osg::ref_ptr colors = new osg::Vec4Array(); + colors->push_back(osg::Vec4f(0.f, 0.5f, 0.f, 1.f)); + + geometry->setColorArray(colors); + geometry->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET); + + // Primitive + osg::ref_ptr primitives = + new osg::DrawElementsUShort(osg::PrimitiveSet::LINE_STRIP, VertexCount+1); + + for (size_t i = 0; i < VertexCount; ++i) + primitives->setElement(i, i); + + primitives->setElement(VertexCount, 0); + + geometry->addPrimitiveSet(primitives); + geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + + + osg::ref_ptr geode = new osg::Geode(); + geode->addDrawable(geometry); + mBaseNode->addChild(geode); +} + +size_t CSVRender::CellBorder::landIndex(int x, int y) +{ + return y * ESM::Land::LAND_SIZE + x; +} + +float CSVRender::CellBorder::scaleToWorld(int value) +{ + return (CellSize + 128) * (float)value / ESM::Land::LAND_SIZE; +} diff --git a/apps/opencs/view/render/cellborder.hpp b/apps/opencs/view/render/cellborder.hpp new file mode 100644 index 000000000..c91aa46c6 --- /dev/null +++ b/apps/opencs/view/render/cellborder.hpp @@ -0,0 +1,54 @@ +#ifndef OPENCS_VIEW_CELLBORDER_H +#define OPENCS_VIEW_CELLBORDER_H + +#include + +#include + +namespace osg +{ + class Group; + class PositionAttitudeTransform; +} + +namespace ESM +{ + struct Land; +} + +namespace CSMWorld +{ + class CellCoordinates; +} + +namespace CSVRender +{ + + class CellBorder + { + public: + + CellBorder(osg::Group* cellNode, const CSMWorld::CellCoordinates& coords); + ~CellBorder(); + + void buildShape(const ESM::Land& esmLand); + + private: + + static const int CellSize; + static const int VertexCount; + + size_t landIndex(int x, int y); + float scaleToWorld(int val); + + // unimplemented + CellBorder(const CellBorder&); + CellBorder& operator=(const CellBorder&); + + osg::Group* mParentNode; + osg::ref_ptr mBaseNode; + + }; +} + +#endif