1. Daniel K. O.
  2. KODE

Commits

Daniel K. O.  committed 0418922

more cylinder code

  • Participants
  • Parent commits 293d997
  • Branches default

Comments (0)

Files changed (13)

File include/kode/Mass.hpp

View file
  • Ignore whitespace
         static Mass CapsuleTotal(Real radius, Real length, Real total);
         static Mass CapsuleDensity(Real radius, Real length, Real density);
 
+        static Mass CylinderTotal(Real radius, Real length, Real total);
+        static Mass CylinderDensity(Real radius, Real length, Real density);
     };
 
 

File include/kode/collision/Cylinder.hpp

View file
  • Ignore whitespace
         inline
         Real getLength() const noexcept;
 
-        void setLength();
+        void setLength(Real len);
 
         void setRadiusLength(Real rad, Real len);
     };

File samples/KODEOgre/data/samples.material

View file
  • Ignore whitespace
     }
 }
 
+material cylinder : Chess
+{
+    technique shader
+    {
+        pass perlight
+        {
+            texture_unit decalmap
+            {
+                scale 0.5 0.5
+            }
+        }
+    }
+}
+
 material SkyBoxGradient
 {
     technique

File samples/KODEOgre/include/BodyCylinder.hpp

View file
  • Ignore whitespace
+#ifndef KODE_OGRE_BODY_CYLINDER_H
+#define KODE_OGRE_BODY_CYLINDER_H
+
+#include "Body.hpp"
+#include "Cylinder.hpp"
+
+#include <OgreSceneManager.h>
+
+
+namespace kode {
+    namespace ogre {
+
+        class BodyCylinder : public Body,
+                            public Cylinder {
+
+        public:
+            BodyCylinder(Real radius, Real length, Real density=1, Ogre::SceneManager* smgr=nullptr);
+            BodyCylinder(World& world, Real radius, Real length, Real density=1, Ogre::SceneManager* smgr=nullptr);
+
+            using Body::getPosition;
+            using Body::setPosition;
+            using Body::getLocalAxes;
+            using Body::setLocalAxes;
+            using Body::getOrientation;
+            using Body::rotate;
+            using Body::translate;
+            using Body::localPointToWorld;
+
+        };
+
+    }
+}
+
+#endif

File samples/KODEOgre/include/Cylinder.hpp

View file
  • Ignore whitespace
+#ifndef KODE_OGRE_CYLINDER_H
+#define KODE_OGRE_CYLINDER_H
+
+#include <OgreSceneManager.h>
+
+#include <kode/collision/Cylinder.hpp>
+
+#include "Shape.hpp"
+
+namespace kode {
+    namespace ogre {
+
+        class Cylinder : public Shape,
+                         public kode::Cylinder {
+            void moved() override;
+        public:
+            Cylinder(Real radius, Real length, Ogre::SceneManager* smgr = nullptr);
+        };
+
+    }
+}
+
+#endif

File samples/KODEOgre/src/BodyCylinder.cpp

View file
  • Ignore whitespace
+#include "BodyCylinder.hpp"
+
+namespace kode {
+    namespace ogre {
+
+        BodyCylinder::BodyCylinder(Real radius, Real length,
+                                   Real density,
+                                   Ogre::SceneManager* smgr) :
+            Body{smgr},
+            Cylinder{radius, length, smgr}
+        {
+            setMass(Mass::CylinderDensity(radius, length, density));
+            attach(*this);
+            Body::getNode()->setVisible(false, false);
+        }
+
+
+        BodyCylinder::BodyCylinder(World& world,
+                                   Real radius, Real length,
+                                   Real density,
+                                   Ogre::SceneManager* smgr) :
+            Body{world, smgr},
+            Cylinder{radius, length, smgr}
+        {
+            setMass(Mass::CylinderDensity(radius, length, density));
+            attach(*this);
+            Body::getNode()->setVisible(false, false);
+        }
+
+    }
+}

File samples/KODEOgre/src/Capsule.cpp

View file
  • Ignore whitespace
                 smgr = App::instance->sceneMgr;
 
 
-            const int numRings = 32;
-            const int numSegments = 16;
-            const int numSegHeight = 2;
+            const unsigned numRings = 32;
+            const unsigned numSegments = 16;
+            const unsigned numSegHeight = 2;
 
             const Real hlength = length/2;
 
             const Real sphereRatio = radius / (2 * radius + length);
             const Real cylinderRatio = length / (radius + length);
 
-            int offset = 0;
+            unsigned offset = 0;
             // Top half sphere
 
             // Generate the group of rings for the sphere

File samples/KODEOgre/src/Cylinder.cpp

View file
  • Ignore whitespace
+#include <cmath>
+#include <iostream>
+#include <assert.h>
+
+#include <OgreEntity.h>
+#include <OgreSceneNode.h>
+#include <OgreManualObject.h>
+#include <OgreEntity.h>
+#include <OgreMesh.h>
+#include <OgreMeshManager.h>
+
+#include "Cylinder.hpp"
+
+#include "conv.hpp"
+#include "App.hpp"
+
+using std::cout;
+using std::endl;
+
+/*
+  Based on Ogre Procedural
+ */
+
+namespace kode {
+    namespace ogre {
+
+        Cylinder::Cylinder(Real radius, Real length,
+                           Ogre::SceneManager* smgr) :
+            kode::Cylinder{radius, length}
+        {
+            using namespace Ogre;
+            using Ogre::Math;
+            using Ogre::Real;
+
+            if (!smgr)
+                smgr = App::instance->sceneMgr;
+
+            const Real hlength = length/2;
+
+            const unsigned numSegHeight = 2;
+            const unsigned numSegBase = 32;
+
+            ManualObject* manual = smgr->createManualObject();
+            manual->estimateVertexCount((numSegHeight+1)*(numSegBase+1)+2*(numSegBase+1)+2);
+            manual->estimateIndexCount(numSegHeight*(numSegBase+1)*6+6*numSegBase);
+
+
+            const Real deltaAngle = (Math::TWO_PI / numSegBase);
+            const Real deltaHeight = length/(Real)numSegHeight;
+            unsigned offset = 0;
+
+            manual->begin("cylinder", RenderOperation::OT_TRIANGLE_LIST);
+
+            for (unsigned i = 0; i <=numSegHeight; i++)
+		for (unsigned j = 0; j<=numSegBase; j++) {
+                    const Real x0 = radius * std::cos(j*deltaAngle);
+                    const Real y0 = radius * std::sin(j*deltaAngle);
+
+                    manual->position(x0, y0, hlength - i*deltaHeight);
+                    manual->normal(x0/radius, y0/radius, 0);
+                    manual->textureCoord(j/(Real)numSegBase,
+                                         i/(Real)numSegHeight);
+
+                    if (i != numSegHeight) {
+                        manual->triangle(offset + numSegBase,
+                                         offset + numSegBase + 1,
+                                         offset);
+                        manual->triangle(offset,
+                                         offset + numSegBase + 1,
+                                         offset + 1);
+                    }
+                    offset ++;
+		}
+
+            //low cap
+            unsigned centerIndex = offset;
+            manual->position(0, 0, -hlength);
+            manual->normal(0, 0, -1);
+            manual->textureCoord(0, 0);
+
+            offset++;
+            for (unsigned j=0; j<=numSegBase; j++) {
+                Real x0 = std::cos(j*deltaAngle);
+                Real y0 = std::sin(j*deltaAngle);
+
+                manual->position(radius*x0, radius*y0, -hlength);
+                manual->normal(0, 0, -1);
+                manual->textureCoord(x0, y0);
+                if (j!=numSegBase) {
+                    manual->triangle(centerIndex,
+                                     offset+1,
+                                     offset);
+                }
+                offset++;
+            }
+
+            // high cap
+            centerIndex = offset;
+            manual->position(0, 0, hlength);
+            manual->normal(0, 0, 1);
+            manual->textureCoord(0,0);
+
+            offset++;
+            for (unsigned j=0; j<=numSegBase; j++) {
+                Real x0 = std::cos(j*deltaAngle);
+                Real y0 = std::sin(j*deltaAngle);
+                manual->position(x0 * radius, radius * y0, hlength);
+                manual->normal(0, 0, 1);
+                manual->textureCoord(x0, y0);
+                if (j!=numSegBase) {
+                    manual->triangle(centerIndex,
+                                     offset,
+                                     offset+1);
+                }
+                offset++;
+            }
+
+            manual->end();
+
+            MeshPtr mesh = manual->convertToMesh(manual->getName());
+            unsigned short src, dest;
+            if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
+                mesh->buildTangentVectors(VES_TANGENT, src, dest);
+
+            node = smgr->getRootSceneNode()->createChildSceneNode();
+            node->attachObject(smgr->createEntity(mesh));
+
+            moved();
+        }
+
+
+        void
+        Cylinder::moved()
+        {
+            node->setPosition(conv( getPosition() ));
+            node->setOrientation(conv( getOrientation() ));
+        }
+
+    }
+}

File samples/KODEOgre/stack.cpp

View file
  • Ignore whitespace
 enum class ObjType {
     Box,
     Capsule,
+    Cylinder,
     Sphere
 };
 
                 obj.reset(new BodyCapsule(world,
                                           0.25*getRand() + 0.1,
                                           getRand() + 0.1));
-                obj->setMass(Mass::SphereDensity(1, 1));
+                break;
+            case ObjType::Cylinder:
+                obj.reset(new BodyCylinder(world,
+                                           0.25*getRand() + 0.1,
+                                           getRand() + 0.1));
                 break;
             case ObjType::Sphere:
                 obj.reset(new BodySphere(world,
             return true;
         }
         if (evt.key == OIS::KC_3) {
+            dropObject(ObjType::Cylinder);
+            return true;
+        }
+        if (evt.key == OIS::KC_4) {
             dropObject(ObjType::Sphere);
             return true;
         }

File src/Mass.cpp

View file
  • Ignore whitespace
                             0, 0, Ib};
         return {total, I, {0,0,0}};
     }
+
+
+    Mass
+    Mass::CylinderTotal(Real radius, Real length, Real total)
+    {
+        const Real a = total * (radius*radius/4 + length*length/12);
+        const Real b = total*radius*radius/2;
+        const Matrix3 I = { a, 0, 0,
+                            0, a, 0,
+                            0, 0, b};
+        return {total, I, {0,0,0}};
+    }
+
+
+    Mass
+    Mass::CylinderDensity(Real radius, Real length, Real density)
+    {
+        return CylinderTotal(radius, length,
+                             Math::Pi * radius * radius * length * density);
+    }
 }

File src/collision/Cylinder.cpp

View file
  • Ignore whitespace
     }
 
 
-    Type
+    Geom::Type
     Cylinder::getType() const noexcept
     {
         return Type::Cylinder;
 
 
     Interval
-    Cylinder::computeProjected(const Vector3& axis) noexcept
+    Cylinder::computeProjected(const Vector3& axis) const
     {
         const Vector3 up = getLocalAxes().col(2);
 
 
 
     Vector3
-    Cylinder::computeSupport(const Vector3& dir) noexcept
+    Cylinder::computeSupport(const Vector3& dir) const
     {
         const Vector3 localDir = worldVectorToLocal(dir);
         Vector3 localSupport = {0, 0, Math::sign(localDir.z) * hlength};
         if (!(rad > 0))
             throw std::domain_error{"radius must be positive"};
         radius = rad;
-        recomputeAABB();
+        computeAABB();
     }
 
 
         if (!(len > 0))
             throw std::domain_error{"length must be positive"};
         hlength = len/2;
-        recomputeAABB();
+        computeAABB();
     }
 
 
             throw std::domain_error{"length must be positive"};
         radius = rad;
         hlength = len/2;
-        recomputeAABB();
+        computeAABB();
     }
 
 }

File src/collision/Makefile.am

View file
  • Ignore whitespace
     Capsule.cpp \
     Collider.cpp \
     ContactPoint.cpp \
+    Cylinder.cpp \
     Geom.cpp \
     HashSpace.cpp \
     Plane.cpp \

File src/collision/tests/CylinderPlane.cpp

View file
  • Ignore whitespace
                       std::vector<ContactPoint>& cp)
     {
         const Vector3 normal = plane.getNormal();
-        const Real cylRadius = cylinder.getRadius();
+        const Real radius = cylinder.getRadius();
         const Vector3 localDir = cylinder.worldVectorToLocal(normal);
         const Real hlength = cylinder.getLength() / 2;
 
                                  cp.push_back({pt, normal, depth});
                          };
 
-        if (dist < Epsilon) {
+        const Real tol = 1/64.; // TODO: make this proportional to radio/length ratio
+        if (dist < tol) {
             // disc is parallel to plane, just generate arbitrary points for stability
             const unsigned numPoints = 4;
             for (unsigned i=0; i<numPoints; ++i) {
-                const Vector3 localPoint = { cylRadius * Math::cos(2*Math::Pi*i / numPoints),
-                                             cylRadius * Math::sin(2*Math::Pi*i / numPoints),
+                const Vector3 localPoint = { radius * Math::cos(2*Math::Pi*i / numPoints),
+                                             radius * Math::sin(2*Math::Pi*i / numPoints),
                                              Math::sign(-localDir.z) * hlength};
                 const Vector3 p = cylinder.localPointToWorld(localPoint);
                 addIfDeep(p);
             }
         } else {
             // check both discs, get only the support point for each
-            const Real scale = -cylRadius / dist;
+            const Real scale = -radius / dist;
 
             const Vector3 p1 = cylinder.localPointToWorld({scale*localDir.x, scale*localDir.y, hlength});
             addIfDeep(p1);