CLOTH SIMULATION IN 9 STEPS

From so long back - while I am still a novice of AS2 programming - I tried to do the cloth simulation myself  from the moment I saw this demo. I even downloaded it and decompiled it(just like Beg, Borrow or Steal a Good Book!). But, what I found is a forest of alphabets (more than 10,000 lines of coding, which I am unable to follow) and lost hopes of creating cloth simulation. But recently I have seen a beautiful tutorial by ALEX NINO Verlet integration (actionscript 3), in 9 minutes, and Suddenly(!) my hopes were  resurrected. What he showed there is a wireframe view of a cloth simulation.I have immediately downloaded the sample from the link he provided, and studied the code.It is very simple. First he defined two objects with classes Verletpoint and and VerletStick, and then he just created a grid of verlet sticks that follows the animation as their P0 and p1which in turn are VerletPoints. He is just drawing the Lines with graphics lineTo command. Amazingly Simple...!

I am very much impressed by the simplicity and vulnerability of the code. Now I can insert an image into the Graphics using Flash AS3's drawTriangles function. And It will be a realistic Cloth Simulation! (But later while I am developping it I found it is not so simple.) What the advantage here is simplicity of coding. Vpoint and Vstick have approximately 30 lines of coding in each class, and main demo file has around 70 lines of code. Construction of the grid is with two for loops, one outer loop for row wise positioning and one inner loop for column wise positioning of VerletPoints and VerletSticks. And, animation also is achieved by processing all the points in a single for loop and processing all the sticks in another single for loop. Ofcourse, he wrapped the sticks loop in another for loop to achieve smothness. But, ultimately the code is very simple.

So, I took up the challenge of converting it into real cloth simulation step by step. I didn't planned to finish it in 9 steps. What I followed is a scientific way- first things first- to try version by version, and I found after finishing the end result that It took nine  steps to complete it. I had an Idea writing this Article:showing a step by step approach of solving a problem. For non-Technical readers It may be disgusting. But If you are interested to walk in the steps of a Programmer, who is going to create new thing from an existing thing, You will find some interesting stuff. As a first step I want to convert his main document class into an Object class, which can be instantiated and can be added to other Display Objects as a Child Object.I have decided not to alter any of the functional code in this version. I have achieved it like this.

package {
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
   
    /**
     * @website http://www.yoambulante.com/
     * @author Alex Nino
     */

    public class VerletCloth extends Sprite {
        private const COLS:uint = 30;
        private const ROWS:uint = 25;
        private var points:Vector.<vpoint>;
        private var sticks:Vector.<vstick>;
        private var w:Number;
       
        public function VerletCloth():void {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
       
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            points = new Vector.<vpoint>(COLS * ROWS, true);
            sticks = new Vector.<vstick>((COLS - 1) * ROWS + (ROWS - 1) * COLS);
            var i:uint = 0;
            for (var r:int = 0; r < ROWS; r++) {
                for (var c:int = 0; c < COLS; c++) {
                    points[r * COLS + c] = new VPoint(c * 10, r * 10);
                    if (c > 0) {
                        sticks[i++] = new VStick(points[r * COLS + c-1], points[r * COLS + c]);
                    }
                    if (r > 0) {
                        sticks[i++] = new VStick(points[r * COLS + c], points[(r-1) * COLS + c]);
                    }
                }
            }                        
            stage.addEventListener(MouseEvent.MOUSE_MOVE, HandleMouseMoveEvent); /*added after video*/            
            this.addEventListener(Event.ENTER_FRAME, onFrame);            
            w = COLS * 10 + 150;            
        }
       
        private function HandleMouseMoveEvent(e:MouseEvent):void {
            /*added after video*/
            if (e.buttonDown) {
                w = e.localX;
            }
        }
       
        private function onFrame(e:Event):void {                        
            var t:uint = points.length;
            var i:uint;
            points[0].setPos(0, 0);
            points[COLS - 1].setPos(w, 0);
            for (i = COLS; i < t; i++) { /*chenged after video i=0 for i=COLS*/
                points[i].y += .2; /*chenged after video from .1 to .2*/
                points[i].refresh();
            }
            t = sticks.length;
            for (var stiff:int = 0; stiff < 10; stiff++) { /*added after video*/
                for (i = 0; i < t; i++) {
                    sticks[i].contract();
                }
            }            
            //renders
            graphics.clear();
            graphics.lineStyle(1, 0xCC2200, 1);
            for (i = 0; i < t; i++) {
                graphics.moveTo(sticks[i].pointa.x, sticks[i].pointa.y);
                graphics.lineTo(sticks[i].pointb.x, sticks[i].pointb.y);
            }
        }
       
    }
   
}

And, I wrote a document class to create this  VerletCloth Object and to add it to stage. This class is very simple. just two comands. One is creating a new VerletCloth instance and next command is adding it to the Dispalylist. I am listing it below:

package{
    import flash.display.Sprite;
    public class MainTimeLine extends Sprite{
        private var my_cloth:VerletCloth;
        public function MainTimeLine(){
            trace("Document Class Constructor");
            InitApp();
        }
        private function InitApp(){
            my_cloth=new VerletCloth();
            this.addChild(my_cloth);
        }
    }
}

If you copy the code and create the two class files, and if you defined the MainTimeLine as Document class for a flash file,You will see this effect after making it an SWF(I just added a graphic rectangle of full stage size later, just to give a border to it):

Now, I got a real strength and inspiration that everything is going on in a right way, and, I took the second step- moved the entry point double for loop structure in the init function into a seperate function.defineVerletData, because I need to create Vertices, UVT data and indices for drawtriangles in the same sequence.This is second step.Then again I moved the MOUSE_MOVE and ENTER_FRAME into a seperate Public function startSwirl. this is a change with practical advantage, because I want to make it full interactive. The Cloth swirling is not a default starting animation. We need to initiate it from an external source. Now I am further modifying into next version. Here I modified the Document class: just added another line of code, {my_cloth.startSwirl();}. Except that functionality It is just same as the old class. So, I am not displaying the SWf or Code snippet. In the third version I have seperated the enterFrame code into two different functions:moveVerlets and renderGraphics. The split has two advantages over the earlier version. renderGraphics will come handy for both static display in init function and for  dynamic rendering of the graphics in enterFrame after processing all the calculations.