📄 texturelod.as
字号:
/**
* project3D Engine
* Material that subdivides its polygons according to distance and size to get better texture quality
* @author John Sword
* @version 2 - AS3
*/
package engine.materials
{
import engine.geom.Face;
import engine.geom.UV;
import engine.geom.Vertex;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.geom.Matrix;
public class TextureLOD extends Material
{
public var smooth:Boolean = false;
public var detail:int = 1;
public var maxdetail:int = 3;
public var fixedDetail:Boolean = false;
public var useWire:Boolean = false;
private static const abs:Function = Math.abs;
public function TextureLOD ( tex:BitmapData, flip:Boolean = true )
{
super( tex );
if(flip)
{
// flip texture
// needs a temp mc to apply the invert matrix
var texMc:Sprite = new Sprite();
var bmp:Bitmap = new Bitmap ( tex );
// apply texture to temp mc
texMc.addChild( bmp );
// apply invert
var textureMatrix:Matrix = new Matrix();
textureMatrix.a = 1;
textureMatrix.b = 0;
textureMatrix.c = 0;
textureMatrix.d = -1;
textureMatrix.tx = 0;
textureMatrix.ty = tex.height;
// recreate texture
texture = new BitmapData(texMc.width, texMc.height, true, 0x00000000);
texture.draw(texMc, textureMatrix);
} else {
texture = tex;
}
}
public override function render ( face:Face, screen:Sprite ) : void
{
if ( !fixedDetail ) {
//detail = Math.round( 1000/face.Z );
var x1:int = face.v1.screen.x;
var y1:int = face.v1.screen.y;
var x2:int = face.v2.screen.x;
var y2:int = face.v2.screen.y;
var x3:int = face.v3.screen.x;
var y3:int = face.v3.screen.y;
// area relative to distance
detail = abs(((x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1)) / face.Z);
//detail = (detail ^ (detail >> 31)) - (detail >> 31);
} else {
detail = maxdetail;
}
//trace(detail)
//wireAlpha = 1;
//wireColor = 0xFF0000;
if ( detail == 0 ) {
renderFace( face, screen );
} else {
if ( detail > maxdetail ) detail = maxdetail;
divide( face, screen, detail );
}
}
private function divide ( face:Face, screen:Sprite, level:int ) : void
{
var faces:Array = subdivide ( face );
if ( level > 0 ) level --;
var i:int = faces.length;
while ( --i > -1 )
{
if ( level > 0 )
{
divide ( faces[i], screen, level );
} else {
renderFace ( faces[i], screen );
}
}
}
private function subdivide ( face:Face ) : Array
{
/*
* subdivide and construct new triangles
* b
* /\
* / \
* ab/____\bc
* /\ /\
* / \ / \
* /____\/____\
* a ca c
*/
var ax:int = face.v1.screen.x;
var ay:int = face.v1.screen.y;
var az:int = face.v1.screen.z;
var bx:int = face.v2.screen.x;
var by:int = face.v2.screen.y;
var bz:int = face.v2.screen.z;
var cx:int = face.v3.screen.x;
var cy:int = face.v3.screen.y;
var cz:int = face.v3.screen.z;
var mabz:Number = 2 / (az + bz);
var mbcz:Number = 2 / (bz + cz);
var mcaz:Number = 2 / (cz + az);
var mabx:Number = (ax*az + bx*bz) * mabz;
var maby:Number = (ay*az + by*bz) * mabz;
var mbcx:Number = (bx*bz + cx*cz) * mbcz;
var mbcy:Number = (by*bz + cy*cz) * mbcz;
var mcax:Number = (cx*cz + ax*az) * mcaz;
var mcay:Number = (cy*cz + ay*az) * mcaz;
var abuv:UV = createMidUV( face.uv1, face.uv2 );
var bcuv:UV = createMidUV( face.uv2, face.uv3 );
var cauv:UV = createMidUV( face.uv3, face.uv1 );
//var m:Material = face.getMaterial();
var abvx:Number = mabx*.5;
var abvy:Number = maby*.5;
var abvz:Number = (az+bz)*.5;
var cavx:Number = mcax*.5;
var cavy:Number = mcay*.5;
var cavz:Number = (cz+az)*.5;
var bcvx:Number = mbcx*.5;
var bcvy:Number = mbcy*.5;
var bcvz:Number = (bz+cz)*.5;
var faces:Array = new Array();
faces.push( buildTri(ax,ay,az,abvx,abvy,abvz,cavx,cavy,cavz,
face.uv1,abuv,cauv, this) );
faces.push( buildTri(abvx,abvy,abvz,bx,by,bz,bcvx,bcvy,bcvz,
abuv,face.uv2,bcuv, this) );
faces.push( buildTri(cavx,cavy,cavz,bcvx,bcvy,bcvz,cx,cy,cz,
cauv,bcuv,face.uv3, this) );
faces.push( buildTri(cavx,cavy,cavz,abvx,abvy,abvz,bcvx,bcvy,bcvz,
cauv,abuv,bcuv, this) );
return faces;
}
private function buildTri ( x1:Number,y1:Number,z1:Number,
x2:Number,y2:Number,z2:Number,
x3:Number,y3:Number,z3:Number,
uv1:UV,uv2:UV,uv3:UV, m:Material ) : Face
{
var vtx1:Vertex = new Vertex();
var vtx2:Vertex = new Vertex();
var vtx3:Vertex = new Vertex();
vtx1.screen.x = x1;
vtx1.screen.y = y1;
vtx1.screen.z = z1;
vtx2.screen.x = x2;
vtx2.screen.y = y2;
vtx2.screen.z = z2;
vtx3.screen.x = x3;
vtx3.screen.y = y3;
vtx3.screen.z = z3;
return new Face ( vtx1, vtx2, vtx3, uv1, uv2, uv3, m );
}
private function renderFace ( face:Face, screen:Sprite ) : void
{
var g:Graphics = screen.graphics;
// Draw triangle
g.beginBitmapFill( texture, face.getTextureMatrix(), false, smooth );
if ( useWire ) g.lineStyle( wireSize, wireColor, wireAlpha);
g.moveTo( face.v1.screen.x, face.v1.screen.y );
g.lineTo( face.v2.screen.x, face.v2.screen.y );
g.lineTo( face.v3.screen.x, face.v3.screen.y );
}
private function createMidUV ( a:UV, b:UV ) : UV
{
return new UV ( ( a.u + b.u ) * .5, ( a.v + b.v ) * .5 );
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -