| 1 | #include "Normals.h" |
|---|
| 2 | |
|---|
| 3 | using namespace osg; |
|---|
| 4 | |
|---|
| 5 | Normals::Normals( Node *node, float scale, Mode mode ) |
|---|
| 6 | { |
|---|
| 7 | setName(mode == VertexNormals ? "VertexNormals" : "SurfaceNormals"); |
|---|
| 8 | |
|---|
| 9 | MakeNormalsVisitor mnv(scale,mode); |
|---|
| 10 | node->accept( mnv ); |
|---|
| 11 | |
|---|
| 12 | ref_ptr<Vec3Array> coords = mnv.getCoords(); |
|---|
| 13 | ref_ptr<Vec4Array> colors = new Vec4Array; |
|---|
| 14 | if( mode == SurfaceNormals ) |
|---|
| 15 | colors->push_back( Vec4( 0, 1, 0, 1 )); |
|---|
| 16 | else if( mode == VertexNormals ) |
|---|
| 17 | colors->push_back( Vec4( 1, 0, 0, 1 )); |
|---|
| 18 | |
|---|
| 19 | ref_ptr<Geometry> geom = new Geometry; |
|---|
| 20 | geom->setVertexArray( coords.get() ); |
|---|
| 21 | geom->setColorArray( colors.get() ); |
|---|
| 22 | geom->setColorBinding( Geometry::BIND_OVERALL ); |
|---|
| 23 | |
|---|
| 24 | geom->addPrimitiveSet( new DrawArrays( PrimitiveSet::LINES, 0, coords->size())); |
|---|
| 25 | |
|---|
| 26 | StateSet *sset = new StateSet; |
|---|
| 27 | sset->setMode( GL_LIGHTING, StateAttribute::OFF); |
|---|
| 28 | geom->setStateSet( sset ); |
|---|
| 29 | addDrawable( geom.get() ); |
|---|
| 30 | } |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | |
|---|
| 34 | Normals::MakeNormalsVisitor::MakeNormalsVisitor( float normalScale, Mode mode): |
|---|
| 35 | NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN), |
|---|
| 36 | _normal_scale(normalScale), |
|---|
| 37 | _mode(mode) |
|---|
| 38 | { |
|---|
| 39 | _local_coords = new Vec3Array; |
|---|
| 40 | _mat = osg::Matrix::identity(); |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | void Normals::MakeNormalsVisitor::apply(osg::MatrixTransform& tx) |
|---|
| 45 | { |
|---|
| 46 | _matStack.push( _mat ); |
|---|
| 47 | _mat = _mat * tx.getMatrix(); |
|---|
| 48 | |
|---|
| 49 | traverse( tx ); |
|---|
| 50 | |
|---|
| 51 | _mat = _matStack.top(); |
|---|
| 52 | _matStack.pop(); |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | void Normals::MakeNormalsVisitor::apply( Geode &geode ) |
|---|
| 56 | { |
|---|
| 57 | for( unsigned int i = 0; i < geode.getNumDrawables(); i++ ) |
|---|
| 58 | { |
|---|
| 59 | Geometry *geom = dynamic_cast<Geometry *>(geode.getDrawable(i)); |
|---|
| 60 | if( geom ) |
|---|
| 61 | { |
|---|
| 62 | Vec3Array *coords = dynamic_cast<Vec3Array*>(geom->getVertexArray()); |
|---|
| 63 | if( coords == 0L ) |
|---|
| 64 | continue; |
|---|
| 65 | |
|---|
| 66 | Vec3Array *normals = dynamic_cast<Vec3Array*>(geom->getNormalArray()); |
|---|
| 67 | if( normals == 0L ) |
|---|
| 68 | continue; |
|---|
| 69 | |
|---|
| 70 | Geometry::AttributeBinding binding = geom->getNormalBinding(); |
|---|
| 71 | if( binding == Geometry::BIND_OFF ) |
|---|
| 72 | continue; |
|---|
| 73 | |
|---|
| 74 | if( binding == Geometry::BIND_OVERALL ) |
|---|
| 75 | { |
|---|
| 76 | Vec3 v(0,0,0); |
|---|
| 77 | Vec3 n = normals->front(); |
|---|
| 78 | |
|---|
| 79 | Vec3Array::iterator coord_index = coords->begin(); |
|---|
| 80 | while( coord_index != coords->end() ) |
|---|
| 81 | v += *(coord_index++) * _mat; |
|---|
| 82 | v /= (float)(coords->size()); |
|---|
| 83 | |
|---|
| 84 | n *= _normal_scale; |
|---|
| 85 | _local_coords->push_back( v ); |
|---|
| 86 | _local_coords->push_back( (v + n)); |
|---|
| 87 | } |
|---|
| 88 | else |
|---|
| 89 | { |
|---|
| 90 | Geometry::PrimitiveSetList& primitiveSets = geom->getPrimitiveSetList(); |
|---|
| 91 | Geometry::PrimitiveSetList::iterator itr; |
|---|
| 92 | |
|---|
| 93 | Vec3Array::iterator coord_index = coords->begin(); |
|---|
| 94 | Vec3Array::iterator normals_index = normals->begin(); |
|---|
| 95 | |
|---|
| 96 | for(itr=primitiveSets.begin(); itr!=primitiveSets.end(); ++itr) |
|---|
| 97 | { |
|---|
| 98 | #ifdef DEBUG |
|---|
| 99 | _printPrimitiveType( (*itr).get() ); |
|---|
| 100 | #endif |
|---|
| 101 | if( binding == Geometry::BIND_PER_PRIMITIVE_SET ) |
|---|
| 102 | { |
|---|
| 103 | Vec3 v(0,0,0); |
|---|
| 104 | Vec3 n = *(normals_index++); |
|---|
| 105 | int ni = (*itr)->getNumIndices(); |
|---|
| 106 | for( int i = 0; i < ni; i++ ) |
|---|
| 107 | v += *(coord_index++) * _mat; |
|---|
| 108 | v /= (float)(ni); |
|---|
| 109 | |
|---|
| 110 | n *= _normal_scale; |
|---|
| 111 | _local_coords->push_back( v ); |
|---|
| 112 | _local_coords->push_back( (v + n)); |
|---|
| 113 | } |
|---|
| 114 | else |
|---|
| 115 | { |
|---|
| 116 | switch((*itr)->getMode()) |
|---|
| 117 | { |
|---|
| 118 | case(PrimitiveSet::TRIANGLES): |
|---|
| 119 | { |
|---|
| 120 | for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ ) |
|---|
| 121 | { |
|---|
| 122 | _processPrimitive( 3, coord_index, normals_index, binding ); |
|---|
| 123 | coord_index += 3; |
|---|
| 124 | if( binding == Geometry::BIND_PER_PRIMITIVE ) |
|---|
| 125 | normals_index++; |
|---|
| 126 | else |
|---|
| 127 | normals_index+=3; |
|---|
| 128 | } |
|---|
| 129 | break; |
|---|
| 130 | } |
|---|
| 131 | case(PrimitiveSet::TRIANGLE_STRIP): |
|---|
| 132 | { |
|---|
| 133 | for( unsigned int j = 0; j < (*itr)->getNumIndices()-2; j++ ) |
|---|
| 134 | { |
|---|
| 135 | _processPrimitive( 3, coord_index, normals_index, binding ); |
|---|
| 136 | coord_index++; |
|---|
| 137 | normals_index++; |
|---|
| 138 | } |
|---|
| 139 | coord_index += 2; |
|---|
| 140 | if( binding == Geometry::BIND_PER_VERTEX ) |
|---|
| 141 | normals_index += 2; |
|---|
| 142 | break; |
|---|
| 143 | } |
|---|
| 144 | case(PrimitiveSet::TRIANGLE_FAN): |
|---|
| 145 | break; |
|---|
| 146 | |
|---|
| 147 | case(PrimitiveSet::QUADS): |
|---|
| 148 | { |
|---|
| 149 | for( unsigned int j = 0; j < (*itr)->getNumPrimitives(); j++ ) |
|---|
| 150 | { |
|---|
| 151 | _processPrimitive( 4, coord_index, normals_index, binding ); |
|---|
| 152 | coord_index += 4; |
|---|
| 153 | if( binding == Geometry::BIND_PER_PRIMITIVE ) |
|---|
| 154 | normals_index++; |
|---|
| 155 | else |
|---|
| 156 | normals_index+=4; |
|---|
| 157 | } |
|---|
| 158 | break; |
|---|
| 159 | } |
|---|
| 160 | case(PrimitiveSet::QUAD_STRIP): |
|---|
| 161 | break; |
|---|
| 162 | |
|---|
| 163 | case(PrimitiveSet::POLYGON): |
|---|
| 164 | { |
|---|
| 165 | DrawArrayLengths* dal = dynamic_cast<DrawArrayLengths*>((*itr).get()); |
|---|
| 166 | if (dal) { |
|---|
| 167 | for (unsigned int j = 0; j < dal->size(); ++j) { |
|---|
| 168 | unsigned int num_prim = (*dal)[j]; |
|---|
| 169 | |
|---|
| 170 | _processPrimitive(num_prim, coord_index, normals_index, binding); |
|---|
| 171 | coord_index += num_prim; |
|---|
| 172 | if (binding == Geometry::BIND_PER_PRIMITIVE) { |
|---|
| 173 | ++normals_index; |
|---|
| 174 | } else { |
|---|
| 175 | normals_index += num_prim; |
|---|
| 176 | } |
|---|
| 177 | } |
|---|
| 178 | } |
|---|
| 179 | break; |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | default: |
|---|
| 183 | break; |
|---|
| 184 | } |
|---|
| 185 | } |
|---|
| 186 | } |
|---|
| 187 | } |
|---|
| 188 | } |
|---|
| 189 | } |
|---|
| 190 | traverse( geode ); |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | |
|---|
| 194 | void Normals::MakeNormalsVisitor::_processPrimitive( unsigned int nv, |
|---|
| 195 | Vec3Array::iterator coords, |
|---|
| 196 | Vec3Array::iterator normals, |
|---|
| 197 | Geometry::AttributeBinding binding ) |
|---|
| 198 | { |
|---|
| 199 | Vec3 v(0,0,0); |
|---|
| 200 | Vec3 n(0,0,0); |
|---|
| 201 | if( _mode == SurfaceNormals || binding == Geometry::BIND_PER_PRIMITIVE ) |
|---|
| 202 | { |
|---|
| 203 | if( binding == Geometry::BIND_PER_PRIMITIVE ) |
|---|
| 204 | { |
|---|
| 205 | n = *(normals++); |
|---|
| 206 | } |
|---|
| 207 | else if( binding == Geometry::BIND_PER_VERTEX ) |
|---|
| 208 | { |
|---|
| 209 | for( unsigned int i = 0; i < nv; i++ ) |
|---|
| 210 | n += *(normals++); |
|---|
| 211 | n /= (float)(nv); |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | for( unsigned int i = 0; i < nv; i++ ) |
|---|
| 215 | v += *(coords++) * _mat; |
|---|
| 216 | v /= (float)(nv); |
|---|
| 217 | |
|---|
| 218 | n *= _normal_scale; |
|---|
| 219 | _local_coords->push_back( v ); |
|---|
| 220 | _local_coords->push_back( (v + n)); |
|---|
| 221 | } |
|---|
| 222 | else if( _mode == VertexNormals ) |
|---|
| 223 | { |
|---|
| 224 | for( unsigned int i = 0; i < nv; i++ ) |
|---|
| 225 | { |
|---|
| 226 | v = *(coords++) * _mat; |
|---|
| 227 | n = *(normals++); |
|---|
| 228 | n *= _normal_scale; |
|---|
| 229 | _local_coords->push_back( v ); |
|---|
| 230 | _local_coords->push_back( (v + n)); |
|---|
| 231 | } |
|---|
| 232 | } |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | #ifdef DEBUG |
|---|
| 236 | void Normals::_printPrimitiveType( osg::PrimitiveSet *pset ) |
|---|
| 237 | { |
|---|
| 238 | std::cout << ( |
|---|
| 239 | pset->getMode() == PrimitiveSet::POINTS ? "POINTS" : |
|---|
| 240 | pset->getMode() == PrimitiveSet::LINES ? "LINES" : |
|---|
| 241 | pset->getMode() == PrimitiveSet::LINE_STRIP ? "LINE_STRIP" : |
|---|
| 242 | pset->getMode() == PrimitiveSet::LINE_LOOP ? "LINE_LOOP" : |
|---|
| 243 | pset->getMode() == PrimitiveSet::TRIANGLES ? "TRIANGLES" : |
|---|
| 244 | pset->getMode() == PrimitiveSet::TRIANGLE_STRIP ? "TRIANGLE_STRIP" : |
|---|
| 245 | pset->getMode() == PrimitiveSet::TRIANGLE_FAN ? "TRIANGLE_FAN" : |
|---|
| 246 | pset->getMode() == PrimitiveSet::QUADS ? "QUADS" : |
|---|
| 247 | pset->getMode() == PrimitiveSet::QUAD_STRIP ? "QUAD_STRIP" : |
|---|
| 248 | pset->getMode() == PrimitiveSet::POLYGON ? "POLYGON" : "Dunno" ) << std::endl; |
|---|
| 249 | } |
|---|
| 250 | #endif |
|---|