0030239: Visualization, Graphic3d_ArrayOfPrimitives - pass Graphic3d_ArrayFlags bitma...
[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// =======================================================================
34253146 46// function : init
7379f442 47// purpose :
48// =======================================================================
34253146 49void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
50 Standard_Integer theMaxVertexs,
51 Standard_Integer theMaxBounds,
52 Standard_Integer theMaxEdges,
53 Graphic3d_ArrayFlags theArrayOptions)
871fa103 54{
34253146 55 myType = theType;
56 myVNor = 0;
57 myVTex = 0;
58 myVCol = 0;
59 myAttribs.Nullify();
60 myIndices.Nullify();
61 myBounds.Nullify();
62
871fa103 63 Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
64 myAttribs = new Graphic3d_Buffer (anAlloc);
65 if (theMaxVertexs < 1)
66 {
67 return;
7fd59977 68 }
69
871fa103 70 if (theMaxEdges > 0)
71 {
72 myIndices = new Graphic3d_IndexBuffer (anAlloc);
09f30297 73 if (theMaxVertexs < Standard_Integer(USHRT_MAX))
871fa103 74 {
75 if (!myIndices->Init<unsigned short> (theMaxEdges))
76 {
77 myIndices.Nullify();
78 return;
79 }
80 }
81 else
82 {
83 if (!myIndices->Init<unsigned int> (theMaxEdges))
84 {
85 myIndices.Nullify();
86 return;
87 }
88 }
89 myIndices->NbElements = 0;
7fd59977 90 }
91
871fa103 92 Graphic3d_Attribute anAttribs[4];
93 Standard_Integer aNbAttribs = 0;
94 anAttribs[aNbAttribs].Id = Graphic3d_TOA_POS;
95 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
96 ++aNbAttribs;
34253146 97 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexNormal) != 0)
871fa103 98 {
99 anAttribs[aNbAttribs].Id = Graphic3d_TOA_NORM;
100 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
101 ++aNbAttribs;
7fd59977 102 }
34253146 103 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexTexel) != 0)
871fa103 104 {
105 anAttribs[aNbAttribs].Id = Graphic3d_TOA_UV;
106 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC2;
107 ++aNbAttribs;
7fd59977 108 }
34253146 109 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexColor) != 0)
871fa103 110 {
111 anAttribs[aNbAttribs].Id = Graphic3d_TOA_COLOR;
112 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC4UB;
113 ++aNbAttribs;
7fd59977 114 }
115
871fa103 116 if (!myAttribs->Init (theMaxVertexs, anAttribs, aNbAttribs))
117 {
118 myAttribs.Nullify();
119 myIndices.Nullify();
120 return;
7fd59977 121 }
34253146 122 myAttribs->NbElements = 0;
123 memset (myAttribs->ChangeData (0), 0, size_t(myAttribs->Stride) * size_t(myAttribs->NbMaxElements()));
871fa103 124
125 if (theMaxBounds > 0)
126 {
127 myBounds = new Graphic3d_BoundBuffer (anAlloc);
34253146 128 if (!myBounds->Init (theMaxBounds, (theArrayOptions & Graphic3d_ArrayFlags_BoundColor) != 0))
871fa103 129 {
130 myAttribs.Nullify();
131 myIndices.Nullify();
132 myBounds .Nullify();
133 return;
7fd59977 134 }
871fa103 135 myBounds->NbBounds = 0;
136 }
7fd59977 137
871fa103 138 for (Standard_Integer anAttribIter = 0; anAttribIter < aNbAttribs; ++anAttribIter)
139 {
140 const Graphic3d_Attribute& anAttrib = anAttribs[anAttribIter];
141 switch (anAttrib.Id)
142 {
143 case Graphic3d_TOA_POS:
144 case Graphic3d_TOA_CUSTOM:
145 break;
146 case Graphic3d_TOA_NORM:
147 {
148 myVNor = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
149 break;
150 }
151 case Graphic3d_TOA_UV:
152 {
153 myVTex = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
154 break;
155 }
156 case Graphic3d_TOA_COLOR:
157 {
158 myVCol = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
159 break;
160 }
7fd59977 161 }
7fd59977 162 }
7fd59977 163}
164
7379f442 165// =======================================================================
166// function : ~Graphic3d_ArrayOfPrimitives
167// purpose :
168// =======================================================================
169Graphic3d_ArrayOfPrimitives::~Graphic3d_ArrayOfPrimitives()
b8ddfc2f 170{
871fa103 171 myVNor = 0;
172 myVTex = 0;
173 myVCol = 0;
174 myIndices.Nullify();
175 myAttribs.Nullify();
176 myBounds .Nullify();
7fd59977 177}
b8ddfc2f 178
7379f442 179// =======================================================================
180// function : AddBound
181// purpose :
182// =======================================================================
871fa103 183Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber)
b8ddfc2f 184{
34253146 185 Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds, "TOO many BOUND");
186 myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
187 return ++myBounds->NbBounds;
7fd59977 188}
189
7379f442 190// =======================================================================
191// function : AddBound
192// purpose :
193// =======================================================================
871fa103 194Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
195 const Standard_Real theR,
196 const Standard_Real theG,
197 const Standard_Real theB)
b8ddfc2f 198{
34253146 199 Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds, "TOO many BOUND");
200 myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
201 ++myBounds->NbBounds;
202 SetBoundColor (myBounds->NbBounds, theR, theG, theB);
203 return myBounds->NbBounds;
7fd59977 204}
205
7379f442 206// =======================================================================
207// function : AddEdge
208// purpose :
209// =======================================================================
871fa103 210Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge (const Standard_Integer theVertexIndex)
b8ddfc2f 211{
34253146 212 Standard_OutOfRange_Raise_if (myIndices.IsNull() || myIndices->NbElements >= myIndices->NbMaxElements(), "TOO many EDGE");
213 Standard_OutOfRange_Raise_if (theVertexIndex < 1 || theVertexIndex > myAttribs->NbElements, "BAD VERTEX index");
214 const Standard_Integer aVertIndex = theVertexIndex - 1;
215 myIndices->SetIndex (myIndices->NbElements, aVertIndex);
216 return ++myIndices->NbElements;
7fd59977 217}
218
7379f442 219// =======================================================================
220// function : StringType
221// purpose :
222// =======================================================================
b8ddfc2f 223Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
224{
871fa103 225 switch (myType)
226 {
227 case Graphic3d_TOPA_POINTS: return "ArrayOfPoints";
871fa103 228 case Graphic3d_TOPA_SEGMENTS: return "ArrayOfSegments";
8e0a2b19 229 case Graphic3d_TOPA_POLYLINES: return "ArrayOfPolylines";
871fa103 230 case Graphic3d_TOPA_TRIANGLES: return "ArrayOfTriangles";
871fa103 231 case Graphic3d_TOPA_TRIANGLESTRIPS: return "ArrayOfTriangleStrips";
871fa103 232 case Graphic3d_TOPA_TRIANGLEFANS: return "ArrayOfTriangleFans";
8e0a2b19 233 case Graphic3d_TOPA_LINES_ADJACENCY: return "ArrayOfLinesAdjacency";
234 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return "ArrayOfLineStripAdjacency";
235 case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return "ArrayOfTrianglesAdjacency";
236 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return "ArrayOfTriangleStripAdjacency";
237 case Graphic3d_TOPA_QUADRANGLES: return "ArrayOfQuadrangles";
238 case Graphic3d_TOPA_QUADRANGLESTRIPS: return "ArrayOfQuadrangleStrips";
239 case Graphic3d_TOPA_POLYGONS: return "ArrayOfPolygons";
871fa103 240 case Graphic3d_TOPA_UNDEFINED: return "UndefinedArray";
7fd59977 241 }
871fa103 242 return "UndefinedArray";
7fd59977 243}
244
7379f442 245// =======================================================================
246// function : ItemNumber
247// purpose :
248// =======================================================================
b8ddfc2f 249Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
250{
871fa103 251 if (myAttribs.IsNull())
252 {
253 return -1;
7fd59977 254 }
255
871fa103 256 switch (myType)
257 {
258 case Graphic3d_TOPA_POINTS: return myAttribs->NbElements;
259 case Graphic3d_TOPA_POLYLINES:
260 case Graphic3d_TOPA_POLYGONS: return !myBounds.IsNull() ? myBounds->NbBounds : 1;
261 case Graphic3d_TOPA_SEGMENTS: return myIndices.IsNull() || myIndices->NbElements < 1
262 ? myAttribs->NbElements / 2
263 : myIndices->NbElements / 2;
264 case Graphic3d_TOPA_TRIANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
265 ? myAttribs->NbElements / 3
266 : myIndices->NbElements / 3;
267 case Graphic3d_TOPA_QUADRANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
268 ? myAttribs->NbElements / 4
269 : myIndices->NbElements / 4;
270 case Graphic3d_TOPA_TRIANGLESTRIPS: return !myBounds.IsNull()
271 ? myAttribs->NbElements - 2 * myBounds->NbBounds
272 : myAttribs->NbElements - 2;
273 case Graphic3d_TOPA_QUADRANGLESTRIPS: return !myBounds.IsNull()
274 ? myAttribs->NbElements / 2 - myBounds->NbBounds
275 : myAttribs->NbElements / 2 - 1;
276 case Graphic3d_TOPA_TRIANGLEFANS: return !myBounds.IsNull()
277 ? myAttribs->NbElements - 2 * myBounds->NbBounds
278 : myAttribs->NbElements - 2;
8e0a2b19 279 case Graphic3d_TOPA_LINES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
280 ? myAttribs->NbElements / 4
281 : myIndices->NbElements / 4;
282 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return !myBounds.IsNull()
283 ? myAttribs->NbElements - 4 * myBounds->NbBounds
284 : myAttribs->NbElements - 4;
285 case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
286 ? myAttribs->NbElements / 6
287 : myIndices->NbElements / 6;
288 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return !myBounds.IsNull()
289 ? myAttribs->NbElements - 4 * myBounds->NbBounds
290 : myAttribs->NbElements - 4;
871fa103 291 case Graphic3d_TOPA_UNDEFINED: return -1;
292 }
293 return -1;
7fd59977 294}
295
7379f442 296// =======================================================================
297// function : IsValid
298// purpose :
299// =======================================================================
b8ddfc2f 300Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
301{
871fa103 302 if (myAttribs.IsNull())
303 {
304 return Standard_False;
305 }
306
307 Standard_Integer nvertexs = myAttribs->NbElements;
308 Standard_Integer nbounds = myBounds.IsNull() ? 0 : myBounds->NbBounds;
309 Standard_Integer nedges = myIndices.IsNull() ? 0 : myIndices->NbElements;
310 switch (myType)
311 {
312 case Graphic3d_TOPA_POINTS:
313 if (nvertexs < 1)
314 {
7fd59977 315 return Standard_False;
316 }
317 break;
871fa103 318 case Graphic3d_TOPA_POLYLINES:
319 if (nedges > 0
320 && nedges < 2)
321 {
7fd59977 322 return Standard_False;
323 }
871fa103 324 if (nvertexs < 2)
325 {
7fd59977 326 return Standard_False;
327 }
328 break;
871fa103 329 case Graphic3d_TOPA_SEGMENTS:
330 if (nvertexs < 2)
331 {
7fd59977 332 return Standard_False;
333 }
334 break;
871fa103 335 case Graphic3d_TOPA_POLYGONS:
336 if (nedges > 0
337 && nedges < 3)
338 {
7fd59977 339 return Standard_False;
340 }
871fa103 341 if (nvertexs < 3)
342 {
7fd59977 343 return Standard_False;
344 }
345 break;
871fa103 346 case Graphic3d_TOPA_TRIANGLES:
347 if (nedges > 0)
348 {
349 if (nedges < 3
350 || nedges % 3 != 0)
351 {
352 if (nedges <= 3)
353 {
354 return Standard_False;
355 }
356 myIndices->NbElements = 3 * (nedges / 3);
357 }
358 }
359 else if (nvertexs < 3
360 || nvertexs % 3 != 0 )
361 {
362 if (nvertexs <= 3)
363 {
364 return Standard_False;
7fd59977 365 }
871fa103 366 myAttribs->NbElements = 3 * (nvertexs / 3);
7fd59977 367 }
368 break;
871fa103 369 case Graphic3d_TOPA_QUADRANGLES:
370 if (nedges > 0)
371 {
372 if (nedges < 4
373 || nedges % 4 != 0)
374 {
375 if (nedges <= 4)
376 {
377 return Standard_False;
378 }
379 myIndices->NbElements = 4 * (nedges / 4);
380 }
381 }
382 else if (nvertexs < 4
383 || nvertexs % 4 != 0)
384 {
385 if (nvertexs <= 4)
386 {
387 return Standard_False;
7fd59977 388 }
871fa103 389 myAttribs->NbElements = 4 * (nvertexs / 4);
7fd59977 390 }
391 break;
871fa103 392 case Graphic3d_TOPA_TRIANGLEFANS:
393 case Graphic3d_TOPA_TRIANGLESTRIPS:
394 if (nvertexs < 3)
395 {
7fd59977 396 return Standard_False;
397 }
398 break;
871fa103 399 case Graphic3d_TOPA_QUADRANGLESTRIPS:
400 if (nvertexs < 4)
401 {
7fd59977 402 return Standard_False;
403 }
404 break;
8e0a2b19 405 case Graphic3d_TOPA_LINES_ADJACENCY:
406 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
407 if (nvertexs < 4)
408 {
409 return Standard_False;
410 }
411 break;
412 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
413 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
414 if (nvertexs < 6)
415 {
416 return Standard_False;
417 }
418 break;
871fa103 419 case Graphic3d_TOPA_UNDEFINED:
7fd59977 420 default:
7fd59977 421 return Standard_False;
422 }
423
871fa103 424 // total number of edges(vertices) in bounds should be the same as variable
425 // of total number of defined edges(vertices); if no edges - only vertices
9558a876 426 // could be in bounds.
871fa103 427 if (nbounds > 0)
428 {
429 Standard_Integer n = 0;
430 for (Standard_Integer aBoundIter = 0; aBoundIter < nbounds; ++aBoundIter)
431 {
432 n += myBounds->Bounds[aBoundIter];
7fd59977 433 }
871fa103 434 if (nedges > 0
435 && n != nedges)
436 {
437 if (nedges <= n)
438 {
439 return Standard_False;
440 }
441 myIndices->NbElements = n;
442 }
443 else if (nedges == 0
444 && n != nvertexs)
445 {
446 if (nvertexs <= n)
447 {
448 return Standard_False;
449 }
450 myAttribs->NbElements = n;
7fd59977 451 }
452 }
453
871fa103 454 // check that edges (indexes to an array of vertices) are in range.
455 if (nedges > 0)
456 {
457 for (Standard_Integer anEdgeIter = 0; anEdgeIter < nedges; ++anEdgeIter)
458 {
459 if (myIndices->Index (anEdgeIter) >= myAttribs->NbElements)
460 {
461 return Standard_False;
7fd59977 462 }
463 }
464 }
7fd59977 465 return Standard_True;
466}