classes
SimpleDisplacerTriangles.as
Stiahnuť SimpleDisplacerTriangles.as
package sk.yoz.displacing
{
import flash.display.BitmapData;
import flash.display.Shape;
import flash.geom.Matrix3D;
import flash.geom.PerspectiveProjection;
import flash.geom.Utils3D;
import flash.geom.Vector3D;
import sk.yoz.geom.Triangle;
public class SimpleDisplacerTriangles extends AbstractDisplacer
{
public var depth:Number = 100;
public var segmentsW:uint = 15;
public var segmentsH:uint = 15;
protected var matrix3D:Matrix3D = new Matrix3D();
protected var projection:PerspectiveProjection = new PerspectiveProjection();
protected var uvtData:Vector.<Number>;
protected var vertices:Vector.<Number>;
protected var projected:Vector.<Number>;
protected var container:Shape = new Shape();
private var _indices:Vector.<int>;
private var indicesCache:Object = {};
private var firstTriangle:Triangle;
private var matrixUpdateRequired:Boolean = true;
public function SimpleDisplacerTriangles(
viewportWidth:Number, viewportHeight:Number,
image:BitmapData, map:BitmapData,
rotationXMax:Number = 30, rotationYMax:Number = 30,
depth:Number = 100, segmentsW:uint = 15, segmentsH:uint = 15):void
{
super(image, map, rotationXMax, rotationYMax, 0, 0);
projection.fieldOfView = 60;
update(depth, segmentsW, segmentsH);
container.x = viewportWidth / 2;
container.y = viewportHeight / 2;
addChild(container);
}
override public function set rotX(value:Number):void
{
super.rotX = value;
matrixUpdateRequired = true;
}
override public function set rotY(value:Number):void
{
super.rotY = value;
matrixUpdateRequired = true;
}
override public function render():void
{
super.render();
if(matrixUpdateRequired)
updateMatrix(matrix3D, rotX, rotY);
matrixUpdateRequired = false;
Utils3D.projectVectors(matrix3D, vertices, projected, uvtData);
container.graphics.clear();
container.graphics.beginBitmapFill(image, null, false, true);
container.graphics.drawTriangles(projected, indices, uvtData);
}
protected function normalizeRotation(rotation:Number):Number
{
var abs:Number = Math.abs(rotation);
if(abs < 5)
return 0;
if(abs < 20)
return rotation > 0 ? 10 : -10;
if(abs < 60)
return rotation > 0 ? 30 : -30;
return rotation > 0 ? 90 : -90;
}
protected function get indices():Vector.<int>
{
var rx:int = normalizeRotation(rotX);
var ry:int = normalizeRotation(rotY);
if(!indicesCache.hasOwnProperty(rx))
indicesCache[rx] = {};
if(!indicesCache[rx].hasOwnProperty(ry))
indicesCache[rx][ry] = zSort(rx, ry);
return indicesCache[rx][ry];
}
public function update(depth:Number, segmentsW:uint, segmentsH:uint):void
{
this.depth = depth || this.depth;
this.segmentsW = segmentsW || this.segmentsW;
this.segmentsH = segmentsH || this.segmentsH;
generateModel();
updateMatrix(matrix3D, rotX, rotY);
indicesCache = {};
firstTriangle = null;
}
protected function generateModel():void
{
vertices = new Vector.<Number>();
uvtData = new Vector.<Number>();
projected = new Vector.<Number>();
var color:uint, x:uint, y:uint;
var sizeW:Number = (image.width - 1) / segmentsW;
var sizeH:Number = (image.height - 1) / segmentsH;
var w:Number = image.width / 2;
var h:Number = image.height / 2;
var d:Number = 1 / 0xff * depth;
for(y = 0; y <= segmentsH; y++)
for(x = 0; x <= segmentsW; x++)
{
color = map.getPixel(x * sizeW, y * sizeH);
vertices.push(x * sizeW - w, y * sizeH - h, -(color >> 16) * d);
uvtData.push(x / segmentsW, y / segmentsH, 0);
}
var verticesW:uint = segmentsW + 1;
_indices = new Vector.<int>();
for(x = 0; x < segmentsW; x++)
for(y = 0; y < segmentsH; y++)
{
var yvW:uint = y * verticesW;
var y1vW:uint = (y + 1) * verticesW;
_indices.push(
x + yvW, x + yvW + 1, x + y1vW,
x + yvW + 1, x + y1vW + 1, x + y1vW);
}
}
private function updateMatrix(matrix3D:Matrix3D,
rotX:Number, rotY:Number):void
{
matrix3D.identity();
matrix3D.appendRotation(-rotX, Vector3D.X_AXIS);
matrix3D.appendRotation(rotY, Vector3D.Y_AXIS);
matrix3D.appendTranslation(0, 0, 550);
matrix3D.append(projection.toMatrix3D());
}
private function zSort(rotX:Number, rotY:Number):Vector.<int>
{
var projected:Vector.<Number> = new Vector.<Number>();
var matrix3D:Matrix3D = new Matrix3D();
updateMatrix(matrix3D, rotX, rotY);
matrix3D.transformVectors(vertices, projected);
if(!firstTriangle)
firstTriangle = Triangle.create(_indices, projected);
else
firstTriangle.vertices = projected;
return firstTriangle.zSort;
}
}
}