计算机图形学课程实验 明暗处理 场景漫游 纹理贴图 stl文件的导入 附源码

计算机图形学 课程实验总结

一、设计思路

1. 实验涉及的模型

本实验中我主要想构建的场景是《龙珠》中的两个人物与一颗龙珠,因此场景中共有三个模型。
其中两个人物由stl文件导入,龙珠由自己绘制球体并导入纹理。

2. 光照效果的实现

本实验中我采用了phong光照模型,通过背景光、漫反射、镜面反射三者的叠加计算出总的颜色,并通过三个不同的三维向量作为系数与三种光分别相乘实现加权的效果,来达到”材质”的效果。明暗与颜色的计算在顶点着色器中实现,计算颜色的空间为视线空间,在最开始时尝试了在世界空间中进行计算(即所有物体均不考虑view矩阵,只考虑model矩阵),但是在这里视线方向的计算极为麻烦,导致镜面反射难以计算,因此最后选择在view空间进行明暗处理。

3. 场景漫游的实现

本实验中的场景漫游的最终效果是通过wasd进行在场景中的移动,jk实现上升与下降,鼠标的移动实现视线方向的改变。主要的实现方式是捕捉wasd、jk的按键来进行摄像头位置的移动,通过鼠标的位置移动来设定俯仰角、偏航角,从而计算出实现方向,最后通过LookAt()函数来获取view矩阵。

4. 纹理贴图的实现

本实验中我对于”龙珠”进行了贴图,也就是我自己绘制的球体。主要通过经纬对球进行划分,并将经纬与纹理图片的坐标对应,从而完成贴图,这一部分的具体实现将在第二部分的对应位置进行介绍。

二、实现步骤

1. 模型导入与绘制

本实验中导入的外部模型为stl格式,其样例格式如下:

solid solidname
 facet normal -0.322416 -0.599127 -0.732867
  outer loop
    vertex -21.2641 -0.370953 53.7396
    vertex -23.9294 -0.278856 54.8369
    vertex -23.9294 2.14269 52.8573
  endloop
 endfacet
 facet normal -0.0122214 -0.342702 -0.939365
  outer loop
    vertex -21.2641 -0.370953 53.7396
    vertex -23.9294 2.14269 52.8573
    vertex -21.2641 2.40239 52.7278
  endloop
 endfacet

其中,solid solidname是stl文件本身在开头的标注,类似于声明文件格式,对于我们的模型导入并无影响,我们要关注的是后续的片元是如何给出的。
stl文件中的片元首先以facet normal开始,其后紧跟下一个片元的法向量坐标,之后在outer loopend loop间的是片元的三个顶点的坐标,最后以endfacet结束片元属性。
因此我们在读片元的时候按顺序略过结构性的英文单词,按顺序对法向量与顶点坐标存储即可,需要注意的是法向量坐标需要进行三次复制,以便正确导入vbo中。这一部分代码被封装在ReadStlFile.h头文件中,在此不再粘贴代码。

至于球的绘制,我使用经纬线对球进行划分,并通过经纬线的当前序号与总数的比值作为参数,利用参数方程计算球的三维坐标,将经纬组成的一个方格划分为两个三角形进行绘制,法向量与顶点坐标保持一致,纹理坐标取经纬线序号与总经纬线数量的比值,此外还需要注意极点位置的经纬需要单独取出考虑,防止出现一个片元中有两个相同顶点的情形。
部分核心代码如下:

//通过经线纬线获取点坐标
glm::vec3 getPoint(float u, float v) {
	GLfloat r = 0.2f;
	GLfloat pi = PI;
	GLfloat z = r * std::cos(pi * u);
	GLfloat x = r * std::sin(pi * u) * std::cos(2 * pi * v);
	GLfloat y = r * std::sin(pi * u) * std::sin(2 * pi * v);
	// std::cout << x << "," << y << "," << z << std::endl;
	return glm::vec3(x, y, z);

//由于极点部分处理代码太长,在此处仅展示非极点位置,完整代码在gllab.cpp的getball函数中
for (float lat = 1; lat < Latitude - 1; lat+=1) {  // 纬线u
	for (float lon = 0; lon <= Longitude; lon+=1) { // 经线v
		// 一次构造4个点,两个三角形,
		glm::vec3 point1 = getPoint(lat * lat_step, lon * lon_step);
		glm::vec3 point2 = getPoint((lat + 1) * lat_step, lon * lon_step);
		glm::vec3 point3 = getPoint((lat + 1) * lat_step, (lon + 1) * lon_step);
		glm::vec3 point4 = getPoint(lat * lat_step, (lon + 1) * lon_step);
		//vertex
		vertices_3.push_back(point1.x);
		vertices_3.push_back(point1.y);
		vertices_3.push_back(point1.z);
		//normal
		vertices_3.push_back(point1.x);
		vertices_3.push_back(point1.y);
		vertices_3.push_back(point1.z);
		//texture
		vertices_3.push_back(lon / Longitude);
		vertices_3.push_back(lat / Latitude);

		vertices_3.push_back(point2.x);
		vertices_3.push_back(point2.y);
		vertices_3.push_back(point2.z);
		vertices_3.push_back(point2.x);
                vertices_3.push_back(point2.y);
		vertices_3.push_back(point2.z);
		vertices_3.push_back(lon / Longitude);
		vertices_3.push_back((lat + 1) / Latitude);
		vertices_3.push_back(point3.x);
		vertices_3.push_back(point3.y);
		vertices_3.push_back(point3.z);
		vertices_3.push_back(point3.x);
		vertices_3.push_back(point3.y);
		vertices_3.push_back(point3.z);
		vertices_3.push_back((lon + 1) / Longitude);
		vertices_3.push_back((lat + 1) / Latitude);
		//第二个片元
		vertices_3.push_back(point1.x);
		vertices_3.push_back(point1.y);
		vertices_3.push_back(point1.z);
		vertices_3.push_back(point1.x);
		vertices_3.push_back(point1.y);
		vertices_3.push_back(point1.z);
		vertices_3.push_back(lon / Longitude);
		vertices_3.push_back(lat / Latitude);
		vertices_3.push_back(point3.x);
		vertices_3.push_back(point3.y);
		vertices_3.push_back(point3.z);
		vertices_3.push_back(point3.x);
		vertices_3.push_back(point3.y);
		vertices_3.push_back(point3.z);
		vertices_3.push_back((lon + 1) / Longitude);
		vertices_3.push_back((lat + 1) / Latitude);
		vertices_3.push_back(point4.x);
		vertices_3.push_back(point4.y);
		vertices_3.push_back(point4.z);
		vertices_3.push_back(point4.x);
		vertices_3.push_back(point4.y);
		vertices_3.push_back(point4.z);
		vertices_3.push_back((lon + 1) / Longitude);
		vertices_3.push_back((lat) / Latitude);
	}
	}
}
2. 光照与明暗处理

此部分实现主要使用了phong光照模型,在顶点着色器中实现,在view空间中进行明暗的计算,即在计算明暗之前先将法向量与顶点进行view和model矩阵的变化。其中,由于法向量的坐标变化与顶点不同,其偏移方向与片元的mv矩阵间存在互为逆转置矩阵的关系。顶点着色器中一些关键变量的计算如下:

// convert to view coordinate system
vec4 P = v_matrix * m_matrix * vec4(vertPos,1.0);
vec3 N = normalize((norm_matrix * vec4(vertNormal,1.0)).xyz);
vec3 L = normalize(test.xyz - P.xyz);
// view vector is equivalent to the negative of view space vertex position
vec3 V = normalize(-P.xyz);
// R is reflection of -L with respect to surface normal N
vec3 R = reflect(-L, N);
// ambient, diffuse, and specular contributions
vec3 ambient = ((globalAmbient * material.ambient) + 
                (light.ambient * material.ambient)).xyz;
vec3 diffuse = light.diffuse.xyz * material.diffuse.xyz * vec3(max(dot(N,L), 0.0f));
vec3 specular = material.specular.xyz * light.specular.xyz * 
                pow(max(dot(R,V), 0.0f), material.shininess);

varyingColor = vec4((ambient + diffuse * torch + specular * torch), 1.0);
// send the position to the fragment shader, as before

需要进行解释的是,这里的torch变量是光源的打开与关闭,其会通过捕捉F键的按下来进行光源的开关,具体是对torch进行赋值为0向量或者全1的向量,与漫反射与镜面反射的结果相乘。

3. 场景漫游

本实验中的场景漫游的最终效果是通过wasd进行在场景中的移动,jk实现上升与下降,鼠标的移动实现视线方向的改变。具体的实现封装在了Camera.h文件中,通过在gllab.cpp文件中对其函数的调用来完成。

  1. 相机位置移动
    相机位置的移动是通过相机的Front向量与当前坐标为基准,捕捉键盘的输入来实现的:
// processes input received from any keyboard-like input system. 
//Accepts input parameter in the form of camera defined ENUM 
//(to abstract it from windowing systems)
    void ProcessKeyboard(Camera_Movement direction, float deltaTime) {
        float velocity = MovementSpeed * deltaTime;
        if (direction == FORWARD)
            Position += Front * velocity;
        if (direction == BACKWARD)
            Position -= Front * velocity;
        if (direction == LEFT)
            Position -= Right * velocity;
        if (direction == RIGHT)
            Position += Right * velocity;
        if (direction == UP)
            Position += Up * velocity;
        if (direction == DOWN)
            Position -= Up * velocity;
    }

其中的durectionCamera.h中的一个枚举对象,包含了其所实现的所有键盘的控制:

enum Camera_Movement {
    FORWARD, BACKWARD, LEFT, RIGHT, DOWN, UP
};

gllab.h中通过processInput函数对其进行了调用:

void Delay(int   time)//time*1000为秒数 
{
	clock_t   now = clock();

	while (clock() - now < time);
}
void processInput(GLFWwindow* window) {

	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
		movedirection = FORWARD;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
		movedirection = BACKWARD;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
		movedirection = LEFT;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
		movedirection = RIGHT;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS) {
		movedirection = UP;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_K) == GLFW_PRESS) {
		movedirection = DOWN;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);

	if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) {
		if (torch[0] == 1.0f) {
			torch = glm::vec3(0.0f);
		}
		else {
			torch = glm::vec3(1.0f);
		}
		Delay(150);
	}
}

可以看到,在键盘对相机的控制之外,还有F控制光源的开关,为了防止其相应频繁导致难以正确操作,在F按下后添加了休眠时间。

  1. 视角的改变
    视角的改变是通过捕捉鼠标的位置移动来修改俯仰角与偏航角的值来实现的:

    // processes input received from a mouse input system. 
    //Expects the offset value in both the x and y direction.
     void ProcessMouseMovement(float xoffset, float yoffset, 
                             GLboolean constrainPitch = true) {
         xoffset *= MouseSensitivity;
         yoffset *= MouseSensitivity;
    
         Yaw += xoffset;
         Pitch -= yoffset;
    
         // make sure that when pitch is out of bounds, screen doesn't get flipped
         if (constrainPitch) {
             if (Pitch > 89.0f)
                 Pitch = 89.0f;
             if (Pitch < -89.0f)
                 Pitch = -89.0f;
         }
    
         // update Front, Right and Up Vectors using the updated Euler angles
         updateCameraVectors();
     }
    // calculates the front vector from the Camera's (updated) Euler Angles
     void updateCameraVectors() {
         // calculate the new Front vector
         glm::vec3 front;
         front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
         front.y = sin(glm::radians(Pitch));
         front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
         Front = glm::normalize(front);
         // also re-calculate the Right and Up vector
         Right = glm::normalize(glm::cross(Front, WorldUp));  
         // normalize the vectors, because their length gets closer to 0 
         // the more you look up or down which results in slower movement.
         Up = glm::normalize(glm::cross(Right, Front));
     }
    
    
4. 纹理贴图

纹理映射的实现其实是很容易的,只需要将物体的坐标与纹理坐标相对应即可,本实验中我对球体进行了贴图,其纹理坐标实现利用经纬网格划分,与纹理图片的坐标相对应,纹理映射即构建完成,在此不加赘述。

三、个人总结

在实验中,能够感觉到的是实验的原理其实很简单,数学过程也很容易,但是实现的过程中会出现一些小问题,导致运行效果与原先设想不同,而由于着色器的透明性也难以像其他cpp程序一般调试,尤其是在第三次实验对整个代码进行整合与封装的时候尤为明显。

附录 源码

gllab.cpp
#include <iostream>
using namespace std;
#define GLEW_STATIC	

#include"GL\glew.h"
#include"GLFW\glfw3.h"
#include"glm\glm.hpp"
#include"glm\gtc\matrix_transform.hpp"
#include"glm\gtc\type_ptr.hpp"
#include"glut.h"

#include"Shader.h"
#include"ReadStlFile.h"
#include"Camera.h"

#include"stb_image.h"
#include <ctime> 

//常量定义
#define numVAOs 4
#define numVBOs 4
#define PI 3.14159f
#define WIDTH 600
#define HEIGHT 600
#define StartTorch false


//全局变量
bool Lock = 0;

GLuint texture;
GLuint vbo[numVBOs];
GLuint vao[numVAOs];
GLuint VAO;
GLuint VBO;
double lastx;
double lasty;
bool firstMouseMove;
Camera_Movement movedirection;
float deltaTime = 0.0f; // 当前帧与上一帧的时间差
float lastFrame = 0.0f; // 绘制上一帧的时间

glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 1.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);

glm::vec4 globalAmbient = glm::vec4(0.2f, 0.2f, 0.2f, 1.0f);
glm::vec4 lightambient = glm::vec4(0.1f, 0.1f, 0.1f, 1.0f);
glm::vec4 lightdiffuse = glm::vec4(0.5f, 0.5f, 0.5f, 1.0f);
glm::vec4 lightspecular = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
glm::vec4 lightposition = glm::vec4(1.0f, 5.0f, 1.0f, 1.0f);
glm::vec4 materialambient = glm::vec4(0.3f, 0.3f, 0.3f, 0.0f);
glm::vec4 materialdiffuse = glm::vec4(0.5f, 0.5f, 0.5f, 0.0f);
glm::vec4 materialspecular = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);

glm::vec3 torch = glm::vec3(1.0f);
float shininess = 5;

Camera camera;
glm::mat4 m_matrix;
glm::mat4 v_matrix;
glm::mat4 norm_matrix;
glm::mat4 projection_matrix;

vector<GLfloat> read_vertex;
vector<GLfloat> read_normal;
vector<GLfloat> read_vertex2;
vector<GLfloat> read_normal2;
vector<GLfloat> vertices_1;
vector<GLfloat> vertices_2;
vector<GLfloat> vertices_3;
vector<GLfloat> vertices_4;
int size_vertex1;
int size_vertex2;

//回调函数
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
	if (firstMouseMove == true) {
		lastx = xpos;
		lasty = ypos;
		firstMouseMove = false;
	}
	camera.ProcessMouseMovement(xpos - lastx, ypos - lasty);
	lastx = xpos;
	lasty = ypos;
}
void Delay(int   time)//time*1000为秒数 
{
	clock_t   now = clock();

	while (clock() - now < time);
}
void processInput(GLFWwindow* window) {

	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
		movedirection = FORWARD;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
		movedirection = BACKWARD;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
		movedirection = LEFT;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
		movedirection = RIGHT;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_J) == GLFW_PRESS) {
		movedirection = UP;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_K) == GLFW_PRESS) {
		movedirection = DOWN;
		camera.ProcessKeyboard(movedirection, deltaTime);
	}
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);

	if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS) {
		if (torch[0] == 1.0f) {
			torch = glm::vec3(0.0f);
		}
		else {
			torch = glm::vec3(1.0f);
		}
		Delay(150);
	}

	if (glfwGetKey(window, GLFW_KEY_L) == GLFW_PRESS) {
		if (Lock == 0) {
			Lock = 1;
		}
		else {
			Lock = 0;
		}
		Delay(150);
	}
}

//通过经线纬线获取点坐标
glm::vec3 getPoint(float u, float v) {
	GLfloat r = 0.2f;
	GLfloat pi = PI;
	GLfloat z = r * std::cos(pi * u);
	GLfloat x = r * std::sin(pi * u) * std::cos(2 * pi * v);
	GLfloat y = r * std::sin(pi * u) * std::sin(2 * pi * v);
	// std::cout << x << "," << y << "," << z << std::endl;
	return glm::vec3(x, y, z);
}

void getball(GLuint Longitude, GLuint Latitude) {
	// Longitude:经线切分个数
	// Latitude:纬线切分个数
	GLfloat lon_step = 1.0f / Longitude;
	GLfloat lat_step = 1.0f / Latitude;
	GLuint offset = 0;
	for (float lon = 0; lon < Longitude; lon+=1) {
		glm::vec3 point1 = getPoint(0, lon * lon_step);
		glm::vec3 point2 = getPoint(lat_step, lon * lon_step);
		glm::vec3 point3 = getPoint(lat_step, (lon + 1) * lon_step);
		//vertex1
		vertices_3.push_back(point1.x);
		vertices_3.push_back(point1.y);
		vertices_3.push_back(point1.z);
		//normal
		vertices_3.push_back(point1.x);
		vertices_3.push_back(point1.y);
		vertices_3.push_back(point1.z);
		//texture
		vertices_3.push_back(lon / Longitude);
		vertices_3.push_back(0);
		
		//vertex2
		vertices_3.push_back(point2.x);
		vertices_3.push_back(point2.y);
		vertices_3.push_back(point2.z);
		//normal
		vertices_3.push_back(point2.x);
		vertices_3.push_back(point2.y);
		vertices_3.push_back(point2.z);
		//texture
		vertices_3.push_back(lon / Longitude);
		vertices_3.push_back(lat_step);
		
		//vertex3
		vertices_3.push_back(point3.x);
		vertices_3.push_back(point3.y);
		vertices_3.push_back(point3.z);
		//normal
		vertices_3.push_back(point3.x);
		vertices_3.push_back(point3.y);
		vertices_3.push_back(point3.z);
		//texture
		vertices_3.push_back((lon + 1) / Longitude);
		vertices_3.push_back(lat_step);
	}
	for (float lat = 1; lat < Latitude - 1; lat+=1) {  // 纬线u
		for (float lon = 0; lon <= Longitude; lon+=1) { // 经线v
			// 一次构造4个点,两个三角形,
			glm::vec3 point1 = getPoint(lat * lat_step, lon * lon_step);
			glm::vec3 point2 = getPoint((lat + 1) * lat_step, lon * lon_step);
			glm::vec3 point3 = getPoint((lat + 1) * lat_step, (lon + 1) * lon_step);
			glm::vec3 point4 = getPoint(lat * lat_step, (lon + 1) * lon_step);
			//vertex
			vertices_3.push_back(point1.x);
			vertices_3.push_back(point1.y);
			vertices_3.push_back(point1.z);
			//normal
			vertices_3.push_back(point1.x);
			vertices_3.push_back(point1.y);
			vertices_3.push_back(point1.z);
			//texture
			vertices_3.push_back(lon / Longitude);
			vertices_3.push_back(lat / Latitude);

			vertices_3.push_back(point2.x);
			vertices_3.push_back(point2.y);
			vertices_3.push_back(point2.z);
			vertices_3.push_back(point2.x);
			vertices_3.push_back(point2.y);
			vertices_3.push_back(point2.z);
			vertices_3.push_back(lon / Longitude);
			vertices_3.push_back((lat + 1) / Latitude);
			vertices_3.push_back(point3.x);
			vertices_3.push_back(point3.y);
			vertices_3.push_back(point3.z);
			vertices_3.push_back(point3.x);
			vertices_3.push_back(point3.y);
			vertices_3.push_back(point3.z);
			vertices_3.push_back((lon + 1) / Longitude);
			vertices_3.push_back((lat + 1) / Latitude);
			//第二个片元
			vertices_3.push_back(point1.x);
			vertices_3.push_back(point1.y);
			vertices_3.push_back(point1.z);
			vertices_3.push_back(point1.x);
			vertices_3.push_back(point1.y);
			vertices_3.push_back(point1.z);
			vertices_3.push_back(lon / Longitude);
			vertices_3.push_back(lat / Latitude);
			vertices_3.push_back(point3.x);
			vertices_3.push_back(point3.y);
			vertices_3.push_back(point3.z);
			vertices_3.push_back(point3.x);
			vertices_3.push_back(point3.y);
			vertices_3.push_back(point3.z);
			vertices_3.push_back((lon + 1) / Longitude);
			vertices_3.push_back((lat + 1) / Latitude);
			vertices_3.push_back(point4.x);
			vertices_3.push_back(point4.y);
			vertices_3.push_back(point4.z);
			vertices_3.push_back(point4.x);
			vertices_3.push_back(point4.y);
			vertices_3.push_back(point4.z);
			vertices_3.push_back((lon + 1) / Longitude);
			vertices_3.push_back((lat) / Latitude);
		}
	}
	for (float lon = 0; lon < Longitude; lon+=1) {
		glm::vec3 point1 = getPoint(1, lon * lon_step);
		glm::vec3 point2 = getPoint(1 - lat_step, lon * lon_step);
		glm::vec3 point3 = getPoint(1 - lat_step, (lon + 1) * lon_step);
		//vertex1
		vertices_3.push_back(point1.x);
		vertices_3.push_back(point1.y);
		vertices_3.push_back(point1.z);
		//normal
		vertices_3.push_back(point1.x);
		vertices_3.push_back(point1.y);
		vertices_3.push_back(point1.z);
		//texture
		vertices_3.push_back(lon / Longitude);
		vertices_3.push_back(1);

		//vertex2
		vertices_3.push_back(point2.x);
		vertices_3.push_back(point2.y);
		vertices_3.push_back(point2.z);
		//normal
		vertices_3.push_back(point2.x);
		vertices_3.push_back(point2.y);
		vertices_3.push_back(point2.z);
		//texture
		vertices_3.push_back(lon / Longitude);
		vertices_3.push_back(1 - lat_step);

		//vertex3
		vertices_3.push_back(point3.x);
		vertices_3.push_back(point3.y);
		vertices_3.push_back(point3.z);
		//normal
		vertices_3.push_back(point3.x);
		vertices_3.push_back(point3.y);
		vertices_3.push_back(point3.z);
		//texture
		vertices_3.push_back((lon + 1) / Longitude);
		vertices_3.push_back(1 - lat_step);
	}
}


void init() {
	{
		vertices_4.push_back(-0.2);
		vertices_4.push_back(0);
		vertices_4.push_back(0);

		vertices_4.push_back(0);
		vertices_4.push_back(0);
		vertices_4.push_back(1);

		vertices_4.push_back(0);
		vertices_4.push_back(0);

		vertices_4.push_back(0.2);
		vertices_4.push_back(0);
		vertices_4.push_back(0);

		vertices_4.push_back(0);
		vertices_4.push_back(0);
		vertices_4.push_back(1);

		vertices_4.push_back(1);
		vertices_4.push_back(0);

		vertices_4.push_back(-0.2);
		vertices_4.push_back(0.4);
		vertices_4.push_back(0);

		vertices_4.push_back(0);
		vertices_4.push_back(0);
		vertices_4.push_back(1);

		vertices_4.push_back(0);
		vertices_4.push_back(1);

		vertices_4.push_back(0.2);
		vertices_4.push_back(0.4);
		vertices_4.push_back(0);

		vertices_4.push_back(0);
		vertices_4.push_back(0);
		vertices_4.push_back(1);

		vertices_4.push_back(1);
		vertices_4.push_back(1); }

	//初始化场景漫游所需的相关参数
	lastx = 0;
	lasty = 0;
	firstMouseMove = true;

	//设置视景体
	projection_matrix = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.0f);
	cout << "projection_matrix:" << endl;
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			cout << projection_matrix[i][j];
		}
		cout << endl;
	}

	//读数据,设置VAO和VBO
	ReadStlFile readstl;
	readstl.read("trunks.stl", read_vertex, read_normal);
	//将read_vertex和read_normal中的数据整合到vertice_1中
	for (int i = 0; i < read_vertex.size() / 3; i++) {
		for (int j = 0; j < 3; j++) {
			vertices_1.push_back(read_vertex[3 * i + j]);
		}
		for (int j = 0; j < 3; j++) {
			vertices_1.push_back(read_normal[3 * (i / 3) + j]);
		}
		vertices_1.push_back(0);
		vertices_1.push_back(0);
	}
	size_vertex1 = read_vertex.size();
	
	ReadStlFile readstl2;
	readstl2.read("goten.stl", read_vertex2, read_normal2);
	for (int i = 0; i < read_vertex2.size() / 3; i++) {
		for (int j = 0; j < 3; j++) {
			vertices_2.push_back(read_vertex2[3 * i + j]);
		}
		for (int j = 0; j < 3; j++) {
			vertices_2.push_back(read_normal2[3 * (i / 3) + j]);
		}
		vertices_2.push_back(0);
		vertices_2.push_back(0);
	}
	size_vertex2 = read_vertex2.size();
	getball(200, 200);
	//

	glGenVertexArrays(numVAOs, vao);
	glGenBuffers(numVBOs, vbo);


	glBindVertexArray(vao[0]);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBufferData(GL_ARRAY_BUFFER, vertices_1.size() * sizeof(float), &vertices_1[0], GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);	// 通道 0 
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);	// 通道 1 
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(5 * sizeof(GLfloat)));
	glEnableVertexAttribArray(2);	// 通道 2 

	glBindVertexArray(vao[1]);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
	glBufferData(GL_ARRAY_BUFFER, vertices_2.size() * sizeof(float), &vertices_2[0], GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);	// 通道 0 
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);	// 通道 1 
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(5 * sizeof(GLfloat)));
	glEnableVertexAttribArray(2);	// 通道 2 

	glBindVertexArray(vao[2]);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
	glBufferData(GL_ARRAY_BUFFER, vertices_3.size() * sizeof(float), &vertices_3[0], GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);	// 通道 0 
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);	// 通道 1 
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
	glEnableVertexAttribArray(2);	// 通道 2 

	glBindVertexArray(vao[3]);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
	glBufferData(GL_ARRAY_BUFFER, vertices_4.size() * sizeof(float), &vertices_4[0], GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);	// 通道 0 
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);	// 通道 1 
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
	glEnableVertexAttribArray(2);	// 通道 2 

	/* 开启深度测试 */
	glEnable(GL_DEPTH_TEST);

	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	
	// 为当前绑定的纹理对象设置环绕、过滤方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	// 加载并生成纹理
	int width, height, nrChannels;
	unsigned char* data = stbi_load("dragonball.png", &width, &height, &nrChannels, 0);
	cout << "nrChannels:" << nrChannels << endl;
	if (data)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	else
	{
		std::cout << "Failed to load texture" << std::endl;
	}
	stbi_image_free(data);
}

void display_1(GLuint shaderProgram) {
	//opengl相关参数的设置
	glClearColor(0, 0, 0, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glUseProgram(shaderProgram);
	glBindVertexArray(vao[0]);
	//uniform变量的计算
	GLuint globalAmbientLoc = glGetUniformLocation(shaderProgram, "globalAmbient");

	GLuint lightambientLoc = glGetUniformLocation(shaderProgram, "light.ambient");
	GLuint lightspecularLoc = glGetUniformLocation(shaderProgram, "light.specular");
	GLuint lightdiffuseLoc = glGetUniformLocation(shaderProgram, "light.diffuse");
	GLuint lightpositionLoc = glGetUniformLocation(shaderProgram, "light.position");

	GLuint materialambientLoc = glGetUniformLocation(shaderProgram, "material.ambient");
	GLuint materialdiffuseLoc = glGetUniformLocation(shaderProgram, "material.diffuse");
	GLuint materialspecularLoc = glGetUniformLocation(shaderProgram, "material.specular");
	GLuint materialshininessLoc = glGetUniformLocation(shaderProgram, "material.shininess");

	GLuint m_matrixLoc = glGetUniformLocation(shaderProgram, "m_matrix");
	GLuint v_matrixLoc = glGetUniformLocation(shaderProgram, "v_matrix");
	GLuint norm_matrixLoc = glGetUniformLocation(shaderProgram, "norm_matrix");
	GLuint projection_matrixLoc = glGetUniformLocation(shaderProgram, "projection_matrix");

	glUniform4fv(globalAmbientLoc, 1, value_ptr(globalAmbient));
	glUniform4fv(lightambientLoc, 1, value_ptr(lightambient));
	glUniform4fv(lightdiffuseLoc, 1, value_ptr(lightdiffuse));
	glUniform4fv(lightspecularLoc, 1, value_ptr(lightspecular));

	glUniform4fv(materialambientLoc, 1, value_ptr(materialambient));
	glUniform4fv(materialdiffuseLoc, 1, value_ptr(materialdiffuse));
	glUniform4fv(materialspecularLoc, 1, value_ptr(materialspecular));
	glUniform1f(materialshininessLoc, shininess);
	
	GLuint torchLoc = glGetUniformLocation(shaderProgram, "torch");
	glUniform3fv(torchLoc, 1, value_ptr(torch));

	m_matrix = glm::mat4(1.0f);
	m_matrix = glm::rotate(m_matrix, glm::radians(-90.0f), glm::vec3(1.0f, 0.0, 0.0));
	m_matrix = glm::translate(m_matrix, glm::vec3(-0.3f, 0.0, 0.0));
	//m_matrix = glm::translate(m_matrix, glm::vec3(-0.3f, 0.0, 0.0));
	v_matrix = camera.GetViewMatrix();
	norm_matrix = transpose(inverse(v_matrix * m_matrix));
	glUniformMatrix4fv(norm_matrixLoc, 1, GL_FALSE, glm::value_ptr(norm_matrix));
	glUniform4fv(lightpositionLoc, 1, glm::value_ptr(lightposition));
	glUniformMatrix4fv(m_matrixLoc, 1, GL_FALSE, glm::value_ptr(m_matrix));
	glUniformMatrix4fv(v_matrixLoc, 1, GL_FALSE, glm::value_ptr(v_matrix));
	glUniformMatrix4fv(projection_matrixLoc, 1, GL_FALSE, glm::value_ptr(projection_matrix));
	glDrawArrays(GL_TRIANGLES, 0, size_vertex1/3);
	float currentFrame = glfwGetTime();
	deltaTime = currentFrame - lastFrame;
	lastFrame = currentFrame;
	
	glBindVertexArray(0);				// 解绑定 VAO
	cout << "1";
}

void display_2(GLint shaderProgram) {
	glUseProgram(shaderProgram);
	glBindVertexArray(vao[1]);
	//uniform变量的计算
	GLuint globalAmbientLoc = glGetUniformLocation(shaderProgram, "globalAmbient");

	GLuint lightambientLoc = glGetUniformLocation(shaderProgram, "light.ambient");
	GLuint lightspecularLoc = glGetUniformLocation(shaderProgram, "light.specular");
	GLuint lightdiffuseLoc = glGetUniformLocation(shaderProgram, "light.diffuse");
	GLuint lightpositionLoc = glGetUniformLocation(shaderProgram, "light.position");

	GLuint materialambientLoc = glGetUniformLocation(shaderProgram, "material.ambient");
	GLuint materialdiffuseLoc = glGetUniformLocation(shaderProgram, "material.diffuse");
	GLuint materialspecularLoc = glGetUniformLocation(shaderProgram, "material.specular");
	GLuint materialshininessLoc = glGetUniformLocation(shaderProgram, "material.shininess");

	GLuint m_matrixLoc = glGetUniformLocation(shaderProgram, "m_matrix");
	GLuint v_matrixLoc = glGetUniformLocation(shaderProgram, "v_matrix");
	GLuint norm_matrixLoc = glGetUniformLocation(shaderProgram, "norm_matrix");
	GLuint projection_matrixLoc = glGetUniformLocation(shaderProgram, "projection_matrix");

	GLuint viewpos_Loc = glGetUniformLocation(shaderProgram, "viewpos");
	glUniform3fv(viewpos_Loc, 1, value_ptr(camera.Position));

	glUniform4fv(globalAmbientLoc, 1, value_ptr(globalAmbient));
	glUniform4fv(lightambientLoc, 1, value_ptr(lightambient));
	glUniform4fv(lightdiffuseLoc, 1, value_ptr(lightdiffuse));
	glUniform4fv(lightspecularLoc, 1, value_ptr(lightspecular));

	glUniform4fv(materialambientLoc, 1, value_ptr(materialambient));
	glUniform4fv(materialdiffuseLoc, 1, value_ptr(materialdiffuse));
	glUniform4fv(materialspecularLoc, 1, value_ptr(materialspecular));
	glUniform1f(materialshininessLoc, shininess);


	GLuint torchLoc = glGetUniformLocation(shaderProgram, "torch");
	glUniform3fv(torchLoc, 1, value_ptr(torch));

	m_matrix = glm::mat4(1.0f);
	m_matrix = glm::rotate(m_matrix, glm::radians(-90.0f), glm::vec3(1.0f, 0.0, 0.0));
	m_matrix = glm::translate(m_matrix, glm::vec3(0.3f, 0.0,0.0)); 
	v_matrix = camera.GetViewMatrix();
	norm_matrix = transpose(inverse(v_matrix * m_matrix));
	glUniformMatrix4fv(norm_matrixLoc, 1, GL_FALSE, glm::value_ptr(norm_matrix));
	glUniform4fv(lightpositionLoc, 1, glm::value_ptr(lightposition));
	glUniformMatrix4fv(m_matrixLoc, 1, GL_FALSE, glm::value_ptr(m_matrix));
	glUniformMatrix4fv(v_matrixLoc, 1, GL_FALSE, glm::value_ptr(v_matrix));
	glUniformMatrix4fv(projection_matrixLoc, 1, GL_FALSE, glm::value_ptr(projection_matrix));
	glDrawArrays(GL_TRIANGLES, 0, size_vertex2 / 3);
	float currentFrame = glfwGetTime();
	deltaTime = currentFrame - lastFrame;
	lastFrame = currentFrame;

	glBindVertexArray(0);				// 解绑定 VAO
	cout << "1";
}

void display_3(GLuint shaderProgram) {
	glUseProgram(shaderProgram);
	glBindVertexArray(vao[2]);
	//uniform变量的计算
	GLuint globalAmbientLoc = glGetUniformLocation(shaderProgram, "globalAmbient");

	GLuint lightambientLoc = glGetUniformLocation(shaderProgram, "light.ambient");
	GLuint lightspecularLoc = glGetUniformLocation(shaderProgram, "light.specular");
	GLuint lightdiffuseLoc = glGetUniformLocation(shaderProgram, "light.diffuse");
	GLuint lightpositionLoc = glGetUniformLocation(shaderProgram, "light.position");

	GLuint materialambientLoc = glGetUniformLocation(shaderProgram, "material.ambient");
	GLuint materialdiffuseLoc = glGetUniformLocation(shaderProgram, "material.diffuse");
	GLuint materialspecularLoc = glGetUniformLocation(shaderProgram, "material.specular");
	GLuint materialshininessLoc = glGetUniformLocation(shaderProgram, "material.shininess");

	GLuint m_matrixLoc = glGetUniformLocation(shaderProgram, "m_matrix");
	GLuint v_matrixLoc = glGetUniformLocation(shaderProgram, "v_matrix");
	GLuint norm_matrixLoc = glGetUniformLocation(shaderProgram, "norm_matrix");
	GLuint projection_matrixLoc = glGetUniformLocation(shaderProgram, "projection_matrix");

	GLuint cameraPosLoc = glGetUniformLocation(shaderProgram, "cameraPos");
	glUniform3fv(cameraPosLoc, 1, value_ptr(camera.Position));

	GLuint viewpos_Loc = glGetUniformLocation(shaderProgram, "viewpos");
	glUniform3fv(viewpos_Loc, 1, value_ptr(camera.Position));

	GLuint testLoc = glGetUniformLocation(shaderProgram, "testlightposition");
	cout << "testLoc:" << testLoc << "end" << endl;
	glUniform4fv(testLoc, 1, value_ptr(lightposition));


	glUniform4fv(globalAmbientLoc, 1, value_ptr(globalAmbient));
	glUniform4fv(lightambientLoc, 1, value_ptr(lightambient));
	glUniform4fv(lightdiffuseLoc, 1, value_ptr(lightdiffuse));
	glUniform4fv(lightspecularLoc, 1, value_ptr(lightspecular));

	glUniform4fv(materialambientLoc, 1, value_ptr(materialambient));
	glUniform4fv(materialdiffuseLoc, 1, value_ptr(materialdiffuse));
	glUniform4fv(materialspecularLoc, 1, value_ptr(materialspecular));
	glUniform1f(materialshininessLoc, shininess);

	GLuint torchLoc = glGetUniformLocation(shaderProgram, "torch");
	glUniform3fv(torchLoc, 1, value_ptr(torch));

	m_matrix = glm::mat4(1.0f);
	//m_matrix = glm::rotate(m_matrix, glm::radians(-90.0f), glm::vec3(1.0f, 0.0, 0.0));
	//m_matrix = glm::translate(m_matrix, glm::vec3(0.3f, 0.0, 0.0));
	GLfloat time = glfwGetTime();
	m_matrix = glm::rotate(m_matrix, glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f));
	m_matrix = glm::rotate(m_matrix, time, glm::vec3(0.0f, 1.0f, 0.0f));
	m_matrix = glm::scale(m_matrix, glm::vec3(0.5, 0.5, 0.5));
	m_matrix = glm::translate(m_matrix, glm::vec3(0.0f, 0.2f, 0.0f));
	v_matrix = camera.GetViewMatrix();
	norm_matrix = transpose(inverse(v_matrix * m_matrix));
	glUniformMatrix4fv(norm_matrixLoc, 1, GL_FALSE, glm::value_ptr(norm_matrix));
	glUniform4fv(lightpositionLoc, 1, glm::value_ptr(lightposition));
	glUniformMatrix4fv(m_matrixLoc, 1, GL_FALSE, glm::value_ptr(m_matrix));
	glUniformMatrix4fv(v_matrixLoc, 1, GL_FALSE, glm::value_ptr(v_matrix));
	glUniformMatrix4fv(projection_matrixLoc, 1, GL_FALSE, glm::value_ptr(projection_matrix));

	glBindTexture(GL_TEXTURE_2D, texture);
	glDrawArrays(GL_TRIANGLES, 0, vertices_3.size() / 8);

	float currentFrame = glfwGetTime();
	deltaTime = currentFrame - lastFrame;
	lastFrame = currentFrame;

	glBindVertexArray(0);				// 解绑定 VAO
	cout << "1";

}

void display_4(GLuint shaderProgram) {
	glUseProgram(shaderProgram);
	glBindVertexArray(vao[3]);
	//uniform变量的计算
	GLuint globalAmbientLoc = glGetUniformLocation(shaderProgram, "globalAmbient");

	GLuint lightambientLoc = glGetUniformLocation(shaderProgram, "light.ambient");
	GLuint lightspecularLoc = glGetUniformLocation(shaderProgram, "light.specular");
	GLuint lightdiffuseLoc = glGetUniformLocation(shaderProgram, "light.diffuse");
	GLuint lightpositionLoc = glGetUniformLocation(shaderProgram, "light.position");

	GLuint materialambientLoc = glGetUniformLocation(shaderProgram, "material.ambient");
	GLuint materialdiffuseLoc = glGetUniformLocation(shaderProgram, "material.diffuse");
	GLuint materialspecularLoc = glGetUniformLocation(shaderProgram, "material.specular");
	GLuint materialshininessLoc = glGetUniformLocation(shaderProgram, "material.shininess");

	GLuint m_matrixLoc = glGetUniformLocation(shaderProgram, "m_matrix");
	GLuint v_matrixLoc = glGetUniformLocation(shaderProgram, "v_matrix");
	GLuint norm_matrixLoc = glGetUniformLocation(shaderProgram, "norm_matrix");
	GLuint projection_matrixLoc = glGetUniformLocation(shaderProgram, "projection_matrix");

	GLuint cameraPosLoc = glGetUniformLocation(shaderProgram, "cameraPos");
	glUniform3fv(cameraPosLoc, 1, value_ptr(camera.Position));

	GLuint viewpos_Loc = glGetUniformLocation(shaderProgram, "viewpos");
	glUniform3fv(viewpos_Loc, 1, value_ptr(camera.Position));

	GLuint testLoc = glGetUniformLocation(shaderProgram, "testlightposition");
	cout << "testLoc:" << testLoc << "end" << endl;
	glUniform4fv(testLoc, 1, value_ptr(lightposition));


	glUniform4fv(globalAmbientLoc, 1, value_ptr(globalAmbient));
	glUniform4fv(lightambientLoc, 1, value_ptr(lightambient));
	glUniform4fv(lightdiffuseLoc, 1, value_ptr(lightdiffuse));
	glUniform4fv(lightspecularLoc, 1, value_ptr(lightspecular));

	glUniform4fv(materialambientLoc, 1, value_ptr(materialambient));
	glUniform4fv(materialdiffuseLoc, 1, value_ptr(materialdiffuse));
	glUniform4fv(materialspecularLoc, 1, value_ptr(materialspecular));
	glUniform1f(materialshininessLoc, shininess);


	m_matrix = glm::mat4(1.0f);
	//m_matrix = glm::rotate(m_matrix, glm::radians(-90.0f), glm::vec3(1.0f, 0.0, 0.0));
	//m_matrix = glm::translate(m_matrix, glm::vec3(0.3f, 0.0, 0.0));
	//m_matrix = glm::scale(m_matrix, glm::vec3(0.5, 0.5, 0.5));
	//m_matrix = glm::translate(m_matrix, glm::vec3(0.0f, 0.2f, 0.0f));
	v_matrix = camera.GetViewMatrix();
	norm_matrix = transpose(inverse(v_matrix * m_matrix));
	glUniformMatrix4fv(norm_matrixLoc, 1, GL_FALSE, glm::value_ptr(norm_matrix));
	glUniform4fv(lightpositionLoc, 1, glm::value_ptr(lightposition));
	glUniformMatrix4fv(m_matrixLoc, 1, GL_FALSE, glm::value_ptr(m_matrix));
	glUniformMatrix4fv(v_matrixLoc, 1, GL_FALSE, glm::value_ptr(v_matrix));
	glUniformMatrix4fv(projection_matrixLoc, 1, GL_FALSE, glm::value_ptr(projection_matrix));

	glBindTexture(GL_TEXTURE_2D, texture);
	glDrawArrays(GL_TRIANGLES, 0, vertices_4.size() / 8);

	float currentFrame = glfwGetTime();
	deltaTime = currentFrame - lastFrame;
	lastFrame = currentFrame;

	glBindVertexArray(0);				// 解绑定 VAO
	cout << "1";

}

int main()
{
	// 初始化
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);	// 一些版本声明
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);			// 启动兼容
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);						// 缩放关闭

	//窗口捕获与处理 
	GLFWwindow* window_1 = glfwCreateWindow(WIDTH, HEIGHT, "gllab2", nullptr, nullptr);
	glfwSetInputMode(window_1, GLFW_CURSOR, GLFW_CURSOR_DISABLED);   //隐藏并捕捉光标
	int screenWidth_1, screenHeight_1;
	glfwGetFramebufferSize(window_1, &screenWidth_1, &screenHeight_1);
	cout << "screenWidth_1 = " << screenWidth_1 << ", screenHeight = " << screenHeight_1 << endl;

	//回调函数设置
	glfwSetCursorPosCallback(window_1, mouse_callback);

	glewExperimental = GL_TRUE;
	glfwMakeContextCurrent(window_1);
	glewInit();

	Shader ourShader = Shader("shader_v.glsl", "shader_f.glsl");		// 相对路径
	GLuint shaderProgram = ourShader.Program;
	Shader shader2 = Shader("vertex2.glsl", "fragment2.glsl");
	GLuint shderprogram2 = shader2.Program;

	//着色器初始化
	init();

	//测试vTexCoord
	/*for (int i = 0; i < vertices_3.size() / 8; i++) {
		cout << vertices_3[8 * i + 6] << "\t" << vertices_3[8 * i + 7] << endl;
	}*/

	//调整坐标
	
	cout << "draw start!" << endl;
	// draw loop 画图循环
	while (!glfwWindowShouldClose(window_1))
	{
		if(Lock == 0)
		lightposition = glm::vec4(camera.Position,1.0f);
		glViewport(0, 0, WIDTH, HEIGHT);
		glfwPollEvents();
		display_1(shaderProgram);
		display_2(shaderProgram);
		display_3(shaderProgram);
		//display_4(shaderProgram);
		glfwSwapBuffers(window_1);
		processInput(window_1);
	}

	// 释放资源
	glDeleteVertexArrays(numVAOs, vao);
	glDeleteBuffers(numVBOs, vbo);
	glfwTerminate();	// 结束
	return 0;
}
imtest.cpp
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
camera.h
#ifndef CAMERA_H
#define CAMERA_H
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
// Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods
enum Camera_Movement {
    FORWARD, BACKWARD, LEFT, RIGHT, DOWN, UP
};

// Default camera values
const float YAW = -90.0f;
const float PITCH = 0.0f;
const float SPEED = 10.0f;
const float SENSITIVITY = 0.1f;
const float ZOOM = 45.0f;

// An abstract camera class that processes input and calculates the corresponding Euler Angles, Vectors and Matrices for use in OpenGL
class Camera {
public:
    // camera Attributes
    glm::vec3 Position;
    glm::vec3 Front;
    glm::vec3 Up;
    glm::vec3 Right;
    glm::vec3 WorldUp;
    // euler Angles
    float Yaw;
    float Pitch;
    // camera options
    float MovementSpeed;
    float MouseSensitivity;
    float Zoom;

    // constructor with vectors
    Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 2.0f),
        glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f),
        float yaw = YAW,
        float pitch = PITCH)
        : Front(glm::vec3(0.0f, 0.0f, -1.0f)),
        MovementSpeed(SPEED),
        MouseSensitivity(SENSITIVITY),
        Zoom(ZOOM)
    {
        Position = position;
        WorldUp = up;
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }
    // constructor with scalar values
    Camera(float posX, float posY, float posZ,
        float upX, float upY, float upZ,
        float yaw, float pitch)
        : Front(glm::vec3(0.0f, 0.0f, -1.0f)),
        MovementSpeed(SPEED),
        MouseSensitivity(SENSITIVITY),
        Zoom(ZOOM)
    {
        Position = glm::vec3(posX, posY, posZ);
        WorldUp = glm::vec3(upX, upY, upZ);
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }

    // returns the view matrix calculated using Euler Angles and the LookAt Matrix
    glm::mat4 GetViewMatrix() {
        return glm::lookAt(Position, Position + Front, Up);
    }

    // processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
    void ProcessKeyboard(Camera_Movement direction, float deltaTime) {
        float velocity = MovementSpeed * deltaTime;
        if (direction == FORWARD)
            Position += Front * velocity;
        if (direction == BACKWARD)
            Position -= Front * velocity;
        if (direction == LEFT)
            Position -= Right * velocity;
        if (direction == RIGHT)
            Position += Right * velocity;
        if (direction == UP)
            Position += Up * velocity;
        if (direction == DOWN)
            Position -= Up * velocity;
    }

    // processes input received from a mouse input system. Expects the offset value in both the x and y direction.
    void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true) {
        xoffset *= MouseSensitivity;
        yoffset *= MouseSensitivity;

        Yaw += xoffset;
        Pitch -= yoffset;

        // make sure that when pitch is out of bounds, screen doesn't get flipped
        if (constrainPitch) {
            if (Pitch > 89.0f)
                Pitch = 89.0f;
            if (Pitch < -89.0f)
                Pitch = -89.0f;
        }

        // update Front, Right and Up Vectors using the updated Euler angles
        updateCameraVectors();
    }

    // processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
    void ProcessMouseScroll(float yoffset) {
        Zoom -= (float)yoffset;
        if (Zoom < 1.0f)
            Zoom = 1.0f;
        if (Zoom > 45.0f)
            Zoom = 45.0f;
    }

private:
    // calculates the front vector from the Camera's (updated) Euler Angles
    void updateCameraVectors() {
        // calculate the new Front vector
        glm::vec3 front;
        front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
        front.y = sin(glm::radians(Pitch));
        front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
        Front = glm::normalize(front);
        // also re-calculate the Right and Up vector
        Right = glm::normalize(glm::cross(Front, WorldUp));  // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
        Up = glm::normalize(glm::cross(Right, Front));
    }
};
#endif

ReadStlFile.h
#pragma once
#pragma warning(disable:4996)
#include<iostream>
#include<stdio.h>
#include"GL\glew.h"
#include"GLFW\glfw3.h"
#include<vector>
#include<stdlib.h>
using namespace std;


class ReadStlFile {
private:
    vector<GLfloat> Vector;
    FILE* myin;
public:
    ReadStlFile() {

    }

    ~ReadStlFile() {
    
    };

    void read(const char* fname, vector<GLfloat>& vertices_vertex, vector<GLfloat>& vertices_normal) {
        char word[15];
        freopen(fname, "r", stdin);
        cin >> word; cin >> word;//读入‘solid ascii‘
        char vertex[15];//存储顶点信息
        float min_position = FLT_MIN;
        float max_position = FLT_MAX;
        for (int k = 0;; k++)
        {
            //先判定,如果读入的是endsolid,则结束顶点输入
            //endloop与endfacet在循环的末尾读出,不会影响此处判定
            cin >> word;
            if (word[0] == 'e')
            {
                break;
            }

            //开始处理三角形片元
            // facet normal 
            cin >> word;
            
            //normal vec
            for (int i = 0; i < 3; i++){
                cin >> vertex;
                vertices_normal.push_back((GLfloat)atof(vertex));
            }
            //outer loop
            cin >> word;
            cin >> word;

            //循环处理三个顶点
            for (int i = 0; i < 3; i++) {
                cin >> word; //读取字符'vector'
                //读取三个顶点并处理
                for (int j = 0; j < 3; j++) {
                    cin >> vertex;
                    if (k == 0 && j == 0) {
                        max_position = atof(vertex);
                        min_position = atof(vertex);
                    }
                    else {
                        max_position = max(max_position, float(atof(vertex)));
                        min_position = min(min_position, float(atof(vertex)));
                    }
                    vertices_vertex.push_back((GLfloat)atof(vertex) * 0.1);
                    Vector.push_back((GLfloat)atof(vertex) * 0.1);
                }
                
            }
            cin >> word;//endloop
            cin >> word;//endfacet
        }
        int x = 1;
        max_position = max(max_position, float((-1.0) * min_position)) / 2;
        cout << "max_position: " << max_position << endl;
        for (int i = 0; i < vertices_vertex.size(); i++) {
            vertices_vertex[i] = vertices_vertex[i] / max_position;
            //cout << vertices_vertex[i] << "  ";
            //if (i % 3 == 2)cout << endl;
        }

        fclose(stdin);

        //至此,顶点坐标与颜色以及全部存至vertices中
    }

    vector<GLfloat> getVector() {
        return Vector;
    }
};

shader.h
#pragma once
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
using namespace std;
#include"GL\glew.h"	
#include"GLFW\glfw3.h"

// 自己的着色器类
class Shader
{
private:
	GLuint vertex, fragment;	// 顶点着色器 和 片元着色器 
public:
	GLuint Program;				// 着色器程序的ID

	// Constructor(着色器构造函数)
	Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
	{
		// 文件读取系列的变量定义
		string vertexCode;
		string fragmentCode;
		ifstream vShaderFile;
		ifstream fShaderFile;

		// 异常机制处理:保证ifstream对象可以抛出异常:
		vShaderFile.exceptions(ifstream::badbit);
		fShaderFile.exceptions(ifstream::badbit);

		try
		{
			// 打开文件
			vShaderFile.open(vertexPath);
			fShaderFile.open(fragmentPath);
			stringstream vShaderStream, fShaderStream;

			// 读取文件的缓冲内容到数据流中
			vShaderStream << vShaderFile.rdbuf();
			fShaderStream << fShaderFile.rdbuf();

			// 关闭文件处理器
			vShaderFile.close();
			fShaderFile.close();

			// 转换数据流到string
			vertexCode = vShaderStream.str();
			fragmentCode = fShaderStream.str();

		}
		catch (ifstream::failure e) {	// 发生异常时输出
			cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << endl;
		}

		// 将 string 类型的字符串转化为 char数组 类型
		const GLchar* vShaderCode = vertexCode.c_str();
		const GLchar* fShaderCode = fragmentCode.c_str();

		// 顶点着色器
		vertex = glCreateShader(GL_VERTEX_SHADER);
		glShaderSource(vertex, 1, &vShaderCode, NULL);
		glCompileShader(vertex);
		GLint flag;
		GLchar infoLog[512];
		glGetShaderiv(vertex, GL_COMPILE_STATUS, &flag); // 获取编译状态
		if (!flag)
		{
			glGetShaderInfoLog(vertex, 512, NULL, infoLog);
			cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl;
		}

		/* 片元着色器 */
		fragment = glCreateShader(GL_FRAGMENT_SHADER);			
		glShaderSource(fragment, 1, &fShaderCode, NULL);		
		glCompileShader(fragment);								
		glGetShaderiv(fragment, GL_COMPILE_STATUS, &flag);		
		if (!flag)
		{
			glGetShaderInfoLog(fragment, 512, NULL, infoLog);
			cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl;
		}

		/* 着色器程序 */
		this->Program = glCreateProgram();
		glAttachShader(this->Program, vertex);
		glAttachShader(this->Program, fragment);
		glLinkProgram(this->Program);
		if (!flag)
		{
			glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
			cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl;
		}
		// 删除着色器,它们已经链接到我们的程序中了,已经不再需要了
		glDeleteShader(vertex);
		glDeleteShader(fragment);
	}

	// Deconstructor(析构函数)
	~Shader()
	{
		glDetachShader(this->Program, vertex);
		glDetachShader(this->Program, fragment);
		glDeleteShader(vertex);
		glDeleteShader(fragment);
		glDeleteProgram(this->Program);
	}

	void Use()
	{
		glUseProgram(this->Program);
	}

	
};

stb_image.h

这个需要自行下载

以上就是本篇博客的所有内容了,感谢您能够看到此处。

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用VTK导入stl纹理贴图的方法如下: 1. 首先,确保你已经安装了VTK并且设置好了工程。 2. 在代码中引入必要的头文件: ``` #include <vtkSmartPointer.h> #include <vtkSTLReader.h> #include <vtkTexture.h> ``` 3. 创建一个vtkSTLReader对象,并设置要加载的stl文件路径: ``` vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New(); reader->SetFileName("path/to/stl/file.stl"); ``` 4. 创建一个vtkTexture对象,并设置要加载的纹理图片路径: ``` vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New(); texture->SetFileName("path/to/texture/image.jpg"); ``` 5. 将纹理对象应用到STL模型上: ``` vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(reader->GetOutputPort()); mapper->Update(); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); actor->SetTexture(texture); ``` 6. 创建一个vtkRenderer对象和一个vtkRenderWindow对象,并将actor添加到渲染器中: ``` vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->AddActor(actor); vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); ``` 7. 创建一个vtkRenderWindowInteractor对象,并启动交互: ``` vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); renderWindowInteractor->SetRenderWindow(renderWindow); renderWindowInteractor->Initialize(); renderWindowInteractor->Start(); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值