diff --git a/src/osgPlugins/lwo/Lwo2.cpp b/src/osgPlugins/lwo/Lwo2.cpp index 3de9b4c85..95c5824df 100644 --- a/src/osgPlugins/lwo/Lwo2.cpp +++ b/src/osgPlugins/lwo/Lwo2.cpp @@ -41,7 +41,6 @@ Lwo2::Lwo2(): _current_layer(0), - _geode(0), _successfully_read(false) { } @@ -83,28 +82,26 @@ Lwo2::ReadFile( const string& filename ) } else { - notify(INFO) << "Detected EA-IFF85 format" << std::endl; + notify(NOTICE) << "Detected EA-IFF85 format" << std::endl; } unsigned long form_size = _read_long(); - notify(DEBUG_INFO) << "Form size: " << form_size << std::endl; + notify(INFO) << "Form size: " << form_size << std::endl; // checking LWO2 format // http://www.lightwave3d.com/developer/75lwsdk/docs/filefmts/lwo2.html if (_read_long() != tag_LWO2) { unsigned long make_id(const char*); - notify(DEBUG_INFO) << "File '" << filename << "' is not LWO2 format file." << std::endl; + notify(NOTICE) << "File '" << filename << "' is not LWO2 format file." << std::endl; _fin.close(); return false; } else { - notify(INFO) << "Detected LWO2 format" << std::endl; + notify(NOTICE) << "Detected LWO2 format" << std::endl; } - _geode = osgNew osg::Geode(); - unsigned long read_bytes = 4; unsigned long current_tag_name; unsigned long current_tag_size; @@ -119,43 +116,43 @@ Lwo2::ReadFile( const string& filename ) if (current_tag_name == tag_TAGS) { - _read_tag_strings(current_tag_size); + _read_tag_strings(current_tag_size); } else if (current_tag_name == tag_LAYR) { - _read_layer(current_tag_size); + _read_layer(current_tag_size); } else if (current_tag_name == tag_PNTS) { - _read_points(current_tag_size); + _read_points(current_tag_size); } else if (current_tag_name == tag_VMAP) { - _read_vertex_mapping(current_tag_size); + _read_vertex_mapping(current_tag_size); } else if (current_tag_name == tag_VMAD) { - _read_polygons_mapping(current_tag_size); + _read_polygons_mapping(current_tag_size); } else if (current_tag_name == tag_POLS) { - _read_polygons(current_tag_size); + _read_polygons(current_tag_size); } else if (current_tag_name == tag_PTAG) { - _read_polygon_tag_mapping(current_tag_size); + _read_polygon_tag_mapping(current_tag_size); } else if (current_tag_name == tag_CLIP) { - _read_image_definition(current_tag_size); + _read_image_definition(current_tag_size); } else if (current_tag_name == tag_SURF) { - _read_surface(current_tag_size); + _read_surface(current_tag_size); } else { - _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); + _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); } } @@ -224,23 +221,23 @@ Lwo2::_read_string(string& str) void Lwo2::_print_tag(unsigned int tag, unsigned int size) { notify(DEBUG_INFO) << "Found tag " - << char(tag >> 24) - << char(tag >> 16) - << char(tag >> 8) - << char(tag) - << " size " << size << " bytes" - << std::endl; + << char(tag >> 24) + << char(tag >> 16) + << char(tag >> 8) + << char(tag) + << " size " << size << " bytes" + << std::endl; } // print 4-char type void Lwo2::_print_type(unsigned int type) { notify(DEBUG_INFO) << " type \t" - << char(type >> 24) - << char(type >> 16) - << char(type >> 8) - << char(type) - << std::endl; + << char(type >> 24) + << char(type >> 16) + << char(type >> 8) + << char(type) + << std::endl; } // read TAGS info @@ -302,51 +299,16 @@ Lwo2::_read_points(unsigned long size) while (count--) { - float x = _read_float(); - float y = _read_float(); - float z = _read_float(); - _current_layer->_points.push_back(Vec3(x, y,z)); + PointData point; + + float x = _read_float(); + float y = _read_float(); + float z = _read_float(); + point.coord = Vec3(x, y, z); + _current_layer->_points.push_back(point); } } -// read POLS info - -void -Lwo2::_read_polygons(unsigned long size) -{ - unsigned int type = _read_long(); - size -= 4; - - _print_type(type); - - if (type == tag_FACE) - { - unsigned short vertex_count; - - while (size > 0) - { - vertex_count = _read_short() & 0x03FF; - size -= 2; - - PointsList* points_list = osgNew PointsList; - _current_layer->_polygons.push_back(points_list); - - while (vertex_count--) - { - points_list->push_back(_read_short()); - size -= 2; - } - } - } - else - { - - // not recognized yet - notify(DEBUG_INFO) << " skipping..." << std::endl; - _fin.seekg(size + size % 2, ios::cur); - } -} - // read VMAP info void @@ -370,18 +332,100 @@ Lwo2::_read_vertex_mapping(unsigned long size) if (type == tag_TXUV && dimension == 2) { int count = size / 10; - _current_layer->_points_map.resize(count); - - short n; + unsigned short n; float u; float v; while (count--) - { - n = _read_short(); - u = _read_float(); - v = _read_float(); - _current_layer->_points_map[n].set(u, v); - } + { + n = _read_short(); + u = _read_float(); + v = _read_float(); + + // point coords must be read previously + if (n < _current_layer->_points.size()) + { + _current_layer->_points[n].texcoord = Vec2(u, v); + } + } + } + else + { + + // not recognized yet + notify(DEBUG_INFO) << " skipping..." << std::endl; + _fin.seekg(size + size % 2, ios::cur); + } +} + +// read POLS info + +void +Lwo2::_read_polygons(unsigned long size) +{ + unsigned int type = _read_long(); + size -= 4; + + _print_type(type); + + if (type == tag_FACE) + { + unsigned short vertex_count; + + while (size > 0) + { + PointData point; + vertex_count = _read_short() & 0x03FF; + size -= 2; + + PointsList points_list; + + while (vertex_count--) + { + unsigned short point_index = _read_short(); + + point = _current_layer->_points[point_index]; + point.point_index = point_index; + + points_list.push_back(point); + size -= 2; + } + + _current_layer->_polygons.push_back(points_list); + } + } + else + { + + // not recognized yet + notify(DEBUG_INFO) << " skipping..." << std::endl; + _fin.seekg(size + size % 2, ios::cur); + } +} + +// read PTAG info + +void +Lwo2::_read_polygon_tag_mapping(unsigned long size) +{ + unsigned int type = _read_long(); + size -= 4; + + _print_type(type); + + if (type == tag_SURF) + { + int count = size / 4; + _current_layer->_polygons_tag.resize(count); + + short polygon_index; + short tag_index; + + while (count--) + { + polygon_index = _read_short(); + tag_index = _read_short(); + _current_layer->_polygons_tag[polygon_index] = tag_index; + } } else { @@ -390,7 +434,6 @@ Lwo2::_read_vertex_mapping(unsigned long size) notify(DEBUG_INFO) << " skipping..." << std::endl; _fin.seekg(size + size % 2, ios::cur); } - } // read VMAD info @@ -415,24 +458,35 @@ Lwo2::_read_polygons_mapping(unsigned long size) if (type == tag_TXUV && dimension == 2) { + notify(DEBUG_INFO) << " polygons mappings:" << endl; + notify(DEBUG_INFO) << "\tpoint\tpolygon\ttexcoord" << endl; + notify(DEBUG_INFO) << "\t=====\t=======\t========" << endl; + int count = size / 12; - // _current_layer->_points_map.resize(count); short point_index; short polygon_index; float u; float v; while (count--) - { - point_index = _read_short(); - polygon_index = _read_short(); - u = _read_float(); - v = _read_float(); + { + point_index = _read_short(); + polygon_index = _read_short(); + u = _read_float(); + v = _read_float(); - Lwo2PolygonMapping pm(polygon_index, Vec2(u, v)); - _current_layer->_polygons_map.insert(PairVMAD(point_index, pm)); + notify(DEBUG_INFO) << " \t" << point_index << "\t" << polygon_index << "\t" << Vec2(u, v) << endl; - } + // apply texture coordinates + PointsList& points_list = _current_layer->_polygons[polygon_index]; + for (unsigned int i = 0; i < points_list.size(); i++) + { + if (points_list[i].point_index == point_index) + { + points_list[i].texcoord = Vec2(u, v); + } + } + } } else { @@ -444,40 +498,6 @@ Lwo2::_read_polygons_mapping(unsigned long size) } -// read PTAG info - -void -Lwo2::_read_polygon_tag_mapping(unsigned long size) -{ - unsigned int type = _read_long(); - size -= 4; - - _print_type(type); - - if (type == tag_SURF) - { - int count = size / 4; - _current_layer->_polygons_tag.resize(count); - - short polygon_index; - short tag_index; - - while (count--) - { - polygon_index = _read_short(); - tag_index = _read_short(); - _current_layer->_polygons_tag[polygon_index] = tag_index; - } - } - else - { - - // not recognized yet - notify(DEBUG_INFO) << " skipping..." << std::endl; - _fin.seekg(size + size % 2, ios::cur); - } -} - // read CLIP info void @@ -505,9 +525,9 @@ Lwo2::_read_image_definition(unsigned long size) size -= name.length() + name.length() % 2; if (index + 1 > _images.size()) - { - _images.resize(index + 1); - } + { + _images.resize(index + 1); + } _images[index] = name.c_str(); @@ -546,77 +566,77 @@ Lwo2::_read_surface(unsigned long size) _print_tag(current_tag_name, current_tag_size); if (current_tag_name == tag_BLOK) - { + { - // BLOK - int blok_size = current_tag_size; - size -= blok_size; - while (blok_size > 0) - { - current_tag_name = _read_long(); - blok_size -= 4; - current_tag_size = _read_short(); - blok_size -= 2; - notify(DEBUG_INFO) << " "; - _print_tag(current_tag_name, current_tag_size); + // BLOK + int blok_size = current_tag_size; + size -= blok_size; + while (blok_size > 0) + { + current_tag_name = _read_long(); + blok_size -= 4; + current_tag_size = _read_short(); + blok_size -= 2; + notify(DEBUG_INFO) << " "; + _print_tag(current_tag_name, current_tag_size); - if (current_tag_name == tag_IMAG) - { - surface->image_index = _read_short(); - notify(DEBUG_INFO) << " image index\t" << surface->image_index << std::endl; - blok_size -= 2; - } - else if (current_tag_name == tag_IMAP) - { + if (current_tag_name == tag_IMAG) + { + surface->image_index = _read_short(); + notify(DEBUG_INFO) << " image index\t" << surface->image_index << std::endl; + blok_size -= 2; + } + else if (current_tag_name == tag_IMAP) + { - // IMAP - int imap_size = current_tag_size; - blok_size -= imap_size; + // IMAP + int imap_size = current_tag_size; + blok_size -= imap_size; - string ordinal; - _read_string(ordinal); - imap_size -= ordinal.length() + ordinal.length() % 2; - notify(DEBUG_INFO) << " ordinal \t'" << ordinal.c_str() << "'" << std::endl; + string ordinal; + _read_string(ordinal); + imap_size -= ordinal.length() + ordinal.length() % 2; + notify(DEBUG_INFO) << " ordinal \t'" << ordinal.c_str() << "'" << std::endl; - while(imap_size > 0) - { - current_tag_name = _read_long(); - imap_size -= 4; - current_tag_size = _read_short(); - imap_size -= 2; - notify(DEBUG_INFO) << " "; - _print_tag(current_tag_name, current_tag_size); + while(imap_size > 0) + { + current_tag_name = _read_long(); + imap_size -= 4; + current_tag_size = _read_short(); + imap_size -= 2; + notify(DEBUG_INFO) << " "; + _print_tag(current_tag_name, current_tag_size); _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); - imap_size -= current_tag_size + current_tag_size % 2; - } - } - else - { - _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); - blok_size -= current_tag_size + current_tag_size % 2; - } - } - } + imap_size -= current_tag_size + current_tag_size % 2; + } + } + else + { + _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); + blok_size -= current_tag_size + current_tag_size % 2; + } + } + } else if (current_tag_name == tag_COLR) - { - float r = _read_float(); - float g = _read_float(); - float b = _read_float(); - surface->color.set(r,g,b); + { + float r = _read_float(); + float g = _read_float(); + float b = _read_float(); + surface->color.set(r,g,b); notify(DEBUG_INFO) << " color \t" << surface->color << std::endl; - current_tag_size -= 12; - size -= 12; + current_tag_size -= 12; + size -= 12; - // skip ununderstooded envelope - _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); - size -= current_tag_size + current_tag_size % 2; - } + // skip ununderstooded envelope + _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); + size -= current_tag_size + current_tag_size % 2; + } else - { - _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); - size -= current_tag_size + current_tag_size % 2; - } + { + _fin.seekg(current_tag_size + current_tag_size % 2, ios::cur); + size -= current_tag_size + current_tag_size % 2; + } } _surfaces[surface->name] = surface; @@ -634,15 +654,22 @@ Lwo2::GenerateGroup( Group& group ) // create geometry from all layers for (IteratorLayers itr = _layers.begin(); itr != _layers.end(); itr++) + // IteratorLayers itr = _layers.begin(); + // itr++; + // itr++; { osg::Geode* geode = osgNew osg::Geode(); - (*itr).second->GenerateGeode(*geode, _tags.size()); + + notify(DEBUG_INFO) << "Generate geode for layer " << (*itr).first << std::endl; + DrawableToTagMapping tag_mapping; + (*itr).second->GenerateGeode(*geode, _tags.size(), tag_mapping); // assign StateSet for each PTAG group for (unsigned int i = 0; i < geode->getNumDrawables(); i++) - { - geode->getDrawable(i)->setStateSet(_surfaces[_tags[i]]->state_set); - } + { + notify(DEBUG_INFO) << " Assigning surface " << _tags[tag_mapping[i]] << " to drawable " << i << std::endl; + geode->getDrawable(i)->setStateSet(_surfaces[_tags[tag_mapping[i]]]->state_set); + } group.addChild(geode); } @@ -659,26 +686,28 @@ Lwo2::_generate_statesets_from_surfaces() Lwo2Surface* surface = (*itr_surf).second; StateSet* state_set = osgNew osg::StateSet; + notify(DEBUG_INFO) << "\tcreating surface " << (*itr_surf).first << std::endl; + // check if exist texture image for this surface if (surface->image_index >= 0) - { - notify(DEBUG_INFO) << "\tloading image '" << _images[surface->image_index] << "'" << std::endl; - Image* image = osgDB::readImageFile(_images[surface->image_index]); - notify(DEBUG_INFO) << "\tresult - " << image << std::endl; - if (image) - { - Texture2D* texture = osgNew osg::Texture2D; - texture->setImage(image); - state_set->setTextureAttributeAndModes(0, texture, StateAttribute::ON); - } - } + { + Image* image = osgDB::readImageFile(_images[surface->image_index]); + notify(DEBUG_INFO) << "\tloaded image '" << _images[surface->image_index] << "'" << std::endl; + notify(DEBUG_INFO) << "\tresult - " << image << std::endl; + if (image) + { + Texture2D* texture = osgNew osg::Texture2D; + texture->setImage(image); + state_set->setTextureAttributeAndModes(0, texture, StateAttribute::ON); + } + } // set color Material* material = osgNew Material(); Vec4 color(surface->color[0], - surface->color[1], - surface->color[2], - 1.0f); + surface->color[1], + surface->color[2], + 1.0f); material->setDiffuse(Material::FRONT_AND_BACK, color); state_set->setAttribute(material); @@ -688,6 +717,8 @@ Lwo2::_generate_statesets_from_surfaces() state_set->setAttribute(cull); state_set->setMode(GL_CULL_FACE, StateAttribute::ON); + state_set->setMode(GL_NORMALIZE, StateAttribute::ON); + surface->state_set = state_set; } } diff --git a/src/osgPlugins/lwo/Lwo2.h b/src/osgPlugins/lwo/Lwo2.h index 153a4f8bc..63f9f49d2 100644 --- a/src/osgPlugins/lwo/Lwo2.h +++ b/src/osgPlugins/lwo/Lwo2.h @@ -45,8 +45,6 @@ class Lwo2Layer; struct Lwo2Surface; struct Lwo2PolygonMapping; -typedef vector< short > PointsList; - typedef vector< string >::iterator IteratorString; typedef map< int, Lwo2Layer* >::iterator IteratorLayers; typedef map< string, Lwo2Surface* >::iterator IteratorSurfaces; @@ -67,7 +65,6 @@ class Lwo2 vector< string > _tags; vector< string > _images; ifstream _fin; - Geode* _geode; unsigned char _read_char(); unsigned short _read_short(); diff --git a/src/osgPlugins/lwo/Lwo2Layer.cpp b/src/osgPlugins/lwo/Lwo2Layer.cpp index 15215a6b3..90836a911 100644 --- a/src/osgPlugins/lwo/Lwo2Layer.cpp +++ b/src/osgPlugins/lwo/Lwo2Layer.cpp @@ -34,13 +34,6 @@ Lwo2Layer::Lwo2Layer(): Lwo2Layer::~Lwo2Layer() { - - // deleting points lists - IteratorPointsList pol_itr; - for (pol_itr = _polygons.begin(); pol_itr != _polygons.end(); pol_itr++) - { - osgDelete (*pol_itr); - } } @@ -55,36 +48,33 @@ Lwo2Layer::notify(NotifySeverity severity) // points osg::notify(severity) << " points:\t" << _points.size() << endl; - IteratorVec3 itr; + osg::notify(severity) << "\tcoord\t\t\t\ttexcoord" << endl; + osg::notify(severity) << "\t=====\t\t\t\t========" << endl; + IteratorPoint itr; for (itr = _points.begin(); itr != _points.end(); itr++) { - osg::notify(severity) << " \t" << (*itr) << endl; - } - - // points mappings - osg::notify(severity) << " points mappings:\t" << _points_map.size() << endl; - IteratorVec2 itr_vec2; - for (itr_vec2 = _points_map.begin(); itr_vec2 != _points_map.end(); itr_vec2++) - { - osg::notify(severity) << " \t" << (*itr_vec2) << endl; + osg::notify(severity) << " \t" << (*itr).coord << "\t\t" << (*itr).texcoord << endl; } // polygons osg::notify(severity) << " polygons:\t" << _polygons.size() << endl; - IteratorPointsList pol_itr; - IteratorShort short_itr; - for (pol_itr = _polygons.begin(); pol_itr != _polygons.end(); pol_itr++) + osg::notify(severity) << "\tcoord\t\t\t\ttexcoord" << endl; + osg::notify(severity) << "\t=====\t\t\t\t========" << endl; + IteratorPolygonsList polygon_iterator; + int polygon_index = 0; + for (polygon_iterator = _polygons.begin(); polygon_iterator != _polygons.end(); polygon_iterator++, polygon_index++) { - osg::notify(severity) << " " << (*pol_itr)->size() << ":"; - for (short_itr = (*pol_itr)->begin(); short_itr != (*pol_itr)->end(); short_itr++) - { - osg::notify(severity) << "\t" << (*short_itr); - } + osg::notify(severity) << " \t" << polygon_index << " ("<< (*polygon_iterator).size() << " vertexes" << "):" << endl; + for (itr = (*polygon_iterator).begin(); itr != (*polygon_iterator).end(); itr++) + { + osg::notify(severity) << " \t" << (*itr).coord << "\t\t" << (*itr).texcoord << endl; + } osg::notify(severity) << endl; } // polygons tags osg::notify(severity) << " polygons tags:\t" << _polygons_tag.size() << endl; + IteratorShort short_itr; for (short_itr = _polygons_tag.begin(); short_itr != _polygons_tag.end(); short_itr++) { osg::notify(severity) << "\t" << (*short_itr) << endl; @@ -92,13 +82,18 @@ Lwo2Layer::notify(NotifySeverity severity) } void -Lwo2Layer::GenerateGeode( Geode& geode, short tags_count ) +Lwo2Layer::GenerateGeode( Geode& geode, short tags_count, DrawableToTagMapping& tag_mapping) { notify(DEBUG_INFO); + + // variable used to track using textures + bool have_texture_coords; // create diffirent geomerty for each tag for (short current_tag = 0; current_tag < tags_count; current_tag++) { + have_texture_coords = false; + // new geometry ref_ptr geometry = osgNew Geometry; @@ -108,77 +103,340 @@ Lwo2Layer::GenerateGeode( Geode& geode, short tags_count ) // create texture array ref_ptr texcoords = osgNew Vec2Array; - // variables for VMAD data processing - pair::iterator, - multimap< short, Lwo2PolygonMapping >::iterator> range; - multimap< short, Lwo2PolygonMapping >::iterator itr; - - // all polygons + // selecting polygons for current layer only int polygon_index = 0; - for (IteratorPointsList pol_itr = _polygons.begin(); pol_itr != _polygons.end(); pol_itr++, polygon_index++) - { + PolygonsList polygons; + for (IteratorPolygonsList polygon_iterator = _polygons.begin(); polygon_iterator != _polygons.end(); polygon_iterator++, polygon_index++) + { + // *polygon_iterator it's a PolygonsList - // polygons of current tag only - if (_polygons_tag[polygon_index] == current_tag) - { + // polygons of current tag only + if (_polygons_tag[polygon_index] == current_tag) + { - // all points - vector< short >::iterator short_itr; - for (short_itr = (*pol_itr)->begin(); short_itr != (*pol_itr)->end(); short_itr++) - { + // reset point_index member for later comparing poins data + PointsList points_list = *polygon_iterator; + for (unsigned int i = 0; i < points_list.size(); i++) + { + points_list[i].point_index = 0; + } - // polygons coords - (*coords).push_back(_points[*short_itr]); + polygons.push_back(*polygon_iterator); + } + } - // point texture coords - if (_points_map.size() > 0) - { - // VMAP data - Vec2 uv = _points_map[*short_itr]; + // find and compose triangle fans + PolygonsList triangle_fans; + _find_triangle_fans(polygons, triangle_fans); - // chech if present VMAD data - if (_polygons_map.size() > 0) - { + // find and compose triangle strips + PolygonsList triangle_strips; + _find_triangle_strips(polygons, triangle_strips); - // select data for current point - range = _polygons_map.equal_range(*short_itr); + // polygons of current layer + polygon_index = 0; + for (IteratorPolygonsList polygon_iterator = polygons.begin(); polygon_iterator != polygons.end(); polygon_iterator++, polygon_index++) + { + if ((*polygon_iterator)[0].point_index != -1) + { + // all points of polygon + for (IteratorPoint itr = (*polygon_iterator).begin(); itr != (*polygon_iterator).end(); itr++) + { + // *itr - it's a PointData - for (itr = range.first; itr != range.second; itr++) - { + // polygons data + (*coords).push_back((*itr).coord); + (*texcoords).push_back((*itr).texcoord); - // found current polygon - if ((*itr).second.polygon_index == polygon_index) - { - uv = (*itr).second.uv; - } - } - } + if ((*itr).texcoord.x() != -1.0f || (*itr).texcoord.y() != -1.0f) + { + have_texture_coords = true; + } + } + + unsigned int points_start = (*coords).size() - (*polygon_iterator).size(); + unsigned int points_count = (*polygon_iterator).size(); + if (points_count == 3) + { + geometry->addPrimitiveSet(osgNew DrawArrays(PrimitiveSet::TRIANGLES, points_start, points_count)); + } + else if (points_count == 4) + { + geometry->addPrimitiveSet(osgNew DrawArrays(PrimitiveSet::QUADS, points_start, points_count)); + } + else + { + geometry->addPrimitiveSet(osgNew DrawArrays(PrimitiveSet::POLYGON, points_start, points_count)); + } + } + } - (*texcoords).push_back(uv); - } - } - geometry->addPrimitiveSet(osgNew DrawArrays(PrimitiveSet::POLYGON, - (*coords).size() - (*pol_itr)->size(), - (*pol_itr)->size())); - } - } + // triangle fans of current layer + polygon_index = 0; + for (IteratorPolygonsList polygon_iterator = triangle_fans.begin(); polygon_iterator != triangle_fans.end(); polygon_iterator++, polygon_index++) + { + + // all points of polygon + for (IteratorPoint itr = (*polygon_iterator).begin(); itr != (*polygon_iterator).end(); itr++) + { + // *itr - it's a PointData + + // polygons data + (*coords).push_back((*itr).coord); + (*texcoords).push_back((*itr).texcoord); + + if ((*itr).texcoord.x() != -1.0f || (*itr).texcoord.y() != -1.0f) + { + have_texture_coords = true; + } + } + + unsigned int points_start = (*coords).size() - (*polygon_iterator).size(); + unsigned int points_count = (*polygon_iterator).size(); + geometry->addPrimitiveSet(osgNew DrawArrays(PrimitiveSet::TRIANGLE_FAN, points_start, points_count)); + } + + // triangle strips of current layer + polygon_index = 0; + for (IteratorPolygonsList polygon_iterator = triangle_strips.begin(); polygon_iterator != triangle_strips.end(); polygon_iterator++, polygon_index++) + { + + // all points of polygon + for (IteratorPoint itr = (*polygon_iterator).begin(); itr != (*polygon_iterator).end(); itr++) + { + // *itr - it's a PointData + + // polygons data + (*coords).push_back((*itr).coord); + (*texcoords).push_back((*itr).texcoord); + + if ((*itr).texcoord.x() != -1.0f || (*itr).texcoord.y() != -1.0f) + { + have_texture_coords = true; + } + } + + unsigned int points_start = (*coords).size() - (*polygon_iterator).size(); + unsigned int points_count = (*polygon_iterator).size(); + geometry->addPrimitiveSet(osgNew DrawArrays(PrimitiveSet::TRIANGLE_STRIP, points_start, points_count)); + } // add geometry if it contains any points if (coords->size() != 0) - { - geometry->setVertexArray(coords.get()); + { + geometry->setVertexArray(coords.get()); - // assign texture array - if ((*texcoords).size() > 0) - { - geometry->setTexCoordArray(0, texcoords.get()); - } + // assign texture array + if (have_texture_coords) + { + geometry->setTexCoordArray(0, texcoords.get()); + } - // generate normals - osgUtil::SmoothingVisitor smoother; - smoother.smooth(*(geometry.get())); + // generate normals + osgUtil::SmoothingVisitor smoother; + smoother.smooth(*(geometry.get())); - geode.addDrawable(geometry.get()); - } + geode.addDrawable(geometry.get()); + + osg::notify(DEBUG_INFO) << " inserting tag " << geode.getNumDrawables() - 1 << ":" << current_tag << std::endl; + tag_mapping.insert(PairDrawableToTag(geode.getNumDrawables() - 1, current_tag)); + } } } + +bool +Lwo2Layer::_find_triangle_fans(PolygonsList& polygons, PolygonsList& triangle_fans) +{ + bool found = false; + + while (_find_triangle_fan(polygons, triangle_fans)) + { + found = true; + } + + if (triangle_fans.size() > 0) + { + osg::notify(INFO) << "LWO2 loader, optimizing: found " << triangle_fans.size() << " triangle fans" << endl; + } + + return found; +} + +bool +Lwo2Layer::_find_triangle_strips(PolygonsList& polygons, PolygonsList& triangle_strips) +{ + bool found = false; + + while (_find_triangle_strip(polygons, triangle_strips)) + { + found = true; + } + + if (triangle_strips.size() > 0) + { + osg::notify(INFO) << "LWO2 loader, optimizing: found " << triangle_strips.size() << " triangle strips" << endl; + } + + return found; +} + +bool +Lwo2Layer::_find_triangle_fan(PolygonsList& polygons, PolygonsList& triangle_fans) +{ + bool found = false; + IteratorPolygonsList polygon_iterator = polygons.begin(); + while (polygon_iterator != polygons.end()) + { + PointsList& points_list = *polygon_iterator; + if (points_list.size() == 3 && points_list[0].point_index != -1) + { + PointData a = points_list[0]; + PointData b = points_list[1]; + PointData c = points_list[2]; + + int next_polygon_index = _find_triangle_begins_with(polygons, a, c); + while (next_polygon_index >= 0) + { + found = true; + PointData d = polygons[next_polygon_index][2]; + + PointsList point_list; + point_list.push_back(a); + point_list.push_back(b); + point_list.push_back(c); + point_list.push_back(d); + + // delete second triangle (mark as deleted) + (*(polygons.begin() + next_polygon_index))[0].point_index = -1; + + // delete current (first) triangle (mark as deleted) + (*polygon_iterator)[0].point_index = -1; + + c = d; + while ((next_polygon_index = _find_triangle_begins_with(polygons, a, c)) >= 0) + { + PointData d = polygons[next_polygon_index][2]; + point_list.push_back(d); + + // delete next triangle (mark as deleted) + (*(polygons.begin() + next_polygon_index))[0].point_index = -1; + + c = d; + } + + triangle_fans.push_back(point_list); + } + } + polygon_iterator++; + } + return found; +} + +bool +Lwo2Layer::_find_triangle_strip(PolygonsList& polygons, PolygonsList& triangle_strips) +{ + bool found = false; + IteratorPolygonsList polygon_iterator = polygons.begin(); + int polygon_index = 0; + while (polygon_iterator != polygons.end()) + { + PointsList& points_list = *polygon_iterator; + if (points_list.size() == 3 && points_list[0].point_index != -1) + { + PointData a = points_list[0]; + PointData b = points_list[1]; + PointData c = points_list[2]; + + int next_polygon_index = _find_triangle_begins_with(polygons, c, b); + + while (next_polygon_index >= 0) + { + found = true; + PointData d = polygons[next_polygon_index][2]; + + PointsList point_list; + point_list.push_back(a); + point_list.push_back(b); + point_list.push_back(c); + point_list.push_back(d); + + // delete second triangle (mark as deleted) + (*(polygons.begin() + next_polygon_index))[0].point_index = -1; + + // delete current (first) triangle (mark as deleted) + (*polygon_iterator)[0].point_index = -1; + + PointData strip_a = c; + PointData strip_b = d; + bool current_strip_a = true; + + while ((next_polygon_index = _find_triangle_begins_with(polygons, strip_a, strip_b)) >= 0) + { + PointData d = polygons[next_polygon_index][2]; + point_list.push_back(d); + + if (current_strip_a) + { + strip_a = d; + } + else + { + strip_b = d; + } + current_strip_a = !current_strip_a; + + // delete next triangle (mark as deleted) + (*(polygons.begin() + next_polygon_index))[0].point_index = -1; + } + + triangle_strips.push_back(point_list); + } + } + polygon_iterator++; + polygon_index++; + } + return found; +} + +int +Lwo2Layer::_find_triangle_begins_with(PolygonsList& polygons, PointData& a, PointData& b) +{ + int result = -1; + + int polygon_index = 0; + for (IteratorPolygonsList polygon_iterator = polygons.begin(); polygon_iterator != polygons.end(); polygon_iterator++, polygon_index++) + { + PointsList& points_list = *polygon_iterator; + if (points_list.size() == 3 && points_list[0].point_index != -1) + { + if (points_list[0] == a && points_list[1] == b) + { + result = polygon_index; + break; + } + else if (points_list[1] == a && points_list[2] == b) + { + // shift points + PointData temp = points_list[0]; + points_list[0] = points_list[1]; + points_list[1] = points_list[2]; + points_list[2] = temp; + + result = polygon_index; + break; + } + else if (points_list[2] == a && points_list[0] == b) + { + // shift points + PointData temp = points_list[2]; + points_list[2] = points_list[1]; + points_list[1] = points_list[0]; + points_list[0] = temp; + + result = polygon_index; + break; + } + } + } + return result; +} diff --git a/src/osgPlugins/lwo/Lwo2Layer.h b/src/osgPlugins/lwo/Lwo2Layer.h index caa730cfe..1e1a582b8 100644 --- a/src/osgPlugins/lwo/Lwo2Layer.h +++ b/src/osgPlugins/lwo/Lwo2Layer.h @@ -24,7 +24,7 @@ */ #ifndef LWO2LAYER_H -#define LWO2LAYER_H 1 +#define LWO2LAYER_H #include #include @@ -42,12 +42,23 @@ using namespace osg; using namespace std; -typedef vector< short > PointsList; +struct PointData +{ + PointData(): + point_index(0), + coord(Vec3(0.0f, 0.0f, 0.0f)), + texcoord(Vec2(-1.0f, -1.0f)) {} -typedef vector< PointsList* >::iterator IteratorPointsList; -typedef vector< Vec3 >::iterator IteratorVec3; -typedef vector< Vec2 >::iterator IteratorVec2; -typedef vector< short >::iterator IteratorShort; + short point_index; + Vec3 coord; + Vec2 texcoord; + + inline bool operator == (const PointData& p) const + { + return coord == p.coord && texcoord == p.texcoord; + } + +}; struct Lwo2Surface { @@ -61,15 +72,16 @@ struct Lwo2Surface StateSet* state_set; }; -struct Lwo2PolygonMapping -{ - Lwo2PolygonMapping(short s, const Vec2& v2): - polygon_index(s), - uv(v2) {} - - short polygon_index; - Vec2 uv; -}; +typedef vector< PointData > PointsList; +typedef vector< PointsList > PolygonsList; +typedef PolygonsList::iterator IteratorPolygonsList; + +typedef map< int, int > DrawableToTagMapping; +typedef pair< int, int > PairDrawableToTag; + +typedef vector< PointData >::iterator IteratorPoint; +typedef vector< Vec2 >::iterator IteratorVec2; +typedef vector< short >::iterator IteratorShort; class Lwo2Layer { @@ -78,19 +90,23 @@ class Lwo2Layer Lwo2Layer(); ~Lwo2Layer(); void notify(NotifySeverity); - void GenerateGeode( Geode&, short ); + void GenerateGeode( Geode&, short, DrawableToTagMapping& ); private: + bool _find_triangle_fans(PolygonsList&, PolygonsList&); + bool _find_triangle_fan(PolygonsList&, PolygonsList&); + bool _find_triangle_strips(PolygonsList&, PolygonsList&); + bool _find_triangle_strip(PolygonsList&, PolygonsList&); + int _find_triangle_begins_with(PolygonsList&, PointData&, PointData&); + short _number; short _flags; short _parent; Vec3 _pivot; string _name; - vector< Vec3 > _points; - vector< Vec2 > _points_map; - vector< PointsList* > _polygons; + vector< PointData > _points; + PolygonsList _polygons; vector< short > _polygons_tag; - multimap< short, Lwo2PolygonMapping > _polygons_map; }; #endif