7fd59977 |
1 | /*********************************************************************** |
2 | |
3 | FONCTION : |
4 | ---------- |
5 | File OpenGl_togl_texture.c : |
6 | |
7 | |
8 | REMARQUES: |
9 | ---------- |
10 | |
11 | |
12 | HISTORIQUE DES MODIFICATIONS : |
13 | -------------------------------- |
14 | 05-08-97 : PCT ; Support texture mapping |
15 | ajout pour deuxieme passe du texture mapping |
16 | |
17 | ************************************************************************/ |
18 | |
19 | #define G003 /* EUG 16-09-99 ZBufferAuto treatment |
20 | */ |
21 | |
22 | /*----------------------------------------------------------------------*/ |
23 | /* |
24 | * Includes |
25 | */ |
26 | |
27 | #include <OpenGl_tgl_all.hxx> |
28 | |
29 | #include <stddef.h> |
30 | #include <stdio.h> |
31 | |
32 | #include <OpenGl_cmn_varargs.hxx> |
33 | #include <OpenGl_tsm.hxx> |
34 | #include <OpenGl_tsm_ws.hxx> |
35 | #include <OpenGl_Memory.hxx> |
36 | |
37 | static MtblPtr TsmMtblArray[TelLast]; |
38 | |
39 | /* Fixed Header info for a structure */ |
40 | struct TSM_HEAD_STRUCT |
41 | { |
42 | Tint num; /* number of elements present */ |
43 | }; |
44 | typedef TSM_HEAD_STRUCT TSM_HEAD; |
45 | typedef TSM_HEAD_STRUCT* tsm_head; |
46 | |
47 | /* The head of the list when the structure is in the form of a list */ |
48 | struct TSM_LHEAD_STRUCT |
49 | { |
50 | tsm_node next; // first list node |
51 | tsm_node prev; // last list node for reverse iteration |
52 | TSM_HEAD header; |
53 | }; |
54 | typedef TSM_LHEAD_STRUCT TSM_LHEAD; |
55 | typedef TSM_LHEAD_STRUCT *tsm_lhead; |
56 | |
57 | /* A Structure having fixed header and variable list of elements */ |
58 | struct TSM_STRUCT_STRUCT |
59 | { |
60 | TSM_LHEAD elemListHead; |
61 | IMPLEMENT_MEMORY_OPERATORS |
62 | }; |
63 | typedef TSM_STRUCT_STRUCT TSM_STRUCT; |
64 | typedef TSM_STRUCT_STRUCT *tsm_struct; |
65 | |
66 | #define TsmStructureNotOpen -1 |
67 | #define TsmInvalidStructure -1 |
68 | |
69 | /* Context maintained for the currently open structure */ |
70 | struct TSM_CONTEXT_STRUCT |
71 | { |
72 | Tint stid; /* Current Open Structure */ |
73 | Tint ind; /* Current Element Index */ |
74 | /* = TsmStructureNotOpen if no structure currently open */ |
75 | tsm_struct s; /* Current Structure Pointer */ |
76 | tsm_node n; /* Current Element list node */ |
77 | }; |
78 | typedef TSM_CONTEXT_STRUCT TSM_CONTEXT; |
79 | typedef TSM_CONTEXT_STRUCT* tsm_context; |
80 | |
81 | static TSM_CONTEXT context = { TsmInvalidStructure, TsmStructureNotOpen, 0, 0 }; |
82 | |
83 | static TEditMode edit_mode; |
84 | |
85 | #define TSM_HTBL_SIZE 251 |
86 | typedef NCollection_List<TSM_NODE*> NodeList; |
87 | typedef NCollection_DataMap<Tint, TSM_STRUCT*> StructMap; |
88 | Handle(NCollection_BaseAllocator) _Allocator = NCollection_BaseAllocator::CommonBaseAllocator(); |
89 | static StructMap _StructMap( 1, _Allocator ); |
90 | |
91 | |
92 | |
93 | /* Global workstation variable */ |
94 | Tint TglActiveWs; /* valid only during traversals */ |
95 | |
96 | void |
97 | TsmInitAllClasses( MtblPtr (**tbl)(TelType*), Tint size ) |
98 | { |
99 | register Tint i; |
100 | TelType el; |
101 | register MtblPtr fp; |
102 | |
103 | for( i=0; i<size; i++ ) |
104 | { |
105 | fp = tbl[i](&el); |
106 | TsmMtblArray[el] = fp; |
107 | } |
108 | return; |
109 | } |
110 | |
111 | /* This function invokes the required method of the element type by looking |
112 | up an array of Method Tables of each element. |
113 | The arguments passed to the method are the data of the element and any |
114 | other data that needs to be sent. |
115 | In the case of ADD_TO_STRUCTURE methods, data should be the address of the |
116 | element data. Other wise, it is the element data itself |
117 | */ |
118 | |
119 | TStatus |
120 | TsmSendMessage( TelType el, TMsgType msg, TSM_ELEM_DATA data, Tint n, ... ) |
121 | { |
122 | #if defined (SOLARIS) || defined (IRIXO32) |
123 | cmn_key *k; |
124 | #else |
125 | cmn_key k[TMaxArgs]; |
126 | |
127 | // Nullifies 0-th element of the "k" array |
128 | // because it might be used in a UserDraw function |
129 | // to get information on view ID, for example. |
130 | k[0] = NULL; |
131 | // Uncomment the code below if you caught |
132 | // exception because of k[1] is NULL. |
133 | // Nullifies the whole array of "k" |
134 | //int i = TMaxArgs; |
135 | //while (--i) |
136 | // k[i] = NULL; |
137 | |
138 | #endif |
139 | TStatus TheStatus = TSuccess; |
140 | |
141 | CMN_GET_STACK( n, k ); |
142 | |
143 | if( TsmMtblArray[el] && TsmMtblArray[el][msg] ) |
144 | TheStatus = TsmMtblArray[el][msg]( data, n, k ); |
145 | return TheStatus; |
146 | } |
147 | |
148 | static void |
149 | TsmFreeList( tsm_struct s ) |
150 | { |
151 | if ( !s ) |
152 | return; |
153 | |
154 | if( _Allocator.IsNull() ) |
155 | return ; |
156 | |
157 | tsm_node node, prev; |
158 | Tint num, i; |
159 | |
160 | num = s->elemListHead.header.num; |
161 | node = s->elemListHead.next; |
162 | |
163 | for( i=0; i<num; i++ ) |
164 | { |
165 | TsmSendMessage( node->elem.el, Delete, node->elem.data, 0 ); |
166 | prev = node; |
167 | node = node->next; |
168 | delete prev; |
169 | } |
170 | |
171 | s->elemListHead.next = s->elemListHead.prev = (tsm_node)&(s->elemListHead); |
172 | s->elemListHead.header.num = 0; |
173 | return; |
174 | } |
175 | |
176 | TStatus |
177 | TsmOpenStructure( Tint stid ) |
178 | { |
179 | tsm_struct s = 0; |
180 | |
181 | if( _Allocator.IsNull() ) |
182 | return TFailure; |
183 | |
184 | if( context.ind != TsmStructureNotOpen ) |
185 | return TFailure; /* Some structure already open */ |
186 | |
187 | if ( !_StructMap.IsBound(stid) ){ |
188 | s = new TSM_STRUCT(); |
189 | if ( !s ) |
190 | return TFailure; // Memory allocation failed |
191 | |
192 | _StructMap.Bind( stid, s ); |
193 | s->elemListHead.next = s->elemListHead.prev = (tsm_node)&(s->elemListHead); |
194 | s->elemListHead.header.num = 0; |
195 | } |
196 | |
197 | s = _StructMap.Find(stid); |
198 | |
199 | context.s = s; |
200 | context.stid = stid; |
201 | // Make the context point at the last node of the structure, |
202 | // this is the list head in case of an empty structure |
203 | context.ind = s->elemListHead.header.num; |
204 | context.n = s->elemListHead.prev; |
205 | |
206 | /* Ajout CAL, 14/09/95 */ |
207 | /* on force l'update_state de toutes les wks a TNotDone */ |
208 | TsmInitUpdateState (); |
209 | |
210 | return TSuccess; |
211 | } |
212 | |
213 | TStatus |
214 | TsmCloseStructure() |
215 | { |
216 | if( context.ind == TsmStructureNotOpen ) |
217 | return TFailure; /* No structure currently open */ |
218 | |
219 | context.ind = TsmStructureNotOpen; |
220 | |
221 | return TSuccess; |
222 | } |
223 | |
224 | |
225 | TStatus |
226 | TsmDisplayStructure( Tint stid, Tint wsid ) |
227 | { |
228 | TSM_ELEM_DATA data; |
229 | CMN_KEY key; |
230 | |
231 | TglActiveWs = wsid; |
232 | |
233 | if( context.ind != TsmStructureNotOpen ) |
234 | return TFailure; /* Some structure currently open */ |
235 | |
236 | key.id = wsid; |
237 | data.ldata = stid; |
238 | TsmSendMessage( TelExecuteStructure, DisplayTraverse, data, 1, &key ); |
239 | |
240 | return TSuccess; |
241 | } |
242 | |
243 | TStatus |
244 | TsmPrintStructure( Tint stid ) |
245 | { |
246 | tsm_node node; |
247 | Tint i, num; |
248 | tsm_struct s; |
249 | |
250 | if( context.ind != TsmStructureNotOpen ) |
251 | return TFailure; /* Some structure currently open */ |
252 | |
253 | if ( _StructMap.IsEmpty() ) |
254 | return TFailure; /* No structure created yet */ |
255 | |
256 | /* Obtain structure pointer from hash table */ |
257 | if ( !_StructMap.IsBound(stid) ) |
258 | return TFailure; /* Non-existent structure */ |
259 | |
260 | s = _StructMap.Find(stid); |
261 | |
262 | printf( "\nPRINT:" ); |
263 | printf( "\n\tSTRUCTURE ID = %d", stid ); |
264 | if( !s ){ |
265 | num = 0; |
266 | node = 0; |
267 | } |
268 | else{ |
269 | num = s->elemListHead.header.num; |
270 | node = s->elemListHead.next; |
271 | } |
272 | |
273 | printf( "\n\tNUMBER OF ELEMENTS = %d", num); |
274 | printf( "\n" ); |
275 | |
276 | /* For each element Send Message Print */ |
277 | for( i = 0; i < num; i++ ){ |
278 | printf("\n\tElement[%d] : ", i+1); |
279 | TsmSendMessage( node->elem.el, Print, node->elem.data, 0 ); |
280 | node = node->next; |
281 | } |
282 | |
283 | return TSuccess; |
284 | } |
285 | |
286 | TStatus |
287 | TsmAddToStructure( TelType el, Tint n, ... ) |
288 | { |
289 | TSM_ELEM_DATA data; |
290 | #if defined (SOLARIS) || defined (IRIXO32) |
291 | cmn_key *k; |
292 | #else |
293 | cmn_key k[TMaxArgs]; |
294 | #endif |
295 | |
296 | if( context.ind == TsmStructureNotOpen ) |
297 | return TFailure; /* No structure currently open */ |
298 | |
299 | CMN_GET_STACK( n, k ); |
300 | data.pdata = &data; |
301 | if( TsmSendMessage( el, Add, data, -n, k ) == TFailure ) |
302 | return TFailure; |
303 | |
304 | if( edit_mode == TEditReplace ){ |
305 | TsmSendMessage( context.n->elem.el, Delete, context.n->elem.data, 0 ); |
306 | } |
307 | else{ |
308 | tsm_node node = new TSM_NODE(); |
309 | |
310 | if( !node ) |
311 | return TFailure; |
312 | |
313 | /* insert the node in the linked list after the current node */ |
314 | node->prev = context.n; |
315 | node->next = context.n->next; |
316 | context.n->next = node; |
317 | node->next->prev = node; |
318 | |
319 | /* Make this node as current node */ |
320 | context.n = node; |
321 | context.ind++; |
322 | |
323 | /* Increment the no of elements */ |
324 | context.s->elemListHead.header.num++; |
325 | } |
326 | |
327 | context.n->elem.el = el; |
328 | context.n->elem.data = data; |
329 | |
330 | return TSuccess; |
331 | } |
332 | |
333 | TStatus |
334 | TsmDeleteStructure( Tint stid ) |
335 | { |
336 | if( context.ind != TsmStructureNotOpen && context.stid == stid ) |
337 | return TFailure; /* Same structure currently open */ |
338 | |
339 | if ( _StructMap.IsEmpty() ) |
340 | return TFailure; /* No structure created yet */ |
341 | |
342 | if ( !_StructMap.IsBound(stid) ) |
343 | return TFailure; /* Non-existent structure */ |
344 | |
345 | tsm_struct s = _StructMap.ChangeFind(stid); |
346 | |
347 | if( stid == context.stid ){ |
348 | context.stid = TsmInvalidStructure; |
349 | // Ensure the context doesn't point to freed memory |
350 | context.s = 0; |
351 | context.n = 0; |
352 | } |
353 | |
354 | if( s ){ |
355 | TsmFreeList( s ); |
356 | |
357 | /* Free structure memory */ |
358 | delete s; |
359 | } |
360 | |
361 | /* Remove hash table entry */ |
362 | _StructMap.UnBind( stid ); |
363 | |
364 | /* Ajout BGN, 27/05/97 */ |
365 | /* on force l'update_state de toutes les wks a TNotDone */ |
366 | TsmInitUpdateState (); |
367 | |
368 | return TSuccess; |
369 | } |
370 | |
371 | TEditMode |
372 | TsmSetEditMode( TEditMode mode ) |
373 | { |
374 | TEditMode m; |
375 | |
376 | m = edit_mode; |
377 | |
378 | /* Set static variable for mode */ |
379 | edit_mode = mode; |
380 | |
381 | /* return previous mode */ |
382 | return m; |
383 | } |
384 | |
385 | TStatus |
386 | TsmDeleteElement() |
387 | { |
388 | tsm_node node; |
389 | |
390 | if( context.ind == TsmStructureNotOpen ) |
391 | return TFailure; /* No structure currently open */ |
392 | |
393 | // Zero ind means the currently open structure is empty |
394 | // or the current node is the list head -> nothing to delete |
395 | // See also TsmSetElementPointer() |
396 | if( !context.ind ) |
397 | return TFailure; |
398 | |
399 | /* Send message DELETE element */ |
400 | TsmSendMessage( context.n->elem.el, Delete, context.n->elem.data, 0 ); |
401 | |
402 | node = context.n; |
403 | node->prev->next = node->next; |
404 | node->next->prev = node->prev; |
405 | |
406 | /* make previous node as current node */ |
407 | context.n = node->prev; |
408 | context.ind--; |
409 | |
410 | /* Decrement the no of elements */ |
411 | context.s->elemListHead.header.num--; |
412 | |
413 | /* free the linked list node */ |
414 | delete node; |
415 | |
416 | return TSuccess; |
417 | } |
418 | |
419 | TStatus |
420 | TsmDeleteElementsBetweenLabels( Tint label_id1, Tint label_id2 ) |
421 | /* label_id1 & label_id2 exclusive */ |
422 | { |
423 | Tint elem1, elem2; |
424 | |
425 | if( context.ind == TsmStructureNotOpen ) |
426 | return TFailure; /* No structure currently open */ |
427 | |
428 | TsmSetElementPointer( 0 ); |
429 | |
430 | if( TsmSetElementPointerAtLabel( label_id1 ) == TFailure) |
431 | return TFailure; |
432 | elem1 = context.ind; |
433 | |
434 | if( TsmSetElementPointerAtLabel( label_id2 ) == TFailure) |
435 | return TFailure; |
436 | elem2 = context.ind; |
437 | |
438 | TsmDeleteElementRange( elem1, elem2 ); |
439 | |
440 | return TSuccess; |
441 | } |
442 | |
443 | TStatus |
444 | TsmDeleteElementRange( Tint elem1, Tint elem2 ) /* elem1 & elem2 exclusive */ |
445 | { |
446 | if( context.ind == TsmStructureNotOpen ) |
447 | return TFailure; /* No structure currently open */ |
448 | |
449 | TsmSetElementPointer( elem2 - 1 ); |
450 | while( context.ind != elem1 && context.ind ) |
451 | TsmDeleteElement(); |
452 | |
453 | return TSuccess; |
454 | } |
455 | |
456 | TStatus |
457 | TsmSetElementPointer( Tint index ) |
458 | { |
459 | if( context.ind == TsmStructureNotOpen ) |
460 | return TFailure; /* No structure currently open */ |
461 | |
462 | /* Set static variable accordingly */ |
463 | if( context.ind == index ){ |
464 | return TSuccess; |
465 | } |
466 | if( index >= context.s->elemListHead.header.num ){ |
467 | index = context.s->elemListHead.header.num; |
468 | context.n = context.s->elemListHead.prev; |
469 | } |
470 | else if( index <= 0 ){ |
471 | index = 0; |
472 | context.n = (tsm_node)&(context.s->elemListHead); |
473 | } |
474 | else{ |
475 | Tint a, b, c, d; |
476 | tsm_node node; |
477 | |
478 | a = index - 0; |
479 | b = context.ind - index; if( b < 0 ) b = -b; /* b = labs(b) */ |
480 | c = context.s->elemListHead.header.num - index; |
481 | d = ( a < b ) ? ( a < c ? a : c ) : ( b < c ? b : c ) ; |
482 | |
483 | if( a == d ){ |
484 | /* Traverse from head in forward direction */ |
485 | d = index-1; |
486 | node = context.s->elemListHead.next; |
487 | while( d-- ){ |
488 | node = node->next; |
489 | } |
490 | } |
491 | else if( b == d ){ |
492 | /* Traverse from current node in appropriate direction */ |
493 | node = context.n; |
494 | d = context.ind; |
495 | if( context.ind < index ){ |
496 | while( d != index ){ |
497 | node = node->next; |
498 | d++; |
499 | } |
500 | } |
501 | else{ |
502 | while( d != index ){ |
503 | node = node->prev; |
504 | d--; |
505 | } |
506 | } |
507 | } |
508 | else{ /* ( c == d ) */ |
509 | /* Traverse from head in backward direction */ |
510 | d = context.s->elemListHead.header.num; |
511 | node = context.s->elemListHead.prev; |
512 | while( d != index ){ |
513 | node = node->prev; |
514 | d--; |
515 | } |
516 | } |
517 | |
518 | context.n = node; |
519 | } |
520 | |
521 | context.ind = index; |
522 | |
523 | return TSuccess; |
524 | } |
525 | |
526 | |
527 | TStatus |
528 | TsmSetElementPointerAtLabel( Tint label_id ) |
529 | { |
530 | Tint i, num; |
531 | tsm_node node; |
532 | |
533 | if( context.ind == TsmStructureNotOpen ) |
534 | return TFailure; /* No structure currently open */ |
535 | |
536 | num = context.s->elemListHead.header.num; |
537 | for( i=context.ind+1, node=context.n->next; i<=num; i++, node=node->next ){ |
538 | if( node->elem.el == TelLabel && node->elem.data.ldata == label_id ){ |
539 | context.ind = i; |
540 | context.n = node; |
541 | return TSuccess; |
542 | } |
543 | } |
544 | |
545 | return TFailure; |
546 | } |
547 | |
548 | TStatus |
549 | TsmOffsetElementPointer( Tint offset ) |
550 | { |
551 | return TsmSetElementPointer( context.ind + offset ); |
552 | } |
553 | |
554 | TStatus |
555 | TsmGetStructure( Tint stid, Tint *num, tsm_node *n ) |
556 | { |
557 | if ( _StructMap.IsEmpty() ) |
558 | return TFailure; /* No structure created yet */ |
559 | |
560 | if ( !_StructMap.IsBound(stid) ) |
561 | return TFailure; /* Non-existent structure */ |
562 | |
563 | tsm_struct s = _StructMap.Find(stid); |
564 | |
565 | *num = s ? s->elemListHead.header.num : 0; |
566 | // Here we cannot return a pointer to the structure's list head, |
567 | // as it will wrongly interpreted as a regular pointer to TSM_NODE, |
568 | // thus returning null pointer - this should be checked by callers! |
569 | *n = s ? s->elemListHead.next : 0; |
570 | |
571 | return TSuccess; |
572 | } |
573 | |
574 | static TStatus |
575 | GetDepth( Tint stid, Tint *depth ) |
576 | { |
577 | tsm_struct s; |
578 | Tint i, d, b, num; |
579 | |
580 | if ( _StructMap.IsEmpty() ) |
581 | return TFailure; /* No structure created yet */ |
582 | |
583 | if ( !_StructMap.IsBound(stid) ) |
584 | return TFailure; /* Non-existent structure */ |
585 | |
586 | s = _StructMap.Find(stid); |
587 | |
588 | (*depth)++; |
589 | d = b = *depth; |
590 | |
591 | if( s ){ |
592 | num = s->elemListHead.header.num; |
593 | tsm_node node = s->elemListHead.next; |
594 | for( i = 0; i < num; i++ ){ |
595 | if( node->elem.el == TelExecuteStructure ){ |
596 | GetDepth( node->elem.data.ldata, &d ); |
597 | if( *depth < d ) |
598 | *depth = d; |
599 | } |
600 | d = b; |
601 | node = node->next; |
602 | } |
603 | } |
604 | |
605 | return TSuccess; |
606 | } |
607 | |
608 | |
609 | TStatus |
610 | TsmGetStructureDepth( Tint stid, Tint *depth ) |
611 | { |
612 | *depth = 0; |
613 | |
614 | GetDepth( stid, depth ); |
615 | return TSuccess; |
616 | } |
617 | |
618 | TStatus |
619 | TsmGetCurElem( TSM_ELEM *elem ) |
620 | { |
621 | // Zero ind means no current element |
622 | if( context.ind == TsmStructureNotOpen || |
623 | !context.ind ) |
624 | return TFailure; |
625 | |
626 | *elem = context.n->elem; |
627 | return TSuccess; |
628 | } |
629 | |
630 | TStatus |
631 | TsmGetCurElemPtr( Tint *ptr ) |
632 | { |
633 | // Zero ind means no current element |
634 | if( context.ind == TsmStructureNotOpen || |
635 | !context.ind ) |
636 | return TFailure; |
637 | |
638 | *ptr = context.ind; |
639 | return TSuccess; |
640 | } |