Bonjour,

Je suis en train de convertir un code en C++ sous GTK, qui produit une lightmap depuis une heightmap.

Mais hélas, je n'obtiens pas le même résultat visuel sous Lazarus que sous le projet originel.

Voilà ce que je devrais obtenir :

Nom : Lightmap-cpp.jpeg
Affichages : 588
Taille : 33,4 Ko

Et ce que j'ai sous Lazarus :

Nom : lightmap.jpg
Affichages : 583
Taille : 65,6 Ko

Chez moi, ma lightmap, est blanche et noire, il n'y a pas de niveaux de gris comme dans l'original.

Voici la routine originelle :
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
 
void on_apercu(GtkWidget* widget, gpointer data)
{
    int ombrage = (int)gtk_adjustment_get_value(adj_ombrage);
    float angle_rayons = (int)gtk_adjustment_get_value(adj_angle_rayons);
    float hauteur_max_rayons = (int)gtk_adjustment_get_value(adj_hauteur_max_rayons);
    float hauteur_max_heightmap = (float)gtk_adjustment_get_value(adj_hauteur_max_heightmap);
 
    int n_channels;
    int rowstride_lightmap, rowstride_heightmap;
    guchar *pixels_lightmap=NULL, *p_lightmap=NULL;
    guchar *pixels_heightmap=NULL, *p_heightmap=NULL;
    int x, y, width, height = 0;
    float step_z=0.0f;
    float z_origine=0.0f;
    int x_rayon=0;
    float z_rayon=0.0f;
 
    n_channels = gdk_pixbuf_get_n_channels(pixbuf_lightmap);
 
    g_assert(gdk_pixbuf_get_colorspace (pixbuf_lightmap) == GDK_COLORSPACE_RGB);
    g_assert(gdk_pixbuf_get_bits_per_sample (pixbuf_lightmap) == 8);
    g_assert(gdk_pixbuf_get_has_alpha (pixbuf_lightmap) == FALSE);
    g_assert(n_channels == 3);
 
    width = gdk_pixbuf_get_width(pixbuf_lightmap);
    height = gdk_pixbuf_get_height(pixbuf_lightmap);
 
    rowstride_lightmap = gdk_pixbuf_get_rowstride(pixbuf_lightmap);
    pixels_lightmap = gdk_pixbuf_get_pixels(pixbuf_lightmap);
 
    rowstride_heightmap = gdk_pixbuf_get_rowstride(pixbuf_heightmap);
    pixels_heightmap = gdk_pixbuf_get_pixels(pixbuf_heightmap);
 
    // Au départ, tout est dans l'ombre...
    for(y=0 ; y<height ; y++)
        for(x=0 ; x<width ; x++)
        {
            p_lightmap = pixels_lightmap + y * rowstride_lightmap + x * n_channels;
            p_lightmap[0] = ombrage;
            p_lightmap[1] = ombrage;
            p_lightmap[2] = ombrage;
        }
 
    // Puis vint la lumière !!
 
    // On calcule de combien on doit incrémenter en z à chaque nouveau rayon
    step_z = fabs(1/tan(angle_rayons));
 
    // On lance les rayons dans le sens horizontal (en voyant de haut), de la gauche vers la droite.
    // On fait donc ça pour toutes les lignes (d'où la boucle en y).
    for(y=0 ; y<height ; y++)
    {
        // On parcourt en montant (i.e. suivant l'axe des Z) pour lancer des rayons à chacune
        // de ces hauteurs
        for(z_origine=0.0f ; z_origine<hauteur_max_rayons ; z_origine+=step_z)
        {
            // Lancer du rayon !
            for(z_rayon=z_origine, x_rayon=0 ;
                x_rayon < width;
                z_rayon-=step_z, x_rayon++)
            {
                // Si la hauteur du pixel en cours est supérieure ou égale à z_rayon,
                // c'est qu'on a touché
                // qqch, alors on le colorie en blanc et on passe au rayon d'après
 
                // On pointe sur le point (x_rayon, y)
                p_heightmap = pixels_heightmap + y * rowstride_heightmap + x_rayon * n_channels;
                p_lightmap = pixels_lightmap + y * rowstride_lightmap + x_rayon * n_channels;
 
                if((float)(p_heightmap[0]/255.0f)*hauteur_max_heightmap >= z_rayon)
                {
                    p_lightmap[0] = p_lightmap[1] = p_lightmap[2] = 255;
                    break;
                }
            }
        }
    }
 
    gtk_image_set_from_pixbuf(GTK_IMAGE(image_lightmap), pixbuf_lightmap);
    redimensionner_image(image_lightmap);
}

Et ma conversion en Pascal :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 
Procedure TForm1.bouton_apercuClick(Sender: TObject);
var
   x, y, x_rayon: integer;
   z_step, z_origine, z_rayon: single;
   Pixel, Final: PRGBTriple;
Begin
    // Calcul du pas en z pour chaque rayon.
    z_step := abs(1 / tan(spin_angle_rayons.Value));
 
    image_lightmap.Picture.Bitmap.BeginUpdate;
 
    // Lancement des rayons dans le sens horizontal et de gauche a droite.
    for y := 0 to image_lightmap.Picture.Bitmap.Height - 1 do
    begin
         // Pointeurs sur les 2 même lignes des 2 bitmaps.
         Final := PRGBTriple(image_heightmap.Picture.Bitmap.RawImage.GetLineStart(y));
         Pixel := PRGBTriple(image_lightmap.Picture.Bitmap.RawImage.GetLineStart(y));
 
         // Par defaut tout a la valeur de l'ombre défini dans l'UI.
         for x := 0 to image_lightmap.Picture.Bitmap.Width - 1 do
         begin
              Pixel[x].rgbtRed   := spin_ombrage.Value;
              Pixel[x].rgbtGreen := spin_ombrage.Value;
              Pixel[x].rgbtBlue  := spin_ombrage.Value;
         End;
 
         // Lancements des rayons pour chaque hauteur en remontant suivant l'axe z
         z_origine := 0.0;
 
         while z_origine < spin_hauteur_max_rayons.Value do
         begin
              // Lancement de rayon.
              z_rayon := z_origine;
 
              for x_rayon := 0 to image_lightmap.Picture.Bitmap.Width - 1 do
              begin
                   // Si la hauteur (rouge pour l'exmple) du pixel est supérieur ou égale a la valeur
                   // du z_rayon alors on le colorie en blanc et on passe au rayoin lancé suivant.
                   if ((Final[x_rayon].rgbtRed / 255) * spin_hauteur_max_heightmap.Value) >= z_rayon then
                   begin
                        Pixel[x_rayon].rgbtRed   := 255;
                        Pixel[x_rayon].rgbtGreen := 255;
                        Pixel[x_rayon].rgbtBlue  := 255;
 
                        break;
                   End;
 
                   z_rayon := z_rayon - z_step;
              end;
 
              z_origine := z_origine + z_step;
         end;
    end;
 
    image_lightmap.Picture.Bitmap.EndUpdate;
end;
À votre avis, où ai-je loupé un truc ?