summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/prc/oPRCFile.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/prc/oPRCFile.cc')
-rw-r--r--Build/source/utils/asymptote/prc/oPRCFile.cc847
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;
+}