Search code examples
processingquaternions

Overlapping issue in P3D when rotating


I'd like to rotate a cube in P3D and my code uses live sensor data to do that. The problem is the previous orientations of the cube are always visible and overlap (as you can see in this image: https://i.sstatic.net/txXw6.jpg), which I don't want. I already tried the functions "hint(DISABLE_OPTIMIZED_STROKE)" and "hint(ENABLE_DEPTH_TEST)", which did nothing. Besides the hint functions I found nothing on a similar issue.

How can I render ONLY the current orientation?

import processing.serial.*;
import toxi.geom.*;

Serial myPort;

float qW;
float qX;
float qY;
float qZ;

float[] axis = new float[4];
Quaternion quat = new Quaternion(1, 0, 0, 0);

void setup()
{
  size(600, 400, P3D);

  myPort = new Serial(this, "COM3", 9600);                 

  background(0);
  lights();
}

void draw()
{
  serialEvent();

  quat.set(qW, qX, qY, qZ);
  axis = quat.toAxisAngle();

  pushMatrix(); 
  translate(width/2, height/2, -100);
  rotate(axis[0], axis[1], axis[2], axis[3]);
  noFill();
  stroke(255);
  box(330, 200, 40);
  popMatrix();
}

void serialEvent()
{
  int newLine = 13; // new line character in ASCII
  String message;

  do
  {
    message = myPort.readStringUntil(newLine); // read from port until new line

    if (message != null)
    {
      String[] list = split(trim(message), " ");
      if (list.length >= 4)
      {
        qW  = float(list[0]);
        qX  = float(list[1]);
        qY  = float(list[2]);
        qZ  = float(list[3]);
      }
    }
  } while (message != null);

}

Solution

  • It looks like you're not clearing the frame buffer. Try adding background(0); as the first line in draw();:

    void draw()
    {
      //clear background
      background(0);
    
      serialEvent();
    
      quat.set(qW, qX, qY, qZ);
      axis = quat.toAxisAngle();
    
      pushMatrix(); 
      translate(width/2, height/2, -100);
      rotate(axis[0], axis[1], axis[2], axis[3]);
      noFill();
      stroke(255);
      box(330, 200, 40);
      popMatrix();
    }
    

    Off topic, it might worth checking out serialEvent(). You could do something like this in setup()

    myPort = new Serial(this, "COM3", 9600);     
    myPort.bufferUntil('\n');
    

    you shouldn't need to call serialEvent() in draw(), the serial library will do that, as it's buffering.

    Then in serialEvent() hopefully you can get away with just:

    String message = myPort.readString();
    if(message !=null){
       String[] list = split(trim(message), " ");
       if (list.length >= 4)
          {
            qW  = float(list[0]);
            qX  = float(list[1]);
            qY  = float(list[2]);
            qZ  = float(list[3]);
          }
    }