C++ Dynamic Array Write Access Violation - c++

This has been bugging me for almost 2 days now. I have in my class definition a 2-D dynamic array:
class Raster {
public:
int pixels[][4];
void drawTriangle(Vector2f & V1, Vector2f & V2, Vector2f & V3, PixelColor & colorA, PixelColor & colorB, PixelColor & colorC);
};
In my drawing method I have this loop
for (int Y = maxY; Y >= minY; Y--) {
for (int X = minX; X <= maxX; X++) {
float lambda1;
float lambda2;
float lambda3;
triangle.getBarycentricCoordinate(X, Y, &lambda1, &lambda2, &lambda3);
if ((0.0f <= lambda1 && 0.0f <= lambda2 && 0.0f <= lambda3)) {
PixelColor a = lambda1 * colorA;
PixelColor b = lambda2 * colorB;
PixelColor c = lambda3 * colorC;
PixelColor interpolatedColor = a + b + c;
pixels[Y*width + X][0] = interpolatedColor.R;
pixels[Y*width + X][1] = interpolatedColor.G;
pixels[Y*width + X][2] = interpolatedColor.B;
}
}
}
Can anyone point out why it is wrong? Here is the error message: "Exception thrown: write access violation.
this was 0x111013530C28FA2."

pixels[][2] doesn't define a non-zero length array here. You need to specify a number for the first dimension too.

I don't think that's a dynamic array.
When you declare an array you are required to declare it's size as well. You can tell what kind of array it is by what you create it as and what the data is.
For instance in the following code :
// Here we can see that the array is a 4X3.
int pixels[][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
This would work just fine, because the size of the array is understood.
Further i would like to add that if you really want something not restrained by size and want the size to be dynamic depending on the data you have, then you could use the various containers that Standard Template Library offers such as a std::vector.

Related

C++. Low level graphics. Polygon mesh data reading via classes. Need elaboration on the code of the constructor

I have been studying C++ and low-level graphics and currently have questions on this code from https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-polygon-mesh.
class PolygonMesh : public Object
{
public:
PolygonMesh(uint32_t nfaces, int *fi, int *vi, Vec3f *p) :
numFaces(nf), faceIndex(NULL), vertexIndex(NULL), P(NULL)
{
// compute vertArraySize and maxVertexIndex
uint32_t vertArraySize = 0;
uint32_t maxVertexIndex = 0, index = 0;
for (uint32_t i = 0; i < numFaces; ++i) {
vertArraySize += nv[i];
for (uint32_t j = 0; j < fi[i]; ++j)
if (vi[index + j] > maxVertexIndex)
maxVertexIndex = vi[index + j];
index += fi[i];
}
maxVertexIndex += 1;
pts = std::unique_ptr<Vec3f []>(new point[maxVertexIndex]);
for (uint32_t i = 0; i < maxVertexIndex; ++i) P[i] = p[i];
vertexIndex = std::unique_ptr<uint32_t []>(new int[maxVertexIndex]);
for (uint32_t i = 0; i < maxVertexIndex; ++i) vertexIndex [i] = vi[i];
faceIndex = std::unique_ptr<uint32_t>(new int[numFaces]);
for (uint32_t i = 0; i < numFaces; ++i) faceIndex[i] = fi[i];
};
~PolygonMesh() { /* release memory */ ... }
bool intersect(...) const { ... }
void getSurfaceData(...) const { ... }
uint32_t numFaces; //number of faces
std::unique_ptr<uint32_t []> faceIndex; //face index
std::unique_ptr<uint32_t []> vertexIndex; //vertex index
std::unique_ptr<Vec3f []> P;
};
int main(...)
{
...
uint32_t numFaces = 2;
uint32_t faceIndex[2] = {4, 4};
uint32_t vertexIndex[8] = {0, 1, 2, 3, 0, 3, 4, 5};
Vec3f P[6] = {
Vec3f (-5, -5, 5), Vec3f ( 5, -5, 5),
Vec3f ( 5, -5, -5), Vec3f (-5, -5, -5),
Vec3f (-5, 5, -5), Vec3f (-5, 5, 5),
};
PolygonMesh *mesh = new PolygonMesh(numFaces, faceIndex, vertexIndex, P);
...
}
The website (the author) says :
The point list, face and vertex index array are passed to the constructor of the MeshPolygon class as well as the number of faces. However we don't know how many points are in the point array. To find out, we look for the vertex with the maximum index value in the vertex index array (lines 13-14). The first element of an array in C++ start at 0, therefore the total number of vertices in the point list is the maximum index value plus 1 (line 17).
So, it is about getting data from polygon mesh! Several questions puzzle me :
Above it says, "...we don't know how many points are in the point array..." In my understanding, why just not read the size of the P array that is being passed from the main() ? That is supposed to be the size of the array, or...?
If my understanding correct, then in the PolygonMesh(..) constructor what happens is deep copying of pointers(and all the values those addresses' possess) ? Is it right? I am asking , because I have just learned( or read) recently about smart pointers, std::move and r-values references. Also, in the code, they don't std::move all the pointers from main to the class object because we want to save those original data (pointers), right?
Is it correct that in order to find Vertex Array Size in the above code for the class object, we could just read the maximum value of uint32_t vertexIndex[8], i.e maximum vertexIndexArray is the total number of vertices?
I assume in line 11 it must be vertIndexArraySize += fi[i]; instead of vertArraySize += nv[i]; because I have no idea where does nv come from what what it means...
Thank you all for your genuine help !

include c++ libraries into openCL kernel?

Is it possible to utilize C++ style libraries for use in an openCL kernel?
I'm trying to implement a kernel that performs the tasks seen in the following code. There are two things that could make this really difficult: 1. The fact that I'm using the GLM math library, and 2. That I'm using structs (land_map_t).
For example, if I wanted to use a kernel to loop through a large 3-dimensional array, is it possible to include the GLM math library inside of the kernel and utilize its functionalities such as glm::simplex? I've heard that modern C++ functionalities such as classes aren't compatible with kernels.
And if that's not possible, how would one pass a struct to the kernel? should I define the same struct in both the kernel and my implementation? All the struct contains is a 3-dimensional array, so I could easily just turn it into a default C++ type if it was necessary.
land_map_t * Chunk::terrain_gen(glm::ivec3 pos)
{
float frequency = 500;
float noise_1;
land_map_t* landmap = new land_map_t;
for (int x = 0; x < chunkSize + 2; x++) {
for (int y = 0; y < chunkSize + 2; y++) {
for (int z = 0; z < chunkSize + 2; z++) {
noise_1 = (glm::simplex(
glm::vec2(glm::ivec2(x, z) + glm::ivec2(pos.x, pos.z)) / frequency));
landmap->i[x][y][z] = BLOCK::AIR;
if (pow(noise_1, 2) * 40.0 + 6.0 > (y + pos.y))
{
landmap->i[x][y][z] = BLOCK::DIRT;
}
}
}
}
return landmap;
}
You cannot include C++ libraries in OpenCL C. OpenCL is C99, not C++. There are no classes and only 1D arrays in OpenCL. Within a kernel there is also no dynamic memory allocation possible with the new operator.
The best solution is to split the class components up into arrays and within each array use linear indexing to get from (x, y, z)=(n%(Lx*Ly)%Lx, n%(Lx*Ly)/Lx, n/(Lx*Ly)) in the rectangular box of the size (Lx,Ly,Lz) to the linear index n=x+(y+z*Ly)*Lx; and back.
Your code in OpenCL could look like this:
kernel void terrain_gen(global uchar* landmap_flags, global float3* pos)
const uint n = get_global_id(0);
const uint x = n%((chunkSize+2)*(chunkSize+2))%(chunkSize+2);
const uint y = n%((chunkSize+2)*(chunkSize+2))/(chunkSize+2);
const uint z = n/((chunkSize+2)*(chunkSize+2))
// paste the SimplexNoise struct definition here
SimplexNoise simplexnoise;
simplexnoise.initialize();
const float frequency = 500;
const float noise_1 = (simplexnoise.noise(x,z)+simplexnoise.noise(pos[n].x, pos[n].z))/ frequency;
landmap_flags[n] = (noise_1*noise_1*40.0f+6.0f>(y+pos[n].y)) ? BLOCK_DIRT : BLOCK_AIR;
}
Regarding GLM, you have to port over the required functions into OpenCL C. For simplex noise, you can use something like this:
struct SimplexNoise { // simplex noise in 2D, sources: https://gist.github.com/Ellpeck/3df75965a542e2163d1ae9cf3e4777bb, https://github.com/stegu/perlin-noise/tree/master/src
const float3 grad3[12] = {
(float3)( 1, 1, 0), (float3)(-1, 1, 0), (float3)( 1,-1, 0), (float3)(-1,-1, 0),
(float3)( 1, 0, 1), (float3)(-1, 0, 1), (float3)( 1, 0,-1), (float3)(-1, 0,-1),
(float3)( 0, 1, 1), (float3)( 0,-1, 1), (float3)( 0, 1,-1), (float3)( 0,-1,-1)
};
const uchar p[256] = {
151,160,137, 91, 90, 15,131, 13,201, 95, 96, 53,194,233, 7,225,140, 36,103, 30, 69,142, 8, 99, 37,240, 21, 10, 23,190, 6,148,
247,120,234, 75, 0, 26,197, 62, 94,252,219,203,117, 35, 11, 32, 57,177, 33, 88,237,149, 56, 87,174, 20,125,136,171,168, 68,175,
74,165, 71,134,139, 48, 27,166, 77,146,158,231, 83,111,229,122, 60,211,133,230,220,105, 92, 41, 55, 46,245, 40,244,102,143, 54,
65, 25, 63,161, 1,216, 80, 73,209, 76,132,187,208, 89, 18,169,200,196,135,130,116,188,159, 86,164,100,109,198,173,186, 3, 64,
52,217,226,250,124,123, 5,202, 38,147,118,126,255, 82, 85,212,207,206, 59,227, 47, 16, 58, 17,182,189, 28, 42,223,183,170,213,
119,248,152, 2, 44,154,163, 70,221,153,101,155,167, 43,172, 9,129, 22, 39,253, 19, 98,108,110,79,113,224,232,178,185, 112,104,
218,246, 97,228,251, 34,242,193,238,210,144, 12,191,179,162,241, 81, 51,145,235,249, 14,239,107, 49,192,214, 31,181,199,106,157,
184, 84,204,176,115,121, 50, 45,127, 4,150,254,138,236,205, 93,222,114, 67, 29, 24, 72,243,141,128,195, 78, 66,215, 61,156,180
};
const float F2=0.5f*(sqrt(3.0f)-1.0f), G2=(3.0f-sqrt(3.0f))/6.0f; // skewing and unskewing factors for 2, 3, and 4 dimensions
const float F3=1.0f/3.0f, G3=1.0f/6.0f;
const float F4=(sqrt(5.0f)-1.0f)*0.25f, G4=(5.0f-sqrt(5.0f))*0.05f;
uchar perm[512]; // to remove the need for index wrapping, double the permutation table length
uchar perm12[512];
//int floor(const float x) const { return (int)x-(x<=0.0f); }
float dot(const float3 g, const float x, const float y) const { return g.x*x+g.y*y; }
void initialize() {
for(int i=0; i<512; i++) {
perm[i] = p[i&255];
perm12[i] = (uchar)(perm[i]%12);
}
}
float noise(float x, float y) const { // 2D simplex noise
float n0, n1, n2; // noise contributions from the three corners, skew the input space to determine simplex cell
float s = (x+y)*F2; // hairy factor for 2D
int i=floor(x+s), j=floor(y+s);
float t = (i+j)*G2;
float X0=i-t, Y0=j-t; // unskew the cell origin back to (x,y) space
float x0=x-X0, y0=y-Y0; // the x,y distances from the cell origin
// for the 2D case, the simplex shape is an equilateral triangle, determine simplex
int i1, j1; // offsets for second (middle) corner of simplex in (i,j) coords
if(x0>y0) { i1=1; j1=0; } // lower triangle, XY order: (0,0)->(1,0)->(1,1)
else /**/ { i1=0; j1=1; } // upper triangle, YX order: (0,0)->(0,1)->(1,1)
float x1=x0- i1+ G2, y1=y0- j1+ G2; // offsets for middle corner in (x,y) unskewed coords
float x2=x0-1.0f+2.0f*G2, y2=y0-1.0f+2.0f*G2; // offsets for last corner in (x,y) unskewed coords
int ii=i&255, jj=j&255; // work out the hashed gradient indices of the three simplex corners
int gi0 = perm12[ii +perm[jj ]];
int gi1 = perm12[ii+i1+perm[jj+j1]];
int gi2 = perm12[ii+ 1+perm[jj+ 1]];
float t0 = 0.5f-x0*x0-y0*y0; // calculate the contribution from the three corners
if(t0<0) n0 = 0.0f; else { t0 *= t0; n0 = t0*t0*dot(grad3[gi0], x0, y0); } // (x,y) of grad3 used for 2D gradient
float t1 = 0.5f-x1*x1-y1*y1;
if(t1<0) n1 = 0.0f; else { t1 *= t1; n1 = t1*t1*dot(grad3[gi1], x1, y1); }
float t2 = 0.5f-x2*x2-y2*y2;
if(t2<0) n2 = 0.0f; else { t2 *= t2; n2 = t2*t2*dot(grad3[gi2], x2, y2); }
return 70.0f*(n0+n1+n2); // add contributions from each corner to get the final noise value, result is scaled to stay inside [-1,1]
}
};

Assigning in high-dimensional Xtensor arrays

I am using the Xtensor library for C++.
I have a xt::zeros({n, n, 3}) array and I would like to assign the its i, j, element an xt::xarray{ , , } so that it would store a 3D dimensional vector at each (i, j). However the documentation does not mention assigning values - I am in general unable to figure out from the documentation how arrays with multiple coodinates works.
What I have been trying is this
xt::xarray<double> force(Body body1, Body body2){
// Function to calulate the vector force on body2 from
// body 1
xt::xarray<double> pos1 = body1.get_position();
xt::xarray<double> pos2 = body2.get_position();
// If the positions are equal return the zero-vector
if(xt::all(xt::equal(pos1, pos2))) {
return xt::zeros<double>({1, 3});
}
xt::xarray<double> r12 = pos2 - pos1;
double dist = xt::linalg::norm(r12);
return -6.67259e-11 * body1.get_mass() * body2.get_mass()/pow(dist, 3) * r12;
}
xt::xarray <double> force_matrix(){
// Initialize the matrix that will hold the force vectors
xt::xarray <double> forces = xt::zeros({self_n, self_n, 3});
// Enter the values into the force matrix
for (int i = 0; i < self_n; ++i) {
for (int j = 0; j < self_n; ++j)
forces({i, j}) = force(self_bodies[i], self_bodies[j]);
}
}
Where I'm trying to assign the output of the force function as the ij'th coordinate in the forces array, but that does not seem to work.
In xtensor, assigning and indexing into multidimensional arrays is quite simple. There are two main ways:
Either index with round brackets:
xarray<double> a = xt::zeros({3, 3, 5});
a(0, 1, 3) = 10;
a(1, 1, 0) = -100; ...
or by using the xindex type (which is a std::vector at the moment), and the square brackets:
xindex idx = {0, 1, 3};
a[idx] = 10;
idx[0] = 1;
a[idx] = -100; ...
Hope that helps.
You can also use view to achieve that.
In the inner loop, you could do:
xt::view(forces, i, j, xt::all()) = a_xarray_with_proper_size;

VexCL: set values common to all vector elements

I work with ray tracing and use GPU to calculate pixel colours. I was using NVIDIA CUDA and now want to go to VexCL. I'm trying to use such code:
struct Ray;
vex::Context ctx(...);
...
unsigned int frame_width, frame_height;
std::array<float, 4> camera_direction, camera_up;
float camera_fov;
...
// initialize values and store them in GPU memory too
...
vex::vector<Ray> rays(ctx, frame_width * frame_height);
and something like
rays = some_expression_to_calculate_ray(vex::element_index(), frame_width,
camera_direction, camera_up, camera_fov);
So my question is: how can I explain to VexCL that some values must be common for all vector elements?
I was trying VEX_CONSTANT, vex::raw_pointer but it is not what I need.
If you change the type of camera_direction and camera_up from std::array<float,4> to cl_float4, then you would be able to directly use those in an expression:
#include <vexcl/vexcl.hpp>
int main() {
vex::Context ctx(vex::Filter::Env);
VEX_FUNCTION(float, dummy, (size_t, idx)(cl_float4, dir)(cl_float4, up)(float, fov),
// whatever
return idx + length(dir - up) + fov;
);
cl_float4 camera_dir = {1, 2, 3, 4}, camera_up = {1, 0, 0, 0};
float camera_fov = 42;
vex::vector<float> rays(ctx, 1024);
rays = dummy(vex::element_index(), camera_dir, camera_up, camera_fov);
}
(I've changed rays to be a vector of floats for simplicity, see the linked question for how to work with structs in VexCL.) camera_dir, camera_up, and camera_fov are defined host-side, and they are passed to the kernel as parameters. So no unnecessary copies are being made. Here is the generated OpenCL kernel:
float dummy(ulong idx, float4 dir, float4 up, float fov) {
return idx + length(dir - up) + fov;
}
kernel void vexcl_vector_kernel(
ulong n,
global float * prm_1,
ulong prm_2,
float4 prm_3,
float4 prm_4,
float prm_5
)
{
for(ulong idx = get_global_id(0); idx < n; idx += get_global_size(0))
{
prm_1[idx] = dummy( (prm_2 + idx), prm_3, prm_4, prm_5 );
}
}

How to initialize 3D array in C++

How do you initialize a 3d array in C++
int min[1][1][1] = {100, { 100, {100}}}; //this is not the way
The array in your question has only one element, so you only need one value to completely initialise it. You need three sets of braces, one for each dimension of the array.
int min[1][1][1] = {{{100}}};
A clearer example might be:
int arr[2][3][4] = { { {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} },
{ {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} } };
As you can see, there are two groups, each containing three groups of 4 numbers.
Instead of static multidimensional arrays you should probably use one-dimensional array and calculate the index by multiplication. E.g.
class Array3D {
size_t m_width, m_height;
std::vector<int> m_data;
public:
Array3D(size_t x, size_t y, size_t z, int init = 0):
m_width(x), m_height(y), m_data(x*y*z, init)
{}
int& operator()(size_t x, size_t y, size_t z) {
return m_data.at(x + y * m_width + z * m_width * m_height);
}
};
// Usage:
Array3D arr(10, 15, 20, 100); // 10x15x20 array initialized with value 100
arr(8, 12, 17) = 3;
std::vector allocates the storage dynamically, which is a good thing because the stack space is often very limited and 3D arrays easily use a lot of space. Wrapping it in a class like that also makes passing the array (by copy or by reference) to other functions trivial, while doing any passing of multidimensional static arrays is very problematic.
The above code is simply an example and it could be optimized and made more complete. There also certainly are existing implementations of this in various libraries, but I don't know of any.
Here's another way to dynamically allocate a 3D array in C++.
int dimX = 100; int dimY = 100; int dimZ = 100;
int*** array; // 3D array definition;
// begin memory allocation
array = new int**[dimX];
for(int x = 0; x < dimX; ++x) {
array[x] = new int*[dimY];
for(int y = 0; y < dimY; ++y) {
array[x][y] = new int[dimZ];
for(int z = 0; z < dimZ; ++z) { // initialize the values to whatever you want the default to be
array[x][y][z] = 0;
}
}
}
Everyone seems to forget std::valarray. It's the STL template for flat multidimensional arrays, and indexing and slicing them.
http://www.cplusplus.com/reference/std/valarray/
No static initialization, but is that really essential?