Wednesday, May 22, 2013

Blender animation visualizer in Processing using XML (data visualization from XML files) Part 2

I did a different visualization of a Blender animation in a 'point cloud' representation in 3D. I divided the screen in two, one for the 3d world, and other for the frame slider.

To run the code below, you'll need a XML file inside the data folder of the processing sketch, as we did in the previous post.

To move inside the 3D world, left-click and move, to zoom, right-click and move





//http://creativec0d1ng.blogspot.com.br/ by Italo Travenzoli



import java.awt.Frame; //import Frame
import java.awt.BorderLayout; //import Border Layout
import controlP5.*; //import proxml library
private ControlP5 cp5; //import controlP5 library
ControlFrame cf; // create a control frame object


import peasy.*; //import Peasy library
PeasyCam cam;


import proxml.*; //import proxml library





//xml element to store and load the data of the xml

XMLElement Animation;
XMLElement Object;
XMLElement frame;
XMLElement framePointer;
XMLElement position;
XMLElement positionPointer;
XMLElement rotation;
XMLElement rotationPointer;


XMLInOut xmlInOut;




float posX, posY, posZ; // float variables for positions 
String objName; // string variables for object name



int frameSelector = 0; //variable to select frames, initialized with the 0 position
int frameSelectorConstrain; ///constrained variable to select frames
int objectSelector = 0; //variable to select objects, initialized with the 0 position


int numFrames=0; //variable to count the number of frames in the animation, initialized with the 0 position

int numObjects=0; //variable to count the number of objects in the scene, initialized with the 0 position

float [] pointCloudX; //array of floats (x positions of points in the cloud)
float [] pointCloudY; //array of floats (y positions of points in the cloud)
float [] pointCloudZ; //array of floats (z positions of points in the cloud)



float varYMap; //float variable to map the y variation


void setup() {
  size(600, 350, P3D); //size & p3d render

  cam = new PeasyCam (this, 1000);
  //cam.setMinimumDistance(1000);
  cam.setMaximumDistance(5000);

  xmlInOut = new XMLInOut(this);
  try {
    xmlInOut.loadElement("data.xml");
  }
  catch(Exception e) {
    //if the xml file could not be loaded it has to be created
    // xmlEvent(new XMLElement("Animation"));
  }



  //controls

  cp5 = new ControlP5(this); //new ControlP5 object
  cf = addControlFrame("extra", 400, 150); //new Control Frame object - secondary window - (name, width, height)


  numObjects = (Animation.countChildren()-1); //define numObjects with the number of childrens of the 'Animation' tag
  numFrames= (Object.countChildren()-1); //define numFrames with the number of childrens of the 'Object' tag


  pointCloudX= new float [numFrames]; //create an float array with the size of number of frames
  pointCloudY= new float [numFrames]; //create an float array with the size of number of frames
  pointCloudZ= new float [numFrames]; //create an float array with the size of number of frames

  
}

void xmlEvent(XMLElement element) {
  Animation = element; //define the Animation element as the element (first tag of XML)
  Object = Animation.getChild(0); //define the Object element as the -first- child of Animation tag in position 0 (the first object of the xml file)

}

void draw() {
  background(255); //white bg
  frameSelectorConstrain = constrain(frameSelector, 0, (Object.countChildren()-2)); // constrain frame selector





  for (int a = 0; a< numObjects; a++) { // for all objects in scene
    Object = Animation.getChild(a); //get objects
    objName  =(Object.getAttribute("name")); //get objects names
      
    for (int b=0; b<numFrames;b++) { // for all frames
      
      
      framePointer = Object.getChild(b); //get frame in context
      positionPointer = framePointer.getChild(0); //read _position as first child of _frame
      rotationPointer = framePointer.getChild(1); //read _rotation as second child of _frame
      
     
      
      pointCloudX[b] = positionPointer.getFloatAttribute("posX"); //read attribute 'posX' as float
      pointCloudY[b] = positionPointer.getFloatAttribute("posY"); //read attribute 'posY' as float
      pointCloudZ[b] = positionPointer.getFloatAttribute("posZ"); //read attribute 'posZ' as float
      fill(255, 0, 0); //red fill
      stroke(255,0,0); //red stroke
      
   
      //draw points (to represent position in time)
      pushMatrix();
      stroke(255,0,0); //red stroke
      strokeWeight(5); //stroke weight 5
      translate(pointCloudX[b]*100, pointCloudZ[b]*-100, pointCloudY[b]*100); //translate each point to the position of the objects in scene (*100, because the values are too low)
      point(0,0); //draw point
      popMatrix();
      
    // draw lines (to represent rotation in time)
      pushMatrix();
      pushStyle();
      stroke(0,0,255); //blue stroke
      strokeWeight(1); //stroke weight 2
      translate(pointCloudX[b]*100, pointCloudZ[b]*-100, pointCloudY[b]*100);  //translate each line to the position of the objects in scene (*100, because the values are too low)
      rotateX(radians(rotationPointer.getFloatAttribute("rotX")*100)); //rotate x
      rotateY(radians(rotationPointer.getFloatAttribute("rotY")*100)); //rotate y
      rotateZ(radians(rotationPointer.getFloatAttribute("rotZ")*100)); //rotate z
      line(0,0,0,-30); //draw line
      popStyle();
      popMatrix();
      
    }
    

      //draw point of the selected frame
      pushMatrix();
      stroke(0,255,0); //green stroke
      strokeWeight(8); //stroke weight 8
      translate(pointCloudX[frameSelectorConstrain]*100, pointCloudZ[frameSelectorConstrain]*-100, pointCloudY[frameSelectorConstrain]*100); //translate each point to the position of the objects in scene (*100, because the values are too low)
      point(0,0); //draw point
      popMatrix();
      //draw text
      pushMatrix();
      fill(255,0,0);
      translate(pointCloudX[0]*100, pointCloudZ[0]*-100, pointCloudY[0]*100); //translate each object name to the position of the objects in scene (*100, because the values are too low)
      textSize(20); // text size 20
      text(objName, 20, 20); //draw text with offset of 20 pixels 
      popMatrix();
     
      
  }

//draw world box
  noFill();
  stroke(150);
  strokeWeight(2);
  box (700);
}


ControlFrame addControlFrame(String theName, int theWidth, int theHeight) {
  Frame f = new Frame(theName);
  ControlFrame p = new ControlFrame(this, theWidth, theHeight);
  f.add(p);
  p.init();
  f.setTitle(theName);
  f.setSize(p.w, p.h);
  f.setLocation(100, 100);
  f.setResizable(false);
  f.setVisible(true);
  return p;
}


// the ControlFrame class extends PApplet, so we 
// are creating a new processing applet inside a
// new frame with a controlP5 object loaded
public class ControlFrame extends PApplet {

  int w, h;

  int abc = 100;

  public void setup() {
    size(w, h);
    frameRate(25);
    cp5 = new ControlP5(this);

//create sliders

//slider to select frame
    numFrames=(Object.countChildren()-1);
    cp5.addSlider("frameSelector")
      .setPosition(20, 20)
        .setWidth(200)
        .setHeight(50)
          .setRange(0, numFrames) // values can range from big to small as well
            .setValue(0)
              //.setSliderMode(Slider.FLEXIBLE)
              .plugTo(parent, "frameSelector")
                ;
    frameSelector = constrain(frameSelector,0,Object.countChildren()-1);
    /*
    cp5.addSlider("abc").setRange(0, 255).setPosition(10,10);
     cp5.addSlider("def").plugTo(parent,"def").setRange(0, 255).setPosition(10,30);
     */
  }

  public void draw() {
    background(255);

    fill(0);
    pushMatrix();


    textSize(20);
    text("frame: "+frameSelector, 20, 100);
    popMatrix();


    
  }

  private ControlFrame() {
  }

  public ControlFrame(Object theParent, int theWidth, int theHeight) {
    parent = theParent;
    w = theWidth;
    h = theHeight;
  }


  public ControlP5 control() {
    return cp5;
  }


  ControlP5 cp5;




  Object parent;

}

No comments:

Post a Comment