【OpenGL学习笔记】地月系

OpenGL学习笔记2-地月系



前言

描述地月系如下
太阳在世界坐标系原点绕着Z轴以速率r1弧度/帧沿顺时针方向自转
地球绕着自身z轴以速率r2弧度/帧逆时针自转,同时在距离太阳为2单位的公转轨道上绕太阳的z轴做以r3弧度每秒做顺时针公转
假设太阳为标准大小,地球大小是太阳大小的(0.3,0.3,0.3)倍。
请写出实现以上描述的渲染效果的渲染步骤及相应的实现变换的代码和对应的顶点着色器程序。
在这里插入图片描述
代码中:
自转:先旋转再平移
公转:先平移再旋转

运行结果

在这里插入图片描述

纹理图片

sun:
sun.jpg
earth:
earth.jpg


一、TexturePool

1.TexturePool.h

#pragma once

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <map>
#include <string>
using namespace std;

typedef map<string, GLuint> Textures;

class TexturePool
{
public:

	virtual ~TexturePool();
private:
	TexturePool();
	Textures textures;
public:
	void addTexture(string name, string path);
	static TexturePool* getInstance();
	GLuint getTexture(string name);
};


2.TexturePool.cpp

#include "TexturePool.h"



#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

#include <iostream>
TexturePool::TexturePool()
{
}


TexturePool::~TexturePool()
{
	for (Textures::iterator ite = textures.begin(); ite != textures.end(); ++ite)
	{
		glDeleteTextures(1, &ite->second);
	}
}
void TexturePool::addTexture(string name, string path)
{
	GLuint texID;
	if (name.empty())
	{
		return;
	}
	stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
	// The FileSystem::getPath(...) is part of the GitHub repository so we can find files on any IDE/platform; replace it with your own image path.
	int width, height, nrChannels;
	unsigned char* data = stbi_load(path.c_str(), &width, &height, &nrChannels, 0);
	if (data)
	{
		glGenTextures(1, &texID);
		glBindTexture(GL_TEXTURE_2D, texID);
		// set the texture wrapping parameters
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	// set texture wrapping to GL_REPEAT (default wrapping method)
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		// set texture filtering parameters
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		// load image, create texture and generate mipmaps


		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
		glGenerateMipmap(GL_TEXTURE_2D);

		textures[name] = texID;
	}
	else
	{
		std::cout << "Failed to load texture" << std::endl;
	}
	stbi_image_free(data);

}
TexturePool* TexturePool::getInstance()
{
	static TexturePool instance;
	return &instance;
}
GLuint TexturePool::getTexture(string name)
{
	if (textures.find(name) != textures.end())
	{
		return textures[name];
	}
	return 0;
}

二、object

1.object.h

#pragma once

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <string>
#include <Shader.h>

typedef struct
{
	glm::vec3 coordinate;//坐标
	glm::vec3 color;//颜色
	glm::vec2 texture;//纹理
} TextureColorVertex;

typedef struct
{
	GLuint	latSegments;      
	GLuint	longSegments;    
	GLfloat radius;
	GLfloat height;
}DataParam;

class Object
{
public:
	Object(std::string vs, std::string fs, std::string texName = "");
	virtual ~Object();
protected:
	Shader*					shader; 
	TextureColorVertex*		vertices; 
	GLushort *				indices;   
	GLuint					indexCount;      

	GLint					verticesSize;
	GLuint					indexSize;
	GLuint					texture;        
	GLuint					VBO, VAO, EBO;
protected:
	glm::mat4				model;
	float					rotationSpeed;
	float					revolutionSpeed;
	float					rotationAngle;
	float					revolutionAngle;
	glm::vec3				translation;

	float					distance;
	float					revolution;

	void createBuffer(bool createEBO = false);
public:
	virtual void initData(DataParam *param = nullptr) = 0;
	void setTexture(std::string texName);
	void render(glm::mat4& view, glm::mat4& projection);
	virtual void update(float dt) {}
	virtual void renderObject() = 0;

	void set_distance(float distance);//设置球体间的距离
	void set_revolution(float revolution);

};


2.object.cpp

#include <glad/glad.h>
#include "TexturePool.h"

#include "Object.h"
Object::Object(std::string vs, std::string fs, std::string texName)
{
	shader = new Shader(vs.c_str(), fs.c_str());
	if (texName != "")
	{
		texture = TexturePool::getInstance()->getTexture(texName);
		// activate shader
		shader->use();

		shader->setInt("tex", 0);

	}
	vertices = nullptr;
	indices = nullptr;

}


Object::~Object()
{
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteBuffers(1, &EBO);
	if (shader)
	{
		delete shader;
	}
	
}


void Object::setTexture(std::string texName)
{
	texture = TexturePool::getInstance()->getTexture(texName);
}

void Object::createBuffer(bool createEBO )
{
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	if (createEBO)
	{
		glGenBuffers(1, &EBO);
	}
	glBindVertexArray(VAO);

	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, verticesSize, vertices, GL_STATIC_DRAW);

	if (createEBO)
	{
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, indices, GL_STATIC_DRAW);
	}

	//position attribute
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TextureColorVertex), (void*)0);
	glEnableVertexAttribArray(0);

	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(TextureColorVertex), (void*)(1 * sizeof(glm::vec3)));
	glEnableVertexAttribArray(1);

	// texture coord attribute
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(TextureColorVertex), (void*)(2 * sizeof(glm::vec3)));
	glEnableVertexAttribArray(2);

}

void Object::render(glm::mat4& view, glm::mat4& projection)
{
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, texture);

	glBindVertexArray(VAO);
	shader->setMat4("model", model);
	shader->setMat4("view", view);
	shader->setMat4("projection", projection);
	
	renderObject();
}

void Object::set_distance(float distance) {
	this->distance = distance;
}
void Object::set_revolution(float revolution) {
	this->revolution = revolution;
}

三、Sun

1.Sun.h

#include "Object.h"
class Sun :
    public Object
{
public:
	Sun(std::string vs, std::string fs, std::string texName = "");
	~Sun();
	void initData(DataParam* param = nullptr);
	void renderObject();
	void update(float dt);
};

2.sun.cpp

#include "Sun.h"
Sun::Sun(std::string vs, std::string fs, std::string texName) :Object(vs, fs, texName)
{
}
Sun::~Sun()
{
}
void Sun::initData(DataParam* param)
{

	GLfloat radius = param->radius;
	GLuint longSegments = param->longSegments;
	GLuint latSegments = param->latSegments;

	float fPhi = glm::pi<float>() / latSegments;					//纬度上角度差:Phi
	float fTheta = (glm::pi<float>() * 2.0f) / longSegments;		//经度上角度差:Theta

	//生成顶点数据
	verticesSize = ((longSegments + 1) * (latSegments + 1)) * sizeof(TextureColorVertex);
	vertices = new TextureColorVertex[(longSegments + 1) * (latSegments + 1)];

	TextureColorVertex* p = vertices;

	for (GLuint i = 0; i < latSegments + 1; i++)
	{
		float latitude = i * fPhi - glm::pi<float>() / 2.0f;	//纬度

		for (GLuint j = 0; j < longSegments + 1; j++)
		{
			float longitude = j * fTheta;		//经度

			p->coordinate.x = radius * cosf(latitude) * cosf(longitude);
			p->coordinate.y = radius * sinf(latitude);
			p->coordinate.z = radius * cosf(latitude) * sinf(longitude);
			p->color.r = p->color.g = p->color.b = 1.0f;
			p->texture.s = longitude / (glm::pi<float>() * 2.0f);
			p->texture.t = (latitude + glm::pi<float>() / 2.0f) / glm::pi<float>();
			p++;
		}
	}


	//生成索引数据
	indexCount = (1 + longSegments) * 2 * (1 + latSegments);
	indices = new GLushort[indexCount];
	indexSize = indexCount * sizeof(GLushort);
	GLushort* pIdx = indices;

	for (GLuint i = 0; i < latSegments + 1; i++)
	{
		for (GLuint j = 0; j < longSegments + 1; j++)
		{
			*pIdx = i * (longSegments + 1) + j;
			pIdx++;

			*pIdx = (i + 1) * (longSegments + 1) + j;
			pIdx++;
		}
	}
	createBuffer(true);
	delete[]vertices;
	delete[]indices;

	revolutionAngle = 0.0f;
	rotationAngle = 0.0f;

	revolutionSpeed = 3.0f;
	rotationSpeed = 10.0f;

}
void Sun::renderObject()
{

	glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, 0);

}

void Sun::update(float dt)
{
	revolutionAngle += revolutionSpeed * dt * 20;
	rotationAngle += rotationSpeed * dt * 20;

	model = glm::mat4(1.0f);
	//model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 1.0f, 0.0f));
	//model = glm::translate(model, glm::vec3(5.0f, 0.0f, 0.0f));
	model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 1.0f, 0.0f));
	model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
}


四、Sphere

1.球体建模

在这里插入图片描述
在这里插入图片描述

2.Sphere.h

#include "Object.h"
class Sphere :
    public Object
{
public:
    Sphere(std::string vs, std::string fs, std::string texName = "");
    ~Sphere();

    void initData(DataParam* param = nullptr);
    void update(float dt);
    void renderObject();
};

3.Sphere.cpp

代码如下:

#include "Sphere.h"
Sphere::Sphere(std::string vs, std::string fs, std::string texName)
	:Object(vs, fs, texName)
{
}
Sphere::~Sphere()
{
}
void Sphere::initData(DataParam* param)
{

	GLfloat radius = param->radius;
	GLuint longSegments = param->longSegments;
	GLuint latSegments = param->latSegments;


	float fPhi = glm::pi<float>() / latSegments;					//纬度上角度差:fPhi
	float fTheta = (glm::pi<float>() * 2.0f) / longSegments;		//经度上角度差:fTheta



	//生成顶点数据
	verticesSize = ((longSegments + 1) * (latSegments + 1)) * sizeof(TextureColorVertex);
	vertices = new TextureColorVertex[(longSegments + 1) * (latSegments + 1)];

	TextureColorVertex* p = vertices;

	for (GLuint i = 0; i < latSegments + 1; i++)
	{
		float latitude = i * fPhi - glm::pi<float>() / 2.0f;	//纬度

		for (GLuint j = 0; j < longSegments + 1; j++)
		{
			float longitude = j * fTheta;		//经度

			p->coordinate.x = radius * cosf(latitude) * cosf(longitude);
			p->coordinate.y = radius * sinf(latitude);
			p->coordinate.z = radius * cosf(latitude) * sinf(longitude);
			p->color.r = p->color.g = p->color.b = 1.0f;
			p->texture.s = longitude / (glm::pi<float>() * 2.0f);
			p->texture.t = (latitude + glm::pi<float>() / 2.0f) / glm::pi<float>();
			p++;
		}
	}


	//生成索引数据
	indexCount = (1 + longSegments) * 2 * (1 + latSegments);
	indices = new GLushort[indexCount];
	indexSize = indexCount * sizeof(GLushort);
	GLushort* pIdx = indices;

	for (GLuint i = 0; i < latSegments + 1; i++)
	{
		for (GLuint j = 0; j < longSegments + 1; j++)
		{
			*pIdx = i * (longSegments + 1) + j;
			pIdx++;

			*pIdx = (i + 1) * (longSegments + 1) + j;
			pIdx++;
		}
	}
	createBuffer(true);
	delete[]vertices;
	delete[]indices;

	revolutionAngle = 0.0f;
	rotationAngle = 0.0f;

	revolutionSpeed = 3.0f;
	rotationSpeed = 10.0f;

}
void Sphere::renderObject()
{

	glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_SHORT, 0);

}

void Sphere::update(float dt)
{
	revolutionAngle += revolutionSpeed * dt * 20;
	rotationAngle += rotationSpeed * dt * 20;

	model = glm::mat4(1.0f);
	model = glm::rotate(model, glm::radians(revolutionAngle), glm::vec3(0.0f, 1.0f, 0.0f));
	model = glm::translate(model, glm::vec3(distance, 0.0f, 0.0f));
	model = glm::rotate(model, glm::radians(rotationAngle), glm::vec3(0.0f, 1.0f, 0.0f));
	model = glm::scale(model, glm::vec3(1.0f, 1.0f, 1.0f));
}


五、着色器

texture.vs

#version 330 core
layout(location = 0) in vec3 aPos;// 位置变量的属性位置值为0
layout(location = 1) in vec3 aColor;// 颜色变量的属性位置值为1
layout(location = 2) in vec2 aTextCoord;// 纹理变量的属性位置值为2

out vec2 TexCoord;// 为片段着色器指定一个纹理输出


uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(aPos,1.0f);
    TexCoord = aTextCoord;//vec2(aTextCoord.x,aTextCoord.y);
}

texture.fs

#version 330 core

out vec4 FragColor;

in vec2 TexCoord;// 从顶点着色器传来的输入变量(名称相同、类型相同)

uniform sampler2D tex; // 在OpenGL程序代码中设定这个变量


void main()
{
    FragColor = texture(tex,TexCoord);
}

六、main


#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>


#include <iostream>
#include"camera.h"
#include "TexturePool.h"
#include "Sphere.h"
#include "Sun.h"


void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
//声明鼠标移动的回调函数
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
//声明鼠标滚轮滚动的回调函数
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);

void init();
void render();
void update(float dt);
void cleanUp();

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int scr_width = 800;
int scr_height = 600;

// 摄像机数值
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;

// 定时
float deltaTime = 0.0f;	// 当前帧和最后一帧之间的时间
float lastFrame = 0.0f;

unsigned int texture1, texture2;
unsigned int VBO, VAO, EBO;
GLFWwindow* window = NULL;

Sun* sun;
Sphere* earth;


int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif

	// glfw window creation
	// --------------------
	window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
	//调用鼠标回调函数
	glfwSetCursorPosCallback(window, mouse_callback);
	glfwSetScrollCallback(window, scroll_callback);


	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

	// glad: load all OpenGL function pointers
	// ---------------------------------------
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}
	int nrAttributes;
	glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes);
	std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl;


	init();

	double t = 0.0;
	// render loop
	// -----------
	while (!glfwWindowShouldClose(window))
	{
		// 每帧的时间逻辑
		// --------------------
		float currentFrame = glfwGetTime();
		deltaTime = currentFrame - lastFrame;
		lastFrame = currentFrame;
		// input
		// -----
		processInput(window);


		double dt = glfwGetTime() - t;
		t = glfwGetTime();
		update(dt);
		render();
		glfwPollEvents();
	}

	cleanUp();
	glfwTerminate();
	return 0;

}
void init()
{
	TexturePool* textPool = TexturePool::getInstance();
	textPool->addTexture("sun", "sun.jpg");//太阳
	sun = new Sun("texture.vs", "texture.fs", "sun");
	DataParam sunParam = { 20,20,0.5f };
	sun->initData(&sunParam);

	
	textPool->addTexture("earth", "earth.jpg");//地球
	earth = new Sphere("texture.vs", "texture.fs", "earth");
	DataParam earthParam = { 20,20,0.3f };
	earth->initData(&earthParam);
	earth->set_distance(3.1f);
	earth->set_revolution(1.5f);

	
}

void cleanUp()
{
	
	if (sun)
	{
		delete sun;
	}
	if (earth)
	{
		delete earth;
	}
}
void update(float dt)
{
	
	sun->update(dt);
	earth->update(dt);
}

void render()
{

	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);//激活深度检测功能


	//创建变换
	glm::mat4 view = glm::mat4(1.0f);
	glm::mat4 projection = glm::mat4(1.0f);

	projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
	view = camera.GetViewMatrix();

	view = glm::translate(view, glm::vec3(0.0f, 0.0f, -12.0f));




	
	sun->render(view, projection);
	earth->render(view, projection);

	// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
	// -------------------------------------------------------------------------------
	glfwSwapBuffers(window);
	glDisable(GL_DEPTH_TEST);
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow* window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);

	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
		camera.ProcessKeyboard(FORWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
		camera.ProcessKeyboard(BACKWARD, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
		camera.ProcessKeyboard(LEFT, deltaTime);
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
		camera.ProcessKeyboard(RIGHT, deltaTime);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	//确保视口与新窗口尺寸匹配;注意宽度和

	//高度将明显大于视网膜显示器上指定的高度。
	scr_width = width;
	scr_height = height;
	glViewport(0, 0, width, height);
}

// glfw:当鼠标移动时,调用该回调函数
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	if (firstMouse)
	{
		lastX = xpos;
		lastY = ypos;
		firstMouse = false;
	}

	float xoffset = xpos - lastX;
	float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
	lastX = xpos;
	lastY = ypos;

	camera.ProcessMouseMovement(xoffset, yoffset);
}

// glfw:当鼠标滚轮滚动时,调用该回调函数
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	camera.ProcessMouseScroll(yoffset);
}

camera

camera.h

#ifndef CAMERA_H
#define CAMERA_H

#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <vector>

// 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
};

// Default camera values
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
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, 0.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
    //返回使用欧拉角和LookAt矩阵计算的视图矩阵 
    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;
    }

    // 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
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值