// When mantra determines that the bounding box needs to be rendered, the // render method is called. At this point, the procedural can either // generate geometry (VRAY_Procedural::openGeometryObject()) or it can // generate further procedurals (VRAY_Procedural::openProceduralObject()). void VRAY_ieProcedural::render() { initialisePython(); ParameterisedProceduralPtr parameterisedProcedural = 0; ScopedGILLock giLock; try { object ieCore = g_mainModuleNamespace["IECore"]; object classLoader = ieCore.attr( "ClassLoader" ).attr( "defaultProceduralLoader" )(); object procedural = classLoader.attr( "load" )( m_className.buffer(), m_classVersion )(); boost::python::list params; UT_WorkArgs argv; if (m_parameterString.tokenize(argv, ",")) { // The Cortex Mantra Inject otl parses the parameters of a // SOP_ProceduralHolder and replaces empty values with a '!' // character to make them easier to parse here. // // This hack is upsetting, a pure python procedural in the style // of IECoreRI iePython.dso could parse these parameters correctly // like python/IECoreRI/ExecuteProcedural.py for (int i = 0; i < argv.getArgc(); i++) { std::string s(argv[i]); if (s == "!") { params.append(std::string("")); } else { params.append(s); } } } object parameterParser = ieCore.attr( "ParameterParser" )(); parameterParser.attr( "parse" )( params, procedural.attr( "parameters" )() ); parameterisedProcedural = extract<ParameterisedProceduralPtr>( procedural ); } catch( const error_already_set &e ) { PyErr_Print(); } catch( const std::exception &e ) { msg( Msg::Error, "VRAY_ieProcedural", e.what() ); } catch( ... ) { msg( Msg::Error, "VRAY_ieProcedural", "Caught unknown exception" ); } if( parameterisedProcedural ) { IECoreMantra::RendererPtr renderer = new IECoreMantra::Renderer( this ); parameterisedProcedural->render( renderer.get(), false, false, true, true ); } }
// The initialize method is called when the procedural is created. // Returning zero (failure) will abort the rendering of this procedural. // The bounding box passed in is the user defined bounding box. // If the user didn't specify a bounding box, then the box will be NULL int VRAY_ieWorld::initialize(const UT_BoundingBox *box) { if ( box ) { m_bound = convert<Imath::Box3f> ( *box ); } import( "ieworldfile", m_worldFileName); import( "ieworldremove", &m_remove, 1); if( access( m_worldFileName.buffer(), R_OK|F_OK ) == -1 ) { msg( Msg::Warning, "VRAY_ieWorld", format("Failed to find ieworld cache file: %s") % m_worldFileName.buffer() ); return 0; } return 1; }
// When mantra determines that the bounding box needs to be rendered, the // render method is called. At this point, the procedural can either // generate geometry (VRAY_Procedural::openGeometryObject()) or it can // generate further procedurals (VRAY_Procedural::openProceduralObject()). void VRAY_ieWorld::render() { ConstVisibleRenderablePtr renderable = 0; try { ReaderPtr reader = Reader::create( m_worldFileName.buffer() ); renderable = runTimeCast<VisibleRenderable>( reader->read() ); } catch ( IECore::Exception e ) { msg( Msg::Warning, "VRAY_ieWorld", format("Failed to load ieworld cache file: %s") % m_worldFileName.buffer() ); } if ( !renderable ) { msg( Msg::Warning, "VRAY_ieWorld", format("Failed to read ieworld cache file: %s") % m_worldFileName.buffer() ); } IECoreMantra::RendererPtr renderer = new IECoreMantra::Renderer( this ); renderable->render( renderer.get() ); }
ratReader::ratReader(Read *r, int fd): Reader(r) { // Init: buffer = NULL; loaded = false; rat = NULL; use_scanline_engine = true; parms = new IMG_FileParms(); // Read knobs: ratReaderFormat* rrf = dynamic_cast<ratReaderFormat*>(r->handler()); if (rrf) { if (rrf->reverse_scanlines()) parms->orientImage(IMG_ORIENT_LEFT_FIRST, IMG_ORIENT_TOP_FIRST); use_scanline_engine = rrf->use_scanline_engine(); } else parms->orientImage(IMG_ORIENT_LEFT_FIRST, IMG_ORIENT_Y_NONE); // Set some of the settings, which are assumed currently by both ::engines. // Leaving them as they are would require some serious switches in logic bellow. parms->setDataType(IMG_FLOAT); parms->setInterleaved(IMG_INTERLEAVED); parms->setComponentOrder(IMG_COMPONENT_RGBA); // Create and open rat file, get stats: rat = IMG_File::open(r->filename(), parms); // TODO: Meta data attempt: #if defined(DEBUG) UT_String info; rat->getAdditionalInfo(info); iop->warning("Rat info: %s\n", info.buffer()); for (int i = 0; i < rat->getNumOptions(); i++) { iop->warning("%s: %s", rat->getOptionName(i), rat->getOptionValue(i)); } UT_SharedPtr<UT_Options> opt; UT_WorkBuffer wbuf; if (opt = rat->imageTextureOptions()) { wbuf.strcpy("DSM Options: "); opt->appendPyDictionary(wbuf); iop->warning("Options %i: %s\n", opt->getNumOptions(), wbuf.buffer()); } #endif if (!rat) { iop->error("Failed to open .rat file."); } const IMG_Stat &stat = rat->getStat(); depth = 0; #if defined(DEBUG) iop->warning("Rat opened: %s", r->filename()); #endif // Since RAT can store varying bitdepth per plane, pixel-byte algebra doesn't // help in finding out a number of channels. We need to iterate over planes. for (int i = 0; i < stat.getNumPlanes(); i++) { IMG_Plane *plane = stat.getPlane(i); // The easiest yet not unequivocal way to determine 2d versus deep RAT files: if (!strcmp(plane->getName(), "Depth-Complexity")) iop->warning("ratReader will treat DCM files as a 2d images. (ignoring deep pixels)"); #if defined(DEBUG) iop->warning("Plane name: %s", plane->getName()); #endif depth += IMGvectorSize(plane->getColorModel()); } ChannelSet mask; for (int i = 0; i < stat.getNumPlanes(); i++) { IMG_Plane *plane = stat.getPlane(i); const int nchan = IMGvectorSize(plane->getColorModel()); for (int j = 0; j < nchan; j++) { std::string chan = std::string(plane->getComponentName(j) ? plane->getComponentName(j): "r"); if (chan == "r") chan = "red"; else if (chan == "g") chan = "green"; else if (chan == "b") chan = "blue"; else if (chan == "a") chan = "alpha"; std::string chan_name = std::string(plane->getName()) + std::string(".") + chan; std::set<Channel> channels; lookupChannels(channels, chan_name.c_str()); if (!channels.empty()) { for (std::set<Channel>::iterator it = channels.begin(); it != channels.end(); it++) { Channel channel = *it; channel_map[channel]= chan_name.c_str(); std::pair<int, int> idx(i, j); rat_chan_index[channel] = idx; #if defined(DEBUG) iop->warning("Rat %s (%i,%i) becomes %s", chan_name.c_str(), i, j, getName(channel)); #endif mask += channel; } } else iop->warning("Can't create a channel from %s", chan_name.c_str()); } } // Set info: #if defined(DEBUG) iop->warning("Channel number: %i", depth); #endif set_info(stat.getDataWidth(), stat.getDataHeight(), depth); info_.channels(mask); }
// 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(); }
void HoudiniScene::readTags( NameList &tags, bool includeChildren ) const { tags.clear(); const OP_Node *node = retrieveNode(); if ( !node ) { return; } // add user supplied tags if we're not inside a SOP if ( !m_contentIndex && node->hasParm( pTags.getToken() ) ) { UT_String parmTagStr; node->evalString( parmTagStr, pTags.getToken(), 0, 0 ); if ( !parmTagStr.equal( UT_String::getEmptyString() ) ) { UT_WorkArgs tokens; parmTagStr.tokenize( tokens, " " ); for ( int i = 0; i < tokens.getArgc(); ++i ) { tags.push_back( tokens[i] ); } } } // add tags from the registered tag readers std::vector<CustomTagReader> &tagReaders = customTagReaders(); for ( std::vector<CustomTagReader>::const_iterator it = tagReaders.begin(); it != tagReaders.end(); ++it ) { NameList values; it->m_read( node, values, includeChildren ); tags.insert( tags.end(), values.begin(), values.end() ); } // add tags based on primitive groups OBJ_Node *contentNode = retrieveNode( true )->castToOBJNode(); if ( contentNode && contentNode->getObjectType() == OBJ_GEOMETRY && m_splitter ) { GU_DetailHandle newHandle = m_splitter->split( contentPathValue() ); if ( !newHandle.isNull() ) { GU_DetailHandleAutoReadLock readHandle( newHandle ); if ( const GU_Detail *geo = readHandle.getGdp() ) { GA_Range prims = geo->getPrimitiveRange(); for ( GA_GroupTable::iterator<GA_ElementGroup> it=geo->primitiveGroups().beginTraverse(); !it.atEnd(); ++it ) { GA_PrimitiveGroup *group = static_cast<GA_PrimitiveGroup*>( it.group() ); if ( group->getInternal() || group->isEmpty() ) { continue; } const UT_String &groupName = group->getName(); if ( groupName.startsWith( tagGroupPrefix ) && group->containsAny( prims ) ) { UT_String tag; groupName.substr( tag, tagGroupPrefix.length() ); tag.substitute( "_", ":" ); tags.push_back( tag.buffer() ); } } } } } }
void SOP_Scallop::SaveData(float time) { OP_Context context(time); bool clip = (lockInputs(context) < UT_ERROR_ABORT); UT_BoundingBox bbox; if(clip) { const GU_Detail* input = inputGeo(0,context); if(input != NULL) { int res = input->getBBox(&bbox); if(res == 0) clip = false; } else clip = false; unlockInputs(); }; UT_String file; STR_PARM(file,"path", 8, 0, time); FILE* fp = fopen(file.buffer(),"wb"); if(fp == NULL) return; float& now=time; ////////////////////////////////////////////////////////////////////////// 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); }; Daemon::now=now; Daemon::bias = evalFloat("bias",0,now); 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; obj->getWorldTransform(d.xform,context); d.weight = evalFloatInst("weight#",&i,0,now); 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); 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; } 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); //fwrite(&total,sizeof(int),1,fp); UT_Vector3 current(0,0,0); float* C = data; float R=1.0f; float rScale = evalFloat("radiiscale",0,now); float param=0.0f; srand(0); for(int i=-50;i<total;i++) { bool ok = false; float w = double(rand())/double(RAND_MAX); for(int j=0;j<totd;j++) { ok = daemons[j].Transform(w,current,C,R,*G); if(ok) break; }; if(i<0) continue; if(clip) { if(!bbox.isInside(current)) continue; }; if(ok) { if(useRamp) { float out[4]; ramp.rampLookup(data[3],out); memcpy(data,out,12); } fwrite(current.vec,12,1,fp); // P float r = R*rScale; fwrite(&r,4,1,fp); // R fwrite(data,16,1,fp); // Cs+p }; }; delete [] daemons; ////////////////////////////////////////////////////////////////////////// fclose(fp); };
void SOP_Scallop::SaveDivMap(float time) { OP_Context context(time); 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(); }; if(!clip) return; UT_String file; STR_PARM(file,"mappath", 11, 0, time); float& now=time; ////////////////////////////////////////////////////////////////////////// Daemon::now=now; Daemon::bias = evalFloat("bias",0,now); int cnt = evalInt("daemons", 0, now); Daemon* daemons=new Daemon[cnt]; float weights = 0; int totd=0; float maxR = 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; obj->getWorldTransform(d.xform,context); d.weight = evalFloatInst("weight#",&i,0,now); 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); 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); if(d.radius > maxR) maxR = d.radius; weights+=d.weight; totd++; }; if(totd == 0) { delete [] daemons; return; }; 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; GU_Detail det; UT_Vector3 current(0,0,0); float C[3] = { 0,0,0 }; float R=1.0f; float param=0.0f; srand(0); bool medial = (evalInt("mapmedial",0,now)!=0); int mapdiv = evalInt("mapdiv",0,now); //BoundBox Box; OctreeBox O(mapdiv); //if(medial) //{ O.bbox=bbox; //} //else //{ // BoundBox::limit = evalInt("nodecount", 0, now); // BoundBox::medial = (evalInt("mapmedial",0,now)!=0); // float boxb[6]; // memcpy(boxb,bbox.minvec().vec,12); // memcpy(boxb+3,bbox.maxvec().vec,12); // Box.Organize(boxb); //}; for(int i=-50;i<total;i++) { bool ok = false; 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(medial) //{ float P[4] = { current.x(), current.y(), current.z(), R }; O.Insert(P); //} //else //{ // Box.CheckPoint(current.vec); //} }; delete [] daemons; ////////////////////////////////////////////////////////////////////////// int ita[3] = {-1,-1,-1}; //if(medial) //{ int count = 0; OctreeBox::at = det.addPrimAttrib("count",4,GB_ATTRIB_INT,&count); det.addVariableName("count","COUNT"); float radius = 0.0f; OctreeBox::rt = det.addAttrib("radius",4,GB_ATTRIB_FLOAT,&radius); det.addVariableName("radius","RADIUS"); OctreeBox::it = det.addPrimAttrib("mask",12,GB_ATTRIB_INT,ita); det.addVariableName("mask","MASK"); float box[6] = {bbox.xmin(),bbox.xmax(),bbox.ymin(),bbox.ymax(),bbox.zmin(),bbox.zmax()}; det.addAttrib("bbox",24,GB_ATTRIB_FLOAT,box); O.maxlevel = 0x01<<mapdiv; O.parentbbox = bbox; O.Build(det); //} //else Box.Build(det); det.save(file.buffer(),1,NULL); // ...SAVE ATLAS { UT_String atlas =file; atlas+=".atlas"; FILE* fa = fopen(atlas.buffer(),"wb"); GEO_PrimList& pl = det.primitives(); int cnt = pl.entries(); fwrite(&cnt,sizeof(int),1,fa); float bb[6] = { bbox.xmin(), bbox.xmax(), bbox.ymin(), bbox.ymax(), bbox.zmin(), bbox.zmax() }; fwrite(bb,sizeof(float),6,fa); fwrite(&(O.maxlevel),sizeof(int),1,fa); fwrite(&(O.maxlevel),sizeof(int),1,fa); fwrite(&(O.maxlevel),sizeof(int),1,fa); for(int i=0;i<cnt;i++) { const GEO_PrimVolume* v = dynamic_cast<const GEO_PrimVolume*>(pl[i]); UT_BoundingBox b; v->getBBox(&b); float _bb[6] = { b.xmin(), b.xmax(), b.ymin(), b.ymax(), b.zmin(), b.zmax() }; fwrite(_bb,sizeof(float),6,fa); // MASK fwrite(v->castAttribData<int>(OctreeBox::it),sizeof(int),3,fa); } fclose(fa); } };