0 / 0 / 0
Регистрация: 11.11.2012
Сообщений: 76
1

В буфер выбора записываются все объекты из стека имен

02.02.2017, 10:23. Показов 403. Ответов 4
Метки нет (Все метки)

Здравствуйте, есть вопрос не дающий покоя. Вроде все правильно, но работает не корректно. Есть класс, в котором происходить непосредственная прорисовка объектов OpenGL.

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
unit ObjClass
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, mathMetrix, gl, glu,GLX, OpenGLContext, ImagingOpenGL;
type
  TObjClass = class(TObject)
    private
      public
        procedure RelayDraw(BasePoint : TArray_BPoint);
 
 
  end;
  var
    clsObj         : TRelayClass;
 
 
 
implementation
 
procedure TObjClass.ObjDraw (BasePointX : GLDouble; BasePointY : GLDouble);
begin
 
glColor3d(0.0, 0.0, 1.0); 
glBegin(GL_POLYGON);
  glVertex2d(BasePointX - 0.01, BasePointY + 0.01 );
  glVertex2d(BasePointX + 0.01, BasePointY + 0.01 );
  glVertex2d(BasePointX + 0.01, BasePointY + 0.01 );
  glVertex2d(BasePointX + 0.01, BasePointY - 0.01 );
  glVertex2d(BasePointX + 0.01, BasePointY - 0.01 );
  glVertex2d(BasePointX - 0.01, BasePointY - 0.01 );
  glVertex2d(BasePointX - 0.01, BasePointY - 0.01 );
  glVertex2d(BasePointX - 0.01, BasePointY + 0.01 );
 glEnd();
end;
 
end.
Есть другой класс, в котором создаются объекты предыдущего. В функции OpenGLControl1Paint создаются объекты и помещаются в стек имен. А потом по нажатию кнопки мыши, находящийся под курсором мышки объект должен быть помещен в буффер выбора:

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
unit Main;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, gl,
  glu, LCLType, ExtCtrls, ComCtrls, Buttons, OpenGLContext, ObjClass;
 
type
 
  { Tfrm }
 
  Tfrm = class(TForm)
    OpenGLControl1: TOpenGLControl;
    OpenGLControl2: TOpenGLControl;
    procedure BtnClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure OpenGLControl1Click(Sender: TObject);
    procedure OpenGLControl1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure OpenGLControl1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure OpenGLControl1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure OpenGLControl1Paint(Sender: TObject);
    procedure OpenGLControl2MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure OpenGLControl2Paint(Sender: TObject);
  private
    { private declarations }
  public
    procedure IdleFunc(Sender: TObject; var Done: Boolean);
    procedure Selection(X : integer; Y : integer);
 
    { public declarations }
  end;
 
var
  BasePointX,
  BasePointY,
        : Double;
  buffer_len: integer = 63;
  MoveFlag  : Boolean;   
 
  ID0               : GLuint    = 0;
  ID1               : GLuint    = 1;
  ID2               : GLuint    = 2;
  ID3               : GLuint    = 3;
  ID4               : GLuint    = 4;
  ID5               : GLuint    = 5;
 
 
implementation
 
{$R *.lfm}
 
{ Tfrm }
 
procedure Tfrm.FormCreate(Sender: TObject);
var p2, p3  :TPoint;
begin
 MoveFlag      := False;  
 Application.OnIdle:= @IdleFunc;
 BasePointX        := 0.7;            // начальное положение объектов расчитывается исходня из данных значений, потом идет перерасчет этих координат, когда нажата правая кнопка мыши, таким образом объект движется
 BasePointY        := 0.7;
 
end;
 
 
procedure Tfrm.OpenGLControl1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 
 
  if (Button = mbLeft) then
     begin
      MoveFlag := not MoveFlag;
      Selection(X, Y);
     end;
 
end;
 
 
//далее идет перевод оконных координат в координаты OpenGL
procedure Tfrm.OpenGLControl1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
  var viewport : array [0..3] of GLint;
      mvMatrix, mvProjMatrix : array [0..15] of TGLdouble;
      realY1 : Integer;
      wx1, wy1, wz1, d1P : GLdouble;
      pwx1, pwy1, pwz1, pd1P : PGLdouble;
      zval : GLfloat;
  begin
    if not MoveFlag then
         exit;
    pwx1:= @wx1;
    pwy1:= @wy1;
    pwz1:= @wz1;
 
    glGetIntegerv(GL_VIEWPORT, @viewport);
    glGetDoublev(GL_MODELVIEW_MATRIX, @mvMatrix);
    glGetDoublev(GL_PROJECTION_MATRIX,@mvProjMatrix);
 
    realY1:=viewport[3]- Y;
    glReadPixels(x, realY1, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, @zval);
    gluUnProject(GLDouble(x), GLDouble(realY1), GLDouble(zval), @mvMatrix, @mvProjMatrix, @viewport, pwx1, pwy1, pwz1);
 
    if wx1>0.95 then
         BasePointX := 0.95
    else if wx1<-0.95 then
       BasePointX := -0.95
    else
       BasePointX   := wx1;
 
    if wy1>0.95 then
       BasePointY := 0.95
    else if wy1<-0.95 then
       BasePointY := -0.95
    else
       BasePointY := wy1;
 
  end;
 
procedure Tfrm.OpenGLControl1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 
MoveFlag := not MoveFlag;
 
end;
 
 
 
procedure Tfrm.OpenGLControl1Paint(Sender: TObject);
var
 
  Obj0, Obj1, Obj2 : TObjClass;
 
begin
 
  glClearColor(0.0, 0.0, 0.0, 0.0);
 
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 
  glMatrixMode(GL_PROJECTION);
  glViewport(0, 0, OpenGLControl1.Width, OpenGLControl1.Height);
  compWidth:=OpenGLControl1.Width;
 
   glPushMatrix();
   glLoadIdentity();
   glInitNames();
   glPushName(0);
 
//заносим 3 объекта в стек имен
 
     glPushMatrix();
     glLoadName(ID0);
     Obj0 :=TObjClass.Create;
     Obj0.ObjDraw (BasePointX, BasePointY);
    glPopMatrix();
 
 
    glTranslated(0.0, -0.4, 0.0);
    glPushMatrix();
    glLoadName(ID1);
    Obj1 :=TObjClass.Create;
    Obj1.ObjDraw (BasePointX, BasePointY);
    glPopMatrix();
 
    glTranslated(-0.4, 0.0, 0.0);
    glPushMatrix();
    glLoadName(ID2);
    Obj2 :=TObjClass.Create;
    Obj2.ObjDraw (BasePointX, BasePointY);
    glPopMatrix();
 
 glPopMatrix();
 
  OpenGLControl1.SwapBuffers;
 
end;
 
procedure Tfrm.IdleFunc(Sender: TObject; var Done: Boolean);
begin
 OpenGLControl1.Invalidate;
end;
 
 
procedure Tfrm.Selection(X : integer; Y : integer);
var selectBuf                 : array [0..63] of GLint;
    viewport              : array [0..3] of GLint;
    fAspect           : GLfloat;
    ObjFound              : GLint;
    lowestDepth, selObject, i : integer;
 
begin
  glSelectBuffer(buffer_len+1, @selectBuf); // инициализирум буфер выбора
  glGetIntegerv(GL_VIEWPORT, @viewport);
 
  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
    glRenderMode(GL_SELECT);
    glLoadIdentity();
    gluPickMatrix(GLdouble(X), GLdouble(viewport[3]-Y), 0.1, 0.1, viewport);
    OpenGLControl1Paint(nil);
    ObjFound := glRenderMode(GL_RENDER);
 
    glMatrixMode(GL_PROJECTION);
 
  glPopMatrix();
 
  i:=1;
  if ObjFound>0 then
     begin
 
      lowestDepth := selectBuf[1];
        selObject       := selectBuf[3];
 
      {ShowMessage('selectBuf[0] ' + IntToStr(selectBuf[0])); // выводятся сообщения о каждом объекте из стека имен
      ShowMessage('selectBuf[1] ' + IntToStr(selectBuf[1]));
      ShowMessage('selectBuf[2] ' + IntToStr(selectBuf[2]));
      ShowMessage('selectBuf[3] ' + IntToStr(selectBuf[3]));
      ShowMessage('selectBuf[4] ' + IntToStr(selectBuf[4]));
      ShowMessage('selectBuf[5] ' + IntToStr(selectBuf[5]));
      ShowMessage('selectBuf[6] ' + IntToStr(selectBuf[6]));
      ShowMessage('selectBuf[7] ' + IntToStr(selectBuf[7]));
      ShowMessage('selectBuf[8] ' + IntToStr(selectBuf[8]));
      ShowMessage('selectBuf[9] ' + IntToStr(selectBuf[9]));
      ShowMessage('selectBuf[10] ' + IntToStr(selectBuf[10]));
      ShowMessage('selectBuf[11] ' + IntToStr(selectBuf[11]));
     }
 
 
      while i < ObjFound do
            begin
             if (selectBuf[(i*4)+1] < GLuint(lowestDepth))then
                    begin
                  lowestDepth := selectBuf[(i * 4) + 1];
                  selObject     := selectBuf[(i * 4) + 3];
 
                 // ShowMessage('new ' + IntToStr(lowestDepth));
                        //  ShowMessage('new ' + IntToStr(selObject));
                end;
             inc(i);
          end;
     end;
end;
end.
Вопрос заключается в том, что перетаскавается по экрану не выбранный объект, а все. Т.е. в буффер выбора записыватся абсолютно все объекты в том порядке, в котором они заносятся в стек имен
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.02.2017, 10:23
Ответы с готовыми решениями:

При инициализации почему-то во все объекты записываются данные последнего
Решил я немного разобраться с наследованием в JS, что то смог более менее понять сам, а что то не...

GluPickMatrix не выбирает из стека имен
Здравствуйте, меня уже сводит сума один вопрос. Раньше была одна проблема, сейчас кардинально...

Стек: Переместить все элементы из первого стека во второй и вывести адрес новой вершины стека
Даны указатели P1 и P2 на вершины двух непустых стеков. Переместить все элементы из первого стека...

Создать два новых стека, переместив в первый из них все элементы исходного стека с четными значениями
Дан указатель P1 на вершину непустого стека. Создать два новых стека, переместив в первый из них...

4
2522 / 1329 / 221
Регистрация: 26.02.2009
Сообщений: 6,165
Записей в блоге: 5
02.02.2017, 18:57 2
Если не считать постоянно утекающую память в рендере TObjClass.Create (где Free?) то основная проблема в том что все изменения делаются с матрицей проекции, а GL_MODELVIEW нигде не фигурирует.
Тут есть пример об использовании gluPickMatrix
When rendering a scene as follows:


Delphi
1
2
3
4
5
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(...);
glMatrixMode(GL_MODELVIEW);
/* Draw the scene */
a portion of the viewport can be selected as a pick region like this:


Delphi
1
2
3
4
5
6
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(x, y, width, height, viewport);
gluPerspective(...);
glMatrixMode(GL_MODELVIEW);
/* Draw the scene */
0
0 / 0 / 0
Регистрация: 11.11.2012
Сообщений: 76
27.02.2017, 13:35  [ТС] 3
Ну так у меня все преобразования в матрице проекций и непосредственно сам выбор. Я не понимаю, вообще не получается...не пойму где ошибка
0
2522 / 1329 / 221
Регистрация: 26.02.2009
Сообщений: 6,165
Записей в блоге: 5
27.02.2017, 13:45 4
Цитата Сообщение от Dev_Dev Посмотреть сообщение
все преобразования в матрице проекций и непосредственно сам выбор.
Сделайте по-нормальному. Матрица проекции предназначена только для проекции. Для остального есть MODELVIEW.
Многие ф-ии старого OpenGL чувствительны к этим матрицам. Глючить будет не только выбор, но и свет, туман...
0
0 / 0 / 0
Регистрация: 11.11.2012
Сообщений: 76
27.02.2017, 14:41  [ТС] 5
ну вот я убираю GL_PROJECTION и все-равно получаю буффер, в который записываются все ID всех объектов, причем в том порядке, в котором они были занесены в список отображения
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  glSelectBuffer(buffer_len+1, @selectBuf);
  glGetIntegerv(GL_VIEWPORT, @viewport);
  glPushMatrix();
     glRenderMode(GL_SELECT);
     gluPickMatrix(GLdouble(X), GLdouble(viewport[3]-Y), 0.1, 0.1, viewport);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     OpenGLControl1Paint(nil);
     ObjFound := glRenderMode(GL_RENDER);
 
   glPopMatrix();
 
   if ObjFound>0 then
      begin
 
       lowestDepth := selectBuf[1];
        selObject       := selectBuf[3];
 
 
       ShowMessage('selectBuf[3] ' + IntToStr(selectBuf[3]));
       ShowMessage('selectBuf[7] ' + IntToStr(selectBuf[7]));
       ShowMessage('selectBuf[11] ' + IntToStr(selectBuf[11]));
Добавлено через 16 минут
если вы догадываетесь где возможна ошибка, пожалуйста подскажите....я голову уже ломаю третью неделю...это просто ужас
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.02.2017, 14:41

Ошибка: переполнение стека (графические объекты)
Turbo Pascal - ошибка переполнение стека (графические объекты)??? что не так?? uses crt,graph; ...

Дан указатель P1 на вершину стека (если стек пуст, то P1 = nil). Извлечь из стека все элементы и вывести их значения
Динамические структуры данных Все числа, используемые в заданиях на динамические структуры...

Удалить все объекты и создать объекты - потомки
Как сделать клоны объекта в другом объекте? Использую метод Instantiate Есть метод public...

создать стек в памяти из этих чисел таким образом, чтобы на вершине стека было самое большое число. Удалить из стека все отрицательные элементы.
Помогите решить. В файл записывается последовательность целых чисел. Прочитать последовательность...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.