不完全照明
papervision3dのReflectionViewを発見した。
http://sebleedelisle.com/2008/07/real-reflections-in-papervision3d/
このサイトを見て、このCubeに照明をあてたらどうなるだろうと、好奇心からこのプログラムを作ってみました。
でも、結論から言って、このプログラム不完全(Z軸がおかしい)です。私のようなど素人がpapervision3d
を使用し、照明を移動させること自体が無謀だったのかも!
もし、こんどこのようなプログラムを作ろうと思った場合、 papervision3dの照明機能(存在不明)
を使用するか、いっそのことpapervision3dは使用しないかも(汗)
ちなみに、照明は、各面(Cube)の法線を求め、色を変化させて実現しています。
「ActionScript3.0 アニメーション Chapter17」に記載されているクラスを借用しています。
「つぶやき」
(PointLight3Dでは、明暗の色限定されちゃうのかな?)
(Cubeはscene.removeChildして再度scene.addChildが一番簡単な色を変更する処理
なのかな?)
(Cubeの各頂点は、z軸が手前プラスの左手座標になっているようみ見えるけど、私の勘違い?)
/**
* Copyright hankuro ( http://wonderfl.net/user/hankuro )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ej0q
*/
package {
import flash.events.Event;
import flash.display.*;
import flash.text.*;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.core.effects.view.ReflectionView;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.lights.PointLight3D;
[SWF (width = "540", height = "480", backgroundColor = "0x000000", frameRate = "30")]
/*
* papervision3dのReflectionViewを発見した。
* http://sebleedelisle.com/2008/07/real-reflections-in-papervision3d/
* このサイトを見て、このCubeに照明をあてたらどうなるだろうと、好奇心からこのプログラムを作ってみました。
* でも、結論から言って、このプログラム不完全(Z軸がおかしい)です。私のようなど素人がpapervision3d
* を使用し、照明を移動させること自体が無謀だったのかも!
* もし、こんどこのようなプログラムを作ろうと思った場合、 papervision3dの照明機能(存在不明)
* を使用するか、いっそのことpapervision3dは使用しないかも(汗)
* ちなみに、照明は、各面(Cube)の法線を求め、色を変化させて実現しています。
* 「ActionScript3.0 アニメーション Chapter17」に記載されているクラスを借用しています。
*
* 「つぶやき」
* (PointLight3Dでは、明暗の色限定されちゃうのかな?)
* (Cubeはscene.removeChildして再度scene.addChildが一番簡単な色を変更する処理
* なのかな?)
* (Cubeの各頂点は、z軸が手前プラスの左手座標になっているようみ見えるけど、私の勘違い?)
*/
public class Main extends ReflectionView
{
private var cube : Cube;
private var light:Light = new Light();
private var sphere:Sphere;
private var ml : MaterialsList;
private var save_point3D:Array = new Array(8);
private var point_const:Array = [[[5 , 7 , 1],[5 , 3 , 1]],
[[4 , 6 , 0],[4 , 2 , 0]],
[[3 , 1 , 0],[3 , 2 , 0]],
[[5 , 7 , 6],[5 , 4 , 6]],
[[1 , 7 , 6],[1 , 0 , 6]],
[[5 , 3 , 2],[5 , 4 , 2]]];
private var cube_const:Array = ["top" , "bottom" , "front" ,"back", "right" , "left"];
private var point3D:Array;
private var yaw:Number = 0;
public var s_x:Number = 0;
public var s_y:Number = 0;
public var s_z:Number = 0;
public var angle:Number = 0;
public var light_3D:PointLight3D;
public var slider_x:SimpleSlider = new SimpleSlider(200,-200,200);
public var slider_y:SimpleSlider = new SimpleSlider(0,150,0);
public var slider_z:SimpleSlider = new SimpleSlider(100,-100,100);
public var label:TextField = new TextField();
public var format:TextFormat = new TextFormat();
public var label2:TextField = new TextField();
public var format2:TextFormat = new TextFormat();
public function Main()
{
super(540,480,false, false);
slider_x.x = 48;
slider_x.y = 200;
slider_y.x = 80;
slider_y.y = 200;
slider_z.x = 112;
slider_z.y = 200;
label.text = "light position\nX Y Z";
format.color = 0xFFFFFF;
label.setTextFormat(format);
label.x = 50;
label.y = 170;
label2.x = 50;
label2.y = 300;
addChild(label);
addChild(label2);
addChild(slider_x);
addChild(slider_y);
addChild(slider_z);
//the height of the reflection plane
surfaceHeight = -50;
initCube();
camera.z = -400;
addEventListener(Event.ENTER_FRAME, enterFrame);
}
public function initCube() : void
{
// create a materials list for the cube.
ml = new MaterialsList();
ml.addMaterial(new ColorMaterial(0xFF0000), "all");
cube = new Cube(ml,100,100,100);
// add the cube to the scene
scene.addChild(cube);
sphere = new Sphere(new ColorMaterial(0xFFFF00), 15, 24, 24)
scene.addChild(sphere);
// light_3D = new PointLight3D(true);
// scene.addChild(light_3D);
}
public function enterFrame(e:Event) : void
{
scene.removeChild(cube);
cube = new Cube(ml,100,100,100);
scene.addChild(cube);
light.set_Light_point(slider_x.value*-1,slider_y.value,slider_z.value*-1);
sphere.x = slider_x.value;
sphere.y = slider_y.value;
sphere.z = slider_z.value;
// scene.removeChild(light_3D);
// light_3D = new PointLight3D(true);
// light_3D.x = slider_x.value;
// light_3D.y = slider_y.value;
// light_3D.z = slider_z.value;
// scene.addChild(light_3D);
label2.text = "x = "+String(int(slider_x.value))+"\ny = "+String(int(slider_y.value))+"\nz = "+String(int(slider_z.value));
format2.color = 0xFFFFFF;
label2.setTextFormat(format2);
yaw += (270-mouseX)*0.05;
cube.yaw(yaw);
// cube.y=(120-(mouseY/2));
cube.y=150;
point3D = new Array(cube.geometry.vertices.length);
for(var i:Number=0;i<point3D.length;i++){
point3D[i] = new Number3D(cube.geometry.vertices[i].x,cube.geometry.vertices[i].y,cube.geometry.vertices[i].z);
// trace("x "+cube.geometry.vertices[i].x+" y "+cube.geometry.vertices[i].y+" z "+cube.geometry.vertices[i].z);
Matrix3D.multiplyVector3x3(cube.transform, point3D[i]);
point3D[i].y += 150;
// trace("x "+point3D[i].x+" y "+point3D[i].y+" z "+point3D[i].z);
}
scene.removeChild(cube);
cube = new Cube( get_color(),100,100,100);
scene.addChild(cube);
cube.yaw(yaw);
// cube.y=(120-(mouseY/2));
cube.y=150;
if(cube.y<0) cube.y = 0;
singleRender();
}
public function get_color() : MaterialsList
{
var rtn:MaterialsList = new MaterialsList();
for(var i:Number=0;i<point_const.length;i++){
var color_save:Array = new Array(2);
for(var j:Number=0;j<point_const[i].length;j++){
color_save[j] = light.getAdjustedColor({
p0_x: point3D[point_const[i][j][0]].x , p0_y: point3D[point_const[i][j][0]].y , p0_z: point3D[point_const[i][j][0]].z ,
p1_x: point3D[point_const[i][j][1]].x , p1_y: point3D[point_const[i][j][1]].y , p1_z: point3D[point_const[i][j][1]].z ,
p2_x: point3D[point_const[i][j][2]].x , p2_y: point3D[point_const[i][j][2]].y , p2_z: point3D[point_const[i][j][2]].z}
,0xFF0000);
}
if(color_save[0]<color_save[1]){
rtn.addMaterial(new ColorMaterial(color_save[0]),cube_const[i]);
}else{
rtn.addMaterial(new ColorMaterial(color_save[1]),cube_const[i]);
}
}
return rtn;
}
}
}
class Light
{
public var x:Number;
public var y:Number;
public var z:Number;
private var _brightness:Number;
public var triangle_data:Object;
private var color:uint;
public function Light(x:Number = -100, y:Number = -100, z:Number = -100, brightness:Number = 1)
{
this.x = x;
this.y = y;
this.z = z;
this.brightness = brightness;
}
public function set_Light_point(x:Number , y:Number , z:Number):void{
this.x = x;
this.y = y;
this.z = z;
}
public function set brightness(b:Number):void
{
_brightness = Math.max(b, 0);
_brightness = Math.min(_brightness, 1);
}
public function get brightness():Number
{
return _brightness;
}
public function getAdjustedColor(p:Object,color:uint = 0xFF0000):uint
{
triangle_data = p;
this.color = color;
// for (var key:String in triangle_data)
// trace("triangle_data : "+key + ":" + triangle_data[key]);
// trace(x+" "+y+" "+z);
var red:Number = color >> 16;
var green:Number = color >> 8 & 0xff;
var blue:Number =color & 0xff;
var lightFactor:Number = getLightFactor();
// trace("lightFactor "+lightFactor);
red *= lightFactor;
green *= lightFactor;
blue *= lightFactor;
// var d:uint = red << 16 | green << 8 | blue;
// trace("color "+d.toString(16));
return red << 16 | green << 8 | blue;
}
private function getLightFactor():Number
{
var ab:Object = new Object();
ab.x = triangle_data.p0_x - triangle_data.p1_x;
ab.y = triangle_data.p0_y - triangle_data.p1_y;
ab.z = triangle_data.p0_z - triangle_data.p1_z;
var bc:Object = new Object();
bc.x = triangle_data.p1_x - triangle_data.p2_x;
bc.y = triangle_data.p1_y - triangle_data.p2_y;
bc.z = triangle_data.p1_z - triangle_data.p2_z;
var norm:Object = new Object();
norm.x = (ab.y * bc.z) - (ab.z * bc.y);
norm.y = -((ab.x * bc.z) - (ab.z * bc.x));
norm.z = (ab.x * bc.y) - (ab.y * bc.x);
// var key:String;
// for (key in ab)
// trace("ab : "+key + ":" + ab[key]);
// for (key in ab)
// trace("bc : "+key + ":" + bc[key]);
// for (key in norm)
// trace("norm : "+key + ":" + ab[key]);
var dotProd:Number = norm.x * x +
norm.y * y +
norm.z * z;
var normMag:Number = Math.sqrt(norm.x * norm.x +
norm.y * norm.y +
norm.z * norm.z);
var lightMag:Number = Math.sqrt(x * x +
y * y +
z * z);
return (Math.acos(dotProd / (normMag * lightMag)) / Math.PI)
* _brightness;
}
}
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.events.Event;
class SimpleSlider extends Sprite
{
private var _width:Number = 16;
private var _height:Number = 100;
private var _value:Number;
private var _max:Number = 100;
private var _min:Number = 0;
private var _handle:Sprite;
private var _back:Sprite;
private var _backWidth:Number = 4;
private var _handleHeight:Number = 6;
private var _backColor:uint = 0xcccccc;
private var _backBorderColor:uint = 0x999999;
private var _handleColor:uint = 0xeeeeee;
private var _handleBorderColor:uint = 0xcccccc;
private var _handleRadius:Number = 2;
private var _backRadius:Number = 2;
public function SimpleSlider(min:Number=0, max:Number=100, value:Number=100)
{
_min = min;
_max = max;
_value = Math.min(Math.max(value, min), max)
init();
}
private function init():void
{
_back = new Sprite();
addChild(_back);
_handle = new Sprite();
addChild(_handle);
_handle.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
draw();
updatePosition();
}
private function draw():void
{
drawBack();
drawHandle();
}
private function drawBack():void
{
_back.graphics.clear();
_back.graphics.beginFill(_backColor);
_back.graphics.lineStyle(0, _backBorderColor);
_back.graphics.drawRoundRect(0, 0, _backWidth, _height, _backRadius, _backRadius);
_back.graphics.endFill();
_back.x = _width / 2 - _backWidth / 2;
}
private function drawHandle():void
{
_handle.graphics.clear();
_handle.graphics.beginFill(_handleColor);
_handle.graphics.lineStyle(0, _handleBorderColor);
_handle.graphics.drawRoundRect(0, 0, _width, _handleHeight, _handleRadius, _handleRadius);
_handle.graphics.endFill();
}
private function updatePosition():void
{
var handleRange:Number = _height - _handleHeight;
var valueRange:Number = _max - _min;
_handle.y = handleRange - (_value - _min) / valueRange * handleRange;
}
private function updateValue():void
{
var handleRange:Number = _height - _handleHeight;
var valueRange:Number = _max - _min;
_value = (handleRange - _handle.y) / handleRange * valueRange + _min;
dispatchEvent(new Event(Event.CHANGE));
}
private function onMouseUp(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
_handle.stopDrag();
}
private function onMouseDown(event:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
_handle.startDrag(false, new Rectangle(0, 0, 0, _height - _handleHeight));
}
private function onMouseMove(event:MouseEvent):void
{
updateValue();
}
public function invalidate():void
{
draw();
}
public function move(x:Number, y:Number):void
{
this.x = x;
this.y = y;
}
public function setSize(w:Number, h:Number):void
{
_width = w;
_height = h;
draw();
}
public function set backBorderColor(n:uint):void
{
_backBorderColor = n;
draw();
}
public function get backBorderColor():uint
{
return _backBorderColor;
}
public function set backColor(n:uint):void
{
_backColor = n;
draw();
}
public function get backColor():uint
{
return _backColor;
}
public function set backRadius(n:Number):void
{
_backRadius = n;
}
public function get backRadius():Number
{
return _backRadius;
}
public function set backWidth(n:Number):void
{
_backWidth = n;
draw();
}
public function get backWidth():Number
{
return _backWidth;
}
public function set handleBorderColor(n:uint):void
{
_handleBorderColor = n;
draw();
}
public function get handleBorderColor():uint
{
return _handleBorderColor;
}
public function set handleColor(n:uint):void
{
_handleColor = n;
draw();
}
public function get handleColor():uint
{
return _handleColor;
}
public function set handleRadius(n:Number):void
{
_handleRadius = n;
draw();
}
public function get handleRadius():Number
{
return _handleRadius;
}
public function set handleHeight(n:Number):void
{
_handleHeight = n;
draw();
updatePosition();
}
public function get handleHeight():Number
{
return _handleHeight;
}
override public function set height(n:Number):void
{
_height = n;
draw();
}
override public function get height():Number
{
return _height;
}
public function set max(n:Number):void
{
_max = n;
updatePosition();
}
public function get max():Number
{
return _max;
}
public function set min(n:Number):void
{
_min = n;
updatePosition();
}
public function get min():Number
{
return _min;
}
public function set value(n:Number):void
{
_value = n;
_value = Math.min(_max, Math.max(_value, _min));
updatePosition();
}
public function get value():Number
{
return _value;
}
override public function set width(n:Number):void
{
_width = n;
draw();
}
override public function get width():Number
{
return _width;
}
}