void OBJWriterNodeVisitor::apply(osg::Geometry& geometry) { osg::Matrix m = osg::computeLocalToWorld(getNodePath()); pushStateSet(geometry.getStateSet()); processGeometry(&geometry,m); popStateSet(geometry.getStateSet()); }
void KdTreeBuilder::apply(osg::Geometry& geometry) { osg::KdTree* previous = dynamic_cast<osg::KdTree*>(geometry.getShape()); if (previous) return; osg::ref_ptr<osg::KdTree> kdTree = osg::clone(_kdTreePrototype.get()); if (kdTree->build(_buildOptions, &geometry)) { geometry.setShape(kdTree.get()); } }
bool FltExportVisitor::atLeastOneMesh( const osg::Geometry& geom ) const { // Return true if at least one PrimitiveSet mode will use a Mesh record. unsigned int jdx; for (jdx=0; jdx < geom.getNumPrimitiveSets(); jdx++) { const osg::PrimitiveSet* prim = geom.getPrimitiveSet( jdx ); if( isMesh( prim->getMode() ) ) return true; } // All PrimitiveSet modes will use Face records. return false; }
void deleteFaces(osg::Geometry& geometry) { geometry.removePrimitiveSet(0, geometry.getNumPrimitiveSets()); auto _vertices = detail::getOrCreateVertexArray(geometry); auto _normals = detail::getOrCreateNormalArray(geometry); auto _colors = detail::getOrCreateColorArray(geometry); _vertices->clear(); _normals->clear(); _colors->clear(); _vertices->dirty(); _normals->dirty(); _colors->dirty(); }
void DrawElementTypeSimplifier::simplify(osg::Geometry & geometry) const { osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList::iterator it, end = psl.end(); unsigned int max = 0; for (it = psl.begin(); it!=end; ++it) { switch ((*it)->getType()) { case osg::PrimitiveSet::DrawElementsUShortPrimitiveType: { osg::DrawElementsUShort & de = *static_cast<osg::DrawElementsUShort*>(it->get()); max = getMax<osg::DrawElementsUShort>(de); if (max < 255) *it = copy<osg::DrawElementsUShort, osg::DrawElementsUByte>(de); break; } case osg::PrimitiveSet::DrawElementsUIntPrimitiveType: { osg::DrawElementsUInt & de = *static_cast<osg::DrawElementsUInt*>(it->get()); max = getMax<osg::DrawElementsUInt>(de); if (max < 256) *it = copy<osg::DrawElementsUInt, osg::DrawElementsUByte>(de); else if (max < 65536) *it = copy<osg::DrawElementsUInt, osg::DrawElementsUShort>(de); break; } default: break; } } }
void FltExportVisitor::writeUVList( int numVerts, const osg::Geometry& geom ) { unsigned int numLayers( 0 ); uint32 flags( 0 ); unsigned int idx; for( idx=1; idx<8; idx++) { if( isTextured( idx, geom ) ) { flags |= LAYER_1 >> (idx-1); numLayers++; } } if( numLayers == 0 ) return; uint16 length( 8 + (8*numLayers*numVerts) ); _records->writeInt16( (int16) UV_LIST_OP ); _records->writeUInt16( length ); _records->writeInt32( flags ); osg::Vec2 defaultCoord( 0., 0. ); // const osg::StateSet* ss = getCurrentStateSet(); for( idx=1; idx<8; idx++) { if( isTextured( idx, geom ) ) { osg::Array* t = const_cast<osg::Array*>( geom.getTexCoordArray( idx ) ); osg::ref_ptr<osg::Vec2Array> t2 = dynamic_cast<osg::Vec2Array*>( t ); if (!t2.valid()) { std::ostringstream warning; warning << "fltexp: No Texture2D for unit " << idx; osg::notify( osg::WARN ) << warning.str() << std::endl; _fltOpt->getWriteResult().warn( warning.str() ); t2 = new osg::Vec2Array; } else if (static_cast<int>(t2->getNumElements()) != numVerts) { std::ostringstream warning; warning << "fltexp: Invalid number of texture coordinates for unit " << idx; osg::notify( osg::WARN ) << warning.str() << std::endl; _fltOpt->getWriteResult().warn( warning.str() ); } const int size = t2->getNumElements(); int vIdx; for( vIdx=0; vIdx<numVerts; vIdx++) { osg::Vec2& tc( defaultCoord ); if (vIdx < size) tc = (*t2)[ vIdx ]; _records->writeFloat32( tc[0] ); _records->writeFloat32( tc[1] ); } } } }
void MeshSubdivider::run(osg::Geometry& geom, double granularity, GeoInterpolation interp) { if ( geom.getNumPrimitiveSets() < 1 ) return; subdivide( granularity, interp, geom, _world2local, _local2world, _maxElementsPerEBO ); }
void createDAIGeometry( osg::Geometry& geom, int nInstances=1 ) { const float halfDimX( .5 ); const float halfDimZ( .5 ); osg::Vec3Array* v = new osg::Vec3Array; v->resize( 4 ); geom.setVertexArray( v ); // Geometry for a single quad. (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., -halfDimZ ); (*v)[ 1 ] = osg::Vec3( halfDimX, 0., -halfDimZ ); (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ ); (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ ); // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances. geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) ); }
void setVertexAttrib(osg::Geometry& geom, const AttributeAlias& alias, osg::Array* array, bool normalize, osg::Array::Binding binding = osg::Array::BIND_UNDEFINED) { unsigned int index = alias.first; const std::string& name = alias.second; array->setName(name); if (binding!=osg::Array::BIND_UNDEFINED) array->setBinding(binding); array->setNormalize(normalize); geom.setVertexAttribArray(index, array); osg::notify(osg::NOTICE)<<" vertex attrib("<<name<<", index="<<index<<", normalize="<<normalize<<" binding="<<binding<<")"<<std::endl; }
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 apply(osg::Geometry& geom) { osg::Vec3Array* array = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (array) { for (unsigned int i = 0; i < array->size(); i++) { double x,y,z; double lng = (*array)[i][0]; double lat = (*array)[i][1]; _coordinates->convertLatLongHeightToXYZ(osg::DegreesToRadians(lat), osg::DegreesToRadians(lng), 0, x, y, z); (*array)[i] = osg::Vec3(x,y,z); } } }
MorphGeometry::MorphGeometry(const osg::Geometry& b) : osg::Geometry(b, osg::CopyOp::DEEP_COPY_ARRAYS), _dirty(false), _method(NORMALIZED), _morphNormals(true) { setUseDisplayList(false); setUpdateCallback(new UpdateVertex); setDataVariance(osg::Object::DYNAMIC); setUseVertexBufferObjects(true); if (b.getInternalOptimizedGeometry()) computeInternalOptimizedGeometry(); }
void createDAIGeometry( osg::Geometry& geom, int nInstances=1 ) { const float halfDimX( .5 ); const float halfDimZ( .5 ); osg::Vec3Array* v = new osg::Vec3Array; v->resize( 4 ); geom.setVertexArray( v ); // Geometry for a single quad. (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., 0. ); (*v)[ 1 ] = osg::Vec3( halfDimX, 0., 0. ); (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ*2.0f ); (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ*2.0f ); // create color array data (each corner of our triangle will have one color component) osg::Vec4Array* pColors = new osg::Vec4Array; pColors->push_back( osg::Vec4( 1.0f, 0.0f, 0.0f, 1.0f ) ); pColors->push_back( osg::Vec4( 0.0f, 1.0f, 0.0f, 1.0f ) ); pColors->push_back( osg::Vec4( 0.0f, 0.0f, 1.0f, 1.0f ) ); pColors->push_back( osg::Vec4( 0.0f, 0.0f, 1.0f, 1.0f ) ); geom.setColorArray( pColors ); // make sure that our geometry is using one color per vertex geom.setColorBinding( osg::Geometry::BIND_PER_VERTEX ); osg::Vec2Array* pTexCoords = new osg::Vec2Array( 4 ); (*pTexCoords)[0].set( 0.0f, 0.0f ); (*pTexCoords)[1].set( 1.0f, 0.0f ); (*pTexCoords)[2].set( 1.0f, 1.0f ); (*pTexCoords)[3].set( 0.0f, 1.0f ); geom.setTexCoordArray( 0, pTexCoords ); // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances. geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) ); }
bool InstancesManagerImpl::_initSkinning(osg::Geometry& geom, const image_data& id ) { osg::Geometry& source = geom; osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray()); if (!positionSrc) { OSG_WARN << "InstancedAnimationManager no vertex array in the geometry " << geom.getName() << std::endl; return false; } osg::ref_ptr<osg::Program> cSkinningProg = creators::createProgram("skininst2").program; cSkinningProg->setName("SkinningShader"); const int attribIndex = cAttribSkinningBaseIndex; int nbAttribs = id.bonesWeights.size(); for (int i = 0; i < nbAttribs; i++) { osg::ref_ptr<osg::Vec4Array> array = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX); const image_data::weights_t& w = id.bonesWeights[i]; for (unsigned j = 0; j < w.size(); j+=id.divisor) { array->push_back(osg::Vec4(w.at(j),w.at(j+1),w.at(j+2),w.at(j+3))); } std::stringstream ss; ss << "boneWeight" << i; cSkinningProg->addBindAttribLocation(ss.str(), attribIndex + i); geom.setVertexAttribArray(attribIndex + i, array); OSG_INFO << "set vertex attrib " << ss.str() << std::endl; } osg::ref_ptr<osg::StateSet> ss = geom.getOrCreateStateSet(); ss->addUniform(new osg::Uniform("nbBonesPerVertex", id.bonesPerVertex)); ss->setAttributeAndModes(cSkinningProg.get()); return true; }
void osgToy::FacetingVisitor::facet( osg::Geometry& geom ) { // count #surfaces, exit if none osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList::iterator itr; unsigned int numSurfacePrimitives=0; for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { switch((*itr)->getMode()) { case osg::PrimitiveSet::TRIANGLES: case osg::PrimitiveSet::TRIANGLE_STRIP: case osg::PrimitiveSet::TRIANGLE_FAN: case osg::PrimitiveSet::QUADS: case osg::PrimitiveSet::QUAD_STRIP: case osg::PrimitiveSet::POLYGON: ++numSurfacePrimitives; break; default: break; } } if (!numSurfacePrimitives) return; // exit if no vertices osg::Vec3Array *coords = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (!coords || !coords->size()) return; // generate the normals osg::Vec3Array *normals = new osg::Vec3Array(coords->size()); osg::TriangleIndexFunctor<FacetingOperator> ftif; ftif.set( coords, normals ); geom.accept(ftif); geom.setNormalArray( normals ); geom.setNormalIndices( geom.getVertexIndices() ); geom.setNormalBinding(osg::Geometry::BIND_PER_VERTEX); geom.dirtyDisplayList(); }
void createFaces(osg::Geometry& geometry, Polyhedron const& polyhedron, unsigned int faceMask = PolyhedronGeometry::All) { osgUtil::Tessellator tessellator; tessellator.setTessellationType(osgUtil::Tessellator::TESS_TYPE_POLYGONS); tessellator.setWindingType(osgUtil::Tessellator::TESS_WINDING_NONZERO); auto _vertices = getOrCreateVertexArray(geometry); auto _normals = getOrCreateNormalArray(geometry); auto _colors = getOrCreateColorArray(geometry); osg::ref_ptr<osg::Vec3Array> vertices = createVertexArray(polyhedron); VertexIndexArrays polygons = createVertexIndexArrays(polyhedron); for (auto const& polygon: polygons) { assert(polygon && polygon->size() >= 3); if (!(faceMask & PolyhedronGeometry::FaceMaskFromSides(polygon->size()))) continue; auto first = _vertices->size(); auto count = polygon->size(); auto normal = detail::calculateNormal(vertices, polygon); auto color = detail::calculateColor(vertices, polygon); for (auto i = 0u; i < polygon->size(); ++i) { auto vertex = vertices->at(polygon->at(i)); _vertices->push_back(vertex); _normals->push_back(normal); _colors->push_back(color); } geometry.addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, first, count)); } tessellator.retessellatePolygons(geometry); }
void ShaderVisitor::apply(osg::Geometry& geometry) { bool needPop = (geometry.getStateSet() != NULL); if (geometry.getStateSet()) { pushRequirements(); applyStateSet(geometry.getStateSet(), geometry); } if (!mRequirements.empty()) { const ShaderRequirements& reqs = mRequirements.back(); if (mAllowedToModifyStateSets) { // make sure that all UV sets are there for (std::map<int, std::string>::const_iterator it = reqs.mTextures.begin(); it != reqs.mTextures.end(); ++it) { if (geometry.getTexCoordArray(it->first) == NULL) geometry.setTexCoordArray(it->first, geometry.getTexCoordArray(0)); } } if (reqs.mTexStageRequiringTangents != -1 && mAllowedToModifyStateSets) { osg::ref_ptr<osgUtil::TangentSpaceGenerator> generator (new osgUtil::TangentSpaceGenerator); generator->generate(&geometry, reqs.mTexStageRequiringTangents); geometry.setTexCoordArray(7, generator->getTangentArray(), osg::Array::BIND_PER_VERTEX); } // TODO: find a better place for the stateset if (reqs.mShaderRequired || mForceShaders) createProgram(reqs, geometry); } if (needPop) popRequirements(); }
OSG::Action::ResultE changeGeo(OSG::Node *node) { OSG::Geometry *geo = dynamic_cast<OSG::Geometry *>(node->getCore()); if(geo == NULL) return OSG::Action::Continue; OSG::GeoColor3fPropertyRefPtr col = dynamic_cast<OSG::GeoColor3fProperty *>(geo->getColors()); if(col == NULL) { col = OSG::GeoColor3fProperty::create(); col->resize(geo->getPositions()->getSize()); // Change the geometry to use the new colors geo->setColors(col); // If multi-indexed, make the colors use the same index as // the geometry if(geo->getIndex(OSG::Geometry::PositionsIndex) != NULL) { geo->setIndex(geo->getIndex(OSG::Geometry::PositionsIndex), OSG::Geometry::ColorsIndex ); } } OSG::Real32 size = col->getSize(); for(OSG::UInt32 i = 0; i < size; ++i) { OSG::Color3f c; c[0] = 0.0f; c[1] = static_cast<OSG::Real32>(i) / size; c[2] = 0.0f; col->setValue(c, i); } return OSG::Action::Continue; }
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 ); } } }
void MeshConsolidator::convertToTriangles( osg::Geometry& geom, bool force ) { if ( !force && !canOptimize(geom) ) return; osg::Geometry::PrimitiveSetList& primSets = geom.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList triSets, nonTriSets; for( osg::Geometry::PrimitiveSetList::iterator i = primSets.begin(); i != primSets.end(); ++i ) { osg::PrimitiveSet* pset = i->get(); switch( pset->getMode() ) { case osg::PrimitiveSet::TRIANGLES: case osg::PrimitiveSet::TRIANGLE_STRIP: case osg::PrimitiveSet::TRIANGLE_FAN: case osg::PrimitiveSet::QUADS: case osg::PrimitiveSet::QUAD_STRIP: case osg::PrimitiveSet::POLYGON: triSets.push_back( pset ); break; default: nonTriSets.push_back( pset ); } } if ( triSets.size() > 0 ) { // we are assuming at this point that all the primitive sets in a single geometry // share a single user data structure. osg::Referenced* sharedUserData = triSets[0]->getUserData(); osg::Array* vertexArray = geom.getVertexArray(); unsigned numVerts = vertexArray->getNumElements(); osg::Geometry::PrimitiveSetList newPrimSets; if ( numVerts < 0x100 ) { osg::TriangleIndexFunctor< Collector<osg::DrawElementsUByte> > collector; collector._newPrimSets = &newPrimSets; collector._maxSize = 0xFF; geom.accept( collector ); } else if ( numVerts < 0x10000 ) { osg::TriangleIndexFunctor< Collector<osg::DrawElementsUShort> > collector; collector._newPrimSets = &newPrimSets; collector._maxSize = 0xFFFF; geom.accept( collector ); } else { #ifdef OSG_GLES2_AVAILABLE // GLES only supports UShort, not UInt osg::TriangleIndexFunctor< Collector<osg::DrawElementsUShort> > collector; collector._newPrimSets = &newPrimSets; collector._maxSize = 0xFFFF; geom.accept( collector ); #else osg::TriangleIndexFunctor< Collector<osg::DrawElementsUInt> > collector; collector._newPrimSets = &newPrimSets; collector._maxSize = 0xFFFFFFFF; geom.accept( collector ); #endif } for( osg::Geometry::PrimitiveSetList::iterator i = newPrimSets.begin(); i != newPrimSets.end(); ++i ) { i->get()->setUserData( sharedUserData ); nonTriSets.push_back( i->get() ); } } geom.setPrimitiveSetList( nonTriSets ); }
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 }
bool Primitive_readLocalData(Input& fr,osg::Geometry& geom) { bool iteratorAdvanced = false; bool firstMatched = false; if ((firstMatched = fr.matchSequence("DrawArrays %w %i %i %i")) || fr.matchSequence("DrawArrays %w %i %i") ) { GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int first; fr[2].getInt(first); int count; fr[3].getInt(count); int numInstances = 0; if (firstMatched) { fr[4].getInt(numInstances); fr += 5; } else { fr += 4; } geom.addPrimitiveSet(new DrawArrays(mode, first, count, numInstances)); iteratorAdvanced = true; } else if ((firstMatched = fr.matchSequence("DrawArrayLengths %w %i %i %i {")) || fr.matchSequence("DrawArrayLengths %w %i %i {") ) { int entry = fr[1].getNoNestedBrackets(); GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int first; fr[2].getInt(first); int capacity; fr[3].getInt(capacity); int numInstances = 0; if (firstMatched) { fr[4].getInt(numInstances); fr += 6; } else { fr += 5; } DrawArrayLengths* prim = new DrawArrayLengths; prim->setMode(mode); prim->setNumInstances(numInstances); prim->setFirst(first); prim->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int i; if (fr[0].getUInt(i)) { prim->push_back(i); ++fr; } } ++fr; geom.addPrimitiveSet(prim); iteratorAdvanced = true; } else if ((firstMatched = fr.matchSequence("DrawElementsUByte %w %i %i {")) || fr.matchSequence("DrawElementsUByte %w %i {")) { int entry = fr[1].getNoNestedBrackets(); GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int capacity; fr[2].getInt(capacity); int numInstances = 0; if (firstMatched) { fr[3].getInt(numInstances); fr += 5; } else { fr += 4; } DrawElementsUByte* prim = new DrawElementsUByte; prim->setMode(mode); prim->setNumInstances(numInstances); prim->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int i; if (fr[0].getUInt(i)) { prim->push_back(i); ++fr; } } ++fr; geom.addPrimitiveSet(prim); iteratorAdvanced = true; } else if ((firstMatched = fr.matchSequence("DrawElementsUShort %w %i %i {")) || fr.matchSequence("DrawElementsUShort %w %i {")) { int entry = fr[1].getNoNestedBrackets(); GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int capacity; fr[2].getInt(capacity); int numInstances = 0; if (firstMatched) { fr[3].getInt(numInstances); fr += 5; } else { fr += 4; } DrawElementsUShort* prim = new DrawElementsUShort; prim->setMode(mode); prim->setNumInstances(numInstances); prim->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int i; if (fr[0].getUInt(i)) { prim->push_back(i); ++fr; } } ++fr; geom.addPrimitiveSet(prim); iteratorAdvanced = true; } else if ((firstMatched = fr.matchSequence("DrawElementsUInt %w %i %i {")) || fr.matchSequence("DrawElementsUInt %w %i {")) { int entry = fr[1].getNoNestedBrackets(); GLenum mode; Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode); int capacity; fr[2].getInt(capacity); int numInstances = 0; if (firstMatched) { fr[3].getInt(numInstances); fr += 5; } else { fr += 4; } DrawElementsUInt* prim = new DrawElementsUInt; prim->setMode(mode); prim->setNumInstances(numInstances); prim->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int i; if (fr[0].getUInt(i)) { prim->push_back(i); ++fr; } } ++fr; geom.addPrimitiveSet(prim); iteratorAdvanced = true; } return iteratorAdvanced; }
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; } 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 ) { 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() ); } else { OE_NOTICE << LC << "Found a NULL array\n"; } } if ( _vbos.size() != 1 ) { OE_NOTICE << LC << "Found a Geometry that uses more than one VBO (non-optimal sharing)\n"; } 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"; } }
nave(int x,int y, int z, int tamaño) { pyramidGeode = new osg::Geode(); pyramidGeometry = new osg::Geometry(); pyramidGeode->addDrawable(pyramidGeometry); osg::Vec3Array* pyramidVertices = new osg::Vec3Array; //0-4 pyramidVertices->push_back( osg::Vec3( x, y, z) ); // front left //1-5 pyramidVertices->push_back( osg::Vec3(tamaño+x, y, z) ); // front right //2-6 pyramidVertices->push_back( osg::Vec3(tamaño+x,tamaño+y, z) ); // back right //3-7 pyramidVertices->push_back( osg::Vec3( x,tamaño+y, z) ); // back left //4-0 pyramidVertices->push_back( osg::Vec3( x, y,tamaño+z) ); // peak //5-1 pyramidVertices->push_back( osg::Vec3(tamaño+x, y,tamaño+z) ); // front right //6-2 pyramidVertices->push_back( osg::Vec3(tamaño+x,tamaño+y,tamaño+z) ); // back right //7-3 pyramidVertices->push_back( osg::Vec3( x,tamaño+y,tamaño+z) ); // back left pyramidGeometry->setVertexArray( pyramidVertices ); osg::DrawElementsUInt* pyramidBase = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidBase->push_back(3); pyramidBase->push_back(2); pyramidBase->push_back(1); pyramidBase->push_back(0); pyramidGeometry->addPrimitiveSet(pyramidBase); osg::DrawElementsUInt* pyramidTop = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidTop->push_back(4); pyramidTop->push_back(5); pyramidTop->push_back(6); pyramidTop->push_back(7); pyramidGeometry->addPrimitiveSet(pyramidTop); //Repeat the same for each of the four sides. Again, vertices are //specified in counter-clockwise order. osg::DrawElementsUInt* pyramidFaceOne = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceOne->push_back(0); pyramidFaceOne->push_back(1); pyramidFaceOne->push_back(5); pyramidFaceOne->push_back(4); pyramidGeometry->addPrimitiveSet(pyramidFaceOne); osg::DrawElementsUInt* pyramidFaceTwo = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceTwo->push_back(1); pyramidFaceTwo->push_back(2); pyramidFaceTwo->push_back(6); pyramidFaceTwo->push_back(5); pyramidGeometry->addPrimitiveSet(pyramidFaceTwo); osg::DrawElementsUInt* pyramidFaceThree = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceThree->push_back(2); pyramidFaceThree->push_back(3); pyramidFaceThree->push_back(7); pyramidFaceThree->push_back(6); pyramidGeometry->addPrimitiveSet(pyramidFaceThree); osg::DrawElementsUInt* pyramidFaceFour = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0); pyramidFaceFour->push_back(3); pyramidFaceFour->push_back(0); pyramidFaceThree->push_back(4); pyramidFaceFour->push_back(7); pyramidGeometry->addPrimitiveSet(pyramidFaceFour); //Declare and load an array of Vec4 elements to store colors. osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 0 red colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 1 green colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 2 blue colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 3 white colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red //The next step is to associate the array of colors with the geometry, //assign the color indices created above to the geometry and set the //binding mode to _PER_VERTEX. pyramidGeometry->setColorArray(colors); pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); };
bool Tessellator::tessellateGeometry(osg::Geometry &geom) { osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray()); if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return false; // copy the original primitive set list osg::Geometry::PrimitiveSetList originalPrimitives = geom.getPrimitiveSetList(); // clear the primitive sets unsigned int nprimsetoriginal= geom.getNumPrimitiveSets(); if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal); bool success = true; for (unsigned int i=0; i < originalPrimitives.size(); i++) { osg::ref_ptr<osg::PrimitiveSet> primitive = originalPrimitives[i].get(); if (primitive->getMode()==osg::PrimitiveSet::POLYGON || primitive->getMode()==osg::PrimitiveSet::LINE_LOOP) { 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) { unsigned int last = first + *itr; osg::PrimitiveSet* newPrimitive = tessellatePrimitive(first, last, vertices); if (newPrimitive) { geom.addPrimitiveSet(newPrimitive); } else { // tessellation failed, add old primitive set back geom.addPrimitiveSet(primitive); success = false; } first = last; } } else { if (primitive->getNumIndices()>=3) { osg::PrimitiveSet* newPrimitive = tessellatePrimitive(primitive.get(), vertices); if (newPrimitive) { geom.addPrimitiveSet(newPrimitive); } else { // tessellation failed, add old primitive set back geom.addPrimitiveSet(primitive); success = false; } } } } else { // // TODO: handle more primitive modes // } } return success; }
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 UnIndexMeshVisitor::apply(osg::Geometry& geom) { // no point optimizing if we don't have enough vertices. if (!geom.getVertexArray()) return; // check for the existence of surface primitives unsigned int numIndexedPrimitives = 0; osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList(); osg::Geometry::PrimitiveSetList::iterator itr; for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { osg::PrimitiveSet::Type type = (*itr)->getType(); if ((type == osg::PrimitiveSet::DrawElementsUBytePrimitiveType || type == osg::PrimitiveSet::DrawElementsUShortPrimitiveType || type == osg::PrimitiveSet::DrawElementsUIntPrimitiveType)) numIndexedPrimitives++; } // no polygons or no indexed primitive, nothing to do if (!numIndexedPrimitives) { return; } // we dont manage lines GeometryArrayList arraySrc(geom); GeometryArrayList arrayList = arraySrc.cloneType(); osg::Geometry::PrimitiveSetList newPrimitives; for(itr=primitives.begin(); itr!=primitives.end(); ++itr) { osg::PrimitiveSet::Mode mode = (osg::PrimitiveSet::Mode)(*itr)->getMode(); switch(mode) { // manage triangles case(osg::PrimitiveSet::TRIANGLES): case(osg::PrimitiveSet::TRIANGLE_STRIP): case(osg::PrimitiveSet::TRIANGLE_FAN): case(osg::PrimitiveSet::QUADS): case(osg::PrimitiveSet::QUAD_STRIP): case(osg::PrimitiveSet::POLYGON): { // for each geometry list indexes of vertexes // to makes triangles TriangleIndexor triangleIndexList; (*itr)->accept(triangleIndexList); unsigned int index = arrayList.size(); // now copy each vertex to new array, like a draw array arraySrc.append(triangleIndexList._indices, arrayList); newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, index, triangleIndexList._indices.size())); } break; // manage lines case(osg::PrimitiveSet::LINES): case(osg::PrimitiveSet::LINE_STRIP): case(osg::PrimitiveSet::LINE_LOOP): { EdgeIndexor edgesIndexList; (*itr)->accept(edgesIndexList); unsigned int index = arrayList.size(); // now copy each vertex to new array, like a draw array arraySrc.append(edgesIndexList._indices, arrayList); newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::LINES, index, edgesIndexList._indices.size())); } break; case(osg::PrimitiveSet::POINTS): { PointIndexor pointsIndexList; (*itr)->accept(pointsIndexList); unsigned int index = arrayList.size(); // now copy each vertex to new array, like a draw array arraySrc.append(pointsIndexList._indices, arrayList); newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::POINTS, index, pointsIndexList._indices.size())); } break; default: break; } } arrayList.setToGeometry(geom); geom.setPrimitiveSetList(newPrimitives); }