void CurveTangentsOp::modifyTypedPrimitive( CurvesPrimitive *curves, const CompoundObject *operands )
{
	if( !curves->arePrimitiveVariablesValid( ) )
	{
		throw InvalidArgumentException( "CurveTangentsOp : CurvesPrimitive variables are invalid." );
	}
	
	// The CurvesPrimitiveEvaluator currently only supports "P".
	Data * pData = curves->variableData<Data>( "P", PrimitiveVariable::Vertex );
	if( !pData )
	{
		throw InvalidArgumentException( "CurveTangentsOp : CurvesPrimitive has no Vertex \"P\" primitive variable." );
	}

	const IntVectorData *vertsPerCurve = curves->verticesPerCurve();
		
	DataCastOpPtr dco = new DataCastOp();
	dco->targetTypeParameter()->setNumericValue( FloatVectorDataTypeId );

	CurvesPrimitiveEvaluatorPtr evaluator = new CurvesPrimitiveEvaluator( curves );

	CalculateTangents f( vertsPerCurve->readable(), evaluator );

	despatchTypedData<CalculateTangents, TypeTraits::IsVec3VectorTypedData, HandleErrors>( pData, f );

	curves->variables[ vTangentPrimVarNameParameter()->getTypedValue() ] = PrimitiveVariable( PrimitiveVariable::Vertex, f.vTangentsData );

	assert( curves->arePrimitiveVariablesValid() );
}
Exemple #2
0
PointsPrimitivePtr mergePoints( const std::vector<const PointsPrimitive *> &pointsPrimitives )
{
	size_t totalPointCount = 0;
	typedef std::map<std::string, IECore::TypeId> FoundPrimvars;
	FoundPrimvars foundPrimvars;

	PrimitiveVariableMap constantPrimVars;

	std::vector<PointsPrimitivePtr> validatedPointsPrimitives( pointsPrimitives.size() );

	// find out which primvars can be merged
	for( size_t i = 0; i < pointsPrimitives.size(); ++i )
	{
		PointsPrimitivePtr pointsPrimitive = validatedPointsPrimitives[i] = pointsPrimitives[i]->copy();

		totalPointCount += pointsPrimitive->getNumPoints();
		PrimitiveVariableMap &variables = pointsPrimitive->variables;
		for( PrimitiveVariableMap::iterator it = variables.begin(); it != variables.end(); ++it )
		{
			DataPtr data = it->second.data;
			const IECore::TypeId typeId = data->typeId();
			PrimitiveVariable::Interpolation interpolation = it->second.interpolation;
			const std::string &name = it->first;

			bool bExistingConstant = constantPrimVars.find( name ) != constantPrimVars.end();
			FoundPrimvars::const_iterator fIt = foundPrimvars.find( name );
			bool bExistingVertex = fIt != foundPrimvars.end();

			if( interpolation == PrimitiveVariable::Constant )
			{
				if( bExistingVertex )
				{
					std::string msg = boost::str( boost::format( "PointsAlgo::mergePoints mismatching primvar %s" ) % name );
					throw InvalidArgumentException( msg );
				}

				if( !bExistingConstant )
				{
					constantPrimVars[name] = it->second;
				}
				continue;
			}

			if( interpolation == PrimitiveVariable::Vertex )
			{

				PrimitiveVariableMap::const_iterator constantPrimVarIt = constantPrimVars.find( name );
				if( constantPrimVarIt != constantPrimVars.end() )
				{
					std::string msg = boost::str( boost::format( "PointsAlgo::mergePoints mismatching primvar %s" ) % name );
					throw InvalidArgumentException( msg );
				}

				if( !bExistingVertex )
				{
					foundPrimvars[name] = typeId;
				}
				else
				{
					if( fIt->second != typeId )
					{
						DataCastOpPtr castOp = new DataCastOp();

						castOp->objectParameter()->setValue( data );
						castOp->targetTypeParameter()->setNumericValue( fIt->second );

						try
						{
							it->second.data = runTimeCast<Data>( castOp->operate() );
						}
						catch( const IECore::Exception &e )
						{
							std::string msg = boost::str( boost::format( "PointsAlgo::mergePoints unable to cast primvar %s (%s) " ) % name % e.what() );
							throw InvalidArgumentException( msg );
						}
					}
				}
			}
		}
	}

	// allocate the new points primitive and copy the primvars
	PointsPrimitivePtr newPoints = new PointsPrimitive( totalPointCount );

	// copy constant primvars
	for( PrimitiveVariableMap::const_iterator it = constantPrimVars.begin(); it != constantPrimVars.end(); ++it )
	{
		newPoints->variables[it->first] = it->second;
	}

	// merge vertex primvars
	for( FoundPrimvars::const_iterator it = foundPrimvars.begin(); it != foundPrimvars.end(); ++it )
	{
		DataPtr mergedData = mergePrimVars( validatedPointsPrimitives, it->first, totalPointCount );
		newPoints->variables[it->first] = PrimitiveVariable( PrimitiveVariable::Vertex, mergedData );
	}

	return newPoints;
}
void MeshTangentsOp::modifyTypedPrimitive( MeshPrimitive * mesh, const CompoundObject * operands )
{
	if( !mesh->arePrimitiveVariablesValid( ) )
	{
		throw InvalidArgumentException( "MeshTangentsOp : MeshPrimitive variables are invalid." );
	}
	
	const std::string &pPrimVarName = pPrimVarNameParameter()->getTypedValue();
	Data * pData = mesh->variableData<Data>( pPrimVarName, PrimitiveVariable::Vertex );
	if( !pData )
	{
		string e = boost::str( boost::format( "MeshTangentsOp : MeshPrimitive has no Vertex \"%s\" primitive variable." ) % pPrimVarName );
		throw InvalidArgumentException( e );
	}

	const IntVectorData * vertsPerFace = mesh->verticesPerFace();
	for ( IntVectorData::ValueType::const_iterator it = vertsPerFace->readable().begin(); it != vertsPerFace->readable().end(); ++it )
	{
		if ( *it != 3 )
		{
			throw InvalidArgumentException( "MeshTangentsOp : MeshPrimitive has non-triangular faces." );
		}
	}

	const std::string &uPrimVarName = uPrimVarNameParameter()->getTypedValue();
	const std::string &vPrimVarName = vPrimVarNameParameter()->getTypedValue();
	const std::string &uvIndicesPrimVarName = uvIndicesPrimVarNameParameter()->getTypedValue();

	FloatVectorDataPtr uData = mesh->variableData<FloatVectorData>( uPrimVarName, PrimitiveVariable::FaceVarying );
	if( !uData )
	{
		throw InvalidArgumentException( ( boost::format( "MeshTangentsOp : MeshPrimitive has no FaceVarying FloatVectorData primitive variable named \"%s\"."  ) % ( uPrimVarName ) ).str() );
	}

	FloatVectorDataPtr vData = mesh->variableData<FloatVectorData>( vPrimVarName, PrimitiveVariable::FaceVarying );
	if( !vData )
	{
		throw InvalidArgumentException( ( boost::format( "MeshTangentsOp : MeshPrimitive has no FaceVarying FloatVectorData primitive variable named \"%s\"."  ) % ( vPrimVarName ) ).str() );
	}

	ConstIntVectorDataPtr uvIndicesData = 0;
	if( uvIndicesPrimVarName=="" )
	{
		uvIndicesData = mesh->vertexIds();
	}
	else
	{
		uvIndicesData = mesh->variableData<IntVectorData>( uvIndicesPrimVarName, PrimitiveVariable::FaceVarying );
		if( !uvIndicesData )
		{
			throw InvalidArgumentException( ( boost::format( "MeshTangentsOp : MeshPrimitive has no FaceVarying IntVectorData primitive variable named \"%s\"."  ) % ( uvIndicesPrimVarName ) ).str() );
		}
	}
	
	DataCastOpPtr dco = new DataCastOp();
	dco->targetTypeParameter()->setNumericValue( FloatVectorDataTypeId );

	bool orthoTangents = orthogonalizeTangentsParameter()->getTypedValue();

	CalculateTangents f( vertsPerFace->readable(), mesh->vertexIds()->readable(), uData->readable(), vData->readable(), uvIndicesData->readable(), orthoTangents );

	despatchTypedData<CalculateTangents, TypeTraits::IsFloatVec3VectorTypedData, HandleErrors>( pData, f );

	mesh->variables[ uTangentPrimVarNameParameter()->getTypedValue() ] = PrimitiveVariable( PrimitiveVariable::FaceVarying, f.fvUTangentsData );
	mesh->variables[ vTangentPrimVarNameParameter()->getTypedValue() ] = PrimitiveVariable( PrimitiveVariable::FaceVarying, f.fvVTangentsData );

	assert( mesh->arePrimitiveVariablesValid() );
}