Defining a static array of floats in C++
I'm working on a planet generation tool in C++ and currently I'm trying to g开发者_开发知识库enerate textures and heightmaps.
I'm using a 3d perlian noise function for this, so every time I generate a texture or heightmap I will calculate the value of the noise function for every vertex on the surface of the sphere.
These co ordinates do not change. Originally I was calculating these by mapping a cube to a sphere using this method.
I then thought well if I know these values are going to be the same each time, why not calculate them once and output them to a headerfile where they can be defined as static arrays.
I want to create textures 512x512 this means 260,000+ co ordinates are generated per face :(
The resulting co ordinates were stored in an array:
float textureMapSaved[6][512][512][3] = {etc};
As the cube has 6 faces, 512x512 pixels per face and 3 co ordinates (x,y & z).
This would hopefully then allow me to just loop through the array getting the co ordinate for the value in the perlian noise function that I am interested in.
Thus far I have only managed to transform my computer into a blubbering mess.
My question is:
Is there a viable way of doing this?
Without creating the output file the program takes about 15 minutes to compute the sphere. I couldn't actually compile with the header, it crashed my computer.
I then tried 256x256 and this worked a little better but my computer was still chugging; I'm guessing this is because it cannot allocate memory for the 4D array efficiently.
Thanks for the quick replies!
At the moment I am doing the following:
std::vector<std::vector<std::vector<std::vector<float>>>> textureFaces = GenerateSphereCoordinates(TEXTURE_MAP);
std::ofstream myfile;
myfile.open ("spheremapping.h");
myfile << "#ifndef _SPHEREMAP \n#define _SPHEREMAP \n\nfloat textureMapSaved[6][" << textureRes << "][" << textureRes << "][3] = {";
for(int i = 0; i < 6; i++)
{
myfile << "{";
for(int j = 0; j < textureRes; j++)
{
myfile << "{";
for(int k = 0; k < textureRes; k++)
{
if(k != textureRes - 1)
{
myfile << "{ " << textureFaces[i][j][k][0] << ", " << textureFaces[i][j][k][1] << ", " << textureFaces[i][j][k][2] << "}, " ;
}
else
{
myfile << "{ " << textureFaces[i][j][k][0] << ", " << textureFaces[i][j][k][1] << ", " << textureFaces[i][j][k][2] << "}" ;
}
}
if(j != textureRes - 1)
{
myfile << "}, \n";
}
else
{
myfile << "} \n";
}
}
if(i != 5)
{
myfile << "}, \n\n";
}
else
{
myfile << "} \n\n";
}
}
myfile << "};\n\n#endif";
myfile.close();
How do I save it as a binary file and read it directly into memory?
The method you describe is the best combination of efficiency and simplicity. If your compiler can't handle the entire array definition all at once, break the problem down into pieces. For example:
typedef float CubeFace[512][512][3];
CubeFace face1 = {etc};
...
CubeFace * textureMapSaved[6] = {&face1, &face2, &face3, &face4, &face5, &face6};
As an alternative, stop trying to make your definition a compilable text file and make it a binary file. You can read it into memory in one operation, or make it a memory mapped file and let the OS swap it as necessary.
Save your faces separately. Also, I seriously doubt that you need three coordinates per pixel; I'd bet that a single scalar, when combined with the inherent x, y values in the array coordinates, would be enough.
As others have pointed out, the array size is no big deal. Something else is going wrong, e.g. you tried to put this on the stack as an automatic variable.
I'll add that when working with data sets of this size, cache efficiency plays a big role in performance. Your algorithm should try to do two things: 1) Keep array reads clustered near each other in both time and memory address. This means don't jump around in the high order dimensions, e.g. cube faces, until you are done processing the low order dimensions, e.g. individual vertices. Reorganize the array dimensions as necessary to help achieve this. 2) Try to touch the array in a predictable incremental pattern in terms of memory address. This allows the cache prefetchers to proactively bring data into cache ahead of time.
You could have all kinds of fun dividing the work into parallel tasks too.
精彩评论