In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

TransparentBox [Alternativa3D 7.6 TIPS]

透明なBOXを表現したいとき、
ただ、Boxに使うFillMaterialのalphaを設定しても、意図した半透明な箱を作る事はできません。

以下のサンプルの様な、半透明な箱を作るには、
1.BoxのFaceの両面が必要
(現VerのBoxでは、reverse(反転)は出来るがTwoSide(両面)は無いので、normalBoxと、reverseしたinnerBoxの2つを重ねて使用)
2.各面の陰影が必要なので、OriginalのFlatShadingを使用しています。

なお、http://wonderfl.net/c/485bで作成したFlatShadingBoxはTextureMaterialを使用していたので、今回FillMaterialはFillMaterialとして、alphaが利く様に改造しています。

2011/01/12 7.5から7.6仕様に変更
Get Adobe Flash player
by narutohyper 23 Oct 2012
/**
 * Copyright narutohyper ( http://wonderfl.net/user/narutohyper )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6qQ3
 */

// forked from narutohyper's Alternativa3D 7.5 Template
package
{

    import alternativ7.engine3d.controllers.SimpleObjectController;
    import alternativ7.engine3d.core.Object3DContainer;
    import alternativ7.engine3d.loaders.MaterialLoader;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.materials.TextureMaterial;
    import alternativ7.engine3d.primitives.Box;
    import alternativ7.engine3d.primitives.GeoSphere;
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    /**
     *
     * Alternativa3D 7.5
     *
     * テンプレート
     *
     * ...
     * @author narutohyper
     */
    [SWF(backgroundColor="#000000", frameRate="60", width="800", height="600")]
    public class Main extends Sprite
    {
        
        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);
        
            //テスト表示
            var bm:Bitmap=new Bitmap();
            //Materialの作成
            addChild(bm);
            
            //AlternativaTemplate作成
            var scene:AlternativaTemplate = new AlternativaTemplate(this);
            addChild(scene.camera.diagram);


            

            
            //回転させる為のContainer
            var objectContainer:Object3DContainer = new Object3DContainer();
            scene.container.addChild(objectContainer);

            
            //色つき球
            
            //6面ぬり分けた箱
            var material:FillMaterial = new FillMaterial(0x6666FF,0.8);
            var box:FlatShadingBox = new FlatShadingBox(new Box(500,500,500,1,1,1,false,false));
            box.setMaterialToAllFaces(material);
            objectContainer.addChild(box);
            box.x = 0;
            box.y = 0;
    
            //var material:FillMaterial = new FillMaterial(0x0000FF,0.5);
            var innerBox:FlatShadingBox = new FlatShadingBox(new Box(500,500,500,1,1,1,true,false));
            innerBox.setMaterialToAllFaces(material);
            objectContainer.addChild(innerBox);
            innerBox.x = 0;
            innerBox.y = 0;
            
            
            var RADIAN:Number = Math.PI / 180;
            
            var lightContainer:Object3DContainer = new Object3DContainer();
            scene.container.addChild(lightContainer);
            var light:Light = new Light(0xFFFFFF,0.8);
            lightContainer.addChild(light);
            lightContainer.rotationY = 30 * RADIAN;
            light.x = 400;
            
            //カメラの調整
            //カメラはControllerに関連付けている為、x,y,zで直接位置を指定できないので
            //SimpleController.setObjectPosXYZを使用
            scene.cameraController.setObjectPosXYZ(0,-1000,0);
            scene.cameraController.lookAtXYZ(0, 0, 0);
            //ObjectControllerの作成
            //MouseDragで、Objectを回転させる為のController
            var objectController:SimpleObjectController = new SimpleObjectController(stage,objectContainer,100);
            objectController.unbindAll();
            
            //描画開始

            var angle:Number=0;
            scene.onPreRender = function():void {
                objectController.update();
                angle+=1;
                light.x = Math.cos(angle * RADIAN) * 700;
                light.y = Math.sin(angle * RADIAN) * 700;
                //引数の2番目には、回転するObject3D
                box.calculateLight(light,[objectContainer]);
                innerBox.calculateLight(light,[objectContainer]);
                //bm.bitmapData = sphere2.bmd;
            }
            scene.startRendering();

            

        }
        
        
        

    }
    
}


import alternativ7.engine3d.core.Face;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.materials.Material;
import alternativ7.engine3d.materials.TextureMaterial;
import alternativ7.engine3d.objects.Mesh;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Shape;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;
/**
 * BoxオブジェクトをFlatShadingする、Meshに変更するクラス
 *
 * サーフェースの概念がなくなったので、ちょっと面倒・・・
 *
 * @author narutohyper
 */
class FlatShadingBox extends Mesh
{
    private var _materialTypes:Vector.<String> = new Vector.<String>(6, true);;
    private var _materials:Vector.<Material> = new Vector.<Material>(6, true);
    private var _tempMaterials:Vector.<Material> = new Vector.<Material>(6, true);
    private var _textures:Vector.<BitmapData> = new Vector.<BitmapData>(6, true);
    private var _bmds:Vector.<BitmapData> = new Vector.<BitmapData>(6, true);
    private var _normals:Vector.<Number> = new Vector.<Number>();
    private var _bmd:BitmapData;
    private var _loadeds:Vector.<Boolean> = new Vector.<Boolean>(6, true);
    private var _fills:Shape = new Shape();
    private var _sp:Point;
    
    public function FlatShadingBox(mesh:Mesh)
    {
        var face:Face;
        var item:*;
        //引数のMeshのgeometryをコピー
        //takeGeometryFrom(mesh.geometry);
        clonePropertiesFrom(mesh);


        //left左
        _normals.push(1, 0, 0);
        //right右
        _normals.push( -1, 0, 0);
        //back奥
        _normals.push(0, 1, 0);
        //front前
        _normals.push(0, -1, 0);
        //top上
        _normals.push(0, 0, 1);
        //bottom下
        _normals.push(0, 0, -1);

        //textureの取り込み

        var i:uint;
        var normal:Vector3D;
        for (item in faces) {
            face = faces[item];
            for (i = 0; i < 6; i++)
            {
                normal = new Vector3D(_normals[i * 3], _normals[i * 3 + 1], _normals[i * 3 + 2]);
                if (face.normal.x == normal.x && face.normal.y == normal.y && face.normal.z == normal.z) {
                    //この時点でTextureが設定されていたら、差し替え
                    if (!_textures[i] && face.material) {
                        setTexture(i, face.material);
                    }
                }
            }
        }

        var RADIAN:Number = Math.PI / 180;
    
        _sp = new Point(0, 0);
    }
    
    override public function setMaterialToAllFaces(material:Material):void {
        var i:int;
        for (i = 0; i < 6; i++)
        {
            setTexture(i,material);
        }
    }
    
    private function setTexture(id:uint,material:Material):void {
        var tempMaterial:TextureMaterial = material as TextureMaterial;

        if (tempMaterial) {
            _materialTypes[id] = 'Texture';
            if (tempMaterial.texture) {
                _textures[id] = tempMaterial.texture;
                _bmds[id] = new BitmapData(_textures[id].width, _textures[id].height, true, 0xFF666666);
                _loadeds[id] = true;
                _materials[id] = new TextureMaterial(_bmds[id]);
                setFaceTexture(id);
            } else {
                //Textureが読み込まれていなかったら、差し替えしない
                _materials[id] = tempMaterial;
            }
        } else {
            var tempFillMaterial:FillMaterial = material as FillMaterial
            _materialTypes[id]='Fill';
            _textures[id] = new BitmapData(400, 400, false, FillMaterial(material).color);
            _bmds[id] = new BitmapData(400, 400, false, FillMaterial(material).color);
            _materials[id] = new FillMaterial(tempFillMaterial.color, tempFillMaterial.alpha, tempFillMaterial.lineThickness, tempFillMaterial.lineColor);
            setFaceTexture(id);
        }
    }
    

    private function setFaceTexture(id:uint):void {
        //該当IDのフェースを差し替える
        var face:Face;
        var normal:Vector3D;
        for (var item:* in faces) {
            face = faces[item];
            normal = new Vector3D(_normals[id * 3], _normals[id * 3 + 1], _normals[id * 3 + 2]);
            if (face.normal.x == normal.x && face.normal.y == normal.y && face.normal.z == normal.z) {
                face.material=_materials[id];
            }
        }
    }


    
    public function calculateLight(light:Light, rotaObject:Array = null):void {
        var i:int;
        var j:int;

        //Textureをloadしている場合、load完了までは、Textureなし
        //読み込まれて、適用された段階で反映する
        
        var normal:Vector3D;

        //光源の位置ベクトル
        var lv:Vector3D = new Vector3D(light.x, light.y, light.z);
        lv = light.localToGlobal(lv);
        
        //自身の位置ベクトル
        var target:Vector3D = new Vector3D(x, y, z);
        target = localToGlobal(target);
        
        //光源に対する方向(単位ベクトル)
        var axis:Vector3D = lv.subtract(target);
        var m:Number = axis.normalize();
        
        //1フェースごとにMatrix変換は、負荷大なので、まとめて変換
        var v3:Vector.<Vector3D>;
        var mtr3D:Matrix3D = new Matrix3D();
        var tempNormals:Vector.<Number> = new Vector.<Number>();
        
        var count2:int;
        tempNormals = _normals.concat() as Vector.<Number>;
        if (rotaObject.length)
        {
            count2 = rotaObject.length;
            for (i = 0; i < count2; i++)
            {
                //回転だけ取り出す
                v3 = rotaObject[i].matrix.decompose();
                v3[0] = new Vector3D(0, 0, 0);
                v3[2] = new Vector3D(1, 1, 1);
                trace(v3[1])
                mtr3D.recompose(v3);
                mtr3D.transformVectors(tempNormals, tempNormals);
            }
        } else {
            v3 = matrix.decompose();
            v3[0] = new Vector3D(0, 0, 0);
            v3[2] = new Vector3D(1, 1, 1);
            mtr3D.recompose(v3);
            mtr3D.transformVectors(tempNormals, tempNormals);
        }


        for (i = 0; i < 6; i++)
        {
            if (_materialTypes[i] == 'Texture') {
                var tempTextureMaterial:TextureMaterial=    _materials[i] as TextureMaterial
                if (!_loadeds[i] && tempTextureMaterial.texture) {
                    _textures[i] = tempTextureMaterial.texture;
                    _bmds[i] = new BitmapData(_textures[i].width, _textures[i].height, true, 0xFF666666);
                    _loadeds[i] = true;
                    _materials[i] = new TextureMaterial(_bmds[i]);
                    setFaceTexture(i);
                }
            }
            //面の法線を得る
            normal = new Vector3D(tempNormals[i*3],tempNormals[i*3+1],tempNormals[i*3+2]);

            //光源との内積で強さを決定
            var strength:Number = normal.dotProduct(axis);
            
            //lightの色成分を分解
            var r:int = light.colorR / 2 * strength * light.strength + light.colorR / 2;
            var g:int = light.colorG / 2 * strength * light.strength + light.colorG / 2;
            var b:int = light.colorB / 2 * strength * light.strength + light.colorB / 2;
            var color:int = r << 16 | g << 8 | b;
            
            _fills.graphics.clear();
            if (_bmds[i]) {
                _fills.graphics.beginFill(color);
                _fills.graphics.drawRect(0, 0, _bmds[i].width, _bmds[i].height);
                _bmds[i].copyPixels(_textures[i], _textures[i].rect, _sp);
                _bmds[i].draw(_fills, null, null, BlendMode.HARDLIGHT);
                if (_materialTypes[i] != 'Texture') {
                    var tempFillMaterial:FillMaterial
                    tempFillMaterial = _materials[i] as FillMaterial;
                    tempFillMaterial.color = BitmapData(_bmds[i]).getPixel(1,1)
                }
            }

        }

        
    }
    
    public function get bmd():BitmapData { return _bmd; }
    
    
}


import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.primitives.GeoSphere;

/**
 *
 * Lightを表現するクラス
 *
 * @author narutohyper
 */
class Light extends GeoSphere
{
    private var _color:int;
    private var _colorR:int;
    private var _colorG:int;
    private var _colorB:int;
    private var _strength:Number;
    private var _material:FillMaterial;
    public function Light(color:Number,strength:Number=1)
    {
        _color = color;
        _strength = strength;
        _colorR = ( _color & 0xff0000 ) >> 16;
        _colorG = ( _color & 0xff00 ) >> 8;
        _colorB = ( _color & 0xff );
        
        _material = new FillMaterial(color);
        super(20, 2, false, _material);
    }
    
    public function get colorR():int { return _colorR; }
    
    public function get colorG():int { return _colorG; }
    
    public function get colorB():int { return _colorB; }
    
    public function get strength():Number { return _strength; }
    
    public function set strength(value:Number):void
    {
        _strength = value;
    }
    
    public function get color():int { return _color; }
    
    public function set color(value:int):void
    {
        _color = value;
    }
    
}


/**
 * 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.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();
    }
    
    
}