vs2013 qt opengl模拟小球自由落体

//mesh.h
#pragma once

#include "vector"
#include "iostream"
#include "string"
#include "fstream"
#include "sstream"
#include "algorithm"
#include "assert.h"
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>//头文件导入
#include <qdebug.h>

#pragma comment(lib, "glut.lib")//雷打不动

using namespace std;//雷打不动

struct vec3
{
	double x, y, z;
};//定义

struct vec2
{
	double x, y;
};//定义

class Vertex           //定点类
{
public:
	int vertIndex;     // 此顶点在顶点列表中的索引
	int normIndex;     // 顶点的法线索引
	int textIndex;     // 顶点的纹理索引
};

class Face
{
public:
	vector<Vertex> vertex; // 顶点和法线索引组成的列表

	Face(){}
	~Face(){}
};

class Mesh                 //网格
{
private:
	vector<vec3> vVertex;  // 顶点数组
	vector<vec2> vText;    // 纹理数组
	vector<vec3> vNorm;    // 法线数组
	vector<Face> vFace;    // 面片数组

public:
	Mesh(){};
	~Mesh(){};

	bool readFile(char* path);//布尔值(path)
	void drawMesh();//在下面
};

bool Mesh::readFile(char* path)//读取.obj文件里头的值
{
	ifstream file(path);//读取文件
	if (!file)
	{
		cerr << "Error::ObjLoader, could not open obj file:"
			<< path << " for reading." << std::endl;
		return false;
	}//读取失败了
	else
	{
		qDebug() << "qweq";
	}
	string line;//定义line
	while (getline(file, line))//读入一行数据
	{
		if (line.substr(0, 2) == "vt")     // 顶点纹理坐标数据 //获得line中从第0位开始的长度为2的字符串
		{
			istringstream s(line.substr(2));
			vec2 v;
			s >> v.x; s >> v.y;
			//cout << "vt " << v.x << " " << v.y << endl;
			v.y = -v.y;                     // 注意这里加载的dds纹理 要对y进行反转
			vText.push_back(v);//该函数将一个新的元素加到vText的最后面,位置为当前最后一个元素的下一个元素,新的元素的值是val的拷贝(或者是移动拷贝)
		}
		else if (line.substr(0, 2) == "vn") // 顶点法向量数据
		{
			istringstream s(line.substr(2));//string对象s中读取字符
			vec3 v;
			s >> v.x; s >> v.y; s >> v.z;//》写入,《 输出
			//cout << "vn " << v.x << " " << v.y << " " << v.z << endl;
			vNorm.push_back(v);
		}
		else if (line.substr(0, 1) == "v")  // 顶点位置数据
		{
			istringstream s(line.substr(1));
			vec3 v;
			s >> v.x; s >> v.y; s >> v.z;
			//cout << "v " << v.x << " " << v.y << " " << v.z << endl;
			vVertex.push_back(v);
		}
		else if (line.substr(0, 1) == "f")  // 面数据
		{
			Face face;
			//cout << "f ";
			istringstream vtns(line.substr(1));
			string vtn;
			while (vtns >> vtn)             // 处理一行中多个顶点属性
			{
				Vertex vertex;
				replace(vtn.begin(), vtn.end(), '/', ' ');//将vtn里头的'/'全部替换为''
				istringstream ivtn(vtn);
				if (vtn.find("  ") != string::npos) // 没有纹理数据,注意这里是2个空格
				{
					ivtn >> vertex.vertIndex
						>> vertex.normIndex;

					vertex.vertIndex--;     //使得下标从0开始
					vertex.normIndex--;
				}
				else
				{
					ivtn >> vertex.vertIndex
						>> vertex.textIndex
						>> vertex.normIndex;

					//cout <<  vertex.vertIndex << "/" << vertex.textIndex << "/" << vertex.normIndex << " ";
					vertex.vertIndex--;
					vertex.textIndex--;
					vertex.normIndex--;
				}
				face.vertex.push_back(vertex);
			}
			vFace.push_back(face);
			//cout << endl;
		}
		else if (line[0] == '#')            // 注释忽略
		{
		}
		else
		{
			// 其余内容 暂时不处理
		}
	}

	return true;
}

void Mesh::drawMesh()
{
	if (vFace.empty())
		return;

	// 有纹理
	if (vText.size() > 0)
	{
		for (int f = 0; f < vFace.size(); f++)  // 绘制每个面片
		{
			int n = vFace[f].vertex.size();    // 面的顶点数
			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//填充方法
			glBegin(GL_TRIANGLES);//glBegin()是和glEnd()结合起来使用。
			glColor3f(1, 0, 0);
			for (int v = 0; v < n; v++)
			{
				int it = vFace[f].vertex[v].textIndex;
				glTexCoord2f(vText[it].x, vText[it].y);//glTexCoord2f(GLfloat s,GLfloat t);s代表x坐标,t代表y坐标;文理载入函数

				int in = vFace[f].vertex[v].normIndex;
				glNormal3f(vNorm[in].x, vNorm[in].y, vNorm[in].z);//设置法向量指向哪里

				int iv = vFace[f].vertex[v].vertIndex;
				glVertex3f(vVertex[iv].x, vVertex[iv].y, vVertex[iv].z);//glVertex3f(x, y, z),这个函数是在空间中确定点的函数
			}
			glEnd();

			glBegin(GL_LINE_LOOP);
			glColor3f(1, 0, 0);
			for (int v = 0; v < n; v++)
			{
				int it = vFace[f].vertex[v].textIndex;
				glTexCoord2f(vText[it].x, vText[it].y);

				int in = vFace[f].vertex[v].normIndex;
				glNormal3f(vNorm[in].x, vNorm[in].y, vNorm[in].z);

				int iv = vFace[f].vertex[v].vertIndex;
				glVertex3f(vVertex[iv].x, vVertex[iv].y, vVertex[iv].z);
			}
			glEnd();
		}
	}
	// 没有纹理
	else
	{
		for (int f = 0; f < vFace.size(); f++)  // 绘制每个面片
		{
			int n = vFace[f].vertex.size();    // 面的顶点数
			glBegin(GL_TRIANGLES);
			for (int v = 0; v < n; v++)
			{
				int in = vFace[f].vertex[v].normIndex;
				glNormal3f(vNorm[in].x, vNorm[in].y, vNorm[in].z);

				int iv = vFace[f].vertex[v].vertIndex;
				glVertex3f(vVertex[iv].x, vVertex[iv].y, vVertex[iv].z);
			}
			glEnd();
		}
	}
}


//.h文件
#ifndef THIRDWINDOW_H
#define THIRDWINDOW_H

#include <QOpenGLWidget>
#include <QOpenGLWidget>
#include <Qtimer.h>
#include <QOpenGLShader>
#include <QtGui>
#include <QtCore>
#include <QTimer>
#include <QOpenGLWindow>
#include <QOpenGLFunctions>
#include <QGLWidget>
#include <QTextStream>
#include <QOpenGLShader>
#include <QtGui>
#include <QtCore>
#include <QTimer>
#include <QOpenGLWindow>
#include <QOpenGLFunctions>
#include "vector"
#include "assert.h"
#include <windows.h>

#include <math.h>

class ThirdWindow : public QOpenGLWidget
{
	Q_OBJECT

public:
	ThirdWindow(QWidget *parent);
	~ThirdWindow();
	typedef struct b //定义储存球体的结构
	{
		GLdouble y;
		GLdouble vy;


	} Ball;
	Ball ball;

	//GLuint texName; //材质路径
	GLdouble dt;    //间隔时间
	bool direction; //小球运动方向,向下为true
	double G;
	GLuint *tex0;//纹理
	QString bmpfile;
	QPoint m_last;
	double dist, horizontal, vertical;

	//void updataScene();
	void initializeGL();
	void paintGL();
	void loadTexture(QString filepath, GLuint *texture);
	void mousePressEvent(QMouseEvent *e);
	void mouseMoveEvent(QMouseEvent *e);

private:
	
};

#endif // THIRDWINDOW_H

//.cpp文件
#include "thirdwindow.h"
#define GLUT_DISABLE_ATEXIT_HACK
#include <GL/glut.h>
#include "mesh.h"

#pragma comment(lib, "glut32.lib")

const int windowWidth = 1080;
const int windowHeight = 1080;

Mesh mesh;

double PI = 3.14159265358979323846;

ThirdWindow::ThirdWindow(QWidget *parent)
	: QOpenGLWidget(parent)
{
	glViewport(0, 0, windowWidth, windowHeight);
	dt = 0.02;//间隔时间
	ball.y = 10; //初始化球体属性
	ball.vy = 0;//ball.vy为速度大小,ball.y为高度坐标(地面位置为-2.0)
	direction = true;
	G = 9.8;
	bmpfile = "://1.jpg";
	tex0 = new GLuint;纹理
	dist = 2.0;
	vertical = 45.0;
	horizontal = 45.0;


	QTimer *timer = new QTimer(this); //创建一个定时器
	//将定时器的计时信号与updateGL()绑定
	connect(timer, SIGNAL(timeout()), this, SLOT(update()));
	timer->start(10);
}

ThirdWindow::~ThirdWindow()
{

}

void ThirdWindow::initializeGL(){

	setGeometry(2, 5, windowWidth, windowHeight);//设置窗口初始位置和大小
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	//glEnable(GL_LIGHTING); //开启光照
	// glEnable(GL_LIGHT0); //开启光源0
	glEnable(GL_AUTO_NORMAL);
	glEnable(GL_NORMALIZE);
	glMaterialf(GL_FRONT, GL_SHININESS, 64.0);
	//loadTexture(bmpfile, tex0);
	mesh.readFile("../JuneThirdOne/3.obj");
}
void ThirdWindow::paintGL(){
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0, 0, 0, 0);
	glLoadIdentity();
	/*float eyex = dist*cos(vertical / 180.0*PI)*sin(horizontal / 180.0*PI);
	float eyey = dist*sin(vertical / 180.0*PI);
	float eyez = dist*cos(vertical / 180.0*PI)*cos(horizontal / 180.0*PI);
	gluLookAt(eyex, eyey, eyez, 0.0, 0.0, 0.0, 0, 1, 0);*/
	glOrtho(-20, 20, -20, 20, -20, 10);
	//gluLookAt(1,2,1,0,0,0,0,1,0);
	glDisable(GL_TEXTURE_2D);   //画小球时先不使用纹理
	glPushMatrix();
	glTranslated(0, ball.y, 0.0);
	//glutSolidSphere(2.0, 40, 40);
	mesh.drawMesh();
	if (ball.vy<1 && ball.y<-2.0){       //中止条件
		ball.vy = 0;
		ball.y = -2.0;
		G = 0;
	}
	if (direction){  //向下运动
		G = 9.8;
		if (ball.y - (ball.vy*dt + 0.5*G*dt*dt) <= -2){
			direction = false; //触发转向条件,改变direction的值,使球体运动方向改变
			G += 6.0;
		}
		ball.y = ball.y - (ball.vy*dt + 0.5*G*dt*dt); //根据牛顿运动定律计算出球的位移公式
		ball.vy = ball.vy + G*dt; //根据牛顿运动定律计算出球体的速度
	}
	else{   //向上运动
		if (ball.y >-2 && ball.vy<0){
			direction = true;
		}
		ball.y = ball.y + (ball.vy*dt - 0.5*G*dt*dt);
		ball.vy = ball.vy - G*dt;
	}
	glPopMatrix(); //将当前矩阵弹出
	glPushMatrix();
	// glPushAttrib(GL_ALL_ATTRIB_BITS);
	// glColor3f(0.0, 0.0, 1.0);
	glEnable(GL_TEXTURE_2D);
	// loadTexture(bmpfile,tex0);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0, 0.0); glVertex3f(10.0, -4.0, 0.0);
	glTexCoord2f(1.0, 0.0); glVertex3f(0.0, -4.0, -6.0);
	glTexCoord2f(1.0, 1.0); glVertex3f(-6.0, -4.0, 0.0);
	glTexCoord2f(0.0, 1.0); glVertex3f(0.0, -4.0, 10.0);
	glEnd();
	//glPopAttrib();
	glPopMatrix();
	glFlush();

}





void ThirdWindow::loadTexture(QString filepath, GLuint *texture){    //加载纹理
	QImage tex, buf;
	if (!buf.load(filepath))
	{
		qDebug() << "Error: failed to load image!";
		exit(1);
	}
	tex = QGLWidget::convertToGLFormat(buf);   //转化为rgba类型的数据集
	glGenTextures(1, texture);
	glBindTexture(GL_TEXTURE_2D, *texture);
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, tex.width(), tex.height(), GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);

}


void ThirdWindow::mousePressEvent(QMouseEvent *e)
{
	m_last = e->pos();
}


void ThirdWindow::mouseMoveEvent(QMouseEvent *e)
{
	if (e->buttons() & Qt::LeftButton)
	{
		QPoint m_now = e->pos();
		float disx = m_now.x() - m_last.x();//两个鼠标x坐标的差
		float disy = m_now.y() - m_last.y();  //m_last是之前点击事件取得的鼠标位置
		//更改观察方向
		horizontal -= disx / 25;
		vertical += disy / 25;
		m_last = m_now;
		update();
	}

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值