FromHoudiniGeometryConverter::Convertability FromHoudiniPolygonsConverter::canConvert( const GU_Detail *geo )
{
	const GA_PrimitiveList &primitives = geo->getPrimitiveList();
	
	for ( GA_Iterator it=geo->getPrimitiveRange().begin(); !it.atEnd(); ++it )
	{
		const GA_Primitive *prim = primitives.get( it.getOffset() );
		if ( prim->getTypeId() != GEO_PRIMPOLY )
		{
			return Inapplicable;
		}
	}
	
	// is there a single named shape?
	const GEO_AttributeHandle attrHandle = geo->getPrimAttribute( "name" );
	if ( attrHandle.isAttributeValid() )
	{
		const GA_ROAttributeRef attrRef( attrHandle.getAttribute() );
		if ( geo->getUniqueValueCount( attrRef ) < 2 )
		{
			return Ideal;
		}
	}
	
	return Suitable;
}
FromHoudiniGeometryConverter::Convertability FromHoudiniCurvesConverter::canConvert( const GU_Detail *geo )
{
	const GA_PrimitiveList &primitives = geo->getPrimitiveList();
	
	unsigned numPrims = geo->getNumPrimitives();
	GA_Iterator firstPrim = geo->getPrimitiveRange().begin();
	if ( !numPrims || !compatiblePrimitive( primitives.get( firstPrim.getOffset() )->getTypeId() ) )
	{
		return Inapplicable;
	}
	
	const GEO_Curve *firstCurve = (const GEO_Curve*)primitives.get( firstPrim.getOffset() );
	bool periodic = firstCurve->isClosed();
	unsigned order = firstCurve->getOrder();
	
	for ( GA_Iterator it=firstPrim; !it.atEnd(); ++it )
	{
		const GA_Primitive *prim = primitives.get( it.getOffset() );
		if ( !compatiblePrimitive( prim->getTypeId() ) )
		{
			return Inapplicable;
		}
		
		const GEO_Curve *curve = (const GEO_Curve*)prim;
		if ( curve->getOrder() != order )
		{
			return Inapplicable;
		}
		
		if ( curve->isClosed() != periodic )
		{
			return Inapplicable;
		}
	}
	
	// is there a single named shape?
	const GEO_AttributeHandle attrHandle = geo->getPrimAttribute( "name" );
	if ( attrHandle.isAttributeValid() )
	{
		const GA_ROAttributeRef attrRef( attrHandle.getAttribute() );
		if ( geo->getUniqueValueCount( attrRef ) < 2 )
		{
			return Ideal;
		}
	}
	
	return Suitable;
}
示例#3
0
void detail::getStringTableMapping(GEO_AttributeHandle &srcAttrH, GEO_AttributeHandle &destAttrH, detail::stringTableMapping& o_stm)
{
	o_stm.clear();

	const GB_Attribute* srcAttr = srcAttrH.getAttribute();
	GB_Attribute* destAttr = destAttrH.getAttribute();

	if( srcAttr->getType() == GB_ATTRIB_INDEX && destAttr->getType() == GB_ATTRIB_INDEX)
	{
		for( int i=0; i<srcAttr->getIndexSize(); ++i)
		{
			int destIndex = destAttr->addIndex(srcAttr->getIndex(i));
			o_stm.insert(stringTableMapping::value_type(i, destIndex));
		}
	}

}
示例#4
0
bool GeoAttributeCopier::createHandles(const attrib_copy& copy, GEO_AttributeHandle& hSrc,
	GEO_AttributeHandle& hDest)
{
	// find source attrib
	hSrc = copy.m_srcGeo->getAttribute(copy.m_srcDict, copy.m_srcName.c_str());
	if(!hSrc.isAttributeValid())
		return false;

	const char* destName_ = copy.m_destName.c_str();
	const GB_Attribute* srcAttrib = hSrc.getAttribute();
	assert(srcAttrib);

	// create attrib if it doesn't exist, or does but data type doesn't match
	bool createAttrib = true;
	GEO_AttributeHandle hExist = m_destGeo.getAttribute(copy.m_destDict, destName_);
	if(hExist.isAttributeValid())
	{
		const GB_Attribute* destAttrib = hExist.getAttribute();
		assert(destAttrib);
		createAttrib = (destAttrib->getType() != srcAttrib->getType());
	}

	if(createAttrib)
	{
		GB_AttributeRef aref = m_destGeo.addAttribute(destName_, srcAttrib->getSize(),
			srcAttrib->getType(), srcAttrib->getDefault(), copy.m_destDict);

		if(!aref.isValid())
			return false;
	}

	hDest = m_destGeo.getAttribute(copy.m_destDict, destName_);
	hDest.setSourceMap(hSrc);
	return true;
}
void IECoreMantra::ProceduralPrimitive::addVisibleRenderable( VisibleRenderablePtr renderable )
{
	ToHoudiniGeometryConverterPtr converter = ToHoudiniGeometryConverter::create( renderable );
	if( !converter ) 
	{
		msg( Msg::Warning, "ProceduralPrimitive::addVisibleRenderable", "converter could not be found" );
		return;
	}
	GU_Detail *gdp = allocateGeometry();
	GU_DetailHandle handle;
	handle.allocateAndSet( (GU_Detail*)gdp, false );
	bool converted = converter->convert( handle );
	if ( !converted )
	{
		msg( Msg::Warning, "ProceduralPrimitive::addVisibleRenderable", "converter failed" );
		return;
	}
	/// \todo ToHoudiniGeometryConverter does not create a Houdini style uv attribute.
	/// We make one from s and t. This code should probably live in a converter or in an Op that
	/// remaps IECore conventions to common Houdini ones.
	MeshPrimitivePtr mesh = runTimeCast<MeshPrimitive> (renderable);
	if ( mesh )
	{
		gdp->addTextureAttribute( GA_ATTRIB_VERTEX );
		GEO_AttributeHandle auv = gdp->getAttribute( GA_ATTRIB_VERTEX, "uv" );
		GEO_AttributeHandle as = gdp->getAttribute( GA_ATTRIB_VERTEX, "s" );
		GEO_AttributeHandle at = gdp->getAttribute( GA_ATTRIB_VERTEX, "t" );
		if ( auv.isAttributeValid() && as.isAttributeValid() && at.isAttributeValid() )
		{
			GA_GBPrimitiveIterator it( *gdp );
			GA_Primitive *p = it.getPrimitive();
			while ( p )
			{
				for (int i = 0; i < p->getVertexCount(); ++i)
				{
					GA_Offset v = p->getVertexOffset(i);
					as.setVertex(v);
					at.setVertex(v);
					auv.setVertex(v);
					auv.setF( as.getF(0), 0 );
					auv.setF( ((at.getF(0) * -1.0f) + 1.0f), 1 ); // wat, t arrives upside down for some reason.
					auv.setF( 0.0f, 2 );
				}
				++it;
				p = it.getPrimitive();
			}
		}
	}

	if ( m_renderer->m_motionType == RendererImplementation::Geometry )
	{
		msg(Msg::Debug, "IECoreMantra::ProceduralPrimitive::addVisibleRenderable", "MotionBlur:Geometry" );
		if ( !m_renderer->m_motionTimes.empty() )
		{
			if ( (size_t)m_renderer->m_motionSize == m_renderer->m_motionTimes.size() )
			{
				openGeometryObject();
			}
			addGeometry(gdp, m_renderer->m_motionTimes.front());
			m_renderer->m_motionTimes.pop_front();
			if ( m_renderer->m_motionTimes.empty() )
			{
				applySettings();
				closeObject();
			}
		}
	}
	else if ( m_renderer->m_motionType == RendererImplementation::ConcatTransform ||
			  m_renderer->m_motionType == RendererImplementation::SetTransform )
	{
		// It isn't clear that this will give correct results. 
		// ConcatTransform may need to interpolate transform snapshots.
		msg(Msg::Debug, "IECoreMantra::ProceduralPrimitive::addVisibleRenderable", "MotionBlur:Transform" );
		openGeometryObject();
			addGeometry(gdp, 0.0f);
			while ( !m_renderer->m_motionTimes.empty() )
			{
				setPreTransform( convert< UT_Matrix4T<float> >(m_renderer->m_motionTransforms.front()),
								 m_renderer->m_motionTimes.front() );
				m_renderer->m_motionTimes.pop_front();
				m_renderer->m_motionTransforms.pop_front();
			}
			applySettings();
		closeObject();
		m_renderer->m_motionType = RendererImplementation::Unknown;
	}
	else if ( m_renderer->m_motionType == RendererImplementation::Velocity )
	{
		msg(Msg::Debug, "IECoreMantra::ProceduralPrimitive::addVisibleRenderable", "MotionBlur:Velocity" );
		openGeometryObject();
			addGeometry(gdp, 0.0f);
			addVelocityBlurGeometry(gdp, m_preBlur, m_postBlur);
			applySettings();
		closeObject();
		m_renderer->m_motionType = RendererImplementation::Unknown;
	}
	else
	{
		msg(Msg::Debug, "IECoreMantra::ProceduralPrimitive::addVisibleRenderable", "MotionBlur:None" );
		openGeometryObject();
			addGeometry( gdp, 0.0f );
			setPreTransform( convert< UT_Matrix4T<float> >(m_renderer->m_transformStack.top()), 0.0f);
			applySettings();
		closeObject();
	}
}
示例#6
0
Geo2Emp::ErrorCode Geo2Emp::loadMeshShape( const Nb::Body* pBody )
{	
	if (!_gdp)
	{
		//If we don't have a GDP for writing data into Houdini, return error.
		return EC_NULL_WRITE_GDP;
	}

	LogInfo() << "=============== Loading mesh shape ===============" << std::endl; 

	const Nb::TriangleShape* pShape;

	pShape = pBody->queryConstTriangleShape();

	if (!pShape)
	{
		//NULL mesh shape, so return right now.
		return EC_NO_TRIANGLE_SHAPE;
	}

	//Get access to shapes we need to loading a mesh (point and triangle)
	const Nb::TriangleShape& triShape = pBody->constTriangleShape();
	const Nb::PointShape& ptShape = pBody->constPointShape();

	//Retrieve the number of points and channels
	int64_t size = ptShape.size();
	int channelCount = ptShape.channelCount();

	//Attribute Lookup Tables
	std::vector< GEO_AttributeHandle > attribLut;
	std::vector<GeoAttributeInfo> attribInfo; //houdini types for the naiad channels.
	GeoAttributeInfo* pInfo;
	GEO_AttributeHandle attr;
	std::string attrName;

	float zero3f[3] = {0,0,0};
	float zero1f = 0;
	int zero3i[3] = {0,0,0};
	int zero1i = 0;
	const void* data;

	attribLut.clear();
	attribInfo.clear();
	attribLut.resize( channelCount );
	attribInfo.resize( channelCount );

	//Prepare for a blind copy of Naiad channels to Houdini attributes.
	//Iterate over the channels and create the corresponding attributes in the GDP
	for (int i = 0; i < channelCount; i++)
	{
		//std::cout << "channel: " << i << std::endl;
		const Nb::ChannelCowPtr& chan = ptShape.channel(i);

		if ( _empAttribMangle.find( chan->name() ) != _empAttribMangle.end() )
			attrName = _empAttribMangle[ chan->name() ];
		else
			attrName = chan->name();

		LogDebug() << "Processing EMP Channel: " << chan->name() << "; mangled: " << attrName << std::endl;

		//Determine the attribute type, and store it
		pInfo = &(attribInfo[ i ]);
		pInfo->supported = false;
		pInfo->size = 0;
		pInfo->use64 = false;

		switch ( chan->type() )
		{
			case Nb::ValueBase::IntType:
				LogDebug() << "IntType " << std::endl;
				pInfo->type = GB_ATTRIB_INT;
				pInfo->entries = 1;
				pInfo->size = sizeof(int);
				pInfo->supported = true;
				data = &zero1i;
				break;
			case Nb::ValueBase::Int64Type: //NOTE: This might need to be handled differently ... just remember this 'hack'
				pInfo->type = GB_ATTRIB_INT;
				pInfo->entries = 1;
				pInfo->size = sizeof(int);
				pInfo->supported = true;
				data = &zero1i;
				break;
			case Nb::ValueBase::FloatType:
				LogDebug() << "FloatType " << std::endl;
				pInfo->type = GB_ATTRIB_FLOAT;
				pInfo->size = sizeof(float);
				pInfo->entries = 1;
				pInfo->supported = true;
				data = &zero1f;
				break;
			case Nb::ValueBase::Vec3fType:
				LogDebug() << "Vec3fType " << std::endl;
				pInfo->type = GB_ATTRIB_VECTOR;
				pInfo->size = sizeof(float);
				pInfo->entries = 3;
				pInfo->supported = true;
				data = &zero3f;
				break;
			default:
				pInfo->supported = false;
				break;
		}

		//If the attribute is not supported, then continue with the next one.
		if (!pInfo->supported)
		{
			LogVerbose() << "Unsupported attribute. Skipping:" << attrName << std::endl;
			continue;
		}

		//Check whether the attribute exists or not
		attr = _gdp->getPointAttribute( attrName.c_str() );
		if ( !attr.isAttributeValid() )
		{
			LogDebug() << "Creating attribute in GDP:" << attrName << std::endl;
			_gdp->addPointAttrib( attrName.c_str(), pInfo->size * pInfo->entries, pInfo->type, data);
			attr = _gdp->getPointAttribute( attrName.c_str() );
		}

		//Put the attribute handle in a Lut for easy access later (during transfer)
		attribLut[i] = attr;
	}	

	//Get index buffer from the triangle shape
	const Nb::Buffer3i& bufIndex ( triShape.constBuffer3i("index") );
	int64_t indexBufSize = bufIndex.size();

	//Before we start adding points to the GDP, just record how many points are already there.
	int initialPointCount = _gdp->points().entries();	

	GEO_Point *ppt;
	//Now, copy all the points into the GDP.
	for (int ptNum = 0; ptNum < ptShape.size(); ptNum ++)
	{
		ppt = _gdp->appendPoint();
		
		//Iterate over the channels in the point shape and copy the data
		for (int channelIndex = 0; channelIndex < channelCount; channelIndex++)
		{
			pInfo = &(attribInfo[ channelIndex ]);
			//If the attribute is not supported then skip it
			if (!pInfo->supported)
			{
				continue;
			}

			attribLut[ channelIndex ].setElement( ppt );

			//Transfer supported attributes (this includes the point Position)
			switch ( pInfo->type )
			{
				case GB_ATTRIB_INT:
					{
						const Nb::Buffer1i& channelData =  ptShape.constBuffer1i(channelIndex);
						//Get the Houdini point attribute using the name list we built earlier.
						attribLut[channelIndex].setI( channelData(ptNum) );
					}
					break;
				case GB_ATTRIB_FLOAT:
					{
						//TODO: Handle more that 1 entry here, if we ever get something like that ... although I doubt it would happen.
						const Nb::Buffer1f& channelData( ptShape.constBuffer1f(channelIndex) );
						//Get the Houdini point attribute using the name list we built earlier.
						attribLut[channelIndex].setF( channelData(ptNum) );
					}
					break;
				case GB_ATTRIB_VECTOR:
					{
						const Nb::Buffer3f& channelData = ptShape.constBuffer3f(channelIndex);
						//Get the Houdini point attribute using the name list we built earlier.
						attribLut[channelIndex].setV3( UT_Vector3( channelData(ptNum)[0], channelData(ptNum)[1], channelData(ptNum)[2]  ) );
					}
					break;
				default:
					//not yet implemented.
					continue;
					break;
			}

		}

	}

	//Now that all the points are in the GDP, build the triangles
	GU_PrimPoly *pPrim;
	for (int tri = 0; tri < indexBufSize; tri++)
	{
		pPrim = GU_PrimPoly::build(_gdp, 3, GU_POLY_CLOSED, 0); //Build a closed poly with 3 points, but don't add them to the GDP.
		//Set the three vertices of the triangle
		for (int i = 0; i < 3; i++ )
		{
			pPrim->setVertex(i, _gdp->points()[ initialPointCount + bufIndex(tri)[i] ] );
		}
	}

	return EC_SUCCESS;
}
示例#7
0
Geo2Emp::ErrorCode Geo2Emp::loadParticleShape( const Nb::Body* pBody )
{
	if (!_gdp)
	{
		//If we don't have a GDP for writing data into Houdini, return error.
		return EC_NULL_WRITE_GDP;
	}

	const Nb::ParticleShape* pShape;

	LogInfo() << "=============== Loading particle shape ===============" << std::endl; 

	pShape = pBody->queryConstParticleShape();

	if (!pShape)
	{
		//std::cout << "Received NULL particle shape!" << std::endl;
		return EC_NO_PARTICLE_SHAPE;
	}

	//Attribute Lookup Tables
	std::vector< GEO_AttributeHandle > attribLut;
	std::vector<GeoAttributeInfo> attribInfo; //houdini types for the naiad channels.
	GeoAttributeInfo* pInfo;
	std::string attrName;

	//We have a valid particle shape. Start copying particle data over to the GDP
	int64_t size = pShape->size();
	int channelCount = pShape->channelCount();
	GEO_Point *ppt;
	GEO_AttributeHandle attr;
	GU_PrimParticle *pParticle;
	std::vector<std::string> houdiniNames; //houdini names that correspond to naiad channels.
	std::vector<GB_AttribType> houdiniTypes; //houdini types for the naiad channels.
	//Default values for attributes
	float zero3f[3] = {0,0,0};
	float zero1f = 0;
	//int zero3i[3] = {0,0,0};
	int zero1i = 0;
	const void* data;

	LogVerbose() << "Particle shape size: " << size << std::endl;
	LogVerbose() << "Particle shape channel count: " << channelCount << std::endl;

	LogVerbose() << "Building particle primitive...";
	pParticle = GU_PrimParticle::build(_gdp, 0);
	LogVerbose() << "done." << std::endl;

	attribLut.clear();
	attribInfo.clear();
	attribLut.resize( channelCount );
	attribInfo.resize( channelCount );

	//Prepare for a blind copy of Naiad channels to Houdini attributes.
	//Iterate over the channels and create the corresponding attributes in the GDP
	for (int i = 0; i < channelCount; i++)
	{
		//std::cout << "channel: " << i << std::endl;
		const Nb::ChannelCowPtr& chan = pShape->channel(i);

		if ( _empAttribMangle.find( chan->name() ) != _empAttribMangle.end() )
			attrName = _empAttribMangle[ chan->name() ];
		else
			attrName = chan->name();

		LogDebug() << "Processing EMP Channel: " << chan->name() << "; mangled: " << attrName << std::endl;

		//Determine the attribute type, and store it
		pInfo = &(attribInfo[ i ]);
		pInfo->supported = false;
		pInfo->size = 0;
		pInfo->use64 = false;

		if (attrName.compare("P") == 0)
			//Don't treat position as an attribute. This needs to be handled separately.
			continue;

		switch ( chan->type() )
		{
			case Nb::ValueBase::IntType:
				pInfo->type = GB_ATTRIB_INT;
				pInfo->entries = 1;
				pInfo->size = sizeof(int);
				pInfo->supported = true;
				data = &zero1i;
				break;			
			case Nb::ValueBase::Int64Type: //NOTE: This might need to be handled differently ... just remember this 'hack'
				pInfo->type = GB_ATTRIB_INT;
				pInfo->entries = 1;
				pInfo->size = sizeof(int);
				pInfo->supported = true;
				pInfo->use64 = true;
				data = &zero1i;
				break;
			case Nb::ValueBase::FloatType:
				pInfo->type = GB_ATTRIB_FLOAT;
				pInfo->size = sizeof(float);
				pInfo->entries = 1;
				pInfo->supported = true;
				data = &zero1f;
				break;
			case Nb::ValueBase::Vec3fType:
				pInfo->type = GB_ATTRIB_VECTOR;
				pInfo->size = sizeof(float);
				pInfo->entries = 3;
				pInfo->supported = true;
				data = &zero3f;
				break;
			default:
				pInfo->supported = false;
				break;
		}

		//If the attribute is not supported, then continue with the next one.
		if (!pInfo->supported)
		{
			LogVerbose() << "Unsupported attribute. Skipping:" << attrName << std::endl;
			continue;
		}

		//Check whether the attribute exists or not
		attr = _gdp->getPointAttribute( attrName.c_str() );
		if ( !attr.isAttributeValid() )
		{
			LogVerbose() << "Creating attribute in GDP:" << attrName << std::endl;
			LogDebug() << "Name: " << attrName << std::endl << "Entries: " << pInfo->entries << std::endl << "Size: " << pInfo->size << std::endl;
			_gdp->addPointAttrib( attrName.c_str(), pInfo->size * pInfo->entries, pInfo->type, data);
			attr = _gdp->getPointAttribute( attrName.c_str() );
		}

		//Put the attribute handle in a Lut for easy access later.
		attribLut[i] = attr;
	}	

	//The channel values for particle shapes are stored in blocks/tiles.
	unsigned int absPtNum = 0;

	//Get the block array for the positions channel
	const em::block3_array3f& positionBlocks( pShape->constBlocks3f("position") );	
	unsigned int numBlocks = positionBlocks.block_count();
	unsigned int bsize;
	float dec_accumulator = 0.0f;
	float dec = (1.0f - (_decimation)/100.0f);
	LogInfo() << "Keeping decimation value: " << dec << std::endl;

	for (int blockIndex = 0; blockIndex < numBlocks; blockIndex ++)
	{
		//if (ptNum % 100 == 0)
		//Get a single block from the position blocks
		const em::block3vec3f& posBlock = positionBlocks(blockIndex);

		if ( blockIndex % 100 == 0 )
			LogDebug() << "Block: " << blockIndex << "/" << numBlocks << std::endl;
		//Iterate over all the points/particles in the position block
		bsize = posBlock.size();

		//Only process the point if the decimation accumulator is greater than one.

		for (int ptNum = 0; ptNum < bsize; ptNum++, absPtNum++)
		{
			dec_accumulator += dec;
			if (dec_accumulator < 1.0f)
				//Skip this point
				continue;
			//Process this point, remove the dec_accumulator rollover.
			dec_accumulator -= (int) dec_accumulator;

			ppt = _gdp->appendPoint();
			pParticle->appendParticle(ppt);

			ppt->setPos( UT_Vector3( posBlock(ptNum)[0], posBlock(ptNum)[1], posBlock(ptNum)[2] ) );
			
			//Loop over the channels and add the attributes
			//This loop needs to be as fast as possible.
			for (int channelIndex = 0; channelIndex < channelCount; channelIndex++)
			{
				pInfo = &(attribInfo[ channelIndex ]);
				//If the attribute is not supported then skip it
				if (!pInfo->supported)
				{
					continue;
				}

				attribLut[ channelIndex ].setElement( ppt );

				switch ( pInfo->type )
				{
					case GB_ATTRIB_INT:
						{
							if (pInfo->use64)
							{
								const em::block3i64& channelData( pShape->constBlocks1i64(channelIndex)(blockIndex) );
								//Get the Houdini point attribute using the name list we built earlier.
								attribLut[channelIndex].setI( channelData(ptNum) );
							}
							else
							{
								const em::block3i& channelData( pShape->constBlocks1i(channelIndex)(blockIndex) );
								//Get the Houdini point attribute using the name list we built earlier.
								attribLut[channelIndex].setI( channelData(ptNum) );
							}
						}
						break;
					case GB_ATTRIB_FLOAT:
						{
							//TODO: Handle more that 1 entry here, if we ever get something like that ... although I doubt it would happen.
							const em::block3f& channelData( pShape->constBlocks1f(channelIndex)(blockIndex) );
							//Get the Houdini point attribute using the name list we built earlier.
							attribLut[channelIndex].setF( channelData(ptNum) );
						}
						break;
					case GB_ATTRIB_VECTOR:
						{
							const em::block3vec3f& channelData( pShape->constBlocks3f(channelIndex)(blockIndex) );
							//Get the Houdini point attribute using the name list we built earlier.
							attribLut[channelIndex].setV3( UT_Vector3( channelData(ptNum)[0], channelData(ptNum)[1], channelData(ptNum)[2]  ) );
						}
						break;
					default:
						//not yet implemented.
						continue;
						break;
				}

			}
		}	
	}

	//std::cout << "all done. " << std::endl;
	return EC_SUCCESS;
}
FromHoudiniGeometryConverter::Convertability FromHoudiniGroupConverter::canConvert( const GU_Detail *geo )
{
	const GA_PrimitiveList &primitives = geo->getPrimitiveList();
	
	// are there multiple primitives?
	unsigned numPrims = geo->getNumPrimitives();
	if ( numPrims < 2 )
	{
		return Admissible;
	}
	
	// are there mixed primitive types?
	GA_Iterator firstPrim = geo->getPrimitiveRange().begin();
	GA_PrimitiveTypeId firstPrimId = primitives.get( firstPrim.getOffset() )->getTypeId();
	for ( GA_Iterator it=firstPrim; !it.atEnd(); ++it )
	{
		if ( primitives.get( it.getOffset() )->getTypeId() != firstPrimId )
		{
			return Ideal;
		}
	}
	
	// are there multiple named shapes?
	const GEO_AttributeHandle attrHandle = geo->getPrimAttribute( "name" );
	if ( attrHandle.isAttributeValid() )
	{
		const GA_ROAttributeRef attrRef( attrHandle.getAttribute() );
		if ( geo->getUniqueValueCount( attrRef ) > 1 )
		{
			return Ideal;
		}
	}
	
	// are the primitives split into groups?
	UT_PtrArray<const GA_ElementGroup*> primGroups;
	geo->getElementGroupList( GA_ATTRIB_PRIMITIVE, primGroups );
	if ( primGroups.isEmpty() )
	{
		return Admissible;
	}
	
	bool externalGroups = false;
	for ( unsigned i=0; i < primGroups.entries(); ++i )
	{
		const GA_ElementGroup *group = primGroups[i];
		if ( group->getInternal() )
		{
			continue;
		}
		
		if ( group->entries() == numPrims )
		{
			return Admissible;
		}
		
		externalGroups = true;
	}
	
	if ( externalGroups )
	{
		return Ideal;
	}
	
	return Admissible;
}
Geo2Emp::ErrorCode Geo2Emp::saveParticleShape(Nb::Body*& pParticleBody)
{
	if (!_gdp)
	{
		//If we don't have a GDP for writing data into Houdini, return error.
		return EC_NULL_READ_GDP;
	}

	LogInfo() << " ************** Saving Particle Shape ************** " << std::endl;	

	
	pParticleBody = Nb::Factory::createBody("Particle", _bodyName);
		
	//get the mutable shapes for the mesh body.
	Nb::ParticleShape& particleShape( pParticleBody->mutableParticleShape() );
	Nb::TileLayout& layout( pParticleBody->mutableLayout() );
	
	layout.worldBoxRefine( em::vec3f(0,0,0), em::vec3f(1,1,1),1,false);

	//Maps houdini attributes to some cached data
  GEO_AttributeHandleList attribList;
  GEO_AttributeHandle* pAttr;
	const GEO_PointList& ptlist = _gdp->points();
	int numpoints = ptlist.entries();
  GB_Attribute* pBaseAttr;
	std::map<int, AttributeInfo> attrLut;
	AttributeInfo* pAttrInfo;
	int attrSize;
	int numAttribs;
	const GEO_PointAttribDict *pPtAttrDict;

	attribList.bindDetail(_gdp);
	
	//Add all the GDP point attributes to the attribute list
	attribList.appendAllAttributes( GEO_POINT_DICT );

	numAttribs = attribList.entries();

	LogVerbose() << "Number of hou attributes: " << attribList.entries() << " empty:" << attribList.isEmpty() << std::endl;	

	for (int i = 0; i < numAttribs; i++)
	{
		pAttr = attribList[i];
		pAttrInfo = &( attrLut[i] );
		pAttrInfo->entries = pAttr->entries();

		LogDebug() << "pAttr: " << pAttr << " - " << std::endl;
		LogDebug() << "Attribute #" << i << " - " << pAttr->getName() << " [size]  " << attrSize << std::endl;

		//Note: if attribute overrides need to be done, this is probably the place.
		//The attribute creation code *might* need to be moved to another function...or at least some of it
		//so that it may be shared by other conversion code
		if ( pAttr->isP() )
		{
			//If we have position, then set up the type manually
			LogDebug() << "We have a position attribute. Set attributes manually." << std::endl;
			pAttrInfo->entries = 3;
			pAttrInfo->type = GB_ATTRIB_VECTOR;
		}
		else
		{
			//Retrieve attribute info through the standard channels...
			LogDebug() << "Retrieving attribute data using the Point Dictionary." << std::endl;

			//Now that we now which attribute we want, find it using the GU_Detail object.
			//TODO: Is there some beter way of doing this???
			pPtAttrDict = dynamic_cast< const GEO_PointAttribDict* >( _gdp->getAttributeDict( GEO_POINT_DICT ) );
			pBaseAttr = _gdp->getAttributeDict( GEO_POINT_DICT )->find( pAttr->getName() );
			pAttrInfo->type = pBaseAttr->getType();
		}

		LogDebug() << "Switching on attribute type." << std::endl;

	}


	//This preprocessor defition was placed here simply because it is only applicable to this code section
	//and will fail to work anywhere else. Not to be classified under "best coding practices".
	#define PROCESSCHANNEL_PARTICLE(type1, type2, defaults) \
	{ \
		particleShape.guaranteeChannel ## type1 (empAttrName); \
		pAttrInfo->empIndex = particleShape.channelIndex( empAttrName ); \
		em::block3_array ## type1 &vectorBlocks( particleShape.mutableBlocks ## type1 ( empAttrName ) ); \
		em::block3 ## type2 &vectorData( vectorBlocks(0) ); \
		vectorData.reserve( _gdp->points().entries() ); \
		pAttrInfo->supported = true; \
	}

	//Iterate over the BGEO attributes and create corresponding channels in the EMP body
	//Also, store the channel index for direct lookups when transferring data.
	for (int i = 0; i < numAttribs; i++)
	{
		//Mangle the geo attribute name right now
		pAttr = attribList[i];
		std::string empAttrName;
		if ( _geoAttribMangle.find( pAttr->getName() ) != _geoAttribMangle.end() )
			empAttrName = _geoAttribMangle[ pAttr->getName() ];
		else
			empAttrName = pAttr->getName();
		LogDebug() << "Mangling name: " << pAttr->getName() << " ==> " << empAttrName << std::endl;
		pAttrInfo = &( attrLut[i] );
		pAttrInfo->supported = false;
		pAttrInfo->flipvector = true; //By default, flip vectors

		if ( std::string(pAttr->getName()).compare("P") == 0 )
		{	
			pAttrInfo->flipvector = false;
		}

		pAttrInfo->empIndex = -1;
		switch ( pAttrInfo->type )
		{
			case GB_ATTRIB_FLOAT:
				LogDebug() << "Float " << pAttrInfo->entries << std::endl;
				switch ( pAttrInfo->entries )
				{
					case 1:
						PROCESSCHANNEL_PARTICLE( 1f, f, 0.0f );
						break;
					case 3:
						PROCESSCHANNEL_PARTICLE( 3f, vec3f, em::vec3f(0.0f) );
						break;
				}
				break;
			case GB_ATTRIB_INT:
				LogDebug() << "Int " << pAttrInfo->entries << std::endl;
				switch ( pAttrInfo->entries )
				{
					case 1:
						PROCESSCHANNEL_PARTICLE( 1i, i, 0 );
						break;
					case 3:
						PROCESSCHANNEL_PARTICLE( 3i, vec3i, em::vec3i(0.0f) );
						break;
				}
				break;
			case GB_ATTRIB_VECTOR:
				{
					LogDebug() << "Vector (Vector3)" << std::endl;
					if ( empAttrName.compare("position") == 0) 
					{ 
						//If this is position, then set the tile layout
						layout.pointRefine( particleShape.mutableBlocks3f("position") ); 
						particleShape.sync( layout ); 
					}
					PROCESSCHANNEL_PARTICLE( 3f, vec3f, em::vec3f(0.0f) );
					break;
				}
			case GB_ATTRIB_MIXED:
			case GB_ATTRIB_INDEX:
			default:
				//Unsupported attribute, so give it a skip.
				LogDebug() << "Unsupported attribute type for blind copy [" << pAttrInfo->type << "]" << std::endl;
				continue;
				break;
		}

		if ( pAttrInfo->supported )
			LogDebug() << "Supported Blind Copy! Channel: [" << empAttrName << "] Index: " << pAttrInfo->empIndex << std::endl;
		else
		{
			LogDebug() << "Unsupported Blind Copy! Channel: [" << empAttrName << "]" <<  std::endl;
			continue;
		}
	} //for numAttribs

	//Loop over the points and transfer attributes

	for (int i = 0; i < numpoints; i++)
	{
		transferParticlePointAttribs( numAttribs, attribList, attrLut, particleShape, ptlist[i] );
	}

	pParticleBody->update();

	return EC_SUCCESS;





	//Ng::TileLayout& layout( pParticleBody->mutableLayout() );
	
	// PLEASE NOTE: this should really be a box close to a particle, instead of (0,0,0)...(1,1,1) but I was in a hurry!
	// so this will make some "dummy" tiles...
	layout.worldBoxRefine( em::vec3f(0,0,0), em::vec3f(1,1,1),1,false);
	particleShape.sync( layout );

	//For the sake of simplicity, copy ALL the points in the GDP across.
	//It will be much slower if we have to filter out all the non-mesh vertices and then remap the vertices to new point numbers.
	UT_Vector3 pos, v3;
	GEO_AttributeHandle attr_v, attr_N;

	//The position attribute needs special/explicit treatment
	//Get the position buffer from the particleShape
	
	em::block3_array3f& vectorBlocks( particleShape.mutableBlocks3f("position") );
	em::block3vec3f& vectorData( vectorBlocks(0) );

	//Make sure we have enough space in the position attribute
	vectorData.reserve( _gdp->points().entries() );

	for (int i = 0; i < numpoints; i++)
	{
		//Set the point position
		pos = _gdp->points()[i]->getPos();
		vectorData.push_back( em::vec3f( pos[0], pos[1], pos[2] ) );
	}

	pParticleBody->update();

	LogInfo() << " ************** Done with Particle Shape ************** " << std::endl;	
	
	return EC_SUCCESS;
}
示例#10
0
Geo2Emp::ErrorCode Geo2Emp::saveMeshShape(std::list<Nb::Body*>& meshBodyList)
{
	const GEO_Primitive* pprim;
	const GEO_Point* ppt;
	GEO_AttributeHandleList attribList;
	GEO_AttributeHandle* pAttr;
	GB_Attribute* pBaseAttr;
	UT_Vector3 pos;
	Nb::Body* pMeshBody;
	std::string bodyName, attrname;
	int ptnum, totalpoints;
	int numAttribs;
	//Maps houdini attributes to some cached data
	std::map<int, AttributeInfo> attrLut;
	AttributeInfo* pAttrInfo;
	int attrSize;
	const GEO_PointAttribDict *pPtAttrDict;

	if (!_gdp)
	{
		//If we don't have a GDP for writing data into Houdini, return error.
		return EC_NULL_READ_GDP;
	}

	LogInfo() << " ************** Saving Mesh Shape ************** " << std::endl;	

	attribList.bindDetail(_gdp);
	
	//Add all the GDP point attributes to the attribute list
	attribList.appendAllAttributes( GEO_POINT_DICT );

	numAttribs = attribList.entries();

	LogVerbose() << "Number of attributes: " << attribList.entries() << " empty:" << attribList.isEmpty() << std::endl;	

	for (int i = 0; i < numAttribs; i++)
	{
		pAttr = attribList[i];
		pAttrInfo = &( attrLut[i] );
		pAttrInfo->entries = pAttr->entries();

		LogDebug() << "pAttr: " << pAttr << " - " << std::endl;
		LogDebug() << "Attribute #" << i << " - " << pAttr->getName() << " - " << attrSize << std::endl;

		//Note: if attribute overrides need to be done, this is probably the place.
		//The attribute creation code *might* need to be moved to another function...or at least some of it
		//so that it may be shared by other conversion code
		if ( pAttr->isP() )
		{
			//If we have position, then set up the type manually
			LogDebug() << "We have a position attribute. Set attributes manually." << std::endl;
			pAttrInfo->entries = 3;
			pAttrInfo->type = GB_ATTRIB_VECTOR;
		}
		else
		{
			//Retrieve attribute info through the standard channels...
			LogDebug() << "Retrieving attribute data using the Point Dictionary." << std::endl;

			//Now that we now which attribute we want, find it using the GU_Detail object.
			//TODO: Is there some beter way of doing this???
			pPtAttrDict = dynamic_cast< const GEO_PointAttribDict* >( _gdp->getAttributeDict( GEO_POINT_DICT ) );
			pBaseAttr = _gdp->getAttributeDict( GEO_POINT_DICT )->find( pAttr->getName() );
			pAttrInfo->type = pBaseAttr->getType();
		}

		LogDebug() << "Switching on attribute type." << std::endl;

	}

	//Build a map to separate bodies using their name attributes
	StringToPrimPolyListMap namesMap;
	StringToPrimPolyListMap::iterator nameIt;
	PrimPolyList::iterator polyIt;
	//Build a vector to remap point numbers.
	std::vector<int> remappedPtNum;

	buildTriPrimNamesMap( namesMap );	

	//Iterate over the names in the map
	for (nameIt = namesMap.begin(); nameIt != namesMap.end(); nameIt++)
	{
		LogInfo() << "Processing Name: " << nameIt->first << std::endl;		
		bodyName = nameIt->first;
		//List of polygons for this body
		PrimPolyList &polyList = nameIt->second;

		//Clear the remapped point numbers for this body
		remappedPtNum.clear();
		//remappedPtNum.resize( _gdp->primitives().entries()*3, -1 );
		remappedPtNum.resize( _gdp->points().entries(), -1 );

		//Create a Naiad mesh body
		pMeshBody = Nb::Factory::createBody("Mesh", bodyName);
		meshBodyList.push_back( pMeshBody );
	
		//get the mutable shapes for the mesh body.
		Nb::TriangleShape& triShape( pMeshBody->mutableTriangleShape() );
		Nb::PointShape& ptShape( pMeshBody->mutablePointShape() );

		Nb::Buffer3f& pPosBuf( ptShape.mutableBuffer3f("position") );
		pPosBuf.reserve( polyList.size() * 3 ); //Each primitive is treated as a triangle

		//This preprocessor defition was placed here simply because it is only applicable to this code section
		//and will fail to work anywhere else. Not to be classified under "best coding practices".
		#define PROCESSCHANNEL(type, defaults) \
		{ \
			if ( !ptShape.hasChannels ## type (empAttrName) ) \
			{ \
				ptShape.createChannel ## type ( empAttrName, (defaults) ); \
			} \
			pAttrInfo->empIndex = ptShape.channelIndex( empAttrName ); \
			ptShape.mutableBuffer ## type ( empAttrName ).reserve ( polyList.size() * 3 ); \
			pAttrInfo->supported = true; \
		}

		//Iterate over the BGEO attributes and create corresponding channels in the EMP
		//Also, store the channel index for direct lookups when transferring data.
		for (int i = 0; i < numAttribs; i++)
		{
			//Mangle the geo attribute name right now
			pAttr = attribList[i];
			std::string empAttrName;
			if ( _geoAttribMangle.find( pAttr->getName() ) != _geoAttribMangle.end() )
				empAttrName = _geoAttribMangle[ pAttr->getName() ];
			else
				empAttrName = pAttr->getName();
			LogDebug() << "Mangling name: " << pAttr->getName() << " ==> " << empAttrName << std::endl;
			pAttrInfo = &( attrLut[i] );
			pAttrInfo->supported = false;
			pAttrInfo->flipvector = true; //By default, flip vectors

			if ( std::string(pAttr->getName()).compare("P") == 0 )
				pAttrInfo->flipvector = false;

			pAttrInfo->empIndex = -1;
			switch ( pAttrInfo->type )
			{
				case GB_ATTRIB_FLOAT:
					LogDebug() << "Float " << pAttrInfo->entries << std::endl;
					switch ( pAttrInfo->entries )
					{
						case 1:
							PROCESSCHANNEL( 1f, 0.0f );
							break;
						case 3:
							PROCESSCHANNEL( 3f, em::vec3f(0.0f) );
							break;
					}
					break;
				case GB_ATTRIB_INT:
					LogDebug() << "Int " << pAttrInfo->entries << std::endl;
					break;
				case GB_ATTRIB_VECTOR:
					{
						LogDebug() << "Vector (Vector3)" << std::endl;
						PROCESSCHANNEL( 3f, em::vec3f(0.0f) );
						break;
					}
				case GB_ATTRIB_MIXED:
				case GB_ATTRIB_INDEX:
				default:
					//Unsupported attribute, so give it a skip.
					LogDebug() << "Unsupported attribute type for blind copy [" << pAttrInfo->type << "]" << std::endl;
					continue;
					break;
			}

			if ( pAttrInfo->supported )
				LogDebug() << "Supported Blind Copy! Channel: [" << empAttrName << "] Index: " << pAttrInfo->empIndex << std::endl;
			else
			{
				LogDebug() << "Unsupported Blind Copy! Channel: [" << empAttrName << "]" <<  std::endl;
				continue;
			}
		} //for numAttribs


		//Now its time to set the index channel to form faces
		Nb::Buffer3i& indexBuffer = triShape.mutableBuffer3i("index");
		indexBuffer.reserve( polyList.size() );
		em::vec3i triVec(0,0,0); //Triangle description for the index buffer
		totalpoints = 0;

		LogDebug() << "Starting poly iteration... " << std::endl;
		//Iterate over all the primitives in this list and remap their point numbers
		for ( polyIt = polyList.begin(); polyIt != polyList.end(); polyIt++ )
		{
			pprim = *polyIt;
			if ( pprim->getVertexCount() >= 3 )
			{
				//only extract the first three vertices from the primitive
				for (int i = 0; i < 3; i++)
				{
					//First iterate the points and make sure they have remapped point numbers
					//NOTE: Houdini & Naiad triangle windings differ.
					ppt = pprim->getVertex(2-i).getPt();
					ptnum = ppt->getNum();

					if (remappedPtNum.at( ptnum ) == -1)
					{
						//We have an unmapped point for this body
						//Push the applicable point attributes into each channel
						transferMeshPointAttribs(numAttribs, attribList, attrLut, ptShape, ppt);
												
						//Push the point into the position buffer
						
						//pos = ppt->getPos();
						//pPosBuf.push_back( em::vec3f( pos[0], pos[1], pos[2]) );

						//Record the position at which this point is stored
						remappedPtNum[ ptnum ] = totalpoints;
						totalpoints++;						
					}

					//At this point the current vertex has been remapped at some stage.
					//Write the remapped index in the triVec
					triVec[i] = remappedPtNum[ ptnum ];

					//Perform a blind copy of all the attributes.

				}
				//Push the remapped indices into the body's index buffer.
				indexBuffer.push_back( triVec );
			}
			else
			{
				//Not interested!
				LogVerbose() << "Warning! Primitive with less than 3 vertices found on body: " << bodyName << " (Vertex count: " << pprim->getVertexCount() << ")" << std::endl;
				continue;
			}
		}
	}

	LogInfo() << " ************** Done with Mesh Shape ************** " << std::endl;	

	return EC_SUCCESS;
}
示例#11
0
void Geo2Emp::transferParticlePointAttribs(int numAttribs, GEO_AttributeHandleList& attribList, std::map<int, AttributeInfo>& attrLut, Nb::ParticleShape& shape, const GEO_Point* ppt)
{
	GEO_AttributeHandle* pAttr;
	AttributeInfo* pAttrInfo;

	for (int i = 0; i < numAttribs; i++)
	{
		pAttr = attribList[i];
		pAttrInfo = &( attrLut[i] );

		if (!pAttrInfo->supported)
			//Skip unsupported attributes
			continue;

		pAttr->setElement( ppt );
		if (! pAttr->isAttributeValid() )
		{
			LogDebug() << "Invalid attribute handle on supported attribute!! [" << pAttr->getName() << "]" << std::endl;
		}

		LogDebug() << "Transferring attribute: " << pAttr->getName() << std::endl;

		switch ( pAttrInfo->type )
		{
			case GB_ATTRIB_FLOAT:
				//LogDebug() << "Transfer Float" << pAttrInfo->entries << "[" << pAttr->getName() << "]" << std::endl;
				switch ( pAttrInfo->entries )
				{
					case 1:
						{
							//LogDebug() << "Float1: " << pAttr->getV3() << std::endl;
							//Get the channel from the point shape
							em::block3_array1f& vecData = shape.mutableBlocks1f( pAttrInfo->empIndex );
							//Write the data into the buffer
							vecData(0).push_back( pAttr->getF() );
						}
						break;
					case 3:
						{
							LogDebug() << "Float3: " << pAttr->getV3() << std::endl;
							//Get the channel from the particle shape
							em::block3_array3f& vecData = shape.mutableBlocks3f( pAttrInfo->empIndex );
							//Write the data into the buffer
							vecData(0).push_back( em::vec3f( pAttr->getF(0), pAttr->getF(1), pAttr->getF(2) ) );
						}
						break;
				}
				break;
			case GB_ATTRIB_INT:
				LogDebug() << "Int " << pAttrInfo->entries << std::endl;
				switch ( pAttrInfo->entries )
				{
					case 1:
						{
							//LogDebug() << "Float1: " << pAttr->getV3() << std::endl;
							//Get the channel from the point shape
							em::block3_array1i& vecData = shape.mutableBlocks1i( pAttrInfo->empIndex );
							//Write the data into the buffer
							vecData(0).push_back( pAttr->getI() );
						}
						break;
					case 3:
						{
							LogDebug() << "Int3: " << std::endl;
							//Get the channel from the particle shape
							em::block3_array3i& vecData = shape.mutableBlocks3i( pAttrInfo->empIndex );
							//Write the data into the buffer
							vecData(0).push_back( em::vec3i( pAttr->getI(0), pAttr->getI(1), pAttr->getI(2) ) );
						}
						break;
				}
				break;
			case GB_ATTRIB_VECTOR:
				{
					//LogDebug() << "Transfer Vector3 [" << pAttr->getName() << "] " <<  pAttr->getF(0) << "," << pAttr->getF(1) << "," << pAttr->getF(2)<< std::endl;
					//If we have a vector, we need to invert it (reverse winding).
					em::block3_array3f& vecData = shape.mutableBlocks3f( pAttrInfo->empIndex );
					//Write the data into the buffer
					vecData(0).push_back( em::vec3f( pAttr->getF(0), pAttr->getF(1), pAttr->getF(2) ) );
					break;
				}
			case GB_ATTRIB_MIXED:
			case GB_ATTRIB_INDEX:
			default:
				//Unsupported attribute, so give it a skip.
				LogDebug() << " !!!!! SHOULDNT GET THIS !!!! Unsupported attribute type for blind copy [" << pAttrInfo->type << "]" << std::endl;
				continue;
				break;
		}

	}

}
示例#12
0
OP_ERROR
SOP_IntersectRay::cookMySop(OP_Context &context)
{
    double t;
    float  edgelength, primarea, generatepoints;
    int    verbose;

    // We optionally add points in self-penetration places:
    GB_PointGroup          *hitPointsGroup;
    UT_RefArray<UT_Vector3> hitPoints;

    if (lockInputs(context) >= UT_ERROR_ABORT)
	    return error();

    t = context.getTime();
    duplicatePointSource(0, context);

    edgelength     = EDGELENGTH(t);
    primarea       = PRIMAREA(t);
    verbose        = VERBOSE(t);
    generatepoints = GENERATEPOINTS(t);

    // Normals:
    GEO_AttributeHandle  nH;
    GEO_AttributeHandle  cdH;
    nH   = gdp->getAttribute(GEO_POINT_DICT, "N");
    cdH  = gdp->getAttribute(GEO_POINT_DICT, "Cd");
   

    // RayInfo parms:
    //float max = 1E18f; // Max specified by edge length...
    float min = 0.0f;
    float tol = 1e-1F;

    // Rayhit objects:
    GU_RayFindType  itype     = GU_FIND_ALL;   
    GU_RayIntersect intersect = GU_RayIntersect(gdp);

    // Profile:
    //Timer timer = Timer();
    //float rayhit_time = 0;
    //float vertex_time = 0;

    // Here we determine which groups we have to work on. 
    if (error() < UT_ERROR_ABORT && cookInputGroups(context) < UT_ERROR_ABORT)
    {
        UT_AutoInterrupt progress("Checking for self-intersections...");
        const GEO_Primitive   *ppr;
        FOR_ALL_GROUP_PRIMITIVES(gdp, myGroup, ppr)
	    {
             // Check if user requested abort
             if (progress.wasInterrupted())
                break;

            // Get rid of primitives smaller than primarea:
            if ( ppr->calcArea() < primarea )
                continue;

            for (int j = 0; j < ppr->getVertexCount() - 1; j++)
            {
                // Get data;
                // TODO: This is extremally inefficent.
                // TODO: Why do we crash with uv vetrex attributes!? 
                const GEO_Vertex ppv1 = ppr->getVertex(j);
                const GEO_Vertex ppv2 = ppr->getVertex(j+1);
                const GEO_Point *ppt1 = ppv1.getPt();
                const GEO_Point *ppt2 = ppv2.getPt();
               
                // Vertices positions:
                UT_Vector3 p1 = ppt1->getPos();
                UT_Vector3 p2 = ppt2->getPos();

                // Ray direction:
                p2   = p2 - p1;
                // Get rid of edges shorter than edgelength:
                if (p2.length() < edgelength)
                    continue;
                // hit info with max distance equal edge length:
                GU_RayInfo  hitinfo = GU_RayInfo(p2.length(), min, itype, tol); 
                p2.normalize();

                // Send ray:
                if (intersect.sendRay(p1, p2, hitinfo))
                {  
                    UT_RefArray<GU_RayInfoHit> hits = *(hitinfo.myHitList);
                    for(int j = 0; j < hits.entries(); j++)
                    {
                        const GEO_Primitive *prim = hits[j].prim;
                        const GEO_PrimPoly  *poly = (const GEO_PrimPoly *) prim; //TODO: Prims only?
                        // We are interested only ff points are not part of prims...:
                        if (poly->find(*ppt1) == -1 && poly->find(*ppt2)== -1)
                        {
                            if (verbose)
                                printf("Edge: %i-%i intersects with prim:%d \n",ppt1->getNum(), ppt2->getNum(), prim->getNum());

                            // Save hit position as points:
                            if (generatepoints)
                            {
                                UT_Vector4 pos;
                                float u = hits[j].u; 
                                float v = hits[j].v;
                                if (!prim->evaluateInteriorPoint(pos, u, v))
                                    hitPoints.append(pos);
                            }

                            // TODO: Should I indicate penetration with red color on both ends of edge?:
                            cdH.setElement(ppt1);
                            cdH.setV3(UT_Vector3(1.0, 0.0, 0.0));
                            cdH.setElement(ppt2);
                            cdH.setV3(UT_Vector3(1.0, 0.0, 0.0));
                        }
                        
                    }
                }
            }
	    } 
     
   
    if (generatepoints)
    {
        hitPointsGroup = gdp->newPointGroup("__self_penetrate", false);
        for (int i = 0; i < hitPoints.entries(); i++)
        {
            GEO_Point *point;
            point = gdp->appendPoint();
            hitPointsGroup->add(point);
            point->setPos(hitPoints(i));
        }
    }
    
    }
示例#13
0
OP_ERROR SOP_FluidSolver2D::cookMySop(OP_Context &context) {

	oldf = f;

	double t = context.getTime();
	int f =	context.getFrame();
	UT_Interrupt	*boss;
	GU_PrimVolume	*volume;

	OP_Node::flags().timeDep = 1;
	fluidSolver->fps = OPgetDirector()->getChannelManager()->getSamplesPerSec();


	int newResX = RESX(t);
	int newResY = RESY(t);

	if ( newResX != fluidSolver->res.x || newResY != fluidSolver->res.y) {
		fluidSolver->changeFluidRes(newResX,newResY);

	}

	UT_Vector3 fluidPos(POSX(t), POSY(t), POSZ(t));
	UT_Vector3 fluidRot(ROTX(t), ROTY(t), ROTZ(t));
	fluidRot.degToRad();

	fluidSolver->fluidSize.x = FLUIDSIZEX(t);
	fluidSolver->fluidSize.y = FLUIDSIZEY(t);

	fluidSolver->borderNegX = BORDERNEGX(t);
	fluidSolver->borderPosX = BORDERPOSX(t);
	fluidSolver->borderNegY = BORDERNEGY(t);
	fluidSolver->borderPosY = BORDERPOSY(t);

	fluidSolver->preview = PREVIEW(t);
	fluidSolver->previewType = PREVIEWTYPE(t);
	fluidSolver->bounds = BOUNDS(t);

	fluidSolver->substeps = SUBSTEPS(t);
	fluidSolver->jacIter = JACITER(t);

	fluidSolver->densDis = DENSDIS(t);
	fluidSolver->densBuoyStrength = DENSBUOYSTRENGTH(t);
	float ddirX = DENSBUOYDIRX(t);
	float ddirY = DENSBUOYDIRY(t);
	fluidSolver->densBuoyDir = cu::make_float2(ddirX,ddirY);

	fluidSolver->velDamp = VELDAMP(t);
	fluidSolver->vortConf = VORTCONF(t);

	fluidSolver->noiseStr = NOISESTR(t);
	fluidSolver->noiseFreq = NOISEFREQ(t);
	fluidSolver->noiseOct = NOISEOCT(t);
	fluidSolver->noiseLacun = NOISELACUN(t);
	fluidSolver->noiseSpeed = NOISESPEED(t);
	fluidSolver->noiseAmp = NOISEAMP(t);

    if (error() < UT_ERROR_ABORT) {
			boss = UTgetInterrupt();

		gdp->clearAndDestroy();		

		// Start the interrupt server
		if (boss->opStart("Building Volume")){

			static float		 zero = 0.0;

#ifdef HOUDINI_11
			GB_AttributeRef fluidAtt = gdp->addAttrib("cudaFluidPreview", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(fluidAtt, fluidSolver->preview);

			GB_AttributeRef solverIdAtt = gdp->addAttrib("solverId", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(solverIdAtt, fluidSolver->id);
#else
			GA_WOAttributeRef fluidAtt = gdp->addIntTuple(GA_ATTRIB_DETAIL, "cudaFluidPreview", 1);
			gdp->element().setValue<int>(fluidAtt, fluidSolver->preview);

			GA_WOAttributeRef solverIdAtt = gdp->addIntTuple(GA_ATTRIB_DETAIL, "solverId", 1);
			gdp->element().setValue<int>(solverIdAtt, fluidSolver->id);
#endif


			UT_Matrix3              xform;
			const UT_XformOrder volXFormOrder;
			
			volume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);

#ifdef HOUDINI_11
			volume->getVertex().getPt()->getPos() = fluidPos;
#else
			volume->getVertexElement(0).getPt()->setPos(fluidPos);
#endif

			xform.identity();
			xform.scale(fluidSolver->fluidSize.x*0.5, fluidSolver->fluidSize.y*0.5, 0.25);
			xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder);

			volume->setTransform(xform);
			

			xform.identity();
			xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder);
			xform.invert();

			if(lockInputs(context) >= UT_ERROR_ABORT)
				return error();

			if(getInput(0)){
				GU_Detail* emittersInput = (GU_Detail*)inputGeo(0, context);
				GEO_PointList emittersList = emittersInput->points();
				int numEmitters = emittersList.entries();

				if (numEmitters != fluidSolver->nEmit) {
					delete fluidSolver->emitters;
					fluidSolver->nEmit = numEmitters;
					fluidSolver->emitters = new FluidEmitter[numEmitters];
				}

				GEO_AttributeHandle radAh, amountAh;
				radAh = emittersInput->getPointAttribute("radius");
				amountAh = emittersInput->getPointAttribute("amount");

				for (int i = 0; i < numEmitters; i++) {

					UT_Vector4 emitPos = emittersList[i]->getPos();
					UT_Vector3 emitPos3(emitPos);

					emitPos3 -= fluidPos;
					emitPos3 = emitPos3*xform;

					fluidSolver->emitters[i].posX = emitPos3.x();
					fluidSolver->emitters[i].posY = emitPos3.y();

					radAh.setElement(emittersList[i]);
					amountAh.setElement(emittersList[i]);

					fluidSolver->emitters[i].radius = radAh.getF(0);
					fluidSolver->emitters[i].amount = amountAh.getF(0);
				}
			} else {

				fluidSolver->nEmit = 0;

			}
		

			if(getInput(1)) {
				GU_Detail* collidersInput = (GU_Detail*)inputGeo(1, context);
		
				GEO_PointList collidersList = collidersInput->points();
				int numColliders = collidersList.entries();

				if (numColliders != fluidSolver->nColliders) {
					delete fluidSolver->colliders;
					fluidSolver->nColliders = numColliders;
					fluidSolver->colliders = new Collider[numColliders];
				}

				GEO_AttributeHandle colRadAh;
				colRadAh = collidersInput->getPointAttribute("radius");

				for (int i = 0; i < numColliders; i++) {

					UT_Vector4 colPos = collidersList[i]->getPos();
					UT_Vector3 colPos3(colPos);

					colPos3 -= fluidPos;
					colPos3 = colPos3*xform;

					if (f > STARTFRAME(t)) {
						fluidSolver->colliders[i].oldPosX = fluidSolver->colliders[i].posX;
						fluidSolver->colliders[i].oldPosY = fluidSolver->colliders[i].posY;
					} else {
						fluidSolver->colliders[i].oldPosX = colPos3.x();
						fluidSolver->colliders[i].oldPosY = colPos3.y();
					}

					fluidSolver->colliders[i].posX = colPos3.x();
					fluidSolver->colliders[i].posY = colPos3.y();

					colRadAh.setElement(collidersList[i]);

					fluidSolver->colliders[i].radius = colRadAh.getF(0);
				}

			} else {
				fluidSolver->nColliders = 0;
			}

			unlockInputs();

			if (f <= STARTFRAME(t)) {

				fluidSolver->resetFluid();

				if (fluidSolver->preview != 1) {
					{
						UT_VoxelArrayWriteHandleF	handle = volume->getVoxelWriteHandle();
						handle->constant(0);
					}
				}


			} else {

				if (f!=oldf) {

					fluidSolver->solveFluid();

				}

				if (fluidSolver->preview != 1) {
					
						cu::cudaMemcpy( fluidSolver->host_dens, fluidSolver->dev_dens,
						fluidSolver->res.x*fluidSolver->res.y*sizeof(float), cu::cudaMemcpyDeviceToHost );
				
					{
						UT_VoxelArrayWriteHandleF	handle = volume->getVoxelWriteHandle();

						handle->size(fluidSolver->res.x, fluidSolver->res.y, 1);

						for (int i = 0; i < fluidSolver->res.x; i++) {
							for (int j = 0; j < fluidSolver->res.y; j++) {
								handle->setValue(i, j, 0, fluidSolver->host_dens[(j*fluidSolver->res.x + i)]);
							}
						}
									

					}

				}
			}


		select(GU_SPrimitive);
		}

		// Tell the interrupt server that we've completed. Must do this
		// regardless of what opStart() returns.
		boss->opEnd();
    }

    gdp->notifyCache(GU_CACHE_ALL);
 
    return error();
}
示例#14
-1
OP_ERROR SOP_FluidSolver3D::cookMySop(OP_Context &context) {

	oldf = f;
	f =	context.getFrame();

	double t = context.getTime();

	fluidSolver->fps = OPgetDirector()->getChannelManager()->getSamplesPerSec();

	UT_Interrupt	*boss;
	GU_PrimVolume	*volume;
	GU_PrimVolume	*velXVolume;
	GU_PrimVolume	*velYVolume;
	GU_PrimVolume	*velZVolume;

	OP_Node::flags().timeDep = 1;

	int newResX = RESX(t);
	int newResY = RESY(t);
	int newResZ = RESZ(t);

	if ( newResX != fluidSolver->res.width || newResY != fluidSolver->res.height || newResZ != fluidSolver->res.depth) {
		fluidSolver->changeFluidRes(newResX,newResY,newResZ);

	}

	UT_Vector3 fluidPos(POSX(t), POSY(t), POSZ(t));
	UT_Vector3 fluidRot(ROTX(t), ROTY(t), ROTZ(t));
	fluidRot.degToRad();

	fluidSolver->fluidSize.x = FLUIDSIZEX(t);
	fluidSolver->fluidSize.y = FLUIDSIZEY(t);
	fluidSolver->fluidSize.z = FLUIDSIZEZ(t);

	fluidSolver->borderNegX = BORDERNEGX(t);
	fluidSolver->borderPosX = BORDERPOSX(t);
	fluidSolver->borderNegY = BORDERNEGY(t);
	fluidSolver->borderPosY = BORDERPOSY(t);
	fluidSolver->borderNegZ = BORDERNEGZ(t);
	fluidSolver->borderPosZ = BORDERPOSZ(t);

	fluidSolver->substeps = SUBSTEPS(t);
	fluidSolver->jacIter = JACITER(t);

	fluidSolver->densDis = DENSDIS(t);
	fluidSolver->densBuoyStrength = DENSBUOYSTRENGTH(t);
	float ddirX = DENSBUOYDIRX(t);
	float ddirY = DENSBUOYDIRY(t);
	float ddirZ = DENSBUOYDIRZ(t);
	fluidSolver->densBuoyDir = cu::make_float3(ddirX,ddirY,ddirZ);

	fluidSolver->velDamp = VELDAMP(t);
	fluidSolver->vortConf = VORTCONF(t);

	fluidSolver->noiseStr = NOISESTR(t);
	fluidSolver->noiseFreq = NOISEFREQ(t);
	fluidSolver->noiseOct = NOISEOCT(t);
	fluidSolver->noiseLacun = NOISELACUN(t);
	fluidSolver->noiseSpeed = NOISESPEED(t);
	fluidSolver->noiseAmp = NOISEAMP(t);

	fluidSolver->preview = PREVIEW(t);
	fluidSolver->drawCube = DRAWCUBE(t);
	fluidSolver->opaScale = OPASCALE(t);
	fluidSolver->stepMul = STEPMUL(t);
	fluidSolver->displayRes = DISPLAYRES(t);


	fluidSolver->doShadows = DOSHADOWS(t);
	float lightPosX = LIGHTPOSX(t);
	float lightPosY = LIGHTPOSY(t);
	float lightPosZ = LIGHTPOSZ(t);
	fluidSolver->lightPos = cu::make_float3(lightPosX,lightPosY,lightPosZ);
	fluidSolver->shadowDens = SHADOWDENS(t);
	fluidSolver->shadowStepMul = SHADOWSTEPMUL(t);
	fluidSolver->shadowThres = SHADOWTHRES(t);

	fluidSolver->displaySlice = DISPLAYSLICE(t);
	fluidSolver->sliceType = SLICETYPE(t);
	fluidSolver->sliceAxis = SLICEAXIS(t);
	fluidSolver->slicePos = SLICEPOS(t);
	fluidSolver->sliceBounds = SLICEBOUNDS(t);


    if (error() < UT_ERROR_ABORT) {
		boss = UTgetInterrupt();

	gdp->clearAndDestroy();		

		// Start the interrupt server
		if (boss->opStart("Building Volume")){

			static float		 zero = 0.0;
			GB_AttributeRef fluidAtt = gdp->addAttrib("cudaFluid3DPreview", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(fluidAtt, fluidSolver->preview);

			GB_AttributeRef fluidSliceAtt = gdp->addAttrib("sliceDisplay", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(fluidSliceAtt, fluidSolver->displaySlice);

			GB_AttributeRef solverIdAtt = gdp->addAttrib("solverId", sizeof(int), GB_ATTRIB_INT, &zero);
			gdp->attribs().getElement().setValue<int>(solverIdAtt, fluidSolver->id);

			GEO_AttributeHandle         name_gah;
			int	def = -1;

			gdp->addPrimAttrib("name", sizeof(int), GB_ATTRIB_INDEX, &def);
			name_gah = gdp->getPrimAttribute("name");


			UT_Matrix3              xform;
			const UT_XformOrder volXFormOrder;

			volume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);

			volume->getVertex().getPt()->getPos() = fluidPos;

			xform.identity();
			xform.scale(fluidSolver->fluidSize.x*0.5, fluidSolver->fluidSize.y*0.5, fluidSolver->fluidSize.z*0.5);
			xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder);

			volume->setTransform(xform);

			name_gah.setElement(volume);
			name_gah.setString("density");

			velXVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);
			velXVolume->getVertex().getPt()->getPos() = fluidPos;
			velXVolume->setTransform(xform);

			name_gah.setElement(velXVolume);
			name_gah.setString("vel.x");

			velYVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);
			velYVolume->getVertex().getPt()->getPos() = fluidPos;
			velYVolume->setTransform(xform);

			name_gah.setElement(velYVolume);
			name_gah.setString("vel.y");

			velZVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp);
			velZVolume->getVertex().getPt()->getPos() = fluidPos;
			velZVolume->setTransform(xform);

			name_gah.setElement(velZVolume);
			name_gah.setString("vel.z");


			xform.identity();
			xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder);
			xform.invert();

			if(lockInputs(context) >= UT_ERROR_ABORT)
				return error();

			if(getInput(0)){
				GU_Detail* emittersInput = (GU_Detail*)inputGeo(0, context);
				GEO_PointList emittersList = emittersInput->points();
				int numEmitters = emittersList.entries();

				if (numEmitters != fluidSolver->nEmit) {
					delete fluidSolver->emitters;
					fluidSolver->nEmit = numEmitters;
					fluidSolver->emitters = new VHFluidEmitter[numEmitters];
				}

				GEO_AttributeHandle radAh, amountAh;
				radAh = emittersInput->getPointAttribute("radius");
				amountAh = emittersInput->getPointAttribute("amount");

				for (int i = 0; i < numEmitters; i++) {

					UT_Vector4 emitPos = emittersList[i]->getPos();
					UT_Vector3 emitPos3(emitPos);

					emitPos3 -= fluidPos;
					emitPos3 = emitPos3*xform;

					fluidSolver->emitters[i].posX = emitPos3.x();
					fluidSolver->emitters[i].posY = emitPos3.y();
					fluidSolver->emitters[i].posZ = emitPos3.z();

					radAh.setElement(emittersList[i]);
					amountAh.setElement(emittersList[i]);

					fluidSolver->emitters[i].radius = radAh.getF(0);
					fluidSolver->emitters[i].amount = amountAh.getF(0);
				}
			} else {

				fluidSolver->nEmit = 0;

			}
		

			if(getInput(1)) {
				GU_Detail* collidersInput = (GU_Detail*)inputGeo(1, context);
		
				GEO_PointList collidersList = collidersInput->points();
				int numColliders = collidersList.entries();

				if (numColliders != fluidSolver->nColliders) {
					delete fluidSolver->colliders;
					fluidSolver->nColliders = numColliders;
					fluidSolver->colliders = new VHFluidCollider[numColliders];
				}

				GEO_AttributeHandle colRadAh;
				colRadAh = collidersInput->getPointAttribute("radius");

				for (int i = 0; i < numColliders; i++) {

					UT_Vector4 colPos = collidersList[i]->getPos();
					UT_Vector3 colPos3(colPos);

					colPos3 -= fluidPos;
					colPos3 = colPos3*xform;

					if (f > STARTFRAME(t)) {
						fluidSolver->colliders[i].oldPosX = fluidSolver->colliders[i].posX;
						fluidSolver->colliders[i].oldPosY = fluidSolver->colliders[i].posY;
						fluidSolver->colliders[i].oldPosZ = fluidSolver->colliders[i].posZ;
					} else {
						fluidSolver->colliders[i].oldPosX = colPos3.x();
						fluidSolver->colliders[i].oldPosY = colPos3.y();
						fluidSolver->colliders[i].oldPosZ = colPos3.z();
					}

					fluidSolver->colliders[i].posX = colPos3.x();
					fluidSolver->colliders[i].posY = colPos3.y();
					fluidSolver->colliders[i].posZ = colPos3.z();

					colRadAh.setElement(collidersList[i]);

					fluidSolver->colliders[i].radius = colRadAh.getF(0);
				}

			} else {
				fluidSolver->nColliders = 0;
			}

			unlockInputs();

			if (f <= STARTFRAME(t)) {

				fluidSolver->resetFluid();

				if (COPYDENS(t)) {

					{
						UT_VoxelArrayWriteHandleF	handle = volume->getVoxelWriteHandle();
						handle->constant(0);

						UT_VoxelArrayWriteHandleF	velXHandle = velXVolume->getVoxelWriteHandle();
						velXHandle->constant(0);
						UT_VoxelArrayWriteHandleF	velYHandle = velYVolume->getVoxelWriteHandle();
						velYHandle->constant(0);
						UT_VoxelArrayWriteHandleF	velZHandle = velZVolume->getVoxelWriteHandle();
						velZHandle->constant(0);
					}

				}


			} else {

				if (f!=oldf) {

					fluidSolver->solveFluid();

				}

				if (COPYDENS(t)) {

					cu::cudaMemcpy( fluidSolver->host_dens, fluidSolver->dev_dens,
					fluidSolver->res.width*fluidSolver->res.height*fluidSolver->res.depth*sizeof(float), cu::cudaMemcpyDeviceToHost );

					{
						UT_VoxelArrayWriteHandleF	handle = volume->getVoxelWriteHandle();

						handle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth);

						for (int i = 0; i < fluidSolver->res.width; i++) {
							for (int j = 0; j < fluidSolver->res.height; j++) {
								for (int k = 0; k < fluidSolver->res.depth; k++) {
									handle->setValue(i, j, k, fluidSolver->host_dens[k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i]);
								}
							}
						}
									

					}

					if (COPYVEL(t)) {

					cu::cudaMemcpy( fluidSolver->host_vel, fluidSolver->dev_vel,
						fluidSolver->res.width*fluidSolver->res.height*fluidSolver->res.depth*sizeof(cu::float4), cu::cudaMemcpyDeviceToHost );

					{
						UT_VoxelArrayWriteHandleF	velXHandle = velXVolume->getVoxelWriteHandle();
						velXHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth);
						UT_VoxelArrayWriteHandleF	velYHandle = velYVolume->getVoxelWriteHandle();
						velYHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth);
						UT_VoxelArrayWriteHandleF	velZHandle = velZVolume->getVoxelWriteHandle();
						velZHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth);

						
						for (int i = 0; i < fluidSolver->res.width; i++) {
							for (int j = 0; j < fluidSolver->res.height; j++) {
								for (int k = 0; k < fluidSolver->res.depth; k++) {
									velXHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)]);
									velYHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)+1]);
									velZHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)+2]);
								}
							}
						}
									

					}


					}

				}
			}


		select(GU_SPrimitive);
		}

		// Tell the interrupt server that we've completed. Must do this
		// regardless of what opStart() returns.
		boss->opEnd();
    }

    gdp->notifyCache(GU_CACHE_ALL);

 
    return error();
}