Laser Sensing Display for UI interfaces in the real world

Dependencies:   mbed

Fork of skinGames_forktest by Alvaro Cassinelli

Revision:
40:3ba2b0ea9f33
Child:
43:1dd4cfc30788
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scene.cpp	Wed Oct 16 16:14:27 2013 +0000
@@ -0,0 +1,161 @@
+#include "Scene.h"
+//#include "hardwareIO.h" //(for tests using serial port only)
+
+Scene scene; // pre-instantiated GLOBAL (cross file object, declared extern in the Scene.h header)
+
+//extern LaserRenderer lsr; // Use of the global object lsr (LaserRenderer type). Object is pre-instantiated in LaserRenderer.cpp
+ 
+ using namespace std;
+
+//======================================= BASE OBJECT CLASS =======================================
+//BaseObject::BaseObject() {}
+
+BaseObject::~BaseObject() {
+ // in principle, we don't need to do anything: 
+ // the vertexArray is a vector that does NOT contain pointers; also myDisplaySensingBuffer is destroyed by calling its destructor.
+}
+
+
+void BaseObject::addVertex(V3& _v3, Mat44& _RT) { // passing the current modelview (lsr.RT) as a parameter seems cleaner (more encapsulated class) than using the global lsr object...
+    vertexArray.push_back(_RT*_v3); 
+}
+
+void BaseObject::transform(Mat44& _RT) { // this transform all the vertices of the object by _RT
+    for (unsigned short i=0; i<vertexArray.size(); i++) vertexArray[i]=_RT*vertexArray[i];
+}
+
+void BaseObject::clear() { // this deletes all the vertices (and their projections) in the object:
+    vertexArray.clear();
+    displaySensingBuffer.lsdTrajectory.clear();
+}
+
+/*  THIS PRODUCE A CIRCULAR REFERENCE!
+void BaseObject::render(LaserRenderer* ptr_lsr) {
+  // Use the lsr methods: again, this would be kind of convoluted if these objects belongs to a scene that belongs to lsr...
+  ptr_lsr->renderObject(this);
+*/
+
+ //Or do it "directly" (but again, we need to use data from the lsr state machine): 
+/*
+// First, clear the current lsdTrajectory:
+  Object.myDisplaySensingBuffer.lsdTrajectory.clear();
+ if (lsr.renderingMode==PROJECTION)
+    for (int i=0; i<vertexArray.size(); i++) {
+    LaserPoint newLp=lsr.renderPointProj(Object.vertexArray[i]); // or use a render method for a LaserPoint or an extended V3 class (or directly)
+    // Set per-vertex color too? No, for the time being one color per object... 
+    // newLp.myColor=color;
+    Object.myDisplaySensingBuffer.lsdTrajectory.push_back(newLp);
+ }
+ else
+    for (int i=0; i<Object.vertexArray.size(); i++) {
+    LaserPoint newLp=lsr.renderPointRaw(Object.vertexArray[i]);
+    // Set per-vertex color too? No, for the time being one color per object... 
+    // newLp.myColor=color;
+    Object.myDisplaySensingBuffer.lsdTrajectory.push_back(newLp);
+    }
+}
+}
+*/
+
+Box3d BaseObject::getEnclosingBox() {
+    // This will give the 3d enclosing box for the object, in LOCAL coordinates. 
+    // (for the time being, let's compute every time we query about it. In the future we can optimize by computing only when the object changed)
+    if (vertexArray.size()==0) {
+    enclosingBox.minX=enclosingBox.maxX=enclosingBox.minY=enclosingBox.maxY=enclosingBox.minZ=enclosingBox.maxZ=0;
+    } 
+    else 
+    { 
+       enclosingBox.minX=enclosingBox.maxX=vertexArray[0].x;
+       enclosingBox.minY=enclosingBox.maxY=vertexArray[0].y;
+       enclosingBox.minZ=enclosingBox.maxZ=vertexArray[0].z;
+        for (unsigned short i=1; i<vertexArray.size(); i++) {
+            if (vertexArray[i].x>enclosingBox.maxX) enclosingBox.maxX=vertexArray[i].x;
+            else if (vertexArray[i].x<enclosingBox.minX) enclosingBox.minX=vertexArray[i].x;
+            if (vertexArray[i].y>enclosingBox.maxY) enclosingBox.maxY=vertexArray[i].y;
+            else if (vertexArray[i].y<enclosingBox.minY) enclosingBox.minY=vertexArray[i].y;
+        }
+      }
+    return (enclosingBox);
+}
+
+ // Sensing methods (query and process sensed data): 
+ // That this is separated from displaying routine make sense: we can query at ANY time for new data,
+ // and this is uncorrelated with the display buffer continuous to work, displaying and sensing things.
+ // ALSO, it is separated from the LaserRenderer: this routine does not uses any "state machine" data.  
+ bool BaseObject::sense() {return(this->displaySensingBuffer.processSensedData());}
+
+ // Max and Min intensity RATIOS (normalized between 0 and 255):
+unsigned char BaseObject::maxIntensity(void) {displaySensingBuffer.processSensedData(); return displaySensingBuffer.maxI;}
+unsigned char BaseObject::minIntensity(void) {displaySensingBuffer.processSensedData(); return displaySensingBuffer.minI;}
+    
+
+//======================================= THE SCENE CLASS =======================================
+
+//Scene::Scene() : numTouchedObjects(0) {}
+
+Scene::~Scene() {
+    this->clear(); // necessary because Scene object variable objectArray is an vector of POINTERS and we need to free memory for the pointed objects. 
+}
+
+void Scene::clear() {
+ //NOTE: objectArray stores POINTERS to objects; we need therefore to delete first the object itself:
+  for (int i=0; i<this->totalObjects(); i++) {
+    // pc.printf("deleting object: %d\n", i);
+     delete objectArray[i]; // this call the destructor for BaseObject
+   }
+    objectArray.clear(); // clear the vector of pointers
+    ptr_currentObject=NULL;
+ }
+ 
+void Scene::addObject(BaseObject* ptr_newObject) {
+    objectArray.push_back(ptr_newObject); // note: the object pointed by ptr_newObject has been instantiated OUTSIDE this method. 
+    //ptr_currentObject=ptr_newObject;
+}
+
+void Scene::addCurrentObject() { // this adds the "current" object (pointed by ptr_currentObject)
+    objectArray.push_back(ptr_currentObject);
+  // Note: the current object pointerd by ptr_currentObject can be BaseObject... or any child class. This is not a problem as long as the methods applied to the 
+  // scene vector array don't use child methods (then we can do a dynamic cast before including in the array: pb = dynamic_cast<CBase*>(&d); ). IF we want
+  // the scene class to be able to use child methods, then we need to make BaseObject polymorphic, by declaring all usable methods VIRTUAL.
+ 
+}
+
+void Scene::transform(Mat44& _RT) { // this transform all the objects of the scene by _RT
+    for (int i=0; i<totalObjects(); i++) objectArray[i]->transform(_RT);
+}
+
+void Scene::deleteObject(int _id) {
+    // We could use an STL map, but here I will do the matching manually:
+    for (int i=0; i<totalObjects(); i++) 
+        if ( (objectArray[i]->ID()) == _id) objectArray.erase(objectArray.begin()+i); // note: I don't stop the for-loop. I delete ALL objects with this ID 
+    // Not sure I will use the "current pointer", but if I do, then we need to decide what it becomes here... let's point to the last element in the vector: 
+    if (!objectArray.empty()) ptr_currentObject=objectArray.back(); else ptr_currentObject=NULL;
+}
+
+// number of objects in the scene:
+int Scene::totalObjects() {return(objectArray.size());}
+
+// total number of points in the scene:
+int Scene::totalPoints() {
+int ttlpoints=0;
+for (unsigned short i=0; i<objectArray.size(); i++) ttlpoints+=objectArray[i]->size();
+return(ttlpoints);
+}
+    
+/*
+void Scene::render(LaserRenderer* ptr_lsr) {
+    ptr_lsr->renderScene(this);
+    // Or, if one want to use the object render method (that also calls lsr methods anyway, so it is heavier):
+    //  for (int i=0; i<Scene.size(); i++) renderObject(ptr_scene->objectArray[i]);
+}
+*/
+
+ int Scene::sense() {
+ numTouchedObjects=0;
+ for (int i=0; i<totalObjects(); i++) 
+    if (objectArray[i]->displaySensingBuffer.processSensedData()) numTouchedObjects++;
+ //touchedScene=(numTouchedObjects>0);
+ return(numTouchedObjects); 
+}
+
+