Форум: "Игры";
Текущий архив: 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.046 c