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); } } } }