2008年02月08日

捨てるMSもあれば救うMSもあり関数を自作する。

D3DXの関数群を実装しないといけないわけだけれど
MS算術関数に式とかあったので
LookatとかPerspectiveFovとか問題なく自作できそうだ。
最初は一般ユーティリティにしようと思ったのだけれど結構多くなりそうなので独立のユニットにすることにした。
これでOpenGLに移行した場合でもgluを使わないとかできる。
実際はもっといろいろ作ったのだが話が散らばるので肝心なところだけ
表示系関数ではfloattostr的な感じも実装した。
今回はベタの言語、delphiは浮動小数点ユニットでの最適化のみだが
Singleだと効率が悪いはず
FPとかGCCだとSSE最適化してくれるので下手にアセンブラで書くよりいいだろうが
もちょっとどうにかしたいのが本音、
あと今回はOrthoはまだ入れていない。

PerspectiveFovLH

function PerspectiveFovLH(out mOut: SMatrixf; fovy, aspect, zn, zf: Single): PSMatrixf; //
var
ysc,xsc,f1:Extended;
begin
(*
ySc = cot(fovY/2)
xSc = yScale / aspect ratio

xSc 0 0 0
0 ySc 0 0
0 0 zf/(zf-zn) 1
0 0 -zn*zf/(zf-zn) 0
//*)
ysc := cotan(fovy *0.5);
xsc := ysc / aspect;
with mout do begin
d[0]:=xsc;
d[1]:=0;
d[2]:=0;
d[3]:=0;

d[4]:= 0;
d[5]:= ysc;
d[6]:= 0;
d[7]:=0;

d[8]:=0;
d[9]:=0;
f1:=zf/(zn-zf);
d[10]:=-f1;
d[11]:= 1;

d[12]:=0;
d[13]:=0;
d[14]:= zn*f1;
d[15]:=0;

end;

result:=@mOut;
end;



LookAtLH

function LookAtLH(out mOut: SMatrixf; const Eye, At, Up: SVectorf): PSMatrixf;
var
zv,xv,yv:SVectorf;
fi:Single;
begin
//(*
zv.x:=At.x - Eye.x;
zv.y:=At.y - Eye.y;
zv.z:=At.z - Eye.Z;
VectorNormalize(zv);
xv:=VectorCross(Up,zv);
VectorNormalize(xv);
yv:=VectorCross(zv,xv);
with mout do begin
d[0]:=xv.x;
d[1]:=yv.x;
d[2]:=zv.x;
d[3]:=0;

d[4]:= xv.y;
d[5]:= yv.y;
d[6]:= zv.y;
d[7]:=0;

d[8]:=xv.z;
d[9]:=yv.z;
d[10]:=zv.z;
d[11]:= 0;

d[12]:=-VectorDot(xv, eye);
d[13]:=-VectorDot(yv, eye);
d[14]:= -VectorDot(zv, eye);
d[15]:=1;
(*
zv = normal(At - Eye)
xv = normal(cross(Up, zv))
yv = cross(zv, xv)
xv.x yv.x zv.x 0
xv.y yv.y zv.y 0
xv.z yv.z zv.z 0
-dot(xv, eye) -dot(yv, eye) -dot(zv, eye) 1
//*)
end;



外積

function VectorCross(const V1, V2: SVectorf): SVectorf;
begin
Result.x := V1.y * V2.z-V1.z * V2.y;
Result.y := V1.z * V2.x-V1.x * V2.z;
Result.z := V1.x * V2.y-V1.y * V2.x;
(*
Vector(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y-a.y*b.x);
//*)
end;



内積

function VectorDot(const V1, V2: SVectorf): Single;
begin
result := V1.x*V2.x + V1.y*V2.y + V1.z*V2.z;
end;


法線化(スケールを返す)

function VectorNormalize(var Vec: SVectorf): Single;
var f:single;
begin
with Vec do begin
Result := Sqrt(Sqr(x) + Sqr(y) + Sqr(z));
f:=1/Result;
x := x *f;
y := y *f;
z := z *f;
end;
end;


CoTan

function CoTan(const X: Extended): Extended;
{ CoTan := Cos(X) / Sin(X) = 1 / Tan(X) }
asm
FLD X
FPTAN
FDIVRP
FWAIT
end;


気に入らないなぁ。
でもいいコンパイラならこれがいいのかも
cotanがアセンブラなのはmathユニットインクルードしないから

floattostrはwsprintfを2変数で宣言してtruncと比較文で整数部と小数部に分けた。
まだ不真面目モードのテスト実装
今回の内容、せいぜい高校レベルだと思うのだが
それにしてもどうしてこの程度やらないでD3DXを使う人ばかりなのかが疑問ではある。

雑な記述だけれど
ちゃんとしたまとめもやるけれど素でやりたい人の道しるべになれば幸い。


posted by Xo_ox at 21:00| Comment(0) | 3D | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。