0

In my program, I'm creating terrain using Perlin noise. The terrain is being generated correctly and now I'm trying to store my calculated normals into a float array called normals. It's storing the normals correctly up to a certain index but then it just stores 0s. Here is my code:

float frequency = 8;
float flagVertices[ N*N*VALS_PER_VERT*VERTICES_PER_QUAD ];
float normals[ N*N*VALS_PER_VERT*VERTICES_PER_QUAD ];
int idxFlag = 0;
int normFlag = 0;
for (int i=0;i < N;i++){
    for (int j=0;j < N;j++){
        // *** Face 1 ***
        // (0,0)
        flagVertices[idxFlag++] = (float)i/N;
        flagVertices[idxFlag++] = 0.2f*PerlinNoise( glm::vec2( (float)i/N*frequency, (float)j/N*frequency ) );
        flagVertices[idxFlag++] = (float)j/N;
        glm::vec3 p0 = glm::vec3(flagVertices[idxFlag-3], flagVertices[idxFlag-2], flagVertices[idxFlag-1]);                

        // (0,1)
        flagVertices[idxFlag++] = (float)i/N;
        flagVertices[idxFlag++] = 0.2f*PerlinNoise( glm::vec2( (float)i/N*frequency, (float)(j+1)/N*frequency ) );
        flagVertices[idxFlag++] = (float)(j+1)/N; 
        glm::vec3 p1 = glm::vec3(flagVertices[idxFlag-3], flagVertices[idxFlag-2], flagVertices[idxFlag-1]); 

        // (1,1)
        flagVertices[idxFlag++] = (float)(i+1)/N;
        flagVertices[idxFlag++] = 0.2f*PerlinNoise( glm::vec2( (float)(i+1)/N*frequency, (float)(j+1)/N*frequency ) );
        flagVertices[idxFlag++] = (float)(j+1)/N; 
        glm::vec3 p2 = glm::vec3(flagVertices[idxFlag-3], flagVertices[idxFlag-2], flagVertices[idxFlag-1]);

        // Adding in normals
        glm::vec3 normal = glm::abs(glm::triangleNormal(p0,p1,p2));
        normals[normFlag++] = normal.x;
        normals[normFlag++] = normal.y;
        normals[normFlag++] = normal.z;

        // *** Face 2 ***
        // (1,1)
        flagVertices[idxFlag++] = (float)(i+1)/N;
        flagVertices[idxFlag++] = 0.2f*PerlinNoise( glm::vec2( (float)(i+1)/N*frequency, (float)(j+1)/N*frequency ) );
        flagVertices[idxFlag++] = (float)(j+1)/N;
        glm::vec3 p3 = glm::vec3(flagVertices[idxFlag-3], flagVertices[idxFlag-2], flagVertices[idxFlag-1]); 

        // (1,0)
        flagVertices[idxFlag++] = (float)(i+1)/N;
        flagVertices[idxFlag++] = 0.2f*PerlinNoise( glm::vec2( (float)(i+1)/N*frequency, (float)j/N*frequency ) );
        flagVertices[idxFlag++] = (float)j/N;
        glm::vec3 p4 = glm::vec3(flagVertices[idxFlag-3], flagVertices[idxFlag-2], flagVertices[idxFlag-1]); 

        // (0,0)
        flagVertices[idxFlag++] = (float)i/N;
        flagVertices[idxFlag++] = 0.2f*PerlinNoise( glm::vec2( (float)i/N*frequency, (float)j/N*frequency ) );
        flagVertices[idxFlag++] = (float)j/N;
        glm::vec3 p5 = glm::vec3(flagVertices[idxFlag-3], flagVertices[idxFlag-2], flagVertices[idxFlag-1]);

        // Adding in normals
        normal = glm::abs(glm::triangleNormal(p3,p4,p5));
        normals[normFlag++] = normal.x;
        normals[normFlag++] = normal.y;
        normals[normFlag++] = normal.z;
    }
}

I'm sure that this is a C++ problem, I'm having, because I've tried printing out the normals just after it's been created and I see no 0s. But when I'm printing out the normals from the array (with the right index), I just get a 0.

HypoFreak
  • 7
  • 2
  • 1
    What is `N`? What is `VALS_PER_VERT`? What is `VERTICES_PER_QUAD`? Are you sure your indexing will never be out of bounds? Try using a memory debugger like [Valgrind](http://valgrind.org/) or similar. – Some programmer dude May 31 '18 at 09:00
  • You might find [this answer](https://stackoverflow.com/a/216731/410767) on array size limitations insightful. More generally, older compilers may have limitations well below what the memory architecture supports. It's probably best to allocate large memory blocks dynamically. – Tony Delroy May 31 '18 at 09:01
  • @TonyDelroy Surely if that was kicking in then the OP would be getting an exception. Still, putting large arrays on the stack is certainly poor practise. They should be dynamically allocated instead. – Paul Sanders May 31 '18 at 09:04
  • N, VALS_PER_VERT and VERTICES_PER_QUAD are just macro numbers, I've defined, that are used for generating the terrain. – HypoFreak May 31 '18 at 09:06
  • I haven't tried allocating memory to the heap yet, I'll give that a shot in a bit. – HypoFreak May 31 '18 at 09:07
  • But what are their definitions? What values will be used in your arrays? Better yet, please try to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) to show us. – Some programmer dude May 31 '18 at 09:08
  • N=64, VALS_PER_VERT=3, VERTICES_PER_QUAD=6. I can't create that sort of example to replicate the actual error because it requires a lot of code. – HypoFreak May 31 '18 at 09:34
  • Making the arrays dynamic still produces the same result. – HypoFreak May 31 '18 at 09:42

1 Answers1

0

For the normals array, drop the multiplication with VALS_PER_VERT. It will make your array three times bigger than it needs to be.

The values of the elements that you don't initialize depends on where you define the arrays: If they are defined as global (or namespace) variables they will be initialized as zero; If they are defined as local variables inside a function their values will be indeterminate (and reading them will lead to undefined behavior).

So definition should be

float normals[ N*N*VERTICES_PER_QUAD ];

and remember to not go out of bounds of it. This will make all elements initialized inside the loop you show.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I see, that explains as to why there are 0s in the array. Edit: Your answer made me realise that I needed to store the normals 4 additional times per loop. Thank you! – HypoFreak May 31 '18 at 09:59