上記の広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書く事で広告が消せます。
Yahoo!ブックマーク はてなブックマーク livedoorClip FC2 Buzzurl 
--.--.-- -- l スポンサー広告 l top
今回はラップアラウンド処理を実装しました。
ラップアラウンド処理は範囲の終端に達した場合に先端に巻き戻す処理です。
画像のフィルタ処理やパーティクルの空間処理など様々な場面に利用可能です。

wraparound
float wraparound( float Value, float Begin, float End )
{
	float dist = End - Begin;
	Value -= Begin;
	Value -= int( Value / dist ) * dist;
	long ofs = ( *(long*)&Value >> 31 ) & *(long*)&dist;
	return Value + *(float*)&ofs + Begin;
}
Yahoo!ブックマーク はてなブックマーク livedoorClip FC2 Buzzurl 
2010.06.13 Sun l 算術 l コメント (1) トラックバック (0) l top
参照テーブルを使用してサイン・コサイン関数を高速化してみました。
サンプル間を線形補間することで少ないサンプル数で精度を高めています。
テーブル生成のコードは以下のようになります。

init_sincosLUT
struct SINCOSCOEFFICIENT
{
	float	Value;
	float	Gradient;
};

SINCOSCOEFFICIENT	sincosLUT[ 0x100 ];
#define TWO_PI		6.2831853071795864

void init_sincosLUT( void )
{
	double t[ 0x100 ];
	for( int i = 0; i < 0x100; i++ )
		t[ i ] = sin( (double)i / 256 * TWO_PI );
	for( int i = 0; i < 0x100; i++ )
	{
		sincosLUT[ i ].Value    = (float)t[ i ];
		sincosLUT[ i ].Gradient = (float)( ( t[ ( i + 1 ) & 0xFF ] - t[ i ] ) / 65536 );
	}
}
作成されたテーブルを利用したサイン・コサイン関数は以下のようになります。

sinFast
inline float sinFast( float Angle )
{
	Angle /= TWO_PI;
	Angle -= (int)Angle;
	int index = int( Angle * 16777216.0f ) & 0x00FFFFFF;
	const SINCOSCOEFFICIENT& coef = sincosLUT[ index >> 16 ];
	return ( coef.Value + coef.Gradient * float( index & 0xFFFF ) );
}
cosFast
inline float cosFast( float Angle )
{
	Angle /= TWO_PI;
	Angle -= (int)Angle;
	int index = int( Angle * 16777216.0f + 4194304.0f ) & 0x00FFFFFF;
	const SINCOSCOEFFICIENT& coef = sincosLUT[ index >> 16 ];
	return ( coef.Value + coef.Gradient * (float)( index & 0xFFFF ) );
}
また、サイン・コサインを同時に生成する関数は以下のようになります。
sincosFast
inline void sincosFast( float Angle, float* pSin, float* pCos )
{
	Angle /= TWO_PI;
	Angle -= (int)Angle;
	int   index = int( Angle * 16777216.0f ) & 0x00FFFFFF;
	float delta = float( index & 0xFFFF );
	index >>= 16;
	const SINCOSCOEFFICIENT& sincoef = sincosLUT[ index ];
	const SINCOSCOEFFICIENT& coscoef = sincosLUT[ ( index + 0x40 ) & 0xFF ];
	*pSin = sincoef.Value + sincoef.Gradient * delta;
	*pCos = coscoef.Value + coscoef.Gradient * delta;
}
Yahoo!ブックマーク はてなブックマーク livedoorClip FC2 Buzzurl 
2010.05.31 Mon l 算術 l コメント (0) トラックバック (0) l top
今回は浮動小数点の剰余計算関数を実装しました。
剰余計算関数は対象となる数値を指定した値で割った剰余を求めます。
以下の関数は CRT の fmodf 関数に比べ高速に動作します。

modf
inline float modf( float X, float Y )
{
	return ( X - int( X / Y ) * Y );
}
Yahoo!ブックマーク はてなブックマーク livedoorClip FC2 Buzzurl 
2010.05.29 Sat l 算術 l コメント (0) トラックバック (0) l top
ランダムな単位ベクトルはパーティクルやオブジェクトの方向ベクトルやサンプリング用のレイなど様々な場面で使用されます。これらはリアルタイムで大量に処理する場合も多く、処理速度が重要になります。
最も単純な生成手法は 3 つの乱数から生成されたベクトルを正規化することです。しかし、この手法はベクトルに偏りがあり、さらに非常に稀ですが零ベクトルのような正規化できないベクトルが生成される可能性もあります。
より良い手法は乱数からヨー・ピッチ角を生成しベクトルに変換します。

randUnitVector
#define PI	3.141592654f

struct vector3
{
	float	x;
	float	y;
	float	z;
};

void randUnitVector( vector3* pOut, random_generator & Rand )
{
	uint32_t value = Rand();
	uint32_t theta;
	float sin, cos;
	// pitch
	theta = ( value & 0xFFFF0000 );
	theta = ( theta >> 9 ) | ( theta >> 25 ) | 0x40000000;
	sincos( ( *(float*)&theta - 3.0f ) * PI, &sin, &cos );
	pOut->x = cos;
	pOut->y = cos;
	pOut->z = -sin;
	// yaw
	theta = ( value & 0x0000FFFF );
	theta = ( theta << 7 ) | ( theta >> 9 ) | 0x40000000;
	sincos( ( *(float*)&theta - 3.0f ) * PI, &sin, &cos );
	pOut->x *= cos;
	pOut->y *= sin;
}
32 ビットの乱数を 16 ビットの 2 つの乱数 ( ヨー・ピッチ角 ) として使用することにより高速化しています。この関数で生成した単位ベクトルは偏りが無く、正規化も不要になります。
Yahoo!ブックマーク はてなブックマーク livedoorClip FC2 Buzzurl 
2010.05.21 Fri l 乱数 l コメント (0) トラックバック (0) l top
FPU 命令の1つである fsincos はサインとコサインを同時に計算します。
今回のコードはインラインアセンブラで記述しています。
sin, cos 関数で別々に取得する場合に比べかなり高速です。

sincos
inline void sincos( float Radian, float* pSin, float* pCos )
{
	float c, s;
	__asm
	{
		fld		Radian
		fsincos
		fstp	c
		fstp	s
	}
	*pSin = s;
	*pCos = c;
}
Yahoo!ブックマーク はてなブックマーク livedoorClip FC2 Buzzurl 
2010.05.20 Thu l 算術 l コメント (0) トラックバック (0) l top