ParticlesDataMutable* readGEO(const char* filename,const bool headersOnly,char** attributes, int percentage) { auto_ptr<istream> input(Gzip_In(filename,ios::in)); if(!*input){ cerr<<"Partio: Can't open particle data file: "<<filename<<endl; return 0; } int NPoints=0, NPointAttrib=0; ParticlesDataMutable* simple=0; if(headersOnly) simple=new ParticleHeaders; else simple=create(); // read NPoints and NPointAttrib string word; while(input->good()){ *input>>word; if(word=="NPoints") *input>>NPoints; else if(word=="NPointAttrib"){*input>>NPointAttrib;break;}
ParticlesDataMutable* readBGEO(const char* filename,const bool headersOnly) { std::auto_ptr<std::istream> input(Gzip_In(filename,std::ios::in|std::ios::binary)); if(!*input){ std::cerr<<"Partio: Unable to open file "<<filename<<std::endl; return 0; } // header values int magic; char versionChar; int version; int nPoints; int nPrims; int nPointGroups; int nPrimGroups; int nPointAttrib; int nVertexAttrib; int nPrimAttrib; int nAttrib; read<BIGEND>(*input,magic,versionChar,version,nPoints,nPrims,nPointGroups); read<BIGEND>(*input,nPrimGroups,nPointAttrib,nVertexAttrib,nPrimAttrib,nAttrib); // Check header magic and version const int bgeo_magic=((((('B'<<8)|'g')<<8)|'e')<<8)|'o'; if(magic!=bgeo_magic){ std::cerr<<"Partio: Magic number '"<<magic<<" of '"<<filename<<"' doesn't match bgeo magic '"<<bgeo_magic<<std::endl; return 0; } if(version!=5){ std::cerr<<"Partio: BGEO must be version 5"<<std::endl; return 0; } // Allocate a simple particle with the appropriate number of points ParticlesDataMutable* simple=0; if(headersOnly) simple=new ParticleHeaders; else simple=create(); simple->addParticles(nPoints); // Read attribute definitions int particleSize=4; // Size in # of 32 bit primitives std::vector<int> attrOffsets; // offsets in # of 32 bit offsets std::vector<ParticleAttribute> attrHandles; std::vector<ParticleAccessor> accessors; attrOffsets.push_back(0); // pull values from byte offset attrHandles.push_back(simple->addAttribute("position",VECTOR,3)); // we always have one accessors.push_back(ParticleAccessor(attrHandles[0])); for(int i=0;i<nPointAttrib;i++){ unsigned short nameLength; read<BIGEND>(*input,nameLength); char* name=new char[nameLength+1]; input->read(name,nameLength);name[nameLength]=0; unsigned short size; int houdiniType; read<BIGEND>(*input,size,houdiniType); if(houdiniType==0 || houdiniType==1 || houdiniType==5){ // read default values. don't do anything with them for(int i=0;i<size;i++) { int defaultValue; input->read((char*)&defaultValue,sizeof(int)); } ParticleAttributeType type=NONE; if(houdiniType==0) type=FLOAT; else if(houdiniType==1) type=INT; else if(houdiniType==5) type=VECTOR; attrHandles.push_back(simple->addAttribute(name,type,size)); accessors.push_back(ParticleAccessor(attrHandles.back())); attrOffsets.push_back(particleSize); particleSize+=size; }else if(houdiniType==4){ std::cerr<<"Partio: attr '"<<name<<"' of type index (string) found, treating as integer"<<std::endl; int numIndices=0; read<BIGEND>(*input,numIndices); for(int ii=0;ii<numIndices;ii++){ unsigned short indexNameLength; read<BIGEND>(*input,indexNameLength); char* indexName=new char[indexNameLength+1];; input->read(indexName,indexNameLength); indexName[indexNameLength]=0; std::cerr<<"Partio: index "<<ii<<" is "<<indexName<<std::endl; delete [] indexName; } attrHandles.push_back(simple->addAttribute(name,INT,size)); accessors.push_back(ParticleAccessor(attrHandles.back())); attrOffsets.push_back(particleSize); particleSize+=size; }else if(houdiniType==2){ std::cerr<<"Partio: found attr of type 'string', aborting"<<std::endl; delete [] name; simple->release(); return 0; }else{ std::cerr<<"Partio: unknown attribute "<<houdiniType<<" type... aborting"<<std::endl; delete [] name; simple->release(); return 0; } delete[] name; } if(headersOnly) return simple; // escape before we try to edit data // Read the points int *buffer=new int[particleSize]; // make iterator and register accessors ParticlesDataMutable::iterator iterator=simple->begin(); for(size_t i=0;i<accessors.size();i++) iterator.addAccessor(accessors[i]); for(ParticlesDataMutable::iterator end=simple->end();iterator!=end;++iterator){ //for(int i=0;i<nPoints;i++){ input->read((char*)buffer,particleSize*sizeof(int)); for(unsigned int attrIndex=0;attrIndex<attrHandles.size();attrIndex++){ ParticleAttribute& handle=attrHandles[attrIndex]; ParticleAccessor& accessor=accessors[attrIndex]; // TODO: this violates strict aliasing, we could just go to char* and make // a different endian swapper int* data=accessor.raw<int>(iterator); for(int k=0;k<handle.count;k++){ BIGEND::swap(buffer[attrOffsets[attrIndex]+k]); data[k]=buffer[attrOffsets[attrIndex]+k]; } } } delete [] buffer; // return the populated simpleParticle return simple; }
ParticlesDataMutable* readPTC(const char* filename,const bool headersOnly) { std::auto_ptr<std::istream> input(Gzip_In(filename,std::ios::in|std::ios::binary)); if(!*input){ std::cerr<<"Partio: Unable to open file "<<filename<<std::endl; return 0; } int magic; read<LITEND>(*input,magic); if(ptc_magic!=magic){ std::cerr<<"Partio: Magic number '"<<magic<<"' of '"<<filename<<"' doesn't match pptc magic '"<<ptc_magic<<"'"<<std::endl; return 0; } int version; read<LITEND>(*input,version); double nPoints; read<LITEND>(*input,nPoints); // TODO: allow access to this in the headers only mode for times when only bbox is necessary float xmin,ymin,zmin,xmax,ymax,zmax; read<LITEND>(*input,xmin,ymin,zmin,xmax,ymax,zmax); float dummy; if (version>=1) for (int d=0;d<4;d++) read<LITEND>(*input,dummy); // world-to-eye for(int i=0;i<16;i++) read<LITEND>(*input,dummy); // eye-to-screen for(int i=0;i<16;i++) read<LITEND>(*input,dummy); float imgWidth,imgHeight,imgDepth; read<LITEND>(*input,imgWidth,imgHeight,imgDepth); int nVars,dataSize; read<LITEND>(*input,nVars,dataSize); // Allocate a simple particle with the appropriate number of points ParticlesDataMutable* simple=0; if(headersOnly) simple=new ParticleHeaders; else simple=create(); simple->addParticles((int)nPoints); // PTC files always have something for these items, so allocate the data std::vector<ParticleAttribute> attrHandles; ParticleAttribute positionHandle=simple->addAttribute("position",VECTOR,3); ParticleAttribute normalHandle=simple->addAttribute("normal",VECTOR,3); ParticleAttribute radiusHandle=simple->addAttribute("radius",FLOAT,1); std::string typeName,name; // data types are "float", "point", "vector", "normal", "color", or "matrix" int parsedSize=0; for(int chanNum=0;chanNum<nVars;chanNum++){ ParseSpec(GetString(*input,'\n'),typeName,name); int dataSize=0; ParticleAttributeType dataType; if(typeName=="color" || typeName=="vector" || typeName=="point" || typeName=="color"){ dataType=VECTOR; dataSize=3; }else if(typeName=="matrix"){ dataType=FLOAT; dataSize=16; }else if(typeName=="float"){ dataType=FLOAT; dataSize=1; }else{ std::cerr<<"Partio: "<<filename<<" had unknown attribute spec "<<typeName<<" "<<name<<std::endl; simple->release(); return 0; } attrHandles.push_back(simple->addAttribute(name.c_str(),dataType,dataSize)); parsedSize+=dataSize; } if(dataSize!=parsedSize){ std::cerr<<"Partio: error with PTC, computed dataSize ("<<dataSize <<") different from read one ("<<parsedSize<<")"<<std::endl; simple->release(); return 0; } // If all we care about is headers, then return. if(headersOnly){ return simple; } // more weird input attributes if(version>=1) for(int i=0;i<2;i++) read<LITEND>(*input,dummy); for(int pointIndex=0;pointIndex<nPoints;pointIndex++){ float* pos=simple->dataWrite<float>(positionHandle,pointIndex); read<LITEND>(*input,pos[0],pos[1],pos[2]); unsigned short phi,z; // normal encoded read<LITEND>(*input,phi,z); float* norm=simple->dataWrite<float>(normalHandle,pointIndex); // Convert unsigned short (phi,nz) to xyz normal // This packing code is based on Per Christensen's rman forum post if (phi != 65535 || z != 65535) { float nz = (float)z / 65535.0f; norm[2] = 2.0f * nz - 1.0f; float fphi = (float)phi / 65535.0f; fphi = 2.0 * M_PI * (fphi - 0.5); //assert(-M_PI-0.0001 <= fphi && fphi <= M_PI+0.0001); double rxy = sqrt(1.0 - norm[2]*norm[2]); norm[0] = rxy * sin(fphi); norm[1] = rxy * cos(fphi); } else { norm[0] = norm[1] = norm[2] = 0.0f; } float* radius=simple->dataWrite<float>(radiusHandle,pointIndex); read<LITEND>(*input,radius[0]); for(unsigned int i=0;i<attrHandles.size();i++){ float* data=simple->dataWrite<float>(attrHandles[i],pointIndex); for(int j=0;j<attrHandles[i].count;j++) read<LITEND>(*input,data[j]); } } return simple; }