5d85b4ed5f2e26cb7ec94d32f27289650742a24e
[occt.git] / src / Graphic3d / Graphic3d_ArrayOfPrimitives.cxx
1 // File         Graphic3d_ArrayOfPrimitives.cxx
2 // Created      16/06/2000 : ATS/GG : G005
3
4 #define TRACE 0
5
6 #include <Graphic3d_ArrayOfPrimitives.ixx>
7 #include <Standard.hxx>
8 #include <TCollection_AsciiString.hxx>
9 #include <OSD_Environment.hxx>
10
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 static Standard_Integer enableArray = 1;
15 static Standard_Boolean interleavedArray = Standard_False;
16
17 Graphic3d_ArrayOfPrimitives :: Graphic3d_ArrayOfPrimitives (
18                         const Graphic3d_TypeOfPrimitiveArray aType,
19                         const Standard_Integer maxVertexs,
20                         const Standard_Integer maxBounds,
21                         const Standard_Integer maxEdges,
22                         const Standard_Boolean hasVNormals,
23                         const Standard_Boolean hasVColors,
24                         const Standard_Boolean hasFColors,
25                         const Standard_Boolean hasVTexels,
26                         const Standard_Boolean hasEdgeInfos
27 ) : myMaxBounds(0),myMaxVertexs(0),myMaxEdges(0) {
28   Standard_Integer size = sizeof(CALL_DEF_PARRAY);
29   Standard_Integer format = MVERTICE;
30   if( hasVNormals ) format |= MVNORMAL;
31   if( hasVColors ) format |= MVCOLOR;
32   if( hasVTexels ) format |= MVTEXEL;
33     
34   myPrimitiveArray = (Graphic3d_PrimitiveArray) Standard::Allocate(size); 
35   memset ( myPrimitiveArray, 0, size );
36
37   if( maxVertexs > 0){
38     myPrimitiveArray->vertices = (TEL_POINT*) Standard::Allocate(maxVertexs *sizeof(TEL_POINT));
39     memset ( myPrimitiveArray->vertices, 0, maxVertexs *sizeof(TEL_POINT));
40   }
41
42   if( hasVNormals ){
43     myPrimitiveArray->vnormals = (TEL_POINT*) Standard::Allocate(sizeof(TEL_POINT) * maxVertexs);
44     memset ( myPrimitiveArray->vnormals, 0, sizeof(TEL_POINT) * maxVertexs);
45   }
46
47   if( hasVColors ){
48     myPrimitiveArray->vcolours = (Tint*) Standard::Allocate(maxVertexs *sizeof(Tint));
49     memset ( myPrimitiveArray->vcolours, 0, sizeof(Tint) * maxVertexs);
50   }
51
52   if( hasVTexels ){
53     myPrimitiveArray->vtexels = (TEL_TEXTURE_COORD*) Standard::Allocate(maxVertexs *sizeof(TEL_TEXTURE_COORD));
54     memset ( myPrimitiveArray->vtexels, 0, sizeof(TEL_TEXTURE_COORD) * maxVertexs);
55   }
56
57   if( hasFColors && (maxBounds > 0) ){
58     myPrimitiveArray->fcolours = (TEL_COLOUR*) Standard::Allocate(maxBounds *sizeof(TEL_COLOUR));
59     memset ( myPrimitiveArray->fcolours, 0, sizeof(TEL_COLOUR) * maxBounds);
60   } 
61
62   if( maxBounds > 0 ){
63     myPrimitiveArray->bounds = (Tint*) Standard::Allocate(maxBounds *sizeof(Tint));
64     memset ( myPrimitiveArray->bounds, 0, maxBounds *sizeof(Tint));
65   }
66
67   if( maxEdges > 0 ){
68     myPrimitiveArray->edges = (Tint*) Standard::Allocate(maxEdges *sizeof(Tint));
69     memset ( myPrimitiveArray->edges, 0,  maxEdges *sizeof(Tint));
70   }
71
72   if( hasEdgeInfos && (maxEdges > 0) ){
73     myPrimitiveArray->edge_vis = (Tchar*)Standard::Allocate(maxEdges *sizeof(Tchar));
74     memset ( myPrimitiveArray->edge_vis, 0, maxEdges *sizeof(Tchar));
75   }
76
77   myPrimitiveArray->keys = NULL;
78   myMaxVertexs = maxVertexs;
79   myMaxBounds = maxBounds;
80   myMaxEdges = maxEdges;
81   myPrimitiveArray->type          = (TelPrimitivesArrayType) aType;
82   myPrimitiveArray->format        = format;
83   myPrimitiveArray->num_bounds    = 0;
84   myPrimitiveArray->num_vertexs   = 0;
85   myPrimitiveArray->num_edges     = 0;
86   myPrimitiveArray->VBOEnabled    = -1;
87   myPrimitiveArray->flagBufferVBO = -1;
88   myPrimitiveArray->contextId     = 0;
89
90   for( int i =0 ; i < VBOMaxType ; i++){
91     myPrimitiveArray->bufferVBO[i] = 0;
92   }
93
94 }
95
96 void Graphic3d_ArrayOfPrimitives::Destroy (  ){
97   if( myPrimitiveArray ) {
98     if( myPrimitiveArray->vertices ){
99       Standard::Free( (Standard_Address&)myPrimitiveArray->vertices );
100       myPrimitiveArray->vertices = 0;
101     }
102
103     if( myPrimitiveArray->vnormals ){
104       Standard::Free( (Standard_Address&)myPrimitiveArray->vnormals );
105       myPrimitiveArray->vnormals = 0;
106     }
107
108     if( myPrimitiveArray->vcolours ){
109       Standard::Free( (Standard_Address&)myPrimitiveArray->vcolours );
110       myPrimitiveArray->vcolours = 0;
111     }
112
113     if( myPrimitiveArray->vtexels ){
114       Standard::Free( (Standard_Address&)myPrimitiveArray->vtexels );
115       myPrimitiveArray->vtexels = 0;
116     }
117
118     if( myPrimitiveArray->fcolours ){
119       Standard::Free( (Standard_Address&)myPrimitiveArray->fcolours );
120       myPrimitiveArray->fcolours = 0;
121     } 
122
123     if( myPrimitiveArray->bounds ){
124       Standard::Free( (Standard_Address&)myPrimitiveArray->bounds );
125       myPrimitiveArray->bounds = 0;
126     }
127
128     if( myPrimitiveArray->edges ){
129       Standard::Free( (Standard_Address&)myPrimitiveArray->edges );
130       myPrimitiveArray->edges = 0;
131     }
132
133     if( myPrimitiveArray->edge_vis ){
134       Standard::Free( (Standard_Address&)myPrimitiveArray->edge_vis );
135       myPrimitiveArray->edge_vis = 0;
136     }
137
138     Standard::Free( (Standard_Address&)myPrimitiveArray );
139 #if TRACE > 0
140     cout << " Graphic3d_ArrayOfPrimitives::Destroy()" << endl;
141 #endif
142   }
143 }
144
145 void Graphic3d_ArrayOfPrimitives::Enable() {
146   enableArray = 1;
147 }
148
149 void Graphic3d_ArrayOfPrimitives::Disable() {
150   enableArray = -1;
151 }
152
153 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsEnable() {
154
155   if( enableArray == 0 ) {
156     OSD_Environment csf(TCollection_AsciiString("CSF_USE_ARRAY_OF_PRIMITIVES"));
157     TCollection_AsciiString value = csf.Value();
158     enableArray = -1;
159     if( value.Length() > 0 ) {
160       if( value.IsIntegerValue() ) {
161         enableArray = value.IntegerValue();
162         if( enableArray > 1 ) {
163           enableArray = 1;
164         } else interleavedArray = Standard_False;
165       }
166     }
167 #if TRACE > 0
168     if( enableArray > 0 ) {
169       if( interleavedArray ) 
170         cout << " ! ENABLE to use Interleaved arrays of primitives" << endl;
171       else
172         cout << " ! ENABLE to use Single arrays of primitives" << endl;
173     } else
174       cout << " ! DISABLE to use arrays of primitives" << endl;
175 #endif
176   }
177   if( enableArray > 0 ) return Standard_True;
178
179   return Standard_False;
180 }
181
182 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
183                 const gp_Pnt& aVertice) {
184   Standard_Real x,y,z;
185   aVertice.Coord(x,y,z);
186   return AddVertex(x,y,z);
187 }
188
189 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
190         const Standard_Real X, const Standard_Real Y, const Standard_Real Z) {
191
192   if( !myPrimitiveArray ) return 0;
193
194   Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
195   if( index > myMaxVertexs ) {
196     Standard_OutOfRange::Raise(" TOO many VERTEX");
197   }
198   SetVertice(index,X,Y,Z);
199   return index;
200 }
201
202 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
203                                                         const gp_Pnt& aVertice,
204                                                         const Quantity_Color& aColor) {
205   Standard_Real x,y,z;
206   aVertice.Coord(x,y,z);
207   Standard_Integer index = AddVertex(x,y,z);
208   Standard_Real r,g,b;
209   aColor.Values(r,g,b,Quantity_TOC_RGB);
210   SetVertexColor(index,r,g,b);
211   return index;
212 }
213 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
214                                                         const gp_Pnt& aVertice,
215                                                         const Standard_Integer aColor) {
216   Standard_Real x,y,z;
217   aVertice.Coord(x,y,z);
218   Standard_Integer index = AddVertex(x,y,z);
219   SetVertexColor(index,aColor);
220   return index;
221 }
222
223
224 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
225                                                         const gp_Pnt& aVertice,
226                                                         const gp_Dir& aNormal) {
227   Standard_Real x,y,z;
228   aVertice.Coord(x,y,z);
229   Standard_Real nx,ny,nz;
230   aNormal.Coord(nx,ny,nz);
231   return AddVertex(x,y,z,nx,ny,nz);
232 }
233
234 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
235         const Standard_Real X, const Standard_Real Y, const Standard_Real Z,
236         const Standard_Real NX, const Standard_Real NY, const Standard_Real NZ) {
237   if( !myPrimitiveArray ) return 0;
238
239   Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
240   if( index > myMaxVertexs ) {
241     Standard_OutOfRange::Raise(" TOO many VERTEX");
242   }
243   SetVertice(index,X,Y,Z);
244   SetVertexNormal(index,NX,NY,NZ);
245   return index;
246 }
247
248
249 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
250                                                         const gp_Pnt& aVertice,
251                                                         const gp_Dir& aNormal,
252                                                         const Quantity_Color& aColor) {
253   Standard_Real x,y,z;
254   aVertice.Coord(x,y,z);
255   Standard_Real nx,ny,nz;
256   aNormal.Coord(nx,ny,nz);
257   Standard_Integer index = AddVertex(x,y,z,nx,ny,nz);
258   Standard_Real r,g,b;
259   aColor.Values(r,g,b,Quantity_TOC_RGB);
260   SetVertexColor(index,r,g,b);
261   return index;
262 }
263
264 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
265                                                         const gp_Pnt& aVertice,
266                                                         const gp_Dir& aNormal,
267                                                         const Standard_Integer aColor) {
268   Standard_Real x,y,z;
269   aVertice.Coord(x,y,z);
270   Standard_Real nx,ny,nz;
271   aNormal.Coord(nx,ny,nz);
272   Standard_Integer index = AddVertex(x,y,z,nx,ny,nz);
273   SetVertexColor(index,aColor);
274   return index;
275 }
276
277 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
278                                                         const gp_Pnt& aVertice,
279                                                         const gp_Pnt2d& aTexel) {
280   Standard_Real x,y,z;
281   aVertice.Coord(x,y,z);
282   Standard_Real tx,ty;
283   aTexel.Coord(tx,ty);
284   return AddVertex(x,y,z,tx,ty);
285 }
286
287 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
288         const Standard_Real X, const Standard_Real Y, const Standard_Real Z,
289         const Standard_Real TX, const Standard_Real TY) {
290   if( !myPrimitiveArray ) return 0;
291
292   Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
293   if( index > myMaxVertexs ) {
294     Standard_OutOfRange::Raise(" TOO many VERTEX");
295   }
296   SetVertice(index,X,Y,Z);
297   SetVertexTexel(index,TX,TY);
298   return index;
299 }
300
301 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
302                                                         const gp_Pnt& aVertice,
303                                                         const gp_Dir& aNormal,
304                                                         const gp_Pnt2d& aTexel) {
305   Standard_Real x,y,z;
306   aVertice.Coord(x,y,z);
307   Standard_Real nx,ny,nz;
308   aNormal.Coord(nx,ny,nz);
309   Standard_Real tx,ty;
310   aTexel.Coord(tx,ty);
311   return AddVertex(x,y,z,nx,ny,nz,tx,ty);
312 }
313
314 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex(
315         const Standard_Real X, const Standard_Real Y, const Standard_Real Z,
316         const Standard_Real NX, const Standard_Real NY, const Standard_Real NZ,
317         const Standard_Real TX, const Standard_Real TY) {
318   if( !myPrimitiveArray ) return 0;
319
320   Standard_Integer index = myPrimitiveArray->num_vertexs + 1;
321   if( index > myMaxVertexs ) {
322     Standard_OutOfRange::Raise(" TOO many VERTEX");
323   }
324   SetVertice(index,X,Y,Z);
325   SetVertexNormal(index,NX,NY,NZ);
326   SetVertexTexel(index,TX,TY);
327   return index;
328 }
329
330 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound( const Standard_Integer edgeNumber) {
331   Standard_Integer index = 0;
332   if( myPrimitiveArray && myPrimitiveArray->bounds ) {
333     index = myPrimitiveArray->num_bounds;
334     if( index < myMaxBounds ) {
335       myPrimitiveArray->bounds[index] = edgeNumber;
336       myPrimitiveArray->num_bounds = ++index;
337     } else {
338       Standard_OutOfRange::Raise(" TOO many BOUNDS");
339     }
340   }
341
342   return index;
343 }
344
345 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound(
346                                                         const Standard_Integer edgeNumber,
347                                                         const Quantity_Color& aFColor
348 ) {
349   Standard_Real r,g,b;
350   aFColor.Values(r,g,b,Quantity_TOC_RGB);
351   return AddBound(edgeNumber,r,g,b);
352 }
353
354 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound(
355                                                         const Standard_Integer edgeNumber,
356                                                         const Standard_Real R, 
357                                                         const Standard_Real G,
358                                                         const Standard_Real B) { 
359   if( !myPrimitiveArray ) return 0;
360
361   Standard_Integer index = myPrimitiveArray->num_bounds;
362   if( index >= myMaxBounds ) {
363     Standard_OutOfRange::Raise(" TOO many BOUND");
364   }
365   myPrimitiveArray->bounds[index] = edgeNumber;
366   myPrimitiveArray->num_bounds = ++index;
367   SetBoundColor(index,R,G,B);
368   return index;
369 }
370
371 Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge(
372                                                       const Standard_Integer vertexIndex,
373                                                       const Standard_Boolean isVisible) {
374   if( !myPrimitiveArray ) return 0;
375
376   Standard_Integer index = myPrimitiveArray->num_edges;
377   if( index >= myMaxEdges ) {
378     Standard_OutOfRange::Raise(" TOO many EDGE");
379   }
380   Standard_Integer vindex = vertexIndex-1;
381   if( vertexIndex > 0 && vindex < myMaxVertexs ) {
382     myPrimitiveArray->edges[index] = vindex;
383     if( myPrimitiveArray->edge_vis ) {
384       myPrimitiveArray->edge_vis[index] = (Tchar) (isVisible ? 1 : 0);
385     }
386     myPrimitiveArray->num_edges = ++index;
387   } else {
388     Standard_OutOfRange::Raise(" BAD EDGE vertex index");
389   }
390
391   return index;
392 }
393
394 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(
395                         const gp_Dir& aNormal) {
396   return Orientate(1,Max(VertexNumber(),EdgeNumber()),aNormal);
397 }
398
399 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(
400                                                         const Standard_Integer aVertexIndex,
401                                                         const Standard_Integer aVertexNumber,
402                                                         const gp_Dir& aNormal) {
403   Standard_Boolean somethingHasChange = Standard_False;
404   if( myPrimitiveArray && (myPrimitiveArray->num_vertexs > 2) ) {
405     Standard_Integer i,j,k=aVertexNumber,n=aVertexIndex-1;
406     Standard_ShortReal x,y,z;
407     if( myPrimitiveArray->edges ) {
408       if( n >= 0 && (n+k) <= myPrimitiveArray->num_edges ) {
409         Standard_Integer i1 = myPrimitiveArray->edges[n];
410         Standard_Integer i2 = myPrimitiveArray->edges[n+1];
411         Standard_Integer i3 = myPrimitiveArray->edges[n+2];
412         gp_Pnt p1(myPrimitiveArray->vertices[i1].xyz[0],
413                   myPrimitiveArray->vertices[i1].xyz[1],
414                   myPrimitiveArray->vertices[i1].xyz[2]);
415         gp_Pnt p2(myPrimitiveArray->vertices[i2].xyz[0],
416                   myPrimitiveArray->vertices[i2].xyz[1],
417                   myPrimitiveArray->vertices[i2].xyz[2]);
418         gp_Pnt p3(myPrimitiveArray->vertices[i3].xyz[0],
419                   myPrimitiveArray->vertices[i3].xyz[1],
420                   myPrimitiveArray->vertices[i3].xyz[2]);
421         gp_Vec v21(p1,p2),v31(p1,p3),fn = v21.Crossed(v31);
422         if( aNormal.IsOpposite(fn,Standard_PI/4.) ) {
423           Standard_Integer e; char v;
424           for( i=0,j=k-1 ; i<k/2 ; i++,j-- ) {
425             e = myPrimitiveArray->edges[n+i];
426             myPrimitiveArray->edges[n+i] = myPrimitiveArray->edges[n+j];
427             myPrimitiveArray->edges[n+j] = e;
428             if( myPrimitiveArray->edge_vis ) {
429               v = myPrimitiveArray->edge_vis[n+i];
430               myPrimitiveArray->edge_vis[n+i] = myPrimitiveArray->edge_vis[n+j];
431               myPrimitiveArray->edge_vis[n+j] = v;
432             }
433             if( myPrimitiveArray->vnormals ) {
434               e = myPrimitiveArray->edges[n+i];
435               x = myPrimitiveArray->vnormals[e].xyz[0];
436               y = myPrimitiveArray->vnormals[e].xyz[1];
437               z = myPrimitiveArray->vnormals[e].xyz[2];
438               gp_Vec vn(x,y,z);
439               if( aNormal.IsOpposite(vn,Standard_PI/4.) ) {
440                 myPrimitiveArray->vnormals[e].xyz[0] = -x;
441                 myPrimitiveArray->vnormals[e].xyz[1] = -y;
442                 myPrimitiveArray->vnormals[e].xyz[2] = -z;
443               }
444             }
445           }
446           somethingHasChange = Standard_True;
447         }
448       } else {
449         Standard_OutOfRange::Raise(" BAD EDGE index or number");
450       }
451       return somethingHasChange;
452     } 
453
454     if( n >= 0 && (n+k) <= myPrimitiveArray->num_vertexs ) {
455       gp_Pnt p1(myPrimitiveArray->vertices[n].xyz[0],
456                   myPrimitiveArray->vertices[n].xyz[1],
457                   myPrimitiveArray->vertices[n].xyz[2]);
458       gp_Pnt p2(myPrimitiveArray->vertices[n+1].xyz[0],
459                   myPrimitiveArray->vertices[n+1].xyz[1],
460                   myPrimitiveArray->vertices[n+1].xyz[2]);
461       gp_Pnt p3(myPrimitiveArray->vertices[n+2].xyz[0],
462                   myPrimitiveArray->vertices[n+2].xyz[1],
463                   myPrimitiveArray->vertices[n+2].xyz[2]);
464       gp_Vec v21(p1,p2),v31(p1,p3),fn = v21.Crossed(v31);
465       if( aNormal.IsOpposite(fn,Standard_PI/4.) ) {
466         for( i=0,j=k-1 ; i<k/2 ; i++,j-- ) {
467           x = myPrimitiveArray->vertices[n+i].xyz[0];
468           y = myPrimitiveArray->vertices[n+i].xyz[1];
469           z = myPrimitiveArray->vertices[n+i].xyz[2];
470           myPrimitiveArray->vertices[n+i].xyz[0] = myPrimitiveArray->vertices[n+j].xyz[0];
471           myPrimitiveArray->vertices[n+i].xyz[1] = myPrimitiveArray->vertices[n+j].xyz[1];
472           myPrimitiveArray->vertices[n+i].xyz[2] = myPrimitiveArray->vertices[n+j].xyz[2];
473           myPrimitiveArray->vertices[n+j].xyz[0] = x;
474           myPrimitiveArray->vertices[n+j].xyz[1] = y;
475           myPrimitiveArray->vertices[n+j].xyz[2] = z;
476           if( myPrimitiveArray->vnormals ) {
477             x = myPrimitiveArray->vnormals[n+i].xyz[0];
478             y = myPrimitiveArray->vnormals[n+i].xyz[1];
479             z = myPrimitiveArray->vnormals[n+i].xyz[2];
480             myPrimitiveArray->vnormals[n+i].xyz[0] = myPrimitiveArray->vnormals[n+j].xyz[0];
481             myPrimitiveArray->vnormals[n+i].xyz[1] = myPrimitiveArray->vnormals[n+j].xyz[1];
482             myPrimitiveArray->vnormals[n+i].xyz[2] = myPrimitiveArray->vnormals[n+j].xyz[2];
483             myPrimitiveArray->vnormals[n+j].xyz[0] = x;
484             myPrimitiveArray->vnormals[n+j].xyz[1] = y;
485             myPrimitiveArray->vnormals[n+j].xyz[2] = z;
486
487             x = myPrimitiveArray->vnormals[n+i].xyz[0];
488             y = myPrimitiveArray->vnormals[n+i].xyz[1];
489             z = myPrimitiveArray->vnormals[n+i].xyz[2];
490             gp_Vec vn(x,y,z);
491             if( aNormal.IsOpposite(vn,Standard_PI/4.) ) {
492               myPrimitiveArray->vnormals[n+i].xyz[0] = -x;
493               myPrimitiveArray->vnormals[n+i].xyz[1] = -y;
494               myPrimitiveArray->vnormals[n+i].xyz[2] = -z;
495             }
496           }
497           if( myPrimitiveArray->vcolours ) {
498             x = (Standard_ShortReal)myPrimitiveArray->vcolours[n+i];
499             myPrimitiveArray->vcolours[n+i] = myPrimitiveArray->vcolours[n+j];
500             myPrimitiveArray->vcolours[n+j] = (Tint)x;
501           }
502           if( myPrimitiveArray->vtexels ) {
503             x = myPrimitiveArray->vtexels[n+i].xy[0];
504             y = myPrimitiveArray->vtexels[n+i].xy[1];
505             myPrimitiveArray->vtexels[n+i].xy[0] = myPrimitiveArray->vtexels[n+j].xy[0];
506             myPrimitiveArray->vtexels[n+i].xy[1] = myPrimitiveArray->vtexels[n+j].xy[1];
507             myPrimitiveArray->vtexels[n+j].xy[0] = x;
508             myPrimitiveArray->vtexels[n+j].xy[1] = y;
509           }
510         }
511         somethingHasChange = Standard_True;
512       }
513     }
514   }
515   return somethingHasChange;
516 }
517
518 Standard_Boolean Graphic3d_ArrayOfPrimitives::Orientate(
519                                                         const Standard_Integer aBoundIndex,
520                                                         const gp_Dir& aNormal) {
521   Standard_Boolean somethingHasChange = Standard_False;
522   if( myPrimitiveArray && myPrimitiveArray->vertices ) {
523     if( myPrimitiveArray->bounds && 
524         (aBoundIndex > 0) && (aBoundIndex <= myPrimitiveArray->num_bounds) ) {
525       Standard_Integer k,n;
526       for( k=n=1 ; k<aBoundIndex ; k++ )
527         n += myPrimitiveArray->bounds[k];
528       k = myPrimitiveArray->bounds[aBoundIndex-1];
529       somethingHasChange = Orientate(n,k,aNormal);
530     } else if( myPrimitiveArray->bounds ) {
531       Standard_OutOfRange::Raise(" BAD BOUND index");
532     } else if( (aBoundIndex > 0) && (aBoundIndex <= ItemNumber()) ) {
533       switch( myPrimitiveArray->type ) {
534         case TelPointsArrayType:
535         case TelPolylinesArrayType:
536         case TelSegmentsArrayType:
537           break;
538         case TelPolygonsArrayType:
539         case TelTriangleStripsArrayType:
540         case TelTriangleFansArrayType:
541         case TelQuadrangleStripsArrayType:
542           somethingHasChange = Orientate(1,VertexNumber(),aNormal);
543           break;
544         case TelTrianglesArrayType:
545           somethingHasChange = Orientate(aBoundIndex*3-2,3,aNormal);
546           break;
547         case TelQuadranglesArrayType:
548           somethingHasChange = Orientate(aBoundIndex*4-3,4,aNormal);
549           break;
550         default:
551           break;
552       }
553     } else {
554       Standard_OutOfRange::Raise(" BAD ITEM index");
555     }
556   }
557   return somethingHasChange;
558 }
559
560 void Graphic3d_ArrayOfPrimitives::SetVertice(
561                                               const Standard_Integer anIndex,
562                                               const gp_Pnt& aVertice) {
563   Standard_Real x,y,z;
564   aVertice.Coord(x,y,z);
565   SetVertice(anIndex,x,y,z);
566 }
567
568 void Graphic3d_ArrayOfPrimitives::SetVertexColor(
569                                                   const Standard_Integer anIndex,
570                                                   const Quantity_Color& aColor) {
571   Standard_Real r,g,b;
572   aColor.Values(r,g,b,Quantity_TOC_RGB);
573   SetVertexColor(anIndex,r,g,b);
574 }
575
576 void Graphic3d_ArrayOfPrimitives::SetVertexColor(
577                                                   const Standard_Integer anIndex,
578                                                   const Standard_Integer aColor) {
579
580   if( !myPrimitiveArray ) return;
581   if( anIndex < 1 || anIndex > myMaxVertexs ) {
582     Standard_OutOfRange::Raise(" BAD VERTEX index");
583   }
584   Standard_Integer index = anIndex - 1;
585   if( myPrimitiveArray->vcolours ) {
586 #if defined (sparc) || defined (__sparc__) || defined (__sparc)
587     /* 
588       Well known processor(x86) architectures that use the little-endian format. 
589       Processors use big-endian format is SPARC. In this case use platform with 
590       SPARC architecture(SUNOS). Byte order could have little-endian format.
591     */
592     const char* p_ch = (const char*)&aColor;
593     myPrimitiveArray->vcolours[index] += p_ch[0];
594     myPrimitiveArray->vcolours[index] += p_ch[1] << 8 ;
595     myPrimitiveArray->vcolours[index] += p_ch[2] << 16;
596     myPrimitiveArray->vcolours[index] += p_ch[3] << 24;
597 #else
598     myPrimitiveArray->vcolours[index] = aColor;
599 #endif
600
601   }
602 }
603 void Graphic3d_ArrayOfPrimitives::SetVertexNormal(
604                                                   const Standard_Integer anIndex,
605                                                   const gp_Dir& aNormal) {
606   Standard_Real x,y,z;
607   aNormal.Coord(x,y,z);
608   SetVertexNormal(anIndex,x,y,z);
609 }
610
611 void Graphic3d_ArrayOfPrimitives::SetVertexTexel(
612                                                   const Standard_Integer anIndex,
613                                                   const gp_Pnt2d& aTexel) {
614   Standard_Real x,y;
615   aTexel.Coord(x,y);
616   SetVertexTexel(anIndex,x,y);
617 }
618
619 void Graphic3d_ArrayOfPrimitives::SetBoundColor(
620                                                 const Standard_Integer anIndex,
621                                                 const Quantity_Color& aColor) {
622   Standard_Real r,g,b;
623   aColor.Values(r,g,b,Quantity_TOC_RGB);
624   SetBoundColor(anIndex,r,g,b);
625 }
626
627 Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const {
628   TCollection_AsciiString name("UndefinedArray");
629   switch( myPrimitiveArray->type ) {
630     case TelPointsArrayType:
631       name = "ArrayOfPoints";
632       break;
633     case TelPolylinesArrayType:
634       name = "ArrayOfPolylines";
635       break;
636     case TelSegmentsArrayType:
637       name = "ArrayOfSegments";
638       break;
639     case TelPolygonsArrayType:
640       name = "ArrayOfPolygons";
641       break;
642     case TelTrianglesArrayType:
643       name = "ArrayOfTriangles";
644       break;
645     case TelQuadranglesArrayType:
646       name = "ArrayOfQuadrangles";
647       break;
648     case TelTriangleStripsArrayType:
649       name = "ArrayOfTriangleStrips";
650       break;
651     case TelQuadrangleStripsArrayType:
652       name = "ArrayOfQuadrangleStrips";
653       break;
654     case TelTriangleFansArrayType:
655       name = "ArrayOfTriangleFans";
656       break;
657     default:
658       break;
659   }
660
661   return name.ToCString();
662 }
663
664 gp_Pnt Graphic3d_ArrayOfPrimitives::Vertice(const Standard_Integer aRank) const {
665   Standard_Real x,y,z;
666   Vertice(aRank,x,y,z);
667   return gp_Pnt(x,y,z);
668 }
669
670 Quantity_Color Graphic3d_ArrayOfPrimitives::VertexColor(const Standard_Integer aRank) const {
671   Standard_Real r,g,b;
672   VertexColor(aRank,r,g,b);
673   return Quantity_Color(r,g,b,Quantity_TOC_RGB);
674 }
675
676 gp_Dir Graphic3d_ArrayOfPrimitives::VertexNormal(const Standard_Integer aRank) const {
677   Standard_Real x,y,z;
678   VertexNormal(aRank,x,y,z);
679   return gp_Dir(x,y,z);
680 }
681
682 gp_Pnt2d Graphic3d_ArrayOfPrimitives::VertexTexel(const Standard_Integer aRank) const {
683   Standard_Real x,y;
684   VertexTexel(aRank,x,y);
685   return gp_Pnt2d(x,y);
686 }
687
688 Quantity_Color Graphic3d_ArrayOfPrimitives::BoundColor(const Standard_Integer aRank) const {
689   Standard_Real r,g,b;
690   BoundColor(aRank,r,g,b);
691   return Quantity_Color(r,g,b,Quantity_TOC_RGB);
692 }
693
694 Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const {
695   Standard_Integer number=-1;
696   if( myPrimitiveArray ) switch( myPrimitiveArray->type ) {
697     case TelPointsArrayType:
698       number = myPrimitiveArray->num_vertexs;
699       break;
700     case TelPolylinesArrayType:
701     case TelPolygonsArrayType:
702       if( myPrimitiveArray->num_bounds > 0 ) 
703         number = myPrimitiveArray->num_bounds;
704       else number = 1;
705       break;
706     case TelSegmentsArrayType:
707       if( myPrimitiveArray->num_edges > 0 ) 
708         number = myPrimitiveArray->num_edges/2;
709       else number = myPrimitiveArray->num_vertexs/2;
710       break;
711     case TelTrianglesArrayType:
712       if( myPrimitiveArray->num_edges > 0 ) 
713         number = myPrimitiveArray->num_edges/3;
714       else number = myPrimitiveArray->num_vertexs/3;
715       break;
716     case TelQuadranglesArrayType:
717       if( myPrimitiveArray->num_edges > 0 ) 
718         number = myPrimitiveArray->num_edges/4;
719       else number = myPrimitiveArray->num_vertexs/4;
720       break;
721     case TelTriangleStripsArrayType:
722       if( myPrimitiveArray->num_bounds > 0 ) 
723         number = myPrimitiveArray->num_vertexs-2*myPrimitiveArray->num_bounds;
724       else number = myPrimitiveArray->num_vertexs-2;
725       break;
726     case TelQuadrangleStripsArrayType:
727       if( myPrimitiveArray->num_bounds > 0 ) 
728         number = myPrimitiveArray->num_vertexs/2-myPrimitiveArray->num_bounds;
729       else number = myPrimitiveArray->num_vertexs/2-1;
730       break;
731     case TelTriangleFansArrayType:
732       if( myPrimitiveArray->num_bounds > 0 ) 
733         number = myPrimitiveArray->num_vertexs-2*myPrimitiveArray->num_bounds;
734       else number = myPrimitiveArray->num_vertexs-2;
735       break;
736     default:
737       break;
738   }
739
740   return number;
741 }
742
743 void Graphic3d_ArrayOfPrimitives::ComputeVNormals(
744                                                   const Standard_Integer from,
745                                                   const Standard_Integer to) {
746   Standard_Integer next = from+1;
747   Standard_Integer last = to+1;
748   gp_Pnt p1,p2,p3;
749
750   if( myMaxEdges > 0 ) {
751     p1 = Vertice(Edge(next++));
752     p2 = Vertice(Edge(next++));
753   } else {
754     p1 = Vertice(next++);
755     p2 = Vertice(next++);
756   }
757
758   gp_Vec vn;
759   
760   while ( next <= last ) {
761     if( myMaxEdges > 0 ) {
762       p3 = Vertice(Edge(next));
763     } else {
764       p3 = Vertice(next);
765     }
766     gp_Vec v21(p2,p1);
767     gp_Vec v31(p3,p1);
768     vn = v21 ^ v31;
769     if( vn.SquareMagnitude() > 0. ) break;
770     next++;
771   }
772
773   if( next > last ) {
774 #if TRACE > 0
775     cout << " An item has a NULL computed facet normal" << endl;
776 #endif
777     return;
778   }
779
780   vn.Normalize();
781   if( myMaxEdges > 0 ) {
782     for( int i=from+1 ; i<=to+1 ; i++ ) {
783       SetVertexNormal(Edge(i),vn);
784     }
785   } else {
786     for( int i=from+1 ; i<=to+1 ; i++ ) {
787       SetVertexNormal(i,vn);
788     }
789   }
790 }
791
792 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid() {
793
794   if( !myPrimitiveArray ) return Standard_False;
795
796   Standard_Integer nvertexs = myPrimitiveArray->num_vertexs;
797   Standard_Integer nbounds = myPrimitiveArray->num_bounds;
798   Standard_Integer nedges = myPrimitiveArray->num_edges;
799   Standard_Integer i,j,k,n;
800
801 #if TRACE > 0
802   Standard_CString name = StringType();
803   cout << " !!! An " << name << " has " << ItemNumber() << " items" << endl;
804 #endif
805
806   switch( myPrimitiveArray->type ) {
807     case TelPointsArrayType:
808       if( nvertexs < 1 ) {
809 #if TRACE > 0
810         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
811 #endif
812         return Standard_False;
813       }
814       break;
815     case TelPolylinesArrayType:
816       if( nedges > 0 && nedges < 2 ) {
817 #if TRACE > 0
818         cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
819 #endif
820         return Standard_False;
821       }
822       if( nvertexs < 2 ) {
823 #if TRACE > 0
824         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
825 #endif
826         return Standard_False;
827       }
828       break;
829     case TelSegmentsArrayType:
830       if( nvertexs < 2 ) {
831 #if TRACE > 0
832         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
833 #endif
834         return Standard_False;
835       }
836       break;
837     case TelPolygonsArrayType:
838       if( nedges > 0 && nedges < 3 ) {
839 #if TRACE > 0
840         cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
841 #endif
842         return Standard_False;
843       }
844       if( nvertexs < 3 ) {
845 #if TRACE > 0
846         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
847 #endif
848         return Standard_False;
849       }
850       break;
851     case TelTrianglesArrayType:
852       if( nedges > 0 ) {
853         if( nedges < 3 || nedges % 3 != 0 ) {
854 #if TRACE > 0
855           cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
856 #endif
857           if( nedges > 3 ) myPrimitiveArray->num_edges = 3 * (nedges / 3);
858           else return Standard_False;
859         }
860       } else if( nvertexs < 3 || nvertexs % 3 != 0 ) {
861 #if TRACE > 0
862         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
863 #endif
864         if( nvertexs > 3 ) myPrimitiveArray->num_vertexs = 3 * (nvertexs / 3);
865         else return Standard_False;
866       }
867       break;
868     case TelQuadranglesArrayType:
869       if( nedges > 0 ) {
870         if( nedges < 4 || nedges % 4 != 0 ) {
871 #if TRACE > 0
872           cout << " *** An " << name << " is unavailable with a too lower number of edges " << nedges << endl;
873 #endif
874           if( nedges > 4 ) myPrimitiveArray->num_edges = 4 * (nedges / 4);
875           else return Standard_False;
876         }
877       } else if( nvertexs < 4 || nvertexs % 4 != 0 ) {
878 #if TRACE > 0
879         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
880 #endif
881         if( nvertexs > 4 ) myPrimitiveArray->num_vertexs = 4 * (nvertexs / 4);
882         else return Standard_False;
883       }
884       break;
885     case TelTriangleFansArrayType:
886     case TelTriangleStripsArrayType:
887       if( nvertexs < 3 ) {
888 #if TRACE > 0
889         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
890 #endif
891         return Standard_False;
892       }
893       break;
894     case TelQuadrangleStripsArrayType:
895       if( nvertexs < 4 ) {
896 #if TRACE > 0
897         cout << " *** An " << name << " is unavailable with a too lower number of vertex " << nvertexs << endl;
898 #endif
899         return Standard_False;
900       }
901       break;
902     default:
903 #if TRACE > 0
904       cout << " *** UNKNOWN Array of primitives type found" << endl;
905 #endif
906       return Standard_False;
907   }
908
909   if( nbounds > 0 ) {
910     for( i=n=0 ; i<nbounds ; i++ ) {
911       n += myPrimitiveArray->bounds[i];
912     }
913     if( nedges > 0 && n != nedges ) {
914 #if TRACE > 0
915       cout << " *** An " << name << " has an incoherent number of edges " << nedges << endl;
916 #endif
917       if( nedges > n ) myPrimitiveArray->num_edges = n;
918       else return Standard_False;
919     } else if( n != nvertexs ) {
920 #if TRACE > 0
921       cout << " *** An " << name << " has an incoherent number of vertexs " << nvertexs << endl;
922 #endif
923       if( nvertexs > n ) myPrimitiveArray->num_vertexs = n;
924       else return Standard_False;
925     }
926   }
927
928   if( nedges > 0 ) {
929     for( i=0 ; i<nedges ; i++ ) {
930       if( myPrimitiveArray->edges[i] >= myPrimitiveArray->num_vertexs ) {
931 #if TRACE > 0
932         cout << " *** An " << name << " has a vertex index " << myPrimitiveArray->edges[i] << " greater than the number of defined vertexs " << myPrimitiveArray->num_vertexs << endl;
933 #endif
934         myPrimitiveArray->edges[i] = myPrimitiveArray->num_vertexs-1;
935       }
936     }
937   }
938
939   Standard_Integer format;
940   Standard_Boolean valid = Standard_True;
941   for( i=0 ; i<nvertexs ; i++ ) {
942     format = myPrimitiveArray->format;
943     if( format != myPrimitiveArray->format ) {
944       valid = Standard_False;
945 #if TRACE > 0
946       cout << " *** An " << name << " has an incoherent kind of vertexs " 
947         << i+1 << " of type " << myPrimitiveArray->format << "/" << format << endl;
948 #endif
949       break;
950     }
951   }
952
953   if( valid ) return Standard_True;
954
955   if( nbounds > 0 ) 
956   {
957     for( j=n=0 ; j<nbounds ; j++ ) 
958     {
959       k = myPrimitiveArray->bounds[j];
960       for( i=0 ; i<k ; i++ ) 
961       {
962          format = myPrimitiveArray->format;
963         if( format != myPrimitiveArray->format ) 
964         {
965           if( myPrimitiveArray->format & MVNORMAL ) switch( myPrimitiveArray->type ) 
966           {
967       case TelPolygonsArrayType:
968         if( i == 0 ) ComputeVNormals(n+i,n+k-1);
969         break;
970       case TelTrianglesArrayType:
971         if( !(i % 3) ) ComputeVNormals(n+i,n+i+2);
972         break;
973       case TelQuadranglesArrayType:
974         if( !(i % 4) ) ComputeVNormals(n+i,n+i+3);
975         break;
976       case TelTriangleFansArrayType:
977       case TelTriangleStripsArrayType:
978         if( i < k-2 ) ComputeVNormals(n+i,n+i+2);
979         else
980           break;
981       case TelQuadrangleStripsArrayType:
982         if( !(i %2) && (i < k-3) ) ComputeVNormals(n+i,n+i+3);
983         break;
984       default:
985         break;
986           }
987         }
988       }
989       n += myPrimitiveArray->bounds[j];
990     }
991   } else if( nedges > 0 ) {
992     for( i=0 ; i<nedges ; i++ ) {
993       k = myPrimitiveArray->edges[i];
994       format = myPrimitiveArray->format;
995       if( format != myPrimitiveArray->format ) {
996         if( myPrimitiveArray->format & MVNORMAL ) switch( myPrimitiveArray->type ) {
997           case TelPolygonsArrayType:
998             if( i == 0 ) ComputeVNormals(i,nedges-1);
999             break;
1000           case TelTrianglesArrayType:
1001             k = i/3*3;
1002             ComputeVNormals(k,k+2);
1003             break;
1004           case TelQuadranglesArrayType:
1005             k = i/4*4;
1006             ComputeVNormals(k,k+3);
1007             break;
1008           case TelTriangleFansArrayType:
1009           case TelTriangleStripsArrayType:
1010             if( i < nedges-2 ) ComputeVNormals(i,i+2);
1011             else
1012             break;
1013           case TelQuadrangleStripsArrayType:
1014             if( !(i %2) && (i < nedges-3) ) ComputeVNormals(i,i+3);
1015             break;
1016           default:
1017             break;
1018         }
1019       }
1020     }
1021   } else if( nvertexs > 0 ) {
1022     for( i=0 ; i<nvertexs ; i++ ) {
1023       format = myPrimitiveArray->format;
1024       if( format != myPrimitiveArray->format ) {
1025         if( myPrimitiveArray->format & MVNORMAL ) switch( myPrimitiveArray->type ) {
1026           case TelPolygonsArrayType:
1027             if( i == 0 ) ComputeVNormals(i,nvertexs-1);
1028             break;
1029           case TelTrianglesArrayType:
1030             if( !(i % 3) ) ComputeVNormals(i,i+2);
1031             break;
1032           case TelQuadranglesArrayType:
1033             if( !(i % 4) ) ComputeVNormals(i,i+3);
1034             break;
1035           case TelTriangleFansArrayType:
1036           case TelTriangleStripsArrayType:
1037             if( i < nvertexs-2 ) ComputeVNormals(i,i+2);
1038             else
1039             break;
1040           case TelQuadrangleStripsArrayType:
1041             if( !(i %2) && (i < nvertexs-3) ) ComputeVNormals(i,i+3);
1042             break;
1043           default:
1044             break;
1045         }
1046       }
1047     }
1048   }
1049
1050   return Standard_True;
1051 }