Actionscript:
-
var squareNum:int = 100;
-
// verts defines a single square
-
var verts:Vector.<Number> = Vector.<Number>([-20, 0, 0, 20, 0, 0, 20, 0, 40, -20, 0, 40, -20, 0, 0]);
-
var cmds:Vector.<int> = Vector.<int>([1,2,2,2,2]);
-
var tempVerts:Vector.<Number> = new Vector.<Number>();
-
var newVerts:Vector.<Number> = new Vector.<Number>();
-
var pVerts:Vector.<Number> = new Vector.<Number>(10 * squareNum);
-
var uv:Vector.<Number> = new Vector.<Number>(15 * squareNum);
-
-
var m:Matrix3D = new Matrix3D();
-
-
// duplicate the verts array a bunch of times
-
// each time randomly rotating, scaling and translating it
-
for (var i:int = 0; i<squareNum; i++){
-
m.identity();
-
m.appendRotation(Math.random()*360,Vector3D.X_AXIS);
-
m.appendRotation(Math.random()*360,Vector3D.Y_AXIS);
-
m.appendRotation(Math.random()*360,Vector3D.Z_AXIS);
-
var s:Number = Math.random()*2 + .1;
-
m.appendScale(s, s, s);
-
m.appendTranslation(Math.random()*400 - 200, Math.random()*400 - 200, Math.random()*400 - 200);
-
m.transformVectors(verts,tempVerts);
-
newVerts = newVerts.concat(tempVerts);
-
cmds = cmds.concat(Vector.<int>([1,2,2,2,2]));
-
}
-
newVerts.fixed = pVerts.fixed = uv.fixed = true;
-
-
var dx:Number = 0, dy:Number = 0;
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
dx += (mouseX - dx) / 4;
-
dy += (mouseY - dy) / 4;
-
-
m.identity();
-
m.appendRotation(dx,Vector3D.Z_AXIS);
-
m.appendRotation(dy,Vector3D.X_AXIS);
-
m.appendTranslation(stage.stageWidth / 2,stage.stageHeight / 2, 0);
-
-
Utils3D.projectVectors(m, newVerts, pVerts, uv);
-
-
graphics.clear();
-
graphics.lineStyle(0,0x000000);
-
graphics.drawPath(cmds, pVerts);
-
}
This is a demo showing how to use transformVectors() and drawPath() together. It creates 100 wireframe squares in 3D:
Have a look at the swf...

Posted in 3D, Graphics, Vector |
Actionscript:
-
[SWF(width = 600, height = 700, frameRate=24)]
-
var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false, 0xFFFFFF);
-
addChild(new Bitmap(canvas));
-
-
var maxBranches:int = 600;
-
var branches:int = 0;
-
var startX:Number = 300
-
makeBranch(startX,690,30,-60, 60);
-
-
function makeBranch(xp:Number, yp:Number, step:Number, min:Number, max:Number):void {
-
var vectors:Shape = Shape(addChild(new Shape()));
-
var cX:Number, cY:Number, eX:Number, eY:Number
-
var dcX:Number=xp, dcY:Number=yp, deX:Number=xp, deY:Number=yp;
-
var theta:Number = (min + Math.random()*(max-min) - 90) * Math.PI / 180;
-
cX = xp + step * Math.cos(theta);
-
cY = yp + step * Math.sin(theta);
-
theta = (min + Math.random()*(max-min)-90) * Math.PI / 180;
-
eX = cX + step * Math.cos(theta);
-
eY = cY + step * Math.sin(theta);
-
var run:Function = function():void{
-
dcX += (cX - dcX) / 2;
-
dcY += (cY - dcY) / 2;
-
deX += (eX - deX) / 8;
-
deY += (eY - deY) / 8;
-
with(vectors.graphics){
-
clear();
-
beginFill(0xFFFFFF,0.8);
-
lineStyle(0,0x000000,0.8);
-
moveTo(startX, yp);
-
lineTo(xp, yp);
-
curveTo(dcX, dcY, deX, deY);
-
lineTo(startX, deY);
-
}
-
if (Math.abs(dcX - cX) <1 && Math.abs(deX - eX) <1 && Math.abs(dcY - cY) <1 && Math.abs(deY - eY) <1){
-
canvas.draw(vectors);
-
removeChild(vectors);
-
if (branches <maxBranches){
-
setTimeout(makeBranch, 10, deX, deY, step - Math.random(), -90, 90);
-
branches++;
-
if (int(Math.random()*2) == 1){
-
setTimeout(makeBranch, 10, deX, deY, step - Math.random()*3, -90, 90);
-
branches++;
-
}
-
}
-
}else{
-
setTimeout(arguments.callee, 1000 / 24);
-
}
-
}();
-
}
This snippet uses a technique similar to what you might use to create a recursive tree. A bit of additional logic is added for bezier branches, filled shapes and animation.
WARNING: may run slow on older machines
Have a look at the swf...

Actionscript:
-
[SWF(backgroundColor = 0xCCCCCC)]
-
var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,true, 0xFFFFFFFF);
-
addChild(new Bitmap(canvas));
-
-
var loader:Loader = new Loader();
-
loader.load(new URLRequest("http://actionsnippet.com/wp-content/chair.jpg"));
-
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
-
function onComplete(evt:Event):void{
-
canvas.draw(loader);
-
}
-
-
var brush:Shape = new Shape();
-
var diameter:Number = 120;
-
var radius:Number = diameter / 2;
-
var matrix:Matrix = new Matrix();
-
-
var brushAlpha:BitmapData = new BitmapData(diameter, diameter, true, 0x00000000);
-
drawRadial();
-
brushAlpha.draw(brush);
-
-
var xp:Number = 0, yp:Number = 0, px:Number = 0, py:Number = 0;
-
var dx:Number, dy:Number;
-
-
stage.addEventListener(MouseEvent.MOUSE_MOVE, onLoop);
-
function onLoop(evt:Event):void {
-
xp = mouseX - radius;
-
yp = mouseY - radius;
-
dx = xp - px;
-
dy = yp - py;
-
canvas.copyPixels(canvas,
-
new Rectangle(px, py, diameter, diameter),
-
new Point(xp, yp), brushAlpha, new Point(0,0), true);
-
px = xp;
-
py = yp
-
}
-
-
function drawRadial():void{
-
matrix.createGradientBox(diameter, diameter, 0, 0, 0);
-
with (brush.graphics){
-
beginGradientFill(GradientType.RADIAL, [0xFFFFFF, 0xFFFFFF], [1,0], [0, 255], matrix, SpreadMethod.PAD);
-
drawCircle(radius, radius, radius);
-
}
-
}
This is a quick snippet I wrote while thinking about how to create a smudge tool using BitmapData... it isn't perfect, but it's a good first step. It still needs some linear interpolation and I may need to do some pixel pushing to prevent a strange alpha anomaly that causes the brush to get darker than expected....
Here is the swf...

Actionscript:
-
[SWF(width = 600, height = 500, backgroundColor=0xFFFFFF)]
-
-
var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false, 0xFFFFFF);
-
addChild(new Bitmap(canvas));
-
-
var matrix:Matrix = new Matrix();
-
var grid:Sprite = new Sprite();
-
grid.filters = [new DropShadowFilter(4, 0, 0, 0.05, 20, 10)];
-
matrix.rotate(Math.PI / 4);
-
matrix.scale(1, 0.6);
-
matrix.translate(stage.stageWidth / 2, stage.stageHeight / 2 + 50);
-
grid.transform.matrix = matrix;
-
-
var rowCol:int = 9;
-
var spikeNum:Number = rowCol * rowCol;
-
var diameter:Number = 30;
-
var space:Number = diameter + 10;
-
var halfGridSize:Number = rowCol * space / 2;
-
var radius:Number;
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
radius = diameter / 2;
-
grid.y -= 0.9;
-
grid.graphics.clear();
-
for (var i:Number = 0; i<spikeNum; i++){
-
var xp:Number = i % rowCol;
-
var yp:Number = int(i / rowCol);
-
drawSpike(xp * space - halfGridSize, yp * space - halfGridSize, (xp + yp) / 4, 0, -yp);
-
}
-
canvas.draw(grid, grid.transform.matrix);
-
diameter -= 0.5;
-
if (diameter <3){
-
removeEventListener(Event.ENTER_FRAME, onLoop);
-
}
-
}
-
function drawSpike(xp:Number, yp:Number, rot:Number = 0, xOff:Number=0, yOff:Number = 0):void{
-
matrix.createGradientBox(diameter, diameter, rot, xp - radius + yOff, yp - radius + xOff);
-
with (grid.graphics){
-
beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0x999999], [1,1], [0, 255], matrix, SpreadMethod.PAD);
-
drawCircle(xp, yp, radius);
-
}
-
}
This snippet draws some isometric cones. Here are some images created by tweaking a few of the values:
