Студопедия — Управляемая анимация изображения
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Управляемая анимация изображения






демонстрируется в следующем примере. Его идея взята из примера OpenGL, множество которых можно найти в MSDN.

¨ Сначала загружаем растровое изображение из bmp -файла и демонстрируем его в окне OpenGL;

¨ Затем мышью указываем произвольное количество точек, которые описывают будущую траекторию движения одной (первой) точки. Траектория определяет цепь последующих трансформаций текстуры;

¨ Запоминаем координаты точек в контейнере STL типа vector;

¨ Для плавности анимации генерируем промежуточные точки, разбивая расстояния между последовательно идущими точками траектории на какое-то число частей. Оно определяется экспериментально и зависит от скорости передачи изображения (rendering), то есть от качества видео-карты;

¨ Двигаясь вдоль всех точек траектории, последовательно изображаем четыре треугольные текстуры, которые, будучи составленными вместе, дают прямоугольное изображение;

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


Чтобы понять что происходит, вообразите рисунок, выполненный на куске резины, из которой делают воздушные шарики. Затем представьте, что произойдет с рисунком, если одну его точку перемещать в плоскости полотна изображения. Изображение будет как-то растягиваться и сжиматься. Следующие 2 рисунка напоминают почтовые конверты. Они показывают 4 треугольника, из которых составлен прямоугольник изображения. Центральная точка движется по некоторой траектории и переходит из одного положения в другое. Начальному положению соответствуют сплошные линии, а следующему — пунктирные. При перемещении одной, выделенной точки в другое положение треугольники трансформируются. Если мы таким же образом трансформируем текстуры, натянутые на них, то получим анимацию, алгоритм которой задает пользователь.

Как видите, алгоритм демонстрации эффекта растяжения текстур достаточно сложен. В связи с этим выделим 4 режима, в которых будет работать приложение (выбор файла с изображением, вывод изображения, ввод точек траектории, анимация изображения). Нам понадобится некоторый набор переменных, который удобно определить глобально. С вершинами треугольников будут ассоциированы координаты двухмерной текстуры, поэтому в класс CVert кроме пространственных координат вершины (v) мы инкапсулировали текстурные координаты (g).

GLUT_RGBImageRec *pImg; // Структура, описывающая RGB-изображение

 

enum eMode // Режим перерисовки

{

eNOP, // Ничего не делаем

eANIMATE, // Запускаем анимацию

ePOINTS, // Рисуем точки траектории

eSTILL // Рисуем весь bitmap

};

 

eMode gMode = eNOP;// Текущий режим

 

class Point2D

{

public:

float x, y;

Point2D () { x=0.; y=0.; }

Point2D (float fx, float fy) { x=fx; y=fy; }

Point2D operator- (const Point2D& pt) { return Point2D (x-pt.x, y-pt.y); }

void operator+= (const Point2D& pt) { x += pt.x; y += pt.y; }

};

 

class CVert

{

public:

Point2D v, g; // Координаты вершины и текстуры в 2D

static Point2D dv; // Сдвиг точки траектории (общий для всех объектов)

 

CVert(): v(), g() {}

CVert (Point2D pv, Point2D pt): v(pv), g(pt) {}

 

CVert& operator= (const CVert& vt)

{

v = vt.v;

g = vt.g;

return *this;

}

void Shift() { v += dv; } // Сдвиг на dv

};

 

Point2D CVert::dv; // Определение статической переменной класса

CVert gVerts[5]; // 5 точек, разделяющих изображение на 4 треугольника

vector<Point2D> gPoints;// Траектория движения первой точки

 

//==== Увеличение количества разбиений gSteps вносит плавность анимации, замедляя ее

int gSteps = 10,// Количество шагов деления интервала между соседними точками траектории

gCX, gCY, // Размеры bitmap

giLast, // Индекс предыдущей точки траектории

giNext, // Индекс следующей точки траектории

giCur; // Индекс текущей точки траектории

 

char szFile[MAX_PATH]; // Файловый путь

 

char* FileDlg (bool bRead) // Работа с файловым диалогом (bRead – режим открытия файла)

{

TCHAR *szFilter = // Фильтр файловых расширений

TEXT("BMP Files (*.bmp)\0*.bmp\0")

TEXT("DIB Files (*.dib)\0*.dib\0");

 

char szCurDir[MAX_PATH]; // Начнем с текущей директории

::GetCurrentDirectory (MAX_PATH-1, szCurDir);

 

OPENFILENAME ofn; // Структура, используемая стандартным диалогом

ZeroMemory (&ofn, sizeof(OPENFILENAME));

 

//====== Параметры настройки диалога

ofn.lStructSize = sizeof(OPENFILENAME);

ofn.hwndOwner = glutGetHWND(); // Окно, которому принадлежит диалог

ofn.lpstrFilter = szFilter;

ofn.nFilterIndex = 1; // Начальный индекс массива строк фильтра равен 1

ofn.lpstrFile = szFile;

ofn.nMaxFile = sizeof(szFile);

ofn.lpstrTitle = "Find a bitmap file";// Заголовок диалога

ofn.nMaxFileTitle = sizeof (ofn.lpstrTitle);

ofn.lpstrInitialDir = szCurDir; // Начальная директория

ofn.Flags = OFN_EXPLORER|OFN_OVERWRITEPROMPT; // Стиль EXPLORER (работает только в Win2K)

ofn.lpstrDefExt = "bmp";

 

//====== Создаем и открываем диалог (при неудаче возвращает 0)

BOOL b = bRead? GetOpenFileName(&ofn): GetSaveFileName(&ofn);

 

return b? ofn.lpstrFile: 0;

}

 

bool Read() // Чтение изображения из файла

{

char *fn;

if ((fn = FileDlg (true))!= 0)

{

pImg = glutDIBImageLoad (fn); //или glutRGBImageLoad

//==== Размеры bitmap в OpenGL должны быть степенью двойки

gCX = int(pow (2., int(log (pImg->sizeX)/log(2.))));

gCY = int(pow (2., int(log (pImg->sizeY)/log(2.))));

return true;

}

else

return false;

}

 

void DrawImage()

{

glRasterPos2i(0, 0);

glDrawPixels (pImg->sizeX, pImg->sizeY,GL_RGB,GL_UNSIGNED_BYTE, pImg->data);

}

 

void DrawPoint()

{

glColor3f(1.0, 0.0, 1.0);

glPointSize(3.0);

 

glBegin(GL_POINTS);

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

glVertex2f(gPoints[i].x, gPoints[i].y);

glEnd();

}

 

void UpdateStep() // Вычисляем шаг смещения (для промежуточных точек)

{

Point2D pt = gPoints[giNext] - gPoints[giLast];

CVert::dv = Point2D (pt.x / gSteps, pt.y / gSteps);

}

 

void Animate()

{

//==== Изображение составлено из 4-х текстурных треугольников

//==== 4 угловых точки и одна точка, движущаяся по траектории

 

//==== Сначала растянем нижний треугольник

glBegin(GL_TRIANGLES); // |------------|

glTexCoord2f(gVerts[0].g.x, gVerts[0].g.y); // | |

glVertex2f(gVerts[0].v.x, gVerts[0].v.y); // | |

glTexCoord2f(gVerts[1].g.x, gVerts[1].g.y); // | 4 |

glVertex2f(gVerts[1].v.x, gVerts[1].v.y); // | / \ |

glTexCoord2f(gVerts[4].g.x, gVerts[4].g.y); // | / \ |

glVertex2f(gVerts[4].v.x, gVerts[4].v.y); // 0___________\1

glEnd();

//==== Затем – правый треугольник

glBegin(GL_TRIANGLES); // |------------2

glTexCoord2f(gVerts[1].g.x, gVerts[1].g.y); // | / |

glVertex2f(gVerts[1].v.x, gVerts[1].v.y); // | / |

glTexCoord2f(gVerts[2].g.x, gVerts[2].g.y); // | 4 |

glVertex2f(gVerts[2].v.x, gVerts[2].v.y); // | \ |

glTexCoord2f(gVerts[4].g.x, gVerts[4].g.y); // | \ |

glVertex2f(gVerts[4].v.x, gVerts[4].v.y); // |____________1

glEnd();

//==== После этого – верхний треугольник

glBegin(GL_TRIANGLES); // 3------------2

glTexCoord2f(gVerts[2].g.x, gVerts[2].g.y); // | \ / |

glVertex2f(gVerts[2].v.x, gVerts[2].v.y); // | \ / |

glTexCoord2f(gVerts[3].g.x, gVerts[3].g.y); // | 4 |

glVertex2f(gVerts[3].v.x, gVerts[3].v.y); // | |

glTexCoord2f(gVerts[4].g.x, gVerts[4].g.y); // | |

glVertex2f(gVerts[4].v.x, gVerts[4].v.y); // |____________|

glEnd();

//==== Наконец, левый треугольник

glBegin(GL_TRIANGLES); // 3------------|

glTexCoord2f(gVerts[3].g.x, gVerts[3].g.y); // | \ |

glVertex2f(gVerts[3].v.x, gVerts[3].v.y); // | \ |

glTexCoord2f(gVerts[0].g.x, gVerts[0].g.y); // | 4 |

glVertex2f(gVerts[0].v.x, gVerts[0].v.y); // | / |

glTexCoord2f(gVerts[4].g.x, gVerts[4].g.y); // | / |

glVertex2f(gVerts[4].v.x, gVerts[4].v.y); // 0____________|

glEnd();

 

//=== Смещаем пятую точку на шаг, но не трогаем ее текстурных координат!!!

if (++giCur <= gSteps)

gVerts[4].Shift();

else // Переходим к следующей точке траектории

{

giLast = giNext;

if (++giNext == gPoints.size()) // Если последняя – зацикливаем

giNext = 0;

 

UpdateStep();

giCur = 0;

}

}

 

void InitVList()// Инициализация массива точек (конверта)

{

giLast = 0;

giNext = 1;

UpdateStep();

 

gVerts[0] = CVert (); // Bottom Left corner

gVerts[1] = CVert (Point2D(gCX,0.), Point2D(1.,0.)); // Bottom Right corner

gVerts[2] = CVert (Point2D(gCX, gCY), Point2D(1.,1.)); // Top Right corner

gVerts[3] = CVert (Point2D(0.,gCY), Point2D(0.,1.)); // Top Left corner

 

//==== Текстурные координаты первой точки траектории

Point2D tex(gPoints[0].x / gCX, gPoints[0].y / gCY);

gVerts[4] = CVert (gPoints[0], tex); // Пятая точка – это первая точка траектории

}

 

void OnPaint()

{

switch (gMode)

{

case eANIMATE: Animate(); break;

case ePOINTS: DrawPoint(); break;

case eSTILL: DrawImage(); break;

}

glutSwapBuffers();

}

 

void OnKey (unsigned char ch, int x, int y)

{

switch (ch)

{

case 27: exit(0); break;

case ' ':

if (gPoints.size() > 1)

{

InitVList();

giCur = 0;

glEnable(GL_TEXTURE_2D);

gMode = eANIMATE;

glutIdleFunc(OnPaint);

}

break;

}

glutPostRedisplay();

}

 

void OnMouse(int button, int state, int x, int y)

{

if (state == GLUT_DOWN)

{

if (gMode == eANIMATE)

{

glDisable(GL_TEXTURE_2D);

gPoints.clear();

gMode = eSTILL;

glutIdleFunc(0);

}

else

{

gPoints.push_back(Point2D(x, gCY - y));

gMode = ePOINTS;

}

}

}

 

void Init()

{

glViewport(0, 0, gCX, gCY);

gluOrtho2D(0, gCX, 0, gCY);

 

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glPixelStorei(GL_PACK_ALIGNMENT, 1);

 

BYTE *buf = (BYTE*) malloc (3 * gCX * gCY);

gluScaleImage (GL_RGB, pImg->sizeX, pImg->sizeY, GL_UNSIGNED_BYTE,

pImg->data, gCX, gCY, GL_UNSIGNED_BYTE, buf);

 

free (pImg->data);

pImg->data = buf;

pImg->sizeX = gCX; pImg->sizeY = gCY;

 

glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

 

glTexImage2D (GL_TEXTURE_2D, 0, 3, pImg->sizeX, pImg->sizeY, 0,

GL_RGB, GL_UNSIGNED_BYTE, (BYTE*)pImg->data);

 

giLast = giNext = 0;

gMode = eSTILL;

}







Дата добавления: 2015-10-19; просмотров: 589. Нарушение авторских прав; Мы поможем в написании вашей работы!



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

Практические расчеты на срез и смятие При изучении темы обратите внимание на основные расчетные предпосылки и условности расчета...

Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...

Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...

ЛЕЧЕБНО-ПРОФИЛАКТИЧЕСКОЙ ПОМОЩИ НАСЕЛЕНИЮ В УСЛОВИЯХ ОМС 001. Основными путями развития поликлинической помощи взрослому населению в новых экономических условиях являются все...

МЕТОДИКА ИЗУЧЕНИЯ МОРФЕМНОГО СОСТАВА СЛОВА В НАЧАЛЬНЫХ КЛАССАХ В практике речевого общения широко известен следующий факт: как взрослые...

СИНТАКСИЧЕСКАЯ РАБОТА В СИСТЕМЕ РАЗВИТИЯ РЕЧИ УЧАЩИХСЯ В языке различаются уровни — уровень слова (лексический), уровень словосочетания и предложения (синтаксический) и уровень Словосочетание в этом смысле может рассматриваться как переходное звено от лексического уровня к синтаксическому...

РЕВМАТИЧЕСКИЕ БОЛЕЗНИ Ревматические болезни(или диффузные болезни соединительно ткани(ДБСТ))— это группа заболеваний, характеризующихся первичным системным поражением соединительной ткани в связи с нарушением иммунного гомеостаза...

Решение Постоянные издержки (FC) не зависят от изменения объёма производства, существуют постоянно...

ТРАНСПОРТНАЯ ИММОБИЛИЗАЦИЯ   Под транспортной иммобилизацией понимают мероприятия, направленные на обеспечение покоя в поврежденном участке тела и близлежащих к нему суставах на период перевозки пострадавшего в лечебное учреждение...

Studopedia.info - Студопедия - 2014-2024 год . (0.013 сек.) русская версия | украинская версия