3Dお絵かき Ver0.3
2011-01-7
papervision3Dの習作として3Dのお絵かきツールを作ってみました。
次は奥行きも考慮して描けるのと、ピクセルではなく線で描けるようにしたいと思います。
2011-01-16
ピクセルからline3Dで描くように変更しました。
W,Sキーで3Dカーソルの奥行き方向の移動ができるようになりました。
----------------操作方法-----------------
青い点:3Dカーソル
マウス左クリック+マウス上下左右:点を描く
Shiftキー+マウス左右:カメラ回転
スペースキー:描いた絵を消す
Wキー:3Dカーソルを奥に移動
Sキー:3Dカーソルを手前に移動
-----------------------------------------
/**
* Copyright sasa ( http://wonderfl.net/user/sasa )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/yNek
*/
package {
import flash.events.*;
import flash.geom.*;
import flash.filters.*;
import flash.utils.*;
import flash.display.StageQuality;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.utils.*;
import org.papervision3d.core.effects.*;
import org.papervision3d.core.geom.*;
import org.papervision3d.core.geom.renderables.*;
import org.papervision3d.materials.*;
import org.papervision3d.materials.special.LineMaterial;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.view.layer.*;
import org.papervision3d.view.*;
[SWF(backgroundColor="0x000000")]
public class Main extends BasicView {
//------------------------------------
// プライベートメンバ変数
//------------------------------------
private var _writeMode:Boolean = false;
private var _dragMode:Boolean = false;
private var _rot:Number = 0;
private var _cursor:Sphere;
private var _cur3Dcursor:Number3D;
private var _old3Dcursor:Number3D;
private var _saveOld3Dcursor:Number3D;
private var _depth:Number = 0;
private var _distDepth:Number = 10;
private var _curpos:Point;
private var _oldpos:Point;
private var _lines3D:Lines3D;
private var _lm:LineMaterial;
private var _layer:BitmapEffectLayer;
//------------------------------------
// コンストラクタ
//------------------------------------
public function Main():void {
stage.quality = StageQuality.LOW;
//地面を作成
var plane:Plane = new Plane(new WireframeMaterial(0x333333), 2000, 2000, 14, 14);
plane.y = -stage.stageHeight/2;
plane.rotationX = 90;
scene.addChild(plane);
//3Dカーソルを作成
_cursor = new Sphere(new WireframeMaterial(0x0099FF), 4, 4, 4);
scene.addChild(_cursor);
//3Dカーソルの移動量を測るための、_old3Dcursor、_cur3Dcursorを作成
_cur3Dcursor = get3DcurPos();
_old3Dcursor = _cur3Dcursor;
//マウスカーソルの移動量を測るための、_curpos、_oldposを作成
//ビューの回転にしか使わない。
_curpos = new Point(mouseX, mouseY);
_oldpos = new Point();
_oldpos = _curpos;
//カメラの初期位置設定
_rot = mouseX / stage.stageWidth * 360;
camera.x = 1000 * Math.cos(_rot * Math.PI / 180);
camera.y = 200;
camera.z = 1000 * Math.sin(_rot * Math.PI / 180);
// ビットマップエフェクトレイヤーを作成
_layer = new BitmapEffectLayer(viewport, 640, 480);
viewport.containerSprite.addLayer(_layer);
// ブラーエフェクトを設定
_layer.addEffect(new BitmapLayerEffect(new BlurFilter(2, 2, 4), false));
//ラインマテリアルを作成
_lm = new LineMaterial(0xFF9900);
// レンダリング
startRendering();
// エンターフレームイベントの登録
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUPHandler);
stage.addEventListener(Event.ENTER_FRAME, loop);
}
//------------------------------------
// MouseDownの挙動
// _writeModeをtrueにし、line3Dを描けるよう準備する
//------------------------------------
private function mouseDownHandler(event:MouseEvent):void
{
_lines3D = new Lines3D();
scene.addChild(_lines3D);
_layer.addDisplayObject3D(_lines3D);
_writeMode = true;
}
//------------------------------------
// MouseUpの挙動
// _writeModeをfalseにし、line3Dを描かないようにする
//------------------------------------
private function mouseUpHandler(event:MouseEvent):void
{
_writeMode = false;
}
//------------------------------------
// KeyDownの挙動
// Shiftキーが押されたら
// 1.マウス位置と_depthを元に、3Dカーソルの位置を求める
// 2.現在のマウス位置を_oldposに保存する
// 3._dragModeをtrueにし、カメラを回転させる準備をする
// スペースキーが押されたら、line3Dをすべて消す
// Wキーが押されたら、_depth(今のカメラ位置を元にした奥行き)を減少させる。
// Sキーが押されたら、_depth(今のカメラ位置を元にした奥行き)を増加させる。
//------------------------------------
private function keyDownHandler(e:KeyboardEvent):void {
switch(e.keyCode)
{
case 16://SHIFTキー
_old3Dcursor = get3DcurPos();
_oldpos = new Point(mouseX, mouseY);
_dragMode = true;
break;
case 32://SPACEキー
_lines3D.removeAllLines();
break;
case 83://Sキー
_depth -= _distDepth;
break;
case 87://Wキー
_depth += _distDepth;
break;
}
}
//------------------------------------
// KeyUpの挙動
// Shiftキーが離されたら
// 1.現在の3dカーソル位置を_old3Dcursorに保存する
// 2._dragModeをtrueにし、カメラを回転させる準備をする
//------------------------------------
private function keyUPHandler(e:KeyboardEvent):void {
if(e.keyCode == 16)
{
_old3Dcursor = _cur3Dcursor;
_dragMode = false;
}
}
//------------------------------------
// EnterFrameの挙動
// 1.カーソルの位置更新
// 2.マウスダウンされていたら(= _writeModeがtrueなら)、3Dカーソルの位置にline3Dを描く
// 3.Shiftキーが押されていたら(= _dragModeがtrueなら)、マウスの位置から角度を計算しカメラを回転させる
//------------------------------------
private function loop(e:Event):void
{
//マウスカーソルの位置取得
_oldpos = _curpos;
_curpos = new Point(mouseX, mouseY);
//3Dカーソルの位置更新
_old3Dcursor = _cur3Dcursor;
_cur3Dcursor = get3DcurPos();
_cursor.x = _cur3Dcursor.x;
_cursor.y = _cur3Dcursor.y;
_cursor.z = _cur3Dcursor.z;
if(_writeMode)
{
//過去と現在の3Dカーソル位置の差から、line3Dを描く
var line3D:Line3D = new Line3D(_lines3D, _lm, 1,
new Vertex3D(_old3Dcursor.x, _old3Dcursor.y, _old3Dcursor.z),
new Vertex3D(_cur3Dcursor.x, _cur3Dcursor.y, _cur3Dcursor.z));
_lines3D.addLine(line3D);
}
else if(_dragMode)
{
//shiftキーが押させる前のマウス位置(_oldpos)と現在のマウス位置(_oldpos)の差分を回転量とし、現在の角度_rotに足す
_rot += (_oldpos.x - _curpos.x) / stage.stageWidth * 360;
camera.x = 1000 * Math.cos(_rot * Math.PI / 180);
camera.z = 1000 * Math.sin(_rot * Math.PI / 180);
}
}
private function get3DcurPos():Number3D
{
//3Dカーソルをカメラと垂直平面上で動かすため、まず3Dカーソルを(現在の角度+90)回転させ、
//またdepth値を元に3Dカーソルの奥行き位置を足して計算する
var tempX:Number = (mouseX - stage.stageWidth / 2) * 2 * Math.cos((_rot + 90) * Math.PI / 180)
+ _depth * Math.cos((_rot + 180) * Math.PI / 180);
var tempY:Number = -mouseY + stage.stageHeight/2;
var tempZ:Number = (mouseX - stage.stageWidth / 2) * 2 * Math.sin((_rot + 90) * Math.PI / 180)
+ _depth * Math.sin((_rot + 180) * Math.PI / 180);
return new Number3D(tempX, tempY, tempZ);
}
}
}