双曲放物面
forked from Checkmate Vol.6 Professional (diff: 160)
@gupon 氏のコードをだいぶ拝借しています。
ActionScript3 source code
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/dpdQ
*/
// forked from checkmate's Checkmate Vol.6 Professional
package {
import flash.events.*;
import flash.geom.*;
import flash.display.*;
import flash.text.*;
// @gupon 氏のコードをだいぶ拝借しています。
[SWF(backgroundColor="#997777")]
public class CheckmateProfessional extends Sprite {
private var _matWorld : Matrix3D;
private var _matView : Matrix3D;
private var _proj : PerspectiveProjection;
private var _viewport : Shape;
private var _vertices : Vector.<Number>;
private var _indices : Vector.<int>;
private var _uvtData : Vector.<Number>;
private var _tf : TextField;
public function CheckmateProfessional() {
_viewport = new Shape();
_viewport.x = stage.stageWidth / 2;
_viewport.y = stage.stageHeight / 2;
addChild(_viewport);
_proj = new PerspectiveProjection();
_proj.fieldOfView = 60;
_proj.focalLength = 300;
_matWorld = new Matrix3D();
_matView = new Matrix3D();
_matView.appendRotation(0, Vector3D.X_AXIS);
_matView.appendTranslation(0, 0, 100);
init();
_tf = new TextField();
_tf.width = 465;
addChild(_tf);
// addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
render();
}
private function onMouseMove(e : MouseEvent) : void
{
var theta : Number = (stage.mouseX - 465 / 2) * 0.003;
var phi : Number = (stage.mouseY - 465 / 2) * 0.005;
_matView = new Matrix3D();
_matView.appendRotation(phi * 180 / Math.PI, Vector3D.X_AXIS);
_matView.appendRotation(theta * 180 / Math.PI, Vector3D.Y_AXIS);
_matView.appendTranslation(0, 0, 100);
render();
}
private const LIM : Number = 15;
private const STEP : Number = 0.6;
private function init() : void
{
_vertices = new Vector.<Number>();
_uvtData = new Vector.<Number>();
for(var x : Number = -LIM;x <= LIM;x+=STEP){
for(var y : Number = -LIM;y <= LIM;y+=STEP){
_vertices.push(x * 3, f(x, y), y * 3.5);
// _uvtData.push(1, 1, 1);
}
}
_indices = new Vector.<int>();
var nx : int = (LIM - (-LIM)) / STEP + 1;
var ny : int = (LIM - (-LIM)) / STEP + 1;
for(var i : int = 0;i < nx - 1;i++){
for(var j : int = 0;j < ny - 1;j++){
// _indices.push(i * ny + j, i * ny + j + 1, (i + 1) * ny + j);
// _indices.push((i + 1) * ny + j, i * ny + j + 1, (i + 1) * ny + j + 1);
_indices.push(i * ny + j, (i + 1) * ny + j, i * ny + j + 1);
_indices.push((i + 1) * ny + j, (i + 1) * ny + j + 1, i * ny + j + 1);
}
}
}
private static function f(x : Number, y : Number) : Number
{
// x * x - y * y + 2 * z = 1
return -0.5 * (1 - x * x + y * y);
}
private function onEnterFrame(e : Event) : void
{
}
private function sortIndices(indices : Vector.<int>, uvtData : Vector.<Number>) : Vector.<int>
{
var triangles : Array = [];
for(var i : int = indices.length/3-1;i >=0;i--){
var i1 : int = indices[3*i];
var i2 : int = indices[3*i+1];
var i3 : int = indices[3*i+2];
var t : Number = Math.min(uvtData[3*i1+2], uvtData[3*i2+2], uvtData[3*i3+2]);
if(t < 0)continue;
triangles[i] = [
t,
i1, i2, i3
];
}
triangles.sortOn("0", Array.NUMERIC);
var ret : Vector.<int> = new Vector.<int>(triangles.length*3);
for(i = triangles.length-1;i >= 0;i--){
ret[3*i] = triangles[i][1];
ret[3*i+1] = triangles[i][2];
ret[3*i+2] = triangles[i][3];
}
return ret;
}
private function render() : void
{
var m : Matrix3D = new Matrix3D();
// m.append(_matWorld);
m.append(_matView);
m.append(_proj.toMatrix3D());
var l : int = _indices.length / 3;
var projected : Vector.<Number> = new Vector.<Number>();
Utils3D.projectVectors(m, _vertices, projected, _uvtData);
var sortedIndices : Vector.<int> = sortIndices(_indices, _uvtData);
var g : Graphics = _viewport.graphics;
g.clear();
for(var i : int = 0;i < l;i++){
var va : Vector3D = new Vector3D(
_vertices[3*sortedIndices[3*i]] - _vertices[3*sortedIndices[3*i+1]],
_vertices[3*sortedIndices[3*i]+1] - _vertices[3*sortedIndices[3*i+1]+1],
_vertices[3*sortedIndices[3*i]+2] - _vertices[3*sortedIndices[3*i+1]+2]
);
var vb : Vector3D = new Vector3D(
_vertices[3*sortedIndices[3*i]] - _vertices[3*sortedIndices[3*i+2]],
_vertices[3*sortedIndices[3*i]+1] - _vertices[3*sortedIndices[3*i+2]+1],
_vertices[3*sortedIndices[3*i]+2] - _vertices[3*sortedIndices[3*i+2]+2]
);
var vo : Vector3D = new Vector3D(
_vertices[3*sortedIndices[3*i]] - 0,
_vertices[3*sortedIndices[3*i]+1] - (30),
_vertices[3*sortedIndices[3*i]+2] - (-30)
);
var n : Vector3D = va.crossProduct(vb);
var light : Number = n.dotProduct(vo) / vo.length / n.length / vo.lengthSquared * 700;
var d : int = 256 * light;
if(d >= 256)d = 255;
if(d < 0)d = 0;
g.beginFill(d << 16 | d << 8 | d);
g.moveTo(projected[2*sortedIndices[3*i]], projected[2*sortedIndices[3*i]+1]);
g.lineTo(projected[2*sortedIndices[3*i+1]], projected[2*sortedIndices[3*i+1]+1]);
g.lineTo(projected[2*sortedIndices[3*i+2]], projected[2*sortedIndices[3*i+2]+1]);
g.lineTo(projected[2*sortedIndices[3*i]], projected[2*sortedIndices[3*i]+1]);
g.endFill();
}
// g.drawTriangles(projected, _indices);
}
}
}