Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

пересечение объектов в OpenGL

53K
23 ноября 2009 года
edweiser
8 / / 23.11.2009
у меня вопрос по использованию openGL в Delphi 7. мне нужно отобразить пятно пересечения двух фигур, иными словами есть полупрозрачный цилиндр и куча тонких цилиндров внутри него, в момент когда "тонкие" пересекают "полупрозрачный", их нужно этим полупрозрачным цилиндром обрезать и если есть такая возможность выделить цветом контур пересечения. буду очень признателен за любые советы.
//рисуночек для наглядности
[ATTACH]3845[/ATTACH]
53K
24 ноября 2009 года
edweiser
8 / / 23.11.2009
один товарищ посоветовал мне искать в буфере трафаретов, но честно говоря я и его то не нашёл....знающие, подскажите пожалуйста что мне делать то!:)
43K
25 ноября 2009 года
loki231
76 / / 27.09.2009
Я не знаю, как там в дельфе работают с OpenGL, я буду излагать с обще-OpenGL'ных позиций.

Скачай спецификацую OpenGL.

Ищи GL_STENCIL_TEST, glStencilFunc(), glStencilOp().

Что касается обрезания цилиндром выступающих частей, то можно поступить следующим образом.

Запрещаешь обновление color-буфер.
 
Код:
glColorMask (false, false, false, false);

Чистишь stencil-буфер.
 
Код:
glClear (GL_STENCIL_BUFFER_BIT);

Включаешь stencil-тест.
 
Код:
glEnable (GL_STENCIL_TEST);

Включаешь режим рисования тыльных сторон полигонов и рисуешь "полупрозрачный" цилиндр записывая в stencil-буфер 1.
 
Код:
glEnable (GL_CULL_FACE);
glCullFace (GL_FACE);
glStencilFunc (GL_ALWAYS, 1, 1);
glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);

Теперь в пикселах, где получается задняя стенка "полупрозрачного" цилиндра, в stencil-буфере будут значения, равные 1. Это нужно для отсекания частей, лежащих за задней стенкой "полупрозрачного" цилиндра.
Далее
 
Код:
glStencilFunc (GL_EQUAL, 1, 1);
glStencilOp (GL_KEEP, GL_KEEP, GL_INCR);

и рисуешь "кучу тонких цилиндров внутри него".
Теперь в тех точках, где "тонкие цилиндры" лежат напротив задней стенки "полупрозрачного" цилиндра значения в stencil буфере будут равны 2.
Далее чистишь Z-буфер и аналогично, рисуешь сначала лицевую сторону "полупрозначного" цилиндра, потом установив режим теста глубины в GL_GREATER
 
Код:
glClear (GL_DEPTH_BUFFER_BIT);
glDepthFunc (GL_GREATER);
glStencilFunc (GL_EQUAL, 2, 3);
glStencilOp (GL_KEEP, GL_KEEP, GL_INCR);

опять рисуешь "тонкие цилиндры" и получаешь в тех пикселах, где эти "тонкие цилиндры" лежат за передней стенкой и перед задней, т.е. внутри "полупрозрачного"
цилиндра значения в stencil-буфере будут равны 3.

Далее все совсем просто включаешь color-буфер. Чистишь Z-буфер. Возвращаешь тест глубины в GL_LESS. Запрещаешь CULL_FACE.
 
Код:
glStencilFunc (GL_EQUAL, 3, 3);
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);


Рисуешь "тонкие цилиндры".
Запрещаешь обновление Z-буфера и рисуешь полупрозрачный цилиндр.

[COLOR="Red"]Важно[/COLOR], чтобы то, что мы обозначили как "полупрозрачный" цилиндр было выпуклым телом. Та воронкообразная конструкция должна быть декомпозирована в множество цилиндров и усеченных конусов. И для каждого из этих объектов должен быть применён описанный алгоритм. К цилиндрам, да и конусам тоже, на этапе формирования stencil-буфера можно прилепить торцевые крышки. Тогда вообще будет правильно.

Кстати, что это за изделие такое? Похоже на кумулятивную гранату... :)
53K
02 декабря 2009 года
edweiser
8 / / 23.11.2009
огромное спасибо за подсказку! сейчас вот попытался реализовать, но пока что то не получается(после всех манипуляций фигура перестаёт вращаться либо при попытке повращать её просто неактивный чёрный экран), наверно чтото делаю не так...буду разбираться
а изделие это и не изделие вовсе, это пучёк электронов в пролётном канале и коллекторе клистрона(усилитель СВЧ-мощности)
53K
06 декабря 2009 года
edweiser
8 / / 23.11.2009
сегодня потратил полдня, пытаясь заставить работать эту процедуру, ничего не выходит....вроде всё сделано как советовал loki231.....отдаю на суд присутствующих код процедуры
Код:
procedure TForm1.FormPaint(Sender: TObject);
const pos:array [0..3] of double=(0.1,0.1,1,1);
FogColor:array [0..3] of double=(0.9,0.9,0.9,1);
var i,k,j,h:integer;
quad,quadDisc:GLUquadricObj;
begin
SetLength(k1,Form8.SG1.RowCount-1,1);
for j:=1 to Form8.SG1.RowCount-1 do
 for h:=0 to 1 do
 begin
 k1[h,j]:=strtofloat(Form8.SG1.Cells[h,j]);
 end;
if ProblemSolved then
 begin
  wglMakeCurrent (Form1.Canvas.Handle, hrc );
  glViewport(0,0,Form1.ClientWidth,Form1.ClientHeight);
  glDisable(GL_LIGHTING);
  glDisable(GL_FOG);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  glClearColor ( 0 , 0 , 0,1);
  glClear ( GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glPushMatrix;
  gluPerspective(20.0, ClientWidth/ClientHeight, Scale-1.1, Scale+1.1);
  glTranslate (0,0,-Scale);
  glTranslate(Dx,0,0);
  glTranslate(0,Dy,0);
  if Light then
   begin
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHT0);
    glLightfv(GL_LIGHT0,GL_POSITION,@pos);
   end;
  if Fog Then
   begin
    glEnable(GL_FOG);
    glFog(GL_FOG_MODE,GL_EXP2);
    glFog(GL_FOG_DENSITY,0.7);
   end;
  glRotate(RotX,1,0,0);
  glRotate (RotY,0,1,0);
  glScale(1/10/Rkan,1/10/Rkan,1/(eZ[length-1]-eZ[0]));
  glTranslate(0,0,-1);
  glBegin(GL_LINES);
  glColor3d(1,0,0);
  glVertex3d(-2,0,0);
  glVertex3d (2,0,0);
  glVertex3d(0,-2,0);
  glVertex3d (0,2,0);
  glEnd;
  glColor3d(0,1,1.2);
  glEnable(GL_CULL_FACE);
  quad:=gluNewQuadric;
  quadDisc:=gluNewQuadric;
  Zkan:=StrToFloat(form3.LabeledEdit13.Text);

  glColorMask (false, false, false, false);
  glClear (GL_STENCIL_BUFFER_BIT);
  glEnable (GL_STENCIL_TEST);
  glEnable (GL_CULL_FACE);
  glCullFace (GL_BACK);
  glStencilFunc (GL_ALWAYS, 1, 1);
  glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);

   //kollektor
   glColor4d(0.9,0.7,0.2,0.5);
   glPushMatrix;
   glTranslate(0,0,Zkan);
   for j:=1 to Form8.SG1.RowCount-1 do
    begin
    glTranslate(0,0,k1[1,j]);
    gluCylinder(quad,k1[0,j]/10,k1[0,j+1]/10,k1[1,j+1],50,1);
    end;
   glPopMatrix;

  glStencilFunc (GL_EQUAL, 1, 1);
  glStencilOp (GL_KEEP, GL_KEEP, GL_INCR);

  //puchek
  for k:=0 to Floor((length-2)/100) do
   begin
   i:=100*k;
   glPushMatrix;
   glTranslate(0,0,(eZ-eZ[0]));
   glPushMatrix;
   glTranslate(eX,eY,0);
   gluQuadricOrientation(quadDisc,GLU_INSIDE);
   gluDisk(quaddisc,0,R[i+100],35,1);
   gluQuadricOrientation(quad,GLU_INSIDE);
   gluCylinder(quad,R,R,eZ[i+100]-eZ,50,10);
   gluQuadricOrientation(quad,GLU_OUTSIDE);
   glPushMatrix;
   glTranslate(eX[i+10]-eX,eY[i+100]-eY,eZ[i+10]-eZ);
   gluQuadricOrientation(quadDisc,GLU_OUTSIDE);
   gluDisk(quadDisc,0,R[i+100],35,1);
   glPopMatrix;
   glPopMatrix;
   glPopMatrix;
   end;

  glClear (GL_STENCIL_BUFFER_BIT);
  glEnable (GL_STENCIL_TEST);
  glEnable (GL_CULL_FACE);
  glCullFace (GL_FRONT);
  glStencilFunc (GL_ALWAYS, 1, 1);
  glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);

   //kollektor
   glColor4d(0.9,0.7,0.2,0.5);
   glPushMatrix;
   glTranslate(0,0,Zkan);
   for j:=1 to Form8.SG1.RowCount-1 do
    begin
    glTranslate(0,0,k1[1,j]);
    gluCylinder(quad,k1[0,j]/10,k1[0,j+1]/10,k1[1,j+1],50,1);
    end;
   glPopMatrix;

  glClear (GL_DEPTH_BUFFER_BIT);
  glDepthFunc (GL_GREATER);
  glStencilFunc (GL_EQUAL, 2, 3);
  glStencilOp (GL_KEEP, GL_KEEP, GL_INCR);

  //puchek
  for k:=0 to Floor((length-2)/100) do
   begin
   i:=100*k;
   glPushMatrix;
   glTranslate(0,0,(eZ-eZ[0]));
   glPushMatrix;
   glTranslate(eX,eY,0);
   gluQuadricOrientation(quadDisc,GLU_INSIDE);
   gluDisk(quaddisc,0,R[i+100],35,1);
   gluQuadricOrientation(quad,GLU_INSIDE);
   gluCylinder(quad,R,R,eZ[i+100]-eZ,50,10);
   gluQuadricOrientation(quad,GLU_OUTSIDE);
   glPushMatrix;
   glTranslate(eX[i+10]-eX,eY[i+100]-eY,eZ[i+10]-eZ);
   gluQuadricOrientation(quadDisc,GLU_OUTSIDE);
   gluDisk(quadDisc,0,R[i+100],35,1);
   glPopMatrix;
   glPopMatrix;
   glPopMatrix;
   end;

  glColorMask (true, true, true, true);
  glClear (GL_STENCIL_BUFFER_BIT);
  glDepthFunc (GL_LESS);
  glDisable (GL_CULL_FACE);
  glStencilFunc (GL_EQUAL, 3, 3);
  glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);

  //puchek
  glColor3d(0,1,1.2);
  for k:=0 to Floor((length-2)/100) do
   begin
   i:=100*k;
   glPushMatrix;
   glTranslate(0,0,(eZ-eZ[0]));
   glPushMatrix;
   glTranslate(eX,eY,0);
   gluQuadricOrientation(quadDisc,GLU_INSIDE);
   gluDisk(quaddisc,0,R[i+100],35,1);
   gluQuadricOrientation(quad,GLU_INSIDE);
   gluCylinder(quad,R,R,eZ[i+100]-eZ,50,10);
   gluQuadricOrientation(quad,GLU_OUTSIDE);
   glPushMatrix;
   glTranslate(eX[i+10]-eX,eY[i+100]-eY,eZ[i+10]-eZ);
   gluQuadricOrientation(quadDisc,GLU_OUTSIDE);
   gluDisk(quadDisc,0,R[i+100],35,1);
   glPopMatrix;
   glPopMatrix;
   glPopMatrix;
   end;

  glDisable(GL_STENCIL_TEST);

  //kanal
  glColor4d(0.9,0.9,0.9,0.5);
  gluQuadricOrientation(quadDisc,GLU_INSIDE);
  gluDisk(quadDisc,0,Rkan,20,1);
  gluQuadricOrientation(quadDisc,GLU_OUTSIDE);
  Zkan:=StrToFloat(form3.LabeledEdit13.Text);
  gluCylinder(quad,Rkan,Rkan,Zkan,20,1);
  glPushMatrix;
  glTranslate(0,0,Zkan);
  gluDisk(quadDisc,0,Rkan,20,1);
  glPopMatrix;

  //kollektor
  glColor4d(0.9,0.7,0.2,0.5);
  glPushMatrix;
  glTranslate(0,0,Zkan);
  for j:=1 to Form8.SG1.RowCount-1 do
    begin
    glTranslate(0,0,k1[1,j]);
    gluCylinder(quad,k1[0,j]/10,k1[0,j+1]/10,k1[1,j+1],50,1);
    end;
  glPopMatrix;

  gluDeleteQuadric(quad);
  gluDeleteQuadric(quadDisc);
  SwapBuffers(Form1.Canvas.Handle);
  glPopMatrix;
  wglMakeCurrent ( 0 , 0 );
 end;
end;

единственное "но", появилась какая то линия, видимо граница между "лицевой" и "тыльной" стороной, увидеть её можно на картинке
43K
08 декабря 2009 года
loki231
76 / / 27.09.2009
Привет!

Я тут ещё рз критически глянул на алгоритм - никуда он не годится! То есть, если бы внутренние цилиндры были бы "нитяными", то есть линиями, тогда ещё он был бы пригоден, а в общем случае работать не будет. Эх, хорошо бы ещё пару Z-буферов. Извини, что ввёл в заблуждение.
53K
08 декабря 2009 года
edweiser
8 / / 23.11.2009
так решение этой проблемы существует или нет?:) возможности реализовать "нитяные" цилиндры нет, к сожалению....
много ведь всяких интересных вещей делали на opengl, неужели нельзя каким то образом организовать запрет рисования/отображения вне какой то области?
и как я понял нельзя, по крайней мере таким алгоритмом, не отображать часть цилиндра, но ведь есть же стандартная функция glScale которая обрезает объекты, выходящие за пределы области отображения, можно ли создать похожую вращающуюся область по нужным мне размерам?
43K
09 декабря 2009 года
loki231
76 / / 27.09.2009
Возможно, решение следует искать здесь http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=244161#Post244161.

Там есть две довольно интересные ссылки. http://developer.nvidia.com/object/Interactive_Order_Transparency.html и http://developer.download.nvidia.com/SDK/10/opengl/samples.html#dual_depth_peeling.
53K
11 декабря 2009 года
edweiser
8 / / 23.11.2009
в процессе шаманства и более глубокого изучения данной процедуры и её функций было обнаружено следующее:
если запретить очистку Z-буфера вот здесь
[ATTACH]3910[/ATTACH]
(несложно найти это место в первом ответе loki231, если обратить внимание на 2е подчёркивание)
получается вот такая штука
[ATTACH]3911[/ATTACH]
правда, вот с такой вот неприятностью
[ATTACH]3912[/ATTACH]
т.е. не прорисовывается внутренняя сторона канала и рисуется коллектор такой же формы как и должен быть, если смотреть через него на пучёк(просто боюсь что если удастся реализовать предложенный алгоритм, отсекаемая часть пучка будет видна под определённым угом).а вообще суть этого сообщения в том что вроде цилиндры то отсекаются, вот только не те....может кто придумает как сделать правильно?

лирическое отступление
ребят, 482 просмотра и один только loki231 отвечает(за что ему огромное спасибо), неужели он один разбирается в этом вопросе? я ж не какой-нибудь халявщик который хочет чтобы за него сделали всё, просто я не программист в принципе:) я физик-электронщик, которому нужно визуализировать рассчитанные процессы. войдите в моё положение, весь семестр писал эту прогу, разобрался со всеми физическими и математическими процессами, а в этом месте полный провал...курсовой срывается из-за, казалось бы, мелочи(а именно так посчитают преподы, они у нас не шарят в программировании). у тех из вас, кто действительно разбирается в этом, решение проблемы займёт ну наверно полчаса. ну не может же такая задача не быть предусмотрена разработчиками того же OpenGL......
53K
11 декабря 2009 года
edweiser
8 / / 23.11.2009
это сообощение наверно персонально для loki231
к сожалению слишком плохо знаю английский чтобы читать такие тексты, а машинный перевод разбирать приходится минуты 3 на предложение.....
и к вопросу о "нитяном пучке", я тут прикинул, мне ведь не нужно заполние всего объёма этими нитями, так же как и с цилиндрами нужен только контур. но вопрос вот в чём, как сделать заполнение этими нитями нужного объёма по радиусу? или, допустим, просчитать 15-20 огибающих и каким то образом сгладить получивщийся каркас? просто сейчас мои рассчёты возвращают радиус в конкретной окружности, её смещение от оси, ну и продольную координату этой окружности
53K
14 декабря 2009 года
edweiser
8 / / 23.11.2009
нашёл статью на русском, которую советовал loki
http://pmg.org.ru/nehe/ogl01.htm
но так и не понял как именно там организуется "расслоение" и как мне применить это к своей проблеме
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог