Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

triloader.cpp

Go to the documentation of this file.
00001 /*
00002     Sheep - A Rigid Body Dynamics Engine
00003     Copyright (C) 2001-2004 Francois Beaune
00004     Contact: http://toxicengine.sourceforge.net/
00005 
00006     This file is part of Sheep.
00007 
00008     Sheep is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     Sheep is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License
00019     along with Sheep; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "triloader.h"  // include first
00024 #include "common/misc/progressmonitor.h"
00025 #include "common/misc/stringutils.h"
00026 #include "common/misc/types.h"
00027 
00028 #include <cctype>
00029 #include <IL/il.h>
00030 
00031 //#define VERBOSE
00032 
00033 #ifdef VERBOSE
00034 #include <iostream>
00035 #endif  // VERBOSE
00036 
00037 using namespace sheep;
00038 using namespace std;
00039 
00040 TRILoader::TRILoader() {}
00041 
00042 void TRILoader::Load(const string &filename,
00043                      IMeshBuilder &builder,
00044                      int option_mask /*= DEFAULT_CONFIGURATION_BIT*/,
00045                      ProgressMonitor *progmon /*= 0*/)
00046 {
00047     m_path = StringUtils::GetPath(filename);
00048     m_texture_filename =
00049         StringUtils::RemoveExtension(StringUtils::GetFilename(filename)) + ".png";
00050 
00051     m_geombuilder = builder.GeometryBuilder();
00052     m_matbuilder = builder.MaterialBuilder();
00053 
00054     m_option_mask = option_mask;
00055 
00056     m_progmon = progmon;
00057 
00058     m_comment_ptr = 0;  // no texture coordinates yet
00059 
00060     open_geometry_file(filename);
00061     open_texture_file(m_texture_filename);
00062 
00063     if(m_progmon) {
00064         m_stream.Seek(0, BinaryStream::SeekFromEnd);
00065         m_progmon->StartJob(0, m_stream.Tell());
00066         m_stream.Seek(0, BinaryStream::SeekFromBeginning);
00067     }
00068 
00069     read_geometry_file();
00070 
00071     if(m_progmon)
00072         m_progmon->Done();
00073 
00074     close_texture_file();
00075     close_geometry_file();
00076 }
00077 
00078 void TRILoader::read_error() {
00079     //!\todo Close files and free resources.
00080     throw ReadingException(m_offset);
00081 }
00082 
00083 void TRILoader::open_geometry_file(const string &filename) {
00084     m_stream.Open(filename, BinaryStream::InputStream);
00085 
00086     if(!m_stream.IsOpen())
00087         throw FileNotFoundException(filename);
00088 
00089     m_offset = 0;
00090 }
00091 
00092 void TRILoader::read_geometry_file() {
00093     // Read endian order.
00094 
00095     char endian[2];
00096 
00097     m_stream.Read(&endian[0]);
00098     m_stream.Read(&endian[1]);
00099 
00100     if(!((endian[0] == 'B' || endian[0] == 'L') && endian[1] == 'E'))
00101         read_error();
00102 
00103     if(endian[0] == 'B')
00104         m_stream.SetEndianness(BinaryStream::BigEndian);
00105     else m_stream.SetEndianness(BinaryStream::LittleEndian);
00106 
00107     // Read the number of vertices.
00108     int32 nvertices;
00109     m_stream.Read(&nvertices);
00110 
00111     // Read the number of faces.
00112     int32 nfaces;
00113     m_stream.Read(&nfaces);
00114 
00115     // Skip reserved bytes.
00116     for(int i = 0; i < 4; ++i) {
00117         char dummy;
00118         m_stream.Read(&dummy);
00119     }
00120 
00121     m_geombuilder->BeginSubMesh("");
00122 
00123     // Read vertices.
00124     for(int i = 0; i < nvertices; ++i) {
00125         float32 x, y, z;
00126         m_stream.Read(&x);
00127         m_stream.Read(&y);
00128         m_stream.Read(&z);
00129 
00130         m_vertex_id[i] = m_geombuilder->AppendVertex(Vector3(x, y, z));
00131 
00132         if(m_progmon) {
00133             //!\todo Fine tune the number of items to read between progress updates.
00134             if((i & 4095) == 0)
00135                 m_progmon->SetJobProgress(m_stream.Tell());
00136         }
00137     }
00138 
00139     // Read faces.
00140     for(int i = 0; i < nfaces; ++i) {
00141         uint32 v0, v1, v2;
00142         m_stream.Read(&v0);
00143         m_stream.Read(&v1);
00144         m_stream.Read(&v2);
00145 
00146         IMeshBuilder::FeatureId vertex_id[3];
00147         vertex_id[0] = m_vertex_id[v0];
00148         vertex_id[1] = m_vertex_id[v1];
00149         vertex_id[2] = m_vertex_id[v2];
00150 
00151         const IMeshBuilder::FeatureId face_id = m_geombuilder->AppendFace(3, vertex_id);
00152 
00153         if(m_comment_ptr) {
00154             IMeshBuilder::FeatureId texcood_id[3];
00155 
00156             for(int i = 0; i < 3; ++i) {
00157                 const int u = strtol(m_comment_ptr, &m_comment_ptr, 10);
00158                 const int v = strtol(m_comment_ptr, &m_comment_ptr, 10);
00159 
00160                 Vector2 vt;
00161                 vt.m_x = (static_cast<Real>(u) + 0.5) / m_texture_width;
00162                 vt.m_y = (static_cast<Real>(v) + 0.5) / m_texture_height;
00163 
00164                 texcood_id[i] = m_geombuilder->AppendTexCoord(vt);
00165             }
00166 
00167             m_geombuilder->SetFaceTexCoords(face_id, 3, texcood_id);
00168         }
00169 
00170         if(m_progmon) {
00171             //!\todo Fine tune the number of items to read between progress updates.
00172             if((i & 4095) == 0)
00173                 m_progmon->SetJobProgress(m_stream.Tell());
00174         }
00175     }
00176 
00177     if(m_matbuilder && m_comment_ptr) {
00178         ILuint image_id;
00179 
00180         ilGenImages(1, &image_id);
00181         ilBindImage(image_id);
00182 
00183         if(TryLoadingImage(m_path, m_texture_filename)) {
00184             const int w = ilGetInteger(IL_IMAGE_WIDTH);
00185             const int h = ilGetInteger(IL_IMAGE_HEIGHT);
00186 
00187             unsigned char *texels = new unsigned char[w * h * 3];
00188 
00189             ilCopyPixels(0, 0, 0, w, h, 1, IL_RGB, IL_UNSIGNED_BYTE, texels);
00190             ilDeleteImages(1, &image_id);
00191 
00192             assert(m_matbuilder);
00193 
00194             const IMeshBuilder::FeatureId material_id = m_matbuilder->BeginMaterial("");
00195             m_matbuilder->SetTexture(w, h, texels);
00196             m_matbuilder->EndMaterial();
00197 
00198             m_geombuilder->SetMaterial(material_id);
00199         } else {
00200             //!\todo Close files and free resources.
00201 
00202             // There is no distinction between a missing texture file
00203             // and an invalid texture file.
00204             if(m_option_mask & STOP_ON_MISSING_FILE_BIT)
00205                 throw FileNotFoundException(m_texture_filename);
00206 
00207             // Ignore invalid or missing texture file.
00208         }
00209     }
00210 
00211     m_geombuilder->EndSubMesh();
00212 }
00213 
00214 void TRILoader::close_geometry_file() {
00215     m_stream.Close();
00216 }
00217 
00218 void TRILoader::open_texture_file(const string &filename) {
00219     const int PNG_BYTES_TO_CHECK = 8;
00220     png_byte header[PNG_BYTES_TO_CHECK];
00221 
00222     FILE *f = TryOpeningFile(m_path, filename, "rb");
00223 
00224     if(!f) {
00225         if(m_option_mask & STOP_ON_MISSING_FILE_BIT) {
00226             //!\todo Close files and free resources.
00227             throw FileNotFoundException(filename);
00228         } else return;  // ignore missing material file
00229     }
00230 
00231     if(fread(header, 1, PNG_BYTES_TO_CHECK, f) < PNG_BYTES_TO_CHECK)
00232         read_error();
00233 
00234     if(png_sig_cmp(header, 0, PNG_BYTES_TO_CHECK))
00235         read_error();
00236 
00237     m_png_ptr = png_create_read_struct(
00238         PNG_LIBPNG_VER_STRING,
00239         NULL,
00240         NULL,
00241         NULL);
00242 
00243     if(!m_png_ptr) {
00244         fclose(f);
00245         read_error();
00246     }
00247 
00248     m_info_ptr = png_create_info_struct(m_png_ptr);
00249 
00250     if(!m_info_ptr) {
00251         png_destroy_read_struct(
00252             &m_png_ptr,
00253             NULL,
00254             NULL);
00255         fclose(f);
00256         read_error();
00257     }
00258 
00259     m_end_info = png_create_info_struct(m_png_ptr);
00260 
00261     if(!m_end_info) {
00262         png_destroy_read_struct(
00263             &m_png_ptr,
00264             &m_info_ptr,
00265             NULL);
00266         fclose(f);
00267         read_error();
00268     }
00269 
00270     png_init_io(m_png_ptr, f);
00271     png_set_sig_bytes(m_png_ptr, PNG_BYTES_TO_CHECK);
00272     png_read_info(m_png_ptr, m_info_ptr);
00273 
00274     fclose(f);
00275 
00276     m_texture_width = png_get_image_width(m_png_ptr, m_info_ptr);
00277     m_texture_height = png_get_image_height(m_png_ptr, m_info_ptr);
00278 
00279     png_textp text_ptr;
00280     int ncomments;
00281 
00282     png_get_text(m_png_ptr, m_info_ptr, &text_ptr, &ncomments);
00283 
00284     if(ncomments < 1) {
00285         png_destroy_read_struct(
00286             &m_png_ptr,
00287             &m_info_ptr,
00288             &m_end_info);
00289         read_error();
00290     }
00291 
00292     if(strcmp(text_ptr[0].key, "uv") != 0) {
00293         png_destroy_read_struct(
00294             &m_png_ptr,
00295             &m_info_ptr,
00296             &m_end_info);
00297         read_error();
00298     }
00299 
00300     m_comment_ptr = text_ptr[0].text;
00301     assert(m_comment_ptr);
00302 }
00303 
00304 void TRILoader::close_texture_file() {
00305     if(m_comment_ptr) {
00306         png_destroy_read_struct(
00307             &m_png_ptr,
00308             &m_info_ptr,
00309             &m_end_info);
00310         m_comment_ptr = 0;
00311     }
00312 }

Generated on Tue May 11 01:31:52 2004 for toxic by doxygen 1.3.6