📄 face.as
字号:
/**
* project3D Engine
* @author John Sword
* @version 2 - AS3
*/
/*
* Based on Papervision's Face class
* papervision3d.org • blog.papervision3d.org • osflash.org/papervision3d
* Copyright 2006 (c) Carlos Ulloa Matesanz, noventaynueve.com.
*/
package engine.geom
{
import engine.materials.Material;
import engine.objects.Object3D;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Matrix;
public class Face
{
/**
* An array of Vertex objects for the three vertices of the triangle.
*/
//public var vertices :Array;
public var v1:Vertex;
public var v2:Vertex;
public var v3:Vertex;
/**
* An array of {x,y} objects for the corresponding UV pixel coordinates of each triangle vertex.
*/
//public var uvs:Array;
public var uv1:UV;
public var uv2:UV;
public var uv3:UV;
/**
* [read-only] The average depth (z coordinate) of the transformed triangle.
* Also known as the distance from the camera.
* Used internally for z-sorting.
*/
public var Z:Number;
/**
* [read-only] A Boolean value that indicates that the face is visible,
* i.e. it's vertices are in front of the camera.
*/
public var visible:Boolean = false;
private var material:Material;
private var matrix:Matrix = new Matrix();
private var _a:Number;
private var _b:Number;
private var _c:Number;
private var _d:Number;
private var _tx:Number;
private var _ty:Number;
private var x0:Number;
private var y0:Number;
private var x1:Number;
private var y1:Number;
private var x2:Number;
private var y2:Number;
/**
* The Face constructor
*/
public function Face ( v1:Vertex,v2:Vertex,v3:Vertex,uv1:UV,uv2:UV,uv3:UV,m:Material )
{
// Vertices
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
// uvs
//uvs = uv;
this.uv1 = uv1;
this.uv2 = uv2;
this.uv3 = uv3;
// Material
this.material = m;
// set texture if needed
if( material.texture )
{
// set vertices x,y positions
x0 = v1.screen.x;
y0 = v1.screen.y;
x1 = v2.screen.x;
y1 = v2.screen.y;
x2 = v3.screen.x;
y2 = v3.screen.y;
transformUV ( material.texture );
}
}
/**
* Applies the updated UV texture mapping values to the triangle. This is required to speed up rendering.
*
*/
public function transformUV ( texture:BitmapData ) : void
{
try {
if( texture )
{
var w :Number = texture.width;
var h :Number = texture.height;
var uu0 :Number = uv1.u * w;
var vv0 :Number = uv1.v * h;
var uu1 :Number = uv2.u * w;
var vv1 :Number = uv2.v * h;
var uu2 :Number = uv3.u * w;
var vv2 :Number = uv3.v * h;
// Fix perpendicular projections
if( (uu0 == uu1 && vv0 == vv1) || (uu0 == uu2 && vv0 == vv2) )
{
uu0 -= (uu0 > 0.05)? 0.05 : -0.05;
vv0 -= (vv0 > 0.07)? 0.07 : -0.07;
}
if( uu2 == uu1 && vv2 == vv1 )
{
uu2 -= (uu2 > 0.05)? 0.04 : -0.04;
vv2 -= (vv2 > 0.06)? 0.06 : -0.06;
}
// Precalculate matrix
var at :Number = ( uu1 - uu0 );
var bt :Number = ( vv1 - vv0 );
var ct :Number = ( uu2 - uu0 );
var dt :Number = ( vv2 - vv0 );
var m :Matrix = new Matrix( at, bt, ct, dt, uu0, vv0 );
m.invert();
_a = m.a;
_b = m.b;
_c = m.c;
_d = m.d;
_tx = m.tx;
_ty = m.ty;
}
} catch (e:Error) {}
}
/**
* draws faces
*
* @param screen default screen
* @return an object under the mouse pointer
*
*/
public function render ( screen:Sprite ) : Object3D
{
material.render ( this, screen );
if ( v1.o )
{
// detect if mouse is inside poly
if ( intersects( screen.mouseX, screen.mouseY ) )
{
return v1.o;
}
}
return null;
}
private function intersects ( xpos:Number, ypos:Number ) : Boolean
{
//trace( xpos )
//trace( ypos )
//trace("");
//if ( !xpos && !ypos ) return false;
// The ray's begining point
var origin:Vector = new Vector(xpos,ypos,0);
// The direction of the ray into infinity (or a very large number)
var direction:Vector = new Vector(xpos,ypos,1000000);
// compute distances' vectors
var diff:Vector = origin.subtract(v1.screen);
var edge1:Vector = v2.screen.subtract(v1.screen);
var edge2:Vector = v3.screen.subtract(v1.screen);
var norm:Vector = edge1.cross ( edge2 );
var dirDotNorm:Number = direction.dot(norm);
var sign:Number;
if (dirDotNorm > 1) {
sign = 1;
} else if (dirDotNorm < -1) {
sign = -1;
dirDotNorm = -dirDotNorm;
} else {
// ray and triangle are parallel
return false;
}
var dirDotDiffxEdge2:Number = sign * direction.dot(diff.cross(edge2));
if (dirDotDiffxEdge2 > 0) {
var dirDotEdge1xDiff:Number = sign * direction.dot(edge1.crossLocal(diff));
if (dirDotEdge1xDiff >= 0) {
if ( dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm ) {
var diffDotNorm:Number = -sign * diff.dot(norm);
if (diffDotNorm >= 0) {
// ray intersects triangle
var inv:Number = 1 / dirDotNorm;
var t:Number = diffDotNorm * inv;
var o:Object3D = v1.o;
o.pickFace = this;
// these weights are used to determine
// interpolated values, such as the texture coord.
// eg. texcoord s,t at intersection point:
// s = w0*s0 + w1*s1 + w2*s2;
// t = w0*t0 + w1*t1 + w2*t2;
var w1:Number = dirDotDiffxEdge2 * inv;
var w2:Number = dirDotEdge1xDiff * inv;
var w0:Number = 1 - w1 - w2;
// interpolate texture coordinates at point
o.pickUV.u = w0*uv1.u + w1*uv2.u + w2*uv3.u;
o.pickUV.v = w0*uv1.v + w1*uv2.v + w2*uv3.v;
//trace( "U: "+(u)+" V: "+(v));
// interpolate xyz position
o.pickPos.x = w0*v1.x + w1*v2.x + w2*v3.x;
o.pickPos.y = w0*v1.y + w1*v2.y + w2*v3.y;
o.pickPos.z = w0*v1.z + w1*v2.z + w2*v3.z;
//trace( o.pickPos )
return true;
}
}
}
}
return false;
}
public function getTextureMatrix () : Matrix
{
var a1:Number = _a,
b1 :Number = _b,
c1 :Number = _c,
d1 :Number = _d,
tx1 :Number = _tx,
ty1 :Number = _ty,
a2 :Number = x1 - x0,
b2 :Number = y1 - y0,
c2 :Number = x2 - x0,
d2 :Number = y2 - y0;
matrix.a = a1*a2 + b1*c2;
matrix.b = a1*b2 + b1*d2;
matrix.c = c1*a2 + d1*c2;
matrix.d = c1*b2 + d1*d2;
matrix.tx = tx1*a2 + ty1*c2 + x0;
matrix.ty = tx1*b2 + ty1*d2 + y0;
return matrix;
}
public function getMaterial () : Material
{
return material;
}
public function getMatrix () : Matrix
{
return matrix;
}
public function setVisible ( screen:Sprite, zc:int, fp:Boolean, c:Boolean ) : Boolean
{
visible = false;
// check if face vertices are all visible
//if ((v1.visible + v2.visible + v3.visible) >0)
//{
if (v1.visible && v2.visible && v3.visible)
{
// get screen size
var top:int = screen.y,
left:int = screen.x,
w:int = screen.width,
h:int = screen.height;
// get vertices x,y positions
x0 = v1.screen.x;
y0 = v1.screen.y;
x1 = v2.screen.x;
y1 = v2.screen.y;
x2 = v3.screen.x;
y2 = v3.screen.y;
// check if face is inside screen boundaries
if ( x0 < left && x1 < left && x2 < left ) return false;
if ( x0 > w && x1 > w && x2 > w ) return false;
if ( y0 < top && y1 < top && y2 < top ) return false;
if ( y0 > h && y1 > h && y2 > h ) return false;
// calculate average z position
Z = int(( v1.screen.z + v2.screen.z + v3.screen.z ) / 3);
if ( !c ) // check if object has culling faces
{
visible = true;
} else {
if ( fp ) // object has normals flipped
{
if ( ((x1 - x0)*(y2 - y0)-(y1 - y0)*(x2 - x0)) > 0 )
{
if (Z > zc) visible = true;
}
} else {
if ( ((x1 - x0)*(y2 - y0)-(y1 - y0)*(x2 - x0)) < 0 )
{
if (Z > zc) visible = true;
}
}
}
}
if ( visible ) {
return true;
}
return false;
}
/*
private function PntInTriangle (Px:Number, Py:Number, x1:Number, y1:Number, x2:Number, y2:Number, x3:Number, y3:Number) : Boolean
{
var Or1:int = Orientation(x1, y1, x2, y2, Px, Py);
var Or2:int = Orientation(x2, y2, x3, y3, Px, Py);
var Or3:int = Orientation(x3, y3, x1, y1, Px, Py);
return (Or1 == Or2) && (Or2 == Or3);
}
private function Orientation (x1:Number, y1:Number, x2:Number, y2:Number, Px:Number, Py:Number) : int
{
var Orin:Number = (x2 - x1) * (Py - y1) - (Px - x1) * (y2 - y1);
if (Orin > 0) return 1; // Orientation is to the right-hand side
else if (Orin < 0) return -1; // Orientation is to the left-hand side
return 0; // Orientation is neutral if result is 0
}
*/
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -