#0 

01-12-2012 15:04:58

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Bonjour à tous,



Je viens de faire mon algorythme pour gérer ma map mais je ne vois pas du tout comment l'adapter à mon code.
Quand je dis Algo, je pense à un morceau de papier avec marqué tout ce que dois faire le jeu pour afficher la map.

Donc voilà, mon algo est coupé en plusieurs parties :

- Le map qui fait appel aux chunks qui eux mêmes font appels aux cubes.
- Donc dans mon chunk (Morceau de map) j'aimerai qu'il fasse 16 x 16 cubes. Puis 5 cubes ayant une texture A en dessous 20 cubes ayant une texture B.
- Ensuite on demande à l'application la position de la caméra (en gros le joueur) et à partir de çà on génère 20 chunks autour de la position de notre caméra. Tout çà contenu dans une boucle pour tjrs actualiser la position.

Et là je ne sais pas trop comment m'y prendre.
Je pense qu'il faut qu'il faut que je créé une classe Chunk et dans celle ci définir la taille du chunk. Mais aucune idée de gérer tout çà
si quelqu'un veux bien m'éclaire sa serai vraiment sympathique wink


Merci d'avance
Cordialement

Hors ligne


#1 

01-12-2012 15:30:30

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

C'est pour ça que tu t'intéresses à minetest et par extension minecraft.

Logeur :

Puis 5 cubes ayant une texture A en dessous 20 cubes ayant une texture B.


Quelques images du rendu attendu serait bien parce que je vois pour le chunk mais cette phrase... incompréhensible pour moi. Tu veux dire 16x16x5 blocs ayant une texture A et en dessous de ce gros bloc 16x16x20 blocs ayant une texture B. En gros, en terme géologique, 1 chunk  = sur une surface de 16x16 mètres -> 1 strate de 5 mètres d'une matière + 1 strate de 20 mètres d'une autre matière, c'est ça?


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#2 

01-12-2012 15:37:08

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

C'est exactement çà.
Désolé si je ce n'est pas très compréhensible ^^

En effet MineTest est interressant pour çà mais je trouve rien sur les chunks ce qui m'embette un peu

Hors ligne


#3 

01-12-2012 15:44:11

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

t'a plusieur possibiliter, plus ou moin optimiser
déjà il faudrais savior si t'est cube seront dynamique ou statique, selon le cas l'implementation seras different
si dans le cas general ils sont statique avec certain dynamic tu isole t'est élément dynamique, tu crée ton environment statique et tu rend les dynamique suivant la distance de vision
il faudrais connaitre le nombre de materiaux possible, si chaque cube a un material differet ou s'il n'ont que la texture qui diffèrent

si tout est statique, le mieux c'est éffectivement de partitionner en chunk sur differents niveaux,
ton chunk "niveaux 0" par exemple represent les données au niveaux voxel
tu dérive le chunk niveaux 1 du chunk niveaux 0 et tu passe par des évents pour notifier les changement a ton chunk supérieur (niveaux1) qui lui ce chargeras de crée un mesh pour la representation graphique de ton chunk voxel
il faut veuiller a ce qu'il crée le tout en 1seul bloque, ce seras beaucoup plus rapide
-dans le cas ou seul la texture de ton material change tu crée une texture plus grande (qui contient les plus petites)  et tu joue sur l'uv map pour définire la texture
-dans le cas ou tu doit utiliser plusieur materials, tu divise ton voxel par type d'obj, qui eux seront merger dans un mesh
puis tu fait un chunk niveaux n(2, 3, ...) plus grand qui englobe t'est chunk niveaux n-1 par bloque, pour diminuer le cout en performance du test de visibiliter, et suivant la distance tu supprime ou crée t'est chunk
-tu doit prévoir la taille de t'est chunk en fonction de la capaciter de la carte graphique faire des ckunk de 5*5*5 utiliseras beaucoup de performance tout comme des chunk de 32768*32768*32768 utilisera beaucoup de memoire et te coutras chère en modification

si tu veut du dynamic c'est un peut plus compliquer la vaut mieux que tu cherche directement une lib voxel, tu perdra moins de temps a ça conception

Hors ligne


#4 

01-12-2012 15:51:30

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Ok, sa m'éclaire beaucoup.
Mais que veux tu dire par dynamique ou statique ?
Il y aura plusieurs matériaux.
Donc si je comprend bien, mon app doit avant tout vérifier la capacité de la carte graphique et en fonction de çà elle s'adapte ?

Hors ligne


#5 

01-12-2012 15:58:12

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

dynamique = lesz cubes changent souvent de position
statique = rien ne bouge

oui et non, dans ton cas tu peut trouver des paramêtre fonctionnant dans la plupar des cas
le mieux en effect c'est de calculer les performance de la carte graphique et d'adapter la taille des chunk en fonction,
il y a ce pendant une limmite commune c'est que tu est limmiter a (2^31)/3 polygonne par mesh buffer (ça peut varier les vielle carte graphique sont a (2^15)/3)
si tu veut pas t'embêter a trouver un algo pur calculer les performance tu laisse le choix a l'utilisateur au lancement
taille des chunk, distance de visions ...

Hors ligne


#6 

01-12-2012 16:04:05

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Oui mais si on prend un utilisateur lambda, je pense pas qu'il sache quoi choisir en fonction de son ordi.
Donc je pense que je vais me chercher un algo. Quoi que au début je ferai plutôt un moyen de sélectionner comme tu le dis wink

Donc si je souhaite casser les cubes et pouvoir en placer c'est donc du dynamique ...

Hors ligne


#7 

01-12-2012 16:26:33

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Oui moi non plus je n'ai pas compris grand chose à son code. Du coup, j'avais fais mon propre système de marching cubes.

Je partirais sur une base de ce style:

Code c++ :


enum MATIERE_BLOC
{
    MB_AIR            = 0,    // si aucune matière
    MB_TRANSPARENCE    = 1,    // si le bloc utilise la transparence (l'eau par exemple)
    MB_MATIERE1        = 2,    // si matière 1
    MB_MATIERE2        = 4,    // si matière 2
};
typedef s32 TypeBloc;
/**
    Il est ainsi possible d'utiliser enum MATIERE_BLOC en tant que Flags.
    ex:
    - Un bloc de matière 1 et utilisant la transparence
        -> TypeBloc type = MB_TRANSPARENCE | MB_MATIERE1;
**/


/*  Je te laise implémenté^^.
    Revoir peut-être la surface d'un chunk
    car pas optimisé tel quel.
*/


class Chunk : public ISceneNode
{
    public:
    //! constructeur par défaut
    Chunk();
    //! constructeur par copie (pour une création rapide de chunks identiques)
    Chunk(const Chunk& other);
    //! destructeur
    virtual Chunk();
   
   
    //! dessine les buffer à l'écran (implémentation de "virtual ISceneNode::render()=0;" )
    void render();
    /**
        Une meilleur méthode serait de ne pas dérivé Chunk de ISceneNode mais
        faire une autre classe dérivée de ISceneNode contenant un tableau de chunk
        qui effectuerait le rendu en fusionnant au passage les chunks ayant le même matériaux 1 et 2.
        Il serait ainsi possible de tirer parti de la taille des buffers (2^16 vertices), réduire le
        nombres de Call du driver et d'utiliser le potentiel des VBOs.
    **/


    //! dessine les faces visibles (contact avec un bloc air ou transparent) blocs dans les buffers
    void updateChunk();
   
   
    //! récupère le type d'un bloc
    const TypeBloc& getTypeBloc(const s32& X, const s32& Y, const s32& Z);
   
   
    //! implémentation de OnRegisterSceneNode() et getBoundingBox()
   
    protected:
    //! MEMBRES
    u8 ListeBloc[16][16][25];
    SMeshBuffer *BufferMatiere1, *BufferMatiere2;
    SMaterial Material1, Material2;
    aabbox3df BoundingBox;
   
    //! dessine un bloc
    void drawBloc(const s32& X, const s32& Y, const s32& Z);
}


J'ai mis dans les commentaires une idées pour un meilleur rendement. Voilà, je pense que ça te donneras quelques idées.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#8 

01-12-2012 16:33:51

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Nan mais sérieux vous êtes super !!!
Je regrette pas du tout d'avoir choisi Irrlicht plutôt qu'Ogre, car même si la communauté et pas très grosse elle est vraiment de bon conseil !!!!
C'est vraiment sympa de votre part wink

Hors ligne


#9 

01-12-2012 17:10:00

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

statique ne veut pas dire immuable
tu peut très bien changer l'environement, il est symplement plus optimiser a ne pas subir de modification
ou s'il y en n'a ce n'est pas tout le temps, mais de façon évènementiel wink

johnplayer te propose quelque chose acces sur du statique par exemple

Hors ligne


#10 

01-12-2012 18:16:34

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Oui, j'ai proposé une solution statique mais comme l'as dit Magun rien ne t'empêche de l'utiliser comme minecraft. Tu peux d'ailleurs utilisé les VBOs en statique car même si le joueur détruit et créé des cubes, il ne va pas le faire 60 fois par secondes donc tu y seras gagnant. Je t'ai donné une base mais à toi de mettre des fonctions et outils permettant de l'utilisant à ta convenance. Le dynamique serait plutot un truc genre ISceneNodeAnimator qui a besoin d'être rafraichit à chaque frame pour rester cohérent.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#11 

01-12-2012 18:32:16

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Ok merci de votre aide.
Mais qu'est ce que des VBOs ?

Hors ligne


#12 

01-12-2012 18:50:31

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

VBO : Virtual Buffer Oject. Je ne saurait te dire techniquement ce que c'est mais je vais essayer. En fait, les buffers sont stocker en RAM et le CPU envoie à chaque frame l'intégralité des buffers (vertex et index) aux GPU, ce qui est très couteux en bande passante et en temps. Les VBOs sont des buffers stockés en VRAM (mémoire de la carte graphique. Le CPU ne les envoies que lorsqu'ils sont modifié. Du coup, comme pour les textures, le GPU à tous sous la main donc il travaille beaucoup plus vite. Le gain de perfs peut être très grands suivant la nature, la taille et la fréquence de changement des buffers.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#13 

02-12-2012 13:45:17

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Je viens  de revoir mon algo, je pense l'organiser autrement.
En 1er je créé une classe bloc qui définie la taille de mon bloc avec des vertices.
Puis je dis au chunk de me créer 16 x 16 x 25 blocs.
Qu'en pensez vous ?

Hors ligne


#14 

02-12-2012 14:33:08

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Oui tu peut découper ton code de cette façon aussi. L'important c'est de rester cohérent dans ton code. La classe bloc doit créer tout ce qui concerne le bloc lui-même et le chunk récupère les infos pour les traiter.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#15 

02-12-2012 14:37:40

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Oui bah je cherche à faire un code très simple. Moi même étant débutant je ne veux pas me perdre dedans.
J'ai trouvé une portion de code pour afficher des vertices dans un cube déjà créé. Donc je me demande comment faire des vertices dans le vide pour faire un cube.

Hors ligne


#16 

02-12-2012 19:59:09

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

SMeshBuffer est un typedef de CMeshBuffer<S3DVertex>. Tu peux accéder librement au vertices et au indices. un cube, c'est 6 face de 2 triangles. Il te faut les 8 positions des coins, ensuite tu créés 3 vertices + 3 indices par triangles.

Voici un exemple:

Code c++ :


SMeshBuffer* buffer = new SMeshBuffer();

// les 8 positions
vector3df pos[8];
// les 4 coins inférieurs
pos[0] = vector3df(-100,-100,-100);
pos[1] = vector3df( 100,-100,-100);
pos[2] = vector3df(-100,-100, 100);
pos[3] = vector3df( 100,-100, 100);
// les 4 coins supérieurs
pos[4] = vector3df(-100, 100,-100);
pos[5] = vector3df( 100, 100,-100);
pos[6] = vector3df(-100, 100, 100);
pos[7] = vector3df( 100, 100, 100);

// quelques variables
vector3df normale;
SColor blanc = SColor(255,255,255,255);
u32 index_vertices = 0;

// face supérieure
  // 1 - ajout des 4 vertices (avec coordonnées de textures : 1 face est remplie par la texture complète)
  normale = vector3df(0,1,0);
  index_vertices = buffer->Vertices.size();
  buffer->Vertices.push_back( S3DVertex (pos[4], normale, blanc, vector2df(0,0)) );
  buffer->Vertices.push_back( S3DVertex (pos[5], normale, blanc, vector2df(0,1)) );
  buffer->Vertices.push_back( S3DVertex (pos[6], normale, blanc, vector2df(1,1)) );
  buffer->Vertices.push_back( S3DVertex (pos[7], normale, blanc, vector2df(1,0)) );
  // 2 - ajout des indices (2 triangles)
  buffer->Indices.push_back(index_vertices); buffer->Indices.push_back(index_vertices+1); buffer->Indices.push_back(index_vertices+2); // tri 1
  buffer->Indices.push_back(index_vertices); buffer->Indices.push_back(index_vertices+2); buffer->Indices.push_back(index_vertices+3); // tri 2



Petite note : le code n'a pas été testé les vertices et les indices ne sont pas forcément dans le bon ordre donc les triangles seront certainement à l'envers.
Les vertices d'un triangle se dessine dans le sens horaire (lorsque l'on regarde la face visible du triangle).

Fais des tests et tu comprendras le fonctionnement.

Dernière modification par johnplayer (02-12-2012 20:00:03)


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#17 

02-12-2012 20:13:43

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Mais comment j'intègre ton code dans le bloc.cpp ??
Je crois que je vais aller relire un peu le SdZ ...

Dernière modification par Logeur (02-12-2012 20:20:42)

Hors ligne


#18 

03-12-2012 11:26:56

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

J'ai repensé à ta classe bloc. En fait, c'est une mauvaise idée. Dans l'exemple que je t'ai donné, j'ai juste 1 octet par bloc, toi, tu vas avoir une classe par bloc. Je te laisse imaginer le gouffre mémoire que tu vas avoir! Le mieux se serait une classe "MapManager" dérivée de ISceneNode qui contient A x B structures "Zone" qui elle-même contient C x D structures "Chunks". Les classes "Zones" et Chunks" ne contiennent que des données nécessaires (aucune fonctions) à la classe "MapManager". "MapManager" sera chargé de créer, gérer et afficher les buffers contenant les faces à afficher.

Code c++ :


enum MATIERE_BLOC
{
    MB_AIR            = 0,    // si aucune matière
    MB_TRANSPARENCE    = 1,    // si le bloc utilise la transparence (l'eau par exemple)
    MB_MATIERE1        = 2,    // si matière 1
    MB_MATIERE2        = 4,    // si matière 2
};
typedef s32 TypeBloc; // il sera converti en u8 pour limiter la mémoire occupée. Donc le type d'un bloc sera stocké en u8

class MapManager;
struct Zone;
struct Chunk;

class MapManager : public ISceneNode
{
public:
MapManager(...)
: ISceneNode(...)
{
}
virtual ~MapManager()
{
}

// rendu (elle est virtuelle pure dans ISceneNode)
void render()
{
    // culling de zone
    // culling de chunk

    // regroupement intelligent (si plusieurs chunks utilisent les 2 mêmes materials, on fusionne leur buffers pour limiter les draw calls) (à voir pour les perfs)

    // affichage des chunks visibles
}

//! implémentation de OnRegisterSceneNode() car elle est virtuelle pure dans ISceneNode
void OnRegisterSceneNode ()
{
    // on enregistre le node dans les matériaux solides
    SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
    // un scrute tous les materials pour voir s'il contient des matérials transparent (si c'est le cas on l'enregistre dans la liste)
    for(tous les materials)
    {
        if(material utilise la transparence)
        {
            SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
            // on a pas besoin d'en savoir plus donc on quitte la boucle
            break;
       }
    }
    // on appelle celui de la classe mère (pour les enfants de ce node)
    ISceneNode::OnRegisterSceneNode();
}

//! implémentation de getBoundingBox() car elle est virtuelle pure dans ISceneNode
const aabbox3df & getBoundingBox()
{
}

// update
void updateMap()
{
    // création des 2 buffers pour chaques chunk (2 buffers par chunk car 2 materials differents)
}
void updateZones()
{
}
void updateChunk()
{
}

// Bounding box (pour culling box par exemple)
aabbox3df getBBofZone(const vector2d<u8>& coord_zone=vector2d<u8>(0,0))
{
    // calcul la box en fonction de la position (dans le repére du node MapManager)
    // en fonction de sa place dans le tableau de Zones et du nombre de chunk qu'elle contient.
}
aabbox3df getBBofChunk(const vector2d<u8>& coord_zone=vector2d<u8>(0,0), const vector2d<u8>& coord_chunk=vector2d<u8>(0,0))
{
    // calcul la box en fonction de la position (dans le repére du node MapManager)
    // en fonction de sa place dans le tableau de Zones et  de sa place dans le tableau de Chunks
}

// récupère le bloc adjacent au bloc donné (pour le marching cube)
const u8 getTypeOfRightBloc(const vector2d<u8>& coord_zone=vector2d<u8>(0,0), const vector2d<u8>& coord_chunk=vector2d<u8>(0,0), const vector3d<u8>& coord_bloc=vector3d<u8>(0,0,0)) const
{
    // si le bloc n'existe pas (hors map)
    return MB_AIR;
}
const u8 getTypeOfLeftBloc(const vector2d<u8>& coord_zone=vector2d<u8>(0,0), const vector2d<u8>& coord_chunk=vector2d<u8>(0,0), const vector3d<u8>& coord_bloc=vector3d<u8>(0,0,0)) const
{
    // si le bloc n'existe pas (hors map)
    return MB_AIR;
}
const u8 getTypeOfUpBloc(const vector2d<u8>& coord_zone=vector2d<u8>(0,0), const vector2d<u8>& coord_chunk=vector2d<u8>(0,0), const vector3d<u8>& coord_bloc=vector3d<u8>(0,0,0)) const
{
    // si le bloc n'existe pas (hors map)
    return MB_AIR;
}
const u8 getTypeOfDownBloc(const vector2d<u8>& coord_zone=vector2d<u8>(0,0), const vector2d<u8>& coord_chunk=vector2d<u8>(0,0), const vector3d<u8>& coord_bloc=vector3d<u8>(0,0,0)) const
{
    // si le bloc n'existe pas (hors map)
    return MB_AIR;
}
const u8 getTypeOfForwardBloc(const vector2d<u8>& coord_zone=vector2d<u8>(0,0), const vector2d<u8>& coord_chunk=vector2d<u8>(0,0), const vector3d<u8>& coord_bloc=vector3d<u8>(0,0,0)) const
{
    // si le bloc n'existe pas (hors map)
    return MB_AIR;
}
const u8 getTypeOfBackwardBloc(const vector2d<u8>& coord_zone=vector2d<u8>(0,0), const vector2d<u8>& coord_chunk=vector2d<u8>(0,0), const vector3d<u8>& coord_bloc=vector3d<u8>(0,0,0)) const
{
    // si le bloc n'existe pas (hors map)
    return MB_AIR;
}

// et ainsi de suite, suivant les besoins

protected:
Zone* ListeZones[10][10]; // une map = 10x10 zones par exemple

};

struct Zone
{
Chunk* ListeChunks[10][10];
};
struct Chunk
{
u8* ListeBloc[16][16][25]; // exemple un bloc de matière 1 et utilisant la transparence : ListeBloc[x][y][z] = u8( MB_MATIERE1 | MB_TRANSPARENT );
SMaterial material1, material2;
};



Avec cette méthode, la gestion sera plus facile et moins coûteuse en mémoire. Le SDZ a un tuto sur la dérivation d'un ISceneNode (que tu as déjà vu je pense).

Le mieux serait que tu créés un projet de base, tu créés un CubeNode (dérivé de ISceneNode) qui dessine un JUSTE UN TRIANGLE à l'écran, puis un cube pour te faire la main sur le fonctionnement. Une fois que tu auras réussi cet exercice de base tu pourras faire quelque chose avec le code de ce que je t'ai donné au-dessus.


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#19 

16-12-2012 15:07:31

Logeur
Membre
Date d'inscription: 16-11-2012
Messages: 61

Me revoilà, je n'es pas eu le temps cette semaine de programmer.
J'ai reçu quelques codes bien sympathique.
Je vais vraiment me pencher dessus pendant les vacances wink

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
883 membres
1429 sujets
11121 messages
Dernier membre inscrit: Saidov17
75 invités en ligne
Aucun membre connecté
RSS Feed