1 // OpenGLView.cpp : implementation of the COpenGLView class
\r
5 #include "OpenGLView.h"
\r
8 typedef struct _Point3d
\r
14 #define new DEBUG_NEW
\r
16 static char THIS_FILE[] = __FILE__;
\r
19 #define vector_length(a) sqrt(a.x*a.x+a.y*a.y+a.z*a.z)
\r
20 #define scalar_product(a,b) (a.x*b.x+a.y*b.y+a.z*b.z)
\r
21 #define vector_angle(a,b) (acos(scalar_product(a,b))*180./3.1415926535)
\r
22 #define vector_product_x(a,b) (a.y*b.z-a.z*b.y)
\r
23 #define vector_product_y(a,b) (a.z*b.x-a.x*b.z)
\r
24 #define vector_product_z(a,b) (a.x*b.y-a.y*b.x)
\r
25 #define vector_product(a,b,c) c.x=vector_product_x(a,b);c.y=vector_product_y(a,b);c.z=vector_product_z(a,b)
\r
26 #define sub_vector(a,b,c) c.x=a.x-b.x;c.y=a.y-b.y;c.z=a.z-b.z
\r
27 #define add_vector(a,b,c) c.x=a.x+b.x;c.y=a.y+b.y;c.z=a.z+b.z
\r
29 #define normalize_vector(a) {float len;len=(float)vector_length(a);if(len>0){a.x /= len;a.y /= len;a.z /= len;}}
\r
31 #define vector_lengthV(a) sqrt(a->x*a->x+a->y*a->y+a->z*a->z)
\r
32 #define normalize_vectorV(a) {float len;len=(float)vector_lengthV(a);if(len>0){a->x /= len;a->y /= len;a->z /= len;}}
\r
34 /////////////////////////////////////////////////////////////////////////////
\r
37 IMPLEMENT_DYNCREATE(COpenGLView, CView)
\r
39 BEGIN_MESSAGE_MAP(COpenGLView, CView)
\r
40 //{{AFX_MSG_MAP(COpenGLView)
\r
47 // Standard printing commands
\r
48 ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
\r
49 ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
\r
50 ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
\r
53 /////////////////////////////////////////////////////////////////////////////
\r
54 // COpenGLView construction/destruction
\r
56 COpenGLView::COpenGLView() : m_pDC(0)
\r
58 InitCameraPosition();
\r
61 COpenGLView::~COpenGLView()
\r
66 BOOL COpenGLView::PreCreateWindow(CREATESTRUCT& cs)
\r
68 // OpenGL òðåáóåò íàëè÷èÿ ñòèëåé WS_CLIPCHILDREN è WS_CLIPSIBLINGS
\r
69 cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
\r
71 return CView::PreCreateWindow(cs);
\r
74 /////////////////////////////////////////////////////////////////////////////
\r
75 // COpenGLView printing
\r
77 BOOL COpenGLView::OnPreparePrinting(CPrintInfo* pInfo)
\r
79 // default preparation
\r
80 return DoPreparePrinting(pInfo);
\r
83 void COpenGLView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
\r
87 void COpenGLView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
\r
91 /////////////////////////////////////////////////////////////////////////////
\r
92 // COpenGLView diagnostics
\r
95 void COpenGLView::AssertValid() const
\r
97 CView::AssertValid();
\r
100 void COpenGLView::Dump(CDumpContext& dc) const
\r
105 CDocument* COpenGLView::GetDocument() // non-debug version is inline
\r
107 ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDocument)));
\r
108 return (CDocument*)m_pDocument;
\r
112 /////////////////////////////////////////////////////////////////////////////
\r
113 // COpenGLView message handlers
\r
115 int COpenGLView::InitOpenGL()
\r
117 // Ôîðìèðóåì êîíòåêñò ðàáî÷åé îáëàñòè
\r
118 m_pDC = new CClientDC(this);
\r
119 ASSERT(m_pDC != NULL);
\r
121 // Ïîëó÷àåì äåñêðèïòîð êîíòåêñòà óñòðîéñòâà
\r
122 HDC hdc = m_pDC->GetSafeHdc();
\r
124 // Óñòàíàâëèâàåì ôîðìàò ïèêñåëåé
\r
125 if (SetPixelFormat(hdc)==FALSE)
\r
128 // Ñîçäàåì è äåëàåì òåêóùèì êîíòåêñò âîñïðîèçâåäåíèÿ
\r
129 if (CreateGLContext(hdc)==FALSE)
\r
135 void COpenGLView::OnDestroy()
\r
137 // Ïîëó÷àåì òåêóùèé êîíòåêñò âîñïðîèçâåäåíèÿ
\r
138 HGLRC hrc = ::wglGetCurrentContext();
\r
140 // Ïåðåä óäàëåíèåì îí íå äîëæåí áûòü òåêóùèì
\r
141 ::wglMakeCurrent(NULL, NULL);
\r
143 // Óäàëÿåì êîíòåêñò âîñïðîèçâåäåíèÿ
\r
145 ::wglDeleteContext(hrc);
\r
147 // Óäàëÿåì êîíòåêñò ðàáî÷åé îáëàñòè
\r
151 CView::OnDestroy();
\r
154 BOOL COpenGLView::SetPixelFormat(HDC hdc)
\r
156 // Çàïîëíÿåì ïîëÿ ñòðóêòóðû
\r
157 static PIXELFORMATDESCRIPTOR pfd = {
\r
158 sizeof(PIXELFORMATDESCRIPTOR), // ðàçìåð ñòðóêòóðû
\r
160 PFD_DRAW_TO_WINDOW | // ïîääåðæêà âûâîäà â îêíî
\r
161 PFD_SUPPORT_OPENGL | // ïîääåðæêà OpenGL
\r
162 PFD_DOUBLEBUFFER, // äâîéíàÿ áóôåðèçàöèÿ
\r
163 PFD_TYPE_RGBA, // öâåòà â ðåæèìå RGBA
\r
164 24, // 24-ðàçðÿäà íà öâåò
\r
165 0, 0, 0, 0, 0, 0, // áèòû öâåòà èãíîðèðóþòñÿ
\r
166 0, // íå èñïîëüçóåòñÿ àëüôà ïàðàìåòð
\r
167 0, // ñìåùåíèå öâåòîâ èãíîðèðóþòñÿ
\r
168 0, // áóôåð àêêóìóëÿòîðà íå èñïîëüçóåòñÿ
\r
169 0, 0, 0, 0, // áèòû àêêóìóëÿòîðà èãíîðèðóþòñÿ
\r
170 32, // 32-ðàçðÿäíûé áóôåð ãëóáèíû
\r
171 0, // áóôåð òðàôàðåòà íå èñïîëüçóåòñÿ
\r
172 0, // âñïîìîãàòåëüíûé áóôåð íå èñïîëüçóåòñÿ
\r
173 PFD_MAIN_PLANE, // îñíîâíîé ñëîé
\r
174 0, // çàðåçåðâèðîâàí
\r
175 0, 0, 0 // ìàñêè ñëîÿ èãíîðèðóþòñÿ
\r
180 // Ïîääåðæèâàåò ëè ñèñòåìà íåîáõîäèìûé ôîðìàò ïèêñåëåé?
\r
181 if((pixelFormat = ::ChoosePixelFormat(hdc, &pfd)) == 0){
\r
182 MessageBox("Ñ çàäàííûì ôîðìàòîì ïèêñåëåé ðàáîòàòü íåëüçÿ");
\r
186 if (::SetPixelFormat(hdc, pixelFormat, &pfd) == FALSE)
\r
188 MessageBox("Îøèáêà ïðè âûïîëíåíèè SetPixelFormat");
\r
195 BOOL COpenGLView::CreateGLContext(HDC hdc)
\r
198 // Ñîçäàåì êîíòåêñò âîñïðîèçâåäåíèÿ
\r
199 if((m_hrc = ::wglCreateContext(hdc)) == NULL)
\r
202 // Äåëàåì êîíòåêñò âîñïðîèçâåäåíèÿ òåêóùèì
\r
203 if(::wglMakeCurrent(hdc, m_hrc) == FALSE)
\r
209 void COpenGLView::OnSize(UINT nType, int cx, int cy)
\r
211 CView::OnSize(nType, cx, cy);
\r
216 glViewport(0, 0, cx, cy);
\r
219 /////////////////////////////////////////////////////////////////////////////
\r
220 // COpenGLView drawing
\r
222 void COpenGLView::OnDraw(CDC* pDC)
\r
224 CDocument* pDoc = GetDocument();
\r
225 ASSERT_VALID(pDoc);
\r
228 void COpenGLView::BeginScene()
\r
231 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
\r
234 void COpenGLView::EndScene()
\r
239 void COpenGLView::Swap()
\r
242 SwapBuffers(m_pDC->m_hDC);
\r
245 void COpenGLView::TrackBall(CPoint last, CPoint init, double& angle, double& x, double& y, double& z)
\r
247 Point3d end, start, out;
\r
248 double sum, len, norm;
\r
249 double pi = 3.1415926535;
\r
251 norm = (double)__min(m_width, m_height);
\r
253 start.x = (2*init.x-m_width)/norm;
\r
254 start.y = (m_height-2.*init.y)/norm;
\r
255 sum = start.x*start.x + start.y*start.y;
\r
256 if (sum < 1.) start.z = sqrt(1 - sum);
\r
259 end.x = (2.*last.x-m_width)/norm;
\r
260 end.y = (m_height-2.*last.y)/norm;
\r
261 sum = end.x*end.x + end.y*end.y;
\r
262 if (sum < 1.) end.z = sqrt(1 - sum);
\r
265 ASSERT(vector_length(start)*vector_length(end)>1.0e-30);
\r
266 angle = scalar_product(start,end)/(vector_length(start)*vector_length(end));
\r
268 if (angle<=-1) angle = -0.99999;
\r
269 if (angle>=1) angle = 0.99999;
\r
271 angle = acos(angle)*180./pi;
\r
272 out.x = vector_product_x(start,end);
\r
273 out.y = vector_product_y(start,end);
\r
274 out.z = vector_product_z(start,end);
\r
276 len = vector_length(out);
\r
288 void COpenGLView::SetOwnContext()
\r
298 m_pDC = new CClientDC(this);
\r
300 if (wglMakeCurrent(m_pDC->m_hDC, m_hrc))
\r
308 void COpenGLView::OnMouseMove(UINT nFlags, CPoint point)
\r
311 if(nFlags & MK_LBUTTON)
\r
313 if(nFlags & MK_SHIFT)
\r
315 /* Track translation */
\r
316 double x = point.x - m_mousePosition.x;
\r
317 double y = point.y - m_mousePosition.y;
\r
320 m_translate[0] += x;
\r
321 m_translate[1] += y;
\r
323 m_mousePosition = point;
\r
327 /* Track rotation */
\r
328 double x, y, z, angle;
\r
330 TrackBall(point, m_mousePosition, angle, x, y, z);
\r
331 m_mousePosition = point;
\r
333 glMatrixMode(GL_MODELVIEW);
\r
336 glRotated(angle, x, y, z);
\r
337 glMultMatrixd(m_rotate);
\r
338 glGetDoublev(GL_MODELVIEW_MATRIX, m_rotate);
\r
345 CView::OnMouseMove(nFlags, point);
\r
348 void COpenGLView::OnLButtonDown(UINT nFlags, CPoint point)
\r
350 m_mousePosition = point;
\r
351 CView::OnLButtonDown(nFlags, point);
\r
354 void COpenGLView::InitCameraPosition()
\r
356 for(int i = 0; i < 16; i++)
\r
357 m_rotate[i] = GLdouble(i/4 == i%4);
\r
358 for(i = 0; i < 3; i++)
\r
359 m_translate[i] = 0;
\r
362 void COpenGLView::DrawScene(CDC* pDC)
\r