👏
OBJ file OpenGL (調整中)
#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