interactive [Alternativa3D 7.6 TIPS]
Object3DをMouseに反応させます。
やり方は、まずViewのinteractiveプロパティをtrue(デフォルト)にして、
Object3DにMouseEvent3D型イベントをaddEventListenerするだけ
簡単になりましたが・・・buttonModeが実装されていなかったorz
(プロパティ自体は用意されてるみたいですがw)
同時に、マテリアルの入れ替え等もやってます。
2011/01/12 7.5から7.6仕様に変更
/**
* Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ejFv
*/
// forked from narutohyper's Alternativa3D 7.5 Template
package
{
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.MouseEvent3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.loaders.MaterialLoader;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.objects.Mesh;
import alternativ7.engine3d.core.Face;
import flash.display.Sprite;
import flash.events.Event;
import flash.system.LoaderContext;
import flash.filters.*;
/**
* Alternativa3D 7.6
*
* interactive
*
* Mouseに反応するObject3Dの作成
*
* やり方は、まずViewのinteractiveプロパティをtrue(デフォルト)にして、
* Object3DにMouseEvent3D型イベントをaddEventListenerするだけ
*
* 簡単になりましたが・・・buttonModeが実装されていなかったorz
* (プロパティ自体は用意されてるみたいですがw)
*
*
* @author narutohyper
*/
[SWF(backgroundColor="#000000", frameRate="100", width="800", height="600")]
public class Main extends Sprite
{
private var dolphinMaterial:TextureMaterial;
private var tigerMaterial:TextureMaterial;
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
//AlternativaTemplate作成
var scene:AlternativaTemplate = new AlternativaTemplate(this);
//まとめてcontrolするために、core.Object3DContainerを作成し、各Objectを入れ子にする
var animeObject:Object3DContainer = new Object3DContainer;
scene.container.addChild(animeObject);
/*
* 一応、Viewに設定はできるが、未実装っぽい
* ちなみにObject3D(Mesh)は、プロパティ自体無い
scene.buttonMode = true
scene.useHandCursor = true;
scene.view.buttonMode = true;
scene.view.useHandCursor = true;
*/
//外部読み込み画像によるmaterial
dolphinMaterial = new TextureMaterial(null, false, true);
dolphinMaterial.diffuseMapURL = 'http://assets.wonderfl.net/images/related_images/e/e9/e987/e9876c502c9e9693205335e106de6baa8865c1a6m';
tigerMaterial = new TextureMaterial(null, false, true);
tigerMaterial.diffuseMapURL = 'http://assets.wonderfl.net/images/related_images/2/23/239d/239d90e633f3ab0f3e95d18c0fab3200d4a2820cm';
var textures:Vector.<TextureMaterial> = new Vector.<TextureMaterial>(2);
textures[0] = dolphinMaterial;
textures[1] = tigerMaterial;
var context:LoaderContext = new LoaderContext(true);
var materialLoader:MaterialLoader = new MaterialLoader();
materialLoader.load(textures,context);
//オリジナルプリミティブ、PolygonPlaneを使用して、様々な図形を作成
plates = new Vector.<PolygonPlane>();
for (var i:int = 0; i < 16; i++)
{
plates[i] = new PolygonPlane(100,36);
plates[i].setMaterialToAllFaces(dolphinMaterial);
plates[i].addEventListener(MouseEvent3D.MOUSE_DOWN, onMouseDown3D);
plates[i].addEventListener(MouseEvent3D.MOUSE_OVER, onMouseOver3D);
plates[i].addEventListener(MouseEvent3D.MOUSE_OUT, onMouseOut3D);
animeObject.addChild(plates[i]);
if (i) {
plates[i].x = (i % 4 * 250) - 375;
plates[i].y = Math.floor(i/4)*250-375;
} else {
plates[i].x = -375;
plates[i].y = -375;
}
}
//円
//カメラの調整
//カメラはControllerに関連付けている為、x,y,zで直接位置を指定できないので
//SimpleController.setObjectPosXYZを使用
scene.cameraController.setObjectPosXYZ(0, 800, 500);
scene.cameraController.lookAtXYZ(0, 0, 0);
//ObjectControllerの作成
//MouseDragで、Objectを回転させる為のController
//var objectController:SimpleObjectController = new SimpleObjectController(stage,animeObject,100)
//objectController.unbindAll()
scene.onPreRender = function():void {
//objectController.update();
}
//描画開始
scene.startRendering();
}
private function onMouseOut3D(e:MouseEvent3D):void
{
var mesh:Mesh = e.target as Mesh;
mesh.filters = null;
}
private function onMouseOver3D(e:MouseEvent3D):void
{
var mesh:Mesh = e.target as Mesh;
if (Face(mesh.faces[0]).material == dolphinMaterial) {
mesh.filters = [new GlowFilter(0x0000FF, 1, 20, 20, 4)];
} else {
mesh.filters = [new GlowFilter(0xFFFF00, 1, 20, 20, 4)];
}
}
private var plates:Vector.<PolygonPlane>;
private var counter:uint =0;
private function onMouseDown3D(e:MouseEvent3D):void
{
var mesh:Mesh = e.target as Mesh;
if (Face(mesh.faces[0]).material == dolphinMaterial) {
mesh.setMaterialToAllFaces(tigerMaterial);
} else {
mesh.setMaterialToAllFaces(dolphinMaterial);
}
onMouseOver3D(e);
}
}
}
import alternativ7.engine3d.objects.Mesh;
import alternativ7.engine3d.materials.Material;
import alternativ7.engine3d.core.Vertex;
/**
* ...
* @author narutohyper
*/
class PolygonPlane extends Mesh
{
public function PolygonPlane(radius:Number = 100, vertexNum:Number = 3, startVertexAngle:Number=-90 , star:Boolean = false, twoFace:Boolean = true, reverse:Boolean = false, frontMaterial:Material = null, backMaterial:Material = null)
{
var vertex:Vector.<Vertex> = new Vector.<Vertex>(vertexNum);
var RADIAN:Number = Math.PI / 180;
var sr:Number = startVertexAngle;
var pitch:Number = 360/vertexNum;
var angle:Number;
var i:uint;
var length:Number = radius;
var tw:Number = Math.cos(0 * RADIAN) * length * 2;
var th:Number = Math.sin(90 * RADIAN) * length * 2;
var tx:Number;
var ty:Number;
var tu:Number;
var tv:Number;
var v:Vertex;
for (i = 0; i < vertexNum; i++) {
angle = (sr + (pitch * i)) * RADIAN;
if (star) {
if (i && i % 2) {
tx = Math.cos(angle) * length;
ty = Math.sin(angle) * length;
} else {
tx = Math.cos(angle) * length/2;
ty = Math.sin(angle) * length/2;
}
} else {
tx = Math.cos(angle) * length;
ty = Math.sin(angle) * length;
}
tu = (tx + tw / 2) / tw;
tv = (ty + th / 2) / th;
vertex[i] = addVertex(tx, ty, 0, tu, tv, 'v'+i);
}
if (!reverse) {
addFace(vertex,frontMaterial, 'faceFront');
if (twoFace) {
vertex.reverse();
v = vertex.shift()
vertex.push(v);
addFace(vertex,backMaterial, 'faceBack');
}
} else {
if (twoFace) {
addFace(vertex,frontMaterial, 'faceFront');
}
vertex.reverse();
v = vertex.shift()
vertex.push(v);
addFace(vertex,backMaterial, 'faceBack');
}
calculateNormals();
x = 0;
y = 0;
}
}
/**
* BasicTemplate for Alternativa3D 7.6
* Alternativa3D 7.6を扱いやすくするためのテンプレートです
* @author narutohyper & clockmaker
*
*/
import alternativ7.engine3d.containers.BSPContainer;
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.containers.DistanceSortContainer;
import alternativ7.engine3d.containers.KDContainer;
import alternativ7.engine3d.containers.LODContainer;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.View;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
class AlternativaTemplate extends Sprite
{
/**
* 子オブジェクトを最適な方法でソートするコンテナ
* (ConflictContainer)
*/
public static const CONFLICT:String = 'conflict';
/**
* 子オブジェクトをBSP(バイナリ空間分割法)によってソートするコンテナ
* (BSPContainer)
*/
public static const BSP:String = 'bsp';
/**
* 子オブジェクトをカメラからのZ値でソートするコンテナ
* (DistanceSortContainer)
*/
public static const ZSORT:String = 'zsort';
/**
* KDツリー(http://ja.wikipedia.org/wiki/Kd%E6%9C%A8)によってソートするコンテナ
* (KDContainer)
*/
public static const KD:String = 'kd';
/**
* detalizationと子オブジェクトの距離でソートするコンテナ(詳細は調査中)
* (LODContainer)
*/
public static const LOD:String = 'lod';
/**
* 3dオブジェクト格納するコンテナインスタンス。
*/
public var container:Object3DContainer;
/**
* ビューインスタンスです。
*/
public var view:View;
/**
* カメラインスタンスです。
*/
public var camera:Camera3D;
/**
* カメラコントローラーです。
*/
public var cameraController:SimpleObjectController;
private var _mc:DisplayObjectContainer;
private var _viewWidth:int;
private var _viewHeight:int;
private var _scaleToStage:Boolean;
private var _containerType:String;
/**
* 新しい Alternativa3DTemplate インスタンスを作成します。
* @param mc
* @param containerType
* @param viewWidth
* @param viewHeight
* @param scaleToStage
*/
public function AlternativaTemplate(mc:DisplayObjectContainer,containerType:String=CONFLICT,viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true)
{
_mc = mc;
_mc.addChild(this);
_containerType = containerType;
_viewWidth = viewWidth;
_viewHeight = viewHeight;
_scaleToStage = scaleToStage;
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理をオーバーライドして記述します。
*/
protected function atInit():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
protected function atPreRender():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング前に実行したい処理をオーバーライドして記述します。
*/
private var _onPreRender:Function = function():void{};
public function get onPreRender():Function { return _onPreRender; }
public function set onPreRender(value:Function):void
{
_onPreRender = value;
}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理をオーバーライドして記述します。
*/
protected function atPostRender():void {}
/**
* Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理を記述します。
*/
private var _onPostRender:Function = function():void{};
public function get onPostRender():Function { return _onPostRender; }
public function set onPostRender(value:Function):void
{
_onPostRender = value;
}
/**
* レンダリングを開始します。
*/
public function startRendering():void
{
addEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* レンダリングを停止します。
*/
public function stopRendering():void
{
removeEventListener(Event.ENTER_FRAME, onRenderTick);
}
/**
* シングルレンダリング(レンダリングを一回だけ)を実行します。
*/
public function singleRender():void
{
onRenderTick();
}
/**
* @private
*/
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
//Root objectの作成
if (_containerType == CONFLICT) {
container = new ConflictContainer();
} else if (_containerType == BSP) {
container = new BSPContainer();
} else if (_containerType == ZSORT) {
container = new DistanceSortContainer();
} else if (_containerType == KD) {
container = new KDContainer();
} else if (_containerType == LOD) {
container = new LODContainer();
}
//Viewの作成
view = new View(stage.stageWidth, stage.stageHeight);
_mc.addChild(view);
//cameraの作成
camera = new Camera3D();
camera.view = view;
camera.x = 0;
camera.y = -500;
camera.z = 0;
container.addChild(camera);
// Camera controller
cameraController = new SimpleObjectController(stage, camera, 10);
cameraController.mouseSensitivity = 0;
cameraController.unbindAll();
cameraController.lookAtXYZ(0, 0, 0);
onResize();
stage.addEventListener(Event.RESIZE, onResize);
atInit();
}
/**
* @private
*/
private function onResize(e:Event = null):void
{
if (_scaleToStage)
{
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}
else
{
view.width = _viewWidth;
view.height = _viewHeight;
}
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void
{
atPreRender();
_onPreRender();
cameraController.update();
camera.render();
atPostRender();
_onPostRender();
}
}