DiskPrimitive::DiskPrimitive( float radius, float z, float thetaMax ) : m_radius( radius ), m_z( z ), m_thetaMax( thetaMax ), m_nPoints( 0 ) { // build vertex attributes for P, N and st, and indexes for triangles. IECore::V3fVectorDataPtr pData = new IECore::V3fVectorData; IECore::V3fVectorDataPtr nData = new IECore::V3fVectorData; IECore::V2fVectorDataPtr stData = new IECore::V2fVectorData; vector<V3f> &pVector = pData->writable(); vector<V3f> &nVector = nData->writable(); vector<V2f> &stVector = stData->writable(); // centre point pVector.push_back( V3f( 0.0f, 0.0f, m_z ) ); nVector.push_back( V3f( 0.0f, 0.0f, 1.0f ) ); stVector.push_back( V2f( 0.5f, 0.5f ) ); const unsigned int n = 20; float thetaMaxRadians = m_thetaMax/180.0f * M_PI; for( unsigned int i=0; i<n; i++ ) { float t = thetaMaxRadians * i/(n-1); float x = Math<float>::cos( t ); float y = Math<float>::sin( t ); pVector.push_back( V3f( m_radius * x, m_radius * y, m_z ) ); nVector.push_back( V3f( 0.0f, 0.0f, 1.0f ) ); stVector.push_back( V2f( x/2.0f + 0.5f, y/2.0f + 0.5f ) ); } m_nPoints = n + 1; addVertexAttribute( "P", pData ); addVertexAttribute( "N", nData ); addVertexAttribute( "st", stData ); }
SpherePrimitive::SpherePrimitive( float radius, float zMin, float zMax, float thetaMax ) : m_radius( radius ), m_zMin( zMin ), m_zMax( zMax ), m_thetaMax( thetaMax ), m_vertIdsBuffer( 0 ) { // figure out bounding box thetaMax = m_thetaMax/180.0f * M_PI; float minX = m_radius * ( thetaMax < M_PI ? Math<float>::cos( thetaMax ) : -1.0f ); float maxY = m_radius * ( thetaMax < M_PI/2 ? Math<float>::sin( thetaMax ) : 1.0f ); float minY = m_radius * ( thetaMax > 3 * M_PI/2 ? -1.0f : min( 0.0f, Math<float>::sin( thetaMax ) ) ); m_bound = Imath::Box3f( V3f( minX, minY, m_zMin * m_radius ), V3f( m_radius, maxY, m_zMax * m_radius ) ); // build vertex attributes for P, N and st, and indexes for triangles. IECore::V3fVectorDataPtr pData = new IECore::V3fVectorData; IECore::V3fVectorDataPtr nData = new IECore::V3fVectorData; IECore::V2fVectorDataPtr stData = new IECore::V2fVectorData; m_vertIds = new IECore::UIntVectorData; vector<V3f> &pVector = pData->writable(); vector<V3f> &nVector = nData->writable(); vector<V2f> &stVector = stData->writable(); vector<unsigned int> &vertIdsVector = m_vertIds->writable(); float oMin = Math<float>::asin( m_zMin ); float oMax = Math<float>::asin( m_zMax ); const unsigned int nO = max( 4u, (unsigned int)( 20.0f * (oMax - oMin) / M_PI ) ); thetaMax = m_thetaMax/180.0f * M_PI; const unsigned int nT = max( 7u, (unsigned int)( 40.0f * thetaMax / (M_PI*2) ) ); for( unsigned int i=0; i<nO; i++ ) { float v = (float)i/(float)(nO-1); float o = lerp( oMin, oMax, v ); float z = m_radius * Math<float>::sin( o ); float r = m_radius * Math<float>::cos( o ); for( unsigned int j=0; j<nT; j++ ) { float u = (float)j/(float)(nT-1); float theta = thetaMax * u; V3f p( r * Math<float>::cos( theta ), r * Math<float>::sin( theta ), z ); stVector.push_back( V2f( u, v ) ); pVector.push_back( p ); nVector.push_back( p ); if( i < nO - 1 && j < nT - 1 ) { unsigned int i0 = i * nT + j; unsigned int i1 = i0 + 1; unsigned int i2 = i0 + nT; unsigned int i3 = i2 + 1; vertIdsVector.push_back( i0 ); vertIdsVector.push_back( i1 ); vertIdsVector.push_back( i2 ); vertIdsVector.push_back( i1 ); vertIdsVector.push_back( i3 ); vertIdsVector.push_back( i2 ); } } } addVertexAttribute( "P", pData ); addVertexAttribute( "N", nData ); addVertexAttribute( "st", stData ); }
IECore::RunTimeTypedPtr ToGLMeshConverter::doConversion( IECore::ConstObjectPtr src, IECore::ConstCompoundObjectPtr operands ) const { IECore::MeshPrimitivePtr mesh = IECore::staticPointerCast<IECore::MeshPrimitive>( src->copy() ); // safe because the parameter validated it for us if( !mesh->variableData<IECore::V3fVectorData>( "P", IECore::PrimitiveVariable::Vertex ) ) { throw IECore::Exception( "Must specify primitive variable \"P\", of type V3fVectorData and interpolation type Vertex." ); } if( mesh->variables.find( "N" )==mesh->variables.end() ) { // the mesh has no normals - we need to explicitly add some. if it's a polygon // mesh (interpolation==linear) then we add per-face normals for a faceted look // and if it's a subdivision mesh we add smooth per-vertex normals. IECore::MeshNormalsOpPtr normalOp = new IECore::MeshNormalsOp(); normalOp->inputParameter()->setValue( mesh ); normalOp->copyParameter()->setTypedValue( false ); normalOp->interpolationParameter()->setNumericValue( mesh->interpolation() == "linear" ? IECore::PrimitiveVariable::Uniform : IECore::PrimitiveVariable::Vertex ); normalOp->operate(); } IECore::TriangulateOpPtr op = new IECore::TriangulateOp(); op->inputParameter()->setValue( mesh ); op->throwExceptionsParameter()->setTypedValue( false ); // it's better to see something than nothing op->copyParameter()->setTypedValue( false ); op->operate(); IECore::FaceVaryingPromotionOpPtr faceVaryingOp = new IECore::FaceVaryingPromotionOp; faceVaryingOp->inputParameter()->setValue( mesh ); faceVaryingOp->copyParameter()->setTypedValue( false ); faceVaryingOp->operate(); MeshPrimitivePtr glMesh = new MeshPrimitive( mesh->vertexIds() ); for ( IECore::PrimitiveVariableMap::iterator pIt = mesh->variables.begin(); pIt != mesh->variables.end(); ++pIt ) { if ( pIt->second.data ) { glMesh->addPrimitiveVariable( pIt->first, pIt->second ); } else { IECore::msg( IECore::Msg::Warning, "ToGLMeshConverter", boost::format( "No data given for primvar \"%s\"" ) % pIt->first ); } } IECore::PrimitiveVariableMap::const_iterator sIt = mesh->variables.find( "s" ); IECore::PrimitiveVariableMap::const_iterator tIt = mesh->variables.find( "t" ); if ( sIt != mesh->variables.end() && tIt != mesh->variables.end() ) { if ( sIt->second.interpolation != IECore::PrimitiveVariable::Constant && tIt->second.interpolation != IECore::PrimitiveVariable::Constant && sIt->second.interpolation == tIt->second.interpolation ) { IECore::ConstFloatVectorDataPtr s = IECore::runTimeCast< const IECore::FloatVectorData >( sIt->second.data ); IECore::ConstFloatVectorDataPtr t = IECore::runTimeCast< const IECore::FloatVectorData >( tIt->second.data ); if ( s && t ) { /// Should hold true if primvarsAreValid assert( s->readable().size() == t->readable().size() ); IECore::V2fVectorDataPtr stData = new IECore::V2fVectorData(); stData->writable().resize( s->readable().size() ); for ( unsigned i = 0; i < s->readable().size(); i++ ) { stData->writable()[i] = Imath::V2f( s->readable()[i], t->readable()[i] ); } glMesh->addPrimitiveVariable( "st", IECore::PrimitiveVariable( sIt->second.interpolation, stData ) ); } else { IECore::msg( IECore::Msg::Warning, "ToGLMeshConverter", "If specified, primitive variables \"s\" and \"t\" must be of type FloatVectorData and interpolation type FaceVarying." ); } } else { IECore::msg( IECore::Msg::Warning, "ToGLMeshConverter", "If specified, primitive variables \"s\" and \"t\" must be of type FloatVectorData and non-Constant interpolation type." ); } } else if ( sIt != mesh->variables.end() || tIt != mesh->variables.end() ) { IECore::msg( IECore::Msg::Warning, "ToGLMeshConverter", "Primitive variable \"s\" or \"t\" found, but not both." ); } return glMesh; }