1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10
11 #if defined(HAVE_STRING_H)
12 #include <string.h>
13 #endif
14
15 #include "hwDeclarations.h"
16 #include "hwXfield.h"
17 #include "hwMatrix.h"
18 #include "hwMemory.h"
19 #include "hwPortLayer.h"
20 #include "hwWindow.h"
21 #include "hwObjectHash.h"
22
23 #define String dxString
24 #define Object dxObject
25 #define Angle dxAngle
26 #define Matrix dxMatrix
27 #define Screen dxScreen
28 #define Boolean dxBoolean
29 #include "../libdx/internals.h"
30 #undef String
31 #undef Object
32 #undef Angle
33 #undef Matrix
34 #undef Screen
35 #undef Boolean
36
37 #include "hwDebug.h"
38
39 #define FLOAT_TO_UBYTE(val) ((val)<=0.0 ? (ubyte)0.f : \
40 (val)>=1.0 ? (ubyte)255.f : (ubyte)((val)*255.0f))
41
42 typedef struct _texture
43 {
44 int width, height;
45 ubyte *pixels;
46 dxObject textureObj;
47 int myPixels;
48 int isRGBA;
49 } *Texture;
50
51 static Error _getTexture_Field(Texture);
52 static Error _getTexture_CompositeField(Texture);
53
54 static Error
_deleteTexture(Pointer p)55 _deleteTexture(Pointer p)
56 {
57 if (p)
58 {
59 Texture t = (Texture)p;
60 if (t->myPixels)
61 DXFree((Pointer)t->pixels);
62 if (t->textureObj)
63 DXDelete(t->textureObj);
64 }
65 return OK;
66 }
67
68 static dxObject
_newTexture(dxObject obj)69 _newTexture(dxObject obj)
70 {
71 dxObject txo = NULL;
72 Texture texture = (Texture)DXAllocateZero(sizeof(struct _texture));
73 if (! texture)
74 goto error;
75
76 texture->textureObj = DXReference(obj);
77
78 if (DXGetObjectClass(obj) == CLASS_FIELD)
79 {
80 if (! _getTexture_Field(texture))
81 goto error;
82 }
83 else if (DXGetObjectClass(obj) == CLASS_GROUP &&
84 DXGetGroupClass((Group)obj) == CLASS_COMPOSITEFIELD)
85 {
86 if (! _getTexture_CompositeField(texture))
87 goto error;
88 }
89 else
90 {
91 DXSetError(ERROR_DATA_INVALID, "invalid object type for texture");
92 goto error;
93 }
94
95 txo = (dxObject)DXNewPrivate((Pointer)texture, _deleteTexture);
96 if (! txo)
97 goto error;
98
99 return txo;
100
101 error:
102 _deleteTexture((Pointer)texture);
103 return ERROR;
104 }
105
106 Error
_XTexture(Field f,xfieldT * xf,void * globals)107 _XTexture(Field f, xfieldT* xf, void *globals)
108 {
109 DEFGLOBALDATA(globals);
110 Type type;
111 int rank, shape[32];
112 dxObject attr, texture = _dxf_xfieldAttributes(xf)->texture;
113 dxObject txo;
114
115 if (texture)
116 {
117 Texture txp;
118
119 xf->uv_array = (Array)DXGetComponentValue(f, "uv");
120 if (! xf->uv_array)
121 {
122 DXSetError(ERROR_DATA_INVALID,
123 "texture attribute but no uv component");
124 goto error;
125 }
126
127 DXGetArrayInfo(xf->uv_array, NULL, &type, NULL, &rank, shape);
128
129 if (type != TYPE_FLOAT || rank != 1 || shape[0] != 2)
130 {
131 DXSetError(ERROR_DATA_INVALID,
132 "uv component must contain float 2-vectors");
133 goto error;
134 }
135
136 attr = DXGetAttribute((dxObject)xf->uv_array, "dep");
137 if (DXGetObjectClass(attr) != CLASS_STRING)
138 {
139 DXSetError(ERROR_DATA_INVALID,
140 "uv dep attribute must be a DXString object");
141 goto error;
142 }
143
144 if (strcmp(DXGetString((dxString)attr), "positions"))
145 {
146 DXSetError(ERROR_DATA_INVALID,
147 "uv must be dep on positions");
148 goto error;
149 }
150
151 xf->uv = DXCreateArrayHandle(xf->uv_array);
152 if (! xf->uv)
153 goto error;
154
155 DXReference((dxObject)xf->uv_array);
156
157 txo = _dxf_QueryObject(TEXTUREHASH, texture);
158 if (! txo)
159 {
160 txo = _newTexture(texture);
161 if (! txo)
162 goto error;
163
164 _dxf_InsertObject(TEXTUREHASH, texture, txo);
165 }
166
167 xf->texture_field = DXReference(txo);
168 txp = (Texture)DXGetPrivateData((Private)txo);
169
170 xf->textureWidth = txp->width;
171 xf->textureHeight = txp->height;
172 xf->texture = txp->pixels;
173 xf->textureIsRGBA = txp->isRGBA;
174
175 if ( xf->textureIsRGBA )
176 /* Set flag so primitives will be added to transparent SORTLIST */
177 _dxf_setFlags(_dxf_attributeFlags(_dxf_xfieldAttributes(xf)),
178 CONTAINS_TRANSPARENT_TEXTURE);
179 }
180 else
181 {
182 xf->texture_field = NULL;
183 xf->uv_array = NULL;
184 xf->texture = NULL;
185 }
186
187 return OK;
188
189 error:
190 if (xf->texture_field)
191 DXDelete((dxObject)xf->texture_field);
192 if (xf->uv_array)
193 DXDelete((dxObject)xf->uv_array);
194
195 xf->texture_field = NULL;
196 xf->texture = NULL;
197 xf->uv_array = NULL;
198 xf->uv = NULL;
199 xf->myTextureData = 0;
200
201 return ERROR;
202 }
203
204 static Error
_expandColorMap(Field tf,ubyte cmap[768])205 _expandColorMap(Field tf, ubyte cmap[768] )
206 /* Extract the color map and convert to ubyte[3] format */
207 {
208 Type type;
209 int i, n, rank, shape[32];
210 Array array;
211
212 array = (Array)DXGetComponentValue(tf, "color map");
213 if (! array)
214 {
215 DXSetError(ERROR_MISSING_DATA,
216 "texture map has indexed colors but is missing color map");
217 goto error;
218 }
219
220 DXGetArrayInfo(array, &n, &type, NULL, &rank, shape);
221
222 if ( n > 256 )
223 {
224 DXSetError(ERROR_MISSING_DATA,
225 "texture map's color map has more than 256 entries");
226 goto error;
227 }
228
229 if (type == TYPE_FLOAT && rank == 1 && shape[0] == 3)
230 {
231 float *map_src = (float *)DXGetArrayData(array);
232
233 for (i = 0; i < 3*n; i++)
234 {
235 float c = *map_src++;
236 cmap[i] = FLOAT_TO_UBYTE(c);
237 }
238 }
239 else if (type == TYPE_UBYTE && rank == 1 && shape[0] == 3)
240 {
241 memcpy( cmap, (ubyte *)DXGetArrayData(array), 3*n );
242 }
243 else
244 {
245 DXSetError(ERROR_DATA_INVALID,
246 "texture has invalid color map type "
247 "(must be float or ubyte 3-vectors)");
248 goto error;
249 }
250
251 return OK;
252
253 error:
254 return ERROR;
255 }
256
257
258 static Error
_expandOpacityMap(Field tf,ubyte omap[256])259 _expandOpacityMap(Field tf, ubyte omap[256] )
260 /* Extract the opacity map and convert to ubyte format */
261 {
262 Type type;
263 int i, n, rank, shape[32];
264 Array array;
265
266 array = (Array)DXGetComponentValue(tf, "opacity map");
267 if (! array)
268 {
269 DXSetError(ERROR_MISSING_DATA,
270 "indirect texture map missing opacity map component");
271 goto error;
272 }
273
274 DXGetArrayInfo(array, &n, &type, NULL, &rank, shape);
275
276 if ( n > 256 )
277 {
278 DXSetError(ERROR_MISSING_DATA,
279 "texture map's opacity map has more than 256 entries");
280 goto error;
281 }
282
283 if ( (type == TYPE_FLOAT &&
284 (rank == 0 || (rank == 1 && shape[0] == 1) )) )
285 {
286 float *map_src = (float *)DXGetArrayData(array);
287
288 for (i = 0; i < n; i++)
289 {
290 float o = *map_src++;
291 omap[i] = FLOAT_TO_UBYTE(o);
292 }
293 }
294 else
295 {
296 DXSetError(ERROR_DATA_INVALID,
297 "texture has invalid opacity map type "
298 "(must be float scalars)");
299 goto error;
300 }
301
302 return OK;
303
304 error:
305 return ERROR;
306 }
307
308
309 static Error
_getTexture_Field(Texture t)310 _getTexture_Field(Texture t)
311 {
312 Type type, o_type;
313 Category cat , o_cat;
314 int n, o_n, rank, o_rank, shape[32], o_shape[32];
315 int counts[2];
316 Array tmp,colors,opac;
317 int i;
318 Field tf = (Field)t->textureObj;
319
320 t->pixels = NULL;
321 t->myPixels = 0;
322
323 tmp = (Array)DXGetComponentValue(tf, "connections");
324 if (! tmp)
325 {
326 DXSetError(ERROR_DATA_INVALID,
327 "texture field has no connections");
328 goto error;
329 }
330
331 if (! DXQueryGridConnections(tmp, &n, counts))
332 {
333 DXSetError(ERROR_DATA_INVALID,
334 "texture field must have regular connections");
335 goto error;
336 }
337
338 if (n != 2)
339 {
340 DXSetError(ERROR_DATA_INVALID,
341 "texture field must be 2-d regular connections");
342 goto error;
343 }
344
345 t->width = counts[1];
346 t->height = counts[0];
347
348 colors = (Array)DXGetComponentValue(tf, "colors");
349 if (! colors)
350 colors = (Array)DXGetComponentValue(tf, "data");
351 if (! colors)
352 {
353 DXSetError(ERROR_DATA_INVALID,
354 "texture has neither colors nor data");
355 return ERROR;
356 }
357 DXGetArrayInfo(colors, &n, &type, &cat, &rank, shape);
358
359 opac = (Array)DXGetComponentValue(tf, "opacities");
360 if ( opac ) {
361 DXGetArrayInfo(opac, &o_n, &o_type, &o_cat, &o_rank, o_shape);
362 if ( o_n != n ) {
363 DXSetError(ERROR_MISSING_DATA,
364 "length of color and opacity components do not match");
365 goto error;
366 }
367 }
368
369 /* Handle ubyte[3] colors (w/ optional float opacities) */
370 if (type == TYPE_UBYTE && rank == 1 && shape[0] == 3)
371 {
372 if ( !opac ) {
373 t->pixels = (ubyte *)DXGetArrayData(colors);
374 t->isRGBA = 0;
375 t->myPixels = 0;
376 }
377 else {
378 if (! (o_type == TYPE_FLOAT &&
379 (o_rank == 0 || (o_rank == 1 && o_shape[0] == 1) )) ) {
380 DXSetError(ERROR_MISSING_DATA,
381 "opacities for a direct color texture map must be float");
382 goto error;
383 }
384 {
385 ubyte *dst, *c_src = (ubyte *)DXGetArrayData(colors);
386 float *o_src = (float *)DXGetArrayData(opac);
387 t->pixels = (ubyte *)tdmAllocate(4*n*sizeof(ubyte));
388 dst = t->pixels;
389
390 for (i = 0; i < n; i++) {
391 float opacity = *(o_src++);
392 *(dst++) = *(c_src++);
393 *(dst++) = *(c_src++);
394 *(dst++) = *(c_src++);
395 *(dst++) = FLOAT_TO_UBYTE(opacity);
396 }
397 t->isRGBA = 1;
398 t->myPixels = 1;
399 }
400 }
401 }
402 else
403 {
404 int Bpp = opac ? 4 : 3;
405 t->pixels = (ubyte *)tdmAllocate(Bpp*n*sizeof(ubyte));
406 if (! t->pixels)
407 goto error;
408 t->myPixels = 1;
409
410 /* Handle float[3] colors (w/ optional float opacities) */
411 if (type == TYPE_FLOAT && rank == 1 && shape[0] == 3)
412 {
413 int i;
414 ubyte *dst = t->pixels;
415 float *c_src = (float *)DXGetArrayData(colors);
416 float *o_src = NULL;
417
418 if ( opac ) {
419 o_src = (float *)DXGetArrayData(opac);
420 if ( ! (o_type == TYPE_FLOAT &&
421 (o_rank == 0 || (o_rank == 1 && o_shape[0] == 1) )) ) {
422 DXSetError(ERROR_MISSING_DATA,
423 "opacities for a direct color texture map must be float");
424 goto error;
425 }
426 Bpp = 4;
427 }
428
429 t->isRGBA = opac != NULL;
430
431 for (i = 0; i < n; i++)
432 {
433 float c, o;
434 c = *c_src++, *dst++ = FLOAT_TO_UBYTE(c);
435 c = *c_src++, *dst++ = FLOAT_TO_UBYTE(c);
436 c = *c_src++, *dst++ = FLOAT_TO_UBYTE(c);
437 if ( opac )
438 o = *o_src++, *dst++ = FLOAT_TO_UBYTE(o);
439 }
440 }
441
442 /* Handle ubyte colors w/ float[3] or ubyte[3] colormap */
443 /* (w/ optional ubyte opacities with float opacity map) */
444 else if (type == TYPE_UBYTE &&
445 (rank == 0 || (rank == 1 && shape[0] == 1) ))
446 {
447 int i;
448 ubyte *dst = t->pixels;
449 ubyte *c_src = (ubyte *)DXGetArrayData(colors);
450 ubyte *o_src = NULL;
451 ubyte cmap[768], omap[256];
452
453 if (!_expandColorMap(tf, cmap))
454 goto error;
455
456 if ( opac ) {
457 if ( !(o_type == TYPE_UBYTE &&
458 (o_rank == 0 || (o_rank == 1 && o_shape[0] == 1) )) ) {
459 DXSetError(ERROR_MISSING_DATA,
460 "indirect texture map opacities must be scalar ubytes");
461 goto error;
462 }
463 if ( !_expandOpacityMap(tf, omap))
464 goto error;
465
466 o_src = (ubyte *)DXGetArrayData(opac);
467 }
468
469 for (i = 0; i < n; i++)
470 {
471 ubyte *c = cmap + 3 * *c_src++;
472 *dst++ = *c++;
473 *dst++ = *c++;
474 *dst++ = *c++;
475 if ( opac )
476 *dst++ = omap[ *o_src++ ];
477 }
478 t->isRGBA = opac != NULL;
479 }
480 else
481 {
482 DXSetError(ERROR_DATA_INVALID,
483 "Bad texture found. Texture must contain float or ubyte "
484 "3-vector colors (with optional float opacities), OR contain "
485 "scalar ubyte colors with a float or ubyte 3-vector color map "
486 "(with optional ubyte opacities and a float opacity map)");
487 goto error;
488 }
489 }
490
491 return OK;
492
493 error:
494 if ( t->pixels && t->myPixels ) {
495 DXFree((Pointer)t->pixels);
496 t->pixels = NULL;
497 t->myPixels = 0;
498 }
499 return ERROR;
500 }
501
502 static Error
_getTexture_CompositeField(Texture t)503 _getTexture_CompositeField(Texture t)
504 {
505 Type type, o_type;
506 Category cat, o_cat;
507 int n, o_n, rank, o_rank, shape[32], o_shape[32], counts[2];
508 int i, Bpp;
509 Group cf = (Group)t->textureObj;
510 Field member;
511 int nMembers;
512
513 t->pixels = NULL;
514 t->myPixels = 0;
515
516 DXGetMemberCount(cf, &nMembers);
517 if ( nMembers == 0 ) {
518 DXSetError(ERROR_DATA_INVALID,
519 "composite texture field has no members");
520 goto error;
521 }
522
523 counts[0] = counts[1] = 0;
524
525 /* Verify all members are regular 2D grids, and calc cumulative size */
526 for (i = 0; i < nMembers; i++)
527 {
528 Array grid;
529 int memberCounts[2], memberOffsets[2], nDim, cnt;
530
531 member = (Field)DXGetEnumeratedMember(cf, i, NULL);
532 grid = (Array)DXGetComponentValue(member, "connections");
533
534 if (!DXQueryGridConnections(grid, &nDim, memberCounts) ||
535 !DXGetMeshOffsets((MeshArray)grid, memberOffsets))
536 {
537 DXSetError(ERROR_DATA_INVALID,
538 "texture field must have regular connections");
539 goto error;
540 }
541
542 if (nDim != 2)
543 {
544 DXSetError(ERROR_DATA_INVALID, "texture fields must be 2-D");
545 goto error;
546 }
547
548 if ((cnt = memberOffsets[0] + memberCounts[0]) > counts[0])
549 counts[0] = cnt;
550
551 if ((cnt = memberOffsets[1] + memberCounts[1]) > counts[1])
552 counts[1] = cnt;
553
554 }
555 t->width = counts[1];
556 t->height = counts[0];
557
558 n = counts[0] * counts[1];
559
560 /* Allocate texture buffer */
561 member = (Field)DXGetEnumeratedMember(cf, 0, NULL);
562 t->isRGBA = (DXGetComponentValue(member, "opacities") != NULL);
563 Bpp = t->isRGBA ? 4 : 3;
564 t->pixels = (ubyte *)tdmAllocate(Bpp*n*sizeof(ubyte));
565 if (! t->pixels)
566 goto error;
567 t->myPixels = 1;
568
569 /* Copy colors/opacities from each member into the texture buffer */
570 for (i = 0; i < nMembers; i++)
571 {
572 Array colors,opac;
573 Array grid;
574 int memberCounts[2], memberOffsets[2];
575
576 member = (Field)DXGetEnumeratedMember(cf, i, NULL);
577 grid = (Array)DXGetComponentValue(member, "connections");
578
579 colors = (Array)DXGetComponentValue(member, "colors");
580 if (! colors)
581 colors = (Array)DXGetComponentValue(member, "data");
582 if (! colors)
583 {
584 DXSetError(ERROR_DATA_INVALID,
585 "texture has neither colors nor data");
586 return ERROR;
587 }
588 DXGetArrayInfo(colors, NULL, &type, &cat, &rank, shape);
589
590 opac = (Array)DXGetComponentValue(member, "opacities");
591 if ( opac ) {
592 DXGetArrayInfo(opac, &o_n, &o_type, &o_cat, &o_rank, o_shape);
593 if ( o_n != n ) {
594 DXSetError(ERROR_MISSING_DATA,
595 "length of color and opacity components do not match");
596 goto error;
597 }
598 }
599
600
601 DXQueryGridConnections(grid, NULL, memberCounts);
602 DXGetMeshOffsets((MeshArray)grid, memberOffsets);
603
604 /* Handle ubyte[3] colors (w/ optional float opacities) */
605 if (type == TYPE_UBYTE && rank == 1 && shape[0] == 3)
606 {
607 int j, k;
608 ubyte *c_src = (ubyte *)DXGetArrayData(colors);
609 float *o_src = NULL;
610 ubyte *dst = t->pixels + Bpp*((memberOffsets[0]*counts[1])
611 + memberOffsets[1]);
612 int dst_stride = Bpp*(counts[1] - memberCounts[1]);
613
614 if ( opac ) {
615 if (! (o_type == TYPE_FLOAT &&
616 (o_rank == 0 || (o_rank == 1 && o_shape[0] == 1) )) ) {
617 DXSetError(ERROR_MISSING_DATA,
618 "opacities for a direct color texture map must be float");
619 goto error;
620 }
621 o_src = (float *)DXGetArrayData(opac);
622 }
623
624 for (j = 0; j < memberCounts[0]; j++)
625 {
626 for (k = 0; k < memberCounts[1]; k++)
627 {
628 float o;
629 *dst++ = *c_src++;
630 *dst++ = *c_src++;
631 *dst++ = *c_src++;
632 if ( opac )
633 o = *o_src++, *dst++ = FLOAT_TO_UBYTE(o);
634 }
635 dst += dst_stride;
636 }
637 }
638
639 /* Handle float[3] colors (w/ optional float opacities) */
640 else if (type == TYPE_FLOAT && rank == 1 && shape[0] == 3)
641 {
642 int j, k;
643 float *c_src = (float *)DXGetArrayData(colors);
644 float *o_src = NULL;
645 ubyte *dst = t->pixels + Bpp*((memberOffsets[0]*counts[1])
646 + memberOffsets[1]);
647 int dst_stride = Bpp*(counts[1] - memberCounts[1]);
648
649 if ( opac ) {
650 if (! (o_type == TYPE_FLOAT &&
651 (o_rank == 0 || (o_rank == 1 && o_shape[0] == 1) )) ) {
652 DXSetError(ERROR_MISSING_DATA,
653 "opacities for a direct color texture map must be float");
654 goto error;
655 }
656 o_src = (float *)DXGetArrayData(opac);
657 }
658
659 for (j = 0; j < memberCounts[0]; j++)
660 {
661 for (k = 0; k < memberCounts[1]; k++)
662 {
663 float c, o;
664 c = *c_src++, *dst++ = FLOAT_TO_UBYTE(c);
665 c = *c_src++, *dst++ = FLOAT_TO_UBYTE(c);
666 c = *c_src++, *dst++ = FLOAT_TO_UBYTE(c);
667 if ( opac )
668 o = *o_src++, *dst++ = FLOAT_TO_UBYTE(o);
669 }
670 dst += dst_stride;
671 }
672 }
673
674 /* Handle ubyte colors w/ float[3] or ubyte[3] colormap */
675 /* (w/ optional ubyte opacities with float opacity map) */
676 else if (type == TYPE_UBYTE &&
677 (rank == 0 || (rank == 1 && shape[0] == 1) ))
678 {
679 int j, k;
680 ubyte cmap[768], omap[256];
681 ubyte *c_src = (ubyte *)DXGetArrayData(colors);
682 ubyte *o_src = NULL;
683 int dst_stride = Bpp*(counts[1] - memberCounts[1]);
684 ubyte *dst = t->pixels + Bpp*((memberOffsets[0]*counts[1])
685 + memberOffsets[1]);
686
687 if (!_expandColorMap(member, cmap))
688 goto error;
689
690 if ( opac ) {
691 if ( !(o_type == TYPE_UBYTE &&
692 (o_rank == 0 || (o_rank == 1 && o_shape[0] == 1) )) ) {
693 DXSetError(ERROR_MISSING_DATA,
694 "indirect texture map opacities must be scalar ubytes");
695 goto error;
696 }
697
698 if ( !_expandOpacityMap(member, omap))
699 goto error;
700
701 o_src = (ubyte *)DXGetArrayData(opac);
702 }
703
704 for (j = 0; j < memberCounts[0]; j++)
705 {
706 for (k = 0; k < memberCounts[1]; k++)
707 {
708 ubyte *c = cmap + (3 * *c_src++);
709 *dst++ = *c++;
710 *dst++ = *c++;
711 *dst++ = *c++;
712 if ( opac )
713 *dst++ = omap[ *o_src++ ];
714 }
715 dst += dst_stride;
716 }
717 }
718 else
719 {
720 DXSetError(ERROR_DATA_INVALID,
721 "Bad texture found. Texture must contain float or ubyte "
722 "3-vector colors (with optional float opacities), OR contain "
723 "scalar ubyte colors with a float or ubyte 3-vector color map "
724 "(with optional ubyte opacities and a float opacity map)");
725 goto error;
726 }
727 }
728
729 return OK;
730
731 error:
732 if ( t->pixels && t->myPixels ) {
733 DXFree((Pointer)t->pixels);
734 t->pixels = NULL;
735 t->myPixels = 0;
736 }
737 return ERROR;
738 }
739