/** Write the RIB for this paint effects toon line. */ void liqRibPfxToonData::write() { LIQDEBUGPRINTF( "-> writing pfxToon curve\n" ); if ( 0 < ncurves ) { unsigned numTokens( tokenPointerArray.size() ); scoped_array< RtToken > tokenArray( new RtToken[ numTokens ] ); scoped_array< RtPointer > pointerArray( new RtPointer[ numTokens ] ); assignTokenArraysV( tokenPointerArray, tokenArray.get(), pointerArray.get() ); RiCurvesV( "linear", ncurves, nverts.get(), "nonperiodic", numTokens, tokenArray.get(), pointerArray.get() ); } else RiIdentity(); // Make sure we don't create empty motion blocks }
static void _write(liqRibCurvesData* pData, const structJob ¤tJob__) { CM_TRACE_FUNC("rm_writeCurvesData.cpp::_write("<<pData->getFullPathName().asChar()<<","<<currentJob__.name.asChar()<<",...)"); // don't write if empty group if( pData->isEmpty() ) return; unsigned numTokens( pData->tokenPointerArray.size() ); boost::scoped_array< RtToken > tokenArray( new RtToken[ numTokens ] ); boost::scoped_array< RtPointer > pointerArray( new RtPointer[ numTokens ] ); assignTokenArraysV( pData->tokenPointerArray, tokenArray.get(), pointerArray.get() ); RiCurvesV( "cubic", pData->getNCurves(), pData->getNVerts().get(), "nonperiodic", numTokens, tokenArray.get(), pointerArray.get() ); }
//-***************************************************************************** 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(); } }
static void _write(liqRibParticleData* pData, const structJob ¤tJob__) { CM_TRACE_FUNC("rm_writeParticleData.cpp::write("<<pData->getFullPathName().asChar()<<","<<currentJob__.name.asChar()<<",...)"); LIQDEBUGPRINTF( "-> writing particles\n"); #ifdef DEBUG RiArchiveRecord( RI_COMMENT, "Number of Valid Particles: %d", pData->m_numValidParticles ); RiArchiveRecord( RI_COMMENT, "Number of Discarded Particles: %d", pData->m_numParticles - pData->m_numValidParticles ); #endif MString notes("Make sure the particle is generated(e.g. sometimes particle is not generated, drag the time slider from frame0 to generate particles.)"); if(pData->m_numValidParticles <= 0 ){ RiArchiveRecord( RI_COMMENT, "Number of Valid Particles: %d. %s", pData->m_numValidParticles, notes.asChar() ); liquidMessage2(messageError, "%s. [%s]", notes.asChar(), pData->getFullPathName().asChar()); return; } unsigned numTokens( pData->tokenPointerArray.size() ); boost::scoped_array< RtToken > tokenArray( new RtToken[ numTokens ] ); boost::scoped_array< RtPointer > pointerArray( new RtPointer[ numTokens ] ); assignTokenArraysV( pData->tokenPointerArray, tokenArray.get(), pointerArray.get() ); switch( pData->particleType ) { case liqRibParticleData::MPTBlobbies: { // Build an array that can be given to RiBlobby std::vector< RtString > stringArray; for( int i(0); i < pData->m_stringArray.size(); i++ ) { stringArray.push_back( const_cast<char *>( pData->m_stringArray[i].c_str()) ); } RiBlobbyV( pData->m_numValidParticles, pData->m_codeArray.size(), const_cast< RtInt* >( &pData->m_codeArray[0] ), pData->m_floatArray.size(), const_cast< RtFloat* >( &pData->m_floatArray[0] ), stringArray.size(), const_cast< RtString* >( &stringArray[0] ), numTokens, tokenArray.get(), const_cast< RtPointer* >( pointerArray.get() ) ); pData->grain = 0; } break; case liqRibParticleData::MPTMultiPoint: case liqRibParticleData::MPTPoints: RiArchiveRecord( RI_COMMENT, "normal has to be reversed to show the MultiPoint/Points particles. // [10/9/2012 yaoyansi]" ); RiReverseOrientation(); #ifdef DELIGHT case liqRibParticleData::MPTSpheres: case liqRibParticleData::MPTSprites: #endif { RiPointsV( pData->m_numValidParticles * pData->m_multiCount, numTokens, tokenArray.get(), pointerArray.get() ); } break; case liqRibParticleData::MPTMultiStreak: case liqRibParticleData::MPTStreak: { unsigned nStreaks( pData->m_numValidParticles * pData->m_multiCount / 2 ); std::vector< RtInt > verts( nStreaks, 2 ); // Alternatively: // scoped_array< RtInt >verts( new RtInt[ nStreaks ] ); // fill( verts.get(), verts.get() + nStreaks, ( RtInt )2 ); // Both ways are way faster than the frickin for() lop that was here before -- Moritz RiCurvesV( "linear", nStreaks, &verts[ 0 ], "nonperiodic", numTokens, tokenArray.get(), pointerArray.get() ); } break; #ifndef DELIGHT case liqRibParticleData::MPTSpheres: { int posAttr = -1, radAttr = -1, colAttr = -1, opacAttr = -1; for ( unsigned i = 0; i < pData->tokenPointerArray.size(); i++ ) { const std::string tokenName( pData->tokenPointerArray[i].getTokenName() ); if ( "P" == tokenName ) { posAttr = i; } else if ( "radius" == tokenName ) { radAttr = i; } else if ( "Cs" == tokenName ) { colAttr = i; } else if ( "Os" == tokenName ) { opacAttr = i; } } for ( unsigned i = 0; i < pData->m_numValidParticles; i++) { RiAttributeBegin(); if ( colAttr != -1 ) { RiColor( &((RtFloat*)pointerArray[colAttr])[i*3] ); } if ( opacAttr != -1 ) { RiOpacity( &((RtFloat*)pointerArray[opacAttr])[i*3] ); } RiTransformBegin(); RiTranslate(((RtFloat*)pointerArray[posAttr])[i*3+0], ((RtFloat*)pointerArray[posAttr])[i*3+1], ((RtFloat*)pointerArray[posAttr])[i*3+2]); RtFloat radius = ((RtFloat*)pointerArray[radAttr])[i]; RiSphere(radius, -radius, radius, 360, RI_NULL); RiTransformEnd(); RiAttributeEnd(); } } break; case liqRibParticleData::MPTSprites: { int posAttr = -1, numAttr = -1, twistAttr = -1, scaleXAttr = -1, scaleYAttr = -1, colAttr = -1, opacAttr = -1; for ( unsigned i( 0 ); i < pData->tokenPointerArray.size(); i++ ) { const std::string tokenName( pData->tokenPointerArray[i].getTokenName() ); if ( "P" == tokenName ) { posAttr = i; } else if ( "spriteNum" == tokenName ) { numAttr = i; } else if ( "spriteTwist" == tokenName ) { twistAttr = i; } else if ( "spriteScaleX" == tokenName ) { scaleXAttr = i; } else if ( "spriteScaleY" == tokenName ) { scaleYAttr = i; } else if ( "Cs" == tokenName ) { colAttr = i; } else if ( "Os" == tokenName ) { opacAttr = i; } } MVector camUp( 0, 1, 0 ); MVector camRight( 1, 0, 0 ); MVector camEye( 0, 0, 1 ); camUp *= currentJob__.camera[0].mat.inverse(); camRight *= currentJob__.camera[0].mat.inverse(); camEye *= currentJob__.camera[0].mat.inverse(); for( unsigned ui( 0 ); ui < pData->m_numValidParticles; ui++ ) { MVector up( camUp ); MVector right( camRight ); float spriteRadiusX( 0.5 ); float spriteRadiusY( 0.5 ); RiAttributeBegin(); RiArchiveRecord( RI_COMMENT, "normal has to be reversed to show the Sprite particles. // [10/9/2012 yaoyansi]" ); RiReverseOrientation(); if ( -1 != colAttr ) RiColor( &( ( RtFloat* )pointerArray[ colAttr ] )[ ui * 3 ] ); if ( -1 != opacAttr ) RiOpacity( &( ( RtFloat* )pointerArray[ opacAttr ] )[ ui * 3 ] ); if ( -1 != twistAttr ) { float twist( -( ( RtFloat* )pointerArray[ twistAttr ] )[ ui ] * M_PI / 180 ); MQuaternion twistQ( twist, camEye ); right = camRight.rotateBy( twistQ ); up = camUp.rotateBy( twistQ ); } if ( scaleXAttr != -1 ) spriteRadiusX *= ( ( RtFloat* )pointerArray[ scaleXAttr ] )[ ui ]; if ( scaleYAttr != -1 ) spriteRadiusY *= ( ( RtFloat* )pointerArray[ scaleYAttr ] )[ ui ]; if ( posAttr != -1 ) { float *P( &( ( RtFloat* ) pointerArray[ posAttr ] )[ ui * 3 ] ); float spriteNumPP = 0; if ( numAttr != -1 ) spriteNumPP = ( ( RtFloat* )pointerArray[ numAttr ] )[ ui ]; float x0 = P[ 0 ] - spriteRadiusX * right[ 0 ] + spriteRadiusY * up[ 0 ]; float y0 = P[ 1 ] - spriteRadiusX * right[ 1 ] + spriteRadiusY * up[ 1 ]; float z0 = P[ 2 ] - spriteRadiusX * right[ 2 ] + spriteRadiusY * up[ 2 ]; float x1 = P[ 0 ] + spriteRadiusX * right[ 0 ] + spriteRadiusY * up[ 0 ]; float y1 = P[ 1 ] + spriteRadiusX * right[ 1 ] + spriteRadiusY * up[ 1 ]; float z1 = P[ 2 ] + spriteRadiusX * right[ 2 ] + spriteRadiusY * up[ 2 ]; float x2 = P[ 0 ] - spriteRadiusX * right[ 0 ] - spriteRadiusY * up[ 0 ]; float y2 = P[ 1 ] - spriteRadiusX * right[ 1 ] - spriteRadiusY * up[ 1 ]; float z2 = P[ 2 ] - spriteRadiusX * right[ 2 ] - spriteRadiusY * up[ 2 ]; float x3 = P[ 0 ] + spriteRadiusX * right[ 0 ] - spriteRadiusY * up[ 0 ]; float y3 = P[ 1 ] + spriteRadiusX * right[ 1 ] - spriteRadiusY * up[ 1 ]; float z3 = P[ 2 ] + spriteRadiusX * right[ 2 ] - spriteRadiusY * up[ 2 ]; float patch[ 12 ] = { x0, y0, z0, x1, y1, z1, x2, y2, z2, x3, y3, z3 }; // !!! if not GENERIC_RIBLIB use RiPatch( "bilinear", "P", &patch, "float spriteNum", &spriteNum, RI_NULL ); // RiPatch( "bilinear", "P", &patch, "float spriteNum", (RtFloat*)&spriteNumPP, RI_NULL ); // Patch "bilinear" "P" [0.446265 0.316269 -0.647637 1.27725 0.316269 -1.20393 0.615752 -0.636188 -0.39446 1.44674 -0.636188 -0.950756 ] "float spriteNum" [2 0 0 0 ] RiArchiveRecord( RI_VERBATIM, "Patch \"bilinear\" \"P\" [%f %f %f %f %f %f %f %f %f %f %f %f] \"float spriteNum\" [%f]", x0, y0, z0,x1, y1, z1, x2, y2, z2,x3, y3, z3, spriteNumPP ); } else { RiIdentity(); } RiAttributeEnd(); }//for } break; #endif // #ifndef DELIGHT case liqRibParticleData::MPTCloudy: { int posAttr = -1, radAttr = -1, colAttr = -1, opacAttr = -1, rotAttr = -1; for ( unsigned i = 0; i < pData->tokenPointerArray.size(); i++ ) { const std::string tokenName( pData->tokenPointerArray[i].getTokenName() ); if ( "P" == tokenName ) { posAttr = i; } else if ( "radius" == tokenName ) { radAttr = i; } else if ( "Cs" == tokenName ) { colAttr = i; } else if ( "Os" == tokenName ) { opacAttr = i; } else if ( "rotation" == tokenName ) { rotAttr = i; } } // Build an array that can be given to RiBlobby std::vector< RtString > stringArray; for( unsigned int i(0); i < pData->m_stringArray.size(); i++ ) { stringArray.push_back( const_cast<char *>( pData->m_stringArray[i].c_str()) ); } if(stringArray.size()==0)//added by yaoyansi, or it leads a crash on windows stringArray.push_back( "" ); boost::scoped_array< RtToken > ithTokenArray( new RtToken[ numTokens ] ); boost::scoped_array< RtPointer > ithPointerArray( new RtPointer[ numTokens ] ); for ( unsigned i = 0; i < pData->m_numValidParticles; i++) { assignIthTokenArraysV( pData->tokenPointerArray, ithTokenArray.get(), ithPointerArray.get(), i ); RiAttributeBegin(); if ( colAttr != -1 ) { RiColor( &((RtFloat*)pointerArray[colAttr])[i*3] ); } if ( opacAttr != -1 ) { RiOpacity( &((RtFloat*)pointerArray[opacAttr])[i*3] ); } RiTransformBegin(); RiTranslate(((RtFloat*)pointerArray[posAttr])[i*3+0], ((RtFloat*)pointerArray[posAttr])[i*3+1], ((RtFloat*)pointerArray[posAttr])[i*3+2]); if ( rotAttr != -1 ) { RiRotate( (( RtFloat *) pointerArray[rotAttr])[i*3] * 360.0, 1.0, 0.0, 0.0 ); RiRotate( (( RtFloat *) pointerArray[rotAttr])[i*3+1] * 360.0, 0.0, 1.0, 0.0 ); RiRotate( (( RtFloat *) pointerArray[rotAttr])[i*3+2] * 360.0, 0.0, 0.0, 1.0 ); } RtFloat radius = ((RtFloat*)pointerArray[radAttr])[i]; RiScale( radius, radius, radius ); //RiSphere(radius, -radius, radius, 360, RI_NULL); float dummy[] = { 0.0, 0.0, 0.0 }; // Worst case : three floats are needed RiBlobbyV( 1, pData->m_codeArray.size(), const_cast< RtInt* >( &pData->m_codeArray[0] ), pData->m_floatArray.size(), const_cast< RtFloat* >( &pData->m_floatArray[0] ), stringArray.size(), const_cast< RtString* >( &stringArray[0] ), numTokens, ithTokenArray.get(), ithPointerArray.get() ); // "vertex color incandescence", (RtPointer *)( dummy ), // "vertex color Cs", (RtPointer *)( dummy ), // "vertex float selfshadow", (RtPointer *)( dummy ), // RI_NULL ); RiTransformEnd(); RiAttributeEnd(); } break; } case liqRibParticleData::MPTNumeric: RiArchiveRecord( RI_COMMENT, "Numeric Particles are not supported" ); break; case liqRibParticleData::MPTTube: RiArchiveRecord( RI_COMMENT, "Tube Particles are not supported" ); break; break; } }