Шаг 31 - Пространство - это куб

В этом шаге нарисуем кубик и посмотрим как влияют установки вида на вид кубика.

Как обычно делаем проект. Добавим в проект 2 переменных: m_iMode - определяет режим вывода граней куба, m_fFar - определяет дальнее расстояние границ пространства.

Для упрощения функции OnDraw(...) добавим функцию DrawCube(void), которая будет просто рисовать куб, отрисовывая последовательно все его 6 граней. Чтобы посмотреть разные режимы отображения полигонов сделаем пункт меню (View->Mode) и сделаем его (меню) обработчик, который будет изменять режим. Вот его код:

void CExampleView::OnViewMode() 
{
	// TODO: Add your command handler code here
	if(m_iMode>=2)
		m_iMode = 0;
	else
		m_iMode++;
	InvalidateRect(NULL, FALSE);
}

Комментарии излишни. Теперь сделаем обработчик от клавиатуры. Напишем его так, чтобы при нажатии на стрелку вверх дальняя граница пространства отодвигалась, а при нажатии на стрелку вниз - приближалась. Допустим такой код:

void CExampleView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default

	if(nChar==VK_UP)
		m_fFar+=0.5f;
	if(nChar==VK_DOWN)
		m_fFar-=0.5f;
	InvalidateRect(NULL, FALSE);

	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

Разумеется, незабудьте создать переменные m_iMode и m_fFar и проинициализировать их в конструкторе.

Теперь наша многострадальная функция OnDraw(...) примет следующий вид:

void CExampleView::OnDraw(CDC* pDC)
{
	CRect clientRect;

	CExampleDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	// TODO: add draw code for native data here
	GetClientRect(&clientRect);
	glViewport(0, 0, clientRect.right, clientRect.bottom);

	glClearColor (0.5, 0.5, 0.75, 1.0);
	glClear (GL_COLOR_BUFFER_BIT);

	glColor3f (1.0, 0.0, 0.5);

	glLoadIdentity();
	glFrustum (-1, 1, -1, 1, 3, m_fFar);
	glTranslatef(0.0, 0.0, -8.0);

	glRotatef(30.0, 1.0, 0.0, 0.0);
	glRotatef(70.0, 0.0, 1.0, 0.0);

	switch(m_iMode)
	{
	case 0:
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		break;
	case 1:
		glEnable(GL_POINT_SMOOTH);
		glPointSize(10);
		glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
		break;
	case 2:
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		break;
	}

	DrawCube();

	SwapBuffers(pDC->m_hDC);
}

Где функция DrawCube(void) выглядит так:

GLvoid CExampleView::DrawCube()
{
	glBegin (GL_QUADS);
		glVertex3f (1.0, 1.0, 1.0);
		glVertex3f (-1.0, 1.0, 1.0);
		glVertex3f (-1.0, -1.0, 1.0);
		glVertex3f (1.0, -1.0, 1.0);
	glEnd();

	glBegin (GL_QUADS);
		glVertex3f (1.0, 1.0, -1.0);
		glVertex3f (1.0, -1.0, -1.0);
		glVertex3f (-1.0, -1.0, -1.0);
		glVertex3f (-1.0, 1.0, -1.0);
	glEnd();

	glBegin (GL_QUADS);
		glVertex3f (-1.0, 1.0, 1.0);
		glVertex3f (-1.0, 1.0, -1.0);
		glVertex3f (-1.0, -1.0, -1.0);
		glVertex3f (-1.0, -1.0, 1.0);
	glEnd();

	glBegin (GL_QUADS);
		glVertex3f (1.0, 1.0, 1.0);
		glVertex3f (1.0, -1.0, 1.0);
		glVertex3f (1.0, -1.0, -1.0);
		glVertex3f (1.0, 1.0, -1.0);
	glEnd();

	glBegin (GL_QUADS);
		glVertex3f (-1.0, 1.0, -1.0);
		glVertex3f (-1.0, 1.0, 1.0);
		glVertex3f (1.0, 1.0, 1.0);
		glVertex3f (1.0, 1.0, -1.0);
	glEnd();

	glBegin(GL_QUADS);
		glVertex3f (-1.0, -1.0, -1.0);
		glVertex3f (1.0, -1.0, -1.0);
		glVertex3f (1.0, -1.0, 1.0);
		glVertex3f (-1.0, -1.0, 1.0);
	glEnd();
}

Единственная особенность новой OnDraw(...) - это 2 команды glRotatef(...), которые просто поворачивают систему координат для удобного простора объекта. Если вы закомментируете эти функции, станет понятно их предназначение.

Вот собственно и все. Соберите проект и понажимайте стрелки...


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Kirill V. Ratkin.