Reputation: 43
I'm trying to create a list of points whose z value will be modified by the alpha values of a grayscale image. As the points are being assigned to a list, I keep getting an access violation. I noticed during debugging that the size of the alpha array is suddenly changing in the middle of the for loop, along with my width and height values. I'm new to C++ so I imagine it's an obvious mistake. Here's the relevant code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
// image processing libs
#include "vendors/stb_image/stb_image.h"
#include "vendors/stb_image/stb_image_write.h"
#include "Image.h"
#include "Renderer.h"
#include "VertexBufferLayout.h"
// signed normalization function for scaling input value with a known input range to an output range
float snorm(float value, float in_Min, float in_Max)
{
float out_Value = ( ((1.0f - 1.0f) * ((value - in_Min) / (in_Max - in_Min))) + -1.0f );
return out_Value;
}
int main(void)
{
// CONSTANTS
const int SCREEN_WIDTH = 2000;
const int SCREEN_HEIGHT = 2000;
// glsl version
const char* glsl_version = "#version 330";
Image image("res/images/drama_mask_white.jpg");
// loads an image to greyscale (normal) and returns the path to that normal
std::string normal_Path = image.ImgToGrayScale("gray_mask");
image.GetAlphas(normal_Path);
image.setMinMaxAlphas();
const std::vector<float> * lcl_Alphas = &image.alpha_Map;
const int lcl_Width = image.img_Width;
const int lcl_Height = image.img_Height;
const float x_Increment = 2.0f / lcl_Width;
const float y_Increment = 2.0f / lcl_Height;
float positions[] = { 0 };
//unsigned int indices[] = { 0 };
unsigned int row = 0;
unsigned int col = 0;
unsigned int num_Rows = 0;
unsigned int num_Cols = 0;
unsigned int num_Verteces = 0;
unsigned int pos_Count = 0;
for (int i = 0; (unsigned)i < image.alpha_Map.size(); i++)
{
// checks for the end of the row
if (i > 0 && (i % (image.img_Width - 1)) == 0)
{
row++; // if we've reached the end of a row, increment row index
num_Cols = col;
col = 0; // reset column index at end of each row
}
// assign position values starting from bottom left
// X
positions[pos_Count] = -1.0f + (col * x_Increment);
// Y
positions[pos_Count + 1] = -1.0f + (row * y_Increment);
// Z
// ERROR OCCURS HERE
positions[pos_Count + 2] = snorm(image.alpha_Map[i], image.min_Alpha, image.max_Alpha);
pos_Count += 3;
// indices
//indices[i] = i;
col++; // increment column index
num_Verteces++;
}
std::cout << "Num Verteces: " << num_Verteces << std::endl;
std::cout << "Num Positions: " << pos_Count << std::endl;
num_Rows = row;
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
// create window and context with core profile
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
// checks if GLEW intializes correctly
if (glewInit() != GLEW_OK)
std::cout << "ERROR!" << std::endl;
std::cout << glGetString(GL_VERSION) << std::endl;
// enable blending
GLCall(glEnable(GL_BLEND));
// get source alpha, subtract from one to blend alpha at destination
GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
// init renderer object
Renderer renderer;
GLfloat test_Vertex[] = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 0.0f };
while (!glfwWindowShouldClose(window)) {
GLCall(glClearColor(0.0, 0.0, 0.0, 1.0));
renderer.Clear();
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, test_Vertex);
glDisableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_POINTS, 0, 1);
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for, and process events
glfwPollEvents();
}
glfwTerminate();
}
Upvotes: 0
Views: 124
Reputation: 189
I see you are a new contributor. I think in the future you can do a better job at 'minimizing' your example code. The general idea: Try to delete lines to have the error happen with little code as possible, maybe you will find a line that makes the difference. This also helps you find mistakes before you have to ask others.
I think a big problem here may be that your array of positions
will always be of size 1.
This makes it harder to figure out any other problems in the rest of the code till this is fixed.
Using float positions[] = { 0 };
means the compiler will only reserve enough space for the positions array to contain 1 float value. So writing to positions[0] = 42
is valid, but writing to positions[1] = 42
can already be bad. Maybe you are lucky and your program crashes immediatly. If you are unlucky your program will write to the memory past the end of your array, and if you are extra unlucky this memory contains something important. It could contain something like the size of your vector of alphas or any other data in memory. So the errors it causes can become very unpredictable.
int main() {
char greeting[] = "Hello World!\n";
float positions[] = { 0 };
positions[0] = 42; // GOOD inside array bounds
positions[4] = 42; // BAD outside array bounds destroying other data
std::cout << greeting;
}
Here is an example where I break a hello-world greeting on purpose by writing out of bounds of an array. If you provide information about the IDE or compiler you are using people are able to tell you how to enable or view warnings for such mistakes. For example GCC's -Wall or -Warray-bounds. Or you can Google it yourself by adding "out of bounds warning".
Output of the example
> clang++-7 -pthread -std=c++17 -o main main.cpp
main.cpp:7:3: warning: array index 4 is past the end of the array
(which contains 1 element) [-Warray-bounds]
positions[4] = 42; // BAD outside array bounds destroying other data
^ ~
main.cpp:5:3: note: array 'positions' declared here
float positions[] = { 0 };
^
1 warning generated.
> ./main
Hello Worl
Upvotes: 1
Reputation: 43
@Rabbid76 and @Peter had the right idea here... I needed to use std::vector because I was initializing the array with only element, but populating it during the for loop. Once I converted to std::vector it worked fine. Now to make this thing actually draw the points...
Upvotes: 1