3D Landscape UPDATED
3D Minecraft-style terrain.
WASD + Mouse controls
Press space to jump
SHIFT to run
Click - shoots rockets
V - Flying
M - Remove/Add projectiles and stone.
You can just run around or fly and destroy all dirt. Press M to remove stone and create endless pits.
IMPORTANT:
@forks: I don't know if it's automatic, but the "wmode" needs to be set to "direct".
If Stage3D does not connect to your GPU, it appears slow and it plays at ~ 3 fps. This is beyond my control(and it pisses me off).
/**
* Copyright Coft ( http://wonderfl.net/user/Coft )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1pjl
*/
package {
import flash.display.Bitmap;
import flash.geom.ColorTransform;
import flash.geom.Matrix3D;
import com.adobe.utils.AGALMiniAssembler
import flash.display.Sprite;
import flash.display.Stage3D
import flash.display3D.*
import flash.display3D.textures.*
import flash.events.Event
import flash.display.BitmapData
import flash.geom.Vector3D
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
import flash.display.Shape;
import flash.filters.BlurFilter;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.filters.GlowFilter;
import flash.display.MovieClip;
public class MW extends Sprite {
private var stage3D:Stage3D
private var context:Context3D
private var _width:Number
private var _height:Number
public function MW() {
addEventListener("addedToStage", added)
}
private function added(e:Event):void {
var ref:* = this.parent
ref.frameRate = 60
stage3D = ref.stage3Ds[0]
stage3D.addEventListener("context3DCreate", init3d)
stage3D.requestContext3D()
_width = 640
_height = 360
Key.initialize(ref)
}
private var scene:Bitmap
private function init3d(e:Event):void {
scene = new Bitmap(new BitmapData(640,360,false))
context = stage3D.context3D
context.configureBackBuffer(640,360,4)
context.clear()
context.present()
start()
}
private function start():void {
start_grid()
start_gfx()
start_scene()
start_frame()
}
private var sandbox:Boolean = false
private var grid:Vector.<int>
private var green:Vector.<Boolean>
private var cobble:Vector.<int>
private var left:Vector.<int>
private var tile:Texture
private var programBg:Program3D
private var programSmoke:Program3D
private var camera:Vector3D
private var defMatrix:Matrix3D
private function start_grid():void {
var bmp:BitmapData = new BitmapData(64, 64, false)
bmp.perlinNoise(4,4,1,2,true,true,7,true)
var max:uint = 1 << 12
grid = new <int>[]
green = new <Boolean>[]
cobble = new <int>[]
for(var i:uint = 0; i < max; i++) {
grid[i] = (bmp.getPixel(i & 63, i >> 6) & 255) >> 5
green[i] = true
cobble[i] = ((bmp.getPixel(i & 63, i >> 6) & 255) >> 4) + 2
}
}
private function start_gfx():void {
tile = context.createTexture(64,64,"bgra",true)
var bmp:BitmapData = new BitmapData(64,64,true,0)
bmp.noise(5,0,255,7,true)
bmp.colorTransform(new Rectangle(0,0,32,32), new ColorTransform((1-0.1)*.7, (1-0.4)*0.7,(1-0)*0.7,1,255*0.1,255*0.4,255*0))
bmp.colorTransform(new Rectangle(32,0,32,32), new ColorTransform((1-0.4)*0.3, (1-0.2)*0.3,(1-0)*0.3,1,255*0.4,255*0.2,255*0))
bmp.colorTransform(new Rectangle(32,32,32,32), new ColorTransform((1-0.5)*0.2, (1-0.5)*0.2,(1-0.5)*0.2,1,255*0.5,255*0.5,255*0.5))
bmp.colorTransform(new Rectangle(0,32,32,32), new ColorTransform(0,0,0,0))
var smp:BitmapData = new BitmapData(32,32,true,0)
var mask:BitmapData = new BitmapData(32,32,true,0)
var sp:Shape = new Shape()
sp.graphics.beginFill(0,0.7)
sp.graphics.drawCircle(16,16,10)
sp.filters = [new BlurFilter(5,5,2)]
mask.draw(sp)
smp.perlinNoise(4,4,6,2,true,true,7,true)
var fin:BitmapData = new BitmapData(32,32,true,0)
fin.copyPixels(smp, smp.rect, new Point(), mask, new Point(), true)
bmp.draw(fin, new Matrix(1,0,0,1,0,32))
for(var i:uint = 0; i < 7; i++) {
tile.uploadFromBitmapData(bmp, i)
if(i < 6) {
var mipmap:BitmapData = new BitmapData(bmp.width/2, bmp.height/2, true, 0)
mipmap.draw(bmp, new Matrix(0.5,0,0,0.5),null,null,null,true)
bmp = mipmap
}
}
context.setTextureAt(0, tile)
context.setBlendFactors("sourceAlpha", "oneMinusSourceAlpha")
}
private function rebuildArea(i:uint):void {
var _x:uint = (i & 7) << 3
var _y:uint = (i >> 3) << 3
var _X:uint = _x + 8
var _Y:uint = _y + 8
var vecs:Vector.<Number> = new <Number>[]
var uvs:Vector.<Number> = new <Number>[]
var tris:Vector.<uint> = new <uint>[]
var v:uint = 0
var u:uint = 0
var t:uint = 0
var ind:uint = 0
left[i] = 0
for(var x:uint = _x; x < _X; x++) {
for(var y:uint = _y; y < _Y; y++) {
var index:uint = x | (y << 6)
var h:int = grid[index]
vecs[v++] = x
vecs[v++] = y
vecs[v++] = h
vecs[v++] = x+1
vecs[v++] = y
vecs[v++] = h
vecs[v++] = x+1
vecs[v++] = y+1
vecs[v++] = h
vecs[v++] = x
vecs[v++] = y + 1
vecs[v++] = h
var g:Number = green[index] || sandbox ? 0 : 0.5
var k:Number = 0
left[i] += (cobble[index] >= h) ? cobble[index] - h : 0
if(h >= cobble[index] && !sandbox) {
g = 0.5
k = 0.5
}
uvs[u++] = 0.01 + g
uvs[u++] = 0.01 + k
uvs[u++] = 0.49 + g
uvs[u++] = 0.01 + k
uvs[u++] = 0.49 + g
uvs[u++] = 0.49 + k
uvs[u++] = 0.01 + g
uvs[u++] = 0.49 + k
tris[t++] = ind
tris[t++] = ind+1
tris[t++] = ind+3
tris[t++] = ind+1
tris[t++] = ind+2
tris[t++] = ind+3
ind += 4
if(x < 63) {
var p1:int = grid[index]
var p2:int = grid[index+1]
var m:int = (p1 < p2) ? p1 : p2
var M:int = (p1 > p2) ? p1 : p2
var c1:int = cobble[index]
var c2:int = cobble[index+1]
var C:int = ((c1 < c2) ? c1 : c2)
for(var c:int = m; c < M; c++) {
vecs[v++] = x+1
vecs[v++] = y
vecs[v++] = c
vecs[v++] = x+1
vecs[v++] = y
vecs[v++] = c+1
vecs[v++] = x+1
vecs[v++] = y+1
vecs[v++] = c+1
vecs[v++] = x+1
vecs[v++] = y+1
vecs[v++] = c
if(c >= C && !sandbox) {
k = 0.5
} else {
k = 0
}
uvs[u++] = 0.51
uvs[u++] = 0.01 + k
uvs[u++] = 0.99
uvs[u++] = 0.01 + k
uvs[u++] = 0.99
uvs[u++] = 0.49 + k
uvs[u++] = 0.51
uvs[u++] = 0.49 + k
tris[t++] = ind
tris[t++] = ind+1
tris[t++] = ind+3
tris[t++] = ind+1
tris[t++] = ind+2
tris[t++] = ind+3
ind += 4
}
}
if(y < 63) {
p1 = grid[index]
p2 = grid[index+64]
m = (p1 < p2) ? p1 : p2
M = (p1 > p2) ? p1 : p2
c1 = cobble[index]
c2 = cobble[index+64]
C = ((c1 < c2) ? c1 : c2)
for(c = m; c < M; c++) {
vecs[v++] = x
vecs[v++] = y+1
vecs[v++] = c
vecs[v++] = x+1
vecs[v++] = y+1
vecs[v++] = c
vecs[v++] = x+1
vecs[v++] = y+1
vecs[v++] = c+1
vecs[v++] = x
vecs[v++] = y+1
vecs[v++] = c+1
if(c >= C && !sandbox) {
k = 0.5
} else {
k = 0
}
uvs[u++] = 0.51
uvs[u++] = 0.01 + k
uvs[u++] = 0.99
uvs[u++] = 0.01 + k
uvs[u++] = 0.99
uvs[u++] = 0.49 + k
uvs[u++] = 0.51
uvs[u++] = 0.49 + k
tris[t++] = ind
tris[t++] = ind+1
tris[t++] = ind+3
tris[t++] = ind+1
tris[t++] = ind+2
tris[t++] = ind+3
ind += 4
}
}
}
}
areas[i] = [vecs, uvs, tris]
}
private var areas:Vector.<Array>
private function start_scene():void {
areas = new <Array>[]
left = new <int>[]
for(var i:uint = 0; i < 64; i++) {
rebuildArea(i)
}
var agalVec:AGALMiniAssembler = new AGALMiniAssembler()
var codeVec:String = "m44 op, va0, vc0 \n" +
"mov v0, va0 \n" +
"mov v1, va1 \n" +
"m44 v2, va0, vc0"
var agalFrag:AGALMiniAssembler = new AGALMiniAssembler()
var codeFrag:String = "mov ft0, v0 \n" +
"tex ft4, v1, fs0<2d,nearest,mipnearest> \n" +
"div ft0, ft0.z, fc0.x \n" +
"sub ft2, v0, fc1 \n" +
"dp3 ft2.w, ft2, ft2 \n" +
"div ft2.w, fc1.w, ft2.w \n" +
"div ft2.z, ft2.w, ft2.w \n" +
"add ft2.w, ft2.w, ft2.z \n" +
"sub ft3, v0, fc3 \n" +
"dp3 ft3.w, ft3, ft3 \n" +
"div ft3.w, fc3.w, ft3.w \n" +
"add ft2.w, ft2.w, ft3.w \n" +
"sub ft3, v0, fc4 \n" +
"dp3 ft3.w, ft3, ft3 \n" +
"div ft3.w, fc4.w, ft3.w \n" +
"add ft2.w, ft2.w, ft3.w \n" +
"sub ft3, v0, fc5 \n" +
"dp3 ft3.w, ft3, ft3 \n" +
"div ft3.w, fc5.w, ft3.w \n" +
"add ft2.w, ft2.w, ft3.w \n" +
"sub ft3, v0, fc6 \n" +
"dp3 ft3.w, ft3, ft3 \n" +
"div ft3.w, fc6.w, ft3.w \n" +
"add ft2.w, ft2.w, ft3.w \n" +
"mul oc, ft4, ft2.w"
agalVec.assemble("vertex", codeVec)
agalFrag.assemble("fragment", codeFrag)
programBg = context.createProgram()
programBg.upload(agalVec.agalcode, agalFrag.agalcode)
agalVec = new AGALMiniAssembler()
codeVec = "m44 op, va0, vc0 \n" +
"mov v0, va1"
agalFrag = new AGALMiniAssembler()
codeFrag = "tex oc, v0, fs0<2d,nearest,mipnearest>"
agalVec.assemble("vertex", codeVec)
agalFrag.assemble("fragment", codeFrag)
programSmoke = context.createProgram()
programSmoke.upload(agalVec.agalcode, agalFrag.agalcode)
defMatrix = getMatrix()
}
private function start_frame():void {
camera = new Vector3D(32,32,3)
stage.addEventListener("enterFrame", render)
stage.scaleMode = "noScale"
stage.align = "topLeft"
stage.addEventListener("resize", resize)
resize(new Event("resize"))
stage.addEventListener("enterFrame", freeLook)
stage.addEventListener("enterFrame", lookAround)
stage.addEventListener("mouseDown", fire)
particles = new <Array>[]
projectiles = new <Array>[]
chain = []
score = txt(24,"Dirt left: 99999")
score.pos = new Point(1,0)
score.dispatchEvent(new Event("resize"))
stage.addChild(score)
lastdirt = 9000
gratz = txt(65, "Congratulations!")
gratz.sin = 0
gratz.addEventListener("enterFrame", glow)
gratz.alpha = 0
gratz.pos = new Point(0.5,0.5)
gratz.dispatchEvent(new Event("resize"))
stage.addChild(gratz)
stage.quality = "medium"
rescore()
}
private function glow(e:Event):void {
gratz.alpha *= 0.997
if(gratz.alpha < 0.05) {
gratz.visible = false
} else {
gratz.visible = true
gratz.sin += 0.9
gratz.filters = [new GlowFilter(0xFFFF00,0.4 + 0.4*Math.sin(gratz.sin),32,5,2,1)]
}
}
private var gratz:MovieClip
private var score:MovieClip
private function txt(size:uint, t:String):MovieClip {
var ans:TextField = new TextField()
var format:TextFormat = new TextFormat()
format.size = size
format.color = 0xFFFFFF
ans.defaultTextFormat = format
ans.width = 500
ans.height = 200
ans.text = t
ans.width = ans.textWidth + 8
ans.height = ans.textHeight + 8
ans.selectable = false
var mc:MovieClip = new MovieClip()
mc.graphics.beginFill(0, 1/255)
mc.graphics.drawRect(0,0,ans.textWidth, ans.textHeight)
mc.graphics.endFill()
mc.addChild(ans)
mc.pos = new Point()
mc.addEventListener("resize", repos)
mc.mouseEnabled = false
return mc
}
private function repos(e:Event):void {
var field:* = e.currentTarget
field.x = field.pos.x * stage.stageWidth - field.width * field.pos.x
field.y = field.pos.y * stage.stageHeight - field.height * field.pos.y
}
private var lastdirt:uint
private var dirtleft:uint
private function rescore():void {
var field:* = score
field = field.getChildAt(0)
dirtleft = 0
for(var i:uint = 0; i < 64; i++) {
dirtleft += left[i]
}
field.text = "Dirt left: " + dirtleft
if(lastdirt > 0 && dirtleft == 0) {
gratz.alpha = 1
}
lastdirt = dirtleft
}
private var yaw:Number = 0
private var pitch:Number = 80
private var vec:Vector3D = new Vector3D(0,0,0)
private function freeLook(e:Event):void {
yaw += (stage.mouseX - stage.stageWidth/2)/100
pitch += (stage.mouseY - stage.stageHeight/2)/100
pitch = (pitch > 89) ? 89 : pitch
pitch = (pitch < -89) ? -89 : pitch
}
private function lookAround(e:Event):void {
var p:Point = new Point()
p.x += int(Key.isDown(68))
p.x -= int(Key.isDown(65))
p.y -= int(Key.isDown(87))
p.y += int(Key.isDown(83))
var F:Vector3D = new Vector3D(0,0,1)
var R:Vector3D = new Vector3D(1,0,0)
var m:Matrix3D = new Matrix3D()
m.appendRotation(-90, new Vector3D(1,0,0))
m.appendRotation(yaw, new Vector3D(0,0,1))
F = m.transformVector(F)
R = m.transformVector(R)
var fin:Vector3D = new Vector3D(R.x*p.x + F.x*p.y, R.y*p.x + F.y*p.y, R.z*p.x + F.z*p.y)
var save:Number = vec.z
fin.normalize()
var speed:Number = 3
if(camera.z > 5) {
speed *= Math.sqrt(camera.z - 4)
}
if(Key.isDown(16)) {
speed *= 3
}
var acc:Number = 0.003
fin.scaleBy(speed/60)
var dif:Vector3D = fin.subtract(vec)
if(dif.length > acc) {
dif.normalize()
dif.scaleBy(acc)
vec = vec.add(dif)
} else {
vec = fin
}
vec.z = save
var terminal:Number = 33/60
if(vec.z < -terminal) {
vec.z = 0.9 * vec.z - 0.1 * terminal
}
if(vec.z > terminal*0.5) {
vec.z = 0.9 * vec.z + 0.1 * terminal*0.5
}
camera = camera.add(vec)
var atX:int = camera.x
var atY:int = camera.y
var max:uint = 64
if(atX >= 0 && atY >= 0 && atX < max && atY < max) {
var h:Number = -grid[atX | (atY << 6)]
if(camera.z < h+0.6) {
camera.z = h+0.6
vec.z = 0
if(Key.isDown(32)) {
vec.z = 0.15
}
}
}
if(Key.isDown(86)) {
if(vec.z < 0) {
vec.z *= 0.95
}
vec.z += 0.008
}
vec.z -= 0.006
var a:uint = 0
var f:uint = projectiles.length
for(var i:int = 0; i < f - a; i++) {
var proj:Array = projectiles[i+a]
proj[0] = proj[0].add(proj[1])
var hit:Boolean = false
if(proj[0].x < 0 || proj[0].y < 0 || proj[0].x >= 64 || proj[0].y >= 64) {
hit = true
} else {
if(-grid[(proj[0].x << 0) | (proj[0].y << 6)] > proj[0].z) {
hit = true
chain.push([proj[0].clone(),0,0])
lights.push([proj[0].clone(),16])
}
}
if(hit) {
i--
a++
} else {
projectiles[i] = projectiles[i+a]
}
if(Math.random() < 100/(100 + particles.length)) {
particles.push([proj[0].clone(), new Vector3D(Math.random()*0.02-0.01, Math.random()*0.02-0.01, 0.1), 55])
}
}
if(a > 0) {
projectiles.splice(-a, a)
}
a = 0
f = particles.length
for(i = 0; i < f - a; i++) {
proj = particles[i+a]
hit = false
if(proj[2]-- < 0) {
hit = true
} else {
proj[1].z -= 0.002
proj[0] = proj[0].add(proj[1])
if(proj[0].x < 0 || proj[0].y < 0 || proj[0].x >= 64 || proj[0].y >= 64) {
hit = true
} else {
if(-grid[(proj[0].x >> 0) | (proj[0].y << 6)] > proj[0].z) {
hit = true
}
}
}
if(hit) {
i--
a++
} else {
particles[i] = particles[i+a]
}
}
if(a > 0) {
particles.splice(-a, a)
}
a = 0
f = chain.length
for(i = 0; i < f - a; i++) {
proj = chain[i+a]
if(proj[2]-- < 0) {
proj[1] += 0.9
explode(proj[0], proj[1])
if(proj[1] >= 3) {
i--
a++
} else {
chain[i] = chain[i+a]
}
proj[2] = 2
} else {
chain[i] = chain[i+a]
}
}
if(a > 0) {
chain.splice(-a, a)
}
var M:Boolean = Key.isDown(77)
if(M && !lastM) {
sandbox = !sandbox
for(i = 0; i < 64; i++) {
rebuildArea(i)
}
}
lastM = M
}
private var lastM:Boolean
private var particles:Vector.<Array>
private var projectiles:Vector.<Array>
private function fire(e:MouseEvent):void {
if(sandbox) {
var l:Vector.<Number> = light()
explode(new Vector3D(l[0], l[1], l[2]), 7)
} else {
var F:Vector3D = new Vector3D(0,0,-1)
var m:Matrix3D = new Matrix3D()
m.appendRotation(-90+pitch, new Vector3D(1,0,0))
m.appendRotation(yaw, new Vector3D(0,0,1))
F = m.transformVector(F)
F.normalize()
F.scaleBy(42/30)
projectiles.push([camera.clone(), F])
}
}
private function resize(e:Event):void {
_width = stage.stageWidth
_height = stage.stageHeight
defMatrix = getMatrix()
context.configureBackBuffer(_width, _height, 4)
scene.bitmapData = new BitmapData(_width,_height,false)
}
private function light():Vector.<Number> {
var p:Vector3D = camera.clone()
var inc:Vector3D = new Vector3D(0,0,-1)
var m:Matrix3D = new Matrix3D()
m.appendRotation(-90+pitch, new Vector3D(1,0,0))
m.appendRotation(yaw, new Vector3D(0,0,1))
inc = m.transformVector(inc)
inc.normalize()
inc.scaleBy(0.01)
var n:uint = 0
for(var goon:Boolean = true;goon;) {
p = p.add(inc)
var cX:int = p.x >> 0
var cY:int = p.y >> 0
var i:int = cX | (cY << 6)
if(i >= 0 && i < (1 << 12)) {
var h:Number = grid[i]
goon = -grid[(p.x << 0) | (p.y << 6)] < p.z
} else {
goon = false
}
if(n++ & 2048) {
goon = false
}
}
return new <Number>[p.x, p.y, -p.z, 0.01]
}
private var chain:Array
private function explode(pos:Vector3D, strength:Number):void {
var _x:int = pos.x - 8
var _y:int = pos.y - 8
_x = (_x < 0) ? 0 : _x
_y = (_y < 0) ? 0 : _y
var _X:int = pos.x + 8
var _Y:int = pos.y + 8
_X = (_X > 64) ? 64 : _X
_Y = (_Y > 64) ? 64 : _Y
var list:Vector.<int> = new Vector.<int>(64,true)
for(var x:uint = _x; x < _X; x++) {
for(var y:uint = _y; y < _Y; y++) {
if(sandbox) {
var h:Number = 5 - Math.sqrt((x-pos.x)*(x-pos.x) + (y - pos.y)*(y - pos.y))
} else {
h = Math.sqrt(strength - Math.sqrt((x-pos.x)*(x-pos.x) + (y - pos.y)*(y - pos.y)))
}
h = (h < 0) ? 0 : h
if(h >> 0) {
var i:uint = x | (y << 6)
var last:uint = grid[i]
grid[i] += h >> 0
green[i] = false
if(grid[i] > cobble[i] && !sandbox) {
grid[i] = (cobble[i] > last) ? cobble[i] : last
}
}
list[(x >> 3) | ((y >> 3) << 3)] = 1
}
}
for(i = 0; i < 64; i++) {
if(list[i]) {
rebuildArea(i)
}
}
if(!sandbox) {
var f:Number = 8*strength/(particles.length/50 + 1)
for(i = 0; i < 8*strength; i++) {
var off:Vector3D = new Vector3D(Math.random()-0.5, Math.random()-0.5, Math.random()-0.5)
off.normalize()
off.scaleBy(Math.random())
var at:Vector3D = pos.add(off)
var vec:Vector3D = at.subtract(pos)
vec.normalize()
vec.scaleBy(6/60 * (1+2*Math.random()))
particles.push([at, vec, 100])
}
quake += 0.15
}
rescore()
}
private var quake:Number = 0
private var lights:Vector.<Array> = new <Array>[]
private function render(e:Event):void {
context.clear()
var m:Matrix3D = new Matrix3D()
quake *= 0.9
quake = (quake < 0.01) ? 0 : quake
m.appendTranslation(-camera.x + quake*(Math.random()-0.5), -camera.y + quake*(Math.random()-0.5), camera.z + quake*(Math.random()-0.5))
m.appendRotation(-yaw, new Vector3D(0,0,1))
m.appendRotation(-90+pitch, new Vector3D(1,0,0))
var m2:Matrix3D = m.clone()
m2.append(defMatrix)
context.setProgramConstantsFromMatrix("vertex", 0, m2, true)
context.setProgramConstantsFromVector("fragment", 0, new <Number>[32*4,0,0,0])
context.setProgramConstantsFromVector("fragment", 1, light())
context.setProgramConstantsFromVector("fragment", 2, new <Number>[10000, 0, 0, 0])
var f:uint = lights.length
var a:uint = 0
var lightsSet:Vector.<int> = new Vector.<int>(8)
for(var i:int = 0; i < f - a; i++) {
var l:Array = lights[i+a]
l[1] *= 0.85
if(l[1] < 0.5) {
i--
a++
} else {
if(i < 4) {
context.setProgramConstantsFromVector("fragment", 3 + i, new <Number>[l[0].x, l[0].y, -l[0].z, l[1]])
lightsSet[i] = 1
}
lights[i] = lights[i+a]
}
}
for(i = 0; i < 4; i++) {
if(!lightsSet[i]) {
context.setProgramConstantsFromVector("fragment", 3 + i, new <Number>[0,0,0,0])
}
}
if(a > 0) {
lights.splice(-a, a)
}
context.setProgram(programBg)
context.setDepthTest(true, "less")
for(i = 0; i < 64; i++) {
var vBuf:VertexBuffer3D = context.createVertexBuffer(areas[i][0].length/3, 3)
var uBuf:VertexBuffer3D = context.createVertexBuffer(areas[i][1].length/2, 2)
var tBuf:IndexBuffer3D = context.createIndexBuffer(areas[i][2].length)
vBuf.uploadFromVector(areas[i][0], 0, areas[i][0].length/3)
uBuf.uploadFromVector(areas[i][1], 0, areas[i][1].length/2)
tBuf.uploadFromVector(areas[i][2], 0, areas[i][2].length)
context.setVertexBufferAt(0, vBuf, 0, "float3")
context.setVertexBufferAt(1, uBuf, 0, "float2")
context.drawTriangles(tBuf, 0, areas[i][2].length/3)
}
f = particles.length
if(f > 0) {
var vec:Vector.<Number> = new <Number>[]
var uvs:Vector.<Number> = new <Number>[]
var tris:Vector.<uint> = new <uint>[]
var order:Vector.<Number> = new <Number>[]
var v:uint = 0
for(i = 0; i < f; i++) {
var v3d:Vector3D = particles[i][0]
order[v++] = v3d.x
order[v++] = v3d.y
order[v++] = -v3d.z
}
var size:Number = 0.2
m.transformVectors(order, order)
v = 0
var u:uint = 0
var t:uint = 0
var ind:uint = 0
for(i = 0; i < f; i++) {
var min:Number = -Infinity
var of:int = -1
for(var j:uint = 0; j < f; j++) {
if(order[3*j+2] > min) {
min = order[3*j+2]
of = j
}
}
if(of < 0) {
i = f
} else {
vec[v++] = order[3*of] - size
vec[v++] = order[3*of+1] - size
vec[v++] = order[3*of+2]
vec[v++] = order[3*of] + size
vec[v++] = order[3*of+1] - size
vec[v++] = order[3*of+2]
vec[v++] = order[3*of] + size
vec[v++] = order[3*of+1] + size
vec[v++] = order[3*of+2]
vec[v++] = order[3*of] - size
vec[v++] = order[3*of+1] + size
vec[v++] = order[3*of+2]
uvs[u++] = 0.01
uvs[u++] = 0.51
uvs[u++] = 0.49
uvs[u++] = 0.51
uvs[u++] = 0.49
uvs[u++] = 0.99
uvs[u++] = 0.01
uvs[u++] = 0.99
tris[t++] = ind
tris[t++] = ind+1
tris[t++] = ind+3
tris[t++] = ind+1
tris[t++] = ind+2
tris[t++] = ind+3
ind += 4
order[3*of+2] = -Infinity
}
}
context.setProgram(programSmoke)
context.setProgramConstantsFromMatrix("vertex", 0, defMatrix, true)
vBuf = context.createVertexBuffer(vec.length/3, 3)
uBuf = context.createVertexBuffer(uvs.length/2, 2)
tBuf = context.createIndexBuffer(tris.length)
vBuf.uploadFromVector(vec, 0, vec.length/3)
uBuf.uploadFromVector(uvs, 0, uvs.length/2)
tBuf.uploadFromVector(tris, 0, tris.length)
context.setVertexBufferAt(0, vBuf, 0, "float3")
context.setVertexBufferAt(1, uBuf, 0, "float2")
context.drawTriangles(tBuf, 0, tris.length/3)
}
if(drawOnScreen) {
context.drawToBitmapData(scene.bitmapData)
}
context.present()
var O:Boolean = Key.isDown(79)
if(O && !lastO) {
drawOnScreen = !drawOnScreen
if(drawOnScreen) {
stage3D.visible = false
addChild(scene)
} else {
stage3D.visible = true
removeChild(scene)
}
}
lastO = O
}
private var lastO:Boolean
private var drawOnScreen:Boolean = false
private function getMatrix():Matrix3D {
var _far:Number = 500
var _near:Number = 0.01
var angle:Number = 90
return new Matrix3D(new <Number>[
16 * Math.max(_height, _width*9/16) / (9 * Math.tan(angle*Math.PI/360) * _width), 0, 0, 0,
0, - 16 * Math.max(_height, _width*9/16) / (Math.tan(angle*Math.PI/360) * 9 * _height), 0, 0,
0, 0, _far/(_far - _near), 1,
0, 0, _far*_near/(_near-_far), 0])
}
}
}
import flash.display.Stage
import flash.events.KeyboardEvent
import flash.events.Event
class Key {
private static var keysDown:Object = new Object();
public static function initialize(stage:Stage):void {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.DEACTIVATE, clearKeys);
}
public static function isDown(keyCode:uint):Boolean {
return Boolean(keyCode in keysDown);
}
private static function keyPressed(event:KeyboardEvent):void {
keysDown[event.keyCode] = true;
}
private static function keyReleased(event:KeyboardEvent):void {
if (event.keyCode in keysDown) {
delete keysDown[event.keyCode];
}
}
private static function clearKeys(event:Event):void {
keysDown = new Object();
}
}