レイトレーシング
レイトレーシング習作
参考文献:Javaではじめるレイトレーシング入門(森北出版)
ボタンはhttp://d.hatena.ne.jp/nitoyon/20090423/as3_simple_buttonを使わせて頂きました。
/**
* Copyright termat ( http://wonderfl.net/user/termat )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/3R1U
*/
/**
レイトレーシング習作
参考文献:Javaではじめるレイトレーシング入門(森北出版)
ボタンはhttp://d.hatena.ne.jp/nitoyon/20090423/as3_simple_buttonを使わせて頂きました。
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
[SWF(width = "500", height = "500", backgroundColor = "0xffffff", fps = "60")]
public class Practice29 extends Sprite {
private var image:RayImage;
private var angle:Number = 0;
private var radius:Number = 5;
private var hh:Number = 3.3;
private var mode:int = 0;
public function Practice29(){
image= new RayImage();
addChild(image);
var bt0:Button = new Button(50, 30, 5, "Rendering", 11);
bt0.x = 450;
bt0.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { image.startRendering(); } );
addChild(bt0);
var bt2:Button = new Button(50, 20, 5, "△", 12);
bt2.x = 225;
bt2.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { mode = 1; } );
bt2.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void { mode = 0; } );
addChild(bt2);
var bt3:Button = new Button(50, 20, 5, "▽", 12);
bt3.x = 225; bt3.y = 480;
bt3.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { mode = 2; } );
bt3.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void { mode = 0; } );
addChild(bt3);
var bt4:Button = new Button(20, 50, 5, "<", 12);
bt4.y = 225;
bt4.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { mode = 3; } );
bt4.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void { mode = 0; } );
addChild(bt4);
var bt5:Button = new Button(20, 50, 5, ">", 12);
bt5.x = 480; bt5.y = 225;
bt5.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { mode = 4; } );
bt5.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void { mode = 0; } );
addChild(bt5);
var bt6:Button = new Button(20, 20, 5, "↑", 12);
bt6.x = 0; bt6.y = 0;
bt6.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { mode = 5; } );
bt6.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void { mode = 0; } );
addChild(bt6);
var bt7:Button = new Button(20, 20, 5, "↓", 12);
bt7.x = 0; bt7.y = 480;
bt7.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void { mode = 6; } );
bt7.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void { mode = 0; } );
addChild(bt7);
addEventListener(Event.ENTER_FRAME,update);
}
private function update(e:Event):void {
if (!image.isCompeleted) return;
switch(mode) {
case 0:
return;
case 1:
radius = Math.max(radius - 0.2, 4);
break;
case 2:
radius = Math.min(radius + 0.2, 8);
break;
case 3:
angle = Math.max(angle-1, -25);
break;
case 4:
angle = Math.min(angle + 1, 25);
break;
case 5:
hh = Math.min(hh + 0.1, 4.5);
break;
case 6:
hh = Math.max(hh - 0.1, 2.5);
break;
}
var rad:Number = angle / 180 * Math.PI;
var xx:Number = Math.cos(rad) * radius - Math.sin(rad) * radius;
var yy:Number = Math.sin(rad) * radius + Math.cos(rad) * radius;
image.ray.setPosition(xx, yy, 5);
image.ray.setReference(3, 3, hh);
image.drawImage();
}
}
}
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.geom.Matrix;
import flash.filters.ColorMatrixFilter;
import flash.filters.GlowFilter;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Vector3D;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.net.URLRequest;
import flash.system.LoaderContext;
class RayImage extends MovieClip {
private var loader:Loader;
public var bmpImage:BitmapData;
private var bmpdata:BitmapData;
private var bmp:Bitmap;
public var ray:Ray;
private var tracer:RayTrace;
private var nodes:Nodes;
private var shade:Shade;
private var im:int=500;
public var isCompeleted:Boolean = true;
public function RayImage():void {
bmpdata = new BitmapData(500, 500, false, 0xffffff);
bmp = new Bitmap(bmpdata);
addChild(bmp);
loader = new Loader();
var url:String = "http://assets.wonderfl.net/images/related_images/f/ff/ff48/ff48d14d79a931bfbf6892b8e2558c3c64bc697e";
var urlReq:URLRequest = new URLRequest(url);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleted);
loader.load(urlReq,new LoaderContext(true));
Wonderfl.capture_delay(20);
}
private function loadCompleted(e:Event):void{
bmpImage = new BitmapData(loader.width, loader.height);
bmpImage.draw(loader);
init();
}
public function init():void {
ray = new Ray();
ray.setPosition(5, 5, 5); //視点位置
ray.setReference(3, 3, 3.3); //注視点
ray.setAbove(0, 0, 1); //上方向のベクトル
ray.createAxis();
ray.createLight( -1.0, 0, 4.0, 150, 150, 150, 2.0, 0.3);
ray.bgcolor = 0xccccff;
ray.setTexture(0);
ray.setObjectColor(255, 0, 0);
ray.shadeParameter(0.3, 0.5, 0.1, 1.4, 0.9);
ray.createSphere(0.0, 0.0, 1.0, 1.0);
ray.setTexture(1);
ray.setObjectColor( 0, 150, 0);
ray.shadeParameter(0.6, 0.7, 0.2, 1.4, 0.5);
ray.createRectangle( -3, 3, 0, -3, -3, 0, 3, -3, 0, 3, 3, 0);
nodes = new Nodes();
var map:Map = new Map(nodes, this);
tracer = new RayTrace(ray);
shade = new Shade(ray, nodes, tracer, map);
tracer.shade = shade;
drawImage();
addEventListener(Event.ENTER_FRAME, update);
}
public function startRendering():void {
if (isCompeleted) {
im = 500;
isCompeleted = false;
}
}
public function update(e:Event):void {
if (!isCompeleted) {
redering();
if (im == 0) isCompeleted = true;
}
}
public function redering():void {
var pj:Number = (im - 250) / 250.0;
for (var j:int = 0; j < 500; j++) {
var pi:Number = (j - 250) / 250.0;
var x:Number = pi * ray.xAxis.x + pj * ray.yAxis.x + ray.reference.x;
var y:Number = pi * ray.xAxis.y + pj * ray.yAxis.y + ray.reference.y;
var z:Number = pi * ray.xAxis.z + pj * ray.yAxis.z + ray.reference.z;
var dirVector:Vector3D = new Vector3D(x - ray.me.x, y - ray.me.y, z - ray.me.z);
dirVector.normalize();
if (tracer.seach(dirVector, ray.me.x, ray.me.y, ray.me.z)) {
nodes.no = 0;
nodes.setData(tracer.index, 1.0, shade.interPoint.x, shade.interPoint.y, shade.interPoint.z, dirVector, tracer.normalVector, 0);
bmpdata.setPixel(j, 500-im, shade.colorSet());
}else {
bmpdata.setPixel(j, 500-im, ray.bgcolor);
}
}
im--;
}
public function drawImage():void{
for (var i:int=0;i<500;i++) {
var pi:Number = (i - 250) / 250.0;
for (var j:int = 0; j < 500; j++) {
var pj:Number = (j - 250) / 250.0;
var x:Number = pi * ray.xAxis.x + pj * ray.yAxis.x + ray.reference.x;
var y:Number = pi * ray.xAxis.y + pj * ray.yAxis.y + ray.reference.y;
var z:Number = pi * ray.xAxis.z + pj * ray.yAxis.z + ray.reference.z;
var dirVector:Vector3D = new Vector3D(x - ray.me.x, y - ray.me.y, z - ray.me.z);
dirVector.normalize();
if (tracer.seach(dirVector, ray.me.x, ray.me.y, ray.me.z)) {
if (tracer.index == 0) {
bmpdata.setPixel(i, 500 - j, 0xff9999);
}else {
bmpdata.setPixel(i, 500 - j, 0xffffff);
}
}else {
bmpdata.setPixel(i, 500-j, 0x999999);
}
}
}
}
}
/* 光源 */
class Light {
public var position:Vector3D;
public var color:Vector3D;
public var brightness:Number;
public var ambient:Number;
}
/* オブジェクト */
class Object3d {
public static const SPHEHE:int = 1;
public static const RECTANGLE:int = 4;
public var op:int;
public var vert1:Vector3D;
public var vert2:Vector3D;
public var vert3:Vector3D;
public var vert4:Vector3D;
public var dh:Vector3D;
public var radius:Number;
public var color:Vector3D;
public var textureNum:int;
public var diffuseReflectance:Number; //拡散反射率
public var specularReflectionRate:Number; //鏡面反射率
public var luster:Number; //面光沢
public var refractiveIndex:Number; //屈折率
public var reflectivity:Number; //反射率
public function Object3d(_op:int,x1:Number,y1:Number,z1:Number,
x2:Number,y2:Number,z2:Number,x3:Number,y3:Number,z3:Number,
x4:Number,y4:Number,z4:Number,dhx:Number, dhy:Number, dhz:Number,
_radius:Number,r:int,g:int,b:int,textureNum:int,
_diffuseReflectance:Number,_specularReflectionRate:Number,_luster:Number,
_refractiveIndex:Number,_reflectivity:Number){
this.op = _op;
vert1 = new Vector3D(x1, y1, z1); vert2 = new Vector3D(x2, y2, z2);
vert3 = new Vector3D(x3, y3, z3); vert4 = new Vector3D(x4, y4, z4);
dh = new Vector3D(dhx, dhy, dhz); radius = _radius;
color = new Vector3D(r, g, b);
this.textureNum = textureNum;
this.diffuseReflectance = _diffuseReflectance;
this.specularReflectionRate = _specularReflectionRate;
this.luster = _luster;
this.refractiveIndex = _refractiveIndex;
this.reflectivity = _reflectivity;
}
}
class Nodes {
public var index:Array=new Array();
public var rate:Array=new Array();
public var node:Array = new Array();
public var sight:Vector.<Vector3D>= new Vector.<Vector3D>();
public var normal:Vector.<Vector3D>= new Vector.<Vector3D>();
public var n:Array = new Array();
public var no:int;
public function setData(_index:int, _rate:Number, _x:Number, _y:Number, _z:Number, _sight:Vector3D, _nolm:Vector3D, n1:int):void {
index[no] = _index;
rate[no] = _rate;
node[no] = new Vector3D(_x, _y, _z);
sight[no] = _sight;
normal[no] = _nolm;
n[no] = n1;
no++;
}
}
class Ray {
public var list:Vector.<Object3d> = new Vector.<Object3d>();
public var color:Vector3D;
public var texture:int;
public var diffusion:Number;
public var specular:Number;
public var luster:Number;
public var refractive:Number;
public var reflectivity:Number;
public var xAxis:Vector3D;
public var yAxis:Vector3D;
public var me:Vector3D;
public var reference:Vector3D;
public var forAbove:Vector3D;
public var bgcolor:uint;
public var light:Light;
public function size():int {
return list.length;
}
public static function setVector(v:Vector3D,x:Number,y:Number,z:Number):void {
v.x = x; v.y = y; v.z = z;
}
public function shadeParameter(_diffusion:Number,_specular:Number,_luster:Number,_refractive:Number,_reflectivity:Number):void {
diffusion = _diffusion;
specular = _specular;
if (_luster < 1 / 100000000.0) {
luster = 1 / 100000000.0;
}else {
luster = _luster;
}
refractive = _refractive;
reflectivity = _reflectivity;
}
public function getObject3d(i:int):Object3d {
return list[i];
}
public function setObjectColor(r:int, g:int, b:int):void {
color = new Vector3D(r, g, b);
}
public function setTexture(m:int):void {
texture=m;
}
public function setPosition(x:Number,y:Number,z:Number):void {
me = new Vector3D(x, y, z);
}
public function setReference(x:Number,y:Number,z:Number):void {
reference=new Vector3D(x,y,z);
}
public function setAbove(x:Number,y:Number,z:Number):void {
forAbove=new Vector3D(x,y,z);
}
public function createLight(x:Number,y:Number,z:Number,r:int,g:int,b:int,_brightness:Number,_ambient:Number):void {
light = new Light();
light.position = new Vector3D(x, y, z);
light.color = new Vector3D(r, g, b);
light.brightness = _brightness;
light.ambient = _ambient;
}
public function createSphere(x:Number,y:Number,z:Number,r:Number):void {
list.push(new Object3d(1, x, y, z, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, r,color.x, color.y, color.z, texture, diffusion,
specular, luster, refractive, reflectivity));
}
public function createRectangle(x1:Number,y1:Number,z1:Number,x2:Number,y2:Number,z2:Number,x3:Number,y3:Number,z3:Number,
x4:Number,y4:Number,z4:Number):void {
list.push(new Object3d(4, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, 0, 0, 0, 0,
color.x,color.y,color.z,texture,diffusion,specular,luster,refractive,reflectivity));
}
public function createAxis():void {
var screenN:Vector3D = new Vector3D(me.x - reference.x, me.y - reference.y, me.z - reference.z);
screenN.normalize();
var d:Number = screenN.dotProduct(forAbove);
yAxis = new Vector3D(forAbove.x - d * screenN.x, forAbove.y - d * screenN.y, forAbove.z - d * screenN.z);
yAxis.normalize();
xAxis = yAxis.crossProduct(screenN);
xAxis.normalize();
}
}
class Map {
private var nodes:Nodes;
private var image:RayImage;
public function Map(n:Nodes,i:RayImage):void {
nodes = n;
image = i;
}
public function mapping(j:int,od:Object3d):Vector3D {
var p:uint = 0;
if (od.op == Object3d.SPHEHE) { p = mapSphere(j, od); }
if (od.op == Object3d.RECTANGLE) { p = mapRectangle(j, od); }
return new Vector3D((0xff & (p >> 16)), (0xff & (p >> 8)), (0xff & p));
}
private function mapSphere(j:int, od:Object3d):uint {
var a1:Number=nodes.node[j].x-od.vert1.x;
var a2:Number=nodes.node[j].y-od.vert1.y;
var a3:Number=nodes.node[j].z-od.vert1.z;
var u:Number=Math.atan2(a2,a1)/(2.0*Math.PI)+0.5;
var v:Number=Math.atan2(a3,Math.sqrt(a1*a1+a2*a2))/Math.PI+0.5;
var x0:int = (u * (image.bmpImage.width - 1));
var y0:int = (v * (image.bmpImage.height - 1));
return image.bmpImage.getPixel(x0, y0);
}
private function mapRectangle(j:int,od:Object3d):uint {
var a1:Number = Vector3D.distance(od.vert1, od.vert2);
var a2:Number = Vector3D.distance(od.vert2, od.vert3);
var a5:Number=a1*a2;
a1 = Vector3D.distance(od.vert1, nodes.node[j]);
a2 = Vector3D.distance(od.vert4, nodes.node[j]);
var a3:Number = Vector3D.distance(od.vert1, od.vert4);
var s:Number = (a1 + a2 + a3) / 2.0;
var a4:Number=Math.sqrt(s*(s-a1)*(s-a2)*(s-a3));
var u:Number = 2.0 * a4 / a5;
a1 = Vector3D.distance(od.vert1, nodes.node[j]);
a2 = Vector3D.distance(od.vert2, nodes.node[j]);
a3 = Vector3D.distance(od.vert1, od.vert2);
s = (a1 + a2 + a3) / 2.0;
a4=Math.sqrt(s*(s-a1)*(s-a2)*(s-a3));
var v:Number = 2.0 * a4 / a5;
var x0:int = (u * (image.bmpImage.width - 1));
var y0:int = (v * (image.bmpImage.height - 1));
return image.bmpImage.getPixel(x0, y0);
}
}
class RayTrace {
public var ray:Ray;
public var shade:Shade;
public var normalVector:Vector3D = new Vector3D();
public var min:Number;
public var max:Number;
public var index:int = 0;
public function RayTrace(r:Ray):void {
ray = r;
}
public function seach(c:Vector3D, x1:Number, y1:Number, z1:Number):Boolean {
min = 100;
for (var i:int = 0; i < ray.size(); i++) {
var ob:Object3d = ray.getObject3d(i);
switch(ob.op) {
case Object3d.SPHEHE:
if (intersectSphere(c, i, x1, y1, z1, 0)) return true;
case Object3d.RECTANGLE:
if (intesectRect(c, i, x1, y1, z1, 0)) return true;
}
}
return false;
}
public function intersectSphere(v:Vector3D, k:int, x1:Number, y1:Number, z1:Number, mode:int):Boolean {
var flag:Boolean=false;
var od:Object3d = ray.getObject3d(k);
var a:Number=(v.x*v.x)+(v.y*v.y)+(v.z*v.z);
var b:Number=(v.x*(x1-od.vert1.x))+(v.y*(y1-od.vert1.y))+(v.z*(z1-od.vert1.z));
var c:Number=od.vert1.x*od.vert1.x+od.vert1.y*od.vert1.y+od.vert1.z*od.vert1.z+x1*x1+y1*y1+z1*z1
-2 * (od.vert1.x * x1 + od.vert1.y * y1 + od.vert1.z * z1) - od.radius * od.radius;
var d:Number = b * b - a * c;
var t:Number = 0;
if (d>0){
t=(-b-Math.sqrt(d))/a;
if (t<0) if (a * c <= 0) t = ( -b + Math.sqrt(d)) / a;
}
if (d==0){t=-b/a;}
if (t>0) {
var x:Number = x1 + v.x * t;
var y:Number = y1 + v.y * t;
var z:Number = z1 + v.z * t;
d = Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y) +(z1 - z) * (z1 - z));
if ((min>d) && (mode==0)) {
min = d;
Ray.setVector(shade.interPoint, x, y, z);
Ray.setVector(normalVector, x - od.vert1.x, y - od.vert1.y, z - od.vert1.z);
if ( -v.x * normalVector.x - v.y * normalVector.y - v.z * normalVector.z < 0) {
Ray.setVector(normalVector, -normalVector.x, -normalVector.y, -normalVector.z);
}
index=k;
flag = true;
}
if ((max>d) && (mode>0))flag=true;
}
return flag;
}
public function intesectRect(v:Vector3D, k:int, xx:Number, yy:Number, zz:Number, mode:int):Boolean {
var flag:Boolean=false;
var od:Object3d = ray.getObject3d(k);
var a:Number = (od.vert2.y - od.vert1.y) * (od.vert4.z - od.vert1.z) - (od.vert2.z - od.vert1.z) * (od.vert4.y - od.vert1.y);
var b:Number = (od.vert2.z - od.vert1.z) * (od.vert4.x - od.vert1.x) - (od.vert2.x - od.vert1.x) * (od.vert4.z - od.vert1.z);
var c:Number = (od.vert2.x - od.vert1.x) * (od.vert4.y - od.vert1.y) - (od.vert2.y - od.vert1.y) * (od.vert4.x - od.vert1.x);
var d:Number = -(a * od.vert1.x + b * od.vert1.y + c * od.vert1.z);
var t1:Number = -(a * xx + b * yy + c * zz + d);
var t2:Number = a * v.x + b * v.y + c * v.z;
if ((t2 != 0) && ((t1 / t2) > 0)) {
var x:Number = xx + v.x * t1 / t2;
var y:Number = yy + v.y * t1 / t2;
var z:Number = zz + v.z * t1 / t2;
d = Math.sqrt((xx - x) * (xx - x) + (yy - y) * (yy - y) + (zz - z) * (zz - z));
var x1:Number = x - od.vert1.x;
var y1:Number = y - od.vert1.y;
var z1:Number = z - od.vert1.z;
var d1:Number=Math.sqrt(x1*x1+y1*y1+z1*z1);
x1=x1/d1;y1=y1/d1;z1=z1/d1;
var x2:Number = od.vert4.x - od.vert1.x;
var y2:Number = od.vert4.y - od.vert1.y;
var z2:Number = od.vert4.z - od.vert1.z;
d1=Math.sqrt(x2*x2+y2*y2+z2*z2);
x2=x2/d1;y2=y2/d1;z2=z2/d1;
var x3:Number = od.vert2.x - od.vert1.x;
var y3:Number = od.vert2.y - od.vert1.y;
var z3:Number = od.vert2.z - od.vert1.z;
d1 = Math.sqrt(x3 * x3 + y3 * y3 + z3 * z3);
x3 = x3 / d1; y3 = y3 / d1; z3 = z3 / d1;
var t:Number = x2 * x3 + y2 * y3 + z2 * z3;
t1 = x1 * x2 + y1 * y2 + z1 * z2;
t2 = x1 * x3 + y1 * y3 + z1 * z3;
if ((t1>t) && (t2>t)) {
x1 = x - od.vert3.x;
y1 = y - od.vert3.y;
z1 = z - od.vert3.z;
d1=Math.sqrt(x1*x1+y1*y1+z1*z1);
x1=x1/d1;y1=y1/d1;z1=z1/d1;
x2 = od.vert4.x - od.vert3.x;
y2 = od.vert4.y - od.vert3.y;
z2 = od.vert4.z - od.vert3.z;
d1 = Math.sqrt(x2 * x2 + y2 * y2 + z2 * z2);
x2 = x2 / d1; y2 = y2 / d1; z2 = z2 / d1;
x3 = od.vert2.x - od.vert3.x;
y3 = od.vert2.y - od.vert3.y;
z3 = od.vert2.z - od.vert3.z;
d1 = Math.sqrt(x3 * x3 + y3 * y3 + z3 * z3);
x3 = x3 / d1; y3 = y3 / d1; z3 = z3 / d1;
t = x2 * x3 + y2 * y3 + z2 * z3;
t1 = x1 * x2 + y1 * y2 + z1 * z2;
t2 = x1 * x3 + y1 * y3 + z1 * z3;
if ((min > d) && (t1 > t) && (t2 > t) && (mode == 0)) {
min = d;
Ray.setVector(shade.interPoint, x, y, z);
Ray.setVector(normalVector, a, b, c);
x=ray.me.x-x;
y=ray.me.y-y;
z=ray.me.z-z;
if (x * normalVector.x + y * normalVector.y + z * normalVector.z < 0) {
Ray.setVector(normalVector, -normalVector.x, -normalVector.y, -normalVector.z);
}
index=k;
flag=true;
}
if ((max>d)&&(t1>t)&&(t2>t)&&(mode>0))flag=true;
}
}
return flag;
}
}
class Shade {
public var nodes:Nodes;
public var light:Light;
public var ray:Ray;
public var checker:RayTrace;
public var map:Map;
private var lightV:Vector3D;
private var normalV:Vector3D;
private var sightV:Vector3D;
private var partV:Vector3D;
public var interPoint:Vector3D=new Vector3D();
private var lightElem:Vector3D = new Vector3D();
public function Shade(r:Ray, n:Nodes, c:RayTrace, m:Map):void {
ray = r;
nodes = n;
checker = c;
map = m;
light = ray.light;
}
private function setBModelVector(_x:Number,_y:Number,_z:Number,_index:int):void{
lightV = new Vector3D(light.position.x - _x, light.position.y - _y, light.position.z - _z);
lightV.normalize();
normalV = new Vector3D(nodes.normal[_index].x, nodes.normal[_index].y, nodes.normal[_index].z);
normalV.normalize();
sightV = new Vector3D( -nodes.sight[_index].x, -nodes.sight[_index].y, -nodes.sight[_index].z);
sightV.normalize();
partV = new Vector3D(lightV.x + sightV.x, lightV.y + sightV.y, lightV.z + sightV.z);
partV.normalize();
}
private function calcSpecularReflectionFactor(x:Number,y:Number,z:Number,r:int):void{
setBModelVector(x,y,z,r);
var pd:Number = lightV.dotProduct(normalV);
if (pd < 0) {
pd = 0;
}else if (pd > 1) {
pd = 1;
}
var od:Object3d = ray.getObject3d(nodes.index[r]);
var dd:Number = scatterCoefficient(od);
var dir:Number = normalV.dotProduct(sightV);
var ff:Number = absorption(od);
var gg:Number = roughly();
var correction:Number = correctionOfDistance(x, y, z);
var ps:Number = dd * gg * ff / dir;
if (ps < 0) {
ps = 0;
}else if (ps > 1) {
ps = 1;
}
Ray.setVector(lightElem, pd, ps, correction);
}
private function scatterCoefficient(od:Object3d):Number {
var t:Number = normalV.dotProduct(partV);
return (1.0 / (od.luster * od.luster * t * t * t * t)) * Math.exp( -(1.0 - t * t) / (od.luster * od.luster * t * t));
}
private function absorption(od:Object3d):Number {
var c:Number = sightV.dotProduct(partV);
var g:Number = Math.sqrt(od.refractiveIndex * od.refractiveIndex + c * c - 1);
var d1:Number=c+g;
var d2:Number=g-c;
return ((d2*d2)/(2*d1*d1))*(((c*d1-1)*(c*d1-1))/((c*d2+1)*(c*d2+1))+1);
}
private function roughly():Number {
var c:Number = sightV.dotProduct(partV);
var g:Number = normalV.dotProduct(partV);
var t1:Number = sightV.dotProduct(normalV);
var t2:Number = normalV.dotProduct(lightV);
var gr:Number=2*g*t1/c;
var gi:Number=2*g*t2/c;
return Math.min(1,Math.min(gr,gi));
}
private function correctionOfDistance(x:Number,y:Number,z:Number):Number {
var w:Number = new Vector3D(light.position.x - x, light.position.y - y, light.position.z - z).length;
return w / 4 + 0.1;
}
public function colorSet():uint {
colorSet2(0);
var col:Vector3D = getPixelColor();
var red:int = Math.min(Math.max(col.x, 0), 255);
var green:int = Math.min(Math.max(col.y, 0), 255);
var blue:int = Math.min(Math.max(col.z, 0), 255);
return (0xff000000 | red << 16 | green << 8 | blue);
}
private function colorSet2(p:int):void {
var r2:Number = 0
var g2:Number = 0;
var b2:Number = 0;
var d2:Number;
var od1:Object3d=ray.getObject3d(nodes.index[p]);
var vSight:Vector3D=new Vector3D();
var vNormal:Vector3D=new Vector3D();
var vReflection:Vector3D=new Vector3D();
if (od1.reflectivity * nodes.rate[p] > 0.3) {
vSight=new Vector3D(-nodes.sight[p].x,-nodes.sight[p].y,-nodes.sight[p].z);
vSight.normalize();
d2 = nodes.normal[p].length;
Ray.setVector(vNormal, nodes.normal[p].x / d2, nodes.normal[p].y / d2, nodes.normal[p].z / d2);
Ray.setVector(vReflection,
2 * vNormal.x * vSight.dotProduct(vNormal) - vSight.x,
2 * vNormal.y * vSight.dotProduct(vNormal) - vSight.y,
2 * vNormal.z * vSight.dotProduct(vNormal) - vSight.z);
vReflection.normalize();
if (checker.seach(vReflection,nodes.node[p].x+0.01*vReflection.x,nodes.node[p].y+0.01*vReflection.y,nodes.node[p].z+0.01*vReflection.z)) {
nodes.setData(checker.index,od1.reflectivity*nodes.rate[p],
interPoint.x,interPoint.y,interPoint.z, vReflection,checker.normalVector,nodes.n[p]);
}
}
var transmittance:Number = 1 - od1.reflectivity;//透過率
var vTrans:Vector3D = new Vector3D();
if (transmittance*nodes.rate[p]>0.3) {
var c1:Number;
var c2:Number;
var n:Number;
Ray.setVector(vSight, nodes.sight[p].x, nodes.sight[p].y, nodes.sight[p].z);
vSight.normalize();
d2 = nodes.normal[p].length;
Ray.setVector(vNormal,nodes.normal[p].x/d2,nodes.normal[p].y/d2,nodes.normal[p].z/d2);
if (nodes.n[p] % 2 == 0) {
n = 1 / od1.refractiveIndex;
} else {
n = od1.refractiveIndex;
}
c1=vSight.x*vNormal.x+vSight.y*vNormal.y+vSight.z*vNormal.z;
c2 = Math.sqrt(1 - ((1 - c1 * c1) * n * n));
Ray.setVector(vTrans,
vSight.x * n - (c2 - c1 * n) * vNormal.x,
vSight.y * n - (c2 - c1 * n) * vNormal.y,
vSight.z * n - (c2 - c1 * n) * vNormal.z);
vTrans.normalize();
if (checker.seach(vTrans,nodes.node[p].x+0.0001*vTrans.x,nodes.node[p].y+0.0001*vTrans.y,
nodes.node[p].z+0.0001*vTrans.z)) {
nodes.setData(checker.index,transmittance*nodes.rate[p],
interPoint.x,interPoint.y,interPoint.z,vTrans,
checker.normalVector,nodes.n[p]+1);
}
}
if (nodes.no > p + 1) colorSet2(p + 1);
}
private function getPixelColor():Vector3D {
var col:Vector3D = new Vector3D();
for (var j:int = 0; j < nodes.no; j++) {
var od3:Object3d = ray.list[nodes.index[j]];
var r2:Number = light.ambient * od3.color.x;
var g2:Number = light.ambient * od3.color.y;
var b2:Number = light.ambient * od3.color.z;
if (serchlight(nodes.node[j].x, nodes.node[j].y,nodes.node[j].z,j)) {
calcSpecularReflectionFactor(nodes.node[j].x, nodes.node[j].y, nodes.node[j].z, j);
r2 += (od3.color.x * light.brightness * od3.diffuseReflectance * lightElem.x
+light.color.x * light.brightness * od3.specularReflectionRate * lightElem.y) / lightElem.z;
g2 += (od3.color.y * light.brightness * od3.diffuseReflectance * lightElem.x
+light.color.y * light.brightness * od3.specularReflectionRate * lightElem.y) / lightElem.z;
b2 += (od3.color.z * light.brightness * od3.diffuseReflectance * lightElem.x
+light.color.z * light.brightness * od3.specularReflectionRate * lightElem.y) / lightElem.z;
}
if (od3.textureNum > 0) {
var pixelRGB:Vector3D = map.mapping(j, od3);
col.x +=nodes.rate[j]*(pixelRGB.x+r2);
col.y +=nodes.rate[j]*(pixelRGB.y+g2);
col.z +=nodes.rate[j]*(pixelRGB.z+b2);
}else {
col.x +=nodes.rate[j]*r2;
col.y +=nodes.rate[j]*g2;
col.z +=nodes.rate[j]*b2;
}
}
return col;
}
public function serchlight(x:Number, y:Number, z:Number, q:int):Boolean {
var kogenV:Vector3D = new Vector3D(light.position.x - x, light.position.y - y, light.position.z - z);
checker.max = kogenV.length;
kogenV.normalize();
checker.index=nodes.index[q];
for (var i:int=0;i<ray.size();i++) {
var od:Object3d = ray.list[i];
if (od.op==Object3d.SPHEHE) {
if (checker.intersectSphere(kogenV,i,x+kogenV.x/100.0,y+kogenV.y/100.0,z+kogenV.z/100.0,1))return false;
}
if (od.op==Object3d.RECTANGLE) {
if (checker.intesectRect(kogenV, i, x + kogenV.x / 100.0, y + kogenV.y / 100.0, z + kogenV.z / 100.0, 1)) return false;
}
}
return true;
}
}
class Button extends Sprite{
private static const mono:ColorMatrixFilter = new ColorMatrixFilter([
1 / 3, 1 / 3, 1 / 3, 0, 10, 1 / 3, 1 / 3, 1 / 3, 0, 10,
1 / 3, 1 / 3, 1 / 3, 0, 10, 0,0,0, 1, 0]);
private var _hover:Boolean = false;
public function get hover():Boolean{
return _hover;
}
public function set hover(value:Boolean):void{
if(_hover != value){
_hover = value;
filters = (_hover ? null : [mono]);
}
}
public function Button(W:Number, H:Number, R:Number, label:String = "", size:int = 11){
var matrix:Matrix = new Matrix();
matrix.createGradientBox(W, H, Math.PI / 2);
var bg:Sprite = new Sprite();
bg.graphics.beginGradientFill("linear", [0xDDE9F4, 0xD5E4F1, 0xBAD2E8], [1, 1, 1],[0, 120, 136], matrix);
bg.graphics.drawRoundRect(0, 0, W, H, R, R);
bg.graphics.endFill();
bg.filters = [new GlowFilter(0xFFFFBE, .5, 10, 10, 2, 1, true)];
addChild(bg);
var line:Sprite = new Sprite();
line.graphics.lineStyle(3, 0xBAD2E8);
line.graphics.drawRoundRect(0, 0, W, H, R, R);
addChild(line);
filters = [mono];
buttonMode = true;
mouseChildren = false;
if (label != ""){
var textField:TextField = new TextField();
textField.selectable = false;
textField.autoSize = "left";
textField.htmlText = <font size={size} color="#6B8399">{label}</font>.toXMLString();
textField.x = (W - textField.width) / 2;
textField.y = (H - textField.height) / 2;
addChild(textField);
}
addEventListener("rollOver", buttonRollOver);
addEventListener("rollOut", buttonRollOut);
addEventListener("removed", function(event:Event):void{
removeEventListener("rollOver", buttonRollOver);
removeEventListener("rollOut", buttonRollOut);
removeEventListener("removed", arguments.callee);
});
}
protected function buttonRollOver(event:Event):void{
hover = true;
}
protected function buttonRollOut(event:Event):void{
hover = false;
}
}