mirror of
				https://github.com/RetroDECK/ES-DE.git
				synced 2025-04-10 19:15:13 +00:00 
			
		
		
		
	
		
			
	
	
		
			895 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			895 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  #
 | ||
|  |  #  File        : vrml.h
 | ||
|  |  #                ( C++ header file - CImg plug-in )
 | ||
|  |  #
 | ||
|  |  #  Description : CImg plugin that provide functions to load/save VRML files.
 | ||
|  |  #                This file is a part of the CImg Library project.
 | ||
|  |  #                ( http://cimg.eu )
 | ||
|  |  #
 | ||
|  |  #  Copyright   : Greg Rami
 | ||
|  |  #                ( greg.rami36 (at) gmail.com )
 | ||
|  |  #
 | ||
|  |  #  License     : CeCILL v2.0
 | ||
|  |  #                ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
 | ||
|  |  #
 | ||
|  |  #  This software is governed by the CeCILL  license under French law and
 | ||
|  |  #  abiding by the rules of distribution of free software.  You can  use,
 | ||
|  |  #  modify and/ or redistribute the software under the terms of the CeCILL
 | ||
|  |  #  license as circulated by CEA, CNRS and INRIA at the following URL
 | ||
|  |  #  "http://www.cecill.info".
 | ||
|  |  #
 | ||
|  |  #  As a counterpart to the access to the source code and  rights to copy,
 | ||
|  |  #  modify and redistribute granted by the license, users are provided only
 | ||
|  |  #  with a limited warranty  and the software's author,  the holder of the
 | ||
|  |  #  economic rights,  and the successive licensors  have only  limited
 | ||
|  |  #  liability.
 | ||
|  |  #
 | ||
|  |  #  In this respect, the user's attention is drawn to the risks associated
 | ||
|  |  #  with loading,  using,  modifying and/or developing or reproducing the
 | ||
|  |  #  software by the user in light of its specific status of free software,
 | ||
|  |  #  that may mean  that it is complicated to manipulate,  and  that  also
 | ||
|  |  #  therefore means  that it is reserved for developers  and  experienced
 | ||
|  |  #  professionals having in-depth computer knowledge. Users are therefore
 | ||
|  |  #  encouraged to load and test the software's suitability as regards their
 | ||
|  |  #  requirements in conditions enabling the security of their systems and/or
 | ||
|  |  #  data to be ensured and,  more generally, to use and operate it in the
 | ||
|  |  #  same conditions as regards security.
 | ||
|  |  #
 | ||
|  |  #  The fact that you are presently reading this means that you have had
 | ||
|  |  #  knowledge of the CeCILL license and that you accept its terms.
 | ||
|  |  #
 | ||
|  | */ | ||
|  | 
 | ||
|  | /*-----------------------------------------------------------------------------------
 | ||
|  | 
 | ||
|  |  IMPORTANT NOTE : | ||
|  | 
 | ||
|  |  You *need* to include the following lines in your own code to use this plugin : | ||
|  | 
 | ||
|  |  #include <vector>
 | ||
|  |  #include <string>
 | ||
|  |  #include <sstream>
 | ||
|  |  #include <algorithm>
 | ||
|  | 
 | ||
|  | ------------------------------------------------------------------------------------*/ | ||
|  | 
 | ||
|  | #ifndef cimg_plugin_vrml
 | ||
|  | #define cimg_plugin_vrml
 | ||
|  | 
 | ||
|  | //! Load a 3d object from a .VRML file.
 | ||
|  | template<typename tf, typename tc> | ||
|  | CImg<T>& load_vrml(const char *const filename, CImgList<tf>& primitives, CImgList<tc>& colors) { | ||
|  |   return _load_vrml(0,filename,primitives,colors); | ||
|  | } | ||
|  | 
 | ||
|  | //! Load a 3d object from a .VRML file.
 | ||
|  | template<typename tf, typename tc> | ||
|  | static CImg<T> get_load_vrml(const char *const filename, CImgList<tf>& primitives, CImgList<tc>& colors) { | ||
|  |   return CImg<T>().load_vrml(filename,primitives,colors); | ||
|  | } | ||
|  | 
 | ||
|  | //! Load a 3d object from a .VRML file.
 | ||
|  | template<typename tf, typename tc> | ||
|  | CImg<T>& load_vrml(std::FILE *const file, CImgList<tf>& primitives, CImgList<tc>& colors) { | ||
|  |   return _load_vrml(file,0,primitives,colors); | ||
|  | } | ||
|  | 
 | ||
|  | //! Load a 3d object from a .VRML file.
 | ||
|  | template<typename tf, typename tc> | ||
|  | static CImg<T> get_load_vrml(std::FILE *const file, CImgList<tf>& primitives, CImgList<tc>& colors) { | ||
|  |   return CImg<T>().load_vrml(file,primitives,colors); | ||
|  | } | ||
|  | 
 | ||
|  | //! Load a 3d object from a .VRML file (internal).
 | ||
|  | template<typename tf, typename tc> | ||
|  | CImg<T>& _load_vrml(std::FILE *const file, const char *const filename,CImgList<tf>& primitives, CImgList<tc>& colors) { | ||
|  |   if (!file && !filename) | ||
|  |     throw CImgArgumentException(_cimg_instance | ||
|  |                                 "load_vrml() : Specified filename is (null).", | ||
|  |                                 cimg_instance); | ||
|  |   std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); | ||
|  | 
 | ||
|  |   char line[1024] = { 0 }; | ||
|  |   int err; | ||
|  | 
 | ||
|  |   // Skip comments, and read the first node.
 | ||
|  |   do { err = std::fscanf(nfile,"%65535[^\n] ",line); } while (!err || (err==1 && *line=='#')); | ||
|  | 
 | ||
|  |   // Check for a first valid vrml valid node.
 | ||
|  |   if (cimg::strncasecmp(line,"Shape",5) && | ||
|  |       cimg::strncasecmp(line,"Transform",9) && | ||
|  |       cimg::strncasecmp(line,"NavigationInfo",14) && | ||
|  |       cimg::strncasecmp(line,"Billboard",9)) { | ||
|  |     if (!file) cimg::fclose(nfile); | ||
|  |     throw CImgIOException(_cimg_instance | ||
|  |                           "load_vrml() : VRML nodes not found in file '%s'.", | ||
|  |                           cimg_instance,filename?filename:"(FILE*)"); | ||
|  |   } | ||
|  | 
 | ||
|  |   // Look for the Shape node (as we do not manage the treatment for the other nodes yet).
 | ||
|  |   if (cimg::strncasecmp(line,"Shape",5)) { | ||
|  |     while (cimg::strncasecmp(line,"Shape",5) && !std::feof(nfile)) err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |     if (std::feof(nfile)) { | ||
|  |       if (!file) cimg::fclose(nfile); | ||
|  |       throw CImgIOException(_cimg_instance | ||
|  |                             "load_vrml() : Shape node not found in file '%s'.", | ||
|  |                             cimg_instance,filename?filename:"(FILE*)"); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   // Look for either geometry or appearance node.
 | ||
|  |   while (cimg::strncasecmp(line,"geometry",8) && cimg::strncasecmp(line,"appearance",10) && !std::feof(nfile)) | ||
|  |     err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |   if (std::feof(nfile)) { // If none of these nodes are defined.
 | ||
|  |     if (!file) cimg::fclose(nfile); | ||
|  |     throw CImgIOException(_cimg_instance | ||
|  |                           "load_vrml() : Geometry and appearance nodes not found in file '%s'.", | ||
|  |                           cimg_instance,filename?filename:"(FILE*)"); | ||
|  |   } | ||
|  | 
 | ||
|  |   std::vector<T> listePoints; // Intermediate list containing the points of the whole object.
 | ||
|  |   primitives.assign(); | ||
|  |   colors.assign(); | ||
|  |   // Count the number of points of the whole object and the number of primitives.
 | ||
|  |   int nbPointsTotal = 0, nbPrimitives = 0; | ||
|  |   float r = 0.78f, g = 0.78f, b = 0.78f; // RGB level of the object, the object is gray by default.
 | ||
|  |   // Boolean used to know if a color is defined for an object,
 | ||
|  |   // if this object has multiple colors or if the object has a texture
 | ||
|  |   bool colorDefined = true, multipleColors = false, textureTest = false; | ||
|  |   char textureFile[1024] = { 0 }; // Variable containing the name of the image used as a texture
 | ||
|  | 
 | ||
|  |   while (!std::feof(nfile)) { | ||
|  |     char type[1024] = { 0 }, textureFileTemp[1024] = { 0 }; | ||
|  |     colorDefined = true; | ||
|  |     if (!cimg::strncasecmp(line,"geometry",8)) {       // We are at the geometry node
 | ||
|  |       std::sscanf(line,"geometry %s",type);            // We are looking for the type of geometry to draw
 | ||
|  |       const CImg<float> coords = CImg<float>::empty(); // CImg used for the texturization of an object
 | ||
|  |       CImgList<tc> colorsTextured;                     // CImgList used for the texturization of the color of an object
 | ||
|  |       CImgList<tf> primitivesTemp;  // Intermediate CImgList used to update the primitives of the whole object
 | ||
|  | 
 | ||
|  |       if (!cimg::strncasecmp(type,"Box",3)) { // If the object to draw is a box
 | ||
|  |         while (cimg::strncasecmp(line,"size",4) && !std::feof(nfile)) // We are looking for the size of the box
 | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  | 
 | ||
|  |         if (std::feof(nfile)) { // If no size is specified
 | ||
|  |           if (!file) cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : size of box not defined in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  | 
 | ||
|  |         float X = 0, Y = 0, Z = 0; // The width, height and depth of the box
 | ||
|  |         if ((err = std::sscanf(line,"size %f %f %f[^\n] ",&X,&Y,&Z))!=3 && | ||
|  |             (err = std::sscanf(line,"size %f,%f,%f[^\n] ",&X,&Y,&Z))!=3) { | ||
|  |           if (!file) cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : Failed to read box size in file '%s'.", | ||
|  |                                 cimg_instance,filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  |         // We generate the primitives and the points of the box
 | ||
|  |         const CImg<T> pointsTemp = CImg<T>::box3d(primitivesTemp,(T)X,(T)Y,(T)Z); | ||
|  | 
 | ||
|  |         nbPrimitives = primitivesTemp.size(); // We save the number of primitives of the object
 | ||
|  | 
 | ||
|  |         if (textureTest) { // If the object has a texture
 | ||
|  |           // We put the image used as a texture into a CImg object
 | ||
|  |           const CImg<float> texture(textureFile); | ||
|  |           // We initialize the colorsTextured list
 | ||
|  |           colorsTextured.insert(primitivesTemp.size(),CImg<unsigned char>::vector(0,50,250)); | ||
|  |           // We texturize the object
 | ||
|  |           pointsTemp.texturize_object3d(primitivesTemp,colorsTextured,texture,coords); | ||
|  |           nbPrimitives = 0; | ||
|  |         } | ||
|  | 
 | ||
|  |         if(nbPointsTotal) { // If there are already some objects in the scene
 | ||
|  |           for (int j=0;j<(int)primitivesTemp.size();j++) { | ||
|  |             for(int i=0;i<4;i++) | ||
|  |               // We shift the indices in the primitives to designate the right points
 | ||
|  |               primitivesTemp(j).at(i) += (tf)nbPointsTotal; | ||
|  |           } | ||
|  |         } | ||
|  |         primitives.push_back(primitivesTemp); // We add the primitives of the box to the general primitives variable
 | ||
|  |         for(int i=0;i<(int)pointsTemp.size()/3;++i) { // We add the points into the temporary list in the right order
 | ||
|  |           listePoints.push_back((T)pointsTemp.at(i)); | ||
|  |           listePoints.push_back((T)pointsTemp.at(i + 8)); | ||
|  |           listePoints.push_back((T)pointsTemp.at(i + 16)); | ||
|  |         } | ||
|  |         nbPointsTotal += pointsTemp.size()/3; // We increase the number of points of the whole object
 | ||
|  |       } | ||
|  |       else if(!cimg::strncasecmp(type,"Sphere",6)) { // If the object to draw is a sphere
 | ||
|  |         while(cimg::strncasecmp(line,"radius",6) && !std::feof(nfile)) | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  | 
 | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : radius of sphere not defined in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  | 
 | ||
|  |         float R = 0; | ||
|  |         if ((err = std::sscanf(line,"radius %f[^\n] ",&R))!=1) { // We get the radius of the sphere
 | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : Failed to read sphere radius in file '%s'.", | ||
|  |                                 cimg_instance,filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  |         // Compute the necessary points and primitives for a sphere of radius R
 | ||
|  |         const CImg<T> pointsTemp = CImg<T>::sphere3d(primitivesTemp,(T)R); | ||
|  |         // We get the number of primitives to used on the attribution of a color, in case no specific color is defined
 | ||
|  |         nbPrimitives = primitivesTemp.size(); | ||
|  | 
 | ||
|  |         if(textureTest) { // If the object has a texture
 | ||
|  |           // We put the image used as a texture into a CImg object
 | ||
|  |           const CImg<float> texture(textureFile); | ||
|  |           // We initialize the colorsTextured list
 | ||
|  |           colorsTextured.insert(primitivesTemp.size(),CImg<unsigned char>::vector(0,50,250)); | ||
|  |           pointsTemp.texturize_object3d(primitivesTemp,colorsTextured,texture,coords); // We texturize the object
 | ||
|  |           nbPrimitives = 0; // We set to 0 because there is no color to use
 | ||
|  |         } | ||
|  | 
 | ||
|  |         if(nbPointsTotal) { // If there are already some objects in the scene
 | ||
|  |           for (int j=0;j<(int)primitivesTemp.size();j++) { | ||
|  |             for(int i=0;i<3;i++) | ||
|  |               primitivesTemp(j).at(i) += (tf)nbPointsTotal; | ||
|  |           } | ||
|  |         } | ||
|  | 
 | ||
|  |         primitives.push_back(primitivesTemp); | ||
|  |         for(int i=0;i<(int)pointsTemp.size()/3;++i) { | ||
|  |           listePoints.push_back((T)pointsTemp.at(i)); | ||
|  |           listePoints.push_back((T)pointsTemp.at(i + pointsTemp.size()/3)); | ||
|  |           listePoints.push_back((T)pointsTemp.at(i + 2*pointsTemp.size()/3)); | ||
|  |         } | ||
|  |         nbPointsTotal += pointsTemp.size()/3; | ||
|  |       } | ||
|  |       else if(!cimg::strncasecmp(type,"Cone",4)) { // If the object to draw is a cone
 | ||
|  |         while(cimg::strncasecmp(line,"bottomRadius",12) && !std::feof(nfile) && cimg::strncasecmp(line,"height",6)) | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         float R = 0, H = 0; | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : bottom radius and height of cone not defined in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  |         else if(!cimg::strncasecmp(line,"bottomRadius",12)) { // We find the bottom radius of the cone first
 | ||
|  |           if ((err = std::sscanf(line,"bottomRadius %f[^\n] ",&R))!=1) { // We get the radius into the variable R
 | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : Failed to read cone bottomRadius in file '%s'.", | ||
|  |                                   cimg_instance,filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |           while(!std::feof(nfile) && cimg::strncasecmp(line,"height",6)) // We look for the height of the cone
 | ||
|  |             err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  | 
 | ||
|  |           if(std::feof(nfile)) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : height of cone not defined in file '%s'.", | ||
|  |                                   cimg_instance, filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  | 
 | ||
|  |           if ((err = std::sscanf(line,"height %f[^\n] ",&H))!=1) { // We get the height into the variable H
 | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : Failed to read cone height in file '%s'.", | ||
|  |                                   cimg_instance,filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |         } | ||
|  |         else { // We find the height of the cone first
 | ||
|  |           if ((err = std::sscanf(line,"height %f[^\n] ",&H))!=1) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : Failed to read cone height in file '%s'.", | ||
|  |                                   cimg_instance,filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |           while(!std::feof(nfile) && cimg::strncasecmp(line,"bottomRadius",12)) | ||
|  |             err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  | 
 | ||
|  |           if(std::feof(nfile)) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : bottom radius of cone not defined in file '%s'.", | ||
|  |                                   cimg_instance, filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  | 
 | ||
|  |           if ((err = std::sscanf(line,"bottomRadius %f[^\n] ",&R))!=1) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : Failed to read cone bottom radius in file '%s'.", | ||
|  |                                   cimg_instance,filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |         } | ||
|  |         // Compute the necessary points and primitives for a cone of radius R and height H
 | ||
|  |         const CImg<T> pointsTemp = CImg<T>::cone3d(primitivesTemp,(T)R,(T)H); | ||
|  | 
 | ||
|  |         nbPrimitives = primitivesTemp.size(); | ||
|  | 
 | ||
|  |         if(textureTest) { // If the object has a texture
 | ||
|  |           // We put the image used as a texture into a CImg object
 | ||
|  |           const CImg<float> texture(textureFile); | ||
|  |           // We initialize the colorsTextured list
 | ||
|  |           colorsTextured.insert(primitivesTemp.size(),CImg<unsigned char>::vector(0,50,250)); | ||
|  |           pointsTemp.texturize_object3d(primitivesTemp,colorsTextured,texture,coords); // We texturize the object
 | ||
|  |           nbPrimitives = 0; | ||
|  |         } | ||
|  | 
 | ||
|  |         if(nbPointsTotal) { | ||
|  |           for (int j=0;j<(int)primitivesTemp.size();j++) { | ||
|  |             for(int i=0;i<3;i++) | ||
|  |               primitivesTemp(j).at(i) += (tf)nbPointsTotal; | ||
|  |           } | ||
|  |         } | ||
|  | 
 | ||
|  |         primitives.push_back(primitivesTemp); | ||
|  |         for(int i=0;i<(int)pointsTemp.size()/3;++i) { | ||
|  |           listePoints.push_back((T)pointsTemp.at(i)); | ||
|  |           listePoints.push_back((T)pointsTemp.at(i + pointsTemp.size()/3)); | ||
|  |           listePoints.push_back((T)pointsTemp.at(i + 2*pointsTemp.size()/3)); | ||
|  |         } | ||
|  |         nbPointsTotal += pointsTemp.size()/3; | ||
|  |       } | ||
|  |       else if(!cimg::strncasecmp(type,"Cylinder",8)) { // If the object to draw is a cylinder
 | ||
|  |         while(cimg::strncasecmp(line,"radius",6) && !std::feof(nfile) && cimg::strncasecmp(line,"height",6)) | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         float R = 0, H = 0; | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : radius or height of cylinder not defined in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  |         else if(!cimg::strncasecmp(line,"radius",6)) { // If we find the radius first
 | ||
|  |           if ((err = std::sscanf(line,"radius %f[^\n] ",&R))!=1) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : Failed to read cylinder radius in file '%s'.", | ||
|  |                                   cimg_instance,filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |           while(!std::feof(nfile) && cimg::strncasecmp(line,"height",6)) // We now look for the height of the cylinder
 | ||
|  |             err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  | 
 | ||
|  |           if(std::feof(nfile)) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : height of cylinder not defined in file '%s'.", | ||
|  |                                   cimg_instance, filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  | 
 | ||
|  |           if ((err = std::sscanf(line,"height %f[^\n] ",&H))!=1) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : Failed to read cylinder height in file '%s'.", | ||
|  |                                   cimg_instance,filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |         } | ||
|  |         else { // If we find the height first
 | ||
|  |           if ((err = std::sscanf(line,"height %f[^\n] ",&H))!=1) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : Failed to read cylinder height in file '%s'.", | ||
|  |                                   cimg_instance,filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |           while(!std::feof(nfile) && cimg::strncasecmp(line,"radius",6))// We now look for the radius of the cylinder
 | ||
|  |             err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  | 
 | ||
|  |           if(std::feof(nfile)) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : radius of cylinder not defined in file '%s'.", | ||
|  |                                   cimg_instance, filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  | 
 | ||
|  |           if ((err = std::sscanf(line,"radius %f[^\n] ",&R))!=1) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : Failed to read cylinder radius in file '%s'.", | ||
|  |                                   cimg_instance,filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |         } | ||
|  |         // Compute the necessary points and primitives for a cylinder of radius R and height H
 | ||
|  |         const CImg<T> pointsTemp = CImg<T>::cylinder3d(primitivesTemp,(T)R,(T)H); | ||
|  | 
 | ||
|  |         if(textureTest) { // If the object has a texture
 | ||
|  |           // We put the image used as a texture into a CImg object
 | ||
|  |           const CImg<float> texture(textureFile); | ||
|  |           // We initialize the colorsTextured list
 | ||
|  |           colorsTextured.insert(primitivesTemp.size(),CImg<unsigned char>::vector(0,50,250)); | ||
|  |           pointsTemp.texturize_object3d(primitivesTemp,colorsTextured,texture,coords); // We texturize the object
 | ||
|  |           nbPrimitives = 0; | ||
|  |         } | ||
|  | 
 | ||
|  |         nbPrimitives = primitivesTemp.size(); | ||
|  | 
 | ||
|  |         if(nbPointsTotal) { | ||
|  |           for (int j=0;j<(int)primitivesTemp.size();j++) { | ||
|  |             for(int i=0;i<3;i++) | ||
|  |               primitivesTemp(j).at(i) += (tf)nbPointsTotal; | ||
|  |           } | ||
|  |         } | ||
|  | 
 | ||
|  |         primitives.push_back(primitivesTemp); | ||
|  |         for(int i=0;i<(int)pointsTemp.size()/3;++i) { | ||
|  |           listePoints.push_back((T)pointsTemp.at(i)); | ||
|  |           listePoints.push_back((T)pointsTemp.at(i + pointsTemp.size()/3)); | ||
|  |           listePoints.push_back((T)pointsTemp.at(i + 2*pointsTemp.size()/3)); | ||
|  |         } | ||
|  |         nbPointsTotal += pointsTemp.size()/3; | ||
|  |       } | ||
|  |       else if(!cimg::strncasecmp(type,"PointSet",8)) { // If the object to draw is a set of points
 | ||
|  |         while(cimg::strncasecmp(line,"point [",7) && !std::feof(nfile)) | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  | 
 | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : points of pointSet node not defined in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  | 
 | ||
|  |         err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         int nbPoints = 0; | ||
|  | 
 | ||
|  |         while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) { | ||
|  |           // while we did not get all the points and while we are not at the end of the file
 | ||
|  |           float X = 0, Y = 0, Z = 0; | ||
|  |           if ((err = std::sscanf(line,"%f %f %f,[^\n] ",&X,&Y,&Z))==3 || | ||
|  |               (err = std::sscanf(line,"%f,%f,%f,[^\n] ",&X,&Y,&Z))==3) { | ||
|  |             // We get the coordinates of all the points and store them into a list of points
 | ||
|  |             listePoints.push_back((T)X); | ||
|  |             listePoints.push_back((T)Y); | ||
|  |             listePoints.push_back((T)Z); | ||
|  |             ++nbPoints; | ||
|  |           } | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         } | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : bad structure of pointSet node in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  |         primitivesTemp.assign(); | ||
|  | 
 | ||
|  |         for(int i=0;i<nbPoints;++i) { // The primitive is only composed of the indice of the point itself
 | ||
|  |           CImg<tf> temp(1,1,1,1,(tf)i); | ||
|  |           primitivesTemp.push_back(temp); | ||
|  |         } | ||
|  | 
 | ||
|  |         if(nbPointsTotal) { | ||
|  |           for (int j=0;j<(int)primitivesTemp.size();j++) { | ||
|  |             for(int i=0;i<(int)primitivesTemp(j).size();i++) | ||
|  |               primitivesTemp(j).at(i) += (tf)nbPointsTotal; | ||
|  |           } | ||
|  |         } | ||
|  |         nbPrimitives = primitivesTemp.size(); | ||
|  | 
 | ||
|  |         primitives.push_back(primitivesTemp); | ||
|  | 
 | ||
|  |         nbPointsTotal += nbPoints; | ||
|  |       } | ||
|  |       else if(!cimg::strncasecmp(type,"IndexedLineSet",14) || | ||
|  |               !cimg::strncasecmp(type,"IndexedFaceSet",14)) { | ||
|  |         // If the object to draw is a set of lines or a set of faces
 | ||
|  |         while(cimg::strncasecmp(line,"point [",7) && !std::feof(nfile)) | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : points of IndexedSet node not defined in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  | 
 | ||
|  |         err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         int nbPoints = 0; | ||
|  |         while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) { | ||
|  |           // As long as there are points defined we add them to the list
 | ||
|  |           float X=0,Y=0,Z=0; | ||
|  |           if ((err = std::sscanf(line,"%f %f %f,[^\n] ",&X,&Y,&Z))==3 || | ||
|  |               (err = std::sscanf(line,"%f,%f,%f,[^\n] ",&X,&Y,&Z))==3) { | ||
|  |             // We get the coordinates of the points into a list of points
 | ||
|  |             listePoints.push_back((T)X); | ||
|  |             listePoints.push_back((T)Y); | ||
|  |             listePoints.push_back((T)Z); | ||
|  |             ++nbPoints; | ||
|  |           } | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         } | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : bad structure of point vector node in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  | 
 | ||
|  |         primitivesTemp.assign(); | ||
|  | 
 | ||
|  |         while(cimg::strncasecmp(line,"coordIndex [",12) && !std::feof(nfile)) | ||
|  |           // We are looking for the index of the points
 | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : coordIndex not furnished for IndexedSet node in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  | 
 | ||
|  |         err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  | 
 | ||
|  |         while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) { // As long as there are indices
 | ||
|  |           if(*line!='#') { | ||
|  |             std::vector<tf> primitiveComponents; | ||
|  |             char * pch; | ||
|  |             pch = std::strtok (line,","); | ||
|  | 
 | ||
|  |             while (pch != NULL && std::atof(pch)!=-1) { // We extract the list of indices and store them into a vector
 | ||
|  |               if(!(int)count(primitiveComponents.begin(),primitiveComponents.end(),(tf)std::atof(pch))) | ||
|  |                 primitiveComponents.push_back((tf)std::atof(pch)); | ||
|  |               pch = std::strtok (NULL, ","); | ||
|  |             } | ||
|  |             CImg<tf> temp(1,primitiveComponents.size(),1,1); | ||
|  | 
 | ||
|  |             for(int i=0;i<(int)primitiveComponents.size();++i) | ||
|  |               temp(0,i) = primitiveComponents.at(i); | ||
|  |             primitivesTemp.push_back(temp); | ||
|  |           } | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         } | ||
|  | 
 | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : bad structure of coordIndex in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  | 
 | ||
|  |         if(nbPointsTotal) { | ||
|  |           for (int j=0;j<(int)primitivesTemp.size();j++) { | ||
|  |             for(int i=0;i<(int)primitivesTemp(j).size();i++) | ||
|  |               primitivesTemp(j).at(i) += (tf)nbPointsTotal; | ||
|  |           } | ||
|  |         } | ||
|  | 
 | ||
|  |         nbPrimitives = primitivesTemp.size(); | ||
|  |         primitives.push_back(primitivesTemp); | ||
|  |         nbPointsTotal += nbPoints; | ||
|  | 
 | ||
|  |         while(cimg::strncasecmp(line,"color [",7) && cimg::strncasecmp(line,"}",1) && !std::feof(nfile)) | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : bad structure of coordIndex in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  |         else if(!cimg::strncasecmp(line,"color [",7)) { // If there are different colors defined for each faces
 | ||
|  |           multipleColors = true; | ||
|  |           std::vector<CImg<tc> > listColors; | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |           while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) { | ||
|  |             // We add the list of all colors defined into the vector listColors
 | ||
|  |             if(*line!='#') { | ||
|  |               if ((err = std::sscanf(line,"%f %f %f[^\n] ",&r,&g,&b))!=3) { | ||
|  |                 if (!file) | ||
|  |                   cimg::fclose(nfile); | ||
|  |                 throw CImgIOException(_cimg_instance | ||
|  |                                       "load_vrml() : wrong number of color furnished in file '%s'.", | ||
|  |                                       cimg_instance,filename?filename:"(FILE*)"); | ||
|  |               } | ||
|  |               CImg<tc> img(3,1,1,1,(tc)(r*255),(tc)(g*255),(tc)(b*255)); | ||
|  |               listColors.push_back(img); | ||
|  |             } | ||
|  |             err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |           } | ||
|  |           if(std::feof(nfile)) { | ||
|  |             if (!file) | ||
|  |               cimg::fclose(nfile); | ||
|  |             throw CImgIOException(_cimg_instance | ||
|  |                                   "load_vrml() : bad structure of color in file '%s'.", | ||
|  |                                   cimg_instance, filename?filename:"(FILE*)"); | ||
|  |           } | ||
|  |           else { | ||
|  |             while(cimg::strncasecmp(line,"colorIndex [",12) && !std::feof(nfile)) | ||
|  |               err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |             if(std::feof(nfile)) { | ||
|  |               if (!file) | ||
|  |                 cimg::fclose(nfile); | ||
|  |               throw CImgIOException(_cimg_instance | ||
|  |                                     "load_vrml() : colorIndex not furnished for Color node in file '%s'.", | ||
|  |                                     cimg_instance, filename?filename:"(FILE*)"); | ||
|  |             } | ||
|  |             err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |             while(cimg::strncasecmp(line,"]",1) && !std::feof(nfile)) { | ||
|  |               // We add the colors at the right index into the vector colors
 | ||
|  |               if(*line!='#') { | ||
|  |                 char * pch; | ||
|  |                 pch = std::strtok (line," "); | ||
|  |                 while (pch != NULL) { | ||
|  |                   int indice = std::atoi(pch); | ||
|  |                   colors.insert(CImg<tc>::vector((tc)(listColors[indice])[0], | ||
|  |                                                  (tc)(listColors[indice])[1], | ||
|  |                                                  (tc)(listColors[indice])[2])); | ||
|  |                   pch = std::strtok (NULL, " "); | ||
|  |                 } | ||
|  |               } | ||
|  |               err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |             } | ||
|  |           } | ||
|  |         } | ||
|  |       } | ||
|  |       else // If none of the known type of shape is defined
 | ||
|  |         cimg::warn(_cimg_instance | ||
|  |                    "load_vrml() : Failed to read type of geometry to draw from file '%s'.", | ||
|  |                    cimg_instance,filename?filename:"(FILE*)"); | ||
|  | 
 | ||
|  |       if(textureTest) { // If the object considered is texturized
 | ||
|  |         colors.push_back(colorsTextured); | ||
|  |         *textureFile = 0; | ||
|  |       } | ||
|  |       while(cimg::strncasecmp(line,"appearance",10) && | ||
|  |             cimg::strncasecmp(line,"Shape",5) && !std::feof(nfile)) | ||
|  |         // We look for the node appearance or for another shape
 | ||
|  |         err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |     } | ||
|  |     if(!cimg::strncasecmp(line,"appearance",10)) { // We are at the appearance node
 | ||
|  |       while(cimg::strncasecmp(line,"texture ImageTexture",20) && | ||
|  |             cimg::strncasecmp(line,"diffuseColor",12) && !std::feof(nfile)) | ||
|  |         // We are looking for a valid appearance node
 | ||
|  |         err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |       if(!cimg::strncasecmp(line,"diffuseColor",12)) { // If the object as a unique diffuse color
 | ||
|  |         if ((err = std::sscanf(line,"diffuseColor %f,%f,%f[^\n] ",&r,&g,&b))!=3 && | ||
|  |             (err = std::sscanf(line,"diffuseColor %f %f %f[^\n] ",&r,&g,&b))!=3) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : wrong number of color furnished in file '%s'.", | ||
|  |                                 cimg_instance,filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  |       } | ||
|  |       else if(!cimg::strncasecmp(line,"texture ImageTexture",20)) { // If there is a texture defined in the VRML file
 | ||
|  |         textureTest = true; | ||
|  |         colorDefined = false; | ||
|  |         while(cimg::strncasecmp(line,"url",3) && !std::feof(nfile)) | ||
|  |           err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |         if(std::feof(nfile)) { | ||
|  |           if (!file) | ||
|  |             cimg::fclose(nfile); | ||
|  |           throw CImgIOException(_cimg_instance | ||
|  |                                 "load_vrml() : texture not defined in file '%s'.", | ||
|  |                                 cimg_instance, filename?filename:"(FILE*)"); | ||
|  |         } | ||
|  |         // We temporary put the name of the texture image into textureFileTemp
 | ||
|  |         std::sscanf(line,"url [%s][^\n] ",textureFileTemp); | ||
|  |         char * pch; | ||
|  |         pch = std::strtok (textureFileTemp,"\""); | ||
|  |         strcpy(textureFile,pch); // We put the url of the texture image into textureFile
 | ||
|  |       } | ||
|  |     } | ||
|  |     else if(!cimg::strncasecmp(line,"Shape",5)) // We have another shape node
 | ||
|  |       textureTest = false; // We reinitialize the texture boolean
 | ||
|  | 
 | ||
|  |     if(nbPrimitives && colorDefined && !multipleColors && !textureTest) { | ||
|  |       // If there is only one color defined we add it to the colors CImgList or if no color
 | ||
|  |       // is defined for an object, we add the default color
 | ||
|  |       CImgList<tc> colorsTemp; | ||
|  |       colorsTemp.insert(nbPrimitives,CImg<tc>::vector((tc)(r*255),(tc)(g*255),(tc)(b*255))); | ||
|  |       colors.push_back(colorsTemp); | ||
|  |       nbPrimitives = 0; | ||
|  |       r = 0.7f; | ||
|  |       g = 0.7f; | ||
|  |       b = 0.7f; | ||
|  |     } | ||
|  |     err = std::fscanf(nfile,"%1023[^\n] ",line); | ||
|  |   } | ||
|  | 
 | ||
|  |   assign(listePoints.size()/3,3); | ||
|  |   cimg_forX(*this,l) { // We add the points coordinates to the calling object
 | ||
|  |     (*this)(l,0) = (T)(listePoints.at(l*3)); | ||
|  |     (*this)(l,1) = (T)(listePoints.at(l*3 + 1)); | ||
|  |     (*this)(l,2) = (T)(listePoints.at(l*3 + 2)); | ||
|  |   } | ||
|  | 
 | ||
|  |   if (!file) | ||
|  |     cimg::fclose(nfile); | ||
|  | 
 | ||
|  |   return *this; | ||
|  | } | ||
|  | 
 | ||
|  | //! Save VRML files.
 | ||
|  | template<typename tf, typename tc> | ||
|  | const CImg<T>& save_vrml(const char *const filename,const CImgList<tf>& primitives, | ||
|  |                          const CImgList<tc>& colors, const char *const texturefile = 0) const { | ||
|  |   return _save_vrml(0,filename,primitives,colors,texturefile); | ||
|  | } | ||
|  | 
 | ||
|  | //! Save VRML files.
 | ||
|  | template<typename tf, typename tc> | ||
|  | const CImg<T>& save_vrml(std::FILE *const file,const CImgList<tf>& primitives, | ||
|  |                          const CImgList<tc>& colors, const char *const texturefile = 0) const { | ||
|  |   return _save_vrml(file,0,primitives,colors,texturefile); | ||
|  | } | ||
|  | 
 | ||
|  | // Save VRML files (internal).
 | ||
|  | template<typename tf, typename tc> | ||
|  | const CImg<T>& _save_vrml(std::FILE *const file, const char *const filename, const CImgList<tf>& primitives, | ||
|  |                           const CImgList<tc>& colors, const char *const texturefile) const { | ||
|  | 
 | ||
|  |   // Check that the user furnished a file to save the object and that the object is not empty.
 | ||
|  |   if (!file && !filename) | ||
|  |     throw CImgArgumentException(_cimg_instance | ||
|  |                                 "save_vrml() : Specified filename is (null).", | ||
|  |                                 cimg_instance); | ||
|  |   if (is_empty()) | ||
|  |     throw CImgInstanceException(_cimg_instance | ||
|  |                                 "save_vrml() : Empty instance, for file '%s'.", | ||
|  |                                 cimg_instance,filename?filename:"(FILE*)"); | ||
|  | 
 | ||
|  |   // Check that the object we want to save is a 3D object.
 | ||
|  |   CImgList<T> opacities; | ||
|  |   char error_message[1024] = {0}; | ||
|  |   if (!is_object3d(primitives,colors,opacities,true,error_message)) | ||
|  |     throw CImgInstanceException(_cimg_instance | ||
|  |                                 "save_vrml() : Invalid specified 3d object, for file '%s' (%s).", | ||
|  |                                 cimg_instance,filename?filename:"(FILE*)",error_message); | ||
|  |   const CImg<tc> default_color(1,3,1,1,200); | ||
|  | 
 | ||
|  |   // We open the file in which we will save the 3D object.
 | ||
|  |   std::FILE * nfile; | ||
|  |   if(file) nfile = file; | ||
|  |   else nfile = cimg::fopen(filename,"w"); | ||
|  | 
 | ||
|  |   // We use the version 2.0 of VRML to represent the object in UTF8
 | ||
|  |   std::fprintf(nfile,"#VRML V2.0 utf8\n"); | ||
|  | 
 | ||
|  |   // We copy the coordinates of all the points
 | ||
|  |   std::fprintf(nfile,"Shape {\n\tgeometry IndexedFaceSet {\n\t\tcoord Coordinate {\n\t\t\tpoint [\n"); | ||
|  |   cimg_forX(*this,i) | ||
|  |     std::fprintf(nfile,"\t\t\t\t%f %f %f,\n",(float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2))); | ||
|  |   std::fprintf(nfile,"\t\t\t]\n\t\t}\n\t\tcoordIndex [\n"); | ||
|  |   bool sameColor = true; | ||
|  | 
 | ||
|  |   float r = colors[0][0]/255.0f; | ||
|  |   float g = colors[0][1]/255.0f; | ||
|  |   float b = colors[0][2]/255.0f; | ||
|  | 
 | ||
|  |   std::vector<std::string> listColor; | ||
|  |   std::string listColorPerFace(""); | ||
|  |   for(int i=0;i<(int)colors.size();++i) {// Test if the object is composed of only one color
 | ||
|  |     float valR = (colors[i][0])/255.0f; | ||
|  |     float valG = (colors[i][1])/255.0f; | ||
|  |     float valB = (colors[i][2])/255.0f; | ||
|  | 
 | ||
|  |     if (r!=valR || g!=valG || b!=valB) { // If the object has different colors
 | ||
|  |       sameColor = false; | ||
|  |       i = colors.size(); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   cimglist_for(primitives,l) { // For each primitive
 | ||
|  |     const CImg<tc>& color = l<colors.width()?colors[l]:default_color; | ||
|  |     const unsigned int psiz = primitives[l].size(), csiz = color.size(); | ||
|  |     float r = color[0]/255.0f; | ||
|  |     float g, b; | ||
|  |     if (csiz > 1) g = color[1]/255.0f; | ||
|  |     else g = r/255.0f; | ||
|  |     if (csiz > 2) b = color[2]/255.0f; | ||
|  |     else b = g/255.0f; | ||
|  | 
 | ||
|  |     switch (psiz) { | ||
|  |     case 1 : | ||
|  |       std::fprintf(nfile,"\t\t\t%u,-1\n",(unsigned int)primitives(l,0)); | ||
|  |       break; | ||
|  |     case 2 : | ||
|  |       std::fprintf(nfile,"\t\t\t%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,1)); | ||
|  |       break; | ||
|  |     case 3 : | ||
|  |       std::fprintf(nfile,"\t\t\t%u,%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,2), | ||
|  |                    (unsigned int)primitives(l,1)); | ||
|  |       break; | ||
|  |     case 4 : | ||
|  |       std::fprintf(nfile,"\t\t\t%u,%u,%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,3), | ||
|  |                    (unsigned int)primitives(l,2),(unsigned int)primitives(l,1)); | ||
|  |       break; | ||
|  |     case 6 : { | ||
|  |       const unsigned int xt = (unsigned int)primitives(l,2), yt = (unsigned int)primitives(l,3); | ||
|  |       r = color.atXY(xt,yt,0)/255.0f; | ||
|  |       g = (csiz>1?color.atXY(xt,yt,1):r)/255.0f; | ||
|  |       b = (csiz>2?color.atXY(xt,yt,2):g)/255.0f; | ||
|  |       std::fprintf(nfile,"\t\t\t%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,1)); | ||
|  |     } break; | ||
|  |     case 9 : { | ||
|  |       const unsigned int xt = (unsigned int)primitives(l,3), yt = (unsigned int)primitives(l,4); | ||
|  |       r = color.atXY(xt,yt,0)/255.0f; | ||
|  |       g = (csiz>1?color.atXY(xt,yt,1):r)/255.0f; | ||
|  |       b = (csiz>2?color.atXY(xt,yt,2):g)/255.0f; | ||
|  |       std::fprintf(nfile,"\t\t\t%u,%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,2), | ||
|  |                    (unsigned int)primitives(l,1)); | ||
|  |     } break; | ||
|  |     case 12 : { | ||
|  |       const unsigned int xt = (unsigned int)primitives(l,4), yt = (unsigned int)primitives(l,5); | ||
|  |       r = color.atXY(xt,yt,0)/255.0f; | ||
|  |       g = (csiz>1?color.atXY(xt,yt,1):r)/255.0f; | ||
|  |       b = (csiz>2?color.atXY(xt,yt,2):g)/255.0f; | ||
|  |       std::fprintf(nfile,"\t\t\t%u,%u,%u,%u,-1\n",(unsigned int)primitives(l,0),(unsigned int)primitives(l,3), | ||
|  |                    (unsigned int)primitives(l,2),(unsigned int)primitives(l,1)); | ||
|  |     } break; | ||
|  |     } | ||
|  |     if (!sameColor) { // If there are different colors we store on every loop the RGB values into the vector listColor
 | ||
|  |       std::ostringstream oss; | ||
|  |       oss << r << " " << g << " " << b << "\n"; | ||
|  |       if (listColor.size() == 0) { | ||
|  |         listColor.push_back(oss.str()); | ||
|  |         listColorPerFace += "0"; // We store the indice of the color
 | ||
|  |       } | ||
|  |       else { | ||
|  |         std::vector<std::string>::iterator it; | ||
|  |         it = find (listColor.begin(), listColor.end(), oss.str()); | ||
|  |         std::ostringstream oss2; | ||
|  |         if(it==listColor.end()) { | ||
|  |           oss2 << " " << listColor.size(); | ||
|  |           listColorPerFace += oss2.str(); | ||
|  |           listColor.push_back(oss.str()); | ||
|  |         } | ||
|  |         else { | ||
|  |           int n = 0; | ||
|  |           for (std::vector<std::string>::iterator iter = listColor.begin(); iter != it; iter++) ++n; | ||
|  |           oss2 << " " << n; | ||
|  |           listColorPerFace += oss2.str(); | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   std::fprintf(nfile,"\t\t]\n"); | ||
|  | 
 | ||
|  |   if (texturefile) // If we have a texture instead of a color
 | ||
|  |     std::fprintf(nfile,"\n\t}\n\tappearance DEF theTexture Appearance " | ||
|  |                  "{\n\t\ttexture ImageTexture {\n\t\t\turl [\"%s\"]\n\t\t}\n\t}\n}", | ||
|  |                  texturefile); | ||
|  |   else { | ||
|  |     if(!sameColor) { // If there are different colors we add all of them
 | ||
|  |       std::fprintf(nfile,"\tcolorPerVertex FALSE\n\tcolor Color {\n\t\tcolor [\n"); | ||
|  |       while(!listColor.empty()) { | ||
|  |         std::fprintf(nfile,"\t\t\t%s",(listColor.back()).c_str()); | ||
|  |         listColor.pop_back(); | ||
|  |       } | ||
|  |       std::fprintf(nfile,"\t\t]\n\t}\n\tcolorIndex [\n\t\t"); | ||
|  |       std::fprintf(nfile,"%s",listColorPerFace.c_str()); | ||
|  |       std::fprintf(nfile,"\n\t]\n\t}\n}"); | ||
|  |     } | ||
|  |     else { // If there is only one color we add it with the Material node
 | ||
|  |       std::fprintf(nfile,"\t}\n\tappearance Appearance " | ||
|  |                    "{\n\t\tmaterial Material {\n\t\t\tdiffuseColor %f,%f,%f\n\t\t}\n\t}\n}", | ||
|  |                    colors[0][0]/255.0f,colors[0][1]/255.0f,colors[0][2]/255.0f); | ||
|  |     } | ||
|  |   } | ||
|  |   if (!file) cimg::fclose(nfile); | ||
|  |   return *this; | ||
|  | } | ||
|  | 
 | ||
|  | #endif /* cimg_plugin_vrml */
 |