第六章
Vector Shapes and Text in 3D
3d環境中的矢量圖和文本
Using the Away3D drawing API
在away3d裏創建的圖形是矢量圖
Flash創建圖形
var shape : Shape = new Shape();
shape.graphics.beginFill(0xffcc00);
shape.graphics.moveTo(-10, -10);
shape.graphics.lineTo(10, -10);
shape.graphics.lineto(10, 10);
shape.graphics.lineTo(-10, -10);
shape.graphics.endFill();
away3d和其類似
var face : Face = new Face();
face.material = new ColorMaterial(0xffcc00);
face.moveTo(-10, -10, 0);
face.lineTo(10, -10, 0);
face.lineTo(10, 10, 0);
face.lineTo(-10, -10, 0);
上面away3d中創建的是一個3D圖形
Away3d中的Face類 類似於flash裏的Graphics類
Away3d中 圖形的創建
在away3d中創建圖形使用的類是Face 但是 還需要將該類添加進Mesh 容器中 只有這樣才能在場景中進行顯示 .Mesh的作用是一個canvas一個待建造的3d對象 Face就像是其的一個零件
away3d 中所有的3d 對象都是直接或者間接繼承於Mesh
Mesh就是一個待建造的3d對象其使用和3d對象類似
三角面的創建:
//創建Mesh容器
var mesh:Mesh = new Mesh();// Mesh (剛創建的Mesh不可見,因爲裏面沒有面) 的作用是一個待建造的3d對象
mesh.bothsides = true;
var material : WireColorMaterial = new WireColorMaterial(0xFF0000);
material.wireColor = 0x000000;
material.thickness = 2;
mesh.material = material;
_view.scene.addChild(mesh);
//創建三角面
// Triangle. 三角面
var face0:Face = new Face();
face0.moveTo(-50, -50, 0);
face0.lineTo(50, 50, 0);
face0.lineTo(-50, 50, 0);
face0.lineTo(-50, -50, 0);
face0.offset(-300, 0, 0);// 該面沿x軸負方向300單位
mesh.addFace(face0);//用它建造Mesh
// Square. 正方形面
var face1:Face = new Face();
face1.moveTo(-50, -50, 0);
face1.lineTo(50, -50, 0);
face1.lineTo(50, 50, 0);
face1.lineTo(-50, 50, 0);
face1.lineTo(-50, -50, 0);//注意:最後又回到起點
face1.offset(-180, 0, 0);
mesh.addFace(face1);
// 創建彎曲的面
// Non-planer shape.
var face3:Face = new Face();
face3.moveTo(-50, -50, 0);
face3.curveTo(0, -50, 50, 50, -50, 0);
face3.lineTo(50, 50, 0);
face3.curveTo(0, 50, 50, -50, 50, 0);
face3.lineTo(-50, -50, 0);
face3.offset(180, 0, 0);
mesh.addFace(face3);
注意Face創建的圖形是封閉的!假如創建不封閉的圖形就要用Segment
用法和Face類似:
// 非封閉曲面
var segment0:Segment = new Segment();
segment0.moveTo(10, 50, 0);
segment0.lineTo(60, 50, 0);
segment0.lineTo(60, 0, 0);
segment0.curveTo(110, 0, 0, 110, -50, 0);//前三個參數是控制點controlPoint 的參數,後三個是endPoint 結束點的參數
mesh.addSegment(segment0);
創建有洞的曲面 實際上就是點的連接
代碼:
//創建 hole
var face4:Face = new Face();
face4.moveTo(-50, -50, 0);
face4.lineTo(50, -50, 0);
face4.lineTo(50, 50, 0);
face4.lineTo(-50, 50, 0);
face4.lineTo(-50, -50, 0);
face4.moveTo(30, 30, 0);
face4.lineTo(0, -30, 0);
face4.lineTo(-30, 30, 0);
face4.lineTo(30, 30, 0);
face4.offset(300, 0, 0);
mesh.addFace(face4);
mesh.addFace(face4);
Importing 3D vector shapes
在使用外部矢量圖形時,在flash中要注意將圖形的註冊點設置在幾何中心!這樣在away3d中才能在中間呈現。因爲away3d對象的註冊點在幾何中心
使用外部圖形兩種方式 :
主要是通過Swf類和Loader3D類
注意 一定要設置swf.libraryClips = ["Pic"];//Pic 爲外部swf資源中的類 libraryClips屬性 即爲 外部鏈接類
當直接將含有矢量圖形的外部文件嵌入到away3d文件中時 的核心代碼:
[Embed(source='import3d.swf',
mimeType="application/octet-stream")]
private var ImportSWF : Class;
var importSWF: ByteArray = new ImportSWF() as ByteArray;
var swf : Swf = new Swf();
swf.libraryClips = ["Pic"];//Pic 爲外部swf中的類 libraryClips屬性 即爲 外部鏈接類
//解析swf中的數據
var import3d : ObjectContainer3D = swf.parseGeometry(importSWF) as
ObjectContainer3D;
_view.scene.addChild(import3d);
動態加載外部swf :
private var loader:Loader3D;
var swf : Swf = new Swf();
swf.libraryClips = ["Pic"];//Pic 爲外部swf中的類 libraryClips屬性 即爲 外部鏈接類
loader= new Loader3D();
loader.addEventListener(Loader3DEvent.LOAD_SUCCESS,onSuccess);
loader.addEventListener(Loader3DEvent.LOAD_ERROR,onError);
//加載外部swf並且解析
loader.loadGeometry("../import3d.swf",swf);
private function onSuccess(e:Loader3DEvent):void
{
//trace("OK");
var import3d:ObjectContainer3D = Loader3D(e.currentTarget).handle as ObjectContainer3D;
_view.scene.addChild(import3d);
loader.removeEventListener(Loader3DEvent.LOAD_SUCCESS,onSuccess);
loader.removeEventListener(Loader3DEvent.LOAD_ERROR,onError);
}
private function onError(e:Loader3DEvent):void
{
//trace("發生流錯誤...");
loader.removeEventListener(Loader3DEvent.LOAD_SUCCESS,onSuccess);
loader.removeEventListener(Loader3DEvent.LOAD_ERROR,onError);
}
注意:外部swf中的圖形全部保存在ObjectContainer3D中,要想訪問圖像本身!則用到父容器ObjectContainer3D.因爲flash圖形經過轉化變爲Mesh類型 並且這些Mesh全部被添加進了ObjectContainer3D實例中。故訪問圖形信息的代碼爲:
ObjectContainer3D.children[index].經常性的 index爲0
圖形轉化爲Mesh的個數與flash中圖形的圖層Layer有關!一般性我們將圖形全部保存在第一層所以最終轉化的Mesh只有一個 所以經過3D轉化後 在away3d中訪問的代碼是: ObjectContainer3D.children[0]
在進一步去操作這個Mesh的點點Vertex以達到各種效果
訪問3d對象的點點: Mesh.vertices
var _mesh:Mesh = Container3D.children[0] as Mesh;
for each (var vertex : Vertex in _mesh.vertices)
vertex.z = 50*Math.sin(vertex.x/50 + getTimer()/200);
Importing 3D Text
Text的使用和圖形的使用類似!
注意擠出命令: TextExtrusion(maya中的擠出命令)
//使用文本擠出命令TextExtrusion
即可用於文本,也可以用於圖形
var _mesh:Mesh = import3d.children[0] as Mesh;
var extrusion : TextExtrusion = new TextExtrusion(_mesh);
extrusion.bothsides = true;
extrusion.pushback=true
_view.scene.addChild(extrusion);//將擠出效果添加進場景
文字沿着指定路徑排列已及運動.
使用的類:
Path類用來形成路徑
PathAlignModifier 用來使3d對象排列在制定路徑上
創建:部分核心代碼:
[Embed(source="verdana.swf",
mimeType="application/octet-stream")]
private var VerdanaSwf:Class;
private var _pathAlignModifier:PathAlignModifier;
private var _maxOffset:Number;
private var _offset:Number = 0;
private var _speed:int = 10;
var verdanaSwf : ByteArray = new VerdanaSwf() as ByteArray;
VectorText.extractFont(verdanaSwf);
var tf3D:TextField3D = new TextField3D('Verdana');
tf3D.text = 'Text along a path';
tf3D.size = 40;
tf3D.width = 2000;
tf3D.leading = 20;
tf3D.x = -450;
tf3D.y = 50;
_view.scene.addChild(tf3D);
var points : Array = []
for (var i : int=0; i<10; i++)
{
points.push(new Vector3D(i*100, i%2? 50 : -25, 0));
}
var path : Path = new Path();
path.continuousCurve(points);//形成路徑
var segment : Segment = new Segment();
segment.drawPath(path);//將路徑畫出來
var mesh : Mesh = new Mesh();
mesh.x = tf3D.x;
mesh.y = tf3D.y;
mesh.addSegment(segment);
_view.scene.addChild(mesh);
//讓3d對象tf3D排列到指定路徑path上
_pathAlignModifier = new PathAlignModifier(tf3D,path);
_pathAlignModifier.execute();
使排列的3d對象運動使用的屬性是offset
_pathAlignModifier.offset.x= 想在X方向上運動的值
_pathAlignModifier.execute();//執行這一效果
_pathAlignModifier.arcLengthPrecision = 1/(1 + mouseY/3);//精確度 ---誤差 值越低 準確度越高
在away3d中使用矢量圖需要注意的問題:
不規則的矢量圖<外部導入的矢量圖,以及文本>只能如下材質:
ColorMaterial, WireColorMaterial, WireframeMaterial, and ShadingColorMaterial.
不規則的矢量圖<外部導入的矢量圖,以及文本>使用的clipping方式只能是RectangleClipping
當使用的字體不一樣時或者字體的效果添加不同時最終導致的結果將會有很大的不同
在使用Textfield3D時 需要將bothsides屬性 設爲true