void wendy_GIO_ROP::save_mata_ass(string arDsoPath,string dpCachePath,GU_Detail *gdp ) { //get arnold dso path g_particle_mataAss assROP; ofstream fout; string getCacheDP=dpCachePath; stringstream ss(getCacheDP); string sub_str; vector <string> sp_strPath; sp_strPath.clear(); while(getline(ss,sub_str,'.')) { sp_strPath.push_back(sub_str); } string newAssPathName = sp_strPath[0]+"."+sp_strPath[1]+string(".ass"); fout.open(newAssPathName); assROP.setGioCachePath(getCacheDP); // set Link GIO CACHE for (GA_AttributeDict::iterator it = gdp->getAttributeDict(GA_ATTRIB_POINT).begin(GA_SCOPE_PUBLIC); !it.atEnd(); ++it) { GA_Attribute *attrib = it.attrib(); string attName( attrib->getName() ); assROP.inserExtraMataInfo(attName); } //set ass bbox UT_BoundingBox BBOX; gdp->getBBox(&BBOX); BBOX.expandBounds(2,2,2); float min_x=BBOX.xmin(); float min_y=BBOX.xmin(); float min_z=BBOX.xmin(); float max_x=BBOX.xmax(); float max_y=BBOX.ymax(); float max_z=BBOX.zmax(); assROP.setBBOX(min_x,min_y,min_z,max_x,max_y,max_z); assROP.setDsoPath(arDsoPath); assROP.save(fout); fout.close(); }
static void updateAttributeList(g_global_io &io,GU_Detail *cur_gdp) { fpreal numPt= cur_gdp->getNumPoints(); GA_Iterator iter(cur_gdp->getPointRange()); fpreal start_point_num = *iter; if ( cur_gdp ) { for (GA_AttributeDict::iterator it = cur_gdp->getAttributeDict(GA_ATTRIB_POINT).begin(GA_SCOPE_PUBLIC); !it.atEnd(); ++it) { GA_Attribute *attrib = it.attrib(); UT_String attName( attrib->getName() ); // std::cout<<"the att name is"<<attName<<std::endl; int attSize = attrib->getTupleSize(); GA_StorageClass storage= attrib->getStorageClass(); GA_TypeInfo typeInfo = attrib->getTypeInfo(); //save mata info switch(attSize) { case 1: // per int or float if(storage==GA_STORECLASS_FLOAT) { std::cout<<"the att name is "<<attName<< " and the type is float\n"; g_particles_io t_io; t_io.GIO_SetCurrentAttributeName(attName); t_io.GIO_SetCurrentAttributeType(g_particles_io::FLT_TYPE); std::vector<float> t_value; // create empty stack forkTheFLTData(t_value,attrib,numPt,start_point_num); t_io.GIO_setFLTAttributeList(t_value); io.GIO_installParticleHandle(t_io); // install this attribute into our global IO } if(storage==GA_STORECLASS_INT) { std::cout<<"the att name is "<<attName<< " and the type is int\n"; g_particles_io t_io; t_io.GIO_SetCurrentAttributeName(attName); t_io.GIO_SetCurrentAttributeType(g_particles_io::INT_TYPE); std::vector<int> t_value; // create empty int stack forkTheINTData(t_value,attrib,numPt,start_point_num); t_io.GIO_setINTAttributeList(t_value); io.GIO_installParticleHandle(t_io); } break; case 3: // int vector or float vector if(storage==GA_STORECLASS_FLOAT) { std::cout<<"the att name is "<<attName<< " and the type is float vector\n"; g_particles_io t_io; t_io.GIO_SetCurrentAttributeName(attName); t_io.GIO_SetCurrentAttributeType(g_particles_io::FLT_VEC_TYPE); std::vector<per_float_vector> t_value; // create empty int stack forkTheFLTVectorData(t_value,attrib,numPt,start_point_num); t_io.GIO_setFLTVecAttributeList(t_value); io.GIO_installParticleHandle(t_io); } if(storage==GA_STORECLASS_INT) { std::cout<<"the att name is "<<attName<< " and the type is int vector\n"; g_particles_io t_io; t_io.GIO_SetCurrentAttributeName(attName); t_io.GIO_SetCurrentAttributeType(g_particles_io::INT_VEC_TYPE); std::vector<per_int_vector> t_value; // create empty int stack forkTheINTVectorData(t_value,attrib,numPt,start_point_num); t_io.GIO_setINTVecAttributeList(t_value); io.GIO_installParticleHandle(t_io); } break; case 4: // P attrib { std::cout<<"the att name is "<<attName<< " and the type is float 4 \n"; g_particles_io t_io; t_io.GIO_SetCurrentAttributeName(attName); t_io.GIO_SetCurrentAttributeType(g_particles_io::FLT_VEC_TYPE); std::vector<per_float_vector> t_value; // create empty int stack forkTheFLTVectorData(t_value,it.attrib(),numPt,start_point_num); t_io.GIO_setFLTVecAttributeList(t_value); io.GIO_installParticleHandle(t_io); } break; } } } }
OP_ERROR SOP_Smoke_Source::cookMySop(OP_Context &context) { // We must lock our inputs before we try to access their geometry. // OP_AutoLockInputs will automatically unlock our inputs when we return. // NOTE: Don't call unlockInputs yourself when using this! OP_AutoLockInputs inputs(this); if (inputs.lock(context) >= UT_ERROR_ABORT) return error(); fpreal now = context.getTime(); duplicateSource(0, context); // These three lines enable the local variable support. This allows // $CR to get the red colour, for example, as well as supporting // any varmap created by the Attribute Create SOP. // Note that if you override evalVariableValue for your own // local variables (like SOP_Star does) it is essential you // still call the SOP_Node::evalVariableValue or you'll not // get any of the benefit of the built in local variables. // The variable order controls precedence for which attribute will be // be bound first if the same named variable shows up in multiple // places. This ordering ensures point attributes get precedence. setVariableOrder(3, 2, 0, 1); // The setCur* functions track which part of the gdp is currently // being processed - it is what is used in the evalVariableValue // callback as the current point. The 0 is for the first input, // you can have two inputs so $CR2 would get the second input's // value. setCurGdh(0, myGdpHandle); // Builds the lookup table matching attributes to the local variables. setupLocalVars(); // Here we determine which groups we have to work on. We only // handle point groups. if (error() < UT_ERROR_ABORT && cookInputGroups(context) < UT_ERROR_ABORT && (!myGroup || !myGroup->isEmpty())) { UT_AutoInterrupt progress("Flattening Points"); // Handle all position, normal, and vector attributes. // It's not entirely clear what to do for quaternion or transform attributes. // We bump the data IDs of the attributes to modify in advance, // since we're already looping over them, and we want to avoid // bumping them all for each point, in case that's slow. UT_Array<GA_RWHandleV3> positionattribs(1); UT_Array<GA_RWHandleV3> normalattribs; UT_Array<GA_RWHandleV3> vectorattribs; GA_Attribute *attrib; GA_FOR_ALL_POINT_ATTRIBUTES(gdp, attrib) { // Skip non-transforming attributes if (!attrib->needsTransform()) continue; GA_TypeInfo typeinfo = attrib->getTypeInfo(); if (typeinfo == GA_TYPE_POINT || typeinfo == GA_TYPE_HPOINT) { GA_RWHandleV3 handle(attrib); if (handle.isValid()) { positionattribs.append(handle); attrib->bumpDataId(); } } else if (typeinfo == GA_TYPE_NORMAL) { GA_RWHandleV3 handle(attrib); if (handle.isValid()) { normalattribs.append(handle); attrib->bumpDataId(); } } else if (typeinfo == GA_TYPE_VECTOR) { GA_RWHandleV3 handle(attrib); if (handle.isValid()) { vectorattribs.append(handle); attrib->bumpDataId(); } } } // Iterate over points up to GA_PAGE_SIZE at a time using blockAdvance. GA_Offset start; GA_Offset end; for (GA_Iterator it(gdp->getPointRange(myGroup)); it.blockAdvance(start, end);) { // Check if user requested abort if (progress.wasInterrupted()) break; for (GA_Offset ptoff = start; ptoff < end; ++ptoff) { // This sets the current point that is beint processed to // ptoff. This means that ptoff will be used for any // local variable for any parameter evaluation that occurs // after this point. // NOTE: Local variables and repeated parameter evaluation // is significantly slower and sometimes more complicated // than having a string parameter that specifies the name // of an attribute whose values should be used instead. // That parameter would only need to be evaluated once, // the attribute could be looked up once, and quickly // accessed; however, a separate point attribute would // be needed for each property that varies per point. // Local variable evaluation isn't threadsafe either, // whereas attributes can be read safely from multiple // threads. // // Long story short: *Local variables are terrible.* myCurPtOff[0] = ptoff; float dist = DIST(now); UT_Vector3 normal; if (!DIRPOP()) { switch (ORIENT()) { case 0 : // XY Plane normal.assign(0, 0, 1); break; case 1 : // YZ Plane normal.assign(1, 0, 0); break; case 2 : // XZ Plane normal.assign(0, 1, 0); break; } } else { normal.assign(NX(now), NY(now), NZ(now)); normal.normalize(); } // Project positions onto the plane by subtracting // off the normal component. for (exint i = 0; i < positionattribs.size(); ++i) { UT_Vector3 p = positionattribs(i).get(ptoff); p -= normal * (dot(normal, p) - dist); positionattribs(i).set(ptoff, p); } // Normals will now all either be normal or -normal. for (exint i = 0; i < normalattribs.size(); ++i) { UT_Vector3 n = normalattribs(i).get(ptoff); if (dot(normal, n) < 0) n = -normal; else n = normal; normalattribs(i).set(ptoff, n); } // Project vectors onto the plane through the origin by // subtracting off the normal component. for (exint i = 0; i < vectorattribs.size(); ++i) { UT_Vector3 v = vectorattribs(i).get(ptoff); v -= normal * dot(normal, v); vectorattribs(i).set(ptoff, v); } } } }
static void exportParticlesDetail( const GU_Detail* gdp, const std::string& filePath, const std::map<std::string, channel_type>& desiredChannels ) { prt_ofstream ostream; static std::map<std::string, std::string> s_reservedChannels; if( s_reservedChannels.empty() ) { s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_NORMAL ) ] = "Normal"; s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_TEXTURE ) ] = "TextureCoord"; s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_VELOCITY ) ] = "Velocity"; s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_DIFFUSE ) ] = "Color"; //s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_ALPHA ) ] = "Density"; //s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_MASS ) ] = "Density"; s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_LIFE ) ] = ""; s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_ID ) ] = "ID"; s_reservedChannels[ gdp->getStdAttributeName( GEO_ATTRIBUTE_PSCALE ) ] = "Scale"; s_reservedChannels[ "accel" ] = "Acceleration"; } float posVal[3]; float lifeVal[2]; ostream.bind( "Position", posVal, 3 ); //We handle the life channel in a special manner GA_ROAttributeRef lifeAttrib = gdp->findPointAttribute( gdp->getStdAttributeName( GEO_ATTRIBUTE_LIFE ) ); if( lifeAttrib.isValid() ){ std::map<std::string,channel_type>::const_iterator it; it = desiredChannels.find( "Age" ); if( it != desiredChannels.end() && it->second.second == 1 ) ostream.bind( "Age", &lifeVal[0], 1, it->second.first ); else if( desiredChannels.empty() ) ostream.bind( "Age", &lifeVal[0], 1, prtio::data_types::type_float16 ); it = desiredChannels.find( "LifeSpan" ); if( it != desiredChannels.end() && it->second.second == 1 ) ostream.bind( "LifeSpan", &lifeVal[1], 1, it->second.first ); else if( desiredChannels.empty() ) ostream.bind( "LifeSpan", &lifeVal[1], 1, prtio::data_types::type_float16 ); } //Using a deque to prevent the memory from moving around after adding the bound_attribute to the container. std::deque< bound_attribute<int> > m_intAttrs; std::deque< bound_attribute<float> > m_floatAttrs; std::deque< bound_attribute<float> > m_vectorAttrs; for ( GA_AttributeDict::iterator it = gdp->getAttributes().getDict(GA_ATTRIB_POINT).begin(GA_SCOPE_PUBLIC); !it.atEnd(); ++it) { GA_Attribute *node = it.attrib(); std::string channelName = node->getName(); //Translate special names std::map<std::string,std::string>::const_iterator itResChannel = s_reservedChannels.find( channelName ); if( itResChannel != s_reservedChannels.end() ){ //If its empty, that means we reserve some sort of special handling. if( itResChannel->second.empty() ) continue; channelName = itResChannel->second; } //Skip channels that aren't on the list. std::map<std::string,channel_type>::const_iterator itChannel = desiredChannels.find( channelName ); bool channelIsDesired = ( itChannel != desiredChannels.end() ); if( !desiredChannels.empty() && !channelIsDesired ) continue; prtio::data_types::enum_t type; //Only add valid channel names if( detail::is_valid_channel_name( channelName.c_str() ) ) { //I add the new item to the deque, THEN initialize it since a deque will not move the object around and this allows //me to allocate the float array and not have to worry about the object getting deleted too early. switch( node->getStorageClass() ){ case GA_STORECLASS_FLOAT: if( node->getTupleSize()==3 ){ m_vectorAttrs.push_back( bound_attribute<float>() ); m_vectorAttrs.back().attr = gdp->findPointAttribute(node->getName()); m_vectorAttrs.back().count = node->getTupleSize(); m_vectorAttrs.back().data = new float[m_vectorAttrs.back().count]; type = prtio::data_types::type_float16; if( channelIsDesired ){ type = itChannel->second.first; if( itChannel->second.second != m_vectorAttrs.back().count ) continue; } ostream.bind( channelName, m_vectorAttrs.back().data, m_vectorAttrs.back().count, type ); } else { m_floatAttrs.push_back( bound_attribute<float>() ); m_floatAttrs.back().attr = gdp->findPointAttribute( node->getName() ); m_floatAttrs.back().count = node->getTupleSize(); m_floatAttrs.back().data = new float[m_floatAttrs.back().count]; type = prtio::data_types::type_float16; if( channelIsDesired ){ type = itChannel->second.first; if( itChannel->second.second != m_floatAttrs.back().count ) continue; } ostream.bind( channelName, m_floatAttrs.back().data, m_floatAttrs.back().count, type ); } break; case GA_STORECLASS_INT: m_intAttrs.push_back( bound_attribute<int>() ); m_intAttrs.back().attr = gdp->findPointAttribute( node->getName() ); m_intAttrs.back().count = node->getTupleSize(); m_intAttrs.back().data = new int[m_intAttrs.back().count]; type = prtio::data_types::type_int32; if( channelIsDesired ){ type = itChannel->second.first; if( itChannel->second.second != m_intAttrs.back().count ) continue; } ostream.bind( channelName, m_intAttrs.back().data, m_intAttrs.back().count, type ); break; default: break; } } } try{ ostream.open( filePath ); } catch( const std::ios::failure& e ) { std::cerr << e.what() << std::endl; throw HOM_OperationFailed( "Failed to open the file" ); } GA_IndexMap map = gdp->getPointMap(); UT_Vector3 p; GEO_Point* pt; GA_Index indexSize = map.indexSize(); GA_Offset offset; for( int i = 0 ; i < indexSize; i++ ) { offset = map.offsetFromIndex( i ); p = gdp->getPos3( offset ); posVal[0] = p.x(); posVal[1] = p.y(); posVal[2] = -1 * p.z(); //TODO: Remove the GEO_Point object that is now deprecated. pt = ( GEO_Point* )gdp->getGBPoint( offset ); //TODO: Convert this into appropriate time values. Is it seconds or frames or what?! if( lifeAttrib.isValid() ) pt->get( lifeAttrib, lifeVal, 2 ); for( std::deque< bound_attribute<float> >::iterator it = m_floatAttrs.begin(), itEnd = m_floatAttrs.end(); it != itEnd; ++it ) pt->get( it->attr, it->data, it->count ); for( std::deque< bound_attribute<float> >::iterator it = m_vectorAttrs.begin(), itEnd = m_vectorAttrs.end(); it != itEnd; ++it ) { pt->get( it->attr, it->data, it->count ); //TODO: Optionally transform into some consistent world space for PRT files. } for( std::deque< bound_attribute<int> >::iterator it = m_intAttrs.begin(), itEnd = m_intAttrs.end(); it != itEnd; ++it ) pt->get( it->attr, it->data, it->count ); ostream.write_next_particle(); } ostream.close(); }
/* static */ GU_PrimPacked* GusdGU_PackedUSD::Build( GU_Detail& detail, const UT_StringHolder& fileName, const SdfPath& primPath, UsdTimeCode frame, const char* lod, GusdPurposeSet purposes, const UsdPrim& prim, const UT_Matrix4D* xform ) { auto packedPrim = GU_PrimPacked::build( detail, k_typeName ); auto impl = UTverify_cast<GusdGU_PackedUSD *>(packedPrim->implementation()); impl->m_fileName = fileName; impl->m_primPath = primPath; impl->m_frame = frame; if( prim && !prim.IsA<UsdGeomBoundable>() ) { UsdGeomImageable geom = UsdGeomImageable(prim); std::vector<UsdGeomPrimvar> authoredPrimvars = geom.GetAuthoredPrimvars(); GT_DataArrayHandle buffer; for( const UsdGeomPrimvar &primvar : authoredPrimvars ) { // XXX This is temporary code, we need to factor the usd read code into GT_Utils.cpp // to avoid duplicates and read for types GfHalf,double,int,string ... GT_DataArrayHandle gtData = GusdPrimWrapper::convertPrimvarData( primvar, frame ); if (!gtData) continue; const UT_String name(primvar.GetPrimvarName()); const GT_Storage gtStorage = gtData->getStorage(); const GT_Size gtTupleSize = gtData->getTupleSize(); GA_Attribute *anAttr = detail.addTuple(GT_Util::getGAStorage(gtStorage), GA_ATTRIB_PRIMITIVE, name, gtTupleSize); if( !anAttr ) { // addTuple could fail for various reasons, like if there's a // non-alphanumeric character in the primvar name. continue; } if( const GA_AIFTuple *aIFTuple = anAttr->getAIFTuple()) { const float* flatArray = gtData->getF32Array( buffer ); aIFTuple->set( anAttr, packedPrim->getMapOffset(), flatArray, gtTupleSize ); } else { //TF_WARN( "Unsupported primvar type: %s, %s, tupleSize = %zd", // GT_String( name ), GTstorage( gtStorage ), gtTupleSize ); } } } if( lod ) { #if SYS_VERSION_FULL_INT < 0x10050000 impl->intrinsicSetViewportLOD( lod ); #else impl->intrinsicSetViewportLOD( packedPrim, lod ); #endif } impl->setPurposes( purposes ); // It seems that Houdini may reuse memory for packed implementations with // out calling the constructor to initialize data. impl->resetCaches(); // If a UsdPrim was passed in, make sure it is used. impl->m_usdPrim = prim; if (xform) { impl->setTransform(*xform); } else { impl->updateTransform(); } return packedPrim; }
/// Cook the SOP! This method does all the work OP_ERROR SOP_OpHolder::cookMySop( OP_Context &context ) { IECore::MessageHandler::Scope handlerScope( getMessageHandler() ); // some defaults and useful variables Imath::Box3f bbox( Imath::V3f(-1,-1,-1), Imath::V3f(1,1,1) ); float now = context.getTime(); // force eval of our nodes parameters with our hidden parameter expression evalInt( "__evaluateParameters", 0, now ); // get our op IECore::OpPtr op = IECore::runTimeCast<IECore::Op>( getParameterised() ); // check for a valid parameterised on this SOP if ( !op ) { UT_String msg( "Op Holder has no parameterised class to operate on!" ); addError( SOP_MESSAGE, msg ); return error(); } if( lockInputs(context)>=UT_ERROR_ABORT ) { return error(); } // start our work UT_Interrupt *boss = UTgetInterrupt(); boss->opStart("Building OpHolder Geometry..."); gdp->clearAndDestroy(); setParameterisedValues( now ); try { // make our Cortex op do it's thing... op->operate(); // pass ourselves onto the GR_Cortex render hook IECoreHoudini::NodePassData data( this, IECoreHoudini::NodePassData::CORTEX_OPHOLDER ); GA_RWAttributeRef attrRef = gdp->createAttribute( GA_ATTRIB_DETAIL, GA_SCOPE_PRIVATE, "IECoreHoudiniNodePassData", NULL, NULL, "blinddata" ); GA_Attribute *attr = attrRef.getAttribute(); const GA_AIFBlindData *blindData = attr->getAIFBlindData(); blindData->setDataSize( attr, sizeof(IECoreHoudini::NodePassData), &data ); // if our result is a visible renderable then set our bounds on our output gdp const IECore::Object *result = op->resultParameter()->getValue(); IECore::ConstVisibleRenderablePtr renderable = IECore::runTimeCast<const IECore::VisibleRenderable>( result ); if ( renderable ) { Imath::Box3f bbox = renderable->bound(); gdp->cube( bbox.min.x, bbox.max.x, bbox.min.y, bbox.max.y, bbox.min.z, bbox.max.z, 0, 0, 0, 1, 1 ); } } catch( boost::python::error_already_set ) { addError( SOP_MESSAGE, "Error raised during Python evaluation!" ); IECorePython::ScopedGILLock lock; PyErr_Print(); } catch( const IECore::Exception &e ) { addError( SOP_MESSAGE, e.what() ); } catch( const std::exception &e ) { addError( SOP_MESSAGE, e.what() ); } catch( ... ) { addError( SOP_MESSAGE, "Caught unknown exception!" ); } // tidy up & go home! boss->opEnd(); unlockInputs(); return error(); }