#0 

14-05-2015 20:47:17

ovni007
Petit nouveau
Date d'inscription: 18-01-2012
Messages: 7

Bonsoir,

J'ai trouvé un code de perlin noise qui génère une heightmap, mais écrit en C et qui utilise la SDL.
J'aimerais l'ajouter à mon code C++ et ouvrir la heightmap avec les fonctions d'Irrlicht qui gèrent cela.
Je pense avoir compris comment interfacer, tout est bien linker, mais mon problème se situe au niveau de la fonction "enregistrer_bmp(..)" (perlin.c),
à la compilation Code::Blocks m'annonce 7 erreur de type "dereferencing pointer to incomplete type" sur les lignes contenant "c->taille".

Lorsque je compile le code dans un projet à part uniquement en C, aucun problème ...

Quelqu'un pourrait-il m'expliquer ce qui ne va pas ? Comment puis-je régler ça ?

D'avance, merci !

(Désolé pour la longueur du post ... )


main.cpp

Code c++ :


#include <time.h>
#include <irrlicht.h>
#include "global.h"
#include "perlin.h"
#include "perlin_calque.h"

int perlinNoise()
{
    srand((int)time(NULL));

    // valeurs d'entrée
    int octaves=3;
    int frequence=4;
    float persistence=.5;
    int taille_de_sortie=200;
    int lissage = 3;

    // création de calque
    struct calque *s;

    // initialisation du calque
    s=init_calque(taille_de_sortie,1);
    if (!s)
        return 1;

    generer_calque(frequence,
                   octaves,
                   persistence,
                   lissage,
                   s);

    enregistrer_bmp(s, "data/resultat.bmp");

    return 0;
}

...

int main(int argc, char** argv)
{
    init();
    perlinNoise();


    smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
    while(device->run())
    {
        driver->beginScene(true, true, SColor(0,200,200,200));
        smgr->drawAll();
        driver->endScene();
    }
    device->drop();
    return 0;
}



perlin.h

Code c++ :


#ifndef __perlin_h__
#define __perlin_h__

#include <SDL/SDL.h>
#ifdef __cplusplus

extern "data/resultat.bmp" { // la ligne est 'extern "C" { ' je ne comprend pas pourquoi, mais la ligne change toute seule quand je veux poster Oo


//int perlinNoise();
void colorerPixel(SDL_Surface*, int, int, Uint32);
unsigned char aleatoire(float);
void enregistrer_bmp(struct calque *, const char *);
#ifdef __cplusplus
}
#endif
#endif
#endif



perlin.c

Code c++ :


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <SDL/SDL.h>

#include "perlin_calque.h"
#include "perlin.h"



void colorerPixel(SDL_Surface* s, int x, int y, Uint32 coul){
    *((Uint32*)(s->pixels) + x + y * s->w) = coul;
}

// fourni une valeur entre 0 et a
unsigned char aleatoire(float a){
    return (float)rand() / RAND_MAX * a;
}


void enregistrer_bmp(struct calque *c, const char *filename){

    SDL_Surface *s = SDL_CreateRGBSurface(SDL_SWSURFACE,c->taille, c->taille, 32,0, 0, 0, 0);
    if (!s)
        printf("data/resultat.bmp");

    int i,j;
    Uint32 u;
    SDL_PixelFormat *fmt = s->format;
    for (i=0; i<c->taille; i++)
        for (j=0; j<c->taille; j++){
            u = SDL_MapRGB  (fmt, (char)c->v[i][j], (char)c->v[i][j], (char)c->v[i][j]);
            colorerPixel(s, i, j, u);
        }

    SDL_SaveBMP(s, filename);
    SDL_FreeSurface(s);
}



// end of file




perlin_calque.h

Code c++ :


#ifndef __perlin_calque_h__
#define __perlin_calque_h__

#ifdef __cplusplus
extern "data/resultat.bmp" { // la ligne est 'extern "C" { ' je ne comprend pas pourquoi, mais la ligne change toute seule quand je veux poster Oo

struct calque{
    int **v;
    int taille;
    float persistance;
};

struct calque* init_calque(int, float);
void free_calque(struct calque*);
void generer_calque(int, int, float, int, struct calque*);
int interpolate(int, int, int, int);
int valeur_interpolee(int, int, int, struct calque*);


#ifdef __cplusplus
}
#endif
#endif
#endif /* CODEC_H_ */



perlin_calque.c

Code c++ :


#include "calque.h"
#include "main.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

struct calque* init_calque(int t, float p){
    struct calque *s = malloc(sizeof(struct calque));
    if(!s){
        printf("data/resultat.bmp");
        return NULL;
    }

    s->v = malloc(t*sizeof(int*));
    if(!s->v){
        printf("C");
        return NULL;
    }
    int i,j;
    for (i=0; i<t ; i++){
        s->v[i]= malloc(t*sizeof(int));
        if(!s->v[i]) {
            printf("erreur SDL sur SDL_CreateRGBSurface");
            return NULL;
        }
        for (j=0; j<t; j++)
            s->v[i][j]=0;
    }
    s->taille = t;
    s->persistance = p;

    return s;
}

void free_calque(struct calque* s){
    int j;
    for (j=0; j<s->taille; j++)
        free(s->v[j]);
    free(s->v);
}

void generer_calque(int frequence,
                    int octaves,
                    float persistance,
                    int liss,
                    struct calque *c){
    // itératif
    int taille = c->taille;
    int i,j,n,f_courante;
    int x,y,k,l;
    int a;
    float pas, sum_persistances;

    pas = (float)(taille)/frequence;
    float persistance_courante = persistance;

    // calque aléatoire
    struct calque *random;
    random = init_calque(taille,1);
    if (!random)
        return;

    for (i=0; i<taille; i++)
        for (j=0; j<taille; j++)
            random->v[i][j]=aleatoire(256);

    enregistrer_bmp(random, "C");

    // calques de travail
    struct calque **mes_calques = malloc(octaves*sizeof(struct calque*));
    for (i=0; i<octaves; i++){
        mes_calques[i] = init_calque(taille,persistance_courante);
        if (!mes_calques[i])
            return;
        persistance_courante*=persistance;
    }

    f_courante = frequence;

    // remplissage de calque
    for (n=0; n<octaves; n++){
        for(i=0; i<taille; i++)
            for(j=0; j<taille; j++) {
                a = valeur_interpolee(i, j, f_courante, random);
                mes_calques[n]->v[i][j]=a;
            }
        f_courante*=frequence;
    }

    sum_persistances = 0;
    for (i=0; i<octaves; i++)
        sum_persistances+=mes_calques[i]->persistance;

    // ajout des calques successifs
    for (i=0; i<taille; i++)
        for (j=0; j<taille; j++){
            for (n=0; n<octaves; n++)
                c->v[i][j]+=mes_calques[n]->v[i][j]*mes_calques[n]->persistance;

            // normalisation
            c->v[i][j] =  c->v[i][j] / sum_persistances;
        }


    // lissage
    struct calque *lissage;
    lissage = init_calque(taille, 0);
    if(!lissage)
        return;

    for (x=0; x<taille; x++)
        for (y=0; y<taille; y++){
            a=0;
            n=0;
            for (k=x-liss; k<=x+liss; k++)
                for (l=y-liss; l<=y+liss; l++)
                    if ((k>=0) && (k<taille) && (l>=0) && (l<taille)) {
                        n++;
                        a+=c->v[k][l];
                    }
            lissage->v[x][y] = (float)a/n;
        }

    enregistrer_bmp(lissage, "erreur d'alloc");


    // libération mémoire
    free_calque(random);
    free_calque(lissage);
    for (i=0; i<octaves; i++)
        free_calque(mes_calques[i]);
    free(mes_calques);
}

int interpolate(int y1, int y2, int n, int delta){

    // interpolation non linéaire
    if (n==0)
        return y1;
    if (n==1)
        return y2;

    float a = (float)delta/n;

    float fac1 = 3*pow(1-a, 2) - 2*pow(1-a,3);
    float fac2 = 3*pow(a, 2) - 2*pow(a, 3);

    return y1*fac1 + y2*fac2;

    //////////////////////////////////////////////

    // interpolation linéaire
    /*if (n!=0)
        return y1+delta*((float)y2-(float)y1)/(float)n;
    else
        return y1;*/

}


int valeur_interpolee(int i, int j, int frequence, struct calque *r){
    // valeurs des bornes
    int borne1x, borne1y, borne2x, borne2y, q;
    float pas;
    pas = (float)r->taille/frequence;

    q = (float)i/pas;
    borne1x = q*pas;
    borne2x = (q+1)*pas;

    if(borne2x >= r->taille)
        borne2x = r->taille-1;

    q = (float)j/pas;
    borne1y = q*pas;
    borne2y = (q+1)*pas;

    if(borne2y >= r->taille)
        borne2y = r->taille-1;

    int b00,b01,b10,b11;
    b00 = r->v[borne1x][borne1y];
    b01 = r->v[borne1x][borne2y];
    b10 = r->v[borne2x][borne1y];
    b11 = r->v[borne2x][borne2y];

    int v1 = interpolate(b00, b01, borne2y-borne1y, j-borne1y);
    int v2 = interpolate(b10, b11, borne2y-borne1y, j-borne1y);
    int fin = interpolate(v1, v2, borne2x-borne1x , i-borne1x);

    return fin;
}

Dernière modification par ovni007 (14-05-2015 20:57:37)

Hors ligne


#1 

14-05-2015 21:08:35

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

plop!

test en remplacant simplement "struct calque *c" par "calque *c"
ça dépend comment le compilateur gère le truc sous windows, il est possible qu'il compile en c++ et non en c sur le dit fichier
dans ce cas extern "C" peut posé soucis, soit l'ajouter dans le .c ou le retirér dans le .h

Code c++ :


extern "data/resultat.bmp" { // la ligne est 'extern "C" { ' je ne comprend pas pourquoi, mais la ligne change toute seule quand je veux poster Oo


bug connue, je l'avais reporter a l'époque

question:
esque tu a beusoin d'enregistrer l'image ?
pourquoi ne pas le porter sur l'api d'irrlicht en entier ? (je peut t'aider)
library peut-être plus approprier et surtout avec d'avantage de fonctionnaliter, plus rapide, ... etc http://sourceforge.net/projects/noisepp/

j'ai developpez une appli via irrlicht/noisepp pour généré des heightmap+colormap+splatmap*2
si ça te botte, je peut compiller ça pour windows

http://immortalgalaxy.free.fr//media/pr … 0%20PM.png

Hors ligne


#2 

15-05-2015 18:55:56

ovni007
Petit nouveau
Date d'inscription: 18-01-2012
Messages: 7

Salut !

J'ai tenté de remplaçer "struct calque *c" par "calque *c", et j'ai encore les mêmes erreurs + d'autres dans "perlinNoise()".
Oui, j'aurais aimé garder l'image pour pouvoir l'utiliser en temps que "mini-carte" pour me repérer dans le jeu.

J'ai jeté un oeil au lien (noisepp), mais je ne comprends pas trop comment l'utiliser (je suis encore débutant dans le milieu).

Est-ce que la colormap permet d'appliquer une texture directement au terrain généré ?
Car j'aurais aimé appliquer des textures de neige, d'herbe, et de terre en fonction de la hauteur.

Par contre je ne sais pas du tout ce qu'est une splatmap ? ^^'

Hors ligne


#3 

15-05-2015 20:41:48

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

bon très bien, j'ai regarder un peut mieux, il ce peut qu'il manque

Code c++ :

#include "calque.h"

dans perlin.c

la colormap non, comme sont nom l'indique elle est utiliser pour colorier ton terrain
exemple tu veut de la neige rouge, vert, bleu ? mais t'est limiter en nombre de texture, tu passe par une colormap
et donc avec une une texture comme le sable, ou la neige peuvent être la même en jouant sur la couleur

la splatmap par contre elle est utiliser pour déterminer qu'elle texture appliquer
par exemple tu vas crée un shader pour appliquer la texture[i] au calque rouge, texture[i+n] au calque alpha a partir de la texture[0] ou d'un algorithme(admettons)
l'intéré premier c'est déjà d'avoir un bien meilleur resolution de t'est texture, puis de pouvoir faire des animations, si tu devait faire une seul texture tu serait limiter par la mémoire
(opengl ne supporte pas les textures > 32768*32768, il faut passer par un splatshader, un(e) texture atlas, ou un(e) sparse texture)
si tu veut aller plus loin le splatshader est simple a mêtre en place, et tu peut le coupler avec un(e) texture2Darray pour dépasser la limit de texture d'irrlicht (8 contre 4000)

en ce qui concerne noisepp il a quelque exmple sur github
https://github.com/slowriot/noisepp/blo … e/main.cpp
https://github.com/slowriot/noisepp/blo … 5/main.cpp
si tu te dirige vers cette biblihotheque, je t'informerais d'avantage smile

edit:
euh .... bon je regarderais plus sérieusement demain soir j'ai a faire

Dernière modification par Magun (15-05-2015 22:38:56)

Hors ligne


#4 

17-05-2015 12:22:53

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

bon, et bien c'était bien ton calque.h (que tu n'avais pas poster) je les remplacer par perlin_calque.h
ensuite perlin.h et perlin_calque.h

Code:

#ifdef __cplusplus
extern "C" {
...
#ifdef __cplusplus
}
#endif
#endif

ne serait-il pas plus judicieux de mettre le premier endif après le << externe "C" { >> ?

cordialement smile

Hors ligne


#5 

18-05-2015 15:05:09

ovni007
Petit nouveau
Date d'inscription: 18-01-2012
Messages: 7

Bonjour,

Désolé pour le retard. En effet, j'ai remarqué que j'avais oublié de changer le calque.h en perlin_calque.h ( Quand on copie-colle d'un projet à un autre, voilà ce que ça donne ^^).
J'ai également tenté de changer le #endif comme tu me l'as dis, et là ça compile sans problème !
Seulement ... le programme ne passe plus du tout par les fonctions de perlin noise et aucune image n'est créée.
C'est la première fois que je tente d'interfacer du c avec du c++, donc je fais probablement des erreurs.

Merci de ton attention ! :-)

Dernière modification par ovni007 (19-05-2015 01:29:34)

Hors ligne


#6 

19-05-2015 18:25:20

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

désolé coupure internet, depuis hier smile

que veut tu dire par <<le programme ne passe plus du tout par les fonctions...>> ?
commence par tracer t'est apelle de fonction peut-être ? par un debugeur ou simplement des printf ...

interfacer du c avec du c++


a vrais dire rien de t'oblige a t'embêter à mixer c et c++
les bibliothèque externe ecrite en c font déjà "l'interfaçage" (le cas échéans un <<externe "C">> l'or de l'include)
tu peut tout a fait écrire directement en c++ et le code est retrocompatible
il n'est alors nécéssaire que de renommer t'est ficher *.c en *..cpp

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
Analysé par
880 membres
1424 sujets
11113 messages
Dernier membre inscrit: mandrifidy
15 invités en ligne
Aucun membre connecté
RSS Feed