👏

OBJ file OpenGL (調整中)

2024/11/17に公開
#include <iostream>
#include <sstream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include"stb_image/stb_image.h"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <fstream>
#include <vector>
#include <string>

//#include "Camera.h"

int gWindowWidth = 1024, gWindowHeight = 768;
GLFWwindow* gWindow = NULL;

//FPSCamera fpsCamera(glm::vec3(0.0f, 0.0f, 5.0f),
//	glm::vec3(1.0, 1.0, 1.0));

glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, -2.0f);
glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraDirection = cameraPos - cameraTarget;
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
glm::vec3 cameraUp = glm::normalize(glm::cross(cameraDirection, cameraRight));

const double ZOOM_SENSITIVITY = -1;
const float MOVE_SPEED = 3.0;
const float MOUSE_SENSITIVITY = 0.03f;

float gRadius = 10.0f, gYaw = 0.0f, gPitch = 0.0f;
float gFOV = 45.0f;

struct Vertex
{
	glm::vec3 position;
	glm::vec2 texCoords;
};

std::vector<Vertex> mVertices;
std::vector<GLfloat> vertices;
std::vector<GLint> indices;

const GLchar* vertexShaderSrc =
"#version 330 core \n"
"layout (location = 0) in vec3 pos;"
"layout (location = 1) in vec2 texCoord;"
"out vec2 TexCoord;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main()"
"{"
"    gl_Position = projection * view * model * vec4(pos, 1.0f);"
"    TexCoord = texCoord;                                                      "
"}";

const GLchar* fragmentShaderSrc =
"#version 330 core \n"
"uniform vec4 vertColor;"
"out vec4 frag_color;"
"void main()"
"{"
"    frag_color = vertColor;"
"}";



void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, GL_TRUE);
	}
}
void glfw_OnFramebufferSize(GLFWwindow* window, int width, int height)
{
	gWindowWidth = width;
	gWindowHeight = height;
	glViewport(0, 0, gWindowWidth, gWindowHeight);
}

void glfw_onMouseMove(GLFWwindow* window, double posX, double posY)
{
	static glm::vec2 lastMousePos = glm::vec2(0, 0);

	if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == 1)
		if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) != 1)
		{
			// Camera orientation
			double yaw = (float)(gWindowWidth / 2.0 - posX) * MOUSE_SENSITIVITY;
			double pitch = (float)(gWindowHeight / 2.0 - posY) * MOUSE_SENSITIVITY;
			gYaw += glm::radians(yaw);
			gPitch += glm::radians(pitch);
			// Constrain the pitch
			gPitch = glm::clamp(gPitch, -glm::pi<float>() / 2.0f + 0.1f, glm::pi<float>() / 2.0f - 0.1f);
			if (gYaw > glm::two_pi<float>())
				gYaw -= glm::two_pi<float>();
			else if (gYaw < 0.0)
				gYaw += glm::two_pi<float>();
		}

	if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == 1)
	{
		float dx = 0.01f * ((float)posX - lastMousePos.x);
		float dy = 0.01f * ((float)posY - lastMousePos.y);
		//gRadius += dx - dy;
	}
	lastMousePos.x = (float)posX;
	lastMousePos.y = (float)posY;
	glfwSetCursorPos(gWindow, gWindowWidth / 2.0, gWindowHeight / 2.0);
}
void glfw_onMouseScroll(GLFWwindow* window, double deltaX, double deltaY)
{
	double fov = gFOV + deltaY * ZOOM_SENSITIVITY;
	fov = glm::clamp(fov, 1.0, 120.0);
	gFOV = fov;
	//deltaYはスクロールの方向を示します。正なら上、負なら下です。
	//gRadius -= (float)deltaY * 0.5f;  // スクロール方向で半径を増減
	//if (gRadius < 1.0f) gRadius = 1.0f; // 半径が小さくなりすぎないように制限
}

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);

	gWindow = glfwCreateWindow(gWindowWidth, gWindowHeight, "Window", NULL, NULL);
	glfwMakeContextCurrent(gWindow);
	glewExperimental = GL_TRUE;
	glewInit();

	glfwSetKeyCallback(gWindow, glfw_onKey);
	glfwSetFramebufferSizeCallback(gWindow, glfw_OnFramebufferSize);
	//glfwSetCursorPosCallback(gWindow, glfw_onMouseMove);
	glfwSetScrollCallback(gWindow, glfw_onMouseScroll);

	// Hides and grabs cursor, unlimited movement
	glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	glfwSetCursorPos(gWindow, gWindowWidth / 2.0, gWindowHeight / 2.0);

	glClearColor(0.23f, 0.38f, 0.47f, 1.0f);

	glViewport(0, 0, gWindowWidth, gWindowHeight);

	glEnable(GL_DEPTH_TEST);
	//////////////////////////////////////
	/////OBJ file import
	const std::string filename = "models/robot.obj";
	if (filename.find(".obj") == std::string::npos) return 0;

	std::ifstream fin(filename, std::ios::in);
	if (!fin)
	{
		std::cerr << "Cannot open " << filename << std::endl;
		return 0;
	}

	std::cout << "Loading OBJ file " << filename << " ..." << std::endl;
	std::string lineBuffer;
	GLuint faceCount = 0;
	while (std::getline(fin, lineBuffer))
	{
		if (lineBuffer.substr(0, 2) == "v ")
		{
			std::istringstream v(lineBuffer.substr(2));
			glm::vec3 vertex;
			v >> vertex.x >> vertex.y >> vertex.z;
			vertices.push_back(vertex.x);
			vertices.push_back(vertex.y);
			vertices.push_back(vertex.z);

		}
		else if (lineBuffer.substr(0, 2) == "f ")
		{
			int p1, p2, p3; //to store mesh index
			int t1, t2, t3;
			int n1, n2, n3;
			const char* face = lineBuffer.c_str();
			int match = sscanf_s(face, "f %i/%i/%i %i/%i/%i %i/%i/%i",
				&p1, &t1, &n1,
				&p2, &t2, &n2,
				&p3, &t3, &n3);
			if (match != 9)
				std::cout << "Failed to parse OBJ file using our very simple OBJ loader" << std::endl;
			// We are ignoring normals (for now)
			indices.push_back(p1 -1);
			indices.push_back(p2 - 1);
			indices.push_back(p3 - 1);
		}
	}
	fin.close();

	// 頂点データの出力
	std::cout << "Vertices:" << std::endl;
	for (unsigned int i = 0; i < vertices.size() / 3; i++) {
		std::cout << "v " << vertices[i * 3] << " "
			<< vertices[i * 3 + 1] << " "
			<< vertices[i * 3 + 2] << std::endl;
	}

	// インデックスデータの出力
	std::cout << "Indices:" << std::endl;
	for (unsigned int i = 0; i < indices.size() / 3; i++) {
		std::cout << "f " << indices[i * 3] << " "
			<< indices[i * 3 + 1] << " "
			<< indices[i * 3 + 2] << std::endl;
	}
	

	/*
	GLfloat vertices[] = {
	 - 1.000000f, 1.000000f, 1.000000f,
     - 1.000000f, - 1.000000f, 1.000000f,
     - 1.000000f, 1.000000f, - 1.000000f,
     - 1.000000f, - 1.000000f, - 1.000000f,
       1.000000f, 1.000000f, 1.000000f,
       1.000000f, - 1.000000f, 1.000000f,
       1.000000f, 1.000000f, - 1.000000f,
       1.000000f, - 1.000000f, - 1.000000f
	};

	GLuint indices[] = {
		4, 2, 0,
        2, 7, 3,
        6, 5, 7,
        1, 7, 5,
        0, 3, 1,
        4, 1, 5,
        4, 6, 2,
        2, 6, 7,
        6, 4, 5,
        1, 3, 7,
        0, 2, 3,
        4, 0, 1
	};
	*/

	glm::vec3 cubePos = glm::vec3(0.0f, -1.0f, 3.0f);
	glm::vec3 floorPos = glm::vec3(0.0f, -1.0f, 0.0f);

	GLuint vbo, ibo, vao;

	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	// Position attribute
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
	//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)(0));
	glEnableVertexAttribArray(0);


	glGenBuffers(1, &ibo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
	//glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLint), indices.data(), GL_STATIC_DRAW);
	glBindVertexArray(0);

	//////////////////////////////////////////////////////////////////
	GLuint vs = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vs, 1, &vertexShaderSrc, NULL);
	glCompileShader(vs);

	GLint fs = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fs, 1, &fragmentShaderSrc, NULL);
	glCompileShader(fs);

	GLint shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vs);
	glAttachShader(shaderProgram, fs);
	glLinkProgram(shaderProgram);
	GLchar infoLog[512];
	glGetProgramInfoLog(shaderProgram, sizeof(infoLog), NULL, infoLog);
	std::cout << infoLog << std::endl;
	glDeleteShader(vs);
	glDeleteShader(fs);


	double lastTime = glfwGetTime();
	//float cubeAngle = 0.0f;

	while (!glfwWindowShouldClose(gWindow))
	{
		double currentTime = glfwGetTime();
		double deltaTime = currentTime - lastTime;

		// Poll for and process events
		glfwPollEvents();

		////////////////////////////////////////
		// FPS Camera 
		////////////////////////////////////////
		double mouseX, mouseY;
		// Get the current mouse cursor position delta
		glfwGetCursorPos(gWindow, &mouseX, &mouseY);
		double yaw = (float)(gWindowWidth / 2.0 - mouseX) * MOUSE_SENSITIVITY;
		double pitch = (float)(gWindowHeight / 2.0 - mouseY) * MOUSE_SENSITIVITY;
		gYaw += glm::radians(yaw);
		gPitch += glm::radians(pitch);
		// Constrain the pitch
		gPitch = glm::clamp(gPitch, -glm::pi<float>() / 2.0f + 0.1f,
			glm::pi<float>() / 2.0f - 0.1f);
		// Constraint the yaw [0, 2*pi]
		if (gYaw > glm::two_pi<float>())
			gYaw -= glm::two_pi<float>();
		else if (gYaw < 0.0)
			gYaw += glm::two_pi<float>();

		glm::vec3 look;
		look.x = cosf(gPitch) * sinf(gYaw);
		look.y = sinf(gPitch);
		look.z = cosf(gPitch) * cosf(gYaw);
		cameraDirection = glm::normalize(look);
		cameraRight = glm::normalize(glm::cross(up, cameraDirection));
		cameraUp = glm::normalize(glm::cross(cameraDirection, cameraRight));

		glfwSetCursorPos(gWindow, gWindowWidth / 2.0, gWindowHeight / 2.0);
		//Forward/backward
		if (glfwGetKey(gWindow, GLFW_KEY_W) == GLFW_PRESS)
			cameraPos += MOVE_SPEED * (float)deltaTime * cameraDirection;
		else if (glfwGetKey(gWindow, GLFW_KEY_S) == GLFW_PRESS)
			cameraPos += MOVE_SPEED * (float)deltaTime * -cameraDirection;
		// Strafe left/right
		if (glfwGetKey(gWindow, GLFW_KEY_A) == GLFW_PRESS)
			cameraPos += MOVE_SPEED * (float)deltaTime * cameraRight;
		else if (glfwGetKey(gWindow, GLFW_KEY_D) == GLFW_PRESS)
			cameraPos += MOVE_SPEED * (float)deltaTime * -cameraRight;
		// Up/down
		if (glfwGetKey(gWindow, GLFW_KEY_Z) == GLFW_PRESS)
			cameraPos += MOVE_SPEED * (float)deltaTime * cameraUp;
		else if (glfwGetKey(gWindow, GLFW_KEY_X) == GLFW_PRESS)
			cameraPos += MOVE_SPEED * (float)deltaTime * -cameraUp;
		////////////////////////////////////////
		////////////////////////////////////////

		glm::mat4 model(1.0), view(1.0), projection(1.0);
		model = glm::translate(model, cubePos);
		view = glm::lookAt(cameraPos, cameraPos + cameraDirection, cameraUp);

		projection = glm::perspective(glm::radians(gFOV),
			(float)gWindowWidth / (float)gWindowHeight, 0.1f, 100.0f);

		// Clear the screen
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


		glUseProgram(shaderProgram);

		GLint ModelLoc = glGetUniformLocation(shaderProgram, "model");
		glUniformMatrix4fv(ModelLoc, 1, GL_FALSE, glm::value_ptr(model));
		GLint ViewlLoc = glGetUniformLocation(shaderProgram, "view");
		glUniformMatrix4fv(ViewlLoc, 1, GL_FALSE, glm::value_ptr(view));
		GLint ProjectionlLoc = glGetUniformLocation(shaderProgram, "projection");
		glUniformMatrix4fv(ProjectionlLoc, 1, GL_FALSE, glm::value_ptr(projection));

		GLint vertColorLoc = glGetUniformLocation(shaderProgram, "vertColor");
		glUniform4f(vertColorLoc, 0.0f, 0.0f, 1.0f, 1.0f);

		glBindVertexArray(vao);
		//glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
		glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);

		glBindVertexArray(0);
		glfwSwapBuffers(gWindow);
		lastTime = currentTime;
	}
	glDeleteProgram(shaderProgram);
	glDeleteVertexArrays(1, &vao);
	glDeleteBuffers(1, &vbo);


	glfwTerminate();

	return 0;
}


Discussion