-
Я нашёл в сети алгорит, но там нужны 2 функции Cross(p, q); и Normalize(n);
-
Немного невкурил, что такое Cross, но нормализацию ни с чем не спутаешь :) type
PT3D = record
x, y, z: single;
end;
...
procedure Norm3D(var v:PT3D);
asm
MOV EDX, EAX;
FLD DWORD PTR [EAX];
FLD DWORD PTR [EAX+4];
FLD DWORD PTR [EAX+8];
FLD ST(2);
FMUL ST(0), ST(0);
FLD ST(2);
FMUL ST(0), ST(0);
FADD;
FLD ST(1);
FMUL ST(0), ST(0);
FADD;
FTST;
FNSTSW AX;
SAHF;
MOV EAX, EDX;
JE @exit;
FSQRT;
FLD1;
FDIVR;
FMUL ST(3), ST(0);
FMUL ST(2), ST(0);
FMUL;
FSTP DWORD PTR [EAX+8];
FSTP DWORD PTR [EAX+4];
FSTP DWORD PTR [EAX];
RET;
@exit:
FCOMPP;
FCOMPP;
end;
-
...."Как рассчитывается нормаль? Для начала возьмем три точки (a,b и c). По этим точкам необходимо вычислить вектора p (из точки a в b) и q (из a в с): p = b - a q = c - a Получив два этих вектора, вычисляем нормаль как перекрестное произведение векторов p и q с нормализацией результата. Это можно представить в псевдокоде как: n = Cross(p, q); Normalize(n); Для нормализации результата необходимо разделить каждый параметр вектора на его длину, которая вычисляется как: length = Sqrt(x2+y2+z2); "..............
Это теория
-
cross - это векторное произведение векторов
-
> Для нормализации результата необходимо разделить каждый > параметр вектора на его длину, которая вычисляется как: > length = Sqrt(x2+y2+z2);
Знаешь, именно это и делает приведённая функция. ВПВ щас может быть найду.
-
Вот. Это функция нахождения нормали. function GetNorm3D(v1, v2, v3:PT3D):PT3D;
asm
FLD DWORD PTR [EAX];
FLD DWORD PTR [EDX];
FSUB ST(1), ST(0);
FSUB DWORD PTR [ECX];
FLD DWORD PTR [EAX+4];
FLD DWORD PTR [EDX+4];
FSUB ST(1), ST(0);
FSUB DWORD PTR [ECX+4];
FLD DWORD PTR [EAX+8];
FLD DWORD PTR [EDX+8];
FSUB ST(1), ST(0);
FSUB DWORD PTR [ECX+8];
MOV EAX, DWORD PTR [ESP+8];
FLD ST(0);
FMUL ST(0), ST(4);
FLD ST(2);
FMUL ST(0), ST(4);
FSUB;
FSTP DWORD PTR [EAX];
FMUL ST(0), ST(5);
FXCH;
FMUL ST(0), ST(4);
FSUBR;
FSTP DWORD PTR [EAX+4];
FMUL ST(0), ST(3);
FXCH;
FMUL ST(0), ST(2);
FSUB;
FSTP DWORD PTR [EAX+8];
FCOMPP;
CALL Norm3D;
end; На входе - три 3D точки (a, b и с). На выходе - одна (конечная точка вектора нормали с началом в [0, 0, 0]). ВНИМАНИЕ! Функция применима только если флоаты в записи - 4х байтные (single)! Если Double/Extended, придётся везде менять смещения.
-
Cross - это векторное произведение. В результе векторного произведения двух векторов получается вектор перпендикулярный им. Соответственно если в качестве векторов взять две стороны треугольник, то произведение и даст нормаль. Потом нормализцем - и все.
Нормализация, кстати, является не обязательной операцией. Нормализация зачастую не нужна, например, когда в шейдере происходит умножение нормали на какой то вектор. Независимо от длины нормали вектор будет один и тот же(за исключением 0 длины конечно же).
P.S. Формула векторного перемножения есть в любом учебнике по АГ.
-
> [5] Renegat (09.05.08 23:02)
Я бы рекомендовал переписать это с учетом современных реалий(SSE).
-
А SSE с какого проца начало поддерживаться? Я вот думаю, пойдёт ли это на моей музейной древности?..
-
Вы че грузите!
:)
> @!!ex ©
А что такое шейдер?
-
> [8] Renegat (10.05.08 00:08)
SSE1 - Начиная с P3. :) Встретить комп без SSE почти не реально сейчас. :))
-
> А что такое шейдер?
Гугль закрыли?
Это код по обработке вершин и пикселей, выполняемый на видеокарте. Помните клевое замедление времени в FEAR? Это шейдеры... Блики и разсытие в NFS? Это шейдеры. Аномалии и супердетализированные поверхности в Сталкере? Это шейдеры. И т.д. Шейдеры дали огромные возможности. Существуеют, кстати, начиная с GeForce 3, так что уже далеко не новая технология..
-
Х.з. панове, то ли у меня или SSE тормознутый, то ли руки кривые, но даже один только код вычитания MOVUPS XMM0, [EAX];
MOVUPS XMM1, [EDX];
SUBPS XMM0, XMM1;
SUBPS XMM1, [ECX]; у меня выполняется в 1.46 раза медленнее, нежели вся вышеприведённая функция... =)
-
Тем более, в структуру пришлось вставлять и инициализировать один, четвёртый, "мусорный" флоат.
-
> вставлять и инициализировать один
зачем инициализировать его?
> у меня выполняется в 1.46 раза медленнее, нежели вся вышеприведённая > функция... =)
ПРи переводе вычислений на SSE мой проект ускорился примерно на 15%.
-
> зачем инициализировать его?
Ха! А если он окажется случайно UNORM-ом, или вообще NAN-ом? SSE его заколебёццо складывать-вычитать... Лучше уж проставить как есть 0, и жить спокойно. Впрочем, FPU рулит. SSE это, я так понял, просто автоматический парсер чисел в тот же самый FPU. Распараллелить вычисления на единственном сопре невозможно, а такая роскошь как многоядерный проц у меня просто отсутствует.
-
> SSE это, я так понял, просто автоматический парсер чисел > в тот же самый FPU.
вроде бы нет. судя по спецификации - это полноценные инструкции.
-
То есть эти инструкции не просто передают автоматически флоаты на конвейер основного сопра, а вычисляют всё на ещё двух отдельных "своих" FPU??? Да быть такого... пойду учить матчасть :(
-
|