Laser Sensing Display for UI interfaces in the real world
Fork of skinGames_forktest by
Scene.cpp
- Committer:
- mbedalvaro
- Date:
- 2014-04-17
- Revision:
- 47:199042980678
- Parent:
- 43:1dd4cfc30788
File content as of revision 47:199042980678:
#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); } // ATTENTION: deleting objects imply stoping the displaying engine, and updating. This is mandatory, not in the case of ADDING objects... 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); }