How to make one object "orbit" another object? - c++

I'm currently working on a project involving two cubes. The first cube meant to be static, while the second is going to rotate, or orbit, around the first. I'm very new to OpenGL programming, so I'm having quite a bit of difficulty getting this to work. Can anyone point me in the right direction? So far, I just have two cubes, but I am unable to get them to move as if they were animated. Here is my code if you would like to offer suggestions. Thank you so much!
Main:
#include "vgl.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
#include "Box.h"
#include "Camera.h"
#include "VertexBufferData.h"
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
using namespace std;
using namespace glm;
#define SPACEBAR_KEY 32
#define ESCAPE_KEY 033
Camera* camera;
vector<Box * > gameObjects;
bool keyDown[255];
void CheckKeyboard(){
if (keyDown['a'])
camera->RotateLeft();
if (keyDown['d'])
camera->RotateRight();
if (keyDown['w'])
camera->MoveForward();
if (keyDown['s'])
camera->MoveBackWard();
if (keyDown['e'])
camera->StrafeRight();
if (keyDown['q'])
camera->StrafeLeft();
}
void closeApp()
{
delete camera;
for (auto it = gameObjects.begin(); it != gameObjects.end(); ++it) {
delete (*it);
}
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case ESCAPE_KEY: // ASCII Escape Key Code
closeApp();
exit(EXIT_SUCCESS);
break;
default:
keyDown[key] = true;
}
glutPostRedisplay();
}
void keyboardUp(unsigned char key, int x, int y)
{
keyDown[key] = false;
}
void mouseWheel(int button, int direction, int x, int y)
{
if (button == 16)
camera->ResetFOV();
else if (direction > 0)
camera->ZoomIn();
else
camera->ZoomOut();
}
void mouseMovement(int x, int y)
{
static bool warp = true;
if (warp)
{
if (x>glutGet(GLUT_WINDOW_WIDTH) / 2)
camera->RotateRight();
else if (x<glutGet(GLUT_WINDOW_WIDTH) / 2)
camera->RotateLeft();
if (y>glutGet(GLUT_WINDOW_HEIGHT) / 2)
camera->RotateUp();
else if (y<glutGet(GLUT_WINDOW_HEIGHT) / 2)
camera->RotateDown();
glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
warp = false;
}
else
warp = true;
}
void timer(int value)
{
glutPostRedisplay();
glutTimerFunc(25, timer, 0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
CheckKeyboard();
camera->Update();
for (auto it = gameObjects.begin(); it != gameObjects.end(); ++it) {
(*it)->shaderProgram->bindShader();
glm::mat4 MVP = camera->ProjectionMatrix * camera->ViewMatrix * (*it)->getModelMatrix();
(*it)->shaderProgram->sendUniform4x4("MVP", glm::value_ptr(MVP));
(*it)->Draw();
}
glutSwapBuffers();
}
void init()
{
int i = 0, forever = 0;
camera = new Camera();
memset(keyDown, false, sizeof(keyDown));
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glutWarpPointer(glutGet(GLUT_WINDOW_WIDTH) / 2, glutGet(GLUT_WINDOW_HEIGHT) / 2);
glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
VertexBufferData vertexBufferData = VertexBufferData("Data\\Models\\Objects.xml");
gameObjects.push_back(new Box(vertexBufferData, glm::vec3(-2.0f, 0.0f, 0.0f), "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader"));
gameObjects.push_back(new Box(vertexBufferData, glm::vec3(2.0f, 0.0f, 0.0f), "Data\\Shaders\\Vertex.shader", "Data\\Shaders\\Fragment.shader"));
gameObjects[1]->setRotation(45.0f, vec3(0.0f, 0.0f, 1.0f));
gameObjects[0]->setScaleMatrix(vec3(2, 2, 2));
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(1024, 768);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow("Satterwhite_Project_3");
if (glewInit())
{
cerr << "Unable to init glew" << endl;
exit(EXIT_FAILURE);
}
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboardUp);
glutPassiveMotionFunc(mouseMovement);
glutMouseWheelFunc(mouseWheel);
glutTimerFunc(25, timer, 0);
glutMainLoop();
return 0;
}
Box.cpp
#include "Box.h"
Box::Box(VertexBufferData &vbd, vec3 initialPosition,const string vertexShader, const string fragmentShader):GameObject(vertexShader, fragmentShader)
{
Position=initialPosition;
vertexBufferData =vbd;
RotationMatrix=mat4(1.0f);
OrbitMatrix = mat4(1.0f);
ScaleMatrix=mat4(1.0f);
TranslationMatrix =translate(glm::mat4(1.0f), Position);
if (!shaderProgram->initialize())
{
std::cerr << "Could not initialize the shaders" << std::endl;
}
shaderProgram->bindShader();
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexBufferData.verticiesSize, &vertexBufferData.verticies[0], GL_STATIC_DRAW);
glGenBuffers(1, &fragmentBuffer);
glBindBuffer(GL_ARRAY_BUFFER, fragmentBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexBufferData.colorSize, &vertexBufferData.colors[0], GL_STATIC_DRAW);
shaderProgram->linkProgram();
}
void Box::setRotation(float degrees, vec3 axis)
{
RotationMatrix=rotate(glm::mat4(1.0f), degrees, axis);
RotationMatrix=rotate(RotationMatrix, degrees, vec3(1.0f,0.0f,0.0f));
}
void Box::setScaleMatrix(vec3 scale)
{
ScaleMatrix = glm::scale(mat4(1.0f), scale);
}
/*void Box::setOrbitMatrix(vec3 Position, vec3 axis)
{
OrbitMatrix =
}*/
void Box::Draw()
{
shaderProgram->bindShader();
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT,GL_FALSE, 0, BUFFER_OFFSET(0));
glBindBuffer(GL_ARRAY_BUFFER, fragmentBuffer);
glVertexAttribPointer(1, 3, GL_FLOAT,GL_FALSE, 0, BUFFER_OFFSET(0));
glDrawArrays(GL_TRIANGLES, 0, vertexBufferData.verticies.size());
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
Box.h
#pragma once
#include "GameObject.h"
class Box : public GameObject
{
private:
mat4 ModelMatrix;
mat4 RotationMatrix;
mat4 OrbitMatrix;
mat4 TranslationMatrix;
mat4 ScaleMatrix;
public:
void Draw();
virtual ObjectType getType() const { return BOX; }
mat4 getModelMatrix() {return TranslationMatrix*RotationMatrix*ScaleMatrix;}
mat4 getMRotationMatrix() {return RotationMatrix;}
mat4 getTranslationMatrix() {return TranslationMatrix;}
mat4 getOrbitMatrix(){ return OrbitMatrix; }
mat4 getScaleMatrix() {return ScaleMatrix;}
void setRotation(float degrees, vec3 axis);
void setScaleMatrix(vec3 scale);
void setOrbitMatrix(vec3 Position, vec3 axis);
Box(VertexBufferData &vertexBufferData, vec3 initialPosition, const string vertexShader, const string fragmentShader);
vec3 Position;
mat4 rot;
mat4 scale;
};

Related

my simple OpenGL program can't draw a model load by assimp

I divide my code to two cpp files, one cpp contains main()function and another one contains model loading codes.
here's the first part
#define STB_IMAGE_IMPLEMENTATION
//OpenGL relations
#include "stb_image.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
//math and time
#include <math.h>
#include <cstdio>
#include <time.h>
#include <iostream>
//matrix
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
//
#include "modelload.h"
// const values here //
const char* defaultpath = "woodenbox.jpeg";
const char* cottagetex = "cottage.fbx";
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n"
"out vec2 TexCoord;\n"
"uniform mat4 transform;\n"
"void main()\n"
"{\n"
" gl_Position = transform * vec4(aPos.x, aPos.y, aPos.z, 1.0f);\n"
" TexCoord = aTexCoord;\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
" FragColor = texture(ourTexture, TexCoord);\n"
"}\n\0";
// functions here //
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void loadtexture(unsigned int& texture, const char* path = defaultpath) {
int width, height, nrChannels;
unsigned char* data = stbi_load(path, &width, &height, &nrChannels, 4);
glGenTextures(1, &texture);
//glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
}
void renderInit(unsigned int& shaderProgram) {
unsigned int vertexShader, fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
}
// main function //
int main(int argc, char* argv[])
{
//初始化glfw
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
// --------------------
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL-1", 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))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
//渲染初始化,生成着色器程序、VAO、顶点初始数据
clock_t start, ends;
start = clock();
//build shader
unsigned int shaderProgram;
renderInit(shaderProgram);
unsigned int texture;
glGenTextures(1, &texture);
// 为当前绑定的纹理对象设置环绕、过滤方式
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
loadtexture(texture);
model* ct1 = new model(cottagetex);
glm::mat4 ori_trans = glm::mat4(1.0f);
glm::mat4 view_trans = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));//glm::translate(ori_trans, glm::vec3(0.0f, 0.0f, -3.0f));
glm::mat4 proj_trans = glm::perspective(glm::radians(45.0f), (float)(800 / 600), 0.1f, 100.0f);
glm::mat4 rotate_trans = glm::mat4(1.0f);
unsigned int count = 0;
float radius = 10.0f;
glEnable(GL_DEPTH_TEST);
// initialization completed
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
float camX = sin(glfwGetTime()) * radius;
float camZ = cos(glfwGetTime()) * radius;
view_trans = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));
//glEnableVertexAttribArray(0);
glUseProgram(shaderProgram);
rotate_trans = proj_trans * view_trans * glm::rotate(ori_trans, glm::radians((float)((clock() - start) - cos(clock() - start) * 4) / 40), glm::vec3(1.0, 1.0, -1.0));
unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(rotate_trans));
ct1->draw();
//glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
rotate_trans = glm::translate(proj_trans * view_trans, glm::vec3(1.0f, 1.0f, -3.0f));
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(rotate_trans));
ct1->draw();
//glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
//std::cout << count << " frame updated" << (float)-(0.25 + sin(clock() - start) / 4) << std::endl;
count++;
glfwSwapBuffers(window);
glfwPollEvents();
}
/*
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
*/
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
and the second part
//OpenGL relations
#include <glad/glad.h>
#include <GLFW/glfw3.h>
//math and time
#include <math.h>
#include <vector>
#include <time.h>
#include <iostream>
//matrix
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
//assets
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
struct Vertex {
glm::vec3 Position;
glm::vec2 TexCoords;
glm::vec3 Normal;
};
class Mesh {
public:
/* 网格数据 */
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
//std::vector<unsigned int> textures;// materials
/* 函数 */
Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices) {
this->vertices = vertices;
this->indices = indices;
}//, std::vector<unsigned int> textures
void Draw();
void setupMesh();
private:
/* 渲染数据 */
unsigned int VAO, VBO, EBO;
/* 函数 */
};
class model {
public:
model(const char* path);
void draw();
private:
std::vector<Mesh> meshes;
void processnode(aiNode* node, const aiScene* scene);
Mesh processmesh(aiMesh* mesh, const aiScene* scene);
// loadmaterials
};
#include "modelload.h"
//STL vector in namespace std
void Mesh::setupMesh() {
/*
for (int i = 0; i < vertices.size(); i++) {
std::cout<<vertices[i].Position.x<<std::endl;
}
*/
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//std::cout << sizeof(Vertex) << std::endl;
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(5 * sizeof(float)));
//glEnableVertexAttribArray(2);
//glBindVertexArray(0);// reload VAO before rendering
}
void Mesh::Draw() {
//std::cout << vertices.size() << std::endl; //vertices:988 indices:1434
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
}
model::model(const char* path) {
Assimp::Importer import;
const aiScene* scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl;
return;
}
processnode((scene->mRootNode), scene);
}
void model::processnode(aiNode* node, const aiScene* scene) {
for (int i = 0; i < node->mNumMeshes; i++) {
meshes.push_back(processmesh(scene->mMeshes[node->mMeshes[i]], scene));
meshes.back().setupMesh();
}
for (int i = 0; i < node->mNumChildren; i++) {
processnode(node->mChildren[i], scene);
}
}
Mesh model::processmesh(aiMesh* mesh, const aiScene* scene) {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
for (int i = 0; i < (mesh->mNumVertices); i++) {
Vertex tvertex;
tvertex.Position.x = mesh->mVertices[i].x/3;
tvertex.Position.y = mesh->mVertices[i].y/3;
tvertex.Position.z = mesh->mVertices[i].z/3;
tvertex.Normal.x = mesh->mNormals[i].x;
tvertex.Normal.y = mesh->mNormals[i].y;
tvertex.Normal.z = mesh->mNormals[i].z;
tvertex.TexCoords.x = mesh->mTextureCoords[0][i].x;
tvertex.TexCoords.y = mesh->mTextureCoords[0][i].y;
vertices.push_back(tvertex);
//std::cout << tvertex.Position.x<<" "<< tvertex.Position.y<<" "<< tvertex.Position.z << std::endl;
//std::cout << tvertex.TexCoords.x << " " << tvertex.TexCoords.y << std::endl;
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for (unsigned int j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
}
return Mesh(vertices, indices);
}
void model::draw() {
for (int i = 0; i < meshes.size(); i++) {
//std::cout << i << std::endl;
meshes[i].Draw();
}
}
It can only draw the background color, but it works when I draw a model I made by myself like:
-0.5, -0.5f, 0.5f, 0.0f,0.0f,//left bottom front 0
-0.5, 0.5f, 0.5f, 0.0f,1.0f,//left ceil front 1
0.5, 0.5f, 0.5f, 1.0f,1.0f,//right ceil front 2
0.5, -0.5f, 0.5f, 1.0f,0.0f,//right bottom front 3
-0.5, -0.5f, -0.5f, 1.0f,0.0f,//left bottom behind 4
-0.5, 0.5f, -0.5f, 1.0f,1.0f,//left ceil behind 5
0.5, 0.5f, -0.5f, 0.0f,1.0f,//right ceil behind 6
0.5, -0.5f, -0.5f, 0.0f,0.0f//right bottom behind 7
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 2,
0, 2, 3,
0, 4, 1,
1, 4, 5,
1, 2, 6,
1, 6, 5,
4, 5, 6,
4, 6, 7,
2, 3, 7,
2, 7, 6,
0, 3, 4,
4, 7, 3
};
I checked memory where the model data is, it seems like many same points was loaded.
enter image description here

Assimp can't load other textures except diffuse texture of FBX

I try to load the FBX model in the last contains of this learnopengl tutorial, but I only can load diffuse texture of the FBX. I had tried the solution of adjusting the order of layout in vertex shader, but it didn't work. The result of material->GetTextureCount(type) is 0 when type isn't aiTextureType_DIFFUSE.
Here is my code:
mesh.h
#ifndef Mesh_h
#define Mesh_h
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "ReviewShader.h"
struct Vertex{
glm::vec3 Position;
glm::vec3 Normal;
glm::vec2 TexCoord;
};
struct Texture{
unsigned int id;
string type;
string path;
};
class Mesh{
public:
vector<Texture> textures;
vector<unsigned int> indices;
unsigned int VAO;
Mesh(vector<Vertex> vertices, vector<Texture> textures, vector<unsigned int> indices){
this->vertices = vertices;
this->textures = textures;
this->indices = indices;
setupMesh();
}
void Draw(ReviewShader shader){
int diffuseCount = 1;
int specularCount = 1;
int reflectionCount = 1;
shader.use();
for(int i = 0; i < textures.size(); i++){
string name = textures[i].type;
string num;
if(name == "texture_diffuse")
num = to_string(diffuseCount++);
else if(name == "texture_specular")
num = to_string(specularCount++);
else if(name == "texture_reflection")
num = to_string(reflectionCount++);
shader.setInt((name+num).c_str(), i);
glActiveTexture(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D, textures[i].id);
}
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(0);
}
private:
vector<Vertex> vertices;
unsigned int VBO, EBO;
void setupMesh(){
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoord));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
}
};
#endif /* Mesh_h */
model.h
#ifndef Model_h
#define Model_h
#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include "Mesh.h"
#include "ReviewShader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
//#define STB_IMAGE_IMPLEMENTATION
#include <stb-master/stb_image.h>
vector<Texture> loaded_textures;
class Model{
public:
vector<Mesh> meshes;
string directory;
Model(char *path){
loadModel(path);
}
void Draw(ReviewShader shader){
for(int i = 0; i < meshes.size(); i++){
meshes[i].Draw(shader);
}
}
private:
void loadModel(string path){
Assimp::Importer importer;
// const aiScene *scene = importer.ReadFile(path, aiProcess_FlipUVs | aiProcess_Triangulate);
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode){
cout << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return;
}
directory = path.substr(0, path.find_last_of("/"));
processNode(scene->mRootNode, scene);
}
void processNode(aiNode *node, const aiScene *scene){
for(int i = 0; i < node->mNumMeshes; i++){
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for(int i = 0; i < node->mNumChildren; i++){
processNode(node->mChildren[i], scene);
}
}
Mesh processMesh(aiMesh *mesh, const aiScene *scene){
vector<Vertex> vertices;
vector<Texture> textures;
vector<unsigned int> indices;
for(int i = 0; i < mesh->mNumVertices; i++){
Vertex vertex;
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
if(mesh->mTextureCoords[0]){
glm::vec2 tex;
tex.x = mesh->mTextureCoords[0][i].x;
tex.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoord = tex;
}
else{
vertex.TexCoord = glm::vec2(0.0, 0.0);
}
vertices.push_back(vertex);
}
for(int i = 0; i < mesh->mNumFaces; i++){
aiFace face = mesh->mFaces[i];
for(int j = 0; j < face.mNumIndices; j++){
indices.push_back(face.mIndices[j]);
}
}
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
vector<Texture> texture_diffuse = loadMaterialTexture(material, aiTextureType_DIFFUSE, "texture_diffuse");
textures.insert(textures.end(), texture_diffuse.begin(), texture_diffuse.end());
vector<Texture> texture_specular = loadMaterialTexture(material, aiTextureType_SPECULAR, "texture_specular");
textures.insert(textures.end(), texture_specular.begin(), texture_specular.end());
vector<Texture> texture_ambient = loadMaterialTexture(material, aiTextureType_SHININESS, "texture_reflection");
textures.insert(textures.end(), texture_ambient.begin(), texture_ambient.end());
return Mesh(vertices, textures, indices);
}
vector<Texture> loadMaterialTexture(aiMaterial *material, aiTextureType type, string Typename){
vector<Texture> textures;
cout << material->GetTextureCount(type) << endl;
for(int i = 0; i < material->GetTextureCount(type); i++){
bool skip = false;
aiString str;
material->GetTexture(type, i, &str);
string tempStr = str.C_Str();
tempStr.replace(tempStr.find("\\"), 1, "/");
cout << tempStr << endl;
for(int j = 0; j < loaded_textures.size(); j++){
if(strcmp(loaded_textures[j].path.c_str(), tempStr.c_str()) == 0){
skip = true;
textures.push_back(loaded_textures[i]);
break;
}
}
if(!skip){
Texture tex;
tex.id = loadTextureFromFile(tempStr, directory);
tex.type = Typename;
tex.path = str.C_Str();
textures.push_back(tex);
loaded_textures.push_back(tex);
}
}
return textures;
}
unsigned int loadTextureFromFile(string path, string &Directory){
unsigned int textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
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);
string filepath = Directory + "/" + path;
int width, height, urChannel;
unsigned char *data = stbi_load(filepath.c_str(), &width, &height, &urChannel, 0);
if(data){
GLenum format;
if(urChannel == 1)
format = GL_RED;
if(urChannel == 3)
format = GL_RGB;
if(urChannel == 4)
format = GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(data);
}
else{
cout << "Read texture Data failed\n";
stbi_image_free(data);
}
return textureID;
}
};
#endif /* Model_h */
model.vs
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aUV;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 Normal;
out vec2 UV;
out vec3 Position;
void main(){
gl_Position = projection * view * model * vec4(aPos, 1.0);
UV = aUV;
Normal = mat3(transpose(inverse(model))) * aNormal;
Position = vec3(model * vec4(aPos, 1.0));
}
model.fs
#version 330 core
out vec4 FragColor;
uniform sampler2D texture_diffuse;
uniform sampler2D texture_specular;
uniform sampler2D texture_roughness;
in vec3 Normal;
in vec2 UV;
in vec3 Position;
void main(){
FragColor = texture(texture_diffuse, UV);
}
main.cpp
#include <...>
...
using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);
unsigned int loadTexture(const char *path);
unsigned int loadHDRTexture(char const * path);
unsigned int loadCubemap(vector<string> faces);
void renderQuad();
void renderCube();
void renderPlane();
void renderSphere();
float lerp(float a, float b, float scale);
// size settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
glm::vec3 lightPos = glm::vec3(2.0, 4.0, -2.0);
glm::vec3 lightColor = glm::vec3(0.2, 0.2, 0.7);
// calculation parameter
const float Pi = 3.14159265359;
const float doublePi = Pi * 2.0;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 10.0f));
float lastX = (float)SCR_WIDTH / 2.0;
float lastY = (float)SCR_HEIGHT / 2.0;
bool firstMouse = true;
// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
// texture normal
glm::vec3 normal(0.0, 0.0, 1.0);
// plane normal
glm::vec3 planeNormal = glm::vec3(0.0, 1.0, 0.0);
int main()
{
// glfw: initialize and configure
// ------------------------------
...
// Create shaders
...
ReviewShader modelShader("shader/model.vs", "shader/model.fs");
// pbr configure
...
Model gunModel = Model("Gun_Model/Cerberus_LP.FBX");
while(!glfwWindowShouldClose(window))
{
// avoid delay
// -----------
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// process input
// -------------
processInput(window);
glViewport(0, 0, SCR_WIDTH * 2, SCR_HEIGHT * 2);
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 model = glm::mat4(1.0);
glm::mat4 view = camera.getViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
modelShader.use();
model = glm::mat4(1.0);
model = glm::scale(model, glm::vec3(0.1));
model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0, 0.0, 0.0));
modelShader.setMat4("model", model);
modelShader.setMat4("view", view);
modelShader.setMat4("projection", projection);
gunModel.Draw(modelShader);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
At first: which version of the Asset-Importer-Lib do you use? We made a lot of improvements in the FBX-Importer, so switching to the latest 5.0-release is strongly recommended.
Normally when the number of textures shows zero it is a sign that there is only one texture used in our model. To verify that yo can just use Blender, The interal Asset-Importer-Viewer or the Editor of the Godot-Engine to check that your model is right.
If there is more than just a diffuse-texture stored in your model please create a new issue report here: Assimp-Bugtracker . And please add a model which we can use to reproduce the issue. Thanks in advance!

Access violation when creating a mesh and launching the window SDL/GLEW C++

I am currently following along on an openGL course and when organising my code into classes, I am getting an access violation error along with this on the console terminal.
SDL window creation failed! (I programmed it to output that when the window cannot be created)
Here's my code:
main.cpp
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <vector>
#include <GL/glew.h>
#define SDL_MAIN_HANDLED
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Window.h"
#include "Mesh.h"
#include "Shader.h"
//Window dimensions
const GLint width = 800, height = 600;
const float toRadians = 3.14159265f / 180.0f;
Window mainWindow;
std::vector<Mesh*> meshList;
std::vector<Shader*> shaderList;
bool direction = true;
float triOffSet = 0.0f;
float triMaxOffSet = 0.7f;
float triIncrement = 0.010f;
float curAngle = 0.0f;
bool sizeDirection = true;
float curSize = 0.4f;
float maxSize = 0.8f;
float minSize = 0.1f;
//Vertex shader
static const char* vShader = "Shaders/shader.vert";
//Fragment shader
static const char* fShader = "Shaders/shader.frag";
void CreateObjects() {
unsigned int indices[] = {
0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 1, 2
};
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 1.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
Mesh* obj1 = new Mesh();
obj1->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj1);
Mesh* obj2 = new Mesh();
obj2->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj2);
Mesh* obj3 = new Mesh();
obj3->CreateMesh(vertices, indices, 12, 12);
meshList.push_back(obj3);
}
void CreateShaders() {
Shader *shader1 = new Shader();
shader1->CreateFromFiles(vShader, fShader);
shaderList.push_back(shader1);
}
int main() {
mainWindow = Window(800, 600);
mainWindow.Initialise();
CreateObjects();
CreateShaders();
GLuint uniformProjection = 0, uniformModel = 0;
glm::mat4 projection = glm::perspective(45.0f, (GLfloat)mainWindow.getBufferWidth() / mainWindow.getBufferHeight(), 0.1f, 100.0f);
SDL_Event windowEvent;
while (true) {
if (SDL_PollEvent(&windowEvent)) {
if (windowEvent.type == SDL_QUIT) {
break;
}
}
if (direction) {
triOffSet += triIncrement;
}
else {
triOffSet -= triIncrement;
}
if (abs(triOffSet) >= triMaxOffSet) {
direction = !direction;
}
curAngle += 1.0f;
if (curAngle >= 360) {
curAngle -= 360;
}
if (direction) {
curSize += 0.001f;
}
else {
curSize -= 0.001f;
}
if (curSize >= maxSize || curSize <= minSize) {
sizeDirection = !sizeDirection;
}
//Clear window
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderList[0]->UseShader();
uniformModel = shaderList[0]->GetModelLocation();
uniformProjection = shaderList[0]->GetProjectionLocation();
glm::mat4 model(1.0f);
model = glm::translate(model, glm::vec3(0.0f, 0.0f, -2.5f));
model = glm::rotate(model, curAngle * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
meshList[0]->RenderMesh();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(-triOffSet, 1.0f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshList[1]->RenderMesh();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(triOffSet, -1.0f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshList[2]->RenderMesh();
glUseProgram(0);
mainWindow.swapWindows();
}
return 0;
}
Mesh.h
#pragma once
#include <GL/glew.h>
class Mesh
{
private:
GLuint VAO, VBO, IBO;
GLsizei indexCount;
public:
Mesh();
void CreateMesh(GLfloat *vertices, unsigned int *indices, unsigned int numOfVertices, unsigned int numOfIndices);
void RenderMesh();
void ClearMesh();
~Mesh();
};
Mesh.cpp
#include "Mesh.h"
#include <GL/glew.h>
Mesh::Mesh() {
VAO = 0;
VBO = 0;
IBO = 0;
indexCount = 0;
}
void Mesh::CreateMesh(GLfloat* vertices, unsigned int* indices, unsigned int numOfVertices, unsigned int numOfIndices) {
indexCount = numOfIndices;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * numOfIndices, indices, GL_STATIC_DRAW);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * numOfVertices, vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void Mesh::RenderMesh() {
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::ClearMesh() {
if (IBO != 0) {
glDeleteBuffers(1, &IBO);
IBO = 0;
}
if (VBO != 0) {
glDeleteBuffers(1, &VBO);
VBO = 0;
}
if (VAO != 0) {
glDeleteBuffers(1, &VAO);
VAO = 0;
}
indexCount = 0;
}
Mesh::~Mesh() {
ClearMesh();
}
Shader.h
#pragma once
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <GL/glew.h>
class Shader
{
private:
GLuint shaderID, uniformProjection, uniformModel;
void CompileShader(const char* vertexCode, const char* fragmentCode);
void AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType);
public:
Shader();
void CreateFromString(const char* vertexCode, const char* fragmentCode);
void CreateFromFiles(const char* vertexLocation, const char* fragmentLocation);
std::string ReadFile(const char* fileLocation);
GLuint GetProjectionLocation();
GLuint GetModelLocation();
void UseShader();
void ClearShader();
~Shader();
};
Shader.cpp
#include "Shader.h"
Shader::Shader()
{
shaderID = 0;
uniformModel = 0;
uniformProjection = 0;
}
void Shader::CreateFromString(const char* vertexCode, const char* fragmentCode)
{
CompileShader(vertexCode, fragmentCode);
}
void Shader::CreateFromFiles(const char* vertexLocation, const char* fragmentLocation)
{
std::string vertexString = ReadFile(vertexLocation);
std::string fragmentString = ReadFile(fragmentLocation);
const char* vertexCode = vertexString.c_str();
const char* fragmentCode = fragmentString.c_str();
CompileShader(vertexCode, fragmentCode);
}
std::string Shader::ReadFile(const char* fileLocation)
{
std::string content;
std::ifstream fileStream(fileLocation, std::ios::in);
if (!fileStream.is_open()) {
printf("Failed to read %s! File doesn't exist.", fileLocation);
return "";
}
std::string line = "";
while (!fileStream.eof())
{
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
void Shader::CompileShader(const char* vertexCode, const char* fragmentCode)
{
shaderID = glCreateProgram();
if (!shaderID)
{
printf("Error creating shader program!\n");
return;
}
AddShader(shaderID, vertexCode, GL_VERTEX_SHADER);
AddShader(shaderID, fragmentCode, GL_FRAGMENT_SHADER);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glLinkProgram(shaderID);
glGetProgramiv(shaderID, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error linking program: '%s'\n", eLog);
return;
}
glValidateProgram(shaderID);
glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error validating program: '%s'\n", eLog);
return;
}
uniformProjection = glGetUniformLocation(shaderID, "projection");
uniformModel = glGetUniformLocation(shaderID, "model");
}
GLuint Shader::GetProjectionLocation()
{
return uniformProjection;
}
GLuint Shader::GetModelLocation()
{
return uniformModel;
}
void Shader::UseShader()
{
glUseProgram(shaderID);
}
void Shader::ClearShader()
{
if (shaderID != 0)
{
glDeleteProgram(shaderID);
shaderID = 0;
}
uniformModel = 0;
uniformProjection = 0;
}
void Shader::AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType)
{
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1];
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(theShader, sizeof(eLog), NULL, eLog);
printf("Error compiling the %d shader: '%s'\n", shaderType, eLog);
return;
}
glAttachShader(theProgram, theShader);
}
Shader::~Shader()
{
ClearShader();
}
Window.h
#pragma once
#include <stdio.h>
#include <GL/glew.h>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
class Window
{
private:
SDL_Window* mainWindow;
SDL_Event windowEvent;
GLint width, height;
public:
Window();
Window(GLint windowWidth, GLint windowHeight);
int Initialise();
GLint getBufferWidth() { return width; }
GLint getBufferHeight() { return height; }
void swapWindows() { SDL_GL_SwapWindow(mainWindow); }
~Window();
};
Window.cpp
#include "Window.h"
Window::Window() {
width = 800;
height = 600;
}
Window::Window(GLint width, GLint height) {
width = width;
height = height;
}
int Window::Initialise() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL initialisation failed\n");
SDL_Quit();
return 1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
mainWindow = SDL_CreateWindow("Test game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
if (!mainWindow) {
printf("SDL window creation failed!\n");
SDL_Quit();
return 1;
}
//Set context for GLEW to use
SDL_GLContext context = SDL_GL_CreateContext(mainWindow);
//Allow modern extension features
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
printf("GLEW initialization failed!\n");
SDL_DestroyWindow(mainWindow);
SDL_Quit();
return 1;
}
glEnable(GL_DEPTH_TEST);
//Setup viewport size
glViewport(0, 0, 800, 600);
}
Window::~Window() {
SDL_DestroyWindow(mainWindow);
SDL_Quit();
}
I've heard that a solution to this could be to put glewExperimental = GL_True before glewInit() but that hasn't worked because those two lines are in Window.cpp and I don't know how that could affect Mesh.cpp.
The debug reads this at the bottom:
Exception thrown at 0x00000000 in OpenGLCourseApp.exe: 0xC0000005: Access violation executing location 0x00000000.
Call stack
Your Window constructor does not actually initialize the fields of the Window object, which means you call SDL_CreateWindow with random width and height.
Use an initializer list instead, which does not suffer this problem:
Window::Window(int width, int height)
: width(width), height(height) {
}
Once you get past that, keep in mind that the statement
mainWindow = Window(800, 600);
will create a temporary Window object, assign it to mainWindow, and then immediately destroy it!
I suggest you change the type of mainWindow to Window* (or better yet a std::unique_ptr<Window>),
and change that line to
mainWindow = new Window(800, 600);
or
mainWindow = std::make_unique<Window>(800, 600);

I'm trying to draw a triangle using shaders and VBO. Why my program doesn't work?

I've tried to use this code for drawing triangle using VBO and shaders.
#include "gl.h"
#include <stdlib.h>
#include <GLFW/glfw3.h>
// utility libraries
#include "OGLShader.h"
#include "OGLProgram.h"
#include "OGLCommon.h"
#include "Shaders.h"
#include "OGLBuffer.h"
using namespace OpenGL;
GLFWwindow *window;
const int window_width = 800;
const int window_height = 600;
Shader **shaders;
Program *mainProgram;
int verticesCount = 3;
float triangle[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
};
int indicesCount = 3;
int indices[] = {
0, 1, 2
};
Buffer *verticesBuffer;
void init() {
glViewport(0, 0, window_width, window_height);
glClearColor(0, 0, 0, 1);
shaders = new OpenGL::Shader*[2];
// this code creates and compiles shaders, links shader program
shaders[0] = new OpenGL::Shader(GL_VERTEX_SHADER, OpenGL::vertexShaderSource);
shaders[1] = new OpenGL::Shader(GL_FRAGMENT_SHADER, OpenGL::fragmentShaderSource);
mainProgram = new OpenGL::Program(2, shaders);
mainProgram->use(); // use program
vertices_attrib_location = 0;
colors_attrib_location = 1;
glBindAttribLocation(mainProgram->getId(), vertices_attrib_location, "iVertex");
glBindAttribLocation(mainProgram->getId(), colors_attrib_location, "iColor");
verticesBuffer = new Buffer(GL_ARRAY_BUFFER);
verticesBuffer->data(verticesCount*3*sizeof(float), triangle, GL_STATIC_DRAW);
}
void deinit() {
delete verticesBuffer;
delete shaders[0];
delete shaders[1];
delete []shaders;
delete mainProgram;
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glVertexAttrib3f(colors_attrib_location, 1, 0, 1);
verticesBuffer->bind();
glEnableVertexAttribArray(vertices_attrib_location);
glVertexAttribPointer(vertices_attrib_location, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void update(double deltaTime) {
}
int main(int argc, char **argv) {
if (!glfwInit()) {
exit(1);
}
glfwWindowHint(GLFW_SAMPLES, 1);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
window = glfwCreateWindow(window_width, window_height, "Test", nullptr, nullptr);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
init();
double lastTime = 0.0;
while (!glfwWindowShouldClose(window)) {
display();
double curTime = glfwGetTime();
update(curTime - lastTime);
lastTime = curTime;
glfwSwapBuffers(window);
glfwPollEvents();
}
deinit();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Here is my shaders:
namespace OpenGL {
std::string vertexShaderSource =
"#version 120\n\
attribute vec3 iVertex;\
attribute vec3 iColor;\
varying vec3 oColor;\
void main(void)\n\
{\n\
oColor = iColor;\n\
\n\
gl_Position = vec4(iVertex, 1);\n\
}\n\
";
std::string fragmentShaderSource =
"#version 120\n\
varying vec3 oColor;\
varying vec2 oTexCoord;\n\
void main(void)\n\
{\n\
gl_FragColor = vec4(oColor, 1);\n\
}\n\
";
}
I tried to run this code both on Intel and ATI videocards, but everything that I see on the screen is empty black window. What I'm doing wrong?

OpenGL, FreeGlut and Glew crash with glGenVertexArrays call

I have a program like below:
#include <iostream>
#include <fstream>
#include <sstream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
GLuint prog, verShader, fragShader;
GLint attrPos, attrNor;
GLint uniModelView, uniProjection, uniModelViewTransposeInverse;
glm::mat4 modelMatrix, viewMatrix, projectionMatrix, MV, MVP;
glm::mat3 MVI;
const string loadFile(string name)
{
ifstream in(name.c_str(), ios::in);
if (in.fail()) {
cout << "File: '" << name << "' could not exist!!" << endl;
return "";
}
stringstream data;
data << in.rdbuf();
in.close();
return data.str();
}
GLuint createShader(GLenum type, const string name)
{
GLint isCompileOk;
GLuint shader;
string shaderText, shaderType;
const char *shaderSource;
switch(type)
{
case GL_VERTEX_SHADER:
shaderType = "GL_VERTEX_SHADER";
break;
case GL_FRAGMENT_SHADER:
shaderType = "GL_FRAGMENT_SHADER";
break;
}
shaderText = loadFile(name);
shaderSource = shaderText.c_str();
shader = glCreateShader(type);
glShaderSource(shader, 1, &shaderSource, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompileOk);
if (isCompileOk == GL_FALSE) {
char *shaderErr;
int errLength, errRetrieve;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &errLength);
shaderErr = new char [errLength + 1];
glGetShaderInfoLog(shader, errLength, &errRetrieve, shaderErr);
cout << "Compile '" << shaderType << "' error:" << endl;
cout << shaderErr << endl;
delete [] shaderErr;
return 0;
} else {
cout << "Compile '" << shaderType << "' ok!" << endl;
}
return shader;
}
bool makeShader()
{
GLint isLinkOk;
verShader = createShader(GL_VERTEX_SHADER, "vert.glsl");
fragShader = createShader(GL_FRAGMENT_SHADER, "frag.glsl");
prog = glCreateProgram();
glAttachShader(prog, verShader);
glAttachShader(prog, fragShader);
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &isLinkOk);
if (isLinkOk == GL_FALSE) {
char *progErr;
int errLenght, errRetrieve;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &errLenght);
progErr = new char[errLenght + 1];
glGetProgramInfoLog(prog, errLenght, &errRetrieve, progErr);
cout << "Link program error:" << endl;
cout << progErr << endl;
delete [] progErr;
return false;
} else {
cout << "Link program Ok!" << endl;
}
attrPos = glGetAttribLocation(prog, "position");
uniModelView = glGetUniformLocation(prog, "ModelViewMatrix");
uniProjection = glGetUniformLocation(prog, "ProjectionMatrix");
uniModelViewTransposeInverse = glGetUniformLocation(prog, "ModelViewTransposeInverseMatrix");
return true;
}
float vertexs[] = {
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f
};
unsigned short indicates[] = {
0, 1, 2,
2, 3, 0
};
GLuint vao, vbo, ibo;
void display()
{
MV = viewMatrix * modelMatrix;
MVP = projectionMatrix * MV;
MVI = glm::transpose(glm::inverse(glm::mat3(MV)));
glUseProgram(prog);
glUniformMatrix4fv(uniModelView, 1, GL_FALSE, glm::value_ptr(MV));
glUniformMatrix3fv(uniModelViewTransposeInverse, 1, GL_FALSE, glm::value_ptr(MVI));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, sizeof(indicates)/sizeof(unsigned short), GL_UNSIGNED_SHORT, 0);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
projectionMatrix = glm::perspective(45.0f, float(w)/h, 0.1f, 1000.0f);
glUseProgram(prog);
glUniformMatrix4fv(uniProjection, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
}
void idle()
{
glutPostRedisplay();
}
void Init()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
modelMatrix = glm::mat4(1.0f);
viewMatrix = glm::lookAt(
glm::vec3(0.0f, 5.0f, 10.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f)
);
projectionMatrix = glm::mat4(1.0f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
glEnableVertexAttribArray(attrPos);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicates), indicates, GL_STATIC_DRAW);
glBindVertexArray(0);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("Rectangle!");
if (glewInit() != GLEW_OK) {
cout << "glewInit() fail!" << endl;
return -1;
}
if (!makeShader()) {
cout << "makeShader() error!!" << endl;
return -1;
}
Init();
reshape(WINDOW_WIDTH, WINDOW_HEIGHT);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
when i adds VAO buffer, freeglut going to crash in glutMainLoop(), if i removes glGenVertexArrays call (of couse, removed what relatives to VAO too), it run ok, so my guess is problem in freeglut with glGenVertexArrays.
Question: What is my problem?
ps: My graphic cal support opengl 2.1, i use Visual Studio 2008.
Update: With VAO, above program work well but only crash when i close freeglut window.
Update shader: My shaders is very simple:
Vertex shader:
#version 120
attribute vec3 position;
// attribute vec3 normal;
uniform mat4 ModelViewMatrix;
uniform mat3 ModelViewTransposeInverseMatrix;
uniform mat4 ProjectionMatrix;
void main(void)
{
gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(position, 1.0);
}
Fragment shader:
#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
Your vertex data is tightly packed. Use a stride of 0 instead of sizeof(float) * 3.
My graphic cal support opengl 2.1
Also, VAOs only became core in 3.0. You should check for ARB_vertex_array_object support before using that functionality.