Глобальное позиционирование освещения в Opengl

  • Автор темы MoDErahN
  • Дата начала
M

MoDErahN

#1
Народ, в общем трабл такой. Пишу прожку для моделирования 3D систем, все пашет нормально, кроме освещения.
Оно ведет себя жутко странно, вроде бы я его включаю до всех преобразований матриц, а в итоге оно отображаеться для всех объектов с разными векторами направления. Причем даже не с соответствующим вектором в системе координат самого объекта, а с каким-то неясно-непонятным вектором.
Вот ссыль на бинарник и модель: http://slil.ru/27717863
Запускаем прогу, тусим в "Визуализацию моделей", там правый клик на окошке с надписью "Новая модель" и выбираем "Открыть модель", выбираем файлик, тот что в архиве с прогой, и смело жмем "Начать визуализацию". Чтобы было проще увидеть в чем трабл, можно поставить скорость где-то на 0,1. Ориентация в пространстве просто мышкой.


Вот листинг отрисовки, подскажите что тут не так. Вроде ж свет в глобальной системе координат врубаеться, почему он так криво отрабатывает?

Код:
//###################################################
//### внизу процедуры вывода объектов ###############
//###################################################

Procedure PaintSSphere(Sph: TSSphere);
Var
i: byte;
Begin
glBegin(GL_TRIANGLES);
For i := 1 to 8 do
Begin
glColor4fv(@Sph.Color[Sph.Triangle[i].F]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].F]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].F]);
glColor4fv(@Sph.Color[Sph.Triangle[i].S]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].S]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].S]);
glColor4fv(@Sph.Color[Sph.Triangle[i].T]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].T]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].T]);
End;
glEnd;
End;

Procedure PaintMSphere(Sph: TMSphere);
Var
i: byte;
Begin
glBegin(GL_TRIANGLES);
For i := 1 to 48 do
Begin
glColor4fv(@Sph.Color[Sph.Triangle[i].F]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].F]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].F]);
glColor4fv(@Sph.Color[Sph.Triangle[i].S]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].S]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].S]);
glColor4fv(@Sph.Color[Sph.Triangle[i].T]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].T]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].T]);
End;
glEnd;
End;

Procedure PaintHSphere(Sph: THSphere);
Var
i: byte;
Begin
glBegin(GL_TRIANGLES);
For i := 1 to 120 do
Begin
glColor4fv(@Sph.Color[Sph.Triangle[i].F]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].F]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].F]);
glColor4fv(@Sph.Color[Sph.Triangle[i].S]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].S]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].S]);
glColor4fv(@Sph.Color[Sph.Triangle[i].T]);
glNormal3fv(@Sph.Normal[Sph.Triangle[i].T]);
glVertex3fv(@Sph.Vartex[Sph.Triangle[i].T]);
End;
glEnd;
End;

Procedure PaintCirc(Circ: TCirc);
Var
i: byte;
Begin
glBegin(GL_TRIANGLES);
glNormal3f(0, -1, 0);
For i := 1 to 216 do
Begin
glColor4fv(@Circ.Color[Circ.Triangle[i].F]);
glVertex3fv(@Circ.Vartex[Circ.Triangle[i].F]);
glColor4fv(@Circ.Color[Circ.Triangle[i].T]);
glVertex3fv(@Circ.Vartex[Circ.Triangle[i].T]);
glColor4fv(@Circ.Color[Circ.Triangle[i].S]);
glVertex3fv(@Circ.Vartex[Circ.Triangle[i].S]);
End;
glNormal3f(0, 1, 0);
For i := 1 to 216 do
Begin
glColor4fv(@Circ.Color[Circ.Triangle[i].F]);
glVertex3fv(@Circ.Vartex[Circ.Triangle[i].F]);
glColor4fv(@Circ.Color[Circ.Triangle[i].S]);
glVertex3fv(@Circ.Vartex[Circ.Triangle[i].S]);
glColor4fv(@Circ.Color[Circ.Triangle[i].T]);
glVertex3fv(@Circ.Vartex[Circ.Triangle[i].T]);
End;
glEnd;
End;

Procedure LightOn(Light: TLight);
Begin
glEnable(GLLight[VM.lights]);
glLightfv(GLLight[VM.lights], GL_AMBIENT, @Light.FonColor);
glLightfv(GLLight[VM.lights], GL_DIFFUSE, @Light.GlColor);
glLightf(GLLight[VM.lights], GL_LINEAR_ATTENUATION, Light.con);
glLightfv(GLLight[VM.lights], GL_POSITION, @Light.Pos);
End;

Function GetPointOrb(a, b, stang, speed: real): TGLPoint;
Var
ang: real;
Begin
ang := stang / 57.2956 + speed * 6.2832 * VM.RealTime;
ang := ang - round(ang / 6.2832 - 0.5) * 6.2832;
GetPointOrb[1] := 0;
GetPointOrb[0] := cos(ang) * a;
GetPointOrb[2] := sin(ang) * b;
End;

Procedure DisableLights;
Var
i: integer;
Begin
For i := 0 to 7 do glDisable(GLLight[i]);
End;

Procedure TVM.SetLights(Root: TOT);
Var
i: byte;
Begin
DisableLights;
lights := 0;
i := 0;
While (i <= length(Root.Child) - 1) and (lights < 7) do
Begin
if Root.Child[i].Obj.ObjType = 5 then
Begin
LightOn(Root.Child[i].Obj.LT);
inc(lights);
End;
inc(i);
End;
End;

//###################################################
//### внизу логическая структура отрисовки ##########
//###################################################

Procedure TVM.GlobalPaint(Root: TOT);
Var
Pnt: TGLPoint;
ang: real;
i: integer;
Begin
glPushMatrix; // <-- (Матрицу в стек)

if Root <> TreeRoot then
Begin //вращаем ось орбиты и смещаемся в точку на орбите
glRotatef(Root.Obj.Rotorb[1][0], Root.Obj.Rotorb[1][1], Root.Obj.Rotorb[1][2], Root.Obj.Rotorb[1][3]);
glRotatef(Root.Obj.Rotorb[2][0], Root.Obj.Rotorb[2][1], Root.Obj.Rotorb[2][2], Root.Obj.Rotorb[2][3]);
glRotatef(Root.Obj.Rotorb[3][0], Root.Obj.Rotorb[3][1], Root.Obj.Rotorb[3][2], Root.Obj.Rotorb[3][3]);
Pnt := GetPointOrb(Root.Obj.a, Root.Obj.b, Root.Obj.stang, Root.Obj.rotspeed);
glTranslatef(Pnt[0], Pnt[1], Pnt[2]);
End;

if Root.Obj.ObjType in [1..4] then
Begin //вращаем ось объекта и масштабируем
glPushMatrix; // <-- (Матрицу в стек)
glRotatef(Root.Obj.Rotspin[1][0], Root.Obj.Rotspin[1][1], Root.Obj.Rotspin[1][2], Root.Obj.Rotspin[1][3]);
glRotatef(Root.Obj.Rotspin[2][0], Root.Obj.Rotspin[2][1], Root.Obj.Rotspin[2][2], Root.Obj.Rotspin[2][3]);
glRotatef(Root.Obj.Rotspin[3][0], Root.Obj.Rotspin[3][1], Root.Obj.Rotspin[3][2], Root.Obj.Rotspin[3][3]);
ang := Root.Obj.stspin + 360 * Root.Obj.spinspeed * RealTime;
ang := ang - round(ang / 360 - 0.5) * 360;
glRotatef(ang, 0, 1, 0);

glScalef (Root.Obj.radius * 2, Root.Obj.radius * 2, Root.Obj.radius * 2); // * 2 потому что модели имеют границы в 0.5
End;

if Root.Obj.shadowed = false then glDisable(GL_LIGHTING); //если у объекта отключено затенение, то вырубаем освещение

case Root.Obj.ObjType of
1: PaintSSphere(Root.Obj.SS);
2: PaintMSphere(Root.Obj.MS);
3: PaintHSphere(Root.Obj.HS);
4: PaintCirc(Root.Obj.CR);
end;

if Root.Obj.shadowed = false then glEnable(GL_LIGHTING);

if Root.Obj.ObjType in [1..4] then
Begin
glPopMatrix; // --> (Матрицу из стека)
End;

If Length(Root.Child) > 0 then
Begin
For i := 0 to Length(Root.Child) - 1 do GlobalPaint(Root.Child[i]);
End;

glPopMatrix; // --> (Матрицу из стека)
End;

//###################################################
//### внизу перехватчик сообщения отрисовки окна ####
//###################################################

procedure TimeProc(uTimerID, uMessage: UINT;dwUser, dw1, dw2: DWORD) stdcall; //процедура обработки мультимедийного таймера 
begin
InvalidateRect(VM.Handle, nil, False); //обновляем окно
end;

procedure TVM.WMPaint(var Msg: TWMPaint); //перехватчик сообщения отрисовки окна
var
ps: TPaintStruct;
begin
//расчет реального времени
TimerTime := GetTickCount - StartTime;
RealTime := LRTime + TimerTime * TimeSpeed / 1000;

//расчет координат камеры
Cam.Eye.X := sin(camgorang) * camrad * cos(camvertang);
Cam.Eye.Z := cos(camgorang) * camrad * cos(camvertang);
Cam.Eye.Y := sin(camvertang) * camrad;

BeginPaint(Handle, ps); //начало отрисовки

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); //очистка буферов цвета и глубины

glLoadIdentity;

//установка камеры
gluLookAt (Cam.Eye.X, Cam.Eye.Y, Cam.Eye.Z,
Cam.Target.X, Cam.Target.Y, Cam.Target.Z,
Cam.RVect.X, Cam.RVect.Y, Cam.RVect.Z);

//установка освещения
SetLights(TreeRoot);

//отрисовка объектов
GlobalPaint(TreeRoot);

SwapBuffers(DC); //"выбрасываем" на экран

EndPaint(Handle, ps); //завершаем отрисовку
end;
Оно поворачивает источник света вместе с объектом, даже не вместе, а с удвоенным углом, т.е. если объект делает оборот вокруг своей оси (т.е. система координат в которой он рисуется делает 1 оборот относительно глобальной системы отсчета) источник света делает два оборота относительно глобальной системы отсчета.

Вот вращение сферы, вид сверху.


Есть идеи?

Не стесняемся в предположениях, буду рад любой идее, уже часов 5 убил на попытки это отладить.
 
M

mastiff

#2
таже проблема.
тллко я смотрю отвечать тут не торопятся)