OpenGL:glfw+glad实现仿真模拟车削

该博客介绍了如何使用OpenGL、glfw和glad库来模拟车削过程。主要内容包括背景图片显示、圆柱体原料和车刀模型的绘制,以及通过鼠标控制车刀移动进行模拟切削。文章详细讲解了绘制背景、圆柱体和车刀的实现思路,并提到了模型加载、纹理处理和PBR光照模型的应用。
摘要由CSDN通过智能技术生成

github仓库:livingsu/OpenGL-simulate-turning

之前用的一直是旧OpenGL的固定管线(glut库),但是当接触了新OpenGL以后,感觉着色器、VAO、VBO实在是太强大了,不仅更加灵活,而且利用缓存可以极大提升渲染性能。

主要参考**Learn-OpenGL-CN官网**,项目中加载模型用到的Assimp库,加载图片用的stb_image库,另外还用到了learn-OpenGL作者写的一些类:camera.h,shader.h,model.h都是及其方便的类。

实现的主要功能:

  1. 显示背景图片,圆柱形原料、车刀模型的绘制
  2. 通过鼠标移动车刀,完成切削
  3. 切削时有粒子系统模拟飞溅效果
  4. 可以选择圆柱体材质(金属或者木质),使用的是pbr光照模型
  5. 切削后圆柱体光照材质发生变化
  6. 可以创建三次贝塞尔曲线作为切削的约束线

效果预览:
在这里插入图片描述

1.背景图片

画两个三角形,设置纹理图片即可,注意将z值设置和w一样,那么其深度就是最大的z/w=1.0,就会显示在所有物体的后面。

// background.vs
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;

out vec2 TexCoords;

void main(){
   
    TexCoords = aTexCoords;
    gl_Position =  vec4(aPos.xy,1.0,1.0);     //设置深度为最大
}

要注意画背景之前打开glDepthFunc(GL_LEQUAL)并在之后恢复默认值。

        // 画背景图片
		// -------------
		glDepthFunc(GL_LEQUAL);   //设置背景在所有物体的最后面(最大深度)绘制
		bgShader.use();
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, bgTexture);
		glBindVertexArray(bgVAO);
		glDrawArrays(GL_TRIANGLES, 0, 6);
		glBindVertexArray(0);
		glDepthFunc(GL_LESS);

2.圆柱体原料

圆柱体拥有很多信息

//圆柱体信息,注意应该用double而不是float,避免精度不够导致除法出错
const double cylinderRadius = 0.4;
const double cylinderLength = 1.6;
const int angleStep = 2;			//切分角度增量
const double lengthStep = 0.001;	//切分长度增量
const double radiusStep = 0.001;	//半径增量
vector<int> radiusArray;			//半径数组,均为radiusStep的整数倍
vector<int> radiusMinArray;			//半径最小值数组,规定半径的最小值,用于贝塞尔曲线的限制
vector<glm::vec3> allPoints;		//所有点数组,包括顶点、法向量和纹理坐标
vector<unsigned int> indices;		//索引数据

unsigned int cylinderVAO;
unsigned int cylinderVBO;
unsigned int vertexNum; //顶点数量

绘制的主要思想:

只需要绘制圆柱体侧面,将侧面展开得到一个矩形,将矩形沿底边分成slices(=360/angleStep)份,沿z轴分成stacks(=cylinderLength/lengthStep)份,得到的小矩形用两个三角形绘制即可。由于相同的点在不同的小矩形中重复利用,故用EBO进行索引缓存即可。

void initCylinder() {
   
	int slices = 360 / angleStep;  //围绕z轴的细分
	int stacks = cylinderLength / lengthStep;  //沿z轴的细分

	//初始化半径数组和半径限制数组
	unsigned int initRadius = cylinderRadius / radiusStep;
	for (int i = 0; i <= stacks; ++i) {
   
		radiusArray.push_back(initRadius);
	}

	for (int i = 0; i <= stacks; ++i) {
   
		radiusMinArray.push_back(0);  //开始时,半径最小均可以取0
	}

	float R, alpha, x
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值