}
if (!LoadTexture (pFile, &texture))
return false;
glClearColor (0, 0, 0, 0);
glShadeModel (GL_SMOOTH);
glClearDepth (1);
glDepthFunc(GL_LEQUAL);
glEnable (GL_DEPTH_TEST);
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable (GL_TEXTURE_2D);
glPolygonMode (GL_BACK, GL_FILL); // Back Face Is Solid Filled
glPolygonMode (GL_FRONT, GL_LINE); // Front Face Is Made Of Lines
float
tenth = nPoints / 10.f,
omega = acos(-1.f) * 2.f / nPoints;
for (int x=0; x<nPoints; x++)
{
float
z0 = x/5.0f - tenth,
z2 = sin (omega * x );
for (int y=0; y<nPoints; y++)
{
pts[x][y][0] = z0;
pts[x][y][1] = y/5.0f - tenth;
pts[x][y][2] = z2;
}
}
return true;
}
void Draw ()
{
static float angleX, angleY, angleZ; // X, Y, Z Rotation angles
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef (0, 0, -12);
glRotatef (angleX, 1, 0, 0);
glRotatef (angleY, 0, 1, 0);
glRotatef (angleZ, 0, 0, 1);
glBindTexture (GL_TEXTURE_2D, texture);
glBegin (GL_QUADS);
for (int x = 0, n = nPoints - 1; x < n; x++)
{
for (int y = 0; y < n; y++)
{
float
xf = float(x) / n,
yf = float(y) / n,
xb = float(x+1) / n,
yb = float(y+1) / n;
glTexCoord2f (xf, yf);
glVertex3f (pts[x][y][0], pts[x][y][1], pts[x][y][2]);
glTexCoord2f (xf, yb);
glVertex3f (pts[x][y+1][0], pts[x][y+1][1], pts[x][y+1][2]);
glTexCoord2f (xb, yb);
glVertex3f (pts[x+1][y+1][0], pts[x+1][y+1][1], pts[x+1][y+1][2]);
glTexCoord2f (xb, yf);
glVertex3f (pts[x+1][y][0], pts[x+1][y][1], pts[x+1][y][2]);
}
}
glEnd();
static int wiggle; // Counter used to control the flag waving
if (wiggle == 2)
{
for (int y = 0; y < nPoints; y++)
{
float hold = pts[0][y][2];
int n = nPoints - 1;
for (int x = 0; x < n; x++)
pts[x][y][2] = pts[x+1][y][2];
pts[n][y][2] = hold;
}
wiggle = 0;
}
wiggle++;
angleX += 0.3f; angleY += 0.2f; angleZ += 0.4f;
}
void Update (DWORD ms)
{
if (gInfo.keys[VK_ESCAPE])
{
gInfo.bQuit = true;
PostMessage (gInfo.hWnd, WM_QUIT, 0, 0);
}
if (gInfo.keys[VK_F1])
PostMessage (gInfo.hWnd, WM_TOGGLEFULLSCREEN, 0, 0);
}
Запустите и убедитесь, что две поверхности флага обнаруживают различное поведение. Одна из них кажется прозрачной, но это не так (ведь blending не включен). Множество полигонов лицевой поверхности флага просто не залито цветом. Это достигается установкой:
glPolygonMode (GL_FRONT, GL_LINE);
В этом режиме прорисовываются только контуры полигонов. Заметьте, что примитивы GL_QUADS считаются полигонами.
Хитрость анимации состоит в постоянном вращении флага вокруг всех трех осей и циклическом сдвиге элементов массива (координат точек поверхности). Он осуществляется на каждом третьем такте перерисовки (см. управление переменной wiggle). В этом примере, как и во многих других, изощренность алгоритма анимации (иначе, мозговых усилий программиста) намного превосходит трудность освоения нового технологического приема OpenGL. Хочется отметить, что авторы (Jeff Molofee, aka NeHe и Ted Bosco) демонстрируют великолепный подход к разработке программ, высокую культуру программирования. Удивляет тщательность и глубина проработки деталей. Далеко не все способны посвятить деталям такое количество времени и усилий. Код компактен и эффективен.
Эффект наложения нескольких текстур может быть получен в результате использования разных текстур, смешивания цветов и повторного изображения объекта. Следующий пример демонстрирует этот прием, а также механизм отображения текстурных координат на поверхность сферы. Режим такого преобразования координат задается с помощью функции glTexGeni. Если мы хотим включить режим генерации сферических координат для текстурной координаты S, то функцию glTexGeni надо вызвать с такими параметрами:
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
Повторный вызов для координаты T завершает настройку текстуры. Теперь даже если использовать эту текстуру для плоской поверхности, она будет искажена так, как если бы она была натянута на сферу. Создайте новый файл SphereTex.cpp, скопируйте в него стандартный код и внесите следующие изменения.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.