forked from: Simple 3D
forked from 3D Landscape UPDATED (diff: 1)
ActionScript3 source code
/**
* Copyright Thumasz ( http://wonderfl.net/user/Thumasz )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/rtHu
*/
// forked from Coft's Simple 3D
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;
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 {
stage3D.visible = false
scene = new Bitmap(new BitmapData(640,360,false))
addChild(scene)
context = stage3D.context3D
context.configureBackBuffer(640,360,4)
context.clear()
context.present()
start()
}
private var waitdraw:int
private function start():void {
side = 6
start_grid()
start_gfx()
start_scene()
start_frame()
waitdraw = 333
}
private var side:uint
private var grid:Vector.<int>
private var tile:Texture
private var bgVec:Vector.<Number>
private var bgUvs:Vector.<Number>
private var bgTri:Vector.<uint>
private var programBg: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 << (2*side)
grid = new <int>[]
for(var i:uint = 0; i < max; i++) {
grid[i] = (bmp.getPixel(i & 63, i >> 6) & 255) >> 5
}
}
private function start_gfx():void {
tile = context.createTexture(64,64,"bgra", false)
var bmp:BitmapData = new BitmapData(64,64,false)
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))
tile.uploadFromBitmapData(bmp)
context.setTextureAt(0, tile)
}
private function start_scene():void {
var v:uint = 0
bgVec = new <Number>[]
var u:uint = 0
bgUvs = new <Number>[]
var t:uint = 0
bgTri = new <uint>[]
var ind:uint = 0
for(var a:uint = 0; !(a >> side); a++) {
for(var b:uint = 0; !(b >> side); b++) {
var h:int = grid[a | (b << side)]
bgVec[v++] = a
bgVec[v++] = b
bgVec[v++] = h
bgVec[v++] = a+1
bgVec[v++] = b
bgVec[v++] = h
bgVec[v++] = a+1
bgVec[v++] = b+1
bgVec[v++] = h
bgVec[v++] = a
bgVec[v++] = b + 1
bgVec[v++] = h
bgUvs[u++] = 0.01
bgUvs[u++] = 0.01
bgUvs[u++] = 0.49
bgUvs[u++] = 0.01
bgUvs[u++] = 0.49
bgUvs[u++] = 0.49
bgUvs[u++] = 0.01
bgUvs[u++] = 0.49
bgTri[t++] = ind
bgTri[t++] = ind+1
bgTri[t++] = ind+3
bgTri[t++] = ind+1
bgTri[t++] = ind+2
bgTri[t++] = ind+3
ind += 4
}
}
for(a = 0; !(a + 1 >> side); a++) {
for(b = 0; !(b >> side); b++) {
var p1:int = grid[a | (b << side)]
var p2:int = grid[1+a | (b << side)]
var m:int = (p1 < p2) ? p1 : p2
var M:int = (p1 > p2) ? p1 : p2
for(var c:int = m; c < M; c++) {
bgVec[v++] = a+1
bgVec[v++] = b
bgVec[v++] = c
bgVec[v++] = a+1
bgVec[v++] = b
bgVec[v++] = c+1
bgVec[v++] = a+1
bgVec[v++] = b+1
bgVec[v++] = c+1
bgVec[v++] = a+1
bgVec[v++] = b+1
bgVec[v++] = c
bgUvs[u++] = 0.51
bgUvs[u++] = 0.01
bgUvs[u++] = 0.99
bgUvs[u++] = 0.01
bgUvs[u++] = 0.99
bgUvs[u++] = 0.49
bgUvs[u++] = 0.51
bgUvs[u++] = 0.49
bgTri[t++] = ind
bgTri[t++] = ind+1
bgTri[t++] = ind+3
bgTri[t++] = ind+1
bgTri[t++] = ind+2
bgTri[t++] = ind+3
ind += 4
}
}
}
for(a = 0; !(a >> side); a++) {
for(b = 0; !(b + 1 >> side); b++) {
p1 = grid[a | (b << side)]
p2 = grid[a | (b + 1 << side)]
m = (p1 < p2) ? p1 : p2
M = (p1 > p2) ? p1 : p2
for(c = m; c < M; c++) {
bgVec[v++] = a
bgVec[v++] = b+1
bgVec[v++] = c
bgVec[v++] = a+1
bgVec[v++] = b+1
bgVec[v++] = c
bgVec[v++] = a+1
bgVec[v++] = b+1
bgVec[v++] = c+1
bgVec[v++] = a
bgVec[v++] = b+1
bgVec[v++] = c+1
bgUvs[u++] = 0.51
bgUvs[u++] = 0.01
bgUvs[u++] = 0.99
bgUvs[u++] = 0.01
bgUvs[u++] = 0.99
bgUvs[u++] = 0.49
bgUvs[u++] = 0.51
bgUvs[u++] = 0.49
bgTri[t++] = ind
bgTri[t++] = ind+1
bgTri[t++] = ind+3
bgTri[t++] = ind+1
bgTri[t++] = ind+2
bgTri[t++] = ind+3
ind += 4
}
}
}
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,mipnone> \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" +
"mul oc, ft4, ft2.w"
agalVec.assemble("vertex", codeVec)
agalFrag.assemble("fragment", codeFrag)
programBg = context.createProgram()
programBg.upload(agalVec.agalcode, agalFrag.agalcode)
defMatrix = getMatrix()
}
private function start_frame():void {
camera = new Vector3D((1 << side)/2,(1 << side)/2,15)
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)
}
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(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
camera = camera.add(vec)
var atX:int = camera.x
var atY:int = camera.y
var max:uint = 1 << side
if(atX >= 0 && atY >= 0 && atX < max && atY < max) {
var h:Number = -grid[atX | (atY << side)]
if(camera.z < h+0.6) {
camera.z = h+0.6
vec.z = 0
if(Key.isDown(32)) {
vec.z = 0.15
}
}
}
vec.z -= 0.006
}
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)
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 << side)
if(i >= 0 && i < (1 << 2*side)) {
var h:Number = grid[i]
goon = -grid[(p.x << 0) | (p.y << side)] < p.z
} else {
goon = false
}
}
return new <Number>[p.x, p.y, -p.z, 1]
}
private function render(e:Event):void {
context.clear()
var m:Matrix3D = new Matrix3D()
m.appendTranslation(-camera.x, -camera.y, camera.z)
m.appendRotation(-yaw, new Vector3D(0,0,1))
m.appendRotation(-90+pitch, new Vector3D(1,0,0))
m.append(defMatrix)
context.setProgramConstantsFromMatrix("vertex", 0, m, 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])
context.setProgram(programBg)
context.setDepthTest(true, "less")
var vBuf:VertexBuffer3D = context.createVertexBuffer(bgVec.length/3, 3)
var uBuf:VertexBuffer3D = context.createVertexBuffer(bgUvs.length/2, 2)
var tBuf:IndexBuffer3D = context.createIndexBuffer(bgTri.length)
vBuf.uploadFromVector(bgVec, 0, bgVec.length/3)
uBuf.uploadFromVector(bgUvs, 0, bgUvs.length/2)
tBuf.uploadFromVector(bgTri, 0, bgTri.length)
context.setVertexBufferAt(0, vBuf, 0, "float3")
context.setVertexBufferAt(1, uBuf, 0, "float2")
context.drawTriangles(tBuf, 0, bgTri.length/3)
if(waitdraw-- == 0) {
stage3D.visible = true
removeChild(scene)
}
if(waitdraw >= 0) {
context.drawToBitmapData(scene.bitmapData)
}
context.present()
}
private function getMatrix():Matrix3D {
var _far:Number = 100
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();
}
}