void SVLocusSet:: getIntersectingEdgeNodes( const LocusIndexType inputLocusIndex, const NodeIndexType inputRemoteNodeIndex, const EdgeMapType& remoteIntersectNodeToLocalNodeMap, const LocusSetIndexerType& remoteIntersectNodes, std::vector<EdgeInfoType>& edges) const { typedef EdgeMapType::const_iterator rliter_t; typedef std::pair<rliter_t,rliter_t> rlmap_range_t; edges.clear(); // find all nodes, from the remoteIntersectNodes set, which intersect this function's input node: // // for this application, inputLocus is an input set isolated from the rest of the graph, so nodes // intersected in the inputLocus are filtered out // std::set<NodeAddressType> edgeIntersectRemoteTemp; getNodeIntersectCore(inputLocusIndex,inputRemoteNodeIndex,remoteIntersectNodes,inputLocusIndex,edgeIntersectRemoteTemp); for (const NodeAddressType& remoteIsectAddy : edgeIntersectRemoteTemp) { // find what local nodes the remote nodes trace back to: const rlmap_range_t remoteIsectRange(remoteIntersectNodeToLocalNodeMap.equal_range(remoteIsectAddy)); assert(remoteIsectRange.first != remoteIntersectNodeToLocalNodeMap.end()); for (rliter_t riter(remoteIsectRange.first); riter != remoteIsectRange.second; ++riter) { const NodeAddressType localIntersectAddy(std::make_pair(remoteIsectAddy.first,riter->second)); edges.push_back(std::make_pair(localIntersectAddy,remoteIsectAddy.second)); } } }
static bool buildGeodesicSphereData( const float radius, const unsigned int subdivisions, osg::Geometry* geom ) { unsigned int subdivide( subdivisions ); if( subdivisions > 5 ) { // Would create index array too large for use with DrawElementsUShort. // For now, clamp. In the future, just use DrawElementsUInt. osg::notify( osg::WARN ) << "makeGeodesicSphere: Clamping subdivisions to 5." << std::endl; subdivide = 5; } GLfloat vertData[] = { 0.000000, 0.850651, 0.525731, 0.000000, 0.850651, -0.525731, 0.000000, -0.850651, -0.525731, 0.000000, -0.850651, 0.525731, 0.525731, 0.000000, 0.850651, 0.525731, 0.000000, -0.850651, -0.525731, 0.000000, -0.850651, -0.525731, 0.000000, 0.850651, 0.850651, 0.525731, 0.000000, 0.850651, -0.525731, 0.000000, -0.850651, -0.525731, 0.000000, -0.850651, 0.525731, 0.000000 }; int faces = 20; int _numVerts = 12; int _numIndices = faces * 3; // Data is initially in "golden mean" coordinate system. // Rotate around y so that 2 verts exist at (0,0,+/-1). { //osg::Vec3 v0( 0.525731, 0.000000, 0.850651 ); //osg::Vec3 v1( 0, 0, 1 ); //const double angle( acos( v0 * v1 ) ); const double sinAngle( 0.525731 ); const double cosAngle( 0.850651 ); int idx; for( idx=0; idx<_numVerts*3; idx+=3 ) { double x( vertData[ idx ] ); double z( vertData[ idx+2 ] ); vertData[ idx ] = x * cosAngle + z * -sinAngle; vertData[ idx+2 ] = x * sinAngle + z * cosAngle; } } int vertsSize = _numVerts * 3; GLfloat* _vertices = new GLfloat[ vertsSize ]; memcpy( _vertices, vertData, sizeof( vertData ) ); GLushort* _indices = new GLushort[ _numIndices ]; GLushort* indexPtr = _indices; *indexPtr++ = 0; *indexPtr++ = 7; *indexPtr++ = 4; *indexPtr++ = 0; *indexPtr++ = 4; *indexPtr++ = 8; *indexPtr++ = 0; *indexPtr++ = 8; *indexPtr++ = 1; *indexPtr++ = 0; *indexPtr++ = 1; *indexPtr++ = 11; *indexPtr++ = 0; *indexPtr++ = 11; *indexPtr++ = 7; *indexPtr++ = 2; *indexPtr++ = 6; *indexPtr++ = 5; *indexPtr++ = 2; *indexPtr++ = 5; *indexPtr++ = 9; *indexPtr++ = 2; *indexPtr++ = 9; *indexPtr++ = 3; *indexPtr++ = 2; *indexPtr++ = 3; *indexPtr++ = 10; *indexPtr++ = 2; *indexPtr++ = 10; *indexPtr++ = 6; *indexPtr++ = 7; *indexPtr++ = 3; *indexPtr++ = 4; *indexPtr++ = 4; *indexPtr++ = 3; *indexPtr++ = 9; *indexPtr++ = 4; *indexPtr++ = 9; *indexPtr++ = 8; *indexPtr++ = 8; *indexPtr++ = 9; *indexPtr++ = 5; *indexPtr++ = 8; *indexPtr++ = 5; *indexPtr++ = 1; *indexPtr++ = 1; *indexPtr++ = 5; *indexPtr++ = 6; *indexPtr++ = 1; *indexPtr++ = 6; *indexPtr++ = 11; *indexPtr++ = 11; *indexPtr++ = 6; *indexPtr++ = 10; *indexPtr++ = 11; *indexPtr++ = 10; *indexPtr++ = 7; *indexPtr++ = 7; *indexPtr++ = 10; *indexPtr++ = 3; GLuint _idxStart = 0; GLuint _idxEnd = 11; // Subdivide as requested int idx; for (idx = subdivide; idx; idx--) { // Make a map of edges typedef std::map< unsigned int, GLushort> EdgeMapType; EdgeMapType edgeMap; indexPtr = _indices; int f; for (f=faces; f; f--) { unsigned int key = makeKey(indexPtr[0], indexPtr[1]); if (edgeMap.find( key ) == edgeMap.end()) edgeMap[key] = ++_idxEnd; key = makeKey(indexPtr[1], indexPtr[2]); if (edgeMap.find( key ) == edgeMap.end()) edgeMap[key] = ++_idxEnd; key = makeKey(indexPtr[2], indexPtr[0]); if (edgeMap.find( key ) == edgeMap.end()) edgeMap[key] = ++_idxEnd; indexPtr += 3; } GLfloat* oldVerts = _vertices; GLushort* oldIndices = _indices; _numVerts += (int)(faces * 1.5f); int newFaces = faces * 4; _numIndices = newFaces * 3; // Create new indices _indices = new GLushort[ _numIndices ]; GLushort* oldIdxPtr = oldIndices; indexPtr = _indices; for (f=faces; f; f--) { GLushort vertA = *oldIdxPtr++; GLushort vertB = *oldIdxPtr++; GLushort vertC = *oldIdxPtr++; GLushort edgeAB = edgeMap[ makeKey(vertA,vertB) ]; GLushort edgeBC = edgeMap[ makeKey(vertB,vertC) ]; GLushort edgeCA = edgeMap[ makeKey(vertC,vertA) ]; *indexPtr++ = vertA; *indexPtr++ = edgeAB; *indexPtr++ = edgeCA; *indexPtr++ = edgeAB; *indexPtr++ = vertB; *indexPtr++ = edgeBC; *indexPtr++ = edgeAB; *indexPtr++ = edgeBC; *indexPtr++ = edgeCA; *indexPtr++ = edgeCA; *indexPtr++ = edgeBC; *indexPtr++ = vertC; } // Copy old vertices into new vertices _vertices = new GLfloat[ _numVerts * 3 ]; memcpy( _vertices, oldVerts, vertsSize * sizeof( GLfloat ) ); // Create new vertices at midpoint of each edge EdgeMapType::const_iterator it = edgeMap.begin(); while (it != edgeMap.end()) { GLushort idxA, idxB; idxA = ((*it).first) >> 16; idxB = ((*it).first) & 0xffff; GLfloat* dest = &(_vertices[ ((*it).second * 3) ]); GLfloat* srcA = &(_vertices[idxA*3]); GLfloat* srcB = &(_vertices[idxB*3]); average3fv( dest, srcA, srcB ); it++; } faces = newFaces; vertsSize = _numVerts * 3; delete[] oldVerts; delete[] oldIndices; } // // Create normal array by making vertices unit length GLfloat* _normals = new GLfloat[ _numVerts * 3 ]; GLfloat* vertPtr = _vertices; GLfloat* normPtr = _normals; for (idx = _numVerts; idx; idx--) { osg::Vec3 v( vertPtr[0], vertPtr[1], vertPtr[2] ); float lengthInv = (float)( 1. / v.length() ); *normPtr++ = *vertPtr++ * lengthInv; *normPtr++ = *vertPtr++ * lengthInv; *normPtr++ = *vertPtr++ * lengthInv; } // // Scale vertices out to the specified radius vertPtr = _vertices; normPtr = _normals; for (idx = _numVerts*3; idx; idx--) *vertPtr++ = *normPtr++ * radius; // // Texture coordinates are identical to normals for cube mapping GLfloat* _texCoords = new GLfloat[ _numVerts * 3 ]; memcpy( _texCoords, _normals, _numVerts * 3 * sizeof( GLfloat) ); // Convert to OSG { osg::Vec3Array* osgV = new osg::Vec3Array; osg::Vec3Array* osgN = new osg::Vec3Array; osg::Vec3Array* osgTC = new osg::Vec3Array; osgV->resize( _numVerts ); osgN->resize( _numVerts ); osgTC->resize( _numVerts ); geom->setVertexArray( osgV ); geom->setNormalArray( osgN ); geom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX ); geom->setTexCoordArray( 0, osgTC ); osg::Vec4Array* osgC = new osg::Vec4Array; osgC->push_back( osg::Vec4( 1., 1., 1., 1. ) ); geom->setColorArray( osgC ); geom->setColorBinding( osg::Geometry::BIND_OVERALL ); vertPtr = _vertices; normPtr = _normals; GLfloat* tcPtr = _texCoords; int idx; for( idx=0; idx<_numVerts; idx++ ) { (*osgV)[ idx ].x() = *vertPtr++; (*osgV)[ idx ].y() = *vertPtr++; (*osgV)[ idx ].z() = *vertPtr++; (*osgN)[ idx ].x() = *normPtr++; (*osgN)[ idx ].y() = *normPtr++; (*osgN)[ idx ].z() = *normPtr++; (*osgTC)[ idx ].x() = *tcPtr++; (*osgTC)[ idx ].y() = *tcPtr++; (*osgTC)[ idx ].z() = *tcPtr++; } osg::UShortArray* osgIdx = new osg::UShortArray; osgIdx->resize( _numIndices ); indexPtr = _indices; for( idx=0; idx<_numIndices; idx++ ) { (*osgIdx)[ idx ] = *indexPtr++; } geom->addPrimitiveSet( new osg::DrawElementsUShort( GL_TRIANGLES, _numIndices, _indices ) ); } delete[] _indices; delete[] _vertices; delete[] _normals; delete[] _texCoords; osg::notify( osg::INFO ) << "makeGeodesicSphere: numVertices: " << _numVerts << std::endl; return( true ); }