Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС
выпущен 4 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Слушай, дружище, зачем так мучиться с этим языком С++, ты ведь не Билл Гейтс. Возьми тот же Python и программируй, он кроссплатформенный, под Windows тоже работает. Я сам давно заметил: то что на Си пишешь в страницу кода, на питоне решается в одну-две строки. При том, питон намного проще, я его сам недавно изучил по видеокурсу вот этому. Кстати, автор отлично там объясняет. Буквально день-два и уже будешь писать на нём, чего не скажешь про сложный С++.

Рисуем объёмное RGB-распределение цветной картинки, используя OpenGL


Авторы: Pierre Alliez и Magali Maziere.

Цель данного примера - показать, как можно цвета обыкновенной картинки разпределить в объёме (в данном случае в кубе). И при всём при том сделать это при помощи OpenGL :) Не знаю зачем это надо, но обезьянка на рисунке красивая :)

Рисунок 1: Наша цель отобразить на экране в палитре RGB цветов это 24 битное BMP цветное изображение интуитивным способом. OpenGL поможет нам в этом.

Рисунок 2: Иллюстрирует две точки обзора цветного распределения в диалоге. Точка обзора изменяется левой кнопкой мышки, которая позволяет вращать изображение в координатах x/y, диалог может быть увеличен или уменьшен и всплывающее меню позволяет загрузить и просмотреть текущую картинку (Рисунок 3).

Рисунок 3: Два примера цветного распределения в RGB кубе, видимое под двумя точками обозрения. В частности красное затемнение компонуется с носовой частью бабуина, показанного на рисунке 1. Облако рисуется при помощи GL_POINTS.

Рисунок 4: Всплывающее меню позволяет загружать 24 битовую RGB картинку, изменять бэкграунд OpenGL, и смотреть изображение в диалоговом окне.

Инициализация движка рендеринга

Следующие строки инициализируют движок в диалоге.

//*********************************
 
 // OnCreate 
 
 //*********************************
 
 int CColorDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
 
 {
 
  // Инициализируем движок OpenGL
 
  HWND hWnd = GetSafeHwnd();
 
  HDC hDC = ::GetDC(hWnd);
 
 
 
  if(SetWindowPixelFormat(hDC)==FALSE)
 
   return 0;
 
 
 
  if(CreateViewGLContext(hDC)==FALSE)
 
   return 0;
 
 
 
  // Линии антиалиасинга
 
  glEnable(GL_LINE_SMOOTH);
 
  glEnable(GL_BLEND);
 
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
 
  glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
 
  glLineWidth(1.5); // required
 
  glPointSize(1.0);
 
  glPolygonMode(GL_FRONT,GL_LINE);
 
  glPolygonMode(GL_BACK,GL_LINE);
 
  glShadeModel(GL_SMOOTH);
 
 
 
  // Вычисленные списки дисплея
 
  BuildListCube();
 
  BuildListCloud();
 
 
 
  return 0;
 
 }
//**********************************************
 
 // OpenGL
 
 //**********************************************
 
 BOOL CColorDlg::SetWindowPixelFormat(HDC hDC)
 
 {
 
  PIXELFORMATDESCRIPTOR pixelDesc;
 
 
 
  pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
 
  pixelDesc.nVersion = 1;
 
 
 
  pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW
 
                    | PFD_SUPPORT_OPENGL
 
                    | PFD_DOUBLEBUFFER
 
                    | PFD_STEREO_DONTCARE;
 
 
 
  pixelDesc.iPixelType = PFD_TYPE_RGBA;
 
  pixelDesc.cColorBits = 32;
 
  pixelDesc.cRedBits = 8;
 
  pixelDesc.cRedShift = 16;
 
  pixelDesc.cGreenBits = 8;
 
  pixelDesc.cGreenShift = 8;
 
  pixelDesc.cBlueBits = 8;
 
  pixelDesc.cBlueShift = 0;
 
  pixelDesc.cAlphaBits = 0;
 
  pixelDesc.cAlphaShift = 0;
 
  pixelDesc.cAccumBits = 64;
 
  pixelDesc.cAccumRedBits = 16;
 
  pixelDesc.cAccumGreenBits = 16;
 
  pixelDesc.cAccumBlueBits = 16;
 
  pixelDesc.cAccumAlphaBits = 0;
 
  pixelDesc.cDepthBits = 32;
 
  pixelDesc.cStencilBits = 8;
 
  pixelDesc.cAuxBuffers = 0;
 
  pixelDesc.iLayerType = PFD_MAIN_PLANE;
 
  pixelDesc.bReserved = 0;
 
  pixelDesc.dwLayerMask = 0;
 
  pixelDesc.dwVisibleMask = 0;
 
  pixelDesc.dwDamageMask = 0;
 
 
 
  m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);
 
  if(m_GLPixelIndex==0) // выбираем default
 
  {
 
   m_GLPixelIndex = 1;
 
   if(!DescribePixelFormat(hDC,m_GLPixelIndex,
 
   sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc))
 
   return FALSE;
 
  }
 
 
 
  if(!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc))
 
   return FALSE;
 
 
 
  return TRUE;
 
 }
 
 
 
 //*********************************
 
 // CreateViewGLContext 
 
 //*********************************
 
 BOOL CColorDlg::CreateViewGLContext(HDC hDC)
 
 {
 
  m_hGLContext = wglCreateContext(hDC);
 
 
 
  if(m_hGLContext==NULL)
 
   return FALSE;
 
 
 
  if(wglMakeCurrent(hDC,m_hGLContext)==FALSE)
 
   return FALSE;
 
 
 
  return TRUE;
 
 }
//*********************************
 
 // OnDestroy 
 
 //*********************************
 
 void CColorDlg::OnDestroy()
 
 {
 
  CDialog::OnDestroy();
 
 
 
  if(wglGetCurrentContext() != NULL)
 
   wglMakeCurrent(NULL,NULL);
 
 
 
  if(m_hGLContext != NULL)
 
  {
 
   wglDeleteContext(m_hGLContext);
 
   m_hGLContext = NULL;
 
  }
 
 
 
  glDeleteLists(1,2);
 
 }

РЕНДЕРИНГ

RGB куб и облака рендерятся в двух отдельных списках. Куб - всегда остаётся постоянным, в то время как облако вычисляется каждый раз при загрузке новой картинки.

//*********************************
 
 // OnPaint 
 
 //*********************************
 
 void CColorDlg::OnPaint()
 
 {
 
  // ** Draw scene **
 
  CPaintDC dc(this);
 
  RenderScene();
 
  SwapBuffers(dc.m_ps.hdc); // двойной буфер
 
 }
//*********************************
 
 // RenderScene 
 
 //*********************************
 
 void CColorDlg::RenderScene()
 
 {
 
  ::glClearColor((float)GetRValue(m_BackColor)/255.0f,
 
                 (float)GetGValue(m_BackColor)/255.0f,
 
                 (float)GetBValue(m_BackColor)/255.0f,1.0f);
 
  ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
 
 
  ::glPushMatrix();
 
  ::glTranslated(0.0,0.0,-8.0);
 
  ::glRotated(m_xRotate, 1.0, 0.0, 0.0);
 
  ::glRotated(m_yRotate, 0.0, 1.0, 0.0);
 
  ::glCallList(1); // cube
 
  ::glCallList(2); // clouds
 
  ::glPopMatrix();
 
 }
 
 
 
 //***********************************************
 
 // BuildList
 
 //***********************************************
 
 void CColorDlg::BuildListCube(BOOL list)
 
 {
 
  GLUquadricObj* pQuadric = gluNewQuadric();
 
 
 
  if(list)
 
   ::glNewList(1,GL_COMPILE_AND_EXECUTE);
 
 
 
  float x = m_Size;
 
 
 
  // RGB куб
 
  glBegin(GL_LINE_LOOP);
 
   glColor3ub(0,0,0);
 
   glVertex3d(-x,-x,-x);
 
   glColor3ub(255,0,0);
 
   glVertex3d(x,-x,-x);
 
   glColor3ub(255,255,0);
 
   glVertex3d(x,x,-x);
 
   glColor3ub(0,255,0);
 
   glVertex3d(-x,x,-x);
 
  glEnd();
 
 
 
  glBegin(GL_LINE_LOOP);
 
   glColor3ub(0,0,255);
 
   glVertex3d(-x,-x,x);
 
   glColor3ub(255,0,255);
 
   glVertex3d(x,-x,x);
 
   glColor3ub(255,255,255);
 
   glVertex3d(x,x,x);
 
   glColor3ub(0,255,255);
 
   glVertex3d(-x,x,x);
 
  glEnd();
 
 
 
  glBegin(GL_LINES);
 
   glColor3ub(0,0,0);
 
   glVertex3d(-x,-x,-x);
 
   glColor3ub(0,0,255);
 
   glVertex3d(-x,-x,x);
 
   glColor3ub(255,0,0);
 
   glVertex3d(x,-x,-x);
 
   glColor3ub(255,0,255);
 
   glVertex3d(x,-x,x);
 
   glColor3ub(255,255,0);
 
   glVertex3d(x,x,-x);
 
   glColor3ub(255,255,255);
 
   glVertex3d(x,x,x);
 
   glColor3ub(0,255,0);
 
   glVertex3d(-x,x,-x);
 
   glColor3ub(0,255,255);
 
   glVertex3d(-x,x,x);
 
  glEnd();
 
 
 
  // Сферы
 
  glPolygonMode(GL_FRONT,GL_FILL);
 
  glPolygonMode(GL_BACK,GL_FILL);
 
  float radius = 0.1f;
 
 
 
  glPushMatrix();
 
  glTranslated(-m_Size,-m_Size,-m_Size);
 
  glColor3ub(0,0,0);
 
  gluSphere(pQuadric,radius,12,12);
 
  glPopMatrix();
 
 
 
  glPushMatrix();
 
  glTranslated(m_Size,-m_Size,-m_Size);
 
  glColor3ub(255,0,0);
 
  gluSphere(pQuadric,radius,12,12);
 
  glPopMatrix();
 
 
 
  glPushMatrix();
 
  glTranslated(-m_Size,m_Size,-m_Size);
 
  glColor3ub(0,255,0);
 
  gluSphere(pQuadric,radius,12,12);
 
  glPopMatrix();
 
 
 
  glPushMatrix();
 
  glTranslated(-m_Size,-m_Size,m_Size);
 
  glColor3ub(0,0,255);
 
  gluSphere(pQuadric,radius,12,12);
 
  glPopMatrix();
 
 
 
  glPushMatrix();
 
  glTranslated(m_Size,m_Size,-m_Size);
 
  glColor3ub(255,255,0);
 
  gluSphere(pQuadric,radius,12,12);
 
  glPopMatrix();
 
 
 
  glPushMatrix();
 
  glTranslated(-m_Size,m_Size,m_Size);
 
  glColor3ub(0,255,255);
 
  gluSphere(pQuadric,radius,12,12);
 
  glPopMatrix();
 
 
 
  glPushMatrix();
 
  glTranslated(m_Size,-m_Size,m_Size);
 
  glColor3ub(255,0,255);
 
  gluSphere(pQuadric,radius,12,12);
 
  glPopMatrix();
 
 
 
  glPushMatrix();
 
  glTranslated(m_Size,m_Size,m_Size);
 
  glColor3ub(255,255,255);
 
  gluSphere(pQuadric,radius,12,12);
 
  glPopMatrix();
 
 
 
  if(list)
 
   ::glEndList();
 
 
 
  gluDeleteQuadric(pQuadric);
 
 }
 
 
 
 //***********************************************
 
 // BuildListCloud
 
 //***********************************************
 
 void CColorDlg::BuildListCloud()
 
 {
 
  TRACE("Build list cloud...");
 
 
 
  // Область изображения
 
  unsigned int area = m_Image.GetWidth()
 
                    * m_Image.GetHeight();
 
 
 
  TRACE("area : %d...",area);
 
 
 
  // Необходимо, чтобы картинка была 24 бита
 
  if(area == 0 ||
 
   m_Image.GetDepth() != 24)
 
  return;
 
 
 
  // Максимум -> область отчётливых цветов / 2^24
 
  // Эта таблица занимает прилично памати, но на короткое время
 
  TRACE("alloc...");
 
  unsigned char *pTable = new unsigned char[16777216];
 
  memset(pTable,0,16777216); // init 0
 
 
 
  // Содержимое картинки
 
  unsigned int wb32 = m_Image.GetWidthByte32();
 
  unsigned char *pData = m_Image.GetData();
 
 
 
  // Строим новый список
 
  TRACE("build list...");
 
  int nb = 0;
 
  ::glNewList(2,GL_COMPILE_AND_EXECUTE);
 
  glBegin(GL_POINTS);
 
  float tmp = 2.0f/255.0f*m_Size;
 
  for(unsigned int j=0;j<m_Image.GetHeight();j++)
 
   for(unsigned int i=0;i<m_Image.GetWidth();i++)
 
   {
 
    unsigned char b = pData[wb32*j+3*i];
 
    unsigned char g = pData[wb32*j+3*i+1];
 
    unsigned char r = pData[wb32*j+3*i+2];
 
    if(!pTable[b*65536+g*256+r])
 
    {
 
     glColor3ub(r,g,b);
 
     float x = -m_Size+(float)r*tmp;
 
     float y = -m_Size+(float)g*tmp;
 
     float z = -m_Size+(float)b*tmp;
 
     glVertex3d(x,y,z);
 
     pTable[b*65536+g*256+r] = 1;
 
     nb++;
 
    }
 
   }
 
 
 
  glEnd();
 
  ::glEndList();
 
  TRACE("%d points...",nb);
 
 
 
  TRACE("cleanup...");
 
  delete [] pTable;
 
  TRACE("ok\n");
 
 }

Downloads

Скачать демонстрационный проект - 530 Kb
Скачать исходник - 10 Kb




<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS