Конференция "Игры" » как найти нормаль к плоскости и грани треуголиника?
 
  • DoKi (09.05.08 09:50) [0]
    Я нашёл в сети алгорит, но там нужны 2 функции Cross(p, q);  и
    Normalize(n);
  • Renegat (09.05.08 11:39) [1]
    Немного невкурил, что такое 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;

  • DoKi (09.05.08 13:52) [2]
    ...."Как рассчитывается нормаль? Для начала возьмем три точки (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); "..............

    Это теория
  • MBo © (09.05.08 16:45) [3]
    cross - это векторное произведение векторов
  • Renegat (09.05.08 22:44) [4]
    > Для нормализации результата необходимо разделить каждый
    > параметр вектора на его длину, которая вычисляется как:
    > length = Sqrt(x2+y2+z2);

    Знаешь, именно это и делает приведённая функция.
    ВПВ щас может быть найду.
  • Renegat (09.05.08 23:02) [5]
    Вот. Это функция нахождения нормали.

    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, придётся везде менять смещения.
  • @!!ex © (09.05.08 23:55) [6]
    Cross - это векторное произведение.
    В результе векторного произведения двух векторов получается вектор перпендикулярный им.
    Соответственно если в качестве векторов взять две стороны треугольник, то произведение и даст нормаль.
    Потом нормализцем - и все.

    Нормализация, кстати, является не обязательной операцией. Нормализация зачастую не нужна, например, когда в шейдере происходит умножение нормали на какой то вектор. Независимо от длины нормали вектор будет один и тот же(за исключением 0 длины конечно же).

    P.S.
    Формула векторного перемножения есть в любом учебнике по АГ.
  • @!!ex © (09.05.08 23:55) [7]
    > [5] Renegat   (09.05.08 23:02)

    Я бы рекомендовал переписать это с учетом современных реалий(SSE).
  • Renegat (10.05.08 00:08) [8]
    А SSE с какого проца начало поддерживаться? Я вот думаю, пойдёт ли это на моей музейной древности?..
  • main © (10.05.08 02:14) [9]
    Вы че грузите!

    :)


    > @!!ex ©


    А что такое шейдер?
  • @!!ex © (10.05.08 09:02) [10]
    > [8] Renegat   (10.05.08 00:08)

    SSE1 - Начиная с P3. :)
    Встретить комп без SSE почти не реально сейчас. :))
  • @!!ex © (10.05.08 09:05) [11]
    > А что такое шейдер?

    Гугль закрыли?

    Это код по обработке вершин и пикселей, выполняемый на видеокарте.
    Помните клевое замедление времени в FEAR? Это шейдеры... Блики и разсытие в NFS? Это шейдеры. Аномалии и супердетализированные поверхности в Сталкере? Это шейдеры. И т.д. Шейдеры дали огромные возможности. Существуеют, кстати, начиная с GeForce 3, так что уже далеко не новая технология..
  • Renegat (10.05.08 18:28) [12]
    Х.з. панове, то ли у меня или SSE тормознутый, то ли руки кривые, но даже один только код вычитания

     MOVUPS XMM0, [EAX];
     MOVUPS XMM1, [EDX];
     SUBPS XMM0, XMM1;
     SUBPS XMM1, [ECX];



    у меня выполняется в 1.46 раза медленнее, нежели вся вышеприведённая функция... =)
  • Renegat (10.05.08 18:31) [13]
    Тем более, в структуру пришлось вставлять и инициализировать один, четвёртый, "мусорный" флоат.
  • @!!ex © (10.05.08 19:06) [14]
    > вставлять и инициализировать один

    зачем инициализировать его?


    > у меня выполняется в 1.46 раза медленнее, нежели вся вышеприведённая
    > функция... =)

    ПРи переводе вычислений на SSE мой проект ускорился примерно на 15%.
  • Renegat (11.05.08 11:19) [15]
    > зачем инициализировать его?

    Ха! А если он окажется случайно UNORM-ом, или вообще NAN-ом? SSE его заколебёццо складывать-вычитать... Лучше уж проставить как есть 0, и жить спокойно. Впрочем, FPU рулит. SSE это, я так понял, просто автоматический парсер чисел в тот же самый FPU. Распараллелить вычисления на единственном сопре невозможно, а такая роскошь как многоядерный проц у меня просто отсутствует.
  • @!!ex © (11.05.08 18:51) [16]
    > SSE это, я так понял, просто автоматический парсер чисел
    > в тот же самый FPU.

    вроде бы нет. судя по спецификации - это полноценные инструкции.
  • Renegat (11.05.08 22:17) [17]
    То есть эти инструкции не просто передают автоматически флоаты на конвейер основного сопра, а вычисляют всё на ещё двух отдельных "своих" FPU??? Да быть такого... пойду учить матчасть :(
  • @!!ex © (12.05.08 06:47) [18]
    > [17] Renegat   (11.05.08 22:17)

    http://ru.wikipedia.org/wiki/SSE
 
Конференция "Игры" » как найти нормаль к плоскости и грани треуголиника?
Есть новые Нет новых   [134430   +3][b:0][p:0.002]