1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 09:35:28 +00:00
OpenMW/apps/openmw/mwrender/bulletdebugdraw.cpp

220 lines
7.1 KiB
C++
Raw Normal View History

#include <algorithm>
2015-05-03 00:39:01 +02:00
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
2015-05-27 22:32:11 +02:00
2015-05-03 00:39:01 +02:00
#include <osg/Geometry>
#include <osg/Group>
2021-08-04 17:49:57 -07:00
#include <osg/Material>
2015-05-03 00:39:01 +02:00
2018-08-14 23:05:43 +04:00
#include <components/debug/debuglog.hpp>
#include <components/misc/convert.hpp>
#include <components/sceneutil/util.hpp>
#include <osg/PolygonMode>
#include <osg/PolygonOffset>
#include <osg/ShapeDrawable>
#include <osg/StateSet>
2018-08-14 23:05:43 +04:00
#include "bulletdebugdraw.hpp"
#include "vismask.hpp"
2015-05-03 00:39:01 +02:00
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
2015-05-03 00:39:01 +02:00
namespace MWRender
{
DebugDrawer::DebugDrawer(osg::ref_ptr<osg::Group> parentNode, btCollisionWorld *world, int debugMode)
2015-05-03 00:39:01 +02:00
: mParentNode(parentNode),
mWorld(world)
2015-05-03 00:39:01 +02:00
{
setDebugMode(debugMode);
2015-05-24 04:28:34 +02:00
}
void DebugDrawer::createGeometry()
{
if (!mLinesGeometry)
2015-05-24 04:28:34 +02:00
{
mLinesGeometry = new osg::Geometry;
mTrisGeometry = new osg::Geometry;
mLinesGeometry->setNodeMask(Mask_Debug);
mTrisGeometry->setNodeMask(Mask_Debug);
2021-08-04 17:49:57 -07:00
mLinesVertices = new osg::Vec3Array;
mTrisVertices = new osg::Vec3Array;
mLinesColors = new osg::Vec4Array;
2015-05-03 00:39:01 +02:00
mLinesDrawArrays = new osg::DrawArrays(osg::PrimitiveSet::LINES);
mTrisDrawArrays = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES);
2015-05-03 00:39:01 +02:00
mLinesGeometry->setUseDisplayList(false);
mLinesGeometry->setVertexArray(mLinesVertices);
mLinesGeometry->setColorArray(mLinesColors);
mLinesGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
mLinesGeometry->setDataVariance(osg::Object::DYNAMIC);
mLinesGeometry->addPrimitiveSet(mLinesDrawArrays);
2021-08-04 17:49:57 -07:00
mTrisGeometry->setUseDisplayList(false);
mTrisGeometry->setVertexArray(mTrisVertices);
mTrisGeometry->setDataVariance(osg::Object::DYNAMIC);
mTrisGeometry->addPrimitiveSet(mTrisDrawArrays);
2015-05-24 04:28:34 +02:00
mParentNode->addChild(mLinesGeometry);
mParentNode->addChild(mTrisGeometry);
auto* stateSet = new osg::StateSet;
stateSet->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE), osg::StateAttribute::ON);
stateSet->setAttributeAndModes(new osg::PolygonOffset(SceneUtil::getReverseZ() ? 1.0 : -1.0, SceneUtil::getReverseZ() ? 1.0 : -1.0));
osg::ref_ptr<osg::Material> material = new osg::Material;
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
stateSet->setAttribute(material);
2021-08-08 17:25:57 +01:00
mLinesGeometry->setStateSet(stateSet);
mTrisGeometry->setStateSet(stateSet);
mShapesRoot = new osg::Group;
mShapesRoot->setStateSet(stateSet);
mShapesRoot->setDataVariance(osg::Object::DYNAMIC);
mShapesRoot->setNodeMask(Mask_Debug);
mParentNode->addChild(mShapesRoot);
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(mLinesGeometry, "debug");
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(mTrisGeometry, "debug");
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(mShapesRoot, "debug");
2015-05-24 04:28:34 +02:00
}
}
void DebugDrawer::destroyGeometry()
{
if (mLinesGeometry)
2015-05-24 04:28:34 +02:00
{
mParentNode->removeChild(mLinesGeometry);
mParentNode->removeChild(mTrisGeometry);
mParentNode->removeChild(mShapesRoot);
mLinesGeometry = nullptr;
mLinesVertices = nullptr;
mLinesColors = nullptr;
mLinesDrawArrays = nullptr;
mTrisGeometry = nullptr;
mTrisVertices = nullptr;
mTrisDrawArrays = nullptr;
2015-05-24 04:28:34 +02:00
}
2015-05-03 00:39:01 +02:00
}
DebugDrawer::~DebugDrawer()
{
2016-03-10 13:17:01 +01:00
destroyGeometry();
2015-05-03 00:39:01 +02:00
}
void DebugDrawer::step()
{
if (mDebugOn)
{
mLinesVertices->clear();
mTrisVertices->clear();
mLinesColors->clear();
mShapesRoot->removeChildren(0, mShapesRoot->getNumChildren());
2015-05-03 00:39:01 +02:00
mWorld->debugDrawWorld();
showCollisions();
mLinesDrawArrays->setCount(mLinesVertices->size());
mTrisDrawArrays->setCount(mTrisVertices->size());
mLinesVertices->dirty();
mTrisVertices->dirty();
mLinesColors->dirty();
mLinesGeometry->dirtyBound();
mTrisGeometry->dirtyBound();
2015-05-03 00:39:01 +02:00
}
}
void DebugDrawer::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)
{
mLinesVertices->push_back(Misc::Convert::toOsg(from));
mLinesVertices->push_back(Misc::Convert::toOsg(to));
mLinesColors->push_back({1,1,1,1});
mLinesColors->push_back({1,1,1,1});
#if BT_BULLET_VERSION < 317
size_t size = mLinesVertices->size();
if (size >= 6
&& (*mLinesVertices)[size - 1] == (*mLinesVertices)[size - 6]
&& (*mLinesVertices)[size - 2] == (*mLinesVertices)[size - 3]
&& (*mLinesVertices)[size - 4] == (*mLinesVertices)[size - 5])
{
mTrisVertices->push_back(mLinesVertices->back());
mLinesVertices->pop_back();
mLinesColors->pop_back();
mTrisVertices->push_back(mLinesVertices->back());
mLinesVertices->pop_back();
mLinesColors->pop_back();
mLinesVertices->pop_back();
mLinesColors->pop_back();
mTrisVertices->push_back(mLinesVertices->back());
mLinesVertices->pop_back();
mLinesColors->pop_back();
mLinesVertices->pop_back();
mLinesColors->pop_back();
mLinesVertices->pop_back();
mLinesColors->pop_back();
}
#endif
}
void DebugDrawer::drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& color, btScalar)
{
mTrisVertices->push_back(Misc::Convert::toOsg(v0));
mTrisVertices->push_back(Misc::Convert::toOsg(v1));
mTrisVertices->push_back(Misc::Convert::toOsg(v2));
}
void DebugDrawer::addCollision(const btVector3& orig, const btVector3& normal)
{
mCollisionViews.emplace_back(orig, normal);
}
void DebugDrawer::showCollisions()
{
const auto now = std::chrono::steady_clock::now();
for (auto& [from, to , created] : mCollisionViews)
{
if (now - created < std::chrono::seconds(2))
{
mLinesVertices->push_back(Misc::Convert::toOsg(from));
mLinesVertices->push_back(Misc::Convert::toOsg(to));
mLinesColors->push_back({1,0,0,1});
mLinesColors->push_back({1,0,0,1});
}
}
mCollisionViews.erase(std::remove_if(mCollisionViews.begin(), mCollisionViews.end(),
[&now](const CollisionView& view) { return now - view.mCreated >= std::chrono::seconds(2); }),
mCollisionViews.end());
2015-05-03 00:39:01 +02:00
}
void DebugDrawer::drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
2015-05-03 00:39:01 +02:00
{
auto* geom = new osg::ShapeDrawable(new osg::Sphere(Misc::Convert::toOsg(transform.getOrigin()), radius));
geom->setColor(osg::Vec4(1, 1, 1, 1));
mShapesRoot->addChild(geom);
2015-05-03 00:39:01 +02:00
}
void DebugDrawer::reportErrorWarning(const char *warningString)
{
2018-08-14 23:05:43 +04:00
Log(Debug::Warning) << warningString;
2015-05-03 00:39:01 +02:00
}
void DebugDrawer::setDebugMode(int isOn)
{
mDebugOn = (isOn != 0);
2015-05-03 00:39:01 +02:00
if (!mDebugOn)
2015-05-24 04:28:34 +02:00
destroyGeometry();
else
createGeometry();
2015-05-03 00:39:01 +02:00
}
int DebugDrawer::getDebugMode() const
{
return mDebugOn;
}
}