OpenGL南邮计算机图形学实验报告四——用键盘控制物体

OpenGL南邮计算机图形学实验报告四——用键盘控制物体

计算机图形学的题目要求

OpenGL配置参考:
南邮老前辈wonz哥的OpenGL配置(Shader.h始终不用改)、SOIL2 环境配置GLM 环境配置

light.vs/light.fs/Camera.h参考上一篇实验报告

学习网站:LearnOpenGL CN

思路:

  1. 上一节课已经做了用键盘控制镜头camera,这节课用键盘控制物体就可以参考镜头的控制。
    镜头camera的位置由向量frontright加减来控制。
    而物体我选择使用直接改变物体坐标,即x,y的值。

  2. 先初始化物体的坐标ObjectPos(0,0,0)。通过键盘来改变坐标。
    然后每次循环画图的时候就按照ObjectPos的坐标画物体即可,注意设置延迟deltaTime和速度velocity和灵敏度(我直接在函数里设置了)。
    为了不删减功能我使用WASD控制镜头camera,用UP\DOWN\LEFT\RIGHT来控制物体。

transform = glm::translate(transform, ObjectPos);
//*
*
*
*//
void ObjectMovement(GLfloat& xPos, GLfloat& yPos,GLfloat deltaTime)
{//物体移动
	GLfloat velocity =10.0f * deltaTime;//10.0f是灵敏度,也可以获取
	if ( keys[GLFW_KEY_UP]) {
		yPos += 1.0f * velocity;
	}
	if ( keys[GLFW_KEY_DOWN]) {
		yPos -= 1.0f * velocity;
	}
	if ( keys[GLFW_KEY_LEFT]) {
		xPos -= 1.0f * velocity;
	}
	if ( keys[GLFW_KEY_RIGHT]) {
		xPos += 1.0f * velocity;
	}
}

效果图如下:
在这里插入图片描述
在这里插入图片描述
话不多说上代码:

main.cpp

#include<iostream>

//GLEW
#define GLEW_STATIC
#include<GL/glew.h>

//GLFW
#include<GLFW/glfw3.h>
#include"shader.h"
#include"Camera.h"
#include"Light.h"

#include "SOIL2/SOIL2.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include<glm/gtx/rotate_vector.hpp>

const GLint WIDTH = 800, HEIGTH = 600;

void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode);
void MouseCallback(GLFWwindow* window, double xPos, double yPos);
void ScrollCallback(GLFWwindow* window, double xOffset, double yOffest);
void DoMovement();
void ObjectMovement(GLfloat &xPos,GLfloat &yPos,GLfloat deltaTime);

bool keys[1024];
Camera camera(glm::vec3(0.0f, 0.0f, 2.0f));
GLfloat deltaTime = 0.0f;
GLfloat lastTime = 0.0f;

GLfloat lastX = WIDTH / 2.0;
GLfloat lastY=HEIGTH/2.0;

bool firstMouse = true;

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_RESIZABLE, GL_FALSE);

	GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGTH, "Learn OpenGL", nullptr, nullptr);
	if (nullptr == window)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	//next two lines are for mac retina display
	int screenWidth, screenHeight;
	glfwGetFramebufferSize(window, &screenWidth, &screenHeight);


	glfwMakeContextCurrent(window);

	glfwSetKeyCallback(window, KeyCallback);
	glfwSetCursorPosCallback(window, MouseCallback);
	glfwSetScrollCallback(window, ScrollCallback);//未实现

	glewExperimental = GL_TRUE;

	if (GLEW_OK != glewInit())
	{
		std::cout << "Failed to initialise GLEW" << std::endl;
		return -1;
	}
	glViewport(0, 0, screenWidth, screenHeight);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	Shader ourShader = Shader("res/shaders/core.vs", "res/shaders/core.fs");
	Shader lightShader= Shader("res/shaders/light.vs", "res/shaders/light.fs");

	Light lightModel = Light();
	glm::vec3 lightPos = glm::vec3(1.0f, 1.0f, 0.0f);
	glm::vec3 ObjectPos = glm::vec3(0.0f, 0.0f, 0.0f);
	
	GLfloat vertices[] =
	{
		// position					//color					//normal

		-0.5f,-0.5f,0.5f,			0.0f,1.0f,0.0f,		0.0f,0.0f,-0.1f,
		0.5f,-0.5f,0.5f,			0.0f,1.0f,0.0f,		0.0f,0.0f,-0.1f,
		0.5f,0.5f,0.5f,			0.0f,1.0f,0.0f,		0.0f,0.0f,-0.1f,
		0.5f,0.5f,0.5f,			0.0f,1.0f,0.0f,		0.0f,0.0f,-0.1f,
		-0.5f,0.5f,0.5f,			0.0f,1.0f,0.0f,		0.0f,0.0f,-0.1f,
		-0.5f,-0.5f,0.5f,			0.0f,1.0f,0.0f,		0.0f,0.0f,-0.1f,

		-0.5f,-0.5f,-0.5f,		1.0f,0.0f,0.0f,		0.0f,0.0f,0.1f,
		0.5f,-0.5f,-0.5f,			1.0f,0.0f,0.0f,		0.0f,0.0f,0.1f,
		0.5f,0.5f,-0.5f,			1.0f,0.0f,0.0f,		0.0f,0.0f,0.1f,
		0.5f,0.5f,-0.5f,			1.0f,0.0f,0.0f,		0.0f,0.0f,0.1f,
		-0.5f,0.5f,-0.5f,			1.0f,0.0f,0.0f,		0.0f,0.0f,0.1f,
		-0.5f,-0.5f,-0.5f,		1.0f,0.0f,0.0f,		0.0f,0.0f,0.1f,

		-0.5f,0.5f,0.5f,			0.0f,0.0f,1.0f,	  1.0f,0.0f,0.0f,
		-0.5f,0.5f,-0.5f,			0.0f,0.0f,1.0f,	  1.0f,0.0f,0.0f,
		-0.5f,-0.5f,-0.5f,		0.0f,0.0f,1.0f,	  1.0f,0.0f,0.0f,
		-0.5f,-0.5f,-0.5f,		0.0f,0.0f,1.0f,	  1.0f,0.0f,0.0f,
		-0.5f,-0.5f,0.5f,			0.0f,0.0f,1.0f,	  1.0f,0.0f,0.0f,
		-0.5f,0.5f,0.5f,			0.0f,0.0f,1.0f,	  1.0f,0.0f,0.0f,

		0.5f,0.5f,0.5f,			1.0f,1.0f,0.0f,		-1.0f,0.0f,0.0f,
		0.5f,0.5f,-0.5f,			1.0f,1.0f,0.0f,		-1.0f,0.0f,0.0f,
		0.5f,-0.5f,-0.5f,			1.0f,1.0f,0.0f,		-1.0f,0.0f,0.0f,
		0.5f,-0.5f,-0.5f,			1.0f,1.0f,0.0f,		-1.0f,0.0f,0.0f,
		0.5f,-0.5f,0.5f,			1.0f,1.0f,0.0f,		-1.0f,0.0f,0.0f,
		0.5f,0.5f,0.5f,			1.0f,1.0f,0.0f,		 -1.0f,0.0f,0.0f,

		-0.5f,-0.5f,-0.5f,		1.0f,0.0f,1.0f,		0.0f,-1.0f,0.0f,
		0.5f,-0.5f,-0.5f,			1.0f,0.0f,1.0f,		0.0f,-1.0f,0.0f,
		0.5f,-0.5f,0.5f,			1.0f,0.0f,1.0f,		0.0f,-1.0f,0.0f,
		0.5f,-0.5f,0.5f,			1.0f,0.0f,1.0f,		0.0f,-1.0f,0.0f,
		-0.5f,-0.5f,0.5f,			1.0f,0.0f,1.0f,		0.0f,-1.0f,0.0f,
		-0.5f,-0.5f,-0.5f,		1.0f,0.0f,1.0f,		0.0f,-1.0f,0.0f,

		-0.5f,0.5f,-0.5f,			0.0f,1.0f,1.0f,		0.0f,1.0f,0.0f,
		0.5f,0.5f,-0.5f,			0.0f,1.0f,1.0f,		0.0f,1.0f,0.0f,
		0.5f,0.5f,0.5f,			0.0f,1.0f,1.0f,		0.0f,1.0f,0.0f,
		0.5f,0.5f,0.5f,			0.0f,1.0f,1.0f,		0.0f,1.0f,0.0f,
		-0.5f,0.5f,0.5f,			0.0f,1.0f,1.0f,		0.0f,1.0f,0.0f,
		-0.5f,0.5f,-0.5f,			0.0f,1.0f,1.0f,		0.0f,1.0f,0.0f,
	};																 
	// the data should transfer to the memory on Graphic Card
	GLuint VAO, VBO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(2);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

	while (!glfwWindowShouldClose(window))
	{
		GLfloat currentTime = glfwGetTime();
		deltaTime = currentTime - lastTime;
		lastTime = currentTime;

		glfwPollEvents();
		DoMovement();
		ObjectMovement(ObjectPos.x,ObjectPos.y, deltaTime);
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		glm::mat4 transform = glm::mat4(1.0f);

		lightPos = glm::rotate(lightPos, glm::radians(0.1f), glm::vec3(0.0f, 0.0f, 1.0f));
		transform = glm::translate(transform, lightPos);
		transform = glm::scale(transform, glm::vec3(0.1f, 0.1f, 0.1f));
		glm::mat4 projection = glm::mat4(1.0f);
		projection = glm::perspective(glm::radians(camera.GetZoom()), float(screenWidth) / float(screenHeight), 0.1f, 100.0f);
		glm::mat4 view = camera.GetViewMatrix();

		lightShader.Use();
		GLuint transLoc = glGetUniformLocation(lightShader.Program, "transform");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));
		transLoc = glGetUniformLocation(lightShader.Program, "projection");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(projection));
		transLoc = glGetUniformLocation(lightShader.Program, "view");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(view));
		lightModel.Draw(lightShader);

		transform = glm::mat4(1.0f);
		transform = glm::translate(transform, ObjectPos);//每次在ObjectPos位置画物体来达到移动
		transform = glm::rotate(transform, glm::radians(90.0f) * static_cast<GLfloat>(glfwGetTime()), glm::vec3(1.0f, 1.0f, 1.0f));
		transform = glm::scale(transform, glm::vec3(0.5f, 0.5f, 0.5f));
		//transform = glm::translate(transform, glm::vec3(0.1f, 0.0f,-0.8f));
		

		ourShader.Use();
		transLoc = glGetUniformLocation(ourShader.Program, "transform");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));
		transLoc= glGetUniformLocation(ourShader.Program, "projection");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(projection));
		transLoc = glGetUniformLocation(ourShader.Program, "view");
		glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(view));
		glUniform3f(glGetUniformLocation(ourShader.Program, "LightPos"), lightPos.x, lightPos.y, lightPos.z);
		glUniform3f(glGetUniformLocation(ourShader.Program, "ViewPos"),camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);
		glUniform1f(glGetUniformLocation(ourShader.Program, "material.diffuse"), 0.6f);
		glUniform1f(glGetUniformLocation(ourShader.Program, "material.specular"), 0.9f);

		glBindVertexArray(VAO);
		glDrawArrays(GL_TRIANGLES, 0, 36);
		glBindVertexArray(0);
		glfwSwapBuffers(window);
	}
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	ourShader.~Shader();
	glfwTerminate();
	return 0;
}

void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, GL_TRUE);
	}
	if (key >= 0 && key < 1024)
	{
		if (action == GLFW_PRESS)
			keys[key] = true;
		else if (action == GLFW_RELEASE)
			keys[key] = false;
	}
}

void DoMovement()
{//镜头移动
	if (keys[GLFW_KEY_W] ) {
		camera.ProcessKeyboard(FORWARD, deltaTime);
	}
	if (keys[GLFW_KEY_S] ) {
		camera.ProcessKeyboard(BACKWARD, deltaTime);
	}
	if (keys[GLFW_KEY_A] ) {
		camera.ProcessKeyboard(LEFT, deltaTime);
	}
	if (keys[GLFW_KEY_D] ) {
		camera.ProcessKeyboard(RIGHT, deltaTime);
	}
}

void MouseCallback(GLFWwindow* window, double xPos, double yPos)
{
	if (firstMouse)
	{
		lastX = xPos;
		lastY = yPos;
		firstMouse = false;
	}
	GLfloat xOffset = xPos - lastX;
	GLfloat yOffset = lastY - yPos;

	lastX = xPos;
	lastY = yPos;
	//Process the camera direction
	camera.ProcessMouseMovement(xOffset, yOffset);
}

void ObjectMovement(GLfloat& xPos, GLfloat& yPos,GLfloat deltaTime)
{//物体移动
	GLfloat velocity =10.0f * deltaTime;
	if ( keys[GLFW_KEY_UP]) {
		yPos += 1.0f * velocity;
	}
	if ( keys[GLFW_KEY_DOWN]) {
		yPos -= 1.0f * velocity;
	}
	if ( keys[GLFW_KEY_LEFT]) {
		xPos -= 1.0f * velocity;
	}
	if ( keys[GLFW_KEY_RIGHT]) {
		xPos += 1.0f * velocity;
	}
}

void ScrollCallback(GLFWwindow* window, double xOffset, double yOffest)
{

}//滚轮操作暂时没写

滚轮操作可以参考wonz哥
需要在camera中添加一个函数即可

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岚-岚岚岚岚岚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值