Added point + destroy sensors to the base level. Also coins that fall
Added point + destroy sensors to the base level. Also coins that fall
through the destroy sensor are destroyed.

--- a/BulletApp.cpp
+++ b/BulletApp.cpp
@@ -1,6 +1,8 @@
 #include "BulletApp.h"
 
 #include "DebugBullet.h"
+
+#include <BulletCollision/CollisionDispatch/btGhostObject.h>
 
 BulletApp::BulletApp()
   : App(),
@@ -48,6 +50,8 @@
 				     _broadphase,
 				     _solver,
 				     _collisionConfig);
+  
+  _broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
 
   // Initialize debug drawing
   _debugDrawer=new BtOgre::DebugDrawer(sceneMngr()->getRootSceneNode(),_world);

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,8 @@
   media/base/Ground.mesh
   media/base/Building.mesh
   media/base/Piston.mesh
+  media/base/PointTrigger.mesh
+  media/base/DestroyTrigger.mesh
   media/base/Ground.material
   media/base/Building.material
   media/base/Piston.material

file:a/Coin.cpp -> file:b/Coin.cpp
--- a/Coin.cpp
+++ b/Coin.cpp
@@ -1,4 +1,6 @@
 #include "Coin.h"
+
+#include "CollisionMasks.h"
 
 #include <OgreEntity.h>
 #include <BtOgrePG.h>
@@ -8,6 +10,7 @@
 btCollisionShape* Coin::_coinShape=new btCylinderShape(btVector3(5.0f,0.5f,5.0f));
 
 Coin::Coin(Ogre::Vector3 startPos,Ogre::SceneManager *sceneMngr,btDynamicsWorld *world)
+  : _world(world)
 {
   _coinCount++;
 
@@ -15,12 +18,12 @@
   Ogre::Entity *coinEntity=sceneMngr->createEntity("Coin"+Ogre::StringConverter::toString(_coinCount),"Coin.mesh");
   coinEntity->setCastShadows(true);
 
-  Ogre::SceneNode *coinNode=sceneMngr->getRootSceneNode()->createChildSceneNode();
-  coinNode->attachObject(coinEntity);
-  coinNode->setPosition(startPos);
+  _coinNode=sceneMngr->getRootSceneNode()->createChildSceneNode();
+  _coinNode->attachObject(coinEntity);
+  _coinNode->setPosition(startPos);
 
   /// Bullet
-  BtOgre::RigidBodyState *coinState=new BtOgre::RigidBodyState(coinNode);
+  BtOgre::RigidBodyState *coinState=new BtOgre::RigidBodyState(_coinNode);
   
   float coinMass=1;
   btVector3 coinIntertia;
@@ -28,7 +31,18 @@
 
   _coinBody=new btRigidBody(coinMass,coinState,_coinShape,coinIntertia);
 
-  world->addRigidBody(_coinBody);
+  world->addRigidBody(_coinBody,CM_COIN,btBroadphaseProxy::AllFilter);
+}
+
+Coin::~Coin()
+{
+  delete _coinBody;
+}
+
+void Coin::remove()
+{ 
+  _coinNode->getParentSceneNode()->removeChild(_coinNode);
+  _world->removeCollisionObject(_coinBody);
 }
 
 btCollisionShape* Coin::shape()

file:a/Coin.h -> file:b/Coin.h
--- a/Coin.h
+++ b/Coin.h
@@ -9,14 +9,19 @@
 {
 public:
   Coin(Ogre::Vector3 startPos,Ogre::SceneManager *sceneMngr,btDynamicsWorld *world);
+  ~Coin();
 
   btCollisionShape *shape();
   btRigidBody* body();
 
+  void remove();
 private:
   static int _coinCount;
   static btCollisionShape *_coinShape;
 
+  btDynamicsWorld *_world;
+
+  Ogre::SceneNode *_coinNode;
   btRigidBody *_coinBody;
 };
 

--- a/CoinGame.cpp
+++ b/CoinGame.cpp
@@ -6,7 +6,9 @@
 CoinGame::CoinGame()
   : BulletApp(),
     _updateTime(0),
-    _piston(0)
+    _piston(0),
+    _pointTrigger(0),
+    _destroyTrigger(0)
 { }
 
 CoinGame::~CoinGame()
@@ -88,6 +90,10 @@
   
   camera->setAspectRatio(Ogre::Real(viewport()->getActualWidth())/Ogre::Real(viewport()->getActualHeight()));  
   viewport()->setCamera(camera);
+
+  // Fetch triggers
+  _pointTrigger=bulletScene->getSensor("PointTrigger");
+  _destroyTrigger=bulletScene->getSensor("DestroyTrigger");
 }
 
 void CoinGame::dropCoin(Ogre::Vector3 pos)
@@ -134,6 +140,40 @@
       _piston->getMotionState()->setWorldTransform(btt);
     }
 
+  // Process sensors
+  if(_pointTrigger)
+    {
+      int numObjectsInGhost = _pointTrigger->getNumOverlappingObjects();
+      ///printf("number of objects inside ghost: %d\n", numObjectsInGhost);
+      for(int i=0; i<numObjectsInGhost;++i)
+	{
+	  btCollisionObject* obj = _pointTrigger->getOverlappingObject(i);
+	  ///printf("obj[%d] = %p\n",i, obj);
+	}
+    }
+  if(_destroyTrigger)
+    {
+      for(int i=0; i<_destroyTrigger->getNumOverlappingObjects();i++)
+	{
+	  btCollisionObject *obj = _destroyTrigger->getOverlappingObject(i);
+
+	  for(std::vector<Coin*>::iterator iter=_coins.begin();
+	      iter!=_coins.end();
+	      iter++)
+	    {
+	      if((*iter)->body()==obj)
+		{
+		  (*iter)->remove();
+		  delete (*iter);
+		  _coins.erase(iter);
+		  break;
+		}
+	    }
+	}
+    }
+
+
+
   return BulletApp::frameRenderingQueued(evt);
 }
 

file:a/CoinGame.h -> file:b/CoinGame.h
--- a/CoinGame.h
+++ b/CoinGame.h
@@ -3,6 +3,8 @@
 
 #include "BulletApp.h"
 #include "Coin.h"
+
+#include <BulletCollision/CollisionDispatch/btGhostObject.h>
 
 class CoinGame : public BulletApp
 {
@@ -25,8 +27,12 @@
 
   Ogre::Real _updateTime;
   std::vector<Coin*> _coins;
+
   btRigidBody *_piston;
   Ogre::SceneNode *_pistonNode;
+
+  btGhostObject *_pointTrigger;
+  btGhostObject *_destroyTrigger;
 };
 
 #endif // COINGAME_H_

file:b/CollisionMasks.h (new)
--- /dev/null
+++ b/CollisionMasks.h
@@ -1,1 +1,9 @@
+#ifndef COLLISIONMASKS_H_
+#define COLLISIONMASKS_H_
 
+#define BIT(x) (1<<(x))
+#define CM_ALL BIT(0)
+#define CM_COIN BIT(1)|CM_ALL
+
+#endif // COLLISIONMASKS_H_
+

--- a/DotSceneBulletCollection.cpp
+++ b/DotSceneBulletCollection.cpp
@@ -14,3 +14,13 @@
   return _rigidBodies[name];
 }
 
+void DotSceneBulletCollection::addSensor(Ogre::String name,btGhostObject *body)
+{
+  _sensors[name]=body;
+}
+
+btGhostObject* DotSceneBulletCollection::getSensor(Ogre::String name)
+{
+  return _sensors[name];
+}
+

--- a/DotSceneBulletCollection.h
+++ b/DotSceneBulletCollection.h
@@ -4,6 +4,7 @@
 #include "DotSceneCollection.h"
 
 #include <btBulletDynamicsCommon.h>
+#include <BulletCollision/CollisionDispatch/btGhostObject.h>
 
 #include <OgreString.h>
 
@@ -15,8 +16,12 @@
   void addRigidBody(Ogre::String name,btRigidBody *body);
   btRigidBody* getRigidBody(Ogre::String name);
 
+  void addSensor(Ogre::String name,btGhostObject *body);
+  btGhostObject* getSensor(Ogre::String name);
+
 private:
   std::map<Ogre::String,btRigidBody *> _rigidBodies;
+  std::map<Ogre::String,btGhostObject *> _sensors;
 };
 
 #endif // DOTSCENEBULLETCOLLECTION_H_

--- a/DotSceneBulletSubloader.cpp
+++ b/DotSceneBulletSubloader.cpp
@@ -5,6 +5,8 @@
 
 #include <OgreEntity.h>
 #include <OgreMeshManager.h>
+
+#include <BulletCollision/CollisionDispatch/btGhostObject.h>
 
 #include <iostream>
 using namespace std;
@@ -30,10 +32,8 @@
     {
       Ogre::String physics_type=entityElement->Attribute("physics_type");
 
-      BtOgre::RigidBodyState *state=new BtOgre::RigidBodyState(node);
-
+      // Setup the shape
       Ogre::String collisionPrim=entityElement->Attribute("collisionPrim");
-
       btCollisionShape *shape;
       if(collisionPrim=="triangle_mesh")
 	{
@@ -49,22 +49,64 @@
 	  shape=new btBoxShape(BtOgre::Convert::toBullet(halfBoundingBox));
 	}
 
-      btScalar mass;
-      btVector3 inertia;
-      if(physics_type=="STATIC")
+      // Determine any collision filters
+      int collisionFilterMask=btBroadphaseProxy::AllFilter;
+
+      tinyxml2::XMLNode *nodeNode=entityElement->Parent();
+      tinyxml2::XMLElement *user_dataElement=nodeNode->FirstChildElement("user_data");
+      while(user_dataElement)
 	{
-	  mass=0;
-	  inertia=btVector3(0,0,0);
+	  // collisionFilterMask
+	  if(user_dataElement->Attribute("name","collisionFilterMask"))
+	    {
+	      collisionFilterMask=0;
+	      Ogre::String user_data=user_dataElement->Attribute("value");
+	      std::replace(user_data.begin(),user_data.end(),',',' ');
+	      std::istringstream iss(user_data);
+	      while(iss)
+		{
+		  int mask;
+		  iss >> mask;
+		  collisionFilterMask|=mask;
+		};
+	    }
+	  user_dataElement=user_dataElement->NextSiblingElement("user_data");
+	};
+      
+
+      // Setup the collision object
+      if(physics_type=="SENSOR") // Sensors are basically ghost objects
+	{
+	  btGhostObject *ghostObject=new btGhostObject();
+	  ghostObject->setCollisionShape(shape);
+	  ghostObject->setWorldTransform(btTransform(BtOgre::Convert::toBullet(node->getOrientation()),
+						     BtOgre::Convert::toBullet(node->getPosition())  ));
+	  ghostObject->setCollisionFlags(ghostObject->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
+	  _world->addCollisionObject(ghostObject,btBroadphaseProxy::DefaultFilter,collisionFilterMask);
+	  _collection->addSensor(name,ghostObject);
+
+	  node->setVisible(false);
 	}
-      else if(physics_type=="RIGID_BODY")
+      else // Assume everything else is some kind of a rigid body
 	{
-	  mass=entityElement->FloatAttribute("mass");
-	  shape->calculateLocalInertia(mass,inertia);
+	  btScalar mass;
+	  btVector3 inertia;
+	  if(physics_type=="RIGID_BODY")
+	    {
+	      mass=entityElement->FloatAttribute("mass");
+	      shape->calculateLocalInertia(mass,inertia);
+	    }
+	  else // Default is static (physics_type=="STATIC")
+	    {
+	      mass=0;
+	      inertia=btVector3(0,0,0);
+	    }
+	  BtOgre::RigidBodyState *state=new BtOgre::RigidBodyState(node);
+	  btRigidBody *body=new btRigidBody(mass,state,shape,inertia);
+	  
+	  _world->addRigidBody(body,btBroadphaseProxy::DefaultFilter,collisionFilterMask);
+	  _collection->addRigidBody(name,body);
 	}
-      btRigidBody *body=new btRigidBody(mass,state,shape,inertia);
-
-      _world->addRigidBody(body);
-      _collection->addRigidBody(name,body);
     }
 }
 

Binary files /dev/null and b/media/base/DestroyTrigger.mesh differ

--- /dev/null
+++ b/media/base/DestroyTrigger.mesh.xml
@@ -1,1 +1,35 @@
-
+<?xml version="1.0" encoding="UTF-8"?>
+<mesh>
+    <sharedgeometry vertexcount="4">
+        <vertexbuffer texture_coords="0" positions="true" colours_diffuse="False" normals="true">
+            <vertex>
+                <position y="0.000000" x="-1.000000" z="1.000000"/>
+                <normal y="1.000000" x="0.000000" z="-0.000000"/>
+            </vertex>
+            <vertex>
+                <position y="0.000000" x="1.000000" z="1.000000"/>
+                <normal y="1.000000" x="0.000000" z="-0.000000"/>
+            </vertex>
+            <vertex>
+                <position y="0.000000" x="1.000000" z="-1.000000"/>
+                <normal y="1.000000" x="0.000000" z="-0.000000"/>
+            </vertex>
+            <vertex>
+                <position y="0.000000" x="-1.000000" z="-1.000000"/>
+                <normal y="1.000000" x="0.000000" z="-0.000000"/>
+            </vertex>
+        </vertexbuffer>
+    </sharedgeometry>
+    <submeshes>
+        <submesh usesharedvertices="true" material="_missing_material_" use32bitindexes="False">
+            <faces count="2">
+                <face v1="0" v2="1" v3="2"/>
+                <face v1="0" v2="2" v3="3"/>
+            </faces>
+        </submesh>
+    </submeshes>
+    <submeshnames>
+        <submesh index="0" name="_missing_material_">
+        </submesh>
+    </submeshnames>
+</mesh>

Binary files a/media/base/Piston.mesh and b/media/base/Piston.mesh differ

--- a/media/base/Piston.mesh.xml
+++ b/media/base/Piston.mesh.xml
@@ -11,19 +11,19 @@
                 <normal y="-0.000000" x="-1.000000" z="-0.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="-20.000000" z="13.000000"/>
+                <position y="1.000000" x="-20.000000" z="13.000000"/>
                 <normal y="-0.000000" x="-1.000000" z="-0.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="-20.000000" z="-13.000000"/>
+                <position y="1.000000" x="-20.000000" z="-13.000000"/>
                 <normal y="-0.000000" x="-1.000000" z="-0.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="-20.000000" z="-13.000000"/>
+                <position y="1.000000" x="-20.000000" z="-13.000000"/>
                 <normal y="-0.000000" x="0.000000" z="-1.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="20.000000" z="-13.000000"/>
+                <position y="1.000000" x="20.000000" z="-13.000000"/>
                 <normal y="-0.000000" x="0.000000" z="-1.000000"/>
             </vertex>
             <vertex>
@@ -35,11 +35,11 @@
                 <normal y="-0.000000" x="0.000000" z="-1.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="20.000000" z="-13.000000"/>
+                <position y="1.000000" x="20.000000" z="-13.000000"/>
                 <normal y="-0.000000" x="1.000000" z="-0.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="20.000000" z="13.000000"/>
+                <position y="1.000000" x="20.000000" z="13.000000"/>
                 <normal y="-0.000000" x="1.000000" z="-0.000000"/>
             </vertex>
             <vertex>
@@ -59,11 +59,11 @@
                 <normal y="-0.000000" x="0.000000" z="1.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="20.000000" z="13.000000"/>
+                <position y="1.000000" x="20.000000" z="13.000000"/>
                 <normal y="-0.000000" x="0.000000" z="1.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="-20.000000" z="13.000000"/>
+                <position y="1.000000" x="-20.000000" z="13.000000"/>
                 <normal y="-0.000000" x="0.000000" z="1.000000"/>
             </vertex>
             <vertex>
@@ -83,19 +83,19 @@
                 <normal y="-1.000000" x="-0.000000" z="-0.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="20.000000" z="13.000000"/>
+                <position y="1.000000" x="20.000000" z="13.000000"/>
                 <normal y="1.000000" x="-0.000000" z="-0.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="20.000000" z="-13.000000"/>
+                <position y="1.000000" x="20.000000" z="-13.000000"/>
                 <normal y="1.000000" x="-0.000000" z="-0.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="-20.000000" z="-13.000000"/>
+                <position y="1.000000" x="-20.000000" z="-13.000000"/>
                 <normal y="1.000000" x="-0.000000" z="-0.000000"/>
             </vertex>
             <vertex>
-                <position y="2.000000" x="-20.000000" z="13.000000"/>
+                <position y="1.000000" x="-20.000000" z="13.000000"/>
                 <normal y="1.000000" x="-0.000000" z="-0.000000"/>
             </vertex>
         </vertexbuffer>

Binary files /dev/null and b/media/base/PointTrigger.mesh differ

--- /dev/null
+++ b/media/base/PointTrigger.mesh.xml
@@ -1,1 +1,35 @@
-
+<?xml version="1.0" encoding="UTF-8"?>
+<mesh>
+    <sharedgeometry vertexcount="4">
+        <vertexbuffer texture_coords="0" positions="true" colours_diffuse="False" normals="true">
+            <vertex>
+                <position y="0.000000" x="-30.000000" z="5.000000"/>
+                <normal y="1.000000" x="0.000000" z="-0.000000"/>
+            </vertex>
+            <vertex>
+                <position y="0.000000" x="30.000000" z="5.000000"/>
+                <normal y="1.000000" x="0.000000" z="-0.000000"/>
+            </vertex>
+            <vertex>
+                <position y="0.000000" x="30.000000" z="-5.000000"/>
+                <normal y="1.000000" x="0.000000" z="-0.000000"/>
+            </vertex>
+            <vertex>
+                <position y="0.000000" x="-30.000000" z="-5.000000"/>
+                <normal y="1.000000" x="0.000000" z="-0.000000"/>
+            </vertex>
+        </vertexbuffer>
+    </sharedgeometry>
+    <submeshes>
+        <submesh usesharedvertices="true" material="_missing_material_" use32bitindexes="False">
+            <faces count="2">
+                <face v1="0" v2="1" v3="2"/>
+                <face v1="0" v2="2" v3="3"/>
+            </faces>
+        </submesh>
+    </submeshes>
+    <submeshnames>
+        <submesh index="0" name="_missing_material_">
+        </submesh>
+    </submeshnames>
+</mesh>

--- a/media/base/base.scene
+++ b/media/base/base.scene
@@ -1,5 +1,27 @@
-<scene exported_by="kkrizka" formatVersion="1.0.1" previous_export_time="1341094050.882756" export_time="1341136760.481651" >
+<scene exported_by="kkrizka" formatVersion="1.0.1" previous_export_time="1341145870.142319" export_time="1341146556.352717" >
 	<nodes >
+		<node name="DestroyTrigger" >
+			<position y="-66.899574" x="0.000000" z="-0.000000" />
+			<rotation qy="0.000000" qx="0.000000" qz="-0.000000" qw="1.000000" />
+			<scale y="100.000000" x="100.000000" z="100.000000" />
+			<user_data type="int" name="collisionFilterMask" value="2" />
+			<game >
+				<sensors />
+				<actuators />
+			</game>
+			<entity anisotropic_friction="False" lock_trans_y="False" damping_trans="0.03999999910593033" damping_rot="0.10000000149011612" inertia_tensor="0.4000000059604645" actor="False" velocity_min="0.0" lock_trans_z="False" physics_type="SENSOR" lock_trans_x="False" meshFile="DestroyTrigger.mesh" friction_y="1.0" friction_x="1.0" friction_z="1.0" velocity_max="0.0" ghost="True" name="DestroyTrigger" mass_radius="1.0" mass="1.0" collisionPrim="triangle_mesh" lock_rot_x="False" lock_rot_y="False" lock_rot_z="False" />
+		</node>
+		<node name="PointTrigger" >
+			<position y="-2.000000" x="0.000000" z="61.000000" />
+			<rotation qy="0.000000" qx="0.000000" qz="-0.000000" qw="1.000000" />
+			<scale y="1.000000" x="1.000000" z="1.000000" />
+			<user_data type="str" name="collisionFilterMask" value="2" />
+			<game >
+				<sensors />
+				<actuators />
+			</game>
+			<entity anisotropic_friction="False" lock_trans_y="False" damping_trans="0.03999999910593033" damping_rot="0.10000000149011612" inertia_tensor="0.4000000059604645" actor="False" velocity_min="0.0" lock_trans_z="False" physics_type="SENSOR" lock_trans_x="False" meshFile="PointTrigger.mesh" friction_y="1.0" friction_x="1.0" friction_z="1.0" velocity_max="0.0" ghost="True" name="PointTrigger" mass_radius="1.0" mass="1.0" collisionPrim="triangle_mesh" lock_rot_x="False" lock_rot_y="False" lock_rot_z="False" />
+		</node>
 		<node name="Piston" >
 			<position y="2.000000" x="0.000000" z="-28.000000" />
 			<rotation qy="0.000000" qx="0.000000" qz="-0.000000" qw="1.000000" />

Binary files a/media/blender/base.blend and b/media/blender/base.blend differ