| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | #include "Object.h" |
|---|
| 9 | |
|---|
| 10 | #include <osg/Notify> |
|---|
| 11 | |
|---|
| 12 | #include <vector> |
|---|
| 13 | #include <string> |
|---|
| 14 | #include <sstream> |
|---|
| 15 | |
|---|
| 16 | using namespace lwosg; |
|---|
| 17 | |
|---|
| 18 | namespace |
|---|
| 19 | { |
|---|
| 20 | |
|---|
| 21 | bool triangle_is_clockwise(const osg::Vec3Array *points, int a, int b, int c) |
|---|
| 22 | { |
|---|
| 23 | const osg::Vec3 &A = (*points)[a]; |
|---|
| 24 | const osg::Vec3 &B = (*points)[b]; |
|---|
| 25 | const osg::Vec3 &C = (*points)[c]; |
|---|
| 26 | float area2 = 0; |
|---|
| 27 | area2 += A.x() * B.y() - B.x() * A.y(); |
|---|
| 28 | area2 += B.x() * C.y() - C.x() * B.y(); |
|---|
| 29 | area2 += C.x() * A.y() - A.x() * C.y(); |
|---|
| 30 | return area2 < 0; |
|---|
| 31 | } |
|---|
| 32 | |
|---|
| 33 | float cylindrical_angle(float x, float y) |
|---|
| 34 | { |
|---|
| 35 | float r = sqrtf(x*x+y*y); |
|---|
| 36 | if (r == 0) return 0; |
|---|
| 37 | x /= r; |
|---|
| 38 | float a; |
|---|
| 39 | if (x < 0 && y >= 0) a = osg::PI_2 - acosf(-x); |
|---|
| 40 | else if (x < 0 && y < 0) a = acosf(-x) + osg::PI_2; |
|---|
| 41 | else if (x >= 0 && y >= 0) a = acosf(x) + 3 * osg::PI_2; |
|---|
| 42 | else if (x >= 0 && y < 0) a = 3 * osg::PI_2 - acosf(x); |
|---|
| 43 | else a = 0.0f; |
|---|
| 44 | return a/osg::PI/2; |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | } |
|---|
| 48 | |
|---|
| 49 | Object::Object() |
|---|
| 50 | : csf_(new LwoCoordFixer) |
|---|
| 51 | { |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | Object::Object(const iff::Chunk_list &data) |
|---|
| 55 | : csf_(new LwoCoordFixer) |
|---|
| 56 | { |
|---|
| 57 | build(data); |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| 60 | void Object::build(const iff::Chunk_list &data) |
|---|
| 61 | { |
|---|
| 62 | clips_.clear(); |
|---|
| 63 | surfaces_.clear(); |
|---|
| 64 | layers_.clear(); |
|---|
| 65 | comment_ = ""; |
|---|
| 66 | description_ = ""; |
|---|
| 67 | |
|---|
| 68 | OSG_INFO << "INFO: lwosg::Object: scanning clips\n"; |
|---|
| 69 | scan_clips(data); |
|---|
| 70 | OSG_INFO << "INFO: lwosg::Object: scanning surfaces\n"; |
|---|
| 71 | scan_surfaces(data); |
|---|
| 72 | OSG_INFO << "INFO: lwosg::Object: parsing LWO2 chunks and building object\n"; |
|---|
| 73 | parse(data); |
|---|
| 74 | OSG_INFO << "INFO: lwosg::Object: generating normals\n"; |
|---|
| 75 | generate_normals(); |
|---|
| 76 | OSG_INFO << "INFO: lwosg::Object: generating automatic texture maps\n"; |
|---|
| 77 | generate_auto_texture_maps(); |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | void Object::scan_clips(const iff::Chunk_list &data) |
|---|
| 81 | { |
|---|
| 82 | for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) { |
|---|
| 83 | const lwo2::FORM::CLIP *clip = dynamic_cast<const lwo2::FORM::CLIP *>(*i); |
|---|
| 84 | if (clip) { |
|---|
| 85 | clips_[clip->index] = Clip(clip); |
|---|
| 86 | } |
|---|
| 87 | } |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | void Object::scan_surfaces(const iff::Chunk_list &data) |
|---|
| 91 | { |
|---|
| 92 | for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) { |
|---|
| 93 | const lwo2::FORM::SURF *surf = dynamic_cast<const lwo2::FORM::SURF *>(*i); |
|---|
| 94 | if (surf) { |
|---|
| 95 | surfaces_[surf->name] = Surface(surf, clips_); |
|---|
| 96 | } |
|---|
| 97 | } |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | void Object::parse(const iff::Chunk_list &data) |
|---|
| 101 | { |
|---|
| 102 | typedef std::vector<std::string> String_list; |
|---|
| 103 | String_list tag_strings; |
|---|
| 104 | |
|---|
| 105 | Layer current_layer; |
|---|
| 106 | |
|---|
| 107 | for (iff::Chunk_list::const_iterator i=data.begin(); i!=data.end(); ++i) { |
|---|
| 108 | |
|---|
| 109 | const lwo2::FORM::LAYR *layr = dynamic_cast<const lwo2::FORM::LAYR *>(*i); |
|---|
| 110 | if (layr) { |
|---|
| 111 | if (!current_layer.units().empty() || current_layer.get_layer_chunk()) { |
|---|
| 112 | layers_[current_layer.number()] = current_layer; |
|---|
| 113 | } |
|---|
| 114 | current_layer.set_layer_chunk(layr); |
|---|
| 115 | current_layer.units().clear(); |
|---|
| 116 | } |
|---|
| 117 | |
|---|
| 118 | const lwo2::FORM::PNTS *pnts = dynamic_cast<const lwo2::FORM::PNTS *>(*i); |
|---|
| 119 | if (pnts) { |
|---|
| 120 | Unit new_unit; |
|---|
| 121 | for (lwo2::FORM::PNTS::Point_list::const_iterator i=pnts->point_location.begin(); i!=pnts->point_location.end(); ++i) { |
|---|
| 122 | new_unit.points()->push_back(csf_->fix_point(osg::Vec3(i->X, i->Y, i->Z) )); |
|---|
| 123 | } |
|---|
| 124 | new_unit.shares().assign(new_unit.points()->size(), Unit::Index_list()); |
|---|
| 125 | current_layer.units().push_back(new_unit); |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | const lwo2::FORM::VMAP *vmap = dynamic_cast<const lwo2::FORM::VMAP *>(*i); |
|---|
| 129 | if (vmap && !current_layer.units().empty()) { |
|---|
| 130 | std::string type(vmap->type.id, 4); |
|---|
| 131 | if (type == "WGHT") { |
|---|
| 132 | if (vmap->dimension != 1) { |
|---|
| 133 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; |
|---|
| 134 | continue; |
|---|
| 135 | } |
|---|
| 136 | VertexMap *new_map = current_layer.units().back().weight_maps()->getOrCreate(vmap->name); |
|---|
| 137 | for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { |
|---|
| 138 | (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), 0, 0, 0); |
|---|
| 139 | } |
|---|
| 140 | } |
|---|
| 141 | if (type == "MNVW") { |
|---|
| 142 | if (vmap->dimension != 1) { |
|---|
| 143 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; |
|---|
| 144 | continue; |
|---|
| 145 | } |
|---|
| 146 | VertexMap *new_map = current_layer.units().back().subpatch_weight_maps()->getOrCreate(vmap->name); |
|---|
| 147 | for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { |
|---|
| 148 | (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), 0, 0, 0); |
|---|
| 149 | } |
|---|
| 150 | } |
|---|
| 151 | if (type == "TXUV") { |
|---|
| 152 | if (vmap->dimension != 2) { |
|---|
| 153 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; |
|---|
| 154 | continue; |
|---|
| 155 | } |
|---|
| 156 | VertexMap *new_map = current_layer.units().back().texture_maps()->getOrCreate(vmap->name); |
|---|
| 157 | for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { |
|---|
| 158 | (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), 0, 0); |
|---|
| 159 | } |
|---|
| 160 | } |
|---|
| 161 | if (type == "RGB ") { |
|---|
| 162 | if (vmap->dimension != 3) { |
|---|
| 163 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; |
|---|
| 164 | continue; |
|---|
| 165 | } |
|---|
| 166 | VertexMap *new_map = current_layer.units().back().rgb_maps()->getOrCreate(vmap->name); |
|---|
| 167 | for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { |
|---|
| 168 | (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), 1); |
|---|
| 169 | } |
|---|
| 170 | } |
|---|
| 171 | if (type == "RGBA") { |
|---|
| 172 | if (vmap->dimension != 4) { |
|---|
| 173 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; |
|---|
| 174 | continue; |
|---|
| 175 | } |
|---|
| 176 | VertexMap *new_map = current_layer.units().back().rgba_maps()->getOrCreate(vmap->name); |
|---|
| 177 | for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { |
|---|
| 178 | (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), i->value.at(3)); |
|---|
| 179 | } |
|---|
| 180 | } |
|---|
| 181 | if (type == "MORF") { |
|---|
| 182 | if (vmap->dimension != 3) { |
|---|
| 183 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; |
|---|
| 184 | continue; |
|---|
| 185 | } |
|---|
| 186 | VertexMap *new_map = current_layer.units().back().displacement_maps()->getOrCreate(vmap->name); |
|---|
| 187 | for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { |
|---|
| 188 | (*new_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), 0); |
|---|
| 189 | } |
|---|
| 190 | } |
|---|
| 191 | if (type == "SPOT") { |
|---|
| 192 | if (vmap->dimension != 3) { |
|---|
| 193 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " vertex map dimension: " << vmap->dimension << std::endl; |
|---|
| 194 | continue; |
|---|
| 195 | } |
|---|
| 196 | VertexMap *new_map = current_layer.units().back().spot_maps()->getOrCreate(vmap->name); |
|---|
| 197 | for (lwo2::FORM::VMAP::Mapping_list::const_iterator i=vmap->mapping.begin(); i!=vmap->mapping.end(); ++i) { |
|---|
| 198 | (*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); |
|---|
| 199 | } |
|---|
| 200 | } |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | const lwo2::FORM::POLS *pols = dynamic_cast<const lwo2::FORM::POLS *>(*i); |
|---|
| 204 | if (pols && !current_layer.units().empty()) { |
|---|
| 205 | std::string type(pols->type.id, 4); |
|---|
| 206 | if (type != "FACE") { |
|---|
| 207 | OSG_INFO << "INFO: Lwo2Object: polygon list of type " << type << " not supported, rendering may be inaccurate" << std::endl; |
|---|
| 208 | } |
|---|
| 209 | for (lwo2::FORM::POLS::Polygon_list::const_iterator i=pols->polygons.begin(); i!=pols->polygons.end(); ++i) { |
|---|
| 210 | Polygon polygon; |
|---|
| 211 | bool must_invert_winding = csf_->invert_winding(); |
|---|
| 212 | |
|---|
| 213 | |
|---|
| 214 | |
|---|
| 215 | |
|---|
| 216 | |
|---|
| 217 | |
|---|
| 218 | |
|---|
| 219 | |
|---|
| 220 | |
|---|
| 221 | |
|---|
| 222 | |
|---|
| 223 | |
|---|
| 224 | if (must_invert_winding) { |
|---|
| 225 | for (unsigned j=0; j<i->numvert; ++j) { |
|---|
| 226 | int index = i->vert.at((i->numvert-j)%i->numvert).index; |
|---|
| 227 | polygon.indices().push_back(index); |
|---|
| 228 | current_layer.units().back().shares().at(index).push_back(current_layer.units().back().polygons().size()); |
|---|
| 229 | } |
|---|
| 230 | } else { |
|---|
| 231 | for (unsigned j=0; j<i->numvert; ++j) { |
|---|
| 232 | int index = i->vert.at(j).index; |
|---|
| 233 | polygon.indices().push_back(index); |
|---|
| 234 | current_layer.units().back().shares().at(index).push_back(current_layer.units().back().polygons().size()); |
|---|
| 235 | } |
|---|
| 236 | } |
|---|
| 237 | current_layer.units().back().polygons().push_back(polygon); |
|---|
| 238 | } |
|---|
| 239 | } |
|---|
| 240 | |
|---|
| 241 | const lwo2::FORM::TAGS *tags = dynamic_cast<const lwo2::FORM::TAGS *>(*i); |
|---|
| 242 | if (tags) { |
|---|
| 243 | tag_strings = tags->tag_string; |
|---|
| 244 | } |
|---|
| 245 | |
|---|
| 246 | const lwo2::FORM::PTAG *ptag = dynamic_cast<const lwo2::FORM::PTAG *>(*i); |
|---|
| 247 | if (ptag && !current_layer.units().empty()) { |
|---|
| 248 | std::string type(ptag->type.id, 4); |
|---|
| 249 | if (type == "SURF") { |
|---|
| 250 | for (lwo2::FORM::PTAG::Mapping_list::const_iterator i=ptag->mapping.begin(); i!=ptag->mapping.end(); ++i) { |
|---|
| 251 | current_layer.units().back().polygons().at(i->poly.index).set_surface(&surfaces_[tag_strings.at(i->tag)]); |
|---|
| 252 | } |
|---|
| 253 | } |
|---|
| 254 | if (type == "PART") { |
|---|
| 255 | for (lwo2::FORM::PTAG::Mapping_list::const_iterator i=ptag->mapping.begin(); i!=ptag->mapping.end(); ++i) { |
|---|
| 256 | current_layer.units().back().polygons().at(i->poly.index).set_part_name(tag_strings.at(i->tag)); |
|---|
| 257 | } |
|---|
| 258 | } |
|---|
| 259 | if (type == "SMGP") { |
|---|
| 260 | for (lwo2::FORM::PTAG::Mapping_list::const_iterator i=ptag->mapping.begin(); i!=ptag->mapping.end(); ++i) { |
|---|
| 261 | current_layer.units().back().polygons().at(i->poly.index).set_smoothing_group(tag_strings.at(i->tag)); |
|---|
| 262 | } |
|---|
| 263 | } |
|---|
| 264 | } |
|---|
| 265 | |
|---|
| 266 | const lwo2::FORM::VMAD *vmad = dynamic_cast<const lwo2::FORM::VMAD *>(*i); |
|---|
| 267 | if (vmad && !current_layer.units().empty()) { |
|---|
| 268 | std::string type(vmad->type.id, 4); |
|---|
| 269 | if (type == "WGHT") { |
|---|
| 270 | if (vmad->dimension != 1) { |
|---|
| 271 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " discontinuous vertex map dimension: " << vmad->dimension << std::endl; |
|---|
| 272 | continue; |
|---|
| 273 | } |
|---|
| 274 | for (lwo2::FORM::VMAD::Mapping_list::const_iterator i=vmad->mapping.begin(); i!=vmad->mapping.end(); ++i) { |
|---|
| 275 | VertexMap *this_map = current_layer.units().back().polygons().at(i->poly.index).weight_maps()->getOrCreate(vmad->name); |
|---|
| 276 | (*this_map)[i->vert.index] = osg::Vec4(i->value.at(0), 0, 0, 0); |
|---|
| 277 | } |
|---|
| 278 | } |
|---|
| 279 | if (type == "TXUV") { |
|---|
| 280 | if (vmad->dimension != 2) { |
|---|
| 281 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " discontinuous vertex map dimension: " << vmad->dimension << std::endl; |
|---|
| 282 | continue; |
|---|
| 283 | } |
|---|
| 284 | for (lwo2::FORM::VMAD::Mapping_list::const_iterator i=vmad->mapping.begin(); i!=vmad->mapping.end(); ++i) { |
|---|
| 285 | VertexMap *this_map = current_layer.units().back().polygons().at(i->poly.index).texture_maps()->getOrCreate(vmad->name); |
|---|
| 286 | (*this_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), 0, 0); |
|---|
| 287 | } |
|---|
| 288 | } |
|---|
| 289 | if (type == "RGB ") { |
|---|
| 290 | if (vmad->dimension != 3) { |
|---|
| 291 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " discontinuous vertex map dimension: " << vmad->dimension << std::endl; |
|---|
| 292 | continue; |
|---|
| 293 | } |
|---|
| 294 | for (lwo2::FORM::VMAD::Mapping_list::const_iterator i=vmad->mapping.begin(); i!=vmad->mapping.end(); ++i) { |
|---|
| 295 | VertexMap *this_map = current_layer.units().back().polygons().at(i->poly.index).rgb_maps()->getOrCreate(vmad->name); |
|---|
| 296 | (*this_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), 1); |
|---|
| 297 | } |
|---|
| 298 | } |
|---|
| 299 | if (type == "RGBA") { |
|---|
| 300 | if (vmad->dimension != 4) { |
|---|
| 301 | OSG_WARN << "Warning: Lwo2Object: invalid " << type << " discontinuous vertex map dimension: " << vmad->dimension << std::endl; |
|---|
| 302 | continue; |
|---|
| 303 | } |
|---|
| 304 | for (lwo2::FORM::VMAD::Mapping_list::const_iterator i=vmad->mapping.begin(); i!=vmad->mapping.end(); ++i) { |
|---|
| 305 | VertexMap *this_map = current_layer.units().back().polygons().at(i->poly.index).rgba_maps()->getOrCreate(vmad->name); |
|---|
| 306 | (*this_map)[i->vert.index] = osg::Vec4(i->value.at(0), i->value.at(1), i->value.at(2), i->value.at(3)); |
|---|
| 307 | } |
|---|
| 308 | } |
|---|
| 309 | } |
|---|
| 310 | |
|---|
| 311 | const lwo2::FORM::DESC *desc = dynamic_cast<const lwo2::FORM::DESC *>(*i); |
|---|
| 312 | if (desc) { |
|---|
| 313 | description_ = desc->description_line; |
|---|
| 314 | } |
|---|
| 315 | |
|---|
| 316 | const lwo2::FORM::TEXT *text = dynamic_cast<const lwo2::FORM::TEXT *>(*i); |
|---|
| 317 | if (text) { |
|---|
| 318 | comment_ = text->comment; |
|---|
| 319 | } |
|---|
| 320 | |
|---|
| 321 | } |
|---|
| 322 | |
|---|
| 323 | if (!current_layer.units().empty() || current_layer.get_layer_chunk()) { |
|---|
| 324 | layers_[current_layer.number()] = current_layer; |
|---|
| 325 | } |
|---|
| 326 | } |
|---|
| 327 | |
|---|
| 328 | void Object::generate_normals() |
|---|
| 329 | { |
|---|
| 330 | for (Layer_map::iterator i=layers_.begin(); i!=layers_.end(); ++i) { |
|---|
| 331 | for (Layer::Unit_list::iterator j=i->second.units().begin(); j!=i->second.units().end(); ++j) { |
|---|
| 332 | j->generate_normals(); |
|---|
| 333 | } |
|---|
| 334 | } |
|---|
| 335 | } |
|---|
| 336 | |
|---|
| 337 | void Object::generate_auto_texture_maps() |
|---|
| 338 | { |
|---|
| 339 | for (Surface_map::iterator i=surfaces_.begin(); i!=surfaces_.end(); ++i) { |
|---|
| 340 | for (Surface::Block_map::iterator j=i->second.blocks().begin(); j!=i->second.blocks().end(); ++j) { |
|---|
| 341 | Block &block = j->second; |
|---|
| 342 | if (block.get_type() == "IMAP") { |
|---|
| 343 | if (block.get_image_map().projection == Image_map::UV) continue; |
|---|
| 344 | |
|---|
| 345 | Image_map::Axis_type axis = block.get_image_map().axis; |
|---|
| 346 | |
|---|
| 347 | std::ostringstream oss; |
|---|
| 348 | oss << "Auto_map_" << █ |
|---|
| 349 | std::string map_name = oss.str(); |
|---|
| 350 | |
|---|
| 351 | OSG_DEBUG << "DEBUG INFO: lwosg::Object: creating automatic texture map '" << map_name << "'\n"; |
|---|
| 352 | |
|---|
| 353 | for (Layer_map::iterator k=layers_.begin(); k!=layers_.end(); ++k) { |
|---|
| 354 | for (Layer::Unit_list::iterator h=k->second.units().begin(); h!=k->second.units().end(); ++h) { |
|---|
| 355 | |
|---|
| 356 | osg::ref_ptr<VertexMap> new_map = new VertexMap; |
|---|
| 357 | (*h->texture_maps())[map_name] = new_map.get(); |
|---|
| 358 | |
|---|
| 359 | if (block.get_image_map().projection == Image_map::FRONT_PROJECTION) { |
|---|
| 360 | OSG_WARN << "Warning: lwosg::Object: front projection is not supported" << std::endl; |
|---|
| 361 | } |
|---|
| 362 | |
|---|
| 363 | if (block.get_image_map().projection == Image_map::CUBIC) { |
|---|
| 364 | |
|---|
| 365 | for (Unit::Polygon_list::iterator p=h->polygons().begin(); p!=h->polygons().end(); ++p) { |
|---|
| 366 | |
|---|
| 367 | Polygon &poly = *p; |
|---|
| 368 | osg::ref_ptr<VertexMap> local_uv_map = poly.texture_maps()->getOrCreate(map_name); |
|---|
| 369 | |
|---|
| 370 | osg::Vec3 N = csf_->fix_vector(poly.face_normal(h->points())); |
|---|
| 371 | |
|---|
| 372 | Image_map::Axis_type axis = Image_map::X; |
|---|
| 373 | if (N.y() > N.x() && N.y() > N.z()) axis = Image_map::Y; |
|---|
| 374 | if (-N.y() > N.x() && -N.y() > N.z()) axis = Image_map::Y; |
|---|
| 375 | if (N.z() > N.x() && N.z() > N.y()) axis = Image_map::Z; |
|---|
| 376 | if (-N.z() > N.x() && -N.z() > N.y()) axis = Image_map::Z; |
|---|
| 377 | |
|---|
| 378 | for (Polygon::Index_list::iterator i=poly.indices().begin(); i!=poly.indices().end(); ++i) { |
|---|
| 379 | |
|---|
| 380 | |
|---|
| 381 | osg::Vec3 P = csf_->fix_point((*h->points())[*i]); |
|---|
| 382 | |
|---|
| 383 | |
|---|
| 384 | P = block.setup_texture_point(P); |
|---|
| 385 | |
|---|
| 386 | osg::Vec2 uv; |
|---|
| 387 | switch (axis) { |
|---|
| 388 | case Image_map::X: uv.set(P.z(), P.y()); break; |
|---|
| 389 | case Image_map::Y: uv.set(P.x(), P.z()); break; |
|---|
| 390 | case Image_map::Z: uv.set(P.x(), P.y()); break; |
|---|
| 391 | default: ; |
|---|
| 392 | } |
|---|
| 393 | uv += osg::Vec2(0.5f, 0.5f); |
|---|
| 394 | |
|---|
| 395 | osg::Vec4 map_value(uv.x(), uv.y(), 0, 0); |
|---|
| 396 | |
|---|
| 397 | if ((new_map->find(*i) != new_map->end()) && (map_value != (*new_map.get())[*i])) { |
|---|
| 398 | (*local_uv_map.get())[*i] = map_value; |
|---|
| 399 | } else { |
|---|
| 400 | (*new_map.get())[*i] = map_value; |
|---|
| 401 | } |
|---|
| 402 | } |
|---|
| 403 | } |
|---|
| 404 | } else { |
|---|
| 405 | |
|---|
| 406 | for (unsigned p=0; p<h->points()->size(); ++p) { |
|---|
| 407 | |
|---|
| 408 | |
|---|
| 409 | osg::Vec3 P = csf_->fix_point((*h->points())[p]); |
|---|
| 410 | |
|---|
| 411 | |
|---|
| 412 | P = block.setup_texture_point(P); |
|---|
| 413 | |
|---|
| 414 | osg::Vec2 uv; |
|---|
| 415 | |
|---|
| 416 | if (block.get_image_map().projection == Image_map::PLANAR) { |
|---|
| 417 | switch (axis) { |
|---|
| 418 | case Image_map::X: uv.set(P.z(), P.y()); break; |
|---|
| 419 | case Image_map::Y: uv.set(P.x(), P.z()); break; |
|---|
| 420 | case Image_map::Z: uv.set(P.x(), P.y()); break; |
|---|
| 421 | default: ; |
|---|
| 422 | } |
|---|
| 423 | uv += osg::Vec2(0.5f, 0.5f); |
|---|
| 424 | } |
|---|
| 425 | |
|---|
| 426 | if (block.get_image_map().projection == Image_map::CYLINDRICAL) { |
|---|
| 427 | switch (axis) { |
|---|
| 428 | case Image_map::X: uv.set(cylindrical_angle(-P.z(), -P.y()), P.x()); break; |
|---|
| 429 | case Image_map::Y: uv.set(cylindrical_angle(P.x(), P.z()), P.y()); break; |
|---|
| 430 | case Image_map::Z: uv.set(cylindrical_angle(P.x(), -P.y()), P.z()); break; |
|---|
| 431 | default: ; |
|---|
| 432 | } |
|---|
| 433 | uv.x() *= block.get_image_map().wrap_amount_w; |
|---|
| 434 | uv += osg::Vec2(0, 0.5f); |
|---|
| 435 | } |
|---|
| 436 | |
|---|
| 437 | if (block.get_image_map().projection == Image_map::SPHERICAL) { |
|---|
| 438 | float r = P.length(); |
|---|
| 439 | if (r != 0) { |
|---|
| 440 | switch (axis) { |
|---|
| 441 | case Image_map::X: uv.set(cylindrical_angle(-P.z(), -P.y()), (asinf(P.x()/r) + osg::PI_2) / osg::PI); break; |
|---|
| 442 | case Image_map::Y: uv.set(cylindrical_angle(P.x(), P.z()), (asinf(P.y()/r) + osg::PI_2) / osg::PI); break; |
|---|
| 443 | case Image_map::Z: uv.set(cylindrical_angle(P.x(), -P.y()), (asinf(P.z()/r) + osg::PI_2) / osg::PI); break; |
|---|
| 444 | default: ; |
|---|
| 445 | } |
|---|
| 446 | } |
|---|
| 447 | uv.x() *= block.get_image_map().wrap_amount_w; |
|---|
| 448 | uv.y() *= block.get_image_map().wrap_amount_h; |
|---|
| 449 | } |
|---|
| 450 | |
|---|
| 451 | (*new_map.get())[p] = osg::Vec4(uv.x(), uv.y(), 0, 0); |
|---|
| 452 | } |
|---|
| 453 | } |
|---|
| 454 | } |
|---|
| 455 | } |
|---|
| 456 | |
|---|
| 457 | block.get_image_map().uv_map = map_name; |
|---|
| 458 | block.get_image_map().projection = Image_map::UV; |
|---|
| 459 | } |
|---|
| 460 | } |
|---|
| 461 | } |
|---|
| 462 | } |
|---|