/***********************************************************************/ /* 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" */ /***********************************************************************/ /*********************************************************************/ /* I.B.M. CONFIENTIAL */ /*********************************************************************/ #include #ifndef hwPolygonDrawSB_c_h #define hwPolygonDrawSB_c_h /*---------------------------------------------------------------------------*\ $Source: /home/gda/dxcvs/dx/src/exec/hwrender/starbase/hwPolygonDrawSB.c.h,v $ This code implements unmeshed triangle and quad fields as Starbase polygons. Vertex opacities are not supported by some HP hardware, such as the current CRX-24. In these cases the first vertex opacity of each polygon is applied to the entire polygon. \*---------------------------------------------------------------------------*/ /* sDepths needs to be accessed by polysort() */ static float *sDepths = 0 ; #define DEPTH(Z,p) (Z.x*p.x + Z.y*p.y + Z.z*p.z) #define DEPTH2D(Z,p) (Z.x*p.x + Z.y*p.y) /* make a sort routine called polysort() */ #define QUICKSORT polysort #define TYPE int #define LT(a,b) (sDepths[*(a)] < sDepths[*(b)]) #define GT(a,b) (sDepths[*(a)] > sDepths[*(b)]) #include "qsort.c" /* * CRX-24 opacities seem to be quite different from DX software renderer * at the low end of the scale. A great deal of color resolution seems * to be lost, possibly because of the 12/12 double buffering instead of * a more comfortable 24-bit resolution. The lookup table below * approximates the square root of the opacity up to 0.07, then increases * linearly up to 1.0. */ static float alpha_lookup[] = {.00, .10, .14, .17, .20, .22, .24, .26, .27, .28, .29, .30, .30, .31, .32, .33, .34, .34, .35, .36, .37, .38, .38, .39, .40, .41, .41, .42, .43, .44, .45, .45, .46, .47, .48, .49, .49, .50, .51, .52, .53, .53, .54, .55, .56, .57, .57, .58, .59, .60, .60, .61, .62, .63, .64, .64, .65, .66, .67, .68, .68, .69, .70, .71, .72, .72, .73, .74, .75, .75, .76, .77, .78, .79, .79, .80, .81, .82, .83, .83, .84, .85, .86, .87, .87, .89, .89, .90, .91, .91, .92, .93, .94, .94, .95, .96, .97, .98, .98, .99, 1.00} ; #define LOOKUP(f) alpha_lookup[(int)((f)*100)] #ifdef MJHDEBUG #define DebugMessage() \ { \ int i ; \ float outx, outy, outz ; \ float minx, maxx, miny, maxy, minz, maxz ; \ \ fprintf (stderr, "\nnumber of points: %d", xf->npositions) ; \ if (xf->origConnections_data) \ fprintf (stderr, "\nnumber of connections: %d", xf->origNConnections) ; \ else \ fprintf (stderr, "\nnumber of connections: %d", xf->nconnections) ; \ fprintf (stderr, "\n%d invalid connections", \ xf->invCntns? DXGetInvalidCount(xf->invCntns): 0) ; \ fprintf (stderr, "\ncolors: 0x%x, color_map: 0x%x, dep on pos: %d", \ (int)fcolors, (int)color_map, xf->colorsDep == dep_positions) ; \ fprintf (stderr, "\nopacities: 0x%x, opacity_map: 0x%x, dep on pos: %d", \ (int)opacities, (int)opacity_map, \ xf->opacitiesDep == dep_positions) ; \ fprintf (stderr, "\nnormals: 0x%x, dep on pos: %d", \ (int)normals, xf->normalsDep == dep_positions) ; \ fprintf (stderr, "\nambient, diffuse, specular: %f %f %f", \ xf->attributes.front.ambient, \ xf->attributes.front.diffuse, \ xf->attributes.front.specular) ; \ \ minx = miny = minz = +MAXFLOAT ; \ maxx = maxy = maxz = -MAXFLOAT ; \ \ if (is_2d) \ { \ minz = maxz = 0 ; \ fprintf (stderr, "\n2-dimensional positions") ; \ for (i=0 ; inpositions ; i++) \ { \ if (pnts2d[i].x < minx) minx = pnts2d[i].x ; \ if (pnts2d[i].y < miny) miny = pnts2d[i].y ; \ \ if (pnts2d[i].x > maxx) maxx = pnts2d[i].x ; \ if (pnts2d[i].y > maxy) maxy = pnts2d[i].y ; \ } \ } \ else \ for (i=0 ; inpositions ; i++) \ { \ if (points[i].x < minx) minx = points[i].x ; \ if (points[i].y < miny) miny = points[i].y ; \ if (points[i].z < minz) minz = points[i].z ; \ \ if (points[i].x > maxx) maxx = points[i].x ; \ if (points[i].y > maxy) maxy = points[i].y ; \ if (points[i].z > maxz) maxz = points[i].z ; \ } \ \ transform_point(FILDES, MC_TO_VDC, minx, miny, minz, &outx, &outy, &outz) ; \ fprintf(stderr, "\nmin MC->VDC %9f %9f %9f -> %9f %9f %9f", \ minx, miny, minz, outx, outy, outz) ; \ \ transform_point(FILDES, MC_TO_VDC, maxx, maxy, maxz, &outx, &outy, &outz) ; \ fprintf(stderr, "\nmax MC->VDC %9f %9f %9f -> %9f %9f %9f", \ maxx, maxy, maxz, outx, outy, outz) ; \ } #else #define DebugMessage() {} #endif /* DEBUG */ int tdmPolygonDraw (tdmPortHandleP portHandle, xfieldT *xf, int buttonUp) { Point *points ; Vector *normals ; RGBColor *fcolors, *color_map ; float *opacities, *opacity_map ; int nshapes, *connections, *sortArray = 0, status, mod ; int cOffs, nOffs, oOffs, numPolys, vertex_flags, facet_flags ; int type, rank, shape, is_2d ; struct p2d {float x, y ;} *pnts2d ; char *cache_id ; enum approxE approx ; register int i, j, vsize, pstride, dP, dV, nverts, fsize, dF ; DEFPORT(portHandle) ; ENTRY(("tdmPolygonDraw(0x%x, 0x%x, %d)", portHandle, xf, buttonUp)); /* * Extract required data from the xfield. */ if (is_2d = IS_2D (xf->positions_array, type, rank, shape)) pnts2d = (struct p2d *) DXGetArrayData(xf->positions_array) ; else points = (Point *) DXGetArrayData(xf->positions_array) ; color_map = (RGBColor *) DXGetArrayData(xf->cmap_array) ; opacity_map = (float *) DXGetArrayData(xf->omap_array) ; if (DXGetArrayClass(xf->fcolors_array) == CLASS_CONSTANTARRAY) fcolors = (Pointer) DXGetArrayEntry(xf->fcolors, 0, NULL) ; else fcolors = (Pointer) DXGetArrayData(xf->fcolors_array) ; if (DXGetArrayClass(xf->opacities_array) == CLASS_CONSTANTARRAY) opacities = (Pointer) DXGetArrayEntry(xf->opacities, 0, NULL) ; else opacities = (Pointer) DXGetArrayData(xf->opacities_array) ; if (DXGetArrayClass(xf->normals_array) == CLASS_CONSTANTARRAY) normals = (Pointer) DXGetArrayEntry(xf->normals, 0, NULL) ; else normals = (Pointer) DXGetArrayData(xf->normals_array) ; if (xf->origConnections_array) { /* connections array had been transformed into strips */ connections = (int *) DXGetArrayData (xf->origConnections_array) ; nshapes = xf->origNConnections ; } else { connections = (int *) DXGetArrayData (xf->connections_array) ; nshapes = xf->nconnections ; } if (buttonUp) { mod = xf->attributes.buttonUp.density ; approx = xf->attributes.buttonUp.approx ; } else { mod = xf->attributes.buttonDown.density ; approx = xf->attributes.buttonDown.approx ; } DebugMessage() ; /* * Set up rendering attributes. */ switch (approx) { case approx_dots: if (xf->colorsDep == dep_field && mod == 1 && !xf->invPositions && !(_dxf_isFlagsSet(_dxf_attributeFlags(&xf->attributes),BEING_CLIPPED))) { /* fast dot approximation */ PRINT(("using polymarker")); marker_type (FILDES, 0) ; SET_COLOR (marker_color, 0) ; if (is_2d) polymarker2d (FILDES, (float *)pnts2d, xf->npositions, 0) ; else polymarker3d (FILDES, (float *)points, xf->npositions, 0) ; EXIT(("OK")); return OK ; } /* * The INT_POINT interior fill style, for position-dependent * colors, is faster than using polymarkers since polymarkers do * not allow colors imbedded within the coordinate list. */ shade_mode (FILDES, CMAP_FULL, FALSE) ; hidden_surface (FILDES, FALSE, FALSE) ; alpha_transparency (FILDES, 0, 0, 0.0, 0.0) ; interior_style (FILDES, INT_POINT, FALSE) ; break ; case approx_lines: if (xf->colorsDep != dep_field) /* * Dense fields of varying colors are visually confusing * without hidden surface, even with wireframe approximation. */ hidden_surface (FILDES, TRUE, FALSE) ; break ; case approx_none: default: if (normals) { /* turn on lighting */ surface_coefficients (FILDES, xf->attributes.front.ambient, xf->attributes.front.diffuse, xf->attributes.front.specular) ; shade_mode (FILDES, CMAP_FULL, TRUE) ; } else shade_mode (FILDES, CMAP_FULL, FALSE) ; if (opacities) { if (xf->opacitiesDep == dep_field) { float opacity ; if (opacity_map) opacity = opacity_map[*(char *)opacities] ; else opacity = *opacities ; alpha_transparency (FILDES, 1, 1, LOOKUP(opacity), 1.0) ; } } else alpha_transparency (FILDES, 0, 0, 0.0, 0.0) ; hidden_surface (FILDES, TRUE, FALSE) ; interior_style (FILDES, INT_SOLID, FALSE) ; break ; } if (xf->colorsDep == dep_field) { /* render field in constant color */ cache_id = CpfPolygon ; SET_COLOR(fill_color, 0) ; SET_COLOR(line_color, 0) ; } else if (approx == approx_flat) { /* leave out normals to achieve flat shading */ cache_id = CpcPolygon ; } else { /* keep normals if supplied */ cache_id = CpvPolygon ; } /* * Generate Starbase polygons and render them. */ vertex_flags = 0 ; facet_flags = UNIT_NORMALS ; vsize = 3 ; /* number of floats of data per vertex */ fsize = 0 ; /* number of floats of data per facet */ numPolys = nshapes/mod ; /* number of polygons to draw */ pstride = PolygonSize*mod ; /* number of indices to next polygon */ nverts = (approx == approx_lines ? PolygonSize+1 : PolygonSize) ; PRINT(("cache_id = %s", cache_id)); PRINT(("%d polygons", numPolys)); if (fcolors && xf->colorsDep != dep_field) if (xf->colorsDep == dep_positions) { /* vertex has at least 6 floats, with color at float 3 */ vsize = 6 ; cOffs = 3 ; vertex_flags |= VERTEX_COLOR ; } else { /* facet has at least 3 floats, with color at float 0 */ fsize = 3 ; cOffs = 0 ; facet_flags |= FACET_COLOR ; } if (normals && approx != approx_flat) /* * Flat shading (approx_flat, now defunct) is forced by withholding * normals. */ if (xf->normalsDep == dep_positions) { /* vertex has 3 more floats, with normal 3rd from end */ vsize += 3 ; nOffs = vsize - 3 ; vertex_flags |= VERTEX_NORMAL ; } else { /* facet has 3 more floats, with normal 3rd from end */ fsize += 3 ; nOffs = fsize - 3 ; facet_flags |= FACET_NORMAL ; } #if (DXD_HW_ALPHA_POSNS == 1) /* hardware supports alpha interpolation */ if (opacities && xf->opacitiesDep == dep_positions && approx == approx_none) { /* vertex has one more float, with opacity at end */ vsize += 1 ; oOffs = vsize - 1 ; vertex_flags |= VERTEX_BLEND ; } #endif sortArray = (int *) tdmAllocate(numPolys*sizeof(int)) ; if (!sortArray) DXErrorGoto(ERROR_INTERNAL, "#13000") ; if (opacities && approx == approx_none) { /* compute depths and sort back-to-front */ Vector Z ; float II[4][4] ; float I[4][4] = {{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,0,1}} ; sDepths = (float *) tdmAllocate(numPolys*sizeof(float)) ; if (!sDepths) DXErrorGoto(ERROR_INTERNAL, "#13000") ; /* get view xform (Starbase thinks it's the modeling xform) */ transform_points (FILDES, (float *)I, (float *)II, 4, 1) ; Z.x = II[0][2] ; Z.y = II[1][2] ; Z.z = II[2][2] ; if (is_2d) for (i=0, dP=0 ; iinvCntns && !DXIsElementValid(xf->invCntns, i)) /* skip invalid connections */ continue ; dP = i * PolygonSize ; clist = cbuff ; if ((facet_flags & FACET_NORMAL) && approx != approx_lines) { /* first vertex is really facet normal */ if (xf->normalsDep == dep_positions) *(Vector *)clist = normals[connections[dP]] ; else if (xf->normalsDep == dep_connections) *(Vector *)clist = normals[i] ; else /* dep field */ *(Vector *)clist = *normals ; clist += vsize ; } if (facet_flags & FACET_COLOR) { if (approx == approx_lines) SET_COLOR (line_color, i) ; else SET_COLOR (fill_color, i) ; } if (opacities && approx == approx_none) { float a ; #if (DXD_HW_ALPHA_POSNS == 0) if (xf->opacitiesDep == dep_positions) { /* * Position-dependent opacities are not supported by the * hardware, so approximate the rendering by applying the * opacity of first vertex to the entire facet. */ if (opacity_map) a = opacity_map[((char *)opacities)[connections[dP]]]; else a = opacities[connections[dP]] ; alpha_transparency (FILDES, 1, 1, LOOKUP(a), 1.0) ; } #endif if (xf->opacitiesDep == dep_connections) { if (opacity_map) a = opacity_map[((char *)opacities)[i]] ; else a = opacities[i] ; alpha_transparency (FILDES, 1, 1, LOOKUP(a), 1.0) ; } } /* copy vertex data */ for (vi=0 ; viz = 0 ; } else *(Point *)(clist) = points[connections[v]] ; clist+=3 ; if (vertex_flags & VERTEX_COLOR) { /* copy vertex color into clist */ if (color_map) *(RGBColor *)(clist) = color_map[((char *)fcolors)[connections[v]]] ; else *(RGBColor *)(clist) = fcolors[connections[v]] ; clist+=3 ; } if (vertex_flags & VERTEX_NORMAL) { /* copy vertex normal into clist */ *(Vector *)(clist) = normals[connections[v]] ; clist+=3 ; } if (vertex_flags & VERTEX_BLEND) /* copy vertex opacity into clist */ if (opacity_map) *clist++ = LOOKUP(opacity_map[((char *)opacities)[connections[v]]]) ; else *clist++ = LOOKUP(opacities[connections[v]]) ; } if (approx == approx_lines) { polyline_with_data3d (FILDES, cbuff, nverts, vsize-3, vertex_flags, NULL) ; } else { polygon_with_data3d (FILDES, cbuff, nverts, vsize-3, vertex_flags, facet_flags & ~FACET_COLOR) ; } } status = OK ; goto done ; error: status = ERROR ; done: if (sDepths) tdmFree(sDepths) ; if (sortArray) tdmFree(sortArray) ; sDepths = 0 ; sortArray = 0 ; hidden_surface(FILDES, FALSE, FALSE) ; EXIT(("%s", status==OK ? "": "ERROR")); return status ; } #endif /* hwPolygonDrawSB_c_h */