package
{
import flash.display.*;
import flash.events.*;
import org.papervision3d.view.BasicView;
import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.NumberUV;
import org.papervision3d.lights.*;
import org.papervision3d.materials.*;
import org.papervision3d.materials.special.*;
import org.papervision3d.materials.shadematerials.* ;
import org.papervision3d.materials.utils.*;
[SWF(width=600, height=500, backgroundColor=0x111111)]
public class Mesh extends BasicView
{
private var mesh:TriangleMesh3D=null;
private var landForm:LandForm;
private var pointLight:PointLight3D;
private var f:Number = 0;
public function Mesh()
{
stage.frameRate = 10;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.quality = StageQuality.MEDIUM;
super (0,0,true,false,"CAMERA3D");
init3D();
stage.addEventListener(MouseEvent.MOUSE_DOWN, buildMesh);
buildMesh();
}
public function init3D():void
{
camera.y = 100;
camera.z = -300;
camera.focus = 500;
camera.zoom = 8;
pointLight = new PointLight3D(true);
pointLight.y = 300;
startRendering();
}
override protected function onRenderTick(event:Event=null):void
{
f += 0.02;
pointLight.x = 100*Math.cos(f);
pointLight.z = 100*Math.cos(f);
mesh.rotationY += 0.1;
super.onRenderTick(event);
}
private function buildMesh(e:* = null):void
{
if(mesh)
scene.removeChild(mesh);
var mat:PhongMaterial = new PhongMaterial(pointLight, 0xcc5555, 0x111111, 1);
mesh = new TriangleMesh3D( mat, [], [], null );
scene.addChild(mesh);
landForm = new LandForm(128);
for(var i:int = 0 ; i < 6 ; i++)
landForm.split();
mesh.geometry.vertices = [];
mesh.geometry.faces = [];
for(var z:int = 0 ; z < landForm.length ; z++){
var vertices:Array = [];
for(var x:int = 0 ; x < landForm.length ; x++){
mesh.geometry.vertices.push(
new Vertex3D(landForm.scale*(x - ( landForm.length - 1)/2),
landForm.value(x,z),
landForm.scale*(z - (landForm.length - 1)/2)));
}
}
for(z = 0 ; z < landForm.length - 1; z++){
for(x = 0 ; x < landForm.length - 1; x++){
var uvA:NumberUV = new NumberUV( 0, 0 );
var uvC:NumberUV = new NumberUV( 1, 0 );
var uvB:NumberUV = new NumberUV( 0, 1 );
mesh.geometry.faces.push( new Triangle3D( mesh,
new Array(mesh.geometry.vertices[x * landForm.length + z],
mesh.geometry.vertices[x * landForm.length + z + 1],
mesh.geometry.vertices[(x+1) * landForm.length + z]),
null, new Array(uvC,uvB,uvA) ));
mesh.geometry.faces.push( new Triangle3D( mesh,
new Array(mesh.geometry.vertices[x * landForm.length + z + 1],
mesh.geometry.vertices[(x+1) * landForm.length + z + 1],
mesh.geometry.vertices[(x+1) * landForm.length + z]),
null, new Array(uvA,uvB,uvC) ));
}
}
mesh.geometry.ready = true;
}
}
}
internal class LandForm{
private var buffer:Array = new Array();
private var range:int ;
private var splitCnt:int = 0;
private var base:Number = 10;
// range は2の乗数であること
public function LandForm(range:int){
this.range = range;
clear();
}
public function clear():void{
buffer = [];
// 変位が格納される2次元配列(w*h)
for(var j:int = 0 ; j < range+1; j++){
var aa:Array = new Array();
for(var k:int = 0 ; k < range+1; k++)
aa.push(0);
buffer.push(aa);
}
buffer[0][0] = base*Math.random();
buffer[range][0] = base*2*Math.random();
buffer[0][range] = base*3*Math.random();
buffer[range][range] = base*4*Math.random();
//trace(buffer[128][128]);
}
public function split():void{
if(Math.pow(2,splitCnt) >= range){
splitCnt=0;
clear();
}
splitCnt++;
for(var x:int = 1 ; x < length ; x+=2){
for(var y:int = 1 ; y < length ; y+=2){
splitMidPoint(x, y);
}
}
}
private function splitMidPoint(x:int, y:int):void{
midPoint(x,y,true);
midPoint(x-1,y);
midPoint(x+1,y);
midPoint(x,y-1);
midPoint(x,y+1);
}
private function midPoint(x:int, y:int, squere:Boolean=false):void{
//trace(x.toString() + ":" + y.toString());
var sum:Array = [];
if(squere){
if(x > 0 && y > 0 && value(x-1,y-1) != 0 )
sum.push(value(x-1, y-1));
if(x > 0 && y < length-1 && value(x-1,y+1) != 0)
sum.push(value(x-1, y+1));
if(x < length - 1 && y > 0 && value(x+1,y-1) != 0)
sum.push(value(x+1, y-1));
if(x < length - 1 && y < length - 1 && value(x+1,y+1) != 0)
sum.push(value(x+1, y+1));
}else{ // diamonds
if(y > 0 && value(x,y-1) != 0)
sum.push(value(x, y-1));
if(x > 0 && value(x-1,y) != 0)
sum.push(value(x-1, y));
if(y < length - 1 && value(x,y+1) != 0)
sum.push(value(x, y+1));
if(x < length - 1 && value(x+1,y) != 0)
sum.push(value(x+1, y));
}
var sumOfHeight:Number = 0;
for each(var v:Number in sum)
sumOfHeight += v;
var avg:Number = sumOfHeight / sum.length ;
setValue(x,y, newHeight(avg));
}
private function newHeight(avg:Number):Number{
// return avg + (Math.random()*(Math.pow(2, - 0.3*splitCnt)));
return avg*(1 + (Math.random ()*2 - 1) * scale * 0.019);
}
public function get length():int{
return Math.pow(2, splitCnt) + 1;
}
public function get scale():int{
return range / Math.pow(2,splitCnt);
}
public function value(x:int, z:int):Number{
return buffer[x*scale][z*scale];
}
private function setValue(x:int, z:int, value:Number):void{
buffer[x*scale][z*scale] = value;
}
}
Author:yamasv@gmail.com
コメント、トラックバック、リンクはお気軽に
-->
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
|---|---|---|---|---|---|---|
| - | - | - | - | - | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 | - | - | - | - | - | - |