-1

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)か?

4

1 に答える 1

1

私の質問は、レンダリング コンテキストが作成されていないか、デバイス コンテキストが有効でない場合、opengl でその白い四角形をどのように描画できるかということです。

あなたが投稿したコードの混乱を通り抜ける忍耐力は本当にありません。しかし、長方形が描画されている時点で、アクティブなコンテキストがあるためです。

長方形のジオメトリにテクスチャが適用されないのはなぜですか?

不完全な画像定義とミップマッピングが有効になっています。描画時にバインドされていてアクティブなテクスチャ ターゲットはありません。これが通常の理由です。

ズーム操作で使用される glScale() のような関数が機能しないのはなぜですか?

glScale は、以前に描画されたものに何らかの即時の影響を与えると考えているようです。それは glScale が行うことではありません。glScale が行うことは、現在アクティブなマトリックス スタックの最上位要素を変更することだけです。これ以上何もない。

一般に、OpenGL はシーンやオブジェクトを維持しません。見た目を変えたい場合は、再描画する必要があります。

ところで: あなたのコードには、OpenGL の誤った使用に加えて、非常に多くの混乱があるため、C++ 101 を再検討することを強くお勧めします。あなたのコードには、たくさんの間違った構造があります。まず、これを考慮してください (以下の問題は何ですか? 1 でない場合numberOfTexturesは間違っていますか?):

textures = new GLuint(); 
…
glGenTextures(numberOfTextures,textures);
于 2013-08-14T16:18:20.683 に答える