0029074: Visualization, TKOpenGl - support Geometry Shader definition
[occt.git] / src / Graphic3d / Graphic3d_ArrayOfPrimitives.cxx
CommitLineData
b311480e 1// Created on: 2000-06-16
973c2be1 2// Copyright (c) 2000-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
7fd59977 14
59ec40f8 15#include <Graphic3d_ArrayOfPrimitives.hxx>
42cf5bc1 16
8e0a2b19 17#include <Graphic3d_ArrayOfPoints.hxx>
18#include <Graphic3d_ArrayOfSegments.hxx>
19#include <Graphic3d_ArrayOfPolylines.hxx>
20#include <Graphic3d_ArrayOfTriangles.hxx>
21#include <Graphic3d_ArrayOfTriangleStrips.hxx>
22#include <Graphic3d_ArrayOfTriangleFans.hxx>
23#include <Graphic3d_ArrayOfQuadrangles.hxx>
24#include <Graphic3d_ArrayOfQuadrangleStrips.hxx>
25#include <Graphic3d_ArrayOfPolygons.hxx>
26
42cf5bc1 27#include <NCollection_AlignedAllocator.hxx>
7fd59977 28#include <TCollection_AsciiString.hxx>
7fd59977 29
30#include <stdio.h>
31#include <stdlib.h>
92efcf78 32
7379f442 33IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives, Standard_Transient)
34
8e0a2b19 35IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPoints, Graphic3d_ArrayOfPrimitives)
36IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfSegments, Graphic3d_ArrayOfPrimitives)
37IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolylines, Graphic3d_ArrayOfPrimitives)
38IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangles, Graphic3d_ArrayOfPrimitives)
39IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleStrips, Graphic3d_ArrayOfPrimitives)
40IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleFans, Graphic3d_ArrayOfPrimitives)
41IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangles, Graphic3d_ArrayOfPrimitives)
42IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangleStrips, Graphic3d_ArrayOfPrimitives)
43IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolygons, Graphic3d_ArrayOfPrimitives)
44
7379f442 45// =======================================================================
46// function : Graphic3d_ArrayOfPrimitives
47// purpose :
48// =======================================================================
871fa103 49Graphic3d_ArrayOfPrimitives::Graphic3d_ArrayOfPrimitives (const Graphic3d_TypeOfPrimitiveArray theType,
50 const Standard_Integer theMaxVertexs,
51 const Standard_Integer theMaxBounds,
52 const Standard_Integer theMaxEdges,
53 const Standard_Boolean theHasVNormals,
54 const Standard_Boolean theHasVColors,
55 const Standard_Boolean theHasFColors,
56 const Standard_Boolean theHasVTexels)
57: myType (theType),
58 myMaxBounds (0),
59 myMaxVertexs (0),
60 myMaxEdges (0),
61 myVNor (0),
62 myVTex (0),
63 myVCol (0)
64{
65 Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
66 myAttribs = new Graphic3d_Buffer (anAlloc);
67 if (theMaxVertexs < 1)
68 {
69 return;
7fd59977 70 }
71
871fa103 72 if (theMaxEdges > 0)
73 {
74 myIndices = new Graphic3d_IndexBuffer (anAlloc);
09f30297 75 if (theMaxVertexs < Standard_Integer(USHRT_MAX))
871fa103 76 {
77 if (!myIndices->Init<unsigned short> (theMaxEdges))
78 {
79 myIndices.Nullify();
80 return;
81 }
82 }
83 else
84 {
85 if (!myIndices->Init<unsigned int> (theMaxEdges))
86 {
87 myIndices.Nullify();
88 return;
89 }
90 }
91 myIndices->NbElements = 0;
7fd59977 92 }
93
871fa103 94 Graphic3d_Attribute anAttribs[4];
95 Standard_Integer aNbAttribs = 0;
96 anAttribs[aNbAttribs].Id = Graphic3d_TOA_POS;
97 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
98 ++aNbAttribs;
99 if (theHasVNormals)
100 {
101 anAttribs[aNbAttribs].Id = Graphic3d_TOA_NORM;
102 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
103 ++aNbAttribs;
7fd59977 104 }
871fa103 105 if (theHasVTexels)
106 {
107 anAttribs[aNbAttribs].Id = Graphic3d_TOA_UV;
108 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC2;
109 ++aNbAttribs;
7fd59977 110 }
871fa103 111 if (theHasVColors)
112 {
113 anAttribs[aNbAttribs].Id = Graphic3d_TOA_COLOR;
114 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC4UB;
115 ++aNbAttribs;
7fd59977 116 }
117
871fa103 118 if (!myAttribs->Init (theMaxVertexs, anAttribs, aNbAttribs))
119 {
120 myAttribs.Nullify();
121 myIndices.Nullify();
122 return;
7fd59977 123 }
6273fa4b 124 memset (myAttribs->ChangeData (0), 0, size_t(myAttribs->Stride) * size_t(myAttribs->NbElements));
871fa103 125
126 if (theMaxBounds > 0)
127 {
128 myBounds = new Graphic3d_BoundBuffer (anAlloc);
129 if (!myBounds->Init (theMaxBounds, theHasFColors))
130 {
131 myAttribs.Nullify();
132 myIndices.Nullify();
133 myBounds .Nullify();
134 return;
7fd59977 135 }
871fa103 136 myBounds->NbBounds = 0;
137 }
7fd59977 138
871fa103 139 for (Standard_Integer anAttribIter = 0; anAttribIter < aNbAttribs; ++anAttribIter)
140 {
141 const Graphic3d_Attribute& anAttrib = anAttribs[anAttribIter];
142 switch (anAttrib.Id)
143 {
144 case Graphic3d_TOA_POS:
145 case Graphic3d_TOA_CUSTOM:
146 break;
147 case Graphic3d_TOA_NORM:
148 {
149 myVNor = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
150 break;
151 }
152 case Graphic3d_TOA_UV:
153 {
154 myVTex = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
155 break;
156 }
157 case Graphic3d_TOA_COLOR:
158 {
159 myVCol = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
160 break;
161 }
7fd59977 162 }
7fd59977 163 }
7fd59977 164
871fa103 165 myAttribs->NbElements = 0;
166 myMaxVertexs = theMaxVertexs;
167 myMaxBounds = theMaxBounds;
168 myMaxEdges = theMaxEdges;
7fd59977 169}
170
7379f442 171// =======================================================================
172// function : ~Graphic3d_ArrayOfPrimitives
173// purpose :
174// =======================================================================
175Graphic3d_ArrayOfPrimitives::~Graphic3d_ArrayOfPrimitives()
b8ddfc2f 176{
871fa103 177 myVNor = 0;
178 myVTex = 0;
179 myVCol = 0;
180 myIndices.Nullify();
181 myAttribs.Nullify();
182 myBounds .Nullify();
7fd59977 183}
b8ddfc2f 184
7379f442 185// =======================================================================
186// function : AddBound
187// purpose :
188// =======================================================================
871fa103 189Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber)
b8ddfc2f 190{
871fa103 191 if (myBounds.IsNull())
192 {
193 return 0;
7fd59977 194 }
871fa103 195 Standard_Integer anIndex = myBounds->NbBounds;
196 if (anIndex >= myMaxBounds)
197 {
9775fa61 198 throw Standard_OutOfRange("TOO many BOUNDS");
7fd59977 199 }
200
871fa103 201 myBounds->Bounds[anIndex] = theEdgeNumber;
202 myBounds->NbBounds = ++anIndex;
203 return anIndex;
7fd59977 204}
205
7379f442 206// =======================================================================
207// function : AddBound
208// purpose :
209// =======================================================================
871fa103 210Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
211 const Standard_Real theR,
212 const Standard_Real theG,
213 const Standard_Real theB)
b8ddfc2f 214{
871fa103 215 if (myBounds.IsNull())
216 {
217 return 0;
218 }
219 Standard_Integer anIndex = myBounds->NbBounds;
220 if (anIndex >= myMaxBounds)
221 {
9775fa61 222 throw Standard_OutOfRange("TOO many BOUND");
7fd59977 223 }
871fa103 224
225 myBounds->Bounds[anIndex] = theEdgeNumber;
226 myBounds->NbBounds = ++anIndex;
227 SetBoundColor (anIndex, theR, theG, theB);
228 return anIndex;
7fd59977 229}
230
7379f442 231// =======================================================================
232// function : AddEdge
233// purpose :
234// =======================================================================
871fa103 235Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge (const Standard_Integer theVertexIndex)
b8ddfc2f 236{
871fa103 237 if (myIndices.IsNull())
238 {
239 return 0;
240 }
241
242 Standard_Integer anIndex = myIndices->NbElements;
243 if (anIndex >= myMaxEdges)
244 {
9775fa61 245 throw Standard_OutOfRange("TOO many EDGE");
871fa103 246 }
247
248 Standard_Integer aVertIndex = theVertexIndex - 1;
249 if (theVertexIndex <= 0
250 || aVertIndex >= myMaxVertexs)
251 {
9775fa61 252 throw Standard_OutOfRange("BAD EDGE vertex index");
7fd59977 253 }
871fa103 254
255 myIndices->SetIndex (anIndex, aVertIndex);
256 myIndices->NbElements = ++anIndex;
257 return anIndex;
7fd59977 258}
259
7379f442 260// =======================================================================
261// function : StringType
262// purpose :
263// =======================================================================
b8ddfc2f 264Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
265{
871fa103 266 switch (myType)
267 {
268 case Graphic3d_TOPA_POINTS: return "ArrayOfPoints";
871fa103 269 case Graphic3d_TOPA_SEGMENTS: return "ArrayOfSegments";
8e0a2b19 270 case Graphic3d_TOPA_POLYLINES: return "ArrayOfPolylines";
871fa103 271 case Graphic3d_TOPA_TRIANGLES: return "ArrayOfTriangles";
871fa103 272 case Graphic3d_TOPA_TRIANGLESTRIPS: return "ArrayOfTriangleStrips";
871fa103 273 case Graphic3d_TOPA_TRIANGLEFANS: return "ArrayOfTriangleFans";
8e0a2b19 274 case Graphic3d_TOPA_LINES_ADJACENCY: return "ArrayOfLinesAdjacency";
275 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return "ArrayOfLineStripAdjacency";
276 case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return "ArrayOfTrianglesAdjacency";
277 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return "ArrayOfTriangleStripAdjacency";
278 case Graphic3d_TOPA_QUADRANGLES: return "ArrayOfQuadrangles";
279 case Graphic3d_TOPA_QUADRANGLESTRIPS: return "ArrayOfQuadrangleStrips";
280 case Graphic3d_TOPA_POLYGONS: return "ArrayOfPolygons";
871fa103 281 case Graphic3d_TOPA_UNDEFINED: return "UndefinedArray";
7fd59977 282 }
871fa103 283 return "UndefinedArray";
7fd59977 284}
285
7379f442 286// =======================================================================
287// function : ItemNumber
288// purpose :
289// =======================================================================
b8ddfc2f 290Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
291{
871fa103 292 if (myAttribs.IsNull())
293 {
294 return -1;
7fd59977 295 }
296
871fa103 297 switch (myType)
298 {
299 case Graphic3d_TOPA_POINTS: return myAttribs->NbElements;
300 case Graphic3d_TOPA_POLYLINES:
301 case Graphic3d_TOPA_POLYGONS: return !myBounds.IsNull() ? myBounds->NbBounds : 1;
302 case Graphic3d_TOPA_SEGMENTS: return myIndices.IsNull() || myIndices->NbElements < 1
303 ? myAttribs->NbElements / 2
304 : myIndices->NbElements / 2;
305 case Graphic3d_TOPA_TRIANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
306 ? myAttribs->NbElements / 3
307 : myIndices->NbElements / 3;
308 case Graphic3d_TOPA_QUADRANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
309 ? myAttribs->NbElements / 4
310 : myIndices->NbElements / 4;
311 case Graphic3d_TOPA_TRIANGLESTRIPS: return !myBounds.IsNull()
312 ? myAttribs->NbElements - 2 * myBounds->NbBounds
313 : myAttribs->NbElements - 2;
314 case Graphic3d_TOPA_QUADRANGLESTRIPS: return !myBounds.IsNull()
315 ? myAttribs->NbElements / 2 - myBounds->NbBounds
316 : myAttribs->NbElements / 2 - 1;
317 case Graphic3d_TOPA_TRIANGLEFANS: return !myBounds.IsNull()
318 ? myAttribs->NbElements - 2 * myBounds->NbBounds
319 : myAttribs->NbElements - 2;
8e0a2b19 320 case Graphic3d_TOPA_LINES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
321 ? myAttribs->NbElements / 4
322 : myIndices->NbElements / 4;
323 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return !myBounds.IsNull()
324 ? myAttribs->NbElements - 4 * myBounds->NbBounds
325 : myAttribs->NbElements - 4;
326 case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
327 ? myAttribs->NbElements / 6
328 : myIndices->NbElements / 6;
329 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return !myBounds.IsNull()
330 ? myAttribs->NbElements - 4 * myBounds->NbBounds
331 : myAttribs->NbElements - 4;
871fa103 332 case Graphic3d_TOPA_UNDEFINED: return -1;
333 }
334 return -1;
7fd59977 335}
336
7379f442 337// =======================================================================
338// function : IsValid
339// purpose :
340// =======================================================================
b8ddfc2f 341Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
342{
871fa103 343 if (myAttribs.IsNull())
344 {
345 return Standard_False;
346 }
347
348 Standard_Integer nvertexs = myAttribs->NbElements;
349 Standard_Integer nbounds = myBounds.IsNull() ? 0 : myBounds->NbBounds;
350 Standard_Integer nedges = myIndices.IsNull() ? 0 : myIndices->NbElements;
351 switch (myType)
352 {
353 case Graphic3d_TOPA_POINTS:
354 if (nvertexs < 1)
355 {
7fd59977 356 return Standard_False;
357 }
358 break;
871fa103 359 case Graphic3d_TOPA_POLYLINES:
360 if (nedges > 0
361 && nedges < 2)
362 {
7fd59977 363 return Standard_False;
364 }
871fa103 365 if (nvertexs < 2)
366 {
7fd59977 367 return Standard_False;
368 }
369 break;
871fa103 370 case Graphic3d_TOPA_SEGMENTS:
371 if (nvertexs < 2)
372 {
7fd59977 373 return Standard_False;
374 }
375 break;
871fa103 376 case Graphic3d_TOPA_POLYGONS:
377 if (nedges > 0
378 && nedges < 3)
379 {
7fd59977 380 return Standard_False;
381 }
871fa103 382 if (nvertexs < 3)
383 {
7fd59977 384 return Standard_False;
385 }
386 break;
871fa103 387 case Graphic3d_TOPA_TRIANGLES:
388 if (nedges > 0)
389 {
390 if (nedges < 3
391 || nedges % 3 != 0)
392 {
393 if (nedges <= 3)
394 {
395 return Standard_False;
396 }
397 myIndices->NbElements = 3 * (nedges / 3);
398 }
399 }
400 else if (nvertexs < 3
401 || nvertexs % 3 != 0 )
402 {
403 if (nvertexs <= 3)
404 {
405 return Standard_False;
7fd59977 406 }
871fa103 407 myAttribs->NbElements = 3 * (nvertexs / 3);
7fd59977 408 }
409 break;
871fa103 410 case Graphic3d_TOPA_QUADRANGLES:
411 if (nedges > 0)
412 {
413 if (nedges < 4
414 || nedges % 4 != 0)
415 {
416 if (nedges <= 4)
417 {
418 return Standard_False;
419 }
420 myIndices->NbElements = 4 * (nedges / 4);
421 }
422 }
423 else if (nvertexs < 4
424 || nvertexs % 4 != 0)
425 {
426 if (nvertexs <= 4)
427 {
428 return Standard_False;
7fd59977 429 }
871fa103 430 myAttribs->NbElements = 4 * (nvertexs / 4);
7fd59977 431 }
432 break;
871fa103 433 case Graphic3d_TOPA_TRIANGLEFANS:
434 case Graphic3d_TOPA_TRIANGLESTRIPS:
435 if (nvertexs < 3)
436 {
7fd59977 437 return Standard_False;
438 }
439 break;
871fa103 440 case Graphic3d_TOPA_QUADRANGLESTRIPS:
441 if (nvertexs < 4)
442 {
7fd59977 443 return Standard_False;
444 }
445 break;
8e0a2b19 446 case Graphic3d_TOPA_LINES_ADJACENCY:
447 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
448 if (nvertexs < 4)
449 {
450 return Standard_False;
451 }
452 break;
453 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
454 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
455 if (nvertexs < 6)
456 {
457 return Standard_False;
458 }
459 break;
871fa103 460 case Graphic3d_TOPA_UNDEFINED:
7fd59977 461 default:
7fd59977 462 return Standard_False;
463 }
464
871fa103 465 // total number of edges(vertices) in bounds should be the same as variable
466 // of total number of defined edges(vertices); if no edges - only vertices
9558a876 467 // could be in bounds.
871fa103 468 if (nbounds > 0)
469 {
470 Standard_Integer n = 0;
471 for (Standard_Integer aBoundIter = 0; aBoundIter < nbounds; ++aBoundIter)
472 {
473 n += myBounds->Bounds[aBoundIter];
7fd59977 474 }
871fa103 475 if (nedges > 0
476 && n != nedges)
477 {
478 if (nedges <= n)
479 {
480 return Standard_False;
481 }
482 myIndices->NbElements = n;
483 }
484 else if (nedges == 0
485 && n != nvertexs)
486 {
487 if (nvertexs <= n)
488 {
489 return Standard_False;
490 }
491 myAttribs->NbElements = n;
7fd59977 492 }
493 }
494
871fa103 495 // check that edges (indexes to an array of vertices) are in range.
496 if (nedges > 0)
497 {
498 for (Standard_Integer anEdgeIter = 0; anEdgeIter < nedges; ++anEdgeIter)
499 {
500 if (myIndices->Index (anEdgeIter) >= myAttribs->NbElements)
501 {
502 return Standard_False;
7fd59977 503 }
504 }
505 }
7fd59977 506 return Standard_True;
507}