gKit2 light
Loading...
Searching...
No Matches
material_data.cpp
Go to the documentation of this file.
1
2
3#include <cstdio>
4#include <algorithm>
5
6#include "image_io.h"
7#include "texture.h"
8#include "material_data.h"
9#include "mesh_data.h"
10
11
13{
14 ImageData diffuse_image;
15 bool use_diffuse= false;
16
17 ImageData ns_image;
18 bool use_ns= false;
19};
20
21static
22unsigned miplevel_size( const ImageData& image, const int lod )
23{
24 unsigned w= std::max(unsigned(1), image.width / (1<<lod));
25 unsigned h= std::max(unsigned(1), image.height / (1<<lod));
26 return image.channels * image.size * w * h;
27}
28
29static inline
30unsigned offset( const unsigned width, const unsigned stride, const unsigned x, const unsigned y, const unsigned c )
31{
32 return (y * width + x) * stride + c;
33}
34
35static
36ImageData mipmap_resize( const ImageData& image, const int lod )
37{
38 assert(image.size == 1);
39
40 ImageData level= ImageData(image.width, image.height, image.channels, image.size);
41 level.pixels= image.pixels;
42
43 unsigned w= level.width;
44 unsigned h= level.height;
45 unsigned stride= level.channels * level.size;
46 unsigned row_stride= image.width; // "preserve" les images de largeur impaire...
47 for(int l= 0; l < lod; l++)
48 {
49 w= std::max(unsigned(1), w / 2);
50 h= std::max(unsigned(1), h / 2);
51
52 for(unsigned y= 0; y < h; y++)
53 for(unsigned x= 0; x < w; x++)
54 for(unsigned i= 0; i < image.channels; i++)
55 {
56 unsigned m= 0;
57 m= m + level.pixels[offset(row_stride, stride, 2*x, 2*y, i)];
58 m= m + level.pixels[offset(row_stride, stride, 2*x +1, 2*y, i)];
59 m= m + level.pixels[offset(row_stride, stride, 2*x, 2*y +1, i)];
60 m= m + level.pixels[offset(row_stride, stride, 2*x +1, 2*y +1, i)];
61
62 level.pixels[offset(w, stride, x, y, i)]= m / 4;
63 }
64
65 row_stride= w;
66 }
67
68 //~ printf(" resize %d : %dx%d, %dx%d\n", lod, image.width, image.height, w, h);
69
70 level.width= w;
71 level.height= h;
72 return level;
73}
74
75static
76Color average_color( const ImageData& image )
77{
78 assert(image.size == 1);
79
80 float color[4]= {0, 0, 0, 0};
81
82 unsigned stride= image.channels * image.size;
83 for(unsigned y= 0; y < image.height; y++)
84 for(unsigned x= 0; x < image.width; x++)
85 for(unsigned i= 0; i < image.channels; i++)
86 color[i]= color[i] + (float) image.pixels[offset(image.width, stride, x, y, i)] / 255.f;
87
88 return Color(color[0], color[1], color[2], color[3]) / (image.width * image.height);
89}
90
91
92int read_textures( std::vector<MaterialData>& materials, const size_t max_size )
93{
94 std::vector<TextureData> textures;
95
96 // evalue la taille totale occuppee par toutes les images / textures
97 size_t total_size= 0;
98 for(int i= 0; i < (int) materials.size(); i++)
99 {
100 const MaterialData &material= materials[i];
101 TextureData data;
102
103 if(!material.diffuse_filename.empty())
104 {
105 data.use_diffuse= true;
106 data.diffuse_image= read_image_data(material.diffuse_filename.c_str());
107 total_size= total_size + data.diffuse_image.width * data.diffuse_image.height * data.diffuse_image.channels * data.diffuse_image.size;
108 }
109 if(!material.ns_filename.empty())
110 {
111 data.use_ns= true;
112 data.ns_image= read_image_data(material.ns_filename.c_str());
113 total_size= total_size + data.ns_image.width * data.ns_image.height * data.ns_image.channels * data.ns_image.size;
114 }
115
116 if(total_size > max_size)
117 {
118 // ne stocke plus les images apres avoir depasse la limite de taille
119 std::vector<unsigned char>().swap(data.diffuse_image.pixels);
120 std::vector<unsigned char>().swap(data.ns_image.pixels);
121 }
122
123 textures.emplace_back(data);
124 }
125
126 printf("using %dMB / %dMB\n", int(total_size / 1024 / 1024), int(max_size / 1024 / 1024));
127
128 // reduit les dimensions des images / textures jusqu'a respecter la limite de taille
129 int lod= 0;
130 for(; total_size > max_size ; lod++)
131 {
132 total_size= 0;
133 for(int i= 0; i < (int) textures.size(); i++)
134 {
135 if(textures[i].use_diffuse)
136 total_size= total_size + miplevel_size(textures[i].diffuse_image, lod);
137 if(textures[i].use_ns)
138 total_size= total_size + miplevel_size(textures[i].ns_image, lod);
139 }
140 }
141
142 printf(" lod %d, %dMB\n", lod, int(total_size / 1024 / 1024));
143
144 // charge une texture par defaut, en cas d'erreur de chargement
145 GLuint default_texture= read_texture(0, "data/grid.png");
146
147 printf("resizing textures...\n");
148 // construit les textures a la bonne resolution
149 for(int i= 0; i < (int) textures.size(); i++)
150 {
151 TextureData& data= textures[i];
152 MaterialData& material= materials[i];
153
154 if(data.use_diffuse && data.diffuse_image.width > 0)
155 {
156 if(data.diffuse_image.pixels.empty())
157 {
158 // recharge l'image, si necessaire
159 data.diffuse_image= read_image_data(material.diffuse_filename.c_str());
160 assert(data.diffuse_image.width > 0);
161 }
162
163 ImageData level= mipmap_resize(data.diffuse_image, lod);
164 material.diffuse_texture= make_texture(0, level);
165
166 material.diffuse_texture_color= average_color(level);
167 }
168 else
169 material.diffuse_texture= default_texture;
170
171 if(data.use_ns && data.ns_image.width > 0)
172 {
173 if(data.ns_image.pixels.empty())
174 {
175 // recharge l'image, si necessaire
176 data.ns_image= read_image_data(material.ns_filename.c_str());
177 assert(data.ns_image.width > 0);
178 }
179
180 ImageData level= mipmap_resize(data.ns_image, lod);
181 material.ns_texture= make_texture(0, level);
182 }
183 else
184 material.ns_texture= default_texture;
185
186 // nettoyage, les images ne sont plus necessaires
187 std::vector<unsigned char>().swap(data.diffuse_image.pixels);
188 std::vector<unsigned char>().swap(data.ns_image.pixels);
189 }
190
191 return total_size;
192}
193
194void release_textures( std::vector<MaterialData>& materials )
195{
196 for(int i= 0; i < (int) materials.size(); i++)
197 {
198 const MaterialData& material= materials[i];
199
200 if(material.diffuse_texture > 0)
201 glDeleteTextures(1, &material.diffuse_texture);
202 if(material.ns_texture > 0)
203 glDeleteTextures(1, &material.ns_texture);
204 }
205}
206
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition text.cpp:140
ImageData read_image_data(const void *buffer, const unsigned size, const bool flipY)
charge les donnees d'un fichier png stocke en memoire. renvoie une image initialisee par defaut en ca...
Definition image_io.cpp:335
GLuint make_texture(const int unit, const int width, const int height, const GLenum texel_type, const GLenum data_format, const GLenum data_type)
creation de textures filtrables / mipmaps
Definition texture.cpp:10
GLuint read_texture(const int unit, const char *filename, const GLenum texel_type)
Definition texture.cpp:133
void release_textures(std::vector< MaterialData > &materials)
detruit les textures.
int read_textures(std::vector< MaterialData > &materials, const size_t max_size)
charge les textures associees a un ensemble de matieres, sans depasser une limite de taille,...
charge les textures utiilisees par un ensemble de matieres.
representation des donnees d'un fichier wavefront .obj
representation d'une couleur (rgba) transparente ou opaque.
Definition color.h:14
stockage temporaire des donnees d'une image.
Definition image_io.h:55
representation d'une matiere texturee.
Definition mesh_data.h:16
GLuint diffuse_texture
texture diffuse
Definition mesh_data.h:21
std::string diffuse_filename
nom de la texture diffuse
Definition mesh_data.h:20
GLuint ns_texture
texture exposant
Definition mesh_data.h:29
std::string ns_filename
nom de la texture exposant
Definition mesh_data.h:28
Color diffuse_texture_color
couleur moyenne de la texture
Definition mesh_data.h:18