From 76008e1ff84543f55982a3843973cf341eb629d5 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Sat, 27 Aug 2022 16:14:03 +0200 Subject: [PATCH] Multiple shapes to draw adds wireCube primitive scale of the command taken into account shading light is more vertical --- apps/openmw/mwrender/debugdraw.cpp | 230 ++++++++++++++++++++++++-- apps/openmw/mwrender/debugdraw.hpp | 34 +++- files/shaders/debugDraw_fragment.glsl | 2 +- files/shaders/debugDraw_vertex.glsl | 3 +- 4 files changed, 245 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwrender/debugdraw.cpp b/apps/openmw/mwrender/debugdraw.cpp index 42eb2a0ce9..cd165cf2be 100644 --- a/apps/openmw/mwrender/debugdraw.cpp +++ b/apps/openmw/mwrender/debugdraw.cpp @@ -31,14 +31,21 @@ namespace MWRenderDebug osg::Uniform* uTrans = const_cast( stateSet->getUniform("trans")); osg::Uniform* uCol = const_cast( stateSet->getUniform("passColor")); + osg::Uniform* uScale = const_cast( stateSet->getUniform("scale")); + auto transLocation = pcp->getUniformLocation(uTrans->getNameID() ); auto colLocation = pcp->getUniformLocation(uCol->getNameID() ); + auto scaleLocation = pcp->getUniformLocation(uScale->getNameID() ); + - for (int i = 0; i < mCubesToDraw.size(); i++) + for (int i = 0; i < mShapsToDraw.size(); i++) { - osg::Vec3f translation = mCubesToDraw[i].mPosition; - osg::Vec3f color = mCubesToDraw[i].mColor; + const auto& shapeToDraw = mShapsToDraw[i]; + osg::Vec3f translation = shapeToDraw.mPosition; + osg::Vec3f color = shapeToDraw.mColor; + osg::Vec3f scale = shapeToDraw.mDims; + if (uTrans) ext->glUniform3f(transLocation, translation.x(), translation.y(), translation.z()); @@ -46,7 +53,22 @@ namespace MWRenderDebug { ext->glUniform3f(colLocation, color.x(), color.y(), color.z()); } - this->mCubeGeometry->drawImplementation(renderInfo); + if (uScale) + { + 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; + } } @@ -54,6 +76,61 @@ namespace MWRenderDebug } } +static osg::Vec3 sphereCoordToCarthesian(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 vertices = new osg::Vec3Array; + osg::ref_ptr normals = new osg::Vec3Array; + + geom.setVertexAttribArray(0, vertices, osg::Array::BIND_PER_VERTEX); + geom.setVertexAttribArray(1, normals, osg::Array::BIND_PER_VERTEX); + + 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 (int i = 0; i < vertices->size(); i ++) + { + normals->push_back(osg::Vec3(1., 1., 1.)); + + } + + geom.addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertices->size())); +} + + static void generateCube(osg::Geometry& geom, float dim) { @@ -105,6 +182,113 @@ static void generateCube(osg::Geometry& geom, float dim) } +static void generateCylinder(osg::Geometry& geom, float radius, float height, int subdiv) +{ + osg::ref_ptr vertices = new osg::Vec3Array; + osg::ref_ptr normals = new osg::Vec3Array; + osg::ref_ptr 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= sphereCoordToCarthesian(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= sphereCoordToCarthesian(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 = sphereCoordToCarthesian(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.setVertexAttribArray(0, vertices, osg::Array::BIND_PER_VERTEX); + geom.setVertexAttribArray(1, normals, osg::Array::BIND_PER_VERTEX); + geom.addPrimitiveSet(indices); +} + MWRenderDebug::DebugDrawer::DebugDrawer(MWRender::RenderingManager& renderingManager,osg::ref_ptr parentNode) { auto& shaderManager = renderingManager.getResourceSystem()->getSceneManager()->getShaderManager(); @@ -112,25 +296,33 @@ MWRenderDebug::DebugDrawer::DebugDrawer(MWRender::RenderingManager& renderingMan auto fragmentShader = shaderManager.getShader("debugDraw_fragment.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::Type::FRAGMENT); auto program = shaderManager.getProgram(vertexShader, fragmentShader); - program->addBindAttribLocation("aPos", 0); - program->addBindAttribLocation("aNormal", 1); mCubeGeometry = new osg::Geometry; - mcustomCubesDrawer = new CubeCustomDraw(mCubeGeometry, mCubesToDrawRead, mDrawCallMutex); + mcustomCubesDrawer = new CubeCustomDraw(mCubeGeometry, mShapesToDrawRead, mDrawCallMutex); osg::StateSet* stateset = mcustomCubesDrawer->getOrCreateStateSet(); stateset->addUniform(new osg::Uniform("passColor", osg::Vec3f(1., 1., 1.))); stateset->addUniform(new osg::Uniform("trans", osg::Vec3f(1., 1., 1.))); + stateset->addUniform(new osg::Uniform("scale", osg::Vec3f(1., 1., 1.))); stateset->setAttributeAndModes(program, osg::StateAttribute::ON); stateset->setMode(GL_DEPTH_TEST, GL_TRUE); stateset->setMode(GL_CULL_FACE, GL_TRUE); - mCubeGeometry->setCullingActive(false); mCubeGeometry->setSupportsDisplayList(false); mCubeGeometry->setUseVertexBufferObjects(true); - generateCube(*mCubeGeometry,50.); + generateCube(*mCubeGeometry,1.); + auto cylinderGeom = new osg::Geometry; + cylinderGeom->setSupportsDisplayList(false); + cylinderGeom->setUseVertexBufferObjects(true); + mcustomCubesDrawer->mCylinderGeometry = cylinderGeom; + generateCylinder(*cylinderGeom, .5, 1., 20); - mCubeGeometry->setStateSet(stateset->clone(osg::CopyOp::DEEP_COPY_ALL)->asStateSet()); + auto wireCube = new osg::Geometry; + wireCube->setSupportsDisplayList(false); + wireCube->setUseVertexBufferObjects(true); + mcustomCubesDrawer->mWireCubeGeometry = wireCube; + generateWireCube(*wireCube, 1.); + //mCubeGeometry->setStateSet(stateset->clone(osg::CopyOp::DEEP_COPY_ALL)->asStateSet()); parentNode->addChild(mcustomCubesDrawer); } @@ -139,14 +331,24 @@ void MWRenderDebug::DebugDrawer::update() { { std::lock_guard lock(mDrawCallMutex); - mCubesToDrawRead.swap(mCubesToDrawWrite); + mShapesToDrawRead.swap(mShapesToDrawWrite); } - mCubesToDrawWrite.clear(); + mShapesToDrawWrite.clear(); +} +void MWRenderDebug::DebugDrawer::drawCube(osg::Vec3f mPosition, osg::Vec3f mDims, osg::Vec3f mColor) +{ + mShapesToDrawWrite.push_back({mPosition, mDims, mColor, DrawShape::Cube}); +} +void MWRenderDebug::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 MWRenderDebug::DebugDrawer::drawCube(osg::Vec3f mPosition, osg::Vec3f mDims, osg::Vec3f mColor) +void MWRenderDebug::DebugDrawer::addDrawCall(const DrawCall& draw) { - mCubesToDrawWrite.push_back({ mDims, mColor, mPosition }); + mShapesToDrawWrite.push_back(draw); } diff --git a/apps/openmw/mwrender/debugdraw.hpp b/apps/openmw/mwrender/debugdraw.hpp index 0b79282751..330d5a45e8 100644 --- a/apps/openmw/mwrender/debugdraw.hpp +++ b/apps/openmw/mwrender/debugdraw.hpp @@ -19,25 +19,41 @@ namespace MWRenderDebug static const osg::Vec3f colorBlack = osg::Vec3(0., 0., 0.); static const osg::Vec3f colorDarkGrey= osg::Vec3(0.25, 0.25, 0.25); + enum class DrawShape + { + Cube, + Cylinder, + WireCube, + }; - struct CubeDraw + struct DrawCall { + osg::Vec3f mPosition; osg::Vec3f mDims; osg::Vec3f mColor; - osg::Vec3f mPosition; + 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 CubeCustomDraw : public osg::Drawable { public: - CubeCustomDraw(osg::ref_ptr& CubeGeometry, std::vector& cubesToDraw,std::mutex& mutex) : mCubeGeometry( CubeGeometry), mCubesToDraw(cubesToDraw),mDrawCallMutex(mutex) {} + CubeCustomDraw(osg::ref_ptr& CubeGeometry, std::vector& cubesToDraw,std::mutex& mutex) : mCubeGeometry( CubeGeometry), mShapsToDraw(cubesToDraw),mDrawCallMutex(mutex) {} - std::vector& mCubesToDraw; + std::vector& mShapsToDraw; std::mutex& mDrawCallMutex; osg::ref_ptr mCubeGeometry; + osg::ref_ptr mCylinderGeometry; + osg::ref_ptr mWireCubeGeometry; + + virtual osg::BoundingSphere computeBound() const { return osg::BoundingSphere(); @@ -52,15 +68,17 @@ namespace MWRenderDebug DebugDrawer(MWRender::RenderingManager& manager,osg::ref_ptr parentNode); void update(); + void drawCube(osg::Vec3f mPosition, osg::Vec3f mDims = osg::Vec3(50.,50.,50.), osg::Vec3f mColor = osg::Vec3(1.,1.,1.)); + void drawCubeMinMax(osg::Vec3f min, osg::Vec3f max, osg::Vec3f mColor = osg::Vec3(1.,1.,1.)); + void addDrawCall(const DrawCall& draw); + private: - - std::vector mCubesToDrawRead; - std::vector mCubesToDrawWrite; + std::vector mShapesToDrawRead; + std::vector mShapesToDrawWrite; std::mutex mDrawCallMutex; osg::ref_ptr mcustomCubesDrawer; osg::ref_ptr mCubeGeometry; - void drawCube(osg::Vec3f mPosition, osg::Vec3f mDims = osg::Vec3(50.,50.,50.), osg::Vec3f mColor = osg::Vec3(1.,1.,1.)); }; } diff --git a/files/shaders/debugDraw_fragment.glsl b/files/shaders/debugDraw_fragment.glsl index d7e6a6c801..5724de3507 100644 --- a/files/shaders/debugDraw_fragment.glsl +++ b/files/shaders/debugDraw_fragment.glsl @@ -7,7 +7,7 @@ out vec4 fragColor; void main() { - vec3 lightDir = normalize(vec3(-1.,-2.,-0.5)); + vec3 lightDir = normalize(vec3(-1.,-0.5,-2.)); float lightAttenuation = dot(-lightDir, vertexNormal) * 0.5 + 0.5; diff --git a/files/shaders/debugDraw_vertex.glsl b/files/shaders/debugDraw_vertex.glsl index a248e7900a..7a7a57475e 100644 --- a/files/shaders/debugDraw_vertex.glsl +++ b/files/shaders/debugDraw_vertex.glsl @@ -10,6 +10,7 @@ uniform mat4 projectionMatrix; uniform vec3 passColor; uniform vec3 trans; +uniform vec3 scale; layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; @@ -19,7 +20,7 @@ out vec3 vertexNormal; void main() { - gl_Position = projectionMatrix * gl_ModelViewMatrix * vec4(aPos + trans, 1.); + gl_Position = projectionMatrix * gl_ModelViewMatrix * vec4(aPos * scale + trans, 1.); vertexNormal = aNormal; vertexColor = passColor.xyz;