Modifying the vertices 頂点の変更
Transforming an arc into a flat piece of paper.
弧(こ)を薄い紙に引き伸ばしたようなもの。
/**
* Copyright GreekFellows ( http://wonderfl.net/user/GreekFellows )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/nz6T
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Vector3D;
/**
* ...
* @author greekfellows
*/
public class Main extends Sprite
{
public var renderer:Renderer;
public var canvas:Sprite;
public var core:Sprite;
public var verts:Array;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
this.x = 465 / 2;
this.y = 465 / 2;
canvas = this;
core = new Sprite();
core.z = 0;
renderer = new Renderer(canvas, core);
var diameter:int = 400;
var unit:int = 10;
for (var ver:int = 0; ver < diameter; ver += unit) {
for (var hor:int = 0; hor < diameter; hor += unit) {
renderer.addNewTriangle(
new Vector3D(hor - diameter / 2, ver - diameter / 2, 0),
new Vector3D(hor + unit - diameter / 2, ver - diameter / 2, 0),
new Vector3D(hor + unit - diameter / 2, ver + unit - diameter / 2, 0),
ver * 1000000
);
renderer.addNewTriangle(
new Vector3D(hor - diameter / 2, ver - diameter / 2, 0),
new Vector3D(hor - diameter / 2, ver + unit - diameter / 2, 0),
new Vector3D(hor + unit - diameter / 2, ver + unit - diameter / 2, 0),
ver * 1000000
);
}
}
verts = [];
for (var i:int = 0; i < renderer.vertices.length; i++) {
verts.push(renderer.vertices[i].clone());
renderer.vertices[i] = new Vector3D(Math.cos(i / renderer.vertices.length * 360 * Math.PI / 180) * 200, Math.sin(i / renderer.vertices.length * 360 * Math.PI / 180) * 200, Math.cos(i / renderer.vertices.length * 360 * Math.PI / 180) * 200);
}
stage.quality = "low";
this.addEventListener(Event.ENTER_FRAME, stuff);
}
public function stuff(e:Event):void {
core.rotationY += mouseX / 100;
core.rotationX += mouseY / 100;
renderer.render();
for (var ti:int = 0; ti < renderer.vertices.length; ti++) {
renderer.vertices[ti].x += (verts[ti].x - renderer.vertices[ti].x) / 100;
renderer.vertices[ti].y += (verts[ti].y - renderer.vertices[ti].y) / 100;
renderer.vertices[ti].z += (verts[ti].z - renderer.vertices[ti].z) / 100;
}
}
}
}
import flash.display.Sprite;
import flash.geom.Vector3D;
/**
* ...
* @author greekfellows
*/
dynamic class Renderer
{
public var canvas:Sprite;
public var core:Sprite;
public var triangles:Array;
public var vertices:Array;
private const dist:int = 500;
public function Renderer(canvas:Sprite, core:Sprite)
{
this.canvas = canvas; // to draw the thing on
this.core = core; // to render the stuff (we use this guy's transformation matrix)
this.triangles = []; // to initialize the triangles array
this.vertices = []; // to initialize the vertices array
}
// basic functions
public function addNewTriangle(v1:Vector3D, v2:Vector3D, v3:Vector3D, color:uint):void {
var i1:int = -1;
var i2:int = -1;
var i3:int = -1;
for (var vi:int = 0; vi < vertices.length; vi++) {
if (v1.equals(vertices[vi])) {
i1 = vi;
}
if (v2.equals(vertices[vi])) {
i2 = vi;
}
if (v3.equals(vertices[vi])) {
i3 = vi;
}
if (i1 != -1 && i2 != -1 && i3 != -1) {
break;
}
}
if (i1 == -1) {
vertices.push(v1);
i1 = vertices.length - 1;
}
if (i2 == -1) {
vertices.push(v2);
i2 = vertices.length - 1;
}
if (i3 == -1) {
vertices.push(v3);
i3 = vertices.length - 1;
}
triangles.push( {
v1:i1, // the first vertex
v2:i2, // the second vertex
v3:i3, // the third vertex
color:color // the color to fill the triangle
} );
}
// render
public function render():void {
var sorted:Array = []; // for sorting the triangles
for (var ti:int = 0; ti < triangles.length; ti++) {
// for every triangle
var v1:Vector3D = vertices[triangles[ti].v1].clone(); // the first vertex
var v2:Vector3D = vertices[triangles[ti].v2].clone(); // the second vertex
var v3:Vector3D = vertices[triangles[ti].v3].clone(); // the third vertex
var vc:Vector3D = new Vector3D((v1.x + v2.x + v3.x) / 3, (v1.y + v2.y + v3.y) / 3, (v1.z + v2.z + v3.z) / 3); // the barycenter
// transform the vertices
v1 = core.transform.matrix3D.transformVector(v1);
v2 = core.transform.matrix3D.transformVector(v2);
v3 = core.transform.matrix3D.transformVector(v3);
vc = core.transform.matrix3D.transformVector(vc);
// set the 'w' property of the vertices and project them to a 2D surface
// dist is for distortion - larger; then less distortion - smaller; then more distortion
v1.w = (v1.z + dist) / dist;
v2.w = (v2.z + dist) / dist;
v3.w = (v3.z + dist) / dist;
v1.project();
v2.project();
v3.project();
// add the following values into the sorted array
sorted.push( {
v1:v1, // the first transformed vertex
v2:v2, // the second transformed vertex
v3:v3, // the third transformed vertex
z:vc.z, // the depth position of the transformed barycenter
color:triangles[ti].color // the color
} );
}
// sort
sorted.sortOn("z", Array.NUMERIC | Array.DESCENDING);
// draw them out!
canvas.graphics.clear();
for (var di:int = 0; di < sorted.length; di++) {
canvas.graphics.beginFill(sorted[di].color, 1);
canvas.graphics.moveTo(sorted[di].v1.x, sorted[di].v1.y);
canvas.graphics.lineTo(sorted[di].v2.x, sorted[di].v2.y);
canvas.graphics.lineTo(sorted[di].v3.x, sorted[di].v3.y);
canvas.graphics.lineTo(sorted[di].v1.x, sorted[di].v1.y);
canvas.graphics.endFill();
canvas.graphics.beginFill(0x000000, (sorted[di].z + 100) / 300);
canvas.graphics.moveTo(sorted[di].v1.x, sorted[di].v1.y);
canvas.graphics.lineTo(sorted[di].v2.x, sorted[di].v2.y);
canvas.graphics.lineTo(sorted[di].v3.x, sorted[di].v3.y);
canvas.graphics.lineTo(sorted[di].v1.x, sorted[di].v1.y);
canvas.graphics.endFill();
}
}
}