📄 object.cpp
字号:
/******************************************************* Lightwave Object Loader for OSG Copyright (C) 2004 Marco Jez <marco.jez@poste.it> OpenSceneGraph is (C) 2004 Robert Osfield********************************************************/#include "Object.h"#include <osg/Notify>#include <vector>#include <string>#include <sstream>using namespace lwosg;namespace{ bool triangle_is_clockwise(const osg::Vec3Array *points, int a, int b, int c) { const osg::Vec3 &A = (*points)[a]; const osg::Vec3 &B = (*points)[b]; const osg::Vec3 &C = (*points)[c]; float area2 = 0; area2 += A.x() * B.y() - B.x() * A.y(); area2 += B.x() * C.y() - C.x() * B.y(); area2 += C.x() * A.y() - A.x() * C.y(); return area2 < 0; } float cylindrical_angle(float x, float y) { float r = sqrtf(x*x+y*y); if (r == 0) return 0; x /= r; float a; if (x < 0 && y >= 0) a = osg::PI_2 - acosf(-x); else if (x < 0 && y < 0) a = acosf(-x) + osg::PI_2; else if (x >= 0 && y >= 0) a = acosf(x) + 3 * osg::PI_2; else if (x >= 0 && y < 0) a = 3 * osg::PI_2 - acosf(x); else a = 0.0f; return a/osg::PI/2; }}Object::Object(): csf_(new LwoCoordFixer){}Object::Object(const iff::Chunk_list &data): csf_(new LwoCoordFixer){ build(data);}void Object::build(const iff::Chunk_list &data){ clips_.clear(); surfaces_.clear(); layers_.clear(); comment_ = ""; description_ = ""; osg::notify(osg::INFO) << "INFO: lwosg::Object: scanning clips\n"; scan_clips(data); osg::notify(osg::INFO) << "INFO: lwosg::Object: scanning surfaces\n"; scan_surfaces(data); osg::notify(osg::INFO) << "INFO: lwosg::Object: parsing LWO2 chunks and building object\n"; parse(data); osg::notify(osg::INFO) << "INFO: lwosg::Object: generating normals\n"; generate_normals(); osg::notify(osg::INFO) << "INFO: lwosg::Object: generating automatic texture maps\n"; generate_auto_texture_maps();}void Object::scan_clips(const iff::Chunk_list &data){ for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) { const lwo2::FORM::CLIP *clip = dynamic_cast<const lwo2::FORM::CLIP *>(*i); if (clip) { clips_[clip->index] = Clip(clip); } }}void Object::scan_surfaces(const iff::Chunk_list &data){ for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) { const lwo2::FORM::SURF *surf = dynamic_cast<const lwo2::FORM::SURF *>(*i); if (surf) { surfaces_[surf->name] = Surface(surf, clips_); } }}void Object::parse(const iff::Chunk_list &data){ typedef std::vector<std::string> String_list; String_list tag_strings; Layer current_layer; for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) { const lwo2::FORM::LAYR *layr = dynamic_cast<const lwo2::FORM::LAYR *>(*i); if (layr) { if (!current_layer.units().empty() || current_layer.get_layer_chunk()) { layers_[current_layer.number()] = current_layer; } current_layer.set_layer_chunk(layr); current_layer.units().clear(); } const lwo2::FORM::PNTS *pnts = dynamic_cast<const lwo2::FORM::PNTS *>(*i); if (pnts) { Unit new_unit; for (lwo2::FORM::PNTS::Point_list::const_iterator i=pnts->point_location.begin(); i!=pnts->point_location.end(); ++i) { new_unit.points()->push_back(csf_->fix_point(osg::Vec3(i->X, i->Y, i->Z) /*+ current_layer.pivot()*/)); } new_unit.shares().assign(new_unit.points()->size(), Unit::Index_list()); current_layer.units().push_back(new_unit); } const lwo2::FORM::VMAP *vmap = dynamic_cast<const lwo2::FORM::VMAP *>(*i); if (vmap && !current_layer.units().empty()) { std::string type(vmap->type.id, 4); if (type == "WGHT") { if (vmap->dimension != 1) { osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; continue; } VertexMap *new_map = current_layer.units().back().weight_maps()->getOrCreate(vmap->name); for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), 0, 0, 0); } } if (type == "MNVW") { if (vmap->dimension != 1) { osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; continue; } VertexMap *new_map = current_layer.units().back().subpatch_weight_maps()->getOrCreate(vmap->name); for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), 0, 0, 0); } } if (type == "TXUV") { if (vmap->dimension != 2) { osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; continue; } VertexMap *new_map = current_layer.units().back().texture_maps()->getOrCreate(vmap->name); for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), 0, 0); } } if (type == "RGB ") { if (vmap->dimension != 3) { osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; continue; } VertexMap *new_map = current_layer.units().back().rgb_maps()->getOrCreate(vmap->name); for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), 1); } } if (type == "RGBA") { if (vmap->dimension != 4) { osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; continue; } VertexMap *new_map = current_layer.units().back().rgba_maps()->getOrCreate(vmap->name); for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), i->value.at(3)); } } if (type == "MORF") { if (vmap->dimension != 3) { osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; continue; } VertexMap *new_map = current_layer.units().back().displacement_maps()->getOrCreate(vmap->name); for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), 0); } } if (type == "SPOT") { if (vmap->dimension != 3) { osg::notify(osg::WARN) << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; continue; } VertexMap *new_map = current_layer.units().back().spot_maps()->getOrCreate(vmap->name); for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { (*new_map)[i->vert.index] = osg::Vec4(csf_->fix_point(osg::Vec3(i->value.at(0), i->value.at(1), i->value.at(2))), 0); } } } const lwo2::FORM::POLS *pols = dynamic_cast<const lwo2::FORM::POLS *>(*i); if (pols && !current_layer.units().empty()) { std::string type(pols->type.id, 4); if (type != "FACE") { osg::notify(osg::INFO) << "INFO: Lwo2Object: polygon list of type " << type << " not supported, rendering may be inaccurate" << std::endl; } for (lwo2::FORM::POLS::Polygon_list::const_iterator i=pols->polygons.begin(); i!=pols->polygons.end(); ++i) { Polygon polygon; bool must_invert_winding = csf_->invert_winding(); // FIX FOR A LIGHTWAVE BUG? MAYBE IT IS A FEATURE, I DON'T KNOW... // if the first vertex is at a concave corner, we must invert the winding of the polygon // beacuse it appears as flipped in Lighwave. Also, we tell the polygon to invert its normal. // (not implemented yet) /*if (i->vert.size() >= 4) { if (must_invert_winding == triangle_is_clockwise(current_layer.units().back().points(), i->vert.front().index, i->vert.back().index, i->vert[1].index)) { must_invert_winding = !must_invert_winding; polygon.set_invert_normal(true); } }*/ if (must_invert_winding) { for (unsigned j=0; j<i->numvert; ++j) { int index = i->vert.at((i->numvert-j)%i->numvert).index; polygon.indices().push_back(index); current_layer.units().back().shares().at(index).push_back(current_layer.units().back().polygons().size()); } } else { for (unsigned j=0; j<i->numvert; ++j) { int index = i->vert.at(j).index;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -