/**
* Copyright Thy ( http://wonderfl.net/user/Thy )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/lpwg
*/
// sorry for dirty code, and for the coments in portuguese
// learning 3D ^^
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
/**
* ...
* @author Thi
*/
public class Main extends Sprite
{
// var dos pontos
private var num:uint = 1000
private var pontos:Vector.<Ponto>
// perspectiva
private var perspectiva:Number = 3000
private var focal:Number // temp
// var da câmera
private var cam:Cam
private var w:Number = stage.stageWidth >> 1
private var h:Number = stage.stageHeight >> 1
// texto e seu desenho
private var texto:String = "Thi"
private var T:TextField
private var format:TextFormat
private var TDATA:BitmapData // onde será guardado o desenho do texto
private var tw:Number // a largura do desenho do texto
private var th:Number // a altura do desenho do texto
// screen
private var D:BitmapData, screen:Bitmap
private var col:ColorTransform, rect:Rectangle
// temp uint
private var i:uint
// temp ponto
private var p:Ponto
// temp posições
private var X:Number, Y:Number, Z:Number
private var X2:Number, Y2:Number, Z2:Number
public function Main():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
// arruma coisas do texto e seu desenho
initText()
// arruma a câmera
cam = new Cam()
cam.cx = w
cam.cy = h
// cria pontos
initPontos()
// init screen
D = new BitmapData(w<<1, h<<1, false, 0xFFFFFF)
screen = new Bitmap(D, "auto", true)
stage.addChild(screen)
//
col = new ColorTransform(.9, .9, .9)
rect = D.rect
// init bars
initBars()
// listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN, down)
stage.addEventListener(Event.ENTER_FRAME, ef)
}
private function initText():void
{
T = new TextField()
format = new TextFormat("Arial", 100)
T.defaultTextFormat = format
T.autoSize = TextFieldAutoSize.LEFT
T.text = texto
tw = T.width
th = T.height
stage.addChild(T)
TDATA = new BitmapData(tw, th, false, 0xFFFFFF)
TDATA.draw(T)
// lixo
stage.removeChild(T)
format = null
T = null
}
private function initPontos():void
{
pontos = new Vector.<Ponto>(num)
p = new Ponto()
//while ( TDATA.getPixel ((X = Math.random()*tw), (Y = Math.random()*th)) != 0)
//{}
p.x = 0
p.y = 0
p.z = 0
pontos[0] = p
i = 0
while (++i < num)
{
p = new Ponto()
while ( TDATA.getPixel ((X = Math.random()*tw), (Y = Math.random()*th)) != 0)
{}
p.x = X - (tw>>1)
p.y = Y - (th>>1)
p.z = Math.random() * 50 + 50
pontos[i] = p
pontos[i - 1].next = p
}
}
private function down(e:KeyboardEvent):void
{
if (e.keyCode == 37)
{
// esquerda
cam.lado-= 1
} else if (e.keyCode == 39)
{
// direta
cam.lado += 1
}
if (e.keyCode == 38)
{
// cima
cam.frente += 1
} else if (e.keyCode == 40)
{
// baixo
cam.frente -= 1
}
}
private var pitch:Sprite = new Sprite()
private var yaw:Sprite = new Sprite()
private var roll:Sprite = new Sprite()
private function initBars():void
{
w = w << 1
h = h << 1
with (pitch.graphics)
{
lineStyle(1, 0xFF0000)
beginFill(0xFFFFFF)
drawRect(0,0,90, 10)
}
stage.addChild(pitch)
with (yaw.graphics)
{
lineStyle(1, 0x00FF00)
beginFill(0xFFFFFF)
drawRect(0,0,10, 90)
}
stage.addChild(yaw)
with (roll.graphics)
{
lineStyle(1, 0x0000FF)
beginFill(0xFFFFFF)
drawRect(0,0,10, 90)
}
stage.addChild(roll)
pitch.x = 10
pitch.y = h- 10
yaw.x = w - 10
w = w >> 1
h = h >> 1
pitch.addEventListener(MouseEvent.MOUSE_DOWN, bd)
yaw.addEventListener(MouseEvent.MOUSE_DOWN, bd)
roll.addEventListener(MouseEvent.MOUSE_DOWN, bd)
stage.addEventListener(MouseEvent.MOUSE_UP, mu)
stage.addEventListener(MouseEvent.MOUSE_MOVE, bm)
}
private var mx:Number, my:Number
private var quem:Number = 0
private function bd(e:MouseEvent):void
{
if (e.target == pitch)
{
mx = mouseX
quem = 1
} else if (e.target == yaw)
{
mx = mouseY
quem = 2
} else if (e.target == roll)
{
mx = mouseY
quem = 3
}
}
private function mu(e:MouseEvent = null):void
{
quem = 0
}
private var d:Number = 0
private function bm(e:MouseEvent):void
{
if (quem == 1)
{
d = mouseX - mx
mx = mouseX
pitch.x += d
cam.pitch = Math.PI*2 * mouseX / (w<<1)
} else if (quem == 2)
{
d = mouseY - mx
mx = mouseY
yaw.y += d
cam.yaw = Math.PI * 2 * mouseY / (h << 1)
} else if (quem == 3)
{
d = mouseY - mx
mx = mouseY
roll.y += d
cam.roll = Math.PI * 2 * mouseY / (h << 1)
}
}
private function ef(e:Event = null):void
{
D.lock()
render()
filtro()
D.unlock()
}
// var pras velocidades x, y, z da câmera
private var vx:Number, vy:Number, vz:Number
private function andarCam():void
{
}
private function render():void
{
p = pontos[0]
// distãncia do ponto com a câmera
X = p.x - cam.x
Y = p.y - cam.y
Z = p.z - cam.z
// posição certa de um ponto 3D numa tela 2D
// eixo x
X2 = X
Y2 = Y
Z2 = Z
Y = Math.cos(cam.pitch) * Y2 - Math.sin (cam.pitch) * Z2
Z = Math.sin(cam.pitch) * Y2 + Math.cos (cam.pitch) * Z2
// eixo y
X2 = X
Y2 = Y
Z2 = Z
Z = Math.cos(cam.yaw) * Z2 - Math.sin (cam.yaw) * X2
X = Math.sin(cam.yaw) * Z2 + Math.cos (cam.yaw) * X2
// eixo z
X2 = X
Y2 = Y
Z2 = Z
X = Math.cos(cam.roll) * X2 - Math.sin (cam.roll) * Y2
Y = Math.sin(cam.roll) * X2 + Math.cos (cam.roll) * Y2
//
focal = perspectiva / (perspectiva + Z)
X *= focal
Y *= focal
//
D.setPixel(X + cam.cx, Y + cam.cy, 0xFF0000)
while ( (p = p.next) != null)
{
// distãncia do ponto com a câmera
X = p.x - cam.x
Y = p.y - cam.y
Z = p.z - cam.z
// posição certa de um ponto 3D numa tela 2D
// eixo x
X2 = X
Y2 = Y
Z2 = Z
Y = Math.cos(cam.pitch) * Y2 - Math.sin (cam.pitch) * Z2
Z = Math.sin(cam.pitch) * Y2 + Math.cos (cam.pitch) * Z2
// eixo y
X2 = X
Y2 = Y
Z2 = Z
Z = Math.cos(cam.yaw) * Z2 - Math.sin (cam.yaw) * X2
X = Math.sin(cam.yaw) * Z2 + Math.cos (cam.yaw) * X2
// eixo z
X2 = X
Y2 = Y
Z2 = Z
X = Math.cos(cam.roll) * X2 - Math.sin (cam.roll) * Y2
Y = Math.sin(cam.roll) * X2 + Math.cos (cam.roll) * Y2
//
focal = perspectiva / (perspectiva + Z)
X *= focal
Y *= focal
//
D.setPixel(X + cam.cx, Y + cam.cy, 0xFFFFFF)
}
}
private function filtro():void
{
D.colorTransform(rect, col)
}
}
}
//package
//{
/**
* ...
* @author Thi
*/
/*public*/ class Cam
{
// centro da câmera, no espeço
public var cx:Number, cy:Number
// posição da camera num espaço 3D
public var x:Number, y:Number, z:Number;
// velocidades (tem à ver com as setas)
public var frente:Number = 0, lado:Number = 0
// rotações da câmera
public var pitch:Number // valor do ângulo na vertical ('empinado') {eixo x}
public var yaw:Number // valor do ângulo da horizonal ('curva de carro') {eixo y}
public var roll:Number // valor do ângulo de rotação ('passar por fenda') {eixo z}
public function Cam(x:Number = 0, y:Number = 0, z:Number = 0, yaw:Number = 0, pitch:Number = 0, roll:Number = 0)
{
this.x = x;
this.y = y;
this.z = z;
this.yaw = yaw;
this.pitch = pitch;
this.roll = roll;
}
}
//}
//package
//{
/**
* ...
* @author Thi
*/
/*public*/ class Ponto
{
// posição do ponto num espaço 3D
public var x:Number, y:Number, z:Number
// próxima partícula, no loop
public var next:Ponto
public function Ponto(x:Number = 0, y:Number = 0, z:Number = 0)
{
this.x = x
this.y = y
this.z = z
}
}
//}