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(); } } } } } |