четверг, 17 марта 2011 г.

OpenGL. Пример построения однополостного гиперболоида

Построение подобной 3D фигуры основано на использовании функции sin(x)/x в ее 2D развертке в узлах прямоугольных треугольников, образующих полигональную сетку 500х1500 (где результат функции определяет координату Z узла). Для контроля объекта пространстве, вызываемого по glCallList(), мы задали классические клавиши контроля W-A-S-D (вверх-вниз-вправо-влево) и  Z-X-Q-E (вращение в плоскости 0X/0Y). Клавиша SPACE задает метод отрисовки линиями или сплошной заливкой полигонов, INS/DEL задают степень прозрачности, колесико мыши позволяет приблизить или отдалить объект, ESC возврат в исходное состояние.

Данный пример (215kB) является частью набора testbench-ев модуля визуализации одного из закрытых проектов, поэтому мы приведем лишь основной код алгоритма построения (при желании вы можете связаться на предмет приобретения полного кода проекта именно данной визуализации):
// ПОВЕРХНОСТЬ ----------------------------------------------------------------
procedure Tpgl.test_sinxx(const Value: Boolean);
const r= 0.05; //масштаб плеча ячейки
var i,j: integer;
    a,b,c: extended;
begin
 FTestPlace3D:= Value;
 if FTestPlace3D then begin
  for i:=0 to strok do
   for j:=0 to stolb div 2 do begin
    val[i,j].name:= inttostr(i*j);
    //набиваем сетку
    ...
    //набиваем Z
   end
 end
end;

procedure tpgl.paintPlace3d;
const position: array[0..3] of glfloat = (0.0, 0.0, 1.0, 1.0);
var i,j,nrm_count: integer;
    v  : tvertex;
    glpr: array [0..3] of glfloat;
begin
 glNewList(Place, GL_Compile);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glpr[0]:= 1.0;
  glpr[1]:= 1.0;
  glpr[2]:= 1.0;

  // ПОСТРОЕНИЕ 3D ------------------------------------------------------------

  //набиваем нормали всех треугольников-
  nrm_count:= 0;
  for i:= 0 to 499-1 do
   for j:=0 to 1499-1 do begin
    nrm[nrm_count]:= CalcNormal(val[i,j],val[i+1,j],val[i+1,j+1]);    inc(nrm_count);
    nrm[nrm_count]:= CalcNormal(val[i+1,j+1],val[i,j+1],val[i,j]);    inc(nrm_count)
  end;

  //----------------------------------
  //строим поверхность треугольниками-
  if smooth=1 then glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) //типа скелет-
   else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  gl_cnt_name:= 0;
  nrm_count:= 0;
  for i:= 0 to 499-1 do
   for j:=0 to 1499-1 do begin
    if (val[i,j].name<>'')and(val[i+1,j+1].name<>'')and(val[i+1,j].name<>'')and(val[i,j+1].name<>'') then begin

    glLoadName(strtoint(val[i,j].name));  

     //прозрачность-
     glpr[3]:= gl_pr+((val[i,j].z + val[i+1,j].z + val[i+1,j+1].z)/3);
     glColor4fv(@glpr);
    
     glBegin(GL_TRIANGLES); //1- треуг
      if (smooth=0)or(smooth=1) then begin
       v:= nrm[nrm_count]; inc(nrm_count);
       glNormal3f(V.X,V.Y,V.Z)
      end;
      glNormal3f(val[i,j].y,val[i,j].x,val[i,j].z); //стандартный метод-
        glVertex3fv(@val[i,j]);    //1- верш
      glNormal3f(val[i+1,j].y,val[i+1,j].x,val[i+1,j].z);
        glVertex3fv(@val[i+1,j]);  //2
      glNormal3f(val[i+1,j+1].y,val[i+1,j+1].x,val[i+1,j+1].z);
        glVertex3fv(@val[i+1,j+1]);//3
     glEnd;

     //прозрачность-
     glpr[3]:= gl_pr+((val[i+1,j+1].z + val[i,j+1].z + val[i,j].z)/3);
     glColor4fv(@glpr);
     //
     glBegin(GL_TRIANGLES); //2- треуг
      if (smooth=0)or(smooth=1) then begin
       v:= nrm[nrm_count]; inc(nrm_count);//CalcNormal(val[i+1,j+1],val[i,j+1],val[i,j]);
       glNormal3f(V.X,V.Y,V.Z);
      end;
      glNormal3f(val[i+1,j+1].y,val[i+1,j+1].x,val[i+1,j+1].z);
        glVertex3fv(@val[i+1,j+1]);
      glNormal3f(val[i,j+1].y,val[i,j+1].x,val[i,j+1].z);
        glVertex3fv(@val[i,j+1]);
      glNormal3f(val[i,j].y,val[i,j].x,val[i,j].z);
        glVertex3fv(@val[i,j]);
     glEnd;

     end
    end;
 
  glDisable(GL_BLEND);
 glendlist
end;



Комментариев нет:

Отправить комментарий

В комментариях уважайте собеседника, внимательно читайте посты и не додумывайте. Просьбы и предложения из разряда: «можно ваш Skype/Viber/телефон», «напишите мне в vk/FB», а также другие им подобные — игнорируются. Выход новых версий ПО, внешняя ссылка, переставшая работать с течением времени и т.п. не является основанием для претензий. Желающие спокойно подискутировать и высказаться — Welcome. Желающие спонсировать блог — Donate. Нарушение этих простых правил ведет к бану и удалению комментариев без предупреждения.