# CLOTHX 3.0.2

`A simple particle system physics engine ported to Haxe from Processing by Martin. Jeff designed this [traer physics] to be application / domain agnostic. All this is supposed to do is let you make particles, apply forces and calculate the positions of particles over time in real-time. `

(source) Traer Physics at Jeff's site
(ported) Clothx Physics at Martin's site

on my my site there's more in depth documentation for each class and some examples swifs inbetween the documentation

# Install

In order to use Clothx, you need to install the library using haxelib, like that :
`haxelib install clothx`

Then you can use the library by adding `-lib clothx` to haxe commandline parameters.

# Introduction

There are four parts,

ParticleSystem - takes care of gravity, drag, making particles, applying forces and advancing the simulation
Particles - they move around in 3D space based on forces you've applied to them
Springs - they act on two particles
Attractions - which also act on two particles

## Getting started

Cloth sim example:

```package ;

import flash.Lib;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.geom.Vector3D;
import clothx.physics.ParticleSystem;
import clothx.physics.Particle;

class ClothSim extends Sprite {

var s : ParticleSystem;

var gridSize : Int;
var particles : Array<Array<Particle>>;

var handle1 : Sprite;
var handle2 : Sprite;

var overlay : Sprite;

static function main()
{
new ClothSim();
}

public function new()
{
super();
particles = new Array();
s = new ParticleSystem(new Vector3D(0, 3.2, 0), .06);
s.setIntegrator(ParticleSystem.RUNGE_KUTTA);
var sx : Int;
sx = 150;
var sy : Int;
sy = 40;
var sp : Int;
sp = 25;

gridSize = 8;

//create a grid for particles
for(i in 0...gridSize)
{
particles[i] = new Array<Particle>();
for(j in 0...gridSize)
{
particles[i][j] = s.makeParticle(.8, new Vector3D(sx+j*sp, sy+i*sp, 0));
}
}

// create spring
for(i in 0...gridSize)
{
for(j in 0...gridSize-1)
{
s.makeSpring(particles[i][j], particles[i][j+1], 1, .6, sp);
}
}
for(i in 0...gridSize-1)
{
for(j in 0...gridSize)
{
s.makeSpring(particles[i][j], particles[i+1][j], 1, .6, sp);
}
}

// dragable handlers

handle1 = new Sprite();
handle1.graphics.beginFill(0xd9d9d9);
handle1.graphics.drawCircle(0,0,20);
handle1.graphics.endFill();
handle1.graphics.lineStyle(1,0x333333);
handle1.graphics.moveTo(0,-3);
handle1.graphics.lineTo(0,4);
handle1.graphics.moveTo(4,0);
handle1.graphics.lineTo(-3,0);

handle1.x = particles[0][0].position.x;
handle1.y = particles[0][0].position.y;

handle2 = new Sprite();
handle2.graphics.beginFill(0xd9d9d9);
handle2.graphics.drawCircle(0,0,20);
handle2.graphics.endFill();
handle2.graphics.lineStyle(1,0x333333);
handle2.graphics.moveTo(0,-3);
handle2.graphics.lineTo(0,4);
handle2.graphics.moveTo(4,0);
handle2.graphics.lineTo(-3,0);

handle2.x = particles[0][gridSize-1].position.x;
handle2.y = particles[0][gridSize-1].position.y;

particles[0][0].makeFixed();
particles[0][gridSize-1].makeFixed();

handle1.buttonMode = handle2.buttonMode = true;

overlay = new Sprite();
overlay.graphics.beginFill(0xFFFFFF);
overlay.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
overlay.graphics.endFill();
overlay.alpha = .75;
for(k in 0...10) s.tick(1);
onFrame(null);
}

function handleMouse(e:MouseEvent):Void
{
switch(e.type)
{
case MouseEvent.MOUSE_DOWN:
e.currentTarget.startDrag();

case MouseEvent.MOUSE_UP:
handle1.stopDrag();
handle2.stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_UP, handleMouse);
}
}

function onEnter(_)
{
overlay.visible = false;
}

function onLeave(_)
{
overlay.visible = true;
stage.removeEventListener(Event.ENTER_FRAME, onFrame);
}

function onFrame(_):Void
{
if(handle1.x > stage.stageWidth) handle1.x = stage.stageWidth;
else if(handle1.x < 0) handle1.x = 0;
if(handle1.y > stage.stageHeight) handle1.y = stage.stageHeight;
else if(handle1.y < 0) handle1.y = 0;
if(handle2.x > stage.stageWidth) handle2.x = stage.stageWidth;
else if(handle2.x < 0) handle2.x = 0;
if(handle2.y > stage.stageHeight) handle2.y = stage.stageHeight;
else if(handle2.y < 0) handle2.y = 0;

particles[0][0].position.x = handle1.x;
particles[0][0].position.y = handle1.y;

particles[0][gridSize-1].position.x = handle2.x;
particles[0][gridSize-1].position.y = handle2.y;

s.tick(1);

graphics.clear();
graphics.lineStyle(1,0x333333);

for(i in 0...gridSize)
{
for(j in 0...gridSize-1)
{
graphics.moveTo(particles[i][j].position.x, particles[i][j].position.y);
graphics.lineTo(particles[i][j+1].position.x, particles[i][j+1].position.y);
}
}
for(i in 0...gridSize-1)
{
for(j in 0...gridSize)
{
graphics.moveTo(particles[i][j].position.x, particles[i][j].position.y);
graphics.lineTo(particles[i+1][j].position.x, particles[i+1][j].position.y);
}
}
}

}```

## Final Note

More in depth documentation will be brought over from my (Martin's) site further on. Hope this get you going with it.

version #10772, modified 2011-07-27 11:52:06 by MartinLindelof