Консультация № 93639
02.07.2007, 12:34
0.00 руб.
0 1 1
Эксперты,помогите справиться с заданием.Условие:
Аппроксимизировать заданную поверхность(сфера) полигональной сеткой и средствами OpenGL обеспечить для неё возможность
а)Изображения в параллельной и перспективной прооекции;
б)Удаления невидимых линий и поверхностей;
в)Реалистичного освещения;
г)Каркасного изображения.
Помогите сделать хоть часть!

Обсуждение

Неизвестный
02.07.2007, 19:00
общий
это ответ
Здравствуйте, Smirnov Artur Sergeevich!

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

Чтобы это все заработало, создай в Visual Studio проект Win32 Application.
Из сгенерированного мастером файла (того в котором WinMain) удали все и вставь этот код. После этого не забудь добавить в Project -> Properties -> Linker -> Additional Dependices библиотеки opengl32.lib glaux.lib glu32.lib

Удачи

Приложение:
#include "stdafx.h"#include <math.h>#include <vector>using namespace std;#define pi 3.1415926//---------настройки//---смещение сценыdouble tX = 0,tY = 0,tZ = -10;//---поворот сценыdouble angleX = 0,angleY = 0;//---координаты мышиshort sX,sY;//---закрашены ли полигоныbool Fill = true;//---детализация (число колец и меридианов)int mer_cnt = 90, rings_cnt = 90;GLfloat light_params[14] = {0.0,0.0,0.0, //position 1.0,1.0,1.0, //direction 15.0, //ambient 70.0, //diffuse 100.0, //specular 100.0, //mat_ambient 100.0, //mat_diffuse 70.0, //mat_specular 70.0, //mat_shininess 0.0}; //mat_emissionstruct point { point() {} point(double x,double y,double z) { point::x = x; point::y = y; point::z = z; } double x,y,z;};//---приводит длину вектора к 1void normalize(point & p){ double l = sqrt(p.x * p.x + p.y * p.y + p.z * p.z); p.x /= l; p.y /= l; p.z /= l;}//---рисует сферу радиусом radius, разбитую опр кол-вом колец и меридиановvoid DrawSphere(double radius,int meridians,int rings){ double dfi = 2*pi/meridians, dr = 2*radius/(rings + 1); double ro = radius,r,fi,theta; int i,j; //---массив точек vector <vector <point> > points; points.resize(rings); //---если в памяти уже находится чтото - освобождаем if (glIsList(1)) glDeleteLists(0,1); //---получаем кольца из точек for (r = -radius + dr,i = 0; i < rings; r += dr, i++) { theta = acos(r/ro); points[i].resize(meridians); for (fi = 0, j = 0; j < meridians; fi += dfi, j++) { //---переводим из сф системы в декартову points[i][j].x = ro * sin(theta) * cos(fi); points[i][j].y = ro * cos(theta); //y = r points[i][j].z = ro * sin(theta) * sin(fi); } } point p1,p2,p3,p4, //---точки n1,n2,n3,n4; //---нормали //---рисуем (результат запоминается в списке N1) glNewList(1,GL_COMPILE); //---основная часть сферы glBegin(GL_QUADS); for (i = 0; i < rings -1; ++i) { for (j = 0; j < meridians; ++j) { int next = j + 1; if (j == meridians - 1) next = 0; //---задаем точки по порядку против часовой стрелки - CCW n1 = p1 = points[i][j]; normalize(n1); n2 = p2 = points[i+1][j]; normalize(n2); n3 = p3 = points[i+1][next]; normalize(n3); n4 = p4 = points[i][next]; normalize(n4); glNormal3d(n1.x,n1.y,n1.z); glVertex3d(p1.x,p1.y,p1.z); glNormal3d(n2.x,n2.y,n2.z); glVertex3d(p2.x,p2.y,p2.z); glNormal3d(n3.x,n3.y,n3.z); glVertex3d(p3.x,p3.y,p3.z); glNormal3d(n4.x,n4.y,n4.z); glVertex3d(p4.x,p4.y,p4.z); } } glEnd(); //---полюса glBegin(GL_TRIANGLES); for (j = 0; j < meridians; ++j) { int next = j + 1; if (j == meridians - 1) next = 0; //---нижний n1 = p1 = points[0][j]; normalize(n1); n2 = p2 = points[0][next]; normalize(n2); n3 = p3 = point(0,-radius,0); normalize(n3); glNormal3d(n1.x,n1.y,n1.z); glVertex3d(p1.x,p1.y,p1.z); glNormal3d(n2.x,n2.y,n2.z); glVertex3d(p2.x,p2.y,p2.z); glNormal3d(n3.x,n3.y,n3.z); glVertex3d(p3.x,p3.y,p3.z); //---верхний n1 = p1 = points[rings-1][j]; normalize(n1); n2 = p2 = point(0,radius,0); normalize(n2); n3 = p3 = points[rings-1][next]; normalize(n3); glNormal3d(n1.x,n1.y,n1.z); glVertex3d(p1.x,p1.y,p1.z); glNormal3d(n2.x,n2.y,n2.z); glVertex3d(p2.x,p2.y,p2.z); glNormal3d(n3.x,n3.y,n3.z); glVertex3d(p3.x,p3.y,p3.z); } glEnd(); glEndList();}//---задает параметры освещенияvoid SetLight(){ //====== Обе поверхности изображения участвуют //====== при вычислении цвета пикселов //====== при учете параметров освещения glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1); float fPos[] = { light_params[0], light_params[1], light_params[2], 1.f }; glLightfv(GL_LIGHT1, GL_POSITION, fPos); float fDir[] = { light_params[3], light_params[4], light_params[5], 1.f }; glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION,fDir); //====== Интенсивность окружающего освещения float f = light_params[6]/100.f; float fAmbient[4] = { f, f, f, 0.f }; glLightfv(GL_LIGHT1, GL_AMBIENT, fAmbient); //====== Интенсивность рассеянного света f = light_params[7]/100.f; float fDiffuse[4] = { f, f, f, 0.f }; glLightfv(GL_LIGHT1, GL_DIFFUSE, fDiffuse); //====== Интенсивность отраженного света f = light_params[8]/100.f; float fSpecular[4] = { f, f, f, 0.f }; glLightfv(GL_LIGHT1, GL_SPECULAR, fSpecular); //====== Отражающие свойства материала //====== для разных компонент света f = light_params[9]/100.f; float fAmbMat[4] = { f, f, f, 0.f }; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, fAmbMat); f = light_params[10]/100.f; float fDifMat[4] = { f, f, f, 1.f }; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fDifMat); f = light_params[11]/100.f; float fSpecMat[4] = { f, f, f, 0.f }; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fSpecMat); //====== Блесткость материала float fShine = 128 * light_params[12]/100.f; glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, fShine); //====== Излучение света материалом f = light_params[13]/100.f; float fEmission[4] = { f, f, f, 0.f }; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, fEmission);}//----инициализация OpenGLvoid InitGL(){ glClearColor (0., 0., 0., 0.); glShadeModel (GL_SMOOTH); glEnable(GL_DEPTH_TEST); //---тест глубины glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_CULL_FACE); //---не отрисовывать задние грани полигонов //---освещение glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL);}//---изменение размеров сценыvoid _stdcall ReSize(int w,int h){ double dAspect = w<=h ? double(h)/w : double(w)/h; glMatrixMode (GL_PROJECTION); glLoadIdentity(); gluPerspective (45.0, dAspect, 0.01, 10000.); glViewport(0, 0, w, h);}void _stdcall DrawScene(){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //---смещаем glTranslated(tX,tY,tZ); //---поворачиваем glRotated(angleX,1.0,0.0,0.0); glRotated(angleY,0.0,1.0,0.0); //---вызываем команды рисования glCallList(1); auxSwapBuffers();}//---обработчики событий клавиатуры и мышиstatic void __stdcall OnButtonDown(AUX_EVENTREC *pEvent){ //====== Запоминаем координаты мыши sX = pEvent->data[AUX_MOUSEX]; sY = pEvent->data[AUX_MOUSEY];}static void __stdcall OnLMouseMove(AUX_EVENTREC *pEvent){ short cX,cY; cX = pEvent->data[AUX_MOUSEX]; cY = pEvent->data[AUX_MOUSEY]; angleY -= (sX - cX)/10.f; angleX -= (sY - cY)/10.f; sX = cX; sY = cY;}static void __stdcall OnRMouseMove(AUX_EVENTREC *pEvent){ short cX,cY; cX = pEvent->data[AUX_MOUSEX]; cY = pEvent->data[AUX_MOUSEY]; tZ-= (((sX - cX) + (sY - cY))/80.f); sX = cX; sY = cY;}static void __stdcall OnPressEscape(){ PostQuitMessage(0);}static void __stdcall OnPressF(){ Fill = !Fill; if (Fill) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); else glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);}static void __stdcall OnPressUp(){ if (mer_cnt < 1000) { mer_cnt += 10; rings_cnt += 10; } DrawSphere(3,mer_cnt,rings_cnt);}static void __stdcall OnPressDown(){ if (mer_cnt > 20) { mer_cnt -= 10; rings_cnt -= 10; } DrawSphere(3,mer_cnt,rings_cnt);}int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){ //---поддержка мыши auxMouseFunc(AUX_LEFTBUTTON, AUX_MOUSELOC, OnLMouseMove); auxMouseFunc(AUX_RIGHTBUTTON, AUX_MOUSELOC, OnRMouseMove); auxMouseFunc(AUX_LEFTBUTTON, AUX_MOUSEDOWN, OnButtonDown); auxMouseFunc(AUX_RIGHTBUTTON, AUX_MOUSEDOWN, OnButtonDown); //---поддержка клавиатуры auxKeyFunc(VK_ESCAPE,OnPressEscape); auxKeyFunc(‘F‘,OnPressF);auxKeyFunc(‘f‘,OnPressF); auxKeyFunc(VK_UP,OnPressUp); auxKeyFunc(VK_DOWN,OnPressDown); //---задаем режим работы auxInitDisplayMode (AUX_DOUBLE|AUX_RGB|AUX_DEPTH); //---и позицию окна auxInitPosition (100, 100, 600, 550); auxInitWindowA("Sphere"); //---юникод версия почемуто не работалаInitGL(); glColor3d(0,0.5,1.0); DrawSphere(3,mer_cnt,rings_cnt); auxReshapeFunc(ReSize); auxMainLoop(DrawScene);}
Форма ответа