Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2008.04.20;
Скачать: [xml.tar.bz2];

Вниз

вектора нормалей   Найти похожие ветки 

 
basf   (2007-01-17 12:34) [0]

В одной книжонке по 3D-графике прочитал что по умолчанию за вектор нормали в OpenGL принимается вектор перпендикулярный к какой-либо плоскости (что, вроде бы, очевидно). Я рисую не самую сложную фигуру ("срезка" эллипсоида), при включении освещения объект пропадает, когда я нормали ставлю сам, то фигура видна, но так как я их ставлю с некоторой "погрешностью" получается не совсем то что надо. В общем, ставит OpenGL нормали сам или нет, может эту "опцию"  нужно как-то включить, подскажите, plz, как их правильно расставить.


 
@!!ex ©   (2007-01-17 13:28) [1]

Не ставит OpenGL нормали сам.
Проблема расчитать чтоли?


 
@!!ex ©   (2007-01-17 13:44) [2]

glut?
GLUT сам считает нормали, если ему указать, никогда им не пользовался...
Рисуй элипс сам? :)


 
Rial ©   (2007-01-17 16:25) [3]

Рассчет нормали (кое что наспех удалил, но работать должно):

function CalcNormal(Const V1X, V1Y, V1Z,
                                     V2X, V2Y, V2Z,
                                     V3X, V3Y, V3Z : GLFloat;
                               Const bNormalize : Boolean) : Array[0..2] of GLFloat;
Var VX1, VY1, VZ1,
    VX2, VY2, VZ2 : GLFloat;
   X, Y, Z : GLFloat;
   WrkI : GLFloat;
begin
VX1:=V1X - V2X;
VY1:=V1Y - V2Y;
VZ1:=V1Z - V2Z;
VX2:=V2X - V3X;
VY2:=V2Y - V3Y;
VZ2:=V2Z - V3Z;
//Вектор перпендикулярен центру треугольника
X:=VY1 * VZ2 - VZ1 * VY2;
Y:=VZ1 * VX2 - VX1 * VZ2;
Z:=VX1 * VY2 - VY1 * VX2;
If (bNormalize)then begin
 //Вычисляем длину
 WrkI:=Sqrt(X * X + Y * Y + Z * Z);
 If (WrkI = 0.0) then WrkI := 1.0; //Для предотвращения деления на ноль
 //Номализуем
 Result[0]:=X / WrkI;
 Result[1]:=Y / WrkI;
 Result[2]:=Z / WrkI;
end else begin
 Result[0]:=X;
 Result[1]:=Y;
 Result[2]:=Z;
end;
end;

procedure SetNormal(Const V1X, V1Y, V1Z,
                                     V2X, V2Y, V2Z,
                                     V3X, V3Y, V3Z : GLFloat);
Var GLNormal : Array[0..2] of GLFloat;
begin
GLNormal:=CalcNormal(V1X, V1Y, V1Z,
                     V2X, V2Y, V2Z,
                     V3X, V3Y, V3Z,
                     True);
glNormal3fv(@GLNormal);
end;


А вот как все делается без лишних библиотек.
Опять же, кое чего не хватает, но это прими как домашнее задание :)

procedure rglCalc_Disk(Const InnerRadius, OuterRadius, Height1, Height2 :  GLFloat);
Var Sn, Cs  :  Extended;
   iX, iY, oX, oY  :  GLFloat;
   biX, biY, boX, boY  :  GLFloat;
   I : Integer;
   iTexPosX, iTexPosY, oTexPosX, oTexPosY  :  GLFloat;
   biTexPosX, biTexPosY, boTexPosX, boTexPosY  :  GLFloat;
begin
 SinCos(TwoPi / DetailedX, Sn, Cs);
 biX :=InnerRadius;
 biY :=0.0;
 boX :=OuterRadius;
 boY :=0.0;

 boTexPosX :=1.0;
 boTexPosY :=0.5;
 biTexPosX :=0.5 + (InnerRadius / OuterRadius) / 2.0;
 biTexPosY :=0.5;

 SetDefaultNormal;

 glBegin(GL_Triangles);
  For I :=0 to DetailedX do begin
   iX :=biX;
   iY :=biY;
   oX :=boX;
   oY :=boY;

   iTexPosX :=biTexPosX;
   iTexPosY :=biTexPosY;
   oTexPosX :=boTexPosX;
   oTexPosY :=boTexPosY;

   PerformCoords(oX, oY, Cs, Sn, boX, boY);
   PerformCoords(iX, iY, Cs, Sn, biX, biY);

   boTexPosX :=oTexPosX + (boX - oX) / 2.0;
   boTexPosY :=oTexPosY + (boY - oY) / 2.0;

   biTexPosX :=iTexPosX + (biX - iX) / 2.0;
   biTexPosY :=iTexPosY + (biY - iY) / 2.0;

   //Первый треугольник
   glTexCoord2f(iTexPosX, iTexPosY);
   glVertex3f(iX, iY, Height1);

   glTexCoord2f(oTexPosX, oTexPosY);
   glVertex3f(oX, oY, Height2);

   glTexCoord2f(boTexPosX, boTexPosY);
   glVertex3f(boX, boY, Height2);

   //Второй треугольник
   glTexCoord2f(iTexPosX, iTexPosY);
   glVertex3f(iX, iY, Height1);

   glTexCoord2f(boTexPosX, boTexPosY);
   glVertex3f(boX, boY, Height2);

   glTexCoord2f(biTexPosX, biTexPosY);
   glVertex3f(biX, biY, Height1);

  end;
 glEnd;
end; //With rglEngine

procedure PerformCoords(Const X, Y, Cs, Sn  :  GLFloat; Var OutX, OutY  :  GLFloat);
begin
OutX :=X * Cs - Y * Sn;
OutY :=Y * Cs + X * Sn;
end;



 
@!!ex ©   (2007-01-17 16:32) [4]


> basf   (17.01.07 12:34)  

На будущее. (Я пока не чтал учиьтся даже и не знал).
Оказывается норамаль - это тупо векторное произведение двух векторов.
Возьми учебник ао Аналитической геометрии и посмотри тему: "векторное произведение". ИМХО это лучше чем тупо скопировать текст.


 
Думкин ©   (2007-01-17 18:42) [5]

> Оказывается норамаль - это тупо векторное произведение двух
> векторов.

Так то оно так, но оно не коммутативно, и при смене порядка - меняет направление. То есть определяет ориентацию. Это самая засада для многих.


 
Думкин ©   (2007-01-17 18:49) [6]

Кстати в glut была ошибка на подобную тему и в одном примере у Краснова, додекаэдр(кажется) при вращении терял одну сторону. :)


 
ors_archangel ©   (2007-01-17 19:36) [7]


//Вычисляем длину
WrkI:=Sqrt(X * X + Y * Y + Z * Z);
If (WrkI = 0.0) then WrkI := 1.0; //Для предотвращения деления на ноль
//Номализуем
Result[0]:=X / WrkI;
Result[1]:=Y / WrkI;
Result[2]:=Z / WrkI;

оптимизация деления:

//Вычисляем длину
WrkI:=Sqrt(X * X + Y * Y + Z * Z);
If WrkI <> 0.0 then begin //Для предотвращения деления на ноль
  WrkI := 1/WrkI;
  //Номализуем
  Result[0]:=X * WrkI;
  Result[1]:=Y * WrkI;
  Result[2]:=Z * WrkI;
end else begin
  Result[0]:=X;
  Result[1]:=Y;
  Result[2]:=Z;
end;


 
Rial ©   (2007-01-17 20:22) [8]

> [6] Думкин ©   (17.01.07 18:49)
> Кстати в glut была ошибка на подобную тему и в одном примере
> у Краснова, додекаэдр(кажется) при вращении терял одну сторону.
> :)

А glut вообще зло, имхо :)
Если glu можно еще использовать, чтобы не мучаться со своими
текстурными координатами и нормалями, то все, что делается
в glut лучше переписать заново.
Возможно, сейчас есть более новые версии, но в той, что испугала
меня, нашлись таки тоже какие то глюки, да и лишнего много там.

P.S.
Как я не изголялся с оптимизацией, а обогнать, например,
gluSphere по производительности хоть на сколько - нибудь
значимое число операций так и не смог,
даже переписав всю процедуру на ассемблере.


 
XProger ©   (2007-01-17 21:03) [9]

Нормаль в OpenGL это перпендикуляр к плоскости плоскости полигона?
СОЖГИТЕ ЭТУ КНИГУ!


 
Думкин ©   (2007-01-18 05:37) [10]


> XProger ©   (17.01.07 21:03) [9]

Ну если под нормалью понимать именно нормаль в математическом смысле в еквлидовом пространстве - то это так. А если конечно, в применении к ЖЛ - то таки нет.


 
Rial ©   (2007-01-18 09:32) [11]

>[7] ors_archangel ©   (17.01.07 19:36)
>оптимизация деления:
> WrkI:=Sqrt(X * X + Y * Y + Z * Z);
> If WrkI <> 0.0 then begin //Для предотвращения деления на ноль
>  WrkI := 1/WrkI;


Это, наверное, опечатка, да ? :)
Ибо во - первых нет
else WrkI:=1.0;
да и на самом деле количество тактов то не уменьшилось %)

Уж если придираешься к тиким глупостям, то уж
придирайся обоснованно.


 
MBo ©   (2007-01-18 10:11) [12]

>да и на самом деле количество тактов то не уменьшилось %)

Три деления обычно медленнее одного деления и трех умножений


 
@!!ex ©   (2007-01-18 10:15) [13]


> Думкин ©   (17.01.07 18:42) [5]

Не думаю что это так. ИМХО каждый должен знать, что нормальный треугольник - треугольник с вершинами заданными по часовой стрелке.
Если перемножать также по часовой - нормаль правильная получается.
Если я не ошибаюсь, конечно.


 
Думкин ©   (2007-01-18 10:36) [14]

> @!!ex ©   (18.01.07 10:15) [13]
>
> > Думкин ©   (17.01.07 18:42) [5]
>
> Не думаю что это так. ИМХО каждый должен знать, что нормальный
> треугольник - треугольник с вершинами заданными по часовой
> стрелке.

Либо треугольник нормальный, либо я ненормальный. Никогда подобные благоглупости не заучивал. И почему то, что ты описал должен знать каждый - в упор не понимаю.


 
MBo ©   (2007-01-18 10:55) [15]

>нормальный треугольник - треугольник с вершинами заданными по часовой стрелке

А в трехмерном пространстве как?


 
@!!ex ©   (2007-01-18 11:27) [16]

Я о трехмерном пространстве и говорю. :))
У треугольника есть лицевая сторона и задная.
Определяется по тому, в какой последовательности заданы вершины.
Соответственно если почасовой - то он повернут лицевой стороной к пользователю - если против, значит задней.
А знать...
Ну вообще как можно писать графику без знания этого? Ведь на этом очень многие алгоритмы построены... Тоже нахождение нормалей. :)))
Плюс для оптимизации обычно не рисуют треугольники повернутые задней стороной. и т.д.


 
Думкин ©   (2007-01-18 11:36) [17]

> @!!ex ©   (18.01.07 11:27) [16]

Это не знание, это предмет договора. Условность. Не инвариант.


 
@!!ex ©   (2007-01-18 12:57) [18]


> Думкин ©   (18.01.07 11:36) [17]

Это стандарт. Не знаю ни одного распространенного API, которое бы основывалось на другом стандарте.
Крестик закрывает окно. Это знание? Это стандарт.


 
Думкин ©   (2007-01-18 13:19) [19]

> @!!ex ©   (18.01.07 12:57) [18]

Да при чем тут АПИ и прочее? Я о высоком. :)
А еще есть правило правого буравчика и левого. :)


 
XProger ©   (2007-01-18 13:29) [20]

Maya, 3ds max хранят нужный порядок вершин. При применении модификаторов по типу Normal - соотсветствующе меняют этот порядок. Никаких проблем с экспортом и дальнейшим расчётом нормалей быть не может.


 
Ricks ©   (2007-01-18 13:35) [21]


> @!!ex ©


> MBo ©


В трехмерном пространстве нормаль к поверхности треугольника должна быть направлена так, чтобы с её конца поворот на минимальный угол от одной стороны к другой был ПРОТИВ часовой стрелке!

Для товарища basf предлагаю код (в принципе это уже было, но у меня немного по другому выглядит):

function PlaneNormal(Plane:array of TVector):TVector;
var v1, v2 : TVector;
begin
if Length(Plane) < 3
 then Result:=VectorOrth( CrossProduct(Plane[0], Plane[1]) )
 else begin
  v1:=SubVector( Plane[0], Plane[1] );
  v2:=SubVector( Plane[1], Plane[2] );
  Result:=VectorOrth( CrossProduct(v1, v2) );
 end;
end;

где:

TVector = record
 x : single;
 y : single;
 z : single;
end;

function SubVector(v1, v2 : TVector):TVector;
begin
Result:=Vector( v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.z );
end;

function CrossProduct(v1, v2 : TVector):TVector; // векторное произведение
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;
end;

function VectorOrth(v:TVector):TVector;
var L : single;
begin
L:=VectorLength( v );
if IsZero(L)
 then Result:=NullVector
 else Result:=Vector( v.X / L, v.Y / L, v.Z / L );
end;

function VectorLength(v:TVector):single;
begin
Result:=Sqrt( Sqr(v.X) + Sqr(v.Y) + Sqr(v.Z) );
end;


пользуясь этим набором функций каждый сможет самостоятельно посчитать себе нормаль к треугольнику! :)


 
Думкин ©   (2007-01-18 14:08) [22]


> Ricks ©   (18.01.07 13:35) [21]
>
> В трехмерном пространстве нормаль к поверхности треугольника
> должна быть направлена так, чтобы с её конца поворот на
> минимальный угол от одной стороны к другой был ПРОТИВ часовой
> стрелке!


Кому должна? если уж пишите, то пишите - должна так согласно стандарту ....

Никто никому ничего изначально никогда в этом не должен.


 
Ricks ©   (2007-01-18 14:28) [23]


> Думкин ©


Ну просто должна она... должна и все! :)

Во всей аналитической геометрии и плюс еще в теоретической/аналитической механике нормаль выбирается именно так. Так уж принято...

А в OpenGL при неправильном выборе просто будет освещена другая сторона треугольника, исправить это можно домножением на (-1)


 
@!!ex ©   (2007-01-18 14:33) [24]


> Ricks ©   (18.01.07 13:35) [21]

А какую систему векторов образует векторное произведение? :)))


 
Думкин ©   (2007-01-18 14:33) [25]


> Ricks ©   (18.01.07 14:28) [23]

Про ЖЛ понимаю. Про аналитическую и далее - первый раз слышу. Если только в каких-нибудь конкретных учебниках.


 
Ricks ©   (2007-01-18 14:43) [26]


> @!!ex ©

Правую систему координат. А что?


> Думкин ©

Нет не только в конкрентых учебниках, это у нас на парах было (не думаю, что только в нашем институте указом ректора такую фигню ввели)! :)


 
Ricks ©   (2007-01-18 15:05) [27]

Кстати о делении на ноль итд итп (посты [3], [7])
если длинна вектора нулевая, то ни о какой дальнейшей нормализации не может быть и речи!


 
ors_archangel ©   (2007-01-18 16:09) [28]


> Ricks ©   (18.01.07 15:05) [27]

Ну, n = (0,0,0) не намного лучше в этом случае...
Тебе тоже нужно оптимизировать деление, и на ноль можно проверить перед Sqrt.
Извините, что придераюсь, люди, просто глаз режет, нормаль - это эе частая операция


 
Думкин ©   (2007-01-18 18:53) [29]

> Ricks ©   (18.01.07 14:43) [26]

Тут такой момент - имеет место быть произвольность выбора, которая в конечном счете на результат не влияет.
Я же говорю: наряду с правилом правого буравчика, есть и правило левого. И ни одно животное от этого не пострадало.

Вот возьмем электричество. Движущийся заряд создает магнитное поле, это магнитное поле действует на другой движущийся заряд.
Как будем работать для счета? Работаем с векторными произведениями. Главное в них четко зафиксировать один выбор - куда итоговый направлять и все и с соответствующим выбором выписать законы. А примите ли вы по часовой или против - в реале два заряда все одно провзаимодействуют точно также. Фиксировать выбор надо при одной работе и содним и тем же набором обектов. Зафиксировать ориентацию. При этом выбора изначально - ровно два. И чем предложенный вами выбор лучше другого - я не знаю. Главное знать об этом и при обсуждении выяснять - какую ориентацию выбрал собеседник. И все. Остальное от лукавого. И в книгах многих, просто сообщают вначале - каким буравчиком они будут врезать вектора. Это хорошие книги. Те же кто не сообщает этого надеясь на "общепринятое" - поступают не совсем верно, если конечно это будет важно. Потому что иногда эо не очень важно. Главное знать, что есть +1 и -1.


 
ors_archangel ©   (2007-01-18 20:45) [30]

В том же OpenGL отлично переключается :) glCullFace, если я не ошибаюсь, у меня друг один проект сначала писал CW (Clock-Wise, по часовой стрелке), а потом взял всё переделал на CCW (были причины, для взаимодействия с какой-то библиотекой), вобщем, выбор не принципиален, но тем не менее общепринятое решение здесь практически полезно


 
basf   (2007-01-23 17:48) [31]

Да уж, расчёт нормали с помощью векторного произв-я кажется вроде бы совсем несложным, а я то сначала через углы считал - кучу времени и нервов потратил, т.к. долго не получалось. Спасибо за ответы!


 
basf   (2007-01-23 17:58) [32]

Теперь задачка - наложить на это дело текстуру, но я с этим ещё мало разбирался и вопросов пока нет ...потом появятся ;-)



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2008.04.20;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.055 c
15-1205082091
who
2008-03-09 20:01
2008.04.20
Игорь Шевченко


2-1206436489
TCrash
2008-03-25 12:14
2008.04.20
Кнопка


2-1206524710
AlexeyMir
2008-03-26 12:45
2008.04.20
Модальная форма


15-1204621683
AndreyD
2008-03-04 12:08
2008.04.20
TMPHexEdit и русские буквы


2-1206545585
MikeLevinN
2008-03-26 18:33
2008.04.20
far





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский