Laser Sensing Display for UI interfaces in the real world

Dependencies:   mbed

Fork of skinGames_forktest by Alvaro Cassinelli

Revision:
43:1dd4cfc30788
Parent:
42:5f21a710ebc5
Child:
44:2432c218f191
--- a/main.cpp	Fri Oct 18 07:25:03 2013 +0000
+++ b/main.cpp	Mon Oct 21 11:26:48 2013 +0000
@@ -5,16 +5,21 @@
   the trajectory and 3d vector array... but where?
 */
 
+//#define WITH_OSC // this consumes about 20kb or RAM!!!
+
 #include "mbed.h"
+#include "WrapperFunctions.h"
+
+#ifdef WITH_OSC
 #include "mbedOSC.h"
-#include "WrapperFunctions.h"
+#endif
 
 // The following is because I still did not "wrap" ALL the LaserRenderer methods (so we have to use the object lsr directly, for instance to set a matrix: lsr.setIdentityPose()...)
 #include "LaserRenderer.h"
 extern LaserRenderer lsr;
 
-
 // mbed IP address (server):
+#ifdef WITH_OSC
 #ifdef DHCP
 EthernetNetIf eth;
 #else
@@ -42,7 +47,7 @@
 
 OSCClass osc;
 //OSCClass osc(&recMes);  // instantiate OSC communication object, and set the receiver container from the OSC packets
-
+#endif
 
 // for tests:
 extern Scene scene;
@@ -92,8 +97,10 @@
 V2 cursorPosition(0,0);
 
 void createTextScene();
+void addText(string, int, float, float);
+
 float angle;
-string textToDisplay = "HELLO";
+string textToDisplay = "O";
 float fontWidth = 2.5, fontHeight = 2.5; // if calibration is in cm, then this is in cm.
 
 // ==============================================================================================================
@@ -103,8 +110,10 @@
 void createSceneTest();
 void setOrthographicView();
 
+#ifdef WITH_OSC
 void processOSC(UDPSocketEvent e);
-void interpretData();
+#endif
+void interpretCommand();
 void processSerial();
 
 int touchedTimes = 0;
@@ -112,7 +121,7 @@
 sensingModes currentSensingMode=SENSING_PER_OBJECT;//NO_SENSING;
 
 // ================= AUXILIARY VARIABLES FOR INTERPRETING COMMAND FROM SERIAL OR OSC =========================
-// NOTE: the following arrays are GLOBAL (used in processOSC and processSerial, as well as in interpretData function):
+// NOTE: the following arrays are GLOBAL (used in processOSC and processSerial, as well as in interpretCommand function):
 // max of two addresses (top and sub), of a max length of 24 characters:
 char address[2][24];
 //long auxdata[2]; // to store a max of two arguments (note: we will only use LONGs)
@@ -125,6 +134,13 @@
 float auxDataBuffer[128];
 int auxDataBuffer_index=0;
 
+// Commands:
+string command1, command2;
+
+// this is a hack for the time being:
+int objectID;
+int xx, yy; // initial position of object
+bool firstTimeDisplay=true;
 
 // ==============================================================================================================
 int main()
@@ -139,6 +155,7 @@
     // (1) Hardware init (laser powers, positions...):
     IO.init();
 
+#ifdef WITH_OSC
     // OSC initialization:
     // Set the Ethernet port:
     printf("Setting up...\r\n");
@@ -162,18 +179,7 @@
     osc.setReceiveMessage(&recMes); // this sets the receiver container for the OSC packets (we can avoid doing this if we use osc.getMessage() to get messages)
     osc.begin(serverPort, &processOSC); // binds the upd (osc) messages to an arbitrary listening port ("server" port), and callback function
     wait(1);
-
-    //while(true) {
-//     // COMMUNICATION:
-//        // (a) Reading commands:
-//        // Ethernet:
-//        Net::poll(); // this will take care of calling processOSC(UDPSocketEvent e) when a new packet arrives.
-//
-//         wait(.5);
-//         sendMes.setTopAddress("osc");
-//         sendMes.setSubAddress("working");
-//         osc.sendOsc( &sendMes );
-//    }
+#endif
 
     //===================================================================
 
@@ -268,13 +274,9 @@
     lsr.loadExtrinsicsMatrix(E1);
 
     // (2) Create the scene in "local" coordinates:
-    createTextScene(); // Create a default scene (for tests)
+    createTextScene(); // Clear scene, and create a default scene (for tests), and update scene (but not yet rendered)
 
-    // or start with nothing:
-    //clearScene();
-    //setOrthographicView();
-
-    // (3) Set a default PERSPECTIVE and GLOBAL POSE for start displaying:
+   // (3) Set a default PERSPECTIVE and GLOBAL POSE for start displaying:
     lsr.loadProjMatrix(K1, scaleFactorProjector1);
     lsr.setIdentityPose();
     lsr.multPoseMatrix(lsr.EXTRINSICS);  // RT=E // we can simply do: lsr.setExtrinsicsPose()
@@ -282,16 +284,35 @@
     // DEFAULT position in CAMERA coordinates (calibration was in cm):
     lsr.translate(0, 0, 130);
 
-    drawScene(); // this will be called when we change the pose matrix - but needs to be called at least once to start displaying
+     drawScene(); // this will be called when we change the pose matrix - but needs to be called at least once to start displaying
+     updateScene(); // this is important: this will compute the number of objects, points, etc, to prepare the displaying engine (but rendering is NOT yet done,
+    // rendering is done in the drawScene() function.
+    // *** AND IMPORTANT *** the FIRST time, we need to set the display engine (ie, attach the interrupt). This is not needed afterwards, ONLY if we change the scene.
+    
+    startDisplay();
 
-    // *** AND IMPORTANT *** the FIRST time, we need to set the display engine (ie, attach the interrupt). This is not needed afterwards, ONLY if we change the scene.
-    startDisplay();
+    // Add more text (testing):
+  //   textToDisplay="1";
+  //   addText();
+     
+      // (3) Set a default PERSPECTIVE and GLOBAL POSE for start displaying:
+  //  lsr.loadProjMatrix(K1, scaleFactorProjector1);
+  //  lsr.setIdentityPose();
+  //  lsr.multPoseMatrix(lsr.EXTRINSICS);  // RT=E // we can simply do: lsr.setExtrinsicsPose()
+    // DEFAULT position in CAMERA coordinates (calibration was in cm):
+  //  lsr.translate(0, 0, 130);
+     
+   //  drawScene(); 
+   //  updateScene();
 
     // (4) Main loop:
     while(true) {
 
         // =========== Query hardware events (knobs, ethernet, serial port) ============
+       #ifdef WITH_OSC
         Net::poll(); // This polls the network connection for new activity, without keeping on calling this you won't receive any OSC!
+        #endif
+        
         if (pc.readable()) processSerial(); // here, the pose can be changed by a pc command
         hardwareKnobs();
         // =============================================================================
@@ -312,7 +333,7 @@
             lastTimeCreated=t.read_ms();
         }
 
-        if ((currentSensingMode!=NO_SENSING)&&((t.read_ms()-lastTimeSensed)>80)) { // check data sensing every xx ms
+        if ((currentSensingMode!=NO_SENSING)&&((t.read_ms()-lastTimeSensed)>70)) { // check data sensing every xx ms
             // Check objects and change colors or other properties as a function of the touch:
             // NOTE: the testing #define debugDelayMirrors should not be defined in the laserSensingDisplay.h
             // (note: we assume we are drawing the text).
@@ -339,7 +360,7 @@
                     }
                     break;
                 case SENSING_PER_OBJECT: // Per-object sensing and action:
-                    for (int i=0; i<textToDisplay.length(); i++) {
+                    for (int i=0; i<scene.totalObjects(); i++) {
                         BaseObject* ptrObj=scene.objectArray[i];
                         if (ptrObj->sense()) { // this calls to ptrObj->displaySensingBuffer.processSensedData()
                             ptrObj->setColor(0x02); // make it green
@@ -356,8 +377,8 @@
                             // or "highlight" the object by putting "cartouche" around it object (note: do this only if it did NOT have
                             //addCartoucheObject(ptrObj);
 
-                            //pc.putc(i+48);
-
+                             //pc.putc(ptrObj->ID());
+                             pc.printf("%d \n", ptrObj->ID());
                         } else
                             ptrObj->setColor(0x01); // make it blue
                     }
@@ -480,15 +501,13 @@
         lsr.translate(1.1*fontWidth, 0, 0);
     }
 
-    updateScene(); // this is important: this will compute the number of objects, points, etc, to prepare the displaying engine (but rendering is NOT yet done,
-    // rendering is done in the drawScene() function.
-
     lsr.popPoseMatrix();
 
 }
 
-void addText()
+void addText(string text, int id, float posx, float posy)
 {
+    //clearScene();
     lsr.pushPoseMatrix();
     //This function just creates text in local coordinates. We have two options: to create it as a unique object, or as separate objects (one per letter).
     // The first option is simpler now, we just use the wrapper function string3d(string _text, float totalWidth, float height):
@@ -503,8 +522,8 @@
     //lsr.translate(2,6,0);
 
     lsr.flipY();
-    lsr.flipX();
-    lsr.translate(-15,-10,0);
+   // lsr.flipX();
+    lsr.translate(posx,posy,0);
 
     // (b) set current color:
     lsr.setColor(0x04); // three LSB bits for RGB - so 0x02 is GREEN ON (note that the sensing laser, now red, is always on...).
@@ -517,24 +536,33 @@
 
     // A string as a *collection* of object-letters:
     //lsr.translate(-textToDisplay.length()*fontWidth/2,-fontHeight/2,0);
-    for (unsigned short i = 0; i < textToDisplay.length(); i++) {
-        char ch = textToDisplay.at(i);
+     
+    for (unsigned short i = 0; i < text.length(); i++) {
+        char ch = text.at(i);
         if (ch != ' ') {
-            begin(i);
+          begin(id);
             letter3d(ch, fontWidth, fontHeight);
-            end();
+        end();
         }
         lsr.translate(1.1*fontWidth, 0, 0);
     }
-
-    updateScene(); // this is important: this will compute the number of objects, points, etc, to prepare the displaying engine (but rendering is NOT yet done,
-    // rendering is done in the drawScene() function.
-
     lsr.popPoseMatrix();
 
 }
 
-//==================  OSC messageReceivedCallback function =====================
+// ============ COMMUNICATION PROTOCOL ======================================
+// String to store ALPHANUMERIC DATA (i.e., integers, floating point numbers, unsigned ints, etc represented as DEC):
+// TO DO: use string objects!
+char receivedStringData[24]; // note: an integer is two bytes long, represented with a maximum of 5 digits, but we may send floats or unsigned int...
+int indexStringData = 0; //position of the byte in the string
+
+// String to store COMMAND WORDS (not used yet):
+char stringCommand[24];
+int indexStringCommand = 0;
+bool commandReady = false; // will become true when receiving the byte 0 (i.e. the '/0' string terminator)
+
+
+#ifdef WITH_OSC
 //============= RECEIVE OSC COMMANDS =========================
 // This is the callback function called when there are packets on the listening socket. It is not nice to have it
 // here, but for the time being having a "wrapping global" is the simplest solution (we cannot pass a member-function pointer
@@ -547,9 +575,9 @@
 
       //  pc.printf("RECEIVED NEW OSC MESSAGE ----\n");
 
-        // Acquire the addresses and arguments and put them in the GLOBAL variables to be processed by the interpretData function (common to serial and OSC):
-        strcpy(address[0],"");
-        strcpy(address[1],"");
+        // Acquire the addresses and arguments and put them in the GLOBAL variables to be processed by the interpretCommand function (common to serial and OSC):
+        command1="";
+        command2="";
         for (int i=0; i<recMes.getAddressNum(); i++)  {
             strcpy(address[i],recMes.getAddress(i)); // NOTE: up to the rest of the program to check if address[1] is really not null
           //  pc.printf("Address %d = %s \n",i, address[i]);
@@ -566,20 +594,19 @@
         }
 
         // Finally, interpret the command or data:
-        interpretData();
+        interpretCommand();
 
     }
 }
-
+#endif
 
 
-//interpretData(const char& address[2][], const int& data[2]) {
-void interpretData()
+//interpretCommand(const char& address[2][], const int& data[2]) {
+void interpretCommand()
 {
-
     // ==========  DATA (all this is a hack because my OSC class does not accept BUNDLES...) =============
     // Add data to auxiliary data buffer:
-    if (!strcmp(address[0], "data")) {
+    if (command1 == "data") {
         // numArgs is the number of arguments (in my OSC version this is max 2):
      //   pc.printf("--- Data pack: %d\n", numArgs);
         for (int i=0; i<numArgs; i++) {
@@ -592,21 +619,28 @@
     }
     // ========== COMMANDS (using data on auxDataBuffer or directly as arguments =========================
 
-    else if ( !strcmp(address[0], "mbedReset" ) ) mbed_reset();
+    else if (command1 == "objectID") { // ID of the object
+            receivedStringData[indexStringData] = 0;
+            indexStringData = 0;
+            objectID=atoi(receivedStringData);
+       }
+        
+       else if (command1=="initialPosition") { // this is for setting the POSITION of the object to be created:
+           xx=auxDataBuffer[0]; yy=auxDataBuffer[1];
+           auxDataBuffer_index=0;
+       }
 
-    else if ( !strcmp(address[0], "testPower" ) ) {
+    else if (command1 == "mbedReset" ) mbed_reset();
+
+    else if (command1 == "testPower" ) {
         // TO DO
     }
 
     // Enable/disable projection:
-    else if ( !strcmp(address[0], "stopDisplay" )) stopDisplay();
-    else if (!strcmp(address[0], "resumeDisplay"))  resumeDisplay();
-    else if (!strcmp(address[0], "showLimits")) {
-        int value=data[0]; // argument is the number of seconds for display
-        if (value!=-1) {
-            showLimitsMirrors(50, value);
-        }
-    } else if (!strcmp(address[0], "setSensingMode")) {
+    else if ( command1 == "stopDisplay" ) stopDisplay();
+    else if (command1 =="resumeDisplay")  resumeDisplay();
+    else if (command1 =="showLimits") showLimitsMirrors(50, 1);
+    else if (command1 == "setSensingMode") {
         int value=data[0];
         if (value!=-1) { // otherwise do nothing, this is a reception error (there was no data)
             switch(value) {
@@ -626,26 +660,25 @@
     }
 
     // Change state machine color (objects created from this point on will have the state machine color)
-    else if (!strcmp(address[0], "setStateColor")) { // example: 0( (all OFF), 1( blue ON, 2( green ON, 4( red ON, 3( blue and green ON; etc.
+    else if (command1 == "setStateColor") { // example: 0( (all OFF), 1( blue ON, 2( green ON, 4( red ON, 3( blue and green ON; etc.
         int value=data[0];
         if (value!=-1) lsr.setColor(value);
     }
 
     // Real time change of color of ALL the objects in the CURRENT scene (state machine color not changed)
-    else if (!strcmp(address[0], "setAllObjectsColor")) { // example: 0) (all OFF), 1) blue ON, 2) green ON, 4) red ON, 3) blue and green ON; etc.
+    else if (command1 == "setAllObjectsColor") { // example: 0) (all OFF), 1) blue ON, 2) green ON, 4) red ON, 3) blue and green ON; etc.
         int value=data[0];
         if (value!=-1) changeColorScene(value);
     }
 
 
 // ===================  CREATION and DESTRUCTION of objects =========================================================
-    else if (!strcmp(address[0], "clearScene")) {
+    else if (command1 == "clearScene") {
         clearScene();
     }
 
-    else if (!strcmp(address[0], "deleteObject")) { // second address is object identifier (a string that will be converted
-        int idobject=atoi(address[1]);
-        deleteObject(idobject);
+    else if (command1 =="deleteObject") { // second address is object identifier (a string that will be converted
+        deleteObject(objectID);
     }
 
     // Produce a grid of points. The projection is ORTHOGRAPHIC. Also, POSE is reset to identity (i.e., the sent points should have
@@ -657,7 +690,7 @@
     //               posX#posY#sizeX#sizeY#nx#ny#:
     // where the names (ex: posX) is in fact an ASCII string representing the number in decimal base. This means that when we arrive here,
     // the auxiliary array auxDataBuffer contains all that data (as floats), ex: auxDataBuffer[0] is just posX, and auxDataBuffer[5] is ny
-    else if (!strcmp(address[0], "gridScene")) {
+    else if (command1 =="gridScene") {
         // Data is now ordered in the auxDataBuffer array:
         float posX = auxDataBuffer[0], posY = auxDataBuffer[1], sizeX = auxDataBuffer[2], sizeY = auxDataBuffer[3], nx = auxDataBuffer[4], ny = auxDataBuffer[5];
         auxDataBuffer_index=0; // to restart loading the auxiliary buffer 'auxDataBuffer'
@@ -692,7 +725,7 @@
     // In the future, we can have functions to add objects, etc. Basically, every wrapped function should be call-able by the PC.
     // NOTE: the POSE is reset to ID, but we could use the current pose (i.e., send it first by the computer). But for the time being, and in order to modify the
     // cameraProjectorCalibration Xcode project as little as possible, I will perform the transformations on the computer.
-    else if (!strcmp(address[0], "arbitraryGridScene")) {
+    else if (command1 == "arbitraryGridScene") {
         // Data is now ordered in the auxDataBuffer array as PAIRS (X,Y). The argument to this message is the IDENTIFIER of the object:
         // The present value of auxDataBuffer_index contains the number of points x 2
         clearScene();
@@ -718,55 +751,30 @@
     }
 
     // This means we received 2D vertex array to add an object assuming it's planar (we will create an object with all points having z=0 in current pose):
-    else if (!strcmp(address[0], "createObject2D")) {
-        unsigned char numPoints= 11;//auxDataBuffer_index/2;
-        //auxDataBuffer_index = 0; // to restart loading the auxiliary buffer 'auxDataBuffer' through serial port
-
-       // pc.printf("creating 2d object with %d points\n", numPoints);
-
-        int IDObject=atoi(address[1]); // the object identifier is on the second address
-        // the initial position is on data[0-1]
-        // pc.printf("Object ID is %d \n", IDObject);
-        //pc.printf("Position at: %4.2f, %4.2f \n", (float)data[0], (float)data[1]);
-        // pc.printf("Position at: %d, %d \n", (int)data[0], (int)data[1]);
-
-        if (IDObject!=-1) {
-
-            if(true) {
-
-                clearScene();
+    else if (command1 == "createObject2D") {
+        unsigned char numPoints= auxDataBuffer_index/2;
+         if (objectID!=-1) {
 
                 // First, create the object:
                 lsr.pushPoseMatrix();
                 lsr.setIdentityPose();
-
-                // lsr.translate(-15,-10,0);
-
-                lsr.translate(20,20,0);
-
-                // lsr.translate(5,10,0);
-                // lsr.translate((int)data[0], (int)data[1], 0);
+                lsr.translate(xx,yy,0);
 
                 lsr.setColor(0x02); // we will render in current color
 
-                //begin(IDObject);
+                begin(objectID);
                 for (unsigned char i = 0; i < numPoints; i++) {
                     begin(i);
-                    //vertex(auxDataBuffer[2 * i], auxDataBuffer[2 * i + 1],0); // z=0 for 2d objects (in current pose)
+                    vertex(auxDataBuffer[2 * i], auxDataBuffer[2 * i + 1],0); // z=0 for 2d objects (in current pose)
                     //letter3d('A', fontWidth, fontHeight);
-                    vertex(10*cos(2*PI/numPoints*i), 10*sin(2*PI/numPoints*i), 0);
-                    vertex(5*cos(2*PI/numPoints*i+.1), 5*sin(2*PI/numPoints*i+.1), 0);
-                    end();
+                    //vertex(10*cos(2*PI/numPoints*i), 10*sin(2*PI/numPoints*i), 0);
+                    //vertex(5*cos(2*PI/numPoints*i+.1), 5*sin(2*PI/numPoints*i+.1), 0);
                     //pc.printf("local (x,y): %f, %f \n", auxDataBuffer[2 * i],  auxDataBuffer[2 * i+1]);
                     // lsr.translate(1.1*fontWidth, 0, 0);
                 }
+                end();
                 lsr.popPoseMatrix();
 
-                // update the scene for display
-                updateScene();
-
-                //createTextScene();
-
                 // Set the global projection and modelview:
                 lsr.loadProjMatrix(K1, scaleFactorProjector1);
                 lsr.setIdentityPose();
@@ -775,24 +783,24 @@
                 lsr.translate(0, 0, 130);
 
                 // RENDER the scene:
-                drawScene(); // this will be called when we change the pose matrix - but needs to be called at least once to start displaying
+               // update the scene for display
+                drawScene();
+                updateScene();
             }
-
-        }
     }
 
     // This means we received 3D vertex data to create an object.
     // It will be rendered in the CURRENT pose.
-    else if (!strcmp(address[0], "createObject3D")) {
-        int IDObject=data[1];
-        if (IDObject!=-1) {
+    else if (command1 == "createObject3D") {
+        int objectID=data[1];
+        if (objectID!=-1) {
             // Data is now ordered in the auxDataBuffer array in triplets (X,Y,Z).
             // The present value of auxDataBuffer_index contains the number of points x 3
             //lsr.pushPoseMatrix(); // we will render on the current pose
             //clearScene();
             //lsr.setIdentityPose();
             //lsr.setColor(0x02); // we will render in current color
-            begin(IDObject);
+            begin(objectID);
             for (unsigned char i = 0; i < auxDataBuffer_index / 3; i++) {
                 vertex(auxDataBuffer[3 * i], auxDataBuffer[3 * i + 1],
                        auxDataBuffer[3 * i + 2]);
@@ -808,59 +816,46 @@
             auxDataBuffer_index = 0; // to restart loading the auxiliary buffer 'auxDataBuffer' through serial port
         }
     }
+    
+      else if (command1=="createText") {
+            receivedStringData[indexStringData] = 0; // termination for the string
+            indexStringData = 0;
+            // Serial.println(receivedStringData);
+            textToDisplay = string(receivedStringData);
+           
+           if (firstTimeDisplay) {clearScene(); firstTimeDisplay=false;}
+           
+           addText(textToDisplay, objectID, xx, yy);
+           drawScene();
+           updateScene();
+        }
 
     // Create text:
-    else if (!strcmp(address[0], "createTextObject")) {
-
-
-        // //NOTE: the actual text will be in the second address, and the argument will be the ID of this new text object:
-        textToDisplay = address[1];
-        int IDObject=data[0];
-        if (IDObject!=-1) {
-
+    else if (command1 == "createTextObject") {
 
-            //createTextScene();
-//                         // Set a default PERSPECTIVE and GLOBAL POSE for start displaying:
-//                         lsr.loadProjMatrix(K1, scaleFactorProjector1);
-//                         lsr.setIdentityPose();
-//                         lsr.multPoseMatrix(lsr.EXTRINSICS);  // RT=E // we can simply do: lsr.setExtrinsicsPose()
-//                         //This means that the current coordinate frame is the CAMERA, and calibration was in cm:
-//                         lsr.translate(0, 0, 100);
-//                        //lsr.flipY();
-//                         drawScene(); // this will be called when we change the pose matrix - but needs to be called at least once to start displaying
-
-
-          //  clearScene();
-          stopDisplay();
+        if (objectID!=-1) {
 
             // CREATE OBJECT:
             lsr.pushPoseMatrix();
-
             lsr.setIdentityPose(); // we could use a wrapper, but I won't for the time being.
             lsr.flipY();
             //lsr.flipX();
-            lsr.translate(-15,-10,0);
+            lsr.translate(xx,yy,0);
 
-            //begin(IDObject);
-//            string3d(textToDisplay, fontWidth*textToDisplay.length(), fontHeight);
-//            end();
-
-            //begin(IDObject);
+            begin(objectID);
             for (unsigned short i = 0; i < textToDisplay.length(); i++) {
                 char ch = textToDisplay.at(i);
                 if (ch != ' ') {
-                    begin(i);
+                   // begin(i);
                     letter3d(ch, fontWidth, fontHeight);
-                    end();
+                   // end();
                 }
                 lsr.translate(1.1*fontWidth, 0, 0);
             }
-            //end();
+            end();
 
             lsr.popPoseMatrix();
 
-            updateScene();
-
             // Set a default PERSPECTIVE and GLOBAL POSE for start displaying:
             lsr.loadProjMatrix(K1, scaleFactorProjector1);
             lsr.setIdentityPose();
@@ -869,12 +864,13 @@
             lsr.translate(0, 0, 130);
 
             drawScene(); // this will be called when we change the pose matrix - but needs to be called at least once to start displaying
+            updateScene();
         }
     }
 
 
     // (d) TERMINATOR indicating data was for the POSE MATRIX of the object (Mp) (with respect to the CAMERA):
-    else if (!strcmp(address[0], "poseMatrix")) { // when receiving this, it means that the WHOLE matrix data (4x4 values) have been sent in row/column format
+    else if (command1 == "poseMatrix") { // when receiving this, it means that the WHOLE matrix data (4x4 values) have been sent in row/column format
         auxDataBuffer_index = 0; // to restart loading the auxiliary buffer 'auxDataBuffer'
         // Now, auxDataBuffer is a buffer with 12 values (4x3), corresponding to the pose of the object in CAMERA coordinartes (RT')
         lsr.setIdentityPose();               // RT=ID
@@ -885,7 +881,7 @@
     }
 
     // (d) TERMINATOR indicating data was for the projection matrix (will probably be saved in "hard" in the microcontroller code):
-    else if (!strcmp(address[0], "projectionMatrix")) {// when receiving this character, it means that the WHOLE matrix data (3x3 values) have been sent (with '#' separator), in row/column format
+    else if (command1 == "projectionMatrix") {// when receiving this character, it means that the WHOLE matrix data (3x3 values) have been sent (with '#' separator), in row/column format
         auxDataBuffer_index = 0; // to restart loading the auxiliary buffer 'auxDataBuffer' through serial port
         // store in projection matrix:
         lsr.loadProjMatrix(auxDataBuffer, 1.0);
@@ -894,7 +890,7 @@
     }
 
     //(e) TERMINATOR indicating the data was for the extrinsic matrix:
-    else if (!strcmp(address[0], "extrinsicMatrix"))  { // when receiving this character, it means that the WHOLE matrix data (3x3 values) have been sent (with '#' separator), in row/column format
+    else if (command1 == "extrinsicMatrix")  { // when receiving this character, it means that the WHOLE matrix data (3x3 values) have been sent (with '#' separator), in row/column format
         auxDataBuffer_index = 0; // to restart loading the auxiliary buffer 'auxDataBuffer' through serial port
         // store in projection matrix:
         lsr.loadExtrinsicsMatrix(auxDataBuffer);
@@ -903,17 +899,6 @@
     }
 }
 
-//============= RECEIVE SERIAL COMMANDS =========================
-// String to store ALPHANUMERIC DATA (i.e., integers, floating point numbers, unsigned ints, etc represented as DEC):
-// TO DO: use string objects!
-char receivedStringData[24]; // note: an integer is two bytes long, represented with a maximum of 5 digits, but we may send floats or unsigned int...
-int indexStringData = 0; //position of the byte in the string
-
-// String to store COMMAND WORDS (not used yet):
-char stringCommand[24];
-int indexStringCommand = 0;
-bool commandReady = false; // will become true when receiving the byte 0 (i.e. the '/0' string terminator)
-
 void processSerial()
 {
     while (pc.readable() > 0) {
@@ -935,6 +920,18 @@
             indexStringData++;
         }
 
+        // (b) a NUMBER to convert to float and to add to the auxiliary data buffer:
+        else if (incomingByte == '#') { // this means that we received a whole number to convert to float (but we don't know yet if it's for
+            // the modelview, the projection matrix or some other data):
+            receivedStringData[indexStringData] = 0;
+            indexStringData = 0;
+            // Serial.println(receivedStringData); // for tests
+            // convert to float and store in auxiliary "matrix" array:
+            auxDataBuffer[auxDataBuffer_index] = atof(receivedStringData);
+            //Serial.println( auxDataBuffer[auxDataBuffer_index]); // for tests
+            auxDataBuffer_index++;
+        }
+
         // Enable/disable projection:
         else if (incomingByte == '}') {
             stopDisplay();
@@ -944,9 +941,12 @@
 
         // Show maximum excursion of mirrors:
         else if (incomingByte == '*') {
-            showLimitsMirrors(50, 120);
+            showLimitsMirrors(50, 1);
         }
 
+        else if (incomingByte=='_') {
+            clearScene();
+        }
 
         else if (incomingByte == '+') {
             receivedStringData[indexStringData] = 0;
@@ -1040,29 +1040,21 @@
         // In the future, we can have functions to add objects, etc. Basically, every wrapped function should be call-able by the PC.
         // NOTE: the POSE is reset to ID, but we could use the current pose (i.e., send it first by the computer). But for the time being, and in order to modify the
         // cameraProjectorCalibration Xcode project as little as possible, I will perform the transformations on the computer.
-        else if (incomingByte == '=') {
-            // Data is now ordered in the auxDataBuffer array as PAIRS (X,Y)
-            // The present value of auxDataBuffer_index contains the number of points x 2
-            clearScene();
-            lsr.setIdentityPose();
-            //lsr.setColor(0x02); // fixed color, or use the current color (in which case, we need to call lsr.pushColor() and then pop it again).
-            lsr.setColor(0x03); // blue+green
-            IO.setLaserLockinPower(0); // DISABLING SENSING LASER! (here the red). This is FOR CALIBRATION laser-camera
-
-            // begin(1) // we can create a single object, or one object per position (with repetition of the point if needed)
-            for (unsigned char i = 0; i < auxDataBuffer_index / 2; i++) {
-                begin(i);
-                for (unsigned char k=0; k<1; k++) // fixed repetition of points - we can send this as a parameter if we want.
-                    vertex(auxDataBuffer[2 * i], auxDataBuffer[2 * i + 1], 0);
-                end();
-            }
-            updateScene();
-            // Set a default GLOBAL POSE and ORTHO projection matrix for start displaying, or use the CURRENT ONE (for that, we should have
-            // properly called lsr.pushPoseMatrix())
-            lsr.setOrthoProjection();
-            lsr.setIdentityPose();
-            drawScene();
-            auxDataBuffer_index = 0; // to restart loading the auxiliary buffer 'auxDataBuffer' through serial port
+        else if (incomingByte == '@') { // ID of the object
+            command1="objectID";
+            interpretCommand();
+       }
+        
+       else if (incomingByte == '~') { // this is for setting the POSITION of the object to be created:
+            command1="initialPosition";
+            interpretCommand();
+            
+       }
+        
+        
+        else if (incomingByte == '=') { // Create 2d object:
+            command1 = "createObject2D"; 
+            interpretCommand();
         }
 
         // This means we received 3D vertex data to create a single scene out of these points (we will create a single object).
@@ -1090,17 +1082,6 @@
             auxDataBuffer_index = 0; // to restart loading the auxiliary buffer 'auxDataBuffer' through serial port
         }
 
-        // (b) a NUMBER to convert to float and to add to the auxiliary data buffer:
-        else if (incomingByte == '#') { // this means that we received a whole number to convert to float (but we don't know yet if it's for
-            // the modelview, the projection matrix or some other data):
-            receivedStringData[indexStringData] = 0;
-            indexStringData = 0;
-            // Serial.println(receivedStringData); // for tests
-            // convert to float and store in auxiliary "matrix" array:
-            auxDataBuffer[auxDataBuffer_index] = atof(receivedStringData);
-            //Serial.println( auxDataBuffer[auxDataBuffer_index]); // for tests
-            auxDataBuffer_index++;
-        }
 
         /*
          else if (incomingByte=='!') { // sets the width of the letter
@@ -1120,17 +1101,9 @@
 
         // (c) TERMINATOR indicating the data was text to display:
         else if (incomingByte == '"') { // this means that the previous data was TEXT to display
-            receivedStringData[indexStringData] = 0; // termination for the string
-            indexStringData = 0;
-            // Serial.println(receivedStringData);
-            textToDisplay = string(receivedStringData);
-           // stopDisplay();
-           // addText();
-           createTextScene();
-            drawScene(); // needed because we changed the geometry, and we need to compute the projection once for display (of course, this will
-            // happens anyway when the computer send the pose matrix).
-            //  resumeDisplay();
-        }
+            command1="createText";
+            interpretCommand();
+            }
 
         // (d) TERMINATOR indicating data was for the POSE MATRIX of the object (Mp) (with respect to the CAMERA):
         else if (incomingByte == '$') { // when receiving this character, it means that the WHOLE matrix data (4x4 values) have been sent (with '#' separator), in row/column format