particle physics experiment kit

Athough it could be used by everyone, this experiment kit is meant for those who can read and tweak daz scripts.

Thomas Jakobsen has an article online where he explains the physics engine he developped for

IO Interactive’s game Hitman: Codename 47.

http://teknikus.dk/tj/gdc2001.htm

This daz-script implements just the basics: 256 particles are projected upward, the physics engine takes it from

there and performs a 100 frames simulation. There's 3 circular platforms at 0, -50 and -100cm, with radius 50,

100 and 150 cm. The "constraints" placed on the particle system is that the particles don't go through the 3 platforms.

There's only one force: constant gravity.

this zip file is found in the attachments at the bottom of this page

it contains the 256-balls figure (256balls.cr2 )

the 3-cone-platforms figure ( cones.cr2 )

the DS3 version of this script mcjPhysicsExp1.dsa

The DS1 & 2 version or mcjPhysicsExp1DS1and2.ds

unzip this in your daz content folder,

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

the files should end up in the folders

\DAZ\Studio\content\Runtime\libraries\Character\mcasual

\DAZ\Studio\content\Runtime\Geometries\mcasual

\DAZ\Studio\content\Scripts\mcasual

\DAZ\Studio\content\ReadMe's

usage:

load the 256-balls and cones figures found in daz studio's

content/Figures/mcasual

run the script, either mcjPhysicsExp1.dsa or mcjPhysicsExp1DS1and2.ds

you'll be given the opportunity to cancel the simulation

on a phenomX3, processing the 256 particles for 100 frames takes 3 minutes ! an eternity.

and unfortunately if you run the script a second time it can be 2 times as long.

so better use a "freshly started" Daz Studio.

code:

// Sample code for physics simulation
// adapted by mcasual/Jacques from code
// by Thomas Jakobsen found at
// http://teknikus.dk/tj/gdc2001.htm
 
// the scene must contain a "256balls.cr2" figure
// or
// 256 nodes named : ball0, ball1 ... ball 255
var NUM_PARTICLES = 256;
var pNodes = []; //particle nodes
var m_pos = []; // Current positions
var m_oldpos = []; // Previous positions
var m_a = []; // Force accumulators
var m_vGravity = new DzVec3( 0, -980, 0 ); // Gravity in cm/s2
var m_fTimeStep = 1 / 30; //in seconds
var t2 = m_fTimeStep * m_fTimeStep;
//=============================================================================================
// get random from range [a,b]
//=============================================================================================
function rnd( a, b )
{
    var d = b - a;
    d = d * Math.random();
    return( d + a );
}
//=============================================================================================
// Verlet integrator
//=============================================================================================
function Verlet()
{
    var a, x, temp;
   
    for( var i = 0; i < NUM_PARTICLES; i++ )
    {
        x = m_pos[i];
        temp = x;
        a = DzVec3( m_a[i] );
        a.x = a.x * t2;
        a.y = a.y * t2;
        a.z = a.z * t2;
        x = x.add( x );
        x = x.subtract( m_oldpos[i] );
        m_pos[i] = x.add( a ); //
        m_oldpos[i] = temp;
    }
}
//=============================================================================================
//
//=============================================================================================
function AccumulateForces()
{   
    for( var i = 0; i < NUM_PARTICLES; i++ )
    {
        m_a[i] = m_vGravity;
    }
}
//=============================================================================================
//
//=============================================================================================
function SatisfyConstraints()
{
    for( var i = 0; i < NUM_PARTICLES; i++ )
    {
        //three circular platforms
        //radius: 50, 100, 150 cm, heights: 0, 50, 100 cm
        var pos = m_pos[i];
        if( pos.y < - 100 )
        {
            if( ( pos.x * pos.x + pos.z * pos.z < 150 * 150 ) )
                pos.y = -100;
        }
        else if( pos.y < - 50 )
        {
            if( ( pos.x * pos.x + pos.z * pos.z < 100 * 100 ) )
                pos.y = -50;
        }
        else if( pos.y < 0 )
        {
            if( ( pos.x * pos.x + pos.z * pos.z < 50 * 50 ) )
                pos.y = -0;
        }
        m_pos[i] = pos;
    }
}
//=============================================================================================
// initial state of the particle system
//=============================================================================================
function init()
{
    for( var i = 0; i < NUM_PARTICLES; i++ )
    {
        m_pos[i] = DzVec3(
            rnd( -.2, .2 ),
            rnd(  0, .4 ),
            rnd( -.2, .2 )
        ); // Current positions
        var speed = rnd( 10, 20 );
        var v = DzVec3( rnd( -.1, .1 ), 1, rnd( -.1, .1 ) )
        v.setLength( speed );
        m_oldpos[i] = m_pos[i].subtract( v );
        pNodes[i] = Scene.findNode( "ball" + i );
        pNodes[i].setWSPos( m_pos[i] );
    }
}
//=============================================================================================
//
//=============================================================================================
// since the only force in this simulation is gravity
// and gravity is posed as being stable through time and space
// we call AccumulateForces(); only once
init();
AccumulateForces();
for( var fr = 0; fr <= 100; fr ++ )
{
    Scene.setFrame( fr );
    //AccumulateForces(); //uncomment if the forces vary
    Verlet();
    SatisfyConstraints();
    for( var i = 0; i < NUM_PARTICLES; i++ )
    {   
        pNodes[i].setWSPos( m_pos[i] );
    }
}