使用OpenGL进行绘制,包含万向节摄像机、着色器、VAO、贴图、立方体圆柱圆球圆环圆锥的面片生成和绘制

#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_STACK_OVERFLOW:                error = "STACK_OVERFLOW"; break;
		case GL_STACK_UNDERFLOW:               error = "STACK_UNDERFLOW"; 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;
	}

	// 1. retrieve the vertex/fragment source code from filePath
	std::string vertexCode;
	std::string fragmentCode;
	std::ifstream vShaderFile;
	std::ifstream fShaderFile;
	// ensure ifstream objects can throw exceptions:
	vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
	fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

	try
	{
		// open files
		vShaderFile.open(vertexPath);
		fShaderFile.open(fragmentPath);
		std::stringstream vShaderStream, fShaderStream;
		// read file's buffer contents into streams
		vShaderStream << vShaderFile.rdbuf();
		fShaderStream << fShaderFile.rdbuf();
		// close file handlers
		vShaderFile.close();
		fShaderFile.close();
		// convert stream into string
		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();
	// 2. compile shaders
	unsigned int vertex, fragment;
	// vertex shader
	vertex = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertex, 1, &vShaderCode, NULL);
	glCompileShader(vertex);
	checkCompileErrors(vertex, "VERTEX");
	// fragment Shader
	fragment = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragment, 1, &fShaderCode, NULL);
	glCompileShader(fragment);
	checkCompileErrors(fragment, "FRAGMENT");
	// shader Program
	ID = glCreateProgram();
	glAttachShader(ID, vertex);
	glAttachShader(ID, fragment);
	glLinkProgram(ID);
	checkCompileErrors(ID, "PROGRAM");
	// delete the shaders as they're linked into our program now and no longer necessary
	glDeleteShader(vertex);
	glDeleteShader(fragment);
}

// utility uniform functions
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)
{
	/*if (iFormat == 4)
	{
		for (int i = 0; i < iWidth; i++)
		{
			for (int j = 0; j < iHeight; j++)
			{
				int iTemp = (i * iHeight + j) * 4;
				GLbyte bTemp = pDIB[iTemp];

				pDIB[iTemp] = pDIB[iTemp + 2];
				pDIB[iTemp + 2] = bTemp;
			}
		}
	}*/

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

	/*if (iFormat == 4)
	{
		for (int i = 0; i < iWidth; i++)
		{
			for (int j = 0; j < iHeight; j++)
			{
				int iTemp = (i * iHeight + j) * 3;
				GLbyte bTemp = pDIB[iTemp];

				pDIB[iTemp] = pDIB[iTemp + 2];
				pDIB[iTemp + 2] = bTemp;
			}
		}
	}*/
}

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)
{
	// bind appropriate textures
	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);
	}

	/*glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);*/
	glBindVertexArray(VAO);
	//for (int i = 0; i < 1000; i++)
	glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(m_vecIndices.size()), GL_UNSIGNED_INT, 0);
	glBindVertexArray(0);
	//glDisable(GL_CULL_FACE);

	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;//x为负,y为正,z为正
	mats[1][1][1] = -1;//x为正,y为负,z为正
	mats[2][0][0] = -1;//x为负,y为负,z为正
	mats[2][1][1] = -1;
	mats[3][2][2] = -1;//x为正,y为正,z为负
	mats[4][2][2] = -1;//x为正,y为负,z为负
	mats[4][1][1] = -1;
	mats[5][0][0] = -1;//x为负,y为正,z为负
	mats[5][2][2] = -1;
	mats[6][0][0] = -1;//x为负,y为负,z为负
	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 = /*-90.0f*/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);

// settings
int SCR_WIDTH = 800;
int SCR_HEIGHT = 600;

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

// timing
float deltaTime = 0.0f;	// time between current frame and last frame
float lastFrame = 0.0f;

int main()
{
	// glfw: initialize and configure
	// ------------------------------
	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

	// glfw window creation
	// --------------------
	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);

	// glad: load all OpenGL function pointers
	// ---------------------------------------
	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);
	//program.use();

	GiShaderProgram programTexture((strPath + "\\shaderTexture.vs").c_str(), (strPath + "\\shaderTexture.fs").c_str());
	//programTexture.use();

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

		// render
		// ------
		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//DrawFloor(programTexture, textureFloor);

		DrawDrawObjs(program);

		// input
		// -----
		processInput(window);

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

	program.Release();
	programTexture.Release();

	// glfw: terminate, clearing all previously allocated GLFW resources.
	// ------------------------------------------------------------------
	glfwTerminate();
	return 0;
}

// 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);
	else if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
	{
		
	}

	if (glfwGetKey(window, GLFW_KEY_UP) != GLFW_PRESS)
	{
		
	}
}

// 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)
{
	// make sure the viewport matches the new window dimensions; note that width and 
	// height will be significantly larger than specified on retina displays.
	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; // reversed since y-coordinates go from bottom to top

	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[] = {
		// positions   // texCoords
		-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);

	/*GiTorus GiTorus(0.5, 0.4);
	GiTorus.SetColor(1.0, 0.0, 0.0);
	GiTorus.Draw(program);

	Gi3dBox Box(0.5, 0.5, 0.5);
	Box.SetColor(1.0, 0.0, 0.0);
	Box.Draw(program);*/
	glDisable(GL_DEPTH_TEST);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值