0023634: Eliminate Polyline and Polygon usage in drawers
[occt.git] / src / Graphic3d / Graphic3d_ArrayOfPrimitives.cxx
1 // Created on: 2000-06-16
2 // Copyright (c) 2000-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19
20 #define TRACE 0
21
22 #include <Graphic3d_ArrayOfPrimitives.ixx>
23 #include <Standard.hxx>
24 #include <TCollection_AsciiString.hxx>
25 #include <OSD_Environment.hxx>
26
27 #include <stdio.h>
28 #include <stdlib.h>
29
30 Graphic3d_ArrayOfPrimitives :: Graphic3d_ArrayOfPrimitives (
31                         const Graphic3d_TypeOfPrimitiveArray aType,
32                         const Standard_Integer maxVertexs,
33                         const Standard_Integer maxBounds,
34                         const Standard_Integer maxEdges,
35                         const Standard_Boolean hasVNormals,
36                         const Standard_Boolean hasVColors,
37                         const Standard_Boolean hasFColors,
38                         const Standard_Boolean hasVTexels,
39                         const Standard_Boolean hasEdgeInfos )
40 : myMaxBounds(0),myMaxVertexs(0),myMaxEdges(0)
41 {
42   const Standard_Integer size = sizeof(CALL_DEF_PARRAY);
43   Standard_Integer format = MVERTICE;
44   if( hasVNormals ) format |= MVNORMAL;
45   if( hasVColors ) format |= MVCOLOR;
46   if( hasVTexels ) format |= MVTEXEL;
47     
48   myPrimitiveArray = (Graphic3d_PrimitiveArray) Standard::Allocate(size); 
49   memset ( myPrimitiveArray, 0, size );
50
51   if( maxVertexs > 0){
52     myPrimitiveArray->vertices = (TEL_POINT*) Standard::Allocate(maxVertexs *sizeof(TEL_POINT));
53     memset ( myPrimitiveArray->vertices, 0, maxVertexs *sizeof(TEL_POINT));
54   }
55
56   if( hasVNormals ){
57     myPrimitiveArray->vnormals = (TEL_POINT*) Standard::Allocate(sizeof(TEL_POINT) * maxVertexs);
58     memset ( myPrimitiveArray->vnormals, 0, sizeof(TEL_POINT) * maxVertexs);
59   }
60
61   if( hasVColors ){
62     myPrimitiveArray->vcolours = (Tint*) Standard::Allocate(maxVertexs *sizeof(Tint));
63     memset ( myPrimitiveArray->vcolours, 0, sizeof(Tint) * maxVertexs);
64   }
65
66   if( hasVTexels ){
67     myPrimitiveArray->vtexels = (TEL_TEXTURE_COORD*) Standard::Allocate(maxVertexs *sizeof(TEL_TEXTURE_COORD));
68     memset ( myPrimitiveArray->vtexels, 0, sizeof(TEL_TEXTURE_COORD) * maxVertexs);
69   }
70
71   if( hasFColors && (maxBounds > 0) ){
72     myPrimitiveArray->fcolours = (TEL_COLOUR*) Standard::Allocate(maxBounds *sizeof(TEL_COLOUR));
73     memset ( myPrimitiveArray->fcolours, 0, sizeof(TEL_COLOUR) * maxBounds);
74   } 
75
76   if( maxBounds > 0 ){
77     myPrimitiveArray->bounds = (Tint*) Standard::Allocate(maxBounds *sizeof(Tint));
78     memset ( myPrimitiveArray->bounds, 0, maxBounds *sizeof(Tint));
79   }
80
81   if( maxEdges > 0 ){
82     myPrimitiveArray->edges = (Tint*) Standard::Allocate(maxEdges *sizeof(Tint));
83     memset ( myPrimitiveArray->edges, 0,  maxEdges *sizeof(Tint));
84   }
85
86   if( hasEdgeInfos && (maxEdges > 0) ){
87     myPrimitiveArray->edge_vis = (Tchar*)Standard::Allocate(maxEdges *sizeof(Tchar));
88     memset ( myPrimitiveArray->edge_vis, 0, maxEdges *sizeof(Tchar));
89   }
90
91   myPrimitiveArray->keys = NULL;
92   myMaxVertexs = maxVertexs;
93   myMaxBounds = maxBounds;
94   myMaxEdges = maxEdges;
95   myPrimitiveArray->type          = (TelPrimitivesArrayType) aType;
96   myPrimitiveArray->format        = format;
97   myPrimitiveArray->num_bounds    = 0;
98   myPrimitiveArray->num_vertexs   = 0;
99   myPrimitiveArray->num_edges     = 0;
100 }
101
102 void Graphic3d_ArrayOfPrimitives::Destroy ()
103 {
104   if( myPrimitiveArray ) {
105     if( myPrimitiveArray->vertices ){
106       Standard::Free( (Standard_Address&)myPrimitiveArray->vertices );
107       myPrimitiveArray->vertices = 0;
108     }
109
110     if( myPrimitiveArray->vnormals ){
111       Standard::Free( (Standard_Address&)myPrimitiveArray->vnormals );
112       myPrimitiveArray->vnormals = 0;
113     }
114
115     if( myPrimitiveArray->vcolours ){
116       Standard::Free( (Standard_Address&)myPrimitiveArray->vcolours );
117       myPrimitiveArray->vcolours = 0;
118     }
119
120     if( myPrimitiveArray->vtexels ){
121       Standard::Free( (Standard_Address&)myPrimitiveArray->vtexels );
122       myPrimitiveArray->vtexels = 0;
123     }
124
125     if( myPrimitiveArray->fcolours ){
126       Standard::Free( (Standard_Address&)myPrimitiveArray->fcolours );
127       myPrimitiveArray->fcolours = 0;
128     } 
129
130     if( myPrimitiveArray->bounds ){
131       Standard::Free( (Standard_Address&)myPrimitiveArray->bounds );
132       myPrimitiveArray->bounds = 0;
133     }
134
135     if( myPrimitiveArray->edges ){
136       Standard::Free( (Standard_Address&)myPrimitiveArray->edges );
137       myPrimitiveArray->edges = 0;
138     }
139
140     if( myPrimitiveArray->edge_vis ){
141       Standard::Free( (Standard_Address&)myPrimitiveArray->edge_vis );
142       myPrimitiveArray->edge_vis = 0;
143     }
144
145     Standard::Free( (Standard_Address&)myPrimitiveArray );
146 #if TRACE > 0
147     cout << " Graphic3d_ArrayOfPrimitives::Destroy()" << endl;
148 #endif
149   }
150 }
151
152 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z)
153 {
154   if( !myPrimitiveArray ) return 0;
155   const Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
156   SetVertice(index,X,Y,Z);
157   return index;
158 }
159
160 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const gp_Pnt& aVertice, const Quantity_Color& aColor)
161 {
162   const Standard_Integer index = AddVertex(aVertice);
163   Standard_Real r,g,b;
164   aColor.Values(r,g,b,Quantity_TOC_RGB);
165   SetVertexColor(index,r,g,b);
166   return index;
167 }
168
169 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const gp_Pnt& aVertice, const Standard_Integer aColor)
170 {
171   const Standard_Integer index = AddVertex(aVertice);
172   SetVertexColor(index,aColor);
173   return index;
174 }
175
176 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z,
177                                                         const Standard_ShortReal NX, const Standard_ShortReal NY, const Standard_ShortReal NZ)
178 {
179   if( !myPrimitiveArray ) return 0;
180   const Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
181   SetVertice(index,X,Y,Z);
182   SetVertexNormal(index,NX,NY,NZ);
183   return index;
184 }
185
186 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const gp_Pnt& aVertice,
187                                                         const gp_Dir& aNormal,
188                                                         const Quantity_Color& aColor)
189 {
190   const Standard_Integer index = AddVertex(aVertice,aNormal);
191   Standard_Real r,g,b;
192   aColor.Values(r,g,b,Quantity_TOC_RGB);
193   SetVertexColor(index,r,g,b);
194   return index;
195 }
196
197 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(const gp_Pnt& aVertice,
198                                                         const gp_Dir& aNormal,
199                                                         const Standard_Integer aColor)
200 {
201   const Standard_Integer index = AddVertex(aVertice,aNormal);
202   SetVertexColor(index,aColor);
203   return index;
204 }
205
206 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
207         const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z,
208         const Standard_ShortReal TX, const Standard_ShortReal TY)
209 {
210   if( !myPrimitiveArray ) return 0;
211   const Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
212   SetVertice(index,X,Y,Z);
213   SetVertexTexel(index,TX,TY);
214   return index;
215 }
216
217 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
218         const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Z,
219         const Standard_ShortReal NX, const Standard_ShortReal NY, const Standard_ShortReal NZ,
220         const Standard_ShortReal TX, const Standard_ShortReal TY)
221 {
222   if( !myPrimitiveArray ) return 0;
223   const Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
224   SetVertice(index,X,Y,Z);
225   SetVertexNormal(index,NX,NY,NZ);
226   SetVertexTexel(index,TX,TY);
227   return index;
228 }
229
230 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound( const Standard_Integer edgeNumber)
231 {
232   Standard_Integer index = 0;
233   if( myPrimitiveArray && myPrimitiveArray->bounds ) {
234     index = myPrimitiveArray->num_bounds;
235     if( index < myMaxBounds ) {
236       myPrimitiveArray->bounds[index] = edgeNumber;
237       myPrimitiveArray->num_bounds = ++index;
238     } else {
239       Standard_OutOfRange::Raise(" TOO many BOUNDS");
240     }
241   }
242
243   return index;
244 }
245
246 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound( const Standard_Integer edgeNumber,
247                                                         const Quantity_Color& aFColor)
248 {
249   Standard_Real r,g,b;
250   aFColor.Values(r,g,b,Quantity_TOC_RGB);
251   return AddBound(edgeNumber,r,g,b);
252 }
253
254 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound( const Standard_Integer edgeNumber,
255                                                         const Standard_Real R, 
256                                                         const Standard_Real G,
257                                                         const Standard_Real B)
258 {
259   if( !myPrimitiveArray ) return 0;
260   Standard_Integer index = myPrimitiveArray->num_bounds;
261   if( index >= myMaxBounds ) {
262     Standard_OutOfRange::Raise(" TOO many BOUND");
263   }
264   myPrimitiveArray->bounds[index] = edgeNumber;
265   myPrimitiveArray->num_bounds = ++index;
266   SetBoundColor(index,R,G,B);
267   return index;
268 }
269
270 Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge(const Standard_Integer vertexIndex,
271                                                       const Standard_Boolean isVisible)
272 {
273   if( !myPrimitiveArray ) return 0;
274
275   Standard_Integer index = myPrimitiveArray->num_edges;
276   if( index >= myMaxEdges ) {
277     Standard_OutOfRange::Raise(" TOO many EDGE");
278   }
279   Standard_Integer vindex = vertexIndex-1;
280   if( vertexIndex > 0 && vindex < myMaxVertexs ) {
281     myPrimitiveArray->edges[index] = vindex;
282     if( myPrimitiveArray->edge_vis ) {
283       myPrimitiveArray->edge_vis[index] = (Tchar) (isVisible ? 1 : 0);
284     }
285     myPrimitiveArray->num_edges = ++index;
286   } else {
287     Standard_OutOfRange::Raise(" BAD EDGE vertex index");
288   }
289
290   return index;
291 }
292
293 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(const gp_Dir& aNormal)
294 {
295   return Orientate(1,Max(VertexNumber(),EdgeNumber()),aNormal);
296 }
297
298 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(const Standard_Integer aVertexIndex,
299                                                         const Standard_Integer aVertexNumber,
300                                                         const gp_Dir& aNormal)
301 {
302   Standard_Boolean somethingHasChange = Standard_False;
303   if( myPrimitiveArray && (myPrimitiveArray->num_vertexs > 2) ) {
304     Standard_Integer i,j,k=aVertexNumber,n=aVertexIndex-1;
305     Standard_ShortReal x,y,z;
306     if( myPrimitiveArray->edges ) {
307       if( n >= 0 && (n+k) <= myPrimitiveArray->num_edges ) {
308         Standard_Integer i1 = myPrimitiveArray->edges[n];
309         Standard_Integer i2 = myPrimitiveArray->edges[n+1];
310         Standard_Integer i3 = myPrimitiveArray->edges[n+2];
311         gp_Pnt p1(myPrimitiveArray->vertices[i1].xyz[0],
312                   myPrimitiveArray->vertices[i1].xyz[1],
313                   myPrimitiveArray->vertices[i1].xyz[2]);
314         gp_Pnt p2(myPrimitiveArray->vertices[i2].xyz[0],
315                   myPrimitiveArray->vertices[i2].xyz[1],
316                   myPrimitiveArray->vertices[i2].xyz[2]);
317         gp_Pnt p3(myPrimitiveArray->vertices[i3].xyz[0],
318                   myPrimitiveArray->vertices[i3].xyz[1],
319                   myPrimitiveArray->vertices[i3].xyz[2]);
320         gp_Vec v21(p1,p2),v31(p1,p3),fn = v21.Crossed(v31);
321         if( aNormal.IsOpposite(fn, M_PI / 4.) ) {
322           Standard_Integer e; char v;
323           for( i=0,j=k-1 ; i<k/2 ; i++,j-- ) {
324             e = myPrimitiveArray->edges[n+i];
325             myPrimitiveArray->edges[n+i] = myPrimitiveArray->edges[n+j];
326             myPrimitiveArray->edges[n+j] = e;
327             if( myPrimitiveArray->edge_vis ) {
328               v = myPrimitiveArray->edge_vis[n+i];
329               myPrimitiveArray->edge_vis[n+i] = myPrimitiveArray->edge_vis[n+j];
330               myPrimitiveArray->edge_vis[n+j] = v;
331             }
332             if( myPrimitiveArray->vnormals ) {
333               e = myPrimitiveArray->edges[n+i];
334               x = myPrimitiveArray->vnormals[e].xyz[0];
335               y = myPrimitiveArray->vnormals[e].xyz[1];
336               z = myPrimitiveArray->vnormals[e].xyz[2];
337               gp_Vec vn(x,y,z);
338               if( aNormal.IsOpposite(vn, M_PI / 4.) ) {
339                 myPrimitiveArray->vnormals[e].xyz[0] = -x;
340                 myPrimitiveArray->vnormals[e].xyz[1] = -y;
341                 myPrimitiveArray->vnormals[e].xyz[2] = -z;
342               }
343             }
344           }
345           somethingHasChange = Standard_True;
346         }
347       } else {
348         Standard_OutOfRange::Raise(" BAD EDGE index or number");
349       }
350       return somethingHasChange;
351     } 
352
353     if( n >= 0 && (n+k) <= myPrimitiveArray->num_vertexs ) {
354       gp_Pnt p1(myPrimitiveArray->vertices[n].xyz[0],
355                   myPrimitiveArray->vertices[n].xyz[1],
356                   myPrimitiveArray->vertices[n].xyz[2]);
357       gp_Pnt p2(myPrimitiveArray->vertices[n+1].xyz[0],
358                   myPrimitiveArray->vertices[n+1].xyz[1],
359                   myPrimitiveArray->vertices[n+1].xyz[2]);
360       gp_Pnt p3(myPrimitiveArray->vertices[n+2].xyz[0],
361                   myPrimitiveArray->vertices[n+2].xyz[1],
362                   myPrimitiveArray->vertices[n+2].xyz[2]);
363       gp_Vec v21(p1,p2),v31(p1,p3),fn = v21.Crossed(v31);
364       if( aNormal.IsOpposite(fn, M_PI / 4.) ) {
365         for( i=0,j=k-1 ; i<k/2 ; i++,j-- ) {
366           x = myPrimitiveArray->vertices[n+i].xyz[0];
367           y = myPrimitiveArray->vertices[n+i].xyz[1];
368           z = myPrimitiveArray->vertices[n+i].xyz[2];
369           myPrimitiveArray->vertices[n+i].xyz[0] = myPrimitiveArray->vertices[n+j].xyz[0];
370           myPrimitiveArray->vertices[n+i].xyz[1] = myPrimitiveArray->vertices[n+j].xyz[1];
371           myPrimitiveArray->vertices[n+i].xyz[2] = myPrimitiveArray->vertices[n+j].xyz[2];
372           myPrimitiveArray->vertices[n+j].xyz[0] = x;
373           myPrimitiveArray->vertices[n+j].xyz[1] = y;
374           myPrimitiveArray->vertices[n+j].xyz[2] = z;
375           if( myPrimitiveArray->vnormals ) {
376             x = myPrimitiveArray->vnormals[n+i].xyz[0];
377             y = myPrimitiveArray->vnormals[n+i].xyz[1];
378             z = myPrimitiveArray->vnormals[n+i].xyz[2];
379             myPrimitiveArray->vnormals[n+i].xyz[0] = myPrimitiveArray->vnormals[n+j].xyz[0];
380             myPrimitiveArray->vnormals[n+i].xyz[1] = myPrimitiveArray->vnormals[n+j].xyz[1];
381             myPrimitiveArray->vnormals[n+i].xyz[2] = myPrimitiveArray->vnormals[n+j].xyz[2];
382             myPrimitiveArray->vnormals[n+j].xyz[0] = x;
383             myPrimitiveArray->vnormals[n+j].xyz[1] = y;
384             myPrimitiveArray->vnormals[n+j].xyz[2] = z;
385
386             x = myPrimitiveArray->vnormals[n+i].xyz[0];
387             y = myPrimitiveArray->vnormals[n+i].xyz[1];
388             z = myPrimitiveArray->vnormals[n+i].xyz[2];
389             gp_Vec vn(x,y,z);
390             if( aNormal.IsOpposite(vn, M_PI / 4.) ) {
391               myPrimitiveArray->vnormals[n+i].xyz[0] = -x;
392               myPrimitiveArray->vnormals[n+i].xyz[1] = -y;
393               myPrimitiveArray->vnormals[n+i].xyz[2] = -z;
394             }
395           }
396           if( myPrimitiveArray->vcolours ) {
397             x = (Standard_ShortReal)myPrimitiveArray->vcolours[n+i];
398             myPrimitiveArray->vcolours[n+i] = myPrimitiveArray->vcolours[n+j];
399             myPrimitiveArray->vcolours[n+j] = (Tint)x;
400           }
401           if( myPrimitiveArray->vtexels ) {
402             x = myPrimitiveArray->vtexels[n+i].xy[0];
403             y = myPrimitiveArray->vtexels[n+i].xy[1];
404             myPrimitiveArray->vtexels[n+i].xy[0] = myPrimitiveArray->vtexels[n+j].xy[0];
405             myPrimitiveArray->vtexels[n+i].xy[1] = myPrimitiveArray->vtexels[n+j].xy[1];
406             myPrimitiveArray->vtexels[n+j].xy[0] = x;
407             myPrimitiveArray->vtexels[n+j].xy[1] = y;
408           }
409         }
410         somethingHasChange = Standard_True;
411       }
412     }
413   }
414   return somethingHasChange;
415 }
416
417 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(const Standard_Integer aBoundIndex,
418                                                         const gp_Dir& aNormal)
419 {
420   Standard_Boolean somethingHasChange = Standard_False;
421   if( myPrimitiveArray && myPrimitiveArray->vertices ) {
422     if( myPrimitiveArray->bounds && 
423         (aBoundIndex > 0) && (aBoundIndex <= myPrimitiveArray->num_bounds) ) {
424       Standard_Integer k,n;
425       for( k=n=1 ; k<aBoundIndex ; k++ )
426         n += myPrimitiveArray->bounds[k];
427       k = myPrimitiveArray->bounds[aBoundIndex-1];
428       somethingHasChange = Orientate(n,k,aNormal);
429     } else if( myPrimitiveArray->bounds ) {
430       Standard_OutOfRange::Raise(" BAD BOUND index");
431     } else if( (aBoundIndex > 0) && (aBoundIndex <= ItemNumber()) ) {
432       switch( myPrimitiveArray->type ) {
433         case TelPointsArrayType:
434         case TelPolylinesArrayType:
435         case TelSegmentsArrayType:
436           break;
437         case TelPolygonsArrayType:
438         case TelTriangleStripsArrayType:
439         case TelTriangleFansArrayType:
440         case TelQuadrangleStripsArrayType:
441           somethingHasChange = Orientate(1,VertexNumber(),aNormal);
442           break;
443         case TelTrianglesArrayType:
444           somethingHasChange = Orientate(aBoundIndex*3-2,3,aNormal);
445           break;
446         case TelQuadranglesArrayType:
447           somethingHasChange = Orientate(aBoundIndex*4-3,4,aNormal);
448           break;
449         default:
450           break;
451       }
452     } else {
453       Standard_OutOfRange::Raise(" BAD ITEM index");
454     }
455   }
456   return somethingHasChange;
457 }
458
459 void Graphic3d_ArrayOfPrimitives::SetVertice( const Standard_Integer anIndex,
460                                               const gp_Pnt& aVertice)
461 {
462   Standard_Real x,y,z;
463   aVertice.Coord(x,y,z);
464   SetVertice(anIndex,Standard_ShortReal(x),Standard_ShortReal(y),Standard_ShortReal(z));
465 }
466
467 void Graphic3d_ArrayOfPrimitives::SetVertexColor( const Standard_Integer anIndex,
468                                                   const Quantity_Color& aColor)
469 {
470   Standard_Real r,g,b;
471   aColor.Values(r,g,b,Quantity_TOC_RGB);
472   SetVertexColor(anIndex,r,g,b);
473 }
474
475 void Graphic3d_ArrayOfPrimitives::SetVertexColor( const Standard_Integer anIndex,
476                                                   const Standard_Integer aColor)
477 {
478   if( !myPrimitiveArray ) return;
479   if( anIndex < 1 || anIndex > myMaxVertexs ) {
480     Standard_OutOfRange::Raise(" BAD VERTEX index");
481   }
482   Standard_Integer index = anIndex - 1;
483   if( myPrimitiveArray->vcolours ) {
484 #if defined (sparc) || defined (__sparc__) || defined (__sparc)
485     /* 
486       Well known processor(x86) architectures that use the little-endian format. 
487       Processors use big-endian format is SPARC. In this case use platform with 
488       SPARC architecture(SUNOS). Byte order could have little-endian format.
489     */
490     const char* p_ch = (const char*)&aColor;
491     myPrimitiveArray->vcolours[index] += p_ch[0];
492     myPrimitiveArray->vcolours[index] += p_ch[1] << 8 ;
493     myPrimitiveArray->vcolours[index] += p_ch[2] << 16;
494     myPrimitiveArray->vcolours[index] += p_ch[3] << 24;
495 #else
496     myPrimitiveArray->vcolours[index] = aColor;
497 #endif
498
499   }
500 }
501
502 void Graphic3d_ArrayOfPrimitives::SetVertexNormal(const Standard_Integer anIndex,
503                                                   const gp_Dir& aNormal)
504 {
505   Standard_Real x,y,z;
506   aNormal.Coord(x,y,z);
507   SetVertexNormal(anIndex,x,y,z);
508 }
509
510 void Graphic3d_ArrayOfPrimitives::SetVertexTexel( const Standard_Integer anIndex,
511                                                   const gp_Pnt2d& aTexel)
512 {
513   Standard_Real x,y;
514   aTexel.Coord(x,y);
515   SetVertexTexel(anIndex,x,y);
516 }
517
518 void Graphic3d_ArrayOfPrimitives::SetBoundColor(const Standard_Integer anIndex,
519                                                 const Quantity_Color& aColor)
520 {
521   Standard_Real r,g,b;
522   aColor.Values(r,g,b,Quantity_TOC_RGB);
523   SetBoundColor(anIndex,r,g,b);
524 }
525
526 Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
527 {
528   TCollection_AsciiString name("UndefinedArray");
529   switch( myPrimitiveArray->type ) {
530     case TelPointsArrayType:
531       name = "ArrayOfPoints";
532       break;
533     case TelPolylinesArrayType:
534       name = "ArrayOfPolylines";
535       break;
536     case TelSegmentsArrayType:
537       name = "ArrayOfSegments";
538       break;
539     case TelPolygonsArrayType:
540       name = "ArrayOfPolygons";
541       break;
542     case TelTrianglesArrayType:
543       name = "ArrayOfTriangles";
544       break;
545     case TelQuadranglesArrayType:
546       name = "ArrayOfQuadrangles";
547       break;
548     case TelTriangleStripsArrayType:
549       name = "ArrayOfTriangleStrips";
550       break;
551     case TelQuadrangleStripsArrayType:
552       name = "ArrayOfQuadrangleStrips";
553       break;
554     case TelTriangleFansArrayType:
555       name = "ArrayOfTriangleFans";
556       break;
557     default:
558       break;
559   }
560
561   return name.ToCString();
562 }
563
564 gp_Pnt Graphic3d_ArrayOfPrimitives::Vertice(const Standard_Integer aRank) const
565 {
566   Standard_Real x,y,z;
567   Vertice(aRank,x,y,z);
568   return gp_Pnt(x,y,z);
569 }
570
571 Quantity_Color Graphic3d_ArrayOfPrimitives::VertexColor(const Standard_Integer aRank) const
572 {
573   Standard_Real r,g,b;
574   VertexColor(aRank,r,g,b);
575   return Quantity_Color(r,g,b,Quantity_TOC_RGB);
576 }
577
578 gp_Dir Graphic3d_ArrayOfPrimitives::VertexNormal(const Standard_Integer aRank) const
579 {
580   Standard_Real x,y,z;
581   VertexNormal(aRank,x,y,z);
582   return gp_Dir(x,y,z);
583 }
584
585 gp_Pnt2d Graphic3d_ArrayOfPrimitives::VertexTexel(const Standard_Integer aRank) const
586 {
587   Standard_Real x,y;
588   VertexTexel(aRank,x,y);
589   return gp_Pnt2d(x,y);
590 }
591
592 Quantity_Color Graphic3d_ArrayOfPrimitives::BoundColor(const Standard_Integer aRank) const
593 {
594   Standard_Real r,g,b;
595   BoundColor(aRank,r,g,b);
596   return Quantity_Color(r,g,b,Quantity_TOC_RGB);
597 }
598
599 Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
600 {
601   Standard_Integer number=-1;
602   if( myPrimitiveArray ) switch( myPrimitiveArray->type ) {
603     case TelPointsArrayType:
604       number = myPrimitiveArray->num_vertexs;
605       break;
606     case TelPolylinesArrayType:
607     case TelPolygonsArrayType:
608       if( myPrimitiveArray->num_bounds > 0 ) 
609         number = myPrimitiveArray->num_bounds;
610       else number = 1;
611       break;
612     case TelSegmentsArrayType:
613       if( myPrimitiveArray->num_edges > 0 ) 
614         number = myPrimitiveArray->num_edges/2;
615       else number = myPrimitiveArray->num_vertexs/2;
616       break;
617     case TelTrianglesArrayType:
618       if( myPrimitiveArray->num_edges > 0 ) 
619         number = myPrimitiveArray->num_edges/3;
620       else number = myPrimitiveArray->num_vertexs/3;
621       break;
622     case TelQuadranglesArrayType:
623       if( myPrimitiveArray->num_edges > 0 ) 
624         number = myPrimitiveArray->num_edges/4;
625       else number = myPrimitiveArray->num_vertexs/4;
626       break;
627     case TelTriangleStripsArrayType:
628       if( myPrimitiveArray->num_bounds > 0 ) 
629         number = myPrimitiveArray->num_vertexs-2*myPrimitiveArray->num_bounds;
630       else number = myPrimitiveArray->num_vertexs-2;
631       break;
632     case TelQuadrangleStripsArrayType:
633       if( myPrimitiveArray->num_bounds > 0 ) 
634         number = myPrimitiveArray->num_vertexs/2-myPrimitiveArray->num_bounds;
635       else number = myPrimitiveArray->num_vertexs/2-1;
636       break;
637     case TelTriangleFansArrayType:
638       if( myPrimitiveArray->num_bounds > 0 ) 
639         number = myPrimitiveArray->num_vertexs-2*myPrimitiveArray->num_bounds;
640       else number = myPrimitiveArray->num_vertexs-2;
641       break;
642     default:
643       break;
644   }
645
646   return number;
647 }
648
649 void Graphic3d_ArrayOfPrimitives::ComputeVNormals(const Standard_Integer from,
650                                                   const Standard_Integer to)
651 {
652   Standard_Integer next = from+1;
653   Standard_Integer last = to+1;
654   gp_Pnt p1,p2,p3;
655
656   if( myMaxEdges > 0 ) {
657     p1 = Vertice(Edge(next++));
658     p2 = Vertice(Edge(next++));
659   } else {
660     p1 = Vertice(next++);
661     p2 = Vertice(next++);
662   }
663
664   gp_Vec vn;
665   
666   while ( next <= last ) {
667     if( myMaxEdges > 0 ) {
668       p3 = Vertice(Edge(next));
669     } else {
670       p3 = Vertice(next);
671     }
672     gp_Vec v21(p2,p1);
673     gp_Vec v31(p3,p1);
674     vn = v21 ^ v31;
675     if( vn.SquareMagnitude() > 0. ) break;
676     next++;
677   }
678
679   if( next > last ) {
680 #if TRACE > 0
681     cout << " An item has a NULL computed facet normal" << endl;
682 #endif
683     return;
684   }
685
686   vn.Normalize();
687   if( myMaxEdges > 0 ) {
688     for( int i=from+1 ; i<=to+1 ; i++ ) {
689       SetVertexNormal(Edge(i),vn);
690     }
691   } else {
692     for( int i=from+1 ; i<=to+1 ; i++ ) {
693       SetVertexNormal(i,vn);
694     }
695   }
696 }
697
698 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
699 {
700   if( !myPrimitiveArray ) return Standard_False;
701
702   Standard_Integer nvertexs = myPrimitiveArray->num_vertexs;
703   Standard_Integer nbounds = myPrimitiveArray->num_bounds;
704   Standard_Integer nedges = myPrimitiveArray->num_edges;
705   Standard_Integer i,n;
706
707 #if TRACE > 0
708   Standard_CString name = StringType();
709   cout << " !!! An " << name << " has " << ItemNumber() << " items" << endl;
710 #endif
711
712   switch( myPrimitiveArray->type ) {
713     case TelPointsArrayType:
714       if( nvertexs < 1 ) {
715 #if TRACE > 0
716         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
717 #endif
718         return Standard_False;
719       }
720       break;
721     case TelPolylinesArrayType:
722       if( nedges > 0 && nedges < 2 ) {
723 #if TRACE > 0
724         cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
725 #endif
726         return Standard_False;
727       }
728       if( nvertexs < 2 ) {
729 #if TRACE > 0
730         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
731 #endif
732         return Standard_False;
733       }
734       break;
735     case TelSegmentsArrayType:
736       if( nvertexs < 2 ) {
737 #if TRACE > 0
738         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
739 #endif
740         return Standard_False;
741       }
742       break;
743     case TelPolygonsArrayType:
744       if( nedges > 0 && nedges < 3 ) {
745 #if TRACE > 0
746         cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
747 #endif
748         return Standard_False;
749       }
750       if( nvertexs < 3 ) {
751 #if TRACE > 0
752         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
753 #endif
754         return Standard_False;
755       }
756       break;
757     case TelTrianglesArrayType:
758       if( nedges > 0 ) {
759         if( nedges < 3 || nedges % 3 != 0 ) {
760 #if TRACE > 0
761           cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
762 #endif
763           if( nedges > 3 ) myPrimitiveArray->num_edges = 3 * (nedges / 3);
764           else return Standard_False;
765         }
766       } else if( nvertexs < 3 || nvertexs % 3 != 0 ) {
767 #if TRACE > 0
768         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
769 #endif
770         if( nvertexs > 3 ) myPrimitiveArray->num_vertexs = 3 * (nvertexs / 3);
771         else return Standard_False;
772       }
773       break;
774     case TelQuadranglesArrayType:
775       if( nedges > 0 ) {
776         if( nedges < 4 || nedges % 4 != 0 ) {
777 #if TRACE > 0
778           cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
779 #endif
780           if( nedges > 4 ) myPrimitiveArray->num_edges = 4 * (nedges / 4);
781           else return Standard_False;
782         }
783       } else if( nvertexs < 4 || nvertexs % 4 != 0 ) {
784 #if TRACE > 0
785         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
786 #endif
787         if( nvertexs > 4 ) myPrimitiveArray->num_vertexs = 4 * (nvertexs / 4);
788         else return Standard_False;
789       }
790       break;
791     case TelTriangleFansArrayType:
792     case TelTriangleStripsArrayType:
793       if( nvertexs < 3 ) {
794 #if TRACE > 0
795         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
796 #endif
797         return Standard_False;
798       }
799       break;
800     case TelQuadrangleStripsArrayType:
801       if( nvertexs < 4 ) {
802 #if TRACE > 0
803         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
804 #endif
805         return Standard_False;
806       }
807       break;
808     default:
809 #if TRACE > 0
810       cout << " *** UNKNOWN Array of primitives type found" << endl;
811 #endif
812       return Standard_False;
813   }
814
815   // total number of edges(verticies) in bounds should be the same as variable
816   // of total number of defined edges(verticies); if no edges - only verticies 
817   // could be in bounds.
818   if( nbounds > 0 ) {
819     for( i=n=0 ; i<nbounds ; i++ ) {
820       n += myPrimitiveArray->bounds[i];
821     }
822     if( nedges > 0 && n != nedges ) {
823 #if TRACE > 0
824       cout << " *** An " << name << " has an incoherent number of edges " << nedges << endl;
825 #endif
826       if( nedges > n ) myPrimitiveArray->num_edges = n;
827       else return Standard_False;
828     } else if ( nedges == 0 && n != nvertexs ) {
829 #if TRACE > 0
830       cout << " *** An " << name << " has an incoherent number of vertexs " << nvertexs << endl;
831 #endif
832       if( nvertexs > n ) myPrimitiveArray->num_vertexs = n;
833       else return Standard_False;
834     }
835   }
836
837   // check that edges (indexes to an array of verticies) are in range.
838   if( nedges > 0 ) {
839     for( i=0 ; i<nedges ; i++ ) {
840       if( myPrimitiveArray->edges[i] >= myPrimitiveArray->num_vertexs ) {
841 #if TRACE > 0
842         cout << " *** An " << name << " has a vertex index " << myPrimitiveArray->edges[i] << " greater than the number of defined vertexs " << myPrimitiveArray->num_vertexs << endl;
843 #endif
844         myPrimitiveArray->edges[i] = myPrimitiveArray->num_vertexs-1;
845       }
846     }
847   }
848
849   return Standard_True;
850 }