Laser Sensing Display for UI interfaces in the real world
Fork of skinGames_forktest by
Scene.cpp@43:1dd4cfc30788, 2013-10-21 (annotated)
- Committer:
- mbedalvaro
- Date:
- Mon Oct 21 11:26:48 2013 +0000
- Revision:
- 43:1dd4cfc30788
- Parent:
- 40:3ba2b0ea9f33
This is working very simply, objects don't have behaviours. IT would be nice to add "behaviours" that may be common to all the objects. These could be a collection of methods acting on the 3d coordintates of the objects, and belong to a friend class
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mbedalvaro | 40:3ba2b0ea9f33 | 1 | #include "Scene.h" |
mbedalvaro | 40:3ba2b0ea9f33 | 2 | //#include "hardwareIO.h" //(for tests using serial port only) |
mbedalvaro | 40:3ba2b0ea9f33 | 3 | |
mbedalvaro | 40:3ba2b0ea9f33 | 4 | Scene scene; // pre-instantiated GLOBAL (cross file object, declared extern in the Scene.h header) |
mbedalvaro | 40:3ba2b0ea9f33 | 5 | |
mbedalvaro | 40:3ba2b0ea9f33 | 6 | //extern LaserRenderer lsr; // Use of the global object lsr (LaserRenderer type). Object is pre-instantiated in LaserRenderer.cpp |
mbedalvaro | 40:3ba2b0ea9f33 | 7 | |
mbedalvaro | 40:3ba2b0ea9f33 | 8 | using namespace std; |
mbedalvaro | 40:3ba2b0ea9f33 | 9 | |
mbedalvaro | 40:3ba2b0ea9f33 | 10 | //======================================= BASE OBJECT CLASS ======================================= |
mbedalvaro | 40:3ba2b0ea9f33 | 11 | //BaseObject::BaseObject() {} |
mbedalvaro | 40:3ba2b0ea9f33 | 12 | |
mbedalvaro | 40:3ba2b0ea9f33 | 13 | BaseObject::~BaseObject() { |
mbedalvaro | 40:3ba2b0ea9f33 | 14 | // in principle, we don't need to do anything: |
mbedalvaro | 40:3ba2b0ea9f33 | 15 | // the vertexArray is a vector that does NOT contain pointers; also myDisplaySensingBuffer is destroyed by calling its destructor. |
mbedalvaro | 40:3ba2b0ea9f33 | 16 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 17 | |
mbedalvaro | 40:3ba2b0ea9f33 | 18 | |
mbedalvaro | 40:3ba2b0ea9f33 | 19 | 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... |
mbedalvaro | 40:3ba2b0ea9f33 | 20 | vertexArray.push_back(_RT*_v3); |
mbedalvaro | 40:3ba2b0ea9f33 | 21 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 22 | |
mbedalvaro | 40:3ba2b0ea9f33 | 23 | void BaseObject::transform(Mat44& _RT) { // this transform all the vertices of the object by _RT |
mbedalvaro | 40:3ba2b0ea9f33 | 24 | for (unsigned short i=0; i<vertexArray.size(); i++) vertexArray[i]=_RT*vertexArray[i]; |
mbedalvaro | 40:3ba2b0ea9f33 | 25 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 26 | |
mbedalvaro | 40:3ba2b0ea9f33 | 27 | void BaseObject::clear() { // this deletes all the vertices (and their projections) in the object: |
mbedalvaro | 40:3ba2b0ea9f33 | 28 | vertexArray.clear(); |
mbedalvaro | 40:3ba2b0ea9f33 | 29 | displaySensingBuffer.lsdTrajectory.clear(); |
mbedalvaro | 40:3ba2b0ea9f33 | 30 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 31 | |
mbedalvaro | 40:3ba2b0ea9f33 | 32 | /* THIS PRODUCE A CIRCULAR REFERENCE! |
mbedalvaro | 40:3ba2b0ea9f33 | 33 | void BaseObject::render(LaserRenderer* ptr_lsr) { |
mbedalvaro | 40:3ba2b0ea9f33 | 34 | // Use the lsr methods: again, this would be kind of convoluted if these objects belongs to a scene that belongs to lsr... |
mbedalvaro | 40:3ba2b0ea9f33 | 35 | ptr_lsr->renderObject(this); |
mbedalvaro | 40:3ba2b0ea9f33 | 36 | */ |
mbedalvaro | 40:3ba2b0ea9f33 | 37 | |
mbedalvaro | 40:3ba2b0ea9f33 | 38 | //Or do it "directly" (but again, we need to use data from the lsr state machine): |
mbedalvaro | 40:3ba2b0ea9f33 | 39 | /* |
mbedalvaro | 40:3ba2b0ea9f33 | 40 | // First, clear the current lsdTrajectory: |
mbedalvaro | 40:3ba2b0ea9f33 | 41 | Object.myDisplaySensingBuffer.lsdTrajectory.clear(); |
mbedalvaro | 40:3ba2b0ea9f33 | 42 | if (lsr.renderingMode==PROJECTION) |
mbedalvaro | 40:3ba2b0ea9f33 | 43 | for (int i=0; i<vertexArray.size(); i++) { |
mbedalvaro | 40:3ba2b0ea9f33 | 44 | LaserPoint newLp=lsr.renderPointProj(Object.vertexArray[i]); // or use a render method for a LaserPoint or an extended V3 class (or directly) |
mbedalvaro | 40:3ba2b0ea9f33 | 45 | // Set per-vertex color too? No, for the time being one color per object... |
mbedalvaro | 40:3ba2b0ea9f33 | 46 | // newLp.myColor=color; |
mbedalvaro | 40:3ba2b0ea9f33 | 47 | Object.myDisplaySensingBuffer.lsdTrajectory.push_back(newLp); |
mbedalvaro | 40:3ba2b0ea9f33 | 48 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 49 | else |
mbedalvaro | 40:3ba2b0ea9f33 | 50 | for (int i=0; i<Object.vertexArray.size(); i++) { |
mbedalvaro | 40:3ba2b0ea9f33 | 51 | LaserPoint newLp=lsr.renderPointRaw(Object.vertexArray[i]); |
mbedalvaro | 40:3ba2b0ea9f33 | 52 | // Set per-vertex color too? No, for the time being one color per object... |
mbedalvaro | 40:3ba2b0ea9f33 | 53 | // newLp.myColor=color; |
mbedalvaro | 40:3ba2b0ea9f33 | 54 | Object.myDisplaySensingBuffer.lsdTrajectory.push_back(newLp); |
mbedalvaro | 40:3ba2b0ea9f33 | 55 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 56 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 57 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 58 | */ |
mbedalvaro | 40:3ba2b0ea9f33 | 59 | |
mbedalvaro | 40:3ba2b0ea9f33 | 60 | Box3d BaseObject::getEnclosingBox() { |
mbedalvaro | 40:3ba2b0ea9f33 | 61 | // This will give the 3d enclosing box for the object, in LOCAL coordinates. |
mbedalvaro | 40:3ba2b0ea9f33 | 62 | // (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) |
mbedalvaro | 40:3ba2b0ea9f33 | 63 | if (vertexArray.size()==0) { |
mbedalvaro | 40:3ba2b0ea9f33 | 64 | enclosingBox.minX=enclosingBox.maxX=enclosingBox.minY=enclosingBox.maxY=enclosingBox.minZ=enclosingBox.maxZ=0; |
mbedalvaro | 40:3ba2b0ea9f33 | 65 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 66 | else |
mbedalvaro | 40:3ba2b0ea9f33 | 67 | { |
mbedalvaro | 40:3ba2b0ea9f33 | 68 | enclosingBox.minX=enclosingBox.maxX=vertexArray[0].x; |
mbedalvaro | 40:3ba2b0ea9f33 | 69 | enclosingBox.minY=enclosingBox.maxY=vertexArray[0].y; |
mbedalvaro | 40:3ba2b0ea9f33 | 70 | enclosingBox.minZ=enclosingBox.maxZ=vertexArray[0].z; |
mbedalvaro | 40:3ba2b0ea9f33 | 71 | for (unsigned short i=1; i<vertexArray.size(); i++) { |
mbedalvaro | 40:3ba2b0ea9f33 | 72 | if (vertexArray[i].x>enclosingBox.maxX) enclosingBox.maxX=vertexArray[i].x; |
mbedalvaro | 40:3ba2b0ea9f33 | 73 | else if (vertexArray[i].x<enclosingBox.minX) enclosingBox.minX=vertexArray[i].x; |
mbedalvaro | 40:3ba2b0ea9f33 | 74 | if (vertexArray[i].y>enclosingBox.maxY) enclosingBox.maxY=vertexArray[i].y; |
mbedalvaro | 40:3ba2b0ea9f33 | 75 | else if (vertexArray[i].y<enclosingBox.minY) enclosingBox.minY=vertexArray[i].y; |
mbedalvaro | 40:3ba2b0ea9f33 | 76 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 77 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 78 | return (enclosingBox); |
mbedalvaro | 40:3ba2b0ea9f33 | 79 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 80 | |
mbedalvaro | 40:3ba2b0ea9f33 | 81 | // Sensing methods (query and process sensed data): |
mbedalvaro | 40:3ba2b0ea9f33 | 82 | // That this is separated from displaying routine make sense: we can query at ANY time for new data, |
mbedalvaro | 40:3ba2b0ea9f33 | 83 | // and this is uncorrelated with the display buffer continuous to work, displaying and sensing things. |
mbedalvaro | 40:3ba2b0ea9f33 | 84 | // ALSO, it is separated from the LaserRenderer: this routine does not uses any "state machine" data. |
mbedalvaro | 40:3ba2b0ea9f33 | 85 | bool BaseObject::sense() {return(this->displaySensingBuffer.processSensedData());} |
mbedalvaro | 40:3ba2b0ea9f33 | 86 | |
mbedalvaro | 40:3ba2b0ea9f33 | 87 | // Max and Min intensity RATIOS (normalized between 0 and 255): |
mbedalvaro | 40:3ba2b0ea9f33 | 88 | unsigned char BaseObject::maxIntensity(void) {displaySensingBuffer.processSensedData(); return displaySensingBuffer.maxI;} |
mbedalvaro | 40:3ba2b0ea9f33 | 89 | unsigned char BaseObject::minIntensity(void) {displaySensingBuffer.processSensedData(); return displaySensingBuffer.minI;} |
mbedalvaro | 40:3ba2b0ea9f33 | 90 | |
mbedalvaro | 40:3ba2b0ea9f33 | 91 | |
mbedalvaro | 40:3ba2b0ea9f33 | 92 | //======================================= THE SCENE CLASS ======================================= |
mbedalvaro | 40:3ba2b0ea9f33 | 93 | |
mbedalvaro | 40:3ba2b0ea9f33 | 94 | //Scene::Scene() : numTouchedObjects(0) {} |
mbedalvaro | 40:3ba2b0ea9f33 | 95 | |
mbedalvaro | 40:3ba2b0ea9f33 | 96 | Scene::~Scene() { |
mbedalvaro | 40:3ba2b0ea9f33 | 97 | this->clear(); // necessary because Scene object variable objectArray is an vector of POINTERS and we need to free memory for the pointed objects. |
mbedalvaro | 40:3ba2b0ea9f33 | 98 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 99 | |
mbedalvaro | 40:3ba2b0ea9f33 | 100 | void Scene::clear() { |
mbedalvaro | 40:3ba2b0ea9f33 | 101 | //NOTE: objectArray stores POINTERS to objects; we need therefore to delete first the object itself: |
mbedalvaro | 40:3ba2b0ea9f33 | 102 | for (int i=0; i<this->totalObjects(); i++) { |
mbedalvaro | 40:3ba2b0ea9f33 | 103 | // pc.printf("deleting object: %d\n", i); |
mbedalvaro | 40:3ba2b0ea9f33 | 104 | delete objectArray[i]; // this call the destructor for BaseObject |
mbedalvaro | 40:3ba2b0ea9f33 | 105 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 106 | objectArray.clear(); // clear the vector of pointers |
mbedalvaro | 40:3ba2b0ea9f33 | 107 | ptr_currentObject=NULL; |
mbedalvaro | 40:3ba2b0ea9f33 | 108 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 109 | |
mbedalvaro | 40:3ba2b0ea9f33 | 110 | void Scene::addObject(BaseObject* ptr_newObject) { |
mbedalvaro | 40:3ba2b0ea9f33 | 111 | objectArray.push_back(ptr_newObject); // note: the object pointed by ptr_newObject has been instantiated OUTSIDE this method. |
mbedalvaro | 40:3ba2b0ea9f33 | 112 | //ptr_currentObject=ptr_newObject; |
mbedalvaro | 40:3ba2b0ea9f33 | 113 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 114 | |
mbedalvaro | 40:3ba2b0ea9f33 | 115 | void Scene::addCurrentObject() { // this adds the "current" object (pointed by ptr_currentObject) |
mbedalvaro | 40:3ba2b0ea9f33 | 116 | objectArray.push_back(ptr_currentObject); |
mbedalvaro | 40:3ba2b0ea9f33 | 117 | // 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 |
mbedalvaro | 40:3ba2b0ea9f33 | 118 | // 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 |
mbedalvaro | 40:3ba2b0ea9f33 | 119 | // the scene class to be able to use child methods, then we need to make BaseObject polymorphic, by declaring all usable methods VIRTUAL. |
mbedalvaro | 40:3ba2b0ea9f33 | 120 | |
mbedalvaro | 40:3ba2b0ea9f33 | 121 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 122 | |
mbedalvaro | 40:3ba2b0ea9f33 | 123 | void Scene::transform(Mat44& _RT) { // this transform all the objects of the scene by _RT |
mbedalvaro | 40:3ba2b0ea9f33 | 124 | for (int i=0; i<totalObjects(); i++) objectArray[i]->transform(_RT); |
mbedalvaro | 40:3ba2b0ea9f33 | 125 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 126 | |
mbedalvaro | 43:1dd4cfc30788 | 127 | // ATTENTION: deleting objects imply stoping the displaying engine, and updating. This is mandatory, not in the case of ADDING objects... |
mbedalvaro | 40:3ba2b0ea9f33 | 128 | void Scene::deleteObject(int _id) { |
mbedalvaro | 40:3ba2b0ea9f33 | 129 | // We could use an STL map, but here I will do the matching manually: |
mbedalvaro | 40:3ba2b0ea9f33 | 130 | for (int i=0; i<totalObjects(); i++) |
mbedalvaro | 40:3ba2b0ea9f33 | 131 | 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 |
mbedalvaro | 40:3ba2b0ea9f33 | 132 | // 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: |
mbedalvaro | 40:3ba2b0ea9f33 | 133 | if (!objectArray.empty()) ptr_currentObject=objectArray.back(); else ptr_currentObject=NULL; |
mbedalvaro | 40:3ba2b0ea9f33 | 134 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 135 | |
mbedalvaro | 40:3ba2b0ea9f33 | 136 | // number of objects in the scene: |
mbedalvaro | 40:3ba2b0ea9f33 | 137 | int Scene::totalObjects() {return(objectArray.size());} |
mbedalvaro | 40:3ba2b0ea9f33 | 138 | |
mbedalvaro | 40:3ba2b0ea9f33 | 139 | // total number of points in the scene: |
mbedalvaro | 40:3ba2b0ea9f33 | 140 | int Scene::totalPoints() { |
mbedalvaro | 40:3ba2b0ea9f33 | 141 | int ttlpoints=0; |
mbedalvaro | 40:3ba2b0ea9f33 | 142 | for (unsigned short i=0; i<objectArray.size(); i++) ttlpoints+=objectArray[i]->size(); |
mbedalvaro | 40:3ba2b0ea9f33 | 143 | return(ttlpoints); |
mbedalvaro | 40:3ba2b0ea9f33 | 144 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 145 | |
mbedalvaro | 40:3ba2b0ea9f33 | 146 | /* |
mbedalvaro | 40:3ba2b0ea9f33 | 147 | void Scene::render(LaserRenderer* ptr_lsr) { |
mbedalvaro | 40:3ba2b0ea9f33 | 148 | ptr_lsr->renderScene(this); |
mbedalvaro | 40:3ba2b0ea9f33 | 149 | // Or, if one want to use the object render method (that also calls lsr methods anyway, so it is heavier): |
mbedalvaro | 40:3ba2b0ea9f33 | 150 | // for (int i=0; i<Scene.size(); i++) renderObject(ptr_scene->objectArray[i]); |
mbedalvaro | 40:3ba2b0ea9f33 | 151 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 152 | */ |
mbedalvaro | 40:3ba2b0ea9f33 | 153 | |
mbedalvaro | 40:3ba2b0ea9f33 | 154 | int Scene::sense() { |
mbedalvaro | 40:3ba2b0ea9f33 | 155 | numTouchedObjects=0; |
mbedalvaro | 40:3ba2b0ea9f33 | 156 | for (int i=0; i<totalObjects(); i++) |
mbedalvaro | 40:3ba2b0ea9f33 | 157 | if (objectArray[i]->displaySensingBuffer.processSensedData()) numTouchedObjects++; |
mbedalvaro | 40:3ba2b0ea9f33 | 158 | //touchedScene=(numTouchedObjects>0); |
mbedalvaro | 40:3ba2b0ea9f33 | 159 | return(numTouchedObjects); |
mbedalvaro | 40:3ba2b0ea9f33 | 160 | } |
mbedalvaro | 40:3ba2b0ea9f33 | 161 | |
mbedalvaro | 40:3ba2b0ea9f33 | 162 |