/** レイトレーシング習作 参考文献: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; } } レイトレーシング