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

LWLayer.cpp

Go to the documentation of this file.
00001 
00002 /*
00003     TEDDY - General graphics application library
00004     Copyright (C) 1999-2002  Timo Suoranta
00005     tksuoran@cc.helsinki.fi
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2.1 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021     $Id: LWLayer.cpp,v 1.7 2002/02/16 12:41:39 tksuoran Exp $
00022 */
00023 
00024 
00025 #include "Teddy/TeddyConfig.h"
00026 #if defined( TEDDY_INCLUDE_LW_SCENE )
00027 
00028 
00029 #include "Teddy/Imports/LWClip.h"
00030 #include "Teddy/Imports/LWEnvelope.h"
00031 #include "Teddy/Imports/LWFile.h"
00032 #include "Teddy/Imports/LWLayer.h"
00033 #include "Teddy/Imports/LWModel.h"
00034 #include "Teddy/Imports/LWSurface.h"
00035 #include "Teddy/Models/Model.h"
00036 #include "Teddy/Models/Face.h"
00037 #include "Teddy/Models/Geometry.h"
00038 #include "Teddy/Models/Vertex.h"
00039 #include "Teddy/SysSupport/Exception.h"
00040 #include "Teddy/SysSupport/Messages.h"
00041 #include "Teddy/SysSupport/StdMaths.h"
00042 #include "Teddy/SysSupport/StdIO.h"
00043 
00044 #ifndef SWIG
00045 #include <algorithm>
00046 using namespace std;
00047 #endif
00048 using namespace Teddy::SysSupport;
00049 
00050 
00051 #define USE_LIGHTWAVE_SCALE   1
00052 #define SCALE                 1
00053 
00054 
00055 namespace Teddy   {
00056 namespace Imports {
00057 
00058 
00060 LWLayer::LWLayer( LWModel *model, const std::string &name, U2 flags, Vector pivot, int parent )
00061 :
00062     Model( name )
00063 {
00064     this->f            = model->getFile();
00065     this->model        = model;
00066     this->pivot        = pivot;
00067     this->flags        = flags;
00068     this->parent_layer = parent;
00069     num_vertices       = 0;
00070     num_faces          = 0;
00071     num_surfaces       = 0;
00072     num_envelopes      = 0;
00073     num_clips          = 0;
00074     current_surface    = 0;
00075     bbox_min           = Vector(0,0,0);
00076     bbox_max           = Vector(0,0,0); 
00077 
00078     dmsg( M_LWO, "LWLayer constructor" );
00079 }
00080 
00081 void LWLayer::processLayer(){
00082     //  Read max file len
00083     while( f->bytesRead()-8 < f->getLen() ){
00084         dmsg( M_LWO, "calling processChunk()" );
00085         bool next_layer = processChunk();
00086         if( next_layer == true ){
00087             break;
00088         }
00089         
00090     }
00091 
00092     //  Post processing - smooth vertices
00093 
00094     list<Model*>::iterator m_it;
00095     m_it = children.begin();
00096     while( m_it != children.end() ){
00097         Model    *model = *m_it;
00098         Material *mat   = model->getMaterial();
00099         //debug_msg( "Surface %s with max smoothing angle % 6.2f", mat->getName(), degs(mat->getMaxSmoothingAngle()) );
00100         model->getGeometry()->smooth(  mat->getMaxSmoothingAngle()  );
00101         m_it++;
00102     }
00103     
00104 }
00105 
00106 
00108 /*virtual*/ LWLayer::~LWLayer(){
00109     //  FIX
00110 }
00111 
00112 
00114 bool LWLayer::processChunk(){
00115     dmsg( M_LWO, "processChunk() @ %lu", f->bytesRead() );
00116     bool next_layer = false;
00117     U4   chunk_id     = f->read_ID4();
00118     U4   chunk_length = f->read_U4();
00119 
00120     dmsg( M_LWO,
00121         "%s::%s (%lu) (%lu bytes)",
00122         did( f->getType() ),
00123         did( chunk_id ),
00124         chunk_id,
00125         chunk_length
00126     );
00127 
00128     f->pushDomain( chunk_length );
00129 
00130     switch( f->getType() ){
00131     case ID_LWOB:
00132     case ID_LWLO:
00133         switch( chunk_id ){
00134         case ID_PNTS: pointList  (); break;
00135         case ID_SRFS: surfaceList(); break;
00136         case ID_POLS: faceList   (); break;
00137         case ID_CRVS: curveList  (); break;
00138         case ID_PCHS: patchList  (); break;
00139         case ID_SURF: surface_sc (); break;
00140         default: break;
00141         }
00142         break;
00143     case ID_LWO2:
00144         switch( chunk_id ){
00145         case ID_PNTS: pointList                (); break;
00146         case ID_VMAP: vertexMapping_ID4_U2_S0_d(); break;
00147         case ID_POLS: polygonList              (); break;
00148         case ID_TAGS: model->tags_d            (); break;
00149         case ID_PTAG: polygonTags_ID4_d        (); break;
00150         case ID_ENVL: envelope_U4_sc           (); break;
00151         case ID_CLIP: clip_U4_sc               (); break;
00152         case ID_SURF: surf_S0_S0_sc            (); break;
00153         case ID_BBOX: boundingBox_VEC12_VEC12  (); break;
00154         case ID_DESC: descriptionLine_S0       (); break;
00155         case ID_TEXT: comments_S0              (); break;
00156         case ID_ICON: thumbnail_U2_U2_d        (); break;
00157         default: break;
00158         }
00159         break;
00160     default: break;
00161     }
00162 
00163     if( chunk_id == ID_LAYR ){
00164         next_layer = true;
00165         switch( f->getType() ){
00166         case ID_LWLO: model->layer_U2_U2_S0         (); break;  //  Actually LWLO only
00167         case ID_LWO2: model->layer_U2_U2_VEC12_S0_U2(); break;
00168         default: break;
00169         }
00170     }else{
00171 
00172     f->popDomain( true );
00173 
00174     }
00175 
00176     return next_layer;
00177 
00178 }
00179 
00180 
00181 LWModel *LWLayer::getModel(){
00182     return model;
00183 }
00184 
00185 
00186 LWClip *LWLayer::getClip( VX clip_index ){
00187     U4_to_LWClip::iterator  c_it = clips.find( clip_index );
00188     LWClip                 *clip = NULL;
00189 
00190     if( c_it != clips.end() ){
00191         clip = (*c_it).second;
00192     }
00193     return clip;
00194 }
00195 
00196 
00219 void LWLayer::pointList(){
00220     Vertex *vertex;
00221     U4      current_v_index = 0;
00222     U4      i;
00223 
00224     num_vertices = f->domainLeft()/12;
00225 
00226     for( i=0; i<num_vertices; i++ ){
00227         if( f->domainLeft()<3*4 ){
00228             emsg( M_LWO, "Not enough floats found in chunk for point" );
00229             break;
00230         }
00231 
00232         Vector vec = f->read_VEC12();
00233         vec += pivot;  //  FIX
00234         vec[2] = -vec[2];
00235 
00236         vertex = new Vertex( vec );
00237 
00238 #       ifdef USE_LIGHTWAVE_SCALE
00239         *vertex *= SCALE; 
00240 #       endif
00241 
00242         //vertex->setNormal( Vector(0,0,0) );
00243         this->vertices.insert( std::make_pair(current_v_index,vertex) );
00244         current_v_index++;
00245     }
00246     dmsg( M_LWO, "pointList() done through %d vertices", i-1 );
00247 }
00248 
00249 
00250 /*
00251     LWOB SRFS { surf-name[S0] * } 
00252     
00253     This chunk contains a list of the names of all the surfaces in an object. 
00254     Each surface name appears as a null-terminated character string. If the 
00255     length of the string (including the null) is odd, an extra null byte is 
00256     added. Surface names should be read from the file until as many bytes as the 
00257     chunk size specifies have been read. 
00258     
00259     In LightWave 3D terminology, a "surface" is defined as a named set of 
00260     shading attributes. Each polygon contains a reference to the surface used to 
00261     color the polygon. The names as listed in the SRFS chunk are numbered in the 
00262     order they occur, starting from 1, and this index is used by polygons to 
00263     define their surface. The SRFS chunk must be before the POLS, CRVS, and PCHS 
00264     chunks in the file.
00265 */
00266 void LWLayer::surfaceList(){
00267     std::string  surface_name;
00268     LWSurface   *surface;
00269     Model       *model;
00270     char        *buffer;
00271 
00272     while( f->domainLeft() > 0 ){
00273         num_surfaces++;
00274         surface_name = f->read_S0();
00275         model        = new Model    ( surface_name );
00276         surface      = new LWSurface( this, model, surface_name );
00277         add( model );
00278         buffer = new char[16];
00279         sprintf( buffer, "SURFACE %d", (int)(num_surfaces) );
00280         surfaces.insert( std::make_pair(surface_name,surface) );
00281         models  .insert( std::make_pair(buffer,      model  ) );
00282         model->setMaterial( surface );  // ? FIX 
00283     }
00284 }
00285 
00286 
00321 void LWLayer::faceList(){
00322     Face   *face   = NULL;
00323     Vertex *vertex = NULL;
00324     Model  *model  = NULL;
00325     U4      num_vertices;
00326     U4      surface_index;
00327     U4      vertex_index;
00328     U4      i;
00329     bool    good;
00330     U4      bad_count   = 0;
00331     U4      point_count = 0;
00332     U4      line_count  = 0;
00333 
00334     while( f->domainLeft() > 0 ){
00335         num_vertices = f->read_U2();
00336 
00337         if( num_vertices<3 ){  //  FIX
00338             bad_count++;
00339             switch( num_vertices ){
00340             case 0: bad_count  ++; emsg( M_LWO, "Bad polygon - 0 vertices" ); break;
00341             case 1: bad_count  ++; point_count++; break;
00342             case 2: bad_count  ++; line_count ++; break;
00343             }
00344             for( i=0; i<num_vertices; i++ ){
00345                 vertex_index = f->read_U2();
00346             }
00347             f->read_U2();
00348             continue;
00349         }
00350 
00351         face = new Face();
00352         good = true;
00353 
00354         for( i=0; i<num_vertices; i++ ){
00355             if( f->domainLeft()<2 ){
00356                 emsg( M_LWO, "Not enough shorts found in chunk" );
00357                 good = false;
00358                 break;
00359             }
00360             vertex_index = f->read_U2();
00361 
00362             if( (vertex_index > this->num_vertices) ){
00363                 emsg( M_LWO, "Not understood as vertex index %ld > %ld", vertex_index, num_vertices );
00364                 good = false;
00365                 break;
00366             }
00367 
00368             //  Find vertex for this index and insert to face
00369             U4_to_Vertex::iterator v_it = vertices.find( vertex_index );
00370             if( v_it!=vertices.end() ){
00371                 vertex = (*v_it).second;
00372                 if( vertex != NULL ){
00373                     face->add( vertex );
00374                 }else{
00375                     emsg( M_LWO, "Vertex %ld pointer is NULL", vertex_index );
00376                     good = false;
00377                 }
00378             }else{
00379                 emsg( M_LWO, "Vertex %ld not found", vertex_index );
00380                 good = false;
00381             }
00382 
00383         }
00384 
00385         if( good ){
00386             surface_index = f->read_U2();
00387             if( surface_index > num_surfaces ){
00388                 bad_count++;
00389                 delete face;
00390                 continue;
00391                 //  FIX error
00392             }
00393 
00394             string_to_Model::iterator  m_it;
00395             char                       surface_name[16];
00396 
00397             sprintf( surface_name, "SURFACE %d", (int)(surface_index) );
00398 
00399             m_it = models.find( surface_name );
00400             if( m_it!=models.end() ){
00401                 model = (*m_it).second;
00402                 if( model==NULL ){
00403                     emsg( M_LWO, "Model-surface %s found as NULL", surface_name );
00404                     bad_count++;
00405                     delete face;
00406                     continue;
00407                 }
00408                 face->makeNormal();
00409                 model->add( face );
00410                 faces.insert( std::make_pair(num_faces,face) );
00411                 num_faces++;
00412             }else{
00413                 emsg( M_LWO, "Model-surface %s not found", surface_name );
00414                 bad_count++;
00415                 delete face;
00416                 continue;
00417             }
00418         }else{
00419             bad_count++;
00420             delete face;
00421         }
00422     }
00423 
00424     if( bad_count > 0 ){
00425         dmsg( M_LWO, "%ld good polygons read %ld bad polygons skipped", num_faces, bad_count );
00426         if( point_count>0 ){
00427             dmsg( M_LWO, "%ld points, not yet supported", point_count );
00428         }
00429         if( line_count>0 ){
00430             dmsg( M_LWO, "%ld lines, not yet supported", line_count );
00431         }
00432     }
00433 }
00434 
00435 
00437 void LWLayer::curveList(){
00438     //  FIX not implemented
00439 }
00440 
00441 
00443 void LWLayer::patchList(){
00444     //  FIX not implemented
00445 }
00446 
00447 
00460 void LWLayer::surface_sc(){
00461     string_to_LWSurface::iterator  s_it;
00462     std::string                    surface_name;
00463     LWSurface                     *surface; 
00464 
00465     surface_name = f->read_S0();
00466 
00467     s_it = surfaces.find( surface_name );
00468     if( s_it != surfaces.end() ){
00469         surface = (*s_it).second;
00470         if( surface == NULL ){
00471             emsg( M_LWO, "NULL surface %s in surfacelist", surface_name.c_str() );
00472             return;
00473         }
00474     }else{
00475         surface = new LWSurface( this, this, surface_name );
00476     }
00477     
00478     while( f->domainLeft() > 0 ){
00479         surface->processSubChunk();
00480     }
00481     surface->endSurface();
00482 }
00483 
00484 
00500 void LWLayer::vertexMapping_ID4_U2_S0_d(){
00501     ID4         vmap_type = f->read_ID4();
00502     U2          vmap_dim  = f->read_U2();
00503     std::string vmap_name = f->read_S0();
00504 
00505     dmsg( M_LWO, "%s Vertex map %s", did(vmap_type), vmap_name.c_str() );
00506 
00507     while( f->domainLeft() > 0 ){
00508         VX vertex_id = f->read_VX();
00509         for( int i=0; i<vmap_dim; i++ ){
00510             F4 value = f->read_F4();
00511         }
00512         switch( vmap_type ){
00513         case ID_TXUV:
00514         case ID_MNUW:
00515         case ID_MORF:
00516         case ID_SPOT:
00517         case ID_RGBA:
00518         default:
00519             break;
00520         }
00521 
00522     }
00523 
00524 }
00525 
00526 
00552 void LWLayer::polygonList(){
00553     Face   *face;
00554     Vertex *vertex;
00555     ID4     polygons_type = f->read_ID4();
00556     U4      vertex_index;
00557     int     i;
00558     bool    good;
00559     int     bad_count   = 0;
00560     int     point_count = 0;
00561     int     line_count  = 0;
00562 
00563     while( f->domainLeft() > 0 ){
00564         U2 data    = f->read_U2();
00565         U2 numvert = data & 0x03ff;
00566         U2 flags   = (data & ~numvert) >> 10;
00567 
00568         if( numvert<3 ){  //  FIX
00569             bad_count++;
00570             switch( num_vertices ){
00571             case 0: bad_count++; emsg( M_LWO, "Bad polygon - 0 vertices" ); break;
00572             case 1: bad_count++; point_count++; break;
00573             case 2: bad_count++; line_count++;  break;
00574             }
00575             for( i=0; i<numvert; i++ ){
00576                 vertex_index = f->read_VX();
00577             }
00578             continue;
00579         }
00580 
00581         face = new Face();
00582         good = true;
00583 
00584         for( i=0; i<numvert; i++ ){
00585 
00586             if( f->domainLeft()<2 ){
00587                 emsg( M_LWO, "Not enough bytes left in chunk" );
00588                 good = false;
00589                 break;
00590             }
00591 
00592             vertex_index = f->read_VX();
00593             if( vertex_index > this->num_vertices ){
00594                 emsg( M_LWO, "Not understood as vertex index %ld > %ld", vertex_index, num_vertices );
00595                 good = false;
00596                 break;
00597             }
00598 
00599             U4_to_Vertex::iterator v_it = vertices.find( vertex_index);
00600             if( v_it!=vertices.end() ){
00601                 vertex = (*v_it).second;
00602                 if( vertex != NULL ){
00603                     face->add( vertex );
00604                 }else{
00605                     emsg( M_LWO, "Vertex %ld pointer is NULL", vertex_index );
00606                     good = false;
00607                 }
00608             }else{
00609                 emsg( M_LWO, "Vertex %ld not found", vertex_index );
00610                 good = false;
00611             }
00612         }
00613         if( good ){
00614             face->makeNormal();
00615             faces.insert( pair<U4,Face*>(num_faces,face) );
00616             num_faces++;
00617         }else{
00618             bad_count++;
00619             delete face;
00620         }
00621 
00622 /*
00623         switch( polygons_type ){
00624             case ID_FACE: break;
00625             case ID_CURV: break;
00626             case ID_PACH: break;
00627             default:
00628                 break;
00629         }
00630 */
00631     }
00632 
00633     if( bad_count > 0 ){
00634         dmsg( M_LWO, "%ld good polygons read %d bad polygons skipped", num_faces, bad_count );
00635         if( point_count>0 ){
00636             dmsg( M_LWO, "%d points, not yet supported", point_count );
00637         }
00638         if( line_count>0 ){
00639             dmsg( M_LWO, "%d lines, not yet supported", line_count );
00640         }
00641     }
00642 }
00643 
00644 
00676 void LWLayer::polygonTags_ID4_d(){
00677     string_to_LWSurface::iterator s_it;
00678     string_to_Model    ::iterator m_it;
00679     U4_to_Face         ::iterator f_it;
00680     
00681     Face        *face;
00682     LWSurface   *surface;
00683     LWModel     *root_model;
00684     Model       *model;
00685     VX           polygon_index;
00686     U4           tag_index;
00687     ID4          tag_type;
00688     std::string  tag_value;
00689 
00690     root_model = this->model;
00691     if( root_model == NULL ){
00692         emsg( M_LWO, "Can not access root Model" );
00693         return;
00694     }
00695 
00696     if( (f->getOptions() & LWFILE_OPTION_SKIP_MATERIAL_M) == LWFILE_OPTION_SKIP_MATERIAL_M ){
00697         surface = new LWSurface( this, this, "skipped materials" );
00698         model   = this;
00699         model->setMaterial( surface );  //  FIX
00700     }
00701 
00702 
00703     tag_type = f->read_ID4();
00704 
00705     while( f->domainLeft() > 0 ){
00706 
00707         polygon_index = f->read_VX();
00708         tag_index     = f->read_U2();
00709         tag_value     = root_model->getTag( tag_index );
00710 
00711         switch( tag_type ){
00712         case ID_SURF:
00713             f_it = faces   .find( polygon_index );
00714             s_it = surfaces.find( tag_value     );
00715             m_it = models  .find( tag_value     );
00716 
00717             //  We absolutely need the face to be added
00718             if( f_it != faces.end() ){
00719                 face = (*f_it).second;
00720                 if( face == NULL ){
00721                     emsg( M_LWO, "FACE FOUND AS NULL" );
00722                     break;
00723                 }
00724             }else{
00725                 emsg( M_LWO, "FACE NOT FOUND" );
00726                 break;
00727             }
00728 
00729             //  If first polygon to be added to the surface,
00730             //  then the surface has not been created yet.
00731             if( !((f->getOptions() & LWFILE_OPTION_SKIP_MATERIAL_M) == LWFILE_OPTION_SKIP_MATERIAL_M) ){
00732                 if( s_it == surfaces.end() ){
00733                     surface = new LWSurface( this, NULL, tag_value );
00734                     surfaces.insert( std::make_pair(tag_value,surface) );
00735                 }else{
00736                     surface = (*s_it).second;
00737                 }
00738 
00739                 //  Find mesh, create new if needed
00740                 if( m_it == models.end() ){
00741                     model = new Model( tag_value );
00742                     models.insert( std::make_pair(tag_value,model) );
00743                     model->setMaterial( surface );  // FIX
00744                     this->add( model );  // == submeshes.push_back( mesh );
00745                 }else{
00746                     model = (*m_it).second;
00747                 }
00748 
00749                 //  Connection needed for texture coordinates
00750                 surface->setModel( model );
00751             }
00752             model->add( face );
00753 
00754             break;
00755 
00756         default:
00757             dmsg( M_LWO, "UNKNOWN TAG" );
00758             break;
00759         }  //  switch( tag_type );
00760     }  //  while( f->domainLeft() > 0 )
00761 }
00762 
00763 
00779 void LWLayer::envelope_U4_sc(){
00780     U4          envelope_index = f->read_U4();
00781     LWEnvelope *envelope       = new LWEnvelope( f );
00782 
00783     envelopes.insert( make_pair(num_envelopes,envelope) );  //  pair<U4,LWEnvelope*>(num_envelopes,envelope)
00784     num_envelopes++;
00785     while( f->domainLeft() > 0 ){
00786         envelope->processEnvelope();
00787     }
00788 }
00789 
00790 
00803 void LWLayer::clip_U4_sc(){
00804     U4      clip_index = f->read_U4();
00805     LWClip *clip       = new LWClip( f );
00806 
00807     if( clip_index >= 0x1000000 ){
00808         emsg( M_LWO, "Clip index not below 0x1000000" );
00809     }
00810 
00811     clips.insert( make_pair(clip_index,clip) );
00812     num_clips++;
00813     while( f->domainLeft() > 0 ){
00814         clip->processClip();
00815     }
00816 }
00817 
00818 
00833 void LWLayer::surf_S0_S0_sc(){
00834     string_to_LWSurface::iterator  s_it;
00835     std::string                    surface_name;
00836     std::string                    surface_source;
00837     LWSurface                     *surface; 
00838 
00839     surface_name   = f->read_S0();
00840     surface_source = f->read_S0();
00841 
00842     s_it = surfaces.find( surface_name );
00843     if( s_it != surfaces.end() ){
00844         surface = (*s_it).second;
00845         if( surface == NULL ){
00846             emsg( M_LWO, "NULL surface %s in surfacelist", surface_name.c_str() );
00847             return;
00848         }
00849     }else{
00850         dmsg( M_LWO, "New SURF" );
00851         surface = new LWSurface( this, NULL, surface_name.c_str() );
00852     }
00853     
00854     if( surface_source.length() > 0 ){
00855         dmsg( M_LWO, "LW Object loader: No material inheritance yet" );
00856         //  FIX copy material properties
00857     }
00858     while( f->domainLeft() > 0 ){
00859         surface->processSubChunk();
00860     }
00861     surface->endSurface();
00862 }
00863 
00864 
00874 void LWLayer::boundingBox_VEC12_VEC12(){
00875     bbox_min = f->read_VEC12();
00876     bbox_max = f->read_VEC12();
00877 }
00878 
00879 
00891 void LWLayer::descriptionLine_S0(){
00892     description_line = f->read_S0();
00893 }
00894 
00895 
00905 void LWLayer::comments_S0(){
00906     commentary_text = f->read_S0();
00907 }
00908 
00909 
00923 void LWLayer::thumbnail_U2_U2_d(){
00924     U2 encoding = f->read_U2();
00925     U2 width    = f->read_U2();
00926 
00927     if( encoding != 0 ){
00928         dmsg( M_LWO, "Unknown thumbnail encoding" );
00929         return;
00930     }
00931 
00932     while( f->domainLeft() > 0 ){
00933         for( int x=0; x<width; x++ ){
00934             U1 red   = f->read_U1();
00935             U1 green = f->read_U1();
00936             U1 blue  = f->read_U1();
00937             //  FIX store data to texture
00938         }
00939     }
00940 }
00941 
00942 
00943 };  //  namespace Imports
00944 };  //  namespace Teddy
00945 
00946 
00947 #endif  //  TEDDY_INCLUDE_LW_SCENE
00948