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 );
}
Exemple #2
0
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;
}