diff options
Diffstat (limited to 'Build/source/utils/asymptote/prc/oPRCFile.cc')
-rw-r--r-- | Build/source/utils/asymptote/prc/oPRCFile.cc | 847 |
1 files changed, 847 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/prc/oPRCFile.cc b/Build/source/utils/asymptote/prc/oPRCFile.cc new file mode 100644 index 00000000000..77e28d76061 --- /dev/null +++ b/Build/source/utils/asymptote/prc/oPRCFile.cc @@ -0,0 +1,847 @@ +/************ +* +* This file is part of a tool for producing 3D content in the PRC format. +* Copyright (C) 2008 Orest Shardt <shardtor (at) gmail dot com> +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +* +*************/ + +#include "oPRCFile.h" +#include <time.h> + +using std::string; + +uint32_t PRCentity::getGraphicsIndex() +{ + if(useMaterial) + return parent->colourMap.size()+parent->getMaterialIndex(material); + else + return parent->getColourIndex(colour); +} + +void PRCline::writeRepresentationItem(PRCbitStream &out,uint32_t index) +{ + out << (uint32_t)(PRC_TYPE_RI_Curve); + ContentPRCBase(&EMPTY_ATTRIBUTES,"line",true,makeCADID(),0,makePRCID()).write(out); + writeGraphics(out,m1,getGraphicsIndex(),1); + out << (uint32_t)0 // index_local_coordinate_system+1 + << (uint32_t)0; // index_tessellation + + out << true // has wire body + << (uint32_t)index+1 // index of context in geometry section + << (uint32_t)1; // body index in topological context + UserData(0,0).write(out); +} + +void PRCline::writeTopologicalContext(PRCbitStream &out) +{ + // topological context + out << (uint32_t)(PRC_TYPE_TOPO_Context); + EMPTY_CONTENTPRCBASE.write(out); + out << (uint8_t)0 // behaviour + << 0.0 // granularity + << 0.0 // tolerance + << false // have smallest face thickness + << false; // have scale + + out << (uint32_t)1; // number of bodies + // body + out << (uint32_t)PRC_TYPE_TOPO_SingleWireBody; + + out << false // base topology: no base information + << (uint8_t)0; // content body: behaviour + // Not sure what a 0 means, since it satisfies no #define, + // but I think it means no bbox + + // wire edge + out << false // not already stored + << (uint32_t)PRC_TYPE_TOPO_WireEdge + << false; // base topology: no base information + + // polyline + out << false // not already stored + << (uint32_t)PRC_TYPE_CRV_PolyLine + << false // base topology: no base information + << (uint32_t)KEPRCExtendTypeNone // extend info + << true // is 3d + << false // no transformation + << 0.0 << static_cast<double>(numberOfPoints-1) // parameterization interval + << 1.0 // no reparameterization + << 0.0 // no reparameterization + << (uint32_t)numberOfPoints; + + // points + for(uint32_t i = 0; i < numberOfPoints; ++i) + out << points[i][0]*scale << points[i][1]*scale << points[i][2]*scale; + + // ending of wire edge + out << false; // trim surface domain +} + +void PRCline::writeExtraGeometryContext(PRCbitStream &out) +{ + //geometry summary + out << (uint32_t)1; // number of bodies + out << (uint32_t)PRC_TYPE_TOPO_SingleWireBody; // body's serial type + //context graphics + out << (uint32_t)0; // number of treat types +} + +void PRCcurve::writeRepresentationItem(PRCbitStream &out,uint32_t index) +{ + out << (uint32_t)(PRC_TYPE_RI_Curve); + ContentPRCBase(&EMPTY_ATTRIBUTES,"curve",true,makeCADID(),0,makePRCID()).write(out); + writeGraphics(out,m1,getGraphicsIndex(),1); + out << (uint32_t)0 // index_local_coordinate_system+1 + << (uint32_t)0; // index_tessellation + + out << true // has wire body + << (uint32_t)index+1 // index of context in geometry section + << (uint32_t)1; // body index in topological context + UserData(0,0).write(out); +} + +void PRCcurve::writeTopologicalContext(PRCbitStream &out) +{ + // topological context + out << (uint32_t)(PRC_TYPE_TOPO_Context); + EMPTY_CONTENTPRCBASE.write(out); + out << (uint8_t)0 // behaviour + << 0.0 // granularity + << 0.0 // tolerance + << false // have smallest face thickness + << false; // have scale + + out << (uint32_t)1; // number of bodies + // body + out << (uint32_t)PRC_TYPE_TOPO_SingleWireBody; + + out << false // base topology: no base information + << (uint8_t)0; // content body: behaviour + // Not sure what a 0 means, since it satisfies no #define, + // but I think it means no bbox + + // wire edge + out << false // not already stored + << (uint32_t)PRC_TYPE_TOPO_WireEdge + << false; // base topology: no base information + + // curve + out << false // not already stored + << (uint32_t)PRC_TYPE_CRV_NURBS + << false // base topology: no base information + << (uint32_t)KEPRCExtendTypeNone // extend info + << true // is 3D + << isRational + << (uint32_t)degree // degree + << (uint32_t)numberOfControlPoints-1 // control points - 1 + << (uint32_t)degree+numberOfControlPoints; // knots - 1 + + // control points + for(uint32_t i = 0; i < numberOfControlPoints; ++i) + { + out << controlPoints[i][0]*scale << controlPoints[i][1]*scale + << controlPoints[i][2]*scale; + if(isRational) + out << weights[i]; + } + + writeKnots(out); + + out << (uint32_t)KEPRCKnotTypeUnspecified // KEPRCKnotTypePiecewiseBezierKnots + << (uint32_t)KEPRCBSplineCurveFormUnspecified; // curve form + + // ending of wire edge + out << false; // trim surface domain + +} + +void PRCcurve::writeExtraGeometryContext(PRCbitStream &out) +{ + //geometry summary + out << (uint32_t)1; // number of bodies + out << (uint32_t)PRC_TYPE_TOPO_SingleWireBody; // body's serial type + //context graphics + out << (uint32_t)0; // number of treat types +} + +void PRCsurface::writeRepresentationItem(PRCbitStream &out,uint32_t index) +{ + out << (uint32_t)(PRC_TYPE_RI_BrepModel); + ContentPRCBase(&EMPTY_ATTRIBUTES,"surface",true,makeCADID(),0,makePRCID()).write(out); + writeGraphics(out,0,getGraphicsIndex(),1); + out << (uint32_t)0 // index_local_coordinate_system+1 + << (uint32_t)0; // index_tessellation + + out << true // has brep data + << (uint32_t)index+1 // index of context in geometry section + << (uint32_t)1 // body index in topological context + << false; // is closed???? when is it closed? + UserData(0,0).write(out); +} + +void PRCsurface::writeTopologicalContext(PRCbitStream &out) +{ + // topological context + out << (uint32_t)(PRC_TYPE_TOPO_Context); + EMPTY_CONTENTPRCBASE.write(out); + out << (uint8_t)0 // behaviour + << granularity // granularity + << 0.0 // tolerance + << false // have smallest face thickness + << false; // have scale + + out << (uint32_t)1; // number of bodies + // body + out << (uint32_t)PRC_TYPE_TOPO_BrepData; + + out << false // base topology: no base information + << (uint8_t)0 // content body: behaviour. Not sure what a 0 means, since it satisfies no #define, but I think it means no bbox + << (uint32_t)1; // number of connex + + // connex + out << false // not already stored + << (uint32_t)PRC_TYPE_TOPO_Connex + << false // base topology: no base information + << (uint32_t)1; // number of shells + + // shell + out << false // not already stored + << (uint32_t)PRC_TYPE_TOPO_Shell + << false // base topology: no base information + << false // shell is closed + << (uint32_t)1; // number of faces + + // face + out << false // not already stored + << (uint32_t)PRC_TYPE_TOPO_Face + << false; // base topology: no base information + + // NURBS + out << false // not already stored + << (uint32_t)PRC_TYPE_SURF_NURBS + << false // base topology: no base information + << (uint32_t)KEPRCExtendTypeNone // Extend Info + << isRational // is rational + << (uint32_t)degreeU // degree in u + << (uint32_t)degreeV // degree in v + << (uint32_t)numberOfControlPointsU-1 // control points in u - 1 + << (uint32_t)numberOfControlPointsV-1 // control points in v - 1 + << (uint32_t)degreeU+numberOfControlPointsU // knots in u - 1 + << (uint32_t)degreeV+numberOfControlPointsV; // knots in v -1 + + // control points + for(uint32_t i = 0; i < numberOfControlPointsU*numberOfControlPointsV; ++i) + { + out << controlPoints[i][0]*scale << controlPoints[i][1]*scale + << controlPoints[i][2]*scale; + if(isRational) + out << weights[i]; + } + + writeKnots(out); + + out << (uint32_t)KEPRCKnotTypeUnspecified // KEPRCKnotTypePiecewiseBezierKnots + << (uint32_t)KEPRCBSplineSurfaceFormUnspecified; // surface form + + // ending of face + out << false // trim surface domain + << false // have tolerance + << (uint32_t)0 // number of loops + << (int32_t)-1; // outer loop index + + // ending of shell + out << (uint8_t)1; + // orientation of surface normal w.r.t. face normal: + // 0: same, 1: opposite, 2: unknown, 1 used in example +} + +void PRCsurface::writeExtraGeometryContext(PRCbitStream &out) +{ + //geometry summary + out << (uint32_t)1; // number of bodies + out << (uint32_t)PRC_TYPE_TOPO_BrepData; // body's serial type + //context graphics + out << (uint32_t)0; // number of treat types +} + + +void PRCCompressedSection::write(std::ostream &out) +{ + if(prepared) + out.write((char*)data,getSize()); +} + +void PRCCompressedSection::prepare() +{ + writeData(); + compress(); + prepared = true; +} + +uint32_t PRCCompressedSection::getSize() +{ + if(!prepared) + return m1; + else + return out.getSize(); +} + +void PRCGlobalsSection::writeData() +{ + // even though this is technically not part of this section, + // it is handled here for convenience + out << (uint32_t)(0); // number of schemas + out << (uint32_t)PRC_TYPE_ASM_FileStructureGlobals; + + SingleAttributeData value = {PRCVersion}; + SingleAttribute sa(false,EMPTY_ATTRIBUTE_TITLE,KEPRCModellerAttributeTypeInt,value); + AttributeTitle iv; iv.text = "__PRC_RESERVED_ATTRIBUTE_PRCInternalVersion"; + Attribute a(false,iv,1,&sa); + Attributes as(1,&a); + ContentPRCBase(&as).write(out); + out << numberOfReferencedFileStructures; // no referencing of file structures + out << tessellationChordHeightRatio; + out << tessellationAngleDegrees; + out << defaultFontFamilyName; // markup serialization helper + + out << numberOfFonts + << (uint32_t)parent->colourMap.size(); + for(std::vector<RGBAColour>::iterator i = parent->colourMap.begin(); i != parent->colourMap.end(); i++) + { + out << i->R << i->G << i->B; + } + out << numberOfPictures << numberOfTextureDefinitions; + + out << (uint32_t)parent->materialMap.size(); // number of materials + for(std::vector<PRCMaterial>::iterator i = parent->materialMap.begin(); i != parent->materialMap.end(); i++) + { + out << (uint32_t)PRC_TYPE_GRAPH_Material; + ContentPRCBase(&EMPTY_ATTRIBUTES,"",true,makeCADID(),0,makePRCID()).write(out); + out << 3*parent->getColourIndex(i->ambient)+1 // ambient + 1 + << 3*parent->getColourIndex(i->diffuse)+1 // diffuse + 1 + << 3*parent->getColourIndex(i->emissive)+1 // emissive + 1 + << 3*parent->getColourIndex(i->specular)+1 // specular + 1 + << i->shininess // shininess + << i->ambient.A // ambient_alpha + << i->diffuse.A // diffuse_alpha + << i->emissive.A // emissive_alpha + << i->specular.A; // specular_alpha + } + + out << (uint32_t)1 // number of line patterns hard coded for now + << (uint32_t)PRC_TYPE_GRAPH_LinePattern; + ContentPRCBase(&EMPTY_ATTRIBUTES,"",true,makeCADID(),0,makePRCID()).write(out); + out << (uint32_t)0 // number of lengths + << 0.0 // phase + << false; // is real length + + out << (uint32_t)(parent->colourMap.size()+parent->materialMap.size()); // number of styles + uint32_t index = 0; + // colours are written first + for(std::vector<RGBAColour>::iterator i = parent->colourMap.begin(); i != parent->colourMap.end(); i++, ++index) + { + out << (uint32_t)PRC_TYPE_GRAPH_Style; + ContentPRCBase(&EMPTY_ATTRIBUTES,"",true,makeCADID(),0,makePRCID()).write(out); + out << 0.0 // line width in mm + << false // is vpicture + << (uint32_t)1 // line pattern index+1 + << false // is material + << (uint32_t)(3*index+1); // 3*color_index+1 + if(i->A < 1.0) + out << true << (uint8_t)(i->A * 256); + else + out << false; + out << false // additional 1 not defined + << false // additional 2 not defined + << false; // additional 3 not defined + } + // materials are after colours + index = 0; + for(std::vector<PRCMaterial>::iterator i = parent->materialMap.begin(); i != parent->materialMap.end(); i++, ++index) + { + out << (uint32_t)PRC_TYPE_GRAPH_Style; + ContentPRCBase(&EMPTY_ATTRIBUTES,"",true,makeCADID(),0,makePRCID()).write(out); + out << 0.0 // line width in mm + << false // is vpicture + << (uint32_t)1 // line pattern index+1 + << true // is material + << index+1; // material_index+1 + if(i->alpha < 1.0) + out << true << (uint8_t)(i->alpha * 256); + else + out << false; + out << false // additional 1 not defined + << false // additional 2 not defined + << false; // additional 3 not defined + } + out << numberOfFillPatterns + << numberOfReferenceCoordinateSystems; + userData.write(out); +} + +void PRCTreeSection::writeData() +{ + out << (uint32_t)(PRC_TYPE_ASM_FileStructureTree); + + EMPTY_CONTENTPRCBASE.write(out); + + out << (uint32_t)1; // number of part definitions + // part definitions + out << (uint32_t)(PRC_TYPE_ASM_PartDefinition); + ContentPRCBase(&EMPTY_ATTRIBUTES,"",true,makeCADID(),0,makePRCID()).write(out); + writeGraphics(out,m1,m1,1,true); + Point3d M=Point3d(1e20,1e20,1e20); + Point3d m=Point3d(-1e20,-1e20,-1e20); + Extent3d(M,m).write(out); + + out << (uint32_t)parent->fileEntities.size(); // number of representation items + for(uint32_t i = 0; i < parent->fileEntities.size(); ++i) + { + parent->fileEntities[i]->writeRepresentationItem(out,i); + } + + writeEmptyMarkups(out); + + out << (uint32_t)0; // no views + + UserData(0,0).write(out); + out << (uint32_t)1; // number of product occurrences + // only one product occurrence + out << (uint32_t)(PRC_TYPE_ASM_ProductOccurence); + SingleAttribute sas[3]; + SingleAttributeData sad; + AttributeTitle at; + + at.text = "FilePath"; + sad.text = "file name not specified"; + sas[0] = SingleAttribute(false,at,KEPRCModellerAttributeTypeString,sad); + + at.text = "FileSize"; + sad.integer = 1234; + sas[1] = SingleAttribute(false,at,KEPRCModellerAttributeTypeInt,sad); + + at.text = "FileModificationTime"; + sad.time = time(NULL); + sas[2] = SingleAttribute(false,at,KEPRCModellerAttributeTypeInt,sad); + + at.text = "__PRC_RESERVED_ATTRIBUTE_A3DF_ProductInformation"; + Attribute attr(false,at,3,sas); + Attributes attrs(1,&attr); + ContentPRCBase(&attrs,"Unknown",true,makeCADID(),0,makePRCID()).write(out); + + writeGraphics(out,m1,m1,1,true); + out << (uint32_t)1 // index_part+1 + << (uint32_t)0 // index_prototype+1 + << (uint32_t)0 // index_external_data+1 + << (uint32_t)0 // number of son product occurrences + << (uint8_t)0; // product behaviour + writeUnit(out,true,10.0); + out << (uint8_t)0 // product information flags + << (uint32_t)KEPRCProductLoadStatus_Loaded; // product_load_status + out << false // has location + << (uint32_t)0; // number of references + writeEmptyMarkups(out); + out << (uint32_t)0 // number_of_views + << false // has entity filter + << (uint32_t)0 // number_of_display_filters + << (uint32_t)0; // number_of_scene_display_parameters + UserData(0,0).write(out); + + // File Structure Internal Data + out << (uint32_t)(PRC_TYPE_ASM_FileStructure); + EMPTY_CONTENTPRCBASE.write(out); + out << makePRCID(); // next available index + out << (uint32_t)1; // product occurrence index + + UserData(0,0).write(out); +} + +void PRCTessellationSection::writeData() +{ + out << (uint32_t)(PRC_TYPE_ASM_FileStructureTessellation); + + EMPTY_CONTENTPRCBASE.write(out); + out << (uint32_t)0; // number of tessellations + UserData(0,0).write(out); // no user data +} + +void PRCGeometrySection::writeData() +{ + out << (uint32_t)(PRC_TYPE_ASM_FileStructureGeometry); + + EMPTY_CONTENTPRCBASE.write(out); + out << (uint32_t)parent->fileEntities.size(); // number of topological contexts + for(uint32_t i = 0; i < parent->fileEntities.size(); ++i) + { + parent->fileEntities[i]->writeTopologicalContext(out); + } + + UserData(0,0).write(out); +} + +void PRCExtraGeometrySection::writeData() +{ + out << (uint32_t)(PRC_TYPE_ASM_FileStructureExtraGeometry); + + EMPTY_CONTENTPRCBASE.write(out); + out << (uint32_t)parent->fileEntities.size(); // number of contexts + for(uint32_t i = 0; i < parent->fileEntities.size(); ++i) + { + parent->fileEntities[i]->writeExtraGeometryContext(out); + } + + UserData(0,0).write(out); +} + +void PRCModelFile::writeData() +{ + // even though this is technically not part of this section, + // it is handled here for convenience + out << (uint32_t)(0); // number of schemas + out << (uint32_t)(PRC_TYPE_ASM_ModelFile); + + SingleAttributeData value = {PRCVersion}; + SingleAttribute sa(false,EMPTY_ATTRIBUTE_TITLE,KEPRCModellerAttributeTypeInt,value); + AttributeTitle at; at.text = "__PRC_RESERVED_ATTRIBUTE_PRCInternalVersion"; + Attribute a(false,at,1,&sa); + Attributes as(1,&a); + ContentPRCBase(&as,"PRC file").write(out); + + writeUnit(out,true,10); // unit is 10 mm, and happens to come from a CAD file + + out << (uint32_t)1; // 1 product occurrence + //UUID + out << parent->fileStructures[0]->header.fileStructureUUID[0] + << parent->fileStructures[0]->header.fileStructureUUID[1] + << parent->fileStructures[0]->header.fileStructureUUID[2] + << parent->fileStructures[0]->header.fileStructureUUID[3]; + // index+1 + out << (uint32_t)1; + // active + out << true; + out << (uint32_t)0; // index in model file + + UserData(0,0).write(out); +} + +void makeFileUUID(uint32_t *UUID) +{ + // make a UUID + static uint32_t count = 0; + ++count; + // the minimum requirement on UUIDs is that all must be unique in the file + UUID[0] = 0x33595341; // some constant + UUID[1] = time(NULL); // the time + UUID[2] = count; + UUID[3] = 0xa5a55a5a; // Something random, not seeded by the time, would be nice. But for now, a constant + // maybe add something else to make it more unique + // so multiple files can be combined + // a hash of some data perhaps? +} + +void makeAppUUID(uint32_t *UUID) +{ + UUID[0] = UUID[1] = UUID[2] = UUID[3] = 0; +} + +void writeUINT32_T(std::ostream &out, uint32_t data) +{ +#ifdef WORDS_BIG_ENDIAN + out.write(((char*)&data)+3,1); + out.write(((char*)&data)+2,1); + out.write(((char*)&data)+1,1); + out.write(((char*)&data)+0,1); +#elif WORDS_LITTLE_ENDIAN + out.write(((char*)&data)+0,1); + out.write(((char*)&data)+1,1); + out.write(((char*)&data)+2,1); + out.write(((char*)&data)+3,1); +#endif +} + +void PRCUncompressedFile::write(std::ostream &out) +{ + writeUINT32_T(out,file_size); + out.write((char*)data,file_size); +} + +uint32_t PRCUncompressedFile::getSize() +{ + return sizeof(file_size)+file_size; +} + + +void PRCStartHeader::write(std::ostream &out) +{ + out.write("PRC",3); + writeUINT32_T(out,minimal_version_for_read); + writeUINT32_T(out,authoring_version); + writeUINT32_T(out,fileStructureUUID[0]); + writeUINT32_T(out,fileStructureUUID[1]); + writeUINT32_T(out,fileStructureUUID[2]); + writeUINT32_T(out,fileStructureUUID[3]); + + writeUINT32_T(out,applicationUUID[0]); + writeUINT32_T(out,applicationUUID[1]); + writeUINT32_T(out,applicationUUID[2]); + writeUINT32_T(out,applicationUUID[3]); +} + +uint32_t PRCStartHeader::getSize() +{ + return 3+(2+2*4)*sizeof(uint32_t); +} + + +void PRCFileStructure::write(std::ostream &out) +{ + header.write(out); + writeUINT32_T(out,number_of_uncompressed_files); + for(uint32_t i = 0; i < number_of_uncompressed_files; ++i) + { + uncompressedFiles[i].write(out); + } + globals.write(out); + tree.write(out); + tessellations.write(out); + geometry.write(out); + extraGeometry.write(out); +} + +void PRCFileStructure::prepare() +{ + globals.prepare(); + resetGraphicsAndName(); + + tree.prepare(); + resetGraphicsAndName(); + + tessellations.prepare(); + resetGraphicsAndName(); + + geometry.prepare(); + resetGraphicsAndName(); + + extraGeometry.prepare(); + resetGraphicsAndName(); +} + +uint32_t PRCFileStructure::getSize() +{ + uint32_t size = 0; + size += header.getSize(); + size += sizeof(uint32_t); + for(uint32_t i = 0; i < number_of_uncompressed_files; ++i) + size += uncompressedFiles[i].getSize(); + size += globals.getSize(); + size += tree.getSize(); + size += tessellations.getSize(); + size += geometry.getSize(); + size += extraGeometry.getSize(); + return size; +} + + +void PRCFileStructureInformation::write(std::ostream &out) +{ + writeUINT32_T(out,UUID[0]); + writeUINT32_T(out,UUID[1]); + writeUINT32_T(out,UUID[2]); + writeUINT32_T(out,UUID[3]); + + writeUINT32_T(out,reserved); + writeUINT32_T(out,number_of_offsets); + for(uint32_t i = 0; i < number_of_offsets; ++i) + { + writeUINT32_T(out,offsets[i]); + } +} + +uint32_t PRCFileStructureInformation::getSize() +{ + return (4+2+number_of_offsets)*sizeof(uint32_t); +} + +void PRCHeader::write(std::ostream &out) +{ + startHeader.write(out); + writeUINT32_T(out,number_of_file_structures); + for(uint32_t i = 0; i < number_of_file_structures; ++i) + { + fileStructureInformation[i].write(out); + } + writeUINT32_T(out,model_file_offset); + writeUINT32_T(out,file_size); + writeUINT32_T(out,number_of_uncompressed_files); + for(uint32_t i = 0; i < number_of_uncompressed_files; ++i) + { + uncompressedFiles[i].write(out); + } +} + +uint32_t PRCHeader::getSize() +{ + uint32_t size = startHeader.getSize() + sizeof(uint32_t); + for(uint32_t i = 0; i < number_of_file_structures; ++i) + size += fileStructureInformation[i].getSize(); + size += 3*sizeof(uint32_t); + for(uint32_t i = 0; i < number_of_uncompressed_files; ++i) + size += uncompressedFiles[i].getSize(); + return size; +} + +bool oPRCFile::add(PRCentity *p) +{ + fileEntities.push_back(p); + if(p->useMaterial) + { + if(getMaterialIndex(p->material) == m1) + { + materialMap.push_back(p->material); + + if(getColourIndex(p->material.ambient) == m1) + colourMap.push_back(p->material.ambient); + + if(getColourIndex(p->material.diffuse) == m1) + colourMap.push_back(p->material.diffuse); + + if(getColourIndex(p->material.emissive) == m1) + colourMap.push_back(p->material.emissive); + + if(getColourIndex(p->material.specular) == m1) + colourMap.push_back(p->material.specular); + } + } + else + { + if(getColourIndex(p->colour) == m1) + { + colourMap.push_back(p->colour); + } + } + return true; +} + +bool oPRCFile::finish() +{ + // only one file structure is currently used + // prepare data + fileStructures[0] = new PRCFileStructure(this,0); + fileStructures[0]->header.minimal_version_for_read = PRCVersion; + fileStructures[0]->header.authoring_version = PRCVersion; + makeFileUUID(fileStructures[0]->header.fileStructureUUID); + makeAppUUID(fileStructures[0]->header.applicationUUID); + fileStructures[0]->number_of_uncompressed_files = 0; + + // write each section's bit data + fileStructures[0]->prepare(); + modelFile.prepare(); + + // create the header + + // fill out enough info so that sizes can be computed correctly + header.number_of_uncompressed_files = 0; + header.number_of_file_structures = number_of_file_structures; + header.fileStructureInformation = new PRCFileStructureInformation[number_of_file_structures]; + for(uint32_t i = 0; i < number_of_file_structures; ++i) + { + header.fileStructureInformation[i].UUID[0] = fileStructures[i]->header.fileStructureUUID[0]; + header.fileStructureInformation[i].UUID[1] = fileStructures[i]->header.fileStructureUUID[1]; + header.fileStructureInformation[i].UUID[2] = fileStructures[i]->header.fileStructureUUID[2]; + header.fileStructureInformation[i].UUID[3] = fileStructures[i]->header.fileStructureUUID[3]; + header.fileStructureInformation[i].reserved = 0; + header.fileStructureInformation[i].number_of_offsets = 6; + header.fileStructureInformation[i].offsets = new uint32_t[6]; + } + + header.startHeader.minimal_version_for_read = PRCVersion; + header.startHeader.authoring_version = PRCVersion; + makeFileUUID(header.startHeader.fileStructureUUID); + makeAppUUID(header.startHeader.applicationUUID); + + header.file_size = getSize(); + header.model_file_offset = header.file_size - modelFile.getSize(); + + uint32_t currentOffset = header.getSize(); + + for(uint32_t i = 0; i < number_of_file_structures; ++i) + { + header.fileStructureInformation[i].offsets[0] = currentOffset; // header offset + currentOffset += fileStructures[i]->header.getSize() + sizeof(uint32_t); + for(uint32_t j = 0; j < fileStructures[i]->number_of_uncompressed_files; ++j) + currentOffset += fileStructures[i]->uncompressedFiles[j].getSize(); + header.fileStructureInformation[i].offsets[1] = currentOffset; // globals offset + currentOffset += fileStructures[i]->globals.getSize(); + header.fileStructureInformation[i].offsets[2] = currentOffset; // tree offset + currentOffset += fileStructures[i]->tree.getSize(); + header.fileStructureInformation[i].offsets[3] = currentOffset; // tessellations offset + currentOffset += fileStructures[i]->tessellations.getSize(); + header.fileStructureInformation[i].offsets[4] = currentOffset; // geometry offset + currentOffset += fileStructures[i]->geometry.getSize(); + header.fileStructureInformation[i].offsets[5] = currentOffset; // extra geometry offset + currentOffset += fileStructures[i]->extraGeometry.getSize(); + } + + // write the data + header.write(output); + + for(uint32_t i = 0; i < number_of_file_structures; ++i) + { + fileStructures[i]->write(output); + } + + modelFile.write(output); + output.flush(); + + for(uint32_t i = 0; i < number_of_file_structures; ++i) + delete[] header.fileStructureInformation[i].offsets; + delete[] header.fileStructureInformation; + + return true; +} + +uint32_t oPRCFile::getColourIndex(const RGBAColour &c) +{ + for(uint32_t i = 0; i < colourMap.size(); ++i) + { + if(colourMap[i] == c) + return i; + } + return m1; +} + +uint32_t oPRCFile::getMaterialIndex(const PRCMaterial &m) +{ + for(uint32_t i = 0; i < materialMap.size(); ++i) + { + if(materialMap[i] == m) + return i; + } + return m1; +} + +uint32_t oPRCFile::getSize() +{ + uint32_t size = header.getSize(); + + for(uint32_t i = 0; i < number_of_file_structures; ++i) + { + size += fileStructures[i]->getSize(); + } + + size += modelFile.getSize(); + return size; +} |