#pragma once
#include "glad/glad.h"
#include "KHR/khrplatform.h"
#include "gl/GL.h"
#include "assert.h"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
class GiShaderProgram
{
public:
GiShaderProgram();
GiShaderProgram(const char* vertexPath, const char* fragmentPath);
~GiShaderProgram();
void Release();
void use();
void SetShaderPath(const char* vertexPath, const char* fragmentPath);
void setBool(const std::string& name, bool value) const;
void setInt(const std::string& name, int value) const;
void setFloat(const std::string& name, float value) const;
void setMat4d(const std::string& name, double* pMat) const;
void setMat4f(const std::string& name, float* pMat) const;
void setVec4f(const std::string& name, float* pvec) const;
void setVec3f(const std::string& name, float* pvec) const;
void setVec3f(const std::string& name, float para1, float para2, float para3) const;
private:
void checkCompileErrors(unsigned int shader, std::string type);
unsigned int ID;
};
class GiVAO
{
public:
GiVAO();
GiVAO(double *pPts, size_t iNum, int ipara1, int ipara2, int ipara3);
GiVAO(float* pPts, size_t iNum, int ipara1, int ipara2, int ipara3);
~GiVAO();
void SetPts(double* pPts, size_t iNum, int ipara1, int ipara2, int ipara3);
void SetPts(float* pPts, size_t iNum, int ipara1, int ipara2, int ipara3);
void Use();
void DrawArrays(int type, int iFirst, int iCount);
private:
unsigned int ID;
unsigned int iVBO;
};
class GiFrameBuffer
{
public:
GiFrameBuffer();
GiFrameBuffer(const unsigned int iWidth, const unsigned int iHight);
~GiFrameBuffer();
void Use();
void ResetRect(const unsigned int iWidth, const unsigned int iHight);
unsigned int GetTextureID();
private:
unsigned int ID;
unsigned int iTexturebuffer;
unsigned int iRbo;
};
class GiTexture
{
public:
GiTexture();
GiTexture(const char* vertexPath);
GiTexture(GLbyte* pDIB, int iWidth, int iHeight, int iFormat, bool bIsLinear = true);
~GiTexture();
void Release();
void use();
unsigned int GetID();
private:
unsigned int loadTexture(char const* path);
unsigned int ID;
};
static GLenum CheckGLError()
{
GLenum errorCode;
while ((errorCode = glGetError()) != GL_NO_ERROR)
{
std::string error;
switch (errorCode)
{
case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
}
assert(false);
}
return errorCode;
}
#include "GiShaderProgram.h"
#include "stb_image.h"
GiShaderProgram::GiShaderProgram()
{
ID = 0;
}
GiShaderProgram::GiShaderProgram(const char* vertexPath, const char* fragmentPath)
{
ID = 0;
SetShaderPath(vertexPath, fragmentPath);
}
GiShaderProgram::~GiShaderProgram()
{
if (ID != 0)
{
glDeleteProgram(ID);
CheckGLError();
ID = 0;
}
}
void GiShaderProgram::Release()
{
if (ID != 0)
{
glDeleteProgram(ID);
CheckGLError();
ID = 0;
}
}
void GiShaderProgram::use()
{
glUseProgram(ID);
CheckGLError();
}
void GiShaderProgram::SetShaderPath(const char* vertexPath, const char* fragmentPath)
{
if (ID != 0)
{
glDeleteProgram(ID);
CheckGLError();
ID = 0;
}
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure& e)
{
assert(false);
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
unsigned int vertex, fragment;
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void GiShaderProgram::setBool(const std::string& name, bool value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
CheckGLError();
}
void GiShaderProgram::setInt(const std::string& name, int value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
CheckGLError();
}
void GiShaderProgram::setFloat(const std::string& name, float value) const
{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
CheckGLError();
}
void GiShaderProgram::setMat4d(const std::string& name, double* pMat) const
{
float pData[16];
for (int i = 0; i < 16; i++)
pData[i] = (float)pMat[i];
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, pData);
CheckGLError();
}
void GiShaderProgram::setMat4f(const std::string& name, float* pMat) const
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, pMat);
CheckGLError();
}
void GiShaderProgram::setVec4f(const std::string& name, float* pvec) const
{
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, pvec);
CheckGLError();
}
void GiShaderProgram::setVec3f(const std::string& name, float* pvec) const
{
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, pvec);
CheckGLError();
}
void GiShaderProgram::setVec3f(const std::string& name, float para1, float para2, float para3) const
{
float pPts[3] = { para1,para2,para3 };
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, pPts);
CheckGLError();
}
void GiShaderProgram::checkCompileErrors(unsigned int shader, std::string type)
{
int success;
char infoLog[1024];
if (type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << infoLog << std::endl;
assert(false);
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << infoLog << std::endl;
assert(false);
}
}
}
GiVAO::GiVAO()
{
ID = 0;
}
GiVAO::GiVAO(double* pPts, size_t iNum, int ipara1, int ipara2, int ipara3)
{
glGenVertexArrays(1, &ID);
glGenBuffers(1, &iVBO);
SetPts(pPts, iNum, ipara1, ipara2, ipara3);
}
GiVAO::GiVAO(float* pPts, size_t iNum, int ipara1, int ipara2, int ipara3)
{
glGenVertexArrays(1, &ID);
glGenBuffers(1, &iVBO);
SetPts(pPts, iNum, ipara1, ipara2, ipara3);
}
GiVAO::~GiVAO()
{
if (ID != 0)
{
glDeleteBuffers(1, &iVBO);
glDeleteVertexArrays(1, &ID);
CheckGLError();
ID = 0;
}
}
void GiVAO::SetPts(float* pPts, size_t iNum, int ipara1, int ipara2, int ipara3)
{
if (ID == 0)
{
glGenVertexArrays(1, &ID);
glGenBuffers(1, &iVBO);
}
glBindVertexArray(ID);
glBindBuffer(GL_ARRAY_BUFFER, iVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * iNum, pPts, GL_STATIC_DRAW);
CheckGLError();
if (ipara1 > 0)
{
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, ipara1, GL_FLOAT, GL_FALSE, (ipara1 + ipara2 + ipara3) * sizeof(float), (void*)0);
}
if (ipara2 > 0)
{
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, ipara2, GL_FLOAT, GL_FALSE, (ipara1 + ipara2 + ipara3) * sizeof(float), (void*)(ipara1 * sizeof(float)));
}
if (ipara3 > 0)
{
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, ipara3, GL_FLOAT, GL_FALSE, (ipara1 + ipara2 + ipara3) * sizeof(float), (void*)((ipara1 + ipara2) * sizeof(float)));
}
glBindVertexArray(0);
}
void GiVAO::SetPts(double* pPts, size_t iNum, int ipara1, int ipara2, int ipara3)
{
if (ID == 0)
{
glGenVertexArrays(1, &ID);
glGenBuffers(1, &iVBO);
}
glBindVertexArray(ID);
glBindBuffer(GL_ARRAY_BUFFER, iVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(double) * iNum, pPts, GL_STATIC_DRAW);
if (ipara1 > 0)
{
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, ipara1, GL_DOUBLE, GL_FALSE, (ipara1 + ipara2 + ipara3) * sizeof(double), (void*)0);
}
if (ipara2 > 0)
{
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, ipara2, GL_DOUBLE, GL_FALSE, (ipara1 + ipara2 + ipara3) * sizeof(double), (void*)(ipara1 * sizeof(double)));
}
if (ipara3 > 0)
{
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, ipara3, GL_DOUBLE, GL_FALSE, (ipara1 + ipara2 + ipara3) * sizeof(double), (void*)((ipara1 + ipara2) * sizeof(double)));
}
glBindVertexArray(0);
}
void GiVAO::Use()
{
glBindVertexArray(ID);
}
void GiVAO::DrawArrays(int type, int iFirst, int iCount)
{
Use();
glDrawArrays(type, iFirst, iCount);
}
GiFrameBuffer::GiFrameBuffer()
{
ID = 0;
iTexturebuffer = 0;
iRbo = 0;
}
GiFrameBuffer::GiFrameBuffer(const unsigned int iWidth, const unsigned int iHight)
{
ID = 0;
iTexturebuffer = 0;
iRbo = 0;
ResetRect(iWidth, iHight);
}
GiFrameBuffer::~GiFrameBuffer()
{
if (ID != 0)
{
glDeleteRenderbuffers(1, &iRbo);
glDeleteTextures(1, &iTexturebuffer);
glDeleteFramebuffers(1, &ID);
CheckGLError();
ID = 0;
}
}
void GiFrameBuffer::Use()
{
glBindFramebuffer(GL_FRAMEBUFFER, ID);
CheckGLError();
}
void GiFrameBuffer::ResetRect(const unsigned int iWidth, const unsigned int iHight)
{
if (ID != 0)
{
glDeleteRenderbuffers(1, &iRbo);
glDeleteTextures(1, &iTexturebuffer);
glDeleteFramebuffers(1, &ID);
CheckGLError();
}
glGenFramebuffers(1, &ID);
glBindFramebuffer(GL_FRAMEBUFFER, ID);
glGenTextures(1, &iTexturebuffer);
glBindTexture(GL_TEXTURE_2D, iTexturebuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, iWidth, iHight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, iTexturebuffer, 0);
glGenRenderbuffers(1, &iRbo);
glBindRenderbuffer(GL_RENDERBUFFER, iRbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, iWidth, iHight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, iRbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
assert(false);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
unsigned int GiFrameBuffer::GetTextureID()
{
return iTexturebuffer;
}
GiTexture::GiTexture()
{
ID = 0;
}
GiTexture::GiTexture(const char* path)
{
ID = loadTexture(path);
}
GiTexture::GiTexture(GLbyte* pDIB, int iWidth, int iHeight, int iFormat, bool bIsLinear)
{
glGenTextures(1, &ID);
GLenum format;
if (iFormat == 1)
format = GL_RED;
else if (iFormat == 2)
format = GL_RGB;
else if (iFormat == 4)
format = GL_RGBA;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ID);
glTexImage2D(GL_TEXTURE_2D, 0, format, iWidth, iHeight, 0, format, GL_UNSIGNED_BYTE, pDIB);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
if (bIsLinear)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
glBindTexture(GL_TEXTURE_2D, 0);
}
GiTexture::~GiTexture()
{
glDeleteTextures(1, &ID);
ID = 0;
}
void GiTexture::Release()
{
glDeleteTextures(1, &ID);
ID = 0;
}
void GiTexture::use()
{
glBindTexture(GL_TEXTURE_2D, ID);
CheckGLError();
}
unsigned int GiTexture::loadTexture(char const* path)
{
unsigned int textureID = 0;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char* data = stbi_load(path, &width, &height, &nrComponents, 0);
if (data)
{
GLenum format;
if (nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
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_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(data);
}
else
{
std::cout << "Texture failed to load at path: " << path << std::endl;
stbi_image_free(data);
}
return textureID;
}
unsigned int GiTexture::GetID()
{
return ID;
}
#pragma once
#include "GiShaderProgram.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "glm/gtc/type_ptr.hpp"
#include <string>
#include <vector>
using namespace std;
static double dPI = 3.1415926;
struct XYZ
{
XYZ(double dx, double dy, double dz) { x = dx; y = dy; z = dz; }
double x;
double y;
double z;
};
struct Vertex
{
double Position[3];
double Normal[3];
double TexCoords[2];
};
struct Material {
bool bTextureMaterial;
glm::vec3 ambient;
glm::vec3 diffuse;
glm::vec3 specular;
GiTexture* pDiffuseT;
GiTexture* pSpecularT;
float shininess;
};
class GiMesh
{
public:
GiMesh();
GiMesh(const vector<Vertex>& vertices, const vector<unsigned int>& indices, const vector<GiTexture*>& textures);
virtual ~GiMesh();
virtual void SetTexture(GiTexture* pTextureDiffuse, GiTexture* pTextureSpecular);
virtual void SetColor(double dR, double dG, double dB);
void SetData(const vector<Vertex>& vertices, const vector<unsigned int>& indices, const vector<GiTexture*>& textures);
virtual void Draw(GiShaderProgram& shader);
protected:
unsigned int VAO;
unsigned int VBO;
unsigned int EBO;
vector<Vertex> m_vecVertices;
vector<unsigned int> m_vecIndices;
Material m_material;
bool m_bShaderAsFace;
void SetupMesh();
};
class Gi3dBox : public GiMesh
{
public:
Gi3dBox() {}
Gi3dBox(double xLen, double yLen, double zLen)
{
Create(xLen, yLen, zLen);
}
virtual ~Gi3dBox(){}
private:
bool Create(double xLen, double yLen, double zLen);
};
class GiSphere : public GiMesh
{
public:
GiSphere() {}
GiSphere(double radius)
{
Create(radius);
}
virtual ~GiSphere() {}
virtual void Draw(GiShaderProgram& shader);
private:
bool Create(double radius);
};
class GiTorus : public GiMesh
{
public:
GiTorus() {}
GiTorus(double majorRadius, double minorRadius)
{
Create(majorRadius, minorRadius);
}
virtual ~GiTorus() {}
private:
bool Create(double majorRadius, double minorRadius);
};
class GiCylinder : public GiMesh
{
public:
GiCylinder() {}
GiCylinder(double radius, double Height)
{
Create(radius, Height);
}
virtual ~GiCylinder() {}
private:
bool Create(double radius, double Height);
};
class GiCone : public GiMesh
{
public:
GiCone() {}
GiCone(double radius, double Height)
{
Create(radius, Height);
}
virtual ~GiCone() {}
private:
bool Create(double radius, double Height);
};
#include "GiObject3d.h"
GiMesh::GiMesh()
{
VAO = 0;
VBO = 0;
EBO = 0;
m_material.bTextureMaterial = false;
m_material.ambient = glm::vec3(1.0f, 1.0f, 1.0f);
m_material.diffuse = glm::vec3(1.0f, 1.0f, 1.0f);
m_material.specular = glm::vec3(0.2f, 0.2f, 0.2f);
m_material.shininess = 32.0f;
m_bShaderAsFace = false;
}
GiMesh::GiMesh(const vector<Vertex>& vertices, const vector<unsigned int>& indices, const vector<GiTexture*>& textures)
{
m_material.bTextureMaterial = false;
m_material.ambient = glm::vec3(1.0f, 1.0f, 1.0f);
m_material.diffuse = glm::vec3(1.0f, 1.0f, 1.0f);
m_material.specular = glm::vec3(0.2f, 0.2f, 0.2f);
m_material.shininess = 32.0f;
SetData(vertices, indices, textures);
}
GiMesh::~GiMesh()
{
if (VAO != 0)
{
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteVertexArrays(1, &VAO);
CheckGLError();
VAO = 0;
VBO = 0;
EBO = 0;
}
}
void GiMesh::SetTexture(GiTexture* pTextureDiffuse, GiTexture* pTextureSpecular)
{
m_material.pDiffuseT = pTextureDiffuse;
m_material.pSpecularT = pTextureSpecular;
m_material.bTextureMaterial = true;
}
void GiMesh::SetColor(double dR, double dG, double dB)
{
m_material.ambient = glm::vec3(dR, dG, dB);
m_material.diffuse = glm::vec3(dR, dG, dB);
m_material.specular = glm::vec3(dR, dG, dB);
m_material.bTextureMaterial = false;
}
void GiMesh::SetData(const vector<Vertex>& vertices, const vector<unsigned int>& indices, const vector<GiTexture*>& textures)
{
m_vecVertices = vertices;
m_vecIndices = indices;
if (textures.size() >= 2)
{
SetTexture(textures[0], textures[1]);
}
SetupMesh();
}
void GiMesh::Draw(GiShaderProgram& shader)
{
if (m_vecVertices.size() == 0 || m_vecIndices.size() == 0)
return;
shader.setInt("material.bTextureMaterial", int(m_material.bTextureMaterial));
if (m_material.bTextureMaterial)
{
glActiveTexture(GL_TEXTURE0);
shader.setInt("material.diffuseT", 0);
m_material.pDiffuseT->use();
glActiveTexture(GL_TEXTURE1);
shader.setInt("material.specularT", 1);
m_material.pSpecularT->use();
}
else
{
shader.setVec3f("material.ambient", glm::value_ptr(m_material.ambient));
shader.setVec3f("material.diffuse", glm::value_ptr(m_material.diffuse));
shader.setVec3f("material.specular", glm::value_ptr(m_material.specular));
shader.setFloat("material.shininess", m_material.shininess);
}
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(m_vecIndices.size()), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glActiveTexture(GL_TEXTURE0);
}
void GiMesh::SetupMesh()
{
if (m_vecVertices.size() == 0 || m_vecIndices.size() == 0)
return;
if (VAO != 0)
{
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteVertexArrays(1, &VAO);
CheckGLError();
VAO = 0;
VBO = 0;
EBO = 0;
}
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, m_vecVertices.size() * sizeof(Vertex), &m_vecVertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_vecIndices.size() * sizeof(unsigned int), &m_vecIndices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_DOUBLE, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_DOUBLE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_DOUBLE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
glBindVertexArray(0);
}
bool Gi3dBox::Create(double xLen, double yLen, double zLen)
{
xLen *= 0.5;
yLen *= 0.5;
zLen *= 0.5;
{
Vertex vertex1 = { xLen, -yLen, -zLen, 0.0, 0.0, -1.0, 0.0, 0.0 };
m_vecVertices.push_back(vertex1);
Vertex vertex2 = { -xLen, -yLen, -zLen, 0.0, 0.0, -1.0, 1.0, 0.0 };
m_vecVertices.push_back(vertex2);
Vertex vertex3 = { -xLen, yLen, -zLen, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f };
m_vecVertices.push_back(vertex3);
Vertex vertex4 = { xLen, yLen, -zLen, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f };
m_vecVertices.push_back(vertex4);
Vertex vertex5 = { -xLen, -yLen, zLen, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
m_vecVertices.push_back(vertex5);
Vertex vertex6 = { xLen, -yLen, zLen, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f };
m_vecVertices.push_back(vertex6);
Vertex vertex7 = { xLen, yLen, zLen, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f };
m_vecVertices.push_back(vertex7);
Vertex vertex8 = { -xLen, yLen, zLen, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f };
m_vecVertices.push_back(vertex8);
Vertex vertex9 = { -xLen, -yLen, -zLen, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f };
m_vecVertices.push_back(vertex9);
Vertex vertex10 = { -xLen, -yLen, zLen, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
m_vecVertices.push_back(vertex10);
Vertex vertex11 = { -xLen, yLen, zLen, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f };
m_vecVertices.push_back(vertex11);
Vertex vertex12 = { -xLen, yLen, -zLen, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
m_vecVertices.push_back(vertex12);
Vertex vertex13 = { xLen, -yLen, zLen, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f };
m_vecVertices.push_back(vertex13);
Vertex vertex14 = { xLen, -yLen, -zLen, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
m_vecVertices.push_back(vertex14);
Vertex vertex15 = { xLen, yLen, -zLen, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f };
m_vecVertices.push_back(vertex15);
Vertex vertex16 = { xLen, yLen, zLen, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
m_vecVertices.push_back(vertex16);
Vertex vertex17 = { -xLen, -yLen, -zLen, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f };
m_vecVertices.push_back(vertex17);
Vertex vertex18 = { xLen, -yLen, -zLen, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
m_vecVertices.push_back(vertex18);
Vertex vertex19 = { xLen, -yLen, zLen, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f };
m_vecVertices.push_back(vertex19);
Vertex vertex20 = { -xLen, -yLen, zLen, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f };
m_vecVertices.push_back(vertex20);
Vertex vertex21 = { -xLen, yLen, zLen, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
m_vecVertices.push_back(vertex21);
Vertex vertex22 = { xLen, yLen, zLen, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f };
m_vecVertices.push_back(vertex22);
Vertex vertex23 = { xLen, yLen, -zLen, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
m_vecVertices.push_back(vertex23);
Vertex vertex24 = { -xLen, yLen, -zLen, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f };
m_vecVertices.push_back(vertex24);
}
unsigned int index[6] = { 0, 1, 3, 1, 2, 3 };
for (size_t i = 0; i < 6; i++)
{
for (size_t j = 0; j < 6; j++)
m_vecIndices.push_back(unsigned int(i * 4 + index[j]));
}
SetupMesh();
return true;
}
bool GiSphere::Create(double radius)
{
long lNum = 10;
double dT = dPI * 0.5 / lNum;
lNum += 1;
long lNumY = lNum;
glm::dmat4 mat1 = glm::rotate(glm::dmat4(1.0), dT, glm::dvec3(1.0, 0.0, 0.0));
vector<XYZ> vecPts;
vecPts.push_back(XYZ(0.0, radius, 0.0));
for (long i = 1; i < lNumY; i++)
{
glm::dvec4 pt1(vecPts[i - 1].x, vecPts[i - 1].y, vecPts[i - 1].z, 1.0);
glm::dvec4 pt2 = mat1 * pt1;
vecPts.push_back(XYZ(pt2.x, pt2.y, pt2.z));
}
glm::dmat4 mat2 = glm::rotate(glm::dmat4(1.0), dT, glm::dvec3(0.0, 1.0, 0.0));
for (long i = 1; i < lNum; i++)
{
for (long j = 0; j < lNumY; j++)
{
long lTemp = (i - 1) * lNumY;
glm::dvec4 pt1(vecPts[lTemp + j].x, vecPts[lTemp + j].y, vecPts[lTemp + j].z, 1.0);
glm::dvec4 pt2 = mat2 * pt1;
vecPts.push_back(XYZ(pt2.x, pt2.y, pt2.z));
}
}
for (long i = 0; i < lNum - 1; i++)
{
for (long j = 0; j < lNumY - 1; j++)
{
long lPos[4] = { i * lNumY + j, i * lNumY + j + 1, (i + 1) * lNumY + j + 1, (i + 1) * lNumY + j };
glm::dvec2 textCoords[4] = { glm::dvec2(0.0f, 0.0f), glm::dvec2(1.0f, 0.0f), glm::dvec2(1.0f, 1.0f), glm::dvec2(0.0f, 1.0f) };
glm::dvec3 ptBound[4];
for (int pos = 0; pos < 4; pos++)
{
long lnow = lPos[pos];
ptBound[pos] = glm::dvec3(vecPts[lnow].x, vecPts[lnow].y, vecPts[lnow].z);
}
glm::dvec3 norm = glm::cross(ptBound[2] - ptBound[1], ptBound[3] - ptBound[2]);
for (int pos = 0; pos < 4; pos++)
{
if (!m_bShaderAsFace)
norm = ptBound[pos];
Vertex vertex1 = { ptBound[pos].x, ptBound[pos].y, ptBound[pos].z,
norm.x, norm.y, norm.z, textCoords[pos].x, textCoords[pos].y };
m_vecVertices.push_back(vertex1);
}
}
}
unsigned int index[6] = { 0, 1, 3, 1, 2, 3 };
for (size_t i = 0; i < (lNum - 1) * (lNumY - 1); i++)
{
for (size_t j = 0; j < 6; j++)
m_vecIndices.push_back(unsigned int(i * 4 + index[j]));
}
SetupMesh();
return true;
}
void GiSphere::Draw(GiShaderProgram& shader)
{
GiMesh::Draw(shader);
if (m_vecVertices.size() == 0 || m_vecIndices.size() == 0)
return;
glBindVertexArray(VAO);
glm::dmat4 mats[7] = { glm::dmat4(1.0) };
mats[0][0][0] = -1;
mats[1][1][1] = -1;
mats[2][0][0] = -1;
mats[2][1][1] = -1;
mats[3][2][2] = -1;
mats[4][2][2] = -1;
mats[4][1][1] = -1;
mats[5][0][0] = -1;
mats[5][2][2] = -1;
mats[6][0][0] = -1;
mats[6][1][1] = -1;
mats[6][2][2] = -1;
for (int i = 0; i < 7; i++)
{
shader.setMat4d("innerMat", glm::value_ptr(mats[i]));
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(m_vecIndices.size()), GL_UNSIGNED_INT, 0);
}
glm::dmat4 mat = glm::dmat4(1.0);
shader.setMat4d("innerMat", glm::value_ptr(mat));
glBindVertexArray(0);
glActiveTexture(GL_TEXTURE0);
}
bool GiTorus::Create(double majorRadius, double minorRadius)
{
double dMidRad = (majorRadius + minorRadius) * 0.5;
double dSectionRad = (majorRadius - minorRadius) * 0.5;
long lNum = 40;
double dT = dPI * 2.0 / lNum;
long lNumY = lNum / 2 + 1;
lNum += 1;
vector<glm::dvec3> vecNorms;
glm::dmat4 mat1 = glm::rotate(glm::dmat4(1.0), dT * 2.0, glm::dvec3(0.0f, 1.0f, 0.0f));
vector<XYZ> vecPts;
vecPts.push_back(XYZ(dMidRad + dSectionRad, 0.0, 0.0));
if (!m_bShaderAsFace)
vecNorms.push_back(glm::dvec3(dSectionRad, 0.0, 0.0));
for (long i = 1; i < lNumY; i++)
{
glm::dvec4 pt1(vecPts[i - 1].x - dMidRad, vecPts[i - 1].y, vecPts[i - 1].z, 1.0);
glm::dvec4 pt2 = mat1 * pt1;
vecPts.push_back(XYZ(pt2.x + dMidRad, pt2.y, pt2.z));
if (!m_bShaderAsFace)
vecNorms.push_back(glm::dvec3(pt2));
}
glm::dmat4 mat2 = glm::rotate(glm::dmat4(1.0), dT, glm::dvec3(0.0, 0.0, 1.0));
for (long i = 1; i < lNum; i++)
{
for (long j = 0; j < lNumY; j++)
{
long lTemp = (i - 1) * lNumY;
glm::dvec4 pt1(vecPts[lTemp + j].x, vecPts[lTemp + j].y, vecPts[lTemp + j].z, 1.0);
glm::dvec4 pt2 = mat2 * pt1;
vecPts.push_back(XYZ(pt2.x, pt2.y, pt2.z));
if (!m_bShaderAsFace)
{
glm::dvec4 pt3(vecNorms[lTemp + j].x, vecNorms[lTemp + j].y, vecNorms[lTemp + j].z, 1.0);
glm::dvec4 pt4 = mat2 * pt3;
vecNorms.push_back(glm::dvec3(pt4));
}
}
}
for (long i = 0; i < lNum - 1; i++)
{
for (long j = 0; j < lNumY - 1; j++)
{
long lPos[4] = { i * lNumY + j, i * lNumY + j + 1, (i + 1) * lNumY + j + 1, (i + 1) * lNumY + j };
glm::dvec2 textCoords[4] = { glm::dvec2(0.0f, 0.0f), glm::dvec2(1.0f, 0.0f), glm::dvec2(1.0f, 1.0f), glm::dvec2(0.0f, 1.0f) };
glm::dvec3 ptBound[4], norms[4];
for (int pos = 0; pos < 4; pos++)
{
long lnow = lPos[pos];
ptBound[pos] = glm::dvec3(vecPts[lnow].x, vecPts[lnow].y, vecPts[lnow].z);
if (!m_bShaderAsFace)
norms[pos] = vecNorms[lnow];
}
glm::dvec3 norm;
if (m_bShaderAsFace)
norm = glm::cross(ptBound[2] - ptBound[1], ptBound[3] - ptBound[2]);
for (int pos = 0; pos < 4; pos++)
{
if (!m_bShaderAsFace)
norm = norms[pos];
Vertex vertex1 = { ptBound[pos].x, ptBound[pos].y, ptBound[pos].z,
norm.x, norm.y, norm.z, textCoords[pos].x, textCoords[pos].y };
m_vecVertices.push_back(vertex1);
}
}
}
unsigned int index[6] = { 0, 1, 3, 1, 2, 3 };
for (size_t i = 0; i < (lNum - 1) * (lNumY - 1); i++)
{
for (size_t j = 0; j < 6; j++)
m_vecIndices.push_back(unsigned int(i * 4 + index[j]));
}
SetupMesh();
return true;
}
bool GiCylinder::Create(double radius, double Height)
{
long lNum = 40;
double dT = dPI * 2.0 / lNum;
lNum += 1;
vector<glm::dvec3> vecNorms;
glm::dmat4 mat1 = glm::rotate(glm::dmat4(1.0), dT, glm::dvec3(0.0, 0.0, 1.0));
vector<XYZ> vecPts;
vecPts.push_back(XYZ(radius, 0.0, 0.0));
if (!m_bShaderAsFace)
vecNorms.push_back(glm::dvec3(radius, 0.0, 0.0));
for (long i = 1; i < lNum; i++)
{
glm::dvec4 pt1(vecPts[i - 1].x, vecPts[i - 1].y, vecPts[i - 1].z, 1.0);
glm::dvec4 pt2 = mat1 * pt1;
vecPts.push_back(XYZ(pt2.x, pt2.y, pt2.z));
if (!m_bShaderAsFace)
vecNorms.push_back(glm::dvec3(pt2));
}
glm::dmat4 mat2 = glm::translate(glm::dmat4(1.0), glm::dvec3(0.0, 0.0, Height));
for (long j = 0; j < lNum; j++)
{
glm::dvec4 pt1(vecPts[j].x, vecPts[j].y, vecPts[j].z, 1.0);
glm::dvec4 pt2 = mat2 * pt1;
vecPts.push_back(XYZ(pt2.x, pt2.y, pt2.z));
if (!m_bShaderAsFace)
{
vecNorms.push_back(vecNorms[j]);
}
}
for (long i = 0; i < 2 - 1; i++)
{
for (long j = 0; j < lNum - 1; j++)
{
long lPos[4] = { i * lNum + j, i * lNum + j + 1, (i + 1) * lNum + j + 1, (i + 1) * lNum + j };
glm::dvec2 textCoords[4] = { glm::dvec2(0.0f, 0.0f), glm::dvec2(1.0f, 0.0f), glm::dvec2(1.0f, 1.0f), glm::dvec2(0.0f, 1.0f) };
glm::dvec3 ptBound[4], norms[4];
for (int pos = 0; pos < 4; pos++)
{
long lnow = lPos[pos];
ptBound[pos] = glm::dvec3(vecPts[lnow].x, vecPts[lnow].y, vecPts[lnow].z);
if (!m_bShaderAsFace)
norms[pos] = vecNorms[lnow];
}
glm::dvec3 norm;
if (m_bShaderAsFace)
norm = glm::cross(ptBound[2] - ptBound[1], ptBound[3] - ptBound[2]);
for (int pos = 0; pos < 4; pos++)
{
if (!m_bShaderAsFace)
norm = norms[pos];
Vertex vertex1 = { ptBound[pos].x, ptBound[pos].y, ptBound[pos].z,
norm.x, norm.y, norm.z, textCoords[pos].x, textCoords[pos].y };
m_vecVertices.push_back(vertex1);
}
}
}
unsigned int index[6] = { 0, 1, 3, 1, 2, 3 };
for (size_t i = 0; i < (2 - 1) * (lNum - 1); i++)
{
for (size_t j = 0; j < 6; j++)
m_vecIndices.push_back(unsigned int(i * 4 + index[j]));
}
for (long j = 0; j < 2; j++)
{
glm::dvec3 norm(0.0, 0.0, -1.0);
long iBegin = 0;
if (j == 1)
{
norm = glm::dvec3(0.0, 0.0, 1.0);
iBegin = lNum;
}
for (long i = iBegin; i < iBegin + lNum - 1; i++)
{
Vertex vertex1 = { 0.0, 0.0, j == 1 ? Height : 0.0, norm.x, norm.y, norm.z, 0.0, 0.0 };
Vertex vertex2 = { vecPts[i].x, vecPts[i].y, vecPts[i].z, norm.x, norm.y, norm.z, 1.0, 0.0 };
Vertex vertex3 = { vecPts[i + 1].x, vecPts[i + 1].y, vecPts[i + 1].z, norm.x, norm.y, norm.z, 0.5, 1.0 };
m_vecVertices.push_back(vertex1);
if (j == 1)
{
m_vecVertices.push_back(vertex2);
m_vecVertices.push_back(vertex3);
}
else
{
m_vecVertices.push_back(vertex3);
m_vecVertices.push_back(vertex2);
}
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 3));
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 2));
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 1));
}
}
SetupMesh();
return true;
}
bool GiCone::Create(double radius, double Height)
{
long lNum = 40;
double dT = dPI * 2.0 / lNum;
lNum += 1;
glm::dmat4 mat1 = glm::rotate(glm::dmat4(1.0), dT, glm::dvec3(0.0, 0.0, 1.0));
vector<XYZ> vecPts;
vecPts.push_back(XYZ(radius, 0.0, 0.0));
for (long i = 1; i < lNum; i++)
{
glm::dvec4 pt1(vecPts[i - 1].x, vecPts[i - 1].y, vecPts[i - 1].z, 1.0);
glm::dvec4 pt2 = mat1 * pt1;
vecPts.push_back(XYZ(pt2.x, pt2.y, pt2.z));
}
glm::dmat4 mat2 = glm::rotate(glm::dmat4(1.0), dT, glm::dvec3(0.0, 0.0, 1.0));
glm::dmat4 mat3 = glm::rotate(glm::dmat4(1.0), 0.5 * dT, glm::dvec3(0.0, 0.0, 1.0));
for (long i = 0; i < lNum - 1; i++)
{
glm::dvec4 dir1, dir2, dir3;
if (m_bShaderAsFace)
{
glm::dvec3 v1 = glm::dvec3(vecPts[i + 1].x - vecPts[i].x, vecPts[i + 1].y - vecPts[i].y, vecPts[i + 1].z - vecPts[i].z);
glm::dvec3 v2 = glm::dvec3(-vecPts[i + 1].x, -vecPts[i + 1].y, Height - vecPts[i + 1].z);
dir1 = glm::dvec4(glm::cross(v1, v2), 1.0);
dir2 = dir1;
dir3 = dir1;
}
else
{
if (i == 0)
{
dir1 = glm::dvec4(Height, 0.0, radius, 1.0);
dir2 = mat2 * dir1;
dir3 = mat3 * dir1;
}
else
{
double* pNorm = m_vecVertices[(i - 1) * 3 + 1].Normal;
dir1 = glm::dvec4(pNorm[0], pNorm[1], pNorm[2], 1.0);
dir2 = mat2 * dir1;
dir3 = mat3 * dir1;
}
}
Vertex vertex1 = { vecPts[i].x, vecPts[i].y, vecPts[i].z, dir1.x, dir1.y, dir1.z, 0.0, 0.0 };
Vertex vertex2 = { vecPts[i + 1].x, vecPts[i + 1].y, vecPts[i + 1].z, dir2.x, dir2.y, dir2.z, 1.0, 0.0 };
Vertex vertex3 = { 0.0, 0.0, Height, dir3.x, dir3.y, dir3.z, 0.5, 1.0 };
m_vecVertices.push_back(vertex1);
m_vecVertices.push_back(vertex2);
m_vecVertices.push_back(vertex3);
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 3));
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 2));
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 1));
}
for (long i = 0; i < lNum - 1; i++)
{
Vertex vertex1 = { 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0 };
Vertex vertex2 = { vecPts[i].x, vecPts[i].y, vecPts[i].z, 0.0, 0.0, -1.0, 1.0, 0.0 };
Vertex vertex3 = { vecPts[i + 1].x, vecPts[i + 1].y, vecPts[i + 1].z, 0.0, 0.0, -1.0, 0.5, 1.0 };
m_vecVertices.push_back(vertex1);
m_vecVertices.push_back(vertex3);
m_vecVertices.push_back(vertex2);
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 3));
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 2));
m_vecIndices.push_back(unsigned int(m_vecVertices.size() - 1));
}
SetupMesh();
return true;
}
#ifndef CAMERA_H
#define CAMERA_H
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
enum Camera_Movement {
FORWARD,
BACKWARD,
LEFT,
RIGHT
};
const float YAW = 0.0f;
const float PITCH = 0.0f;
const float SENSITIVITY = 0.01f;
class GiCamera
{
public:
glm::vec3 m_ptEye;
glm::vec3 m_ptCenter;
glm::vec3 m_ptUp;
glm::vec3 frontOld;
float Yaw;
float Pitch;
float MouseSensitivity;
GiCamera(glm::vec3 eye = glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3 center = 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) : MouseSensitivity(SENSITIVITY)
{
m_ptEye = eye;
m_ptCenter = center;
m_ptUp = up;
frontOld = m_ptCenter - m_ptEye;
glm::normalize(frontOld);
Yaw = yaw;
Pitch = pitch;
updateCameraVectors();
}
glm::mat4 GetViewMatrix()
{
glm::vec3 lookAt(0.0, 0.0, 0.0);
return glm::lookAt(m_ptEye, m_ptCenter, m_ptUp);
}
void ProcessMouseMovement(float xoffset, float yoffset, bool isMButtonDown = false)
{
if (!isMButtonDown)
{
xoffset *= MouseSensitivity;
yoffset *= MouseSensitivity;
Yaw = xoffset;
Pitch = yoffset;
}
else
{
}
updateCameraVectors();
}
void ProcessMouseScroll(float yoffset)
{
glm::vec3 dir = m_ptEye - m_ptCenter;
if (yoffset < 0)
{
dir *= 1.5;
m_ptEye = m_ptCenter + dir;
}
else
{
dir *= 0.667;
m_ptEye = m_ptCenter + dir;
}
}
private:
glm::dmat4 getRotMat(double axisX, double axisY, double axisZ, double angle)
{
if (axisX < 1e-12 && axisY < 1e-12 && axisZ < 1e-12)
{
glm::dmat4 mat(1);
return mat;
}
glm::dvec3 RotAxis = glm::dvec3(axisX, axisY, axisZ);
RotAxis = glm::normalize(RotAxis);
axisX = RotAxis.x;
axisY = RotAxis.y;
axisZ = RotAxis.z;
double dAngle = angle * 0.5;
double dSin = sin(dAngle);
double dCos = cos(dAngle);
glm::dvec4 v(axisX * dSin, axisY * dSin, axisZ * dSin, dCos);
double wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
x2 = v.x + v.x;
y2 = v.y + v.y;
z2 = v.z + v.z;
xx = v.x * x2;
xy = v.x * y2;
xz = v.x * z2;
yy = v.y * y2;
yz = v.y * z2;
zz = v.z * z2;
wx = v.w * x2;
wy = v.w * y2;
wz = v.w * z2;
glm::dmat4 mat(1.0);
mat[0][0] = 1.0f - (yy + zz);
mat[1][0] = xy - wz;
mat[2][0] = xz + wy;
mat[3][0] = 0.0f;
mat[0][1] = xy + wz;
mat[1][1] = 1.0f - (xx + zz);
mat[2][1] = yz - wx;
mat[3][1] = 0.0f;
mat[0][2] = xz - wy;
mat[1][2] = yz + wx;
mat[2][2] = 1.0f - (xx + yy);
mat[3][2] = 0.0f;
return mat;
}
void updateCameraVectors()
{
glm::dmat4 view = glm::lookAt(m_ptEye, m_ptCenter, m_ptUp);
glm::dmat4 viewReverse = glm::inverse(view);
glm::vec4 pt1(0, 0, 0, 0), pt2(Pitch, -Yaw, 0, 0);
pt1 = viewReverse * pt1;
pt2 = viewReverse * pt2;
glm::dvec3 RotAxis = glm::dvec3(pt2.x - pt1.x, pt2.y - pt1.y, pt2.z - pt1.z);
glm::dmat4 mat = getRotMat(RotAxis.x, RotAxis.y, RotAxis.z, sqrt(Pitch * Pitch + Yaw * Yaw));
glm::dvec3 front = glm::dvec3(mat * glm::dvec4(frontOld.x, frontOld.y, frontOld.z, 0.0));
front = glm::normalize(front);
frontOld.x = front.x;
frontOld.y = front.y;
frontOld.z = front.z;
glm::dvec3 upNew = glm::dvec3(mat * glm::dvec4(m_ptUp.x, m_ptUp.y, m_ptUp.z, 0.0));
m_ptUp = upNew;
glm::vec3 dir = m_ptEye - m_ptCenter;
double dLen = sqrt(pow(dir[0], 2) + pow(dir[1], 2) + pow(dir[2], 2));
m_ptEye.x = -front.x * dLen + m_ptCenter.x;
m_ptEye.y = -front.y * dLen + m_ptCenter.y;
m_ptEye.z = -front.z * dLen + m_ptCenter.z;
}
};
#endif
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
#include "windows.h"
#include "GiShaderProgram.h"
#include "GiObject3d.h"
#include "GiCamera.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 mouse_scrollback(GLFWwindow* window, double xoffset, double yoffset);
void DrawFloor(GiShaderProgram& program, GiTexture& texture);
void DrawDrawObjs(GiShaderProgram& program);
int SCR_WIDTH = 800;
int SCR_HEIGHT = 600;
GiCamera 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;
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);
#endif
SCR_WIDTH = GetSystemMetrics(SM_CXSCREEN);
SCR_HEIGHT = GetSystemMetrics(SM_CYSCREEN);
lastX = SCR_WIDTH / 2.0f;
lastY = SCR_HEIGHT / 2.0f;
GLFWwindow* 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);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
glfwTerminate();
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, mouse_scrollback);
char szPath[MAX_PATH] = { 0 };
GetModuleFileNameA(NULL, szPath, MAX_PATH);
std::string strPath(szPath);
strPath = strPath.substr(0, strPath.find_last_of('\\'));
GiShaderProgram program((strPath+"\\shaderLightTexture.vs").c_str(), (strPath+"\\shaderLightTexture.fs").c_str());
program.use();
program.setVec3f("dirLight.direction", -0.1f, -1.0f, -1.0f);
program.setVec3f("dirLight.ambient", 0.2f, 0.2f, 0.2f);
program.setVec3f("dirLight.diffuse", 0.5f, 0.5f, 0.5f);
program.setVec3f("dirLight.specular", 1.0f, 1.0f, 1.0f);
program.setVec3f("viewPos", 0.0f, 0.0f, 1.0f);
GiShaderProgram programTexture((strPath + "\\shaderTexture.vs").c_str(), (strPath + "\\shaderTexture.fs").c_str());
GiTexture textureFloor((strPath + "\\Floor.png").c_str());
while (!glfwWindowShouldClose(window))
{
float currentFrame = static_cast<float>(glfwGetTime());
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
program.use();
glm::mat4 projection = glm::perspective(glm::radians(45.0), (double)SCR_WIDTH / (double)SCR_HEIGHT, 0.1, 1000.0);
program.setMat4f("projection", glm::value_ptr(projection));
glm::mat4 view = camera.GetViewMatrix();
program.setMat4f("view", glm::value_ptr(view));
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawDrawObjs(program);
processInput(window);
glfwSwapBuffers(window);
glfwPollEvents();
}
program.Release();
programTexture.Release();
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
else if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
{
}
if (glfwGetKey(window, GLFW_KEY_UP) != GLFW_PRESS)
{
}
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
SCR_WIDTH = width;
SCR_HEIGHT = height;
}
void mouse_callback(GLFWwindow* window, double xposIn, double yposIn)
{
float xpos = static_cast<float>(xposIn);
float ypos = static_cast<float>(yposIn);
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos;
lastX = xpos;
lastY = ypos;
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) != GLFW_PRESS)
{
return;
}
camera.ProcessMouseMovement(xoffset, yoffset);
}
void mouse_scrollback(GLFWwindow* window, double xoffset, double yoffset)
{
firstMouse = true;
camera.ProcessMouseScroll(yoffset);
}
void DrawFloor(GiShaderProgram& program, GiTexture& texture)
{
glDisable(GL_DEPTH_TEST);
program.use();
texture.use();
float quadVertices[] = {
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, -1.0f, 0.0f, 1.0f,
1.0f, -1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, -1.0f, 1.0f, 1.0f
};
GiVAO vao(quadVertices, 6 * 5, 3, 2, 0);
vao.DrawArrays(GL_TRIANGLES, 0, 6);
}
void DrawDrawObjs(GiShaderProgram& program)
{
glEnable(GL_DEPTH_TEST);
program.use();
GiCone cone(0.5, 0.5);
cone.SetColor(1.0, 0.0, 0.0);
cone.Draw(program);
glDisable(GL_DEPTH_TEST);
}