1 /************
2 *
3 * This file is part of a tool for producing 3D content in the PRC format.
4 * Copyright (C) 2008 Orest Shardt <shardtor (at) gmail dot com>
5 * with enhancements contributed by Michail Vidiassov.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 *************/
21
22 #include "oPRCFile.h"
23 #include <time.h>
24 #include <sstream>
25 #include <iostream>
26 #include <fstream>
27 #include <iomanip>
28 #include <string>
29 #include <zlib.h>
30 #include <string.h>
31
32 #define WriteUnsignedInteger( value ) out << (uint32_t)(value);
33 #define WriteInteger( value ) out << (int32_t)(value);
34 #define WriteDouble( value ) out << (double)(value);
35 #define WriteString( value ) out << (value);
36 #define WriteUncompressedUnsignedInteger( value ) writeUncompressedUnsignedInteger(out, (uint32_t)(value));
37 #define WriteUncompressedBlock( value, count ) out.write((char *)(value),(count));
38 #define SerializeFileStructureUncompressedUniqueId( value ) (value).serializeFileStructureUncompressedUniqueId(out);
39 #define SerializeCompressedUniqueId( value ) (value).serializeCompressedUniqueId(out);
40 #define SerializeContentPRCBase write(out);
41 #define SerializeRgbColor( value ) (value).serializeRgbColor(out);
42 #define SerializePicture( value ) (value)->serializePicture(out);
43 #define SerializeTextureDefinition( value ) (value)->serializeTextureDefinition(out);
44 #define SerializeMarkup( value ) (value)->serializeMarkup(out);
45 #define SerializeAnnotationEntity( value ) (value)->serializeAnnotationEntity(out);
46 #define SerializeFontKeysSameFont( value ) (value).serializeFontKeysSameFont(out);
47 #define SerializeMaterial( value ) (value)->serializeMaterial(out);
48
49 #define SerializeUserData UserData(0,0).write(out);
50 #define SerializeEmptyContentPRCBase ContentPRCBase(PRC_TYPE_ROOT_PRCBase).serializeContentPRCBase(out);
51 #define SerializeCategory1LineStyle( value ) (value)->serializeCategory1LineStyle(out);
52 #define SerializeCoordinateSystem( value ) (value)->serializeCoordinateSystem(out);
53 #define SerializeRepresentationItem( value ) (value)->serializeRepresentationItem(out);
54 #define SerializePartDefinition( value ) (value)->serializePartDefinition(out);
55 #define SerializeProductOccurrence( value ) (value)->serializeProductOccurrence(out);
56 #define SerializeContextAndBodies( value ) (value)->serializeContextAndBodies(out);
57 #define SerializeGeometrySummary( value ) (value)->serializeGeometrySummary(out);
58 #define SerializeContextGraphics( value ) (value)->serializeContextGraphics(out);
59 #define SerializeStartHeader serializeStartHeader(out);
60 #define SerializeUncompressedFile( value ) (value)->serializeUncompressedFile(out);
61 #define SerializeUncompressedFiles serializeUncompressedFiles(out);
62
63 #define SerializeModelFileData serializeModelFileData(modelFile_out); modelFile_out.compress();
64 #define SerializeUnit( value ) (value).serializeUnit(out);
65
66 using std::string;
67 using namespace std;
68
69 // Map [0,1] to [0,255]
toByte(double r)70 inline uint8_t toByte(double r)
71 {
72 if(r < 0.0) r=0.0;
73 else if(r > 1.0) r=1.0;
74 int a=(int)(256.0*r);
75 if(a == 256) a=255;
76 return a;
77 }
78
serializeFileStructureGlobals(PRCbitStream & out)79 void PRCFileStructure::serializeFileStructureGlobals(PRCbitStream &out)
80 {
81 // even though this is technically not part of this section,
82 // it is handled here for convenience
83 const uint32_t number_of_schema = 0;
84 WriteUnsignedInteger (number_of_schema)
85
86 WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureGlobals)
87
88 PRCSingleAttribute sa((int32_t)PRCVersion);
89 PRCAttribute a("__PRC_RESERVED_ATTRIBUTE_PRCInternalVersion");
90 a.addKey(sa);
91 ContentPRCBase cb(PRC_TYPE_ROOT_PRCBase);
92 cb.addAttribute(a);
93 cb.serializeContentPRCBase(out);
94 WriteUnsignedInteger (number_of_referenced_file_structures)
95 // SerializeFileStructureInternalGlobalData
96 WriteDouble (tessellation_chord_height_ratio)
97 WriteDouble (tessellation_angle_degree)
98
99 // SerializeMarkupSerializationHelper
100 WriteString (default_font_family_name)
101
102 const uint32_t number_of_fonts = font_keys_of_font.size();
103 WriteUnsignedInteger (number_of_fonts)
104 for (uint32_t i=0;i<number_of_fonts;i++)
105 {
106 SerializeFontKeysSameFont (font_keys_of_font[i])
107 }
108
109 const uint32_t number_of_colors = colors.size();
110 WriteUnsignedInteger (number_of_colors)
111 for (uint32_t i=0;i<number_of_colors;i++)
112 SerializeRgbColor (colors[i])
113
114 const uint32_t number_of_pictures = pictures.size();
115 WriteUnsignedInteger (number_of_pictures)
116 for (uint32_t i=0;i<number_of_pictures;i++)
117 SerializePicture (pictures[i])
118
119 const uint32_t number_of_texture_definitions = texture_definitions.size();
120 WriteUnsignedInteger (number_of_texture_definitions)
121 for (uint32_t i=0;i<number_of_texture_definitions;i++)
122 SerializeTextureDefinition (texture_definitions[i])
123
124 const uint32_t number_of_materials = materials.size();
125 WriteUnsignedInteger (number_of_materials)
126 for (uint32_t i=0;i<number_of_materials;i++)
127 SerializeMaterial (materials[i])
128
129 // number of line patterns hard coded for now
130 const uint32_t number_of_line_patterns = 1;
131 WriteUnsignedInteger (number_of_line_patterns)
132 PRCLinePattern().serializeLinePattern(out);
133
134 const uint32_t number_of_styles = styles.size();
135 WriteUnsignedInteger (number_of_styles)
136 for (uint32_t i=0;i<number_of_styles;i++)
137 SerializeCategory1LineStyle (styles[i])
138
139 const uint32_t number_of_fill_patterns = 0;
140 WriteUnsignedInteger (number_of_fill_patterns)
141
142 const uint32_t number_of_reference_coordinate_systems = reference_coordinate_systems.size();
143 WriteUnsignedInteger (number_of_reference_coordinate_systems)
144 for (uint32_t i=0;i<number_of_reference_coordinate_systems;i++)
145 SerializeCoordinateSystem (reference_coordinate_systems[i])
146
147 SerializeUserData
148 }
149
serializeFileStructureTree(PRCbitStream & out)150 void PRCFileStructure::serializeFileStructureTree(PRCbitStream &out)
151 {
152 WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureTree)
153
154 SerializeEmptyContentPRCBase
155
156 const uint32_t number_of_part_definitions = part_definitions.size();
157 WriteUnsignedInteger (number_of_part_definitions)
158 for (uint32_t i=0;i<number_of_part_definitions;i++)
159 SerializePartDefinition (part_definitions[i])
160
161 const uint32_t number_of_product_occurrences = product_occurrences.size();
162 WriteUnsignedInteger (number_of_product_occurrences)
163 for (uint32_t i=0;i<number_of_product_occurrences;i++)
164 {
165 product_occurrences[i]->unit_information.unit_from_CAD_file = true;
166 product_occurrences[i]->unit_information.unit = unit;
167 SerializeProductOccurrence (product_occurrences[i])
168 }
169
170 // SerializeFileStructureInternalData
171 WriteUnsignedInteger (PRC_TYPE_ASM_FileStructure)
172 SerializeEmptyContentPRCBase
173 const uint32_t next_available_index = makePRCID();
174 WriteUnsignedInteger (next_available_index)
175 const uint32_t index_product_occurence = number_of_product_occurrences; // Asymptote (oPRCFile) specific - we write the root product last
176 WriteUnsignedInteger (index_product_occurence)
177
178 SerializeUserData
179 }
180
serializeFileStructureTessellation(PRCbitStream & out)181 void PRCFileStructure::serializeFileStructureTessellation(PRCbitStream &out)
182 {
183 WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureTessellation)
184
185 SerializeEmptyContentPRCBase
186 const uint32_t number_of_tessellations = tessellations.size();
187 WriteUnsignedInteger (number_of_tessellations)
188 for (uint32_t i=0;i<number_of_tessellations;i++)
189 tessellations[i]->serializeBaseTessData(out);
190
191 SerializeUserData
192 }
193
serializeFileStructureGeometry(PRCbitStream & out)194 void PRCFileStructure::serializeFileStructureGeometry(PRCbitStream &out)
195 {
196 WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureGeometry)
197
198 SerializeEmptyContentPRCBase
199 const uint32_t number_of_contexts = contexts.size();
200 WriteUnsignedInteger (number_of_contexts)
201 for (uint32_t i=0;i<number_of_contexts;i++)
202 SerializeContextAndBodies (contexts[i])
203
204 SerializeUserData
205 }
206
serializeFileStructureExtraGeometry(PRCbitStream & out)207 void PRCFileStructure::serializeFileStructureExtraGeometry(PRCbitStream &out)
208 {
209 WriteUnsignedInteger (PRC_TYPE_ASM_FileStructureExtraGeometry)
210
211 SerializeEmptyContentPRCBase
212 const uint32_t number_of_contexts = contexts.size();
213 WriteUnsignedInteger (number_of_contexts)
214 for (uint32_t i=0;i<number_of_contexts;i++)
215 {
216 SerializeGeometrySummary (contexts[i])
217 SerializeContextGraphics (contexts[i])
218 }
219
220 SerializeUserData
221 }
222
serializeModelFileData(PRCbitStream & out)223 void oPRCFile::serializeModelFileData(PRCbitStream &out)
224 {
225 // even though this is technically not part of this section,
226 // it is handled here for convenience
227 const uint32_t number_of_schema = 0;
228 WriteUnsignedInteger (number_of_schema)
229 WriteUnsignedInteger (PRC_TYPE_ASM_ModelFile)
230
231 PRCSingleAttribute sa((int32_t)PRCVersion);
232 PRCAttribute a("__PRC_RESERVED_ATTRIBUTE_PRCInternalVersion");
233 a.addKey(sa);
234 ContentPRCBase cb(PRC_TYPE_ROOT_PRCBase,"PRC file");
235 cb.addAttribute(a);
236 cb.serializeContentPRCBase(out);
237
238 SerializeUnit (unit)
239
240 out << (uint32_t)1; // 1 product occurrence
241 //UUID
242 SerializeCompressedUniqueId( fileStructures[0]->file_structure_uuid )
243 // index+1
244 out << (uint32_t)fileStructures[0]->product_occurrences.size();
245 // active
246 out << true;
247 out << (uint32_t)0; // index in model file
248
249 SerializeUserData
250 }
251
makeFileUUID(PRCUniqueId & UUID)252 void makeFileUUID(PRCUniqueId& UUID)
253 {
254 // make a UUID
255 static uint32_t count = 0;
256 ++count;
257 // the minimum requirement on UUIDs is that all must be unique in the file
258 UUID.id0 = 0x33595341; // some constant
259 UUID.id1 = (uint32_t)time(NULL); // the time
260 UUID.id2 = count;
261 UUID.id3 = 0xa5a55a5a; // Something random, not seeded by the time, would be nice. But for now, a constant
262 // maybe add something else to make it more unique
263 // so multiple files can be combined
264 // a hash of some data perhaps?
265 }
266
makeAppUUID(PRCUniqueId & UUID)267 void makeAppUUID(PRCUniqueId& UUID)
268 {
269 UUID.id0 = UUID.id1 = UUID.id2 = UUID.id3 = 0;
270 }
271
serializeStartHeader(ostream & out) const272 void PRCStartHeader::serializeStartHeader(ostream &out) const
273 {
274 WriteUncompressedBlock ("PRC",3)
275 WriteUncompressedUnsignedInteger (minimal_version_for_read)
276 WriteUncompressedUnsignedInteger (authoring_version)
277 SerializeFileStructureUncompressedUniqueId( file_structure_uuid );
278 SerializeFileStructureUncompressedUniqueId( application_uuid );
279 }
280
serializeUncompressedFiles(ostream & out) const281 void PRCStartHeader::serializeUncompressedFiles(ostream &out) const
282 {
283 const uint32_t number_of_uncompressed_files = uncompressed_files.size();
284 WriteUncompressedUnsignedInteger (number_of_uncompressed_files)
285 for (uint32_t i=0; i<number_of_uncompressed_files; i++)
286 SerializeUncompressedFile (uncompressed_files[i])
287 }
288
getStartHeaderSize() const289 uint32_t PRCStartHeader::getStartHeaderSize() const
290 {
291 return 3+(2+2*4)*sizeof(uint32_t);
292 }
293
getUncompressedFilesSize() const294 uint32_t PRCStartHeader::getUncompressedFilesSize() const
295 {
296 uint32_t size = 0;
297 for(PRCUncompressedFileList::const_iterator it = uncompressed_files.begin(); it != uncompressed_files.end(); it++)
298 size += (*it)->getSize();
299 return size;
300 }
301
write(ostream & out)302 void PRCFileStructure::write(ostream &out)
303 {
304 // SerializeFileStructureHeader
305 SerializeStartHeader
306 SerializeUncompressedFiles
307 globals_out.write(out);
308 tree_out.write(out);
309 tessellations_out.write(out);
310 geometry_out.write(out);
311 extraGeometry_out.write(out);
312 }
313
314 #define SerializeFileStructureGlobals serializeFileStructureGlobals(globals_out); globals_out.compress(); sizes[1]=globals_out.getSize();
315 #define SerializeFileStructureTree serializeFileStructureTree(tree_out); tree_out.compress(); sizes[2]=tree_out.getSize();
316 #define SerializeFileStructureTessellation serializeFileStructureTessellation(tessellations_out); tessellations_out.compress(); sizes[3]=tessellations_out.getSize();
317 #define SerializeFileStructureGeometry serializeFileStructureGeometry(geometry_out); geometry_out.compress(); sizes[4]=geometry_out.getSize();
318 #define SerializeFileStructureExtraGeometry serializeFileStructureExtraGeometry(extraGeometry_out); extraGeometry_out.compress(); sizes[5]=extraGeometry_out.getSize();
319 #define FlushSerialization resetGraphicsAndName();
prepare()320 void PRCFileStructure::prepare()
321 {
322 uint32_t size = 0;
323 size += getStartHeaderSize();
324 size += sizeof(uint32_t);
325 size += getUncompressedFilesSize();
326 sizes[0]=size;
327
328 SerializeFileStructureGlobals
329 FlushSerialization
330
331 SerializeFileStructureTree
332 FlushSerialization
333
334 SerializeFileStructureTessellation
335 FlushSerialization
336
337 SerializeFileStructureGeometry
338 FlushSerialization
339
340 SerializeFileStructureExtraGeometry
341 FlushSerialization
342 }
343
getSize()344 uint32_t PRCFileStructure::getSize()
345 {
346 uint32_t size = 0;
347 for(size_t i=0; i<6; i++)
348 size += sizes[i];
349 return size;
350 }
351
352
write(ostream & out)353 void PRCFileStructureInformation::write(ostream &out)
354 {
355 SerializeFileStructureUncompressedUniqueId( UUID );
356
357 WriteUncompressedUnsignedInteger (reserved)
358 WriteUncompressedUnsignedInteger (number_of_offsets)
359 for(uint32_t i = 0; i < number_of_offsets; ++i)
360 {
361 WriteUncompressedUnsignedInteger (offsets[i])
362 }
363 }
364
getSize()365 uint32_t PRCFileStructureInformation::getSize()
366 {
367 return (4+2+number_of_offsets)*sizeof(uint32_t);
368 }
369
write(ostream & out)370 void PRCHeader::write(ostream &out)
371 {
372 SerializeStartHeader
373 WriteUncompressedUnsignedInteger (number_of_file_structures)
374 for(uint32_t i = 0; i < number_of_file_structures; ++i)
375 {
376 fileStructureInformation[i].write(out);
377 }
378 WriteUncompressedUnsignedInteger (model_file_offset)
379 WriteUncompressedUnsignedInteger (file_size)
380 SerializeUncompressedFiles
381 }
382
getSize()383 uint32_t PRCHeader::getSize()
384 {
385 uint32_t size = getStartHeaderSize() + sizeof(uint32_t);
386 for(uint32_t i = 0; i < number_of_file_structures; ++i)
387 size += fileStructureInformation[i].getSize();
388 size += 3*sizeof(uint32_t);
389 size += getUncompressedFilesSize();
390 return size;
391 }
392
doGroup(PRCgroup & group)393 void oPRCFile::doGroup(PRCgroup& group)
394 {
395 const string& name = group.name;
396
397 PRCProductOccurrence*& product_occurrence = group.product_occurrence;
398 PRCProductOccurrence*& parent_product_occurrence = group.parent_product_occurrence;
399 PRCPartDefinition*& part_definition = group.part_definition;
400 PRCPartDefinition*& parent_part_definition = group.parent_part_definition;
401
402 if(group.options.tess)
403 {
404 if(!group.lines.empty())
405 {
406 for(PRCtesslineMap::const_iterator wit=group.lines.begin(); wit!=group.lines.end(); wit++)
407 {
408 bool same_color = true;
409 const PRCtesslineList& lines = wit->second;
410 const PRCRgbColor &color = lines.front().color;
411 for(PRCtesslineList::const_iterator lit=lines.begin(); lit!=lines.end(); lit++)
412 if(color!=lit->color)
413 {
414 same_color = false;
415 break;
416 }
417 map<PRCVector3d,uint32_t> points;
418 PRC3DWireTess *tess = new PRC3DWireTess();
419 if(!same_color)
420 {
421 tess->is_segment_color = true;
422 tess->is_rgba = false;
423 }
424 for(PRCtesslineList::const_iterator lit=lines.begin(); lit!=lines.end(); lit++)
425 {
426 tess->wire_indexes.push_back(lit->point.size());
427 for(uint32_t i=0; i<lit->point.size(); i++)
428 {
429 map<PRCVector3d,uint32_t>::iterator pPoint = points.find(lit->point[i]);
430 if(pPoint!=points.end())
431 tess->wire_indexes.push_back(pPoint->second);
432 else
433 {
434 const uint32_t point_index = tess->coordinates.size();
435 points.insert(make_pair(lit->point[i],point_index));
436 tess->wire_indexes.push_back(point_index);
437 tess->coordinates.push_back(lit->point[i].x);
438 tess->coordinates.push_back(lit->point[i].y);
439 tess->coordinates.push_back(lit->point[i].z);
440 }
441 if(!same_color && i>0)
442 {
443 tess->rgba_vertices.push_back(toByte(lit->color.red));
444 tess->rgba_vertices.push_back(toByte(lit->color.green));
445 tess->rgba_vertices.push_back(toByte(lit->color.blue));
446 }
447 }
448 }
449 const uint32_t tess_index = add3DWireTess(tess);
450 PRCPolyWire *polyWire = new PRCPolyWire();
451 polyWire->index_tessellation = tess_index;
452 if(same_color)
453 polyWire->index_of_line_style = addColourWidth(RGBAColour(color.red,color.green,color.blue),wit->first);
454 else
455 polyWire->index_of_line_style = addColourWidth(RGBAColour(1,1,1),wit->first);
456 part_definition->addPolyWire(polyWire);
457 }
458 }
459 // make rectangles pairs of triangles in a tesselation
460 if(!group.rectangles.empty())
461 {
462 bool same_color = true;
463 const uint32_t &style = group.rectangles.front().style;
464 for(PRCtessrectangleList::const_iterator rit=group.rectangles.begin(); rit!=group.rectangles.end(); rit++)
465 if(style!=rit->style)
466 {
467 same_color = false;
468 break;
469 }
470 map<PRCVector3d,uint32_t> points;
471 PRC3DTess *tess = new PRC3DTess();
472 tess->crease_angle = group.options.crease_angle;
473 PRCTessFace *tessFace = new PRCTessFace();
474 tessFace->used_entities_flag=PRC_FACETESSDATA_Triangle;
475 uint32_t triangles = 0;
476 for(PRCtessrectangleList::const_iterator rit=group.rectangles.begin(); rit!=group.rectangles.end(); rit++)
477 {
478 const bool degenerate = (rit->vertices[0]==rit->vertices[1]);
479 uint32_t vertex_indices[4];
480 for(size_t i = (degenerate?1:0); i < 4; ++i)
481 {
482 map<PRCVector3d,uint32_t>::const_iterator pPoint = points.find(rit->vertices[i]);
483 if(pPoint!=points.end())
484 vertex_indices[i] = pPoint->second;
485 else
486 {
487 points.insert(make_pair(rit->vertices[i],(vertex_indices[i] = tess->coordinates.size())));
488 tess->coordinates.push_back(rit->vertices[i].x);
489 tess->coordinates.push_back(rit->vertices[i].y);
490 tess->coordinates.push_back(rit->vertices[i].z);
491 }
492 }
493 if(degenerate)
494 {
495 tess->triangulated_index.push_back(vertex_indices[1]);
496 tess->triangulated_index.push_back(vertex_indices[2]);
497 tess->triangulated_index.push_back(vertex_indices[3]);
498 triangles++;
499 if(!same_color)
500 tessFace->line_attributes.push_back(rit->style);
501 }
502 else
503 {
504 tess->triangulated_index.push_back(vertex_indices[0]);
505 tess->triangulated_index.push_back(vertex_indices[2]);
506 tess->triangulated_index.push_back(vertex_indices[3]);
507 triangles++;
508 if(!same_color)
509 tessFace->line_attributes.push_back(rit->style);
510 tess->triangulated_index.push_back(vertex_indices[3]);
511 tess->triangulated_index.push_back(vertex_indices[1]);
512 tess->triangulated_index.push_back(vertex_indices[0]);
513 triangles++;
514 if(!same_color)
515 tessFace->line_attributes.push_back(rit->style);
516 }
517 }
518 tessFace->sizes_triangulated.push_back(triangles);
519 tess->addTessFace(tessFace);
520 const uint32_t tess_index = add3DTess(tess);
521 PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
522 polyBrepModel->index_tessellation = tess_index;
523 polyBrepModel->is_closed = group.options.closed;
524 if(same_color)
525 polyBrepModel->index_of_line_style = style;
526 part_definition->addPolyBrepModel(polyBrepModel);
527 }
528 }
529
530 if(!group.quads.empty())
531 {
532 map<PRCVector3d,uint32_t> points;
533 PRC3DTess *tess = new PRC3DTess();
534 tess->crease_angle = group.options.crease_angle;
535 PRCTessFace *tessFace = new PRCTessFace();
536 tessFace->used_entities_flag=PRC_FACETESSDATA_Triangle;
537 uint32_t triangles = 0;
538
539 tessFace->is_rgba = false;
540 for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
541 {
542 const RGBAColour* C = qit->colours;
543 if(C[0].A != 1.0 || C[1].A != 1.0 || C[2].A != 1.0 || C[3].A != 1.0)
544 {
545 tessFace->is_rgba = true;
546 break;
547 }
548 }
549 bool same_colour = true;
550 const RGBAColour& colour = group.quads.front().colours[0];
551 for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
552 {
553 const RGBAColour* C = qit->colours;
554 if(colour!=C[0] || colour!=C[1] || colour!=C[2] || colour!=C[3])
555 {
556 same_colour = false;
557 break;
558 }
559 }
560
561 for(PRCtessquadList::const_iterator qit=group.quads.begin(); qit!=group.quads.end(); qit++)
562 {
563 const RGBAColour* C = qit->colours;
564 const bool degenerate = (qit->vertices[0]==qit->vertices[1]);
565 uint32_t vertex_indices[4];
566 for(size_t i = (degenerate?1:0); i < 4; ++i)
567 {
568 map<PRCVector3d,uint32_t>::const_iterator pPoint = points.find(qit->vertices[i]);
569 if(pPoint!=points.end())
570 vertex_indices[i] = pPoint->second;
571 else
572 {
573 points.insert(make_pair(qit->vertices[i],(vertex_indices[i] = tess->coordinates.size())));
574 tess->coordinates.push_back(qit->vertices[i].x);
575 tess->coordinates.push_back(qit->vertices[i].y);
576 tess->coordinates.push_back(qit->vertices[i].z);
577 }
578 }
579 if(degenerate)
580 {
581 tess->triangulated_index.push_back(vertex_indices[1]);
582 tess->triangulated_index.push_back(vertex_indices[2]);
583 tess->triangulated_index.push_back(vertex_indices[3]);
584 triangles++;
585 if(!same_colour)
586 {
587 tessFace->rgba_vertices.push_back(toByte(C[1].R));
588 tessFace->rgba_vertices.push_back(toByte(C[1].G));
589 tessFace->rgba_vertices.push_back(toByte(C[1].B));
590 if(tessFace->is_rgba)
591 tessFace->rgba_vertices.push_back(toByte(C[1].A));
592
593 tessFace->rgba_vertices.push_back(toByte(C[2].R));
594 tessFace->rgba_vertices.push_back(toByte(C[2].G));
595 tessFace->rgba_vertices.push_back(toByte(C[2].B));
596 if(tessFace->is_rgba)
597 tessFace->rgba_vertices.push_back(toByte(C[2].A));
598
599 tessFace->rgba_vertices.push_back(toByte(C[3].R));
600 tessFace->rgba_vertices.push_back(toByte(C[3].G));
601 tessFace->rgba_vertices.push_back(toByte(C[3].B));
602 if(tessFace->is_rgba)
603 tessFace->rgba_vertices.push_back(toByte(C[3].A));
604 }
605 }
606 else
607 {
608 tess->triangulated_index.push_back(vertex_indices[0]);
609 tess->triangulated_index.push_back(vertex_indices[2]);
610 tess->triangulated_index.push_back(vertex_indices[3]);
611 triangles++;
612 if(!same_colour)
613 {
614 tessFace->rgba_vertices.push_back(toByte(C[0].R));
615 tessFace->rgba_vertices.push_back(toByte(C[0].G));
616 tessFace->rgba_vertices.push_back(toByte(C[0].B));
617 if(tessFace->is_rgba)
618 tessFace->rgba_vertices.push_back(toByte(C[0].A));
619
620 tessFace->rgba_vertices.push_back(toByte(C[2].R));
621 tessFace->rgba_vertices.push_back(toByte(C[2].G));
622 tessFace->rgba_vertices.push_back(toByte(C[2].B));
623 if(tessFace->is_rgba)
624 tessFace->rgba_vertices.push_back(toByte(C[2].A));
625
626 tessFace->rgba_vertices.push_back(toByte(C[3].R));
627 tessFace->rgba_vertices.push_back(toByte(C[3].G));
628 tessFace->rgba_vertices.push_back(toByte(C[3].B));
629 if(tessFace->is_rgba)
630 tessFace->rgba_vertices.push_back(toByte(C[3].A));
631 }
632 tess->triangulated_index.push_back(vertex_indices[3]);
633 tess->triangulated_index.push_back(vertex_indices[1]);
634 tess->triangulated_index.push_back(vertex_indices[0]);
635 triangles++;
636 if(!same_colour)
637 {
638 tessFace->rgba_vertices.push_back(toByte(C[3].R));
639 tessFace->rgba_vertices.push_back(toByte(C[3].G));
640 tessFace->rgba_vertices.push_back(toByte(C[3].B));
641 if(tessFace->is_rgba)
642 tessFace->rgba_vertices.push_back(toByte(C[3].A));
643
644 tessFace->rgba_vertices.push_back(toByte(C[1].R));
645 tessFace->rgba_vertices.push_back(toByte(C[1].G));
646 tessFace->rgba_vertices.push_back(toByte(C[1].B));
647 if(tessFace->is_rgba)
648 tessFace->rgba_vertices.push_back(toByte(C[1].A));
649
650 tessFace->rgba_vertices.push_back(toByte(C[0].R));
651 tessFace->rgba_vertices.push_back(toByte(C[0].G));
652 tessFace->rgba_vertices.push_back(toByte(C[0].B));
653 if(tessFace->is_rgba)
654 tessFace->rgba_vertices.push_back(toByte(C[0].A));
655 }
656 }
657 }
658 tessFace->sizes_triangulated.push_back(triangles);
659 tess->addTessFace(tessFace);
660 const uint32_t tess_index = add3DTess(tess);
661 PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
662 polyBrepModel->index_tessellation = tess_index;
663 polyBrepModel->is_closed = group.options.closed;
664 if(same_colour)
665 polyBrepModel->index_of_line_style = addColour(colour);
666 part_definition->addPolyBrepModel(polyBrepModel);
667 }
668
669 if(!group.points.empty())
670 {
671 for(PRCpointsetMap::const_iterator pit=group.points.begin(); pit!=group.points.end(); pit++)
672 {
673 PRCPointSet *pointset = new PRCPointSet();
674 pointset->index_of_line_style = pit->first;
675 pointset->point = pit->second;
676 part_definition->addPointSet(pointset);
677 }
678 }
679
680 if(!group.pointsets.empty())
681 {
682 for(std::vector<PRCPointSet*>::iterator pit=group.pointsets.begin(); pit!=group.pointsets.end(); pit++)
683 {
684 part_definition->addPointSet(*pit);
685 }
686 }
687
688 if(!group.polymodels.empty())
689 {
690 for(std::vector<PRCPolyBrepModel*>::iterator pit=group.polymodels.begin(); pit!=group.polymodels.end(); pit++)
691 {
692 (*pit)->is_closed = group.options.closed;
693 part_definition->addPolyBrepModel(*pit);
694 }
695 }
696
697 if(!group.polywires.empty())
698 {
699 for(std::vector<PRCPolyWire*>::iterator pit=group.polywires.begin(); pit!=group.polywires.end(); pit++)
700 {
701 part_definition->addPolyWire(*pit);
702 }
703 }
704
705 if(!group.wires.empty())
706 {
707 PRCTopoContext *wireContext = NULL;
708 const uint32_t context_index = getTopoContext(wireContext);
709 for(PRCwireList::iterator wit=group.wires.begin(); wit!=group.wires.end(); wit++)
710 {
711 PRCWireEdge *wireEdge = new PRCWireEdge;
712 wireEdge->curve_3d = wit->curve;
713 PRCSingleWireBody *wireBody = new PRCSingleWireBody;
714 wireBody->setWireEdge(wireEdge);
715 const uint32_t wire_body_index = wireContext->addSingleWireBody(wireBody);
716 PRCWire *wire = new PRCWire();
717 wire->index_of_line_style = wit->style;
718 wire->context_id = context_index;
719 wire->body_id = wire_body_index;
720 if(wit->transform)
721 wire->index_local_coordinate_system = addTransform(wit->transform);
722 part_definition->addWire(wire);
723 }
724 }
725
726 PRCfaceList &faces = group.faces;
727 if(!faces.empty())
728 {
729 bool same_color = true;
730 const uint32_t style = faces.front().style;
731 for(PRCfaceList::const_iterator fit=faces.begin(); fit!=faces.end(); fit++)
732 if(style!=fit->style)
733 {
734 same_color = false;
735 break;
736 }
737 PRCTopoContext *context = NULL;
738 const uint32_t context_index = getTopoContext(context);
739 context->granularity = group.options.granularity;
740 // Acrobat 9 also does the following:
741 // context->tolerance = group.options.granularity;
742 // context->have_smallest_face_thickness = true;
743 // context->smallest_thickness = group.options.granularity;
744 PRCShell *shell = new PRCShell;
745
746 for(PRCfaceList::iterator fit=faces.begin(); fit!=faces.end(); fit++)
747 {
748 if(fit->transform || group.options.do_break ||
749 (fit->transparent && !group.options.no_break))
750 {
751 PRCShell *shell = new PRCShell;
752 shell->addFace(fit->face);
753 PRCConnex *connex = new PRCConnex;
754 connex->addShell(shell);
755 PRCBrepData *body = new PRCBrepData;
756 body->addConnex(connex);
757 const uint32_t body_index = context->addBrepData(body);
758
759 PRCBrepModel *brepmodel = new PRCBrepModel();
760 brepmodel->index_of_line_style = fit->style;
761 brepmodel->context_id = context_index;
762 brepmodel->body_id = body_index;
763 brepmodel->is_closed = group.options.closed;
764
765 brepmodel->index_local_coordinate_system = addTransform(fit->transform);
766
767 part_definition->addBrepModel(brepmodel);
768 }
769 else
770 {
771 if(!same_color)
772 fit->face->index_of_line_style = fit->style;
773 shell->addFace(fit->face);
774 }
775 }
776 if(shell->face.empty())
777 {
778 delete shell;
779 }
780 else
781 {
782 PRCConnex *connex = new PRCConnex;
783 connex->addShell(shell);
784 PRCBrepData *body = new PRCBrepData;
785 body->addConnex(connex);
786 const uint32_t body_index = context->addBrepData(body);
787 PRCBrepModel *brepmodel = new PRCBrepModel();
788 if(same_color)
789 brepmodel->index_of_line_style = style;
790 brepmodel->context_id = context_index;
791 brepmodel->body_id = body_index;
792 brepmodel->is_closed = group.options.closed;
793 part_definition->addBrepModel(brepmodel);
794 }
795 }
796
797 PRCcompfaceList &compfaces = group.compfaces;
798 if(!compfaces.empty())
799 {
800 bool same_color = true;
801 const uint32_t style = compfaces.front().style;
802 for(PRCcompfaceList::const_iterator fit=compfaces.begin(); fit!=compfaces.end(); fit++)
803 if(style!=fit->style)
804 {
805 same_color = false;
806 break;
807 }
808 PRCTopoContext *context = NULL;
809 const uint32_t context_index = getTopoContext(context);
810 PRCCompressedBrepData *body = new PRCCompressedBrepData;
811
812 body->serial_tolerance=group.options.compression;
813 body->brep_data_compressed_tolerance=0.1*group.options.compression;
814
815 for(PRCcompfaceList::const_iterator fit=compfaces.begin(); fit!=compfaces.end(); fit++)
816 {
817 if(group.options.do_break ||
818 (fit->transparent && !group.options.no_break))
819 {
820 PRCCompressedBrepData *body = new PRCCompressedBrepData;
821 body->face.push_back(fit->face);
822
823 body->serial_tolerance=group.options.compression;
824 body->brep_data_compressed_tolerance=2.8346456*
825 group.options.compression;
826 const uint32_t body_index = context->addCompressedBrepData(body);
827
828 PRCBrepModel *brepmodel = new PRCBrepModel();
829 brepmodel->index_of_line_style = fit->style;
830 brepmodel->context_id = context_index;
831 brepmodel->body_id = body_index;
832 brepmodel->is_closed = group.options.closed;
833
834 part_definition->addBrepModel(brepmodel);
835 }
836 else
837 {
838 if(!same_color)
839 fit->face->index_of_line_style = fit->style;
840 body->face.push_back(fit->face);
841 }
842 }
843 if(body->face.empty())
844 {
845 delete body;
846 }
847 else
848 {
849 const uint32_t body_index = context->addCompressedBrepData(body);
850 PRCBrepModel *brepmodel = new PRCBrepModel();
851 if(same_color)
852 brepmodel->index_of_line_style = style;
853 brepmodel->context_id = context_index;
854 brepmodel->body_id = body_index;
855 brepmodel->is_closed = group.options.closed;
856 part_definition->addBrepModel(brepmodel);
857 }
858 }
859
860 // Simplify and reduce to as simple entities as possible
861 // products with named representation items can not be reduced to sets, since
862 // outside references are already set
863 bool nonamedparts = true;
864 for(PRCRepresentationItemList::const_iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
865 {
866 if (!(*it)->name.empty())
867 {
868 nonamedparts = false;
869 break;
870 }
871 }
872 lastgroupname.clear();
873 lastgroupnames.clear();
874 // First option - reduce to one element in parent
875 if (parent_part_definition && product_occurrence->index_son_occurrence.empty() &&
876 part_definition->representation_item.size() == 1 &&
877 ( name.empty() || part_definition->representation_item.front()->name.empty() ) &&
878 ( !group.transform || part_definition->representation_item.front()->index_local_coordinate_system==m1) )
879 {
880 if(part_definition->representation_item.front()->name.empty() )
881 part_definition->representation_item.front()->name = name;
882 if(part_definition->representation_item.front()->index_local_coordinate_system==m1)
883 part_definition->representation_item.front()->index_local_coordinate_system = addTransform(group.transform);
884 lastgroupname = calculate_unique_name(part_definition->representation_item.front(), parent_product_occurrence);
885 parent_part_definition->addRepresentationItem(part_definition->representation_item.front());
886 part_definition->representation_item.clear();
887 delete product_occurrence; product_occurrence = NULL;
888 delete part_definition; part_definition = NULL;
889 }
890 // Second option - reduce to a set
891 else if (parent_part_definition && product_occurrence->index_son_occurrence.empty() &&
892 !part_definition->representation_item.empty() &&
893 !group.options.do_break && nonamedparts)
894 {
895 PRCSet *set = new PRCSet(name);
896 set->index_local_coordinate_system = addTransform(group.transform);
897 lastgroupname = calculate_unique_name(set, parent_product_occurrence);
898 for(PRCRepresentationItemList::iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
899 {
900 lastgroupnames.push_back(calculate_unique_name(*it, parent_product_occurrence));
901 set->addRepresentationItem(*it);
902 }
903 part_definition->representation_item.clear();
904 parent_part_definition->addSet(set);
905 delete product_occurrence; product_occurrence = NULL;
906 delete part_definition; part_definition = NULL;
907 }
908 // Third option - create product
909 else if ( !product_occurrence->index_son_occurrence.empty() || !part_definition->representation_item.empty())
910 {
911 // if everything is enclosed in one group - drop the root group
912 if (parent_product_occurrence == NULL && group.transform == NULL &&
913 part_definition->representation_item.empty() && product_occurrence->index_son_occurrence.size()==1) {
914 delete part_definition; part_definition = NULL;
915 delete product_occurrence; product_occurrence = NULL;
916 }
917 else
918 {
919 lastgroupname = calculate_unique_name(product_occurrence, NULL);
920 if (part_definition->representation_item.empty()) {
921 delete part_definition; part_definition = NULL;
922 }
923 else
924 {
925 for(PRCRepresentationItemList::const_iterator it=part_definition->representation_item.begin(); it!=part_definition->representation_item.end(); it++)
926 if ((*it)->name.empty())
927 lastgroupnames.push_back(calculate_unique_name(*it, product_occurrence));
928 product_occurrence->index_part = addPartDefinition(part_definition);
929 }
930 if (group.transform) {
931 product_occurrence->location = group.transform;
932 group.transform = NULL;
933 }
934 if (parent_product_occurrence) {
935 parent_product_occurrence->index_son_occurrence.push_back(addProductOccurrence(product_occurrence));
936 }
937 else {
938 addProductOccurrence(product_occurrence);
939 }
940 }
941 }
942 // Last case - absolutely nothing to do
943 else
944 {
945 delete product_occurrence; product_occurrence = NULL;
946 delete part_definition; part_definition = NULL;
947 }
948
949 }
950
calculate_unique_name(const ContentPRCBase * prc_entity,const ContentPRCBase * prc_occurence)951 std::string oPRCFile::calculate_unique_name(const ContentPRCBase *prc_entity,const ContentPRCBase *prc_occurence)
952 {
953 std::stringstream ss (std::stringstream::in | std::stringstream::out);
954 uint8_t *serialization_buffer = NULL;
955 PRCbitStream serialization(serialization_buffer,0u);
956 const PRCFileStructure *pfile_structure = fileStructures[0];
957 const PRCUniqueId& uuid = pfile_structure->file_structure_uuid;
958 // ConvertUniqueIdentifierToString (prc_entity)
959 // SerializeCompressedUniqueId (file_structure)
960 serialization << uuid.id0 << uuid.id1 << uuid.id2 << uuid.id3;
961 // WriteUnsignedInteger (type)
962 serialization << prc_entity->getType();
963 // WriteUnsignedInteger (unique_identifier)
964 serialization << prc_entity->getPRCID();
965 if (prc_occurence)
966 {
967 // serialization_buffer = Flush serialization (serialization)
968 {
969 const uint32_t size_serialization = serialization.getSize();
970 while(size_serialization == serialization.getSize())
971 serialization << false;
972 }
973 // ConvertUniqueIdentifierToString (prc_occurrence_unique_id)
974 // SerializeCompressedUniqueId (file_structure)
975 serialization << uuid.id0 << uuid.id1 << uuid.id2 << uuid.id3;
976 // WriteUnsignedInteger (type)
977 serialization << (uint32_t)PRC_TYPE_ASM_ProductOccurence;
978 // WriteUnsignedInteger (unique_identifier)
979 serialization << prc_occurence->getPRCID();
980 }
981 ss << (prc_entity->name.empty()?"node":prc_entity->name.c_str()) << '.';
982 const uint32_t size_serialization = serialization.getSize();
983 for(size_t j=0; j<size_serialization; j++)
984 ss << hex << setfill('0') << setw(2) << (uint32_t)(serialization_buffer[j]);
985 free(serialization_buffer);
986
987 return ss.str();
988 }
989
finish()990 bool oPRCFile::finish()
991 {
992 if(groups.size()!=1) {
993 fputs("begingroup without matching endgroup",stderr);
994 exit(1);
995 }
996 doGroup(groups.top());
997
998 // write each section's bit data
999 fileStructures[0]->prepare();
1000 SerializeModelFileData
1001
1002 // create the header
1003
1004 // fill out enough info so that sizes can be computed correctly
1005 header.number_of_file_structures = number_of_file_structures;
1006 header.fileStructureInformation = new PRCFileStructureInformation[number_of_file_structures];
1007 for(uint32_t i = 0; i < number_of_file_structures; ++i)
1008 {
1009 header.fileStructureInformation[i].UUID = fileStructures[i]->file_structure_uuid;
1010 header.fileStructureInformation[i].reserved = 0;
1011 header.fileStructureInformation[i].number_of_offsets = 6;
1012 header.fileStructureInformation[i].offsets = new uint32_t[6];
1013 }
1014
1015 header.minimal_version_for_read = PRCVersion;
1016 header.authoring_version = PRCVersion;
1017 makeFileUUID(header.file_structure_uuid);
1018 makeAppUUID(header.application_uuid);
1019
1020 header.file_size = getSize();
1021 header.model_file_offset = header.file_size - modelFile_out.getSize();
1022
1023 uint32_t currentOffset = header.getSize();
1024
1025 for(uint32_t i = 0; i < number_of_file_structures; ++i)
1026 {
1027 for(size_t j=0; j<6; j++)
1028 {
1029 header.fileStructureInformation[i].offsets[j] = currentOffset;
1030 currentOffset += fileStructures[i]->sizes[j];
1031 }
1032 }
1033
1034 // write the data
1035 header.write(output);
1036
1037 for(uint32_t i = 0; i < number_of_file_structures; ++i)
1038 {
1039 fileStructures[i]->write(output);
1040 }
1041
1042 modelFile_out.write(output);
1043 output.flush();
1044
1045 for(uint32_t i = 0; i < number_of_file_structures; ++i)
1046 delete[] header.fileStructureInformation[i].offsets;
1047 delete[] header.fileStructureInformation;
1048
1049 return true;
1050 }
1051
getSize()1052 uint32_t oPRCFile::getSize()
1053 {
1054 uint32_t size = header.getSize();
1055
1056 for(uint32_t i = 0; i < number_of_file_structures; ++i)
1057 {
1058 size += fileStructures[i]->getSize();
1059 }
1060
1061 size += modelFile_out.getSize();
1062 return size;
1063 }
1064
addPicture(EPRCPictureDataFormat format,uint32_t size,const uint8_t * p,uint32_t width,uint32_t height,string name)1065 uint32_t PRCFileStructure::addPicture(EPRCPictureDataFormat format, uint32_t size, const uint8_t *p, uint32_t width, uint32_t height, string name)
1066 {
1067 uint8_t *data = NULL;
1068 if(size==0 || p==NULL)
1069 { cerr << "image not set" << endl; return m1; }
1070 if(format==KEPRCPicture_PNG || format==KEPRCPicture_JPG)
1071 {
1072 width = 0; // width and height are ignored for JPG and PNG pictures - but let us keep things clean
1073 height = 0;
1074 data = new uint8_t[size];
1075 memcpy(data, p, size);
1076 }
1077 else
1078 {
1079 uint32_t components=0;
1080 switch(format)
1081 {
1082 case KEPRCPicture_BITMAP_RGB_BYTE:
1083 components = 3; break;
1084 case KEPRCPicture_BITMAP_RGBA_BYTE:
1085 components = 4; break;
1086 case KEPRCPicture_BITMAP_GREY_BYTE:
1087 components = 1; break;
1088 case KEPRCPicture_BITMAP_GREYA_BYTE:
1089 components = 2; break;
1090 default:
1091 { cerr << "unknown picture format" << endl; return m1; }
1092 }
1093 if(width==0 || height==0)
1094 { cerr << "width or height parameter not set" << endl; return m1; }
1095 if (size < width*height*components)
1096 { cerr << "image too small" << endl; return m1; }
1097 {
1098 uint32_t compressedDataSize = 0;
1099 const int CHUNK= 1024; // is this reasonable?
1100
1101 z_stream strm;
1102 strm.zalloc = Z_NULL;
1103 strm.zfree = Z_NULL;
1104 strm.opaque = Z_NULL;
1105 if(deflateInit(&strm,Z_DEFAULT_COMPRESSION) != Z_OK)
1106 { cerr << "Compression initialization failed" << endl; return m1; }
1107 unsigned int sizeAvailable = deflateBound(&strm,size);
1108 uint8_t *compressedData = (uint8_t*) malloc(sizeAvailable);
1109 strm.avail_in = size;
1110 strm.next_in = (unsigned char*)p;
1111 strm.next_out = (unsigned char*)compressedData;
1112 strm.avail_out = sizeAvailable;
1113
1114 int code;
1115 unsigned int chunks = 0;
1116 while((code = deflate(&strm,Z_FINISH)) == Z_OK)
1117 {
1118 ++chunks;
1119 // strm.avail_out should be 0 if we got Z_OK
1120 compressedDataSize = sizeAvailable - strm.avail_out;
1121 compressedData = (uint8_t*) realloc(compressedData,CHUNK*chunks);
1122 strm.next_out = (Bytef*)(compressedData + compressedDataSize);
1123 strm.avail_out += CHUNK;
1124 sizeAvailable += CHUNK;
1125 }
1126 compressedDataSize = sizeAvailable-strm.avail_out;
1127
1128 if(code != Z_STREAM_END)
1129 {
1130 deflateEnd(&strm);
1131 free(compressedData);
1132 { cerr << "Compression error" << endl; return m1; }
1133 }
1134
1135 deflateEnd(&strm);
1136 size = compressedDataSize;
1137 data = new uint8_t[compressedDataSize];
1138 memcpy(data, compressedData, compressedDataSize);
1139 free(compressedData);
1140 }
1141 }
1142
1143 uint32_t uncompressed_file_index = m1;
1144 {
1145 PRCUncompressedFile* uncompressed_file = new PRCUncompressedFile(size, data);
1146 uncompressed_file_index = addUncompressedFileUnique(uncompressed_file);
1147 delete[] data;
1148 }
1149 uint32_t picture_index = m1;
1150 {
1151 PRCPicture* picture = new PRCPicture(name);
1152 picture->format = format;
1153 picture->uncompressed_file_index = uncompressed_file_index;
1154 picture->pixel_width = width;
1155 picture->pixel_height = height;
1156 picture_index = addPictureUnique(picture);
1157 }
1158 return picture_index;
1159 }
1160
addColour(const RGBAColour & colour)1161 uint32_t oPRCFile::addColour(const RGBAColour &colour)
1162 {
1163 PRCcolourMap::const_iterator pColour = colourMap.find(colour);
1164 if(pColour!=colourMap.end())
1165 return pColour->second;
1166 const uint32_t color_index = addRgbColorUnique(colour.R, colour.G, colour.B);
1167 PRCStyle *style = new PRCStyle();
1168 style->line_width = 1.0;
1169 style->is_vpicture = false;
1170 style->line_pattern_vpicture_index = 0;
1171 style->is_material = false;
1172 style->color_material_index = color_index;
1173 style->is_transparency_defined = (colour.A < 1.0);
1174 style->transparency = (uint8_t)(colour.A * 256);
1175 style->additional = 0;
1176 const uint32_t style_index = addStyle(style);
1177 colourMap.insert(make_pair(colour,style_index));
1178 return style_index;
1179 }
1180
addColourWidth(const RGBAColour & colour,double width)1181 uint32_t oPRCFile::addColourWidth(const RGBAColour &colour, double width)
1182 {
1183 const RGBAColourWidth colourwidth(colour.R, colour.G, colour.B, colour.A, width);
1184 PRCcolourwidthMap::const_iterator pColour = colourwidthMap.find(colourwidth);
1185 if(pColour!=colourwidthMap.end())
1186 return pColour->second;
1187 const uint32_t color_index = addRgbColorUnique(colour.R, colour.G, colour.B);
1188 PRCStyle *style = new PRCStyle();
1189 style->line_width = width;
1190 style->is_vpicture = false;
1191 style->line_pattern_vpicture_index = 0;
1192 style->is_material = false;
1193 style->color_material_index = color_index;
1194 style->is_transparency_defined = (colour.A < 1.0);
1195 style->transparency = (uint8_t)(colour.A * 256);
1196 style->additional = 0;
1197 const uint32_t style_index = addStyle(style);
1198 colourwidthMap.insert(make_pair(colourwidth,style_index));
1199 return style_index;
1200 }
1201
addTransform(PRCGeneralTransformation3d * & transform)1202 uint32_t oPRCFile::addTransform(PRCGeneralTransformation3d*& transform)
1203 {
1204 if(!transform)
1205 return m1;
1206 PRCtransformMap::const_iterator pTransform = transformMap.find(*transform);
1207 if(pTransform!=transformMap.end())
1208 return pTransform->second;
1209 PRCCoordinateSystem *coordinateSystem = new PRCCoordinateSystem();
1210 bool transform_replaced = false;
1211 if( transform->M(0,1)==0 && transform->M(0,2)==0 &&
1212 transform->M(1,0)==0 && transform->M(1,2)==0 &&
1213 transform->M(2,0)==0 && transform->M(2,1)==0 &&
1214 transform->M(3,0)==0 && transform->M(3,1)==0 && transform->M(3,2)==0 && transform->M(3,3)==1 )
1215 {
1216 transform_replaced = true;
1217 PRCCartesianTransformation3d *carttransform = new PRCCartesianTransformation3d;
1218 // if(transform->M(0,3)==0 && transform->M(1,3)==0 && transform->M(1,3)==0 &&
1219 // transform->M(0,0)==1 && transform->M(1,1)==1 && transform->M(2,2)==1 )
1220 // carttransform->behaviour = PRC_TRANSFORMATION_Identity;
1221 if(transform->M(0,3)!=0 || transform->M(1,3)!=0 || transform->M(2,3)!=0)
1222 {
1223 carttransform->behaviour |= PRC_TRANSFORMATION_Translate;
1224 carttransform->origin.Set(transform->M(0,3),transform->M(1,3),transform->M(2,3));
1225 }
1226 if(transform->M(0,0)!=transform->M(1,1) || transform->M(0,0)!=transform->M(2,2))
1227 {
1228 carttransform->behaviour |= PRC_TRANSFORMATION_NonUniformScale;
1229 carttransform->scale.Set(transform->M(0,0),transform->M(1,1),transform->M(2,2));
1230 }
1231 else
1232 if(transform->M(0,0)!=1)
1233 {
1234 carttransform->behaviour |= PRC_TRANSFORMATION_Scale;
1235 carttransform->uniform_scale=transform->M(0,0);
1236 }
1237 coordinateSystem->axis_set = carttransform;
1238 }
1239 else
1240 coordinateSystem->axis_set = transform;
1241
1242 const uint32_t coordinate_system_index = fileStructures[0]->addCoordinateSystem(coordinateSystem);
1243 transformMap.insert(make_pair(*transform,coordinate_system_index));
1244 if(transform_replaced)
1245 delete transform;
1246 transform = NULL;
1247 return coordinate_system_index;
1248 }
1249
addTransform(const double * t)1250 uint32_t oPRCFile::addTransform(const double* t)
1251 {
1252 if(!t)
1253 return m1;
1254 PRCGeneralTransformation3d* transform = new PRCGeneralTransformation3d(t);
1255 return addTransform(transform);
1256 }
1257
addTransform(const double origin[3],const double x_axis[3],const double y_axis[3],double scale)1258 uint32_t oPRCFile::addTransform(const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
1259 {
1260 PRCCartesianTransformation3d* transform = new PRCCartesianTransformation3d(origin, x_axis, y_axis, scale);
1261 if(transform->behaviour==PRC_TRANSFORMATION_Identity)
1262 { delete transform; return m1; }
1263 PRCCoordinateSystem *coordinateSystem = new PRCCoordinateSystem();
1264 coordinateSystem->axis_set = transform;
1265 const uint32_t coordinate_system_index = fileStructures[0]->addCoordinateSystem(coordinateSystem);
1266 return coordinate_system_index;
1267 }
1268
addMaterial(const PRCmaterial & m)1269 uint32_t oPRCFile::addMaterial(const PRCmaterial& m)
1270 {
1271 PRCmaterialMap::const_iterator pMaterial = materialMap.find(m);
1272 if(pMaterial!=materialMap.end())
1273 return pMaterial->second;
1274
1275 uint32_t material_index = m1;
1276 {
1277 PRCMaterialGeneric *materialGeneric = new PRCMaterialGeneric;
1278 materialGeneric->ambient = addRgbColorUnique(m.ambient.R, m.ambient.G, m.ambient.B);
1279 materialGeneric->diffuse = addRgbColorUnique(m.diffuse.R, m.diffuse.G, m.diffuse.B);
1280 materialGeneric->emissive = addRgbColorUnique(m.emissive.R, m.emissive.G, m.emissive.B);
1281 materialGeneric->specular = addRgbColorUnique(m.specular.R, m.specular.G, m.specular.B);
1282 materialGeneric->shininess = m.shininess;
1283 materialGeneric->ambient_alpha = m.ambient.A;
1284 materialGeneric->diffuse_alpha = m.diffuse.A;
1285 materialGeneric->emissive_alpha = m.emissive.A;
1286 materialGeneric->specular_alpha = m.specular.A;
1287 material_index = addMaterialGenericUnique(materialGeneric);
1288 }
1289
1290 uint32_t style_index = m1;
1291 {
1292 PRCStyle *style = new PRCStyle;
1293 style->line_width = m.width;
1294 style->is_vpicture = false;
1295 style->line_pattern_vpicture_index = 0;
1296 style->is_material = true;
1297 style->is_transparency_defined = (m.alpha < 1.0);
1298 style->transparency = (uint8_t)(m.alpha * 256);
1299 style->additional = 0;
1300 style->color_material_index = material_index;
1301 style_index = addStyleUnique(style);
1302 }
1303 materialMap.insert(make_pair(m,style_index));
1304 return style_index;
1305 }
1306
addTexturedMaterial(const PRCmaterial & m,uint32_t n,const PRCtexture * const tt[])1307 uint32_t oPRCFile::addTexturedMaterial(const PRCmaterial& m, uint32_t n, const PRCtexture* const tt[])
1308 {
1309 uint32_t material_generic_index = m1;
1310 {
1311 PRCMaterialGeneric *materialGeneric = new PRCMaterialGeneric;
1312 materialGeneric->ambient = addRgbColorUnique(m.ambient.R, m.ambient.G, m.ambient.B);
1313 materialGeneric->diffuse = addRgbColorUnique(m.diffuse.R, m.diffuse.G, m.diffuse.B);
1314 materialGeneric->emissive = addRgbColorUnique(m.emissive.R, m.emissive.G, m.emissive.B);
1315 materialGeneric->specular = addRgbColorUnique(m.specular.R, m.specular.G, m.specular.B);
1316 materialGeneric->shininess = m.shininess;
1317 materialGeneric->ambient_alpha = m.ambient.A;
1318 materialGeneric->diffuse_alpha = m.diffuse.A;
1319 materialGeneric->emissive_alpha = m.emissive.A;
1320 materialGeneric->specular_alpha = m.specular.A;
1321 material_generic_index = addMaterialGenericUnique(materialGeneric);
1322 }
1323
1324 uint32_t color_material_index = material_generic_index;
1325
1326 uint32_t texture_application_index = m1;
1327 for (uint32_t i=n; i>0; i--) {
1328 const PRCtexture* t = tt[i-1];
1329 if (t == NULL) {
1330 continue;
1331 }
1332 const uint32_t picture_index = addPicture(t->format, t->size, t->data, t->height, t->width);
1333
1334 uint32_t texture_definition_index = m1;
1335 {
1336 PRCTextureDefinition *textureDefinition = new PRCTextureDefinition;
1337 textureDefinition->picture_index = picture_index;
1338 textureDefinition->texture_mapping_attribute = t->mapping;
1339 textureDefinition->texture_mapping_attribute_components = t->components;
1340 textureDefinition->texture_function = t->function;
1341 textureDefinition->texture_wrapping_mode_S = t->wrapping_mode_S;
1342 textureDefinition->texture_wrapping_mode_T = t->wrapping_mode_T;
1343 texture_definition_index = addTextureDefinitionUnique(textureDefinition);
1344 }
1345 {
1346 PRCTextureApplication *textureApplication = new PRCTextureApplication;
1347 textureApplication->material_generic_index=material_generic_index;
1348 textureApplication->texture_definition_index=texture_definition_index;
1349 textureApplication->next_texture_index = texture_application_index;
1350 texture_application_index = addTextureApplicationUnique(textureApplication);
1351 }
1352 color_material_index = texture_application_index;
1353 }
1354
1355 uint32_t style_index = m1;
1356 {
1357 PRCStyle *style = new PRCStyle;
1358 style->line_width = 0.0;
1359 style->is_vpicture = false;
1360 style->line_pattern_vpicture_index = 0;
1361 style->is_material = true;
1362 style->is_transparency_defined = (m.alpha < 1.0);
1363 style->transparency = (uint8_t)(m.alpha * 256);
1364 style->additional = 0;
1365 style->color_material_index = color_material_index;
1366 style_index = addStyleUnique(style);
1367 }
1368 return style_index;
1369 }
1370
isid(const double * t)1371 bool isid(const double* t)
1372 {
1373 return(
1374 t[0]==1 && t[4]==0 && t[ 8]==0 && t[12]==0 &&
1375 t[1]==0 && t[5]==1 && t[ 9]==0 && t[13]==0 &&
1376 t[2]==0 && t[6]==0 && t[10]==1 && t[14]==0 &&
1377 t[3]==0 && t[7]==0 && t[11]==0 && t[15]==1 );
1378 }
1379
1380
begingroup(const char * name,const PRCoptions * options,const double * t)1381 void oPRCFile::begingroup(const char *name, const PRCoptions *options,
1382 const double* t)
1383 {
1384 const PRCgroup &parent_group = groups.top();
1385 groups.push(PRCgroup());
1386 PRCgroup &group = groups.top();
1387 group.name=name;
1388 if(options) group.options=*options;
1389 if(t&&!isid(t))
1390 group.transform = new PRCGeneralTransformation3d(t);
1391 group.product_occurrence = new PRCProductOccurrence(name);
1392 group.parent_product_occurrence = parent_group.product_occurrence;
1393 group.part_definition = new PRCPartDefinition;
1394 group.parent_part_definition = parent_group.part_definition;
1395 }
1396
endgroup()1397 void oPRCFile::endgroup()
1398 {
1399 if(groups.size()<2) {
1400 fputs("begingroup without matching endgroup",stderr);
1401 exit(1);
1402 }
1403
1404 doGroup(groups.top());
1405 groups.pop();
1406
1407 // std::cout << lastgroupname << std::endl;
1408 // for(std::vector<std::string>::const_iterator it=lastgroupnames.begin(); it!=lastgroupnames.end(); it++)
1409 // std::cout << " " << *it << std::endl;
1410
1411 }
1412
findGroup()1413 PRCgroup& oPRCFile::findGroup()
1414 {
1415 return groups.top();
1416 }
1417
1418 #define ADDWIRE(curvtype) \
1419 PRCgroup &group = findGroup(); \
1420 group.wires.push_back(PRCwire()); \
1421 PRCwire &wire = group.wires.back(); \
1422 curvtype *curve = new curvtype; \
1423 wire.curve = curve; \
1424 wire.style = addColour(c);
1425
1426 #define ADDFACE(surftype) \
1427 PRCgroup &group = findGroup(); \
1428 group.faces.push_back(PRCface()); \
1429 PRCface& face = group.faces.back(); \
1430 surftype *surface = new surftype; \
1431 face.face = new PRCFace; \
1432 face.face->base_surface = surface; \
1433 face.transparent = m.alpha < 1.0; \
1434 face.style = addMaterial(m);
1435
1436 #define ADDCOMPFACE \
1437 PRCgroup &group = findGroup(); \
1438 group.compfaces.push_back(PRCcompface()); \
1439 PRCcompface& face = group.compfaces.back(); \
1440 PRCCompressedFace *compface = new PRCCompressedFace; \
1441 face.face = compface; \
1442 face.transparent = m.alpha < 1.0; \
1443 face.style = addMaterial(m);
1444
addPoint(const double P[3],const RGBAColour & c,double w)1445 void oPRCFile::addPoint(const double P[3], const RGBAColour &c, double w)
1446 {
1447 PRCgroup &group = findGroup();
1448 group.points[addColourWidth(c,w)].push_back(PRCVector3d(P[0],P[1],P[2]));
1449 }
1450
addPoint(double x,double y,double z,const RGBAColour & c,double w)1451 void oPRCFile::addPoint(double x, double y, double z, const RGBAColour &c, double w)
1452 {
1453 PRCgroup &group = findGroup();
1454 group.points[addColourWidth(c,w)].push_back(PRCVector3d(x,y,z));
1455 }
1456
1457
addPoints(uint32_t n,const double P[][3],const RGBAColour & c,double w)1458 void oPRCFile::addPoints(uint32_t n, const double P[][3], const RGBAColour &c, double w)
1459 {
1460 if(n==0 || P==NULL)
1461 return;
1462 PRCgroup &group = findGroup();
1463 PRCPointSet *pointset = new PRCPointSet();
1464 group.pointsets.push_back(pointset);
1465 pointset->index_of_line_style = addColourWidth(c,w);
1466 pointset->point.reserve(n);
1467 for(uint32_t i=0; i<n; i++)
1468 pointset->point.push_back(PRCVector3d(P[i][0],P[i][1],P[i][2]));
1469 }
1470
addPoints(uint32_t n,const double P[][3],uint32_t style_index)1471 void oPRCFile::addPoints(uint32_t n, const double P[][3], uint32_t style_index)
1472 {
1473 if(n==0 || P==NULL)
1474 return;
1475 PRCgroup &group = findGroup();
1476 PRCPointSet *pointset = new PRCPointSet();
1477 group.pointsets.push_back(pointset);
1478 pointset->index_of_line_style = style_index;
1479 pointset->point.reserve(n);
1480 for(uint32_t i=0; i<n; i++)
1481 pointset->point.push_back(PRCVector3d(P[i][0],P[i][1],P[i][2]));
1482 }
1483
useMesh(uint32_t tess_index,uint32_t style_index,const double origin[3],const double x_axis[3],const double y_axis[3],double scale)1484 void oPRCFile::useMesh(uint32_t tess_index, uint32_t style_index, const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
1485 {
1486 PRCgroup &group = findGroup();
1487 PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
1488 polyBrepModel->index_local_coordinate_system = addTransform(origin, x_axis, y_axis, scale);
1489 polyBrepModel->index_tessellation = tess_index;
1490 polyBrepModel->is_closed = group.options.closed;
1491 polyBrepModel->index_of_line_style = style_index;
1492 group.polymodels.push_back(polyBrepModel);
1493 }
1494
useMesh(uint32_t tess_index,uint32_t style_index,const double * t)1495 void oPRCFile::useMesh(uint32_t tess_index, uint32_t style_index, const double* t)
1496 {
1497 PRCgroup &group = findGroup();
1498 PRCPolyBrepModel *polyBrepModel = new PRCPolyBrepModel();
1499 polyBrepModel->index_local_coordinate_system = addTransform(t);
1500 polyBrepModel->index_tessellation = tess_index;
1501 polyBrepModel->is_closed = group.options.closed;
1502 polyBrepModel->index_of_line_style = style_index;
1503 group.polymodels.push_back(polyBrepModel);
1504 }
1505
useLines(uint32_t tess_index,uint32_t style_index,const double origin[3],const double x_axis[3],const double y_axis[3],double scale)1506 void oPRCFile::useLines(uint32_t tess_index, uint32_t style_index, const double origin[3], const double x_axis[3], const double y_axis[3], double scale)
1507 {
1508 PRCgroup &group = findGroup();
1509 PRCPolyWire *polyWire = new PRCPolyWire();
1510 polyWire->index_local_coordinate_system = addTransform(origin, x_axis, y_axis, scale);
1511 polyWire->index_tessellation = tess_index;
1512 polyWire->index_of_line_style = style_index;
1513 group.polywires.push_back(polyWire);
1514 }
1515
useLines(uint32_t tess_index,uint32_t style_index,const double * t)1516 void oPRCFile::useLines(uint32_t tess_index, uint32_t style_index, const double* t)
1517 {
1518 PRCgroup &group = findGroup();
1519 PRCPolyWire *polyWire = new PRCPolyWire();
1520 polyWire->index_local_coordinate_system = addTransform(t);
1521 polyWire->index_tessellation = tess_index;
1522 polyWire->index_of_line_style = style_index;
1523 group.polywires.push_back(polyWire);
1524 }
1525
addTriangles(uint32_t nP,const double P[][3],uint32_t nI,const uint32_t PI[][3],const PRCmaterial & m,uint32_t nN,const double N[][3],const uint32_t NI[][3],uint32_t nT,const double T[][2],const uint32_t TI[][3],uint32_t nC,const RGBAColour C[],const uint32_t CI[][3],uint32_t nM,const PRCmaterial M[],const uint32_t MI[],double ca)1526 void oPRCFile::addTriangles(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][3], const PRCmaterial& m,
1527 uint32_t nN, const double N[][3], const uint32_t NI[][3],
1528 uint32_t nT, const double T[][2], const uint32_t TI[][3],
1529 uint32_t nC, const RGBAColour C[], const uint32_t CI[][3],
1530 uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca)
1531 {
1532 if(nP==0 || P==NULL || nI==0 || PI==NULL)
1533 return;
1534 const uint32_t tess_index = createTriangleMesh(nP, P, nI, PI, m, nN, N, NI, nT, T, TI, nC, C, CI, nM, M, MI, ca);
1535 useMesh(tess_index,m1);
1536 }
1537
createTriangleMesh(uint32_t nP,const double P[][3],uint32_t nI,const uint32_t PI[][3],const uint32_t style_index,uint32_t nN,const double N[][3],const uint32_t NI[][3],uint32_t nT,const double T[][2],const uint32_t TI[][3],uint32_t nC,const RGBAColour C[],const uint32_t CI[][3],uint32_t nS,const uint32_t S[],const uint32_t SI[],double ca)1538 uint32_t oPRCFile::createTriangleMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][3], const uint32_t style_index,
1539 uint32_t nN, const double N[][3], const uint32_t NI[][3],
1540 uint32_t nT, const double T[][2], const uint32_t TI[][3],
1541 uint32_t nC, const RGBAColour C[], const uint32_t CI[][3],
1542 uint32_t nS, const uint32_t S[], const uint32_t SI[], double ca)
1543 {
1544 if(nP==0 || P==NULL || nI==0 || PI==NULL)
1545 return m1;
1546
1547 const bool triangle_color = (nS != 0 && S != NULL && SI != NULL);
1548 const bool vertex_color = (nC != 0 && C != NULL && CI != NULL);
1549 const bool has_normals = (nN != 0 && N != NULL && NI != NULL);
1550 const bool textured = (nT != 0 && T != NULL && TI != NULL);
1551
1552 PRC3DTess *tess = new PRC3DTess();
1553 PRCTessFace *tessFace = new PRCTessFace();
1554 tessFace->used_entities_flag = textured ? PRC_FACETESSDATA_TriangleTextured : PRC_FACETESSDATA_Triangle;
1555 tessFace->number_of_texture_coordinate_indexes = textured ? 1 : 0;
1556 tess->coordinates.reserve(3*nP);
1557 for(uint32_t i=0; i<nP; i++)
1558 {
1559 tess->coordinates.push_back(P[i][0]);
1560 tess->coordinates.push_back(P[i][1]);
1561 tess->coordinates.push_back(P[i][2]);
1562 }
1563 if(has_normals)
1564 {
1565 tess->normal_coordinate.reserve(3*nN);
1566 for(uint32_t i=0; i<nN; i++)
1567 {
1568 tess->normal_coordinate.push_back(N[i][0]);
1569 tess->normal_coordinate.push_back(N[i][1]);
1570 tess->normal_coordinate.push_back(N[i][2]);
1571 }
1572 }
1573 else
1574 tess->crease_angle = ca;
1575 if(textured)
1576 {
1577 tess->texture_coordinate.reserve(2*nT);
1578 for(uint32_t i=0; i<nT; i++)
1579 {
1580 tess->texture_coordinate.push_back(T[i][0]);
1581 tess->texture_coordinate.push_back(T[i][1]);
1582 }
1583 }
1584 tess->triangulated_index.reserve(3*nI+(has_normals?3:0)*nI+(textured?3:0)*nI);
1585 for(uint32_t i=0; i<nI; i++)
1586 {
1587 if(has_normals)
1588 tess->triangulated_index.push_back(3*NI[i][0]);
1589 if(textured)
1590 tess->triangulated_index.push_back(2*TI[i][0]);
1591 tess->triangulated_index.push_back(3*PI[i][0]);
1592 if(has_normals)
1593 tess->triangulated_index.push_back(3*NI[i][1]);
1594 if(textured)
1595 tess->triangulated_index.push_back(2*TI[i][1]);
1596 tess->triangulated_index.push_back(3*PI[i][1]);
1597 if(has_normals)
1598 tess->triangulated_index.push_back(3*NI[i][2]);
1599 if(textured)
1600 tess->triangulated_index.push_back(2*TI[i][2]);
1601 tess->triangulated_index.push_back(3*PI[i][2]);
1602 }
1603 tessFace->sizes_triangulated.push_back(nI);
1604 if(triangle_color)
1605 {
1606 tessFace->line_attributes.reserve(nI);
1607 for(uint32_t i=0; i<nI; i++)
1608 tessFace->line_attributes.push_back(SI[i]);
1609 }
1610 else if (style_index != m1 )
1611 {
1612 tessFace->line_attributes.push_back(style_index);
1613 }
1614 if(vertex_color)
1615 {
1616 tessFace->is_rgba=false;
1617 for(uint32_t i=0; i<nI; i++)
1618 if(1.0 != C[CI[i][0]].A || 1.0 != C[CI[i][1]].A || 1.0 != C[CI[i][2]].A)
1619 {
1620 tessFace->is_rgba=true;
1621 break;
1622 }
1623
1624 tessFace->rgba_vertices.reserve((tessFace->is_rgba?4:3)*3*nI);
1625 for(uint32_t i=0; i<nI; i++)
1626 {
1627 tessFace->rgba_vertices.push_back(toByte(C[CI[i][0]].R));
1628 tessFace->rgba_vertices.push_back(toByte(C[CI[i][0]].G));
1629 tessFace->rgba_vertices.push_back(toByte(C[CI[i][0]].B));
1630 if(tessFace->is_rgba)
1631 tessFace->rgba_vertices.push_back(toByte(C[CI[i][0]].A));
1632 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].R));
1633 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].G));
1634 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].B));
1635 if(tessFace->is_rgba)
1636 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].A));
1637 tessFace->rgba_vertices.push_back(toByte(C[CI[i][2]].R));
1638 tessFace->rgba_vertices.push_back(toByte(C[CI[i][2]].G));
1639 tessFace->rgba_vertices.push_back(toByte(C[CI[i][2]].B));
1640 if(tessFace->is_rgba)
1641 tessFace->rgba_vertices.push_back(toByte(C[CI[i][2]].A));
1642 }
1643 }
1644 tess->addTessFace(tessFace);
1645 const uint32_t tess_index = add3DTess(tess);
1646 return tess_index;
1647 }
1648
addQuads(uint32_t nP,const double P[][3],uint32_t nI,const uint32_t PI[][4],const PRCmaterial & m,uint32_t nN,const double N[][3],const uint32_t NI[][4],uint32_t nT,const double T[][2],const uint32_t TI[][4],uint32_t nC,const RGBAColour C[],const uint32_t CI[][4],uint32_t nM,const PRCmaterial M[],const uint32_t MI[],double ca)1649 void oPRCFile::addQuads(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], const PRCmaterial& m,
1650 uint32_t nN, const double N[][3], const uint32_t NI[][4],
1651 uint32_t nT, const double T[][2], const uint32_t TI[][4],
1652 uint32_t nC, const RGBAColour C[], const uint32_t CI[][4],
1653 uint32_t nM, const PRCmaterial M[], const uint32_t MI[], double ca)
1654 {
1655 if(nP==0 || P==NULL || nI==0 || PI==NULL)
1656 return;
1657 const uint32_t tess_index = createQuadMesh(nP, P, nI, PI, m, nN, N, NI, nT, T, TI, nC, C, CI, nM, M, MI, ca);
1658 useMesh(tess_index,m1);
1659 }
1660
createQuadMesh(uint32_t nP,const double P[][3],uint32_t nI,const uint32_t PI[][4],uint32_t style_index,uint32_t nN,const double N[][3],const uint32_t NI[][4],uint32_t nT,const double T[][2],const uint32_t TI[][4],uint32_t nC,const RGBAColour C[],const uint32_t CI[][4],uint32_t nS,const uint32_t S[],const uint32_t SI[],double ca)1661 uint32_t oPRCFile::createQuadMesh(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][4], uint32_t style_index,
1662 uint32_t nN, const double N[][3], const uint32_t NI[][4],
1663 uint32_t nT, const double T[][2], const uint32_t TI[][4],
1664 uint32_t nC, const RGBAColour C[], const uint32_t CI[][4],
1665 uint32_t nS, const uint32_t S[], const uint32_t SI[], double ca)
1666 {
1667 if(nP==0 || P==NULL || nI==0 || PI==NULL)
1668 return m1;
1669
1670 const bool triangle_color = (nS != 0 && S != NULL && SI != NULL);
1671 const bool vertex_color = (nC != 0 && C != NULL && CI != NULL);
1672 const bool has_normals = (nN != 0 && N != NULL && NI != NULL);
1673 const bool textured = (nT != 0 && T != NULL && TI != NULL);
1674
1675 PRC3DTess *tess = new PRC3DTess();
1676 PRCTessFace *tessFace = new PRCTessFace();
1677 tessFace->used_entities_flag = textured ? PRC_FACETESSDATA_TriangleTextured : PRC_FACETESSDATA_Triangle;
1678 tessFace->number_of_texture_coordinate_indexes = textured ? 1 : 0;
1679 tess->coordinates.reserve(3*nP);
1680 for(uint32_t i=0; i<nP; i++)
1681 {
1682 tess->coordinates.push_back(P[i][0]);
1683 tess->coordinates.push_back(P[i][1]);
1684 tess->coordinates.push_back(P[i][2]);
1685 }
1686 if(has_normals)
1687 {
1688 tess->normal_coordinate.reserve(3*nN);
1689 for(uint32_t i=0; i<nN; i++)
1690 {
1691 tess->normal_coordinate.push_back(N[i][0]);
1692 tess->normal_coordinate.push_back(N[i][1]);
1693 tess->normal_coordinate.push_back(N[i][2]);
1694 }
1695 }
1696 else
1697 tess->crease_angle = ca;
1698 if(textured)
1699 {
1700 tess->texture_coordinate.reserve(2*nT);
1701 for(uint32_t i=0; i<nT; i++)
1702 {
1703 tess->texture_coordinate.push_back(T[i][0]);
1704 tess->texture_coordinate.push_back(T[i][1]);
1705 }
1706 }
1707 tess->triangulated_index.reserve(2*(3*nI+(has_normals?3:0)*nI+(textured?3:0)*nI));
1708 for(uint32_t i=0; i<nI; i++)
1709 {
1710 // first triangle
1711 if(has_normals)
1712 tess->triangulated_index.push_back(3*NI[i][0]);
1713 if(textured)
1714 tess->triangulated_index.push_back(2*TI[i][0]);
1715 tess->triangulated_index.push_back(3*PI[i][0]);
1716 if(has_normals)
1717 tess->triangulated_index.push_back(3*NI[i][1]);
1718 if(textured)
1719 tess->triangulated_index.push_back(2*TI[i][1]);
1720 tess->triangulated_index.push_back(3*PI[i][1]);
1721 if(has_normals)
1722 tess->triangulated_index.push_back(3*NI[i][3]);
1723 if(textured)
1724 tess->triangulated_index.push_back(2*TI[i][3]);
1725 tess->triangulated_index.push_back(3*PI[i][3]);
1726 // second triangle
1727 if(has_normals)
1728 tess->triangulated_index.push_back(3*NI[i][1]);
1729 if(textured)
1730 tess->triangulated_index.push_back(2*TI[i][1]);
1731 tess->triangulated_index.push_back(3*PI[i][1]);
1732 if(has_normals)
1733 tess->triangulated_index.push_back(3*NI[i][2]);
1734 if(textured)
1735 tess->triangulated_index.push_back(2*TI[i][2]);
1736 tess->triangulated_index.push_back(3*PI[i][2]);
1737 if(has_normals)
1738 tess->triangulated_index.push_back(3*NI[i][3]);
1739 if(textured)
1740 tess->triangulated_index.push_back(2*TI[i][3]);
1741 tess->triangulated_index.push_back(3*PI[i][3]);
1742 }
1743 tessFace->sizes_triangulated.push_back(2*nI);
1744 if(triangle_color)
1745 {
1746 tessFace->line_attributes.reserve(2*nI);
1747 for(uint32_t i=0; i<nI; i++)
1748 {
1749 tessFace->line_attributes.push_back(SI[i]);
1750 tessFace->line_attributes.push_back(SI[i]);
1751 }
1752 }
1753 else
1754 {
1755 tessFace->line_attributes.push_back(style_index);
1756 }
1757 if(vertex_color)
1758 {
1759 tessFace->is_rgba=false;
1760 for(uint32_t i=0; i<nI; i++)
1761 if(1.0 != C[CI[i][0]].A || 1.0 != C[CI[i][1]].A || 1.0 != C[CI[i][2]].A)
1762 {
1763 tessFace->is_rgba=true;
1764 break;
1765 }
1766
1767 tessFace->rgba_vertices.reserve(2*(tessFace->is_rgba?4:3)*3*nI);
1768 for(uint32_t i=0; i<nI; i++)
1769 {
1770 // first triangle
1771 tessFace->rgba_vertices.push_back(toByte(C[CI[i][0]].R));
1772 tessFace->rgba_vertices.push_back(toByte(C[CI[i][0]].G));
1773 tessFace->rgba_vertices.push_back(toByte(C[CI[i][0]].B));
1774 if(tessFace->is_rgba)
1775 tessFace->rgba_vertices.push_back(toByte(C[CI[i][0]].A));
1776 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].R));
1777 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].G));
1778 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].B));
1779 if(tessFace->is_rgba)
1780 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].A));
1781 tessFace->rgba_vertices.push_back(toByte(C[CI[i][3]].R));
1782 tessFace->rgba_vertices.push_back(toByte(C[CI[i][3]].G));
1783 tessFace->rgba_vertices.push_back(toByte(C[CI[i][3]].B));
1784 if(tessFace->is_rgba)
1785 tessFace->rgba_vertices.push_back(toByte(C[CI[i][3]].A));
1786 // second triangle
1787 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].R));
1788 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].G));
1789 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].B));
1790 if(tessFace->is_rgba)
1791 tessFace->rgba_vertices.push_back(toByte(C[CI[i][1]].A));
1792 tessFace->rgba_vertices.push_back(toByte(C[CI[i][2]].R));
1793 tessFace->rgba_vertices.push_back(toByte(C[CI[i][2]].G));
1794 tessFace->rgba_vertices.push_back(toByte(C[CI[i][2]].B));
1795 if(tessFace->is_rgba)
1796 tessFace->rgba_vertices.push_back(toByte(C[CI[i][2]].A));
1797 tessFace->rgba_vertices.push_back(toByte(C[CI[i][3]].R));
1798 tessFace->rgba_vertices.push_back(toByte(C[CI[i][3]].G));
1799 tessFace->rgba_vertices.push_back(toByte(C[CI[i][3]].B));
1800 if(tessFace->is_rgba)
1801 tessFace->rgba_vertices.push_back(toByte(C[CI[i][3]].A));
1802 }
1803 }
1804 tess->addTessFace(tessFace);
1805 const uint32_t tess_index = add3DTess(tess);
1806 return tess_index;
1807 }
1808
addQuad(const double P[][3],const RGBAColour C[])1809 void oPRCFile::addQuad(const double P[][3], const RGBAColour C[])
1810 {
1811 PRCgroup &group = findGroup();
1812
1813 group.quads.push_back(PRCtessquad());
1814 PRCtessquad &quad = group.quads.back();
1815 for(size_t i = 0; i < 4; i++)
1816 {
1817 quad.vertices[i].x = P[i][0];
1818 quad.vertices[i].y = P[i][1];
1819 quad.vertices[i].z = P[i][2];
1820 quad.colours[i] = C[i];
1821 }
1822 }
1823 /*
1824 void oPRCFile::addTriangle(const double P[][3], const double T[][2], uint32_t style_index)
1825 {
1826 PRCgroup &group = findGroup();
1827
1828 group.triangles.push_back(PRCtesstriangle());
1829 PRCtesstriangle &triangle = group.triangles.back();
1830 for(size_t i = 0; i < 3; i++)
1831 {
1832 triangle.vertices[i].x = P[i][0];
1833 triangle.vertices[i].y = P[i][1];
1834 triangle.vertices[i].z = P[i][2];
1835 triangle.texcoords[i].x = T[i][0];
1836 triangle.texcoords[i].y = T[i][1];
1837 }
1838 triangle.style = style_index;
1839 }
1840 */
1841
addLines(uint32_t nP,const double P[][3],uint32_t nI,const uint32_t PI[],const RGBAColour & c,double w,bool segment_color,uint32_t nC,const RGBAColour C[],uint32_t nCI,const uint32_t CI[])1842 void oPRCFile::addLines(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[],
1843 const RGBAColour& c, double w,
1844 bool segment_color, uint32_t nC, const RGBAColour C[], uint32_t nCI, const uint32_t CI[])
1845 {
1846 if(nP==0 || P==NULL || nI==0 || PI==NULL)
1847 return;
1848 const uint32_t tess_index = createLines(nP, P, nI, PI, segment_color, nC, C, nCI, CI);
1849 useLines(tess_index, c, w);
1850 }
1851
createLines(uint32_t nP,const double P[][3],uint32_t nI,const uint32_t PI[],bool segment_color,uint32_t nC,const RGBAColour C[],uint32_t nCI,const uint32_t CI[])1852 uint32_t oPRCFile::createLines(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[],
1853 bool segment_color, uint32_t nC, const RGBAColour C[], uint32_t nCI, const uint32_t CI[])
1854 {
1855 if(nP==0 || P==NULL || nI==0 || PI==NULL)
1856 return m1;
1857
1858 const bool vertex_color = (nC != 0 && C != NULL && CI != NULL);
1859
1860 PRC3DWireTess *tess = new PRC3DWireTess();
1861 tess->coordinates.reserve(3*nP);
1862 for(uint32_t i=0; i<nP; i++)
1863 {
1864 tess->coordinates.push_back(P[i][0]);
1865 tess->coordinates.push_back(P[i][1]);
1866 tess->coordinates.push_back(P[i][2]);
1867 }
1868 tess->wire_indexes.reserve(nI);
1869 for(uint32_t i=0; i<nI;)
1870 {
1871 tess->wire_indexes.push_back(PI[i]);
1872 const uint32_t ni = i+PI[i]+1;
1873 for(i++; i<ni; i++)
1874 tess->wire_indexes.push_back(3*PI[i]);
1875 }
1876 if(vertex_color)
1877 {
1878 tess->is_segment_color = segment_color;
1879 tess->is_rgba=false;
1880 for(uint32_t i=0; i<nCI; i++)
1881 if(1.0 != C[CI[i]].A)
1882 {
1883 tess->is_rgba=true;
1884 break;
1885 }
1886 tess->rgba_vertices.reserve((tess->is_rgba?4:3)*nCI);
1887 for(uint32_t i=0; i<nCI; i++)
1888 {
1889 tess->rgba_vertices.push_back(toByte(C[CI[i]].R));
1890 tess->rgba_vertices.push_back(toByte(C[CI[i]].G));
1891 tess->rgba_vertices.push_back(toByte(C[CI[i]].B));
1892 if(tess->is_rgba)
1893 tess->rgba_vertices.push_back(toByte(C[CI[i]].A));
1894 }
1895 }
1896 const uint32_t tess_index = add3DWireTess(tess);
1897 return tess_index;
1898 }
1899
createSegments(uint32_t nP,const double P[][3],uint32_t nI,const uint32_t PI[][2],bool segment_color,uint32_t nC,const RGBAColour C[],const uint32_t CI[][2])1900 uint32_t oPRCFile::createSegments(uint32_t nP, const double P[][3], uint32_t nI, const uint32_t PI[][2],
1901 bool segment_color, uint32_t nC, const RGBAColour C[], const uint32_t CI[][2])
1902 {
1903 if(nP==0 || P==NULL || nI==0 || PI==NULL)
1904 return m1;
1905
1906 const bool vertex_color = (nC != 0 && C != NULL && CI != NULL);
1907
1908 PRC3DWireTess *tess = new PRC3DWireTess();
1909 tess->coordinates.reserve(3*nP);
1910 for(uint32_t i=0; i<nP; i++)
1911 {
1912 tess->coordinates.push_back(P[i][0]);
1913 tess->coordinates.push_back(P[i][1]);
1914 tess->coordinates.push_back(P[i][2]);
1915 }
1916 tess->wire_indexes.reserve(3*nI);
1917 for(uint32_t i=0; i<nI; i++)
1918 {
1919 tess->wire_indexes.push_back(2);
1920 tess->wire_indexes.push_back(3*PI[i][0]);
1921 tess->wire_indexes.push_back(3*PI[i][1]);
1922 }
1923 if(vertex_color)
1924 {
1925 tess->is_segment_color = segment_color;
1926 tess->is_rgba=false;
1927 for(uint32_t i=0; i<nI; i++)
1928 if(1.0 != C[CI[i][0]].A || 1.0 != C[CI[i][1]].A)
1929 {
1930 tess->is_rgba=true;
1931 break;
1932 }
1933 tess->rgba_vertices.reserve((tess->is_rgba?4:3)*(segment_color?1:2)*nI);
1934 for(uint32_t i=0; i<nI; i++)
1935 {
1936 if (segment_color) {
1937 tess->rgba_vertices.push_back(toByte(0.5*C[CI[i][0]].R+0.5*C[CI[i][1]].R));
1938 tess->rgba_vertices.push_back(toByte(0.5*C[CI[i][0]].G+0.5*C[CI[i][1]].G));
1939 tess->rgba_vertices.push_back(toByte(0.5*C[CI[i][0]].B+0.5*C[CI[i][1]].B));
1940 if(tess->is_rgba)
1941 tess->rgba_vertices.push_back(toByte(0.5*C[CI[i][0]].A+0.5*C[CI[i][1]].A));
1942 } else {
1943 tess->rgba_vertices.push_back(toByte(C[CI[i][0]].R));
1944 tess->rgba_vertices.push_back(toByte(C[CI[i][0]].G));
1945 tess->rgba_vertices.push_back(toByte(C[CI[i][0]].B));
1946 if(tess->is_rgba)
1947 tess->rgba_vertices.push_back(toByte(C[CI[i][0]].A));
1948 tess->rgba_vertices.push_back(toByte(C[CI[i][1]].R));
1949 tess->rgba_vertices.push_back(toByte(C[CI[i][1]].G));
1950 tess->rgba_vertices.push_back(toByte(C[CI[i][1]].B));
1951 if(tess->is_rgba)
1952 tess->rgba_vertices.push_back(toByte(C[CI[i][1]].A));
1953 }
1954 }
1955 }
1956 const uint32_t tess_index = add3DWireTess(tess);
1957 return tess_index;
1958 }
1959
addLine(uint32_t n,const double P[][3],const RGBAColour & c,double w)1960 void oPRCFile::addLine(uint32_t n, const double P[][3], const RGBAColour &c, double w)
1961 {
1962 PRCgroup &group = findGroup();
1963 if(group.options.tess)
1964 {
1965 group.lines[w].push_back(PRCtessline());
1966 PRCtessline& line = group.lines[w].back();
1967 line.color.red = c.R;
1968 line.color.green = c.G;
1969 line.color.blue = c.B;
1970 for(uint32_t i=0; i<n; i++)
1971 line.point.push_back(PRCVector3d(P[i][0],P[i][1],P[i][2]));
1972 }
1973 else
1974 {
1975 ADDWIRE(PRCPolyLine)
1976 curve->point.resize(n);
1977 for(uint32_t i=0; i<n; i++)
1978 curve->point[i].Set(P[i][0],P[i][1],P[i][2]);
1979 curve->interval.min = 0;
1980 curve->interval.max = curve->point.size()-1;
1981 }
1982 }
1983
addSegment(const double P1[3],const double P2[3],const RGBAColour & c,double w)1984 void oPRCFile::addSegment(const double P1[3], const double P2[3], const RGBAColour &c, double w)
1985 {
1986 PRCgroup &group = findGroup();
1987 if(group.options.tess)
1988 {
1989 group.lines[w].push_back(PRCtessline());
1990 PRCtessline& line = group.lines[w].back();
1991 line.color.red = c.R;
1992 line.color.green = c.G;
1993 line.color.blue = c.B;
1994 line.point.push_back(PRCVector3d(P1[0],P1[1],P1[2]));
1995 line.point.push_back(PRCVector3d(P2[0],P2[1],P2[2]));
1996 }
1997 else
1998 {
1999 ADDWIRE(PRCPolyLine)
2000 curve->point.resize(2);
2001 curve->point[0].Set(P1[0],P1[1],P1[2]);
2002 curve->point[1].Set(P2[0],P2[1],P2[2]);
2003 curve->interval.min = 0;
2004 curve->interval.max = curve->point.size()-1;
2005 }
2006 }
2007
addBezierCurve(uint32_t n,const double cP[][3],const RGBAColour & c)2008 void oPRCFile::addBezierCurve(uint32_t n, const double cP[][3],
2009 const RGBAColour &c)
2010 {
2011 ADDWIRE(PRCNURBSCurve)
2012 curve->is_rational = false;
2013 curve->degree = 3;
2014 const size_t NUMBER_OF_POINTS = n;
2015 curve->control_point.resize(NUMBER_OF_POINTS);
2016 for(size_t i = 0; i < NUMBER_OF_POINTS; ++i)
2017 curve->control_point[i].Set(cP[i][0],cP[i][1],cP[i][2]);
2018 curve->knot.resize(3+NUMBER_OF_POINTS+1);
2019 curve->knot[0] = 1;
2020 for(size_t i = 1; i < 3+NUMBER_OF_POINTS; ++i)
2021 curve->knot[i] = (i+2)/3; // integer division is intentional
2022 curve->knot[3+NUMBER_OF_POINTS] = (3+NUMBER_OF_POINTS+1)/3;
2023 }
2024
addCurve(uint32_t d,uint32_t n,const double cP[][3],const double * k,const RGBAColour & c,const double w[])2025 void oPRCFile::addCurve(uint32_t d, uint32_t n, const double cP[][3], const double *k, const RGBAColour &c, const double w[])
2026 {
2027 ADDWIRE(PRCNURBSCurve)
2028 curve->is_rational = (w!=NULL);
2029 curve->degree = d;
2030 curve->control_point.resize(n);
2031 for(uint32_t i = 0; i < n; i++)
2032 if(w)
2033 curve->control_point[i].Set(cP[i][0]*w[i],cP[i][1]*w[i],cP[i][2]*w[i],w[i]);
2034 else
2035 curve->control_point[i].Set(cP[i][0],cP[i][1],cP[i][2]);
2036 curve->knot.resize(d+n+1);
2037 for(uint32_t i = 0; i < d+n+1; i++)
2038 curve->knot[i] = k[i];
2039 }
2040
addRectangle(const double P[][3],const PRCmaterial & m)2041 void oPRCFile::addRectangle(const double P[][3], const PRCmaterial &m)
2042 {
2043 PRCgroup &group = findGroup();
2044 if(group.options.tess)
2045 {
2046 group.rectangles.push_back(PRCtessrectangle());
2047 PRCtessrectangle &rectangle = group.rectangles.back();
2048 rectangle.style = addMaterial(m);
2049 for(size_t i = 0; i < 4; i++)
2050 {
2051 rectangle.vertices[i].x = P[i][0];
2052 rectangle.vertices[i].y = P[i][1];
2053 rectangle.vertices[i].z = P[i][2];
2054 }
2055 }
2056 else if(group.options.compression == 0.0)
2057 {
2058 ADDFACE(PRCNURBSSurface)
2059
2060 surface->is_rational = false;
2061 surface->degree_in_u = 1;
2062 surface->degree_in_v = 1;
2063 surface->control_point.resize(4);
2064 for(size_t i = 0; i < 4; ++i)
2065 {
2066 surface->control_point[i].x = P[i][0];
2067 surface->control_point[i].y = P[i][1];
2068 surface->control_point[i].z = P[i][2];
2069 }
2070 surface->knot_u.resize(4);
2071 surface->knot_v.resize(4);
2072 surface->knot_v[0] = surface->knot_u[0] = 1;
2073 surface->knot_v[1] = surface->knot_u[1] = 3;
2074 surface->knot_v[2] = surface->knot_u[2] = 4;
2075 surface->knot_v[3] = surface->knot_u[3] = 4;
2076 }
2077 else
2078 {
2079 ADDCOMPFACE
2080
2081 compface->degree = 1;
2082 compface->control_point.resize(4);
2083 for(size_t i = 0; i < 4; ++i)
2084 {
2085 compface->control_point[i].x = P[i][0];
2086 compface->control_point[i].y = P[i][1];
2087 compface->control_point[i].z = P[i][2];
2088 }
2089 }
2090 }
2091
addPatch(const double cP[][3],const PRCmaterial & m)2092 void oPRCFile::addPatch(const double cP[][3], const PRCmaterial &m)
2093 {
2094 PRCgroup &group = findGroup();
2095 if(group.options.compression == 0.0)
2096 {
2097 ADDFACE(PRCNURBSSurface)
2098
2099 surface->is_rational = false;
2100 surface->degree_in_u = 3;
2101 surface->degree_in_v = 3;
2102 surface->control_point.resize(16);
2103 for(size_t i = 0; i < 16; ++i)
2104 {
2105 surface->control_point[i].x = cP[i][0];
2106 surface->control_point[i].y = cP[i][1];
2107 surface->control_point[i].z = cP[i][2];
2108 }
2109 surface->knot_u.resize(8);
2110 surface->knot_v.resize(8);
2111 surface->knot_v[0] = surface->knot_u[0] = 1;
2112 surface->knot_v[1] = surface->knot_u[1] = 1;
2113 surface->knot_v[2] = surface->knot_u[2] = 1;
2114 surface->knot_v[3] = surface->knot_u[3] = 1;
2115 surface->knot_v[4] = surface->knot_u[4] = 2;
2116 surface->knot_v[5] = surface->knot_u[5] = 2;
2117 surface->knot_v[6] = surface->knot_u[6] = 2;
2118 surface->knot_v[7] = surface->knot_u[7] = 2;
2119 }
2120 else
2121 {
2122 ADDCOMPFACE
2123
2124 compface->degree = 3;
2125 compface->control_point.resize(16);
2126 for(size_t i = 0; i < 16; ++i)
2127 {
2128 compface->control_point[i].x = cP[i][0];
2129 compface->control_point[i].y = cP[i][1];
2130 compface->control_point[i].z = cP[i][2];
2131 }
2132 }
2133 }
2134
addSurface(uint32_t dU,uint32_t dV,uint32_t nU,uint32_t nV,const double cP[][3],const double * kU,const double * kV,const PRCmaterial & m,const double w[])2135 void oPRCFile::addSurface(uint32_t dU, uint32_t dV, uint32_t nU, uint32_t nV,
2136 const double cP[][3], const double *kU,
2137 const double *kV, const PRCmaterial &m,
2138 const double w[])
2139 {
2140 ADDFACE(PRCNURBSSurface)
2141
2142 surface->is_rational = (w!=NULL);
2143 surface->degree_in_u = dU;
2144 surface->degree_in_v = dV;
2145 surface->control_point.resize(nU*nV);
2146 for(size_t i = 0; i < nU*nV; i++)
2147 if(w)
2148 surface->control_point[i]=PRCControlPoint(cP[i][0]*w[i],cP[i][1]*w[i],cP[i][2]*w[i],w[i]);
2149 else
2150 surface->control_point[i]=PRCControlPoint(cP[i][0],cP[i][1],cP[i][2]);
2151 surface->knot_u.insert(surface->knot_u.end(), kU, kU+(dU+nU+1));
2152 surface->knot_v.insert(surface->knot_v.end(), kV, kV+(dV+nV+1));
2153 }
2154
2155 #define SETTRANSF \
2156 if(t&&!isid(t)) \
2157 face.transform = new PRCGeneralTransformation3d(t); \
2158 if(origin) surface->origin.Set(origin[0],origin[1],origin[2]); \
2159 if(x_axis) surface->x_axis.Set(x_axis[0],x_axis[1],x_axis[2]); \
2160 if(y_axis) surface->y_axis.Set(y_axis[0],y_axis[1],y_axis[2]); \
2161 surface->scale = scale; \
2162 surface->geometry_is_2D = false; \
2163 if(surface->origin!=PRCVector3d(0.0,0.0,0.0)) \
2164 surface->behaviour = surface->behaviour | PRC_TRANSFORMATION_Translate; \
2165 if(surface->x_axis!=PRCVector3d(1.0,0.0,0.0)||surface->y_axis!=PRCVector3d(0.0,1.0,0.0)) \
2166 surface->behaviour = surface->behaviour | PRC_TRANSFORMATION_Rotate; \
2167 if(surface->scale!=1) \
2168 surface->behaviour = surface->behaviour | PRC_TRANSFORMATION_Scale; \
2169 surface->has_transformation = (surface->behaviour != PRC_TRANSFORMATION_Identity);
2170
2171 #define PRCFACETRANSFORM const double origin[3], const double x_axis[3], const double y_axis[3], double scale, const double* t
2172
addTube(uint32_t n,const double cP[][3],const double oP[][3],bool straight,const PRCmaterial & m,PRCFACETRANSFORM)2173 void oPRCFile::addTube(uint32_t n, const double cP[][3], const double oP[][3], bool straight, const PRCmaterial &m, PRCFACETRANSFORM)
2174 {
2175 ADDFACE(PRCBlend01)
2176 SETTRANSF
2177 if(straight)
2178 {
2179 PRCPolyLine *center_curve = new PRCPolyLine;
2180 center_curve->point.resize(n);
2181 for(uint32_t i=0; i<n; i++)
2182 center_curve->point[i].Set(cP[i][0],cP[i][1],cP[i][2]);
2183 center_curve->interval.min = 0;
2184 center_curve->interval.max = center_curve->point.size()-1;
2185 surface->center_curve = center_curve;
2186
2187 PRCPolyLine *origin_curve = new PRCPolyLine;
2188 origin_curve->point.resize(n);
2189 for(uint32_t i=0; i<n; i++)
2190 origin_curve->point[i].Set(oP[i][0],oP[i][1],oP[i][2]);
2191 origin_curve->interval.min = 0;
2192 origin_curve->interval.max = origin_curve->point.size()-1;
2193 surface->origin_curve = origin_curve;
2194
2195 surface->uv_domain.min.x = 0;
2196 surface->uv_domain.max.x = 2*pi;
2197 surface->uv_domain.min.y = 0;
2198 surface->uv_domain.max.y = n-1;
2199 }
2200 else
2201 {
2202 PRCNURBSCurve *center_curve = new PRCNURBSCurve;
2203 center_curve->is_rational = false;
2204 center_curve->degree = 3;
2205 const uint32_t CENTER_NUMBER_OF_POINTS = n;
2206 center_curve->control_point.resize(CENTER_NUMBER_OF_POINTS);
2207 for(uint32_t i = 0; i < CENTER_NUMBER_OF_POINTS; ++i)
2208 center_curve->control_point[i].Set(cP[i][0],cP[i][1],cP[i][2]);
2209 center_curve->knot.resize(3+CENTER_NUMBER_OF_POINTS+1);
2210 center_curve->knot[0] = 1;
2211 for(uint32_t i = 1; i < 3+CENTER_NUMBER_OF_POINTS; ++i)
2212 center_curve->knot[i] = (i+2)/3; // integer division is intentional
2213 center_curve->knot[3+CENTER_NUMBER_OF_POINTS] = (3+CENTER_NUMBER_OF_POINTS+1)/3;
2214 surface->center_curve = center_curve;
2215
2216 PRCNURBSCurve *origin_curve = new PRCNURBSCurve;
2217 origin_curve->is_rational = false;
2218 origin_curve->degree = 3;
2219 const uint32_t ORIGIN_NUMBER_OF_POINTS = n;
2220 origin_curve->control_point.resize(ORIGIN_NUMBER_OF_POINTS);
2221 for(uint32_t i = 0; i < ORIGIN_NUMBER_OF_POINTS; ++i)
2222 origin_curve->control_point[i].Set(oP[i][0],oP[i][1],oP[i][2]);
2223 origin_curve->knot.resize(3+ORIGIN_NUMBER_OF_POINTS+1);
2224 origin_curve->knot[0] = 1;
2225 for(size_t i = 1; i < 3+ORIGIN_NUMBER_OF_POINTS; ++i)
2226 origin_curve->knot[i] = (i+2)/3; // integer division is intentional
2227 origin_curve->knot[3+ORIGIN_NUMBER_OF_POINTS] = (3+ORIGIN_NUMBER_OF_POINTS+1)/3;
2228 surface->origin_curve = origin_curve;
2229
2230 surface->uv_domain.min.x = 0;
2231 surface->uv_domain.max.x = 2*pi;
2232 surface->uv_domain.min.y = 1; // first knot
2233 surface->uv_domain.max.y = (3+CENTER_NUMBER_OF_POINTS+1)/3; // last knot
2234 }
2235 }
2236
addHemisphere(double radius,const PRCmaterial & m,PRCFACETRANSFORM)2237 void oPRCFile::addHemisphere(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
2238 {
2239 ADDFACE(PRCSphere)
2240 SETTRANSF
2241 surface->uv_domain.min.x = 0;
2242 surface->uv_domain.max.x = 2*pi;
2243 surface->uv_domain.min.y = 0;
2244 surface->uv_domain.max.y = 0.5*pi;
2245 surface->radius = radius;
2246 }
2247
addSphere(double radius,const PRCmaterial & m,PRCFACETRANSFORM)2248 void oPRCFile::addSphere(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
2249 {
2250 ADDFACE(PRCSphere)
2251 SETTRANSF
2252 surface->uv_domain.min.x = 0;
2253 surface->uv_domain.max.x = 2*pi;
2254 surface->uv_domain.min.y =-0.5*pi;
2255 surface->uv_domain.max.y = 0.5*pi;
2256 surface->radius = radius;
2257 }
2258
addDisk(double radius,const PRCmaterial & m,PRCFACETRANSFORM)2259 void oPRCFile::addDisk(double radius, const PRCmaterial &m, PRCFACETRANSFORM)
2260 {
2261 ADDFACE(PRCRuled)
2262 SETTRANSF
2263 PRCCircle *first_curve = new PRCCircle;
2264 first_curve->radius = radius;
2265 surface->first_curve = first_curve;
2266 PRCCircle *second_curve = new PRCCircle;
2267 second_curve->radius = 0;
2268 surface->second_curve = second_curve;
2269
2270 surface->uv_domain.min.x = 0;
2271 surface->uv_domain.max.x = 1;
2272 surface->uv_domain.min.y = 0;
2273 surface->uv_domain.max.y = 2*pi;
2274 surface->parameterization_on_v_coeff_a = -1;
2275 surface->parameterization_on_v_coeff_b = 2*pi;
2276 }
2277
addCylinder(double radius,double height,const PRCmaterial & m,PRCFACETRANSFORM)2278 void oPRCFile::addCylinder(double radius, double height, const PRCmaterial &m, PRCFACETRANSFORM)
2279 {
2280 ADDFACE(PRCCylinder)
2281 SETTRANSF
2282 surface->uv_domain.min.x = 0;
2283 surface->uv_domain.max.x = 2*pi;
2284 surface->uv_domain.min.y = (height>0)?0:height;
2285 surface->uv_domain.max.y = (height>0)?height:0;
2286 surface->radius = radius;
2287 }
2288
addCone(double radius,double height,const PRCmaterial & m,PRCFACETRANSFORM)2289 void oPRCFile::addCone(double radius, double height, const PRCmaterial &m, PRCFACETRANSFORM)
2290 {
2291 ADDFACE(PRCCone)
2292 SETTRANSF
2293 surface->uv_domain.min.x = 0;
2294 surface->uv_domain.max.x = 2*pi;
2295 surface->uv_domain.min.y = (height>0)?0:height;
2296 surface->uv_domain.max.y = (height>0)?height:0;
2297 surface->bottom_radius = radius;
2298 surface->semi_angle = -atan(radius/height);;
2299 }
2300
addTorus(double major_radius,double minor_radius,double angle1,double angle2,const PRCmaterial & m,PRCFACETRANSFORM)2301 void oPRCFile::addTorus(double major_radius, double minor_radius, double angle1, double angle2, const PRCmaterial &m, PRCFACETRANSFORM)
2302 {
2303 ADDFACE(PRCTorus)
2304 SETTRANSF
2305 surface->uv_domain.min.x = (angle1/180)*pi;
2306 surface->uv_domain.max.x = (angle2/180)*pi;
2307 surface->uv_domain.min.y = 0;
2308 surface->uv_domain.max.y = 2*pi;
2309 surface->major_radius = major_radius;
2310 surface->minor_radius = minor_radius;
2311 }
2312
2313 #undef PRCFACETRANSFORM
2314 #undef ADDFACE
2315 #undef ADDWIRE
2316 #undef SETTRANSF
2317
addRgbColor(double r,double g,double b)2318 uint32_t PRCFileStructure::addRgbColor(double r, double g, double b)
2319 {
2320 const PRCRgbColor color(r, g, b);
2321 colors.push_back(color);
2322 return 3*(colors.size()-1);
2323 }
2324
addRgbColorUnique(double r,double g,double b)2325 uint32_t PRCFileStructure::addRgbColorUnique(double r, double g, double b)
2326 {
2327 const PRCRgbColor color(r, g, b);
2328 uint32_t color_index = m1;
2329 PRCRgbColorMap::const_iterator iRgbColor = colorMap.find(color);
2330 if(iRgbColor!=colorMap.end())
2331 {
2332 color_index = iRgbColor->second;
2333 }
2334 else
2335 {
2336 color_index = 3*colors.size();
2337 colors.push_back(color);
2338 colorMap.insert(make_pair(color,color_index));
2339 }
2340 return color_index;
2341 }
2342
2343 #define ADD_ADDUNIQ( prctype, prcmap, prclist) \
2344 uint32_t PRCFileStructure::add##prctype(PRC##prctype *& p##prctype) \
2345 { \
2346 prclist.push_back(p##prctype); \
2347 p##prctype = NULL; \
2348 return prclist.size()-1; \
2349 } \
2350 \
2351 uint32_t PRCFileStructure::add##prctype##Unique(PRC##prctype*& p##prctype) \
2352 { \
2353 uint32_t prc_index = m1; \
2354 PRC##prctype##Map::const_iterator i##prctype = prcmap.find(p##prctype); \
2355 if(i##prctype!=prcmap.end()) \
2356 { \
2357 delete p##prctype; \
2358 prc_index = i##prctype->second; \
2359 } \
2360 else \
2361 { \
2362 prc_index = prclist.size(); \
2363 prclist.push_back(p##prctype); \
2364 prcmap.insert(make_pair(p##prctype,prc_index)); \
2365 } \
2366 p##prctype = NULL; \
2367 return prc_index; \
2368 }
2369
ADD_ADDUNIQ(UncompressedFile,uncompressedfileMap,uncompressed_files)2370 ADD_ADDUNIQ(UncompressedFile, uncompressedfileMap, uncompressed_files )
2371 ADD_ADDUNIQ(Picture, pictureMap, pictures )
2372 ADD_ADDUNIQ(TextureDefinition, texturedefinitionMap, texture_definitions )
2373 ADD_ADDUNIQ(MaterialGeneric, materialgenericMap, materials )
2374 ADD_ADDUNIQ(TextureApplication, textureapplicationMap, materials )
2375 ADD_ADDUNIQ(Style, styleMap, styles )
2376
2377 #undef ADD_ADDUNIQ
2378
2379 uint32_t PRCFileStructure::addPartDefinition(PRCPartDefinition*& pPartDefinition)
2380 {
2381 part_definitions.push_back(pPartDefinition);
2382 pPartDefinition = NULL;
2383 return part_definitions.size()-1;
2384 }
2385
addProductOccurrence(PRCProductOccurrence * & pProductOccurrence)2386 uint32_t PRCFileStructure::addProductOccurrence(PRCProductOccurrence*& pProductOccurrence)
2387 {
2388 product_occurrences.push_back(pProductOccurrence);
2389 pProductOccurrence = NULL;
2390 return product_occurrences.size()-1;
2391 }
2392
addTopoContext(PRCTopoContext * & pTopoContext)2393 uint32_t PRCFileStructure::addTopoContext(PRCTopoContext*& pTopoContext)
2394 {
2395 contexts.push_back(pTopoContext);
2396 pTopoContext = NULL;
2397 return contexts.size()-1;
2398 }
2399
getTopoContext(PRCTopoContext * & pTopoContext)2400 uint32_t PRCFileStructure::getTopoContext(PRCTopoContext*& pTopoContext)
2401 {
2402 pTopoContext = new PRCTopoContext;
2403 contexts.push_back(pTopoContext);
2404 return contexts.size()-1;
2405 }
2406
add3DTess(PRC3DTess * & p3DTess)2407 uint32_t PRCFileStructure::add3DTess(PRC3DTess*& p3DTess)
2408 {
2409 tessellations.push_back(p3DTess);
2410 p3DTess = NULL;
2411 return tessellations.size()-1;
2412 }
2413
add3DWireTess(PRC3DWireTess * & p3DWireTess)2414 uint32_t PRCFileStructure::add3DWireTess(PRC3DWireTess*& p3DWireTess)
2415 {
2416 tessellations.push_back(p3DWireTess);
2417 p3DWireTess = NULL;
2418 return tessellations.size()-1;
2419 }
2420 /*
2421 uint32_t PRCFileStructure::addMarkupTess(PRCMarkupTess*& pMarkupTess)
2422 {
2423 tessellations.push_back(pMarkupTess);
2424 pMarkupTess = NULL;
2425 return tessellations.size()-1;
2426 }
2427
2428 uint32_t PRCFileStructure::addMarkup(PRCMarkup*& pMarkup)
2429 {
2430 markups.push_back(pMarkup);
2431 pMarkup = NULL;
2432 return markups.size()-1;
2433 }
2434
2435 uint32_t PRCFileStructure::addAnnotationItem(PRCAnnotationItem*& pAnnotationItem)
2436 {
2437 annotation_entities.push_back(pAnnotationItem);
2438 pAnnotationItem = NULL;
2439 return annotation_entities.size()-1;
2440 }
2441 */
addCoordinateSystem(PRCCoordinateSystem * & pCoordinateSystem)2442 uint32_t PRCFileStructure::addCoordinateSystem(PRCCoordinateSystem*& pCoordinateSystem)
2443 {
2444 reference_coordinate_systems.push_back(pCoordinateSystem);
2445 pCoordinateSystem = NULL;
2446 return reference_coordinate_systems.size()-1;
2447 }
2448
addCoordinateSystemUnique(PRCCoordinateSystem * & pCoordinateSystem)2449 uint32_t PRCFileStructure::addCoordinateSystemUnique(PRCCoordinateSystem*& pCoordinateSystem)
2450 {
2451 for(uint32_t i = 0; i < reference_coordinate_systems.size(); ++i)
2452 {
2453 if(*(reference_coordinate_systems[i])==*pCoordinateSystem) {
2454 pCoordinateSystem = NULL;
2455 return i;
2456 }
2457 }
2458 reference_coordinate_systems.push_back(pCoordinateSystem);
2459 pCoordinateSystem = NULL;
2460 return reference_coordinate_systems.size()-1;
2461 }
2462