//-*****************************************************************************
void WriteMotionBegin( ProcArgs &args, const SampleTimeSet &sampleTimes )
{
    std::vector<RtFloat> outputTimes;
    outputTimes.reserve( sampleTimes.size() );

    chrono_t frameTime = args.frame / args.fps;

    for ( SampleTimeSet::const_iterator iter = sampleTimes.begin();
          iter != sampleTimes.end() ; ++iter )
    {
        // why is this static?
        static const chrono_t epsilon = 1.0 / 10000.0;

        RtFloat value = ( (*iter) - frameTime ) * args.fps;

        if ( fabs( value ) < epsilon )
        {
            value = 0.0f;
        }

        outputTimes.push_back( value );
    }

    RiMotionBeginV( outputTimes.size(), &outputTimes[0] );
}
Example #2
0
void ConcatenateXformSamples( ProcArgs &args,
        const MatrixSampleMap & parentSamples,
        const MatrixSampleMap & localSamples,
        MatrixSampleMap & outputSamples)
{
    SampleTimeSet unionOfSampleTimes;
    
    for (MatrixSampleMap::const_iterator I = parentSamples.begin();
            I != parentSamples.end(); ++I)
    {
        unionOfSampleTimes.insert((*I).first);
    }
    
    for (MatrixSampleMap::const_iterator I = localSamples.begin();
            I != localSamples.end(); ++I)
    {
        unionOfSampleTimes.insert((*I).first);
    }
    
    for (SampleTimeSet::iterator I = unionOfSampleTimes.begin();
            I != unionOfSampleTimes.end(); ++I)
    {
        M44d parentMtx = GetNaturalOrInterpolatedSampleForTime(parentSamples,
                (*I));
        M44d localMtx = GetNaturalOrInterpolatedSampleForTime(localSamples,
                (*I));
        
        outputSamples[(*I)] = localMtx * parentMtx;
    }
}
Example #3
0
void ProcessPolyMesh( IPolyMesh &polymesh, ProcArgs &args,
        MatrixSampleMap * xformSamples, const std::string & facesetName )
{
    SampleTimeSet sampleTimes;
    std::vector<AtUInt32> vidxs;
    
    AtNode * meshNode = ProcessPolyMeshBase(
            polymesh, args, sampleTimes, vidxs, 0, xformSamples,
                    facesetName );
    
    // This is a valid condition for the second instance onward and just
    // means that we don't need to do anything further.
    if ( !meshNode )
    {
        return;
    }
    
    IPolyMeshSchema &ps = polymesh.getSchema();
    
    std::vector<float> nlist;
    std::vector<AtUInt32> nidxs;
    
    ProcessIndexedBuiltinParam(
            ps.getNormalsParam(),
            sampleTimes,
            nlist,
            nidxs,
            3);
    
    if ( !nlist.empty() )
    {
        AiNodeSetArray(meshNode, "nlist",
            ArrayConvert( nlist.size() / sampleTimes.size(), 
                    sampleTimes.size(), AI_TYPE_FLOAT, (void*)(&(nlist[0]))));
        
        if ( !nidxs.empty() )
        {
            AiNodeSetArray(meshNode, "nidxs",
                    ArrayConvert(nidxs.size(), 1, AI_TYPE_UINT,
                            &(nidxs[0])));
        }
        else
        {
            AiNodeSetArray(meshNode, "nidxs",
                    ArrayConvert(vidxs.size(), 1, AI_TYPE_UINT,
                            &(vidxs[0])));
        }
    }
    
}
Example #4
0
//-*****************************************************************************
void ProcessPoints( IPoints &points, ProcArgs &args )
{
    IPointsSchema &ps = points.getSchema();
    TimeSamplingPtr ts = ps.getTimeSampling();
    
    SampleTimeSet sampleTimes;
    
    //for now, punt on the changing point count case -- even for frame ranges
    //for which the point count isn't changing
    
    if ( ps.getIdsProperty().isConstant() )
    {
        //grab only the current time
        sampleTimes.insert( args.frame / args.fps );
    }
    else
    {
         GetRelevantSampleTimes( args, ts, ps.getNumSamples(), sampleTimes );
    }
    
    
    bool multiSample = sampleTimes.size() > 1;
    
    if ( multiSample ) { WriteMotionBegin( args, sampleTimes ); }
    
    for ( SampleTimeSet::iterator iter = sampleTimes.begin();
          iter != sampleTimes.end(); ++iter )
    {
        ISampleSelector sampleSelector( *iter );
        
        IPointsSchema::Sample sample = ps.getValue( sampleSelector );
        
        
        ParamListBuilder paramListBuilder;
        paramListBuilder.add( "P", (RtPointer)sample.getPositions()->get() );
        
        ICompoundProperty arbGeomParams = ps.getArbGeomParams();
        AddArbitraryGeomParams( arbGeomParams,
                    sampleSelector, paramListBuilder );
        
        RiPointsV(sample.getPositions()->size(),
                paramListBuilder.n(),
                paramListBuilder.nms(),
                paramListBuilder.vals() );
    }
    
    if ( multiSample ) { RiMotionEnd(); }
    
}
//-*****************************************************************************
void GetRelevantSampleTimes( ProcArgs &args, TimeSamplingPtr timeSampling,
                            size_t numSamples, SampleTimeSet &output )
{
    if ( numSamples < 2 )
    {
        output.insert( 0.0 );
        return;
    }

    chrono_t frameTime = args.frame / args.fps;

    chrono_t shutterOpenTime = ( args.frame + args.shutterOpen ) / args.fps;

    chrono_t shutterCloseTime = ( args.frame + args.shutterClose ) / args.fps;

    std::pair<index_t, chrono_t> shutterOpenFloor =
        timeSampling->getFloorIndex( shutterOpenTime, numSamples );

    std::pair<index_t, chrono_t> shutterCloseCeil =
        timeSampling->getCeilIndex( shutterCloseTime, numSamples );

    //TODO, what's a reasonable episilon?
    static const chrono_t epsilon = 1.0 / 10000.0;

    //check to see if our second sample is really the
    //floor that we want due to floating point slop
    //first make sure that we have at least two samples to work with
    if ( shutterOpenFloor.first < shutterCloseCeil.first )
    {
        //if our open sample is less than open time,
        //look at the next index time
        if ( shutterOpenFloor.second < shutterOpenTime )
        {
            chrono_t nextSampleTime =
                     timeSampling->getSampleTime( shutterOpenFloor.first + 1 );

            if ( fabs( nextSampleTime - shutterOpenTime ) < epsilon )
            {
                shutterOpenFloor.first += 1;
                shutterOpenFloor.second = nextSampleTime;
            }
        }
    }


    for ( index_t i = shutterOpenFloor.first; i < shutterCloseCeil.first; ++i )
    {
        output.insert( timeSampling->getSampleTime( i ) );
    }

    //no samples above? put frame time in there and get out
    if ( output.size() == 0 )
    {
        output.insert( frameTime );
        return;
    }

    chrono_t lastSample = *(output.rbegin() );

    //determine whether we need the extra sample at the end
    if ( ( fabs( lastSample - shutterCloseTime ) > epsilon )
         && lastSample < shutterCloseTime )
    {
        output.insert( shutterCloseCeil.second );
    }
}
void ProcessIndexedBuiltinParam(
        geomParamT & param,
        const SampleTimeSet & sampleTimes,
        std::vector<float> & values,
        std::vector<unsigned int> & idxs,
        size_t elementSize)
{
    if ( !param.valid() ) { return; }
    
    bool isFirstSample = true;
    for ( SampleTimeSet::iterator I = sampleTimes.begin();
          I != sampleTimes.end(); ++I, isFirstSample = false)
    {
        ISampleSelector sampleSelector( *I );
        
        
        switch ( param.getScope() )
        {
        case kVaryingScope:
        case kVertexScope:
        {
            // a value per-point, idxs should be the same as vidxs
            // so we'll leave it empty
            
            // we'll get the expanded form here
            typename geomParamT::Sample sample = param.getExpandedValue(
                    sampleSelector);
            
            size_t footprint = sample.getVals()->size() * elementSize;
            
            values.reserve( values.size() + footprint );
            values.insert( values.end(),
                    (float32_t*) sample.getVals()->get(),
                    ((float32_t*) sample.getVals()->get()) + footprint );
            
            break;
        }
        case kFacevaryingScope:
        {
            // get the indexed form and feed to nidxs
            
            typename geomParamT::Sample sample = param.getIndexedValue(
                    sampleSelector);
            
            if ( isFirstSample )
            {
                idxs.reserve( sample.getIndices()->size() );
                idxs.insert( idxs.end(),
                        sample.getIndices()->get(),
                        sample.getIndices()->get() +
                                sample.getIndices()->size() );
            }
            
            size_t footprint = sample.getVals()->size() * elementSize;
            values.reserve( values.size() + footprint );
            values.insert( values.end(),
                    (const float32_t*) sample.getVals()->get(),
                    ((const float32_t*) sample.getVals()->get()) + footprint );
            
            break;
        }
        default:
            break;
        }
        
        
    }
    
    
}
AtNode * ProcessPointsBase(
        IPoints & prim, ProcArgs & args,
        SampleTimeSet & sampleTimes,
        std::vector<AtPoint> & vidxs,
		std::vector<float> & radius,
		MatrixSampleMap * xformSamples )
{
    if ( !prim.valid() )
    {
        return NULL;
    }
    
    Alembic::AbcGeom::IPointsSchema  &ps = prim.getSchema();
    TimeSamplingPtr ts = ps.getTimeSampling();
    
	sampleTimes.insert( ts->getFloorIndex(args.frame / args.fps, ps.getNumSamples()).second );
    
    std::string name = args.nameprefix + prim.getFullName();
    
    AtNode * instanceNode = NULL;
    
    std::string cacheId;
    
    SampleTimeSet singleSampleTimes;
    singleSampleTimes.insert( ts->getFloorIndex(args.frame / args.fps, ps.getNumSamples()).second );

	ICompoundProperty arbGeomParams = ps.getArbGeomParams();
	ISampleSelector frameSelector( *singleSampleTimes.begin() );
	std::vector<std::string> tags;

	//get tags
	if ( arbGeomParams != NULL && arbGeomParams.valid() )
	{
		if (arbGeomParams.getPropertyHeader("mtoa_constant_tags") != NULL)
		{
			const PropertyHeader * tagsHeader = arbGeomParams.getPropertyHeader("mtoa_constant_tags");
			if (IStringGeomParam::matches( *tagsHeader ))
			{
				IStringGeomParam param( arbGeomParams,  "mtoa_constant_tags" );
				if ( param.valid() )
				{
					IStringGeomParam::prop_type::sample_ptr_type valueSample =
									param.getExpandedValue( frameSelector ).getVals();

					if ( param.getScope() == kConstantScope || param.getScope() == kUnknownScope)
					{
						Json::Value jtags;
						Json::Reader reader;
						if(reader.parse(valueSample->get()[0], jtags))
							for( Json::ValueIterator itr = jtags.begin() ; itr != jtags.end() ; itr++ )
							{
								tags.push_back(jtags[itr.key().asUInt()].asString());
							}
					}
				}
			}
		}
	}

    if ( args.makeInstance )
    {
        std::ostringstream buffer;
        AbcA::ArraySampleKey sampleKey;
        
        
        for ( SampleTimeSet::iterator I = sampleTimes.begin();
                I != sampleTimes.end(); ++I )
        {
            ISampleSelector sampleSelector( *I );
            ps.getPositionsProperty().getKey(sampleKey, sampleSelector);
            
            buffer << GetRelativeSampleTime( args, (*I) ) << ":";
            sampleKey.digest.print(buffer);
            buffer << ":";
        }
        
        cacheId = buffer.str();
        
        instanceNode = AiNode( "ginstance" );
        AiNodeSetStr( instanceNode, "name", name.c_str() );
		args.createdNodes.push_back(instanceNode);

        if ( args.proceduralNode )
        {
            AiNodeSetByte( instanceNode, "visibility",
                    AiNodeGetByte( args.proceduralNode, "visibility" ) );
        
        }
        else
        {
            AiNodeSetByte( instanceNode, "visibility", AI_RAY_ALL );
        }

		ApplyTransformation( instanceNode, xformSamples, args );

		NodeCache::iterator I = g_meshCache.find(cacheId);

		// parameters overrides
		if(args.linkOverride)
			ApplyOverrides(name, instanceNode, tags, args);

		// shader assignation
		if (nodeHasParameter( instanceNode, "shader" ) )
		{
			if(args.linkShader)
			{
				ApplyShaders(name, instanceNode, tags, args);
			}
			else
			{
				AtArray* shaders = AiNodeGetArray(args.proceduralNode, "shader");
				if (shaders->nelements != 0)
				   AiNodeSetArray(instanceNode, "shader", AiArrayCopy(shaders));
			}
		}

        if ( I != g_meshCache.end() )
        {
            AiNodeSetPtr(instanceNode, "node", (*I).second );	
			return NULL;
        }
    }
    

    bool isFirstSample = true;

	float radiusPoint = 0.1f;
	if (AiNodeLookUpUserParameter(args.proceduralNode, "radiusPoint") !=NULL )
		radiusPoint = AiNodeGetFlt(args.proceduralNode, "radiusPoint");
	
	

	bool useVelocities = false;
	if ((sampleTimes.size() == 1) && (args.shutterOpen != args.shutterClose))
	{
		// no sample, and motion blur needed, let's try to get velocities.
		if(ps.getVelocitiesProperty().valid())
			useVelocities = true;
	}

	for ( SampleTimeSet::iterator I = sampleTimes.begin();
          I != sampleTimes.end(); ++I, isFirstSample = false)
    {
        ISampleSelector sampleSelector( *I );
        Alembic::AbcGeom::IPointsSchema::Sample sample = ps.getValue( sampleSelector );

		Alembic::Abc::P3fArraySamplePtr v3ptr = sample.getPositions();
		size_t pSize = sample.getPositions()->size(); 

		if(useVelocities && isFirstSample)
		{
			float scaleVelocity = 1.0f;
			if (AiNodeLookUpUserParameter(args.proceduralNode, "scaleVelocity") !=NULL )
				scaleVelocity = AiNodeGetFlt(args.proceduralNode, "scaleVelocity");

			vidxs.resize(pSize*2);
			Alembic::Abc::V3fArraySamplePtr velptr = sample.getVelocities();

			float timeoffset = ((args.frame / args.fps) - ts->getFloorIndex((*I), ps.getNumSamples()).second) * args.fps;

			for ( size_t pId = 0; pId < pSize; ++pId ) 
			{
				Alembic::Abc::V3f posAtOpen = ((*v3ptr)[pId] + (*velptr)[pId] * scaleVelocity *-timeoffset);			
				AtPoint pos1;
				pos1.x = posAtOpen.x;
				pos1.y = posAtOpen.y;
				pos1.z = posAtOpen.z;
				vidxs[pId]= pos1;

				Alembic::Abc::V3f posAtEnd = ((*v3ptr)[pId] + (*velptr)[pId]* scaleVelocity *(1.0f-timeoffset));
				AtPoint pos2;
				pos2.x = posAtEnd.x;
				pos2.y = posAtEnd.y;
				pos2.z = posAtEnd.z;
				vidxs[pId+pSize]= pos2;
				
				radius.push_back(radiusPoint);	
			}
		}
		else
			// not motion blur or correctly sampled particles
		{
			for ( size_t pId = 0; pId < pSize; ++pId ) 
			{
				AtPoint pos;
				pos.x = (*v3ptr)[pId].x;
				pos.y = (*v3ptr)[pId].y;
				pos.z = (*v3ptr)[pId].z;
				vidxs.push_back(pos);
				radius.push_back(radiusPoint);
			}
		}
	}
    
    AtNode* pointsNode = AiNode( "points" );
    
    if (!pointsNode)
    {
        AiMsgError("Failed to make points node for %s",
                prim.getFullName().c_str());
        return NULL;
    }
    

    args.createdNodes.push_back(pointsNode);
    if ( instanceNode != NULL)
    {
        AiNodeSetStr( pointsNode, "name", (name + ":src").c_str() );
    }
    else
    {
        AiNodeSetStr( pointsNode, "name", name.c_str() );
    }
    
    if(!useVelocities)
	{
		AiNodeSetArray(pointsNode, "points",
				AiArrayConvert( vidxs.size() / sampleTimes.size(), 
						sampleTimes.size(), AI_TYPE_POINT, (void*)(&(vidxs[0]))
								));
		AiNodeSetArray(pointsNode, "radius",
				AiArrayConvert( vidxs.size() / sampleTimes.size(), 
						sampleTimes.size(), AI_TYPE_FLOAT, (void*)(&(radius[0]))
								));

		if ( sampleTimes.size() > 1 )
		{
			std::vector<float> relativeSampleTimes;
			relativeSampleTimes.reserve( sampleTimes.size() );
        
			for (SampleTimeSet::const_iterator I = sampleTimes.begin();
					I != sampleTimes.end(); ++I )
			{
			   chrono_t sampleTime = GetRelativeSampleTime( args, (*I) );

				relativeSampleTimes.push_back(sampleTime);
                    
			}
        
			AiNodeSetArray( pointsNode, "deform_time_samples",
					AiArrayConvert(relativeSampleTimes.size(), 1,
							AI_TYPE_FLOAT, &relativeSampleTimes[0]));
		}
	}
	else
	{
		AiNodeSetArray(pointsNode, "points",
				AiArrayConvert( vidxs.size() / 2, 
						2, AI_TYPE_POINT, (void*)(&(vidxs[0]))
								));
		AiNodeSetArray(pointsNode, "radius",
				AiArrayConvert( vidxs.size() /2 / sampleTimes.size(), 
						sampleTimes.size(), AI_TYPE_FLOAT, (void*)(&(radius[0]))
								));		
		
		AiNodeSetArray( pointsNode, "deform_time_samples",
					AiArray(2, 1, AI_TYPE_FLOAT, 0.f, 1.f));

	}

   AddArbitraryGeomParams( arbGeomParams, frameSelector, pointsNode );
    
    if ( instanceNode == NULL )
	{
        if ( xformSamples )
        {
            ApplyTransformation( pointsNode, xformSamples, args );
        }
        
        return pointsNode;
	}
    else
    {
        AiNodeSetByte( pointsNode, "visibility", 0 );

		  AiNodeSetInt( pointsNode, "mode", 1 );
        
        AiNodeSetPtr(instanceNode, "node", pointsNode );
        g_meshCache[cacheId] = pointsNode;
        return pointsNode;
    }
    
}
Example #8
0
//-*****************************************************************************
void ProcessCurves( ICurves &curves, ProcArgs &args )
{
    ICurvesSchema &cs = curves.getSchema();
    TimeSamplingPtr ts = cs.getTimeSampling();
    
    SampleTimeSet sampleTimes;
    
    GetRelevantSampleTimes( args, ts, cs.getNumSamples(), sampleTimes );
    
    bool multiSample = sampleTimes.size() > 1;
    
    bool firstSample = true;
    
    for ( SampleTimeSet::iterator iter = sampleTimes.begin();
          iter != sampleTimes.end(); ++iter )
    {
        ISampleSelector sampleSelector( *iter );
        
        ICurvesSchema::Sample sample = cs.getValue( sampleSelector );
        
        //need to set the basis prior to the MotionBegin block
        if ( firstSample )
        {
            firstSample = false;
            
            BasisType basisType = sample.getBasis();
            if ( basisType != kNoBasis )
            {
                RtBasis * basis = NULL;
                RtInt step = 0;
                
                switch ( basisType )
                {
                case kBezierBasis:
                    basis = &RiBezierBasis;
                    step = RI_BEZIERSTEP;
                    break;
                case kBsplineBasis:
                    basis = &RiBSplineBasis;
                    step = RI_BSPLINESTEP;
                    break;
                case kCatmullromBasis:
                    basis = &RiCatmullRomBasis;
                    step = RI_CATMULLROMSTEP;
                    break;
                case kHermiteBasis:
                    basis = &RiHermiteBasis;
                    step = RI_HERMITESTEP;
                    break;
                case kPowerBasis:
                    basis = &RiPowerBasis;
                    step = RI_POWERSTEP;
                    break;
                default:
                    break;
                }
                
                if ( basis != NULL )
                {
                    RiBasis( *basis, step, *basis, step);
                }
            }
            
            
            if ( multiSample ) { WriteMotionBegin( args, sampleTimes ); }
        }
        
        ParamListBuilder paramListBuilder;
        paramListBuilder.add( "P", (RtPointer)sample.getPositions()->get() );
        
        IFloatGeomParam widthParam = cs.getWidthsParam();
        if ( widthParam.valid() )
        {
            ICompoundProperty parent = widthParam.getParent();
            
            //prman requires "width" to be named "constantwidth" when
            //constant instead of declared as "constant float width".
            //It's even got an error message specifically for it.
            std::string widthName;
            if ( widthParam.getScope() == kConstantScope ||
                    widthParam.getScope() == kUnknownScope )
            {
                widthName = "constantwidth";
            }
            else
            {
                widthName = "width";
            }
            
            AddGeomParamToParamListBuilder<IFloatGeomParam>(
                parent,
                widthParam.getHeader(),
                sampleSelector,
                "float",
                paramListBuilder,
                1,
                widthName);
        }
        
        IN3fGeomParam nParam = cs.getNormalsParam();
        if ( nParam.valid() )
        {
            ICompoundProperty parent = nParam.getParent();
            
            AddGeomParamToParamListBuilder<IN3fGeomParam>(
                parent,
                nParam.getHeader(),
                sampleSelector,
                "normal",
                paramListBuilder);
        }
        
        IV2fGeomParam uvParam = cs.getUVsParam();
        if ( uvParam.valid() )
        {
            ICompoundProperty parent = uvParam.getParent();
            
            AddGeomParamToParamListBuilder<IV2fGeomParam>(
                parent,
                uvParam.getHeader(),
                sampleSelector,
                "float",
                paramListBuilder,
                2,
                "st");
        }

        ICompoundProperty arbGeomParams = cs.getArbGeomParams();
        AddArbitraryGeomParams( arbGeomParams,
                    sampleSelector, paramListBuilder );
        
        RtToken curveType;
        switch ( sample.getType() )
        {
        case kCubic:
            curveType = const_cast<RtToken>( "cubic" );
            break;
        default:
            curveType = const_cast<RtToken>( "linear" );
        }
        
        
        RtToken wrap;
        switch ( sample.getWrap() )
        {
        case kPeriodic:
            wrap = const_cast<RtToken>( "periodic" );
            break;
        default:
            wrap = const_cast<RtToken>( "nonperiodic" );
        }

        RiCurvesV(curveType,
                sample.getNumCurves(),
                (RtInt*) sample.getCurvesNumVertices()->get(),
                wrap,
                paramListBuilder.n(),
                paramListBuilder.nms(),
                paramListBuilder.vals() );

    }
    
    if ( multiSample ) { RiMotionEnd(); }
    
}
Example #9
0
//-*****************************************************************************
void ProcessNuPatch( INuPatch &patch, ProcArgs &args )
{
    INuPatchSchema &ps = patch.getSchema();
    
    TimeSamplingPtr ts = ps.getTimeSampling();
    
    SampleTimeSet sampleTimes;
    GetRelevantSampleTimes( args, ts, ps.getNumSamples(), sampleTimes );
    
    
    //trim curves are described outside the motion blocks
    if ( ps.hasTrimCurve() )
    {
        //get the current time sample independent of any shutter values
        INuPatchSchema::Sample sample = ps.getValue(
                ISampleSelector( args.frame / args.fps ) );
        
        RiTrimCurve( sample.getTrimNumCurves()->size(), //numloops
                (RtInt*) sample.getTrimNumCurves()->get(),
                (RtInt*) sample.getTrimOrders()->get(),
                (RtFloat*) sample.getTrimKnots()->get(),
                (RtFloat*) sample.getTrimMins()->get(),
                (RtFloat*) sample.getTrimMaxes()->get(),
                (RtInt*) sample.getTrimNumVertices()->get(),
                (RtFloat*) sample.getTrimU()->get(),
                (RtFloat*) sample.getTrimV()->get(),
                (RtFloat*) sample.getTrimW()->get() );
    }
    
    
    bool multiSample = sampleTimes.size() > 1;
    
    if ( multiSample ) { WriteMotionBegin( args, sampleTimes ); }
    
    for ( SampleTimeSet::iterator iter = sampleTimes.begin();
          iter != sampleTimes.end(); ++iter )
    {
        ISampleSelector sampleSelector( *iter );
        
        INuPatchSchema::Sample sample = ps.getValue( sampleSelector );
        
        
        ParamListBuilder paramListBuilder;
        
        //build this here so that it's still in scope when RiNuPatchV is
        //called.
        std::vector<RtFloat> pwValues;
        
        if ( sample.getPositionWeights() )
        {
            if ( sample.getPositionWeights()->size() == sample.getPositions()->size() )
            {
                //need to combine P with weight form Pw
                pwValues.reserve( sample.getPositions()->size() * 4 );
                
                const float32_t * pStart = reinterpret_cast<const float32_t * >(
                        sample.getPositions()->get() );
                const float32_t * wStart = reinterpret_cast<const float32_t * >(
                        sample.getPositionWeights()->get() );
                
                for ( size_t i = 0, e = sample.getPositionWeights()->size();
                        i < e;  ++i )
                {
                    pwValues.push_back( pStart[i*3] );
                    pwValues.push_back( pStart[i*3+1] );
                    pwValues.push_back( pStart[i*3+2] );
                    pwValues.push_back( wStart[i] );
                }
                
                paramListBuilder.add( "Pw", (RtPointer) &pwValues[0] );
            }
        }
        
        if ( pwValues.empty() )
        {
            //no Pw so go straight with P
            paramListBuilder.add( "P",
                    (RtPointer)sample.getPositions()->get() );
        }
        
        ICompoundProperty arbGeomParams = ps.getArbGeomParams();
        AddArbitraryGeomParams( arbGeomParams,
                    sampleSelector, paramListBuilder );
        
        //For now, use the last knot value for umin and umax as it's
        //not described in the alembic data 
        
        RiNuPatchV(
                sample.getNumU(),
                sample.getUOrder(),
                (RtFloat *) sample.getUKnot()->get(),
                0.0, //umin
                sample.getUKnot()->get()[sample.getUKnot()->size()-1],//umax
                sample.getNumV(),
                sample.getVOrder(),
                (RtFloat *) sample.getVKnot()->get(),
                0.0, //vmin
                sample.getVKnot()->get()[sample.getVKnot()->size()-1], //vmax
                paramListBuilder.n(),
                paramListBuilder.nms(),
                paramListBuilder.vals() );
    }
    
    if ( multiSample ) { RiMotionEnd(); }
    
    
}
Example #10
0
//-*****************************************************************************
void ProcessSubD( ISubD &subd, ProcArgs &args, const std::string & facesetName )
{
    ISubDSchema &ss = subd.getSchema();

    TimeSamplingPtr ts = ss.getTimeSampling();

    SampleTimeSet sampleTimes;
    GetRelevantSampleTimes( args, ts, ss.getNumSamples(), sampleTimes );

    bool multiSample = sampleTimes.size() > 1;

    //include this code path for future expansion
    bool isHierarchicalSubD = false;
    bool hasLocalResources = false;
    
    
    
    std::vector<IFaceSet> faceSets;
    std::vector<std::string> faceSetResourceNames;
    if ( facesetName.empty() )
    {
        std::vector <std::string> childFaceSetNames;
        ss.getFaceSetNames(childFaceSetNames);
        
        faceSets.reserve(childFaceSetNames.size());
        faceSetResourceNames.reserve(childFaceSetNames.size());
        
        for (size_t i = 0; i < childFaceSetNames.size(); ++i)
        {
            faceSets.push_back(ss.getFaceSet(childFaceSetNames[i]));
            
            IFaceSet & faceSet = faceSets.back();
            
            std::string resourceName = args.getResource(
                    faceSet.getFullName() );
            
            if ( resourceName.empty() )
            {
                resourceName = args.getResource( faceSet.getName() );
            }
            
#ifdef PRMAN_USE_ABCMATERIAL
                
                Mat::MaterialFlatten mafla(faceSet);
                
                if (!mafla.empty())
                {
                    if (!hasLocalResources)
                    {
                        RiResourceBegin();
                        hasLocalResources = true;
                    }
                    
                    RiAttributeBegin();
                    
                    if ( !resourceName.empty() )
                    {
                        //restore existing resource state here
                        RestoreResource( resourceName );
                    }
                    
                    
                    WriteMaterial( mafla, args );
                    
                    resourceName = faceSet.getFullName();
                    SaveResource( resourceName );
                    
                    RiAttributeEnd();
                }
#endif
            faceSetResourceNames.push_back(resourceName);
            
        }
    }
#ifdef PRMAN_USE_ABCMATERIAL    
    else
    {
        //handle single faceset material directly
        if ( ss.hasFaceSet( facesetName ) )
        {
            IFaceSet faceSet = ss.getFaceSet( facesetName );
            ApplyObjectMaterial(faceSet, args);
            
        }
    }
#endif
    
    
    
    
    

    if ( multiSample ) { WriteMotionBegin( args, sampleTimes ); }

    for ( SampleTimeSet::iterator iter = sampleTimes.begin();
          iter != sampleTimes.end(); ++iter )
    {
        
        ISampleSelector sampleSelector( *iter );

        ISubDSchema::Sample sample = ss.getValue( sampleSelector );

        RtInt npolys = (RtInt) sample.getFaceCounts()->size();

        ParamListBuilder paramListBuilder;

        paramListBuilder.add( "P", (RtPointer)sample.getPositions()->get() );

        IV2fGeomParam uvParam = ss.getUVsParam();
        if ( uvParam.valid() )
        {
            ICompoundProperty parent = uvParam.getParent();
            
            if ( !args.flipv )
            {
                AddGeomParamToParamListBuilder<IV2fGeomParam>(
                    parent,
                    uvParam.getHeader(),
                    sampleSelector,
                    "float",
                    paramListBuilder,
                    2,
                    "st");
            }
            else if ( std::vector<float> * values =
                    AddGeomParamToParamListBuilderAsFloat<IV2fGeomParam, float>(
                        parent,
                        uvParam.getHeader(),
                        sampleSelector,
                        "float",
                        paramListBuilder,
                        "st") )
            {
                for ( size_t i = 1, e = values->size(); i < e; i += 2 )
                {
                    (*values)[i] = 1.0 - (*values)[i];
                }
            }
            
        }

        ICompoundProperty arbGeomParams = ss.getArbGeomParams();
        AddArbitraryGeomParams( arbGeomParams,
                    sampleSelector, paramListBuilder );

        std::string subdScheme = sample.getSubdivisionScheme();

        SubDTagBuilder tags;

        ProcessFacevaryingInterpolateBoundry( tags, sample );
        ProcessInterpolateBoundry( tags, sample );
        ProcessFacevaryingPropagateCorners( tags, sample );
        ProcessHoles( tags, sample );
        ProcessCreases( tags, sample );
        ProcessCorners( tags, sample );
        
        if ( !facesetName.empty() )
        {
            if ( ss.hasFaceSet( facesetName ) )
            {
                IFaceSet faceSet = ss.getFaceSet( facesetName );
                
                ApplyResources( faceSet, args );
                
                // TODO, move the hold test outside of MotionBegin
                // as it's not meaningful to change per sample
                
                IFaceSetSchema::Sample faceSetSample = 
                        faceSet.getSchema().getValue( sampleSelector );
                
                std::set<int> facesToKeep;
                
                facesToKeep.insert( faceSetSample.getFaces()->get(),
                        faceSetSample.getFaces()->get() +
                                faceSetSample.getFaces()->size() );
                
                for ( int i = 0; i < npolys; ++i )
                {
                    if ( facesToKeep.find( i ) == facesToKeep.end() )
                    {
                        tags.add( "hole" );
                        tags.addIntArg( i );
                    }
                }
            }
        }
        else
        {
            //loop through the facesets and determine whether there are any
            //resources assigned to each
            
            for (size_t i = 0; i < faceSetResourceNames.size(); ++i)
            {
                const std::string & resourceName = faceSetResourceNames[i];
                
                //TODO, visibility?
                
                if ( !resourceName.empty() )
                {
                    IFaceSet & faceSet = faceSets[i];
                    
                    isHierarchicalSubD = true;
                    
                    tags.add("faceedit");
                    
                    Int32ArraySamplePtr faces = faceSet.getSchema().getValue(
                            sampleSelector ).getFaces();
                    
                    for (size_t j = 0, e = faces->size(); j < e; ++j)
                    {
                        tags.addIntArg(1); //yep, every face gets a 1 in front of it too
                        tags.addIntArg( (int) faces->get()[j]);
                    }
                    
                    tags.addStringArg( "attributes" );
                    tags.addStringArg( resourceName );
                    tags.addStringArg( "shading" );
                }
            }
        }


        if ( isHierarchicalSubD )
        {
            RiHierarchicalSubdivisionMeshV(
                const_cast<RtToken>( subdScheme.c_str() ),
                npolys,
                (RtInt*) sample.getFaceCounts()->get(),
                (RtInt*) sample.getFaceIndices()->get(),
                tags.nt(),
                tags.tags(),
                tags.nargs( true ),
                tags.intargs(),
                tags.floatargs(),
                tags.stringargs(),
                paramListBuilder.n(),
                paramListBuilder.nms(),
                paramListBuilder.vals()
                                          );
        }
        else
        {
            RiSubdivisionMeshV(
                const_cast<RtToken>(subdScheme.c_str() ),
                npolys,
                (RtInt*) sample.getFaceCounts()->get(),
                (RtInt*) sample.getFaceIndices()->get(),
                tags.nt(),
                tags.tags(),
                tags.nargs( false ),
                tags.intargs(),
                tags.floatargs(),
                paramListBuilder.n(),
                paramListBuilder.nms(),
                paramListBuilder.vals()
                              );
        }
    }

    if ( multiSample ) { RiMotionEnd(); }
    
    if ( hasLocalResources ) { RiResourceEnd(); }
}
Example #11
0
//-*****************************************************************************
void ProcessPolyMesh( IPolyMesh &polymesh, ProcArgs &args )
{
    IPolyMeshSchema &ps = polymesh.getSchema();

    TimeSamplingPtr ts = ps.getTimeSampling();

    SampleTimeSet sampleTimes;
    GetRelevantSampleTimes( args, ts, ps.getNumSamples(), sampleTimes );

    bool multiSample = sampleTimes.size() > 1;

    if ( multiSample ) { WriteMotionBegin( args, sampleTimes ); }


    for ( SampleTimeSet::iterator iter = sampleTimes.begin();
          iter != sampleTimes.end(); ++ iter )
    {

        ISampleSelector sampleSelector( *iter );

        IPolyMeshSchema::Sample sample = ps.getValue( sampleSelector );

        RtInt npolys = (RtInt) sample.getFaceCounts()->size();

        ParamListBuilder paramListBuilder;

        paramListBuilder.add( "P", (RtPointer)sample.getPositions()->get() );

        IV2fGeomParam uvParam = ps.getUVsParam();
        if ( uvParam.valid() )
        {
            ICompoundProperty parent = uvParam.getParent();
            
            
            if ( !args.flipv )
            {
                AddGeomParamToParamListBuilder<IV2fGeomParam>(
                    parent,
                    uvParam.getHeader(),
                    sampleSelector,
                    "float",
                    paramListBuilder,
                    2,
                    "st");
            }
            else if ( std::vector<float> * values =
                    AddGeomParamToParamListBuilderAsFloat<IV2fGeomParam, float>(
                        parent,
                        uvParam.getHeader(),
                        sampleSelector,
                        "float",
                        paramListBuilder,
                        "st") )
            {
                for ( size_t i = 1, e = values->size(); i < e; i += 2 )
                {
                    (*values)[i] = 1.0 - (*values)[i];
                }
            }
        }
        IN3fGeomParam nParam = ps.getNormalsParam();
        if ( nParam.valid() )
        {
            ICompoundProperty parent = nParam.getParent();
            
            AddGeomParamToParamListBuilder<IN3fGeomParam>(
                parent,
                nParam.getHeader(),
                sampleSelector,
                "normal",
                paramListBuilder);

        }



        ICompoundProperty arbGeomParams = ps.getArbGeomParams();
        AddArbitraryGeomParams( arbGeomParams,
                    sampleSelector, paramListBuilder );

        RiPointsPolygonsV(
            npolys,
            (RtInt*) sample.getFaceCounts()->get(),
            (RtInt*) sample.getFaceIndices()->get(),
            paramListBuilder.n(),
            paramListBuilder.nms(),
            paramListBuilder.vals() );
    }

    if (multiSample) RiMotionEnd();

}
Example #12
0
//-*****************************************************************************
void ProcessXform( IXform &xform, ProcArgs &args )
{
    IXformSchema &xs = xform.getSchema();

    TimeSamplingPtr ts = xs.getTimeSampling();

    size_t xformSamps = xs.getNumSamples();

    SampleTimeSet sampleTimes;
    GetRelevantSampleTimes( args, ts, xformSamps, sampleTimes );

    bool multiSample = sampleTimes.size() > 1;

    std::vector<XformSample> sampleVectors;
    sampleVectors.resize( sampleTimes.size() );

    //fetch all operators at each sample time first
    size_t sampleTimeIndex = 0;
    for ( SampleTimeSet::iterator I = sampleTimes.begin();
          I != sampleTimes.end(); ++I, ++sampleTimeIndex )
    {
        ISampleSelector sampleSelector( *I );

        xs.get( sampleVectors[sampleTimeIndex], sampleSelector );
    }

    if (xs.getInheritsXforms () == false)
    {
        RiIdentity ();
    }

    //loop through the operators individually since a MotionBegin block
    //can enclose only homogenous statements
    for ( size_t i = 0, e = xs.getNumOps(); i < e; ++i )
    {
        if ( multiSample ) { WriteMotionBegin(args, sampleTimes); }

        for ( size_t j = 0; j < sampleVectors.size(); ++j )
        {
            XformOp &op = sampleVectors[j][i];

            switch ( op.getType() )
            {
            case kScaleOperation:
            {
                V3d value = op.getScale();
                RiScale( value.x, value.y, value.z );
                break;
            }
            case kTranslateOperation:
            {
                V3d value = op.getTranslate();
                RiTranslate( value.x, value.y, value.z );
                break;
            }
            case kRotateOperation:
            case kRotateXOperation:
            case kRotateYOperation:
            case kRotateZOperation:
            {
                V3d axis = op.getAxis();
                float degrees = op.getAngle();
                RiRotate( degrees, axis.x, axis.y, axis.z );
                break;
            }
            case kMatrixOperation:
            {
                WriteConcatTransform( op.getMatrix() );
                break;
            }
            }
        }

        if ( multiSample ) { RiMotionEnd(); }
    }
}
Example #13
0
AtNode * ProcessPolyMeshBase(
        primT & prim, ProcArgs & args,
        SampleTimeSet & sampleTimes,
        std::vector<AtUInt32> & vidxs,
        int subdiv_iterations,
        MatrixSampleMap * xformSamples, 
        const std::string & facesetName = "" )
{
    if ( !prim.valid() )
    {
        return NULL;
    }
    
    typename primT::schema_type  &ps = prim.getSchema();
    TimeSamplingPtr ts = ps.getTimeSampling();
    
    if ( ps.getTopologyVariance() != kHeterogenousTopology )
    {
        GetRelevantSampleTimes( args, ts, ps.getNumSamples(), sampleTimes );
    }
    else
    {
        sampleTimes.insert( args.frame / args.fps );
    }
    
    std::string name = args.nameprefix + prim.getFullName();
    
    AtNode * instanceNode = NULL;
    
    std::string cacheId;
    
    if ( args.makeInstance )
    {
        std::ostringstream buffer;
        AbcA::ArraySampleKey sampleKey;
        
        
        for ( SampleTimeSet::iterator I = sampleTimes.begin();
                I != sampleTimes.end(); ++I )
        {
            ISampleSelector sampleSelector( *I );
            ps.getPositionsProperty().getKey(sampleKey, sampleSelector);
            
            buffer << GetRelativeSampleTime( args, (*I) ) << ":";
            sampleKey.digest.print(buffer);
            buffer << ":";
        }
        
        buffer << "@" << subdiv_iterations;
        buffer << "@" << facesetName;
        
        cacheId = buffer.str();
        
        instanceNode = AiNode( "ginstance" );
        AiNodeSetStr( instanceNode, "name", name.c_str() );
        args.createdNodes.push_back(instanceNode);
        
        if ( args.proceduralNode )
        {
            AiNodeSetInt( instanceNode, "visibility",
                    AiNodeGetInt( args.proceduralNode, "visibility" ) );
        
        }
        else
        {
            AiNodeSetInt( instanceNode, "visibility", AI_RAY_ALL );
        }
        
        ApplyTransformation( instanceNode, xformSamples, args );
        
        
        NodeCache::iterator I = g_meshCache.find(cacheId);
        if ( I != g_meshCache.end() )
        {
            AiNodeSetPtr(instanceNode, "node", (*I).second );
            return NULL;
        }
        
    }
    
    
    
    SampleTimeSet singleSampleTimes;
    singleSampleTimes.insert( args.frame / args.fps );
    
    
    std::vector<AtByte> nsides;
    std::vector<float> vlist;
    
    std::vector<float> uvlist;
    std::vector<AtUInt32> uvidxs;
    
    
    // POTENTIAL OPTIMIZATIONS LEFT TO THE READER
    // 1) vlist needn't be copied if it's a single sample
    
    bool isFirstSample = true;
    for ( SampleTimeSet::iterator I = sampleTimes.begin();
          I != sampleTimes.end(); ++I, isFirstSample = false)
    {
        ISampleSelector sampleSelector( *I );
        typename primT::schema_type::Sample sample = ps.getValue( sampleSelector );
        
        if ( isFirstSample )
        {
            size_t numPolys = sample.getFaceCounts()->size();
            nsides.reserve( sample.getFaceCounts()->size() );
            for ( size_t i = 0; i < numPolys; ++i ) 
            {
                int32_t n = sample.getFaceCounts()->get()[i];
                
                if ( n > 255 )
                {
                    // TODO, warning about unsupported face
                    return NULL;
                }
                
                nsides.push_back( (AtByte) n );
            }
            
            size_t vidxSize = sample.getFaceIndices()->size();
            vidxs.reserve( vidxSize );
            vidxs.insert( vidxs.end(), sample.getFaceIndices()->get(),
                    sample.getFaceIndices()->get() + vidxSize );
        }
        
        
        vlist.reserve( vlist.size() + sample.getPositions()->size() * 3);
        vlist.insert( vlist.end(),
                (const float32_t*) sample.getPositions()->get(),
                ((const float32_t*) sample.getPositions()->get()) +
                        sample.getPositions()->size() * 3 );
    }
    
    ProcessIndexedBuiltinParam(
            ps.getUVsParam(),
            singleSampleTimes,
            uvlist,
            uvidxs,
            2);
    
    
    AtNode* meshNode = AiNode( "polymesh" );
    
    if (!meshNode)
    {
        AiMsgError("Failed to make polymesh node for %s",
                prim.getFullName().c_str());
        return NULL;
    }
    
    args.createdNodes.push_back(meshNode);
    
    if ( instanceNode != NULL)
    {
        AiNodeSetStr( meshNode, "name", (name + ":src").c_str() );
    }
    else
    {
        AiNodeSetStr( meshNode, "name", name.c_str() );
    }
    
    
    
    
    AiNodeSetArray(meshNode, "vidxs", 
            ArrayConvert(vidxs.size(), 1, AI_TYPE_UINT,
                    (void*)&vidxs[0]));
    
    AiNodeSetArray(meshNode, "nsides",
            ArrayConvert(nsides.size(), 1, AI_TYPE_BYTE,
                    &(nsides[0])));
    
    AiNodeSetArray(meshNode, "vlist",
            ArrayConvert( vlist.size() / sampleTimes.size(), 
                    sampleTimes.size(), AI_TYPE_FLOAT, (void*)(&(vlist[0]))));
    
    if ( !uvlist.empty() )
    {
        //TODO, option to disable v flipping
        for (size_t i = 1, e = uvlist.size(); i < e; i += 2)
        {
            uvlist[i] = 1.0 - uvlist[i];
        }
        
        AiNodeSetArray(meshNode, "uvlist",
            ArrayConvert( uvlist.size(), 1, AI_TYPE_FLOAT,
                (void*)(&(uvlist[0]))));
        
        if ( !uvidxs.empty() )
        {
            AiNodeSetArray(meshNode, "uvidxs",
                    ArrayConvert(uvidxs.size(), 1, AI_TYPE_UINT,
                            &(uvidxs[0])));
        }
        else
        {
            AiNodeSetArray(meshNode, "uvidxs",
                    ArrayConvert(vidxs.size(), 1, AI_TYPE_UINT,
                            &(vidxs[0])));
        }
    }
    
    if ( sampleTimes.size() > 1 )
    {
        std::vector<float> relativeSampleTimes;
        relativeSampleTimes.reserve( sampleTimes.size() );
        
        for (SampleTimeSet::const_iterator I = sampleTimes.begin();
                I != sampleTimes.end(); ++I )
        {
            relativeSampleTimes.push_back(
                    GetRelativeSampleTime( args, (*I) ) );
                    
        }
        
        AiNodeSetArray( meshNode, "deform_time_samples",
                ArrayConvert(relativeSampleTimes.size(), 1,
                        AI_TYPE_FLOAT, &relativeSampleTimes[0]));
    }
    
    // faceset visibility array
    if ( !facesetName.empty() )
    {
        if ( ps.hasFaceSet( facesetName ) )
        {
            ISampleSelector frameSelector( *singleSampleTimes.begin() );
            
            
            IFaceSet faceSet = ps.getFaceSet( facesetName );
            IFaceSetSchema::Sample faceSetSample = 
                    faceSet.getSchema().getValue( frameSelector );
            
            std::set<int> facesToKeep;
            
            
            facesToKeep.insert( faceSetSample.getFaces()->get(),
                    faceSetSample.getFaces()->get() +
                            faceSetSample.getFaces()->size() );
            
            bool *faceVisArray = new bool(nsides.size());
            
            for ( int i = 0; i < (int) nsides.size(); ++i )
            {
                faceVisArray[i] = facesToKeep.find( i ) != facesToKeep.end();
            }
            
            if ( AiNodeDeclare( meshNode, "face_visibility", "uniform BOOL" ) )
            {
                AiNodeSetArray( meshNode, "face_visibility",
                        ArrayConvert( nsides.size(), 1, AI_TYPE_BOOLEAN,
                                faceVisArray ) );
            }
            
            delete[] faceVisArray;
        }
    }
    
    {
        ICompoundProperty arbGeomParams = ps.getArbGeomParams();
        ISampleSelector frameSelector( *singleSampleTimes.begin() );
        
        AddArbitraryGeomParams( arbGeomParams, frameSelector, meshNode );
    }
    
    
    if ( instanceNode == NULL )
    {
        if ( xformSamples )
        {
            ApplyTransformation( meshNode, xformSamples, args );
        }
        
        return meshNode;
    }
    else
    {
        AiNodeSetInt( meshNode, "visibility", 0 );
        
        AiNodeSetPtr(instanceNode, "node", meshNode );
        g_meshCache[cacheId] = meshNode;
        return meshNode;
        
    }
    
}