MFC コントロールで OpenGL を設定するクラスをダウンロードし、目的に合わせてカスタマイズしました (画像を表示し、ズームやその他の変換を行います)。
OpenGLControl.h
#pragma once
#include "afxwin.h"
#include "gl\GL.h"
#include "gl\GLU.h"
#include "gdal_priv.h"
#include <algorithm>
#include <math.h>
#include <vector>
using std::vector;
using std::min;
class COpenGLControl2D : public CWnd
{
public:
COpenGLControl2D(void); //Constructor and destructor
virtual ~COpenGLControl2D(void);
void oglCreate(CRect , CWnd *); //Manually added functions
void oglInitialize(void);
void oglDrawScene(void);
//call this function just first time of calling OnTimer and after setting pImage
//for the next calls of OnTimer and when updating pImage there's no need to call
//this function. If you do so, your client code slows down
void setImageWidthHeightType(int,int,GDALDataType);
//For second and more calls of OnTimer you should call this function after setting pImage
//In the first call of OnTimer and before calling setImageWidthHeightType(int,int,GDALDataType)
//this function should not be called and if so, the program will encounter an unhandled exception
//because there you still don't have any texture object to be updated
void updataTextureObject();
void ZoomToFullExtent();
/******************/
/* PUBLIC MEMBERS */
/******************/
// Timer
UINT_PTR m_unpTimer;
//you should update value of this member variable whenever you want to call OnTimer
vector<unsigned char>pImage;
private:
//used internally by function ZoomIn,ZoomOut and Pan and etc
float m_fLastX;
float m_fLastY;
float m_fPosX;
float m_fPosY;
float m_fZoom;
//texture object used internally by the class
GLuint *textures;
GLsizei numberOfTextures;
private:
/*******************/
/* PRIVATE MEMBERS */
/*******************/
// Window information
CWnd *hWnd;
HDC hdc;
HGLRC hrc;
int m_nPixelFormat;
CRect m_rect;
CRect m_oldWindow;
CRect m_originalRect;
GLsizei ImageWidth;
GLsizei ImageHeight;
GLsizei oglWindowWidth;
GLsizei oglWindowHeight;
GLenum format;
GLenum type;
GLenum target;
GLint level;
GLint internalformat;
GLint border;
GLint xOffset;
GLint yOffset;
private:
//used internally by the public member function setImageWidthHeightType of the class
void InitializeTextureObject();
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnPaint();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDraw(CDC *pDC);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnSize(UINT nType, int cx, int cy);
//afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};
OpenGLControl.cpp
#include "StdAfx.h"
#include "OpenGLControl.h"
COpenGLControl2D::COpenGLControl2D(void)
{
ImageWidth = 0;
ImageHeight = 0;
format = GL_LUMINANCE;
type = GL_BITMAP;
m_fPosX = 0.0f; // X position of model in camera view
m_fPosY = 0.0f; // Y position of model in camera view
m_fZoom = 1.0f; // Zoom on model in camera view
oglWindowWidth = 0;
oglWindowHeight = 0;
textures = new GLuint();
numberOfTextures = 1;
target = GL_TEXTURE_2D;
level = 0;
internalformat = format;
border = 0;
xOffset = 0;
yOffset = 0;
}
COpenGLControl2D::~COpenGLControl2D(void)
{
delete textures;
}
void COpenGLControl2D::oglCreate(CRect rect, CWnd *parent)
{
CString className = AfxRegisterWndClass(CS_HREDRAW |
CS_VREDRAW | CS_OWNDC, NULL,
(HBRUSH)GetStockObject(BLACK_BRUSH), NULL);
char *windowName = "OpenGL";
CA2T TwindowName(windowName);
CString strTwindowName = TwindowName.m_psz;
CreateEx(0, className, strTwindowName, WS_CHILD | WS_VISIBLE |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);
// Set initial variables' values
m_oldWindow = rect;
m_originalRect = rect;
oglWindowWidth = rect.right - rect.left;
oglWindowHeight = rect.bottom - rect.top;
hWnd = parent;
}
BEGIN_MESSAGE_MAP(COpenGLControl2D, CWnd)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_SIZE()
//ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
void COpenGLControl2D::OnPaint()
{
//CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CWnd::OnPaint() for painting messages
ValidateRect(NULL);
}
int COpenGLControl2D::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
oglInitialize();
return 0;
}
void COpenGLControl2D::oglInitialize(void)
{
// Initial Setup:
//
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32, //bit depth
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16, // z-buffer depth
0, 0, 0, 0, 0, 0, 0,
};
// Get device context only once.
hdc = GetDC()->m_hDC;
// Pixel format.
m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, m_nPixelFormat, &pfd);
// Create the OpenGL Rendering Context.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
hrc = wglCreateContext(hdc);
GLenum error1 = glGetError();
wglMakeCurrent(hdc, hrc);
// Basic Setup:
//
// Set color to use when clearing the background.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
// Turn on backface culling
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
// Turn on depth testing
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// Send draw request
OnDraw(NULL);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error9 = glGetError();
}
void COpenGLControl2D::OnDraw(CDC *pDC)
{
wglMakeCurrent(hdc, hrc);
// TODO: Camera controls.
glLoadIdentity();
glScalef(m_fZoom,m_fZoom,1);
GLenum error42 = glGetError();
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL,NULL);
GLenum error12 = glGetError();
}
void COpenGLControl2D::OnTimer(UINT_PTR nIDEvent)
{
wglMakeCurrent(hdc, hrc);
// TODO: Add your message handler code here and/or call default
switch (nIDEvent)
{
case 1:
{
// Clear color and depth buffer bits
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw OpenGL scene
oglDrawScene();
// Swap buffers
SwapBuffers(hdc);
break;
}
default:
break;
}
CWnd::OnTimer(nIDEvent);
}
void COpenGLControl2D::setImageWidthHeightType(int localWidth,int localHeight,GDALDataType localType)
{
ImageWidth = localWidth;
ImageHeight = localHeight;
switch (localType)
{
case GDT_Byte:
{
type = GL_UNSIGNED_BYTE;
break;
}
case GDT_UInt16:
{
type = GL_UNSIGNED_SHORT;
break;
}
case GDT_Int16:
{
type = GL_SHORT;
break;
}
case GDT_UInt32:
{
type = GL_UNSIGNED_INT;
break;
}
case GDT_Int32:
{
type = GL_INT;
break;
}
}
InitializeTextureObject();
}
void COpenGLControl2D::oglDrawScene(void)
{
wglMakeCurrent(hdc, hrc);
float x0 = 0; // top left corner of image
float y0 = 0;
float x1 = x0 + ImageWidth; // bottom right corner of image
float y1 = y0 + ImageHeight;
glBegin(GL_TRIANGLE_STRIP);
{
glTexCoord2f(0, 1); glVertex2f(x0, y1);
glTexCoord2f(0, 0); glVertex2f(x0, y0);
glTexCoord2f(1, 1); glVertex2f(x1, y1);
glTexCoord2f(1, 0); glVertex2f(x1, y0);
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
glEnd();
GLenum error24 = glGetError();
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error26 = glGetError();
}
void COpenGLControl2D::OnSize(UINT nType, int cx, int cy)
{
wglMakeCurrent(hdc, hrc);
CWnd::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;
oglWindowWidth = cx;
oglWindowHeight = cy;
// Map the OpenGL coordinates.
glViewport(0, 0, oglWindowWidth, oglWindowHeight);
// Projection view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set our current view perspective
glOrtho(0, oglWindowWidth, oglWindowHeight,0, -1, 1);
// Model view
glMatrixMode(GL_MODELVIEW);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error33 = glGetError();
}
void COpenGLControl2D::InitializeTextureObject()
{
wglMakeCurrent(hdc, hrc);
glGenTextures(numberOfTextures,textures);
glBindTexture(GL_TEXTURE_2D, *textures);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(target,level,internalformat,ImageWidth,ImageHeight,border,format,type,&pImage[0]);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error38 = glGetError();
}
void COpenGLControl2D::updataTextureObject()
{
wglMakeCurrent(hdc, hrc);
glTexSubImage2D(target,level,xOffset,yOffset,ImageWidth,ImageHeight,format,type,&pImage[0]);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error41 = glGetError();
}
void COpenGLControl2D::ZoomToFullExtent()
{
float zoom1 = oglWindowWidth/ImageWidth;
float zoom2 = oglWindowHeight/ImageHeight;
float minZoom = min(zoom1,zoom2);
m_fZoom = floor(minZoom);
OnDraw(NULL);
}
void COpenGLControl2D::FixedZoomIn()
{
m_fZoom = 2*m_fZoom;
}
このコードでこのクラスを使用すると:
COpenGLControl m_oglWindow;
m_oglWindow = new COpenGLControl2D();
CRect rect;
GetDlgItem(IDC_OPENGL)->GetWindowRect(rect);
ScreenToClient(rect);
m_oglWindow -> oglCreate(rect, this);
const char* filename = "D:\\DataPrevious\\globalMapper.tif";
GDALDataset *poDataset = NULL ;
GDALAllRegister();
poDataset = (GDALDataset *) GDALOpen( filename, GA_ReadOnly );
m_files -> ReadRasterData(poDataset);
m_oglWindow -> pImage = m_files -> pRasterData;
m_oglWindow -> setImageWidthHeightType(m_files->RasterXSize,m_files->RasterYSize,m_files->eType);
m_oglWindow -> m_unpTimer = m_oglWindow -> SetTimer(1, 1, 0);
m_oglWindow ->updataTextureObject();
m_oglWindow ->ZoomToFullExtent();
m_oglWindow ->FixedZoomIn();
512x512 の画像でこれを取得します。
ジオメトリにテクスチャが適用されていないことがわかります。また、機能も何もしないようですFixedZoomIn()
。ZoomToFullExtent()
これは、OpenGLがOnTimer
関数内でのみ描画を行うためでしょうか?
とにかくglGetError()
、プレフィックスで始まるすべての関数を使用した後、指定した場所にエラーがスローされるgl
ことに気付きました。INVALID_OPERATION(1282)
が作成されていないように見えますが、 hrc(rendering context)
opengl がその白いジオメトリをそこに描画する方法がわかりませんか? またglEnd()
、そのエラーもスローしています。クラスのいくつかの関数で、なぜand
を使用したのか疑問に思われるかもしれません。wglMakeCurrent(hdc,hrc)
wglMakeCurrent(NULL,NULL)
これは、私がここで学んだことによるものです。単一の MFC ダイアログで OpenGL の 2 つの異なる 3D レンダリング画像コントロールが機能しない
私の質問は、レンダリング コンテキストが作成されていないか、デバイス コンテキストが有効でない場合、opengl でその白い四角形をどのように描画できるかということです。
問題が他の何かである場合、それは何ですか?
長方形のジオメトリにテクスチャが適用されないのはなぜですか?
ズーム操作で使用される glScale() のような関数が機能しないのはなぜですか?
なぜ glEnd() も 1282 エラーを生成するのですか? 機能によるものですかglTexCoord
、それともglVertex
?
また、問題がコンテキストが作成されていないことである場合、どのように作成できますhrc = wglCreateContext(hdc)
か?