/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include /* * Header: /usr/people/gresh/code/svs/src/libdx/RCS/paint.c,v 5.0 92/11/12 09:08:25 svs Exp Locker: gresh * Locker: gresh */ #include #include #include "internals.h" #include "render.h" /* * Parameters */ #define PARAMETER(parm, name, type, get) { \ type p; \ Object a; \ a = DXGetAttribute(o, name); \ if (a) { \ if (!get(a, &p)) \ DXErrorReturn(ERROR_BAD_PARAMETER, "invalid " name " attribute"); \ new->parm = p; \ } \ } static Error parameters(Object o, struct tile *new, struct tile *old, int *if_object) { *new = *old; *if_object = 0; if (DXGetAttribute(o, "interference object")) { new->if_object = 1; if (!old->if_object) *if_object = 1; } if (DXGetAttribute(o, "interference group")) new->if_group = 1; if (!_dxf_approx(o, &new->approx)) return ERROR; return OK; } Object _dxfField_Paint(Field f, struct buffer *b, int clip_status, struct tile *tile) { int i, j, k, n; struct xfield xf; int if_object = 0; /* get the stuff we need */ DXMarkTimeLocal("start field"); if (DXEmptyField(f)) return (Object) f; #if 0 if (!_dxf_XBox(f, &xf, XR_REQUIRED, XD_GLOBAL)) goto error; if (xf.box[0].x>=b->max.x || xf.box[0].y>=b->max.y || xf.box[7].xmin.x || xf.box[7].ymin.y) { DXMarkTimeLocal("culled"); return (Object) f; } #endif /* store parameters and get new ones */ _dxf_XZero(&xf); if (!parameters((Object)f, &xf.tile, tile, &if_object)) goto error; if (xf.tile.if_group && !xf.tile.if_object) { xf.tile.if_object = 1; if_object = 1; } DXMarkTimeLocal("parameters"); /* extract what we need */ if (clip_status==CLIPPING) { if (xf.tile.approx!=approx_dots) { if (!_dxf_XConnections(f, &xf, XR_OPTIONAL)) goto error; if (!_dxf_XPolylines(f, &xf, XR_OPTIONAL, XD_GLOBAL)) goto error; } } else { if (!_dxf_XColors(f, &xf, XR_REQUIRED, XD_GLOBAL)) goto error; if (xf.tile.approx!=approx_dots) { if (!_dxf_XOpacities(f, &xf, XR_OPTIONAL, XD_GLOBAL)) goto error; if (!_dxf_XConnections(f, &xf, XR_OPTIONAL)) goto error; if (!_dxf_XPolylines(f, &xf, XR_OPTIONAL, XD_GLOBAL)) goto error; if (xf.ct!=ct_triangles && xf.ct!=ct_quads && xf.ct != ct_polylines && xf.ct!=ct_lines && xf.ct!=ct_none) return (Object) f; } } DXMarkTimeLocal("extract"); if (!_dxf_XPositions(f, &xf, XR_REQUIRED, XD_LOCAL)) goto error; n = xf.nconnections; DXMarkTimeLocal("localize"); /* get box for near plane for perspective clipping */ if (xf.tile.perspective) { if (!_dxf_XBox(f, &xf, XR_REQUIRED, XD_GLOBAL)) goto error; xf.nearPlane = xf.box[0].z; } if (! _dxf_XLighting(f, &xf)) goto error; /* for now */ # define EXPAND_QUADS \ xf.c.quads = (Quadrilateral *) DXGetArrayData(xf.connections_array); \ if (!xf.c.quads) \ goto error; \ DXGetArrayInfo(xf.connections_array, &n, NULL, NULL, NULL, NULL); /* if we're a clipping surface */ if (clip_status==CLIPPING) { if (xf.ct==ct_triangles) { if (!_dxf_TriangleClipping(b, &xf, n, xf.c.triangles, NULL)) goto error; } else if (xf.ct==ct_quads) { EXPAND_QUADS; if (!_dxf_QuadClipping(b, &xf, n, xf.c.quads, NULL)) goto error; } else if (xf.ct!=ct_none) DXErrorGoto(ERROR_INVALID_DATA, "clipping object must be triangles or quads"); /* if we're an opaque surface */ } else if (!xf.opacities) { /* render triangles */ if (xf.ct==ct_triangles) { if (!_dxf_XInvalidConnections(f, &xf)) goto error; if (xf.colors_dep == dep_positions || xf.lights) { if (!_dxf_Triangle(b, &xf, n, xf.c.triangles, NULL, 0, clip_status, INV_UNKNOWN)) goto error; } else if (xf.colors_dep == dep_connections) { if (!_dxf_TriangleFlat(b, &xf, n, xf.c.triangles, NULL, xf.fcolors, xf.bcolors, xf.opacities, 0, clip_status, INV_UNKNOWN)) goto error; } } /* render quads */ else if (xf.ct==ct_quads) { EXPAND_QUADS; if (!_dxf_XInvalidConnections(f, &xf)) goto error; if (xf.colors_dep == dep_positions || xf.lights) { if (!_dxf_Quad(b, &xf, n, xf.c.quads, NULL, 0, clip_status, INV_UNKNOWN)) goto error; } else if (xf.colors_dep == dep_connections) { if (!_dxf_QuadFlat(b, &xf, n, xf.c.quads, NULL, xf.fcolors, xf.bcolors, xf.opacities, 1, clip_status, INV_UNKNOWN)) goto error; } } /* render lines */ else if (xf.ct==ct_lines) { if (!_dxf_XInvalidConnections(f, &xf)) goto error; if (xf.colors_dep == dep_positions || xf.lights) { if (!_dxf_Line(b, &xf, xf.nconnections, xf.c.lines, NULL, clip_status, INV_UNKNOWN)) goto error; } else if (xf.colors_dep == dep_connections) { if (!_dxf_LineFlat(b, &xf, xf.nconnections, xf.c.lines, NULL, xf.fcolors, xf.opacities, clip_status, INV_UNKNOWN)) goto error; } else DXErrorGoto(ERROR_INVALID_DATA, "invalid color dependency"); } else if (xf.ct==ct_polylines) { if (!_dxf_XInvalidPolylines(f, &xf)) goto error; if (xf.colors_dep == dep_positions || xf.lights) { if (!_dxf_Polyline(b, &xf, xf.nconnections, xf.polylines, NULL, clip_status, INV_UNKNOWN)) goto error; } else if (xf.colors_dep == dep_polylines) { if (!_dxf_PolylineFlat(b, &xf, xf.nconnections, xf.polylines, NULL, xf.fcolors, xf.opacities, clip_status, INV_UNKNOWN)) goto error; } else DXErrorGoto(ERROR_INVALID_DATA, "invalid color dependency"); } /* * Note: we do the loops in reverse order so that the first * loop gets painted last. This ensures that the first loop * determines whether front or back colors are used, on the * assumption that the first loop is the "main" loop. * XXX - find a better solution. Also, if this is the case, * the colors need not be interpolated in any but the first * loop. */ else if (xf.ct==ct_none) { if (!_dxf_XInvalidPositions(f, &xf)) goto error; if (xf.colors_dep==dep_positions) { if (!_dxf_Points(b, &xf)) goto error; } else DXErrorGoto(ERROR_INVALID_DATA, "invalid color dependency"); } /* eh? */ else DXErrorGoto(ERROR_INVALID_DATA, "unknown connections type"); } if (if_object) _dxf_InterferenceObject(b); _dxf_XFreeLocal(&xf); DXMarkTimeLocal("work"); return (Object) f; error: _dxf_XFreeLocal(&xf); return NULL; } /* * DXRender the opaque "triangles" of a group */ Object _dxfGroup_Paint(Group g, struct buffer *b, int clip_status, struct tile *tile) { Object o; int i, if_object; struct tile new; float minx, miny, maxx, maxy; minx = b->min.x - .5 /* for lines */; miny = b->min.y - .5 /* for lines */; maxx = b->max.x + .5 /* for lines */; maxy = b->max.y + .5 /* for lines */; if (!parameters((Object)g, &new, tile, &if_object)) return NULL; if (DXGetObjectClass((Object)g)==CLASS_COMPOSITEFIELD) new.ignore = 1; for (i=0; o=DXGetEnumeratedMember(g, i, NULL); i++) { if (DXGetObjectClass(o)==CLASS_FIELD) { Array a; Point *box; a = (Array)DXGetComponentValue((Field)o, BOX); box = (Point *) DXGetArrayData(a); if (box[0].x>=maxx || box[0].y>=maxy || box[7].xperspective) if (! _dxfCapClipping(b, DXD_MAX_FLOAT)) return NULL; if (!_dxfPaint(render, b, NEST(clip_status), &new)) return NULL; _dxf_EndClipping(b); } else { if (!_dxfPaint(render, b, clip_status, &new)) return NULL; } if (if_object) _dxf_InterferenceObject(b); return (Object) clipped; }