void apply(osg::Geometry& geom) { geom.setUseDisplayList(false); if (!_manualVertexAliasing) return; osg::notify(osg::NOTICE)<<"Found geometry "<<&geom<<std::endl; if (geom.getVertexArray()) { setVertexAttrib(geom, _vertexAlias, geom.getVertexArray(), false, osg::Array::BIND_PER_VERTEX); geom.setVertexArray(0); } if (geom.getNormalArray()) { setVertexAttrib(geom, _normalAlias, geom.getNormalArray(), true); geom.setNormalArray(0); } if (geom.getColorArray()) { setVertexAttrib(geom, _colorAlias, geom.getColorArray(), false); geom.setColorArray(0); } if (geom.getSecondaryColorArray()) { setVertexAttrib(geom, _secondaryColorAlias, geom.getSecondaryColorArray(), false); geom.setSecondaryColorArray(0); } if (geom.getFogCoordArray()) { // should we normalize the FogCoord array? Don't think so... setVertexAttrib(geom, _fogCoordAlias, geom.getFogCoordArray(), false); geom.setFogCoordArray(0); } unsigned int maxNumTexCoords = geom.getNumTexCoordArrays(); if (maxNumTexCoords>8) { osg::notify(osg::NOTICE)<<"Warning: Ignoring "<<maxNumTexCoords-8<<" texture coordinate arrays, only 8 are currently supported in vertex attribute conversion code."<<std::endl; maxNumTexCoords = 8; } for(unsigned int i=0; i<maxNumTexCoords; ++i) { if (geom.getTexCoordArray(i)) { setVertexAttrib(geom, _texCoordAlias[i], geom.getTexCoordArray(i), false, osg::Array::BIND_PER_VERTEX); geom.setTexCoordArray(i,0); } else { osg::notify(osg::NOTICE)<<"Found empty TexCoordArray("<<i<<")"<<std::endl; } } }
void RigGeometry::copyFrom(osg::Geometry& from) { bool copyToSelf = (this==&from); osg::Geometry& target = *this; if (!copyToSelf) target.setStateSet(from.getStateSet()); // copy over primitive sets. if (!copyToSelf) target.getPrimitiveSetList() = from.getPrimitiveSetList(); if (from.getVertexArray()) { if (!copyToSelf) target.setVertexArray(from.getVertexArray()); } if (from.getNormalArray()) { if (!copyToSelf) target.setNormalArray(from.getNormalArray()); } if (from.getColorArray()) { if (!copyToSelf) target.setColorArray(from.getColorArray()); } if (from.getSecondaryColorArray()) { if (!copyToSelf) target.setSecondaryColorArray(from.getSecondaryColorArray()); } if (from.getFogCoordArray()) { if (!copyToSelf) target.setFogCoordArray(from.getFogCoordArray()); } for(unsigned int ti=0;ti<from.getNumTexCoordArrays();++ti) { if (from.getTexCoordArray(ti)) { if (!copyToSelf) target.setTexCoordArray(ti,from.getTexCoordArray(ti)); } } osg::Geometry::ArrayList& arrayList = from.getVertexAttribArrayList(); for(unsigned int vi=0;vi< arrayList.size();++vi) { osg::Array* array = arrayList[vi].get(); if (array) { if (!copyToSelf) target.setVertexAttribArray(vi,array); } } }
VertexAttribComparitor(osg::Geometry& geometry) { add(geometry.getVertexArray()); add(geometry.getNormalArray()); add(geometry.getColorArray()); add(geometry.getSecondaryColorArray()); add(geometry.getFogCoordArray()); unsigned int i; for(i=0;i<geometry.getNumTexCoordArrays();++i) { add(geometry.getTexCoordArray(i)); } for(i=0;i<geometry.getNumVertexAttribArrays();++i) { add(geometry.getVertexAttribArray(i)); } }
void FltExportVisitor::writeLocalVertexPool( const osg::Geometry& geom ) { // Attribute Mask static const unsigned int HAS_POSITION = 0x80000000u >> 0; // static const unsigned int HAS_COLOR_INDEX = 0x80000000u >> 1; static const unsigned int HAS_RGBA_COLOR = 0x80000000u >> 2; static const unsigned int HAS_NORMAL = 0x80000000u >> 3; static const unsigned int HAS_BASE_UV = 0x80000000u >> 4; static const unsigned int HAS_UV_LAYER1 = 0x80000000u >> 5; static const unsigned int HAS_UV_LAYER2 = 0x80000000u >> 6; static const unsigned int HAS_UV_LAYER3 = 0x80000000u >> 7; static const unsigned int HAS_UV_LAYER4 = 0x80000000u >> 8; static const unsigned int HAS_UV_LAYER5 = 0x80000000u >> 9; static const unsigned int HAS_UV_LAYER6 = 0x80000000u >> 10; static const unsigned int HAS_UV_LAYER7 = 0x80000000u >> 11; const osg::Array* v = geom.getVertexArray(); uint32 numVerts( v->getNumElements() ); osg::ref_ptr< const osg::Vec3dArray > v3 = VertexPaletteManager::asVec3dArray( v, numVerts ); if (!v3) { std::string warning( "fltexp: writeLocalVertexPool: VertexArray is not Vec3Array." ); osg::notify( osg::WARN ) << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); return; } // Compute attribute bits and vertex size. const osg::Array* c = geom.getColorArray(); const osg::Array* n = geom.getNormalArray(); const osg::Array* t = geom.getTexCoordArray( 0 ); osg::ref_ptr< const osg::Vec4Array > c4 = VertexPaletteManager::asVec4Array( c, numVerts ); osg::ref_ptr< const osg::Vec3Array > n3 = VertexPaletteManager::asVec3Array( n, numVerts ); osg::ref_ptr< const osg::Vec2Array > t2 = VertexPaletteManager::asVec2Array( t, numVerts ); if (c && !c4) return; if (n && !n3) return; if (t && !t2) return; std::vector< osg::ref_ptr< const osg::Vec2Array > > mtc; mtc.resize( 8 ); int unit=1; for( ;unit<8; unit++) mtc[ unit ] = VertexPaletteManager::asVec2Array( geom.getTexCoordArray( unit ), numVerts ); uint32 attr( HAS_POSITION ); unsigned int vertSize( sizeof( float64 ) * 3 ); if ( ( c4 != NULL ) && ( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX) ) { attr |= HAS_RGBA_COLOR; vertSize += sizeof( unsigned int ); } if ( ( n3 != NULL ) && ( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) ) { attr |= HAS_NORMAL; vertSize += ( sizeof( float32 ) * 3 ); } if ( t2 != NULL ) { attr |= HAS_BASE_UV; vertSize += ( sizeof( float32 ) * 2 ); } // Add multitex if (isTextured( 1, geom )) { attr |= HAS_UV_LAYER1; vertSize += ( sizeof( float32 ) * 2 ); } if (isTextured( 2, geom )) { attr |= HAS_UV_LAYER2; vertSize += ( sizeof( float32 ) * 2 ); } if (isTextured( 3, geom )) { attr |= HAS_UV_LAYER3; vertSize += ( sizeof( float32 ) * 2 ); } if (isTextured( 4, geom )) { attr |= HAS_UV_LAYER4; vertSize += ( sizeof( float32 ) * 2 ); } if (isTextured( 5, geom )) { attr |= HAS_UV_LAYER5; vertSize += ( sizeof( float32 ) * 2 ); } if (isTextured( 6, geom )) { attr |= HAS_UV_LAYER6; vertSize += ( sizeof( float32 ) * 2 ); } if (isTextured( 7, geom )) { attr |= HAS_UV_LAYER7; vertSize += ( sizeof( float32 ) * 2 ); } unsigned int maxVerts = (0xffff - 12) / vertSize; unsigned int thisVertCount = (maxVerts > numVerts) ? numVerts : maxVerts; unsigned int currentIndexLimit = maxVerts; uint16 length( 12 + (vertSize * thisVertCount) ); _records->writeInt16( (int16) LOCAL_VERTEX_POOL_OP ); _records->writeUInt16( length ); _records->writeUInt32( numVerts ); // number of vertices _records->writeUInt32( attr ); // attribute bits unsigned int idx; for( idx=0; idx<numVerts; idx++ ) { _records->writeVec3d( (*v3)[ idx ] ); if (attr & HAS_RGBA_COLOR) { osg::Vec4 color = (*c4)[ idx ]; unsigned int packedColor = (int)(color[3]*255) << 24 | (int)(color[2]*255) << 16 | (int)(color[1]*255) << 8 | (int)(color[0]*255); _records->writeUInt32( packedColor ); } if (attr & HAS_NORMAL) _records->writeVec3f( (*n3)[ idx ] ); if (attr & HAS_BASE_UV) _records->writeVec2f( (*t2)[ idx ] ); if (attr & HAS_UV_LAYER1) _records->writeVec2f( (*mtc[1])[ idx ] ); if (attr & HAS_UV_LAYER2) _records->writeVec2f( (*mtc[2])[ idx ] ); if (attr & HAS_UV_LAYER3) _records->writeVec2f( (*mtc[3])[ idx ] ); if (attr & HAS_UV_LAYER4) _records->writeVec2f( (*mtc[4])[ idx ] ); if (attr & HAS_UV_LAYER5) _records->writeVec2f( (*mtc[5])[ idx ] ); if (attr & HAS_UV_LAYER6) _records->writeVec2f( (*mtc[6])[ idx ] ); if (attr & HAS_UV_LAYER7) _records->writeVec2f( (*mtc[7])[ idx ] ); // Handle continuation record if necessary. if ( (idx+1 == currentIndexLimit) && (idx+1 < numVerts) ) { currentIndexLimit += maxVerts; unsigned int remaining( numVerts - (idx+1) ); thisVertCount = (maxVerts > remaining) ? remaining : maxVerts; writeContinuationRecord( (vertSize * thisVertCount) ); } } }
void FltExportVisitor::writeMesh( const osg::Geode& geode, const osg::Geometry& geom ) { enum DrawMode { SOLID_BACKFACE = 0, SOLID_NO_BACKFACE = 1, WIREFRAME_CLOSED = 2, WIREFRAME_NOT_CLOSED = 3, SURROUND_ALTERNATE_COLOR = 4, OMNIDIRECTIONAL_LIGHT = 8, UNIDIRECTIONAL_LIGHT = 9, BIDIRECTIONAL_LIGHT = 10 }; enum TemplateMode { FIXED_NO_ALPHA_BLENDING = 0, FIXED_ALPHA_BLENDING = 1, AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2, POINT_ROTATE_WITH_ALPHA_BLENDING = 4 }; // const unsigned int TERRAIN_BIT = 0x80000000u >> 0; //const unsigned int NO_COLOR_BIT = 0x80000000u >> 1; //const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2; const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3; //const unsigned int FOOTPRINT_BIT = 0x80000000u >> 4; // Terrain culture cutout const unsigned int HIDDEN_BIT = 0x80000000u >> 5; //const unsigned int ROOFLINE_BIT = 0x80000000u >> 6; uint32 flags( PACKED_COLOR_BIT ); if (geode.getNodeMask() == 0) flags |= HIDDEN_BIT; enum LightMode { FACE_COLOR = 0, VERTEX_COLOR = 1, FACE_COLOR_LIGHTING = 2, VERTEX_COLOR_LIGHTING = 3 }; int8 lightMode; osg::Vec4 packedColorRaw( 1., 1., 1., 1. ); uint16 transparency( 0 ); if (geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX) { if (isLit( geom )) lightMode = VERTEX_COLOR_LIGHTING; else lightMode = VERTEX_COLOR; } else { const osg::Vec4Array* c = dynamic_cast<const osg::Vec4Array*>( geom.getColorArray() ); if (c && (c->size() > 0)) { packedColorRaw = (*c)[0]; transparency = flt::uint16((1. - packedColorRaw[3]) * (double)0xffff); } if (isLit( geom )) lightMode = FACE_COLOR_LIGHTING; else lightMode = FACE_COLOR; } uint32 packedColor; packedColor = (int)(packedColorRaw[3]*255) << 24 | (int)(packedColorRaw[2]*255) << 16 | (int)(packedColorRaw[1]*255) << 8 | (int)(packedColorRaw[0]*255); int8 drawType; osg::StateSet const* ss = getCurrentStateSet(); { // Default to no facet culling drawType = SOLID_NO_BACKFACE; // If facet-culling isn't *dis*abled, check whether the CullFace mode is BACK if (ss->getMode(GL_CULL_FACE) & osg::StateAttribute::ON) { osg::CullFace const* cullFace = static_cast<osg::CullFace const*>( ss->getAttribute(osg::StateAttribute::CULLFACE) ); if( cullFace->getMode() == osg::CullFace::BACK ) drawType = SOLID_BACKFACE; // Note: OpenFlt can't handle FRONT or FRONT_AND_BACK settings, so ignore these(??) } } // Determine the material properties for the face int16 materialIndex( -1 ); if (isLit( geom )) { osg::Material const* currMaterial = static_cast<osg::Material const*>( ss->getAttribute(osg::StateAttribute::MATERIAL) ); materialIndex = _materialPalette->add(currMaterial); } // Get base texture int16 textureIndex( -1 ); if (isTextured( 0, geom )) { const osg::Texture2D* texture = static_cast<const osg::Texture2D*>( ss->getTextureAttribute( 0, osg::StateAttribute::TEXTURE ) ); if (texture != NULL) textureIndex = _texturePalette->add( 0, texture ); else { std::string warning( "fltexp: Mesh is textured, but Texture2D StateAttribute is NULL." ); osg::notify( osg::WARN ) << warning << std::endl; _fltOpt->getWriteResult().warn( warning ); } } // Set the appropriate template mode based // on blending or Billboarding. TemplateMode templateMode( FIXED_NO_ALPHA_BLENDING ); const osg::Billboard* bb = dynamic_cast< const osg::Billboard* >( &geode ); if (bb != NULL) { if( bb->getMode() == osg::Billboard::AXIAL_ROT ) templateMode = AXIAL_ROTATE_WITH_ALPHA_BLENDING; else templateMode = POINT_ROTATE_WITH_ALPHA_BLENDING; } else if ( ss->getMode( GL_BLEND ) & osg::StateAttribute::ON ) { const osg::BlendFunc* bf = static_cast<const osg::BlendFunc*>( ss->getAttribute(osg::StateAttribute::BLENDFUNC) ); if( (bf->getSource() == osg::BlendFunc::SRC_ALPHA) && (bf->getDestination() == osg::BlendFunc::ONE_MINUS_SRC_ALPHA) ) templateMode = FIXED_ALPHA_BLENDING; } uint16 length( 84 ); IdHelper id( *this, geode.getName() ); _records->writeInt16( (int16) MESH_OP ); _records->writeUInt16( length ); _records->writeID( id ); _records->writeInt32( 0 ); // Reserved _records->writeInt32( 0 ); // IR color code _records->writeInt16( 0 ); // Relative priority _records->writeInt8( drawType ); // Draw type _records->writeInt8( 0 ); // Texture white _records->writeInt16( -1 ); // Color name index _records->writeInt16( -1 ); // Alternate color name index _records->writeInt8( 0 ); // Reserved _records->writeInt8( templateMode ); // Template (billboard) _records->writeInt16( -1 ); // Detail texture pattern index _records->writeInt16( textureIndex ); // Texture pattern index _records->writeInt16( materialIndex ); // Material index _records->writeInt16( 0 ); // Surface material code _records->writeInt16( 0 ); // Feature ID _records->writeInt32( 0 ); // IR material code _records->writeUInt16( transparency ); // Transparency _records->writeInt8( 0 ); // LOD generation control _records->writeInt8( 0 ); // Line style index _records->writeUInt32( flags ); // Flags _records->writeInt8( lightMode ); // Light mode _records->writeFill( 7 ); // Reserved _records->writeUInt32( packedColor ); // Packed color, primary _records->writeUInt32( 0x00ffffff ); // Packed color, alternate _records->writeInt16( -1 ); // Texture mapping index _records->writeInt16( 0 ); // Reserved _records->writeInt32( -1 ); // Primary color index _records->writeInt32( -1 ); // Alternate color index // Next four bytes: // 15.8: two 2-byte "reserved" fields // 15.9: one 4-byte "reserved" field _records->writeInt16( 0 ); // Reserved _records->writeInt16( -1 ); // Shader index }
void GeometryValidator::apply(osg::Geometry& geom) { if ( geom.getVertexArray() == 0L ) { OE_NOTICE << LC << "NULL vertex array!!\n"; return; } unsigned numVerts = geom.getVertexArray()->getNumElements(); if ( numVerts == 0 ) { OE_NOTICE << LC << "No verts!! name=" << geom.getName() << "\n"; return; } #if OSG_VERSION_GREATER_OR_EQUAL(3,1,9) std::set<osg::BufferObject*> _vbos; osg::Geometry::ArrayList arrays; geom.getArrayList(arrays); for(unsigned i=0; i<arrays.size(); ++i) { osg::Array* a = arrays[i].get(); if ( a == NULL ) { OE_NOTICE << LC << "Found a NULL array\n"; } else if ( a->getBinding() == a->BIND_OVERALL && a->getNumElements() != 1 ) { OE_NOTICE << LC << "Found an array with BIND_OVERALL and size <> 1\n"; } else if ( a->getBinding() == a->BIND_PER_VERTEX && a->getNumElements() != numVerts ) { OE_NOTICE << LC << "Found BIND_PER_VERTEX with wrong number of elements (expecting " << numVerts << "; found " << a->getNumElements() << ")\n"; } _vbos.insert( a->getVertexBufferObject() ); } if ( _vbos.size() != 1 ) { OE_NOTICE << LC << "Found a Geometry that uses more than one VBO (non-optimal sharing)\n"; } #else // pre-3.1.9 ... phase out. if ( geom.getColorArray() ) { if ( geom.getColorBinding() == osg::Geometry::BIND_OVERALL && geom.getColorArray()->getNumElements() != 1 ) { OE_NOTICE << "Color: BIND_OVERALL with wrong number of elements" << std::endl; } else if ( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX && geom.getColorArray()->getNumElements() != numVerts ) { OE_NOTICE << "Color: BIND_PER_VERTEX with colors.size != verts.size" << std::endl; } } if ( geom.getNormalArray() ) { if ( geom.getNormalBinding() == osg::Geometry::BIND_OVERALL && geom.getNormalArray()->getNumElements() != 1 ) { OE_NOTICE << "Normal: BIND_OVERALL with wrong number of elements" << std::endl; } else if ( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX && geom.getNormalArray()->getNumElements() != numVerts ) { OE_NOTICE << "Normal: BIND_PER_VERTEX with normals.size != verts.size" << std::endl; } } #endif const osg::Geometry::PrimitiveSetList& plist = geom.getPrimitiveSetList(); std::set<osg::BufferObject*> _ebos; for( osg::Geometry::PrimitiveSetList::const_iterator p = plist.begin(); p != plist.end(); ++p ) { osg::PrimitiveSet* pset = p->get(); osg::DrawArrays* da = dynamic_cast<osg::DrawArrays*>(pset); if ( da ) { if ( da->getFirst() >= numVerts ) { OE_NOTICE << LC << "DrawArrays: first > numVerts\n"; } if ( da->getFirst()+da->getCount() > numVerts ) { OE_NOTICE << LC << "DrawArrays: first/count out of bounds\n"; } if ( da->getCount() < 1 ) { OE_NOTICE << LC << "DrawArrays: count is zero\n"; } } bool isDe = pset->getDrawElements() != 0L; osg::DrawElementsUByte* de_byte = dynamic_cast<osg::DrawElementsUByte*>(pset); if ( de_byte ) { validateDE(de_byte, 0xFF, numVerts ); _ebos.insert( de_byte->getElementBufferObject() ); } osg::DrawElementsUShort* de_short = dynamic_cast<osg::DrawElementsUShort*>(pset); if ( de_short ) { validateDE(de_short, 0xFFFF, numVerts ); _ebos.insert( de_short->getElementBufferObject() ); } osg::DrawElementsUInt* de_int = dynamic_cast<osg::DrawElementsUInt*>(pset); if ( de_int ) { validateDE(de_int, 0xFFFFFFFF, numVerts ); _ebos.insert( de_int->getElementBufferObject() ); } if ( pset->getNumIndices() == 0 ) { OE_NOTICE << LC << "Primset: num elements = 0; class=" << pset->className() << ", name=" << pset->getName() << "\n"; } else if ( pset->getType() >= GL_TRIANGLES && pset->getNumIndices() < 3 ) { OE_NOTICE << LC << "Primset: not enough indicies for surface prim type\n"; } else if ( pset->getType() >= GL_LINE_STRIP && pset->getNumIndices() < 2 ) { OE_NOTICE << LC << "Primset: not enough indicies for linear prim type\n"; } else if ( isDe && pset->getType() == GL_LINES && pset->getNumIndices() % 2 != 0 ) { OE_NOTICE << LC << "Primset: non-even index count for GL_LINES\n"; } } if ( _ebos.size() != 1 ) { OE_NOTICE << LC << "Found a Geometry that uses more than one EBO (non-optimal sharing)\n"; } }
void Tessellator::collectTessellation(osg::Geometry &geom, unsigned int originalIndex) { osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); VertexPtrToIndexMap vertexPtrToIndexMap; // populate the VertexPtrToIndexMap. for(unsigned int vi=0;vi<vertices->size();++vi) { vertexPtrToIndexMap[&((*vertices)[vi])] = vi; } handleNewVertices(geom, vertexPtrToIndexMap); // we don't properly handle per primitive and per primitive_set bindings yet // will need to address this soon. Robert Oct 2002. { osg::Vec3Array* normals = NULL; // GWM Sep 2002 - add normals for extra facets int iprim=0; if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE || geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET) { normals = dynamic_cast<osg::Vec3Array*>(geom.getNormalArray()); // GWM Sep 2002 } // GWM Dec 2003 - needed to add colours for extra facets osg::Vec4Array* cols4 = NULL; // GWM Dec 2003 colours are vec4 osg::Vec3Array* cols3 = NULL; // GWM Dec 2003 colours are vec3 if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE || geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET) { Array* colours = geom.getColorArray(); // GWM Dec 2003 - need to duplicate face colours switch (colours->getType()) { case osg::Array::Vec4ArrayType: cols4=dynamic_cast<osg::Vec4Array *> (colours); break; case osg::Array::Vec3ArrayType: cols3=dynamic_cast<osg::Vec3Array *> (colours); break; default: break; } } // GWM Dec 2003 - these holders need to go outside the loop to // retain the flat shaded colour &/or normal for each tessellated polygon osg::Vec3 norm(0.0f,0.0f,0.0f); osg::Vec4 primCol4(0.0f,0.0f,0.0f,1.0f); osg::Vec3 primCol3(0.0f,0.0f,0.0f); for(PrimList::iterator primItr=_primList.begin(); primItr!=_primList.end(); ++primItr, ++_index) { Prim* prim=primItr->get(); int ntris=0; if(vertexPtrToIndexMap.size() <= 255) { osg::DrawElementsUByte* elements = new osg::DrawElementsUByte(prim->_mode); for(Prim::VecList::iterator vitr=prim->_vertices.begin(); vitr!=prim->_vertices.end(); ++vitr) { elements->push_back(vertexPtrToIndexMap[*vitr]); } // add to the drawn primitive list. geom.addPrimitiveSet(elements); ntris=elements->getNumIndices()/3; } else if(vertexPtrToIndexMap.size() > 255 && vertexPtrToIndexMap.size() <= 65535) { osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(prim->_mode); for(Prim::VecList::iterator vitr=prim->_vertices.begin(); vitr!=prim->_vertices.end(); ++vitr) { elements->push_back(vertexPtrToIndexMap[*vitr]); } // add to the drawn primitive list. geom.addPrimitiveSet(elements); ntris=elements->getNumIndices()/3; } else { osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(prim->_mode); for(Prim::VecList::iterator vitr=prim->_vertices.begin(); vitr!=prim->_vertices.end(); ++vitr) { elements->push_back(vertexPtrToIndexMap[*vitr]); } // add to the drawn primitive list. geom.addPrimitiveSet(elements); ntris=elements->getNumIndices()/3; } if (primItr==_primList.begin()) { // first primitive so collect primitive normal & colour. if (normals) { if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) norm=(*normals)[originalIndex + _extraPrimitives]; else norm=(*normals)[iprim]; // GWM Sep 2002 the flat shaded normal } if (cols4) { primCol4=(*cols4)[iprim]; // GWM Dec 2003 the flat shaded rgba colour if (_index>=cols4->size()) { cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet } } if (cols3) { primCol3=(*cols3)[iprim]; // GWM Dec 2003 flat shaded rgb colour if (_index>=cols3->size()) { cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet } } } else { // later primitives use same colour if (normals) { if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { _extraPrimitives++; normals->insert(normals->begin() + originalIndex + _extraPrimitives, norm); } else normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet } if (cols4 && _index>=cols4->size()) { cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet } if (cols3 && _index>=cols3->size()) { if (cols3) cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet } if (prim->_mode==GL_TRIANGLES) { if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET || geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set. for (int ii=1; ii<ntris; ii++) { if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet } } if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET || geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set. for (int ii=1; ii<ntris; ii++) { if (cols3 && _index>=cols3->size()) { if (cols3) cols3->push_back(primCol3); } if (cols4 && _index>=cols4->size()) { if (cols4) cols4->push_back(primCol4); } _index++; } } } // osg::notify(osg::WARN)<<"Add: "<< iprim << std::endl; } iprim++; // GWM Sep 2002 count which normal we should use } } }
void Tessellator::handleNewVertices(osg::Geometry& geom,VertexPtrToIndexMap &vertexPtrToIndexMap) { if (!_newVertexList.empty()) { osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); osg::Vec3Array* normals = NULL; if (geom.getNormalBinding()==osg::Geometry::BIND_PER_VERTEX) { normals = dynamic_cast<osg::Vec3Array*>(geom.getNormalArray()); } typedef std::vector<osg::Array*> ArrayList; ArrayList arrays; if (geom.getColorBinding()==osg::Geometry::BIND_PER_VERTEX) { arrays.push_back(geom.getColorArray()); } if (geom.getSecondaryColorBinding()==osg::Geometry::BIND_PER_VERTEX) { arrays.push_back(geom.getSecondaryColorArray()); } if (geom.getFogCoordBinding()==osg::Geometry::BIND_PER_VERTEX) { arrays.push_back(geom.getFogCoordArray()); } osg::Geometry::ArrayDataList& tcal = geom.getTexCoordArrayList(); for(osg::Geometry::ArrayDataList::iterator tcalItr=tcal.begin(); tcalItr!=tcal.end(); ++tcalItr) { if (tcalItr->array.valid()) { arrays.push_back(tcalItr->array.get()); } } // now add any new vertices that are required. for(NewVertexList::iterator itr=_newVertexList.begin(); itr!=_newVertexList.end(); ++itr) { NewVertex& newVertex = (*itr); osg::Vec3* vertex = newVertex._vpos; // assign vertex. vertexPtrToIndexMap[vertex]=vertices->size(); vertices->push_back(*vertex); // assign normals if (normals) { osg::Vec3 norm(0.0f,0.0f,0.0f); if (newVertex._v1) norm += (*normals)[vertexPtrToIndexMap[newVertex._v1]] * newVertex._f1; if (newVertex._v2) norm += (*normals)[vertexPtrToIndexMap[newVertex._v2]] * newVertex._f2; if (newVertex._v3) norm += (*normals)[vertexPtrToIndexMap[newVertex._v3]] * newVertex._f3; if (newVertex._v4) norm += (*normals)[vertexPtrToIndexMap[newVertex._v4]] * newVertex._f4; norm.normalize(); normals->push_back(norm); } if (!arrays.empty()) { InsertNewVertices inv(newVertex._f1,vertexPtrToIndexMap[newVertex._v1], newVertex._f2,vertexPtrToIndexMap[newVertex._v2], newVertex._f3,vertexPtrToIndexMap[newVertex._v3], newVertex._f4,vertexPtrToIndexMap[newVertex._v4]); // assign the rest of the attributes. for(ArrayList::iterator aItr=arrays.begin(); aItr!=arrays.end(); ++aItr) { (*aItr)->accept(inv); } } } } }
void Tessellator::retessellatePolygons(osg::Geometry &geom) { #ifdef OSG_GLU_AVAILABLE // turn the contour list into primitives, a little like Tessellator does but more generally osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return; // we currently don't handle geometry which use indices... if (geom.getVertexIndices() || geom.getNormalIndices() || geom.getColorIndices() || geom.getSecondaryColorIndices() || geom.getFogCoordIndices()) return; // not even text coord indices don't handle geometry which use indices... for(unsigned int unit=0;unit<geom.getNumTexCoordArrays();++unit) { if (geom.getTexCoordIndices(unit)) return; } if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) _numberVerts=0; // 09.04.04 GWM reset Tessellator // the reset is needed by the flt loader which reuses a Tessellator for triangulating polygons. // as such it might be reset by other loaders/developers in future. _index=0; // reset the counter for indexed vertices _extraPrimitives = 0; if (!_numberVerts) { _numberVerts=geom.getVertexArray()->getNumElements(); // save the contours for complex (winding rule) tessellations _Contours=geom.getPrimitiveSetList(); } // now cut out vertex attributes added on any previous tessellation reduceArray(geom.getVertexArray(), _numberVerts); reduceArray(geom.getColorArray(), _numberVerts); reduceArray(geom.getNormalArray(), _numberVerts); reduceArray(geom.getFogCoordArray(), _numberVerts); for(unsigned int unit1=0;unit1<geom.getNumTexCoordArrays();++unit1) { reduceArray(geom.getTexCoordArray(unit1), _numberVerts); } // remove the existing primitives. unsigned int nprimsetoriginal= geom.getNumPrimitiveSets(); if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal); // the main difference from osgUtil::Tessellator for Geometry sets of multiple contours is that the begin/end tessellation // occurs around the whole set of contours. if (_ttype==TESS_TYPE_GEOMETRY) { beginTessellation(); gluTessProperty(_tobj, GLU_TESS_WINDING_RULE, _wtype); gluTessProperty(_tobj, GLU_TESS_BOUNDARY_ONLY , _boundaryOnly); } // process all the contours into the Tessellator int noContours = _Contours.size(); int currentPrimitive = 0; for(int primNo=0;primNo<noContours;++primNo) { osg::ref_ptr<osg::PrimitiveSet> primitive = _Contours[primNo].get(); if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) { // this recovers the 'old' tessellation which just retessellates single polygons. if (primitive->getMode()==osg::PrimitiveSet::POLYGON || _ttype==TESS_TYPE_DRAWABLE) { if (primitive->getType()==osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) { osg::DrawArrayLengths* drawArrayLengths = static_cast<osg::DrawArrayLengths*>(primitive.get()); unsigned int first = drawArrayLengths->getFirst(); for(osg::DrawArrayLengths::iterator itr=drawArrayLengths->begin(); itr!=drawArrayLengths->end(); ++itr) { beginTessellation(); unsigned int last = first + *itr; addContour(primitive->getMode(),first,last,vertices); first = last; endTessellation(); collectTessellation(geom, currentPrimitive); currentPrimitive++; } } else { if (primitive->getNumIndices()>3) { // April 2005 gwm only retessellate "complex" polygons beginTessellation(); addContour(primitive.get(), vertices); endTessellation(); collectTessellation(geom, currentPrimitive); currentPrimitive++; } else { // April 2005 gwm triangles don't need to be retessellated geom.addPrimitiveSet(primitive.get()); } } } else { // copy the contour primitive as it is not being tessellated geom.addPrimitiveSet(primitive.get()); } } else { if (primitive->getMode()==osg::PrimitiveSet::POLYGON || primitive->getMode()==osg::PrimitiveSet::QUADS || primitive->getMode()==osg::PrimitiveSet::TRIANGLES || primitive->getMode()==osg::PrimitiveSet::LINE_LOOP || primitive->getMode()==osg::PrimitiveSet::QUAD_STRIP || primitive->getMode()==osg::PrimitiveSet::TRIANGLE_FAN || primitive->getMode()==osg::PrimitiveSet::TRIANGLE_STRIP) { addContour(primitive.get(), vertices); } else { // copy the contour primitive as it is not being tessellated // in this case points, lines or line_strip geom.addPrimitiveSet(primitive.get()); } } } if (_ttype==TESS_TYPE_GEOMETRY) { endTessellation(); collectTessellation(geom, 0); } #endif }
void GeometryValidator::apply(osg::Geometry& geom) { unsigned numVerts = geom.getVertexArray()->getNumElements(); if ( geom.getColorArray() ) { if ( geom.getColorBinding() == osg::Geometry::BIND_OVERALL && geom.getColorArray()->getNumElements() != 1 ) { OE_WARN << "Color: BIND_OVERALL with wrong number of elements" << std::endl; } else if ( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX && geom.getColorArray()->getNumElements() != numVerts ) { OE_WARN << "Color: BIND_PER_VERTEX with color.size != verts.size" << std::endl; } } if ( geom.getNormalArray() ) { if ( geom.getNormalBinding() == osg::Geometry::BIND_OVERALL && geom.getNormalArray()->getNumElements() != 1 ) { OE_WARN << "Normal: BIND_OVERALL with wrong number of elements" << std::endl; } else if ( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX && geom.getNormalArray()->getNumElements() != numVerts ) { OE_WARN << "Normal: BIND_PER_VERTEX with color.size != verts.size" << std::endl; } } const osg::Geometry::PrimitiveSetList& plist = geom.getPrimitiveSetList(); for( osg::Geometry::PrimitiveSetList::const_iterator p = plist.begin(); p != plist.end(); ++p ) { osg::PrimitiveSet* pset = p->get(); osg::DrawElementsUByte* de_byte = dynamic_cast<osg::DrawElementsUByte*>(pset); if ( de_byte ) { if ( numVerts > 0xFF ) { OE_WARN << "DrawElementsUByte used when numVerts > 255 (" << numVerts << ")" << std::endl; } validateDE(de_byte, 0xFF, numVerts ); } osg::DrawElementsUShort* de_short = dynamic_cast<osg::DrawElementsUShort*>(pset); if ( de_short ) { if ( numVerts > 0xFFFF ) { OE_WARN << "DrawElementsUShort used when numVerts > 65535 (" << numVerts << ")" << std::endl; } validateDE(de_short, 0xFFFF, numVerts ); } osg::DrawElementsUInt* de_int = dynamic_cast<osg::DrawElementsUInt*>(pset); if ( de_int ) { validateDE(de_int, 0xFFFFFFFF, numVerts ); } } }