diff --git a/apps/opencs/model/world/cellcoordinates.cpp b/apps/opencs/model/world/cellcoordinates.cpp index 9f98c7b4c..af8c26d70 100644 --- a/apps/opencs/model/world/cellcoordinates.cpp +++ b/apps/opencs/model/world/cellcoordinates.cpp @@ -91,9 +91,14 @@ std::pair CSMWorld::CellCoordinates::toVertexCoords(const osg::Vec3d& return std::make_pair(x, y); } -float CSMWorld::CellCoordinates::textureGlobalToWorldCoords(int textureGlobal) +float CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(int textureGlobal) { - return ESM::Land::REAL_SIZE * static_cast(textureGlobal) / ESM::Land::LAND_TEXTURE_SIZE; + return ESM::Land::REAL_SIZE * (static_cast(textureGlobal) + 0.25f) / ESM::Land::LAND_TEXTURE_SIZE; +} + +float CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(int textureGlobal) +{ + return ESM::Land::REAL_SIZE * (static_cast(textureGlobal) - 0.25f) / ESM::Land::LAND_TEXTURE_SIZE; } float CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(int vertexGlobal) diff --git a/apps/opencs/model/world/cellcoordinates.hpp b/apps/opencs/model/world/cellcoordinates.hpp index 77d76f6ef..9317c28b2 100644 --- a/apps/opencs/model/world/cellcoordinates.hpp +++ b/apps/opencs/model/world/cellcoordinates.hpp @@ -54,8 +54,11 @@ namespace CSMWorld ///Converts worldspace coordinates to global vertex selection. static std::pair toVertexCoords(const osg::Vec3d& worldPos); - ///Converts global texture coordinate to worldspace coordinate that is at the upper left corner of the selected texture. - static float textureGlobalToWorldCoords(int textureGlobal); + ///Converts global texture coordinate X to worldspace coordinate, offset by 0.25f. + static float textureGlobalXToWorldCoords(int textureGlobal); + + ///Converts global texture coordinate Y to worldspace coordinate, offset by 0.25f. + static float textureGlobalYToWorldCoords(int textureGlobal); ///Converts global vertex coordinate to worldspace coordinate static float vertexGlobalToWorldCoords(int vertexGlobal); diff --git a/apps/opencs/view/render/brushdraw.cpp b/apps/opencs/view/render/brushdraw.cpp index b963b09f5..0280d19ce 100644 --- a/apps/opencs/view/render/brushdraw.cpp +++ b/apps/opencs/view/render/brushdraw.cpp @@ -5,25 +5,23 @@ #include #include #include -#include -#include -#include #include +#include "../../model/world/cellcoordinates.hpp" #include "../widget/brushshapes.hpp" #include "mask.hpp" CSVRender::BrushDraw::BrushDraw(osg::ref_ptr parentNode, bool textureMode) : - mParentNode(parentNode) + mParentNode(parentNode), mTextureMode(textureMode) { mBrushDrawNode = new osg::Group(); mGeometry = new osg::Geometry(); mBrushDrawNode->addChild(mGeometry); mParentNode->addChild(mBrushDrawNode); - if (textureMode) mLandSizeFactor = ESM::Land::REAL_SIZE / ESM::Land::LAND_TEXTURE_SIZE / 2; - else mLandSizeFactor = ESM::Land::REAL_SIZE / ESM::Land::LAND_SIZE / 2; + if (mTextureMode) mLandSizeFactor = ESM::Land::REAL_SIZE / ESM::Land::LAND_TEXTURE_SIZE; + else mLandSizeFactor = ESM::Land::REAL_SIZE / ESM::Land::LAND_SIZE; } CSVRender::BrushDraw::~BrushDraw() @@ -37,7 +35,7 @@ float CSVRender::BrushDraw::getIntersectionHeight (const osg::Vec3d& point) osg::Vec3d start = point; osg::Vec3d end = point; start.z() = std::numeric_limits::max(); - end.z() = std::numeric_limits::min(); + end.z() = std::numeric_limits::lowest(); osg::Vec3d direction = end - start; // Get intersection @@ -66,9 +64,52 @@ float CSVRender::BrushDraw::getIntersectionHeight (const osg::Vec3d& point) return 0.0f; } -void CSVRender::BrushDraw::buildPointGeometry(const float& radius, const osg::Vec3d& point) +void CSVRender::BrushDraw::buildPointGeometry(const osg::Vec3d& point) { - // Not implemented + osg::ref_ptr geom = new osg::Geometry(); + osg::ref_ptr vertices (new osg::Vec3Array()); + osg::ref_ptr colors (new osg::Vec4Array()); + const float brushOutlineHeight (1.0f); + const float crossHeadSize (8.0f); + osg::Vec4f lineColor(1.0f, 1.0f, 1.0f, 0.6f); + + vertices->push_back(osg::Vec3d( + point.x() - crossHeadSize, + point.y() - crossHeadSize, + getIntersectionHeight(osg::Vec3d( + point.x() - crossHeadSize, + point.y() - crossHeadSize, + point.z()) ) + brushOutlineHeight)); + colors->push_back(lineColor); + vertices->push_back(osg::Vec3d( + point.x() + crossHeadSize, + point.y() + crossHeadSize, + getIntersectionHeight(osg::Vec3d( + point.x() + crossHeadSize, + point.y() + crossHeadSize, + point.z()) ) + brushOutlineHeight)); + colors->push_back(lineColor); + vertices->push_back(osg::Vec3d( + point.x() + crossHeadSize, + point.y() - crossHeadSize, + getIntersectionHeight(osg::Vec3d( + point.x() + crossHeadSize, + point.y() - crossHeadSize, + point.z()) ) + brushOutlineHeight)); + colors->push_back(lineColor); + vertices->push_back(osg::Vec3d( + point.x() - crossHeadSize, + point.y() + crossHeadSize, + getIntersectionHeight(osg::Vec3d( + point.x() - crossHeadSize, + point.y() + crossHeadSize, + point.z()) ) + brushOutlineHeight)); + colors->push_back(lineColor); + + geom->setVertexArray(vertices); + geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX); + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 4)); + mGeometry = geom; } void CSVRender::BrushDraw::buildSquareGeometry(const float& radius, const osg::Vec3d& point) @@ -76,46 +117,95 @@ void CSVRender::BrushDraw::buildSquareGeometry(const float& radius, const osg::V osg::ref_ptr geom = new osg::Geometry(); osg::ref_ptr vertices (new osg::Vec3Array()); osg::ref_ptr colors (new osg::Vec4Array()); - std::vector corners; - const float brushOutLineHeight (200.0f); - corners.push_back(osg::Vec3d(point.x() - radius, point.y() - radius, point.z())); - corners.push_back(osg::Vec3d(point.x() + radius, point.y() - radius, point.z())); - corners.push_back(osg::Vec3d(point.x() + radius, point.y() + radius, point.z())); - corners.push_back(osg::Vec3d(point.x() - radius, point.y() + radius, point.z())); - corners.push_back(osg::Vec3d(point.x() - radius, point.y() - radius, point.z())); + const float brushOutlineHeight (1.0f); + float diameter = radius * 2; + int resolution = (diameter / mLandSizeFactor) * 2; //half a vertex resolution + float resAdjustedLandSizeFactor = mLandSizeFactor / 2; + osg::Vec4f lineColor(1.0f, 1.0f, 1.0f, 0.6f); - for (const auto& point : corners) + for (int i = 0; i < resolution; i++) { - vertices->push_back(osg::Vec3d( - point.x(), - point.y(), + int step = i * resAdjustedLandSizeFactor; + int step2 = (i + 1) * resAdjustedLandSizeFactor; + + osg::Vec3d upHorizontalLinePoint1( + point.x() - radius + step, + point.y() - radius, getIntersectionHeight(osg::Vec3d( - point.x(), - point.y(), - point.z()) ))); - colors->push_back(osg::Vec4f( - 50.0f, - 50.0f, - 50.0f, - 100.0f)); - vertices->push_back(osg::Vec3d( - point.x(), - point.y(), + point.x() - radius + step, + point.y() - radius, + point.z())) + brushOutlineHeight); + osg::Vec3d upHorizontalLinePoint2( + point.x() - radius + step2, + point.y() - radius, + getIntersectionHeight(osg::Vec3d( + point.x() - radius + step2, + point.y() - radius, + point.z())) + brushOutlineHeight); + osg::Vec3d upVerticalLinePoint1( + point.x() - radius, + point.y() - radius + step, getIntersectionHeight(osg::Vec3d( - point.x(), - point.y(), - point.z())) + brushOutLineHeight)); - colors->push_back(osg::Vec4f( - 50.0f, - 50.0f, - 50.0f, - 100.0f)); + point.x() - radius, + point.y() - radius + step, + point.z())) + brushOutlineHeight); + osg::Vec3d upVerticalLinePoint2( + point.x() - radius, + point.y() - radius + step2, + getIntersectionHeight(osg::Vec3d( + point.x() - radius, + point.y() - radius + step2, + point.z())) + brushOutlineHeight); + osg::Vec3d downHorizontalLinePoint1( + point.x() + radius - step, + point.y() + radius, + getIntersectionHeight(osg::Vec3d( + point.x() + radius - step, + point.y() + radius, + point.z())) + brushOutlineHeight); + osg::Vec3d downHorizontalLinePoint2( + point.x() + radius - step2, + point.y() + radius, + getIntersectionHeight(osg::Vec3d( + point.x() + radius - step2, + point.y() + radius, + point.z())) + brushOutlineHeight); + osg::Vec3d downVerticalLinePoint1( + point.x() + radius, + point.y() + radius - step, + getIntersectionHeight(osg::Vec3d( + point.x() + radius, + point.y() + radius - step, + point.z())) + brushOutlineHeight); + osg::Vec3d downVerticalLinePoint2( + point.x() + radius, + point.y() + radius - step2, + getIntersectionHeight(osg::Vec3d( + point.x() + radius, + point.y() + radius - step2, + point.z())) + brushOutlineHeight); + vertices->push_back(upHorizontalLinePoint1); + colors->push_back(lineColor); + vertices->push_back(upHorizontalLinePoint2); + colors->push_back(lineColor); + vertices->push_back(upVerticalLinePoint1); + colors->push_back(lineColor); + vertices->push_back(upVerticalLinePoint2); + colors->push_back(lineColor); + vertices->push_back(downHorizontalLinePoint1); + colors->push_back(lineColor); + vertices->push_back(downHorizontalLinePoint2); + colors->push_back(lineColor); + vertices->push_back(downVerticalLinePoint1); + colors->push_back(lineColor); + vertices->push_back(downVerticalLinePoint2); + colors->push_back(lineColor); } geom->setVertexArray(vertices); geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX); - geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, (10 + 2) - 2)); + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, resolution * 8)); mGeometry = geom; } @@ -126,7 +216,8 @@ void CSVRender::BrushDraw::buildCircleGeometry(const float& radius, const osg::V osg::ref_ptr colors (new osg::Vec4Array()); const int amountOfPoints = (osg::PI * 2.0f) * radius / 20; const float step ((osg::PI * 2.0f) / static_cast(amountOfPoints)); - const float brushOutLineHeight (200.0f); + const float brushOutlineHeight (1.0f); + osg::Vec4f lineColor(1.0f, 1.0f, 1.0f, 0.6f); for (int i = 0; i < amountOfPoints + 2; i++) { @@ -137,12 +228,8 @@ void CSVRender::BrushDraw::buildCircleGeometry(const float& radius, const osg::V getIntersectionHeight(osg::Vec3d( point.x() + radius * cosf(angle), point.y() + radius * sinf(angle), - point.z()) ))); - colors->push_back(osg::Vec4f( - 50.0f, - 50.0f, - 50.0f, - 100.0f)); + point.z()) ) + brushOutlineHeight)); + colors->push_back(lineColor); angle = static_cast(i + 1) * step; vertices->push_back(osg::Vec3d( point.x() + radius * cosf(angle), @@ -150,17 +237,13 @@ void CSVRender::BrushDraw::buildCircleGeometry(const float& radius, const osg::V getIntersectionHeight(osg::Vec3d( point.x() + radius * cosf(angle), point.y() + radius * sinf(angle), - point.z()) ) + brushOutLineHeight)); - colors->push_back(osg::Vec4f( - 50.0f, - 50.0f, - 50.0f, - 100.0f)); + point.z()) ) + brushOutlineHeight)); + colors->push_back(lineColor); } geom->setVertexArray(vertices); geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX); - geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, (amountOfPoints + 2) * 2 - 2)); + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, amountOfPoints * 2)); mGeometry = geom; } @@ -173,39 +256,45 @@ void CSVRender::BrushDraw::update(osg::Vec3d point, int brushSize, CSVWidget::Br { if (mBrushDrawNode->containsNode(mGeometry)) mBrushDrawNode->removeChild(mGeometry); mBrushDrawNode->setNodeMask (Mask_EditModeCursor); - float radius = static_cast(brushSize * mLandSizeFactor); + float radius = (mLandSizeFactor * brushSize) / 2; + osg::Vec3d snapToGridPoint = point; + if (mTextureMode) + { + std::pair snapToGridXY = CSMWorld::CellCoordinates::toTextureCoords(point); + float offsetToMiddle = mLandSizeFactor * 0.5f; + snapToGridPoint = osg::Vec3d( + CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(snapToGridXY.first) + offsetToMiddle, + CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(snapToGridXY.second) + offsetToMiddle, + point.z()); + } + else + { + std::pair snapToGridXY = CSMWorld::CellCoordinates::toVertexCoords(point); + snapToGridPoint = osg::Vec3d( + CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(snapToGridXY.first), + CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(snapToGridXY.second), + point.z()); + } + switch (toolShape) { case (CSVWidget::BrushShape_Point) : - buildSquareGeometry(1, point); - //buildPointGeometry(radius, point); + buildPointGeometry(snapToGridPoint); break; case (CSVWidget::BrushShape_Square) : - buildSquareGeometry(radius, point); + buildSquareGeometry(radius, snapToGridPoint); break; case (CSVWidget::BrushShape_Circle) : - buildCircleGeometry(radius, point); + buildCircleGeometry(radius, snapToGridPoint); break; case (CSVWidget::BrushShape_Custom) : - buildSquareGeometry(1, point); + buildSquareGeometry(1, snapToGridPoint); //buildCustomGeometry break; } - osg::BlendFunc* blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA); - mGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc); - - mGeometry->getOrCreateStateSet()->setMode( GL_CULL_FACE, osg::StateAttribute::OFF ); - - osg::ref_ptr material = new osg::Material; - material->setColorMode(osg::Material::AMBIENT); - material->setAmbient (osg::Material::FRONT_AND_BACK, osg::Vec4(0.3, 0.3, 0.3, 1)); - material->setAlpha(osg::Material::FRONT_AND_BACK, 0.5); - - mGeometry->getOrCreateStateSet()->setAttributeAndModes(material.get(), osg::StateAttribute::ON); - mGeometry->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); - mGeometry->getOrCreateStateSet()->setRenderingHint (osg::StateSet::TRANSPARENT_BIN); + mGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); mBrushDrawNode->addChild(mGeometry); } diff --git a/apps/opencs/view/render/brushdraw.hpp b/apps/opencs/view/render/brushdraw.hpp index 6ecfccde7..0551631cd 100644 --- a/apps/opencs/view/render/brushdraw.hpp +++ b/apps/opencs/view/render/brushdraw.hpp @@ -19,7 +19,7 @@ namespace CSVRender void hide(); private: - void buildPointGeometry(const float& radius, const osg::Vec3d& point); + void buildPointGeometry(const osg::Vec3d& point); void buildSquareGeometry(const float& radius, const osg::Vec3d& point); void buildCircleGeometry(const float& radius, const osg::Vec3d& point); void buildCustomGeometry(const float& radius, const osg::Vec3d& point); @@ -28,6 +28,7 @@ namespace CSVRender osg::ref_ptr mParentNode; osg::ref_ptr mBrushDrawNode; osg::ref_ptr mGeometry; + bool mTextureMode; float mLandSizeFactor; }; } diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index e16a69048..4e209af57 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -171,9 +171,6 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+(i-1), y2)+2)); - vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+i, y2)+2)); + float drawPreviousX = CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + float drawCurrentX = CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + vertices->push_back(osg::Vec3f(drawPreviousX, CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y + 1), calculateLandHeight(x1+(i-1), y2)+2)); + vertices->push_back(osg::Vec3f(drawCurrentX, CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y + 1), calculateLandHeight(x1+i, y2)+2)); } } @@ -208,10 +205,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+(i-1), y1)+2)); - vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+i, y1)+2)); + float drawPreviousX = CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x) + (i - 1) *(ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + float drawCurrentX = CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + vertices->push_back(osg::Vec3f(drawPreviousX, CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y), calculateLandHeight(x1+(i-1), y1)+2)); + vertices->push_back(osg::Vec3f(drawCurrentX, CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y), calculateLandHeight(x1+i, y1)+2)); } } @@ -220,10 +217,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x + 1) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x2, y1+(i-1))+2)); - vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x + 1) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x2, y1+i)+2)); + float drawPreviousY = CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + float drawCurrentY = CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x + 1), drawPreviousY, calculateLandHeight(x2, y1+(i-1))+2)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x + 1), drawCurrentY, calculateLandHeight(x2, y1+i)+2)); } } @@ -232,10 +229,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x1, y1+(i-1))+2)); - vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x1, y1+i)+2)); + float drawPreviousY = CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + float drawCurrentY = CSMWorld::CellCoordinates::textureGlobalYToWorldCoords(y) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x), drawPreviousY, calculateLandHeight(x1, y1+(i-1))+2)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalXToWorldCoords(x), drawCurrentY, calculateLandHeight(x1, y1+i)+2)); } } }