我想创建一个应用程序,其中应用程序视图将在使用拆分器附加到 Childframe 的两个不同视图中与 OpenGL 3d 模型分开。为此,我创建了一个从视图类扩展的父类,并且在这个类中我已经初始化了所有 opengl 所需的代码。
例如
#pragma once
#include <gl/gl.h>
#include <gl/glu.h>
#define IL //when you dont want to use image library and you want to load everything by your self then remove this
// COpenGlView view
class COpenGlView : public CView
{
DECLARE_DYNCREATE(COpenGlView)
protected:
void oglBeginRendering();
COpenGlView(); // protected constructor used by dynamic creation
virtual ~COpenGlView();
/*******************/
/* Private Members */
/*******************/
// Window information
CWnd *hWnd;
HDC hdc;
HGLRC hrc;
int m_nPixelFormat;
CRect m_rect;
CRect m_oldWindow;
CRect m_originalRect;
public:
/******************/
/* Public Members */
/******************/
UINT_PTR m_unpTimer;
// View information variables
float m_fLastX;
float m_fLastY;
float m_fPosX;
float m_fPosY;
float m_fZoom;
float m_fRotX;
float m_fRotY;
bool m_bIsMaximized;
float m_fZoomSpeed;
float m_fRotateSpeed;
GLuint texture[1];
void oglCreate(CRect rect, CWnd *parent,CString strWindowName=L"OpenGl");
virtual void oglInitialize(void);
virtual void oglDrawScene(void);
float randFloat(const float& min, const float& max);
int randInt(const int& min, const int& max);
void Reset();
virtual void OnDraw(CDC* pDC); // overridden to draw this view
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnPaint();
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnTimer(UINT_PTR nIDEvent);
virtual void OnInitialUpdate();
};
这是cpp
// OpenGlView.cpp : implementation file
//
#include "stdafx.h"
#include "OpenGlView.h"
// COpenGlView
IMPLEMENT_DYNCREATE(COpenGlView, CView)
COpenGlView::COpenGlView()
{
m_fPosX = 0.0f; // X position of model in camera view
m_fPosY = 0.0f; // Y position of model in camera view
m_fZoom = 5.0f; // Zoom on model in camera view
m_fRotX = 0.0f; // Rotation on model in camera view
m_fRotY = 0.0f; // Rotation on model in camera view
m_fZoomSpeed=0.05f;
m_fRotateSpeed = 0.05f;
m_bIsMaximized = false;
}
COpenGlView::~COpenGlView()
{
}
void COpenGlView::Reset()
{
m_fPosX = 0.0f; // X position of model in camera view
m_fPosY = 0.0f; // Y position of model in camera view
m_fZoom = 5.0f; // Zoom on model in camera view
m_fRotX = 0.0f; // Rotation on model in camera view
m_fRotY = 0.0f; // Rotation on model in camera view
m_fZoomSpeed=0.05f;
m_fRotateSpeed = 0.05f;
m_bIsMaximized = false;
}
BEGIN_MESSAGE_MAP(COpenGlView, CView)
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
ON_WM_SIZE()
ON_WM_TIMER()
END_MESSAGE_MAP()
// COpenGlView drawing
void COpenGlView::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here
}
// COpenGlView diagnostics
#ifdef _DEBUG
void COpenGlView::AssertValid() const
{
CView::AssertValid();
}
#ifndef _WIN32_WCE
void COpenGlView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
#endif
#endif //_DEBUG
// COpenGlView message handlers
int COpenGlView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
void COpenGlView::OnPaint()
{
//CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CView::OnPaint() for painting messages
ValidateRect(NULL);
}
void COpenGlView::OnMouseMove(UINT nFlags, CPoint point)
{
int diffX = (int)(point.x - m_fLastX);
int diffY = (int)(point.y - m_fLastY);
m_fLastX = (float)point.x;
m_fLastY = (float)point.y;
// Left mouse button
if (nFlags & MK_LBUTTON)
{
m_fRotX += (float)m_fRotateSpeed * diffY;
if ((m_fRotX > 360.0f) || (m_fRotX < -360.0f))
{
m_fRotX = 0.0f;
}
m_fRotY += (float)0.5f * diffX;
if ((m_fRotY > 360.0f) || (m_fRotY < -360.0f))
{
m_fRotY = 0.0f;
}
}
// Right mouse button
else if (nFlags & MK_RBUTTON)
{
m_fZoom -= (float)m_fZoomSpeed * diffY;
}
// Middle mouse button
else if (nFlags & MK_MBUTTON)
{
m_fPosX += (float)0.05f * diffX;
m_fPosY -= (float)0.05f * diffY;
}
OnDraw(NULL);
CView::OnMouseMove(nFlags, point);
}
void COpenGlView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;
// Map the OpenGL coordinates.
glViewport(0, 0, cx, cy);
// Projection view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set our current view perspective
gluPerspective(35.0f, (float)cx / (float)cy, 0.01f, 2000.0f);
// Model view
glMatrixMode(GL_MODELVIEW);
switch (nType)
{
// If window resize token is "maximize"
case SIZE_MAXIMIZED:
{
// Get the current window rect
GetWindowRect(m_rect);
// Move the window accordingly
MoveWindow(6, 6, cx - 14, cy - 14);
// Get the new window rect
GetWindowRect(m_rect);
// Store our old window as the new rect
m_oldWindow = m_rect;
break;
}
// If window resize token is "restore"
case SIZE_RESTORED:
{
// If the window is currently maximized
if (m_bIsMaximized)
{
// Get the current window rect
GetWindowRect(m_rect);
// Move the window accordingly (to our stored old window)
MoveWindow(m_oldWindow.left, m_oldWindow.top - 18, m_originalRect.Width() - 4, m_originalRect.Height() - 4);
// Get the new window rect
GetWindowRect(m_rect);
// Store our old window as the new rect
m_oldWindow = m_rect;
}
break;
}
}
}
void COpenGlView::oglBeginRendering()
{
SetTimer(1, 1, 0);
}
void COpenGlView::OnTimer(UINT_PTR nIDEvent)
{
switch (nIDEvent)
{
case 1:
{
// Clear color and depth buffer bits
wglMakeCurrent(hdc, hrc);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw OpenGL scene
oglDrawScene();
// Swap buffers
SwapBuffers(hdc);
glFlush();
wglMakeCurrent(NULL, NULL);
break;
}
default:
break;
}
CView::OnTimer(nIDEvent);
}
void COpenGlView::OnInitialUpdate()
{
CView::OnInitialUpdate();
COpenGlView::oglInitialize();
// TODO: Add your specialized code here and/or call the base class
}
void COpenGlView::oglCreate(CRect rect, CWnd *parent,CString strWindowName)
{
CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, (HBRUSH)GetStockObject(BLACK_BRUSH), NULL);
CreateEx(0, className,strWindowName, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);
// Set initial variables' values
m_oldWindow = rect;
m_originalRect = rect;
hWnd = parent;
GLenum s = glGetError();
}
void COpenGlView::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.
hrc = wglCreateContext(hdc);
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);
GLenum a = glGetError();
OnDraw(NULL);
//wglMakeCurrent(NULL, NULL);
}
void COpenGlView::oglDrawScene(void)
{
// Wireframe Mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBegin(GL_QUADS);
// Front Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Back Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
// Bottom Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
// Left Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -m_fZoom);
glTranslatef(m_fPosX, m_fPosY, 0.0f);
glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);
glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
GLenum a = glGetError();
}
//--------------------------------------------------------
// Get an random integer within a specified range
//--------------------------------------------------------
int COpenGlView::randInt(const int& min, const int& max) {
return ((rand()%(int)(((max) + 1)-(min)))+ (min));
}
//--------------------------------------------------------
// Get a random float within a specified range
//--------------------------------------------------------
float COpenGlView::randFloat(const float& min, const float& max) {
float range = max - min;
float num = range * rand() / RAND_MAX;
return (num + min);
}
然后我从同一个类类中扩展了另外两个视图类
C3dRightView : public COpenGlView
和
C3dRightView : public COpenGlView
然后在子框架类中我添加了拆分器代码并在拆分器窗口中调用了这两个类。问题是两个opengl视图代码都可以正常工作,但是如果我停止opengl的初始化之一,那么另一个会显示。我尝试了一切,但我无法在这两个不同的视图中显示两个不同的图形 opengl 动画。我检查了 HDC 内存映射,似乎两个类都在使用父类来处理它们的动态 hdc 对象,但是如果我停止一个代码,那么其他视图会正确显示。
详细课程如下
class C3dRightView : public COpenGlView
{
DECLARE_DYNCREATE(C3dRightView)
protected:
GLuint m_left_texture[53];
C3dRightView(); // protected constructor used by dynamic creation
virtual ~C3dRightView();
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
virtual void OnInitialUpdate();
void oglDrawScene(void);
void oglInitialize(void);
afx_msg void OnTimer(UINT_PTR nIDEvent);
};
void C3dRightView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CView::OnPaint() for painting messages
}
void C3dRightView::OnInitialUpdate()
{
hdc = C3dRightView::GetDC()->m_hDC;
/** If i open below code then left view stop displaying model **/
COpenGlView::OnInitialUpdate();
oglInitialize();
//-=-=-=-=-=-=-==--=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
oglBeginRendering();
// TODO: Add your specialized code here and/or call the base class
}
void C3dRightView::oglInitialize(void)
{
COpenGlView::oglInitialize();
}
void C3dRightView::oglDrawScene(void)
{
// Wireframe Mode
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 1.0f, 1.0f, 0.0f);
glLoadIdentity();
//glTranslatef(0.0f, 0.0f, -m_fZoom);//this is for zoom using left mouse click but no placing
glTranslatef(m_fPosX, m_fPosY,-m_fZoom); // this is for placing + zooming using middle scroll button mouse click
glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);//these two for mouse movement
glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
glRotated(90,0.0f, 0.0f, -1.0f);
glRotatef(180,1.0f,0,0.0f);
GLenum a = glGetError();
glBegin(GL_TRIANGLES); // Start Drawing A Triangle
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Left Of Triangle (Front)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Right Of Triangle (Front)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)
glEnd();
}
第二个视图文件是这样的
class C3dLeftView : public COpenGlView
{
DECLARE_DYNCREATE(C3dLeftView)
protected:
GLuint m_left_texture[53];
C3dLeftView(); // protected constructor used by dynamic creation
virtual ~C3dLeftView();
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
virtual void OnInitialUpdate();
void oglDrawScene(void);
void oglInitialize(void);
afx_msg void OnTimer(UINT_PTR nIDEvent);
};
void C3dLeftView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CView::OnPaint() for painting messages
}
void C3dLeftView::OnInitialUpdate()
{
hdc = C3dLeftView::GetDC()->m_hDC;
COpenGlView::OnInitialUpdate();
oglInitialize();
oglBeginRendering();
// TODO: Add your specialized code here and/or call the base class
}
void C3dLeftView::oglInitialize(void)
{
COpenGlView::oglInitialize();
}
void C3dLeftView::oglDrawScene(void)
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glLoadIdentity();
//glTranslatef(0.0f, 0.0f, -m_fZoom);//this is for zoom using left mouse click but no placing
glTranslatef(m_fPosX, m_fPosY,-m_fZoom); // this is for placing + zooming using middle scroll button mouse click
glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);//these two for mouse movement
glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
glRotated(90,0.0f, 0.0f, -1.0f);
glRotatef(180,1.0f,0,0.0f);
GLenum a = glGetError();
glBegin(GL_TRIANGLES); // Start Drawing A Triangle
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Left Of Triangle (Front)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Right Of Triangle (Front)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)
glEnd();
/*************************************************************************************/
}
如果在视图的 initialupdate 函数内的代码下方注释,则其他视图代码可以正常工作。
COpenGlView::OnInitialUpdate();
oglInitialize();
一些父代码的初始更新代码如何为其一个孩子而不是其中两个工作。