VectorShape3DTest
3D Vector drawing in Alternativa3D 7. (test)
/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/udP6
*/
package {
import alternativ7.engine3d.alternativa3d;
import alternativ7.engine3d.controllers.SimpleObjectController;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Object3DContainer;
import alternativ7.engine3d.core.Vertex;
import alternativ7.engine3d.core.View;
import alternativ7.engine3d.materials.FillMaterial;
import alternativ7.engine3d.objects.Mesh;
import flash.display.GraphicsEndFill;
import flash.display.GraphicsPath;
import flash.display.GraphicsSolidFill;
import flash.display.GraphicsStroke;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
/**
* Working with vector graphics in 3d.
*/
public class VectorShape3DTest extends Sprite {
private var rootContainer:Object3DContainer = new Object3DContainer();
private var camera:Camera3D;
private var controller:SimpleObjectController;
public function VectorShape3DTest() {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
// Camera and view
// Создание камеры и вьюпорта
camera = new Camera3D();
camera.view = new View(stage.stageWidth, stage.stageHeight);
addChild(camera.view);
addChild(camera.diagram);
// Initial position
// Установка начального положения камеры
camera.rotationX = -120*Math.PI/180;
camera.y = -400;
camera.z = 200;
camera.x = 88;
controller = new SimpleObjectController(stage, camera, 500);
rootContainer.addChild(camera);
// Adding of geometry
// Создание геометрии
var graphics3D:VectorShape3D = new VectorShape3D();
graphics3D.beginFill(0xFF0000, 1);
graphics3D.lineStyle(5, 0x0000FF, 1);
var path:GraphicsPath = new GraphicsPath();
//GraphicsPathUtils.drawRect(path, 0, 0, 120, 120);
//graphics3D.addGraphicsPath(path);
var width:Number = 100;
var height:Number = 200;
graphics3D.moveTo(0, 0);
graphics3D.lineTo(0 + width, 0, 100);
graphics3D.lineTo(0 + width, 0 + height, 100);
graphics3D.lineTo(0, 0 + height, 0);
graphics3D.lineTo(0, 0, 0);
graphics3D.endFill();
//graphics3D.graphicsData.push( new GraphicsEndFill() );
graphics3D.lineTo(0, 0, 120);
graphics3D.lineTo(0, 100, 180);
graphics3D.lineTo(0, 120, 200);
graphics3D.lineTo(0, 100, 220);
graphics3D.calculateBounds();
//graphics3D.curveTo3D(150, 200, 620, 100, 150, 100);
rootContainer.addChild(graphics3D);
// Listeners
// Подписка на события
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(Event.RESIZE, onResize);
}
private function onEnterFrame(e:Event):void {
controller.update();
camera.render();
}
private function onResize(e:Event = null):void {
// Width and height of view
// Установка ширины и высоты вьюпорта
camera.view.width = stage.stageWidth;
camera.view.height = stage.stageHeight;
}
}
}
//package iss.engine3d.vector
//{
import alternativ7.engine3d.alternativa3d;
import alternativ7.engine3d.core.Camera3D;
import alternativ7.engine3d.core.Canvas;
import alternativ7.engine3d.core.Object3D;
import alternativ7.engine3d.core.Vertex;
import alternativ7.engine3d.core.Wrapper;
import alternativ7.engine3d.objects.Mesh;
import flash.display.GraphicsEndFill;
import flash.display.GraphicsPath;
import flash.display.GraphicsPathCommand;
import flash.display.GraphicsPathWinding;
import flash.display.GraphicsSolidFill;
import flash.display.GraphicsStroke;
import flash.display.GraphicsTrianglePath;
import flash.display.IGraphicsData;
import flash.display.IGraphicsPath;
use namespace alternativa3d;
/**
* Rough class to handle vector shape drawing.
*
* What's missing? :
* - VG implementation for dynamic bsp cases
* - CurveTo implementation
* - Add Triangle path implementation
* - Public Methods to provide proxy mesh geometry for collision detection.
* (currently, you can just add faces manually), as they won't be drawn.
* - Side Camera clipping support for large-scaled lines and vector geometry
* - Vector text support through extended class.
*
* @author Glenn Ko
*/
//public
class VectorShape3D extends Mesh
{
public var graphicsData:Vector.<IGraphicsData> = new Vector.<IGraphicsData>();
//protected var vertexList:Vertex;
protected var _lastVertex:Vertex;
private var _lastPath:GraphicsPath;
public function VectorShape3D()
{
}
// -- Boiler plate
public function endFill():void {
graphicsData.push( new GraphicsEndFill() );
_lastPath = null;
}
public function beginFill(color:uint=0, alpha:Number=1):void {
graphicsData.push( new GraphicsSolidFill(color, alpha) );
}
public function lineStyle(thickness:Number = 0, color:uint = 0, alpha:Number = 1, pixelHinting:Boolean = false, scaleMode:String = "normal", caps:String = "none", joints:String = "round", miterLimit:Number = 3):void {
graphicsData.push( new GraphicsStroke(thickness, pixelHinting, scaleMode, caps, joints, miterLimit, new GraphicsSolidFill(color, alpha) ) );
}
/*
public function curveTo3D(x:Number, y:Number, z:Number, cx:Number, cy:Number, cz:Number):void {
curveTo(x, y, cx, cy, z, cz);
}
public function curveTo(x:Number, y:Number, cx:Number, cy:Number, z:Number=0, cz:Number=0):void {
if (_lastPath == null) {
_lastPath = new GraphicsPath( new Vector.<int>(), new Vector.<Number>() );
graphicsData.push(_lastPath);
}
var dataLen:int = _lastPath.data.length;
var cmdLen:int = _lastPath.commands.length;
_lastPath.commands[cmdLen++] = GraphicsPathCommand.CURVE_TO;
var v:Vertex;
v = new Vertex();
v.x = x;
v.y = y;
v.z = z;
if (_lastVertex != null)
_lastVertex.next = v;
else vertexList = v;
_lastPath.moveTo[dataLen++] = ;
_lastPath.curveTo(x, y, cx, cy);
v.index = _lastPath.data.length - 4;
v.id = _lastPath.data;
_lastVertex = v;
}
*/
public function lineTo(x:Number, y:Number, z:Number=0):void {
if (_lastPath == null) {
_lastPath = new GraphicsPath();
graphicsData.push(_lastPath);
}
var v:Vertex = new Vertex();
v.x = x;
v.y = y;
v.z = z;
_lastPath.lineTo(x, y);
v.index = _lastPath.data.length - 2;
v.id = _lastPath.data;
if (_lastVertex != null)
_lastVertex.next = v;
else vertexList = v;
_lastVertex = v;
}
public function moveTo(x:Number, y:Number, z:Number=0):void {
if (_lastPath == null) {
_lastPath = new GraphicsPath();
graphicsData.push(_lastPath);
}
var v:Vertex = new Vertex();
v.x = x;
v.y = y;
v.z = z;
_lastPath.moveTo(x, y);
v.index = _lastPath.data.length - 2;
v.id = _lastPath.data;
if (_lastVertex != null)
_lastVertex.next = v;
else vertexList = v;
_lastVertex = v;
}
/**
* Registers a graphic path instance
* @param path A valid graphics path where each command represents 1 vertex.
* So, each command cannot be a 'zero' (do nothing) command.
*/
public function addGraphicsPath(path:GraphicsPath):void {
_lastPath = path;
var i:int = 0;
var v:Vertex;
var cmds:Vector.<int> = path.commands;
var len:int = cmds.length;
var data:Vector.<Number> = path.data;
var dataCount:int = 0;
for (i = 0; i < len; i++ ) {
if (cmds[i] != GraphicsPathCommand.CURVE_TO) {
v = new Vertex();
v.id = path.data;
v.index = dataCount;
v.x = data[dataCount++];
v.y = data[dataCount++];
if (_lastVertex != null)
_lastVertex.next = v;
else vertexList = v;
}
else { // 2 control vertices for curve
v = new Vertex();
v.id = path.data;
v.index = dataCount;
v.x = data[dataCount++];
v.y = data[dataCount++];
if (_lastVertex != null)
_lastVertex.next = v;
else vertexList = v;
v.next = new Vertex();
v = v.next;
v.id = path.data;
v.index = dataCount;
v.x = data[dataCount++];
v.y = data[dataCount++];
}
_lastVertex = v;
}
graphicsData.push(path);
}
/*
public function addGraphicsTrianglePath(path:GraphicsTrianglePath):void {
graphicsData.push(path);
}
*/
override alternativa3d function draw(camera:Camera3D, parentCanvas:Canvas):void {
if (culling > 0 && (culling & 1) ) { // cull against near clip plane at least
return;
}
// Simple implementation of drawing items without side clipping
var viewSizeX:Number = camera.viewSizeX;
var viewSizeY:Number = camera.viewSizeY;
for (var v:Vertex = vertexList; v != null; v = v.next) {
var pathData:Vector.<Number> = v.id as Vector.<Number>;
var x:Number = v.x;
var y:Number = v.y;
var z:Number = v.z;
v.cameraX = ma*x + mb*y + mc*z + md;
v.cameraY = me*x + mf*y + mg*z + mh;
v.cameraZ = mi*x + mj*y + mk*z + ml;
x = v.cameraX*viewSizeX/v.cameraZ;
y = v.cameraY*viewSizeY/v.cameraZ;
pathData[v.index] = x;
pathData[v.index + 1] = y;
}
parentCanvas.getChildCanvas(true, false, this, alpha, blendMode, colorTransform, filters).gfx.drawGraphicsData(graphicsData);
}
}
//}
//package iss.engine3d.vector
//{
import flash.display.GraphicsPath;
/**
* From PV3D
* @author Glenn Ko
*/
//public
class GraphicsPathUtils
{
public static function drawRect(path:GraphicsPath, x : Number, y : Number, width : Number, height : Number) : void
{
path.moveTo(x, y);
path.lineTo(x + width, y);
path.lineTo(x + width, y + height);
path.lineTo(x, y + height);
path.lineTo(x, y);
}
public static function drawRoundRect(path:GraphicsPath, x : Number, y : Number, width : Number, height : Number, ellipseWidth : Number, ellipseHeight : Number) : void
{
path.moveTo(x, y + ellipseHeight);
path.curveTo(x, y , x + ellipseWidth, y);
path.lineTo(x + width - ellipseWidth, y);
path.curveTo(x + width , y , x + width , y + ellipseHeight);
path.lineTo(x + width, y + height - ellipseHeight);
path.curveTo(x + width, y + height , x + width - ellipseHeight, y + height);
path.lineTo(x + ellipseWidth, y + height);
path.curveTo(x , y + height , x , y + height - ellipseHeight);
path.lineTo(x, y + ellipseHeight);
}
//Based on Keith Peters MultiCurves
public static function drawEllipse(path:GraphicsPath, x: Number , y:Number , width : Number , height : Number , numPoints : int = 8):void
{
var points:Array = new Array();
var step : Number = 2 * Math.PI / numPoints;
for (var i:int = 0; i < numPoints; i++)
{
points[i] = new Object();
points[i].x = x + Math.sin(i * step) * width;
points[i].y = y + Math.cos(i * step) * height;
}
// find the first midpoint and move to it
var xc1:Number = (points[0].x + points[numPoints - 1].x) / 2;
var yc1:Number = (points[0].y + points[numPoints - 1].y) / 2;
path.moveTo(xc1, yc1);
// curve through the rest, stopping at midpoints
for (i = 0; i < numPoints - 1; i ++)
{
var xc:Number = (points[i].x + points[i + 1].x) / 2;
var yc:Number = (points[i].y + points[i + 1].y) / 2;
path.curveTo(points[i].x, points[i].y, xc, yc);
}
// curve through the last point, back to the first midpoint
path.curveTo(points[i].x, points[i].y, xc1, yc1);
}
}
//}