Feb 272011
 

This is a very simple script I wrote to make BVH’s exported from DANCE (Dynamic Animation and Control Environment) able to be imported into Blender.

It just adds blank channels to joints if there are less than 3.

"""
DANCE BVH EXPORT THING
-Simple BVH file thing that adds blank channels of
    position to JOINTS and FRAMES to allow BVH Exports from 
    DANCE (Dynamic Animation and Control Environment) to be
    imported into Blender.
www.funkboxing.com
"""

infile = "c:\workspace\bvhMINE\bvhdata\skelORIG2.bvh"
outfile = "c:\workspace\bvhMINE\bvhdata\skelTESTOUT.bvh"

def loadDANCEBVH(fin, fout):
    tab = chr(9)
    f = open(fin, 'r')
    lines = f.readlines()
    f.close()
    
    newlines = list(lines)
    newlines[16] = str(tab+tab+tab+tab+"CHANNELS 3 Xrotation Yrotation Zrotationn")
    newlines[30] = str(tab+tab+tab+tab+"CHANNELS 3 Yrotation Xrotation Zrotationn")
    newlines[34] = str(tab+tab+tab+tab+"CHANNELS 3 Yrotation Zrotation Xrotationn")
    newlines[49] = str(tab+tab+tab+tab+"CHANNELS 3 Yrotation Xrotation Zrotationn")    
    newlines[53] = str(tab+tab+tab+tab+"CHANNELS 3 Yrotation Zrotation Xrotationn")    
    newlines[69] = str(tab+tab+tab+tab+"CHANNELS 3 Xrotation Yrotation Zrotationn")    
    newlines[73] = str(tab+tab+tab+tab+"CHANNELS 3 Xrotation Zrotation Yrotationn")    
    newlines[88] = str(tab+tab+tab+tab+"CHANNELS 3 Xrotation Yrotation Zrotationn")
    newlines[92] = str(tab+tab+tab+tab+"CHANNELS 3 Xrotation Zrotation Yrotationn")    

    for li in range(104, len(lines)):
        vals = lines[li].split(" ")
        vals.insert(12, '0')
        vals.insert(12, '0')
        vals.insert(19, '0')
        vals.insert(21, '0')
        vals.insert(27, '0')
        vals.insert(30, '0')
        vals.insert(30, '0')
        vals.insert(35, '0')
        vals.insert(35, '0')
        vals.insert(39, '0')
        vals.insert(44, '0')
        vals.insert(44, '0')
        vals.insert(48, '0')
        newlines[li] = " ".join(vals) 
    
    fo = open(fout, 'w')
    fo.writelines(newlines)
        
        
        
        
loadDANCEBVH(infile, outfile)
Feb 222011
 

There’s a lot of Kinect-driven mocap development going on and that is fantastic. I also wanted to show off a couple of other animation tools out there. I’d like to see more physics and algorithmic animation tools available and I found a couple of very promising pieces of open-source software.

cartwheel-3d – Physics Based Character Animation Framework


DANCE – Dynamic Animation and Control Environment


Both can be used to create animation with a combination of physics and scripted control. The details of how they work are beyond me, but what they do is pretty amazing. Both are written in c++ but they both heavily use python for scripting and UI.

I am working with cartwheel-3d to try and use some of the features in Blender. I could try to work out a simple BVH exporter for cartwheel, or maybe an OSC server to send animation data to be recorded in Blender. Or simply try to use the functions direction in Blender. Still haven’t got that far. So far all I’ve done is compile cartwheel-3d. So I’ve included some notes on how I did it so if anyone else wants to work on this too they can get started easier.

COMPILE NOTES:
-Basically I followed the instructions on the ‘Get Started‘ page for cartwheel-3d with a few important exceptions.

COMPILING C++ : MS VStudioExpress2010
*no spaces in paths!
*lib folder in workspace ie. “C:workspacelib”
*glew32.dll and glut32.dll lib and lib in PATH variable

-After getting repository and opening- VS2010 converts and messes up target and extensions. To fix this.
>VIEW>PROJECT PAGE>CONFIGURATION PROPERTIES>GENERAL>
-Change Target Name from $(ProjectName) to _$(ProjectName)
-Change Target Extension to .pyd
-Repeat on all projects except ode and gls
-Repeat on debug and release

-Make sure BROWSE INFORMATION is OFF on all projects
>VIEW>PROJECT PAGE>CONFIGURATION PROPERTIES>C/C++>BROWSE INFORMATION
>ENABLE BROWSE INFORMATION – “NO”

DEBUGGING PYTHON: ECLIPSE (CLASSIC) + PYDEV
-Open eclipse (classic)
-Install pydev
-Set interpreter to py26
-Make a copy of ‘cartwheel-3d’ project folder- rename ‘simbicon’
-Install wxpython
-Install pyopengl

-Got some error about Core.py returning _mod before assignment. not sure what I did to siz it- sorry. I remember I opened core.py in the editor to look for the error, then ran again and it worked… weird.

So that’s it for now. Hope to do something constructive with this.

Feb 202011
 

I added a ‘VerletHinge’ class that’s a little hacky but it works to give rotation limits on certain joints. Provides slightly more lifelike flailing… also added a little drawing touch and made the ragdoll hang out until clicked.
[processing]

VerletPoint vPointA = new VerletPoint(100, 100);
VerletPoint[] vPointArr = new VerletPoint[9];
VerletStick[] vStickArr = new VerletStick[8];
VerletHinge[] vHingeArr = new VerletHinge[5];

int nVP = 9;
int nVS = 8;
int nVH = 5;

int xDIM = 300;
int yDIM = 120;

float GraV = .15

xSTART = xDIM/2;
ySTART = yDIM/4;
rdSCALE = 12;

boolean initRD = false;

void setup() {
background(255);
fill(255);
stroke(#568984);
size(xDIM, yDIM);
smooth();
frameRate(30);
strokeWeight(3);

vPointArr[0] = new VerletPoint(xSTART, ySTART+rdSCALE/2); //
vPointArr[1] = new VerletPoint(xSTART-rdSCALE*1.5, ySTART+rdSCALE);
vPointArr[2] = new VerletPoint(xSTART, ySTART+rdSCALE);
vPointArr[3] = new VerletPoint(xSTART+rdSCALE*1.5, ySTART+rdSCALE);
vPointArr[4] = new VerletPoint(xSTART, ySTART+rdSCALE*2);
vPointArr[5] = new VerletPoint(xSTART-rdSCALE, ySTART+rdSCALE*3);
vPointArr[6] = new VerletPoint(xSTART-rdSCALE, ySTART+rdSCALE*4);
vPointArr[7] = new VerletPoint(xSTART+rdSCALE, ySTART+rdSCALE*3);
vPointArr[8] = new VerletPoint(xSTART+rdSCALE, ySTART+rdSCALE*4);

vStickArr[0] = new VerletStick(vPointArr[0], vPointArr[2]);
vStickArr[1] = new VerletStick(vPointArr[2], vPointArr[1]);
vStickArr[2] = new VerletStick(vPointArr[2], vPointArr[3]);
vStickArr[3] = new VerletStick(vPointArr[2], vPointArr[4]);
vStickArr[4] = new VerletStick(vPointArr[4], vPointArr[5]);
vStickArr[5] = new VerletStick(vPointArr[5], vPointArr[6]);
vStickArr[6] = new VerletStick(vPointArr[4], vPointArr[7]);
vStickArr[7] = new VerletStick(vPointArr[7], vPointArr[8]);

vHingeArr[0] = new VerletHinge(vPointArr[5], vPointArr[4], vPointArr[7], 45, 160);

vHingeArr[1] = new VerletHinge(vPointArr[1], vPointArr[2], vPointArr[4], 45, 90);
vHingeArr[2] = new VerletHinge(vPointArr[4], vPointArr[2], vPointArr[3], 45, 90);

vHingeArr[3] = new VerletHinge(vPointArr[6], vPointArr[5], vPointArr[4], 10, 160);
vHingeArr[4] = new VerletHinge(vPointArr[8], vPointArr[7], vPointArr[4], 10, 160);

}

void draw() {
background(225);

if(initRD == false){
vPointArr[0].x = xSTART;
vPointArr[0].y = ySTART;
}
if(mousePressed){
initRD = true;
vPointArr[0].x = mouseX;
vPointArr[0].y = mouseY;
}else{

vPointA.y += GraV;
}
vPointA.update();
vPointA.bounds(0, 0, xDIM, yDIM);

for(int p = 0; p < nVP; p++){
if(p==0,1,3,6,8){
vPointArr[p].y += GraV;
}
vPointArr[p].update();
vPointArr[p].bounds(0, 0, xDIM, yDIM);
}

for(int s = 0; s < nVS; s++){
vStickArr[s].update();
}

for(int h = 0; h < nVH; h++){
//ustr = str(vHingeArr[h].pointA.x)+”,”+str(vHingeArr[h].pointB.x)+”,”+str(vHingeArr[h].pointC.x)
// +”-“+str(vHingeArr[h].aMin)+”,”+str(vHingeArr[h].aMax)+”,”+str(vHingeArr[h].aAng)
//println(ustr);
vHingeArr[h].update();
}
oCOL = 0;
iCOL = 255;

stroke(oCOL); strokeWeight(3); //ARMS
line(vPointArr[2].x, vPointArr[2].y, vPointArr[1].x, vPointArr[1].y);
line(vPointArr[2].x, vPointArr[2].y, vPointArr[3].x, vPointArr[3].y);
stroke(iCOL); strokeWeight(2);
line(vPointArr[2].x, vPointArr[2].y, vPointArr[1].x, vPointArr[1].y);
line(vPointArr[2].x, vPointArr[2].y, vPointArr[3].x, vPointArr[3].y);
stroke(oCOL); strokeWeight(4); //SHINS
line(vPointArr[5].x, vPointArr[5].y, vPointArr[6].x, vPointArr[6].y);
line(vPointArr[7].x, vPointArr[7].y, vPointArr[8].x, vPointArr[8].y);
stroke(iCOL); strokeWeight(3);
line(vPointArr[5].x, vPointArr[5].y, vPointArr[6].x, vPointArr[6].y);
line(vPointArr[7].x, vPointArr[7].y, vPointArr[8].x, vPointArr[8].y);
stroke(oCOL); strokeWeight(5); //THIGHS
line(vPointArr[4].x, vPointArr[4].y, vPointArr[5].x, vPointArr[5].y);
line(vPointArr[4].x, vPointArr[4].y, vPointArr[7].x, vPointArr[7].y);
stroke(iCOL); strokeWeight(4);
line(vPointArr[4].x, vPointArr[4].y, vPointArr[5].x, vPointArr[5].y);
line(vPointArr[4].x, vPointArr[4].y, vPointArr[7].x, vPointArr[7].y);
stroke(oCOL); strokeWeight(6); //CHEST
line(vPointArr[2].x, vPointArr[2].y, vPointArr[4].x, vPointArr[4].y);
stroke(iCOL); strokeWeight(5);
line(vPointArr[2].x, vPointArr[2].y, vPointArr[4].x, vPointArr[4].y);
stroke(oCOL); strokeWeight(7); //HEAD
line(vPointArr[0].x, vPointArr[0].y, vPointArr[2].x, vPointArr[2].y);
stroke(iCOL); strokeWeight(5);

line(vPointArr[0].x, vPointArr[0].y, vPointArr[2].x, vPointArr[2].y);
}

class VerletPoint {
float x, y, oldX, oldY;
VerletPoint(float _x, float _y) {
setPosition(_x, _y);
}
void setPosition(float _x, float _y) {
x = oldX = _x;
y = oldY = _y;
}
void update(){
float tempX = x, tempY = y;
x += getVx();
y += getVy();
oldX = tempX;
oldY = tempY;
}
void bounds(float left, float top, float right, float bottom){
x = constrain(x, left, right);
y = constrain(y, top, bottom-5);
}
void setVx(float value){
oldX = x – value;
}
float getVx(){
return x – oldX;
}
void setVy(float value){
oldY = y – value;
}
float getVy(){
return y – oldY;
}
void render(){
ellipse(x, y, 10, 10);
}
}

class VerletStick {
VerletPoint pointA, pointB;
float len;
VerletStick(VerletPoint _pointA, VerletPoint _pointB){
pointA = _pointA;
pointB = _pointB;
len = dist(pointA.x, pointA.y , pointB.x, pointB.y);
}
void update(){
float dst = dist(pointA.x, pointA.y , pointB.x, pointB.y);
float diff = len – dst;
float offsetX = (diff * (pointB.x – pointA.x) / dst) / 2;
float offsetY = (diff * (pointB.y – pointA.y) / dst) / 2;
pointA.x -= offsetX; pointA.y -= offsetY; pointB.x += offsetX; pointB.y += offsetY;
}
void render(){
line(pointA.x, pointA.y , pointB.x, pointB.y);
}
}

void getAngleABC( PVector a, PVector b, PVector c ){
q1 = b.x-a.x;
q2 = dist(a.x,a.y, b.x,b.y);
q3 = q1/q2;
q4 = degrees(asin(q3));
angBA = degrees(asin((b.x-a.x)/(dist(a.x,a.y, b.x,b.y))));
angBC = degrees(asin((b.x-c.x)/(dist(c.x,c.y, b.x,b.y))));
angABC = abs(angBA-angBC);
return angABC;
}

// ptB
// stickA / stickB
// ptA ptC
class VerletHinge {

VerletPoint pointA, pointB, pointC;
int aMin, aMax;
float aAng;

VerletHinge(VerletPoint _pointA, VerletPoint _pointB, VerletPoint _pointC, int _aMin, int _aMax){
aMin = _aMin; aMax = _aMax;
pointA = _pointA;
pointB = _pointB;
pointC = _pointC;

aAng = getAngleABC(pointA, pointB, pointC);
}

void update(){
aAng = getAngleABC(pointA, pointB, pointC);

//HACK – just move the points closer/further away from each other
if(aAng<aMin){
aCS = constrain((pointC.y – pointA.y) / (pointC.x – pointA.x), 0, 1);
aCRate = constrain(abs(radians(aAng-aMin)), 0, 10);
pointA.x -= aCRate; pointA.y -= aCRate*aCS;
pointC.x += aCRate; pointC.y += aCRate*aCS;
}

if(aAng>aMax){
//println(“doing”);
aCS = (pointC.y – pointA.y) / (pointC.x – pointA.x);
aCRate = abs(radians(aAng-aMin));
if(pointC.x>pointA.x){
pointA.x += aCRate; pointA.y += aCRate*aCS;
pointC.x -= aCRate; pointC.y -= aCRate*aCS;
} else if(pointA.x>pointC.x){
pointA.x -= aCRate; pointA.y -= aCRate*aCS;
pointC.x += aCRate; pointC.y += aCRate*aCS;
}
}
}
void render(){
//line(stickA.pointA.x, stickA.pointA.y , stickA.pointB.x, stickA.pointB.y);
//line(stickB.pointA.x, stickB.pointA.y , stickB.pointB.x, stickB.pointB.y);
}
}

 

[/processing]

Feb 202011
 

Collection of the videos I did for various bands.

Destruction of the Western Hemisphere (Blues and the Gunfighters)

The Rich Don’t Die

Comatoaster

Movin’ Weight – South Park Medley

Feb 202011
 

[EDIT] – Just wanted to post this here in case I forget:

A driver can use the current frame in the expression with – bpy.context.scene.frame_current

So you could do something like: sin((bpy.context.scene.frame_current-10)/5)

BUT!!! After 2.68 expressions in drivers only work if you have Auto Run Python Scripts turned on in UserPrefs>File

————————————

B2.56 doesn’t have proper events yet – so this is a hacky way to drive scene animation. I forgot where I found this info – but it worked so I wanted to make it available.
1) create Empty
2) add single keyframe to Zrot (frame 1)
– should have default expanded poly generator on it
3) add single driver to Yloc (frame1)
– in Drivers> choose – Scripted sxpression
– enter this expression

float(exec("\n".join([l.body for l in bpy.data.texts["RUN"].lines]))==None)

4) then a script called ‘RUN’ should execute every time the frame changes
– Zrot of Empty drives expression which (i think) grabs the text datablock of the script and runs it

here’s a quick thing I did. set up the empty as above…
then make a cube (named ‘Cube’) subdivide it a lot, then run this-

 import bpy import random ob = bpy.data.objects['Cube'] verts = ob.data.vertices for v in verts: rxnum = round(random.uniform(-0.01 ,0.01), 4) rynum = round(random.uniform(-0.01 ,0.01), 4) rznum = round(random.uniform(-0.01 ,0.01), 4) v.co[0] = v.co[0] + rxnum v.co[1] = v.co[1] + rynum v.co[2] = v.co[2] + rznum scene = bpy.context.scene 

BLENDER ARTIST THREAD

Feb 182011
 

Here are two models I made awhile ago for fun. I decided to make them low poly so I could put them up on the web here. I know the viewer is crappy – I’ll work on it later.
Anyway here they are.

Gumby .blend .png

Pokey .blend .png

…and here’s the animation I made from these awhile back
[videoplayer file=”wp-content/video/Gumby-SoulMachine.flv” /]