Библиотека трехмерной графики Open gl


Оконные координаты. Порт наблюдения. Метод Viewport



бет7/15
Дата29.05.2016
өлшемі1.07 Mb.
#100718
1   2   3   4   5   6   7   8   9   10   ...   15

4 Оконные координаты. Порт наблюдения. Метод Viewport


Какие преобразования проводит OpenGL с объектными координатами, прежде чем они оказываются оконными координатами?
Перед воспроизведением на экране объектные координаты xo, yo, zo, wo, указываемые в качестве параметров метода Vertex, претерпевают ряд линейных преобразований. Вначале они преобразуются в так называемые координаты наблюдения xe, ye, ze, we. Далее, координаты наблюдения преобразуются в координаты отсечения xc, yc, zc, wc. Координаты отсечения делятся на значение wc, образовав нормализованные координаты устройства xd, yd, zd. Под "устройством" понимается "порт наблюдения" – прямоугольник в окне, с которым связан контекст воспроизведения. В данном случае этим окном является панель panelGL.

По умолчанию матрицы преобразования от объектных координат к координатам наблюдения и от координат наблюдения к координатам отсечения являются единичными. Поэтому, по умолчанию xo = xc, yo = yc, zo = zc, wo = wc. Следовательно, если координата wo = 1, то объектные координаты xo, yo, zo совпадают с нормализованными координатами устройства xd, yd, zd.

Координаты пикселя относительно границ панели xw, yw, zw называются оконными. Оконные координаты xw, yw измеряются в пикселях относительно нижнего левого угла клиентской области окна (в данном случае панели panelGL).

Портом наблюдения (Viewport) называют прямоугольную область, выделенную в оконных координатах, в границах которой воспроизводятся объекты OpenGL. В общем случае порт наблюдения определяется положением своего нижнего левого угла (x, y) в оконных координатах относительно левого нижнего угла окна, шириной w и высотой h, выраженных в пикселях. Поэтому положение центра порта ox, oy относительно левого нижнего угла окна имеет вид ox = x + w/2; oy = y + h/2. Между оконными xw, yw и координатами устройства xd, yd (координаты z будут рассматриваться позже) существуют соотношения вида

xw = (w/2)*xd + ox; yw = (h/2)*yd + oy.

По умолчанию порт наблюдения совпадает со всей клиентской областью окна, то есть, в данном случае, занимает всю поверхность панели panelGL. Поэтому в последних формулах x = 0, y = 0, h - высота клиентской области панели, w – ширина этой области. Отсюда следует, что точка с координатами xo = 0, yo = 0 должна по умолчанию получить оконные координаты xw = ox = w/2, yw = oy = h/2. Поэтому точка изображается в центре панели.

Однако, изменение размеров панели не влечет за собой автоматического изменения размеров порта наблюдения w, h, фигурирующих в формулах. В OpenGL существует специальная команда Viewport, задающая параметры порта наблюдения.

///

/// Устанавливает порт наблюдения.

///

///

/// Определяет левую сторону прямоугольника порта наблюдения

/// по отношению к левой стороне окна.

/// По умолчанию 0.

///

///

/// Определяет нижнюю сторону прямоугольника порта наблюдения

/// по отношению к нижней стороне окна. По умолчанию 0.

///

///

/// Определяет ширину порта наблюдения в пикселях.

/// Когда контекст воспроизведения впервые привязывается

/// к окну значение равно ширине окна.

///

///

/// Определяет высоту порта наблюдения в пикселях.

/// Когда контекст воспроизведения впервые привязывается

/// к окну значение равно высоте окна.

///

[DllImport("OPENGL32.DLL", EntryPoint = "glViewport")]

public static extern void Viewport(int x, int y, int width, int height);

Поместите это описание в класс gl библиотеки GL.

Можно связать изменение размеров панели с размерами порта наблюдения. Для этого на форме f3D выберите панель panelGL и в окне свойств этой панели на странице обработчиков (кнопка с изображением молнии) найдите обработчик события SizeChanged. Этот обработчик будет выполняться при изменении размеров панели panelGL. Поместите в обработчик события SizeChanged панели panelGL код

// Если контекст воспроизведения не установлен, то выход из метода

if (null == port) return;

gl.Viewport(0, 0, panelGL.ClientSize.Width, panelGL.ClientSize.Height);

RenderFrame();

Теперь изменения размеров панели не будет влиять на положение точки, так как порт наблюдения будет автоматически подстраиваться под размеры панели. Порт наблюдения всегда будет совпадать с клиентской областью панели panelGL и точка с объектными координатами 0, 0 окажется в центре панели.


Метод Project


В OpenGL существует команда Project, которая позволяет по объектным координатам вершины определить оконные координаты

///

/// Отображает объектные координат objx, objy, objz

/// на оконные координаты winx, winy, winz при заданных:

/// матрице преобразования от объектных к координатам наблюдения modelMatrix,

/// матрице преобразования projMatrix от координат наблюдения к координатам отсечения

/// и параметрах порта наблюдения viewport

///

[DllImport("GLU32.DLL", EntryPoint = "gluProject")]

public static extern void Project(double objx, double objy, double objz,

double[] modelMatrix, double[] projMatrix, int[] viewport,

out double winx, out double winy, out double winz);

Поместите это описание метода Project в класс gl библиотеки GL.

Для использования этого метода необходимо знать текущую матрицу преобразования от объектных координат к координатам наблюдения (MODELVIEW_MATRIX), от координат наблюдения к координатам отсечения (PROJECTION_MATRIX), и, наконец, параметры порта наблюдения (VIEWPORT). Все эти величины можно получить, используя функцию Get в форме

double[] prMtrx = new double[16], mvMtrx = new double[16];

int[] vp = new int[4];

for (int i = 0; i < 16; i++)

{

prMtrx[i] = gl.Get(gl.PROJECTION_MATRIX, 16)[i];



mvMtrx[i] = gl.Get(gl.MODELVIEW_MATRIX, 16)[i];

if (i < 4) vp[i] = (int)gl.Get(gl.VIEWPORT, 4)[i];

}

Константы, которые использует Get в данном случае, имеют вид



///

/// Аргумент Get требует возврата значения 16 параметров матрицы преобразования

/// от объектных координат к координатам наблюдения, находящейся на верху стека.

///

public const int MODELVIEW_MATRIX = 0x0BA6;

///

/// Аргумент Get требует возврата значения 16 параметров матрицы преобразования

/// от координат наблюдения к координатам отсечения, находящейся на верху стека.

///

public const int PROJECTION_MATRIX = 0x0BA7;

///

/// Аргумент Get требует возврата значения четырех параметров порта наблюдения

/// x, y, width, height.

///

public const int VIEWPORT = 0x0BA2;

Описание констант поместите в класс gl библиотеки GL.

Чтобы наблюдать значения оконных координат вершины, которые возвращает метод Project, добавьте к коду оператора case "One point": код вывода этих значений в строку статуса. Так, что полный код оператора case будет иметь вид

case "One point":

double[] prMtrx = new double[16], mvMtrx = new double[16];

int[] vp = new int[4];

for (int i = 0; i < 16; i++)

{

prMtrx[i] = gl.Get(gl.PROJECTION_MATRIX, 16)[i];



mvMtrx[i] = gl.Get(gl.MODELVIEW_MATRIX, 16)[i];

if (i < 4) vp[i] = (int)gl.Get(gl.VIEWPORT, 4)[i];

}

float Xo, Yo, Zo;



Xo = 0; Yo = 0; Zo = 0;

gl.Begin(gl.POINTS);

gl.Vertex(Xo, Yo);

gl.End();

double Xw, Yw, Zw;

gl.Project(Xo, Yo, Zo, mvMtrx, prMtrx, vp, out Xw, out Yw, out Zw);

stLabel.Text = string.Format(

"Xw={0:f}; Yw={1:f}; panelGL: Width={2}; Height={3}; Центр: Ox={4}; Oy={5}",

Xw, Yw, panelGL.ClientSize.Width, panelGL.ClientSize.Height,

panelGL.ClientSize.Width / 2, panelGL.ClientSize.Height / 2);

break;

В результате в строке статуса должна появиться информация, с помощью которой можно проверить формулы преобразования от объектных координат xo, yo к оконным координатам xw, yw:



xw = (w/2)*xd + ox; yw = (h/2)*yd + oy.
Читатель может отредактировать свой проект, либо посмотреть иллюстрирующее приложение. Ссылка для того, кто продолжает создавать авторское приложение.
Посмотрите и проанализируйте результат, меняя положение вершины на панели panelGL.
Если возникает необходимость сохранить параметры порта наблюдения в стеке, то используется метод PushAttrib с параметром VIEWPORT.
Тест рубежного контроля

  1. Какие системы координат используют команды OpenGL?

  2. Что такое порт наблюдения?

  3. Что такое оконные координаты?

  4. Как определены параметры порта наблюдения по умолчанию?

  5. Какой метод управляет параметрами порта наблюдения?

  6. Где следует вызывать метод, определяющий порт наблюдения?

  7. Что делает метод Project?

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



Достарыңызбен бөлісу:
1   2   3   4   5   6   7   8   9   10   ...   15




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет