mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-14 01:19:59 +00:00
Merge branch 'debug_draw_commands' into 'master'
API to draw primitives See merge request OpenMW/openmw!2345
This commit is contained in:
commit
435eacdaad
@ -52,6 +52,7 @@
|
||||
|
||||
#include <components/detournavigator/navigator.hpp>
|
||||
#include <components/detournavigator/navmeshcacheitem.hpp>
|
||||
#include <components/debug/debugdraw.hpp>
|
||||
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
@ -490,6 +491,7 @@ namespace MWRender
|
||||
mViewer->getIncrementalCompileOperation()->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells"));
|
||||
}
|
||||
|
||||
mDebugDraw = std::make_unique<Debug::DebugDrawer>(mResourceSystem->getSceneManager()->getShaderManager(), mRootNode);
|
||||
mResourceSystem->getSceneManager()->setIncrementalCompileOperation(mViewer->getIncrementalCompileOperation());
|
||||
|
||||
mEffectManager = std::make_unique<EffectManager>(sceneRoot, mResourceSystem);
|
||||
|
@ -75,6 +75,11 @@ namespace MWWorld
|
||||
class GroundcoverStore;
|
||||
}
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
struct DebugDrawer;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class StateUpdater;
|
||||
@ -234,6 +239,8 @@ namespace MWRender
|
||||
|
||||
void exportSceneGraph(const MWWorld::Ptr& ptr, const std::filesystem::path& filename, const std::string& format);
|
||||
|
||||
Debug::DebugDrawer& getDebugDrawer() const { return *mDebugDraw; }
|
||||
|
||||
LandManager* getLandManager() const;
|
||||
|
||||
bool toggleBorders();
|
||||
@ -306,6 +313,7 @@ namespace MWRender
|
||||
osg::ref_ptr<NpcAnimation> mPlayerAnimation;
|
||||
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> mPlayerNode;
|
||||
std::unique_ptr<Camera> mCamera;
|
||||
std::unique_ptr<Debug::DebugDrawer> mDebugDraw;
|
||||
|
||||
osg::ref_ptr<StateUpdater> mStateUpdater;
|
||||
osg::ref_ptr<SharedUniformStateUpdater> mSharedUniformStateUpdater;
|
||||
|
@ -205,7 +205,7 @@ add_component_dir (stereo
|
||||
)
|
||||
|
||||
add_component_dir (debug
|
||||
debugging debuglog gldebug
|
||||
debugging debuglog gldebug debugdraw
|
||||
)
|
||||
|
||||
IF(NOT WIN32 AND NOT APPLE)
|
||||
|
425
components/debug/debugdraw.cpp
Normal file
425
components/debug/debugdraw.cpp
Normal file
@ -0,0 +1,425 @@
|
||||
#include "debugdraw.hpp"
|
||||
#include <components/sceneutil/nodecallback.hpp>
|
||||
#include <components/shader/shadermanager.hpp>
|
||||
|
||||
#include <osg/Array>
|
||||
#include <osg/Drawable>
|
||||
#include <osg/GLExtensions>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Program>
|
||||
#include <osg/Uniform>
|
||||
#include <osg/Vec3>
|
||||
|
||||
static osg::Vec3 sphereCoordToCartesian(float theta, float phi, float r)
|
||||
{
|
||||
osg::Vec3 returnVec = osg::Vec3(0.0, 0.0, 0.0);
|
||||
float phiToHorizontal = osg::PI_2 - phi;
|
||||
returnVec.x() = std::cos(theta);
|
||||
returnVec.y() = std::sin(theta);
|
||||
returnVec.z() = std::sin(phiToHorizontal);
|
||||
|
||||
returnVec.x() *= std::cos(phiToHorizontal);
|
||||
returnVec.y() *= std::cos(phiToHorizontal);
|
||||
returnVec.x() *= r;
|
||||
returnVec.z() *= r;
|
||||
|
||||
returnVec.y() *= r;
|
||||
return returnVec;
|
||||
}
|
||||
|
||||
static void generateWireCube(osg::Geometry& geom, float dim)
|
||||
{
|
||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
|
||||
|
||||
osg::Vec2i indexPos[] = { osg::Vec2i(0, 0), osg::Vec2i(1, 0), osg::Vec2i(1, 1), osg::Vec2i(0, 1) };
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
osg::Vec3 vert1 = osg::Vec3(indexPos[i].x() - 0.5, indexPos[i].y() - 0.5, 0.5);
|
||||
int next = (i + 1) % 4;
|
||||
osg::Vec3 vert2 = osg::Vec3(indexPos[next].x() - 0.5, indexPos[next].y() - 0.5, 0.5);
|
||||
|
||||
vertices->push_back(vert1 * dim);
|
||||
vertices->push_back(vert2 * dim);
|
||||
vert1.z() *= -1;
|
||||
vert2.z() *= -1;
|
||||
vertices->push_back(vert1 * dim);
|
||||
vertices->push_back(vert2 * dim);
|
||||
|
||||
auto vert3 = vert1;
|
||||
vert3.z() *= -1;
|
||||
vertices->push_back(vert1 * dim);
|
||||
vertices->push_back(vert3 * dim);
|
||||
}
|
||||
for (std::size_t i = 0; i < vertices->size(); i++)
|
||||
{
|
||||
normals->push_back(osg::Vec3(1., 1., 1.));
|
||||
}
|
||||
|
||||
geom.setVertexArray(vertices);
|
||||
geom.setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
|
||||
geom.addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertices->size()));
|
||||
}
|
||||
|
||||
static void generateCube(osg::Geometry& geom, float dim)
|
||||
{
|
||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::DrawElementsUShort> indices = new osg::DrawElementsUShort(osg::DrawElementsUShort::TRIANGLES, 0);
|
||||
|
||||
for (int i_face = 0; i_face < 6; i_face++)
|
||||
{
|
||||
osg::Vec3f normale(0., 0., 0.);
|
||||
osg::Vec3f u(0., 0., 0.);
|
||||
osg::Vec3f v(0., 0., 0.);
|
||||
int axis = i_face / 2;
|
||||
int dir = i_face % 2 == 0 ? -1 : 1;
|
||||
float float_dir = dir;
|
||||
normale[axis] = float_dir;
|
||||
u[(axis + 1) % 3] = 1.0;
|
||||
v[(axis + 2) % 3] = 1.0;
|
||||
|
||||
for (int i_point = 0; i_point < 4; i_point++)
|
||||
{
|
||||
float iu = i_point % 2 == 1 ? float_dir : -float_dir; //This is to get the right triangle orientation when the normal changes*
|
||||
float iv = i_point / 2 == 1 ? 1.0 : -1.0;
|
||||
osg::Vec3f point = (u * iu) + (v * iv);
|
||||
point = (point + normale);
|
||||
point = point * (dim * 0.5f);
|
||||
vertices->push_back(point);
|
||||
normals->push_back(normale);
|
||||
}
|
||||
int start_vertex(i_face * 4);
|
||||
int newFace1[] = { start_vertex, start_vertex + 1, start_vertex + 2 };
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
indices->push_back(newFace1[i]);
|
||||
}
|
||||
int newFace2[] = { start_vertex + 2, start_vertex + 1, start_vertex + 3 };
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
indices->push_back(newFace2[i]);
|
||||
}
|
||||
}
|
||||
geom.setVertexArray(vertices);
|
||||
geom.setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
|
||||
geom.addPrimitiveSet(indices);
|
||||
}
|
||||
|
||||
static void generateCylinder(osg::Geometry& geom, float radius, float height, int subdiv)
|
||||
{
|
||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::DrawElementsUShort> indices = new osg::DrawElementsUShort(osg::DrawElementsUShort::TRIANGLES, 0);
|
||||
int vertexCount = subdiv * 4 + 2; //2 discs + top and bottom + 2 center
|
||||
indices->reserve(vertexCount);
|
||||
int iVertex = 0;
|
||||
|
||||
int beginTop = iVertex;
|
||||
auto topNormal = osg::Vec3(0., 0., 1.);
|
||||
//top disk
|
||||
for (int i = 0; i < subdiv; i++)
|
||||
{
|
||||
float theta = (float(i) / float(subdiv)) * osg::PI * 2.;
|
||||
osg::Vec3 pos = sphereCoordToCartesian(theta, osg::PI_2, 1.);
|
||||
pos *= radius;
|
||||
pos.z() = height / 2.;
|
||||
vertices->push_back(pos);
|
||||
normals->push_back(topNormal);
|
||||
iVertex += 1;
|
||||
}
|
||||
auto centerTop = iVertex;
|
||||
//centerTop
|
||||
{
|
||||
vertices->push_back(osg::Vec3(0., 0., height / 2.));
|
||||
normals->push_back(topNormal);
|
||||
iVertex += 1;
|
||||
}
|
||||
auto centerBot = iVertex;
|
||||
//centerBot
|
||||
{
|
||||
vertices->push_back(osg::Vec3(0., 0., -height / 2));
|
||||
normals->push_back(-topNormal);
|
||||
iVertex += 1;
|
||||
}
|
||||
//bottom disk
|
||||
auto begin_bot = iVertex;
|
||||
for (int i = 0; i < subdiv; i++)
|
||||
{
|
||||
float theta = float(i) / float(subdiv) * osg::PI * 2.;
|
||||
osg::Vec3 pos = sphereCoordToCartesian(theta, osg::PI_2, 1.);
|
||||
pos *= radius;
|
||||
pos.z() = -height / 2.;
|
||||
vertices->push_back(pos);
|
||||
normals->push_back(-topNormal);
|
||||
iVertex += 1;
|
||||
}
|
||||
//sides
|
||||
int beginSide = iVertex;
|
||||
for (int i = 0; i < subdiv; i++)
|
||||
{
|
||||
float theta = float(i) / float(subdiv) * osg::PI * 2.;
|
||||
osg::Vec3 normal = sphereCoordToCartesian(theta, osg::PI_2, 1.);
|
||||
auto posTop = normal;
|
||||
posTop *= radius;
|
||||
auto posBot = posTop;
|
||||
posTop.z() = height / 2.;
|
||||
posBot.z() = -height / 2.;
|
||||
vertices->push_back(posTop);
|
||||
normals->push_back(normal);
|
||||
iVertex += 1;
|
||||
vertices->push_back(posBot);
|
||||
normals->push_back(normal);
|
||||
iVertex += 1;
|
||||
}
|
||||
|
||||
//create triangles sides
|
||||
for (int i = 0; i < subdiv; i++)
|
||||
{
|
||||
auto next_vert = (i + 1) % subdiv;
|
||||
auto v1 = (beginSide + 2 * i);
|
||||
auto v2 = (beginSide + 2 * i + 1);
|
||||
auto v3 = (beginSide + 2 * next_vert);
|
||||
auto v4 = (beginSide + 2 * next_vert + 1);
|
||||
indices->push_back(v1);
|
||||
indices->push_back(v2);
|
||||
indices->push_back(v4);
|
||||
|
||||
indices->push_back(v4);
|
||||
indices->push_back(v3);
|
||||
indices->push_back(v1);
|
||||
}
|
||||
for (int i = 0; i < subdiv; i++)
|
||||
{
|
||||
auto next_vert = (i + 1) % subdiv;
|
||||
auto top1 = (beginTop + i);
|
||||
auto top2 = (beginTop + next_vert);
|
||||
|
||||
auto bot1 = (begin_bot + i);
|
||||
auto bot2 = (begin_bot + next_vert);
|
||||
|
||||
indices->push_back(top2);
|
||||
indices->push_back(centerTop);
|
||||
indices->push_back(top1);
|
||||
|
||||
indices->push_back(bot1);
|
||||
indices->push_back(centerBot);
|
||||
indices->push_back(bot2);
|
||||
}
|
||||
|
||||
geom.setVertexArray(vertices);
|
||||
geom.setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
|
||||
geom.addPrimitiveSet(indices);
|
||||
}
|
||||
|
||||
static int getIdexBufferReadFromFrame(const long long int& nFrame)
|
||||
{
|
||||
return nFrame % 2;
|
||||
}
|
||||
|
||||
static int getIdexBufferWriteFromFrame(const long long int& nFrame)
|
||||
{
|
||||
return (nFrame + 1) % 2;
|
||||
}
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
void DebugCustomDraw::drawImplementation(osg::RenderInfo& renderInfo) const
|
||||
{
|
||||
auto state = renderInfo.getState();
|
||||
osg::GLExtensions* ext = osg::GLExtensions::Get(state->getContextID(), true);
|
||||
|
||||
const osg::StateSet* stateSet = this->getStateSet();
|
||||
|
||||
auto program = static_cast<const osg::Program*>(stateSet->getAttribute(osg::StateAttribute::PROGRAM));
|
||||
const osg::Program::PerContextProgram* pcp = program->getPCP(*state);
|
||||
if (!pcp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const osg::Uniform* uTrans = stateSet->getUniform("trans");
|
||||
const osg::Uniform* uCol = stateSet->getUniform("color");
|
||||
const osg::Uniform* uScale = stateSet->getUniform("scale");
|
||||
const osg::Uniform* uUseNormalAsColor = stateSet->getUniform("useNormalAsColor");
|
||||
|
||||
auto transLocation = pcp->getUniformLocation(uTrans->getNameID());
|
||||
auto colLocation = pcp->getUniformLocation(uCol->getNameID());
|
||||
auto scaleLocation = pcp->getUniformLocation(uScale->getNameID());
|
||||
auto normalAsColorLocation = pcp->getUniformLocation(uUseNormalAsColor->getNameID());
|
||||
|
||||
ext->glUniform3f(transLocation, 0., 0., 0.);
|
||||
ext->glUniform3f(colLocation, 1., 1., 1.);
|
||||
ext->glUniform3f(scaleLocation, 1., 1., 1.);
|
||||
ext->glUniform1i(normalAsColorLocation, true);
|
||||
|
||||
mLinesToDraw->drawImplementation(renderInfo);
|
||||
|
||||
ext->glUniform1i(normalAsColorLocation, false);
|
||||
|
||||
for (const auto& shapeToDraw : mShapesToDraw)
|
||||
{
|
||||
osg::Vec3f translation = shapeToDraw.mPosition;
|
||||
osg::Vec3f color = shapeToDraw.mColor;
|
||||
osg::Vec3f scale = shapeToDraw.mDims;
|
||||
|
||||
ext->glUniform3f(transLocation, translation.x(), translation.y(), translation.z());
|
||||
ext->glUniform3f(colLocation, color.x(), color.y(), color.z());
|
||||
ext->glUniform3f(scaleLocation, scale.x(), scale.y(), scale.z());
|
||||
|
||||
switch (shapeToDraw.mDrawShape)
|
||||
{
|
||||
case DrawShape::Cube:
|
||||
this->mCubeGeometry->drawImplementation(renderInfo);
|
||||
break;
|
||||
case DrawShape::Cylinder:
|
||||
this->mCylinderGeometry->drawImplementation(renderInfo);
|
||||
break;
|
||||
case DrawShape::WireCube:
|
||||
this->mWireCubeGeometry->drawImplementation(renderInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mShapesToDraw.clear();
|
||||
static_cast<osg::Vec3Array*>(mLinesToDraw->getVertexArray())->clear();
|
||||
static_cast<osg::Vec3Array*>(mLinesToDraw->getNormalArray())->clear();
|
||||
}
|
||||
|
||||
struct DebugLines
|
||||
{
|
||||
|
||||
static void makeLineInstance(osg::Geometry& lines)
|
||||
{
|
||||
auto vertices = new osg::Vec3Array;
|
||||
auto color = new osg::Vec3Array;
|
||||
|
||||
lines.setUseVertexArrayObject(true);
|
||||
lines.setUseDisplayList(false);
|
||||
lines.setCullingActive(false);
|
||||
|
||||
lines.setVertexArray(vertices);
|
||||
lines.setNormalArray(color, osg::Array::BIND_PER_VERTEX);
|
||||
|
||||
lines.addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertices->size()));
|
||||
}
|
||||
|
||||
DebugLines()
|
||||
{
|
||||
mLinesGeom[0] = new osg::Geometry();
|
||||
mLinesGeom[1] = new osg::Geometry();
|
||||
|
||||
makeLineInstance(*mLinesGeom[0]);
|
||||
makeLineInstance(*mLinesGeom[1]);
|
||||
}
|
||||
|
||||
std::array<osg::ref_ptr<osg::Geometry>, 2> mLinesGeom;
|
||||
};
|
||||
|
||||
class DebugDrawCallback : public SceneUtil::NodeCallback<DebugDrawCallback>
|
||||
{
|
||||
public:
|
||||
DebugDrawCallback(Debug::DebugDrawer& debugDrawer) : mDebugDrawer(debugDrawer) {}
|
||||
|
||||
void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
mDebugDrawer.mCurrentFrame = nv->getTraversalNumber();
|
||||
int indexRead = getIdexBufferReadFromFrame(mDebugDrawer.mCurrentFrame);
|
||||
auto& lines = mDebugDrawer.mDebugLines;
|
||||
lines->mLinesGeom[indexRead]->removePrimitiveSet(0, 1);
|
||||
lines->mLinesGeom[indexRead]->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, static_cast<osg::Vec3Array*>(lines->mLinesGeom[indexRead]->getVertexArray())->size()));
|
||||
|
||||
nv->pushOntoNodePath(mDebugDrawer.mCustomDebugDrawer[indexRead]);
|
||||
nv->apply(*mDebugDrawer.mCustomDebugDrawer[indexRead]);
|
||||
nv->popFromNodePath();
|
||||
}
|
||||
|
||||
Debug::DebugDrawer& mDebugDrawer;
|
||||
};
|
||||
}
|
||||
|
||||
Debug::DebugDrawer::DebugDrawer(Shader::ShaderManager& shaderManager, osg::ref_ptr<osg::Group> parentNode)
|
||||
{
|
||||
mCurrentFrame = 0;
|
||||
auto vertexShader = shaderManager.getShader("debug_vertex.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::Type::VERTEX);
|
||||
auto fragmentShader = shaderManager.getShader("debug_fragment.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::Type::FRAGMENT);
|
||||
|
||||
auto program = shaderManager.getProgram(vertexShader, fragmentShader);
|
||||
mDebugLines = std::make_unique<DebugLines>();
|
||||
|
||||
mDebugDrawSceneObjects = new osg::Group;
|
||||
mDebugDrawSceneObjects->setCullingActive(false);
|
||||
osg::StateSet* stateset = mDebugDrawSceneObjects->getOrCreateStateSet();
|
||||
stateset->addUniform(new osg::Uniform("color", osg::Vec3f(1., 1., 1.)));
|
||||
stateset->addUniform(new osg::Uniform("trans", osg::Vec3f(0., 0., 0.)));
|
||||
stateset->addUniform(new osg::Uniform("scale", osg::Vec3f(1., 1., 1.)));
|
||||
stateset->addUniform(new osg::Uniform("useNormalAsColor", false));
|
||||
stateset->addUniform(new osg::Uniform("useAdvancedShader", true));
|
||||
|
||||
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
|
||||
stateset->setMode(GL_DEPTH_TEST, GL_TRUE);
|
||||
stateset->setMode(GL_CULL_FACE, GL_TRUE);
|
||||
|
||||
auto cubeGeometry = new osg::Geometry;
|
||||
cubeGeometry->setSupportsDisplayList(false);
|
||||
cubeGeometry->setUseVertexBufferObjects(true);
|
||||
generateCube(*cubeGeometry, 1.);
|
||||
|
||||
auto cylinderGeom = new osg::Geometry;
|
||||
cylinderGeom->setSupportsDisplayList(false);
|
||||
cylinderGeom->setUseVertexBufferObjects(true);
|
||||
generateCylinder(*cylinderGeom, .5, 1., 20);
|
||||
|
||||
auto wireCube = new osg::Geometry;
|
||||
wireCube->setSupportsDisplayList(false);
|
||||
wireCube->setUseVertexBufferObjects(true);
|
||||
generateWireCube(*wireCube, 1.);
|
||||
|
||||
for (std::size_t i = 0; i < mShapesToDraw.size(); i++)
|
||||
{
|
||||
mCustomDebugDrawer[i] = new DebugCustomDraw(mShapesToDraw[i], mDebugLines->mLinesGeom[i]);
|
||||
mCustomDebugDrawer[i]->setStateSet(stateset);
|
||||
mCustomDebugDrawer[i]->mWireCubeGeometry = wireCube;
|
||||
mCustomDebugDrawer[i]->mCubeGeometry = cubeGeometry;
|
||||
mCustomDebugDrawer[i]->mCylinderGeometry = cylinderGeom;
|
||||
}
|
||||
mDebugDrawSceneObjects->addCullCallback(new DebugDrawCallback(*this));
|
||||
|
||||
parentNode->addChild(mDebugDrawSceneObjects);
|
||||
}
|
||||
|
||||
Debug::DebugDrawer::~DebugDrawer()
|
||||
{
|
||||
}
|
||||
|
||||
void Debug::DebugDrawer::drawCube(osg::Vec3f mPosition, osg::Vec3f mDims, osg::Vec3f mColor)
|
||||
{
|
||||
mShapesToDraw[getIdexBufferWriteFromFrame(this->mCurrentFrame)].push_back({ mPosition, mDims, mColor, DrawShape::Cube });
|
||||
}
|
||||
|
||||
void Debug::DebugDrawer::drawCubeMinMax(osg::Vec3f min, osg::Vec3f max, osg::Vec3f color)
|
||||
{
|
||||
osg::Vec3 dims = max - min;
|
||||
osg::Vec3 pos = min + dims * 0.5f;
|
||||
drawCube(pos, dims, color);
|
||||
}
|
||||
|
||||
void Debug::DebugDrawer::addDrawCall(const DrawCall& draw)
|
||||
{
|
||||
mShapesToDraw[getIdexBufferWriteFromFrame(this->mCurrentFrame)].push_back(draw);
|
||||
}
|
||||
|
||||
void Debug::DebugDrawer::addLine(const osg::Vec3& start, const osg::Vec3& end, const osg::Vec3 color)
|
||||
{
|
||||
const int indexWrite = getIdexBufferWriteFromFrame(this->mCurrentFrame);
|
||||
auto vertices = static_cast<osg::Vec3Array*>(mDebugLines->mLinesGeom[indexWrite]->getVertexArray());
|
||||
auto colors = static_cast<osg::Vec3Array*>(mDebugLines->mLinesGeom[indexWrite]->getNormalArray());
|
||||
|
||||
vertices->push_back(start);
|
||||
vertices->push_back(end);
|
||||
vertices->dirty();
|
||||
|
||||
colors->push_back(color);
|
||||
colors->push_back(color);
|
||||
colors->dirty();
|
||||
}
|
95
components/debug/debugdraw.hpp
Normal file
95
components/debug/debugdraw.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
#ifndef OPENMW_COMPONENTS_DEBUG_DEBUGDRAW_H
|
||||
#define OPENMW_COMPONENTS_DEBUG_DEBUGDRAW_H
|
||||
|
||||
#include <memory>
|
||||
#include <osg/Drawable>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/ref_ptr>
|
||||
#include <vector>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
class Geometry;
|
||||
class Geometry;
|
||||
class RenderInfo;
|
||||
}
|
||||
namespace Shader
|
||||
{
|
||||
class ShaderManager;
|
||||
}
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
static const osg::Vec3f colorWhite = osg::Vec3(1., 1., 1.);
|
||||
static const osg::Vec3f colorRed = osg::Vec3(1., 0., 0.);
|
||||
static const osg::Vec3f colorBlue = osg::Vec3(0., 0., 1.);
|
||||
static const osg::Vec3f colorGreen = osg::Vec3(0., 1., 0.);
|
||||
static const osg::Vec3f colorMagenta = osg::Vec3(1., 0., 1.);
|
||||
static const osg::Vec3f colorYellow = osg::Vec3(1., 1., 0.);
|
||||
static const osg::Vec3f colorCyan = osg::Vec3(0., 1., 1.);
|
||||
static const osg::Vec3f colorBlack = osg::Vec3(0., 0., 0.);
|
||||
static const osg::Vec3f colorDarkGrey = osg::Vec3(0.25, 0.25, 0.25);
|
||||
|
||||
class DebugDrawCallback;
|
||||
|
||||
enum class DrawShape
|
||||
{
|
||||
Cube,
|
||||
Cylinder,
|
||||
WireCube,
|
||||
};
|
||||
|
||||
struct DrawCall
|
||||
{
|
||||
osg::Vec3f mPosition;
|
||||
osg::Vec3f mDims;
|
||||
osg::Vec3f mColor;
|
||||
|
||||
DrawShape mDrawShape;
|
||||
|
||||
static DrawCall cube(osg::Vec3f pos, osg::Vec3 dims = osg::Vec3(50., 50., 50.), osg::Vec3 color = colorWhite) { return { pos, dims, color, DrawShape::Cube }; }
|
||||
static DrawCall wireCube(osg::Vec3f pos, osg::Vec3 dims = osg::Vec3(50., 50., 50.), osg::Vec3 color = colorWhite) { return { pos, dims, color, DrawShape::WireCube }; }
|
||||
static DrawCall cylinder(osg::Vec3f pos, osg::Vec3 dims = osg::Vec3(50., 50., 50.), osg::Vec3 color = colorWhite) { return { pos, dims, color, DrawShape::Cylinder }; }
|
||||
};
|
||||
|
||||
class DebugCustomDraw : public osg::Drawable
|
||||
{
|
||||
public:
|
||||
DebugCustomDraw(std::vector<DrawCall>& cubesToDraw, osg::ref_ptr<osg::Geometry>& linesToDraw) : mShapesToDraw(cubesToDraw), mLinesToDraw(linesToDraw) {}
|
||||
|
||||
std::vector<DrawCall>& mShapesToDraw;
|
||||
osg::ref_ptr<osg::Geometry>& mLinesToDraw;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> mCubeGeometry;
|
||||
osg::ref_ptr<osg::Geometry> mCylinderGeometry;
|
||||
osg::ref_ptr<osg::Geometry> mWireCubeGeometry;
|
||||
|
||||
virtual void drawImplementation(osg::RenderInfo&) const;
|
||||
};
|
||||
|
||||
struct DebugLines;
|
||||
|
||||
struct DebugDrawer
|
||||
{
|
||||
friend DebugDrawCallback;
|
||||
|
||||
DebugDrawer(Shader::ShaderManager& shaderManager, osg::ref_ptr<osg::Group> parentNode);
|
||||
~DebugDrawer();
|
||||
|
||||
void drawCube(osg::Vec3f mPosition, osg::Vec3f mDims = osg::Vec3(50., 50., 50.), osg::Vec3f mColor = colorWhite);
|
||||
void drawCubeMinMax(osg::Vec3f min, osg::Vec3f max, osg::Vec3f mColor = colorWhite);
|
||||
void addDrawCall(const DrawCall& draw);
|
||||
void addLine(const osg::Vec3& start, const osg::Vec3& end, const osg::Vec3 color = colorWhite);
|
||||
|
||||
private:
|
||||
std::unique_ptr<DebugLines> mDebugLines;
|
||||
|
||||
std::array<std::vector<DrawCall>, 2> mShapesToDraw;
|
||||
long long int mCurrentFrame;
|
||||
|
||||
std::array<osg::ref_ptr<DebugCustomDraw>, 2> mCustomDebugDrawer;
|
||||
osg::ref_ptr<osg::Group> mDebugDrawSceneObjects;
|
||||
};
|
||||
}
|
||||
#endif // !
|
@ -2,7 +2,22 @@
|
||||
|
||||
#include "vertexcolors.glsl"
|
||||
|
||||
varying vec3 vertexNormal;
|
||||
|
||||
uniform bool useAdvancedShader = false;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragData[0] = getDiffuseColor();
|
||||
vec3 lightDir = normalize(vec3(-1., -0.5, -2.));
|
||||
|
||||
float lightAttenuation = dot(-lightDir, vertexNormal) * 0.5 + 0.5;
|
||||
|
||||
if(!useAdvancedShader)
|
||||
{
|
||||
gl_FragData[0] = getDiffuseColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_FragData[0] = vec4(passColor.xyz * lightAttenuation, 1.);
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,30 @@
|
||||
|
||||
#include "openmw_vertex.h.glsl"
|
||||
|
||||
uniform vec3 color;
|
||||
uniform vec3 trans;
|
||||
uniform vec3 scale;
|
||||
uniform bool useNormalAsColor;
|
||||
uniform bool useAdvancedShader = false;
|
||||
|
||||
centroid varying vec4 passColor;
|
||||
varying vec3 vertexNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = mw_modelToClip(gl_Vertex);
|
||||
if(!useAdvancedShader)
|
||||
{
|
||||
gl_Position = mw_modelToClip( vec4(gl_Vertex));
|
||||
vertexNormal = vec3(1., 1., 1.);
|
||||
passColor = gl_Color;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_Position = mw_modelToClip( vec4(gl_Vertex.xyz * scale + trans,1));
|
||||
|
||||
passColor = gl_Color;
|
||||
vertexNormal = useNormalAsColor ? vec3(1., 1., 1.) : gl_Normal.xyz;
|
||||
vec3 colorOut = useNormalAsColor? gl_Normal.xyz : color;
|
||||
passColor = vec4(colorOut, 1.);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user