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
10INCLUDE3 <dxconfig.h>
11
12INCLUDE1 "triangles.h"
13INCLUDE2 "triangles.h"
14
15INCLUDE3 <string.h>
16INCLUDE3 <dx/dx.h>
17INCLUDE3 "render.h"
18INCLUDE3 "internals.h"
19
20DEFINE3 CAT(a,b) a##b
21
22
23#define QUADS(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL) { 	    $\
24									    $\
25    Point *p;								    $\
26    int v1, v2, v3, i, width, height;					    $\
27    int i1, i2, i3;							    $\
28    float ox, oy;							    $\
29    InvalidComponentHandle iElts;					    $\
30    RGBColor vcolors[8];						    $\
31    int shademe;							    $\
32    char fcst = xf->fcst, bcst = xf->bcst, ncst = xf->ncst;		    $\
33									    $\
34    iElts = (invalid_status == INV_UNKNOWN) ? xf->iElts : NULL;		    $\
35									    $\
36    width = buf->width, height = buf->height;				    $\
37    ox = buf->ox, oy = buf->oy;						    $\
38									    $\
39    if (shrgb && xf->lights) {						    $\
40	fcolors = (Pointer)vcolors;					    $\
41	bcolors = (Pointer)(vcolors+4);					    $\
42	_dxfInitApplyLights(xf->kaf, xf->kdf, xf->ksf, xf->kspf,	    $\
43			    xf->kab, xf->kdb, xf->ksb, xf->kspb,            $\
44			    xf->fcolors, xf->bcolors, xf->cmap,		    $\
45			    xf->normals, xf->lights,			    $\
46			    xf->colors_dep, xf->normals_dep,		    $\
47			    fcolors, bcolors, 4, fcst, bcst, ncst, 	    $\
48			    fbyte, bbyte);				    $\
49	cmap    = NULL;							    $\
50	shademe = 1;							    $\
51    } else {								    $\
52	shademe = 0;							    $\
53	if (fbyte || bbyte)						    $\
54	    _dxf_initUbyteToFloat();                                        $\
55    }									    $\
56									    $\
57    for (i=0; i<nquad; i++, quad++) {					    $\
58	int index = (indices == NULL) ? i : indices[i];			    $\
59									    $\
60	if (iElts && DXIsElementInvalid(iElts, index))			    $\
61	    continue;							    $\
62									    $\
63	/* points */							    $\
64	v1=quad->p, p= &xf->positions[v1], x1=p->x, y1=p->y, z1=p->z;	    $\
65	v2=quad->r, p= &xf->positions[v2], x2=p->x, y2=p->y, z2=p->z;	    $\
66	v3=quad->s, p= &xf->positions[v3], x3=p->x, y3=p->y, z3=p->z;	    $\
67									    $\
68	if (shademe)							    $\
69	{ 								    $\
70	    i1 = 0; i2 = 2; i3 = 3;					    $\
71	    if (! _dxfApplyLights((int *)quad, &index, 1))	    	    $\
72		return ERROR;						    $\
73	}								    $\
74									    $\
75	if (xf->tile.perspective) {					    $\
76	    if (z1>nearPlane || z2>nearPlane || z3>nearPlane)		    $\
77		goto CAT(LABEL,1);					    $\
78	    z1=(float)-1.0/z1;  x1*=z1;  y1*=z1;			    $\
79	    z2=(float)-1.0/z2;  x2*=z2;  y2*=z2;			    $\
80	    z3=(float)-1.0/z3;  x3*=z3;  y3*=z3;			    $\
81	}								    $\
82	if (!((x1<minx && x2<minx && x3<minx) ||			    $\
83	      (x1>maxx && x2>maxx && x3>maxx) ||			    $\
84	      (y1<miny && y2<miny && y3<miny) ||			    $\
85	      (y1>maxy && y2>maxy && y3>maxy)))				    $\
86	{								    $\
87									    $\
88	  buf->triangles++;						    $\
89	  TRIANGLEX1(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL, 1) $\
90	  TRIANGLEX2(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL, 1);$\
91	}								    $\
92									    $\
93 CAT(LABEL,1) :								    $\
94	/* points */							    $\
95	v1=quad->p, p= &xf->positions[v1], x1=p->x, y1=p->y, z1=p->z;	    $\
96	v2=quad->s, p= &xf->positions[v2], x2=p->x, y2=p->y, z2=p->z;	    $\
97	v3=quad->q, p= &xf->positions[v3], x3=p->x, y3=p->y, z3=p->z;	    $\
98									    $\
99	if (shademe) i1 = 0, i2 = 3, i3 = 1;				    $\
100									    $\
101	if (xf->tile.perspective) {					    $\
102	    if (z1>nearPlane || z2>nearPlane || z3>nearPlane)		    $\
103		continue;						    $\
104	    z1=(float)-1.0/z1;  x1*=z1;  y1*=z1;			    $\
105	    z2=(float)-1.0/z2;  x2*=z2;  y2*=z2;			    $\
106	    z3=(float)-1.0/z3;  x3*=z3;  y3*=z3;			    $\
107	}								    $\
108	if ((x1<minx && x2<minx && x3<minx) ||				    $\
109	    (x1>maxx && x2>maxx && x3>maxx) ||				    $\
110	    (y1<miny && y2<miny && y3<miny) ||				    $\
111	    (y1>maxy && y2>maxy && y3>maxy))				    $\
112		continue;						    $\
113									    $\
114	buf->triangles++;						    $\
115	TRIANGLEX1(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL, 2) $\
116	TRIANGLEX2(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL, 2);$\
117									    $\
118 CAT(LABEL,2) :								    $\
119	continue;							    $\
120    }									    $\
121}
122
123/*
124 * Quads
125 *
126 * p q
127 * r s
128 */
129
130#define TRI_QR_1 v1=quad[i].p, v2=quad[i].r, v3=quad[i].q
131#define TRI_QR_2 v1=quad[i].q, v2=quad[i].r, v3=quad[i].s
132
133#define TRI_PS_1 v1=quad[i].p, v2=quad[i].r, v3=quad[i].s
134#define TRI_PS_2 v1=quad[i].q, v2=quad[i].p, v3=quad[i].s
135
136
137#define DIFF(i1, i2) (							$\
138	c1 = cmap? &cmap[((unsigned char *)colors)[i1]]			$\
139		 : &((RGBColor *)colors)[i1],				$\
140	c2 = cmap? &cmap[((unsigned char *)colors)[i2]]			$\
141		 : &((RGBColor *)colors)[i2],				$\
142	dr = c1->r - c2->r,						$\
143	dg = c1->g - c2->g,						$\
144	db = c1->b - c2->b,						$\
145	dr*dr + dg*dg + db*db						$\
146)
147
148#define QUAD_VOLUME(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL){ $\
149									    $\
150    Point *p;								    $\
151    int v1, v2, v3, width, height, valid;				    $\
152    float ox, oy;							    $\
153    InvalidComponentHandle iElts;					    $\
154    RGBColor *colors;							    $\
155    /*int cstcolors;*/							    $\
156									    $\
157    if (xf->fcolors) {							    $\
158	colors = xf->fcolors /*, cstcolors = xf->fcst */;		    $\
159    } else {								    $\
160	colors = xf->bcolors /*, cstcolors = xf->bcst */;		    $\
161    }									    $\
162									    $\
163    if (! colors)							    $\
164	DXErrorReturn(ERROR_MISSING_DATA, "no colors in field");	    $\
165									    $\
166    /* for volume quads, we determine validity here			    $\
167     */									    $\
168    switch(invalid_status) {						    $\
169	case INV_VALID:   iElts = NULL;      valid = 1; break;		    $\
170	case INV_INVALID: iElts = NULL;      valid = 0; break;		    $\
171	case INV_UNKNOWN: iElts = xf->iElts;            break;		    $\
172    }									    $\
173									    $\
174    width = buf->width, height = buf->height;				    $\
175    ox = buf->ox, oy = buf->oy;						    $\
176									    $\
177    for (i=0; i<nquad; i++, quad++) {					    $\
178	int index = (indices == NULL) ? i : indices[i];			    $\
179									    $\
180	if (iElts)							    $\
181	    valid = DXIsElementValid(iElts, index);	    		    $\
182									    $\
183	TRI_PS_1;							    $\
184									    $\
185	/* points */							    $\
186	p = &xf->positions[v1], x1=p->x, y1=p->y, z1=p->z;	    	    $\
187	p = &xf->positions[v2], x2=p->x, y2=p->y, z2=p->z;	    	    $\
188	p = &xf->positions[v3], x3=p->x, y3=p->y, z3=p->z;	    	    $\
189									    $\
190	if (!((x1<minx && x2<minx && x3<minx) ||			    $\
191	      (x1>maxx && x2>maxx && x3>maxx) ||			    $\
192	      (y1<miny && y2<miny && y3<miny) ||			    $\
193	      (y1>maxy && y2>maxy && y3>maxy)))				    $\
194	{								    $\
195	  buf->triangles++;						    $\
196	  TRIANGLEV1(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL, 1) $\
197	  TRIANGLEV2(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL, 1);$\
198	}								    $\
199									    $\
200 CAT(LABEL,1) :								    $\
201	TRI_PS_2;							    $\
202									    $\
203	/* points */							    $\
204	p = &xf->positions[v1], x1=p->x, y1=p->y, z1=p->z;	    	    $\
205	p = &xf->positions[v2], x2=p->x, y2=p->y, z2=p->z;	    	    $\
206	p = &xf->positions[v3], x3=p->x, y3=p->y, z3=p->z;	    	    $\
207									    $\
208	if ((x1<minx && x2<minx && x3<minx) ||				    $\
209	    (x1>maxx && x2>maxx && x3>maxx) ||				    $\
210	    (y1<miny && y2<miny && y3<miny) ||				    $\
211	    (y1>maxy && y2>maxy && y3>maxy))				    $\
212		continue;						    $\
213									    $\
214	buf->triangles++;						    $\
215	TRIANGLEV1(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL, 2);$\
216	TRIANGLEV2(pstr, pptr, shrgb, sho, col, face, TEST, PIXEL, LABEL, 2);$\
217 CAT(LABEL,2) :								    $\
218	continue;							    $\
219    }									    $\
220}
221
222#define QUADDCL								    $\
223    RGBColor *c1, *c2, *c3;						    $\
224    float x1, y1, x2, y2, x3, y3;					    $\
225    float r1, g1, b1, o1, z1, r2, g2, b2, o2, z2, r3, g3, b3, o3, z3;	    $\
226    float Qx, dxo, dxz, dxr, dxg, dxb;					    $\
227    float Qy, dyr, dyg, dyb, dyo, dyz, dyA, dyB;			    $\
228    float r, g, b, o, obar, z, nearPlane=xf->nearPlane ;		    $\
229    float A, B, d, d1, d2, d3;						    $\
230    int iy1, iy2, iy3;							    $\
231    int iA, iB, iy, i, n, nn, left, right;				    $\
232    float minx = buf->min.x, miny = buf->min.y;				    $\
233    float maxx = buf->max.x, maxy = buf->max.y
234
235
236
237/*
238 * The following are the templates for the quad rendering routines
239 */
240
241#define QUADPROLOGUE(name)						    $\
242    static Error							    $\
243    name(								    $\
244	struct buffer *buf,						    $\
245	struct xfield *xf,						    $\
246	int nquad,							    $\
247	Quadrilateral *quad,						    $\
248	int *indices,							    $\
249	int surface,							    $\
250	int clip_status,						    $\
251	inv_stat invalid_status						    $\
252    ) {									    $\
253	QUADDCL;							    $\
254	Pointer fcolors = xf->fcolors;					    $\
255	Pointer bcolors = xf->bcolors;					    $\
256	Pointer opacities = xf->opacities;				    $\
257	RGBColor *cmap = xf->cmap;					    $\
258	float *omap = xf->omap;						    $\
259	char fbyte = xf->fbyte, bbyte = xf->bbyte;			    $\
260
261#define QUADEPILOGUE							    $\
262	return OK;							    $\
263    }
264
265
266
267QUADPROLOGUE(quad_vol)
268    float cmul = xf->tile.color_multiplier;
269    float omul = xf->tile.opacity_multiplier / cmul;
270    if (xf->tile.perspective)
271	DXErrorReturn(ERROR_BAD_PARAMETER,
272		    "perspective volume rendering is not supported");
273    if (!buf->merged)
274	_dxf_MergeBackIntoZ(buf);
275    if (opacities) {
276	QUAD_VOLUME(struct big, u.big, SHRGB, SHO, COL, 0, 1, VOLUME, qvo);
277    } else {
278	QUAD_VOLUME(struct big, u.big, SHRGB,NOSHO, COL, 0, 1, VOLUME, qvno);
279    }
280QUADEPILOGUE
281
282
283QUADPROLOGUE(quad_translucent)
284    if (xf->colors_dep == dep_connections)
285    {
286	if (clip_status) {
287	    QUADS(struct big,u.big,SHRGB,NOSHO,COL,
288				0,TRANSCLIPZ,TRANSLUCENT, qtcdc);
289	} else if (buf->pix_type==pix_fast) {
290	    QUADS(struct fast,u.fast,SHRGB,NOSHO,COL,
291				0,NOCLIPZ,TRANSLUCENT, qtfdc);
292	} else if (buf->pix_type==pix_big) {
293	    QUADS(struct big,u.big,SHRGB,NOSHO,COL,
294				0,NOCLIPZ,TRANSLUCENT, qtbdc);
295	} else {
296	    DXSetError(ERROR_INTERNAL, "unknown pix_type %d", buf->pix_type);
297	    return ERROR;
298	}
299    }
300    else
301    {
302	if (clip_status) {
303	    QUADS(struct big,u.big,SHRGB,SHO,COL,
304				0,TRANSCLIPZ,TRANSLUCENT,qtcdp);
305	} else if (buf->pix_type==pix_fast) {
306	    QUADS(struct fast,u.fast,SHRGB,SHO,COL,
307				0,NOCLIPZ,TRANSLUCENT,qtfdp);
308	} else if (buf->pix_type==pix_big) {
309	    QUADS(struct big,u.big,SHRGB,SHO,COL,
310				0,NOCLIPZ,TRANSLUCENT,qtbdp);
311	} else {
312	    DXSetError(ERROR_INTERNAL, "unknown pix_type %d", buf->pix_type);
313	    return ERROR;
314	}
315    }
316QUADEPILOGUE
317
318
319QUADPROLOGUE(quad_opaque)
320    if (clip_status) {
321	QUADS(struct big,u.big,SHRGB,NOSHO,COL,0,CLIPZ,OPAQUE,qoc);
322    } else if (buf->pix_type==pix_fast) {
323	QUADS(struct fast,u.fast,SHRGB,NOSHO,COL,0,NOCLIPZ,OPAQUE,qof);
324    } else if (buf->pix_type==pix_big) {
325	QUADS(struct big,u.big,SHRGB,NOSHO,COL,0,NOCLIPZ,OPAQUE,qob);
326    } else {
327	DXSetError(ERROR_INTERNAL, "unknown pix_type %d", buf->pix_type);
328	return ERROR;
329    }
330QUADEPILOGUE
331
332Error
333_dxf_QuadClipping(
334    struct buffer *buf,
335    struct xfield *xf,
336    int nquad,
337    Quadrilateral *quad,
338    int *indices)
339{
340    QUADDCL;
341    Pointer fcolors = NULL;		/* UNCOL guarantees not ref'ed */
342    Pointer bcolors = NULL;		/* UNCOL guarantees not ref'ed */
343    Pointer opacities = NULL;
344    RGBColor *cmap = NULL;
345    float *omap = NULL;
346    inv_stat invalid_status = INV_VALID;
347    char fbyte = xf->fbyte, bbyte = xf->bbyte;
348
349    if (xf->tile.perspective) {
350	struct xfield xx;
351	for (i=0; i<nquad; ) {
352	    i = _dxf_zclip_quads(xf, (int *)quad, i, indices, nquad, &xx, INV_VALID);
353	    if (xx.nconnections)
354		_dxf_TriangleClipping(buf, &xx, xx.nconnections,
355		xx.c.triangles, xx.indices);
356	}
357    }
358
359    QUADS(struct big,u.big,NOSHRGB,NOSHO,UNCOL,0,1,CLIPPINGPIXEL, qc);
360    return OK;
361}
362
363static Error
364_dxf_QuadComposite(
365    struct buffer *buf,
366    struct xfield *xf,
367    int nquad,
368    Quadrilateral *quad,
369    int *indices,
370    int clip_status,
371    inv_stat invalid_status
372) {
373    QUADDCL;
374    Pointer fcolors = xf->fcolors;
375    Pointer bcolors = xf->bcolors;
376    Pointer opacities = xf->opacities;
377    RGBColor *cmap = xf->cmap;
378    float *omap = xf->omap;
379    char fbyte = xf->fbyte, bbyte = xf->bbyte;
380
381    if (xf->tile.perspective)
382	DXErrorReturn(ERROR_BAD_PARAMETER,
383		    "perspective volume rendering is not supported");
384
385    if (clip_status) {
386	QUADS(struct big,u.big,SHRGB,SHO,COL,0,TRANSCLIPZ,COMPOSITE,qcc);
387    } else if (buf->pix_type==pix_fast) {
388	QUADS(struct fast,u.fast,SHRGB,SHO,COL,0,NOCLIPZ,COMPOSITE,qcf);
389    } else if (buf->pix_type==pix_big) {
390	QUADS(struct big,u.big,SHRGB,SHO,COL,0,NOCLIPZ,COMPOSITE,qcb);
391    } else {
392	DXSetError(ERROR_INTERNAL, "unknown pix_type %d", buf->pix_type);
393	return ERROR;
394    }
395
396    return OK;
397}
398
399Error
400_dxf_Quad(struct buffer *buf,
401	  struct xfield *xf,
402	  int nquad,
403	  Quadrilateral *quad,
404	  int *indices,
405	  int surface,
406	  int clip_status,
407	  inv_stat invalid_status)
408{
409    int i;
410
411    if (xf->tile.perspective) {
412	struct xfield xx;
413	for (i=0; i<nquad; ) {
414	    i = _dxf_zclip_quads(xf, (int *)quad, i, indices, nquad, &xx, invalid_status);
415	    if (xx.nconnections)
416		_dxf_Triangle(buf, &xx, xx.nconnections, xx.c.triangles,
417			xx.indices, surface, clip_status, INV_VALID);
418	}
419    }
420
421    if (xf->volume)
422	return quad_vol(buf, xf, nquad, quad, indices, surface,
423				    clip_status, invalid_status);
424    if (xf->opacities)
425	return quad_translucent(buf, xf, nquad, quad, indices, surface,
426				    clip_status, invalid_status);
427    else
428	return quad_opaque(buf, xf, nquad, quad, indices, surface,
429				    clip_status, invalid_status);
430}
431
432
433#define QUADFLATPROLOGUE(name)				$\
434    static Error					$\
435    name(						$\
436	struct buffer *buf,				$\
437	struct xfield *xf,				$\
438	int nquad,					$\
439	Quadrilateral *quad,				$\
440	int *indices,					$\
441	Pointer fcolors,				$\
442	Pointer bcolors,				$\
443	Pointer opacities,				$\
444	int surface,					$\
445	int clip_status,				$\
446	inv_stat invalid_status				$\
447    ) {							$\
448	QUADDCL;					$\
449	RGBColor *cmap = xf->cmap;			$\
450	float *omap = xf->omap;				$\
451	char fbyte = xf->fbyte, bbyte = xf->bbyte;	$\
452	/*char obyte = xf->obyte;*/
453
454#define QUADFLATEPILOGUE				$\
455	return OK;					$\
456    }
457
458
459QUADFLATPROLOGUE(quad_flat_face)
460    QUADS(struct big, u.big, NOSHRGB, NOSHO, COL, 1, 1, FACE,qff);
461QUADFLATEPILOGUE
462
463
464QUADFLATPROLOGUE(quad_flat_vol)
465    float cmul = xf->tile.color_multiplier;
466    float omul = xf->tile.opacity_multiplier / cmul;
467    if (xf->tile.perspective)
468	DXErrorReturn(ERROR_BAD_PARAMETER,
469		    "perspective volume rendering is not supported");
470    if (!buf->merged)
471        _dxf_MergeBackIntoZ(buf);
472    QUAD_VOLUME(struct big, u.big, NOSHRGB, NOSHO, COL, 0, 1, VOLUME, qfv);
473QUADFLATEPILOGUE
474
475
476QUADFLATPROLOGUE(quad_flat_translucent)
477    if (clip_status) {
478	QUADS(struct big,u.big,NOSHRGB,NOSHO,COL,
479					0,TRANSCLIPZ,TRANSLUCENT,qftc);
480    } else if (buf->pix_type==pix_fast) {
481	QUADS(struct fast,u.fast,NOSHRGB,NOSHO,COL,
482					0,NOCLIPZ,TRANSLUCENT,qftf);
483    } else if (buf->pix_type==pix_big) {
484	QUADS(struct big,u.big,NOSHRGB,NOSHO,COL,
485					0,NOCLIPZ,TRANSLUCENT,qftb);
486    } else {
487	DXSetError(ERROR_INTERNAL, "unknown pix_type %d", buf->pix_type);
488	return ERROR;
489    }
490QUADFLATEPILOGUE
491
492
493QUADFLATPROLOGUE(quad_flat_opaque)
494    if (clip_status) {
495	QUADS(struct big,u.big,NOSHRGB,NOSHO,COL,
496					0,CLIPZ,OPAQUE,qfoc);
497    } else if (buf->pix_type==pix_fast) {
498	QUADS(struct fast,u.fast,NOSHRGB,NOSHO,COL,
499					0,NOCLIPZ,OPAQUE,qfof);
500    } else if (buf->pix_type==pix_big) {
501	QUADS(struct big,u.big,NOSHRGB,NOSHO,COL,
502					0,NOCLIPZ,OPAQUE,qfob);
503    } else {
504	DXSetError(ERROR_INTERNAL, "unknown pix_type %d", buf->pix_type);
505	return ERROR;
506    }
507QUADFLATEPILOGUE
508
509
510Error
511_dxf_QuadFlat(
512    struct buffer *buf,
513    struct xfield *xf,
514    int nquad,
515    Quadrilateral *quad,
516    int *indices,
517    Pointer fcolors,
518    Pointer bcolors,
519    Pointer opacities,
520    int surface,
521    int clip_status,
522    inv_stat invalid_status
523) {
524    QUADDCL;
525
526    if (xf->tile.perspective) {
527	struct xfield xx;
528	for (i=0; i<nquad; ) {
529	    i = _dxf_zclip_quads(xf, (int *)quad, i, indices, nquad, &xx, invalid_status);
530	    if (xx.nconnections)
531		_dxf_TriangleFlat(buf, &xx, xx.nconnections, xx.c.triangles,
532			      xx.indices, xx.fcolors, xx.bcolors, xx.opacities,
533			      surface, clip_status, invalid_status);
534	}
535    }
536
537
538
539    if (xf->ct!=ct_triangles && xf->ct!=ct_quads)
540	return quad_flat_vol(buf, xf, nquad, quad, indices,
541			    fcolors, bcolors, opacities,
542			    surface, clip_status, invalid_status);
543    else if (xf->opacities)
544	return quad_flat_translucent(buf, xf, nquad, quad, indices,
545				    fcolors, bcolors, opacities,
546				    surface, clip_status, invalid_status);
547    else
548	return quad_flat_opaque(buf, xf, nquad, quad, indices,
549			       fcolors, bcolors, opacities,
550			       surface, clip_status, invalid_status);
551}
552