cimg.cxx 3.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CImg.h +70659 -0
- package/Licence_CeCILL-C_V1-en.txt +508 -0
- package/Licence_CeCILL_V2-en.txt +504 -0
- package/README.md +44 -0
- package/README.txt +180 -0
- package/package.json +15 -0
- package/plugins/add_fileformat.h +79 -0
- package/plugins/bayer.h +212 -0
- package/plugins/chlpca.h +323 -0
- package/plugins/cvMat.h +350 -0
- package/plugins/draw_gradient.h +269 -0
- package/plugins/inpaint.h +508 -0
- package/plugins/ipl.h +309 -0
- package/plugins/ipl_alt.h +122 -0
- package/plugins/jpeg_buffer.h +377 -0
- package/plugins/loop_macros.h +24166 -0
- package/plugins/matlab.h +287 -0
- package/plugins/nlmeans.h +242 -0
- package/plugins/skeleton.h +587 -0
- package/plugins/tiff_stream.h +196 -0
- package/plugins/tinymatwriter.h +109 -0
- package/plugins/vrml.h +894 -0
- package/plugins/vtk.h +103 -0
package/plugins/vrml.h
ADDED
|
@@ -0,0 +1,894 @@
|
|
|
1
|
+
/*
|
|
2
|
+
#
|
|
3
|
+
# File : vrml.h
|
|
4
|
+
# ( C++ header file - CImg plug-in )
|
|
5
|
+
#
|
|
6
|
+
# Description : CImg plugin that provide functions to load/save VRML files.
|
|
7
|
+
# This file is a part of the CImg Library project.
|
|
8
|
+
# ( http://cimg.eu )
|
|
9
|
+
#
|
|
10
|
+
# Copyright : Greg Rami
|
|
11
|
+
# ( greg.rami36 (at) gmail.com )
|
|
12
|
+
#
|
|
13
|
+
# License : CeCILL v2.0
|
|
14
|
+
# ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
|
|
15
|
+
#
|
|
16
|
+
# This software is governed by the CeCILL license under French law and
|
|
17
|
+
# abiding by the rules of distribution of free software. You can use,
|
|
18
|
+
# modify and/ or redistribute the software under the terms of the CeCILL
|
|
19
|
+
# license as circulated by CEA, CNRS and INRIA at the following URL
|
|
20
|
+
# "http://www.cecill.info".
|
|
21
|
+
#
|
|
22
|
+
# As a counterpart to the access to the source code and rights to copy,
|
|
23
|
+
# modify and redistribute granted by the license, users are provided only
|
|
24
|
+
# with a limited warranty and the software's author, the holder of the
|
|
25
|
+
# economic rights, and the successive licensors have only limited
|
|
26
|
+
# liability.
|
|
27
|
+
#
|
|
28
|
+
# In this respect, the user's attention is drawn to the risks associated
|
|
29
|
+
# with loading, using, modifying and/or developing or reproducing the
|
|
30
|
+
# software by the user in light of its specific status of free software,
|
|
31
|
+
# that may mean that it is complicated to manipulate, and that also
|
|
32
|
+
# therefore means that it is reserved for developers and experienced
|
|
33
|
+
# professionals having in-depth computer knowledge. Users are therefore
|
|
34
|
+
# encouraged to load and test the software's suitability as regards their
|
|
35
|
+
# requirements in conditions enabling the security of their systems and/or
|
|
36
|
+
# data to be ensured and, more generally, to use and operate it in the
|
|
37
|
+
# same conditions as regards security.
|
|
38
|
+
#
|
|
39
|
+
# The fact that you are presently reading this means that you have had
|
|
40
|
+
# knowledge of the CeCILL license and that you accept its terms.
|
|
41
|
+
#
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/*-----------------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
IMPORTANT NOTE :
|
|
47
|
+
|
|
48
|
+
You *need* to include the following lines in your own code to use this plugin :
|
|
49
|
+
|
|
50
|
+
#include <vector>
|
|
51
|
+
#include <string>
|
|
52
|
+
#include <sstream>
|
|
53
|
+
#include <algorithm>
|
|
54
|
+
|
|
55
|
+
------------------------------------------------------------------------------------*/
|
|
56
|
+
|
|
57
|
+
#ifndef cimg_plugin_vrml
|
|
58
|
+
#define cimg_plugin_vrml
|
|
59
|
+
|
|
60
|
+
//! Load a 3d object from a .VRML file.
|
|
61
|
+
template<typename tf, typename tc>
|
|
62
|
+
CImg<T>& load_vrml(const char *const filename, CImgList<tf>& primitives, CImgList<tc>& colors) {
|
|
63
|
+
return _load_vrml(0,filename,primitives,colors);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//! Load a 3d object from a .VRML file.
|
|
67
|
+
template<typename tf, typename tc>
|
|
68
|
+
static CImg<T> get_load_vrml(const char *const filename, CImgList<tf>& primitives, CImgList<tc>& colors) {
|
|
69
|
+
return CImg<T>().load_vrml(filename,primitives,colors);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
//! Load a 3d object from a .VRML file.
|
|
73
|
+
template<typename tf, typename tc>
|
|
74
|
+
CImg<T>& load_vrml(std::FILE *const file, CImgList<tf>& primitives, CImgList<tc>& colors) {
|
|
75
|
+
return _load_vrml(file,0,primitives,colors);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//! Load a 3d object from a .VRML file.
|
|
79
|
+
template<typename tf, typename tc>
|
|
80
|
+
static CImg<T> get_load_vrml(std::FILE *const file, CImgList<tf>& primitives, CImgList<tc>& colors) {
|
|
81
|
+
return CImg<T>().load_vrml(file,primitives,colors);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//! Load a 3d object from a .VRML file (internal).
|
|
85
|
+
template<typename tf, typename tc>
|
|
86
|
+
CImg<T>& _load_vrml(std::FILE *const file, const char *const filename,CImgList<tf>& primitives, CImgList<tc>& colors) {
|
|
87
|
+
if (!file && !filename)
|
|
88
|
+
throw CImgArgumentException(_cimg_instance
|
|
89
|
+
"load_vrml() : Specified filename is (null).",
|
|
90
|
+
cimg_instance);
|
|
91
|
+
std::FILE *const nfile = file?file:cimg::fopen(filename,"r");
|
|
92
|
+
|
|
93
|
+
char line[1024] = { 0 };
|
|
94
|
+
int err;
|
|
95
|
+
|
|
96
|
+
// Skip comments, and read the first node.
|
|
97
|
+
do { err = std::fscanf(nfile,"%65535[^\n] ",line); } while (!err || (err==1 && *line=='#'));
|
|
98
|
+
|
|
99
|
+
// Check for a first valid vrml valid node.
|
|
100
|
+
if (cimg::strncasecmp(line,"Shape",5) &&
|
|
101
|
+
cimg::strncasecmp(line,"Transform",9) &&
|
|
102
|
+
cimg::strncasecmp(line,"NavigationInfo",14) &&
|
|
103
|
+
cimg::strncasecmp(line,"Billboard",9)) {
|
|
104
|
+
if (!file) cimg::fclose(nfile);
|
|
105
|
+
throw CImgIOException(_cimg_instance
|
|
106
|
+
"load_vrml() : VRML nodes not found in file '%s'.",
|
|
107
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Look for the Shape node (as we do not manage the treatment for the other nodes yet).
|
|
111
|
+
if (cimg::strncasecmp(line,"Shape",5)) {
|
|
112
|
+
while (cimg::strncasecmp(line,"Shape",5) && !std::feof(nfile)) err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
113
|
+
if (std::feof(nfile)) {
|
|
114
|
+
if (!file) cimg::fclose(nfile);
|
|
115
|
+
throw CImgIOException(_cimg_instance
|
|
116
|
+
"load_vrml() : Shape node not found in file '%s'.",
|
|
117
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Look for either geometry or appearance node.
|
|
122
|
+
while (cimg::strncasecmp(line,"geometry",8) && cimg::strncasecmp(line,"appearance",10) && !std::feof(nfile))
|
|
123
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
124
|
+
if (std::feof(nfile)) { // If none of these nodes are defined.
|
|
125
|
+
if (!file) cimg::fclose(nfile);
|
|
126
|
+
throw CImgIOException(_cimg_instance
|
|
127
|
+
"load_vrml() : Geometry and appearance nodes not found in file '%s'.",
|
|
128
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
std::vector<T> listePoints; // Intermediate list containing the points of the whole object.
|
|
132
|
+
primitives.assign();
|
|
133
|
+
colors.assign();
|
|
134
|
+
// Count the number of points of the whole object and the number of primitives.
|
|
135
|
+
int nbPointsTotal = 0, nbPrimitives = 0;
|
|
136
|
+
float r = 0.78f, g = 0.78f, b = 0.78f; // RGB level of the object, the object is gray by default.
|
|
137
|
+
// Boolean used to know if a color is defined for an object,
|
|
138
|
+
// if this object has multiple colors or if the object has a texture
|
|
139
|
+
bool colorDefined = true, multipleColors = false, textureTest = false;
|
|
140
|
+
char textureFile[1024] = { 0 }; // Variable containing the name of the image used as a texture
|
|
141
|
+
|
|
142
|
+
while (!std::feof(nfile)) {
|
|
143
|
+
char type[1024] = { 0 }, textureFileTemp[1024] = { 0 };
|
|
144
|
+
colorDefined = true;
|
|
145
|
+
if (!cimg::strncasecmp(line,"geometry",8)) { // We are at the geometry node
|
|
146
|
+
std::sscanf(line,"geometry %s",type); // We are looking for the type of geometry to draw
|
|
147
|
+
const CImg<float> coords = CImg<float>::empty(); // CImg used for the texturization of an object
|
|
148
|
+
CImgList<tc> colorsTextured; // CImgList used for the texturization of the color of an object
|
|
149
|
+
CImgList<tf> primitivesTemp; // Intermediate CImgList used to update the primitives of the whole object
|
|
150
|
+
|
|
151
|
+
if (!cimg::strncasecmp(type,"Box",3)) { // If the object to draw is a box
|
|
152
|
+
while (cimg::strncasecmp(line,"size",4) && !std::feof(nfile)) // We are looking for the size of the box
|
|
153
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
154
|
+
|
|
155
|
+
if (std::feof(nfile)) { // If no size is specified
|
|
156
|
+
if (!file) cimg::fclose(nfile);
|
|
157
|
+
throw CImgIOException(_cimg_instance
|
|
158
|
+
"load_vrml() : size of box not defined in file '%s'.",
|
|
159
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
float X = 0, Y = 0, Z = 0; // The width, height and depth of the box
|
|
163
|
+
if ((err = std::sscanf(line,"size %f %f %f[^\n] ",&X,&Y,&Z))!=3 &&
|
|
164
|
+
(err = std::sscanf(line,"size %f,%f,%f[^\n] ",&X,&Y,&Z))!=3) {
|
|
165
|
+
if (!file) cimg::fclose(nfile);
|
|
166
|
+
throw CImgIOException(_cimg_instance
|
|
167
|
+
"load_vrml() : Failed to read box size in file '%s'.",
|
|
168
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
169
|
+
}
|
|
170
|
+
// We generate the primitives and the points of the box
|
|
171
|
+
const CImg<T> pointsTemp = CImg<T>::box3d(primitivesTemp,(T)X,(T)Y,(T)Z);
|
|
172
|
+
|
|
173
|
+
nbPrimitives = primitivesTemp.size(); // We save the number of primitives of the object
|
|
174
|
+
|
|
175
|
+
if (textureTest) { // If the object has a texture
|
|
176
|
+
// We put the image used as a texture into a CImg object
|
|
177
|
+
const CImg<float> texture(textureFile);
|
|
178
|
+
// We initialize the colorsTextured list
|
|
179
|
+
colorsTextured.insert(primitivesTemp.size(),CImg<unsigned char>::vector(0,50,250));
|
|
180
|
+
// We texturize the object
|
|
181
|
+
pointsTemp.texturize_object3d(primitivesTemp,colorsTextured,texture,coords);
|
|
182
|
+
nbPrimitives = 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if(nbPointsTotal) { // If there are already some objects in the scene
|
|
186
|
+
for (int j=0;j<(int)primitivesTemp.size();j++) {
|
|
187
|
+
for(int i=0;i<4;i++)
|
|
188
|
+
// We shift the indices in the primitives to designate the right points
|
|
189
|
+
primitivesTemp(j).at(i) += (tf)nbPointsTotal;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
primitives.push_back(primitivesTemp); // We add the primitives of the box to the general primitives variable
|
|
193
|
+
for(int i=0;i<(int)pointsTemp.size()/3;++i) { // We add the points into the temporary list in the right order
|
|
194
|
+
listePoints.push_back((T)pointsTemp.at(i));
|
|
195
|
+
listePoints.push_back((T)pointsTemp.at(i + 8));
|
|
196
|
+
listePoints.push_back((T)pointsTemp.at(i + 16));
|
|
197
|
+
}
|
|
198
|
+
nbPointsTotal += pointsTemp.size()/3; // We increase the number of points of the whole object
|
|
199
|
+
}
|
|
200
|
+
else if(!cimg::strncasecmp(type,"Sphere",6)) { // If the object to draw is a sphere
|
|
201
|
+
while(cimg::strncasecmp(line,"radius",6) && !std::feof(nfile))
|
|
202
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
203
|
+
|
|
204
|
+
if(std::feof(nfile)) {
|
|
205
|
+
if (!file)
|
|
206
|
+
cimg::fclose(nfile);
|
|
207
|
+
throw CImgIOException(_cimg_instance
|
|
208
|
+
"load_vrml() : radius of sphere not defined in file '%s'.",
|
|
209
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
float R = 0;
|
|
213
|
+
if ((err = std::sscanf(line,"radius %f[^\n] ",&R))!=1) { // We get the radius of the sphere
|
|
214
|
+
if (!file)
|
|
215
|
+
cimg::fclose(nfile);
|
|
216
|
+
throw CImgIOException(_cimg_instance
|
|
217
|
+
"load_vrml() : Failed to read sphere radius in file '%s'.",
|
|
218
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
219
|
+
}
|
|
220
|
+
// Compute the necessary points and primitives for a sphere of radius R
|
|
221
|
+
const CImg<T> pointsTemp = CImg<T>::sphere3d(primitivesTemp,(T)R);
|
|
222
|
+
// We get the number of primitives to used on the attribution of a color, in case no specific color is defined
|
|
223
|
+
nbPrimitives = primitivesTemp.size();
|
|
224
|
+
|
|
225
|
+
if(textureTest) { // If the object has a texture
|
|
226
|
+
// We put the image used as a texture into a CImg object
|
|
227
|
+
const CImg<float> texture(textureFile);
|
|
228
|
+
// We initialize the colorsTextured list
|
|
229
|
+
colorsTextured.insert(primitivesTemp.size(),CImg<unsigned char>::vector(0,50,250));
|
|
230
|
+
pointsTemp.texturize_object3d(primitivesTemp,colorsTextured,texture,coords); // We texturize the object
|
|
231
|
+
nbPrimitives = 0; // We set to 0 because there is no color to use
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if(nbPointsTotal) { // If there are already some objects in the scene
|
|
235
|
+
for (int j=0;j<(int)primitivesTemp.size();j++) {
|
|
236
|
+
for(int i=0;i<3;i++)
|
|
237
|
+
primitivesTemp(j).at(i) += (tf)nbPointsTotal;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
primitives.push_back(primitivesTemp);
|
|
242
|
+
for(int i=0;i<(int)pointsTemp.size()/3;++i) {
|
|
243
|
+
listePoints.push_back((T)pointsTemp.at(i));
|
|
244
|
+
listePoints.push_back((T)pointsTemp.at(i + pointsTemp.size()/3));
|
|
245
|
+
listePoints.push_back((T)pointsTemp.at(i + 2*pointsTemp.size()/3));
|
|
246
|
+
}
|
|
247
|
+
nbPointsTotal += pointsTemp.size()/3;
|
|
248
|
+
}
|
|
249
|
+
else if(!cimg::strncasecmp(type,"Cone",4)) { // If the object to draw is a cone
|
|
250
|
+
while(cimg::strncasecmp(line,"bottomRadius",12) && !std::feof(nfile) && cimg::strncasecmp(line,"height",6))
|
|
251
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
252
|
+
float R = 0, H = 0;
|
|
253
|
+
if(std::feof(nfile)) {
|
|
254
|
+
if (!file)
|
|
255
|
+
cimg::fclose(nfile);
|
|
256
|
+
throw CImgIOException(_cimg_instance
|
|
257
|
+
"load_vrml() : bottom radius and height of cone not defined in file '%s'.",
|
|
258
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
259
|
+
}
|
|
260
|
+
else if(!cimg::strncasecmp(line,"bottomRadius",12)) { // We find the bottom radius of the cone first
|
|
261
|
+
if ((err = std::sscanf(line,"bottomRadius %f[^\n] ",&R))!=1) { // We get the radius into the variable R
|
|
262
|
+
if (!file)
|
|
263
|
+
cimg::fclose(nfile);
|
|
264
|
+
throw CImgIOException(_cimg_instance
|
|
265
|
+
"load_vrml() : Failed to read cone bottomRadius in file '%s'.",
|
|
266
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
267
|
+
}
|
|
268
|
+
while(!std::feof(nfile) && cimg::strncasecmp(line,"height",6)) // We look for the height of the cone
|
|
269
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
270
|
+
|
|
271
|
+
if(std::feof(nfile)) {
|
|
272
|
+
if (!file)
|
|
273
|
+
cimg::fclose(nfile);
|
|
274
|
+
throw CImgIOException(_cimg_instance
|
|
275
|
+
"load_vrml() : height of cone not defined in file '%s'.",
|
|
276
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if ((err = std::sscanf(line,"height %f[^\n] ",&H))!=1) { // We get the height into the variable H
|
|
280
|
+
if (!file)
|
|
281
|
+
cimg::fclose(nfile);
|
|
282
|
+
throw CImgIOException(_cimg_instance
|
|
283
|
+
"load_vrml() : Failed to read cone height in file '%s'.",
|
|
284
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else { // We find the height of the cone first
|
|
288
|
+
if ((err = std::sscanf(line,"height %f[^\n] ",&H))!=1) {
|
|
289
|
+
if (!file)
|
|
290
|
+
cimg::fclose(nfile);
|
|
291
|
+
throw CImgIOException(_cimg_instance
|
|
292
|
+
"load_vrml() : Failed to read cone height in file '%s'.",
|
|
293
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
294
|
+
}
|
|
295
|
+
while(!std::feof(nfile) && cimg::strncasecmp(line,"bottomRadius",12))
|
|
296
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
297
|
+
|
|
298
|
+
if(std::feof(nfile)) {
|
|
299
|
+
if (!file)
|
|
300
|
+
cimg::fclose(nfile);
|
|
301
|
+
throw CImgIOException(_cimg_instance
|
|
302
|
+
"load_vrml() : bottom radius of cone not defined in file '%s'.",
|
|
303
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if ((err = std::sscanf(line,"bottomRadius %f[^\n] ",&R))!=1) {
|
|
307
|
+
if (!file)
|
|
308
|
+
cimg::fclose(nfile);
|
|
309
|
+
throw CImgIOException(_cimg_instance
|
|
310
|
+
"load_vrml() : Failed to read cone bottom radius in file '%s'.",
|
|
311
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Compute the necessary points and primitives for a cone of radius R and height H
|
|
315
|
+
const CImg<T> pointsTemp = CImg<T>::cone3d(primitivesTemp,(T)R,(T)H);
|
|
316
|
+
|
|
317
|
+
nbPrimitives = primitivesTemp.size();
|
|
318
|
+
|
|
319
|
+
if(textureTest) { // If the object has a texture
|
|
320
|
+
// We put the image used as a texture into a CImg object
|
|
321
|
+
const CImg<float> texture(textureFile);
|
|
322
|
+
// We initialize the colorsTextured list
|
|
323
|
+
colorsTextured.insert(primitivesTemp.size(),CImg<unsigned char>::vector(0,50,250));
|
|
324
|
+
pointsTemp.texturize_object3d(primitivesTemp,colorsTextured,texture,coords); // We texturize the object
|
|
325
|
+
nbPrimitives = 0;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if(nbPointsTotal) {
|
|
329
|
+
for (int j=0;j<(int)primitivesTemp.size();j++) {
|
|
330
|
+
for(int i=0;i<3;i++)
|
|
331
|
+
primitivesTemp(j).at(i) += (tf)nbPointsTotal;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
primitives.push_back(primitivesTemp);
|
|
336
|
+
for(int i=0;i<(int)pointsTemp.size()/3;++i) {
|
|
337
|
+
listePoints.push_back((T)pointsTemp.at(i));
|
|
338
|
+
listePoints.push_back((T)pointsTemp.at(i + pointsTemp.size()/3));
|
|
339
|
+
listePoints.push_back((T)pointsTemp.at(i + 2*pointsTemp.size()/3));
|
|
340
|
+
}
|
|
341
|
+
nbPointsTotal += pointsTemp.size()/3;
|
|
342
|
+
}
|
|
343
|
+
else if(!cimg::strncasecmp(type,"Cylinder",8)) { // If the object to draw is a cylinder
|
|
344
|
+
while(cimg::strncasecmp(line,"radius",6) && !std::feof(nfile) && cimg::strncasecmp(line,"height",6))
|
|
345
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
346
|
+
float R = 0, H = 0;
|
|
347
|
+
if(std::feof(nfile)) {
|
|
348
|
+
if (!file)
|
|
349
|
+
cimg::fclose(nfile);
|
|
350
|
+
throw CImgIOException(_cimg_instance
|
|
351
|
+
"load_vrml() : radius or height of cylinder not defined in file '%s'.",
|
|
352
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
353
|
+
}
|
|
354
|
+
else if(!cimg::strncasecmp(line,"radius",6)) { // If we find the radius first
|
|
355
|
+
if ((err = std::sscanf(line,"radius %f[^\n] ",&R))!=1) {
|
|
356
|
+
if (!file)
|
|
357
|
+
cimg::fclose(nfile);
|
|
358
|
+
throw CImgIOException(_cimg_instance
|
|
359
|
+
"load_vrml() : Failed to read cylinder radius in file '%s'.",
|
|
360
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
361
|
+
}
|
|
362
|
+
while(!std::feof(nfile) && cimg::strncasecmp(line,"height",6)) // We now look for the height of the cylinder
|
|
363
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
364
|
+
|
|
365
|
+
if(std::feof(nfile)) {
|
|
366
|
+
if (!file)
|
|
367
|
+
cimg::fclose(nfile);
|
|
368
|
+
throw CImgIOException(_cimg_instance
|
|
369
|
+
"load_vrml() : height of cylinder not defined in file '%s'.",
|
|
370
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if ((err = std::sscanf(line,"height %f[^\n] ",&H))!=1) {
|
|
374
|
+
if (!file)
|
|
375
|
+
cimg::fclose(nfile);
|
|
376
|
+
throw CImgIOException(_cimg_instance
|
|
377
|
+
"load_vrml() : Failed to read cylinder height in file '%s'.",
|
|
378
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else { // If we find the height first
|
|
382
|
+
if ((err = std::sscanf(line,"height %f[^\n] ",&H))!=1) {
|
|
383
|
+
if (!file)
|
|
384
|
+
cimg::fclose(nfile);
|
|
385
|
+
throw CImgIOException(_cimg_instance
|
|
386
|
+
"load_vrml() : Failed to read cylinder height in file '%s'.",
|
|
387
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
388
|
+
}
|
|
389
|
+
while(!std::feof(nfile) && cimg::strncasecmp(line,"radius",6))// We now look for the radius of the cylinder
|
|
390
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
391
|
+
|
|
392
|
+
if(std::feof(nfile)) {
|
|
393
|
+
if (!file)
|
|
394
|
+
cimg::fclose(nfile);
|
|
395
|
+
throw CImgIOException(_cimg_instance
|
|
396
|
+
"load_vrml() : radius of cylinder not defined in file '%s'.",
|
|
397
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if ((err = std::sscanf(line,"radius %f[^\n] ",&R))!=1) {
|
|
401
|
+
if (!file)
|
|
402
|
+
cimg::fclose(nfile);
|
|
403
|
+
throw CImgIOException(_cimg_instance
|
|
404
|
+
"load_vrml() : Failed to read cylinder radius in file '%s'.",
|
|
405
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
// Compute the necessary points and primitives for a cylinder of radius R and height H
|
|
409
|
+
const CImg<T> pointsTemp = CImg<T>::cylinder3d(primitivesTemp,(T)R,(T)H);
|
|
410
|
+
|
|
411
|
+
if(textureTest) { // If the object has a texture
|
|
412
|
+
// We put the image used as a texture into a CImg object
|
|
413
|
+
const CImg<float> texture(textureFile);
|
|
414
|
+
// We initialize the colorsTextured list
|
|
415
|
+
colorsTextured.insert(primitivesTemp.size(),CImg<unsigned char>::vector(0,50,250));
|
|
416
|
+
pointsTemp.texturize_object3d(primitivesTemp,colorsTextured,texture,coords); // We texturize the object
|
|
417
|
+
nbPrimitives = 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
nbPrimitives = primitivesTemp.size();
|
|
421
|
+
|
|
422
|
+
if(nbPointsTotal) {
|
|
423
|
+
for (int j=0;j<(int)primitivesTemp.size();j++) {
|
|
424
|
+
for(int i=0;i<3;i++)
|
|
425
|
+
primitivesTemp(j).at(i) += (tf)nbPointsTotal;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
primitives.push_back(primitivesTemp);
|
|
430
|
+
for(int i=0;i<(int)pointsTemp.size()/3;++i) {
|
|
431
|
+
listePoints.push_back((T)pointsTemp.at(i));
|
|
432
|
+
listePoints.push_back((T)pointsTemp.at(i + pointsTemp.size()/3));
|
|
433
|
+
listePoints.push_back((T)pointsTemp.at(i + 2*pointsTemp.size()/3));
|
|
434
|
+
}
|
|
435
|
+
nbPointsTotal += pointsTemp.size()/3;
|
|
436
|
+
}
|
|
437
|
+
else if(!cimg::strncasecmp(type,"PointSet",8)) { // If the object to draw is a set of points
|
|
438
|
+
while(cimg::strncasecmp(line,"point [",7) && !std::feof(nfile))
|
|
439
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
440
|
+
|
|
441
|
+
if(std::feof(nfile)) {
|
|
442
|
+
if (!file)
|
|
443
|
+
cimg::fclose(nfile);
|
|
444
|
+
throw CImgIOException(_cimg_instance
|
|
445
|
+
"load_vrml() : points of pointSet node not defined in file '%s'.",
|
|
446
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
450
|
+
int nbPoints = 0;
|
|
451
|
+
|
|
452
|
+
while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) {
|
|
453
|
+
// while we did not get all the points and while we are not at the end of the file
|
|
454
|
+
float X = 0, Y = 0, Z = 0;
|
|
455
|
+
if ((err = std::sscanf(line,"%f %f %f,[^\n] ",&X,&Y,&Z))==3 ||
|
|
456
|
+
(err = std::sscanf(line,"%f,%f,%f,[^\n] ",&X,&Y,&Z))==3) {
|
|
457
|
+
// We get the coordinates of all the points and store them into a list of points
|
|
458
|
+
listePoints.push_back((T)X);
|
|
459
|
+
listePoints.push_back((T)Y);
|
|
460
|
+
listePoints.push_back((T)Z);
|
|
461
|
+
++nbPoints;
|
|
462
|
+
}
|
|
463
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
464
|
+
}
|
|
465
|
+
if(std::feof(nfile)) {
|
|
466
|
+
if (!file)
|
|
467
|
+
cimg::fclose(nfile);
|
|
468
|
+
throw CImgIOException(_cimg_instance
|
|
469
|
+
"load_vrml() : bad structure of pointSet node in file '%s'.",
|
|
470
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
471
|
+
}
|
|
472
|
+
primitivesTemp.assign();
|
|
473
|
+
|
|
474
|
+
for(int i=0;i<nbPoints;++i) { // The primitive is only composed of the indice of the point itself
|
|
475
|
+
CImg<tf> temp(1,1,1,1,(tf)i);
|
|
476
|
+
primitivesTemp.push_back(temp);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if(nbPointsTotal) {
|
|
480
|
+
for (int j=0;j<(int)primitivesTemp.size();j++) {
|
|
481
|
+
for(int i=0;i<(int)primitivesTemp(j).size();i++)
|
|
482
|
+
primitivesTemp(j).at(i) += (tf)nbPointsTotal;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
nbPrimitives = primitivesTemp.size();
|
|
486
|
+
|
|
487
|
+
primitives.push_back(primitivesTemp);
|
|
488
|
+
|
|
489
|
+
nbPointsTotal += nbPoints;
|
|
490
|
+
}
|
|
491
|
+
else if(!cimg::strncasecmp(type,"IndexedLineSet",14) ||
|
|
492
|
+
!cimg::strncasecmp(type,"IndexedFaceSet",14)) {
|
|
493
|
+
// If the object to draw is a set of lines or a set of faces
|
|
494
|
+
while(cimg::strncasecmp(line,"point [",7) && !std::feof(nfile))
|
|
495
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
496
|
+
if(std::feof(nfile)) {
|
|
497
|
+
if (!file)
|
|
498
|
+
cimg::fclose(nfile);
|
|
499
|
+
throw CImgIOException(_cimg_instance
|
|
500
|
+
"load_vrml() : points of IndexedSet node not defined in file '%s'.",
|
|
501
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
505
|
+
int nbPoints = 0;
|
|
506
|
+
while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) {
|
|
507
|
+
// As long as there are points defined we add them to the list
|
|
508
|
+
float X=0,Y=0,Z=0;
|
|
509
|
+
if ((err = std::sscanf(line,"%f %f %f,[^\n] ",&X,&Y,&Z))==3 ||
|
|
510
|
+
(err = std::sscanf(line,"%f,%f,%f,[^\n] ",&X,&Y,&Z))==3) {
|
|
511
|
+
// We get the coordinates of the points into a list of points
|
|
512
|
+
listePoints.push_back((T)X);
|
|
513
|
+
listePoints.push_back((T)Y);
|
|
514
|
+
listePoints.push_back((T)Z);
|
|
515
|
+
++nbPoints;
|
|
516
|
+
}
|
|
517
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
518
|
+
}
|
|
519
|
+
if(std::feof(nfile)) {
|
|
520
|
+
if (!file)
|
|
521
|
+
cimg::fclose(nfile);
|
|
522
|
+
throw CImgIOException(_cimg_instance
|
|
523
|
+
"load_vrml() : bad structure of point vector node in file '%s'.",
|
|
524
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
primitivesTemp.assign();
|
|
528
|
+
|
|
529
|
+
while(cimg::strncasecmp(line,"coordIndex [",12) && !std::feof(nfile))
|
|
530
|
+
// We are looking for the index of the points
|
|
531
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
532
|
+
if(std::feof(nfile)) {
|
|
533
|
+
if (!file)
|
|
534
|
+
cimg::fclose(nfile);
|
|
535
|
+
throw CImgIOException(_cimg_instance
|
|
536
|
+
"load_vrml() : coordIndex not furnished for IndexedSet node in file '%s'.",
|
|
537
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
541
|
+
|
|
542
|
+
while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) { // As long as there are indices
|
|
543
|
+
if(*line!='#') {
|
|
544
|
+
std::vector<tf> primitiveComponents;
|
|
545
|
+
char * pch;
|
|
546
|
+
pch = std::strtok (line,",");
|
|
547
|
+
|
|
548
|
+
while (pch != NULL && std::atof(pch)!=-1) { // We extract the list of indices and store them into a vector
|
|
549
|
+
if(!(int)count(primitiveComponents.begin(),primitiveComponents.end(),(tf)std::atof(pch)))
|
|
550
|
+
primitiveComponents.push_back((tf)std::atof(pch));
|
|
551
|
+
pch = std::strtok (NULL, ",");
|
|
552
|
+
}
|
|
553
|
+
CImg<tf> temp(1,primitiveComponents.size(),1,1);
|
|
554
|
+
|
|
555
|
+
for(int i=0;i<(int)primitiveComponents.size();++i)
|
|
556
|
+
temp(0,i) = primitiveComponents.at(i);
|
|
557
|
+
primitivesTemp.push_back(temp);
|
|
558
|
+
}
|
|
559
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
if(std::feof(nfile)) {
|
|
563
|
+
if (!file)
|
|
564
|
+
cimg::fclose(nfile);
|
|
565
|
+
throw CImgIOException(_cimg_instance
|
|
566
|
+
"load_vrml() : bad structure of coordIndex in file '%s'.",
|
|
567
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if(nbPointsTotal) {
|
|
571
|
+
for (int j=0;j<(int)primitivesTemp.size();j++) {
|
|
572
|
+
for(int i=0;i<(int)primitivesTemp(j).size();i++)
|
|
573
|
+
primitivesTemp(j).at(i) += (tf)nbPointsTotal;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
nbPrimitives = primitivesTemp.size();
|
|
578
|
+
primitives.push_back(primitivesTemp);
|
|
579
|
+
nbPointsTotal += nbPoints;
|
|
580
|
+
|
|
581
|
+
while(cimg::strncasecmp(line,"color [",7) && cimg::strncasecmp(line,"}",1) && !std::feof(nfile))
|
|
582
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
583
|
+
if(std::feof(nfile)) {
|
|
584
|
+
if (!file)
|
|
585
|
+
cimg::fclose(nfile);
|
|
586
|
+
throw CImgIOException(_cimg_instance
|
|
587
|
+
"load_vrml() : bad structure of coordIndex in file '%s'.",
|
|
588
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
589
|
+
}
|
|
590
|
+
else if(!cimg::strncasecmp(line,"color [",7)) { // If there are different colors defined for each faces
|
|
591
|
+
multipleColors = true;
|
|
592
|
+
std::vector<CImg<tc> > listColors;
|
|
593
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
594
|
+
while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) {
|
|
595
|
+
// We add the list of all colors defined into the vector listColors
|
|
596
|
+
if(*line!='#') {
|
|
597
|
+
if ((err = std::sscanf(line,"%f %f %f[^\n] ",&r,&g,&b))!=3) {
|
|
598
|
+
if (!file)
|
|
599
|
+
cimg::fclose(nfile);
|
|
600
|
+
throw CImgIOException(_cimg_instance
|
|
601
|
+
"load_vrml() : wrong number of color furnished in file '%s'.",
|
|
602
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
603
|
+
}
|
|
604
|
+
CImg<tc> img(3,1,1,1,(tc)(r*255),(tc)(g*255),(tc)(b*255));
|
|
605
|
+
listColors.push_back(img);
|
|
606
|
+
}
|
|
607
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
608
|
+
}
|
|
609
|
+
if(std::feof(nfile)) {
|
|
610
|
+
if (!file)
|
|
611
|
+
cimg::fclose(nfile);
|
|
612
|
+
throw CImgIOException(_cimg_instance
|
|
613
|
+
"load_vrml() : bad structure of color in file '%s'.",
|
|
614
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
while(cimg::strncasecmp(line,"colorIndex [",12) && !std::feof(nfile))
|
|
618
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
619
|
+
if(std::feof(nfile)) {
|
|
620
|
+
if (!file)
|
|
621
|
+
cimg::fclose(nfile);
|
|
622
|
+
throw CImgIOException(_cimg_instance
|
|
623
|
+
"load_vrml() : colorIndex not furnished for Color node in file '%s'.",
|
|
624
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
625
|
+
}
|
|
626
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
627
|
+
while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) {
|
|
628
|
+
// We add the colors at the right index into the vector colors
|
|
629
|
+
if(*line!='#') {
|
|
630
|
+
char * pch;
|
|
631
|
+
pch = std::strtok (line," ");
|
|
632
|
+
while (pch != NULL) {
|
|
633
|
+
int indice = std::atoi(pch);
|
|
634
|
+
colors.insert(CImg<tc>::vector((tc)(listColors[indice])[0],
|
|
635
|
+
(tc)(listColors[indice])[1],
|
|
636
|
+
(tc)(listColors[indice])[2]));
|
|
637
|
+
pch = std::strtok (NULL, " ");
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
else // If none of the known type of shape is defined
|
|
646
|
+
cimg::warn(_cimg_instance
|
|
647
|
+
"load_vrml() : Failed to read type of geometry to draw from file '%s'.",
|
|
648
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
649
|
+
|
|
650
|
+
if(textureTest) { // If the object considered is texturized
|
|
651
|
+
colors.push_back(colorsTextured);
|
|
652
|
+
*textureFile = 0;
|
|
653
|
+
}
|
|
654
|
+
while(cimg::strncasecmp(line,"appearance",10) &&
|
|
655
|
+
cimg::strncasecmp(line,"Shape",5) && !std::feof(nfile))
|
|
656
|
+
// We look for the node appearance or for another shape
|
|
657
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
658
|
+
}
|
|
659
|
+
if(!cimg::strncasecmp(line,"appearance",10)) { // We are at the appearance node
|
|
660
|
+
while(cimg::strncasecmp(line,"texture ImageTexture",20) &&
|
|
661
|
+
cimg::strncasecmp(line,"diffuseColor",12) && !std::feof(nfile))
|
|
662
|
+
// We are looking for a valid appearance node
|
|
663
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
664
|
+
if(!cimg::strncasecmp(line,"diffuseColor",12)) { // If the object as a unique diffuse color
|
|
665
|
+
if ((err = std::sscanf(line,"diffuseColor %f,%f,%f[^\n] ",&r,&g,&b))!=3 &&
|
|
666
|
+
(err = std::sscanf(line,"diffuseColor %f %f %f[^\n] ",&r,&g,&b))!=3) {
|
|
667
|
+
if (!file)
|
|
668
|
+
cimg::fclose(nfile);
|
|
669
|
+
throw CImgIOException(_cimg_instance
|
|
670
|
+
"load_vrml() : wrong number of color furnished in file '%s'.",
|
|
671
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
else if(!cimg::strncasecmp(line,"texture ImageTexture",20)) { // If there is a texture defined in the VRML file
|
|
675
|
+
textureTest = true;
|
|
676
|
+
colorDefined = false;
|
|
677
|
+
while(cimg::strncasecmp(line,"url",3) && !std::feof(nfile))
|
|
678
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
679
|
+
if(std::feof(nfile)) {
|
|
680
|
+
if (!file)
|
|
681
|
+
cimg::fclose(nfile);
|
|
682
|
+
throw CImgIOException(_cimg_instance
|
|
683
|
+
"load_vrml() : texture not defined in file '%s'.",
|
|
684
|
+
cimg_instance, filename?filename:"(FILE*)");
|
|
685
|
+
}
|
|
686
|
+
// We temporary put the name of the texture image into textureFileTemp
|
|
687
|
+
std::sscanf(line,"url [%s][^\n] ",textureFileTemp);
|
|
688
|
+
char * pch;
|
|
689
|
+
pch = std::strtok (textureFileTemp,"\"");
|
|
690
|
+
strcpy(textureFile,pch); // We put the url of the texture image into textureFile
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
else if(!cimg::strncasecmp(line,"Shape",5)) // We have another shape node
|
|
694
|
+
textureTest = false; // We reinitialize the texture boolean
|
|
695
|
+
|
|
696
|
+
if(nbPrimitives && colorDefined && !multipleColors && !textureTest) {
|
|
697
|
+
// If there is only one color defined we add it to the colors CImgList or if no color
|
|
698
|
+
// is defined for an object, we add the default color
|
|
699
|
+
CImgList<tc> colorsTemp;
|
|
700
|
+
colorsTemp.insert(nbPrimitives,CImg<tc>::vector((tc)(r*255),(tc)(g*255),(tc)(b*255)));
|
|
701
|
+
colors.push_back(colorsTemp);
|
|
702
|
+
nbPrimitives = 0;
|
|
703
|
+
r = 0.7f;
|
|
704
|
+
g = 0.7f;
|
|
705
|
+
b = 0.7f;
|
|
706
|
+
}
|
|
707
|
+
err = std::fscanf(nfile,"%1023[^\n] ",line);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
assign(listePoints.size()/3,3);
|
|
711
|
+
cimg_forX(*this,l) { // We add the points coordinates to the calling object
|
|
712
|
+
(*this)(l,0) = (T)(listePoints.at(l*3));
|
|
713
|
+
(*this)(l,1) = (T)(listePoints.at(l*3 + 1));
|
|
714
|
+
(*this)(l,2) = (T)(listePoints.at(l*3 + 2));
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
if (!file)
|
|
718
|
+
cimg::fclose(nfile);
|
|
719
|
+
|
|
720
|
+
return *this;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
//! Save VRML files.
|
|
724
|
+
template<typename tf, typename tc>
|
|
725
|
+
const CImg<T>& save_vrml(const char *const filename,const CImgList<tf>& primitives,
|
|
726
|
+
const CImgList<tc>& colors, const char *const texturefile = 0) const {
|
|
727
|
+
return _save_vrml(0,filename,primitives,colors,texturefile);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
//! Save VRML files.
|
|
731
|
+
template<typename tf, typename tc>
|
|
732
|
+
const CImg<T>& save_vrml(std::FILE *const file,const CImgList<tf>& primitives,
|
|
733
|
+
const CImgList<tc>& colors, const char *const texturefile = 0) const {
|
|
734
|
+
return _save_vrml(file,0,primitives,colors,texturefile);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Save VRML files (internal).
|
|
738
|
+
template<typename tf, typename tc>
|
|
739
|
+
const CImg<T>& _save_vrml(std::FILE *const file, const char *const filename, const CImgList<tf>& primitives,
|
|
740
|
+
const CImgList<tc>& colors, const char *const texturefile) const {
|
|
741
|
+
|
|
742
|
+
// Check that the user furnished a file to save the object and that the object is not empty.
|
|
743
|
+
if (!file && !filename)
|
|
744
|
+
throw CImgArgumentException(_cimg_instance
|
|
745
|
+
"save_vrml() : Specified filename is (null).",
|
|
746
|
+
cimg_instance);
|
|
747
|
+
if (is_empty())
|
|
748
|
+
throw CImgInstanceException(_cimg_instance
|
|
749
|
+
"save_vrml() : Empty instance, for file '%s'.",
|
|
750
|
+
cimg_instance,filename?filename:"(FILE*)");
|
|
751
|
+
|
|
752
|
+
// Check that the object we want to save is a 3D object.
|
|
753
|
+
CImgList<T> opacities;
|
|
754
|
+
char error_message[1024] = {0};
|
|
755
|
+
if (!is_object3d(primitives,colors,opacities,true,error_message))
|
|
756
|
+
throw CImgInstanceException(_cimg_instance
|
|
757
|
+
"save_vrml() : Invalid specified 3d object, for file '%s' (%s).",
|
|
758
|
+
cimg_instance,filename?filename:"(FILE*)",error_message);
|
|
759
|
+
const CImg<tc> default_color(1,3,1,1,200);
|
|
760
|
+
|
|
761
|
+
// We open the file in which we will save the 3D object.
|
|
762
|
+
std::FILE * nfile;
|
|
763
|
+
if(file) nfile = file;
|
|
764
|
+
else nfile = cimg::fopen(filename,"w");
|
|
765
|
+
|
|
766
|
+
// We use the version 2.0 of VRML to represent the object in UTF8
|
|
767
|
+
std::fprintf(nfile,"#VRML V2.0 utf8\n");
|
|
768
|
+
|
|
769
|
+
// We copy the coordinates of all the points
|
|
770
|
+
std::fprintf(nfile,"Shape {\n\tgeometry IndexedFaceSet {\n\t\tcoord Coordinate {\n\t\t\tpoint [\n");
|
|
771
|
+
cimg_forX(*this,i)
|
|
772
|
+
std::fprintf(nfile,"\t\t\t\t%f %f %f,\n",(float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2)));
|
|
773
|
+
std::fprintf(nfile,"\t\t\t]\n\t\t}\n\t\tcoordIndex [\n");
|
|
774
|
+
bool sameColor = true;
|
|
775
|
+
|
|
776
|
+
float r = colors[0][0]/255.0f;
|
|
777
|
+
float g = colors[0][1]/255.0f;
|
|
778
|
+
float b = colors[0][2]/255.0f;
|
|
779
|
+
|
|
780
|
+
std::vector<std::string> listColor;
|
|
781
|
+
std::string listColorPerFace("");
|
|
782
|
+
for(int i=0;i<(int)colors.size();++i) {// Test if the object is composed of only one color
|
|
783
|
+
float valR = (colors[i][0])/255.0f;
|
|
784
|
+
float valG = (colors[i][1])/255.0f;
|
|
785
|
+
float valB = (colors[i][2])/255.0f;
|
|
786
|
+
|
|
787
|
+
if (r!=valR || g!=valG || b!=valB) { // If the object has different colors
|
|
788
|
+
sameColor = false;
|
|
789
|
+
i = colors.size();
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
cimglist_for(primitives,l) { // For each primitive
|
|
794
|
+
const CImg<tc>& color = l<colors.width()?colors[l]:default_color;
|
|
795
|
+
const unsigned int psiz = primitives[l].size(), csiz = color.size();
|
|
796
|
+
float r = color[0]/255.0f;
|
|
797
|
+
float g, b;
|
|
798
|
+
if (csiz > 1) g = color[1]/255.0f;
|
|
799
|
+
else g = r/255.0f;
|
|
800
|
+
if (csiz > 2) b = color[2]/255.0f;
|
|
801
|
+
else b = g/255.0f;
|
|
802
|
+
|
|
803
|
+
switch (psiz) {
|
|
804
|
+
case 1 :
|
|
805
|
+
std::fprintf(nfile,"\t\t\t%u,-1\n",(unsigned int)primitives(l,0));
|
|
806
|
+
break;
|
|
807
|
+
case 2 :
|
|
808
|
+
std::fprintf(nfile,"\t\t\t%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,1));
|
|
809
|
+
break;
|
|
810
|
+
case 3 :
|
|
811
|
+
std::fprintf(nfile,"\t\t\t%u,%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,2),
|
|
812
|
+
(unsigned int)primitives(l,1));
|
|
813
|
+
break;
|
|
814
|
+
case 4 :
|
|
815
|
+
std::fprintf(nfile,"\t\t\t%u,%u,%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,3),
|
|
816
|
+
(unsigned int)primitives(l,2),(unsigned int)primitives(l,1));
|
|
817
|
+
break;
|
|
818
|
+
case 6 : {
|
|
819
|
+
const unsigned int xt = (unsigned int)primitives(l,2), yt = (unsigned int)primitives(l,3);
|
|
820
|
+
r = color.atXY(xt,yt,0)/255.0f;
|
|
821
|
+
g = (csiz>1?color.atXY(xt,yt,1):r)/255.0f;
|
|
822
|
+
b = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
|
|
823
|
+
std::fprintf(nfile,"\t\t\t%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,1));
|
|
824
|
+
} break;
|
|
825
|
+
case 9 : {
|
|
826
|
+
const unsigned int xt = (unsigned int)primitives(l,3), yt = (unsigned int)primitives(l,4);
|
|
827
|
+
r = color.atXY(xt,yt,0)/255.0f;
|
|
828
|
+
g = (csiz>1?color.atXY(xt,yt,1):r)/255.0f;
|
|
829
|
+
b = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
|
|
830
|
+
std::fprintf(nfile,"\t\t\t%u,%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,2),
|
|
831
|
+
(unsigned int)primitives(l,1));
|
|
832
|
+
} break;
|
|
833
|
+
case 12 : {
|
|
834
|
+
const unsigned int xt = (unsigned int)primitives(l,4), yt = (unsigned int)primitives(l,5);
|
|
835
|
+
r = color.atXY(xt,yt,0)/255.0f;
|
|
836
|
+
g = (csiz>1?color.atXY(xt,yt,1):r)/255.0f;
|
|
837
|
+
b = (csiz>2?color.atXY(xt,yt,2):g)/255.0f;
|
|
838
|
+
std::fprintf(nfile,"\t\t\t%u,%u,%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,3),
|
|
839
|
+
(unsigned int)primitives(l,2),(unsigned int)primitives(l,1));
|
|
840
|
+
} break;
|
|
841
|
+
}
|
|
842
|
+
if (!sameColor) { // If there are different colors we store on every loop the RGB values into the vector listColor
|
|
843
|
+
std::ostringstream oss;
|
|
844
|
+
oss << r << " " << g << " " << b << "\n";
|
|
845
|
+
if (listColor.size() == 0) {
|
|
846
|
+
listColor.push_back(oss.str());
|
|
847
|
+
listColorPerFace += "0"; // We store the indice of the color
|
|
848
|
+
}
|
|
849
|
+
else {
|
|
850
|
+
std::vector<std::string>::iterator it;
|
|
851
|
+
it = find (listColor.begin(), listColor.end(), oss.str());
|
|
852
|
+
std::ostringstream oss2;
|
|
853
|
+
if(it==listColor.end()) {
|
|
854
|
+
oss2 << " " << listColor.size();
|
|
855
|
+
listColorPerFace += oss2.str();
|
|
856
|
+
listColor.push_back(oss.str());
|
|
857
|
+
}
|
|
858
|
+
else {
|
|
859
|
+
int n = 0;
|
|
860
|
+
for (std::vector<std::string>::iterator iter = listColor.begin(); iter != it; iter++) ++n;
|
|
861
|
+
oss2 << " " << n;
|
|
862
|
+
listColorPerFace += oss2.str();
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
std::fprintf(nfile,"\t\t]\n");
|
|
868
|
+
|
|
869
|
+
if (texturefile) // If we have a texture instead of a color
|
|
870
|
+
std::fprintf(nfile,"\n\t}\n\tappearance DEF theTexture Appearance "
|
|
871
|
+
"{\n\t\ttexture ImageTexture {\n\t\t\turl [\"%s\"]\n\t\t}\n\t}\n}",
|
|
872
|
+
texturefile);
|
|
873
|
+
else {
|
|
874
|
+
if(!sameColor) { // If there are different colors we add all of them
|
|
875
|
+
std::fprintf(nfile,"\tcolorPerVertex FALSE\n\tcolor Color {\n\t\tcolor [\n");
|
|
876
|
+
while(!listColor.empty()) {
|
|
877
|
+
std::fprintf(nfile,"\t\t\t%s",(listColor.back()).c_str());
|
|
878
|
+
listColor.pop_back();
|
|
879
|
+
}
|
|
880
|
+
std::fprintf(nfile,"\t\t]\n\t}\n\tcolorIndex [\n\t\t");
|
|
881
|
+
std::fprintf(nfile,"%s",listColorPerFace.c_str());
|
|
882
|
+
std::fprintf(nfile,"\n\t]\n\t}\n}");
|
|
883
|
+
}
|
|
884
|
+
else { // If there is only one color we add it with the Material node
|
|
885
|
+
std::fprintf(nfile,"\t}\n\tappearance Appearance "
|
|
886
|
+
"{\n\t\tmaterial Material {\n\t\t\tdiffuseColor %f,%f,%f\n\t\t}\n\t}\n}",
|
|
887
|
+
colors[0][0]/255.0f,colors[0][1]/255.0f,colors[0][2]/255.0f);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
if (!file) cimg::fclose(nfile);
|
|
891
|
+
return *this;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
#endif /* cimg_plugin_vrml */
|