mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 02:45:32 +00:00
Implement brush outline for terrainshapemode
This commit is contained in:
parent
4c5d2feee8
commit
24c8b32d4c
10 changed files with 199 additions and 1 deletions
|
@ -89,7 +89,7 @@ opencs_units (view/render
|
|||
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
|
||||
previewwidget editmode instancemode instanceselectionmode instancemovemode
|
||||
orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller
|
||||
cellwater terraintexturemode actor terrainselection terrainshapemode
|
||||
cellwater terraintexturemode actor terrainselection terrainshapemode brushdraw
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/render
|
||||
|
|
136
apps/opencs/view/render/brushdraw.cpp
Normal file
136
apps/opencs/view/render/brushdraw.cpp
Normal 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);
|
||||
}
|
31
apps/opencs/view/render/brushdraw.hpp
Normal file
31
apps/opencs/view/render/brushdraw.hpp
Normal 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
|
|
@ -73,6 +73,8 @@ void CSVRender::EditMode::dropEvent (QDropEvent *event) {}
|
|||
|
||||
void CSVRender::EditMode::dragMoveEvent (QDragMoveEvent *event) {}
|
||||
|
||||
void CSVRender::EditMode::mouseMoveEvent (QMouseEvent *event) {}
|
||||
|
||||
int CSVRender::EditMode::getSubMode() const
|
||||
{
|
||||
return -1;
|
||||
|
|
|
@ -98,6 +98,8 @@ namespace CSVRender
|
|||
/// Default-implementation: ignored
|
||||
virtual void dragMoveEvent (QDragMoveEvent *event);
|
||||
|
||||
virtual void mouseMoveEvent (QMouseEvent *event);
|
||||
|
||||
/// Default: return -1
|
||||
virtual int getSubMode() const;
|
||||
};
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "../../model/world/tablemimedata.hpp"
|
||||
#include "../../model/world/universalid.hpp"
|
||||
|
||||
#include "brushdraw.hpp"
|
||||
#include "editmode.hpp"
|
||||
#include "pagedworldspacewidget.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)
|
||||
{
|
||||
if (!mTerrainShapeSelection)
|
||||
|
@ -67,6 +74,9 @@ void CSVRender::TerrainShapeMode::activate(CSVWidget::SceneToolbar* toolbar)
|
|||
connect(mShapeBrushScenetool->mShapeBrushWindow->mToolStrengthSlider, SIGNAL(valueChanged(int)), this, SLOT(setShapeEditToolStrength(int)));
|
||||
}
|
||||
|
||||
if (!mBrushDraw)
|
||||
mBrushDraw.reset(new BrushDraw(mParentNode));
|
||||
|
||||
EditMode::activate(toolbar);
|
||||
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)
|
||||
{
|
||||
mBrushSize = brushSize;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "../widget/brushshapes.hpp"
|
||||
#endif
|
||||
|
||||
#include "brushdraw.hpp"
|
||||
#include "terrainselection.hpp"
|
||||
|
||||
namespace CSVWidget
|
||||
|
@ -57,6 +58,7 @@ namespace CSVRender
|
|||
|
||||
/// Editmode for terrain shape grid
|
||||
TerrainShapeMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr);
|
||||
~TerrainShapeMode();
|
||||
|
||||
void primaryOpenPressed (const WorldspaceHitResult& hit) final;
|
||||
|
||||
|
@ -89,6 +91,7 @@ namespace CSVRender
|
|||
|
||||
void dragWheel (int diff, double speedFactor) final;
|
||||
void dragMoveEvent (QDragMoveEvent *event) final;
|
||||
void mouseMoveEvent (QMouseEvent *event) final;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -168,6 +171,7 @@ namespace CSVRender
|
|||
std::string mBrushTexture;
|
||||
int mBrushSize = 1;
|
||||
CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point;
|
||||
std::unique_ptr<BrushDraw> mBrushDraw;
|
||||
std::vector<std::pair<int, int>> mCustomBrushShape;
|
||||
CSVWidget::SceneToolShapeBrush *mShapeBrushScenetool = nullptr;
|
||||
int mDragMode = InteractionType_None;
|
||||
|
|
|
@ -707,6 +707,8 @@ void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event)
|
|||
{
|
||||
}
|
||||
|
||||
void CSVRender::TerrainTextureMode::mouseMoveEvent (QMouseEvent *event) {}
|
||||
|
||||
void CSVRender::TerrainTextureMode::setBrushSize(int brushSize)
|
||||
{
|
||||
mBrushSize = brushSize;
|
||||
|
|
|
@ -81,6 +81,8 @@ namespace CSVRender
|
|||
void dragWheel (int diff, double speedFactor) final;
|
||||
void dragMoveEvent (QDragMoveEvent *event) final;
|
||||
|
||||
void mouseMoveEvent (QMouseEvent *event) final;
|
||||
|
||||
private:
|
||||
/// \brief Handle brush mechanics, maths regarding worldspace hit etc.
|
||||
void editTerrainTextureGrid (const WorldspaceHitResult& hit);
|
||||
|
|
|
@ -613,6 +613,8 @@ void CSVRender::WorldspaceWidget::updateOverlay()
|
|||
|
||||
void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
|
||||
{
|
||||
dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent()).mouseMoveEvent (event);
|
||||
|
||||
if (mDragging)
|
||||
{
|
||||
int diffX = event->x() - mDragX;
|
||||
|
|
Loading…
Reference in a new issue