⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scene.cpp

📁 基于NEHE第48课的程序,改为MFC下运行.运用轨迹球技术,初学者值得参考
💻 CPP
字号:
//Version 1.1c
//Code by Phil.Z
//Date 2007-12-28

#include "stdafx.h"
#include "Scene.h"
#include "Figure.h"



#include <cmath>

const double PI = 3.1415926;

Scene::Scene(CWnd *pWnd)
:m_pWnd(pWnd),
 m_fXRot(0),m_fYRot(0),
 m_bLight(false),
 m_pFigure(0),
 m_pCurFigure(0),
 m_fWalkDistance(0.5f),
 m_fXPos(0.0f),
 m_fZPos(0.0f)
{
	m_afBkColor[0] = 0.0f;
	m_afBkColor[1] = 0.0f;
	m_afBkColor[2] = 0.0f;
	m_afBkColor[3] = 0.0f;
}

Scene::~Scene()
{
	while (m_pFigure)
	{
		FigureNode *p = m_pFigure;
		m_pFigure = m_pFigure->next;
		delete p->figure;
		delete p;
	}
}

void Scene::SetParam(float *initList)
{
	m_fXRot = initList[0];
	m_fYRot = initList[1];
	m_bLight = initList[2];
	for (int i = 0;i < 4;i++)
		m_afBkColor[i] = initList[i + 3];
	for (i = 0;i < 8;i++)
		m_afLightColor[i] = initList[i + 7];
	UpdateLightState();
}

void Scene::InitGLScene()
{
	glClearColor(m_afBkColor[0],m_afBkColor[1],m_afBkColor[2],m_afBkColor[3]);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LINE_SMOOTH);
	glEnable(GL_POINT_SMOOTH);
	glEnable(GL_POLYGON_SMOOTH);
	UpdateLightState();
}

void Scene::ResizeGLScene(float width,float height)
{
	float aspect;
	if (height == 0)
		aspect = 1;
	else
		aspect = width / height;
	glViewport(0,0,width,height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45,aspect,0.1,400);
	glMatrixMode(GL_MODELVIEW);
}

void Scene::DrawGLScene()
{
	//初始化场景为当前的视角和位置
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glTranslatef(0,0,-30);
	glTranslatef(m_fXPos,0,m_fZPos);
	glRotatef(m_fXRot,1,0,0);
	glRotatef(m_fYRot,0,1,0);
	if (m_bLight)
		glLightfv(GL_LIGHT0,GL_POSITION,m_afLightPos);
		
		
	//绘制链表当中的各个图形
	FigureNode *p = m_pFigure;
	while (p)
	{
		p->figure->Display();
		p = p->next;
	}
	
	glFinish();
	
}

bool Scene::NewFigure(int FigureClass,float *initList)
{
	FigureNode *p = new FigureNode;
	if (!p)
		return false;

	switch (FigureClass)
	{
	case F2D_POINT:
		p->figure = new Point(initList);
		break;
	case F2D_LINE:
		p->figure = new Line(initList);
		break;
	case F2D_RECT:
		p->figure = new Rect(initList);
		break;
	case F2D_CIRCLE:
		p->figure = new Circle(initList);
		break;
	case F3D_CUBE:
		p->figure = new Cube(initList);
		break;
	case F3D_SPHERE:
		p->figure = new Sphere(initList);
		break;
	case F3D_CYLINDER:
		p->figure = new Cylinder(initList);
		break;
	case F3D_DISK:
		p->figure = new Disk(initList);
		break;
	}

	if (!p->figure)
		return false;

	p->prior = NULL;

	if (!m_pFigure)			//新节点插入到链表头部
	{
		p->next = 0;
		m_pFigure = p;
	}
	else
	{
		p->next = m_pFigure;
		m_pFigure->prior = p;
		m_pFigure = p;
	}
	return true;
}

bool Scene::DeleteSelFigure()
{
	if (!IsCurSelected())
		return false;
	if (m_pCurFigure == m_pFigure)
	{
		m_pFigure = m_pFigure->next;
		if (m_pFigure)
			m_pFigure->prior = NULL;
	}
	else
	{
		if (m_pCurFigure->prior)
			m_pCurFigure->prior->next = m_pCurFigure->next;
		if (m_pCurFigure->next)
			m_pCurFigure->next->prior = m_pCurFigure->prior;
	}
	delete m_pCurFigure->figure;
	delete m_pCurFigure;
	m_pCurFigure = 0;

	m_pWnd->Invalidate();
	return true;
}

void Scene::SetSceneLight(bool bLight)
{
	m_bLight = bLight;
	UpdateLightState();
}

void Scene::SetSceneLight(int LightParam,float * value)
{
	int i;
	switch (LightParam)
	{
	case LP_AMBIENT:
		for (i = 0;i < 4;i++)
			m_afLightColor[i] = value[i];
		break;
	case LP_DIFFUSE:
		for (i = 0;i < 4;i++)
			m_afLightColor[i + 4] = value[i];
		break;
	case LP_POSITION:
		for (i = 0;i < 4;i++)
			m_afLightPos[i] = value[i];
		break;
	}
	UpdateLightState();
}

void Scene::SetSceneBkColor(float *value)
{
	for (int i = 0;i < 4;i++)
		m_afBkColor[i] = value[i];
	glClearColor(m_afBkColor[0],m_afBkColor[1],m_afBkColor[2],m_afBkColor[3]);
	m_pWnd->Invalidate();
}

void Scene::SetSceneRot(int RotCrood,float *value)
{
	switch (RotCrood)
	{
	case RC_XROT:
		m_fXRot = *value;
		break;
	case RC_YROT:
		m_fYRot = *value;
		break;
	case RC_XANDY:
		m_fXRot = value[0];
		m_fYRot = value[1];
		break;
	}
	m_pWnd->Invalidate();
}

void Scene::UpdateLightState()
{
	if (m_bLight)
	{
		glLightModelfv(GL_LIGHT_MODEL_AMBIENT,m_afLightColor);
		glLightfv(GL_LIGHT0,GL_DIFFUSE,&m_afLightColor[4]);
		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);
		glEnable(GL_COLOR_MATERIAL);
	}
	else
	{
		glDisable(GL_LIGHT0);
		glDisable(GL_LIGHTING);
		glDisable(GL_COLOR_MATERIAL);
	}
}

void Scene::SetDistance(float StepDistance)
{
	//限制步长在0.5到5之间
	m_fWalkDistance = StepDistance;
	if (m_fWalkDistance < 0.05f)
		m_fWalkDistance = 0.05f;
	if (m_fWalkDistance > 5.0f)
		m_fWalkDistance = 5.0f;
}

float Scene::GetDistance() const
{
	return m_fWalkDistance;
}

void Scene::Move(unsigned int Direction)
{
	//算法是将移动的距离分解到X/Z两个方向上
	switch (Direction)
	{
	case MV_FORWARD:
		m_fXPos += (float)sin(m_fYRot * PI / 180.0) * m_fWalkDistance;
		m_fZPos += (float)cos(m_fYRot * PI / 180.0) * m_fWalkDistance;
		break;
	case MV_BACK:
		m_fXPos -= (float)sin(m_fYRot * PI / 180.0) * m_fWalkDistance;
		m_fZPos -= (float)cos(m_fYRot * PI / 180.0) * m_fWalkDistance;
		break;
	case MV_LEFT:
		m_fXPos += (float)cos(m_fYRot * PI / 180) * m_fWalkDistance;
		m_fZPos -= (float)sin(m_fYRot * PI / 180) * m_fWalkDistance;
		break;
	case MV_RIGHT:
		m_fXPos -= (float)cos(m_fYRot * PI / 180) * m_fWalkDistance;
		m_fZPos += (float)sin(m_fYRot * PI / 180) * m_fWalkDistance;
		break;
	default:
		return;
	}
	m_pWnd->Invalidate();
}

void Scene::SetPick(int xMousePos,int yMousePos)
{
	GLint viewport[4];
	const int BUFFERSIZE = 128;
	GLuint selbuffer[BUFFERSIZE];
	glGetIntegerv(GL_VIEWPORT,viewport);
	glSelectBuffer(BUFFERSIZE,selbuffer);
	glRenderMode(GL_SELECT);
	glInitNames();
	glPushName(0);
	float aspect = 1;
	if (viewport[2])
		aspect = (float)viewport[2] / (float)viewport[3];
	if (m_pCurFigure)
		m_pCurFigure = 0;

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
		glLoadIdentity();
		gluPickMatrix((GLdouble)xMousePos,(GLdouble)viewport[3] - yMousePos,1,1,viewport);
		gluPerspective(45,aspect,1,400);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0,0,-30);
		glTranslatef(m_fXPos,0,m_fZPos);
		glRotatef(m_fXRot,1,0,0);
		glRotatef(m_fYRot,0,1,0);
		FigureNode *p = m_pFigure;
		int nName = 1;
		while (p)
		{
			glLoadName(nName);
			p->figure->Display();
			p->figure->SetName(nName);
			p->figure->SetCurStatue(false);
			p = p->next;
			nName++;
		}
		glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glFinish();
	GLuint nSel = glRenderMode(GL_RENDER);
	p = m_pFigure;
	
	if (nSel)
	{
		while (p)
		{
			if ((p->figure->GetName()) == selbuffer[3])
			{
				p->figure->SetCurStatue(true);
				m_pCurFigure = p;
			}
			p = p->next;
		}
	}
	m_pWnd->Invalidate();
}

bool Scene::IsCurSelected()
{
	return m_pCurFigure;
}

void Scene::MoveCurFigure(int Coord,int OP,int value)
{
	if (!IsCurSelected())
		return;
	float FigurePos[3];
	m_pCurFigure->figure->GetPos(FigurePos);
	if (OP == OP_MINUS)
		value = -value;
	switch (Coord)
	{
	case FP_XPOS:
		FigurePos[0] += value;
		break;
	case FP_YPOS:
		FigurePos[1] += value;
		break;
	case FP_ZPOS:
		FigurePos[2] += value;
		break;
	}
	m_pCurFigure->figure->SetPos(FigurePos);
	m_pWnd->Invalidate();
}

void Scene::RotateCurFigure(int Coord,int OP,int value)
{
	if (!IsCurSelected())
		return;
	float FigureRot[3];
	m_pCurFigure->figure->GetRot(FigureRot);
	if (OP == OP_MINUS)
		value = -value;
	switch (Coord)
	{
	case FR_XROT:
		FigureRot[0] += value;
		break;
	case FR_YROT:
		FigureRot[1] += value;
		break;
	case FR_ZROT:
		FigureRot[2] += value;
		break;
	}
	m_pCurFigure->figure->SetRot(FigureRot);
	m_pWnd->Invalidate();
}

void Scene::SetInsertMode()
{
	m_fXPos = 0;
	m_fZPos = 0;
	m_fXRot = 0;
	m_fYRot = 0;
	m_pWnd->Invalidate();
}

void Scene::WinPosToGLPos(float GLPos[],CPoint WinPos)
{
	const double PI = 3.1415926;
	int viewport[4];
	glGetIntegerv(GL_VIEWPORT,viewport);
	int xPos = WinPos.x;
	int yPos = viewport[3] - WinPos.y;
	float yRange = (double)30 * (double)tan((double)(22.5 / 180.0 * PI));
	float xRange = yRange * ((double)viewport[2] / (double)viewport[3]);
	GLPos[0] = 2 * (double) xPos * xRange / (double) viewport[2] - xRange;
	GLPos[1] = 2 * (double) yPos * yRange / (double) viewport[3] - yRange;
	GLPos[2] = 0;

	/*GLint         viewport[4];   
	GLdouble   modelview[16];   
	GLdouble   projection[16];   
	GLfloat     winX,   winY,   winZ;   
	GLdouble   posX,   posY,   posZ;   

	glGetIntegerv(GL_VIEWPORT,   viewport);   
	glGetDoublev(GL_MODELVIEW_MATRIX,   modelview);   
	glGetDoublev(GL_PROJECTION_MATRIX,   projection);

	winX =(float) WinPos.x;
	winY =(float) WinPos.y;

	winX   =   (float)WinPos.x;   
	winY   =   viewport[3]   -   (float)WinPos.y; 
	glReadPixels((int)winX,   (int)winY,   1,   1,   GL_DEPTH_COMPONENT,   GL_FLOAT,   &winZ);   
	gluUnProject(winX,   winY,   winZ,   modelview,   projection,   viewport,   &posX,   &posY,   &posZ);
	
	GLPos[0] = posX;
	GLPos[1] = posY;
	GLPos[2] = posZ;*/
	
}

void Scene::Display()
{
	FigureNode *p = m_pFigure;
	while (p)
	{
		p->figure->Display();
		p = p->next;
	}
	
	glFinish();

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -