forked from: Camera & Model rotation Test
forked from Camera & Model rotation Test (diff: 210)
forked from: Camera & Model rotation Test カメラとモデル回転に対する視点変更のテストコード 2010/08/22 Zier * 操作方法は onKeyDown() を見てください * * モデルの回転処理に関しては KoheiTAKAMIYA さんの * 『転がるサイコロver.1』 http://wonderfl.net/c/jhbr を * 参考にさせていただきました。ありがとうございます。 *
ActionScript3 source code
/**
* Copyright zier ( http://wonderfl.net/user/zier )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/63o7
*/
// forked from zier's Camera & Model rotation Test
/*
* カメラとモデル回転に対する視点変更のテストコード 2010/08/22 Zier
* 操作方法は onKeyDown() を見てください
*
* モデルの回転処理に関しては KoheiTAKAMIYA さんの
* 『転がるサイコロver.1』 http://wonderfl.net/c/jhbr を
* 参考にさせていただきました。ありがとうございます。
*
*/
package {
import com.bit101.components.Text;
import flash.display.Sprite;
import flash.events.Event
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.Number3D;
// Papervision3D
import org.papervision3d.view.BasicView
import org.papervision3d.lights.*
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.materials.shadematerials.*
import org.papervision3d.objects.primitives.*
// tweener
import caurina.transitions.*
[SWF(width="400", height="400", backgroundColor='0x4e616b', frameRate="60")]
public class Main extends BasicView {
private const DEGREE_TO_RADIAN: Number = Math.PI / 180
private var model: Cube = null
private var cubeDir: CubeDirection;
private var light:PointLight3D = new PointLight3D()
private var white: FlatShadeMaterial = new FlatShadeMaterial(light, 0xFFFFFF, 0xFFFFFF)
private var blue: FlatShadeMaterial = new FlatShadeMaterial(light, 0x0000FF, 0x0000FF)
private var green: FlatShadeMaterial = new FlatShadeMaterial(light, 0x00FF00, 0x00FF00)
private var red: FlatShadeMaterial = new FlatShadeMaterial(light, 0xFF0000, 0xFF0000)
private var yellow: FlatShadeMaterial = new FlatShadeMaterial(light, 0xFFFF00, 0xFFFF00)
private var orange: FlatShadeMaterial = new FlatShadeMaterial(light, 0xFF8000, 0xFF8000)
private var black: FlatShadeMaterial = new FlatShadeMaterial(light, 0x000000, 0x000000)
private function createCube(size: int): Cube {
var list: MaterialsList = new MaterialsList()
list.addMaterial(red, "front")
list.addMaterial(white, "top")
list.addMaterial(green, "right")
list.addMaterial(yellow, "left")
list.addMaterial(blue, "bottom")
list.addMaterial(orange, "back")
return new Cube(list, size, size, size, 1, 1, 1, 0, 0)
}
public function Main() {
var text: Text = new Text(this, 5, 5, "");
text.width = 80;
text.height = 20;
text.editable = false;
model = createCube(500)
scene.addChild(model)
cubeDir = new CubeDirection(model)
cubeDir.addEventListener(CubeDirection.CHANGE_FACE, function (): void { text.text = cubeDir.nearFaceName() } );
cubeDir.refresh()
startRendering()
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown)
tweenCamera(-1, +1);
}
private function tweenCamera(dx: int, dy: int): void {
const CAMERA_TIME: Number = 2.5
const CAMERA_TRANSITION: String = "easeOutElastic"
var _r: Number = (180 + dx * 25) * DEGREE_TO_RADIAN
var _x: Number = 1000 * Math.sin(_r)
var _y: Number = 400 * dy
var _z: Number = 1000 * Math.cos(_r)
Tweener.addTween(camera, { x: _x, y: _y, z: _z, time: CAMERA_TIME, transition: CAMERA_TRANSITION } );
}
private function onKeyDown(e: KeyboardEvent): void {
switch (e.keyCode) {
// cursor
case 37: break // left
case 38: break // up
case 39: break // right
case 40: break // down
case 32: break // Space
// camera control
case 81: tweenCamera(+1, +1); break // Q 左上から
case 69: tweenCamera(-1, +1); break // E 右上から
case 90: tweenCamera(+1, -1); break // Z 左下から
case 67: tweenCamera(-1, -1); break // C 右下から
// model control
case 82: cubeDir.reset(); break // R リセット
case 87: cubeDir.pitchBack(); break // W 上の面を手前に
case 65: cubeDir.yawLeft(); break // A 左の面を手前に
case 83: cubeDir.reverse(); break // S 前の面を手前に
case 68: cubeDir.yawRight(); break // D 右の面を手前に
case 88: cubeDir.pitchFore(); break // X 下の面を手前に
case 70: cubeDir.rollLeft(); break // F 上の面を右に
case 71: cubeDir.rollRight(); break // G 右の面を上に
}
}
}
}
import flash.events.Event
import flash.events.EventDispatcher;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.objects.primitives.Cube
import caurina.transitions.*
// 立方体の向き管理用クラス
class CubeDirection extends EventDispatcher {
public static const CHANGE_FACE: String = "changeFace";
private static const TOP: String = "TOP";
private static const FRONT: String = "FRONT";
private static const RIGHT: String = "RIGHT";
private static const BACK: String = "BACK";
private static const LEFT: String = "LEFT";
private static const BOTTOM: String = "BOTTOM";
private static const CUBE_TIME: Number = 1.0
private static const CUBE_TRANSITION: String = "easeOutBack"
private var _cube: Cube = null
private var _x: Number = 0
private var _y: Number = 0
private var _z: Number = 0
public function get x(): Number { return _x }
public function get y(): Number { return _y }
public function get z(): Number { return _z }
public function set x(value: Number): void { _x = value }
public function set y(value: Number): void { _y = value }
public function set z(value: Number): void { _z = value }
public function direction(): Number3D { return new Number3D( _x, _y, _z ); }
// _state は X, Y, Z 軸の + 方向を示す。初期値は X: right(green), Y: top(white), Z: front(red)
private var _state: Array = [RIGHT, TOP, FRONT];
private var prevLocal: Number3D = null;
private var resetFlag: Boolean = false
public function CubeDirection(cube: Cube, x: String = RIGHT, y: String = TOP, z: String = FRONT) {
_cube = cube
reset(x, y, z)
}
private function roll(c: uint, ... faces): void {
if (resetFlag) return
var shift: Array = [0, 0, 0];
// c は処理回数 : 通常1だが、半回転をサポートするために用意している。
while (0 < c--) {
var i: int = 0
for each (var state: String in _state) {
if (state == faces[0]) shift[i] -= 90;
else if (state == faces[1]) shift[i] += 90;
else if (state == faces[2]) _state[i] = faces[3]
else if (state == faces[3]) _state[i] = faces[4]
else if (state == faces[4]) _state[i] = faces[5]
else if (state == faces[5]) _state[i] = faces[2]
i++;
}
}
_x += shift[0]
_y += shift[1]
_z += shift[2]
// この補正が無いと軸の違う回転を行った場合にモデル自体が傾いてしまう
if (null != prevLocal) {
_cube.localRotationX = prevLocal.x
_cube.localRotationY = prevLocal.y
_cube.localRotationZ = prevLocal.z
}
Tweener.addTween(_cube, { localRotationX: _x, localRotationY: _y, localRotationZ: _z,
time: CUBE_TIME, transition: CUBE_TRANSITION, onComplete: onComplete } );
prevLocal = direction();
refresh()
}
public function reset(x: String = RIGHT, y: String = TOP, z: String = FRONT): void {
_x = _y = _z = 0
_state = [x, y, z]
Tweener.addTween(_cube, { localRotationX: 0, localRotationY: 0, localRotationZ: 0,
rotationX: 0, rotationY: 0, rotationZ: 0,
time: CUBE_TIME, transition: CUBE_TRANSITION, onComplete: onComplete} );
resetFlag = true
refresh()
}
// pitch control - X
public function pitchFore(): void { roll(1, RIGHT, LEFT, TOP, FRONT, BOTTOM, BACK) }
public function pitchBack(): void { roll(1, LEFT, RIGHT, TOP, BACK, BOTTOM, FRONT) }
// yaw control - Y
public function yawRight(): void { roll(1, TOP, BOTTOM, FRONT, RIGHT, BACK, LEFT) }
public function yawLeft(): void { roll(1, BOTTOM, TOP, FRONT, LEFT, BACK, RIGHT) }
// roll control - Z
public function rollRight(): void { roll(1, FRONT, BACK, TOP, LEFT, BOTTOM, RIGHT) }
public function rollLeft(): void { roll(1, BACK, FRONT, TOP, RIGHT, BOTTOM, LEFT) }
public function reverse(): void { roll(2, RIGHT, LEFT, TOP, FRONT, BOTTOM, BACK) }
public function refresh(): void { dispatchEvent(new Event(CHANGE_FACE)); }
private function onComplete(e: Event = null): void {
function adjust(value: Number): Number {
if ((value - 90) % 360 == 0) return 90
if ((value + 90) % 360 == 0) return -90
if ((value + 180) % 360 == 0) return 180
return 0
}
_x = _cube.localRotationX = adjust(_cube.localRotationX)
_y = _cube.localRotationY = adjust(_cube.localRotationY)
_z = _cube.localRotationZ = adjust(_cube.localRotationZ)
resetFlag = false
prevLocal = null
}
// 今どの面が手前にあるか?
public function nearFaceName(): String {
if (_state[0] == FRONT) return "Yellow"
if (_state[0] == BACK) return "Green"
if (_state[1] == FRONT) return "Blue"
if (_state[1] == BACK) return "White"
if (_state[2] == FRONT) return "Orange"
if (_state[2] == BACK) return "Red"
return "UNKNOWN";
}
}
