package
{
import __AS3__.vec.Vector;
import com.adobe.viewsource.ViewSource;
import flash.display.*;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Vector3D;
import fr.kikko.SystemTracker;
[SWF(backgroundColor="#010101", frameRate=30)]
public class LightSphere extends Sprite
{
private var PI:Number = 3.14159;
private var TWO_PI:Number;
private var H_PI:Number;
private var _container:Shape;
private var _vertices:Vector.<Number>;
private var _indices:Vector.<int>;
private var _vertices3d:Vector.<Number>;
private var _cols:int;
private var _rows:int;
private var _centerZ:Number = 200;
private var _focalLength:Number = 1000;
private var _radius:Number = 300;
private var _offset:Number = 0;
private var _zoffset:Number = 0;
private var _useZOffset:Boolean = false;
private var showMesh:Boolean;
private var _light:Light3D;
private var _ui:UI;
public function LightSphere()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
ViewSource.addMenuItem(this, "srcview/index.html");
SystemTracker.init( stage );
_ui = new UI();
_ui.y = 100;
addChild( _ui );
init();
}
private function init():void
{
_vertices = new Vector.<Number>();
_vertices3d = new Vector.<Number>();
_indices = new Vector.<int>();
_rows = _cols = 40;
_container = new Shape();
_container.x = stage.stageWidth >> 1;
_container.y = stage.stageHeight >> 1;
addChild( _container );
showMesh = true;
TWO_PI = PI * 2;
H_PI = PI * .5;
_light = new Light3D( 1000, 1000, 1000 );
makeTriangles();
render( null );
addEventListener( Event.ENTER_FRAME, render );
stage.addEventListener( MouseEvent.MOUSE_WHEEL, changeLightZ );
stage.addEventListener( MouseEvent.CLICK, toggleMesh );
stage.addEventListener( KeyboardEvent.KEY_DOWN, toggleZoffset );
}
private function changeLightZ( e:MouseEvent ):void
{
_light.z = ( e.delta > 0 ) ? _light.z - 20: _light.z + 20;
_ui.setLightZ( _light.z );
}
private function toggleMesh( e:MouseEvent ):void
{
showMesh = !showMesh;
_ui.setMesh( showMesh );
}
private function toggleZoffset( e:KeyboardEvent ):void
{
if ( e.charCode == 122 )
_useZOffset = true;
else if ( e.charCode == 97 )
_useZOffset = false;
}
private function render( e:Event ):void
{
_container.graphics.clear();
_offset += .01;
_zoffset = ( _useZOffset ) ? _zoffset + .01 : 0;
_vertices.length = 0;
_vertices3d.length = 0;
for ( var i:int = 0; i < _rows; ++i )
{
for ( var j:int = 0; j < _cols; ++j )
{
var angle:Number = TWO_PI / ( _cols - 1 ) * j + _offset;
var angle2:Number = PI * i / ( _rows - 1 ) - H_PI;
var cosAngle2:Number = _radius * Math.cos( angle2 );
var xpos:Number = Math.cos( angle ) * cosAngle2;
var ypos:Number = Math.sin( angle2 + _zoffset ) * _radius;
var zpos:Number = Math.sin( angle ) * cosAngle2;
var scale:Number = _focalLength / ( _focalLength + zpos + _centerZ );
_vertices.push( xpos * scale, ypos * scale );
_vertices3d.push( xpos, ypos, zpos );
}
}
for ( i = 0; i < _indices.length; i += 3 )
{
var index1:int = _indices[ i ] << 1;
var index2:int = _indices[ i + 1 ] << 1;
var index3:int = _indices[ i + 2 ] << 1;
var ax:Number = _vertices[ index1 ];
var ay:Number = _vertices[ index1 + 1 ];
var bx:Number = _vertices[ index2 ];
var by:Number = _vertices[ index2 + 1 ];
var cx:Number = _vertices[ index3 ];
var cy:Number = _vertices[ index3 + 1 ];
if ( (cx - ax) * (by - cy) < (cy - ay) * (bx - cx) )
{
index1 += index1 >> 1;
index2 += index2 >> 1;
index3 += index3 >> 1;
var vecA:Vector3D = new Vector3D( _vertices3d[ index1 ] - _vertices3d[ index2 ],
_vertices3d[ index1 + 1 ] - _vertices3d[ index2 + 1 ],
_vertices3d[ index1 + 2 ] - _vertices3d[ index2 + 2 ] );
var vecB:Vector3D = new Vector3D( _vertices3d[ index2 ] - _vertices3d[ index3 ],
_vertices3d[ index2 + 1 ] - _vertices3d[ index3 + 1 ],
_vertices3d[ index2 + 2 ] - _vertices3d[ index3 + 2 ] );
var norm:Vector3D = vecA.crossProduct( vecB );
_light.x = ( stage.stageWidth >> 1 ) - mouseX;
_light.y = ( stage.stageHeight >> 1 ) - mouseY;
var ca:Number = ( norm.x * _light.x +
norm.y * _light.y +
norm.z * _light.z ) / ( norm.length * _light.length );
var color:uint = 0x5522FF;
if ( ca <= 0 ) color = 0;
else
{
color = ( ( color >> 16 & 0xFF ) * ca ) << 16 |
( ( color >> 8 & 0xFF ) * ca ) << 8 |
( color & 0xFF ) * ca;
}
if ( showMesh )
_container.graphics.lineStyle( 1, color );
else
_container.graphics.beginFill( color );
_container.graphics.moveTo( ax, ay );
_container.graphics.lineTo( bx, by );
_container.graphics.lineTo( cx, cy );
_container.graphics.lineTo( ax, ay );
}
}
}
private function makeTriangles():void
{
for ( var i:int = 0; i < _rows; ++i )
{
for ( var j:int = 0; j < _cols; ++j )
{
if ( i < _rows - 1 && j < _cols - 1 )
{
_indices.push( i * _cols + j,
i * _cols + j + 1,
( i + 1 ) * _cols + j );
_indices.push( i * _cols + j + 1,
( i + 1 ) * _cols + j + 1,
( i + 1 ) * _cols + j );
}
}
}
}
}
}