forked from: Alternativa3D discipline
@OKASUKE
*2010/02/26
* Alternativa3D discipline(Alternativa3Dの鍛錬)
* たまに小Boxがくっつきます。。。そのうち分裂・・・
* 小Box数を多くするとPlaneにちかちか線がはしる。。。なして?
*
* ↑説明すると長くなるので、詳しくは割愛しますが、
* alternativa3DのWireMaterialはBSPツリーの階層に基ずくポリゴン分割の視覚化を目的とした
* デバッグの為の機能と位置づけられています。なので、ちかちか走るのは「仕様」だそうです。
* とりあえずObject3Dのmobility(BSPの階層Lv)を指定する事で、分割線を(ある程度)制御できます。
*
* boxがくっつくのは、Object3D同士が2度続けて当たらないようにする事で、ある程度は解消できます。
*
* @narutohyper
/**
* Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/96de
*/
// forked from OKASUKE's Alternativa3D discipline
/*@OKASUKE
*2010/02/26
* Alternativa3D discipline(Alternativa3Dの鍛錬)
* たまに小Boxがくっつきます。。。そのうち分裂・・・
* 小Box数を多くするとPlaneにちかちか線がはしる。。。なして?
*
* ↑説明すると長くなるので、詳しくは割愛しますが、
* alternativa3DのWireMaterialはBSPツリーの階層に基ずくポリゴン分割の視覚化を目的とした
* デバッグの為の機能と位置づけられています。なので、ちかちか走るのは「仕様」だそうです。
* とりあえずObject3Dのmobility(BSPの階層Lv)を指定する事で、分割線を(ある程度)制御できます。
*
* boxがくっつくのは、Object3D同士が2度続けて当たらないようにする事で、ある程度は解消できます。
*
* @narutohyper
*/
package {
import alternativ5.engine3d.materials.FillMaterial;
import alternativ5.engine3d.primitives.Box;
import alternativ5.engine3d.events.MouseEvent3D
import alternativ5.types.Point3D;
import alternativ5.engine3d.primitives.Plane;
import alternativ5.engine3d.materials.WireMaterial;
import alternativ5.engine3d.core.Object3D;
import alternativ5.utils.FPS
import flash.display.Sprite;
import flash.display.BlendMode;
import flash.display.DisplayObject;
[SWF(width = 465, height = 465, frameRate = 30, backgroundColor=0x00000000)]
public class Main extends Sprite {
public static const COUNTBOX:Number = 60; //小Box数
private var _materialList:Vector.<FillMaterial> = new Vector.<FillMaterial>;
private var _boxList:Vector.<Ball> = new Vector.<Ball>;
public function Main():void {
FPS.init(stage);
var template:BasicTemplate = new BasicTemplate();
addChild(template);
var box:Box = new Box(500,500,500,10,10,10,true)
box.mobility=0;
box.name="outerWall";
box.cloneMaterialToAllSurfaces(new WireMaterial(1, 0xFF00FFFF));
template.scene.root.addChild(box);
for (var i:uint = 0; i < COUNTBOX; i++) {
_materialList[i] = new FillMaterial(Math.random() * 0xFFFFFF, 1,BlendMode.NORMAL,-1,0x000000);
_boxList[i] = new Ball(template.scene, 30, 30, 30, _materialList[i]);
//_boxList[i].cloneMaterialToAllSurfaces(_materialList[i]);
template.scene.root.addChild(_boxList[i]);
}
template.onPreRender = function():void {
var rateZ:Number;
var rateX:Number;
rateZ = (mouseY - stage.stageHeight/2)/2;
rateX = (mouseX - stage.stageWidth/ 2)/ 2;
for (var i:int = 0; i <= _boxList.length - 1; i++) {
_boxList[i].doAction();
}
//trace(template.camera.y)
if (template.camera.y >= 640) {
template.camera.z += ( rateZ - template.camera.z) * 0.02;
template.camera.y += ( rateX - template.camera.x) * 0.02;
} else {
if (template.camera.y <= -640 ) {
template.camera.z += ( rateZ - template.camera.z) * 0.01;
template.camera.y += ( rateX - template.camera.x) * 0.01;
} else {
template.camera.z += ( rateZ - template.camera.z) * 0.1;
template.camera.y += ( rateX - template.camera.x) * 0.1;
}
}
template.cameraContoller.lookAt(new Point3D());
}
}
}
}
import alternativ5.engine3d.core.Mesh;
import alternativ5.engine3d.core.Surface;
import alternativ5.engine3d.primitives.Box;
import alternativ5.types.Set;
import alternativ5.engine3d.physics.Collision;
import alternativ5.engine3d.physics.EllipsoidCollider;
import alternativ5.types.Point3D;
import alternativ5.engine3d.materials.TextureMaterial;
import alternativ5.engine3d.materials.SurfaceMaterial;
import alternativ5.engine3d.materials.FillMaterial;
import alternativ5.types.Texture;
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.display.GradientType;
import flash.geom.Matrix;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
//Ballクラスはnarutohyperさんのを参考
//ここらへんかな、
//http://marubayashi.net/tips/alternativa3d/step2/a2-3/index.html
class Ball extends Box {
private var collider:EllipsoidCollider;
private var collision:Collision;
private var nowPoint:Point3D; //現在の位置
private var newPoint:Point3D; //移動位置
private var speed:Point3D; //スピード
private var deceleration:Number; //跳ね
private var acceleration:Point3D; //加速
private var tempPoint:Point3D;
private var _firstmaterial:FillMaterial;
private var tempBall:Mesh
public function Ball(scene:Scene3D,w:Number,h:Number,l:Number,mate:FillMaterial) {
super(w,h,l);
mobility=1;
tempPoint= new Point3D();
nowPoint = new Point3D();
newPoint = new Point3D();
//等速運動なので、speedの値が固定
speed=new Point3D(Math.random()*10-5,Math.random()*10+0.5,Math.random()*10+0.5); //スピード
//加速・減速は重力計算で使用するので使わない
//deceleration=0.6; //減速
//acceleration=new Point3D(Math.random()-0.5,Math.random()+0.5,Math.random()+0.5); //加速
collider = new EllipsoidCollider (scene,w,h,l);
collision = new Collision();
collider.collisionSet = new Set()
collider.collisionSet.add(this);
nowPoint = new Point3D (Math.random() * 460 - 230,Math.random() * 460 - 230,Math.random() * 460 - 230);
this.coords = nowPoint;
_firstmaterial = mate;
changeMaterial();
}
public function doAction():void {
//speed.add(acceleration); //加速減速は、重力関係ないので必要なし
if (collider.getCollision (nowPoint, speed, collision)) {
//壁で方向転換、同じ球には続けて当たらないように処理
if (tempBall!=collision.face.mesh || collision.face.mesh.name=="outerWall") {
tempBall=collision.face.mesh
//speed.multiply(deceleration); //加速減速は、重力関係ないので必要なし
//当たった面の法線を使い、内積で方向を反転させる
tempPoint=collision.normal
tempPoint.multiply(2 * Point3D.dot(tempPoint, speed));
speed.subtract(tempPoint);
this.cloneMaterialToAllSurfaces(_textureMaterialArray[0]);
} else {
collider.calculateDestination(nowPoint, speed , newPoint);
this.cloneMaterialToAllSurfaces(_firstmaterial);
}
}else {
collider.calculateDestination(nowPoint, speed , newPoint);
this.cloneMaterialToAllSurfaces(_firstmaterial);
}
nowPoint.copy(newPoint);
this.coords = nowPoint;
this.rotationX += 1;
this.rotationY += 1;
this.rotationZ += 1;
}
private var _textureMaterialArray:Array = [];
private function changeMaterial():void {
_textureMaterialArray.push(new FillMaterial(0xFFFFFF));
}
}
import alternativ5.engine3d.controllers.CameraController;
import alternativ5.engine3d.core.Camera3D;
import alternativ5.engine3d.core.Object3D;
import alternativ5.engine3d.core.Scene3D;
import alternativ5.engine3d.display.View;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
/**
* BasicTemplate for Alternativa3D
* Alternativa3Dを扱いやすくするためのテンプレートです
* @author Yasu
*/
class BasicTemplate extends Sprite{
/**
* シーンインスタンスです。
*/
public var scene:Scene3D;
/**
* ビューインスタンスです。
*/
public var view:View;
/**
* カメラインスタンスです。
*/
public var camera:Camera3D;
/**
* カメラコントローラーです。
*/
public var cameraContoller:CameraController;
private var _viewWidth:int;
private var _viewHeight:int;
private var _scaleToStage:Boolean;
/**
* 新しい BasicTemplate インスタンスを作成します。
* @param viewWidth
* @param viewHeight
* @param scaleToStage
*/
public function BasicTemplate(viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true) {
_viewWidth = viewWidth;
_viewHeight = viewHeight;
_scaleToStage = scaleToStage;
// Creating scene
scene = new Scene3D();
scene.splitAnalysis = false; // not analysis for performance
scene.root = new Object3D();
// Adding camera
camera = new Camera3D();
camera.y = -500;
scene.root.addChild(camera);
// camera contoller
cameraContoller = new CameraController(this);
cameraContoller.camera = camera;
// set view
view = new View();
view.camera = camera;
addChild(view);
// stage
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理をオーバーライドして記述します。
*/
protected function atInit():void {}
/**
* 初期化されたときに実行されるイベントです。
* 初期化時に実行したい処理を記述します。
*/
private var _onInit:Function = function():void { };
public function get onInit():Function { return _onInit; }
public function set onInit(value:Function):void {
_onInit = value;
}
/**
* 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 時に実行されるレンダリングのイベントです。
* レンダリング後に実行したい処理を記述します。
*/
protected 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 {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.HIGH;
// resize
stage.addEventListener(Event.RESIZE, onResize);
onResize(null);
// render
startRendering();
atInit();
_onInit();
}
/**
* @private
*/
private function onRenderTick(e:Event = null):void {
atPostRender();
_onPostRender();
scene.calculate();
atPreRender();
_onPreRender();
}
/**
* @private
*/
private function onResize(event:Event = null):void {
if (_scaleToStage) {
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}else {
view.width = _viewWidth;
view.height = _viewHeight;
}
}
}