Archive for 十一月, 2010


前段时间弄3D的时候没太闹明白投影矩阵是怎么解出视锥体的,如何最快判断一个顶点是否处于视锥体之内(也就是这个顶点是否可见)?

直到看了一篇文章《Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix》才恍然大悟。

道理其实很简单,想象一下视锥体的8个顶点经过投影之后会落在哪里?

没错,就是视口的四角,视锥体的LEFT,RIGHT,TOP,BOTTOM四个超平面投影之后实际就是视口的上下左右四条边界。

那么要判断一个顶点是否可见,只要求出投影之后的顶点是否落在这个范围之内就可以了。

有启发意义的原文如下:

After this transformation, the vertex v ‘ is in homogeneous clipping space. In this space the viewing frustum actually

is an axis-aligned box whose size is API-specific. If vertex v ‘ is inside this box, then the untransformed vertex v is

inside the ‘untransformed’ viewing frustum.

原文链接

中译文链接

近乎完美的AS3枚举

AS3不支持枚举类型,所以通常的做法是把静态常量用作枚举,像这样:
类的枚举
不过这个方法有点麻烦:用的时候要写类名和一个点。

其实我们可以用包级常量来解决这个问题。

包级常量这个东西听起来挺陌生的,不过你记得像setInterval(), navigateToURL()那样的函数么?

没错,只要import了就可以这样写:

navigateToURL(“www.site.com”);

包级常(变)量也是一个道理。

AS3中定义一个包级变量的格式如下:

变量名.as

package [包名]
{
	[命名空间][限定符] var|const 变量名[:类型][赋值语句];
}

这里举个颜色的例子说明一下,我们要定义一组颜色的枚举,有红色,绿色和蓝色。

首先,建立一个叫colors的包,然后声明一个颜色类Color:

package colors
{
	/**
	 * @author Cz
	 */
	public final class Color
	{
		// 色彩代码
		private var _code : uint;
		
		/**
		 * @param k 传递一个包内部对象用作限定,防止在包外生成实例。
		 */
		public function Color(k : Object, code : uint)
		{
			if (k != KEY)
			{
				throw "只能在Colors包内定义颜色枚举。";
			}
			_code = code;
		}

		public function get code() : uint
		{
			return _code;
		}
	}
}

注意这里有个用作限定的参数k,它是一个只能包内访问的包级常量,我们这样定义它:

package colors
{
	/**
	 * @author Cz
	 */
	internal const KEY : Object = new Object();
}

这个internal属性能限制不让包外的对象访问到它,因此也就不能在Colors包外构造枚举了。
下面开始定义具体的颜色:
colors/RED.as

package colors
{
	/**
	 * @author Cz
	 */
	public const RED : Color = new Color(KEY, 0xff0000);
}

colors/GREEN.as

package colors
{

	/**
	 * @author Cz
	 */
	public const GREEN : Color = new Color(KEY, 0x00ff00);
}

接下来是colors/BLUE.as

package colors
{

	/**
	 * @author Cz
	 */
	public const BLUE: Color = new Color(KEY, 0x0000ff);
}

最后测试一下:

package
{
	import colors.BLUE;
	import colors.Color;
	import colors.GREEN;
	import colors.RED;

	import flash.display.Sprite;

	/**
	 * @author Cz
	 */
	public class Main extends Sprite
	{
		public function Main()
		{
			fillColor(RED);
			// fillColor(GREEN)
			// fillColor(BLUE)
		}

		private function fillColor(c : Color) : void
		{
			graphics.beginFill(c.code);
			graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
			graphics.endFill();
		}
	}
}

欢迎扔砖:)
源码在这里