Laser Sensing Display for UI interfaces in the real world
Fork of skinGames_forktest by
Diff: Scene.cpp
- 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); +} + +