cloth physics exp. kit

══════════════════

Introduction

══════════════════

this is part 2 of a series

although you may be able to use this, it is meant as a study and demonstration for

daz-script coders

in part 1 we saw particle physics : http://sites.google.com/site/mcasualsdazscripts/particle-physics

this script too is based on the article "Advanced Character Physics" by Thomas Jakobsen

http://www.gamasutra.com/resource_guide/20030121/jacobson_01.shtml

══════════════════

History

══════════════════

02/07/2010 Release

══════════════════

Installation

══════════════════

download the dip at the bottom of this page

unzip it in your daz content folder

typically c:\program files\daz\studio\content

this will install the cloth.cr2 figure in the

content / Figure / mcasual folder

and the scripts mcjPhysicsExp2.dsa and mcjPhysicsExp2DS1and2.ds

scripts in the studio/scripts/mcasual folder

also mcjPhysicsExp2_readme.txt will be placed in content/readme's

your scene must contain a "cloth.cr2" figure

this figure is part of the distribution Zip file

see the attachments at the bottom of this page

when you load it, the cloth is invisible because

all the vertices are located at ( 0, 0, 0 )

this figure has 243 morph channels that allow

this script to totally control its shape

you should never move the cloth figure

your scene must also contain a cylinder (re)named "pole"

this cylinder should be 1 meter long

the piece of cloth will attach itself to this pole

during the simulation

══════════════════

Use

══════════════════

- parent the 'pole' to a character's hand

- animate the character. the animation goes from frames 0 to 100

run the script, processing on a recently started Daz Studio can take 46 seconds

this delay may then double! each time the script is run

so we suggest you save your scene, close daz studio,

then reload your scene before running the script

source code:

// DAZ Studio version 3.0 filetype DAZ Script

// written by mCasual/Jacques

// based on: "Advanced Character Physics" by Thomas Jakobsen

// http://www.gamasutra.com/resource_guide/20030121/jacobson_01.shtml

// your scene must contain a "cloth.cr2" figure

// this figure is part of the distribution Zip file

// when you load it, the cloth is invisible because

// all the vertices are located at ( 0, 0, 0 )

// this figure has 243 morph channels that allow

// this script to totally control its shape

// you should never move the cloth figure

// your scene must contain a cylinder (re)named "pole"

// this cylinder should be 1 meter long

// the piece of cloth will attach itself to this pole

// during the simulation

// typical use:

// - parent the 'pole' to a character's hand

// - animate the character. the animation goes from frames 0 to 100

// run the script, processing on a recently started Daz Studio can take 46 seconds

// this delay may then double! each time the script is run

// so we suggest you save your scene, close daz studio,

// then reload your scene before running the script

//================================================================================================

//

//================================================================================================

var clothNode;

var clothObj;

var poleNode;

var NUM_PARTICLES = 81;

m_x = new Array(); // Current positions

m_oldx = new Array(); // Previous positions

m_a = new Array(); // Force accumulators

m_fTimeStep = 1.0 / 30.0;

m_fTimeStepSquared = m_fTimeStep * m_fTimeStep;

//note: gravity was reduced from the real value of 980

//to get a more "floaty" cloth

//things to try : no gravity, strong wind from the side : DzVec3( -400, 0, 0 )

m_vGravity = new DzVec3( 0, -400, 0 ); // Gravity in cm / sec^2

var NumDiv = 8; //the cloth figure is based on a simple 8x8 plane

var numRows = NumDiv +1

var numCols = NumDiv + 1

var linklen = 100 / NumDiv; //setting the distance between the vertices

//================================================================================================

//

//================================================================================================

function Verlet()

{

var a;

getPole(); //the first row of the cloth vertices follows the pole

//the other vertices are subject to the forces( gravity in this case )

//and velocity

for( var i = numCols; i < NUM_PARTICLES; i++ )

{

x = m_x[i];

tempx = x;

x = x.add( tempx );

x = x.subtract( m_oldx[i] );

a = DzVec3( m_a[i] );

a.x = a.x * m_fTimeStepSquared;

a.y = a.y * m_fTimeStepSquared;

a.z = a.z * m_fTimeStepSquared;

m_x[i] = x.add( a );

m_oldx[i] = tempx;

}

}

//================================================================================================

//

//================================================================================================

function TimeStep()

{

AccumulateForces();

Verlet();

SatisfyConstraints();

}

//================================================================================================

//

//================================================================================================

function SatisfyConstraints()

{

//there's 9 columns of vertices

//the top of each column if firmly attached to the 'pole'

//the other vertices down that column are allowed to

//swing around, the only constrain being that they keep

//the original separation / distance

//todo : constrain the separation between columns from top to bottom

var col, row, idx, prevPos, thisPos;

for( col = 0; col < numCols; col++ )

{

idx = col;

prevPos = m_x[col];

for( row = 1; row < numRows; row++ )

{

idx += numCols;

thisPos = m_x[idx];

delta = thisPos.subtract( prevPos );

delta.setLength( linklen );

m_x[idx] = prevPos.add( delta );

prevPos = m_x[idx];

}

}

}

//================================================================================================

// in this simulation the only force is gravity

// this is where we could add wind, turbulence, vacuums etc

//================================================================================================

function AccumulateForces()

{

for( var i = 0; i < NUM_PARTICLES; i++ )

{

m_a[i] = m_vGravity;

}

}

//================================================================================================

// position the 81 vertices of the cloth figure

//================================================================================================

function Draw()

{

for( var i = 0; i < NUM_PARTICLES; i++ )

{

poke( i, m_x[i] );

}

}

//================================================================================================

// top row of vertices glued to the 'pole'

// other vertices dangling below

// vertical and horizontal spacing = linklen

//================================================================================================

function initParticles()

{

getPole();

for( var col = 0; col < numCols; col++ )

{

var topPos = m_x[col]

for( var row = 1; row < numRows; row++ )

{

var idx = row * numCols + col;

m_oldx[idx] = m_x[idx] = DzVec3(

topPos.x,

topPos.y - row * linklen,

topPos.z

);

debug( m_x[idx].x + " " + m_x[idx].y + " " + m_x[idx].z );

}

}

}

//================================================================================================

// the position of each vertex of the cloth figure is controlled by 3 morphs ( x, y, z )

// setting a morph to 100% = 1 meter displacement along the corresponding axis

//================================================================================================

function poke( idx, pos )

{

idx *= 3;

clothObj.getModifier( idx++ ).getValueChannel().setValue( pos.x/100 );

clothObj.getModifier( idx++ ).getValueChannel().setValue( pos.y/100 );

clothObj.getModifier( idx++ ).getValueChannel().setValue( pos.z/100 );

}

//================================================================================================

// the first row of vertices of the cloth is glued along the 'pole' spacing is linklen

//================================================================================================

function getPole()

{

var rot = poleNode.getWSRot();

var pos = poleNode.getWSPos();

var vec = rot.getYAxis();

vec.normalize();

for( var i = 0; i < 9; i++ )

{

var len = i * linklen;

m_x[i] = new DzVec3(

pos.x + vec.x * len,

pos.y + vec.y * len,

pos.z + vec.z * len

);

}

}

//================================================================================================

//

//================================================================================================

function main()

{

clothNode = Scene.findNode( "cloth1" );

if( !clothNode )

{

MessageBox.information( "Could not find required cloth figure in the scene", "error", "&OK" );

return;

}

clothObj = clothNode.getObject();

poleNode = Scene.findNodeByLabel( "pole" );

if( !poleNode )

{

MessageBox.information( "Your scene should contain a 1 meter long cylinder named 'pole'", "error", "&OK" );

return;

}

Scene.setFrame( 0 );

initParticles()

Draw();

setBusyCursor();

startProgress( "Processing " + 100 + " frames" , 100, true , true );

for( var i = 1; i <= 100; i++ )

{

processEvents();

updateProgress( i );

if( progressIsCancelled() )

{

clearBusyCursor();

finishProgress();

break;

}

Scene.setFrame( i );

TimeStep();

Draw();

}

clearBusyCursor();

finishProgress();

}

//launch

main();