forked from: Dynamic 2D Shadows
forked from Dynamic 2D Shadows (diff: 316)
use shader
ActionScript3 source code
/**
* Copyright heroboy ( http://wonderfl.net/user/heroboy )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/39zp
*/
package
{
import com.bit101.components.PushButton;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shader;
import flash.display.ShaderJob;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.filters.ShaderFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.utils.ByteArray;
import flash.utils.getTimer;
/*
<languageVersion : 1.0;>
kernel DistanceBasedBlur
< namespace : "Your Namespace";
vendor : "Your Vendor";
version : 1;
>
{
parameter float2 center
<
parameterType:"position";
minValue:float2(0.0);
maxValue:float2(1024.0);
>;
parameter float factor
<
minValue:0.0;
maxValue:1.0;
defaultValue:0.25;
>;
parameter float threshold
<
minValue:0.0;
maxValue:1000.0;
defaultValue:0.1;
>;
input image4 src;
output pixel4 dst;
void
evaluatePixel()
{
float d = factor * (distance(outCoord(),center) - threshold);
if (d<0.0) d = 0.0;
float d2 = d/2.0;
dst = (4.0*sampleNearest(src,outCoord()) +
2.0 * sampleNearest(src,outCoord()+float2(-d2,-d2)) +
2.0 * sampleNearest(src,outCoord()+float2(d2,-d2)) +
2.0 * sampleNearest(src,outCoord()+float2(-d2,d2)) +
2.0 * sampleNearest(src,outCoord()+float2(d2,d2)) +
sampleNearest(src,outCoord()+float2(d,0.0))+
sampleNearest(src,outCoord()+float2(0.0,d))+
sampleNearest(src,outCoord()+float2(-d2,0.0))+
sampleNearest(src,outCoord()+float2(0.0,-d2))
)/16.0;
}
}
*/
/*
<languageVersion : 1.0;>
kernel DistanceMap
< namespace : "Your Namespace";
vendor : "Your Vendor";
version : 1;
>
{
parameter float lightRadius
<
defaultValue:100.0;
>;
parameter float2 outputSize
<
defaultValue:float2(400.0);
>;
parameter float2 srcSize
<
parameterType:"inputSize";
inputSizeName:"src";
>;
parameter float2 center
<
defaultValue:float2(200.0);
>;
input image4 src;
output pixel4 dst;
void
evaluatePixel()
{
float r = lightRadius * (outCoord().x / outputSize.x);
float t = 2.0 * 3.141592654 * outCoord().y / outputSize.y;
float cx = r * cos(t) + center.x;
float cy = r * sin(t) + center.y;
//float2 c = float2(r * cos(t) + center.x,r * sin(t) + center.y);
if ( cx>=0.0 && cy>=0.0 && cx<(srcSize.x) && cy<(srcSize.y) )
{
float dist = distance(float2(cx,cy),center);
if (dist > lightRadius)
{
dst = float4(1.0,1.0,1.0,1.0);
}
else
{
if (sampleLinear(src,float2(cx,cy)).x < 1.0)
{
dist /= lightRadius;
dist = clamp(dist,0.0,1.0);
dst = float4(dist,dist,dist,1.0);
}
else
{
dst = float4(1.0,1.0,1.0,1.0);
}
}
}
else
{
dst = float4(1.0,1.0,1.0,1.0);
}
}
}
*/
/*
<languageVersion : 1.0;>
kernel RenderLight
< namespace : "Your Namespace";
vendor : "Your Vendor";
version : 1;
>
{
parameter float2 srcSize
<
parameterType:"inputSize";
inputSizeName:"src";
>;
parameter float lightRadius
<
defaultValue:100.0;
>;
parameter float2 center
<
defaultValue:float2(100.0,100.0);
>;
input image4 src;
output pixel4 dst;
void
evaluatePixel()
{
float2 dpos = outCoord() - center;
float dist = length(dpos);
float distFactor = atan(dpos.y,dpos.x);
if (distFactor < 0.0)
{
distFactor += 2.0 * 3.141592654;
}
distFactor /= 2.0*3.141592654;
float obstacleDist = lightRadius * sampleNearest(src,float2(0.0,
distFactor * srcSize.y
)).x;
if (dist < obstacleDist)
{
float val = clamp(1.0 - dist/lightRadius,0.0,1.0);
dst = float4(val,val,val,1.0);
}
else
{
dst = float4(0.0,0.0,0.0,1.0);
}
//dst = sampleNearest(src,outCoord());
}
}
*/
/**
* Inspired by:
* http://www.catalinzima.com/2010/07/my-technique-for-the-shader-based-dynamic-2d-shadows/
*/
public class Main extends Sprite
{
private const PI :Number = Math.PI;
private const TWO_PI :Number = 2 * Math.PI;
private const HALF_PI :Number = 0.5 * Math.PI;
private const QUARTER_PI :Number = 0.25 * Math.PI;
private const NUM_OBSTACLES :int = 10;
private const OBSTACLE_SIZE :Number = 50;
private const OBSTACLE_SIZE_VAR :Number = 15;
private const LIGHT_RADIUS :Number = 100;
private const BLUR :Number = 2;
private const DIST_BLUR_FACTOR :Number = 0.25;
private const DIST_BLUR_THRESHOLD:Number = 27;
private var resultBMP :Bitmap;
private var dataBMP :Bitmap;
private var obstacles :Sprite;
private var result :BitmapData;
private var resultBlurTemp :BitmapData;
private var obstacleMap :BitmapData;
private var distanceMap :BitmapData;
private var reducedDistanceMap :BitmapData;
private var useShader:Boolean = false;
//[Embed("DistanceMap.pbj",mimeType="application/octet-stream")]
//private var distanceMapShaderData:Class;
//private var distanceMapShader:Shader = new Shader(new distanceMapShaderData() as ByteArray);
private var distanceMapShaderData:String = "a501000000a40b0044697374616e63654d6170a00c6e616d65737061636500596f7572204e616d65737061636500a00c76656e646f7200596f75722056656e646f7200a00876657273696f6e000100a1010200000c5f4f7574436f6f726400a101010000026c6967687452616469757300a20164656661756c7456616c75650042c80000a1010201000c6f757470757453697a6500a20264656661756c7456616c75650043c8000043c80000a1010201000373726353697a6500a20c706172616d657465725479706500696e70757453697a6500a20c696e70757453697a654e616d650073726300a1010202000c63656e74657200a20264656661756c7456616c7565004348000043480000a3000473726300a1020403000f64737400040000100100000003000010000000001d02002000008000030200200000c0001d000010020080003202002040c90fdb1d0200100200800003020010000040000402002001004000030200200200c0001d020010020080000d0200200200c0001d0400800000c00003040080020080001d0200200400000001020020020000001d040080020080000c0200200200c0001d0400400000c00003040040020080001d0200200400400001020020020040001d0400400200800032020020000000002b020020040000001d0180800080000032020020000000002b020020040040001d018040008000001d018020018000002d018020018040002a040080010080001d018080008000001d018040018080002d018040018000002a0400400100c0001d018080008000001d018020018040002d0180200180000034000000018080001d040020040000001d040010040040001d0500c10400b000250500c1020010001d020020050000002a000020020080001d018080008000003400000001800000320300803f800000320300403f800000320300203f800000320300103f80000035000000000000001d040020040000001d04001004004000310500f10400b000320400203f8000002a050080040080001d018040008000003400000001804000040400200000800003020020040080001d040020020080003204001000000000320500803f8000001d050040040080000a0500400400c0001d0500200500400009050020050000001d020020050080001d050080020080001d050040020080001d05002002008000320400203f8000001d050010040080001d0300f305001b003500000000000000320300803f800000320300403f800000320300203f800000320300103f800000360000000000000036000000000000003500000000000000320300803f800000320300403f800000320300203f800000320300103f8000003600000000000000";
private var distanceMapShader:Shader = new Shader(byteArrayFromString(distanceMapShaderData));
//[Embed("RenderLight.pbj", mimeType = "application/octet-stream")]
//private var renderLightShaderData:Class;
//private var renderLightShader:Shader = new Shader(new renderLightShaderData() as ByteArray);
private var renderLightShaderData:String = "a501000000a40b0052656e6465724c69676874a00c6e616d65737061636500596f7572204e616d65737061636500a00c76656e646f7200596f75722056656e646f7200a00876657273696f6e000100a1010200000c5f4f7574436f6f726400a1010200000373726353697a6500a20c706172616d657465725479706500696e70757453697a6500a20c696e70757453697a654e616d650073726300a101010100086c6967687452616469757300a20164656661756c7456616c75650042c80000a1010201000663656e74657200a20264656661756c7456616c75650042c8000042c80000a3000473726300a1020402000f647374001d0300c100001000020300c1010060001d03003103001000240100110300b0001d0300800100c0001d0100100300c00006010010030080001d0300400100c00032010010000000002a0300400100c0001d0180800080000034000000018000003201001040c90fdb010300400100c00036000000000000003201001040c90fdb040400800100c000030300400400000032010010000000001d0400800100c0001d01001003004000030100100000c0001d0400400100c000300500f1040010001d0100100100000003010010050000001d0400800100c0002a030080040000001d018080008000003400000001800000320100103f800000040400400100000003040040030000001d0400200100c00002040020040040001d010010040080003204004000000000320400103f8000001d0500800100c0000a050080040040001d05004005000000090500400400c0001d010010050040001d0500800100c0001d0500400100c0001d0500200100c000320400403f8000001d050010040040001d0200f305001b003500000000000000320200800000000032020040000000003202002000000000320200103f8000003600000000000000";
private var renderLightShader:Shader = new Shader(byteArrayFromString(renderLightShaderData));
//[Embed("DistanceBasedBlur.pbj",mimeType="application/octet-stream")]
//private var BlurShaderData:Class;
//private var blurShader:Shader = new Shader(new BlurShaderData() as ByteArray);
private var BlurShaderData:String = "a501000000a4110044697374616e63654261736564426c7572a00c6e616d65737061636500596f7572204e616d65737061636500a00c76656e646f7200596f75722056656e646f7200a00876657273696f6e000100a1010200000c5f4f7574436f6f726400a1010200000363656e74657200a20c706172616d657465725479706500706f736974696f6e00a2026d696e56616c7565000000000000000000a2026d617856616c7565004480000044800000a10101010008666163746f7200a2016d696e56616c75650000000000a2016d617856616c7565003f800000a20164656661756c7456616c7565003e800000a101010100047468726573686f6c6400a2016d696e56616c75650000000000a2016d617856616c756500447a0000a20164656661756c7456616c7565003dcccccda3000473726300a1020402000f647374001d01003100001000250100310000b0001d0100100100800002010010010040001d01002001000000030100200100c0001d0100100100800032010020000000002a010010010080001d0180800080000034000000018000003201001000000000360000000000000032010020400000000403008001008000030300800100c0001d010020030000003203008040800000300400f1000010001d0500f303000000030500f304001b003203008040000000320300100000000002030010010080001d0300400300c000320300100000000002030010010080001d0300200300c0001d0400c100001000010400c103006000300600f1040010001d0400f303000000030400f306001b001d0300f305001b00010300f304001b0032040080400000001d04004001008000320400100000000002040010010080001d0400200400c0001d0500c100001000010500c104006000300600f1050010001d0500f304000000030500f306001b001d0400f303001b00010400f305001b003203008040000000320300100000000002030010010080001d0300400300c0001d030020010080001d0500c100001000010500c103006000300600f1050010001d0500f303000000030500f306001b001d0300f304001b00010300f305001b0032040080400000001d040040010080001d040020010080001d0500c100001000010500c104006000300600f1050010001d0500f304000000030500f306001b001d0400f303001b00010400f305001b001d0300800100c00032030020000000001d030040030080001d030031000010000103003103001000300500f10300b0001d0300f304001b00010300f305001b0032040020000000001d040080040080001d0400400100c0001d040031000010000104003104001000300500f10400b0001d0400f303001b00010400f305001b00320300200000000002030020010080001d0300800300800032030020000000001d030040030080001d030031000010000103003103001000300500f10300b0001d0300f304001b00010300f305001b0032040020000000001d04008004008000320400200000000002040020010080001d040040040080001d040031000010000104003104001000300500f10400b0001d0400f303001b00010400f305001b003203008041800000040500f303000000030500f304001b001d0200f305001b00";
private var blurShader:Shader = new Shader(byteArrayFromString(BlurShaderData));
private function byteArrayToString(arr:ByteArray):String
{
var result:String = "";
var s:String;
for (var i:uint = 0; i < arr.length;++i )
{
s = arr[i].toString(16);
if (s.length == 1) s = "0" + s;
result += s;
}
return result;
}
private function byteArrayFromString(s:String):ByteArray
{
var result:ByteArray = new ByteArray();
for (var i:uint = 0; i < s.length; i += 2 )
{
result.writeByte( parseInt(s.substr(i,2),16 ));
}
result.position = 0;
return result;
}
public function Main()
{
init();
stage.addEventListener(MouseEvent.MOUSE_MOVE, mainLoop);
}
private function init():void
{
result = new BitmapData(150, 150, false, 0xFFFFFF);
resultBlurTemp = new BitmapData(150, 150, false, 0xFFFFFF);
obstacleMap = new BitmapData(150, 150, false, 0xFFFFFF);
distanceMap = new BitmapData(100, 100, false, 0xFFFFFF);
reducedDistanceMap = new BitmapData( 1, 100, false, 0xFFFFFF);
dataBMP = new Bitmap();
addChild(dataBMP);
resultBMP = new Bitmap(result);
resultBMP.scaleX = stage.stageWidth / result.width;
resultBMP.scaleY = stage.stageHeight / result.height;
addChild(resultBMP);
obstacles = new Sprite();
//addChild(obstacles);
new PushButton(this, 10, 10, "Regenerate Obstacles", regenerateObstacles);
new PushButton(this, 10, 30, "Result", showResult);
new PushButton(this, 10, 50, "Obstacle Map", showObstacleMap);
new PushButton(this, 10, 70, "Distance Map", showDistanceMap);
new PushButton(this, 10, 90, "Reduced Distance Map", showReducedDistanceMap);
new PushButton(this, 10, 110, "use shader", function(e:Event):void
{
useShader = (e.target as PushButton).selected;
mainLoop();
}).toggle = true;
regenerateObstacles();
//trace("distanceMapShaderData:" + byteArrayToString(new distanceMapShaderData() as ByteArray));
//trace("renderLightShaderData:" + byteArrayToString(new renderLightShaderData() as ByteArray));
//trace("BlurShaderData:" + byteArrayToString(new BlurShaderData() as ByteArray));
}
private function mainLoop(e:Event = null):void
{
result.lock();
distanceMap.lock();
reducedDistanceMap.lock();
//var t1:int = getTimer();
//pre-processing
updateDistanceMap(useShader);
//var t2:int = getTimer();
//trace("updateDistanceMap:"+(t2-t1));
reduceDistanceMap();
//var t3:int = getTimer();
//trace("reduceDistanceMap:"+(t3-t2));
//rendering
result.fillRect(result.rect, 0xFFFFFF);
//var t4:int = getTimer();
renderLight(useShader);
//var t5:int = getTimer();
//trace("renderLight:" + (t5 - t4));
blurLight(useShader);
//var t6:int = getTimer();
//trace("blurLight:" + (t6 - t5));
renderObstacles();
result.unlock();
distanceMap.unlock();
reducedDistanceMap.unlock();
//var t7:int = getTimer();
//trace("total:" + (t7 - t1));
//trace("\n");
}
private function updateDistanceMap(useShader:Boolean = true):void
{
var mx:Number = stage.mouseX * obstacleMap.width / stage.stageWidth;
var my:Number = stage.mouseY * obstacleMap.height / stage.stageHeight;
if (useShader)
{
distanceMapShader.data.lightRadius.value = [LIGHT_RADIUS];
distanceMapShader.data.outputSize.value = [distanceMap.rect.width, distanceMap.rect.height];
distanceMapShader.data.src.input = obstacleMap;
distanceMapShader.data.srcSize.value = [obstacleMap.rect.width, obstacleMap.rect.height];
distanceMapShader.data.center.value = [mx, my];
var job:ShaderJob = new ShaderJob(distanceMapShader, distanceMap);
job.start(true);
return;
}
distanceMap.fillRect(distanceMap.rect, 0xFFFFFF);
for (var j:int = 0; j < distanceMap.height; ++j)
{
for (var i:int = 0; i < distanceMap.width; ++i)
{
//polar to cartesian
var r:Number = LIGHT_RADIUS * (i / distanceMap.width);
var t:Number = TWO_PI * (j/ distanceMap.height);
var cx:Number = r * Math.cos(t) + mx;
var cy:Number = r * Math.sin(t) + my;
if
(
cx >= 0 && cx <= obstacleMap.width
&& cy >= 0 && cy <= obstacleMap.height
)
{
var dx:Number = cx - mx;
var dy:Number = cy - my;
var dist:Number = Math.sqrt(dx * dx + dy * dy);
if (dist > LIGHT_RADIUS)
{
//out of light radius
distanceMap.setPixel(i, j, 0xFFFFFF);
}
else
{
//draw distance color
var channel:uint = 0xFF * (dist / LIGHT_RADIUS);
var color:uint = 0;
color |= channel << 16;
color |= channel << 8;
color |= channel;
distanceMap.setPixel
(
i, j,
(obstacleMap.getPixel(cx, cy) < 0xFFFFFF)
?(color):(0xFFFFFF)
);
}
}
}
}
}
private function reduceDistanceMap():void
{
reducedDistanceMap.fillRect(reducedDistanceMap.rect, 0xFFFFFF);
for (var t:int = 0; t < reducedDistanceMap.height; ++t)
{
for (var i:int = 0; i < distanceMap.width; ++i)
{
var color:uint = distanceMap.getPixel(i, t);
if (color != 0xFFFFFF)
{
reducedDistanceMap.setPixel(0, t, color);
break;
}
}
}
}
private function reduceDistanceMap2():void
{
reducedDistanceMap.fillRect(reducedDistanceMap.rect, 0xFFFFFF);
var vec:Vector.<uint> = distanceMap.getVector(distanceMap.rect);
for (var t:int = 0; t < reducedDistanceMap.height; ++t)
{
for (var i:int = 0; i < distanceMap.width; ++i)
{
var color:uint = vec[t * distanceMap.width + i];//distanceMap.getPixel(i, t);
//color = distanceMap.getPixel(i, t);
if (color != 0xFFFFFFff)
{
reducedDistanceMap.setPixel(0, t, color);
break;
}
}
}
}
private function renderLight(useShader:Boolean=true):void
{
var mx:Number = stage.mouseX * result.width / stage.stageWidth;
var my:Number = stage.mouseY * result.height / stage.stageHeight;
if (useShader)
{
renderLightShader.data.src.input = reducedDistanceMap;
renderLightShader.data.srcSize.value = [reducedDistanceMap.width, reducedDistanceMap.height];
renderLightShader.data.center.value = [mx, my];
renderLightShader.data.lightRadius.value = [LIGHT_RADIUS];
//renderLightShader.data.outputSize.value = [result.width, result.height];
var job:ShaderJob = new ShaderJob(renderLightShader, result);
job.start(true);
return;
}
for (var j:int = 0; j < result.width; ++j)
{
for (var i:int = 0; i < result.height; ++i)
{
var dx:Number = i - mx;
var dy:Number = j - my;
var dist:Number = Math.sqrt(dx * dx + dy * dy);
var obstacleDist:Number;
var color:uint;
var channel:uint;
var distFactor:Number = Math.atan2(dy, dx);
if (distFactor < 0) distFactor += TWO_PI;
distFactor /= TWO_PI;
obstacleDist =
LIGHT_RADIUS
* reducedDistanceMap.getPixel
(0, reducedDistanceMap.height * distFactor);
obstacleDist /= 0xFFFFFF;
if (dist < obstacleDist)
{
channel = 0xFF * (1 - dist / LIGHT_RADIUS);
color = 0;
color |= channel << 16;
color |= channel << 8;
color |= channel;
}
else
{
color = 0x000000;
}
result.setPixel(i, j, color);
}
}
}
private function blurLight(useShader:Boolean = true):void
{
var mx:Number = stage.mouseX * result.width / stage.stageWidth;
var my:Number = stage.mouseY * result.height / stage.stageHeight;
if (useShader)
{
blurShader.data.center.value = [ mx, my];
blurShader.data.factor.value = [DIST_BLUR_FACTOR];
blurShader.data.threshold.value = [DIST_BLUR_THRESHOLD];
blurShader.data.src.input = result;
var job:ShaderJob = new ShaderJob(blurShader, resultBlurTemp);
job.start(true);
}
else
{
resultBlurTemp.copyPixels(result, result.rect, new Point(0, 0));
//distance-based blur
for (var j:int = 0; j < result.height; ++j)
{
for (var i:int = 0; i < result.width; ++i)
{
var dx:Number = i - mx;
var dy:Number = j - my;
var d:Number =
DIST_BLUR_FACTOR
* (Math.sqrt(dx * dx + dy * dy) - DIST_BLUR_THRESHOLD);
d = (d < 0)?(0):(d);
var channel:uint =
(
4 * (result.getPixel(i, j) & 0xFF)
+ 2 * (result.getPixel(i - d / 2, j - d / 2) & 0xFF)
+ 2 * (result.getPixel(i + d / 2, j - d / 2) & 0xFF)
+ 2 * (result.getPixel(i + d / 2, j + d / 2) & 0xFF)
+ 2 * (result.getPixel(i - d / 2, j + d / 2) & 0xFF)
+ (result.getPixel(i - d, j) & 0xFF)
+ (result.getPixel(i, j - d) & 0xFF)
+ (result.getPixel(i + d, j) & 0xFF)
+ (result.getPixel(i, j + d) & 0xFF)
) / 16;
var color:uint = 0;
color |= channel << 16;
color |= channel << 8;
color |= channel;
resultBlurTemp.setPixel(i, j, color);
}
}
}
var temp:BitmapData = result;
result = resultBlurTemp;
resultBlurTemp = temp;
resultBMP.bitmapData = result;
//global blur
result.applyFilter
(
result, result.rect, new Point(0, 0),
new BlurFilter(BLUR, BLUR, 2)
);
}
private function renderObstacles():void
{
result.draw
(
obstacles,
new Matrix
(
result.width / stage.stageWidth, 0,
0, result.height / stage.stageHeight
)
);
}
private function regenerateObstacles(e:Event = null):void
{
while (obstacles.numChildren) obstacles.removeChildAt(0);
for (var i:int = 0; i < NUM_OBSTACLES; ++i)
{
var shape:Shape = new Shape();
var size:Number =
OBSTACLE_SIZE
+ OBSTACLE_SIZE_VAR * (2 * (0.5 - Math.random()));
shape.graphics.beginFill(0x808080, 1);
shape.graphics.drawRect( -0.5 * size, -0.5 * size, size, size);
shape.rotation = 360 * Math.random();
shape.x = stage.stageWidth * Math.random();
shape.y = stage.stageHeight * Math.random();
obstacles.addChild(shape);
}
obstacleMap.lock();
obstacleMap.fillRect(obstacleMap.rect, 0xFFFFFF);
obstacleMap.draw
(
obstacles,
new Matrix
(
obstacleMap.width / stage.stageWidth, 0,
0, obstacleMap.height / stage.stageHeight
)
);
obstacleMap.threshold
(
obstacleMap, obstacleMap.rect, new Point(0, 0), "<",
0xFF0000, 0x000000, 0xFF0000, true
);
obstacleMap.unlock();
//update
mainLoop();
}
private function showResult(e:Event = null):void
{
resultBMP.visible = true;
obstacles.visible = true;
dataBMP.visible = false;
}
private function showObstacleMap(e:Event = null):void
{
resultBMP.visible = false;
obstacles.visible = false;
dataBMP.visible = true;
dataBMP.bitmapData = obstacleMap;
dataBMP.scaleX = stage.stageWidth / obstacleMap.width;
dataBMP.scaleY = stage.stageHeight / obstacleMap.height;
}
private function showDistanceMap(e:Event = null):void
{
resultBMP.visible = false;
obstacles.visible = false;
dataBMP.visible = true;
dataBMP.bitmapData = distanceMap;
dataBMP.scaleX = stage.stageWidth / distanceMap.width;
dataBMP.scaleY = stage.stageHeight / distanceMap.height;
}
private function showReducedDistanceMap(e:Event = null):void
{
resultBMP.visible = false;
obstacles.visible = false;
dataBMP.visible = true;
dataBMP.bitmapData = reducedDistanceMap;
dataBMP.scaleX = stage.stageWidth / reducedDistanceMap.width;
dataBMP.scaleY = stage.stageHeight / reducedDistanceMap.height;
}
}
}
