/* ****************************************************************************** * Function Name : instancePoint() * * Description : Instance a point * * Input Arguments : GU_Detail *inst_gdp, GU_Detail *mb_gdp * * Return Value : int * ***************************************************************************** */ int VRAY_clusterThis::instancePoint(GU_Detail * inst_gdp, GU_Detail * mb_gdp) { #ifdef DEBUG std::cout << "VRAY_clusterThis::instancePoint()" << std::endl; #endif GEO_Point * ppt; ppt = inst_gdp->appendPointElement(); ppt->setPos((float)myPointAttributes.myNewPos[0], (float)myPointAttributes.myNewPos[1], (float)myPointAttributes.myNewPos[2], 1.0); VRAY_clusterThis::setPointInstanceAttributes(inst_gdp, ppt); if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) { ppt = mb_gdp->appendPointElement(); ppt->setPos((float)myPointAttributes.myMBPos[0], (float)myPointAttributes.myMBPos[1], (float)myPointAttributes.myMBPos[2], 1.0); VRAY_clusterThis::setPointInstanceAttributes(mb_gdp, ppt); } if(myCVEX_Exec) VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname, CLUSTER_CVEX_POINT); return 0; }
/* ****************************************************************************** * Function Name : instanceCube() * * Description : * * Input Arguments : GU_Detail *inst_gdp, GU_Detail *mb_gdp * * Return Value : int * ***************************************************************************** */ int VRAY_clusterThis::instanceCube(GU_Detail * inst_gdp, GU_Detail * mb_gdp) { #ifdef DEBUG std::cout << "VRAY_clusterThis::instanceCube()" << std::endl; #endif GEO_Primitive * myCube; GEO_Point * ppt; UT_Matrix4 xform(1.0); // UT_XformOrder xformOrder(UT_XformOrder::TRS, UT_XformOrder::XYZ); UT_Matrix3 rot_xform(1.0); // UT_Vector3 myDir = myPointAttributes.N; UT_Vector3 myUp = UT_Vector3(0,1,0); rot_xform.orient(myPointAttributes.N, myUp); xform = rot_xform; myCube = (GEO_Primitive *) inst_gdp->cube( myPointAttributes.myNewPos[0] - ((mySize[0] * myPointAttributes.pscale) / 2), myPointAttributes.myNewPos[0] + ((mySize[0] * myPointAttributes.pscale) / 2), myPointAttributes.myNewPos[1] - ((mySize[1] * myPointAttributes.pscale) / 2), myPointAttributes.myNewPos[1] + ((mySize[1] * myPointAttributes.pscale) / 2), myPointAttributes.myNewPos[2] - ((mySize[2] * myPointAttributes.pscale) / 2), myPointAttributes.myNewPos[2] + ((mySize[2] * myPointAttributes.pscale) / 2)); for(int i=0; i < myCube->getVertexCount(); i++) { ppt = myCube->getVertexElement(i).getPt(); UT_Vector4 P = ppt->getPos(); P *= xform; ppt->setPos(P); } VRAY_clusterThis::setInstanceAttributes(myCube); if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) { myCube = (GEO_Primitive *) mb_gdp->cube(myPointAttributes.myMBPos[0] - ((mySize[0] * myPointAttributes.pscale) / 2), myPointAttributes.myMBPos[0] + ((mySize[0] * myPointAttributes.pscale) / 2), myPointAttributes.myMBPos[1] - ((mySize[1] * myPointAttributes.pscale) / 2), myPointAttributes.myMBPos[1] + ((mySize[1] * myPointAttributes.pscale) / 2), myPointAttributes.myMBPos[2] - ((mySize[2] * myPointAttributes.pscale) / 2), myPointAttributes.myMBPos[2] + ((mySize[2] * myPointAttributes.pscale) / 2)); for(int i=0; i < myCube->getVertexCount(); i++) { ppt = myCube->getVertexElement(i).getPt(); UT_Vector4 P = ppt->getPos(); P *= xform; ppt->setPos(P); } VRAY_clusterThis::setInstanceAttributes(myCube); } if(myCVEX_Exec) VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname, CLUSTER_CVEX_POINT); if(myCVEX_Exec_prim) VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM); return 0; }
/* ****************************************************************************** * Function Name : instanceGrid() * * Description : Instance a grid * * Input Arguments : GU_Detail *inst_gdp, GU_Detail *mb_gdp * * Return Value : int * ***************************************************************************** */ int VRAY_clusterThis::instanceGrid(GU_Detail * inst_gdp, GU_Detail * mb_gdp) { #ifdef DEBUG std::cout << "VRAY_clusterThis::instanceGrid()" << std::endl; #endif GEO_Primitive * myGrid; GU_GridParms grid_parms; UT_XformOrder xformOrder(UT_XformOrder::TRS, UT_XformOrder::XYZ); UT_Matrix4 xform(1.0); xform.rotate(myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2], xformOrder); grid_parms.rows = 2; grid_parms.cols = 2; grid_parms.xsize = mySize[0] * myPointAttributes.pscale; grid_parms.ysize = mySize[1] * myPointAttributes.pscale; grid_parms.xcenter = myPointAttributes.myNewPos[0]; grid_parms.ycenter = myPointAttributes.myNewPos[1]; grid_parms.zcenter = myPointAttributes.myNewPos[2]; grid_parms.plane = GU_PLANE_XY; myGrid = inst_gdp->buildGrid(grid_parms, GU_GRID_POLY); for(int i = 0; i < myGrid->getVertexCount(); i++) { GEO_Point * ppt = myGrid->getVertexElement(i).getPt(); UT_Vector4 P = ppt->getPos(); P *= xform; ppt->setPos(P); } VRAY_clusterThis::setInstanceAttributes(myGrid); if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) { grid_parms.xcenter = myPointAttributes.myMBPos[0]; grid_parms.ycenter = myPointAttributes.myMBPos[1]; grid_parms.zcenter = myPointAttributes.myMBPos[2]; myGrid = mb_gdp->buildGrid(grid_parms, GU_GRID_POLY); for(int i = 0; i < myGrid->getVertexCount(); i++) { GEO_Point * ppt = myGrid->getVertexElement(i).getPt(); UT_Vector4 P = ppt->getPos(); P *= xform; ppt->setPos(P); } VRAY_clusterThis::setInstanceAttributes(myGrid); } if(myCVEX_Exec) VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname, CLUSTER_CVEX_POINT); if(myCVEX_Exec_prim) VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM); return 0; }
/* ****************************************************************************** * Function Name : setFileAttributes() * * Description : * * Input Arguments : GEO_Point *ppt, GU_Detail *inst_gdp * * Return Value : int * ***************************************************************************** */ inline int VRAY_clusterThis::setFileAttributes(GU_Detail * file_gdp) { #ifdef DEBUG cout << "VRAY_clusterThis::setFileAttributes() " << endl; #endif GEO_Point * ppt; #ifdef DEBUG long int num_points = (long int) file_gdp->points().entries(); cout << "VRAY_clusterThis::setFileAttributes() - num points :" << num_points << endl; #endif // NOTE: File instanced geo should have normals already, do not set the normals to the source point normals GA_FOR_ALL_GPOINTS(file_gdp, ppt) { ppt->setValue<UT_Vector3>(myFileAttrOffsets.Cd, (const UT_Vector3)myPointAttributes.Cd); ppt->setValue<float>(myFileAttrOffsets.Alpha, (const float)myPointAttributes.Alpha); ppt->setValue<UT_Vector3>(myFileAttrOffsets.pointV, (const UT_Vector3)myPointAttributes.v); ppt->setValue<int>(myFileAttrOffsets.pointId, (const int)myPointAttributes.id); ppt->setString(myFileAttrOffsets.material, myPointAttributes.material); }
/* ****************************************************************************** * Function Name : setInstanceAttributes() * * Description : Set the attributes of the instanced primitive * * Input Arguments : GEO_Primitive *myGeoPrim * * Return Value : void * ***************************************************************************** */ inline void VRAY_clusterThis::setInstanceAttributes(GEO_Primitive * myGeoPrim) { #ifdef DEBUG cout << "VRAY_clusterThis::setInstanceAttributes() " << endl; #endif GEO_Point * ppt; myGeoPrim->setValue<UT_Vector3>(myInstAttrRefs.Cd, (const UT_Vector3)myPointAttributes.Cd); myGeoPrim->setValue<fpreal>(myInstAttrRefs.Alpha, (const fpreal)myPointAttributes.Alpha); myGeoPrim->setValue<UT_Vector3>(myInstAttrRefs.v, (const UT_Vector3)myPointAttributes.v); myGeoPrim->setValue<UT_Vector3>(myInstAttrRefs.N, (const UT_Vector3)myPointAttributes.N); // myGeoPrim->setValue<UT_Vector4>(myInstAttrRefs.orient (const UT_Vector4)myPointAttributes.orient); myGeoPrim->setValue<fpreal>(myInstAttrRefs.pscale, (const fpreal)myPointAttributes.pscale); myGeoPrim->setValue<int>(myInstAttrRefs.id, (const int)myPointAttributes.id); myGeoPrim->setValue<int>(myInstAttrRefs.inst_id, (const int)myInstanceNum); myGeoPrim->setValue<fpreal>(myInstAttrRefs.weight, (const fpreal)myPointAttributes.weight); myGeoPrim->setValue<fpreal>(myInstAttrRefs.width, (const fpreal)myPointAttributes.width); myGeoPrim->setString(myInstAttrRefs.material, myPointAttributes.material); // apply attribues to each vertex for (int i=0; i < myGeoPrim->getVertexCount(); i++) { ppt = myGeoPrim->getVertexElement(i).getPt(); ppt->setValue<UT_Vector3>(myInstAttrRefs.pointCd, (const UT_Vector3)myPointAttributes.Cd); ppt->setValue<float>(myInstAttrRefs.pointAlpha, (const float)myPointAttributes.Alpha); ppt->setValue<UT_Vector3>(myInstAttrRefs.pointV, (const UT_Vector3)myPointAttributes.v); ppt->setValue<UT_Vector3>(myInstAttrRefs.pointN, (const UT_Vector3)myPointAttributes.N); ppt->setValue<float>(myInstAttrRefs.pointPscale, (const float)myPointAttributes.pscale); ppt->setValue<int>(myInstAttrRefs.pointId, (const int)myPointAttributes.id); ppt->setValue<int>(myInstAttrRefs.pointInstId, (const int)myInstanceNum); ppt->setString(myInstAttrRefs.pointMaterial, myPointAttributes.material); } }
/* ****************************************************************************** * Function Name : runCVEX() * * Description : Run VEX code on the instanced geometry from an external .vex file * * Input Arguments : GU_Detail *inst_gdp, GU_Detail *mb_gdp * * Return Value : int * ***************************************************************************** */ int VRAY_clusterThis::runCVEX(GU_Detail * inst_gdp, GU_Detail * mb_gdp, UT_String theCVEXFname, uint method) { if (myVerbose == CLUSTER_MSG_DEBUG) { std::cout << "VRAY_clusterThis::runCVEX() - Processing CVEX arrays - points: " << inst_gdp->points().entries() << " primitives: " << inst_gdp->primitives().entries() << std::endl; } UT_Vector3 * P = NULL, *POut = NULL, *N = NULL, *NOut = NULL, *v = NULL, *vOut = NULL, *Cd = NULL, *CdOut = NULL; fpreal * weight = NULL, *weightOut = NULL, *Alpha = NULL, *AlphaOut = NULL, *pscale = NULL, *pscaleOut = NULL; int * id = NULL, *inst_id = NULL; // helper local class to clean up memory class cleanUpCVEXMem { public: void cleanUp(UT_Vector3 * P, UT_Vector3 * POut, UT_Vector3 * N, UT_Vector3 * NOut, UT_Vector3 * v, UT_Vector3 * vOut, UT_Vector3 * Cd, UT_Vector3 * CdOut, fpreal * weight, fpreal * weightOut, fpreal * Alpha, fpreal * AlphaOut, fpreal * pscale, fpreal * pscaleOut, int * id, int * inst_id) { if (P) delete []P; if (POut) delete []POut; if (Cd) delete []Cd; if (CdOut) delete []CdOut; if (Alpha) delete []Alpha; if (AlphaOut) delete []AlphaOut; if (N) delete []N; if (NOut) delete []NOut; if (v) delete []v; if (vOut) delete []vOut; if (pscale) delete []pscale; if (pscaleOut) delete []pscaleOut; if (weight) delete []weight; if (weightOut) delete []weightOut; if (id) delete []id; if (inst_id) delete []inst_id; return; }; } memCleaner; try { uint32 num_inst = 0, num_points = 0, num_prim = 0; long int num = 0; GEO_Point * ppt; GEO_Primitive * prim; UT_Vector4 pos; CVEX_Context cvex; GU_Detail * cvex_gdp; uint32 num_passes = 1; uint32 mb_pass = 0; fpreal time = myCurrentTime; // std::cout << "VRAY_clusterThis::runCVEX() - time: " << time << endl; if (myDoMotionBlur == CLUSTER_MB_DEFORMATION) num_passes = 2; if (myPrimType == CLUSTER_POINT) { num_inst = myInstanceNum; // num_inst = inst_gdp->points().entries(); num_points = inst_gdp->points().entries(); // std::cout << "VRAY_clusterThis::runCVEX() - num_inst: " << num_inst << std::endl; } else { num_inst = myInstanceNum; num_prim = inst_gdp->primitives().entries(); num_points = inst_gdp->points().entries(); num_inst = num_points; // std::cout << "VRAY_clusterThis::runCVEX() - num_inst: " << num_inst << " num_points: " << num_points << " num_prim: " << num_prim << std::endl; } UT_Vector3 primAttr, ptAttr; GA_RWAttributeRef primN_ref, primV_ref, primCd_ref, primAlpha_ref, primPscale_ref, primId_ref, primWeight_ref; GA_RWAttributeRef ptN_ref, ptV_ref, ptCd_ref, ptAlpha_ref, ptPscale_ref, ptId_ref, ptInstId_ref; if (myPrimType == CLUSTER_POINT) { // Allocate the space for the point positions P = new UT_Vector3[num_points]; POut = new UT_Vector3[num_points]; if (myCVEXPointVars.cvex_Cd_pt) { Cd = new UT_Vector3[num_points]; CdOut = new UT_Vector3[num_points]; } if (myCVEXPointVars.cvex_Alpha_pt) { Alpha = new fpreal[num_points]; AlphaOut = new fpreal[num_points]; } if (myCVEXPointVars.cvex_N_pt) { N = new UT_Vector3[num_points]; NOut = new UT_Vector3[num_points]; } if (myCVEXPointVars.cvex_v_pt) { v = new UT_Vector3[num_points]; vOut = new UT_Vector3[num_points]; } if (myCVEXPointVars.cvex_pscale_pt) { pscale = new fpreal[num_points]; pscaleOut = new fpreal[num_points]; } id = new int[num_points]; inst_id = new int[num_points]; } else { // If we're processing the points of the prims, allocate the space if (method == CLUSTER_CVEX_POINT) { P = new UT_Vector3[num_points]; POut = new UT_Vector3[num_points]; // Allocate space for the id and inst_id attr's id = new int[num_points]; inst_id = new int[num_points]; } // Else we're working on primitives, so allocate sace for the attrs the user wants to CVEX! else { if (myCVEXPrimVars.cvex_Cd_prim) { Cd = new UT_Vector3[num_prim]; CdOut = new UT_Vector3[num_prim]; } if (myCVEXPrimVars.cvex_Alpha_prim) { Alpha = new fpreal[num_prim]; AlphaOut = new fpreal[num_prim]; } if (myCVEXPrimVars.cvex_N_prim) { N = new UT_Vector3[num_prim]; NOut = new UT_Vector3[num_prim]; } if (myCVEXPrimVars.cvex_v_prim) { v = new UT_Vector3[num_prim]; vOut = new UT_Vector3[num_prim]; } if (myCVEXPrimVars.cvex_pscale_prim) { pscale = new fpreal[num_prim]; pscaleOut = new fpreal[num_prim]; } if (myPrimType == VRAY_clusterThis::CLUSTER_PRIM_METABALL && myCVEXPrimVars.cvex_weight_prim) { weight = new fpreal[num_prim]; weightOut = new fpreal[num_prim]; } // Allocate space for the id and inst_id attr's id = new int[num_prim]; inst_id = new int[num_prim]; } } // Retrieve the attribute offsets for (uint32 pass = 0; pass < num_passes; pass++) { if (pass == 0) { cvex_gdp = inst_gdp; mb_pass = 0; } else { cvex_gdp = mb_gdp; mb_pass = 1; } if (myPrimType == CLUSTER_POINT) { if (myCVEXPointVars.cvex_Cd_pt) { ptCd_ref = cvex_gdp->findDiffuseAttribute(GEO_POINT_DICT); } if (myCVEXPointVars.cvex_Alpha_pt) { ptAlpha_ref = cvex_gdp->findFloatTuple(GA_ATTRIB_POINT, "Alpha", 1); } if (myCVEXPointVars.cvex_N_pt) { ptN_ref = cvex_gdp->findNormalAttribute(GEO_POINT_DICT); } if (myCVEXPointVars.cvex_v_pt) { ptV_ref = cvex_gdp->findVelocityAttribute(GEO_POINT_DICT); } if (myCVEXPointVars.cvex_pscale_pt) { ptPscale_ref = cvex_gdp->findFloatTuple(GA_ATTRIB_POINT, "pscale", 1); } ptId_ref = cvex_gdp->findIntTuple(GA_ATTRIB_POINT, "id", 1); ptInstId_ref = cvex_gdp->findIntTuple(GA_ATTRIB_POINT, "inst_id", 1); } else { // If we're not processing the points of the prims, get the attr's offset for the attrs the user wants to use if (method != CLUSTER_CVEX_POINT) { if (myCVEXPrimVars.cvex_Cd_prim) { primCd_ref = cvex_gdp->findDiffuseAttribute(GEO_PRIMITIVE_DICT); } if (myCVEXPrimVars.cvex_Alpha_prim) { primAlpha_ref = cvex_gdp->findFloatTuple(GA_ATTRIB_POINT, "Alpha", 1); } if (myCVEXPrimVars.cvex_N_prim) { primN_ref = cvex_gdp->findFloatTuple(GA_ATTRIB_POINT, "N", 3); // primN_ref = cvex_gdp->findNormalAttribute ( GEO_PRIMITIVE_DICT ); } if (myCVEXPrimVars.cvex_v_prim) { primV_ref = cvex_gdp->findVelocityAttribute(GEO_PRIMITIVE_DICT); } if (myCVEXPrimVars.cvex_pscale_prim) { ptPscale_ref = cvex_gdp->findFloatTuple(GA_ATTRIB_POINT, "pscale", 1); } if (myPrimType == VRAY_clusterThis::CLUSTER_PRIM_METABALL && myCVEXPrimVars.cvex_weight_prim) { primWeight_ref = cvex_gdp->findFloatTuple(GA_ATTRIB_POINT, "weight", 1); } } // Get the offset for id attr ptId_ref = cvex_gdp->findIntTuple(GA_ATTRIB_POINT, "id", 1); ptInstId_ref = cvex_gdp->findIntTuple(GA_ATTRIB_POINT, "inst_id", 1); } #ifdef DEBUG std::cout << "VRAY_clusterThis::runCVEX() - Retrieved attribute offsets" << std::endl; #endif // Set the values of the incoming arrays if (myPrimType == CLUSTER_POINT) { num = 0; GA_FOR_ALL_GPOINTS(cvex_gdp, ppt) { pos = ppt->getPos(); P[num][0] = pos.x(); P[num][1] = pos.y(); P[num][2] = pos.z(); // P[num] = ppt->getPos(); id[num] = static_cast<int>(ppt->getValue<int>(ptId_ref, 0)); if (ptInstId_ref.isValid()) inst_id[num] = static_cast<int>(ppt->getValue<int>(ptInstId_ref, 0)); else inst_id[num] = id[num]; // cout << "IN - id : " << id[num] << "\tinst_id " << inst_id[num] << "\tnum " << num << endl; ++num; } if (myCVEXPointVars.cvex_Cd_pt) { num = 0; GA_FOR_ALL_GPOINTS(cvex_gdp, ppt) { ptAttr = static_cast<UT_Vector3>(ppt->getValue<UT_Vector3>(ptCd_ref, 0)); Cd[num][0] = ptAttr.x(); Cd[num][1] = ptAttr.y(); Cd[num][2] = ptAttr.z(); // cout << "IN - Cd: " << Cd[num] << endl; ++num; } }
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; }
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(); }
void GR_rmanPtc::renderWire( GU_Detail *gdp, RE_Render &ren, const GR_AttribOffset &ptinfo, const GR_DisplayOption *dopt, float lod, const GU_PrimGroupClosure *hidden_geometry ) { int i, nprim; GEO_Primitive *prim; UT_Vector3 v3; rmanPtcSop::rmanPtcDetail *detail = dynamic_cast<rmanPtcSop::rmanPtcDetail*>(gdp); if ( !detail ) return; // rebuild our display list if ( detail->redraw ) { srand(0); GEO_PointList &points = detail->points(); int display_channel = detail->display_channel; // render as points GEO_Point *pt = 0; UT_Vector4 pos; float col[3] = {1.0,1.0,1.0}; if ( !detail->use_disk ) { ren.pushPointSize(detail->point_size); ren.beginPoint(); } for ( unsigned int i=0; i<points.entries(); ++i ) { if ( rand()/(float)RAND_MAX<=detail->display_probability ) { // point position pt = points[i]; pos = pt->getPos(); // display colour float *ptr = NULL; if (detail->attributes.size() >0) { ptr = pt->castAttribData<float>( detail->attributes[display_channel] ); if (ptr) { if ( detail->attribute_size[display_channel]==1) col[0] = col[1] = col[2] = ptr[0]; else { col[0] = ptr[0]; col[1] = ptr[1]; col[2] = ptr[2]; } } } // draw point if ( !detail->use_cull_bbox || detail->cull_bbox.isInside( pos ) ) { if ( !detail->use_disk ) { // render as points ren.setColor( col[0], col[1], col[2], 1 ); ren.vertex3DW( pos.x(), pos.y(), pos.z() ); } else { // render as disks UT_Vector3 n = *pt->castAttribData<UT_Vector3>(detail->N_attrib); float r = *pt->castAttribData<float>(detail->R_attrib); n.normalize(); UT_Vector3 ref(1,0,0); UT_Vector3 up = ref; up.cross(n); up.normalize(); UT_Vector3 right = up; right.cross(n); right.normalize(); UT_DMatrix4 mat( right.x(), right.y(), right.z(), 0, up.x(), up.y(), up.z(), 0, n.x(), n.y(), n.z(), 0, pos.x(), pos.y(), pos.z(), 1 ); ren.pushMatrix(); ren.multiplyMatrix(mat); ren.pushColor( UT_Color( UT_RGB, col[0], col[1], col[2] ) ); ren.circlefW( 0, 0, detail->point_size * r, 8 ); ren.popColor(); ren.popMatrix(); } } } } if ( !detail->use_disk ) { ren.endPoint(); } } }
OP_ERROR SOP_CudaParticles::cookMySop(OP_Context &context) { oldf = f; f = context.getFrame(); GEO_ParticleVertex* pvtx; double t = context.getTime(); particlesSystem->dt = 1/(OPgetDirector()->getChannelManager()->getSamplesPerSec() * SUBSTEPS(t)); particlesSystem->preview = PREVIEW(t); particlesSystem->partsLife = LIFE(t); particlesSystem->partsLifeVar = LIFEVAR(t); particlesSystem->velDamp = VELDAMP(t); particlesSystem->gravityStrength = GRAVITYSTR(t); particlesSystem->gravityDir = cu::make_float3(GRAVITYX(t),GRAVITYY(t),GRAVITYZ(t)); particlesSystem->fluidStrength = FLUIDSTR(t); particlesSystem->noiseAmp = cu::make_float3(NOISEAMP(t),NOISEAMP(t),NOISEAMP(t)); particlesSystem->noiseOct = NOISEOCT(t); particlesSystem->noiseFreq = NOISEFREQ(t); particlesSystem->noiseLac = NOISELACUN(t); particlesSystem->noiseOffset = cu::make_float3(NOISEOFFSETX(t),NOISEOFFSETY(t),NOISEOFFSETZ(t)); particlesSystem->pointSize = POINTSIZE(t); particlesSystem->opacity = OPACITY(t); particlesSystem->startColor = cu::make_float3(STARTCOLORX(t),STARTCOLORY(t),STARTCOLORZ(t)); particlesSystem->endColor = cu::make_float3(ENDCOLORX(t),ENDCOLORY(t),ENDCOLORZ(t)); UT_Interrupt *boss; OP_Node::flags().timeDep = 1; if (error() < UT_ERROR_ABORT) { boss = UTgetInterrupt(); // Start the interrupt server if (boss->opStart("Building Particles")){ //gdp->clearAndDestroy(); static float zero = 0.0; GB_AttributeRef partsAtt = gdp->addAttrib("cudaParticlesPreview", sizeof(int), GB_ATTRIB_INT, &zero); gdp->attribs().getElement().setValue<int>(partsAtt, particlesSystem->preview); GB_AttributeRef systemIdAtt = gdp->addAttrib("systemId", sizeof(int), GB_ATTRIB_INT, &zero); gdp->attribs().getElement().setValue<int>(systemIdAtt, particlesSystem->id); if (f < STARTFRAME(t)) { gdp->clearAndDestroy(); particlesSystem->resetParticles(); } else if (f == STARTFRAME(t)) { gdp->clearAndDestroy(); particlesSystem->resetParticles(); int maxParts = MAXPARTS(t); if (particlesSystem->nParts!=maxParts) particlesSystem->changeMaxParts(maxParts); //hSystem = (GEO_PrimParticle *)gdp->appendPrimitive(GEOPRIMPART); //hSystem->clearAndDestroy(); GB_AttributeRef hVelocity = gdp->addPointAttrib("v", sizeof(UT_Vector3),GB_ATTRIB_VECTOR, 0); GB_AttributeRef hLife = gdp->addPointAttrib("life", sizeof(float)*2,GB_ATTRIB_FLOAT, 0); if(particlesSystem->preview!=1) { UT_Vector4 orig = UT_Vector4(0,0,0,1); for (int i = 0; i<particlesSystem->nParts; i++) { GEO_Point* newPoint = gdp->appendPoint(); newPoint->setPos(orig); /*pvtx = hSystem->giveBirth(); GEO_Point* ppt = pvtx->getPt(); //ppt->getPos().assign(0,0,0,1);*/ hSystemInit = 1; } } } else { if(particlesSystem->nParts != -1) { 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 != particlesSystem->nEmit) { delete particlesSystem->emitters; particlesSystem->nEmit = numEmitters; particlesSystem->emitters = new ParticlesEmitter[numEmitters]; } GEO_AttributeHandle radAh, amountAh; GEO_AttributeHandle initVelAh, radVelAmpAh, noiseVelAmpAh, noiseVelOffsetAh, noiseVelOctAh, noiseVelLacAh, noiseVelFreqAh; radAh = emittersInput->getPointAttribute("radius"); amountAh = emittersInput->getPointAttribute("amount"); initVelAh = emittersInput->getPointAttribute("initVel"); radVelAmpAh = emittersInput->getPointAttribute("radVelAmp"); noiseVelAmpAh = emittersInput->getPointAttribute("noiseVelAmp"); noiseVelOffsetAh = emittersInput->getPointAttribute("noiseVelOffset"); noiseVelOctAh = emittersInput->getPointAttribute("noiseVelOct"); noiseVelLacAh = emittersInput->getPointAttribute("noiseVelLac"); noiseVelFreqAh = emittersInput->getPointAttribute("noiseVelFreq"); for (int i = 0; i < numEmitters; i++) { UT_Vector4 emitPos = emittersList[i]->getPos(); UT_Vector3 emitPos3(emitPos); particlesSystem->emitters[i].posX = emitPos.x(); particlesSystem->emitters[i].posY = emitPos.y(); particlesSystem->emitters[i].posZ = emitPos.z(); radAh.setElement(emittersList[i]); amountAh.setElement(emittersList[i]); initVelAh.setElement(emittersList[i]); radVelAmpAh.setElement(emittersList[i]); noiseVelAmpAh.setElement(emittersList[i]); noiseVelOffsetAh.setElement(emittersList[i]); noiseVelOctAh.setElement(emittersList[i]); noiseVelLacAh.setElement(emittersList[i]); noiseVelFreqAh.setElement(emittersList[i]); particlesSystem->emitters[i].radius = radAh.getF(0); particlesSystem->emitters[i].amount = amountAh.getF(0); particlesSystem->emitters[i].velX = initVelAh.getF(0); particlesSystem->emitters[i].velY = initVelAh.getF(1); particlesSystem->emitters[i].velZ = initVelAh.getF(2); particlesSystem->emitters[i].radVelAmp = radVelAmpAh.getF(0); particlesSystem->emitters[i].noiseVelAmpX = noiseVelAmpAh.getF(0); particlesSystem->emitters[i].noiseVelAmpY = noiseVelAmpAh.getF(1); particlesSystem->emitters[i].noiseVelAmpZ = noiseVelAmpAh.getF(2); particlesSystem->emitters[i].noiseVelOffsetX = noiseVelOffsetAh.getF(0); particlesSystem->emitters[i].noiseVelOffsetY = noiseVelOffsetAh.getF(1); particlesSystem->emitters[i].noiseVelOffsetZ = noiseVelOffsetAh.getF(2); particlesSystem->emitters[i].noiseVelOct = noiseVelOctAh.getF(0); particlesSystem->emitters[i].noiseVelLac = noiseVelLacAh.getF(0); particlesSystem->emitters[i].noiseVelFreq = noiseVelFreqAh.getF(0); } } else { particlesSystem->nEmit = 0; } if(getInput(1)){ GU_Detail* fluidInput = (GU_Detail*)inputGeo(1, context); GEO_AttributeHandle fluidIdAh= fluidInput->getDetailAttribute("solverId"); fluidIdAh.setElement(fluidInput); int sId = fluidIdAh.getI(); VHFluidSolver3D* curr3DSolver = VHFluidSolver3D::solverList[sId]; particlesSystem->fluidSolver = curr3DSolver; } unlockInputs(); if (f!=oldf) { particlesSystem->emitParticles(); particlesSystem->updateParticles(); } if(particlesSystem->preview!=1 && hSystemInit == 1) { cu::cudaMemcpy( particlesSystem->host_pos, particlesSystem->dev_pos, particlesSystem->nParts*sizeof(cu::float3), cu::cudaMemcpyDeviceToHost ); GEO_Point* ppt; int i = 0; UT_Vector4 p; FOR_ALL_GPOINTS(gdp, ppt) { ppt->getPos() = UT_Vector4(particlesSystem->host_pos[i*3], particlesSystem->host_pos[i*3+1], particlesSystem->host_pos[i*3+2], 1); i++; } /*pvtx = hSystem->iterateInit(); for (int i =0; i<particlesSystem->nParts; i++){ pvtx->getPos().assign(particlesSystem->host_pos[i*3], particlesSystem->host_pos[i*3+1], particlesSystem->host_pos[i*3+2], 1); pvtx = hSystem->iterateFastNext(pvtx); }*/ } } }
/* ****************************************************************************** * Function Name : render() * * Description : Render VRAY_clusterThis object * * Input Arguments : None * * Return Value : None * ***************************************************************************** */ void VRAY_clusterThis::render() { GU_Detail * gdp, *inst_gdp, *mb_gdp, *file_gdp; GEO_Point * ppt; // GEO_AttributeHandle attrHandleVelocity, attrHandleForce, attrHandleVorticity, attrHandleNormal, attrHandleNumNeighbors, // attrHandleTextureUV, attrHandleMass, attrHandleAge, attrHandleTemperature, attrHandleID, // attrHandleDensity, attrHandleViscosity, attrHandlePressure, attrHandlePscale; long int point_num = 0; static bool rendered = false; if(myVerbose > CLUSTER_MSG_QUIET) { std::cout << "VRAY_clusterThis::render() - Version: " << DCA_VERSION << std::endl; std::cout << "VRAY_clusterThis::render() - Built for Houdini Version: " << UT_MAJOR_VERSION << "." << UT_MINOR_VERSION << "." << UT_BUILD_VERSION_INT << std::endl; std::cout << "VRAY_clusterThis::render() - Instancing ..." << endl; } try { // cout << "VM_GEO_clusterThis OTL version: " << myOTLVersion << endl; // if(myOTLVersion != DCA_VERSION) { // cout << "VM_GEO_clusterThis OTL is wrong version: " << myOTLVersion << ", should be version: " << DCA_VERSION << ", please install correct version." << endl; // throw VRAY_clusterThis_Exception ( "VRAY_clusterThis::render() VM_GEO_clusterThis OTL is wrong version!", 1 ); // } if(!rendered || !myUseTempFile) { void * handle = VRAY_Procedural::queryObject(0); gdp = VRAY_Procedural::allocateGeometry(); if(myUseGeoFile) { // If the file failed to load, throw an exception if(!(gdp->load((const char *)mySrcGeoFname).success())) throw VRAY_clusterThis_Exception("VRAY_clusterThis::render() - Failed to read source geometry file ", 1); if(myVerbose > CLUSTER_MSG_INFO) cout << "VRAY_clusterThis::render() - Successfully loaded source geo file: " << mySrcGeoFname << endl; } else { gdp->copy(*VRAY_Procedural::queryGeometry(handle, 0)); if(myVerbose > CLUSTER_MSG_INFO) cout << "VRAY_clusterThis::render() - Copied incoming geometry" << endl; } gdp->getBBox(&myBox); // std::cout << "VRAY_clusterThis::render() - gdp->getBBox(&myBox): " << myBox << std::endl; VRAY_Procedural::querySurfaceShader(handle, myMaterial); myMaterial.harden(); // myPointAttributes.material = myMaterial; // const char ** getSParm (int token) const // cout << "VRAY_clusterThis::render() getSParm: " << *getSParm (0) << endl; #ifdef DEBUG cout << "VRAY_clusterThis::render() myMaterial: " << myMaterial << endl; #endif myLOD = getLevelOfDetail(myBox); if(myVerbose > CLUSTER_MSG_INFO) cout << "VRAY_clusterThis::render() myLOD: " << myLOD << endl; // Get the number if points of the incoming geometery, calculate an interval for reporting the status of the instancing to the user long int num_points = (long int) gdp->points().entries(); long int stat_interval = (long int)(num_points * 0.10) + 1; if(myVerbose > CLUSTER_MSG_QUIET) cout << "VRAY_clusterThis::render() Number of points of incoming geometry: " << num_points << endl; myObjectName = VRAY_Procedural::queryObjectName(handle); // cout << "VRAY_clusterThis::render() Object Name: " << myObjectName << endl; // cout << "VRAY_clusterThis::render() Root Name: " << queryRootName() << endl; // DEBUG stuff ... // changeSetting("object:geo_velocityblur", "on"); UT_String str; int vblur = 0; import("object:velocityblur", &vblur, 0); if(vblur) { str = 0; import("velocity", str); if(str.isstring()) { // const char * name; // name = queryObjectName(handle); VRAYwarning("%s[%s] cannot get %s", VRAY_Procedural::getClassName(), (const char *)myObjectName, " motion blur attr"); } } myXformInverse = queryTransform(handle, 0); myXformInverse.invert(); #ifdef DEBUG cout << "Geometry Samples: " << queryGeometrySamples(handle) << endl; // cout << "scale: " << getFParm ( "scale" ) << endl; #endif // Dump the user parameters to the console if(myVerbose == CLUSTER_MSG_DEBUG) VRAY_clusterThis::dumpParameters(); switch(myMethod) { case CLUSTER_INSTANCE_NOW: inst_gdp = VRAY_Procedural::allocateGeometry(); if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) mb_gdp = VRAY_Procedural::allocateGeometry(); if(myVerbose > CLUSTER_MSG_QUIET) cout << "VRAY_clusterThis::render() - Using \"instance all the geometry at once\" method" << endl; break; case CLUSTER_INSTANCE_DEFERRED: if(myVerbose > CLUSTER_MSG_QUIET) cout << "VRAY_clusterThis::render() - Using \"addProcedural()\" method" << endl; break; } rendered = true; // Get the point's attribute offsets VRAY_clusterThis::getAttributeOffsets(gdp); // Check for required attributes VRAY_clusterThis::checkRequiredAttributes(); // Check for weight attribute if the user wants metaballs if((myPrimType == CLUSTER_PRIM_METABALL) && (myPointAttrOffsets.weight.isInvalid())) { cout << "Incoming points must have weight attribute if instancing metaballs! Throwing exception ..." << endl; throw VRAY_clusterThis_Exception("VRAY_clusterThis::render() Incoming points must have weight attribute if instancing metaballs!", 1); } if(myPrimType == CLUSTER_FILE) { file_gdp = VRAY_Procedural::allocateGeometry(); int file_load_stat = VRAY_clusterThis::preLoadGeoFile(file_gdp); if(!file_load_stat) { // myFileGDP = file_gdp; if(myVerbose > CLUSTER_MSG_INFO) cout << "VRAY_clusterThis::render() Successfully loaded geometry file: " << myGeoFile << endl; } else { throw VRAY_clusterThis_Exception("VRAY_clusterThis::render() Failed to load geometry file ", 1); } } // init some vars ... myPointAttributes.Cd = (UT_Vector3(1, 1, 1)); myPointAttributes.v = (UT_Vector3(0, 0, 0)); myPointAttributes.N = (UT_Vector3(0, 1, 0)); myPointAttributes.Alpha = 1.0; myPointAttributes.pscale = 1.0; myPointAttributes.id = 0; myNoise.initialize(myNoiseSeed, myNoiseType); // Create the attribute "offsets" for the geometry to be instanced VRAY_clusterThis::createAttributeOffsets(inst_gdp, mb_gdp); //changeSetting("surface", "constant Cd ( 1 0 0 )", "object"); fpreal theta = (2.0 * M_PI) / myNumCopies; myInstanceNum = 0; if(myCVEX_Exec_pre) { if(myVerbose > CLUSTER_MSG_INFO) cout << "VRAY_clusterThis::render() Executing Pre Process CVEX code" << endl; VRAY_clusterThis::runCVEX(gdp, gdp, myCVEXFname_pre, CLUSTER_CVEX_POINT); } /// For each point of the incoming geometry GA_FOR_ALL_GPOINTS(gdp, ppt) { myPointAttributes.myPos = ppt->getPos(); // get the point's attributes VRAY_clusterThis::getAttributes(ppt, gdp); #ifdef DEBUG cout << "VRAY_clusterThis::render() " << "theta: " << theta << endl; #endif uint seed = 37; fpreal dice; bool skip = false; if((myPrimType != CLUSTER_PRIM_CURVE) || ((myMethod == CLUSTER_INSTANCE_DEFERRED && (myPrimType == CLUSTER_PRIM_CURVE)))) { // For each point, make a number of copies of and recurse a number of times for each copy ... for(int copyNum = 0; copyNum < myNumCopies; copyNum++) { for(int recursionNum = 0; recursionNum < myRecursion; recursionNum++) { // generate random number to determine to instance or not dice = SYSfastRandom(seed); (dice > myBirthProb)?skip = true:skip = false; // cout << dice << " " << skip << endl; seed = uint(dice * 100); // Calculate the position for the next instanced object ... VRAY_clusterThis::calculateNewPosition(theta, copyNum, recursionNum); if(!skip) { // Instance an object ... switch(myMethod) { // For the "create all geometry at once" method, instance the object now ... case CLUSTER_INSTANCE_NOW: // Create a primitive based upon user's selection // TODO: can later be driven by a point attribute switch(myPrimType) { case CLUSTER_POINT: VRAY_clusterThis::instancePoint(inst_gdp, mb_gdp); break; case CLUSTER_PRIM_SPHERE: VRAY_clusterThis::instanceSphere(inst_gdp, mb_gdp); break; case CLUSTER_PRIM_CUBE: VRAY_clusterThis::instanceCube(inst_gdp, mb_gdp); break; case CLUSTER_PRIM_GRID: VRAY_clusterThis::instanceGrid(inst_gdp, mb_gdp); break; case CLUSTER_PRIM_TUBE: VRAY_clusterThis::instanceTube(inst_gdp, mb_gdp); break; case CLUSTER_PRIM_CIRCLE: VRAY_clusterThis::instanceCircle(inst_gdp, mb_gdp); break; case CLUSTER_PRIM_METABALL: VRAY_clusterThis::instanceMetaball(inst_gdp, mb_gdp); break; case CLUSTER_FILE: VRAY_clusterThis::instanceFile(file_gdp, inst_gdp, mb_gdp); break; // In case a instance type comes through that's not "legal", throw exception default: throw VRAY_clusterThis_Exception("VRAY_clusterThis::render() Illegal instance type, exiting ...", 1); break; } break; // For the "deferred instance" method, add the procedural now ... case CLUSTER_INSTANCE_DEFERRED: VRAY_Procedural::openProceduralObject(); VRAY_clusterThisChild * child = new VRAY_clusterThisChild::VRAY_clusterThisChild(this); VRAY_Procedural::addProcedural(child); VRAY_Procedural::changeSetting("object:geo_velocityblur", "on"); VRAY_Procedural::closeObject(); //changeSetting("surface", "constant Cd ( 1 0 0 )", "object"); // changeSetting("object:geo_velocityblur", "on"); break; } myInstanceNum++; #ifdef DEBUG cout << "VRAY_clusterThis::render() - myInstanceNum: " << myInstanceNum << std::endl; #endif } } // for number of recursions ... } // for number of copies ... } // User wants a curve instanced on this point if((myPrimType == CLUSTER_PRIM_CURVE) && (myMethod == CLUSTER_INSTANCE_NOW) && (!skip)) VRAY_clusterThis::instanceCurve(inst_gdp, mb_gdp, theta, point_num); // Increment our point counter point_num++; // Print out stats to the console if(myVerbose > CLUSTER_MSG_INFO && (myPrimType != CLUSTER_PRIM_CURVE)) if((long int)(point_num % stat_interval) == 0) cout << "VRAY_clusterThis::render() Number of points processed: " << point_num << " Number of instances: " << myInstanceNum << endl; } // for all points ... if(myVerbose > CLUSTER_MSG_QUIET) if(myMethod == CLUSTER_INSTANCE_NOW) if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) cout << "VRAY_clusterThis::render() - Memory usage(MB): " << (fpreal)(inst_gdp->getMemoryUsage() + mb_gdp->getMemoryUsage() / (1024.0 * 1024.0)) << endl; else cout << "VRAY_clusterThis::render() - Memory usage(MB): " << (fpreal)(inst_gdp->getMemoryUsage() / (1024.0 * 1024.0)) << endl; // If the "instance all the geo at once method" is used, add the the instanced geo for mantra to render ... switch(myMethod) { case CLUSTER_INSTANCE_NOW: if(myCVEX_Exec_post) { if(myVerbose > CLUSTER_MSG_INFO) cout << "VRAY_clusterThis::render() Executing Post Process CVEX code" << endl; VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname_post, CLUSTER_CVEX_POINT); } VRAY_Procedural::openGeometryObject(); VRAY_Procedural::addGeometry(inst_gdp, 0.0); if(myDoMotionBlur == CLUSTER_MB_VELOCITY) VRAY_Procedural::addVelocityBlurGeometry(inst_gdp, myShutter, myShutter2); // float addVelocityBlurGeometry (GU_Detail *gdp, fpreal pre_blur, fpreal post_blur, const char *velocity_attribute="v") if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) VRAY_Procedural::addGeometry(mb_gdp, myShutter); VRAY_Procedural::setComputeN(1); // setSurface(myMaterial); VRAY_Procedural::closeObject(); break; case CLUSTER_INSTANCE_DEFERRED: break; } if(myVerbose > CLUSTER_MSG_QUIET && (myPrimType != CLUSTER_PRIM_CURVE)) cout << "VRAY_clusterThis::render() Total number of instances: " << myInstanceNum << endl; // Save the geo to temp location so it doesn't have to be regenerated for a deep shadow pass, etc. if(myMethod == CLUSTER_INSTANCE_NOW && myUseTempFile) { ofstream myGeoStream; // myGeoStream.open("/tmp/thisGeo.bgeo"); myGeoStream.open((const char *)myTempFname, ios_base::binary); UT_Options myOptions; inst_gdp->save(myGeoStream, 1, &myOptions); myGeoStream.flush(); myGeoStream.close(); if(myVerbose > CLUSTER_MSG_QUIET) cout << "VRAY_clusterThis::render() - Saved geometry to temp file: " << myTempFname << endl; } if(myPrimType == CLUSTER_FILE) VRAY_Procedural::freeGeometry(file_gdp); // We're done, free the original geometry VRAY_Procedural::freeGeometry(gdp); } /// if (rendered) ...
void VRAY_clusterThis::preProcess(GU_Detail * gdp) { GEO_Point * ppt; long int num_points = (long int) gdp->points().entries(); long int stat_interval = (long int)(num_points * 0.10) + 1; for(uint32 i = gdp->points().entries(); i-- > 0;) { ppt = gdp->points()(i); myPointList.append(i); } // If the user wants to build grids for pre processing // TODO: Should this be an option? There may be functions/features that will depend on this ... discuss! if(!myPreProcess) return; if(myVerbose > CLUSTER_MSG_INFO) cout << "VRAY_clusterThis::preProcess() Pre Processing Voxels" << std::endl; // openvdb::ScalarGrid::Accessor accessor; // openvdb::FloatTree myTree; openvdb::FloatTree::ConstPtr myGeoTreePtr; openvdb::VectorTree::ConstPtr myGeoGradTreePtr; ParticleList paGeoList(gdp, myPreVDBRadiusMult, myPreVDBVelocityMult); openvdb::tools::PointSampler myGeoSampler, geoGradSampler; // openvdb::tools::GridSampling<openvdb::FloatTree> myGridSampler; if(myVerbose == CLUSTER_MSG_DEBUG) std::cout << "VRAY_clusterThis::preProcess() paGeoList.size() ... " << paGeoList.size() << std::endl; if(paGeoList.size() != 0) { hvdb::Interrupter boss("VRAY_clusterThis::preProcess() Converting particles to level set"); Settings settings; settings.mRadiusMin = myPreRadiusMin; settings.mRasterizeTrails = myPreRasterType; settings.mDx = myPreDx; // only used for rasterizeTrails() settings.mFogVolume = myPreFogVolume; settings.mGradientWidth = myPreGradientWidth; // only used for fog volume float background; // background in WS units if(myPreWSUnits) background = myPreBandWidth; // background NOT in WS units else background = myPreVoxelSize * myPreBandWidth; // Construct a new scalar grid with the specified background value. openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(myPreVoxelSize); // openvdb::ScalarGrid::Ptr myGeoGrid = openvdb::ScalarGrid::create(background); myGeoGrid = openvdb::ScalarGrid::create(background); myGeoGrid->setTransform(transform); myGeoGrid->setGridClass(openvdb::GRID_LEVEL_SET); // Perform the particle conversion. this->convert(myGeoGrid, paGeoList, settings, boss); if(myVerbose == CLUSTER_MSG_DEBUG) { std::cout << "VRAY_clusterThis::preProcess() - activeVoxelCount(): " << myGeoGrid->activeVoxelCount() << std::endl; std::cout << "VRAY_clusterThis::preProcess() - background: " << myGeoGrid->background() << std::endl; } // Insert the new grid into the ouput detail. UT_String gridNameStr = "ClusterGrid"; myGeoGrid->insertMeta("float type", openvdb::StringMetadata("averaged_velocity")); myGeoGrid->insertMeta("name", openvdb::StringMetadata((const char *)gridNameStr)); myGeoGrid->insertMeta("VoxelSize", openvdb::FloatMetadata(myPreVoxelSize)); myGeoGrid->insertMeta("background", openvdb::FloatMetadata(background)); UT_Vector3 pos, seed_pos, currVel; // const GA_PointGroup * sourceGroup = NULL; long int pt_counter = 0; float radius = 5.0f; if(myVerbose > CLUSTER_MSG_INFO) std::cout << "VRAY_clusterThis::preProcess() - Massaging data ... " << std::endl; long int pointsFound = 0; GEO_AttributeHandle inst_vel_gah = gdp->getPointAttribute("v"); GEO_AttributeHandle source_vel_gah = gdp->getPointAttribute("v"); GEO_AttributeHandle inst_N_gah = gdp->getPointAttribute("N"); GEO_AttributeHandle source_N_gah = gdp->getPointAttribute("N"); GEO_AttributeHandle inst_Cd_gah = gdp->getPointAttribute("Cd"); GEO_AttributeHandle source_Cd_gah = gdp->getPointAttribute("Cd"); GEO_AttributeHandle inst_Alpha_gah = gdp->getPointAttribute("Alpha"); GEO_AttributeHandle source_Alpha_gah = gdp->getPointAttribute("Alpha"); if(!inst_vel_gah.isAttributeValid()) throw VRAY_clusterThis_Exception("VRAY_clusterThis::preProcess() Instance velocity handle invalid, exiting ...", 1); if(!source_vel_gah.isAttributeValid()) throw VRAY_clusterThis_Exception("VRAY_clusterThis::preProcess() Source velocity handle invalid, exiting ...", 1); if(!inst_N_gah.isAttributeValid()) throw VRAY_clusterThis_Exception("VRAY_clusterThis::preProcess() Instance normal handle invalid, exiting ...", 1); if(!source_N_gah.isAttributeValid()) throw VRAY_clusterThis_Exception("VRAY_clusterThis::preProcess() Source normal handle invalid, exiting ...", 1); if(!inst_Cd_gah.isAttributeValid()) throw VRAY_clusterThis_Exception("VRAY_clusterThis::preProcess() Instance color handle invalid, exiting ...", 1); if(!source_Cd_gah.isAttributeValid()) throw VRAY_clusterThis_Exception("VRAY_clusterThis::preProcess() Source color handle invalid, exiting ...", 1); if(!inst_Alpha_gah.isAttributeValid()) throw VRAY_clusterThis_Exception("VRAY_clusterThis::preProcess() Instance alpha handle invalid, exiting ...", 1); if(!source_Alpha_gah.isAttributeValid()) throw VRAY_clusterThis_Exception("VRAY_clusterThis::preProcess() Source alpha handle invalid, exiting ...", 1); openvdb::FloatTree::ValueType sampleResult; openvdb::VectorGrid::ValueType gradResult; const openvdb::FloatTree aTree; openvdb::FloatTree& myGeoTree = myGeoGrid->treeRW(); openvdb::tools::Filter<openvdb::FloatGrid> preProcessFilter(*myGeoGrid); // openvdb::tools::Filter<openvdb::FloatGrid> barFilter(myGeoGrid); if(myPreVDBMedianFilter) preProcessFilter.median(); if(myPreVDBMeanFilter) preProcessFilter.mean(); if(myPreVDBMeanCurvatureFilter) preProcessFilter.meanCurvature(); if(myPreVDBLaplacianFilter) preProcessFilter.laplacian(); // if(myVDBReNormalizeFilter) // float r = barFilter.renormalize(3, 0.1); if(myPreVDBOffsetFilter) preProcessFilter.offset(myPreVDBOffsetFilterAmount); myGradientGrid = openvdb::VectorGrid::create(); // openvdb::VectorGrid::Ptr myGradientGrid = openvdb::VectorGrid::create(); myGradientGrid->setTransform(transform); // myGradientGrid->setGridClass(openvdb::GRID_FOG_VOLUME ); myGradientGrid->setGridClass(openvdb::GRID_LEVEL_SET); openvdb::tools::Gradient<openvdb::ScalarGrid> myGradient(*myGeoGrid); myGradientGrid = myGradient.process(); openvdb::VectorTree& myGeoGradTree = myGradientGrid->treeRW(); gridNameStr = "ClusterGradientGrid"; myGradientGrid->insertMeta("vector type", openvdb::StringMetadata("covariant (gradient)")); myGradientGrid->insertMeta("name", openvdb::StringMetadata((const char *)gridNameStr)); myGradientGrid->insertMeta("VoxelSize", openvdb::FloatMetadata(myPreVoxelSize)); myGradientGrid->insertMeta("background", openvdb::FloatMetadata(background)); GA_FOR_ALL_GPOINTS(gdp, ppt) { // myCurrPtOff = ppt->getMapOffset(); // std::cout << "myCurrPtOff: " << myCurrPtOff << std::endl; pos = ppt->getPos(); // Vec3d worldToIndex ( const Vec3d & xyz ) const // openvdb::Vec3R theIndex = // (openvdb::Vec3R(pos[0], pos[1], pos[2])); openvdb::Vec3R theIndex = myGeoGrid->worldToIndex(openvdb::Vec3R(pos[0], pos[1], pos[2])); radius = static_cast<fpreal>(ppt->getValue<fpreal>(myInstAttrRefs.pointVDBRadius, 0)); // std::cout << "radius: " << radius << std::endl; // static bool sample (const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &sampleResult) const openvdb::Vec3R inst_sample_pos(theIndex[0], theIndex[1], theIndex[2]); bool success = myGeoSampler.sample(myGeoTree, inst_sample_pos, sampleResult); geoGradSampler.sample(myGeoGradTree, inst_sample_pos, gradResult); // // std::cout << "success: " << success << "\tpos: " << pos // << "\tinst_sample_pos: " << inst_sample_pos // << "\tsampleResult: " << sampleResult << std::endl; //ValueType sampleWorld (const Vec3R &pt) const //ValueType sampleWorld (Real x, Real y, Real z) const // if the instanced point is within the vdb volume if(success) { // std::cout << "pos: " << pos << " inst_sample_pos: " // << inst_sample_pos << " sampleResult: " << sampleResult // << " gradResult: " << gradResult << std::endl; // float weight; pointsFound++; inst_vel_gah.setElement(ppt); currVel = inst_vel_gah.getV3(); UT_Vector3 gradVect = UT_Vector3(gradResult[0], gradResult[1], gradResult[2]); ppt->setPos(pos + (myPrePosInfluence *(sampleResult * gradVect))); // ppt->setPos(pos + (sampleResult * myPosInfluence *(currVel / myFPS))); // inst_vel_gah.setV3(currVel * ((1 / sampleResult) * radius)); inst_vel_gah.setV3(currVel + (myPreVelInfluence *(sampleResult * gradVect))); // std::cout << "currVel: " << currVel << " sampleResult " << sampleResult // << " new vel: " << currVel * sampleResult << std::endl; inst_N_gah.setV3(inst_N_gah.getV3() + (myPreNormalInfluence *(sampleResult * gradVect))); // inst_Cd_gah.setElement(ppt); // inst_Cd_gah.setV3(inst_Cd_gah.getV3() * abs(sampleResult)); // // // inst_Alpha_gah.setElement(ppt); // inst_Alpha_gah.setF(inst_Alpha_gah.getF() * abs(sampleResult)); } // if the instanced point is within the vdb volume if(myVerbose == CLUSTER_MSG_DEBUG) { pt_counter++; if((long int)(pt_counter % (stat_interval * myNumCopies * myRecursion)) == 0) { cout << "VRAY_clusterThis::preProcess() Number of points pre processed: " << pt_counter << "\t - Number of points found in vdb grid: " << pointsFound << std::endl; } } }
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)); } } }
OP_ERROR SOP_Scallop::cookMySop(OP_Context &context) { //OP_Node::flags().timeDep = 1; bool clip = (lockInputs(context) < UT_ERROR_ABORT); UT_BoundingBox bbox; if(clip) { const GU_Detail* input = inputGeo(0,context); if(input != NULL) { //UT_Matrix4 bm; int res = input->getBBox(&bbox); if(res == 0) clip = false; } else clip = false; unlockInputs(); }; float now = context.getTime(); Daemon::now=now; Daemon::caller=this; Daemon::bias = evalFloat("bias",0,now); UT_Ramp ramp; float rampout[4]; bool useRamp = (evalInt("parmcolor",0,now)!=0); if(useRamp) { //PRM_Template *rampTemplate = PRMgetRampTemplate ("ramp", PRM_MULTITYPE_RAMP_RGB, NULL, NULL); if (ramp.getNodeCount () < 2) { ramp.addNode (0, UT_FRGBA (0, 0, 0, 1)); ramp.addNode (1, UT_FRGBA (1, 1, 1, 1)); }; updateRampFromMultiParm(now, getParm("ramp"), ramp); }; gdp->clearAndDestroy(); bool showPts = (evalInt("showpts",0,now)!=0); /* if(showPts) { float sz = evalInt("ptssz",0,now); if(sz > 0) { float one = 1.0f; gdp->addAttribute("showpoints",4,GA_ATTRIB_FLOAT_&one); gdp->addAttribute("revealsize",4,GB_ATTRIB_FLOAT,&sz); }; }; */ int cnt = evalInt("daemons", 0, now); Daemon* daemons=new Daemon[cnt]; float weights = 0; int totd=0; for(int i=1;i<=cnt;i++) { bool skip = (evalIntInst("enabled#",&i,0,now)==0); if(skip) continue; Daemon& d = daemons[totd]; UT_String path = ""; evalStringInst("obj#", &i, path, 0, now); if(path == "") continue; SOP_Node* node = getSOPNode(path); OBJ_Node* obj = dynamic_cast<OBJ_Node*>(node->getParent()); if(obj == NULL) continue; addExtraInput(obj, OP_INTEREST_DATA); //d.xform = obj->getWorldTransform(context); // 10.0 obj->getWorldTransform(d.xform, context); d.weight = evalFloatInst("weight#",&i,0,now); if(!useRamp) { d.c[0] = evalFloatInst("color#",&i,0,now); d.c[1] = evalFloatInst("color#",&i,1,now); d.c[2] = evalFloatInst("color#",&i,2,now); }; int mth = evalIntInst("model#",&i,0,now); switch(mth) { case 1: d.method = Methods::Spherical; break; case 2: d.method = Methods::Polar; break; case 3: d.method = Methods::Swirl; break; case 4: d.method = Methods::Trigonometric; break; case 5: { UT_String script; evalStringInst("vexcode#", &i, script, 0, now); d.SetupCVEX(script); if(d.useVex) { OP_Node* shop = (OP_Node*)findSHOPNode(script); addExtraInput(shop, OP_INTEREST_DATA); } break; } case 0: default: d.method = Methods::Linear; }; d.power = evalFloatInst("power#",&i,0,now); d.radius = evalFloatInst("radius#",&i,0,now); d.parameter = evalFloatInst("parameter#",&i,0,now); weights+=d.weight; totd++; }; if(totd == 0) { delete [] daemons; return error(); } float base = 0.0; for(int i=0;i<totd;i++) { Daemon& d = daemons[i]; d.range[0]=base; d.range[1] = base+d.weight/weights; base=d.range[1]; }; int total = evalInt("count",0,now); int degr = evalInt("degr",0,now); total >>= degr; GA_RWHandleI cntt(gdp->addIntTuple(GA_ATTRIB_POINT, "count", 4, GA_Defaults(1.0))); GB_AttributeRef dt(gdp->addDiffuseAttribute(GEO_POINT_DICT)); gdp->addVariableName("Cd","Cd"); UT_Vector3 current(0,0,0); float C[3] = { 0,0,0 }; float R=1.0f; bool trackRadii = (evalInt("trackradii",0,now)!=0); float rScale = evalFloat("radiiscale",0,now); GB_AttributeRef rt; if(trackRadii) { float one=1.0f; rt = gdp->addPointAttrib("width",4,GB_ATTRIB_FLOAT,&one); if(!GBisAttributeRefValid(rt)) trackRadii=false; else gdp->addVariableName("width","WIDTH"); }; float zero=0.0f; GB_AttributeRef pt = gdp->addPointAttrib("parameter",4,GB_ATTRIB_FLOAT,&zero); if(GBisAttributeRefValid(pt)) gdp->addVariableName("parameter","PARAMETER"); float param=0.0f; srand(0); UT_Interrupt* boss = UTgetInterrupt(); boss->opStart("Computing..."); for(int i=-50;i<total;i++) { bool ok = false; if (boss->opInterrupt()) break; float w = double(rand())/double(RAND_MAX); for(int j=0;j<totd;j++) { ok = daemons[j].Transform(w,current,C,R,param); if(ok) break; }; if(i<0) continue; if(clip) { if(!bbox.isInside(current)) continue; }; if(ok) { GEO_Point* p = gdp->appendPoint(); p->setPos(current); float* Cd=p->castAttribData<float>(dt); if(useRamp) { ramp.rampLookup(param,C); } memcpy(Cd,C,12); if(trackRadii) { float* _R = p->castAttribData<float>(rt); *_R=rScale*R; }; if(GBisAttributeRefValid(pt)) { float* _p = p->castAttribData<float>(pt); *_p=param; } }; }; boss->opEnd(); delete [] daemons; return error(); };
OP_ERROR SOP_Ocean::cookMySop(OP_Context &context) { float now = context.getTime(); //std::cout << "cook ocean, t = " << now << std::endl; // lock inputs if (lockInputs(context) >= UT_ERROR_ABORT ) { return error(); } GEO_Point *ppt; UT_Interrupt *boss; // Check to see that there hasn't been a critical error in cooking the SOP. if (error() < UT_ERROR_ABORT) { boss = UTgetInterrupt(); // Start the interrupt server boss->opStart("Updating Ocean"); duplicatePointSource(0,context); int gridres = 1 << int(GRID_RES(now)); float stepsize = GRID_SIZE(now) / (float)gridres; bool do_chop = CHOP(now); bool do_jacobian = JACOBIAN(now); bool do_normals = NORMALS(now) && !do_chop; if (!_ocean || _ocean_needs_rebuild) { if (_ocean) { delete _ocean; } if (_ocean_context) { delete _ocean_context; } _ocean = new drw::Ocean(gridres,gridres,stepsize,stepsize, V(0),L(0),1.0,W(0),1-DAMP(0),ALIGN(0), DEPTH(0),SEED(0)); _ocean_scale = _ocean->get_height_normalize_factor(); _ocean_context = _ocean->new_context(true,do_chop,do_normals,do_jacobian); _ocean_needs_rebuild = false; // std::cout << "######### SOP, rebuilt ocean, norm_factor = " << _ocean_scale // << " chop = " << do_chop // << " norm = " << do_normals // << " jacobian = " << do_jacobian // << std::endl; } float chop_amount = CHOPAMOUNT(now); // sum up the waves at this timestep _ocean->update(TIME(now),*_ocean_context,true,do_chop,do_normals,do_jacobian, _ocean_scale * SCALE(now),chop_amount); bool linterp = ! INTERP(now); // get our attribute indices GA_RWAttributeRef normal_index; GA_RWAttributeRef jminus_index; GA_RWAttributeRef eminus_index; if (do_normals) { normal_index = gdp->addNormalAttribute(GEO_POINT_DICT); } if (do_jacobian) { // jminus_index = gdp->addPointAttrib("mineigval",sizeof(float),GB_ATTRIB_FLOAT,0); // eminus_index = gdp->addPointAttrib("mineigvec",sizeof(UT_Vector3),GB_ATTRIB_VECTOR,0); jminus_index = gdp->addTuple(GA_STORE_REAL32,GA_ATTRIB_POINT,"mineigval",1,GA_Defaults(0)); eminus_index = gdp->addFloatTuple(GA_ATTRIB_POINT,"mineigvec",1,GA_Defaults(0)); } // this is not that fast, can it be done quicker ??? GA_FOR_ALL_GPOINTS(gdp, ppt) { UT_Vector4 p = ppt->getPos(); if (linterp) { _ocean_context->eval_xz(p(0),p(2)); } else { _ocean_context->eval2_xz(p(0),p(2)); } if (do_chop) { p.assign( p(0) + _ocean_context->disp[0], p(1) + _ocean_context->disp[1], p(2) + _ocean_context->disp[2] ); } else { // ppt->getPos()(1) += _ocean_context->disp[1]; UT_Vector4 tmp_p = ppt->getPos(); tmp_p(1) += _ocean_context->disp[1]; ppt->setPos(tmp_p); } if (do_normals) { /* UT_Vector3* normal = (UT_Vector3*) ppt->castAttribData<UT_Vector3>(normal_index); normal->assign(_ocean_context->normal[0], _ocean_context->normal[1], _ocean_context->normal[2]); normal->normalize(); */ ppt->getValue<UT_Vector3>(normal_index).assign(_ocean_context->normal[0], _ocean_context->normal[1], _ocean_context->normal[2]); ppt->getValue<UT_Vector3>(normal_index).normalize(); } if (do_jacobian) {/* float *js = (float*)ppt->castAttribData<float>(jminus_index); *js = _ocean_context->Jminus; UT_Vector3* eminus = (UT_Vector3*)ppt->castAttribData<UT_Vector3>(eminus_index); eminus->assign(_ocean_context->Eminus[0],0,_ocean_context->Eminus[1]); */ ppt->setValue<float>(jminus_index,_ocean_context->Jminus); ppt->getValue<UT_Vector3>(eminus_index).assign(_ocean_context->Eminus[0],0,_ocean_context->Eminus[1]); } ppt->setPos(p); }
// the bit that does all the work OP_ERROR SOP_rmanPtc::cookMySop(OP_Context &context) { // get some useful bits & bobs UT_Interrupt *boss; float now = context.myTime; UT_String ptcFile = getPtcFile(now); int loadPercentage = getLoadPercentage(now); int displayPercentage = getDisplayPercentage(now); float pointSize = getPointSize(now); int useDisk = getUseDisk(now); int boundOnLoad = getBoundOnLoad(now); int displayChannel = getDisplayChannel(now); int onlyOutputDisplayChannel = getOnlyOutputDisplayChannel(now); /* float nearDensity = getNearDensity(now); float farDensity = getFarDensity(now); UT_String cullCamera = getCullCamera(now); */ // lock out inputs if ( lockInputs(context) >= UT_ERROR_ABORT) error(); // Check to see that there hasn't been a critical error in cooking the SOP. if (error() < UT_ERROR_ABORT) { boss = UTgetInterrupt(); // here we make sure our detail is an instance of rmanPtcDetail rmanPtcDetail *ptc_gdp = dynamic_cast<rmanPtcSop::rmanPtcDetail *>(gdp); if ( !ptc_gdp ) ptc_gdp = allocateNewDetail(); // clear our gdp ptc_gdp->clearAndDestroy(); // start our work boss->opStart("Loading point cloud"); // get our bbox bool has_bbox = false; const GU_Detail *input_geo = inputGeo( 0, context ); updateBBox( input_geo ); // pass information to our detail ptc_gdp->point_size = pointSize; ptc_gdp->use_disk = useDisk; ptc_gdp->cull_bbox = mBBox; ptc_gdp->use_cull_bbox = (mHasBBox&&(!mBoundOnLoad))?true:false; ptc_gdp->display_probability = displayPercentage/100.f; ptc_gdp->display_channel = displayChannel; if ( onlyOutputDisplayChannel ) ptc_gdp->display_channel = 0; // here we load our ptc if ( mReload ) { // clear everything mChannelNames.clear(); cachePoints.clear(); cacheNormals.clear(); cacheRadius.clear(); cacheData.clear(); mRedraw = true; // open the point cloud PtcPointCloud ptc = PtcSafeOpenPointCloudFile( const_cast<char*>(ptcFile.buffer()) ); if ( !ptc ) { UT_String msg( "Unable to open input file: " ); msg += ptcFile; addError( SOP_MESSAGE, msg); boss->opEnd(); return error(); } // get some information from the ptc ptc_gdp->path = std::string(ptcFile.fileName()); char **vartypes, **varnames; PtcGetPointCloudInfo( ptc, const_cast<char*>("npoints"), &ptc_gdp->nPoints ); PtcGetPointCloudInfo( ptc, const_cast<char*>("npointvars"), &ptc_gdp->nChannels ); PtcGetPointCloudInfo( ptc, const_cast<char*>("pointvartypes"), &vartypes ); PtcGetPointCloudInfo( ptc, const_cast<char*>("pointvarnames"), &varnames ); PtcGetPointCloudInfo( ptc, const_cast<char*>("datasize"), &ptc_gdp->datasize ); PtcGetPointCloudInfo( ptc, const_cast<char*>("bbox"), ptc_gdp->bbox ); // process our channel names ptc_gdp->types.clear(); ptc_gdp->names.clear(); for ( unsigned int i=0; i<ptc_gdp->nChannels; ++i ) { ptc_gdp->types.push_back( std::string(vartypes[i]) ); ptc_gdp->names.push_back( std::string(varnames[i]) ); std::string name = ptc_gdp->types[i] + " " + ptc_gdp->names[i]; mChannelNames.push_back( name ); } // what percentage of points should we load? float load_probability = loadPercentage/100.f; // load points into memory float point[3], normal[3]; float radius; float data[ptc_gdp->datasize]; srand(0); for ( unsigned int i=0; i<ptc_gdp->nPoints; ++i ) { PtcReadDataPoint( ptc, point, normal, &radius, data ); // bound on load if ( boundOnLoad ) { UT_Vector3 pt( point[0], point[1], point[2] ); if ( !mBBox.isInside(pt) ) continue; } // discard a percentage of our points if ( rand()/(float)RAND_MAX>load_probability ) continue; // put points into our cache cachePoints.push_back( point ); cacheNormals.push_back( normal ); cacheRadius.push_back( radius ); for ( unsigned int j=0; j<ptc_gdp->datasize; ++j ) cacheData.push_back( data[j] ); // break for the interrupt handler (i.e. press ESC) if ( boss->opInterrupt() ) break; } ptc_gdp->nLoaded = cachePoints.size(); // mark our detail as valid and close our ptc PtcClosePointCloudFile( ptc ); mReload = false; // force update on channel parameter getParm("chan").revertToDefaults(now); } // build a new primitive GU_PrimParticle::build( ptc_gdp, cachePoints.size(), 0 ); // create our output geometry using the output % parameter // this is the same variable as GR_ uses to preview std::vector<UT_Vector3>::const_iterator pos_it = cachePoints.begin(); std::vector<UT_Vector3>::const_iterator norm_it = cacheNormals.begin(); std::vector<float>::const_iterator rad_it = cacheRadius.begin(); std::vector<float>::const_iterator data_it = cacheData.begin(); // add some standard attributes GB_AttributeRef n_attrib = ptc_gdp->addPointAttrib( "N", sizeof(UT_Vector3), GB_ATTRIB_VECTOR, 0 ); GB_AttributeRef r_attrib = ptc_gdp->addPointAttrib( "radius", sizeof(float), GB_ATTRIB_FLOAT, 0 ); ptc_gdp->N_attrib = n_attrib; ptc_gdp->R_attrib = r_attrib; // process the rest of our data attributes std::vector<GB_AttribType> data_types; std::vector<GB_AttributeRef> data_attribs; std::vector<int> data_size, data_offset; int offset_total = 0; ptc_gdp->attributes.clear(); ptc_gdp->attribute_size.clear(); for ( unsigned int i=0; i<ptc_gdp->nChannels; ++i ) { GB_AttribType type = GB_ATTRIB_FLOAT; // float, vector int size = 1; if ( ptc_gdp->types[i] == "point" || ptc_gdp->types[i] == "vector" || ptc_gdp->types[i] == "normal" ) { type = GB_ATTRIB_VECTOR; size = 3; } if ( ptc_gdp->types[i] == "color" ) { size=3; } if ( ptc_gdp->types[i] == "matrix" ) { size=16; } offset_total += size; data_types.push_back( type ); data_size.push_back( size ); data_offset.push_back( offset_total ); if ( onlyOutputDisplayChannel ) { if ( displayChannel==i ) { GB_AttributeRef attrib = ptc_gdp->addPointAttrib( ptc_gdp->names[i].c_str(), sizeof(float)*size, type, 0 ); ptc_gdp->attributes.push_back( attrib ); ptc_gdp->attribute_size.push_back( size ); data_attribs.push_back( attrib ); } } else { GB_AttributeRef attrib = ptc_gdp->addPointAttrib( ptc_gdp->names[i].c_str(), sizeof(float)*size, type, 0 ); ptc_gdp->attributes.push_back( attrib ); ptc_gdp->attribute_size.push_back( size ); data_attribs.push_back( attrib ); } } cacheDataOffsets = data_offset; /* // cull camera bool use_cull_cam = false; UT_Vector3 cam_pos(0,0,0); float cam_near=0.0, cam_far=0.0; if ( cullCamera!="" ) { OBJ_Node *cam_node = OPgetDirector()->findOBJNode( cullCamera ); if ( cam_node ) { OBJ_Camera *cam = cam_node->castToOBJCamera(); if ( cam ) { UT_DMatrix4 mtx; cam->getWorldTransform( mtx, context ); std::cerr << "mtx: " << mtx << std::endl; cam_pos *= mtx; std::cerr << "pos: " << cam_pos << std::endl; use_cull_cam = true; cam_near = cam->getNEAR(now); cam_far = cam->getFAR(now); std::cerr << "near: " << cam_near << std::endl; std::cerr << "far: " << cam_far << std::endl; mRedraw = true; } } std::cerr << "cull camera: " << cullCamera << std::endl; std::cerr << nearDensity << ", " << farDensity << std::endl; } */ // add data from our cached points to geometry // based on display/output probability srand(0); float density_mult = 1.f; while( pos_it!=cachePoints.end() ) { /* if ( use_cull_cam ) { float dist = ((*pos_it)-cam_pos).length(); if ( dist<cam_near ) density_mult = nearDensity; else if ( dist>cam_far ) density_mult = farDensity; else { float normalize_dist =( dist - cam_near ) / ( cam_far - cam_near ); density_mult = 1.f - normalize_dist; } } */ if ( rand()/(float)RAND_MAX < ptc_gdp->display_probability*density_mult ) { if ( (!ptc_gdp->use_cull_bbox) || (ptc_gdp->use_cull_bbox && ptc_gdp->cull_bbox.isInside( *pos_it ) ) ) { // add to our SOP geometry GEO_Point *pt = ptc_gdp->appendPoint(); pt->setPos( *pos_it ); (*pt->castAttribData<UT_Vector3>(n_attrib)) = *norm_it; (*pt->castAttribData<float>(r_attrib)) = *rad_it; const float *data = &*data_it; for ( unsigned int i=0; i<data_types.size(); ++i ) { if ( onlyOutputDisplayChannel ) { if ( i==displayChannel ) { pt->set( data_attribs[0], data, data_size[i] ); } data += data_size[i]; } else { pt->set( data_attribs[i], data, data_size[i] ); data += data_size[i]; } } } } // increment our interators pos_it++; norm_it++; rad_it++; data_it+=ptc_gdp->datasize; } // delete our particle primitive ptc_gdp->deletePrimitive(0,0); // info in sop's message area std::stringstream ss; ss << "Name: " << ptc_gdp->path << std::endl; ss << "Points: " << ptc_gdp->nPoints << " - [ " << ptc_gdp->nLoaded << " loaded ]" << std::endl; ss << "Channels: " << ptc_gdp->nChannels << std::endl; for ( unsigned int i=0; i<ptc_gdp->nChannels; ++i ) ss << " " << i << ": " << mChannelNames[i] << std::endl; addMessage( SOP_MESSAGE, ss.str().c_str() ); // Tell the interrupt server that we've completed boss->opEnd(); // force update? ptc_gdp->redraw = mRedraw; mRedraw = false; } // tidy up & go home unlockInputs(); return error(); }
/* ****************************************************************************** * Function Name : instanceCurve() * * Description : Instance a curve * * Input Arguments : GU_Detail *inst_gdp, GU_Detail *mb_gdp * * Return Value : int * ***************************************************************************** */ int VRAY_clusterThis::instanceCurve(GU_Detail * inst_gdp, GU_Detail * mb_gdp, fpreal theta, long int point_num) { #ifdef DEBUG std::cout << "VRAY_clusterThis::instanceCurve()" << std::endl; #endif GEO_Point * ppt; GU_PrimNURBCurve * myCurve, * myMBCurve; uint32 num_vtx; int myCurvePointNum = 0; UT_Vector4 pt_pos; GU_Detail * curve_gdp, * curve_mb_gdp; curve_gdp = allocateGeometry(); GA_RWAttributeRef prim_Cd = curve_gdp->addDiffuseAttribute(GEO_PRIMITIVE_DICT); GA_RWAttributeRef prim_Alpha = curve_gdp->addAlphaAttribute(GEO_PRIMITIVE_DICT); GA_RWAttributeRef prim_v = curve_gdp->addVelocityAttribute(GEO_PRIMITIVE_DICT); GA_RWAttributeRef prim_N = curve_gdp->addNormalAttribute(GEO_PRIMITIVE_DICT); GA_RWAttributeRef prim_material = curve_gdp->addStringTuple(GEO_PRIMITIVE_DICT, "shop_materialpath", 1); GA_RWAttributeRef pt_Cd = curve_gdp->addDiffuseAttribute(GEO_POINT_DICT); GA_RWAttributeRef pt_Alpha = curve_gdp->addAlphaAttribute(GEO_POINT_DICT); GA_RWAttributeRef pt_v = curve_gdp->addVelocityAttribute(GEO_POINT_DICT); GA_RWAttributeRef pt_N = curve_gdp->addNormalAttribute(GEO_POINT_DICT); GA_RWAttributeRef pt_pscale = curve_gdp->addFloatTuple(GA_ATTRIB_POINT, "pscale", 1); GA_RWAttributeRef pt_width = curve_gdp->addFloatTuple(GA_ATTRIB_POINT, "width", 1); GA_RWAttributeRef pt_id = curve_gdp->addIntTuple(GA_ATTRIB_POINT, "id", 1); GA_RWAttributeRef pt_instId = curve_gdp->addIntTuple(GA_ATTRIB_POINT, "inst_id", 1); GA_RWAttributeRef pt_material = curve_gdp->addStringTuple(GA_ATTRIB_POINT, "shop_materialpath", 1); GA_RWAttributeRef pt_mb_Cd; GA_RWAttributeRef pt_mb_Alpha; GA_RWAttributeRef pt_mb_v; GA_RWAttributeRef pt_mb_N; GA_RWAttributeRef pt_mb_pscale; GA_RWAttributeRef pt_mb_width; GA_RWAttributeRef pt_mb_id; GA_RWAttributeRef pt_mb_instId; GA_RWAttributeRef pt_mb_material; num_vtx = ((myNumCopies * myRecursion) > 4) ? (myNumCopies * myRecursion) : 4; myCurve = (GU_PrimNURBCurve *)GU_PrimNURBCurve::build((GU_Detail *)curve_gdp, num_vtx, 4, 0, 1, 1); myCurve->setValue<UT_Vector3>(prim_Cd, (const UT_Vector3)myPointAttributes.Cd); myCurve->setValue<fpreal>(prim_Alpha, (const fpreal)myPointAttributes.Alpha); myCurve->setString(prim_material, myPointAttributes.material); // cout << "VRAY_clusterThis::instanceCurve() - num vertices: " << myCurve->getVertexCount() << endl;; // cout << "id: " << myCurve->getPrimitiveId() << endl; // cout << "breakCount: " << myCurve->breakCount() << endl; if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) { curve_mb_gdp = allocateGeometry(); myMBCurve = (GU_PrimNURBCurve *)GU_PrimNURBCurve::build((GU_Detail *)curve_mb_gdp, num_vtx, 4, 0, 1, 1); pt_mb_Cd = curve_gdp->addDiffuseAttribute(GEO_POINT_DICT); pt_mb_Alpha = curve_gdp->addAlphaAttribute(GEO_POINT_DICT); pt_mb_v = curve_gdp->addVelocityAttribute(GEO_POINT_DICT); pt_mb_N = curve_gdp->addNormalAttribute(GEO_POINT_DICT); pt_mb_pscale = curve_gdp->addFloatTuple(GA_ATTRIB_POINT, "pscale", 1); pt_mb_width = curve_gdp->addFloatTuple(GA_ATTRIB_POINT, "width", 1); pt_mb_id = curve_gdp->addIntTuple(GA_ATTRIB_POINT, "id", 1); pt_mb_instId = curve_gdp->addIntTuple(GA_ATTRIB_POINT, "inst_id", 1); pt_mb_material = curve_gdp->addStringTuple(GA_ATTRIB_POINT, "shop_materialpath", 1); } for(int copyNum = 0; copyNum < myNumCopies; copyNum++) for(int recursionNum = 0; recursionNum < myRecursion; recursionNum++) { VRAY_clusterThis::calculateNewPosition(theta, copyNum, recursionNum); ppt = myCurve->getVertexElement(myCurvePointNum).getPt(); ppt->setPos((float)myPointAttributes.myNewPos[0], (float)myPointAttributes.myNewPos[1], (float)myPointAttributes.myNewPos[2], 1.0); // Assign attributes to each point ppt->setValue<UT_Vector3>(pt_Cd, (const UT_Vector3)myPointAttributes.Cd); ppt->setValue<fpreal>(pt_Alpha, (const fpreal)myPointAttributes.Alpha); ppt->setValue<UT_Vector3>(pt_v, (const UT_Vector3)myPointAttributes.v); ppt->setValue<UT_Vector3>(pt_N, (const UT_Vector3)myPointAttributes.N); ppt->setValue<fpreal>(pt_pscale, (const fpreal)myPointAttributes.pscale); ppt->setValue<fpreal>(pt_width, (const fpreal)myPointAttributes.width); ppt->setValue<int>(pt_id, (const int)myPointAttributes.id); ppt->setValue<int>(pt_instId, (const int)myCurvePointNum); ppt->setString(pt_material, myPointAttributes.material); if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) { ppt = myMBCurve->getVertexElement(myCurvePointNum).getPt(); ppt->setPos((float)myPointAttributes.myNewPos[0], (float)myPointAttributes.myMBPos[1], (float)myPointAttributes.myMBPos[2], 1.0); // Assign attributes to each point ppt->setValue<UT_Vector3>(pt_mb_Cd, (const UT_Vector3)myPointAttributes.Cd); ppt->setValue<fpreal>(pt_mb_Alpha, (const fpreal)myPointAttributes.Alpha); ppt->setValue<UT_Vector3>(pt_mb_v, (const UT_Vector3)myPointAttributes.v); ppt->setValue<UT_Vector3>(pt_mb_N, (const UT_Vector3)myPointAttributes.N); ppt->setValue<fpreal>(pt_mb_pscale, (const fpreal)myPointAttributes.pscale); ppt->setValue<fpreal>(pt_mb_width, (const fpreal)myPointAttributes.width); ppt->setValue<int>(pt_mb_id, (const int)myPointAttributes.id); ppt->setValue<int>(pt_mb_instId, (const int)myInstanceNum); ppt->setString(pt_mb_material, myPointAttributes.material); } // std::cout << "VRAY_clusterThis::instanceCurve() myCurvePointNum: " << myCurvePointNum << std::endl; myCurvePointNum++; } // myCurve->close(); // myMBCurve->close (); if(myCVEX_Exec) VRAY_clusterThis::runCVEX(curve_gdp, curve_mb_gdp, myCVEXFname, CLUSTER_CVEX_POINT); if(myCVEX_Exec_prim) VRAY_clusterThis::runCVEX(curve_gdp, curve_mb_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM); inst_gdp->merge(*curve_gdp); VRAY_Procedural::freeGeometry(curve_gdp); if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) { mb_gdp->merge(*curve_mb_gdp); VRAY_Procedural::freeGeometry(curve_mb_gdp); } return 0; }
void add_simple_mesh(GU_Detail& gdp, const dgal::simple_mesh<Imath::V3f>& smesh, const std::string& pointIDAttrib, const std::vector<int>* pointIDs, const std::string& polyIDAttrib, const std::vector<int>* polyIDs, const std::string& cellTypeAttrib, unsigned int cellType, const std::string& cellIDAttrib, unsigned int cellID) { unsigned int first_point = gdp.points().entries(); unsigned int first_prim = gdp.primitives().entries(); // create dest points for(std::vector<Imath::V3f>::const_iterator it=smesh.m_points.begin(); it!=smesh.m_points.end(); ++it) { GEO_Point* pt = gdp.appendPoint(); pt->setPos(it->x, it->y, it->z); } GEO_PointList& points = gdp.points(); GEO_PrimList& prims = gdp.primitives(); // create dest polys for(unsigned int i=0; i<smesh.m_polys.size(); ++i) { const std::vector<unsigned int>& cpoly = smesh.m_polys[i]; GEO_PrimPoly* poly = GU_PrimPoly::build(&gdp, cpoly.size(), GU_POLY_CLOSED, 0); for(unsigned int j=0; j<cpoly.size(); ++j) poly->getVertex(j).setPt(points[cpoly[j] + first_point]); } // create cell-type attribute if(!cellTypeAttrib.empty()) { int defaultv = -1; GB_AttributeRef aref = gdp.addAttribute(cellTypeAttrib.c_str(), sizeof(int), GB_ATTRIB_INT, &defaultv, GEO_PRIMITIVE_DICT); if(aref.isValid()) { unsigned int npolys = prims.entries(); for(unsigned int i=first_prim; i<npolys; ++i) prims[i]->setValue<int32>(aref, static_cast<int>(cellType)); } } // create cell-id attribute if(!cellIDAttrib.empty()) { int defaultv = -1; GB_AttributeRef aref = gdp.addAttribute(cellIDAttrib.c_str(), sizeof(int), GB_ATTRIB_INT, &defaultv, GEO_PRIMITIVE_DICT); if(aref.isValid()) { unsigned int npolys = prims.entries(); for(unsigned int i=first_prim; i<npolys; ++i) prims[i]->setValue<int32>(aref, static_cast<int>(cellID)); } } // create point-id attribute if(!pointIDAttrib.empty()) { int defaultv = -1; GB_AttributeRef aref = gdp.addAttribute(pointIDAttrib.c_str(), sizeof(int), GB_ATTRIB_INT, &defaultv, GEO_POINT_DICT); if(aref.isValid() && pointIDs) { unsigned int sz = std::min(points.entries()-first_point, static_cast<unsigned int>(pointIDs->size())); for(unsigned int i=0; i<sz; ++i) points[i + first_point]->setValue<int32>(aref, (*pointIDs)[i]); } } // create poly-id attribute if(!polyIDAttrib.empty()) { int defaultv = 0; GB_AttributeRef aref = gdp.addAttribute(polyIDAttrib.c_str(), sizeof(int), GB_ATTRIB_INT, &defaultv, GEO_PRIMITIVE_DICT); if(aref.isValid() && polyIDs) { unsigned int sz = std::min(prims.entries()-first_prim, static_cast<unsigned int>(polyIDs->size())); for(unsigned int i=0; i<sz; ++i) prims[i + first_prim]->setValue<int32>(aref, (*polyIDs)[i]); } } }