Цветное движущееся изображение: песочные часы

Министерство  образования и науки Российской Федерации

Южно-Уральский  государственный университет

Приборостроительный факультет

Кафедра «Электронные вычислительные машины»

 

 

 

 

 

Цветное движущееся изображение:

песочные часы

 

 

 

 

ПОЯСНИТЕЛЬНАЯ ЗАПИСКА

К КУРСВОЙ РАБОТЕ

по дисциплине

«Компьютерная графика»

ЮУрГУ-010400-2011-561 ПЗ КР

 

 

 

 

 

 

 

 

Руководитель

доцент кафедры  «ЭВМ»

___________ Е.С.  Ярош

«__» __________ 2011 г.

 

Автор работы

студент группы ПС-458

________ М.Ю.  Осипов

«__» __________ 2011 г.

 

 

 

 

 

 

 

 

 

 

 

 

 

Челябинск 2011 

Министерство образования и  науки Российской Федерации

Южно-Уральский государственный  университет

 

Факультет: Приборостроительный

Кафедра: «Электронные вычислительные машины»

Направление: «Информационные технологии»

 

 

 

 

ЗАДАНИЕ

на курсовую работу

студента группы ПС-458 Осипова Максима  Юрьевича

 

Дисциплина: «Компьютерная графика»

Тема работы: «Цветное движущееся изображение: песочные часы»

Дата выдачи работы: «__» __________ 2011 г.

Перечень вопросов, подлежащих разработке:

  1. Обеспечить построение движущегося изображения (отсчитывающих время песочных часов) средствами OpenGL и DirectX.
  2. Предусмотреть возможность регулировки скорости и приостановки анимации пользователем с помощью мыши и/или клавиатуры.
  3. Предусмотреть удобный пользовательский интерфейс (элементы управления и меню) для управления анимацией в соответствии с п. 2.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Руководитель проекта _____________________________ / Е.С. Ярош /

Студент __________________________ / М.Ю. Осипов /

ОГЛАВЛЕНИЕ

1. Алгоритмические  особенности реализации 4

1.1. Модель  колбы песочных часов 4

1.2. Модель  перетекающей воды 5

1.3. Модель  пересыпающегося песка 5

1.4. Объект  сцены и построение изображения 5

2. Исходные тексты программы 7

2.1. Модель  песочных часов 7

2.2. Объект  сцены 9

2.3. Построение  изображения средствами OpenGL 12

2.4. Построение  изображения средствами DirectX 15

3. Требования  к системе пользователя 18

3.1. Требования  к программному обеспечению 18

3.2. Минимальные  требования к аппаратному обеспечению 18

4. Примеры  работы программы 19

Библиографический список 21

 

1. АЛГОРИТМИЧЕСКИЕ ОСОБЕННОСТИ  РЕАЛИЗАЦИИ

1.1. Модель колбы песочных часов

Изображение колбы песочных часов формируется  совокупностью четырехугольников, как это показано на рисунке 1.1.

 

Рис. 1.1. Схема разбиения изображения  колбы на четырехугольники.

 

При этом форма линии, ограничивающей вогнутую часть колбы, задается кубической параболой (y = x3) на промежутке [-1; -0,5]. Для выпуклой части парабола задается на отрезке [0,5; 1]. В соответствии с шириной колбы и ее положением на координатной плоскости заданные линии смещаются в нужном направлении и масштабируются. Для этого в уравнение кубической параболы вводятся дополнительные коэффициенты и величины смещения.

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

Из получаемых точек формируются четырехугольники. Информация о них сохраняется  в специальный объект — геометрическую модель, которая затем будет отрисовываться с помощью OpenGL и DirectX.

1.2. Модель перетекающей воды

Алгоритм  получения модели перетекающей воды достаточно прост. За основу берется  описанная выше модель колбы (так  как вода повторяет ее форму). Меняется лишь верхняя (или нижняя) координата y — таким образом регулируется уровень воды в верхней (ограничение сверху) и нижней (ограничение снизу) части колбы. Обычное сравнение координат позволяет выяснить, какие точки должны быть исключены из модели.

Кроме того, модель имеет некоторое множество состояний. Текущее состояние определяет уровень воды. В состоянии, когда уровень воды равен высоте колбы, модели колбы и перетекающей воды идентичны.

1.3. Модель пересыпающегося песка

Модель  песка является модификацией модели перетекающей воды. Отличие состоит в том, что в этом случае необходимо выполнить имитацию «горки» песка при его пересыпании в нижнюю часть колбы часов.

Это реализуется  путем введения в модель смещения по оси y крайних точек относительно центральной (средней) точки — вершины «горки». К моменту наполнения нижней части колбы смещение начинает уменьшаться, и уровень песка плавно выравнивается.

1.4. Объект сцены и построение  изображения

Все созданные  экземпляры моделей помещаются в объект сцены. Этот объект имеет свое множество состояний (кадров), которые последовательно меняются по внешнему сигналу от системного таймера (вообще говоря, источник внешних сигналов может быть любым). Принцип действия модели подобен закону функционирования автомата Мура, а данный сигнал играет роль сигнала синхронизации. После изменения состояния объект сцены обновляет (если требуется) состояние всех моделей.

Кроме того, объект сцены обладает параметром, задающим угол поворота всего изображения вокруг начала координат. Значение этого параметра также устанавливается в зависимости от текущего состояния. Смена состояний происходит циклически.

Таким образом, объект сцены содержит полную информацию обо всем изображении, поэтому  именно на его основе будет осуществляться рендеринг.

Для построения изображения используются два независимых  объекта, имеющих одинаковый интерфейс, каждый из которых отвечает за рендеринг  изображения средствами  OpenGL и DirectX соответственно. Также эти объекты берут на себя ответственность за инициализацию графической библиотеки и освобождение ресурсов. В пределах одного сеанса работы с приложением активируется только один из этих объектов.

Принцип построения изображения достаточно прост. Каждая из моделей, включенных в  сцену, отрисовывается в виде совокупности заданных в ней четырехугольников с помощью средств рисования многоугольников (полигонов) графической библиотеки. Перед началом отображения моделей к изображению применяется матрица поворота, величина угла которого хранится в качестве параметра объекта сцены.

В DirectX отсутствуют средства автоматического рисования произвольных выпуклых многоугольников. Поэтому четырехугольники, из которых состоят модели, подвергаются предварительной триангуляции — каждый из них разбивается на два треугольника. Триангуляция выполняется на этапе формирования вершинных буферов. В OpenGL триангуляция выполняется автоматически при построении многоугольника.

2. ИСХОДНЫЕ ТЕКСТЫ ПРОГРАММЫ

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

2.1. Модель песочных часов

 

Данный  класс содержит в себе модели пересыпающегося  песка, перетекающей воды и колбы  песочных часов, так как их формы схожи, алгоритмы их построения отличаются незначительно, и эти отличия заключаются в задании разных параметров.

Листинг 2.1. Файл HourglassModel.h

 

#ifndef HOURGLASSMODEL_HEADER

#define HOURGLASSMODEL_HEADER

 

#include "ColoredModel.h"

 

class HourglassModel : public ColoredModel

{

private:

    PolygonMap polyMap_; // список четырехугольников

    bool isInverse_; // признак нижней части колбы

    double width_; // ширина модели

    double height_; // высота модели

    double interY_; // ограничение высоты модели

    bool isSand_; // признак формы модели (песок или вода)

public:

    HourglassModel(double width = 2.0, double height = 8.0,

        bool isInverse = false, double interY = 0.0);

    void build(); // построение модели

    virtual void setState(double state = 0.0); // установка состояния модели

    virtual const PolygonMap& getPolygonMap() const; // извлечение полигонов

};

 

#endif // HOURGLASSMODEL_HEADER

 

Листинг 2.2. Файл HourglassModel.cpp

 

#include "HourglassModel.h"

 

HourglassModel::HourglassModel(double width, double height, bool isInverse,

    double interY) : width_(width), height_(height), isInverse_(isInverse),

    interY_(interY), isSand_(false)

{

    build();

}

 

void HourglassModel::build()

{

    pointMap_.clear();

    polyMap_.clear();

 

    double halfWidth = width_ / 2.0;

    double topY = (isInverse_) ? height_ : height_ - interY_;

    double bottomY = (isInverse_) ? interY_ : 0.0;

    double quaWidth = halfWidth / 2.0;

    double offset = halfWidth - 2.0 * quaWidth * quaWidth * quaWidth;

 

    PointMap slideMap;

 

    double deltaB = (bottomY >= 3.0) ? quaWidth :

        (bottomY - 3.0) / 2.0 + quaWidth; // смещение

    if ((isSand_) && (deltaB >= 0.0))

        bottomY += deltaB;

    double delta = (bottomY >= 1.0) ? quaWidth : (bottomY - quaWidth);

    if ((!isSand_) || (delta < 0.0)) // компенсирующее смещение

        delta = 0.0;

    slideMap.push_back(Point(0.0, bottomY - delta));

    slideMap.push_back(Point(0.04, bottomY - delta));

    for (double x = 0.04; x < halfWidth; x += 0.01)

    {

        double x3 = (x < quaWidth) ? x - halfWidth : x;

        double y = x3 * x3 * x3 + ((x < quaWidth) ? halfWidth : offset);

        if ((y <= topY) && (y >= bottomY))

            slideMap.push_back(Point(x, y));

    }

    double lastY = halfWidth + offset;

    if ((lastY <= topY) && (lastY >= bottomY))

        slideMap.push_back(Point(halfWidth, lastY));

    else if (bottomY > lastY)

    {

        double x = (bottomY > topY) ?

            (delta - (bottomY - topY)) * 2 : halfWidth;

        double y = (bottomY > topY) ? topY : bottomY;

        slideMap.push_back(Point(x, y));

    }

 

    PointMap::iterator pos = slideMap.begin();

    if (pos != slideMap.end())

    {

        double prevX = pos->x;

        double prevY = pos->y;

        ++pos;

        while (pos != slideMap.end())

        {

            double x = pos->x;

            double y = pos->y;

            PointMap polygon;

            if (!isInverse_)

            {

                polygon.push_back(Point(x, topY));

                polygon.push_back(Point(x, y));

                polygon.push_back(Point(prevX, prevY));

                polygon.push_back(Point(prevX, topY));

                polyMap_.push_back(polygon);

                polygon.clear();

                polygon.push_back(Point(-prevX, topY));

                polygon.push_back(Point(-prevX, prevY));

                polygon.push_back(Point(-x, y));

                polygon.push_back(Point(-x, topY));

                polyMap_.push_back(polygon);

            }

            else

            {

                polygon.push_back(Point(prevX, -topY));

                polygon.push_back(Point(prevX, -prevY));

                polygon.push_back(Point(x, -y));

                polygon.push_back(Point(x, -topY));

                polyMap_.push_back(polygon);

                polygon.clear();

                polygon.push_back(Point(-x, -topY));

                polygon.push_back(Point(-x, -y));

                polygon.push_back(Point(-prevX, -prevY));

                polygon.push_back(Point(-prevX, -topY));

                polyMap_.push_back(polygon);

            }

            ++pos;

            prevX = x;

            prevY = y;

        }

    }

}

 

void HourglassModel::setState(double state)

{

    isSand_ = (state > 1.0);

    if (isSand_)

        state -= 1.0;

    interY_ = height_ * state;

    build();

}

 

const PolygonMap& HourglassModel::getPolygonMap() const

{

    return polyMap_;

}

 

2.2. Объект сцены

 

Листинг 2.3. Файл Scene.h

 

#ifndef SCENE_HEADER

#define SCENE_HEADER

 

#include <vector>

 

#include "IModel.h"

 

class Scene

{

private:

    std::vector<IModel*> models_; // список моделей сцены

    double angle_; // угол поворота изображения

    unsigned int state_; // текущее состояние сцены

    unsigned int speed_; // скорость (количество пропускаемых кадров)

    bool isPaused_; // признак приостановки

    bool isSand_; // признак материала (вода или песок)

public:

    Scene();

    unsigned int count(); // количество моделей

    // возвращает модель с указанным индексом

    const IModel& operator [](unsigned int index);

    void synchronize(); // переход к следующему состоянию (такт автомата)

    void setSand(bool isSand = true); // установка признака материала

    bool pause(); // приостановка сцены

    bool increaseSpeed(); // увеличение скорости

    bool decreaseSpeed(); // уменьшение скорости

    bool isPaused(); // возвращает признак приостановки

    double getAngle(); // возвращает угол поворота

    unsigned int getSpeed(); // возвращает скорость

    void setSpeed(unsigned int speed); // устанавливает скорость

    ~Scene();

};

 

#endif // SCENE_HEADER

 

Листинг 2.4. Файл Scene.cpp

 

#include "Scene.h"

#include "HourglassModel.h"

#include "StandModel.h"

#include "WaterlineModel.h"

 

Scene::Scene() : angle_(0.0), state_(0), speed_(5), isPaused_(false),

    isSand_(false)

{

    models_.push_back(new HourglassModel(2.0, 3.2));

    models_.push_back(new HourglassModel(2.0, 3.2, true));

    models_.push_back(new WaterlineModel(3.2, 3.2));

    models_.back()->setColor(Color(0, 127, 255));

    models_.push_back(new HourglassModel(2.0, 3.2, false, 0.0));

    models_.back()->setColor(Color(0, 127, 255));

    models_.push_back(new HourglassModel(2.0, 3.2, true, 3.2));

    models_.back()->setColor(Color(0, 127, 255));

    models_.push_back(new StandModel(2.5, 0.5, 3.2));

    models_.back()->setColor(Color(0, 180, 0));

    models_.back()->setLineColor(Color(0, 180, 0));

    models_.push_back(new StandModel(2.5, 0.5, -3.7));

    models_.back()->setColor(Color(0, 180, 0));

    models_.back()->setLineColor(Color(0, 180, 0));

}

 

unsigned int Scene::count()

{

    return models_.size();

}

 

const IModel& Scene::operator [](unsigned int index)

{

    return *(models_[index]);

}

 

void Scene::synchronize()

{

    if (!isPaused_)

    {

        models_[2]->setState(

            (state_ < 20) ? (200 - (double)state_) / 200 :

            (state_ < 820) ? 0.0 : 1.0);

        models_[3]->setState(

            (state_ < 0) ? 0.0 :

            (state_ < 800) ? ((double)state_) / 800 : 1.0);

        double state4 = (820 - ((double)state_ - 20)) / 820;

        models_[4]->setState(

            (state_ < 20) ? 1.0 :

            (state_ < 820) ?

            (isSand_ ? state4 + 1.0 : state4) : 0.0);

        angle_ = (state_ < 820) ? 0.0 : (state_ - 820) * 1.0;

        state_ = (state_ + speed_) % 1000 + 1;

    }

}

 

void Scene::setSand(bool isSand)

{

    isSand_ = isSand;

    Color cl = (isSand_) ? Color(255, 127, 0) : Color(0, 127, 255);

    models_[2]->setColor(cl);

    models_[3]->setColor(cl);

    models_[4]->setColor(cl);

}

 

double Scene::getAngle()

{

    return angle_;

}

 

bool Scene::pause()

{

    return isPaused_ = !isPaused_;

}

 

bool Scene::increaseSpeed()

{

    if (speed_ >= 20)

        return false;

    ++speed_;

    return true;

}

 

bool Scene::decreaseSpeed()

{

    if (speed_ <= 1)

        return false;

    --speed_;

    return true;

}

 

bool Scene::isPaused()

{

    return isPaused_;

}

 

unsigned int Scene::getSpeed()

{

    return speed_;

}

 

void Scene::setSpeed(unsigned int speed)

{

    if ((speed >= 1) && (speed <= 20))

        speed_ = speed;

}

 

Scene::~Scene()

{

    while (models_.size() > 0)

    {

        delete models_.back();

        models_.pop_back();

    }

}

 

2.3. Построение изображения  средствами OpenGL

 

Листинг 2.5. Файл GlRenderer.h

 

#ifndef GLRENDERER_HEADER

#define GLRENDERER_HEADER

 

#include <windows.h>

#include <gl/gl.h>

#include <gl/glu.h>

 

#include "IRenderer.h"

#include "HourglassModel.h"

 

class GlRenderer : public IRenderer

{

private:

    HDC device_; // контекст устройства Windows

    HGLRC renderDevice_; // контекст устройства OpenGL

    Scene scene_; // объект сцены

    void decorateWindow(); // устанавливает атрибуты окна

    void initialize(); // инициализирует OpenGL

    void cleanup(); // освобождает ресурсы OpenGL

    bool formatPixel(); // устанавливает формат пикселя

    void setViewport(RECT viewport); // устанавливает размеры области просмотра

public:

    GlRenderer();

    virtual void tick(); // переход к рисованию следующего кадра

    virtual void render(); // построение изображения

    virtual void updateViewport(); // обновление размеров области просмотра

    virtual Scene& getScene(); // возвращает объект сцены

    ~GlRenderer();

};

 

#endif // GLRENDERER_HEADER

 

Листинг 2.6. Файл GlRenderer.cpp

 

#include "GlRenderer.h"

#include "MainWindow.h"

 

void GlRenderer::decorateWindow()

{

    HWND window = MainWindow::instance()->getHandle();

    SetWindowLong(window, GWL_STYLE,

        GetWindowLong(window, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);

    SetWindowText(window, TEXT("Hourglass: OpenGL Renderer"));

}

 

void GlRenderer::initialize()

{

    MainWindow* mainWindow = MainWindow::instance();

    device_ = mainWindow->getDevice();

    if (!formatPixel())

        PostQuitMessage(1);

    renderDevice_ = wglCreateContext(device_);

    wglMakeCurrent(device_, renderDevice_);

    setViewport(mainWindow->getClientRect());

}

 

void GlRenderer::cleanup()

{

    if (device_)

    {

        if (renderDevice_)

        {

            wglMakeCurrent(NULL, NULL);

            wglDeleteContext(renderDevice_);

        }

        MainWindow::instance()->releaseDevice(device_);

    }

}

 

bool GlRenderer::formatPixel()

{

    PIXELFORMATDESCRIPTOR pfd;

    int pixelFormat;

    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);

    pfd.nVersion = 1;

    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;

    pfd.dwLayerMask = PFD_MAIN_PLANE;

    pfd.iPixelType = PFD_TYPE_RGBA;

    pfd.cColorBits = 32;

    pfd.cDepthBits = 32;

    pfd.cAccumBits = 0;

    pfd.cStencilBits = 0;

    if (FALSE == (pixelFormat = ChoosePixelFormat(device_, &pfd)))

    {

        MessageBox(NULL, TEXT("Unable to choose pixel format."),

            TEXT("OpenGL Renderer"), MB_OK);

        return false;

    }

    if (FALSE == SetPixelFormat(device_, pixelFormat, &pfd))

    {

        MessageBox(NULL, TEXT("Unable to set pixel format."),

            TEXT("OpenGL Renderer"), MB_OK);

        return false;

    }

    return true;

}

 

void GlRenderer::setViewport(RECT viewport)

{

    int width = viewport.right - viewport.left;

    int height = viewport.bottom - viewport.top;

    if (0 == height)

        height = 1;

    glViewport(viewport.left, viewport.top, width, height);

 

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

   

    glOrtho(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0);

 

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

 

GlRenderer::GlRenderer()

{

    decorateWindow();

    initialize();

}

 

void GlRenderer::tick()

{

    scene_.synchronize();

}

 

void GlRenderer::render()

{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();

    glRotatef((GLfloat)scene_.getAngle(), 0.0, 0.0, 1.0);

    for (unsigned int i = 0; i < scene_.count(); ++i)

    {

        unsigned char r = scene_[i].getColor().r;

        unsigned char g = scene_[i].getColor().g;

        unsigned char b = scene_[i].getColor().b;

        PolygonMap poly = scene_[i].getPolygonMap();

        for (PolygonMap::iterator pos = poly.begin();

            pos != poly.end();

            ++pos)

        {

            glBegin(GL_POLYGON);

            for (PointMap::iterator pt = pos->begin(); pt != pos->end(); ++pt)

            {

                glColor3ub(r, g, b);

                glVertex3d(pt->x, pt->y, 0.0);

            }

            glEnd();

        }

        glTranslatef(0.0, 0.0, 0.001);

    }

    glFinish();

    SwapBuffers(device_);

}

 

void GlRenderer::updateViewport()

{

    setViewport(MainWindow::instance()->getClientRect());

}

 

Scene& GlRenderer::getScene()

{

    return scene_;

}

 

GlRenderer::~GlRenderer()

{

    cleanup();

}

 

2.4. Построение изображения средствами DirectX

 

Листинг 2.7. Файл DirectRenderer.h

 

#ifndef DIRECTRENDERER_HEADER

#define DIRECTRENDERER_HEADER

#include <windows.h>

#include <d3d9.h>

#include <d3dx9.h>

#include "IRenderer.h"

#include "DirectVertex.h"

 

class DirectRenderer : public IRenderer

{

private:

    Scene scene_; // объект сцены

    IDirect3D9* direct_; // объект DirectX

    IDirect3DDevice9* renderDevice_; // объект устройства (видеокарты)

    void decorateWindow(); // устанавливает атрибуты окна

    void initialize(); // инициализирует DirectX

    void cleanup(); // освобождает ресурсы DirectX

    void setViewport(); // устанавливает размеры области просмотра

public:

    DirectRenderer();

    virtual void tick(); // переход к рисованию следующего кадра

    virtual void render(); // построение изображения

    virtual void updateViewport(); // обновление размеров области просмотра

    virtual Scene& getScene(); // возвращает объект сцены

    ~DirectRenderer();

};

 

#endif // DIRECTRENDERER_HEADER

 

Листинг 2.8. Файл DirectRenderer.cpp

 

#include "DirectRenderer.h"

#include "MainWindow.h"

 

void DirectRenderer::decorateWindow()

{

    HWND window = MainWindow::instance()->getHandle();

    SetWindowText(window, TEXT("Hourglass: DirectX Renderer"));

}

 

void DirectRenderer::initialize()

{

    MainWindow* mainWindow = MainWindow::instance();

    device_ = mainWindow->getDevice();

 

    direct_ = NULL;

    renderDevice_ = NULL;

 

    direct_ = Direct3DCreate9(D3D_SDK_VERSION);

    D3DDISPLAYMODE dm;

    direct_->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm);

 

    D3DPRESENT_PARAMETERS pp;

    memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));

 

    pp.BackBufferFormat = dm.Format;

    pp.SwapEffect = D3DSWAPEFFECT_DISCARD;

    pp.Windowed = true;

 

    direct_->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,

        mainWindow->getHandle(), D3DCREATE_SOFTWARE_VERTEXPROCESSING,

        &pp, &renderDevice_);

    setViewport();

 

    renderDevice_->SetRenderState(D3DRS_LIGHTING, false);

}

 

void DirectRenderer::cleanup()

{

    if (NULL != renderDevice_)

        renderDevice_->Release();

    if (NULL != direct_)

        direct_->Release();

}

 

void DirectRenderer::setViewport()

{

    D3DXMATRIX identity;

    D3DXMatrixIdentity(&identity);

    D3DXMATRIX trans;

    D3DXMatrixOrthoLH(&trans, 10.0, 10.0, -5.0, 5.0);

    renderDevice_->SetTransform(D3DTS_WORLD, &trans);

}

 

DirectRenderer::DirectRenderer()

{

    decorateWindow();

    initialize();

}

 

void DirectRenderer::tick()

{

    scene_.synchronize();

}

 

void DirectRenderer::render()

{

    renderDevice_->Clear(

        0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0, 0);

    D3DXMATRIX trans;

    D3DXMatrixIdentity(&trans);

    renderDevice_->SetTransform(D3DTS_VIEW, &trans);

    D3DXMatrixRotationZ(&trans, scene_.getAngle() / 180.0 * 3.14);

    renderDevice_->MultiplyTransform(D3DTS_VIEW, &trans);

    renderDevice_->BeginScene();

    for (unsigned int s = 0; s < scene_.count(); ++s)

    {

        PolygonMap map = scene_[s].getPolygonMap();

        DWORD color = D3DCOLOR_ARGB(255, scene_[s].getColor().r,

            scene_[s].getColor().g, scene_[s].getColor().b);

        if (map.size() > 0)

        {

            ID3DXMesh* model;

            D3DXCreateMeshFVF(2 * map.size(), 4 * map.size(), D3DXMESH_MANAGED,

                D3DFVF_XYZ | D3DFVF_DIFFUSE, renderDevice_, &model);

            DirectVertex* vertex = 0;

            model->LockVertexBuffer(0, (void **)&vertex);

                unsigned int n = 0;

                for (PolygonMap::iterator pos = map.begin();

                    pos != map.end();

                    ++pos)

                {

                    for (PointMap::iterator pt = pos->begin();

                        pt != pos->end();

                        ++pt)

                    {

                        vertex[n] = DirectVertex(

                            (float)pt->x, (float)pt->y, 0.0, color);

                        ++n;

                    }

                }

            model->UnlockVertexBuffer();

            WORD* index = 0;

            model->LockIndexBuffer(0, (void**)&index);

                int j = 0;

                WORD k = 0;

                for (unsigned int i = 0; i < map.size(); ++i)

                {

                    index[j++] = k;

                    index[j++] = k + 1;

                    index[j++] = k + 2;

                    index[j++] = k;

                    index[j++] = k + 2;

                    index[j++] = k + 3;

                    k += 4;

                }

            model->UnlockIndexBuffer();

            DWORD* attr = 0;

            model->LockAttributeBuffer(0, &attr);

                for (unsigned int i = 0; i < 2 * map.size(); ++i)

                    attr[i] = 0;

            model->UnlockAttributeBuffer();

            model->DrawSubset(0);

            model->Release();

        }

    }

    renderDevice_->EndScene();

    renderDevice_->Present(NULL,

        &MainWindow::instance()->getClientRect(),

        NULL, NULL);

}

 

void DirectRenderer::updateViewport()

{

    setViewport();

}

 

Scene& DirectRenderer::getScene()

{

    return scene_;

}

 

DirectRenderer::~DirectRenderer()

{

    cleanup();

}

3. ТРЕБОВАНИЯ К СИСТЕМЕ ПОЛЬЗОВАТЕЛЯ

3.1. Требования к программному обеспечению

  • Операционная система Microsoft Windows XP/Vista/7;
  • Microsoft Visual C++ 2008 Redistributable;
  • DirectX 9;
  • OpenGL 2.

3.2. Минимальные требования к аппаратному  обеспечению

  • Оперативная память: 256 Мбайт для Microsoft Windows XP, 512 Мбайт для Microsoft Windows 7, 1 Гбайт для Microsoft Windows Vista;
  • Процессор с частотой от 1 ГГц;
  • Видеокарта с поддержкой аппаратного режима DirectX 9 с видеопамятью от 128 Мбайт.

4. ПРИМЕРЫ РАБОТЫ ПРОГРАММЫ

Так как  внешних отличий в изображениях, построенных средствами OpenGL и DirectX, практически не наблюдается, имеет смысл показать только различие изображений водяных (рис. 4.1) и песочных (рис. 4.2) часов.

 

Рис. 4.1. Водяные часы.

Рис. 4.2. Песочные часы.

БИБЛИОГРАФИЧЕСКИЙ СПИСОК

  1. OpenGL. Программирование компьютерной графики / Ф. Хилл. — Спб.: Питер, 2006.
  2. DirectX и C++. Искусство программирования / М. Фленов. — Спб.: БХВ, 2006.
  3. Win32 API. Эффективная разработка приложений / Ю.А. Щупак. — Спб.: Питер, 2007.
  4. Windows для профессионалов / Дж. Рихтер. — Спб.: Питер, 2000.