1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-04-01 07:36:41 +00:00

Implement brush outline for terrainshapemode

This commit is contained in:
Nelsson Huotari 2020-02-07 19:04:28 +02:00
parent 4c5d2feee8
commit 24c8b32d4c
10 changed files with 199 additions and 1 deletions

View file

@ -89,7 +89,7 @@ opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget editmode instancemode instanceselectionmode instancemovemode previewwidget editmode instancemode instanceselectionmode instancemovemode
orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller
cellwater terraintexturemode actor terrainselection terrainshapemode cellwater terraintexturemode actor terrainselection terrainshapemode brushdraw
) )
opencs_units_noqt (view/render opencs_units_noqt (view/render

View file

@ -0,0 +1,136 @@
#include "brushdraw.hpp"
#include <osg/Group>
#include <osg/Geometry>
#include <osg/Array>
#include <osg/BlendFunc>
#include <osg/CullFace>
#include <osg/Material>
#include <osgUtil/LineSegmentIntersector>
#include "mask.hpp"
CSVRender::BrushDraw::BrushDraw(osg::Group* parentNode) :
mParentNode(parentNode)
{
mBrushDrawNode = new osg::Group();
mGeometry = new osg::Geometry();
mBrushDrawNode->addChild(mGeometry);
mParentNode->addChild(mBrushDrawNode);
}
CSVRender::BrushDraw::~BrushDraw()
{
if (mBrushDrawNode->containsNode(mGeometry)) mBrushDrawNode->removeChild(mGeometry);
if (mParentNode->containsNode(mBrushDrawNode)) mParentNode->removeChild(mBrushDrawNode);
}
float CSVRender::BrushDraw::getIntersectionHeight (const osg::Vec3d& point)
{
osg::Vec3d start = point;
osg::Vec3d end = point;
start.z() += 8000.0f; // these numbers need fixing
end.z() -= 8000.0f;
osg::Vec3d direction = end - start;
// Get intersection
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector (new osgUtil::LineSegmentIntersector(
osgUtil::Intersector::MODEL, start, end) );
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT);
osgUtil::IntersectionVisitor visitor(intersector);
visitor.setTraversalMask(Mask_Terrain);
mParentNode->accept(visitor);
for (osgUtil::LineSegmentIntersector::Intersections::iterator it = intersector->getIntersections().begin();
it != intersector->getIntersections().end(); ++it)
{
osgUtil::LineSegmentIntersector::Intersection intersection = *it;
// reject back-facing polygons
if (direction * intersection.getWorldIntersectNormal() > 0)
{
continue;
}
return intersection.getWorldIntersectPoint().z();
}
return 0.0f;
}
void CSVRender::BrushDraw::buildGeometry(const float& radius, const osg::Vec3d& point, int amountOfPoints)
{
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> vertices (new osg::Vec3Array());
osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array());
const float step ((osg::PI * 2.0f) / static_cast<float>(amountOfPoints));
for (int i = 0; i < amountOfPoints + 2; i++)
{
float angle (static_cast<float>(i) * step);
vertices->push_back(osg::Vec3d(
point.x() + radius * cosf(angle),
point.y() + radius * sinf(angle),
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));
angle = static_cast<float>(i + 1) * step;
vertices->push_back(osg::Vec3d(
point.x() + radius * cosf(angle),
point.y() + radius * sinf(angle),
getIntersectionHeight(osg::Vec3d(
point.x() + radius * cosf(angle),
point.y() + radius * sinf(angle),
point.z()) ) + 200.0f));
colors->push_back(osg::Vec4f(
50.0f,
50.0f,
50.0f,
100.0f));
}
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));
mGeometry = geom;
}
void CSVRender::BrushDraw::update(osg::Vec3d point, int brushSize)
{
if (mBrushDrawNode->containsNode(mGeometry)) mBrushDrawNode->removeChild(mGeometry);
mBrushDrawNode->setNodeMask (Mask_EditModeCursor);
float radius = static_cast<float>(brushSize * mLandSizeFactor);
int amountOfPoints = (osg::PI * 2.0f) * radius / 20;
buildGeometry(radius, point, amountOfPoints);
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<osg::Material> 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);
mBrushDrawNode->addChild(mGeometry);
}
void CSVRender::BrushDraw::hide()
{
if (mBrushDrawNode->containsNode(mGeometry)) mBrushDrawNode->removeChild(mGeometry);
}

View file

@ -0,0 +1,31 @@
#ifndef CSV_RENDER_BRUSHDRAW_H
#define CSV_RENDER_BRUSHDRAW_H
#include <osg/Group>
#include <osg/Geometry>
#include <components/esm/loadland.hpp>
namespace CSVRender
{
class BrushDraw
{
public:
BrushDraw(osg::Group* parentNode);
~BrushDraw();
void update(osg::Vec3d point, int brushSize);
void hide();
private:
void buildGeometry(const float& radius, const osg::Vec3d& point, int amountOfPoints);
float getIntersectionHeight (const osg::Vec3d& point);
osg::Group* mParentNode;
osg::ref_ptr<osg::Group> mBrushDrawNode;
osg::ref_ptr<osg::Geometry> mGeometry;
float mLandSizeFactor = ESM::Land::REAL_SIZE / ESM::Land::LAND_SIZE / 2;
};
}
#endif

View file

@ -73,6 +73,8 @@ void CSVRender::EditMode::dropEvent (QDropEvent *event) {}
void CSVRender::EditMode::dragMoveEvent (QDragMoveEvent *event) {} void CSVRender::EditMode::dragMoveEvent (QDragMoveEvent *event) {}
void CSVRender::EditMode::mouseMoveEvent (QMouseEvent *event) {}
int CSVRender::EditMode::getSubMode() const int CSVRender::EditMode::getSubMode() const
{ {
return -1; return -1;

View file

@ -98,6 +98,8 @@ namespace CSVRender
/// Default-implementation: ignored /// Default-implementation: ignored
virtual void dragMoveEvent (QDragMoveEvent *event); virtual void dragMoveEvent (QDragMoveEvent *event);
virtual void mouseMoveEvent (QMouseEvent *event);
/// Default: return -1 /// Default: return -1
virtual int getSubMode() const; virtual int getSubMode() const;
}; };

View file

@ -37,6 +37,7 @@
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
#include "brushdraw.hpp"
#include "editmode.hpp" #include "editmode.hpp"
#include "pagedworldspacewidget.hpp" #include "pagedworldspacewidget.hpp"
#include "tagbase.hpp" #include "tagbase.hpp"
@ -49,6 +50,12 @@ CSVRender::TerrainShapeMode::TerrainShapeMode (WorldspaceWidget *worldspaceWidge
{ {
} }
CSVRender::TerrainShapeMode::~TerrainShapeMode ()
{
if (mBrushDraw)
mBrushDraw.reset();
}
void CSVRender::TerrainShapeMode::activate(CSVWidget::SceneToolbar* toolbar) void CSVRender::TerrainShapeMode::activate(CSVWidget::SceneToolbar* toolbar)
{ {
if (!mTerrainShapeSelection) if (!mTerrainShapeSelection)
@ -67,6 +74,9 @@ void CSVRender::TerrainShapeMode::activate(CSVWidget::SceneToolbar* toolbar)
connect(mShapeBrushScenetool->mShapeBrushWindow->mToolStrengthSlider, SIGNAL(valueChanged(int)), this, SLOT(setShapeEditToolStrength(int))); connect(mShapeBrushScenetool->mShapeBrushWindow->mToolStrengthSlider, SIGNAL(valueChanged(int)), this, SLOT(setShapeEditToolStrength(int)));
} }
if (!mBrushDraw)
mBrushDraw.reset(new BrushDraw(mParentNode));
EditMode::activate(toolbar); EditMode::activate(toolbar);
toolbar->addTool (mShapeBrushScenetool); toolbar->addTool (mShapeBrushScenetool);
} }
@ -1382,6 +1392,13 @@ void CSVRender::TerrainShapeMode::dragMoveEvent (QDragMoveEvent *event)
{ {
} }
void CSVRender::TerrainShapeMode::mouseMoveEvent (QMouseEvent *event)
{
WorldspaceHitResult hit = getWorldspaceWidget().mousePick(event->pos(), getInteractionMask());
if (hit.hit && mBrushDraw && !(mShapeEditTool == ShapeEditTool_Drag && mIsEditing)) mBrushDraw->update(hit.worldPos, mBrushSize);
if (!hit.hit && !(mShapeEditTool == ShapeEditTool_Drag && mIsEditing)) mBrushDraw->hide();
}
void CSVRender::TerrainShapeMode::setBrushSize(int brushSize) void CSVRender::TerrainShapeMode::setBrushSize(int brushSize)
{ {
mBrushSize = brushSize; mBrushSize = brushSize;

View file

@ -19,6 +19,7 @@
#include "../widget/brushshapes.hpp" #include "../widget/brushshapes.hpp"
#endif #endif
#include "brushdraw.hpp"
#include "terrainselection.hpp" #include "terrainselection.hpp"
namespace CSVWidget namespace CSVWidget
@ -57,6 +58,7 @@ namespace CSVRender
/// Editmode for terrain shape grid /// Editmode for terrain shape grid
TerrainShapeMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr); TerrainShapeMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr);
~TerrainShapeMode();
void primaryOpenPressed (const WorldspaceHitResult& hit) final; void primaryOpenPressed (const WorldspaceHitResult& hit) final;
@ -89,6 +91,7 @@ namespace CSVRender
void dragWheel (int diff, double speedFactor) final; void dragWheel (int diff, double speedFactor) final;
void dragMoveEvent (QDragMoveEvent *event) final; void dragMoveEvent (QDragMoveEvent *event) final;
void mouseMoveEvent (QMouseEvent *event) final;
private: private:
@ -168,6 +171,7 @@ namespace CSVRender
std::string mBrushTexture; std::string mBrushTexture;
int mBrushSize = 1; int mBrushSize = 1;
CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point; CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point;
std::unique_ptr<BrushDraw> mBrushDraw;
std::vector<std::pair<int, int>> mCustomBrushShape; std::vector<std::pair<int, int>> mCustomBrushShape;
CSVWidget::SceneToolShapeBrush *mShapeBrushScenetool = nullptr; CSVWidget::SceneToolShapeBrush *mShapeBrushScenetool = nullptr;
int mDragMode = InteractionType_None; int mDragMode = InteractionType_None;

View file

@ -707,6 +707,8 @@ void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event)
{ {
} }
void CSVRender::TerrainTextureMode::mouseMoveEvent (QMouseEvent *event) {}
void CSVRender::TerrainTextureMode::setBrushSize(int brushSize) void CSVRender::TerrainTextureMode::setBrushSize(int brushSize)
{ {
mBrushSize = brushSize; mBrushSize = brushSize;

View file

@ -81,6 +81,8 @@ namespace CSVRender
void dragWheel (int diff, double speedFactor) final; void dragWheel (int diff, double speedFactor) final;
void dragMoveEvent (QDragMoveEvent *event) final; void dragMoveEvent (QDragMoveEvent *event) final;
void mouseMoveEvent (QMouseEvent *event) final;
private: private:
/// \brief Handle brush mechanics, maths regarding worldspace hit etc. /// \brief Handle brush mechanics, maths regarding worldspace hit etc.
void editTerrainTextureGrid (const WorldspaceHitResult& hit); void editTerrainTextureGrid (const WorldspaceHitResult& hit);

View file

@ -613,6 +613,8 @@ void CSVRender::WorldspaceWidget::updateOverlay()
void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event) void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
{ {
dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent()).mouseMoveEvent (event);
if (mDragging) if (mDragging)
{ {
int diffX = event->x() - mDragX; int diffX = event->x() - mDragX;