Renderer gives error when created with default constructor

If I create the renderer in the following way, everything works fine:

SpriteRenderer_convexhull* renderer_convexhull;
renderer_convexhull = new SpriteRenderer_convexhull(myProgramShader_convexhull, hull[0]);

But if I change the above code to first invoke default constructor and then the parametric one (I need this, because my goal is to create array of renderers) I am getting the error. The modified code is given below:

SpriteRenderer_convexhull* renderer_convexhull;
renderer_convexhull = new SpriteRenderer_convexhull[1];
renderer_convexhull[0] = SpriteRenderer_convexhull(myProgramShader_convexhull, hull[0]);

The following error pops up when the glDrawElements function is used:

Exception thrown at 0x00007FFB2C310260 (nvoglv64.dll) in ParticleCollison-BulletPhysics.exe: 0xC0000005: Access violation reading location 0x0000000000000000.

Before the glDrawElements function, the glBindVertexArray(VAO) is used and the glGetError() gives 1282 (glGetError() is used after glBindVertexArray(VAO)).

During debugging I discovered that the renderer class fields have the same values in both cases, hence I have no idea what causes the error.

I attach the codes below:
SpriteRenderer.h:

#pragma once

#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <quickhull/QuickHull.hpp>

#include "Shader.h"
#include "camera.h"
#include "Vertex.h"
#include "rng.h"

#define M_PI 3.1415926f


using namespace quickhull;


class SpriteRenderer_convexhull
{
	Shader shader;
	unsigned int VAO;

	std::vector<Vertex> vertices;
	std::vector<float> vertices_data_for_GPU; // contains positions and normals. It will be used to send data to GPU
	std::vector<unsigned int> indices;
	ConvexHull<float> hull;


public:
	SpriteRenderer_convexhull();
	SpriteRenderer_convexhull(const Shader& shader_, const ConvexHull<float>& hull_);
	~SpriteRenderer_convexhull();

	void initRenderData();
	void drawSprite(glm::vec3 position, glm::vec3 size, glm::vec3 rotate, glm::vec3 color, glm::vec3* point_light_positions);
	void printVertices();


};

SpriteRenderer.cpp:

#include "SpriteRenderer_convexhull.h"

extern const unsigned int SCR_WIDTH;
extern const unsigned int SCR_HEIGHT;
extern Camera camera;


std::uniform_real_distribution<float> uniform_float(-1.0f, 1.0f);


glm::vec3 calculateNormal(glm::vec3 vertex1, glm::vec3 vertex2, glm::vec3 vertex3);


SpriteRenderer_convexhull::SpriteRenderer_convexhull()
{

}

SpriteRenderer_convexhull::SpriteRenderer_convexhull(const Shader& shader_, const ConvexHull<float>& hull_)
	: shader(shader_), hull(hull_)
{
	initRenderData();
}


SpriteRenderer_convexhull::~SpriteRenderer_convexhull()
{
	glDeleteVertexArrays(1, &VAO);
}

void SpriteRenderer_convexhull::initRenderData()
{
	const auto& vertexBuffer = hull.getVertexBuffer();
	const auto& indexBuffer = hull.getIndexBuffer();

	for (size_t i = 0; i < vertexBuffer.size(); ++i)
		this->vertices.push_back(Vertex(glm::vec3(vertexBuffer[i].x, vertexBuffer[i].y, vertexBuffer[i].z)));

	for (size_t i = 0; i < indexBuffer.size(); ++i)
		this->indices.push_back(indexBuffer[i]);

	// Add normals
	for (size_t i = 0; i < this->indices.size(); i+=3) // iterate triangle by triangle
	{
		glm::vec3 normal = calculateNormal(this->vertices[this->indices[i]].position, this->vertices[this->indices[i+1]].position, this->vertices[this->indices[i+2]].position);
		this->vertices[this->indices[i]].normal = normal;
		this->vertices[this->indices[i+1]].normal = normal;
		this->vertices[this->indices[i+2]].normal = normal;
	}

	// Finally, construct vertices array, which will be send to GPU. It contains positions and normals
	for (size_t i = 0; i < vertexBuffer.size(); ++i)
	{
		this->vertices_data_for_GPU.push_back(this->vertices[i].position.x);
		this->vertices_data_for_GPU.push_back(this->vertices[i].position.y);
		this->vertices_data_for_GPU.push_back(this->vertices[i].position.z);
		this->vertices_data_for_GPU.push_back(this->vertices[i].normal.x * (-1));
		this->vertices_data_for_GPU.push_back(this->vertices[i].normal.y * (-1));
		this->vertices_data_for_GPU.push_back(this->vertices[i].normal.z * (-1));
	}
	

	// Send to GPU
	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	unsigned int VBO;
	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices_data_for_GPU.size(), vertices_data_for_GPU.data(), GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
	glEnableVertexAttribArray(0); //0 = location
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);



	unsigned int EBO;
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indices.size(), indices.data(), GL_STATIC_DRAW);

	glBindVertexArray(0);
}

void SpriteRenderer_convexhull::drawSprite(glm::vec3 position, glm::vec3 size, glm::vec3 rotate, glm::vec3 color, glm::vec3* point_light_positions)
{
	shader.use();

	glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), static_cast<float>(SCR_WIDTH) / static_cast<float>(SCR_HEIGHT), 0.1f, 100.0f);

	glm::mat4 view = camera.GetViewMatrix();
	shader.setMat4("view", view);
	shader.setMat4("projection", projection);

	glm::mat4 model = glm::mat4(1.0f);
	model = glm::translate(model, position);

	glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
	rotation = glm::rotate(rotation, glm::radians(rotate.z), glm::vec3(0.0f, 0.0f, 1.0f));
	rotation = glm::rotate(rotation, glm::radians(rotate.y), glm::vec3(0.0f, 1.0f, 0.0f));
	rotation = glm::rotate(rotation, glm::radians(rotate.x), glm::vec3(1.0f, 0.0f, 0.0f));
	model *= glm::mat4_cast(rotation);

	model = glm::scale(model, glm::vec3(size));
	shader.setMat4("model", model);

	shader.setVec3f("spriteColor", color);

	shader.setVec3f("viewPos", camera.Position);
	shader.setFloat("material.shininess", 32.0f);
	shader.setVec3f("dirLight.direction", -0.2f, -1.0f, -0.3f);
	shader.setVec3f("dirLight.ambient", 0.05f, 0.05f, 0.05f);
	shader.setVec3f("dirLight.diffuse", 0.4f, 0.4f, 0.4f);
	shader.setVec3f("dirLight.specular", 0.0f, 0.0f, 0.0f);

	// point light 1
	shader.setVec3f("pointLights[0].position", point_light_positions[0]);
	shader.setVec3f("pointLights[0].ambient", 0.05f, 0.05f, 0.05f);
	shader.setVec3f("pointLights[0].diffuse", 0.8f, 0.8f, 0.8f);
	shader.setVec3f("pointLights[0].specular", 0.0f, 0.0f, 0.0f);
	shader.setFloat("pointLights[0].constant", 1.0f);
	shader.setFloat("pointLights[0].linear", 0.09f);
	shader.setFloat("pointLights[0].quadratic", 0.032f);

	glBindVertexArray(VAO);
	std::cout << glGetError() << std::endl;

	glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
	std::cout << glGetError() << std::endl;
	glBindVertexArray(0);
}

void SpriteRenderer_convexhull::printVertices()
{
	std::cout << "Vertices data (rendering)" << std::endl;
	for (size_t i = 0; i < this->vertices.size(); ++i)
	{
		std::cout << "Vertex " << i << ": (" << this->vertices[i].position.x << ", " << this->vertices[i].position.y <<", " << this->vertices[i].position.z << ")" << std::endl;
	}
}


glm::vec3 calculateNormal(glm::vec3 vertex1, glm::vec3 vertex2, glm::vec3 vertex3) 
{
	glm::vec3 edge1 = vertex2 - vertex1;
	glm::vec3 edge2 = vertex3 - vertex1;

	return glm::normalize(glm::cross(edge1, edge2));
}

How to solve the problem?

This is a standard violation of the C++ Rule of 5. Please pay attention to it.

1 Like

Thanks. This seems to be the cause. I have to understand and implement this, which will take some time. Iā€™ll write here if I still have problems.

It is working now. Thanks Alfonse.

The working code is given below:
SpriteRenderer.h

#pragma once

#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <quickhull/QuickHull.hpp>

#include "Shader.h"
#include "camera.h"
#include "Vertex.h"
#include "rng.h"

#define M_PI 3.1415926f


using namespace quickhull;


class SpriteRenderer_convexhull
{
	Shader shader;
	unsigned int VAO;

	std::vector<Vertex> vertices;
	std::vector<float> vertices_data_for_GPU; // contains positions and normals. It will be used to send data to GPU
	std::vector<unsigned int> indices;
	ConvexHull<float> hull;


public:
	SpriteRenderer_convexhull();
	SpriteRenderer_convexhull(const Shader& shader_, const ConvexHull<float>& hull_);
	SpriteRenderer_convexhull(const SpriteRenderer_convexhull&) = delete;
	SpriteRenderer_convexhull& operator=(const SpriteRenderer_convexhull&) = delete;
	SpriteRenderer_convexhull(SpriteRenderer_convexhull&& other);
	SpriteRenderer_convexhull& operator=(SpriteRenderer_convexhull&& other);


	~SpriteRenderer_convexhull();
	void Release();


	void initRenderData();
	void drawSprite(glm::vec3 position, glm::vec3 size, glm::vec3 rotate, glm::vec3 color, glm::vec3* point_light_positions);
	void printVertices();


};

SpriteRenderer.cpp

#include "SpriteRenderer_convexhull.h"

extern const unsigned int SCR_WIDTH;
extern const unsigned int SCR_HEIGHT;
extern Camera camera;


std::uniform_real_distribution<float> uniform_float(-1.0f, 1.0f);


glm::vec3 calculateNormal(glm::vec3 vertex1, glm::vec3 vertex2, glm::vec3 vertex3);


SpriteRenderer_convexhull::SpriteRenderer_convexhull()
{

}

SpriteRenderer_convexhull::SpriteRenderer_convexhull(const Shader& shader_, const ConvexHull<float>& hull_)
	: shader(shader_), hull(hull_)
{
	initRenderData();
}


SpriteRenderer_convexhull::SpriteRenderer_convexhull(SpriteRenderer_convexhull&& other)
	:VAO(other.VAO), shader(std::move(other.shader)), hull(std::move(other.hull))
{
	other.VAO = 0;
}

SpriteRenderer_convexhull& SpriteRenderer_convexhull::operator=(SpriteRenderer_convexhull&& other)
{
	//ALWAYS check for self-assignment
	if (this != &other)
	{
		Release();
		VAO = other.VAO;
		other.VAO = 0;
		shader = std::move(other.shader);
		hull = std::move(other.hull);
		vertices = std::move(other.vertices);
		vertices_data_for_GPU = std::move(other.vertices_data_for_GPU);
		indices = std::move(other.indices);
	}

	return *this;
}



SpriteRenderer_convexhull::~SpriteRenderer_convexhull()
{
	Release();
}

void SpriteRenderer_convexhull::Release()
{
	if (VAO)
	{
		glDeleteVertexArrays(1, &VAO);
		VAO = 0;

	}
}

void SpriteRenderer_convexhull::initRenderData()
{
	const auto& vertexBuffer = hull.getVertexBuffer();
	const auto& indexBuffer = hull.getIndexBuffer();

	for (size_t i = 0; i < vertexBuffer.size(); ++i)
		this->vertices.push_back(Vertex(glm::vec3(vertexBuffer[i].x, vertexBuffer[i].y, vertexBuffer[i].z)));

	for (size_t i = 0; i < indexBuffer.size(); ++i)
		this->indices.push_back(indexBuffer[i]);

	// Add normals
	for (size_t i = 0; i < this->indices.size(); i+=3) // iterate triangle by triangle
	{
		glm::vec3 normal = calculateNormal(this->vertices[this->indices[i]].position, this->vertices[this->indices[i+1]].position, this->vertices[this->indices[i+2]].position);
		this->vertices[this->indices[i]].normal = normal;
		this->vertices[this->indices[i+1]].normal = normal;
		this->vertices[this->indices[i+2]].normal = normal;
	}

	// Finally, construct vertices array, which will be send to GPU. It contains positions and normals
	for (size_t i = 0; i < vertexBuffer.size(); ++i)
	{
		this->vertices_data_for_GPU.push_back(this->vertices[i].position.x);
		this->vertices_data_for_GPU.push_back(this->vertices[i].position.y);
		this->vertices_data_for_GPU.push_back(this->vertices[i].position.z);
		this->vertices_data_for_GPU.push_back(this->vertices[i].normal.x * (-1));
		this->vertices_data_for_GPU.push_back(this->vertices[i].normal.y * (-1));
		this->vertices_data_for_GPU.push_back(this->vertices[i].normal.z * (-1));
	}
	

	// Send to GPU
	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	unsigned int VBO;
	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices_data_for_GPU.size(), vertices_data_for_GPU.data(), GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
	glEnableVertexAttribArray(0); //0 = location
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);



	unsigned int EBO;
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * indices.size(), indices.data(), GL_STATIC_DRAW);

	glBindVertexArray(0);
}

void SpriteRenderer_convexhull::drawSprite(glm::vec3 position, glm::vec3 size, glm::vec3 rotate, glm::vec3 color, glm::vec3* point_light_positions)
{
	shader.use();

	glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), static_cast<float>(SCR_WIDTH) / static_cast<float>(SCR_HEIGHT), 0.1f, 100.0f);

	glm::mat4 view = camera.GetViewMatrix();
	shader.setMat4("view", view);
	shader.setMat4("projection", projection);

	glm::mat4 model = glm::mat4(1.0f);
	model = glm::translate(model, position);

	glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
	rotation = glm::rotate(rotation, glm::radians(rotate.z), glm::vec3(0.0f, 0.0f, 1.0f));
	rotation = glm::rotate(rotation, glm::radians(rotate.y), glm::vec3(0.0f, 1.0f, 0.0f));
	rotation = glm::rotate(rotation, glm::radians(rotate.x), glm::vec3(1.0f, 0.0f, 0.0f));
	model *= glm::mat4_cast(rotation);

	model = glm::scale(model, glm::vec3(size));
	shader.setMat4("model", model);

	shader.setVec3f("spriteColor", color);

	shader.setVec3f("viewPos", camera.Position);
	shader.setFloat("material.shininess", 32.0f);
	shader.setVec3f("dirLight.direction", -0.2f, -1.0f, -0.3f);
	shader.setVec3f("dirLight.ambient", 0.05f, 0.05f, 0.05f);
	shader.setVec3f("dirLight.diffuse", 0.4f, 0.4f, 0.4f);
	shader.setVec3f("dirLight.specular", 0.0f, 0.0f, 0.0f);

	// point light 1
	shader.setVec3f("pointLights[0].position", point_light_positions[0]);
	shader.setVec3f("pointLights[0].ambient", 0.05f, 0.05f, 0.05f);
	shader.setVec3f("pointLights[0].diffuse", 0.8f, 0.8f, 0.8f);
	shader.setVec3f("pointLights[0].specular", 0.0f, 0.0f, 0.0f);
	shader.setFloat("pointLights[0].constant", 1.0f);
	shader.setFloat("pointLights[0].linear", 0.09f);
	shader.setFloat("pointLights[0].quadratic", 0.032f);

	glBindVertexArray(VAO);
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
	glBindVertexArray(0);
}

void SpriteRenderer_convexhull::printVertices()
{
	std::cout << "Vertices data (rendering)" << std::endl;
	for (size_t i = 0; i < this->vertices.size(); ++i)
	{
		std::cout << "Vertex " << i << ": (" << this->vertices[i].position.x << ", " << this->vertices[i].position.y <<", " << this->vertices[i].position.z << ")" << std::endl;
	}
}


glm::vec3 calculateNormal(glm::vec3 vertex1, glm::vec3 vertex2, glm::vec3 vertex3) 
{
	glm::vec3 edge1 = vertex2 - vertex1;
	glm::vec3 edge2 = vertex3 - vertex1;

	return glm::normalize(glm::cross(edge1, edge2));
}

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.