/**
* Copyright mutantleg ( http://wonderfl.net/user/mutantleg )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/by0Q
*/
package {
import flash.text.TextField;
import flash.display.BitmapData;
import flash.display.StageQuality;
import flash.geom.Vector3D;
import flash.geom.Matrix3D;
import flash.events.Event;
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
stage.quality = StageQuality.LOW;
deb = new TextField();
deb.width =320;
deb.height=240;
deb.mouseEnabled=false;
addChild(deb);
var dat:BitmapData;
dat = new BitmapData(17,17, false, 0);
dat.perlinNoise(31,32, 14,15, true,true);
myHeight = new xHeightMap();
myHeight.cw=16; myHeight.ch=16;
myHeight.initHeight(dat, 2, -128);
myHeight.cx = -8*myHeight.cw;
myHeight.cz = -8*myHeight.ch;
myHeight.initMap(16,16);
stage.addEventListener(Event.ENTER_FRAME, onEnter);
}//ctor
public var frust:xFrustum = new xFrustum();
public var temp:Matrix3D = new Matrix3D();
public var gt:int = 0;
public var ang:Number = 0;
public function onEnter(e:Event):void
{
var mx:Number; var my:Number;
mx = stage.mouseX; my = stage.mouseY;
// if (mx < 120) {ang-=3;}
// if (mx >300) {ang+=3;}
graphics.clear();
graphics.beginFill(0x404040,1);
graphics.drawRect(0,0,465,465);
graphics.endFill();
//graphics.lineStyle(1,0);
gt += 1;
temp.identity();
// temp.appendScale(1, 1, 1);
// temp.appendRotation(45+ang, Vector3D.Y_AXIS);
temp.appendRotation(45+gt*0.5, Vector3D.Z_AXIS);
// temp.appendRotation(45, Vector3D.Z_AXIS);
temp.appendRotation(-30, Vector3D.X_AXIS);
myMat = temp.rawData;
drawMesh(myHeight.vecFace, myHeight.vecVert, myMat);
/*
mx-=scrw; my-=scrh;
temp.invert();
myMat = temp.rawData;
drawSprite(-x,-y,0,8,myMat,0x00FF00);
temp.identity();
myMat=temp.rawData;
drawMesh(myHeight.vecFace, myHeight.vecVert, myMat);
*/
/*
myMat = temp.rawData;
// frust.setOrtho(scrw,scrh, 0, 512);
frust.setOrtho(64, 64, 0, 128);
frust.makeFrustum2(myMat);
frust.setMouseLine(0,0);
deb.text="";
// deb.appendText(" "+frust.retNear.x);
// deb.appendText(" "+frust.retNear.y);
// deb.appendText(" "+frust.retNear.z);
deb.appendText(" "+frust.nearCenter.x);
deb.appendText(" "+frust.nearCenter.y);
deb.appendText(" "+frust.nearCenter.z);
deb.appendText(" "+frust.farCenter.x);
deb.appendText(" "+frust.farCenter.y);
deb.appendText(" "+frust.farCenter.z);
drawSprite(frust.farCenter.x,frust.farCenter.y,frust.farCenter.z,16,myMat);
drawSprite(frust.nearCenter.x,frust.nearCenter.y,frust.nearCenter.z,8,myMat);
drawSprite(frust.farTopLeft.x,frust.farTopLeft.y,frust.farTopLeft.z,16,myMat);
drawSprite(frust.farBotLeft.x,frust.farBotLeft.y,frust.farBotLeft.z,16,myMat);
drawSprite(frust.farTopRight.x,frust.farTopRight.y,frust.farTopRight.z,16,myMat);
drawSprite(frust.farBotRight.x,frust.farBotRight.y,frust.farBotRight.z,16,myMat);
drawSprite(frust.nearTopLeft.x,frust.nearTopLeft.y,frust.nearTopLeft.z,8,myMat);
drawSprite(frust.nearBotLeft.x,frust.nearBotLeft.y,frust.nearBotLeft.z,8,myMat);
drawSprite(frust.nearTopRight.x,frust.nearTopRight.y,frust.nearTopRight.z,8,myMat);
drawSprite(frust.nearBotRight.x,frust.nearBotRight.y,frust.nearBotRight.z,8,myMat);
drawSprite(frust.retNear.x,frust.retNear.y,frust.retNear.z,8,myMat,0x00FF00);
drawSprite(frust.retFar.x,frust.retFar.y,frust.retFar.z,16,myMat,0x00FF00);
*/
}//onenter
public var deb:TextField;
public var myHeight:xHeightMap;
public var myMat:Vector.<Number> = Vector.<Number>([
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
public var scrw:Number = 235;
public var scrh:Number = 235;
public function drawSprite(ax:Number, ay:Number, az:Number, rad:Number, mat:Vector.<Number>, c:uint=0x802343):void
{
var sx0:Number; var sy0:Number;
sx0 = ax * mat[0] + ay * mat[4] + az * mat[8] + mat[12];
sy0 = ax * mat[1] + ay * mat[5] + az * mat[9] + mat[13];
graphics.beginFill(c,0.5);
graphics.drawCircle(sx0+scrw,sy0+scrh, rad);
graphics.endFill();
}//drawsprite
public function drawMesh(vf:Vector.<int>, vec:Vector.<Number>, mat:Vector.<Number>):void
{
var rx:Number; var ry:Number; var rz:Number;
var sx0:Number; var sy0:Number;
var sx1:Number; var sy1:Number;
var sx2:Number; var sy2:Number;
var wind:Number;
var i:int; var num:int;
var k:int;
num = vf.length;
for (k = 0; k < num; k += 3)
{
i = vf[k] * 3;
rx = vec[i]; ry = vec[i+1]; rz = vec[i+2];
sx0 = rx * mat[0] + ry * mat[4] + rz * mat[8] + mat[12];
sy0 = rx * mat[1] + ry * mat[5] + rz * mat[9] + mat[13];
//sz = a.cx * mat[2] + a.cy * mat[6] + a.cz * mat[10] + mat[14];
// w = a.cx * mat[3] + a.cy * mat[7] + a.cz * mat[11] + mat[15];
i = vf[k+1] * 3;
rx = vec[i]; ry = vec[i+1]; rz = vec[i+2];
sx1 = rx * mat[0] + ry * mat[4] + rz * mat[8] + mat[12];
sy1 = rx * mat[1] + ry * mat[5] + rz * mat[9] + mat[13];
i = vf[k+2] * 3;
rx = vec[i]; ry = vec[i+1]; rz = vec[i+2];
sx2 = rx * mat[0] + ry * mat[4] + rz * mat[8] + mat[12];
sy2 = rx * mat[1] + ry * mat[5] + rz * mat[9] + mat[13];
//backface cull -> check winding of verts
wind = (sx1 - sx0) * (sy2 - sy0) - (sx2 - sx0) * (sy1 - sy0);
if (wind > 0) { continue; }
graphics.beginFill(rz*0x0000ff, 0.75);
graphics.moveTo(sx0+scrw, sy0+scrh);
graphics.lineTo(sx1+scrw, sy1+scrh);
graphics.lineTo(sx2+scrw, sy2+scrh);
graphics.endFill();
}//nexti
}//drawmesh2
}//classend
}
import flash.display.BitmapData;
import flash.display.Graphics;
internal class xVec
{
public var x:Number = 0; public var y:Number = 0; public var z:Number = 0;
public function xVec(ax:Number=0,ay:Number=0,az:Number=0)
{ x = ax; y = ay; z = az; }
public function setValue(ax:Number=0,ay:Number=0,az:Number=0):void
{ x = ax; y = ay; z = az; }
public function copyVec(a:xVec):void { x=a.x; y=a.y; z=a.z; }
public function addVec(a:xVec):void { x+=a.x;y+=a.y; z+=a.z; }
public function subVec(a:xVec):void { x-=a.x;y-=a.y; z-=a.z; }
public function mulNum(a:Number):void { x*=a; y*=a; z*=a; }
public function normalise():void
{ var mag:Number; mag=Math.sqrt(x*x+y*y+z*z);
if(mag==0){return;} mag=1/mag; x*=mag; y*=mag; z*=mag; }
public function cross2(a:xVec, b:xVec ):void
{
var tx:Number, ty:Number, tz:Number;
tx = (a.y * b.z) - (a.z * b.y);
ty = (a.z * b.x) - (a.x * b.z);
tz = (a.x * b.y) - (a.y * b.x);
x = tx; y = ty; z = tz;
}//cross2
}//xvec
internal class xFrustum
{
public var nearWidth:Number, nearHeight:Number;
public var farWidth:Number, farHeight:Number;
public var nearDist:Number, farDist:Number;
public var farTopLeft:xVec = new xVec(); public var farBotLeft:xVec = new xVec();
public var farTopRight:xVec = new xVec(); public var farBotRight:xVec = new xVec();
public var nearTopLeft:xVec = new xVec(); public var nearBotLeft:xVec = new xVec();
public var nearTopRight:xVec = new xVec(); public var nearBotRight:xVec = new xVec();
public var farUp:xVec = new xVec(); public var farSide:xVec = new xVec();
public var nearUp:xVec = new xVec(); public var nearSide:xVec = new xVec();
public var farCenter:xVec = new xVec(); public var nearCenter:xVec = new xVec();
public var vecPoint:Vector.<xVec> = Vector.<xVec>([new xVec(),new xVec(),new xVec(),new xVec(),new xVec(),new xVec()]);
public var vecNorm:Vector.<xVec> = Vector.<xVec>([new xVec(),new xVec(),new xVec(),new xVec(),new xVec(),new xVec()]);
public function setOrtho(w:Number, h:Number, neard:Number, fard:Number):void
{
nearDist = neard; farDist = fard;
nearWidth = w; nearHeight = h;
farWidth = w; farHeight = h;
}//setortho
public function makeFrustum2(mat:Vector.<Number>):void
{
var v0:xVec,v1:xVec,v2:xVec,v3:xVec;
v0=new xVec(); v1=new xVec(); v2=new xVec(); v3=new xVec();
v0.setValue(mat[0],mat[1],mat[2]);
v1.setValue(mat[4],mat[5],mat[6]);
v2.setValue(mat[8],mat[9],mat[10]);
v3.setValue(mat[12],mat[13],mat[14]);
makeFrustum(v3, v2, v1, v0);
}//makefrustum2
public function makeFrustum(pos:xVec, front:xVec, up:xVec, side:xVec):void
{
farUp.copyVec(up); farUp.mulNum(farHeight);
farSide.copyVec(side); farSide.mulNum(farWidth);
nearUp.copyVec(up); nearUp.mulNum(nearHeight);
nearSide.copyVec(side); nearSide.mulNum(nearWidth);
farCenter.copyVec(front); farCenter.mulNum(farDist);
farCenter.addVec(pos);
farTopLeft.copyVec(farCenter); farTopLeft.addVec(farUp); farTopLeft.subVec(farSide);
farTopRight.copyVec(farCenter); farTopRight.addVec(farUp); farTopRight.addVec(farSide);
farBotLeft.copyVec(farCenter); farBotLeft.subVec(farUp); farBotLeft.subVec(farSide);
farBotRight.copyVec(farCenter); farBotRight.subVec(farUp); farBotRight.addVec(farSide);
nearCenter.copyVec(front); nearCenter.mulNum(nearDist);
nearCenter.addVec(pos);
nearTopLeft.copyVec(nearCenter); nearTopLeft.addVec(nearUp); nearTopLeft.subVec(nearSide);
nearTopRight.copyVec(nearCenter); nearTopRight.addVec(nearUp); nearTopRight.addVec(nearSide);
nearBotLeft.copyVec(nearCenter); nearBotLeft.subVec(nearUp); nearBotLeft.subVec(nearSide);
nearBotRight.copyVec(nearCenter); nearBotRight.subVec(nearUp); nearBotRight.addVec(nearSide);
//near
vecPoint[0].copyVec(nearCenter);
vecNorm[0].copyVec(farCenter); vecNorm[0].subVec(nearCenter);
vecNorm[0].normalise();
//far
vecPoint[1].copyVec(farCenter);
vecNorm[1].copyVec(nearCenter); vecNorm[1].subVec(farCenter);
vecNorm[1].normalise();
//left
calcPlane(nearTopLeft, nearBotLeft, farBotLeft, vecPoint[2], vecNorm[2]);
addPos(farBotLeft, nearTopLeft, vecPoint[2]);
//right
calcPlane(nearBotRight, nearTopRight, farBotRight, vecPoint[3], vecNorm[3]);
addPos(farTopRight, nearBotRight, vecPoint[3]);
//top
calcPlane(nearTopRight, nearTopLeft, farTopLeft, vecPoint[4], vecNorm[4]);
addPos(farTopLeft, nearTopRight, vecPoint[4]);
//bottom
calcPlane(nearBotLeft, nearBotRight, farBotRight, vecPoint[5], vecNorm[5]);
addPos(farBotRight, nearBotLeft, vecPoint[5]);
}//makefrustum
private var e0:xVec = new xVec();
private var e1:xVec = new xVec();
public function calcPlane(p0:xVec, p1:xVec, p2:xVec, p:xVec, n:xVec):void
{
e0.copyVec(p1); e0.subVec(p0);
e1.copyVec(p2); e1.subVec(p0);
p.copyVec(p0); n.cross2(e0, e1);
n.mulNum( -1);
n.normalise();
}//calcplane
public function addPos(p0:xVec, p1:xVec, ret:xVec):void
{
ret.x += (p0.x - p1.x) * 0.5;
ret.y += (p0.y - p1.y) * 0.5;
ret.z += (p0.z - p1.z) * 0.5;
}//setpos
private var tmp0:xVec = new xVec();
public var retNear:xVec = new xVec();
public var retFar:xVec = new xVec();
public function setMouseLine(umx:Number, umy:Number ):void
{
retNear.copyVec(nearCenter);
tmp0.copyVec(nearUp); tmp0.mulNum(umy); retNear.addVec(tmp0);
tmp0.copyVec(nearSide); tmp0.mulNum(umx); retNear.addVec(tmp0);
retFar.copyVec(farCenter);
tmp0.copyVec(farUp); tmp0.mulNum(umy); retFar.addVec(tmp0);
tmp0.copyVec(farSide); tmp0.mulNum(umx); retFar.addVec(tmp0);
}//setmouseline
}//xfrustum
internal class xHeightMap
{
public var vecHeight:Vector.<Number>;
public var vecVert:Vector.<Number>;
public var vecFace:Vector.<int>;
//face grid size
public var mw:int = 0; public var mh:int = 0;
//height grid size
public var vmw:int = 0; public var vmh:int = 0;
public var cw:Number = 32; public var ch:Number = 32;
public var cx:Number = 0;
//public var cy:Number = 0;
public var cz:Number = 0;
public function initHeight(bdat:BitmapData, sy:Number=1, ay:Number=0):void
{
var i:int; var k:int;
var w:int; var h:int;
var yt:int;
var num:int;
w = bdat.width; h = bdat.height;
num = w * h;
vecHeight = new Vector.<Number>(num,false);
for (i = 0; i < h; i++)
{
yt = i*w;
for (k = 0; k < w; k++)
{
vecHeight[k+yt] = (bdat.getPixel(k,i) & 0xFF) * sy + ay;
}//nextk
}//nexti
}//initheight
//note -- w and h is for the number of quads
public function initMap(w:int, h:int):void
{
mw = w; mh = h;
vmw = w+1; vmh = h+1;
var i:int; var k:int; var num:int;
var w:int; var yt:int;
num = mw*mh;
vecFace = new Vector.<int>(num,false);
w = 0;
for (i = 0; i < mh; i++)
{
yt = i*(mw+1);
for (k = 0; k < mw; k++)
{
vecFace[w] = 0 + k + yt; //0
vecFace[w+1] = 0 + k + (mw+1) + yt; //1
vecFace[w+2] = 1 + k + yt; //2
vecFace[w+3] = 1 + k + yt; //2
vecFace[w+4] = 0 + k + (mw+1) + yt; //1
vecFace[w+5] = 1 + k + (mw+1) + yt; //3
w+=6;
}//nextk
}//nexti
num = (mw+1)*(mh+1);
if (vecHeight == null)
{
vecHeight = new Vector.<Number>(num,false);
for(i= 0;i <num;i++){vecHeight[i]=Math.random()*3;}
}
vecVert = new Vector.<Number>(num*3,false);
w = 0;
for (i = 0; i < (mh+1); i++)
{
yt = i*(mw+1);
for (k = 0; k < (mw+1); k++)
{
vecVert[w] = k*cw + cx;
vecVert[w+2] = vecHeight[yt+k];
vecVert[w+1] = i * ch + cz;
w+=3;
}//nextk
}//nexti
}//initmap
public function getHeight(ax:Number, az:Number):Number
{
var tx:int; var ty:int; var yt:int;
ax -= cx; az -=cz; //transform by heightmap coords first
tx = Math.floor(ax/cw); ty = Math.floor(az/ch);
var h0:Number; var h1:Number;
var z0:Number; var z1:Number;
var u:Number; var v:Number;
if (tx < 0) { return 0; } if (ty < 0) { return 0; }
if (tx + 1 >= mw) { return 0; } if (ty + 1 >= mh) { return 0; }
yt = ty * vmw;
u = (ax/cw)-tx; v = (az/ch)-ty;
z0 = vecHeight[yt+tx]; z1 = vecHeight[yt+tx+1];
h0 = z0 + (z1-z0)*u;
z0 = vecHeight[yt+tx+vmw]; z1 = vecHeight[yt+tx+vmw+1];
h1 = z0 + (z1 -z0)*u;
return (h0 +(h1-h0) * v);
}//getheight
}//xheightmap