/**
* Copyright YoupSolo ( http://wonderfl.net/user/YoupSolo )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/wTOe
*/
package
{
import flash.display.BitmapData;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.display.TriangleCulling;
import flash.events.Event;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
/**
*
* @author YopSolo
*/
public class Main extends Sprite
{
private const FRAMERATE:int = 30;
private var _stageW:int;
private var _stageH:int;
private var _halfStageW:int;
private var _halfStageH:int;
private var _texture:BitmapData;
private var _model:Mesh3D;
private var _transform:Matrix3D;
/**
* Constructor. Centers sprite, creates model and texture
*/
public function Main()
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// config stage
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
//stage.quality = StageQuality.MEDIUM;
stage.stageFocusRect = false;
stage.tabChildren = false;
stage.frameRate = FRAMERATE;
_stageW = stage.stageWidth;
_stageH = stage.stageHeight;
_halfStageW = _stageW >> 1;
_halfStageH = _stageH >> 1;
// add custom menu
new CustomMenu(this);
// run app
run();
}
// == APP ==
private function run():void
{
buildTextField(this, 'TIP 12 : Basic use of drawTriangle and Matrix3D', (2-_halfStageW)>>0, (2-_halfStageH)>>0);
x = _halfStageW;
y = _halfStageH;
_texture = new XORTexture(256, 256);
_model = new PyramidMesh(this);
// creates initial 3D transform
_transform = new Matrix3D();
addEventListener( Event.ENTER_FRAME, _oef);
}
/**
* Draws the 3D model to the screen using drawTriangles().
*/
private function render():void {
// applies current transform to the model
_model.applyTransform(_transform);
this.graphics.clear(); /*thx !*/
this.graphics.beginFill(0x333333,1);
this.graphics.drawRect(-_halfStageW ,-_halfStageH,_stageW, _stageH);
this.graphics.endFill();
this.graphics.beginBitmapFill(_texture);
this.graphics.drawTriangles(
_model.vertices,
_model.sides,
_model.uvtData,
TriangleCulling.NEGATIVE
);
this.graphics.endFill();
}
/**
* onEnterFrame
* @param event
*/
private function _oef(event:Event):void {
_transform.appendRotation(2, Vector3D.Y_AXIS);
render();
}
// == COMMON ==
private function buildTextField(doc:DisplayObjectContainer, txt:String, x:int = 0, y:int = 0):TextField
{
var fmt:TextFormat = new TextFormat;
fmt.color = 0xFFFFFF;
fmt.font = 'Arial'; //(new FONT_HARMONY() as Font).fontName;
fmt.size = 11; // 8;
var tf:TextField = new TextField;
tf.autoSize = TextFieldAutoSize.LEFT;
tf.opaqueBackground = 0x333333; // opaque background allow a perfect font rendering even in StageQuality.LOW mode
tf.selectable = false;
//tf.embedFonts = true;
tf.defaultTextFormat = fmt;
tf.text = txt;
tf.x = x;
tf.y = y;
doc.addChild(tf);
return tf;
}
}
}
import flash.display.DisplayObject;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;
/**
* Abstract base class for 3D models. This holds the untransformed vertices, sides and UVT data,
* then can convert the 3D vertices into 2D coordinates to be rendered on the screen.
*/
class Mesh3D {
private var _vertices:Vector.<Number>;
private var _container3D:DisplayObject;
protected var _vectors:Vector.<Vector3D>;
protected var _sides:Vector.<int>;
protected var _uvtData:Vector.<Number>;
/**
* Constructor. This saves a reference to the parent container of the model for
* use in transforming coordinates into the parent coordinate space, as well
* as calls the createMesh() method to initialize all of the model properties.
*
* @param container The container display object in which the model will be rendered.
*/
public function Mesh3D(container:DisplayObject) {
_container3D = container;
createMesh();
}
/**
* Abstract method to be overridden by concrete child classes.
* This should initialize all of the vertices, sides and UVT data.
*/
protected function createMesh():void {}
/**
* Transforms a 3D vector into a 2D screen coordinate.
*
* @param vector The 3D vector to convert.
*
* @return The 2D coordinate in the parent container's coordinate space.
*/
private function getPoint2D(vector:Vector3D):Point {
var point:Point = _container3D.local3DToGlobal(vector);
return _container3D.globalToLocal(point);
}
/**
* Applies the specified matrix transform to the vertices in the model.
* This is non-destructive, creating a separate list of transformed vertices.
*
* @param matrix The 3D matrix transform to apply to the model.
*/
public function applyTransform(matrix:Matrix3D):void {
_vertices = new Vector.<Number>();
var vertex:Point;
var transformedVector:Vector3D;
// run through each vertex
for each (var vector:Vector3D in _vectors) {
// transforms the vector using the matrix transform
transformedVector = matrix.deltaTransformVector(vector);
// converts the transformed 3D point to a 2D screen coordinate
vertex = getPoint2D(transformedVector);
// separates point into separate x and y properties, as required by drawTriangles()
_vertices.push(vertex.x, vertex.y);
}
}
/**
* Returns the 2D coordinates that can be used to draw the 3D model.
* This returns the vertices in the form required by drawTriangles().
*
* @return The 2D coordinates that can be used to draw the 3D model.
*/
public function get vertices():Vector.<Number> {
return _vertices;
}
/**
* Returns the sides data that can be used to draw the 3D model.
* This returns the sides in the form required by drawTriangles().
*
* @return The sides that can be used to draw the 3D model.
*/
public function get sides():Vector.<int> {
return _sides;
}
/**
* Returns the UVT data that can be used to texture the 3D model.
* This returns the data in the form required by drawTriangles().
*
* @return The UVT data that can be used to texture the 3D model.
*/
public function get uvtData():Vector.<Number> {
return _uvtData;
}
}
import flash.display.DisplayObject;
import flash.geom.Vector3D;
/**
* Class holding 3D values for pyramid model.
*/
class PyramidMesh extends Mesh3D {
/**
* Constructor. Calls super's contructor.
*
* @param container The object in which the model will be rendered.
*/
public function PyramidMesh(container:DisplayObject) {
super(container);
}
/**
* Initializes all the values needed to render the model,
* including vertices, sides and uvt data.
*/
override protected function createMesh():void {
_vectors = new Vector.<Vector3D>();
_vectors.push(new Vector3D(0, -100, 0));
_vectors.push(new Vector3D(130, 100, 130));
_vectors.push(new Vector3D(130, 100, -130));
_vectors.push(new Vector3D(-130, 100, -130));
_vectors.push(new Vector3D(-130, 100, 130));
_sides = new Vector.<int>();
_sides.push(0, 1, 2);
_sides.push(0, 2, 3);
_sides.push(0, 3, 4);
_sides.push(0, 4, 1);
_uvtData = new Vector.<Number>();
_uvtData.push(0.5, 0.5);
_uvtData.push(0, 1);
_uvtData.push(0, 0);
_uvtData.push(1, 0);
_uvtData.push(1, 1);
}
}
// create the XOR texture
import flash.display.BitmapData;
class XORTexture extends BitmapData
{
public function XORTexture(width:int, height:int)
{
super(width, height, false, 0x0);
var color:uint;
var rbg_color:uint;
for (var w:int = 0; w < width; w++)
{
for (var h:int = 0; h < height; h++)
{
color = w ^ h;
rbg_color = color << 16 | color << 8 | color;
this.setPixel(w, h, rbg_color);
}
}
}
}
import flash.display.Sprite;
import flash.events.ContextMenuEvent;
import flash.net.navigateToURL;
import flash.net.URLRequest;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
class CustomMenu
{
private const NAME:String = "Flash Tips Collection : 'Basic use of drawTriangle and Matrix3D'";
public function CustomMenu(ref:Sprite):void
{
var appContextMenu:ContextMenu = new ContextMenu;
appContextMenu.hideBuiltInItems();
var cmi:ContextMenuItem = new ContextMenuItem(NAME);
var credits:ContextMenuItem = new ContextMenuItem("by YopSolo");
appContextMenu.customItems.push(cmi);
appContextMenu.customItems.push(credits);
cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, _onClickCollection);
credits.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, _onClickCredits);
ref.contextMenu = appContextMenu;
}
private function _onClickCollection(e:ContextMenuEvent):void
{
navigateToURL(new URLRequest('http://www.yopsolo.fr/wp/2012/01/14/flash-tips-collection/'), '_blank');
}
private function _onClickCredits(e:ContextMenuEvent):void
{
navigateToURL(new URLRequest('http://www.yopsolo.fr'), '_blank');
}
}