2010-11-05 9 views
2

Je travaille sur un outil de génération de planètes en C++ et actuellement j'essaie de générer des textures et des heightmaps. J'utilise une fonction de bruit perlian 3d pour cela, donc chaque fois que je génère une texture ou heightmap je vais calculer la valeur de la fonction de bruit pour chaque sommet sur la surface de la sphère.Définition d'un tableau statique de flottants en C++

Ces coordonnées ne changent pas. À l'origine je calculais ces derniers en mappant un cube à une sphère en utilisant this method. Je pensais alors bien si je sais que ces valeurs vont être les mêmes à chaque fois, pourquoi ne pas les calculer une fois et les sortir dans un fichier d'en-tête où elles peuvent être définies comme des tableaux statiques.

Je veux créer des textures de 512x512, cela signifie 260,000+ co coordonnées sont générées par face :(

Les coordonnées de co résultantes ont été stockées dans un tableau:

float textureMapSaved[6][512][512][3] = {etc}; 

Comme le cube a 6 faces, 512x512 pixels par face et 3 co-ordonnées (x, y & z)

Cela je l'espère me permettra alors que la boucle à travers le réseau obtenir la co ordonnée de la valeur dans la fonction du bruit perlian que je suis intéressé.

Jusqu'à présent, je n'ai réussi à transformer mon ordinateur en chialer désordre.

Ma question est:

Y at-il un moyen viable de le faire?

Sans créer le fichier de sortie, le programme prend environ 15 minutes pour calculer la sphère. Je ne pouvais pas vraiment compiler avec l'en-tête, il a crashé mon ordinateur. J'ai ensuite essayé 256x256 et cela a fonctionné un peu mieux mais mon ordinateur continuait de caler; Je suppose que c'est parce qu'il ne peut pas allouer de la mémoire pour le tableau 4D efficacement.


Merci pour les réponses rapides!

En ce moment je suis en train de faire ce qui suit:

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(); 

Comment puis-je enregistrer comme un fichier binaire et le lire directement dans la mémoire?

+1

La baie ne mesure que 16 Mo environ. Tant qu'il est alloué statiquement (en utilisant static ou en le plaçant dans l'espace de noms) ou dynamiquement (en utilisant new) et tant que vous n'avez pas de mémoire ou que vous n'avez plus de morceaux contigus assez grands pour le contenir , l'allocation elle-même ne devrait pas être un goulot d'étranglement. –

+0

Si votre ordinateur est tombé en panne, vous faites probablement autre chose de mal. Comme dit James, ce n'est pas vraiment un grand choix. Code postal –

+0

Alors, avez-vous déjà généré le fichier d'en-tête? Ou est-ce que cela prend 15 minutes juste pour calculer la carte de texture? Si cela prend si longtemps et que vous avez déjà généré et inclus l'en-tête, je soupçonne que le préprocesseur ne passe pas un bon moment à gérer un énorme fichier d'en-tête. –

Répondre

4

La méthode que vous décrivez est la meilleure combinaison d'efficacité et de simplicité. Si votre compilateur ne peut pas gérer toute la définition de tableau en une fois, divisez le problème en plusieurs parties.Par exemple:

typedef float CubeFace[512][512][3]; 
CubeFace face1 = {etc}; 
... 
CubeFace * textureMapSaved[6] = {&face1, &face2, &face3, &face4, &face5, &face6}; 

Comme alternative, arrêter d'essayer de faire de votre définition d'un fichier texte compilable et en faire un fichier binaire. Vous pouvez le lire en mémoire en une opération ou en faire un fichier mappé en mémoire et laisser le système d'exploitation l'échanger si nécessaire.

+0

En effet. Compilez la définition de tableau dans un fichier objet séparé et liez-le statiquement ou dynamiquement ou "extern". –

+1

Non ne pas du tout compiler le tableau, le dernier paragraphe est le meilleur conseil: ne créez pas de code source mais écrivez le tableau créé dans un fichier binaire et chargez-le en mémoire en utilisant la fonction read() library. –

+0

J'ai l'intention de faire comme vous le dites et de le sauvegarder en tant que binaire. En ce moment j'ai essayé la première de vos suggestions et je peux compiler le code mais quand il construit, il bloque juste les studios visuels. Qu'est-ce qui peut causer cela? – henryprescott

0

Sauvegardez vos visages séparément. Aussi, je doute sérieusement que vous ayez besoin de trois coordonnées par pixel; Je parie qu'un seul scalaire, combiné avec les valeurs inhérentes x, y dans les coordonnées du tableau, serait suffisant.

0

Comme d'autres l'ont fait remarquer, la taille du tableau n'est pas une grosse affaire. Quelque chose d'autre ne va pas, par ex. vous avez essayé de mettre ceci sur la pile comme une variable automatique.

J'ajouterai que lorsque l'on travaille avec des ensembles de données de cette taille, l'efficacité du cache joue un grand rôle dans les performances. Votre algorithme devrait essayer de faire deux choses: 1) Garder les lectures de tableau groupées les unes près des autres à la fois en temps et en adresse mémoire. Cela signifie ne pas sauter dans les dimensions d'ordre élevé, par ex. faces de cube, jusqu'à ce que vous ayez fini de traiter les dimensions de poids faible, par ex. sommets individuels. Réorganisez les dimensions du tableau selon les besoins pour y parvenir. 2) Essayez de toucher la matrice dans un modèle incrémentiel prévisible en termes d'adresse mémoire. Cela permet aux préextracteurs de cache de mettre les données dans le cache de manière proactive à l'avance.

Vous pourriez aussi vous amuser en divisant le travail en tâches parallèles.

Questions connexes