// SceneView.cpp : implementation of the CSceneView class // #include "stdafx.h" #include "3DExplore.h" #include "SceneView.h" #include "Mainfrm.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define REDRAW(cmd) cmd; Invalidate(FALSE); UpdateWindow(); UpdateControl(); ///////////////////////////////////////////////////////////////////////////// // CSceneView CSceneView::CSceneView() { ReadInput(); SetDefaults(); } CSceneView::~CSceneView() { } IMPLEMENT_DYNCREATE(CSceneView, CView) BEGIN_MESSAGE_MAP(CSceneView, CView) //{{AFX_MSG_MAP(CSceneView) ON_COMMAND(ID_ACCEL_R, OnAccelR) ON_COMMAND(ID_ACCEL_L, OnAccelL) ON_COMMAND(ID_ACCEL_DOWN, OnAccelDown) ON_COMMAND(ID_ACCEL_UP, OnAccelUp) ON_COMMAND(ID_ACCEL_SCALE_DOWN, OnAccelScaleDown) ON_COMMAND(ID_ACCEL_SCALE_UP, OnAccelScaleUp) ON_COMMAND(ID_ACCEL_ROTATE_OY_CW, OnAccelRotateOYCw) ON_COMMAND(ID_ACCEL_ROTATE_OY_ACW, OnAccelRotateOYAcw) ON_COMMAND(ID_ACCEL_ROTATE_OX_CW, OnAccelRotateOXCw) ON_COMMAND(ID_ACCEL_ROTATE_OX_ACW, OnAccelRotateOXAcw) ON_COMMAND(ID_ACCEL_ROTATE_OZ_ACW, OnAccelRotateOzACW) ON_COMMAND(ID_ACCEL_ROTATE_OZ_CW, OnAccelRotateOzCW) ON_BN_CLICKED(IDC_UPDATE, OnUpdate) ON_WM_CREATE() ON_BN_CLICKED(IDC_FIT, OnFit) ON_BN_CLICKED(IDC_CENTER, OnCenter) ON_WM_SIZE() ON_WM_ERASEBKGND() ON_COMMAND(IDM_RESTART, OnRestart) ON_COMMAND(ID_ACCEL_PERSPECTIVE_UP, OnAccelPerspectiveUp) ON_COMMAND(ID_ACCEL_PERSPECTIVE_DOWN, OnAccelPerspectiveDown) //}}AFX_MSG_MAP END_MESSAGE_MAP() void CSceneView::DrawScene() { static GLdouble red[3] = {0.8, 0.0, 0.0 } ; static GLdouble green[3] = {0.0, 0.75, 0.0} ; static GLdouble purple[3] = {1.0, 0.14, 0.6667} ; const GLdouble TransformM[] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, attr.offsetX, attr.offsetY, 0, 1 }; const GLdouble TransformP[] = { 1, 0, 0, attr.PerspectiveX, 0, 1, 0, attr.PerspectiveX, 0, 0, 1, attr.PerspectiveX, 0, 0, 0, 1, }; // Enable lighting calculations glEnable(GL_LIGHTING) ; OutputGlError("glEnable (GL_LIGHTING) ;") ; glEnable(GL_LIGHT0) ; OutputGlError("glEnable (GL_LIGHT0) ;") ; // Enable depth calculations glEnable(GL_DEPTH_TEST); OutputGlError("glEnable (GL_DEPTH_TEST);") ; // Clear the color and depth buffers glClearColor(0.0f, 0.0f, 0.0f, 0.0f) ; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set the material color to follow the current color glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE) ; glEnable(GL_COLOR_MATERIAL) ; GLfloat materialDiffuse[] = { 0.6, 0.6, 0.6, 1.0 }; GLfloat materialSpecular[] = { 1.0 ,1.0, 1.0, 1.0 }; GLfloat materialShininess[] = { 100 }; /* setup material settings */ glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular ); glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess ); /* enable lighting */ glEnable( GL_LIGHTING ); glEnable( GL_LIGHT0 ); glDepthFunc( GL_LEQUAL ); glEnable( GL_DEPTH_TEST ); glEnable( GL_AUTO_NORMAL ); glEnable( GL_NORMALIZE ); glMatrixMode(GL_PROJECTION); OutputGlError("MatrixMode") ; glLoadIdentity(); glMultMatrixd( TransformP ); glMatrixMode(GL_MODELVIEW); OutputGlError("MatrixMode") ; glLoadIdentity(); glViewport( 0, 0, attr.m_cxClient, attr.m_cyClient); glMultMatrixd( TransformM ); glScaled(attr.scaleX * 0.5, attr.scaleY * 0.5, attr.scaleZ * 0.5); glRotated(attr.angleX, 1.0, 0.0, 0.0); glRotated(attr.angleY, 0.0, 1.0, 0.0); glRotated(attr.angleZ, 0.0, 0.0, 1.0); glColor3dv(purple) ; glCallList(Figure) ; glFlush(); } void CSceneView::PrepareScene() { Plane *pp = pPlane; Curve *pc = pCurve; Surface *ps = pSurface; CClientDC dc(this) ; BOOL bResult = wglMakeCurrent(dc.m_hDC, m_hrc); if (!bResult) { TRACE("wglMakeCurrent Failed %x\r\n", GetLastError() ) ; } glNewList(Figure, GL_COMPILE); do { glBegin(GL_POLYGON); glNormal3d(pp->normal.x, pp->normal.y, pp->normal.z); for(int i = 0; i < pp->N; i++) glVertex3d( pp->attr[i].x, pp->attr[i].y, pp->attr[i].z ); glEnd(); }while( pp = pp->next ); GLfloat knots[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; while( pc->next) { GLfloat m[4][4]; for( int i=0; i < 4; i++) { m[i][0] = pc->attr[i].x; m[i][1] = pc->attr[i].y; m[i][2] = pc->attr[i].z; m[i][3] = pc->attr[i].h; } GLUnurbsObj *nurbCurve; nurbCurve = gluNewNurbsRenderer(); gluBeginCurve(nurbCurve); glNormal3d(-1,-1,-1); gluNurbsCurve(nurbCurve, 8, knots, 4, (GLfloat *)m, 4, GL_MAP1_VERTEX_4); gluEndCurve(nurbCurve); pc = pc->next; }; while( ps->next) { GLUnurbsObj *nurbSurface; nurbSurface = gluNewNurbsRenderer(); gluNurbsProperty( nurbSurface, GLU_SAMPLING_TOLERANCE, 100.0 ); gluNurbsProperty( nurbSurface, GLU_DISPLAY_MODE, GLU_FILL ); GLfloat m[4][4][4]; for( int u=0; u < 4; u++) { for( int v=0; v < 4; v++) { int index = u * 4 + v; m[u][v][0] = ps->attr[index].x; m[u][v][1] = ps->attr[index].y; m[u][v][2] = ps->attr[index].z; m[u][v][3] = ps->attr[index].h; } } gluBeginSurface( nurbSurface ); gluNurbsSurface( nurbSurface, 8, knots, 8, knots, 4 * 4, 4, (GLfloat *)m, 4, 4, GL_MAP2_VERTEX_4 ); gluEndSurface( nurbSurface ); ps = ps->next; }; glEndList(); gluPerspective( 45, attr.m_cxClient / attr.m_cyClient, 2, 5); wglMakeCurrent(NULL, NULL) ; } ///////////////////////////////////////////////////////////////////////////// // CSceneView message handlers BOOL CSceneView::PreCreateWindow(CREATESTRUCT& cs) { if (!CView::PreCreateWindow(cs)) return FALSE; cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; cs.dwExStyle |= WS_EX_CLIENTEDGE; cs.style &= ~WS_BORDER; cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL); return TRUE; } void CSceneView::OnAccelR() { REDRAW( attr.offsetX += attr.offsetStep); } void CSceneView::OnAccelL() { REDRAW( attr.offsetX -= attr.offsetStep); } void CSceneView::OnAccelDown() { REDRAW( attr.offsetY -= attr.offsetStep ); } void CSceneView::OnAccelUp() { REDRAW( attr.offsetY += attr.offsetStep ); } void CSceneView::OnAccelScaleUp() { REDRAW( attr.scaleX *= attr.scaleStep; attr.scaleY *= attr.scaleStep; attr.scaleZ *= attr.scaleStep; ); } void CSceneView::OnAccelScaleDown() { REDRAW( attr.scaleX /= attr.scaleStep; attr.scaleY /= attr.scaleStep; attr.scaleZ /= attr.scaleStep; ); } void CSceneView::OnAccelRotateOYCw() { if(attr.angleY >= 360) attr.angleY -= 360; REDRAW( attr.angleY += attr.angleStep ); } void CSceneView::OnAccelRotateOYAcw() { if(attr.angleY <= -360) attr.angleY += 360; REDRAW( attr.angleY -= attr.angleStep ); } void CSceneView::OnAccelRotateOXCw() { if(attr.angleX >= 360) attr.angleX -= 360; REDRAW( attr.angleX += attr.angleStep ); } void CSceneView::OnAccelRotateOXAcw() { if(attr.angleX <= -360) attr.angleX += 360; REDRAW( attr.angleX -= attr.angleStep ); } void CSceneView::OnAccelRotateOzACW() { if(attr.angleZ <= -360) attr.angleZ += 360; REDRAW( attr.angleZ -= attr.angleStep ); } void CSceneView::OnAccelRotateOzCW() { if(attr.angleZ >= 360) attr.angleZ -= 360; REDRAW( attr.angleZ += attr.angleStep ); } void CSceneView::OnDraw(CDC* pDC) { CSceneDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); BOOL bResult = wglMakeCurrent(pDC->m_hDC, m_hrc); if (!bResult) { TRACE("wglMakeCurrent Failed %x\r\n", GetLastError() ) ; } // Draw DrawScene() ; //Swap Buffers SwapBuffers(pDC->m_hDC) ; SetBkMode(pDC->m_hDC, TRANSPARENT); SetTextColor(pDC->m_hDC, RGB(255,240,255)); RECT rc = { 0, 0, attr.m_cxClient, 50 }; DrawText(pDC->m_hDC, "Indigo Interactive... find us on the Web: http://www.kulios.com", -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); wglMakeCurrent(NULL, NULL) ; } void CSceneView::OnInitialUpdate() { TRACE0("OnInitialUpdate\r\n") ; PrepareScene() ; CView::OnInitialUpdate(); } #define SEEKARGS(buffer) in.getline(buffer, 255, '('); #define SEEKBRA(buffer) in.getline(buffer, 255, '{'); #define SEEKKET(buffer) CHAR t; in >> t; if(t == '}') break; else in.putback(t); void CSceneView::ReadInput() { Plane *pp; Curve *pc; Surface *ps; pPlane = pp = new Plane; pCurve = pc = new Curve; pSurface = ps = new Surface; ifstream in("input.txt"); while(!in.eof()) { CHAR buffer[255], type; INT i; type=' '; in >> type; switch(type) { case 'P': SEEKARGS(buffer); in >> pp->normal.x >> pp->normal.y >> pp->normal.z; SEEKBRA(buffer); for( i = 0;; i++) { in >> pp->attr[i].x >> pp->attr[i].y >> pp->attr[i].z >> pp->attr[i].h; SEEKKET(buffer); } pp->N = ++i; pp->next = new Plane; pp = pp->next; break; case 'C': SEEKBRA(buffer); for( i = 0; i < 4; i++) { in >> pc->attr[i].x >> pc->attr[i].y >> pc->attr[i].z >> pc->attr[i].h; SEEKKET(buffer); } pc->N = ++i; pc->next = new Curve; pc = pc->next; break; case 'S': SEEKBRA(buffer); for( i = 0; i < 16; i++) { in >> ps->attr[i].x >> ps->attr[i].y >> ps->attr[i].z >> ps->attr[i].h; SEEKKET(buffer); } ps->N = ++i; ps->next = new Surface; ps = ps->next; break; default: break; } } pp->next = 0; pc->next = 0; ps->next = 0; } void CSceneView::SetDefaults() { attr.offsetX = 0; attr.offsetY = 0; attr.offsetStep = 0.01; attr.scaleStep = 1.1; attr.scaleX = 0.5; attr.scaleY = 0.5; attr.scaleZ = 0.5; attr.angleX = 230; attr.angleY = 5; attr.angleZ = 57; attr.angleStep = 1; attr.PerspectiveX = 0; attr.PerspectiveY = 0; attr.PerspectiveZ = 0; attr.PerspectiveStep = 0.1; firstRun = 1; } void CSceneView::OnUpdate() { CString ChScaleX, ChScaleY; pControl->GetDlgItemText(IDC_EDIT_STRETCH_X, ChScaleX); pControl->GetDlgItemText(IDC_EDIT_STRETCH_Y, ChScaleY); CString ChOffsetX, ChOffsetY; pControl->GetDlgItemText(IDC_EDIT_OFFSET_X, ChOffsetX); pControl->GetDlgItemText(IDC_EDIT_OFFSET_Y, ChOffsetY); CString ChPerspectiveX; pControl->GetDlgItemText(IDC_EDIT_PERSPECTIVE, ChPerspectiveX); REDRAW( attr.offsetX = atof(ChOffsetX); attr.offsetY = atof(ChOffsetY); attr.scaleX = atof(ChScaleX); attr.scaleY = atof(ChScaleY); attr.angleX = pControl->GetDlgItemInt(IDC_EDIT_ROTATE_OX); attr.angleY = pControl->GetDlgItemInt(IDC_EDIT_ROTATE_OY); attr.angleZ = pControl->GetDlgItemInt(IDC_EDIT_ROTATE_OZ); attr.PerspectiveX = atof(ChPerspectiveX); ); } int CSceneView::OnCreate(LPCREATESTRUCT lpCreateStruct) { TRACE0("OnCreate\r\n") ; if (CView::OnCreate(lpCreateStruct) == -1) return -1; if(!m_Control.Create(this, IDD_ACTION, CBRS_LEFT|CBRS_TOOLTIPS|CBRS_FLYBY, IDD_ACTION)) { TRACE0("Failed to create control bar\n"); return -1; // fail to create } pControl = &((CMainFrame *)GetOwner())->m_Control; CClientDC dc(this) ; PIXELFORMATDESCRIPTOR pfd ; memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR)) ; pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1 ; // Version number pfd.dwFlags = PFD_DOUBLEBUFFER | // Use double buffer PFD_SUPPORT_OPENGL | // Use OpenGL PFD_DRAW_TO_WINDOW ; // Pixel format is for a window. pfd.iPixelType = PFD_TYPE_RGBA ; pfd.cColorBits = 24; // 8-bit color pfd.cDepthBits = 32 ; // 32-bit depth buffer pfd.iLayerType = PFD_MAIN_PLANE ; // Layer type int nPixelFormat = ChoosePixelFormat(dc.m_hDC, &pfd); if (nPixelFormat == 0) { TRACE("ChoosePixelFormat Failed %d\r\n",GetLastError()) ; return -1 ; } TRACE("Pixel Format %d\r\n", nPixelFormat) ; BOOL bResult = SetPixelFormat(dc.m_hDC, nPixelFormat, &pfd); if (!bResult) { TRACE("SetPixelFormat Failed %d\r\n",GetLastError()) ; return -1 ; } // // Create a rendering context. // m_hrc = wglCreateContext(dc.m_hDC); if (!m_hrc) { TRACE("wglCreateContext Failed %x\r\n", GetLastError()) ; return -1; } // Create the palette CreateRGBPalette(dc.m_hDC) ; return 0; } void CSceneView::UpdateControl() { CString ChOffsetX; ChOffsetX.Format("%f", attr.offsetX); pControl->SetDlgItemText(IDC_EDIT_OFFSET_X, (LPCTSTR)ChOffsetX); CString ChOffsetY; ChOffsetY.Format("%f", attr.offsetY); pControl->SetDlgItemText(IDC_EDIT_OFFSET_Y, (LPCTSTR)ChOffsetY); pControl->SetDlgItemInt(IDC_EDIT_ROTATE_OX, (int)attr.angleX); pControl->SetDlgItemInt(IDC_EDIT_ROTATE_OY, (int)attr.angleY); pControl->SetDlgItemInt(IDC_EDIT_ROTATE_OZ, (int)attr.angleZ); CString ChScaleX; ChScaleX.Format("%f", attr.scaleX); CString ChScaleY; ChScaleY.Format("%f", attr.scaleY); pControl->SetDlgItemText(IDC_EDIT_STRETCH_X, (LPCTSTR) ChScaleX); pControl->SetDlgItemText(IDC_EDIT_STRETCH_Y, (LPCTSTR) ChScaleY); CString ChPerspectiveX; ChPerspectiveX.Format("%f", attr.PerspectiveX); pControl->SetDlgItemText(IDC_EDIT_PERSPECTIVE, (LPCTSTR)ChPerspectiveX); pControl->UpdateWindow(); } void CSceneView::OnFit() { CClientDC dc(this); /* if( rect.right < rect.bottom ) { REDRAW( attr.scaleX *= 0.97 * rect.right / (float)(Rightmost - Leftmost); attr.scaleY = attr.scaleX; ); } else { REDRAW( attr.scaleY *= 0.97 * rect.bottom / (float)(Top - Bottom); attr.scaleX = attr.scaleY; ); } REDRAW( attr.offsetX -= ( Rightmost - (Rightmost - Leftmost) / 2 ); attr.offsetY -= Top - (Top - Bottom) / 2; ); */ } void CSceneView::OnCenter() { REDRAW( attr.offsetX -= Rightmost - (Rightmost - Leftmost) / 2; attr.offsetY -= Top - (Top - Bottom) / 2; ); } void CSceneView::OnSize(UINT nType, int cx, int cy) { attr.m_cxClient = cx; attr.m_cyClient = cy; TRACE0("OnSize\r\n") ; CView::OnSize(nType, cx, cy); if ( (cx <= 0) || (cy <= 0) ) return ; CClientDC dc(this) ; // // Make the rendering context m_hrc current // BOOL bResult = wglMakeCurrent(dc.m_hDC, m_hrc); if (!bResult) { TRACE("wglMakeCurrent Failed %x\r\n", GetLastError() ) ; return ; } // // Set up the mapping of 3-space to screen space // glMatrixMode(GL_PROJECTION); OutputGlError("MatrixMode") ; glLoadIdentity(); glViewport(0, 0, cx, cy); // // No rendering context will be current. // wglMakeCurrent(NULL, NULL); } void CSceneView::OutputGlError(char* label) { GLenum errorno = glGetError() ; if (errorno != GL_NO_ERROR) TRACE("%s had error: #(%d) %s\r\n", label, errorno, gluErrorString(errorno)) ; } unsigned char CSceneView::m_threeto8[8] = { 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377 }; unsigned char CSceneView::m_twoto8[4] = { 0, 0x55, 0xaa, 0xff }; unsigned char CSceneView::m_oneto8[2] = { 0, 255 }; int CSceneView::m_defaultOverride[13] = { 0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91 }; PALETTEENTRY CSceneView::m_defaultPalEntry[20] = { { 0, 0, 0, 0 }, //0 { 0x80,0, 0, 0 }, { 0, 0x80,0, 0 }, { 0x80,0x80,0, 0 }, { 0, 0, 0x80, 0 }, { 0x80,0, 0x80, 0 }, { 0, 0x80,0x80, 0 }, { 0xC0,0xC0,0xC0, 0 }, //7 { 192, 220, 192, 0 }, //8 { 166, 202, 240, 0 }, { 255, 251, 240, 0 }, { 160, 160, 164, 0 }, //11 { 0x80,0x80,0x80, 0 }, //12 { 0xFF,0, 0, 0 }, { 0, 0xFF,0, 0 }, { 0xFF,0xFF,0, 0 }, { 0, 0, 0xFF, 0 }, { 0xFF,0, 0xFF, 0 }, { 0, 0xFF,0xFF, 0 }, { 0xFF,0xFF,0xFF, 0 } //19 }; unsigned char CSceneView::ComponentFromIndex(int i, UINT nbits, UINT shift) { unsigned char val; val = (unsigned char) (i >> shift); switch (nbits) { case 1: val &= 0x1; return m_oneto8[val]; case 2: val &= 0x3; return m_twoto8[val]; case 3: val &= 0x7; return m_threeto8[val]; default: return 0; } } BOOL CSceneView::CreateRGBPalette(HDC hDC) { // // Check to see if we need a palette // PIXELFORMATDESCRIPTOR pfd; int n = GetPixelFormat(hDC); DescribePixelFormat(hDC, n, sizeof(PIXELFORMATDESCRIPTOR), &pfd); if (!(pfd.dwFlags & PFD_NEED_PALETTE)) return FALSE ; TRACE0("Creating palette\r\n") ; // allocate a log pal and fill it with the color table info LOGPALETTE* pPal = (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)); if (!pPal) { TRACE("Out of memory for logpal"); return FALSE; } pPal->palVersion = 0x300; // Windows 3.0 pPal->palNumEntries = 256; // table size // // Create RGB Palette // ASSERT( pfd.cColorBits == 8) ; n = 1 << pfd.cColorBits; for (int i=0; ipalPalEntry[i].peRed = ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift); pPal->palPalEntry[i].peGreen = ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift); pPal->palPalEntry[i].peBlue = ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift); pPal->palPalEntry[i].peFlags = 0; } // // Fix up color table with system colors. // if ((pfd.cColorBits == 8) && (pfd.cRedBits == 3) && (pfd.cRedShift == 0) && (pfd.cGreenBits == 3) && (pfd.cGreenShift == 3) && (pfd.cBlueBits == 2) && (pfd.cBlueShift == 6) ) { for (int j = 1 ; j <= 12 ; j++) pPal->palPalEntry[m_defaultOverride[j]] = m_defaultPalEntry[j]; } // Delete any existing GDI palette if (m_pPal) delete m_pPal ; m_pPal = new CPalette ; BOOL bResult = m_pPal->CreatePalette(pPal); free (pPal); return bResult; } BOOL CSceneView::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default return FALSE; } void CSceneView::OnRestart() { SetDefaults(); ReadInput(); REDRAW(); } void CSceneView::OnAccelPerspectiveUp() { REDRAW( attr.PerspectiveX+=attr.PerspectiveStep ); } void CSceneView::OnAccelPerspectiveDown() { REDRAW( attr.PerspectiveX-=attr.PerspectiveStep ); }