// 3D.cpp : implementation file
//
#include "stdafx.h"
#include "Open_GL_CV.h"
#include "3D.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// C3D

IMPLEMENT_DYNCREATE(C3D, CView)

C3D::C3D()
{
	eye[0] = 0.;
	eye[1] = 0.;
	eye[2] = 3.;
	center[0] = 0.;
	center[1] = 0.;
	center[2] = 0.;
	m_xPos=0.;
	m_yPos=0.;
	m_zPos=0.;
	rot[0] = 0.;
	rot[1] = 0.;
	rot[2] = 0.;
	mouseX = 0;
	mouseY = 0;
	zoomFactor=1.0f;
}

C3D::~C3D()
{
}


BEGIN_MESSAGE_MAP(C3D, CView)
	//{{AFX_MSG_MAP(C3D)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSEWHEEL()
	ON_WM_RBUTTONDOWN()
	ON_WM_SIZE()
	ON_WM_MOVE()
	ON_WM_KEYDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// C3D drawing

void C3D::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	
	::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glLoadIdentity();
	
	gluLookAt(eye[0], eye[1], eye[2], center[0], center[1], center[2], 0, 1, 0);
	
	glTranslatef(m_xPos,m_yPos,m_zPos);
	
 	glRotatef(rot[0], 1.0f, 0.0f, 0.0f);
 	glRotatef(rot[1], 0.0f, 1.0f, 0.0f);
 	glRotatef(rot[2], 0.0f, 0.0f, 1.0f);
	
	glScalef(zoomFactor, zoomFactor, zoomFactor);
/*		
	glBegin(GL_LINES);
		glColor3f(1.0,0.0,0.0);
		glVertex3f(0,0,0);
		glVertex3f(1,0,0);
		glColor3f(0.0,1.0,0.0);
		glVertex3f(0,0,0);
		glVertex3f(0,1,0);
		glColor3f(0.0,0.0,1.0);
		glVertex3f(0,0,0);
		glVertex3f(0,0,1);
	glEnd();
*/	
	RenderScene();
	::glFinish();
	::SwapBuffers( m_pDC->GetSafeHdc());
}

/////////////////////////////////////////////////////////////////////////////
// C3D diagnostics

#ifdef _DEBUG
void C3D::AssertValid() const
{
	CView::AssertValid();
}

void C3D::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// C3D message handlers

int C3D::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
	return -1;
	
	// TODO: Add your specialized creation code here
	InitializeOpenGL();
	return 0;
}

void C3D::OnDestroy() 
{
	CView::OnDestroy();
	
	// TODO: Add your message handler code here
	if(::wglMakeCurrent(0,0)==FALSE)
	{
		MessageBox("Could not make RC non-current");
	}
	if(::wglDeleteContext(m_hRC)==FALSE)
	{
		MessageBox("Could not delete RC");
	}
	if(m_pDC)
	{
		delete m_pDC;
	}
	m_pDC=NULL;
}

BOOL C3D::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	
	//return CView::OnEraseBkgnd(pDC);
	return TRUE;
}

void C3D::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if((nFlags&MK_RBUTTON)==MK_RBUTTON) 
	{
		rot[1] -= (mouseX - point.x);
		rot[0] += (mouseY - point.y);
		mouseX = point.x;
		mouseY = point.y;
		Invalidate();
	}
	CView::OnMouseMove(nFlags, point);
}

BOOL C3D::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	// TODO: Add your message handler code here and/or call default
	if(zDelta>=0)
		OnViewZoomOut(); 
	else
		OnViewZoomIn(); 
	return CView::OnMouseWheel(nFlags, zDelta, pt);
}

void C3D::OnRButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	mouseX=point.x;
	mouseY=point.y;
	CView::OnRButtonDown(nFlags, point);
}

void C3D::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
	GLdouble aspect_ratio;
	if(0>=cx || 0>=cy)
	{
		return;
	}
	::glViewport(0, 0, cx, cy);
	aspect_ratio= (GLdouble)cx/(GLdouble)cy;

	::glMatrixMode(GL_PROJECTION);
	::glLoadIdentity();

	::gluPerspective(45.0f, (GLfloat)cx/cy, 0.01f, 1000.f);
//	glOrtho(-330,330,-330,330,-100,1000);
	::glMatrixMode(GL_MODELVIEW);
	::glLoadIdentity();
}

void C3D::OnMove(int x, int y) 
{
	CView::OnMove(x, y);
	
	// TODO: Add your message handler code here
	
}

void C3D::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	// TODO: Add your message handler code here and/or call default
	
	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void C3D::OnViewZoomIn()
{
	zoomFactor *= 1.05;
	Invalidate();
}

void C3D::OnViewZoomOut()
{
	zoomFactor *= 0.95;
	Invalidate();
}

BOOL C3D::SetupPixelFormat()
{
static PIXELFORMATDESCRIPTOR pfd = 
	{
        sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
        1,                              // version number
        PFD_DRAW_TO_WINDOW |            // support window
        PFD_SUPPORT_OPENGL |		    // support OpenGL
        PFD_DOUBLEBUFFER,				// double buffered
        PFD_TYPE_RGBA,                  // RGBA type
        24,                             // 24-bit color depth
        0, 0, 0, 0, 0, 0,               // color bits ignored
        0,                              // no alpha buffer
        0,                              // shift bit ignored
        0,                              // no accumulation buffer
        0, 0, 0, 0,                     // accum bits ignored
        16,                             // 16-bit z-buffer
        0,                              // no stencil buffer
        0,                              // no auxiliary buffer
        PFD_MAIN_PLANE,                 // main layer
        0,                              // reserved
        0, 0, 0                         // layer masks ignored
    };
    
    int m_nPixelFormat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);

	if ( m_nPixelFormat == 0 )
	{
       return FALSE;
	}

    if ( ::SetPixelFormat(m_pDC->GetSafeHdc(), m_nPixelFormat, &pfd) == FALSE)
    {
       return FALSE;
	}
    return TRUE;
}

BOOL C3D::InitializeOpenGL()
{
	//Get a DC for the Client Area
	m_pDC = new CClientDC(this);

	//Failure to Get DC
	if(m_pDC == NULL)
	{
		MessageBox("Error Obtaining DC");
		return FALSE;
	}

	//Failure to set the pixel format
	if(!SetupPixelFormat())
	{
		return FALSE;
	}

	//Create Rendering Context
	m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc());

	//Failure to Create Rendering Context
	if(m_hRC == 0)
	{
		MessageBox("Error Creating RC");
		return FALSE;
	}

	//Make the RC Current
	if(::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC)==FALSE)
	{
		MessageBox("Error making RC Current");
		return FALSE;
	}

	//Specify Black as the clear color
//	::glClearColor(0.92549f, 0.91373f, 0.84706f, 0.0f);
	::glClearColor(0.75f, 0.75f, 0.75f, 0.0f);

	//Specify Depth Testing
	::glClearDepth(1.0f);

	//Enable Depth Testing
	::glEnable(GL_DEPTH_TEST);

	return TRUE;
}

void C3D::RenderScene()
{
	glColor3f(1.0,0.,0.);
	glBegin(GL_LINES);
	glVertex3f(0,0,0);
	glVertex3f(0,1,0);
	glEnd();
}
