/***********************************************************************/ /* 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 /* TeX starts here. Do not remove this comment. */ /* \section{Rendering} This section describes the internal routines and data structures associated with rendering. /* \paragraph{Xfield} The {\tt xfield} data structure contains information extracted from a field. Extracting this information once avoids a lot of overhead. The {\tt tile} structure contains tiling parameters relevant to the field. We declare it as a separate structure, because we use it later on to pass down tiling parameters as we traverse the structure. */ struct tile { /* tiling parameters */ int ignore; /* don't get new parameters - e.g. w/in comp field */ int fast_exp; /* use fast exponent in volume rendering */ int flat_x; /* flat x in volume rendering */ int flat_y; /* flat y in volume rendering */ int flat_z; /* flat z in volume rendering */ int skip; /* skip faces at random in volume rendering */ int patch_size; /* volume rendering patch size */ float color_multiplier; /* multiplier for volume colors */ float opacity_multiplier; /* multiplier for volume opacities */ int if_group; /* in interference group */ int if_object; /* in interference object */ int perspective; /* do perspective for this field? */ enum approx { approx_none, /* no approximation */ approx_flat, /* flat shading - NOT IMPLEMENTED */ approx_lines, /* line rendering - NOT IMPLEMENTED */ approx_dots, /* dots */ approx_box /* box */ } approx; }; Error _dxf_approx(Object o, enum approx *approx); #define MAXLIGHTS 100 struct lightList { int na; int nl; RGBColor ambient; Light lights[MAXLIGHTS]; Vector h[MAXLIGHTS]; }; typedef struct lightList *LightList; typedef enum { dep_positions, dep_connections, dep_polylines } dependency; struct xfield { Point *box; /* bounding box */ int nbox; float nearPlane; /* near plane for perspective clipping */ /* positions and typically point-dependent data */ Point *positions; /* control points */ Pointer fcolors, bcolors; /* front/back colors or byte data */ RGBColor *cmap; /* color map iff above is byte data */ Pointer opacities; /* opacities or byte data */ float *omap; /* opacity map iff above is byte data */ Vector *normals; /* normals */ /* counts */ int npositions; /* number of positions */ int ncolors; /* number of colors, normals, opacities */ /* dependencies */ dependency colors_dep, normals_dep; /* standard connections */ enum ct { /* type of connections */ ct_none, /* none specified */ ct_lines, /* line segments */ ct_polylines, /* line segments */ ct_triangles, /* triangles */ ct_quads, /* quads */ ct_tetrahedra, /* tetrahedra */ ct_cubes /* cubes */ } ct; union { /* data array for the irregular ones only */ Line *lines; Triangle *triangles; Tetrahedron *tetrahedra; Quadrilateral *quads; Cube *cubes; int *i; } c; int volume; /* whether it is a volume connection */ int nconnections; /* number of connection elements */ Pointer neighbors; /* neighbors data */ int *polylines, npolylines; /* polylines are handled separately since */ int *edges, nedges; /* they require an indirection through an */ /* "edges" component */ /* information about regular partition */ Point o; /* back corner of partition */ Vector d[3]; /* axes of partition box, relative to o */ int n; /* point id of back corner of partition */ int k[3], s[3]; /* counts, strides in each direction */ int cn; /* point id of back corner of partition */ int ck[3], cs[3]; /* counts, strides in each direction */ /* tiling options applicable to this field */ struct tile tile; /* the arrays */ Array box_array; Array positions_array; Array neighbors_array; Array fcolors_array; Array bcolors_array; Array opacities_array; Array normals_array; Array faces_array; Array polylines_array; Array loops_array; Array edges_array; Array inner_array; Array connections_array; Array cmap_array; Array omap_array; /* flags to indicate whether data is local */ char box_local; char positions_local; char neighbors_local; char opacities_local; char fcolors_local; char bcolors_local; char normals_local; char surface_local; char inner_local; char faces_local; char polylines_local; char loops_local; char edges_local; char cmap_local; char omap_local; char volAlg; InvalidComponentHandle iElts, iPts; /* * lighting parameters for delayed lighting */ LightList lights; float kaf, kdf, ksf; int kspf; float kab, kdb, ksb; int kspb; int *indices; /* * The following has been added to support constant normals and colors * components without expansion. If the components are constant, the * following buffers will contain the component value and the cst flags * will be set. */ Point nbuf; RGBColor fbuf, bbuf; float obuf; char fcst, bcst, ncst, ocst; char fbyte, bbyte, obyte; }; enum xr { XR_OPTIONAL=0, XR_REQUIRED=1 }; enum xd { XD_NONE, XD_GLOBAL, XD_LOCAL }; typedef enum { INV_UNKNOWN, INV_VALID, INV_INVALID } inv_stat; void _dxf_XZero(struct xfield *xf); Error _dxf_XBox(Field f, struct xfield *xf, enum xr required, enum xd xd); Error _dxf_XPositions(Field f, struct xfield *xf, enum xr required, enum xd xd); Error _dxf_XConnections(Field f, struct xfield *xf, enum xr required); Error _dxf_XNeighbors(Field f, struct xfield *xf, enum xr required, enum xd xd); Error _dxf_XColors(Field f, struct xfield *xf, enum xr required, enum xd xd); Error _dxf_XNormals(Field f, struct xfield *xf, enum xr required, enum xd xd); Error _dxf_XOpacities(Field f, struct xfield *xf, enum xr required, enum xd xd); Error _dxf_XSurface(Field f, struct xfield *xf, enum xr required, enum xd xd); Error _dxf_XInner(Field f, struct xfield *xf, enum xr required, enum xd xd); Error _dxf_XLighting(Field f, struct xfield *xf); /** These routines extract various components. The {\tt xr} parameter indicates whether the component is required, i.e. whether it is an error for it not to be present. The {\tt xd} parameter tells us whether to get the data, and if so whether to copy it to local memory. This is an issue because getting the data from a regular array potentially involves expanding a compact representation. **/ Error _dxf_XFreeLocal(struct xfield *xf); /** Frees the local data for all the arrays in {\tt *xf} that were copied to local memory. **/ /* \paragraph{Rendering Buffer} The rendering buffer data structure contains information relevant to rendering a particular screen patch, including a pointer to the pixels themselves (in local memory). This section describes the rendering buffer and a set of low-level routines for rendering primitives into the buffer. */ struct rgbo { float r, g, b, o; }; struct buffer { int width, height; /* size */ int ox, oy; /* origin */ int merged; /* have back and z been merged? */ Point min, max; /* for bbox check */ Point omin, omax; /* object size for interference */ Point fmin, fmax; /* face size */ union { struct big { RGBColor c; /* accumulated color */ struct rgbo co; /* 1) volume interp 2) face color */ float z; /* last rendered z */ float front, back; /* front/back clip surfaces */ int in; /* in/out of 1) volume 2) face */ } *big; /* buffer */ struct fast { RGBColor c; /* color */ float z; /* z value */ } *fast; /* fast buffer */ struct zbuf { float z; /* z value */ } *zbuf; } u; /* possibly aligned buffer */ enum pix_type { pix_big, pix_fast, pix_zbuf } pix_type; /* buffer pixel type */ Pointer buffer; /* the buffer for freeing */ int iwidth; /* image width */ union { struct fbpixel *fb; /* image is fb pixels */ struct RGBColor *rgb; /* image is float colors */ unsigned char *x; /* image is x byte image */ } img; enum img_type { img_fb, /* image is fb pixels */ img_rgb, /* image is float colors */ img_x /* image is x byte image */ } img_type; int init; /* init method to use */ int showpatches; /* whether to show patch outline */ int notriangles; /* return at beginning of Triangle */ int setuponly; /* return after triangle setup */ int tri; /* triangle method to use */ int irregular; /* force irregular */ char *vol; /* regular volume method to use */ int triangles; /* return count */ int pixels; /* return count */ }; Error _dxf_InitBuffer(struct buffer *b, enum pix_type pix_type, int width, int height, int ox, int oy, RGBColor c); /** Initialize a rendering buffer structure. **/ Error _dxf_CopyBufferToImage(struct buffer *b, Field i, int xoff, int yoff); Error _dxf_CopyBufferToFBImage(struct buffer *b, Field i, int xoff, int yoff); Error _dxf_CopyBufferToXImage(struct buffer *b, Field i, int xoff, int yoff); /** Copies rendering buffer {\tt b} to image {\tt i} at the specified offset in the image. Returns {\tt b} or null to indicate an error. **/ Error _dxf_BeginClipping(struct buffer *b); /** Initialize the buffer for clipping. **/ Error _dxf_EndClipping(struct buffer *b); /** Restore the buffer after clipping. **/ Error _dxfCapClipping(struct buffer *b, float); /** If in perspective, may need to cap the clipping volume (eg. if part of the front surface was clipped away by the Z clip). **/ Error _dxf_Triangle(struct buffer *b, struct xfield *xf, int n, Triangle *tri, int *indices, int surface, int clip_status, inv_stat invalid_status); Error _dxf_Quad(struct buffer *b, struct xfield *xf, int n, Quadrilateral *quad, int *indices, int surface, int clip_status, inv_stat invalid_status); /** Renders face {\tt tri} from field {\tt xf} into rendering buffer {\tt b}, treating it as a surface face or an inner face according to {\tt surface}. Returns {\tt b} or null to indicate an error. (Question: should we include {\tt clip\_status} as an argument to allow selection of clipped/non-clipped algorithm, for performance?) **/ Error _dxf_TriangleFlat(struct buffer *b, struct xfield *xf, int n, Triangle *tri, int *indices, Pointer front, Pointer back, Pointer o, int surface, int clip_status, inv_stat invalid_status); Error _dxf_QuadFlat(struct buffer *b, struct xfield *xf, int n, Quadrilateral *quad, int *indices, Pointer front, Pointer back, Pointer o, int surface, int clip_status, inv_stat invalid_status); /** Renders face {\tt tri} from field {\tt xf} into rendering buffer {\tt b}, treating it as a surface face or an inner face according to {\tt surface}. Uses flat shading with specified color and opacity. Returns {\tt b} or null to indicate an error. **/ Error _dxf_TriangleClipping(struct buffer *b, struct xfield *xf, int n, Triangle *tri, int *indices); Error _dxf_QuadClipping(struct buffer *b, struct xfield *xf, int n, Quadrilateral *quad, int *indices); /** Renders face {\tt tri} from field {\tt xf} as a clipping triangle. **/ static Error _dxf_TriangleComposite(struct buffer *b, struct xfield *xf, int n, Triangle *tri, int *indices, int clip_status, inv_stat invalid_status); static Error _dxf_QuadComposite(struct buffer *b, struct xfield *xf, int n, Quadrilateral *quad, int *indices, int clip_status, inv_stat invalid_status); /** Composites a triangle or a quad. **/ Error _dxf_TriangleCompositeFlat(struct buffer *b, struct xfield *xf, int n, Triangle *tri, int *indices, Pointer colors, Pointer op, int clip_status, inv_stat invalid_status); Error _dxf_QuadCompositeFlat(struct buffer *b, struct xfield *xf, int n, Quadrilateral *quad, int *indices, Pointer colors, Pointer op, int clip_status, inv_stat invalid_status); Error _dxf_Polyline(struct buffer *b, struct xfield *xf, int n, int *line, int *indices, int clip_status, inv_stat invalid_status); Error _dxf_PolylineFlat(struct buffer *b, struct xfield *xf, int n, int *line, int *indices, Pointer colors, Pointer opacities, int clip_status, inv_stat invalid_status); Error _dxf_Line(struct buffer *b, struct xfield *xf, int n, Line *line, int *indices, int clip_status, inv_stat invalid_status); Error _dxf_LineFlat(struct buffer *b, struct xfield *xf, int n, Line *line, int *indices, Pointer colors, Pointer opacities, int clip_status, inv_stat invalid_status); Error _dxf_Points(struct buffer *b, struct xfield *xf); Error _dxf_Point(struct buffer *b, struct xfield *xf, int i); /** DXRender all the positions of field {\tt xf} as points in buffer {\tt b}, or render one translucent point. **/ #define ALL8(b,op,m,x) ( \ b[0].x op m.x && b[1].x op m.x && b[2].x op m.x && b[3].x op m.x && \ b[4].x op m.x && b[5].x op m.x && b[6].x op m.x && b[7].x op m.x ) #define CULLBOX(b,min,max) \ (ALL8(b,<,min,x)|| ALL8(b,<,min,y)||ALL8(b,>=,max,x)||ALL8(b,>=,max,y)) /* \paragraph{Object traversal} The following routines traverse entire objects. In general, they are called from Tile. */ /* clip_status values */ #define CLIPPING (-1) /* this is a clipping object */ #define UNCLIPPED 0 /* this is an unclipped object */ #define CLIPPED(x) ((x)>0) /* this is a clipped object */ #define NEST(x) ((x)+1) /* nested clipping */ Object _dxfPaint(Object o, struct buffer *b, int clip_status, struct tile *tile); /** Adds the opaque parts of the {\tt Object} to the rendering buffer. The {\tt clip} argument specifies whether we are rendering an unclipped object, rendering a clipped object, or rendering the object that does the clipping. Returns {\tt b} or null to indicate an error. **/ struct count { lock_type DXlock; /* for parallel update */ int nx, ny; /* input number of screen patches */ int width, height; /* size of image */ int irregular; /* number of irregular (vol/surf) fields */ int volume; /* number of volume fields */ int regular; /* number of regular volume fields */ int fast; /* whether fast small fb can be used */ struct pcount { /* patch count */ int nconnections; /* number of connections for work estimate */ int tfields; /* number of translucent fields */ int nbytes; /* number of bytes for sort array */ } *pcount; }; #define SORT_POINT 1 /* index into point connections component */ #define SORT_LINE 2 /* index into line connections component */ #define SORT_POLYLINE 3 /* index into line connections component */ #define SORT_TRI 4 /* index into triangle connections component */ #define SORT_QUAD 5 /* index into quads connections component */ #define SORT_TRI_PTS 6 /* three point indices forming a triangle */ #define SORT_QUAD_PTS 7 /* four point indices forming a quad */ #define SORT_TRI_FLAT 8 /* three point indices plus color index */ #define SORT_QUAD_FLAT 9 /* four point indices plus color index */ /* * For volume elements that we a) sort and b) have to render even if * invalid, determine the validity type. */ #define SORT_INV_TRI_PTS 10 /* three point indices forming a triangle */ #define SORT_INV_QUAD_PTS 11 /* four point indices forming a quad */ #define SORT_INV_TRI_FLAT 12 /* three point indices plus color index */ #define SORT_INV_QUAD_FLAT 13 /* four point indices plus color index */ struct sort { short field; /* index into gather->xfields array */ char type; /* type (one of the SORT_... constants) */ char surface; /* whether it's a surface face */ }; struct sortindex { struct sort *sort; float z; }; struct gather { int cull; /* do/don't cull (e.g. perspective) XXX */ Point min, max; /* bounds to cull clip against */ struct sort *sort; /* beginning of sort array */ struct sort *current; /* current position in sort array */ int nthings; /* number of triangles, etc. seen */ int nfields; /* number of fields seen */ struct xfield *fields; /* array of xfield data structures */ Object clipping; /* clipping object for translucent surfaces */ }; Object _dxfGather(Object o, struct gather *gather, struct tile *tile); /** Gathers all the translucent faces from {\tt r} into {\tt sort} that are visible in the box specified by {\tt min} and {\tt max}, and adds the count of the number of faces gathered to {\tt nfaces}. The faces can then be sorted by $z$ and rendered. (Question: sort by $z$ is only approximately correct; this is ok for small faces in volume rendering, but what about translucent surfaces?) The clipping object, if any, is returned in {\tt clipping}; all volumes and translucent faces in the scene must have the same clipping object. **/ Error _dxf_VolumeIrregular(struct buffer *b, struct gather *gather, int clip); /** DXRender the volume and translucent faces gathered in {\tt gather} into buffer {\tt b}, using the irregular face algorithm. **/ Error _dxf_VolumeRegular(struct buffer *b, struct gather *gather, int clip); /** DXRender the volumes gathered in {\tt gather} into buffer {\tt b}, using a regular volume rendering algorithm. **/ Error _dxf_CompositePlane(struct buffer *b, float osx, float osy, float osz, int clip, float ux, float uy, float uz, float vx, float vy, float vz, Pointer ic, char cstcolors, RGBColor *cmap, Pointer io, char cstopacities, float *omap, float cmul, float omul, int idx, int idy, int inx, int iny); /** Composite a plane of quads. **/ Error _dxf_MergeBackIntoZ(struct buffer *b); /** Merge the back and z buffers; needed for the irregular face algorithm. **/ #define IN_FACE 1 #define IF_OBJECT 2 #define IF_UNION 4 #define IF_INTERSECTION 8 #define D_POS 1 #define D_CON 2 Error _dxf_CopyFace(struct buffer *b, int if_object); Error _dxf_InterferenceObject(struct buffer *buf); Private _dxfGetLights(Object, Camera); Error _dxfFreeLightList(LightList); Error _dxfInitApplyLights(float, float, float, int, float, float, float, int, Pointer, Pointer, RGBColor *, Vector *, LightList, dependency, dependency, RGBColor *, RGBColor *, int, char, char, char, char, char); Error _dxfApplyLights(int *, int *, int); #define FRONTFACING 1 #define BACKFACING 2 int _dxf_zclip_triangles(struct xfield *, int *, int, int *, int, struct xfield *, inv_stat); int _dxf_zclip_quads(struct xfield *, int *, int, int *, int, struct xfield *, inv_stat); extern float _dxd_ubyteToFloat[256]; void _dxf_initUbyteToFloat();