phiaq – Mocap

Mocap – Fusion Dance Team

For this project, I firstly experimented with Mocap on Processing and the idea came naturally. I took bvh files for dancing from the CMU mocap library (Salsa, ballet, Russian) and interpolated them with lerp to get the “average dance” of all the dances. For this part, I matched Salsa with  Ballet, Salsa with Russia, and Russian with Salsa. I then lined the dancers up and filled them with rainbow hue, making sure the interpolated dances had the midtones. Conceptually, combining various cultures together through dance is an interesting concept because there are natural and political barriers that prevent cultures from mixing. However, naturally different cultures grab ideas from other cultures and inject them into their own lifestyles.

Looking back, I wish I made the graphics better, with the attire of the dancers matching with the type of performance.  To revise this project, I’d can choose more culturally opposite dances to make the interpolation more graphic

Sketch

Process:

Here’s the Video:

Code:

Most of the code is from Golan’s template. Here it is in two separate files

 

// Renders a BVH file with Processing v3.2.1
// Note: mouseX controls the camera.
//PImage img;
PBvh bvh1;
PBvh bvh2;
PBvh bvh3;
 
//------------------------------------------------
void setup() {
  size( 1280, 720, P3D );
  //img = loadImage("russia-flag");
  // Load a BVH file recorded with a Kinect v2, made in Brekel Pro Body v2.
  bvh1 = new PBvh( loadStrings( "55_02.bvh" ) );
  bvh2 = new PBvh( loadStrings( "90_30.bvh" ) );
  bvh3 = new PBvh( loadStrings( "55_20.bvh" ) );
}
 
//------------------------------------------------
void draw() {
  colorMode(HSB);
 
  lights() ;
  background(0, 0, 0);
  //image(img,0,0);
  setMyCamera();        // Position the camera. See code below.
  drawMyGround();       // Draw the ground. See code below.
  updateAndDrawBody();  // Update and render the BVH file. See code below.
}
 
 
//------------------------------------------------
void updateAndDrawBody() {
  int x1 = width/3;
  int x2 = width/2;
  int x3 = 2*(width/3) ;
  int z1 = 0;
  int z2 = -width/3;
 
  //bvh2.drawIntersTo(bvh1, x1, z2, x2, z2, 40, 150, 3);
 
  bvh1.drawIntersTo(bvh2, x2, z1, x3, z2, 0, 50, 3);
  bvh1.drawIntersTo(bvh2, x2, z1, x1, z2, 0, 50,3);
  bvh2.drawIntersTo(bvh3, x1, z2, x2, z2, 50, 150,3);
  bvh2.drawIntersTo(bvh3, x3, z2, x2, z2, 50, 150,3);
  bvh3.drawIntersTo(bvh1, x2, z2, x2, z1, 150, 200,3);
 
  textSize(30);
 
  fill(255);
  text("FUSION DANCE TEAM", x1-20, z1+100, z2-200); 
  textSize(25);
  text("Feat. Ballet, Salsa, Russian ", x1-20, z1+125, z2-200); 
 
  updateBVHs();
}
 
void updateBVHs() {
  bvh1.update(millis());
  bvh2.update(millis());
  bvh3.update(millis());
}
 
//------------------------------------------------
void setMyCamera() {
 
  // Adjust the position of the camera
  float eyeX = mouseX;          // x-coordinate for the eye
  float eyeY = height/2.0f - 200;   // y-coordinate for the eye
  float eyeZ = 350;             // z-coordinate for the eye
  float centerX = width/2.0f;   // x-coordinate for the center of the scene
  float centerY = height/2.0f;  // y-coordinate for the center of the scene
  float centerZ = -400;         // z-coordinate for the center of the scene
  float upX = 0;                // usually 0.0, 1.0, or -1.0
  float upY = 1;                // usually 0.0, 1.0, or -1.0
  float upZ = 0;                // usually 0.0, 1.0, or -1.0
 
  camera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
}
 
//------------------------------------------------
void drawMyGround() {
  // Draw a grid in the center of the ground 
  pushMatrix(); 
  translate(width/2, height/2, 0); // position the body in space
  scale(-1, -1, 1);
 
  stroke(100);
  strokeWeight(1); 
 
  float gridSize = 400; 
  int nGridDivisions = 10; 
 
  for (int col=0; col<=nGridDivisions; col++) {
    float x = map(col, 0, nGridDivisions, -gridSize, gridSize);
    line (x, 0, -gridSize, x, 0, gridSize);
  }
  for (int row=0; row<=nGridDivisions; row++) {
    float z = map(row, 0, nGridDivisions, -gridSize, gridSize); 
    line (-gridSize, 0, z, gridSize, 0, z);
  }
 
  popMatrix();
}
import java.util.List;
 
class PBvh {
    public BvhParser parser;
 
    PBvh(String[] data) {
        parser = new BvhParser();
        parser.init();
        parser.parse(data);
    }
 
    void update(int ms) {
        parser.moveMsTo(ms);//30-sec loop
        parser.update();
    }
 
    //------------------------------------------------
    void draw() {
        // Previous method of drawing, provided by Rhizomatiks/Perfume
 
        fill(color(255));
        for (BvhBone b : parser.getBones()) {
            pushMatrix();
            translate(b.absPos.x, b.absPos.y, b.absPos.z);
            ellipse(0, 0, 2, 2);
            popMatrix();
            if (!b.hasChildren()) {
                pushMatrix();
                translate(b.absEndPos.x, b.absEndPos.y, b.absEndPos.z);
                ellipse(0, 0, 10, 10);
                popMatrix();
 
            }
        }
    }
 
    //------------------------------------------------
    // Alternate method of drawing, added by Golan
    void drawBones() {
        noFill();
        stroke(255);
        strokeWeight(1.0);
 
        List theBvhBones = parser.getBones();
        int nBones = theBvhBones.size();       // How many bones are there?
        for (int i = 0; i < nBones; i++) {         // Loop over all the bones
            BvhBone aBone = theBvhBones.get(i);  // Get the i'th bone
 
            PVector boneCoord0 = aBone.absPos;   // Get its start point
            float x0 = boneCoord0.x;             // Get the (x,y,z) values
            float y0 = boneCoord0.y;             // of its start point
            float z0 = boneCoord0.z;
 
            if (aBone.hasChildren()) {
 
                // If this bone has children,
                // draw a line from this bone to each of its children
                List childBvhBones = aBone.getChildren();
                int nChildren = childBvhBones.size();
                for (int j = 0; j < nChildren; j++) {
                    BvhBone aChildBone = childBvhBones.get(j);
                    PVector boneCoord1 = aChildBone.absPos;
 
                    float x1 = boneCoord1.x;
                    float y1 = boneCoord1.y;
                    float z1 = boneCoord1.z;
 
                    stroke(255);
                    line(x0, y0, z0, x1, y1, z1);
                    line(x0+5, y0+5, z0+5, x1+5,y1+5,z1+5);
 
                }
            } else {
                // Otherwise, if this bone has no children (it's a terminus)
                // then draw it differently.
 
                PVector boneCoord1 = aBone.absEndPos;  // Get its start point
                float x1 = boneCoord1.x;
                float y1 = boneCoord1.y;
                float z1 = boneCoord1.z;
 
                line(x0, y0, z0, x1, y1, z1);
 
                String boneName = aBone.getName();
                if (boneName.equals("Head")) {
                    pushMatrix();
                    translate(x1, y1, z1);
                    scale(-1.0 / 5, -1.0 / 5, 1);
                    noFill();
                    ellipse(0, 0, 30, 30);
                    ellipse(5, 0, 30, 30);
                    popMatrix();
                }
            }
        }
    }
 
    void drawIntersTo(PBvh other, int tX1, int tZ1, int tX2, int tZ2, int sHue, int fHue, int num) {
        noFill();
        strokeWeight(0.5);
 
        List thisBones = parser.getBones();
        List otherBones = other.parser.getBones();
        for (int i = 0; i < thisBones.size(); i++) {
            BvhBone thisBone = thisBones.get(i);
            PVector thisP0 = thisBone.absPos;
 
            BvhBone otherBone = otherBones.get(i);
            PVector otherP0 = otherBone.absPos;
 
            if (thisBone.hasChildren()) {
                List thisBoneChildren = thisBone.getChildren();
                List otherBoneChildren = otherBone.getChildren();
                for (int j = 0; j < thisBoneChildren.size(); j++) {
                    BvhBone thisChildBone = thisBoneChildren.get(j);
                    PVector thisP1 = thisChildBone.absPos;
 
                    BvhBone otherChildBone = otherBoneChildren.get(j);
                    PVector otherP1 = otherChildBone.absPos;
 
                    for(int k = 0; k <= num-1; k++) {
                        float t = (float)k/(num-1);
                        stroke(lerp(sHue, fHue, t), 255, 255);
 
                        float x0 = lerp(thisP0.x, otherP0.x, t);
                        float y0 = lerp(thisP0.y, otherP0.y, t);
                        float z0 = lerp(thisP0.z, otherP0.z, t);
 
                        float x1 = lerp(thisP1.x, otherP1.x, t);
                        float y1 = lerp(thisP1.y, otherP1.y, t);
                        float z1 = lerp(thisP1.z, otherP1.z, t);
 
                        float tX = lerp(tX1, tX2, t);
                        float tZ = lerp(tZ1, tZ2, t);
 
                        pushMatrix();
                        translate(tX, height/2, tZ);
                        scale(-5, -5, 5);
                        line(x0, y0, z0, x1, y1, z1);//draws person
 
 
                        popMatrix();
                    }
                }
            } else {
                PVector thisP1 = thisBone.absEndPos;
                PVector otherP1 = otherBone.absEndPos;
 
                for(int k = 0; k <= num-1; k++) {
                    float t = (float)k/(num-1);
                    stroke(lerp(sHue, fHue, t), 255, 255);
 
                    float x0 = lerp(thisP0.x, otherP0.x, t);
                    float y0 = lerp(thisP0.y, otherP0.y, t);
                    float z0 = lerp(thisP0.z, otherP0.z, t);
 
                    float x1 = lerp(thisP1.x, otherP1.x, t);
                    float y1 = lerp(thisP1.y, otherP1.y, t);
                    float z1 = lerp(thisP1.z, otherP1.z, t);
 
                    float tX = lerp(tX1, tX2, t);
                    float tZ = lerp(tZ1, tZ2, t);
 
                    pushMatrix();
                    {
                        translate(tX, height / 2, tZ);
                        scale(-5, -5, 5);
                        line(x0, y0, z0, x1, y1, z1);//finger
 
 
                        String boneName = thisBone.getName();
                        if (boneName.equals("Head")) {
                            pushMatrix();
                            translate(x1, y1, z1);
                            scale(-1.0 / 5, -1.0 / 5, 5);
 
                            //face
                            pushMatrix();
                            fill(0);
                            ellipse(0, 0, 30, 30);
                            pushMatrix();
                            //fill(lerp(sHue, fHue, t), 255, 255);
 
                            stroke(lerp(sHue, fHue, t), 255, 255);
                            ellipse(6,0,6,6);
                            ellipse(-6,0,6,6);
                            popMatrix();
                            arc(0, 5, 10, 12, 0, PI);
                            popMatrix();
 
                            //hair
                            pushMatrix();
                            noFill();
                            //fill(lerp(sHue, fHue, t), 255, 255,100);
                            bezier(0, -15,25, 0, 30, 20, 15, 20);
                            bezier(0, -15,-25, 0, -30, 20, -15, 20);
                            bezier(0, -15,-30, 0, -40, 20, -10, 20);
                            bezier(0, -15,30, 0, 40, 20, 10, 20);
                            bezier(0, -15,15, 0, 25, 20, 10, 20);
                            bezier(0, -15,-15, 0, -25, 20, -10, 20);
                            popMatrix();
 
                            //dress
                            pushMatrix();
                            //rect(-10,20,20,30);
                            fill(lerp(sHue, fHue, t), 255, 255,100);
                            bezier(0,30,-19, 20, -5, 35, -10, 50); //tanktopleft
                            bezier(0,30,19, 20, 5, 35, 10, 50); //tanktopright
                            bezier(10,50,19, 20, 70, 90, 0, 80);
                            bezier(-10,50,-19, 20, -70, 90, 0, 80);
                            noStroke();
                            quad(0,30,10,50,0,80,-10,50);
                            //triangle(0,30,10,50,0,80);
                            popMatrix();
                            popMatrix();
                        }
                    }
                    popMatrix();
                }
            }
        }
    }
}