Beispiel #1
0
IECore::ConstFloatVectorDataPtr Shape::computeChannelData( const std::string &channelName, const Imath::V2i &tileOrigin, const Gaffer::Context *context, const ImagePlug *parent ) const
{
	assert( parent == shapePlug() );
	if( channelName == g_shapeChannelName )
	{
		// Private channel we use for caching the shape but don't advertise via channelNames.
		return computeShapeChannelData( tileOrigin, context );
	}
	else
	{
		ConstFloatVectorDataPtr shape = parent->channelData( g_shapeChannelName, context->get<V2i>( ImagePlug::tileOriginContextName ) );
		const float c = channelValue( parent, channelName );
		if( c == 1 )
		{
			return shape;
		}
		else
		{
			FloatVectorDataPtr resultData = shape->copy();
			vector<float> &result = resultData->writable();
			for( vector<float>::iterator it = result.begin(), eIt = result.end(); it != eIt; ++it )
			{
				*it *= c;
			}
			return resultData;
		}
	}
}
Beispiel #2
0
		virtual void imageData( const Imath::Box2i &box, const float *data, size_t dataSize )
		{
			Box2i yUpBox = m_gafferFormat.yDownToFormatSpace( box );
			const V2i boxMinTileOrigin = ImagePlug::tileOrigin( yUpBox.min );
			const V2i boxMaxTileOrigin = ImagePlug::tileOrigin( yUpBox.max );
			for( int tileOriginY = boxMinTileOrigin.y; tileOriginY <= boxMaxTileOrigin.y; tileOriginY += ImagePlug::tileSize() )
			{
				for( int tileOriginX = boxMinTileOrigin.x; tileOriginX <= boxMaxTileOrigin.x; tileOriginX += ImagePlug::tileSize() )
				{
					for( int channelIndex = 0, numChannels = channelNames().size(); channelIndex < numChannels; ++channelIndex )
					{
						const V2i tileOrigin( tileOriginX, tileOriginY );
						ConstFloatVectorDataPtr tileData = getTile( tileOrigin, channelIndex );
						if( !tileData )
						{
							// we've been sent data outside of the data window
							continue;
						}

						// we must create a new object to hold the updated tile data,
						// because the old one might well have been returned from
						// computeChannelData and be being held in the cache.
						FloatVectorDataPtr updatedTileData = tileData->copy();
						vector<float> &updatedTile = updatedTileData->writable();

						const Box2i tileBound( tileOrigin, tileOrigin + Imath::V2i( GafferImage::ImagePlug::tileSize() - 1 ) );
						const Box2i transferBound = IECore::boxIntersection( tileBound, yUpBox );
						for( int y = transferBound.min.y; y<=transferBound.max.y; ++y )
						{
							int srcY = m_gafferFormat.formatToYDownSpace( y );
							size_t srcIndex = ( ( srcY - box.min.y ) * ( box.size().x + 1 ) * numChannels ) + ( transferBound.min.x - box.min.x ) + channelIndex;
							size_t dstIndex = ( y - tileBound.min.y ) * ImagePlug::tileSize() + transferBound.min.x - tileBound.min.x;
							const size_t srcEndIndex = srcIndex + transferBound.size().x * numChannels;
							while( srcIndex <= srcEndIndex )
							{
								updatedTile[dstIndex] = data[srcIndex];
								srcIndex += numChannels;
								dstIndex++;
							}
						}

						setTile( tileOrigin, channelIndex, updatedTileData );
					}
				}
			}

			dataReceivedSignal()( this, box );
		}
SmoothSkinningData::SmoothSkinningData( ConstStringVectorDataPtr influenceNames,
										ConstM44fVectorDataPtr influencePose,
										ConstIntVectorDataPtr pointIndexOffsets,
										ConstIntVectorDataPtr pointInfluenceCounts,
										ConstIntVectorDataPtr pointInfluenceIndices,
										ConstFloatVectorDataPtr pointInfluenceWeights)
{
	assert( influenceNames );
	assert( influencePose );
	assert( pointIndexOffsets );
	assert( pointInfluenceCounts );
	assert( pointInfluenceIndices );
	assert( pointInfluenceWeights );

	m_influenceNames = influenceNames->copy();
	m_influencePose = influencePose->copy();
	m_pointIndexOffsets = pointIndexOffsets->copy();
	m_pointInfluenceCounts = pointInfluenceCounts->copy();
	m_pointInfluenceIndices = pointInfluenceIndices->copy();
	m_pointInfluenceWeights = pointInfluenceWeights->copy();
}
Beispiel #4
0
IECore::ConstFloatVectorDataPtr Merge::merge( F f, const std::string &channelName, const Imath::V2i &tileOrigin ) const
{
	FloatVectorDataPtr resultData = NULL;
	// Temporary buffer for computing the alpha of intermediate composited layers.
	FloatVectorDataPtr resultAlphaData = NULL;

	const Box2i tileBound( tileOrigin, tileOrigin + V2i( ImagePlug::tileSize() ) );

	for( ImagePlugIterator it( inPlugs() ); !it.done(); ++it )
	{
		if( !(*it)->getInput<ValuePlug>() )
		{
			continue;
		}

		IECore::ConstStringVectorDataPtr channelNamesData = (*it)->channelNamesPlug()->getValue();
		const std::vector<std::string> &channelNames = channelNamesData->readable();

		ConstFloatVectorDataPtr channelData;
		ConstFloatVectorDataPtr alphaData;

		if( channelExists( channelNames, channelName ) )
		{
			channelData = (*it)->channelDataPlug()->getValue();
		}
		else
		{
			channelData = ImagePlug::blackTile();
		}

		if( channelExists( channelNames, "A" ) )
		{
			alphaData = (*it)->channelData( "A", tileOrigin );
		}
		else
		{
			alphaData = ImagePlug::blackTile();
		}

		const Box2i validBound = boxIntersection( tileBound, (*it)->dataWindowPlug()->getValue() );

		if( !resultData )
		{
			// The first connected layer, with which we must initialise our result.
			// There's no guarantee that this layer actually covers the full data
			// window though (the data window could have been expanded by the upper
			// layers) so we must take care to mask out any invalid areas of the input.
			/// \todo I'm not convinced this is correct - if we have no connection
			/// to in[0] then should that not be treated as being a black image, so
			/// we should unconditionally initaliase with in[0] and then always use
			/// the operation for in[1:], even if in[0] is disconnected. In other
			/// words, shouldn't multiplying a white constant over an unconnected
			/// in[0] produce black?
			resultData = channelData->copy();
			resultAlphaData = alphaData->copy();
			float *B = &resultData->writable().front();
			float *b = &resultAlphaData->writable().front();
			for( int y = tileBound.min.y; y < tileBound.max.y; ++y )
			{
				const bool yValid = y >= validBound.min.y && y < validBound.max.y;
				for( int x = tileBound.min.x; x < tileBound.max.x; ++x )
				{
					if( !yValid || x < validBound.min.x || x >= validBound.max.x )
					{
						*B = *b = 0.0f;
					}
					++B; ++b;
				}
			}
		}
		else
		{
			// A higher layer (A) which must be composited over the result (B).
			const float *A = &channelData->readable().front();
			float *B = &resultData->writable().front();
			const float *a = &alphaData->readable().front();
			float *b = &resultAlphaData->writable().front();

			for( int y = tileBound.min.y; y < tileBound.max.y; ++y )
			{
				const bool yValid = y >= validBound.min.y && y < validBound.max.y;
				for( int x = tileBound.min.x; x < tileBound.max.x; ++x )
				{
					const bool valid = yValid && x >= validBound.min.x && x < validBound.max.x;

					*B = f( valid ? *A : 0.0f, *B, valid ? *a : 0.0f, *b );
					*b = f( valid ? *a : 0.0f, *b, valid ? *a : 0.0f, *b );

					++A; ++B; ++a; ++b;
				}
			}
		}
	}

	return resultData;
}
void NURBSPrimitive::setTopology(  int uOrder, ConstFloatVectorDataPtr uKnot, float uMin, float uMax,
	int vOrder, ConstFloatVectorDataPtr vKnot, float vMin, float vMax )
{
	// check order isn't too small
	if( uOrder<2 )
	{
		throw Exception( "Order in u direction too small." );
	}
	if( vOrder<2 )
	{
		throw Exception( "Order in v direction too small." );
	}

	// check knots have enough entries for the order.
	// an order of N demands at least N control points
	// and numKnots==numControlPoints + order
	// so we need numKnots>=2*order
	if( (int)uKnot->readable().size() < uOrder * 2 )
	{
		throw Exception( "Not enough knot values in u direction." );
	}
	if( (int)vKnot->readable().size() < vOrder * 2 )
	{
		throw Exception( "Not enough knot values in v direction." );
	}

	// check knots are monotonically increasing
	const vector<float> &u = uKnot->readable();
	float previous = u[0];
	for( unsigned int i=0; i<u.size(); i++ )
	{
		if( u[i]<previous )
		{
			throw Exception( "Knots not monotonically increasing in u direction." );
		}
		previous = u[i];
	}
	const vector<float> &v = vKnot->readable();
	previous = v[0];
	for( unsigned int i=0; i<v.size(); i++ )
	{
		if( v[i]<previous )
		{
			throw Exception( "Knots not monotonically increasing in v direction." );
		}
		previous = v[i];
	}

	// check min and max parametric values are in range
	if( uMin > uMax )
	{
		throw Exception( "uMin greater than uMax." );
	}
	if( vMin > vMax )
	{
		throw Exception( "vMin greater than vMax." );
	}

	if( uMin < u[uOrder-2] )
	{
		throw Exception( "uMin too small." );
	}
	if( uMax > u[u.size()-uOrder+1] )
	{
		throw Exception( "uMax too great." );
	}

	if( vMin < v[vOrder-2] )
	{
		throw Exception( "vMin too small." );
	}
	if( vMax > v[v.size()-vOrder+1] )
	{
		throw Exception( "vMax too great." );
	}

	// set everything (taking copies of the data)

	m_uOrder = uOrder;
	m_uKnot = uKnot->copy();
	m_uMin = uMin;
	m_uMax = uMax;
	m_vOrder = vOrder;
	m_vKnot = vKnot->copy();
	m_vMin = vMin;
	m_vMax = vMax;
}