四角い薔薇


四角い薔薇三年位前(Flash9のPublic Alpha版!!)にクリッピングできたわーいで作ったものを、元にWonderflで動くようにしながら細々ブラシュアップ。

マウスの位置で回転や、光源をコントロール。キーボードの↑↓キーで視点、マウスのdeltaでviewpointを変えたりできるはず。

4角形ポリンゴンで、立方体の面を作っていて、zの座標に応じて、クリッピングしている。

レンダリング側は、4角以上のポリゴンにも対応しているので、クリッピングした結果の5角形とかも描ける。

これで、自動的に三角ポリゴンに分割とかできるようになったら、テクスチャーつきでクリッピングできるのかな。今後の課題だ。

あと、やっぱsortがボトルネックになっていたので、作り直した。

▼関連情報
クリッピング
http://game.watch.impress.co.jp/docs/20040406/psp06.htm

3DゲームファンのためのPSPグラフィックス講座
http://game.watch.impress.co.jp/docs/20040406/psp.htm

Get Adobe Flash player

▼Wonderfl
http://wonderfl.net/code/72469aff4c775bb14887d25e63d31823b19c6ad1

▼ActionScript AS3(FP9)
[sourcecode language=”as3″]
/*
三年位前(Flash9のPublic Alpha版!!)にクリッピングできたわーいで作ったものを、
元にWondeflで動くようにしながら細々ブラシュアップ。

マウスの位置で回転や、光源をコントロール。
キーボードの↑↓キーで視点、マウスのdeltaでviewpointを変えたりできるはず。

4角形ポリンゴンで、立方体の面を作っていて、
zの座標に応じて、クリッピングしている。

レンダリング側は、4角以上のポリゴンにも対応しているので、
クリッピングした結果の5角形とかも描ける。

これで、自動的に三角ポリゴンに分割とかできるようになったら、
テクスチャーつきでクリッピングできるのかな。今後の課題だ。

あと、やっぱsortがボトルネックになっていたので、作り直した。

*クリッピング
http://game.watch.impress.co.jp/docs/20040406/psp06.htm
http://game.watch.impress.co.jp/docs/20040406/psp.htm

*/
package
{
/**
* …
* @author umhr
*/
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.events.Event;

public class Main extends Sprite

{
function Main(){
var i:int;

var origin_array:Array = new Array();
var num:int = 4
for (i = 0 ; i < 7; i++) {
num = num*1.8;
origin_array.push([0, ["plane", 0], [[ -num, -num, -num], [num, -num, -num], [num, num, -num], [ -num, num, -num]]], [0, ["plane", 0], [[num, num, num], [num, -num, num], [ -num, -num, num], [ -num, num, num]]], [0, ["plane", 0], [[ -num, num, num], [ -num, -num, num], [ -num, -num, -num], [ -num, num, -num]]], [0, ["plane", 0], [[num, -num, -num], [num, -num, num], [num, num, num], [num, num, -num]]], [0, ["plane", 0], [[num, num, num], [ -num, num, num], [ -num, num, -num], [num, num, -num]]], [0, ["plane", 0], [[ -num, -num, -num], [ -num, -num, num], [num, -num, num], [num, -num, -num]]]);
}

var stageWidth:int = stage.stageWidth;
var stageHeight:int = stage.stageHeight;

var vpcutpoint_num:Number = new Number(290);
var lightpoz_array:Array = new Array(0, 0, 300);
var mcnum_num:int = origin_array.length;
var n_dx:Number = new Number(0);
var n_dy:Number = new Number(0);
var n_dz:Number = new Number(0);
var n_rx:Number = new Number(0);
var n_ry:Number = new Number(0);
var n_rz:Number = new Number(0);
var sprits:Array = new Array();

for (i = 0 ; i < origin_array.length;i++) {
var sp:Sprite = new Sprite();
this.addChild(sp);
sp.x = stageWidth/2;
sp.y = stageHeight/2;
sprits.push(sp);
}
var sorter_array:Array = new Array();
var sq_array:Array = new Array();
function fc_create(fc_dx:Number, fc_dy:Number, fc_dz:Number, fc_rx:Number, fc_ry:Number, fc_rz:Number):void {
var i:int;
var j:int;

//map
var data_array:Array = Math3D.arraycopy(origin_array);

//affine
for (i = 0; i < data_array.length; i++) {

var _array:Array = new Array();
if(int(i/6)%2 == 0){
_array[0] = Math.cos(fc_rx);
_array[1] = Math.sin(fc_rx);
_array[2] = Math.cos(fc_ry);
_array[3] = Math.sin(fc_ry);
_array[4] = Math.cos(fc_rz);
_array[5] = Math.sin(fc_rz);
_array[6] = fc_dz;
}else{
_array[0] = Math.cos(fc_ry);
_array[1] = Math.sin(fc_ry);
_array[2] = Math.cos(fc_rx);
_array[3] = Math.sin(fc_rx);
_array[4] = Math.cos(fc_rz);
_array[5] = Math.sin(fc_rz);
_array[6] = fc_dz;
}

for (j = 0; j<data_array[i][2].length; j++) {
data_array[i][2][j] = Math3D.affine(data_array[i][2][j][0], data_array[i][2][j][1], data_array[i][2][j][2], _array);
}
}

//clipping
var dispcount_num:int = new int(0);
var vp_difference_num:Number = new Number(vpcutpoint_num-Math3D.vp);
for (i = 0; i<data_array.length; i++) {
var ar_array:Array= new Array();
for (j = 0; j<data_array[i][2].length; j++) {
if (data_array[i][2][j][2]<vp_difference_num) {
for (var k:int = 0; k<2; k++) {
var m:int = (data_array[i][2].length-1+j+2*k)%data_array[i][2].length;
var n:int = j%data_array[i][2].length;
if (data_array[i][2][m][2]>vp_difference_num) {
var n_wariai:Number = (vp_difference_num-data_array[i][2][n][2])/(data_array[i][2][m][2]-data_array[i][2][n][2]);
var n_repointx:Number = (data_array[i][2][m][0]-data_array[i][2][n][0])*n_wariai+data_array[i][2][n][0];
var n_repointy:Number = (data_array[i][2][m][1]-data_array[i][2][n][1])*n_wariai+data_array[i][2][n][1];
ar_array.push([n_repointx, n_repointy, vp_difference_num]);
}
}
} else {
ar_array.push(data_array[i][2][j]);
}
}
if(ar_array.length < 1){
data_array[i][1][0] = "culled";
}else{
data_array[i][2] = ar_array.concat();
}
}

//normal
for (i = 0; i<data_array.length; i++) {
if(data_array[i][1][0] == "culled"){
continue;
}

var n_cx:Number = (data_array[i][2][1][1]-data_array[i][2][0][1])*(data_array[i][2][2][2]-data_array[i][2][1][2])-(data_array[i][2][1][2]-data_array[i][2][0][2])*(data_array[i][2][2][1]-data_array[i][2][1][1]);
var n_cy:Number = (data_array[i][2][1][2]-data_array[i][2][0][2])*(data_array[i][2][2][0]-data_array[i][2][1][0])-(data_array[i][2][1][0]-data_array[i][2][0][0])*(data_array[i][2][2][2]-data_array[i][2][1][2]);
var n_cz:Number = (data_array[i][2][1][0]-data_array[i][2][0][0])*(data_array[i][2][2][1]-data_array[i][2][1][1])-(data_array[i][2][1][1]-data_array[i][2][0][1])*(data_array[i][2][2][0]-data_array[i][2][1][0]);
var n_clxyz:Number = lightpoz_array[0]*n_cx+lightpoz_array[1]*n_cy+lightpoz_array[2]*n_cz;
var n_cxyz:Number = Math.sqrt(n_cx*n_cx+n_cy*n_cy+n_cz*n_cz);
var n_lxyz:Number = Math.sqrt(lightpoz_array[0]*lightpoz_array[0]+lightpoz_array[1]*lightpoz_array[1]+lightpoz_array[2]*lightpoz_array[2]);
data_array[i][1][1] = Math.floor((Math.acos(n_clxyz/(n_cxyz*n_lxyz))/Math.PI)*256);

for (j = 0; j<data_array[i][2].length; j++) {
data_array[i][0] += data_array[i][2][j][2]/data_array[i][2].length;
}
data_array[i][0] -=7000;
}
///pertrance
for (i = 0; i<data_array.length; i++) {
if(data_array[i][1][0] == "culled"){
continue;
}
for (j = 0; j<data_array[i][2].length; j++) {
data_array[i][2][j] = Math3D.pertrans(data_array[i][2][j][0], data_array[i][2][j][1], data_array[i][2][j][2]);
}
}
//sort
var z_array:Array = Math3D.zSort(data_array);

//render
for (i =0;i < mcnum_num; i++) {
sprits[i].graphics.clear();
}

// Spriteインスタンスへの矩形の描画
mcnum_num = data_array.length
for (k = 0; k < mcnum_num; k++) {
i = z_array[k]
if(data_array[i][1][0] == "culled"){
continue;
}
//trace(data_array[i][1][1]);
sprits[k].graphics.lineStyle(1,0xFF0000,1);
//sprits[k].graphics.beginFill(data_array[i][1][1]*65793,0.7);
sprits[k].graphics.beginFill(data_array[i][1][1]<<16,0.7);
sprits[k].graphics.moveTo(data_array[i][2][0][0],data_array[i][2][0][1]);
for (j = 1; j<data_array[i][2].length; j++) {
sprits[k].graphics.lineTo(data_array[i][2][j][0],data_array[i][2][j][1]);
}
}
}

//addEventListener類
addEventListener(Event.ENTER_FRAME, ENTER_FRAME);
function ENTER_FRAME(e:Event):void {
n_rx += (stage.mouseY – stageHeight / 2) / 10000;
n_ry += (stage.mouseX – stageWidth / 2) / 10000;
lightpoz_array[0] = stage.mouseX – stageWidth / 2;
lightpoz_array[1] = stage.mouseY – stageHeight / 2;
fc_create(n_dx, n_dy, n_dz, n_rx, n_ry, n_rz);
}

addEventListener( MouseEvent.MOUSE_WHEEL , MOUSE_WHEEL );
function MOUSE_WHEEL( event:MouseEvent ):void{
Math3D.vp += event.delta*3;
lightpoz_array[2] = Math3D.vp;
}

stage.addEventListener( KeyboardEvent.KEY_DOWN , KEY_DOWN );
function KEY_DOWN( event:KeyboardEvent ):void {
if(event.keyCode == 38){
n_dz -= 5;
}else if(event.keyCode == 40){
n_dz += 5;
}
}

}
}
}

class Math3D {
static public function zSort(pt_array:Array):Array{
var len:int = pt_array.length;
var sorter_array:Array = [];
for (var i:int = 0; i<len; i++) {
sorter_array[i] = 10000-pt_array[i][0];
}
return sorter_array.sort(Array.NUMERIC | Array.RETURNINDEXEDARRAY);// | Array.DESCENDING
}
public static var vp:Number = 300;
public static function pertrans(arg_x_num:Number, arg_y_num:Number, arg_z_num:Number):Array {
var _per:Number = vp/(vp+arg_z_num);
return [arg_x_num*_per, arg_y_num*_per, _per*100];
}
public static function affine(x:Number, y:Number, z:Number, arg_array:Array):Array {
var n_cx:Number = arg_array[0];
var n_sx:Number = arg_array[1];
var n_cy:Number = arg_array[2];
var n_sy:Number = arg_array[3];
var n_cz:Number = arg_array[4];
var n_sz:Number = arg_array[5];
var _array:Array = new Array(3);
_array[0] = x*(n_cz*n_cy+n_sy*n_sx*n_sz)+y*(-n_sz*n_cy+n_sy*n_sx*n_cz)+z*(n_sy*n_cx);
_array[1] = x*(n_cx*n_sz)+y*n_cx*n_cz-z*(n_sx);
_array[2] = x*(-n_sy*n_cz+n_cy*n_sx*n_sz)+y*(n_sy*n_sz+n_cy*n_sx*n_cz)+z*(n_cy*n_cx)+arg_array[6];;
return _array;
}
public static function arraycopy(copy_array:Array):Array {
var _array:Array = new Array();
var i_array:Array = new Array();
var length:int = copy_array.length;
for(var i:int= 0;i<length;i++){
i_array[0] = copy_array[i][0];
i_array[1] = copy_array[i][1].concat();
var j_array:Array = new Array();
for(var j:int= 0;j<copy_array[i][2].length;j++){
j_array[j] = copy_array[i][2][j].concat();
}
i_array[2] = j_array.concat();
_array[i] = i_array.concat();
}
return _array
}
}
[/sourcecode]