CMapView::CMapView()
{
// TODO: 在此处添加构造代码
m_iClientHeight = 0;
m_iClientWidth = 0;
}
CMapView::~CMapView()
{
}
BOOL CMapView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return CView::PreCreateWindow(cs);
}
// CMapView 绘制
void CMapView::DrawInOpenGL(void)
{
// 设置视口
glViewport(0, 0, m_iClientWidth, m_iClientHeight);
// 设置投影矩阵(透视投影)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)m_iClientWidth/(GLfloat)m_iClientHeight, 1.0, 9999999.0);
// 设置模型视图矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//gluLookAt(0.0,0.0,0.0, 1.0,1.0,0.0, 0.0,1.0,0.0);
gluLookAt(m_fListDelta*m_iListCount/2.0, 4.0*maxZ, m_fRowDelta*m_iRowCount,
m_fListDelta*m_iListCount/2.0 , (maxZ+minZ)/2.0, -m_fRowDelta*m_iRowCount/2.0 ,
0.0, 1.0, 0.0);
}
void CMapView::OnDraw(CDC* pDC)
{
CMapDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
DrawInOpenGL();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 绘制场景
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
{
//绘制地形
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
DrawGLScene(); //绘制场景
}
glPopMatrix();
// 交换缓冲区
SwapBuffers(wglGetCurrentDC());
// TODO: 在此处为本机数据添加绘制代码
}
// CMapView 打印
void CMapView::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
AFXPrintPreview(this);
#endif
}
BOOL CMapView::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默认准备
return DoPreparePrinting(pInfo);
}
void CMapView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加额外的打印前进行的初始化过程
}
void CMapView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印后进行的清理过程
}
void CMapView::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
ClientToScreen(&point);
OnContextMenu(this, point);
}
void CMapView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}
// CMapView 诊断
#ifdef _DEBUG
void CMapView::AssertValid() const
{
CView::AssertValid();
}
void CMapView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMapDoc* CMapView::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMapDoc)));
return (CMapDoc*)m_pDocument;
}
// 计算两个向量的法线, pt2是中间点, 符合右手法则
void CMapView::CalcNormal(const VERTEX& pt1, const VERTEX& pt2, const VERTEX& pt3, NORMAL& nv)
{
double w0=pt1.x-pt2.x;
double w1=pt1.y-pt2.y;
double w2=pt1.z-pt2.z;
double v0=pt3.x-pt2.x;
double v1=pt3.y-pt2.y;
double v2=pt3.z-pt2.z;
double nx=(w1*v2-w2*v1);
double ny=(w2*v0-w0*v2);
double nz=(w0*v1-w1*v0);
double nr=(double)sqrt(nx*nx+ny*ny+nz*nz);
if(nr)
{
nv.n0=(float)-nx/nr;
nv.n1=(float)-ny/nr;
nv.n2=(float)-nz/nr;
}
else
{
nv.n0=0.0f;
nv.n1=0.0f;
nv.n2=1.0f;
}
}
//绘制场景
int CMapView::DrawGLScene(void)
{
TRIANGLE Point; // 顶点的临时 X, Y, Z的数值
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除 场景 和 深度缓冲
glLoadIdentity(); // 重置当前矩阵
// 逐个处理三角形
glColor3f( 0.0f, 1.0f, 0.0f);
for (int iRow = 0; iRow < m_iRowCount ; iRow++) // 遍历所有的点
{
for ( int iList = 0; iList <m_iListCount ; iList++)
{ NORMAL n;
glBegin(GL_TRIANGLES); // 开始绘制三角形
CalcNormal(m_PointData[iRow+1][iList],m_PointData[iRow][iList],m_PointData[iRow][iList+1], n);
glNormal3f(n.n0, n.n2, -n.n1);
glVertex3f( m_PointData[iRow][iList].x, m_PointData[iRow][iList].z, -m_PointData[iRow][iList].y);
glVertex3f( m_PointData[iRow+1][iList].x, m_PointData[iRow+1][iList].z, -m_PointData[iRow+1][iList].y);
glVertex3f( m_PointData[iRow][iList+1].x, m_PointData[iRow][iList+1].z, -m_PointData[iRow][iList+1].y);
glEnd(); // 三角形绘制结束
glBegin(GL_TRIANGLES); // 开始绘制三角形
CalcNormal(m_PointData[iRow+1][iList],m_PointData[iRow+1][iList+1],m_PointData[iRow][iList+1],n);
glNormal3f(n.n0, n.n2, -n.n1);
glVertex3f( m_PointData[iRow+1][iList].x, m_PointData[iRow+1][iList].z, -m_PointData[iRow+1][iList].y);
glVertex3f( m_PointData[iRow+1][iList+1].x, m_PointData[iRow+1][iList+1].z, -m_PointData[iRow+1][iList+1].y);
glVertex3f( m_PointData[iRow][iList+1 ].x, m_PointData[iRow][iList+1].z, -m_PointData[iRow][iList+1].y);
glEnd(); // 三角形绘制结束
}
}
glFlush();
return 0;
}
void CMapView::OnDestroy()
{
CView::OnDestroy();
// TODO: 在此处添加消息处理程序代码
// 释放资源
wglMakeCurrent(NULL, NULL);
wglDeleteContext(m_hRC);
delete m_pDC;
}
void CMapView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
m_iClientWidth = cx;
m_iClientHeight = cy;
// TODO: 在此处添加消息处理程序代码
}
bool CMapView::bSetDCPixelFormat(void)
{
// 设置像素格式
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // 结构的大小
1, // 结构的版本
PFD_DRAW_TO_WINDOW | // 在窗口(而不是位图)中绘图
PFD_SUPPORT_OPENGL | // 支持在窗口中进行OpenGL调用
PFD_DOUBLEBUFFER, // 双缓冲模式
PFD_TYPE_RGBA, // RGBA颜色模式
32, // 需要32位颜色
0, 0, 0, 0, 0, 0, // 不用于选择模式
0, 0, // 不用于选择模式
0, 0, 0, 0, 0, // 不用于选择模式
16, // 深度缓冲区的大小
0, // 在此不使用
0, // 在此不使用
0, // 在此不使用
0, // 在此不使用
0, 0, 0 // 在此不使用
};
// 选择一种与pfd所描述的最匹配的像素格式
int nPixelFormat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);
if(0 == nPixelFormat)
return false;
// 为设备环境设置像素格式
return SetPixelFormat(m_pDC->GetSafeHdc(), nPixelFormat, &pfd);
return TRUE;
}
int CMapView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
// 创建DC
m_pDC = new CClientDC(this);
ASSERT(m_pDC != NULL);
// 选择像素格式
if(!bSetDCPixelFormat()) return -1;
// 创建渲染环境, 并使它成为当前渲染环境
m_hRC = wglCreateContext(m_pDC->GetSafeHdc());
wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC);
return 0;
}