Google Tech Talk: Simple interactive 3D modeling for all – VideoTrace

3D models from basic video… This can be huge in all sorts of ways.  For exponential growth you need to go virtual.

  • This is a technology called VideoTrace from Australia
  • The Siggraph paper describing VideoTrace is available here (pdf 6MB)
  • Larger videos available here, with a more compressed version here.

A Peek into the AS3 and AVM2 Virtual Machine and ‘Elastic Racetrack’

Physaxe 2D Flash Physics Kit for haXe and List of Flash Flex Actionscript Physics Engines for AS3

Nicolas Cannasse, a virtual machine genius (maker of MTASC compiler, Neko and haXe (haXe compiles to target flash 6-9 but really only flash 9 is used anymore unless you are making banners)) released the Physaxe 2D Physics kit for haXe today.

It is heavily based on Glaze (demos) and Box2D which the Motor2, Glaze and Box2DFlashAS3 physics kits are all based on. Box2D is a great C++ 2D physics engine, it is simple which lended itself to being ported to AS3 quite easily. It is also a testament to AS3 that C++ kits are being ported into the language, not once, but many times. Also C ports like Chipmunk and other signs point to == AS3 is of fun.

Physaxe is quite amazing you must see the demos (very similar to Glade demos), it will get the inspirational wheels turning in your idea machines.

2D Physics in Flash and AS3 are extremely hot and can be used for many, many things from game development to promotions to simulations to user interface or visualizations and even modeling natural systems. It is nice to have a port of Box2D and similar to glade capabilities with Chipmunk like Glade has.

A game and physics engine for Flash including:

  • Rigid Body Dynamics
  • Scene management
  • Line of sight
  • User Input
  • Scrolling
  • AI

Core parts of the physics solver and collision system are based on the C physics engine Chipmunk

Notes about Physaxe:

Physaxe is a 2D Rigid Body Library written in haXe. It’s been highly optimized for the Flash 9 Player, with the best optimizations available.

Physaxe is based on several existing physics engines, mainly :

  • Box2D, the reference open source physics engine
  • Glaze, an AS3 engine which is a port of Chipmunk, itself based on Box2D

Physaxe features are :

  • rigid body consisting in several shapes
  • shapes supported are circles, segments (with rounded edges) and arbitrary convex polygons
  • customizable broadphase (currently bruteforce and y-sorted list are available)
  • island resolution and sleeping (allow ~0 CPU to be spent when groups are sleeping)
  • constraint solver based on Box2D sequential impulses
  • customizable body properties, such as linear/angular friction and maximized motion

Updated list of physics engines are like this:

AS3 3D Physics Engines (Open Source)

AS3 2D Physics Engines (Open Source)

haXe 2D Physics Engines

Get your game on! It is best to get them out early and often. I need to take my own advice.

TweenMax Bezier Tweening Released for AS2 and AS3 by Jack at GreenSock – And List of Animation Kits

TweenMax (Speed Test) has been released that adds a main feature missing from GreenSock’s offerings in tween animation libraries and kits over Tweener. That is the bezier curve tween. Tweener is very popular for use in PV3d and AS3 due to the bezier curve and Zeh’s great example that is really the base of a possible 3d editor. TweenMax now adds this and bezier tween capability for the GreenSock animation libraries.

Tweener and TweenLite have become the micro animation kits as well as micro kits you can make with Go base kits. TweenLite, TweenFilterLite and TweenMax divided up into different kits allows it to be embedded for banners or small assets easier if you don’t need the filters or other advanced tweens (this comes into play heavily with large games and asset collections when the compiled SWF each need the library). Tweener packs all features into one kit for simplicity. GreenSock kits are divided up for need. The comparison together is about the same but for basic tweens TweenLite is only 2k.

Performance is one area that the kits from GreenSock have really shined and since the addition of the speed tests and benchmarks it has become a great focus on showing how the open source kits are much better than bloated included animation calls in Flash and Flex defaults. I think all the kits have niches that they fit and Tweener and TweenLite are just very simple to use which adds alot to an animation kit success.

List of Animation Kits for AS3 (some for AS2 as well)

If you are using the Flex of Flash default animation classes, I am sorry…

AS3 Real-Time Raytracing

Forrest Briggs throwing down with a real-time raytracer in AS3. Also a C++ OpenGL version sample on the page.

Real-time pixel manipulation in flash is getting faster, but is still probably going to have to be faked in AS3, maybe AS4 will provide us per pixel speeds that Andre Michelle has been harping on since flash 8.5. Native operations can be much faster in that area. AIF might look to change some of that but that is Flash 10.

Here is the code for the as3 raytracer. Read more at laserpirate.

package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.utils.getTimer;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFormat;

public class RayTracer extends Sprite
{
private var t:Number;
private var dt:Number = .01;
private var frameTimeTxt:TextField;

public static const BUFFER_WIDTH:int = 160;
public static const BUFFER_HEIGHT:int = 120;
public static const BUFFER_SCALEDDOWN:int = 320 / BUFFER_WIDTH;

public static const HALF_BUFFER_WIDTH:int = BUFFER_WIDTH / 2;
public static const HALF_BUFFER_HEIGHT:int = BUFFER_HEIGHT / 2;

private var outputBitmapData:BitmapData;
private var outputBitmap:Bitmap;

public var FOV:Number = 20;

public var sphereCenterX:Array = [0, 0, 0, 0];
public var sphereCenterY:Array = [0, -.2, .4, 100.5];
public var sphereCenterZ:Array = [4, 4, 4, 10];
public var sphereRadius:Array = [.35, .35, .25, 100];
public var sphereR:Array = [255, 0, 0, 20];
public var sphereG:Array = [0, 150, 0, 20];
public var sphereB:Array = [0, 0, 255, 20];
public var sphereReflects:Array = [false, false, false, true];
public var sphereReflectiveness:Array = [0,0,0,.3];
public var sphere2dX:Array = new Array(sphereCenterX.length);
public var sphere2dY:Array = new Array(sphereCenterX.length);
public var sphere2dR:Array = new Array(sphereCenterX.length);

public var numSpheres = sphereCenterX.length;

var skyR:int = 20;
var skyG:int = 20;
var skyB:int = 20;
var skyColor:int = (skyR< <16) + (skyG<<8) + skyB; var ambientIllumination:Number = .1; var canvas:BlankClip; var theta:Number = 0; var mouseIsDown:Boolean = false; var mouseDownTheta:Number = 0; var mouseDownX:Number = 0; public function RayTracer() { outputBitmapData = new BitmapData(BUFFER_WIDTH, BUFFER_HEIGHT, false); outputBitmap = new Bitmap(outputBitmapData); addChild(outputBitmap); //outputBitmap.smoothing = true; outputBitmap.width= 320; outputBitmap.height = 240; canvas = new BlankClip; addChild(canvas); canvas.buttonMode = true; canvas.useHandCursor = true; frameTimeTxt = new TextField(); frameTimeTxt.defaultTextFormat = new TextFormat("Arial"); frameTimeTxt.x = 8; frameTimeTxt.y = 8; frameTimeTxt.width = 640; frameTimeTxt.textColor = 0xFFFFFF; frameTimeTxt.selectable = false; addChild(frameTimeTxt); t = 0; addEventListener(Event.ENTER_FRAME, update, false, 0, true); canvas.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); canvas.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler); } public function mouseDownHandler(e:*):void { mouseIsDown = true; mouseDownX = stage.mouseX; mouseDownTheta = theta; } public function mouseUpHandler(e:*):void { mouseIsDown = false; } public function update(e:*) { // start frame timer and update global time var timer:Number = getTimer(); t += dt; // handle mouse rotation if( mouseIsDown ) theta = mouseDownTheta - .0015 * (stage.mouseX - mouseDownX); theta += dt; // do some funky animation sphereCenterX[0] = .5*Math.sin(theta*5); sphereCenterZ[0] =1 + .5*Math.cos(theta*5); sphereCenterX[1] = .5*Math.sin(theta*5 + 2 * Math.PI / 3); sphereCenterZ[1] = 1 + .5*Math.cos(theta*5 + 2 * Math.PI / 3); sphereCenterX[2] = .5*Math.sin(theta*5 + 4 * Math.PI / 3); sphereCenterZ[2] = 1 + .5*Math.cos(theta*5 + 4 * Math.PI / 3); // reused variables var x:int; var y:int; var i:int; var j:int; var r:int; var g:int; var b:int; var dx:Number; var dy:Number; var rayDirX:Number; var rayDirY:Number; var rayDirZ:Number; var rayDirMag:Number; var reflectRayDirX:Number; var reflectRayDirY:Number; var reflectRayDirZ:Number; var intersectionX:Number; var intersectionY:Number; var intersectionZ:Number; var reflectIntersectionX:Number; var reflectIntersectionY:Number; var reflectIntersectionZ:Number; var rayToSphereCenterX:Number; var rayToSphereCenterY:Number; var rayToSphereCenterZ:Number; var lengthRTSC2:Number; var closestApproach:Number; var halfCord2:Number; var dist:Number; var normalX:Number; var normalY:Number; var normalZ:Number; var normalMag:Number; var illumination:Number; var reflectIllumination:Number; var reflectR:Number; var reflectG:Number; var reflectB:Number; // setup light dir var lightDirX:Number = .3; var lightDirY:Number = -1; var lightDirZ:Number = -.5; var lightDirMag:Number = 1/Math.sqrt(lightDirX*lightDirX +lightDirY*lightDirY +lightDirZ*lightDirZ); lightDirX *= lightDirMag; lightDirY *= lightDirMag; lightDirZ *= lightDirMag; // vars used to in intersection tests var closestIntersectionDist:Number; var closestSphereIndex:int; var reflectClosestSphereIndex:int; // compute screen space bounding circles //canvas.graphics.clear(); //canvas.graphics.lineStyle(1, 0xFF0000, .25); for(i = 0; i < numSpheres; ++i) { sphere2dX[i] = (BUFFER_WIDTH / 2 + FOV * sphereCenterX[i] / sphereCenterZ[i]); sphere2dY[i] = (BUFFER_HEIGHT /2 + FOV * sphereCenterY[i] / sphereCenterZ[i]); sphere2dR[i] = (3 * FOV * sphereRadius[i] / sphereCenterZ[i]); //canvas.graphics.drawCircle(sphere2dX[i]*BUFFER_SCALEDDOWN, sphere2dY[i]*BUFFER_SCALEDDOWN, sphere2dR[i]*BUFFER_SCALEDDOWN); sphere2dR[i] *= sphere2dR[i]; // store the squared value } // write to each pixel outputBitmapData.lock(); for(y = 0; y < BUFFER_HEIGHT; ++y) { for(x = 0; x < BUFFER_WIDTH; ++x) { // compute ray direction rayDirX = x - HALF_BUFFER_WIDTH; rayDirY = y - HALF_BUFFER_HEIGHT; rayDirZ = FOV; rayDirMag = 1/Math.sqrt(rayDirX * rayDirX + rayDirY * rayDirY +rayDirZ * rayDirZ); rayDirX *= rayDirMag; rayDirY *= rayDirMag; rayDirZ *= rayDirMag; /// trace the primary ray /// closestIntersectionDist = Number.POSITIVE_INFINITY; closestSphereIndex = -1 for(i = 0; i < numSpheres; ++i) { // check against screen space bounding circle dx = x - sphere2dX[i]; dy = y - sphere2dY[i]; if( dx * dx + dy * dy > sphere2dR[i] ) continue;

// begin actual ray tracing if its inside the bounding circle

lengthRTSC2 = sphereCenterX[i] * sphereCenterX[i] +
sphereCenterY[i] * sphereCenterY[i] +
sphereCenterZ[i] * sphereCenterZ[i];

closestApproach = sphereCenterX[i] * rayDirX +
sphereCenterY[i] * rayDirY +
sphereCenterZ[i] * rayDirZ;

if( closestApproach < 0 ) // intersection behind the origin continue; halfCord2 = sphereRadius[i] * sphereRadius[i] - lengthRTSC2 + (closestApproach * closestApproach); if( halfCord2 < 0 ) // ray misses the sphere continue; // ray hits the sphere dist = closestApproach - Math.sqrt(halfCord2); if( dist < closestIntersectionDist ) { closestIntersectionDist = dist; closestSphereIndex=i; } } /// end of trace primary ray /// // primary ray doesn't hit anything if( closestSphereIndex == - 1) { outputBitmapData.setPixel(x, y, skyColor); } else // primary ray hits a sphere.. calculate shading, shadow and reflection { // location of ray-sphere intersection intersectionX = rayDirX * closestIntersectionDist; intersectionY = rayDirY * closestIntersectionDist; intersectionZ = rayDirZ * closestIntersectionDist; // sphere normal at intersection point normalX = intersectionX - sphereCenterX[closestSphereIndex]; normalY = intersectionY - sphereCenterY[closestSphereIndex]; normalZ = intersectionZ - sphereCenterZ[closestSphereIndex]; normalX /= sphereRadius[closestSphereIndex]; // could be multiply by precacluated 1/rad normalY /= sphereRadius[closestSphereIndex]; normalZ /= sphereRadius[closestSphereIndex]; // diffuse illumination coef illumination = normalX * lightDirX + normalY * lightDirY + normalZ * lightDirZ; if( illumination < ambientIllumination ) illumination = ambientIllumination; /// trace a shadow ray /// var isInShadow:Boolean = false; for(j = 0; j < numSpheres; ++j) { if( j == closestSphereIndex ) continue; rayToSphereCenterX = sphereCenterX[j] - intersectionX; rayToSphereCenterY = sphereCenterY[j] - intersectionY; rayToSphereCenterZ = sphereCenterZ[j] - intersectionZ; lengthRTSC2 = rayToSphereCenterX * rayToSphereCenterX + rayToSphereCenterY * rayToSphereCenterY + rayToSphereCenterZ * rayToSphereCenterZ; closestApproach = rayToSphereCenterX * lightDirX + rayToSphereCenterY * lightDirY + rayToSphereCenterZ * lightDirZ; if( closestApproach < 0 ) // intersection behind the origin continue; halfCord2 = sphereRadius[j] * sphereRadius[j] - lengthRTSC2 + (closestApproach * closestApproach); if( halfCord2 < 0 ) // ray misses the sphere continue; isInShadow = true; break; } /// end of shadow ray /// if( isInShadow ) illumination *= .5; /// trace reflected ray /// if( sphereReflects[closestSphereIndex] ) { // calculate reflected ray direction var reflectCoef:Number = 2 * (rayDirX * normalX + rayDirY * normalY + rayDirZ * normalZ); reflectRayDirX = rayDirX - normalX * reflectCoef; reflectRayDirY = rayDirY - normalY * reflectCoef; reflectRayDirZ = rayDirZ - normalZ * reflectCoef; closestIntersectionDist = Number.POSITIVE_INFINITY; reflectClosestSphereIndex = -1 for(j = 0; j < numSpheres; ++j) { if( j == closestSphereIndex ) continue; rayToSphereCenterX = sphereCenterX[j] - intersectionX; rayToSphereCenterY = sphereCenterY[j] - intersectionY; rayToSphereCenterZ = sphereCenterZ[j] - intersectionZ; lengthRTSC2 = rayToSphereCenterX * rayToSphereCenterX + rayToSphereCenterY * rayToSphereCenterY + rayToSphereCenterZ * rayToSphereCenterZ; closestApproach = rayToSphereCenterX * reflectRayDirX + rayToSphereCenterY * reflectRayDirY + rayToSphereCenterZ * reflectRayDirZ; if( closestApproach < 0 ) // intersection behind the origin continue; halfCord2 = sphereRadius[j] * sphereRadius[j] - lengthRTSC2 + (closestApproach * closestApproach); if( halfCord2 < 0 ) // ray misses the sphere continue; // ray hits the sphere dist = closestApproach - Math.sqrt(halfCord2); if( dist < closestIntersectionDist ) { closestIntersectionDist = dist; reflectClosestSphereIndex=j; } } // end loop through spheres for reflect ray if( reflectClosestSphereIndex == - 1) // reflected ray misses { r = sphereR[closestSphereIndex] * illumination; g = sphereG[closestSphereIndex] * illumination; b = sphereB[closestSphereIndex] * illumination; } else { //trace("ref hit"); // location of ray-sphere intersection reflectIntersectionX = reflectRayDirX * closestIntersectionDist + intersectionX; reflectIntersectionY = reflectRayDirY * closestIntersectionDist + intersectionY; reflectIntersectionZ = reflectRayDirZ * closestIntersectionDist + intersectionZ; // sphere normal at intersection point normalX = reflectIntersectionX - sphereCenterX[reflectClosestSphereIndex]; normalY = reflectIntersectionY - sphereCenterY[reflectClosestSphereIndex]; normalZ = reflectIntersectionZ - sphereCenterZ[reflectClosestSphereIndex]; normalX /= sphereRadius[reflectClosestSphereIndex]; // could be multiply by precacluated 1/rad normalY /= sphereRadius[reflectClosestSphereIndex]; normalZ /= sphereRadius[reflectClosestSphereIndex]; // diffuse illumination coef reflectIllumination = normalX * lightDirX + normalY * lightDirY + normalZ * lightDirZ; if( reflectIllumination < ambientIllumination ) reflectIllumination = ambientIllumination; r = sphereR[closestSphereIndex] * illumination + .5 * sphereR[reflectClosestSphereIndex] * reflectIllumination; g = sphereG[closestSphereIndex] * illumination + .5 * sphereG[reflectClosestSphereIndex] * reflectIllumination; b = sphereB[closestSphereIndex] * illumination + .5 * sphereB[reflectClosestSphereIndex] * reflectIllumination; if( r > 255 ) r = 255;
if( g > 255 ) g = 255;
if( b > 255 ) b = 255;

} // end if reflected ray hits

} /// end if reflects
else // primary ray doesn’t reflect
{
r = sphereR[closestSphereIndex] * illumination;
g = sphereG[closestSphereIndex] * illumination;
b = sphereB[closestSphereIndex] * illumination;
}

outputBitmapData.setPixel(x, y, (r<<16) + (g<<8) + b); } // end if primary ray hit } // end x loop } // end y loop outputBitmapData.unlock(); // compute FPS var fps:Number = 1.0/((getTimer() - timer) / 1000.0); frameTimeTxt.text = "Drag to rotate. FPS: " + int(fps); } } }[/sourcecode]

AS3 Water Effects in Papervision 3D, Away3D and Sandy3D

I was messing with water effects and Perlin Noise (sandy3d) and some other stuff and collected some water effects and simulations that are fluid like for research, a snapshot of the state of fluid and water effects in 3d in flash.

Ralph Hauwert, of course one of the original pv3d team members, posted some great samples on water effects on 3d objects in Papervision 3D. Of course the papervision list spawned this discussion from another great post on water simulation in papervision and away3d by Exey Panteleev .

Also, some other water like effects from Fabrice Closier and the notorious mrdoob.

Ralph’s Water Effect Demos:

Hey look, the water ball is smiling at you.

Exey Panteleev’s Water Simulation:

Some other Water Like Fluid Effects:

Water is hard in flash. Fluid dynamics will probably have to be cheated but it is still looking pretty good. The amount of processor usage depends on how real you want it to look.

If you are looking to make some agua, with x, the y AND the z in Flash or Flex, these are a good place to start.

Degrafa for Flex Looking Pretty Sweet (AS3 and Commonizing Paths Graphics Pipeline for Silverlight and Flex)


Just recently through the holidays Degrafa has made some great strides as a very cool SVG pathing and designers toolkit for Flex. I have to say some recent Flex apps have really looked good like Picnik and Buzzword but this kit looks to clean up the lack of design and default style-itis that has plagued most common Flex Apps.

This so far looking like a pretty strong kit for bringing the designer pipeline into Flex to provide some really nice looking web styled apps. It has a direct crossover to Silverlight and Path objects that are largely just a series of data created in Expression or exported from Illustrator into XAML. The one benefit of Flex/Flash is it compiles to a very small SWF where with Silverlight you have to package the XAML in a zip and use the downloader object to extract it out. These XAML files and Paths can get massive as I am sure the ones for Degrafa will for Flex but the compile option is nice as it is compressed heavily.

All about Degrafa

Yes the launch includes shiny buttons…

Sphere Sample (right click for source)

Also, it appears it is a way to bridge the pathing and pipeline for flash or Silverlight. At one of the contributors blogs they mention this:

We have lot of interesting features planned for the coming releases. There is also a converter app that will be made available for converting the juicy Degrafa graphics to XAML.

Degrafa has gone live.

Developing…