1 /*******************************************************
2       Lightwave Object Loader for OSG
3 
4   Copyright (C) 2004 Marco Jez <marco.jez@poste.it>
5   OpenSceneGraph is (C) 2004 Robert Osfield
6 ********************************************************/
7 
8 #include "Block.h"
9 
10 #include <osg/Notify>
11 #include <osg/Matrix>
12 
13 using namespace lwosg;
14 
Block(const lwo2::FORM::SURF::BLOK * blok)15 Block::Block(const lwo2::FORM::SURF::BLOK *blok)
16 :    enabled_(true),
17     opacity_type_(ADDITIVE),
18     opacity_amount_(1),
19     displacement_axis_(X)
20 {
21     if (blok) {
22         compile(blok);
23     }
24 }
25 
read_common_attributes(const iff::Chunk_list & subchunks)26 void Block::read_common_attributes(const iff::Chunk_list &subchunks)
27 {
28     for (iff::Chunk_list::const_iterator i=subchunks.begin(); i!=subchunks.end(); ++i) {
29         const lwo2::FORM::SURF::BLOK::CHAN *chan = dynamic_cast<const lwo2::FORM::SURF::BLOK::CHAN *>(*i);
30         if (chan) {
31             channel_ = std::string(chan->texture_channel.id, 4);
32         }
33         const lwo2::FORM::SURF::BLOK::ENAB *enab = dynamic_cast<const lwo2::FORM::SURF::BLOK::ENAB *>(*i);
34         if (enab) {
35             enabled_ = enab->enable != 0;
36         }
37         const lwo2::FORM::SURF::BLOK::OPAC *opac = dynamic_cast<const lwo2::FORM::SURF::BLOK::OPAC *>(*i);
38         if (opac) {
39             opacity_type_ = static_cast<Opacity_type>(opac->type);
40             opacity_amount_ = opac->opacity.fraction;
41         }
42         const lwo2::FORM::SURF::BLOK::AXIS *axis = dynamic_cast<const lwo2::FORM::SURF::BLOK::AXIS *>(*i);
43         if (axis) {
44             displacement_axis_ = static_cast<Axis_type>(axis->displacement_axis);
45         }
46     }
47 }
48 
compile(const lwo2::FORM::SURF::BLOK * blok)49 void Block::compile(const lwo2::FORM::SURF::BLOK *blok)
50 {
51     const lwo2::FORM::SURF::BLOK::IMAP *imap = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP *>(blok->header);
52     if (imap) {
53         type_ = "IMAP";
54         ordinal_ = imap->ordinal;
55 
56         // read common parameters
57         read_common_attributes(imap->block_attributes);
58 
59         // read imagemap-related attributes
60         for (iff::Chunk_list::const_iterator bi=blok->attributes.begin(); bi!=blok->attributes.end(); ++bi) {
61             const lwo2::FORM::SURF::BLOK::IMAP::TMAP *tmap = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP *>(*bi);
62             if (tmap) {
63                 Texture_mapping mapping;
64                 for (iff::Chunk_list::const_iterator i=tmap->attributes.begin(); i!=tmap->attributes.end(); ++i) {
65                     const lwo2::FORM::SURF::BLOK::IMAP::TMAP::CNTR *cntr = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP::CNTR *>(*i);
66                     if (cntr) {
67                         mapping.center_ = osg::Vec3(cntr->vector.X, cntr->vector.Y, cntr->vector.Z);
68                     }
69                     const lwo2::FORM::SURF::BLOK::IMAP::TMAP::SIZE *size = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP::SIZE *>(*i);
70                     if (size) {
71                         mapping.size_ = osg::Vec3(size->vector.X, size->vector.Y, size->vector.Z);
72                     }
73                     const lwo2::FORM::SURF::BLOK::IMAP::TMAP::ROTA *rota = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP::ROTA *>(*i);
74                     if (rota) {
75                         mapping.rotation_ = osg::Vec3(rota->vector.X, rota->vector.Y, rota->vector.Z);
76                     }
77                     const lwo2::FORM::SURF::BLOK::IMAP::TMAP::CSYS *csys = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TMAP::CSYS *>(*i);
78                     if (csys) {
79                         mapping.csys_ = static_cast<Texture_mapping::Coordinate_system_type>(csys->type);
80                     }
81                 }
82                 imap_.mapping = mapping;
83             }
84 
85             const lwo2::FORM::SURF::BLOK::IMAP::PROJ *proj = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::PROJ *>(*bi);
86             if (proj) {
87                 imap_.projection = static_cast<Image_map::Projection_mode>(proj->projection_mode);
88             }
89 
90             const lwo2::FORM::SURF::BLOK::IMAP::AXIS *axis = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::AXIS *>(*bi);
91             if (axis) {
92                 imap_.axis = static_cast<Image_map::Axis_type>(axis->texture_axis);
93             }
94 
95             const lwo2::FORM::SURF::BLOK::IMAP::IMAG *imag = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::IMAG *>(*bi);
96             if (imag) {
97                 imap_.image_map = imag->texture_image.index;
98             }
99 
100             const lwo2::FORM::SURF::BLOK::IMAP::WRAP *wrap = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::WRAP *>(*bi);
101             if (wrap) {
102                 imap_.width_wrap = static_cast<Image_map::Wrap_type>(wrap->width_wrap);
103                 imap_.height_wrap = static_cast<Image_map::Wrap_type>(wrap->height_wrap);
104             }
105 
106             const lwo2::FORM::SURF::BLOK::IMAP::WRPW *wrpw = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::WRPW *>(*bi);
107             if (wrpw) {
108                 imap_.wrap_amount_w = wrpw->cycles.fraction;
109             }
110 
111             const lwo2::FORM::SURF::BLOK::IMAP::WRPH *wrph = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::WRPH *>(*bi);
112             if (wrph) {
113                 imap_.wrap_amount_h = wrph->cycles.fraction;
114             }
115 
116             const lwo2::FORM::SURF::BLOK::IMAP::VMAP *vmap = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::VMAP *>(*bi);
117             if (vmap) {
118                 imap_.uv_map = vmap->txuv_map_name;
119             }
120 
121             const lwo2::FORM::SURF::BLOK::IMAP::TAMP *tamp = dynamic_cast<const lwo2::FORM::SURF::BLOK::IMAP::TAMP *>(*bi);
122             if (tamp) {
123                 imap_.texture_amplitude = tamp->amplitude.fraction;
124             }
125         }
126 
127     } else {
128         OSG_WARN << "Warning: lwosg::Block: only IMAP (image map) block types are supported, this block will be ignored" << std::endl;
129     }
130 }
131 
setup_texture_point(const osg::Vec3 & P) const132 osg::Vec3 Block::setup_texture_point(const osg::Vec3 &P) const
133 {
134     osg::Vec3 Q = P;
135 
136     const osg::Vec3 &ypr = imap_.mapping.rotation_;
137     Q -= imap_.mapping.center_;
138     Q = Q * osg::Matrix::rotate(ypr.z(), osg::Vec3(0, 0, -1));
139     Q = Q * osg::Matrix::rotate(ypr.x(), osg::Vec3(0, 1, 0));
140     Q = Q * osg::Matrix::rotate(ypr.y(), osg::Vec3(-1, 0, 0));
141     if (imap_.projection != Image_map::SPHERICAL) {
142         Q.x() *= 1/imap_.mapping.size_.x();
143         Q.y() *= 1/imap_.mapping.size_.y();
144         Q.z() *= 1/imap_.mapping.size_.z();
145     }
146 
147     return Q;
148 }
149