earthっぽいの [Alternativa3D 7.6 TIPS]
本家ロシア語フォーラムで、どうすればいいのみたいなのがあったので、作ったサンプル
earth Drag = Rotation the earth
cosmos Drag = Rotation the camera
earth CLICK = Put mark & Move the camera
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/lUDh
*/
// forked from narutohyper's Alternativa3D 7.5 Template
package
{
import alternativ7.engine3d.containers.ConflictContainer;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.MouseEvent3D;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.RayIntersectionData;
import alternativ7.engine3d.core.Sorting;
import alternativ7.engine3d.loaders.MaterialLoader;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.objects.Sprite3D;
import alternativ7.engine3d.primitives.GeoSphere;
import com.bit101.components.Label;
import com.bit101.components.Slider;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;
import flash.system.LoaderContext;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.events.TweenEvent;
import org.libspark.betweenas3.tweens.ITween;
/**
*
* Alternativa3D 7.6
*
* earthっぽいの
*
* ...
* @author narutohyper
*/
[SWF(backgroundColor="#000000", frameRate="60", width="800", height="600")]
public class Main extends Sprite
{
private const RADIAN:Number = Math.PI / 180;
private var cameraController:SimpleObjectController;
private var zoomController:SimpleObjectController;
private var objectController:SimpleObjectController;
private var earthContainer:Object3DContainer;
private var earth:GeoSphere;
private var camera:Camera3D;
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);
addChild(scene.camera.diagram);
//星パーティクル
var stars:Vector.<Sprite3D> = new Vector.<Sprite3D>(500, true);
var circle:Shape = new Shape();
circle.graphics.beginFill(0xFFFFFF);
circle.graphics.drawCircle(25, 25, 25);
var bmd:BitmapData = new BitmapData(50, 50, true, 0);
bmd.draw(circle);
var material:TextureMaterial = new TextureMaterial(bmd);
var angle:Number;
var length:Number;
for (var i:int = 0; i < 500; i++)
{
stars[i] = new Sprite3D(100, 100, material);
scene.container.addChild(stars[i]);
angle = Math.random() * 360 * RADIAN;
length = Math.random() * 100000 + 5000;
stars[i].x = Math.cos(angle) * length;
stars[i].y = Math.sin(angle) * length;
angle = Math.random() * 360 * RADIAN;
length = Math.random() * 100000 + 5000;
stars[i].z = Math.sin(angle) * length;
}
//地球
var earthMaterial:TextureMaterial = new TextureMaterial(null, false, true);
earthMaterial.diffuseMapURL = 'http://assets.wonderfl.net/images/related_images/e/e9/e987/e9876c502c9e9693205335e106de6baa8865c1a6';
var textures:Vector.<TextureMaterial> = new Vector.<TextureMaterial>();
textures[0] = earthMaterial;
var context:LoaderContext = new LoaderContext(true);
var materialLoader:MaterialLoader = new MaterialLoader();
materialLoader.load(textures,context);
earthContainer = new ConflictContainer();
earth = new GeoSphere(200, 8);
earth.sorting = Sorting.DYNAMIC_BSP;
earth.setMaterialToAllFaces(earthMaterial);
earthContainer.addChild(earth);
scene.container.addChild(earthContainer);
earth.x = 0;
earth.y = 0;
//cameraの制御を簡単にするために、cameraをObject3DContainerに格納
camera = scene.camera;
var cameraContainer:Object3DContainer = new Object3DContainer();
scene.container.addChild(cameraContainer);
scene.container.removeChild(camera);
cameraContainer.addChild(camera);
//カメラの調整
//カメラはControllerに関連付けている為、x,y,zで直接位置を指定できないので
//SimpleController.setObjectPosXYZを使用
zoomController = scene.cameraController;
zoomController.mouseSensitivity = 0;
zoomController.unbindAll();
zoomController.setObjectPosXYZ(0,-250,0);
zoomController.lookAtXYZ(0, 0, 0);
//cameraControllerの作成
//MouseDragで、cameraを回転させる為のController
cameraController = new SimpleObjectController(stage, cameraContainer, 100);
cameraController.mouseSensitivity = 0;
cameraController.unbindAll();
cameraController.setObjectPosXYZ(0,-300,0);
cameraController.lookAtXYZ(0, 0, 0);
earthContainer.addEventListener(MouseEvent3D.CLICK, onClick3D);
earthContainer.addEventListener(MouseEvent3D.MOUSE_DOWN, onMouseDown3D);
stage.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
makeSlider();
//描画開始
scene.onPreRender = function():void {
//objectController.update();
cameraController.updateObjectTransform()
cameraController.lookAtXYZ(0, 0, 0);
cameraController.update();
}
scene.startRendering();
}
private var startPos:Vector3D;
private var mouseSensitivity:Number = 0.5;
private var startMouseX:Number;
private var startMouseY:Number;
private var startRotationZ:Number;
private var startUV:Point;
private var startMatrix:Matrix3D;
private var _t:ITween;
/**
* cameraMove
*
*/
private function onClick3D(e:MouseEvent3D):void
{
var object:Object3D = e.target as Object3D;
var data:RayIntersectionData = object.intersectRay(e.localOrigin, e.localDirection);
if (data != null) {
var texture:BitmapData = (data.face.material as TextureMaterial).texture;
var uv:Point = data.face.getUV(data.point);
if (startUV) {
//var spot:Shape = new Shape();
//spot.graphics.beginFill(0xFF0000);
//spot.graphics.drawCircle(uv.x * texture.width, uv.y * texture.height,1);
//texture.draw(spot);
//CLICKされた位置に3Dobjectをおいてみる
var marker:Sprite3D = new Sprite3D(10,10, new FillMaterial(0xFF0000,0.5));
earthContainer.addChild(marker);
var matrix:Matrix3D = new Matrix3D();
var angle:Number;
var v:Vector3D;
matrix = new Matrix3D();
matrix.appendTranslation(210, 0, 0);
angle = (uv.y * 180 - 90);
matrix.appendRotation(angle, Vector3D.Y_AXIS);
angle = (uv.x * 360 - 180);
matrix.appendRotation(angle, Vector3D.Z_AXIS);
v = matrix.transformVector(new Vector3D())
marker.x = v.x;
marker.y = v.y;
marker.z = v.z;
matrix = new Matrix3D();
matrix.appendTranslation(220, 0, 0);
angle = (uv.y * 180 - 90);
matrix.appendRotation(angle, Vector3D.Y_AXIS);
angle = (uv.x * 360 - 180) + earthContainer.rotationZ*180/Math.PI;
matrix.appendRotation(angle, Vector3D.Z_AXIS);
v = matrix.transformVector(new Vector3D())
if (_t) _t.stop();
var tweenArr:Array = [];
tweenArr[0] = BetweenAS3.tween(cameraController.object, {x:v.x }, null, 1);
tweenArr[1] = BetweenAS3.tween(cameraController.object, {y:v.y }, null, 1);
tweenArr[2] = BetweenAS3.tween(cameraController.object, {z:v.z }, null, 1);
_t = BetweenAS3.parallelTweens(tweenArr);
_t.addEventListener(TweenEvent.COMPLETE, onComplete);
_t.play();
function onComplete(e:TweenEvent):void {
_t.removeEventListener(TweenEvent.COMPLETE, onComplete);
}
}
}
}
/**
* earthRotation
*
*/
private function onMouseUp3D(e:MouseEvent):void
{
mouseSensitivity=0.5;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove3D);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp3D);
}
private function onMouseDown3D(e:MouseEvent3D):void
{
mouseSensitivity = 0;
if (_t) _t.stop();
startMouseX = this.mouseX;
startMouseY = this.mouseY;
startRotationZ = earthContainer.rotationZ;
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove3D);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp3D);
var object:Object3D = e.target as Object3D;
var data:RayIntersectionData = object.intersectRay(e.localOrigin, e.localDirection);
if (data != null) {
startUV = data.face.getUV(data.point);
} else {
startUV = null;
}
}
private function onMouseMove3D(e:MouseEvent):void
{
earthContainer.rotationZ = startRotationZ + (startMouseX - this.mouseX) * RADIAN;
startUV = null;
}
/**
* cameraRotation
*
*/
private function onMouseUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseDown(e:MouseEvent):void
{
if (_t) _t.stop();
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
startMouseX = mouseX;
startMouseY = mouseY;
startPos = new Vector3D(cameraController.object.x, cameraController.object.y, cameraController.object.z);
}
private function onMouseMove(e:MouseEvent):void
{
if (mouseSensitivity) {
var mtr:Matrix3D = new Matrix3D();
mtr.appendRotation((mouseX - startMouseX)*mouseSensitivity, Vector3D.Z_AXIS);
mtr.appendRotation((mouseY - startMouseY)*mouseSensitivity, Vector3D.X_AXIS);
var pos:Vector3D = mtr.transformVector(startPos)
cameraController.object.x = pos.x;
cameraController.object.y = pos.y;
cameraController.object.z = pos.z;
}
}
/**
* zoomSlider
*
*/
private function makeSlider():void {
var base:Sprite = new Sprite();
addChild(base);
base.graphics.beginFill(0xCCCCCC);
base.graphics.drawRect(0, 0, 250, 40);
base.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
base.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
function onMouseOver(e:MouseEvent):void {
mouseSensitivity = 0;
}
function onMouseOut(e:MouseEvent):void {
mouseSensitivity = 0.5;
}
var labelYaw:Label = new Label(base, 20,10);
labelYaw.text = "CameraZoom";
var zoom:Slider = new Slider(Slider.HORIZONTAL, base, 100, 10, onSliderZoom);
zoom.value = 0;
var RADIAN:Number=Math.PI/180;
function onSliderZoom(e:Event):void {
var value:Number = (zoom.value / 100) * -3000 - 250;
zoomController.setObjectPosXYZ(0, value, 0);
}
}
}
}
/**
* BasicTemplate for Alternativa3D 7.5
* Alternativa3D 7.5を扱いやすくするためのテンプレートです
* @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.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();
}
}