Example #1
0
bool writeBGEO(const char* filename,const ParticlesData& p,const bool compressed)
{
    auto_ptr<ostream> output(
        compressed ? 
        Gzip_Out(filename,ios::out|ios::binary)
        :new ofstream(filename,ios::out|ios::binary));

    if(!*output){
        cerr<<"Partio Unable to open file "<<filename<<endl;
        return false;
    }

    int magic=((((('B'<<8)|'g')<<8)|'e')<<8)|'o';
    char versionChar='V';
    int version=5;
    int nPoints=p.numParticles();
    int nPrims=1;
    int nPointGroups=0;
    int nPrimGroups=0;
    int nPointAttrib=p.numAttributes()-1;
    int nVertexAttrib=0;
    int nPrimAttrib=1;
    int nAttrib=0;

    write<BIGEND>(*output,magic,versionChar,version,nPoints,nPrims,nPointGroups);
    write<BIGEND>(*output,nPrimGroups,nPointAttrib,nVertexAttrib,nPrimAttrib,nAttrib);

    vector<ParticleAttribute> handles;
    vector<ParticleAccessor> accessors;
    vector<int> attrOffsets;
    bool foundPosition=false;
    int particleSize=4;
    for(int i=0;i<p.numAttributes();i++){
        ParticleAttribute attr;
        p.attributeInfo(i,attr);
        if(attr.name=="position"){
            attrOffsets.push_back(0);
            foundPosition=true;
        }else{
            writeHoudiniStr(*output,attr.name);
            if(attr.type==INDEXEDSTR){
                int houdiniType=4;
                unsigned short size=attr.count;
                const std::vector<std::string>& indexTable=p.indexedStrs(attr);
                int numIndexes=indexTable.size();
                write<BIGEND>(*output,size,houdiniType,numIndexes);
                for(int i=0;i<numIndexes;i++)
                    writeHoudiniStr(*output,indexTable[i]);
            }else{
                int houdiniType=0;
                switch(attr.type){
                    case FLOAT: houdiniType=0;break;
                    case INT: houdiniType=1;break;
                    case VECTOR: houdiniType=5;break;
                    case INDEXEDSTR:
                    case NONE: assert(false);houdiniType=0;break;
                }
                unsigned short size=attr.count;
                write<BIGEND>(*output,size,houdiniType);
                for(int i=0;i<attr.count;i++){
                    int defaultValue=0;
                    write<BIGEND>(*output,defaultValue);
                }
            }
            attrOffsets.push_back(particleSize);
            particleSize+=attr.count;
        }
        handles.push_back(attr);
        accessors.push_back(ParticleAccessor(handles.back()));
    }
    if(!foundPosition){
        cerr<<"Partio: didn't find attr 'position' while trying to write GEO"<<endl;
        return false;
    }

    ParticlesData::const_iterator iterator=p.begin();
    for(size_t i=0;i<accessors.size();i++) iterator.addAccessor(accessors[i]);

    int *buffer=new int[particleSize];
    for(ParticlesData::const_iterator end=p.end();iterator!=end;++iterator){
        for(unsigned int attrIndex=0;attrIndex<handles.size();attrIndex++){
            ParticleAttribute& handle=handles[attrIndex];
            ParticleAccessor& accessor=accessors[attrIndex];
            // TODO: this violates strict aliasing, we could just go to char* and make
            // a different endian swapper
            const int* data=accessor.raw<int>(iterator);
            for(int k=0;k<handle.count;k++){
                buffer[attrOffsets[attrIndex]+k]=data[k];
                BIGEND::swap(buffer[attrOffsets[attrIndex]+k]);
            }
        }        
        // set homogeneous coordinate
        float *w=(float*)&buffer[3];
        *w=1.;
        BIGEND::swap(*w);
        output->write((char*)buffer,particleSize*sizeof(int));
    }
    delete [] buffer;

    // Write primitive attribs
    writeHoudiniStr(*output,"generator");
    write<BIGEND>(*output,(short)0x1); // count 1
    write<BIGEND>(*output,(int)0x4); // type 4 index
    write<BIGEND>(*output,(int)0x1); // type 4 index
    writeHoudiniStr(*output,"papi");

    // Write the primitive
    write<BIGEND>(*output,(int)0x8000);
    write<BIGEND>(*output,(int)nPoints);
    if(nPoints>(int)1<<16)
        for(int i=0;i<nPoints;i++) write<BIGEND>(*output,(int)i);
    else
        for(int i=0;i<nPoints;i++) write<BIGEND>(*output,(unsigned short)i);
    write<BIGEND>(*output,(int)0);

    // Write extra
    write<BIGEND>(*output,(char)0x00);
    write<BIGEND>(*output,(char)0xff);

    // success
    return true;
}
Example #2
0
bool writeRIB(const char* filename, const ParticlesData& p, const bool compressed,std::ostream* errorStream)
{
    auto_ptr<ostream> output(
        compressed ? Gzip_Out(filename, ios::out | ios::binary)
        : new ofstream(filename, ios::out | ios::binary));

    ParticleAttribute dummy;
    bool foundP     = p.attributeInfo("position",  dummy) || p.attributeInfo("P",     dummy);
    bool foundP2    = p.attributeInfo("position2", dummy) || p.attributeInfo("P2",    dummy);
    bool foundWidth = p.attributeInfo("radius",    dummy) || p.attributeInfo("width", dummy) || p.attributeInfo("radiusPP", dummy);

    if (!foundP)
    {
        if(errorStream) *errorStream << "Partio: failed to find attr 'position' or 'P' for RIB output" << endl;
        return false;
    }

    if (!foundWidth)
        if(errorStream) *errorStream << "Partio: failed to find attr 'width','radius', or 'radiusPP' for RIB output, using constantwidth = 1" << endl;

    *output << "version 3.04" << endl;

    if (foundP2)
        *output << "GeometricApproximation \"motionfactor\" 1.0" << endl;

    *output << "AttributeBegin" << endl;
    *output << "  ResourceBegin" << endl;
    *output << "    Attribute \"identifier\" \"name\" [\"|partioParticle1|partioParticleShape1\"]" << endl;

    int numPasses = foundP2 ? 2 : 1;

    if (foundP2)
        *output << "    MotionBegin [0.0 1.0]" << endl;

    for (int passIndex = 0; passIndex < numPasses; ++passIndex)
    {
        *output << (foundP2 ? "  " : "") << "    Points ";

        for (int attrIndex = 0; attrIndex < p.numAttributes(); ++attrIndex)
        {
            ParticleAttribute attr;
            p.attributeInfo(attrIndex, attr);

            if ((passIndex == 0 && (attr.name == "P2" || attr.name == "position2")) ||
                    (passIndex == 1 && (attr.name == "P"  || attr.name == "position"))) continue;

            string attrname = (attr.name == "position" || attr.name == "position2" || attr.name == "P" || attr.name == "P2")
                              ? "P"
                              : (attr.name == "radius" ? "width" : attr.name);

            *output << "\"" << attrname << "\" [ ";
			int spaceCount = 0;
            switch (attr.type)
            {
            case Partio::FLOAT:
            case Partio::VECTOR:
			{
                for (int particleIndex = 0; particleIndex < p.numParticles(); ++particleIndex)
                {
                    const float *data = p.data<float>(attr, particleIndex);
                    for (int count = 0; count < attr.count; ++count)
					{
                        *output << data[count] << " ";
						spaceCount ++;
					}
                    if (spaceCount > 12)
                    {
                        *output << "\n    ";
                        spaceCount = 0;
                    }
                }
                break;
			}
            case Partio::INT:
			{
                for (int particleIndex = 0; particleIndex < p.numParticles(); ++particleIndex)
                {
                    const int *data = p.data<int>(attr, particleIndex);
                    for (int count = 0; count < attr.count; ++count)
					{
                        *output << data[count] << " ";
						spaceCount ++;
					}
					if (spaceCount > 12)
                    {
                        *output << "\n    ";
                        spaceCount = 0;
                    }
                }
                break;
			}
            case Partio::NONE:
            default:
                break;
            }

            *output << "]\n    ";
        }

        if (!foundWidth)
            *output << "\"constantwidth\" [1.0]";

        *output << endl;
    }

    if (foundP2)
        *output << "    MotionEnd" << endl;

    *output << "  ResourceEnd" << endl;
    *output << "AttributeEnd" << endl;

    return true;
}
Example #3
0
bool writePRT(const char* filename,const ParticlesData& p,const bool /*compressed*/)
{
	/// Krakatoa pukes on 0 particle files for some reason so don't export at all....
    int numParts = p.numParticles();
    if (numParts)
    {
        std::auto_ptr<std::ostream> output(
        new std::ofstream(filename,std::ios::out|std::ios::binary));

        if (!*output) {
            std::cerr<<"Partio Unable to open file "<<filename<<std::endl;
            return false;
        }

        FileHeadder header;
        memcpy(header.magic, magic, sizeof(magic));
        memcpy(header.signature, signature, sizeof(signature));
        header.headersize = 0x38;
        header.version = 1;
        header.numParticles = p.numParticles();
        int reserve = 4;
        output->write((char*)&header,sizeof(FileHeadder));
        write<LITEND>(*output, reserve);
        write<LITEND>(*output, (int)p.numAttributes());
            reserve = 0x2c;
        write<LITEND>(*output, reserve);

        std::vector<ParticleAttribute> attrs;
        int offset = 0;
        for (int i=0;i<p.numAttributes();i++) {
            ParticleAttribute attr;
            p.attributeInfo(i,attr);
            Channel ch;
            memset(&ch, 0, sizeof(Channel));
                    memcpy((char*)ch.name, attr.name.c_str(), attr.name.size());
            ch.offset = offset;
            switch (attr.type) {
            case FLOAT: ch.type=4; ch.arity=attr.count; offset += sizeof(float)*attr.count; break;
            case INT: ch.type=1; ch.arity=attr.count; offset += sizeof(int)*attr.count; break;
            case VECTOR: ch.type=4; ch.arity=attr.count; offset += sizeof(float)*attr.count; break;
			case INDEXEDSTR:; break;
            case NONE:;break;
            }
            if (ch.arity) {
    #ifdef AUTO_CASES
                if (ch.name[0] >= 'a' && ch.name[0] <= 'z') {
                    ch.name[0] -= 0x20;
                }
    #endif
                output->write((char*)&ch,sizeof(Channel));
                attrs.push_back(attr);
            }
        }

        z_stream z;
        z.zalloc = Z_NULL;z.zfree = Z_NULL;z.opaque = Z_NULL;
        if (deflateInit( &z, Z_DEFAULT_COMPRESSION ) != Z_OK) {
            std::cerr<<"Zlib deflateInit error"<<std::endl;
            return false;
        }

        char out_buf[OUT_BUFSIZE+10];
        for (int particleIndex=0;particleIndex<p.numParticles();particleIndex++) {
            for (unsigned int attrIndex=0;attrIndex<attrs.size();attrIndex++) {
                if (attrs[attrIndex].type==Partio::INT) {
                    const int* data=p.data<int>(attrs[attrIndex],particleIndex);
                    if (!write_buffer(*output, z, (char*)out_buf, (void*)data, sizeof(int)*attrs[attrIndex].count, false))
                        return false;
                } else if (attrs[attrIndex].type==Partio::FLOAT || attrs[attrIndex].type==Partio::VECTOR) {
                    const float* data=p.data<float>(attrs[attrIndex],particleIndex);
                    if (!write_buffer(*output, z, (char*)out_buf, (void*)data, sizeof(int)*attrs[attrIndex].count, false))
                        return false;
                }
            }
        }
        write_buffer(*output, z, (char*)out_buf, 0, 0, true);
        if (deflateEnd( &z ) != Z_OK) {
            std::cerr<<"Zlib deflateEnd error"<<std::endl;
            return false;
        }
        // success
    }// end if numParticles > 0
    return true;
}
Example #4
0
bool writePTC(const char* filename,const ParticlesData& p,const bool compressed)
{
    //ofstream output(filename,ios::out|ios::binary);

    auto_ptr<ostream> output(
        compressed ? 
        Gzip_Out(filename,ios::out|ios::binary)
        :new ofstream(filename,ios::out|ios::binary));

    if(!*output){
        cerr<<"Partio Unable to open file "<<filename<<endl;
        return false;
    }

    // magic & version
    write<LITEND>(*output,ptc_magic);
    write<LITEND>(*output,(int)0);

    // particle count
    double numParticlesAsDouble=p.numParticles();
    write<LITEND>(*output,numParticlesAsDouble);

    ParticleAttribute positionHandle,normalHandle,radiusHandle;
    bool foundPosition=p.attributeInfo("position",positionHandle);
    bool foundNormal=p.attributeInfo("normal",normalHandle);
    bool foundRadius=p.attributeInfo("radius",radiusHandle);

    if(!foundPosition){
        cerr<<"Partio: failed to find attr 'position' for PTC output"<<endl;
        return false;
    }
    if(!foundNormal) cerr<<"Partio: failed to find attr 'normal' for PTC output, using 0,0,0"<<endl;
    if(!foundRadius) cerr<<"Partio: failed to find attr 'radius' for PTC output, using 1"<<endl;

    // compute bounding box
    float boxmin[3]={FLT_MAX,FLT_MAX,FLT_MAX},boxmax[3]={-FLT_MAX,-FLT_MAX,-FLT_MAX};
    for(int i=0;i<p.numParticles();i++){
        const float* pos=p.data<float>(positionHandle,i);
        for(int k=0;k<3;k++){
            boxmin[k]=min(pos[k],boxmin[k]);
            boxmax[k]=max(pos[k],boxmax[k]);
        }
    }
    write<LITEND>(*output,boxmin[0],boxmin[1],boxmin[2]);
    write<LITEND>(*output,boxmax[0],boxmax[1],boxmax[2]);

    // world-to-eye & 
    for(int i=0;i<4;i++) for(int j=0;j<4;j++){
            if(i==j) write<LITEND>(*output,(float)1);
            else write<LITEND>(*output,(float)0);
    }
    // eye-to-screen
    const float foo[4][4]={{1.8f,0,0,0}, {0,2.41f,0,0}, {0,0,1,1}, {0,0,-.1f,0}};
    for(int i=0;i<4;i++) for(int j=0;j<4;j++){
            write<LITEND>(*output,foo[i][j]);
    }
    

    // imgwidth imgheight, imgdepth
    write<LITEND>(*output,(float)640,(float)480,(float)300);

    int nVars=0,dataSize=0;
    vector<string> specs;
    vector<ParticleAttribute> attrs;
    for(int i=0;i<p.numAttributes();i++){
        ParticleAttribute attr;
        p.attributeInfo(i,attr);
        if(attr.name!="position" && attr.name!="radius" && attr.name!="normal"){
            if(attr.count==3 && attr.type!=INT){
                attrs.push_back(attr);
                specs.push_back("color "+attr.name+"\n");
                dataSize+=attr.count;
                nVars++;
            }else if(attr.count==1 && attr.type!=INT){
                attrs.push_back(attr);
                dataSize+=attr.count;
                nVars++;
                specs.push_back("float "+attr.name+"\n");
            }else if(attr.count==16 && attr.type!=INT){
                nVars++;
                attrs.push_back(attr);
                dataSize+=attr.count;
                specs.push_back("matrix "+attr.name+"\n");
            }else{
                cerr<<"Partio: Unable to write data type "<<TypeName(attr.type)<<"["<<attr.count<<"] to a ptc file"<<endl;
            }
        }
    }
    //cerr<<"writing dataSize"<<dataSize<<endl;
    write<LITEND>(*output,nVars,dataSize);

    for(unsigned int i=0;i<specs.size();i++){
        output->write(specs[i].c_str(),specs[i].length());
    }

    for(int pointIndex=0;pointIndex<p.numParticles();pointIndex++){
        // write position
        const float* pos=p.data<float>(positionHandle,pointIndex);
        write<LITEND>(*output,pos[0],pos[1],pos[2]);
        // write normal
        static const float static_n[3]={0,0,0};
        const float* n=static_n;
        if(foundNormal)
            n=p.data<float>(normalHandle,pointIndex);
        // normalize and encode normals as two unsigned short integers z and
        // phi, representing the z coordinate and angle in the xy plane.  The
        // special value z == phi == 65535 encodes a zero normal.
	int phi, z;
	if (n[0] == 0 && n[1] == 0 && n[2] == 0) phi = z = 65535;
	else {
            float mag_squared=n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
	    phi = int((atan2(n[0], n[1]) * (1/(2*M_PI)) + 0.5) * 65535 + 0.5);
	    z = std::min(int((n[2]/sqrt(mag_squared)+1)/2 * 65535 + 0.5), 65535);
            // phi is redundent when z == 65535; avoid the special value.
            if (phi == 65535 && z == 65535)
                phi = 0;
	}
        write<LITEND>(*output,(unsigned short)phi,(unsigned short)z);
        // write radius
        static const float static_r[1]={1.f};
        const float* radius=static_r;
        if(foundRadius)
            radius=p.data<float>(radiusHandle,pointIndex);
        write<LITEND>(*output,radius[0]);
        // write other attributes
        for(unsigned int i=0;i<specs.size();i++){
            const float* data=p.data<float>(attrs[i],pointIndex);
            for(int k=0;k<attrs[i].count;k++){
                write<LITEND>(*output,data[k]);
            }
        }
        
    }
    return true;
}