From 5215ffd964aaa13297f8fd15d96a2f1a9e79eb9e Mon Sep 17 00:00:00 2001
From: fredzio <chardon.frederic@gmail.com>
Date: Tue, 22 Dec 2020 14:51:16 +0100
Subject: [PATCH] The debug drawer rely on Bullet to determines the vertices of
 collision shapes. It doesn't work in the case of spheres (used by
 projectiles): resulting shape is malformed. It can also leads to this error
 which makes the debug drawer non-working till game restart:
 CullVisitor::apply(Geode&) detected NaN,     depth=nan, center=(nan nan nan),
     matrix={        -0.265814 -0.0639702 0.9619 0        0.964024 -0.0176387
 0.265228 0        -4.29769e-09 0.997796 0.0663574 0        18178.6 -3550.91
 42154.4 1 }

Avoid this issue by using osg::Sphere

While here, remove an unused function. We don't use Bullet's solver so
we never have any contact points (in Bullet parlance).
---
 apps/openmw/mwrender/bulletdebugdraw.cpp | 22 +++++++++++++++++-----
 apps/openmw/mwrender/bulletdebugdraw.hpp |  4 +++-
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/apps/openmw/mwrender/bulletdebugdraw.cpp b/apps/openmw/mwrender/bulletdebugdraw.cpp
index 00529ef80d..207b0ee504 100644
--- a/apps/openmw/mwrender/bulletdebugdraw.cpp
+++ b/apps/openmw/mwrender/bulletdebugdraw.cpp
@@ -7,6 +7,9 @@
 
 #include <components/debug/debuglog.hpp>
 #include <components/misc/convert.hpp>
+#include <osg/PolygonMode>
+#include <osg/ShapeDrawable>
+#include <osg/StateSet>
 
 #include "bulletdebugdraw.hpp"
 #include "vismask.hpp"
@@ -41,6 +44,14 @@ void DebugDrawer::createGeometry()
         mGeometry->addPrimitiveSet(mDrawArrays);
 
         mParentNode->addChild(mGeometry);
+
+        auto* stateSet = new osg::StateSet;
+        stateSet->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE), osg::StateAttribute::ON);
+        mShapesRoot = new osg::Group;
+        mShapesRoot->setStateSet(stateSet);
+        mShapesRoot->setDataVariance(osg::Object::DYNAMIC);
+        mShapesRoot->setNodeMask(Mask_Debug);
+        mParentNode->addChild(mShapesRoot);
     }
 }
 
@@ -49,6 +60,7 @@ void DebugDrawer::destroyGeometry()
     if (mGeometry)
     {
         mParentNode->removeChild(mGeometry);
+        mParentNode->removeChild(mShapesRoot);
         mGeometry = nullptr;
         mVertices = nullptr;
         mDrawArrays = nullptr;
@@ -66,6 +78,7 @@ void DebugDrawer::step()
     {
         mVertices->clear();
         mColors->clear();
+        mShapesRoot->removeChildren(0, mShapesRoot->getNumChildren());
         mWorld->debugDrawWorld();
         showCollisions();
         mDrawArrays->setCount(mVertices->size());
@@ -106,12 +119,11 @@ void DebugDrawer::showCollisions()
             mCollisionViews.end());
 }
 
-void DebugDrawer::drawContactPoint(const btVector3 &PointOnB, const btVector3 &normalOnB, btScalar distance, int lifeTime, const btVector3 &color)
+void DebugDrawer::drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
 {
-    mVertices->push_back(Misc::Convert::toOsg(PointOnB));
-    mVertices->push_back(Misc::Convert::toOsg(PointOnB) + (Misc::Convert::toOsg(normalOnB) * distance * 20));
-    mColors->push_back({1,1,1,1});
-    mColors->push_back({1,1,1,1});
+    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);
 }
 
 void DebugDrawer::reportErrorWarning(const char *warningString)
diff --git a/apps/openmw/mwrender/bulletdebugdraw.hpp b/apps/openmw/mwrender/bulletdebugdraw.hpp
index ec421bd742..b24640427d 100644
--- a/apps/openmw/mwrender/bulletdebugdraw.hpp
+++ b/apps/openmw/mwrender/bulletdebugdraw.hpp
@@ -32,6 +32,7 @@ private:
         CollisionView(btVector3 orig, btVector3 normal) : mOrig(orig), mEnd(orig + normal * 20), mCreated(std::chrono::steady_clock::now()) {};
     };
     std::vector<CollisionView> mCollisionViews;
+    osg::ref_ptr<osg::Group> mShapesRoot;
 
 protected:
     osg::ref_ptr<osg::Group> mParentNode;
@@ -59,7 +60,8 @@ public:
 
     void showCollisions();
 
-    void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) override;
+    void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color) override {};
+    void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color) override;
 
     void reportErrorWarning(const char* warningString) override;