なんで円とかリングがないのかと思って作ってみた。
Circle.as 平面系の円
Ring2D.as 平面系の輪
Ring3D.as 立体系の輪
org.papervision3d.objects.* のクラスを参考に作ってみた。
これらは、Papervision3D のプリミティブオブジェクトのような雰囲気で使う。
Papervision3D には PaperPlane という紙飛行機風なふざけたオブジェクト(・∀・)が存在しているぐらいなので、もっとまともな&変なオブジェクトを大量投入してもよさそうなもん。
ついでに XYZ軸(Axes.as)も入れてみた。
axis の 複数形が axes. 斧(axe)の複数形と同じ綴り。
以下、ソースコード。
RotatingObjects.as
package {
import flash.display.*;
import flash.events.*;
import org.papervision3d.core.proto.*;
import org.papervision3d.scenes.*;
import org.papervision3d.objects.*;
import org.papervision3d.cameras.*;
import org.papervision3d.materials.*;
[SWF(width="400", height="400", backgroundColor="#000000", frameRate="30")]
// Papervision3D は左手系座標
public class RotatingObjects extends Sprite {
private var container : Sprite;
private var scene : Scene3D;
private var camera : Camera3D;
private var rootNode : DisplayObject3D;
private var obj:Array = new Array();
// 3Dオブジェクト踊らせ用パラメータ
private var valx : Number = 0;
private var valy : Number = 0;
public function RotatingObjects():void {
addEventListener(Event.ENTER_FRAME, onEnterFrame);
addEventListener(MouseEvent.CLICK, onMouseClick);
stage.addEventListener(Event.RESIZE, onStageResize);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
// 表示用の Sprite オブジェクトを生成
container = new Sprite();
container.x = 400 / 2; // at center : swf width = 400
container.y = 400 / 2; // at center : swf height = 400
addChild(container);
// シーンオブジェクトを作る
scene = new Scene3D(container);
// カメラオブジェクトを作る
camera = new Camera3D();
camera.z = -200;
camera.focus = 500;
camera.zoom = 1;
// ルートノードを作る
rootNode = new DisplayObject3D();
scene.addChild(rootNode);
// いろんな3Dオブジェクトを作ってみて、配列に入れておく
obj.push(
new Axes(
createWireframeMaterial(0xFF0000),
createWireframeMaterial(0x00FF00),
createWireframeMaterial(0x0000FF)));
obj.push( createPlane(createWireframeMaterial(0x00FF00)));
obj.push(createCircle(createWireframeMaterial(0x00FF00)));
obj.push(createRing2D(createWireframeMaterial(0x00FF00)));
obj.push(createRing3D(createWireframeMaterial(0x00FF00)));
// 3Dオブジェクトをルートノードに追加
for(var i:int; i<obj.length; i++){
rootNode.addChild(obj[i]);
}
}
private function createPlane(material:MaterialObject3D):DisplayObject3D {
var obj:Plane = new Plane(material, 200, 200);
obj.x = -100;
obj.y = -100;
obj.z = 100;
return obj;
}
private function createCircle(material:MaterialObject3D):DisplayObject3D {
var obj:Circle = new Circle(material, 100, 16);
obj.x = 100;
obj.y = 100;
obj.z = 100;
return obj;
}
private function createRing2D(material:MaterialObject3D):DisplayObject3D {
var obj:Ring2D = new Ring2D(material, 80, 100, 32);
obj.x = -100;
obj.y = 100;
obj.z = 100;
return obj;
}
private function createRing3D(material:MaterialObject3D):DisplayObject3D {
var obj:Ring3D = new Ring3D(material, 80, 100, 50, 32);
obj.x = 100;
obj.y = -100;
obj.z = 100;
return obj;
}
private function createWireframeMaterial(color:Number):MaterialObject3D {
var material:WireframeMaterial = new WireframeMaterial(color);
//material.lineColor = 0x00FF00;
material.lineAlpha = 1;
material.oneSide = true;
return material;
}
private function createColorMaterial(color:Number):MaterialObject3D {
var material:ColorMaterial = new ColorMaterial(color);
material.oneSide = true;
return material;
}
private function onEnterFrame(event:Event):void {
valx += container.mouseX / 100;
valy += container.mouseY / 100;
for(var i:int; i<obj.length; i++){
obj[i].rotationY = valx;
obj[i].rotationX = valy;
}
scene.renderCamera(camera);
}
private function onStageResize(event:Event):void {
container.x = stage.stageWidth / 2;
container.y = stage.stageHeight / 2;
}
private function onKeyDown(event:KeyboardEvent):void {
switch(event.keyCode) {
case 90: // zキー: zoomのテスト
if(event.shiftKey){
camera.zoom = camera.zoom + 1;
}else{
camera.zoom = camera.zoom - 1;
}
break;
case 88: // xキー: focusのテスト
if(event.shiftKey){
camera.focus = camera.focus + 1;
}else{
camera.focus = camera.focus - 1;
}
break;
}
}
private function onMouseClick(event:Event):void {
// do nothing
}
}
}
Axes.as
package {
import org.papervision3d.core.proto.*;
import org.papervision3d.objects.*;
// 軸オブジェクト(X軸Y軸Z軸を描画)
public class Axes extends DisplayObject3D {
public function Axes(
xMaterial:MaterialObject3D = null,
yMaterial:MaterialObject3D = null,
zMaterial:MaterialObject3D = null,
length:Number = 1000, thickness:Number = 1,
initObject:Object = null){
var name:String = null;
var geometry:GeometryObject3D = null;
super(name, geometry, initObject);
buildAxes(xMaterial, yMaterial, zMaterial, length, thickness);
}
private function buildAxes(
xm:MaterialObject3D, ym:MaterialObject3D, zm:MaterialObject3D,
length:Number, thickness:Number):void {
// Cube(material, width, depth, height);
//x=width, z=depth, y=height だと思って書いてみたが
//z=width, x=depth, y=height になっているような……
var axisx:Cube = new Cube(xm, length, thickness, thickness);
var axisy:Cube = new Cube(ym, thickness, thickness, length);
var axisz:Cube = new Cube(zm, thickness, length, thickness);
addChild(axisx);
addChild(axisy);
addChild(axisz);
}
}
}
Circle.as
package {
import org.papervision3d.core.proto.*;
import org.papervision3d.core.geom.*;
// 円オブジェクト
public class Circle extends Mesh3D {
public function Circle(
material:MaterialObject3D = null,
radius:Number = 100,
segments:int = 8,
initObject:Object = null){
super(material, new Array(), new Array(), null, initObject);
buildCircle(radius, segments);
}
private function buildCircle(s:Number, segments:int):void {
const density:int = segments + 2;
const rad:Number = degree2radian(360.0 / density);
var i:int;
var vertices:Array = new Array();
for(i=0; i<density; i++){
var x:Number = Math.cos(rad * i) * s;
var y:Number = Math.sin(rad * i) * s;
vertices.push(new Vertex3D(x, y, 0));
}
// vertices に無い頂点を含む Face3D を入れるとエラーになる
var faces:Array = new Array();
for(i=1; i<vertices.length-1; i++){
//var v:Array = new Array();
//v.push(vertices[0]);
//v.push(vertices[i]);
//v.push(vertices[i+1]);
//faces.push(new Face3D(v));
faces.push(new Face3D([vertices[0], vertices[i], vertices[i+1]]));
}
this.geometry.vertices = vertices;
this.geometry.faces = faces;
this.projectTexture("x", "z");
this.geometry.ready = true;
}
private static function degree2radian(degree:Number):Number{
return degree / 180.0 * Math.PI;
}
}
}
Ring2D.as
package {
import org.papervision3d.core.proto.*;
import org.papervision3d.core.geom.*;
// 輪オブジェクト平面版
public class Ring2D extends Mesh3D {
public function Ring2D(
material:MaterialObject3D = null,
inRadius:Number = 80,
exRadius:Number = 100,
segments:int = 8,
initObject:Object = null){
super(material, new Array(), new Array(), null, initObject);
buildRing2D(inRadius, exRadius, segments);
}
private function buildRing2D(inRadius:Number, exRadius:Number, segments:int):void {
const density:int = segments;
const rad :Number = degree2radian(360.0 / density);
const half:Number = degree2radian(360.0 / density / 2.0);
// internal circle
var inVertices:Array = createVertices(density, rad, 0, inRadius);
// external circle
var exVertices:Array = createVertices(density, rad, half, exRadius);
var faces:Array = new Array();
for(var i:int=0; i<density; i++){
// clockwise
faces.push(new Face3D([get(inVertices, i), get(exVertices, i), get(inVertices, i+1)]));
faces.push(new Face3D([get(exVertices, i), get(exVertices, i+1), get(inVertices, i+1)]));
}
this.geometry.vertices = inVertices.concat(exVertices);
this.geometry.faces = faces;
this.projectTexture("x", "z");
this.geometry.ready = true;
}
private static function get(a:Array, i:int):Object{
if(a.length <= i){
i = i % a.length;
}
return a[i];
}
private static function createVertices(density:int, rad:Number, offsetRad:Number, radius:Number):Array{
var v:Array = new Array();
for(var i:int=0; i<density; i++){
var angle:Number = (rad * i) + offsetRad;
var x:Number = Math.cos(angle) * radius;
var y:Number = Math.sin(angle) * radius;
v.push(new Vertex3D(x, y, 0));
}
return v;
}
private static function degree2radian(degree:Number):Number{
return degree / 180.0 * Math.PI;
}
}
}
Ring3D.as
package {
import org.papervision3d.core.proto.*;
import org.papervision3d.core.geom.*;
// 輪オブジェクト立体版
public class Ring3D extends Mesh3D {
public function Ring3D(
material:MaterialObject3D = null,
inRadius:Number = 80,
exRadius:Number = 100,
depth:Number = 50,
segments:int = 8,
initObject:Object = null){
super(material, new Array(), new Array(), null, initObject);
buildRing3D(inRadius, exRadius, depth, segments);
}
private function buildRing3D(inRadius:Number, exRadius:Number, depth:Number, segments:int):void {
const density:int = segments;
const rad :Number = degree2radian(360.0 / density);
const half:Number = degree2radian(360.0 / density / 2.0);
// near side internal circle
var nsInVertices:Array = createVertices(density, rad, 0, inRadius, depth / -2.0);
// near side external circle
var nsExVertices:Array = createVertices(density, rad, half, exRadius, depth / -2.0);
// far side internal circle
var fsInVertices:Array = createVertices(density, rad, 0, inRadius, depth / 2.0);
// far side external circle
var fsExVertices:Array = createVertices(density, rad, half, exRadius, depth / 2.0);
var faces:Array = new Array();
for(var i:int=0; i<density; i++){
// clockwise(時計回りの表側がオブジェクトの表側)
// near side Ring2D
faces.push(new Face3D([get(nsInVertices, i), get(nsExVertices, i), get(nsInVertices, i+1)]));
faces.push(new Face3D([get(nsExVertices, i), get(nsExVertices, i+1), get(nsInVertices, i+1)]));
// far side Ring2D
faces.push(new Face3D([get(fsInVertices, i+1), get(fsExVertices, i), get(fsInVertices, i)]));
faces.push(new Face3D([get(fsInVertices, i+1), get(fsExVertices, i+1), get(fsExVertices, i)]));
// connection internal circles for far and near
faces.push(new Face3D([get(fsInVertices, i), get(nsInVertices, i), get(fsInVertices, i+1)]));
faces.push(new Face3D([get(nsInVertices, i), get(nsInVertices, i+1), get(fsInVertices, i+1)]));
// connection external circles for far and near
faces.push(new Face3D([get(nsExVertices, i), get(fsExVertices, i), get(nsExVertices, i+1)]));
faces.push(new Face3D([get(fsExVertices, i), get(fsExVertices, i+1), get(nsExVertices, i+1)]));
}
this.geometry.vertices = nsInVertices.concat(nsExVertices, fsInVertices, fsExVertices);
this.geometry.faces = faces;
this.projectTexture("x", "z");
this.geometry.ready = true;
}
private static function get(a:Array, i:int):Object{
if(a.length <= i){
i = i % a.length;
}
return a[i];
}
private static function createVertices(density:int, rad:Number, offsetRad:Number, radius:Number, depth:Number):Array{
var v:Array = new Array();
for(var i:int=0; i<density; i++){
var angle:Number = (rad * i) + offsetRad;
var x:Number = Math.cos(angle) * radius;
var y:Number = Math.sin(angle) * radius;
v.push(new Vertex3D(x, y, depth));
}
return v;
}
private static function degree2radian(degree:Number):Number{
return degree / 180.0 * Math.PI;
}
}
}
RotatingObjects-config.xml
<flex-config>
<use-network>true</use-network>
<benchmark>true</benchmark>
<compiler>
<incremental>true</incremental>
<source-path>
<path-element>../libs/</path-element>
</source-path>
</compiler>
</flex-config>
コンパイル
mxmlc RotatingObjects.as
追記: 2007-11-25
テクスチャ版 -> Papervision3D のいろいろなオブジェクトにテクスチャを貼ってみる
tags: zlashdot Flash Flash Flex Papervision3D
Posted by NI-Lab. (@nilab)