Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПЗ2-v004.docx
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
610 Кб
Скачать
☆

Литература

  1. OpenGL. Руководство по программированию: М. Ву, Т. Девис, Дж. Нейдер, Д. Шрайнер — Москва, Питер, 2010 г.- 624 с.

  2. Графика трехмерной компьютерной игры на основе OpenGL: А. В. Боресков — Санкт-Петербург, Диалог-МИФИ, 2009 г.- 384 с.

  3. Инструментальные средства программирования и отладки шейдеров в DirectX и OpenGL (+ CD-ROM): Станислав Горнаков — Санкт-Петербург, БХВ-Петербург, 2011 г.- 256 с.

  4. Компьютерная графика. Полигональные модели: Е. В. Шикин, А. В. Боресков — Санкт-Петербург, Диалог-МИФИ, 2009 г.- 464 с.

  5. Моделирование объектов с дискретно-распределенными параметрами: А. В. Седов — Санкт-Петербург, Наука, 2010 г.- 440 с.

  6. Разработка и отладка шейдеров (+ CD-ROM): Алексей Боресков — Москва, БХВ-Петербург, 2012 г.- 488 с.

  7. Расширения OpenGL (+ CD-ROM): Алексей Боресков — Санкт-Петербург, БХВ-Петербург, 2009 г.- 688 с.

  8. Свободное программное обеспечение. FREE PASCAL для студентов и школьников (+ CD): Ю. Л. Кетков, А. Ю. Кетков — Санкт-Петербург, БХВ-Петербург, 2011 г.- 376 с.

  9. Эффективное использование С++: Билл Вагнер — Санкт-Петербург, Лори, 2011 г.- 256 с.

Приложения Приложение 1. Листинг программы

// main.cpp

const char * szTitle = "Obj";

#include <gl/gl.h>

#include "../basecode/app.h"

#include "obj.h"

//Переменные

//Работа с мышью

#ifndef WM_MOUSEWHEEL

#define WM_MOUSEWHEEL (WM_MOUSELAST+1) // Сообщение, которое связано с колесом мыши

#endif

//Кнопки мыши

#define K_MWHEELDOWN 239

#define K_MWHEELUP 240

#define K_MOUSE1 200

#define K_MOUSE2 201

#define K_MOUSE3 202

//Номер сообщения мыши

static UINT MSH_MOUSEWHEEL;

//Управление обзором через мышь

int mouse_buttons;

int mouse_oldbuttonstate;

POINT current_pos;

int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum;

int old_x, old_y;

int mouseactive; // 0 - когда наше окно не имеет фокуса ввода

//Состояние мыши (для восстановления)

int restore_spi;

int mouseinitialized;

int originalmouseparms[3], newmouseparms[3] = {0, 0, 1};

int mouseparmsvalid;

//Размеры окна и указатель окна HWND

int window_center_x, window_center_y;

//Кнопка паузы (0-нет паузы,1-пауза)

int pause = 0;

RECT window_rect;

HWND cl_hwnd;

//---------------------------------------------

//Работа с клавиатурой

//Буфер нажатий кнопок (0-не нажата кнопка, 1-нажата)

char cmd[1024];

//---------------------------------------------

//Работа с позицией камеры

//Углы поворота

float angles[3];

//Позиция камеры

float org[3];

//Скорость камеры

float orgspeed[3];

//Ускорение камеры

float orgvel[3];

//Пузырьки

struct _bubble {

//Координаты

float x,y,z;

//Скорость

float vx,vy,vz;

} bubble[100];

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

float bubblea,bubbleb;

float bubblec,bubbled;

//Работа с файлами формата *.obj

//Объекты для рендера

CObj g_Obj1,g_Obj2,g_Obj3,g_Obj4,g_Obj5;

//Текстура

CImage g_Skin;

IN_MouseMove - функция обработки движения мыши

void IN_MouseMove ()

{

int mx, my;

//Фильтрация мыши (1-включена, 0-выключена)

int m_filter = 0;

//Чувствительность мыши (1-12)

float sensitivity = 2;

//Чувствительность поворота мыши

float m_yaw=0.22,m_pitch=0.22;

if (!mouseactive)

return;

// find mouse movement

if (!GetCursorPos (&current_pos))

return;

mx = current_pos.x - window_center_x;

my = current_pos.y - window_center_y;

#if 0

if (!mx && !my)

return;

#endif

if (m_filter==1)

{

mouse_x = (mx + old_mouse_x) * 0.5;

mouse_y = (my + old_mouse_y) * 0.5;

}

else

{

mouse_x = mx;

mouse_y = my;

}

old_mouse_x = mx;

old_mouse_y = my;

mouse_x *= sensitivity;

mouse_y *= sensitivity;

//Взгляд влево-вправо

angles[1]+=m_yaw*mouse_x;

//Ограничиваем взгляд

if(angles[1]<0)

angles[1]+=360.0;

if(angles[1]>360.0)

angles[1]-=360.0;

//Взгляд вверх-вниз

angles[0]+= m_pitch*mouse_y;

//Ограничиваем взгляд вверх-вниз

if(angles[0]<-90.0)

angles[0]=-90.0;

if(angles[0]>90.0)

angles[0]=90.0;

// Ставим курсор мыши в центр (чтобы было место для движения

if (mx || my)

SetCursorPos (window_center_x, window_center_y);

}

Key_Event

Вызывается каждый кадр для события нажатия и отпускания кнопок

void Key_Event (int key, int key1, int down, unsigned time)

{

char *kb;

static int first=1;

int i;

if(first==1){

first=0;

}

// сохраняем статус нажатия кнопки в специальном буфере

if (down) {

//Кнопка нажата

cmd[key1&0x3ff]=1;

} else {

//Кнопка отпущена

cmd[key1&0x3ff]=0;

}

}

IN_MouseEvent - нажатие кнопок мыши

void IN_MouseEvent (int mstate)

{

int i;

if (!mouseinitialized)

return;

// Обработаем кнопки мыши

for (i=0 ; i<mouse_buttons ; i++)

{

if ( (mstate & (1<<i)) &&

!(mouse_oldbuttonstate & (1<<i)) )

{

Key_Event (K_MOUSE1 + i, 0, true, APP->sys_msg_time);

}

if ( !(mstate & (1<<i)) &&

(mouse_oldbuttonstate & (1<<i)) )

{

Key_Event (K_MOUSE1 + i,0, false, APP->sys_msg_time);

}

}

mouse_oldbuttonstate = mstate;

}

//key sensitivity - чувствительность клавиатуры (чем больше тем быстрее

//будем двигаться при нажатии клавиш

float keysens = 0.2;

//Функции для перемещения камеры (влево-вправо-вперед-назад)

void forward(){

org[2]+=cos((float)angles[1]*3.1415926/180.0)*keysens;

org[0]-=sin((float)angles[1]*3.1415926/180.0)*keysens;

}

void backword(){

org[2]-=cos((float)angles[1]*3.1415926/180.0)*keysens;

org[0]+=sin((float)angles[1]*3.1415926/180.0)*keysens;

}

void left(){

org[2]+=sin((float)angles[1]*3.1415926/180.0)*keysens;

org[0]+=cos((float)angles[1]*3.1415926/180.0)*keysens;

}

void right(){

org[2]-=sin((float)angles[1]*3.1415926/180.0)*keysens;

org[0]-=cos((float)angles[1]*3.1415926/180.0)*keysens;

}

IN_ActivateMouse

Вызывается когда окно получает фокус ввода

void IN_ActivateMouse(void)

{

int width, height;

if (!mouseinitialized)

return;

if (mouseactive)

return;

mouseactive = true;

// if (mouseparmsvalid)

restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);

width = GetSystemMetrics (SM_CXSCREEN);

height = GetSystemMetrics (SM_CYSCREEN);

GetWindowRect ( cl_hwnd, &window_rect);

if (window_rect.left < 0)

window_rect.left = 0;

if (window_rect.top < 0)

window_rect.top = 0;

if (window_rect.right >= width)

window_rect.right = width-1;

if (window_rect.bottom >= height-1)

window_rect.bottom = height-1;

window_center_x = (window_rect.right + window_rect.left)/2;

window_center_y = (window_rect.top + window_rect.bottom)/2;

SetCursorPos (window_center_x, window_center_y);

old_x = window_center_x;

old_y = window_center_y;

SetCapture ( cl_hwnd );

ClipCursor (&window_rect);

while (ShowCursor (FALSE) >= 0)

;

}

IN_DeactivateMouse

Вызывается когда окно теряет фокус ввода

void IN_DeactivateMouse (void)

{

if (!mouseinitialized)

return;

if (!mouseactive)

return;

if (restore_spi)

SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0);

mouseactive = false;

ClipCursor (NULL);

ReleaseCapture ();

while (ShowCursor (TRUE) < 0)

;

}

//Цвет ламп

float col1[4] = {0.5,0,0,1};

float col2[4] = {0.5,0.5,0.8,1};

float col3[4] = {0.0,0.3,0.8,1};

//- Main

//- Main game loop - Главный цикл программы (отрисовывает 1 кадр)

void Main()

{

//Переменная цикла

int i;

//Угол поворота картинки

static float rot = 0;

//Скорость движения крышки вверх или вниз

static float hatpos = 0.0;

static float hspeed = 0.01f;

static float hatposspeed = hspeed;

//Скорость вращения крышки

static float hatrot = 0;

static float hatrotspeed = 2.0;

//Временная строка

char szDD[2048],temp[2048];

IN_ActivateMouse();

IN_MouseMove();

glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glLightfv(GL_LIGHT0, GL_DIFFUSE, col1);

glLightfv(GL_LIGHT1, GL_DIFFUSE, col2);

glLightfv(GL_LIGHT2, GL_DIFFUSE, col3);

if(pause == 0){

if(col1[0]<1.0)

col1[0]=col1[0]+0.015;

else

col1[0]=0;

if(col2[1]<1.0)

col2[1]=col2[1]+0.001;

else

col2[1]=0;

if(col3[2]<1.0)

col3[2]=col3[2]+0.02;

else

col3[2]=0;

}

glShadeModel(GL_SMOOTH);

glColor4f(1, 1, 1, 1);

// glColor3f(1, 1, 1);

APP->Print(.75f, .9f, "FPS: %4.2f", APP->GetFPS());

//szDD[0]=0;

//for(i=0;i<1024;i++){

// if(cmd[i]!=0){

// sprintf(temp,"%d,",i);

// strcat(szDD,temp);

// }

//}

// APP->Print(.65f, .9f, "Key: %s", szDD);

// sprintf(szDD,"%f;%f;%f:%f;%f;%f",angles[0],angles[1],angles[2],org[0],org[1],org[2]);

// APP->Print(.015f, .2f, "Angles: %s", szDD);

// glMatrixMode(GL_PROJECTION);

// glLoadIdentity();

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

// glPolygonMode(GL_FRONT_AND_BACK, GL_SOLID);

// glMatrixMode(GL_PROJECTION);

// glLoadIdentity();

glRotatef(angles[0], 1, 0, 0);

glRotatef(angles[1], 0, 1, 0);

glRotatef(angles[2], 0, 0, 1);

glTranslatef(org[0], org[1], org[2]); //Translation for the gear model (gear.obj) may have to mess with this

// glRotatef(90*3, 0, 0, 1);

// glCullFace(GL_FRONT);

// glMatrixMode(GL_MODELVIEW);

// glLoadIdentity ();

glRotatef(rot, 0, 1, 0);

// glTranslatef(0.f, -1.f, -4.f); //Translation for the gear model (gear.obj) may have to mess with this

//to get other models to display correctly

//Устанавливаем цвет

glColor4f(1, 1, 1, 1);

//Режим текстурирования

//Режим текстуры

glEnable(GL_TEXTURE_2D);

//1) Выводим комнату

g_Obj4.Render();

//2) Выводим воду

g_Obj2.Render();

//3) Выводим пузырьки

if(hatpos>0.2){

g_Obj5.PartBind();

for(i=0;i<100;i++){

glPushMatrix();

if(pause == 0){

bubble[i].x+=bubble[i].vx;

bubble[i].y+=bubble[i].vy;

bubble[i].z+=bubble[i].vz;

if(bubble[i].y<bubblea){

bubble[i].vy=0.01+0.02*(float)rand()/RAND_MAX;

//Меняем положение

bubble[i].x=1.3*(float)rand()/RAND_MAX-0.75;

bubble[i].y=bubblea+0.01*(float)rand()/RAND_MAX;

bubble[i].z=1.3*(float)rand()/RAND_MAX-1.45;

}

if(bubble[i].y>bubbleb)

bubble[i].vy=-0.01-0.02*(float)rand()/RAND_MAX;

}

glTranslatef(bubble[i].x, bubble[i].y, bubble[i].z);

g_Obj5.RenderPart();

glPopMatrix();

}

}

//Выводим бутылку

g_Obj1.Render();

//Поднять крышку

if(pause == 0){

if(hatposspeed>0){

if(hatpos<3)

hatpos+=hatposspeed;

hatrot+=hatrotspeed;

} else if(hatposspeed<0){

if(hatpos>0)

hatpos+=hatposspeed;

hatrot-=hatrotspeed;

} else {

//Пауза - ничего не делаем!

}

if(hatpos<=0)

hatposspeed=0.005f;

if(hatpos>=3)

hatposspeed=-0.005f;

}

glLoadIdentity();

// glTranslatef(0, hatpos, 0);

glRotatef(angles[0], 1, 0, 0);

glRotatef(angles[1], 0, 1, 0);

glRotatef(angles[2], 0, 0, 1);

glTranslatef(org[0], org[1]+hatpos, org[2]);

glRotatef(rot+hatrot, 0, 1, 0);

g_Obj3.Render();

//Обработка клавиш

if(cmd[65]!=0){

//a-Влево

left();

// orgvel[0]=0.02;

// org[0]+=orgvel[0];

}

if(cmd[68]!=0){

//d-Вправо

right();

// orgvel[0]=0.02;

// org[0]-=orgvel[0];

}

if(cmd[90]!=0){

//z-Вверх

orgvel[1]=0.02;

org[1]+=orgvel[1];

}

if(cmd[88]!=0){

//x-Вниз

orgvel[1]=0.02;

org[1]-=orgvel[1];

}

if(cmd[87]!=0){

//w-Вперед

forward();

// orgvel[2]=0.02;

// org[2]+=orgvel[0];

}

if(cmd[83]!=0){

//s-Назад

backword();

// orgvel[2]=0.02;

// org[2]-=orgvel[0];

}

if(cmd[13]!=0){

//Enter-Старт

}

if(cmd[32]!=0){

//Пробел-Пауза

cmd[32]=0;

pause = 1 - pause;

}

if(pause == 0){

rot += 0.2f;

}

}

//- Init

//- Initialization code - Начальная инициализация ламп, мешей

void Init()

{

int i;

//1

static float LightAmbient1 [] = { 0.2f, 0.2f, 0.2f, 1.0f };

static float LightDiffuse1 [] = { 0.5f, 0.5f, 0.0f, 1.0f };

static float LightPosition1 [] = { 0, 30, 30, 1};

//2

static float LightAmbient2 [] = { 0.2f, 0.2f, 0.2f, 1.0f };

static float LightDiffuse2 [] = { 0.0f, 0.0f, 0.5f, 1.0f };

static float LightPosition2 [] = { 10, -30, -30, 1};

//3

static float LightAmbient3 [] = { 0.2f, 0.2f, 0.2f, 1.0f };

static float LightDiffuse3 [] = { 0.3f, 0.2f, 0.0f, 1.0f };

static float LightPosition3 [] = { -10, 30, 30, 1};

glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient1);

glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse1);

glLightfv(GL_LIGHT1, GL_POSITION, LightPosition1);

glLightfv(GL_LIGHT2, GL_AMBIENT, LightAmbient2);

glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse2);

glLightfv(GL_LIGHT2, GL_POSITION, LightPosition2);

glLightfv(GL_LIGHT3, GL_AMBIENT, LightAmbient3);

glLightfv(GL_LIGHT3, GL_DIFFUSE, LightDiffuse3);

glLightfv(GL_LIGHT3, GL_POSITION, LightPosition3);

glEnable(GL_LIGHT1);

glEnable(GL_LIGHT2);

glEnable(GL_LIGHT3);

glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

glPolygonMode( GL_FRONT_AND_BACK,GL_FILL);

//glPolygonMode( GL_FRONT_AND_BACK,GL_LINE);

//Бутылка

g_Obj1.Load("bottle006.obj","00bottle006.tga");

//Вода в бутылке

g_Obj2.Load("water006.obj","00water006.tga");

//Крышка

g_Obj3.Load("hat006.obj","00hat006.tga");

//Комната

g_Obj4.Load("box006.obj","skin001.jpg");

//Пузырек

g_Obj5.Load("bubble006.obj","00Bubble006.tga");

//Устанавливаем начальную позицию камеры

angles[0]=0;

angles[1]=0;

angles[2]=0;

org[0]=0.f;

org[1]=-4.f;

org[2]=-12.f;

orgspeed[0]=0;

orgspeed[1]=0;

orgspeed[2]=0;

orgvel[0]=0;

orgvel[1]=0;

orgvel[2]=0;

//Задаем начальную позицию пузырьков

bubblea = -1.95;

bubbleb = bubblea+0.2;

bubblec = -3.0;

bubbled = 3.0;

for(i=0;i<100;i++){

bubble[i].x=1.3*(float)rand()/RAND_MAX-0.75;

bubble[i].y=bubblea+0.2*(float)rand()/RAND_MAX;

bubble[i].z=1.3*(float)rand()/RAND_MAX-1.45;

bubble[i].vx=0.0;

bubble[i].vy=0.01;

bubble[i].vz=0.0;

}

//Включаем освещение

glEnable(GL_LIGHTING);

//Прозрачный рендеринг

glEnable(GL_BLEND);

//Режим текстуры

glEnable(GL_TEXTURE_2D);

}

//- WinMain

//- Entry point for the application - Точка входа в программу (main или WinMain)

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

{

int i;

//Сбрасываем установки мыши

mouseinitialized = true;

mouse_buttons = 3;

//Очищаем буфер клавиатуры

for(i=0;i<1024;i++)

cmd[i]=0;

APP->Init(Main);

APP->CreateWnd();

Init();

APP->CreateFnt("Arial", 16);

APP->Run();

APP->Destroy();

return 0;

}

//- WndProc

//- Windows Procedure - главная процедура обработки сообщений окна

LRESULT CALLBACK CWindow::WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)

{

if ( uiMsg == MSH_MOUSEWHEEL )

{

if ( ( ( int ) wParam ) > 0 )

{

Key_Event( K_MWHEELUP, 0, true, APP->sys_msg_time );

Key_Event( K_MWHEELUP, 0, false, APP->sys_msg_time );

}

else

{

Key_Event( K_MWHEELDOWN, 0, true, APP->sys_msg_time );

Key_Event( K_MWHEELDOWN, 0, false, APP->sys_msg_time );

}

return DefWindowProc (hWnd, uiMsg, wParam, lParam);

}

switch(uiMsg)

{

case WM_MOUSEWHEEL:

if ( ( short ) HIWORD( wParam ) > 0 )

{

Key_Event( K_MWHEELUP, 0, true, APP->sys_msg_time );

Key_Event( K_MWHEELUP, 0, false, APP->sys_msg_time );

}

else

{

Key_Event( K_MWHEELDOWN, 0, true, APP->sys_msg_time );

Key_Event( K_MWHEELDOWN, 0, false, APP->sys_msg_time );

}

break;

case WM_CREATE:

{

cl_hwnd=hWnd;

SetWindowText(hWnd, szTitle);

MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");

break;

}

case WM_SYSCOMMAND:

{

switch(wParam)

{

//Отключаем скринсейверы

case SC_SCREENSAVE:

case SC_MONITORPOWER:

return 0;

}

break;

}

case WM_CLOSE:

{

PostQuitMessage(0);

return 0;

}

case WM_SIZE:

{

Resize(LOWORD(lParam), HIWORD(lParam));

return 0;

}

case WM_LBUTTONDOWN:

case WM_LBUTTONUP:

case WM_RBUTTONDOWN:

case WM_RBUTTONUP:

case WM_MBUTTONDOWN:

case WM_MBUTTONUP:

case WM_MOUSEMOVE:

{

int temp;

temp = 0;

if (wParam & MK_LBUTTON)

temp |= 1;

if (wParam & MK_RBUTTON)

temp |= 2;

if (wParam & MK_MBUTTON)

temp |= 4;

IN_MouseEvent (temp);

}

break;

case WM_SYSKEYDOWN:

if ( wParam == 13 )

{

//Enter

return 0;

}

// Падаем дальше

case WM_KEYDOWN:

switch(wParam)

{

case VK_ESCAPE:

{

PostQuitMessage(0);

break;

}

}

Key_Event( lParam, wParam, true, APP->sys_msg_time);

break;

case WM_SYSKEYUP:

case WM_KEYUP:

Key_Event( lParam, wParam, false, APP->sys_msg_time);

break;

}

return (DefWindowProc(hWnd, uiMsg, wParam, lParam));

}