/***********************************************************************/ /* 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 /*---------------------------------------------------------------------------*\ $Source: /home/gda/dxcvs/dx/src/exec/hwrender/gl/hwPortUtil.c,v $ \*---------------------------------------------------------------------------*/ #ifndef HELPERCODE #include #define X_H #define Cursor glCursor #define String glString #define Boolean glBoolean #define Object glObject #include #undef Object #undef Boolean #undef String #undef Cursor #undef X_H #include "hwDeclarations.h" #include "hwPortLayer.h" #include "hwXfield.h" #include "hwWindow.h" #include "hwPortGL.h" #include "hwTmesh.h" #include "hwSort.h" #define String dxString #define Object dxObject #define Angle dxAngle #define Matrix dxMatrix #define Screen dxScreen #define Boolean dxBoolean #include "internals.h" #undef String #undef Object #undef Angle #undef Matrix #undef Screen #undef Boolean #define TIMER(s) finish(); DXMarkTime(s); #include "hwDebug.h" #if 0 #define DXGetArrayEntry(x,y,z) (&zeroFloat) static float zeroFloat[] = {0.57, 0.57, 0.57}; #endif #ifdef DOPV #include "pv/pv.h" #else #define PHASE_START(x) {} #define PHASE_END(y) {} #endif #define NOTUSED 0 typedef void (*helperFunc) (xfieldP xf, int posPerConn, int ctIndex, int *translation, float *rgba); static helperFunc getHelper(dependencyT colorsDep, dependencyT normalsDep, dependencyT opacitiesDep, int texture); static Error points (xfieldP xf, helperFunc helper, int firstConnection, int lastConnection, int face, enum approxE approx, int skip); static Error bbox (xfieldP xf); static void _deleteGLObject(xfieldP xf); #define RENDER_OPAQUE 1 #define RENDER_TRANSPARENT 2 #define SENDPOSITION(offset) \ { \ float *position; \ position = (float*)DXGetArrayEntry(xf->positions,offset,fscratch); \ if(xf->shape < 3) \ v2f(position); /* gl default z = 0.0 if 2d data */ \ else \ v3f(position); \ } #ifdef sgi #define SENDUV(offset) \ { \ float *uv ; \ uv = (float *)DXGetArrayEntry(xf->uv,offset,uvscratch) ; \ t2f(uv) ; \ } #endif #define OPACITY(offset) \ ((xf->nomap) ? \ *(float *)DXGetArrayEntry(xf->omap, \ *(char *)DXGetArrayEntry(xf->opacities, \ offset, \ &iscratch), \ fscratch) \ : \ *(float *)DXGetArrayEntry(xf->opacities, offset, fscratch)) #define SENDOPACITY(offset) \ if((xf->opacitiesDep != dep_none && GETOPACITY(0) < .75) || \ xf->attributes.flags & CONTAINS_VOLUME) \ setpattern(PATTERN_INDEX) #define SENDNORMAL(offset) \ { \ Vector normal; \ normal = *(Vector*)DXGetArrayEntry(xf->normals,offset,fscratch); \ n3f((float*)&normal); \ } #define SENDSPECCOLOR() \ { \ RGBColor rgbspec; \ rgbspec.r = rgbspec.g = rgbspec.b = \ xf->attributes.front.specular; \ lmcolor (LMC_SPECULAR); \ c3f((float *)&rgbspec); \ } #define GETCOLOR(offset) \ { \ Vector rgbvec; \ \ if(xf->ncmap) \ rgbvec = *(Vector*)DXGetArrayEntry(xf->cmap, \ *(ubyte *)DXGetArrayEntry(xf->fcolors, \ offset, \ &iscratch), \ fscratch); \ else \ rgbvec = *(Vector*)DXGetArrayEntry(xf->fcolors,offset,fscratch); \ \ rgba[0] = rgbvec.x; \ rgba[1] = rgbvec.y; \ rgba[2] = rgbvec.z; \ } #define GETOPACITY(offset) \ { \ rgba[3] = OPACITY(offset); \ } #define SENDLITCOLOR(transp) \ { \ lmcolor(LMC_AD); \ if (transp) \ c4f(rgba); \ else \ c3f(rgba); \ } #define SENDCOLOR(transp) \ { \ lmcolor(LMC_COLOR); \ if (transp) \ c4f(rgba); \ else \ c3f(rgba); \ } #define PERFIELD(lit, transp) \ { \ int _lit = lit && xf->normalsDep != dep_none; \ int sendc = (xf->colorsDep == dep_field && \ (!transp || xf->opacitiesDep == dep_field)); \ \ if (xf->colorsDep == dep_field) \ GETCOLOR(0); \ \ if (transp && xf->opacitiesDep == dep_field) \ GETOPACITY(0); \ \ if(_lit) { \ SENDSPECCOLOR(); \ lmcolor(LMC_AD); \ if(xf->normalsDep == dep_field) \ SENDNORMAL(0); \ if (sendc) \ SENDLITCOLOR(transp); \ } else { \ lmcolor(LMC_COLOR); \ if (sendc) \ SENDCOLOR(transp); \ } \ \ if (doesPattern) \ if ((xf->opacitiesDep != dep_none) && (OPACITY(0) < 0.75)) \ setpattern(PATTERN_INDEX); \ } #define ENDPERFIELD() \ if (doesPattern) setpattern(0); /* * For cubes each face of the cube is drawn as a quad with * face = [4..9] and posPerCon = 4. * For Tetras, triangles with face=[0..3] and posPerCon = 3 */ static int faceList[][4] = { {0,1,2,0}, /* Tetra front */ /* <- also all triangles */ {1,3,2,0}, /* Tetra right */ {0,2,3,0}, /* Tetra left */ {0,1,3,0}, /* Tetra bottom */ {2,3,1,0}, /* Cube front */ /* <- also all quads */ {0,1,5,4}, /* Cube bottom */ {0,4,6,2}, /* Cube left */ {1,5,7,3}, /* Cube right */ {3,7,6,2}, /* Cube top */ {4,5,7,6}, /* Cube back */ }; #define TRANSLATE(new,old,face) \ { \ int i; \ for(i=xf->posPerConn-1;i>=0;i--) { \ new[i] = old[faceList[face][i]]; \ } \ } #define GET_CONNECTION(ctIndex) \ { \ static int cscratch[8]; \ static int *connection; \ \ connection = (int*)DXGetArrayEntry(xf->connections,ctIndex,cscratch); \ TRANSLATE(translation,connection,face); \ } static int doesTrans, doesPattern; static Error dots (xfieldP xf, enum approxE approx, int skip) { static float fscratch[3]; static int iscratch; int p,i; helperFunc helper; float rgba[4]; PERFIELD(0, 0); for(p=0;pnpositions;) { bgnpoint(); for(i=0;pnpositions && i<256;) { if(! xf->invPositions || ! DXIsElementInvalidSequential(xf->invPositions, p)) { SENDCOLOR(p); SENDPOSITION(p); i++; p+= skip; } else { p++; } } endpoint(); } EXIT(("OK")); return OK; } static Error translucentPoints (xfieldP xf, helperFunc helper, SortD list, int n, int face, enum approxE approx, int skip) { static int translation[8]; static float fscratch[3]; static int iscratch; int i, c, c1; dependencyT odep = xf->opacitiesDep; dependencyT cdep = xf->colorsDep; float opacity; float rgba[4]; PERFIELD(0, 1); if (!n) return OK; bgnpoint(); for (c = 0; c < n; c ++) { if (xf->connections) c1 = *(int*)DXGetArrayEntry(xf->connections, list[c].poly,(Pointer)iscratch); else c1 = list[c].poly; if (odep == dep_connections) GETOPACITY(list[c].poly); if (cdep == dep_connections) GETCOLOR(list[c].poly); (*helper)(xf,1,list[c].poly,&c1,rgba); } endpoint(); ENDPERFIELD(); return OK; } static Error points (xfieldP xf, helperFunc helper, int firstConnection, int lastConnection, int face, enum approxE approx, int skip) { static int translation[8]; static float fscratch[3]; static int iscratch; int c, i=0, translu = 0; dependencyT odep = xf->opacitiesDep; dependencyT cdep = xf->colorsDep; float opacity; float rgba[4]; ENTRY(("points(0x%x, 0x%x, %d, %d, %d, %d, %d)", xf, helper, firstConnection, lastConnection, face, approx, skip)); PERFIELD(0, 0); if (doesTrans) { switch(odep = xf->opacitiesDep) { case dep_none: translu = 0; break; case dep_field: translu = OPACITY(0) < 1.0f; break; default: break; } if (! translu) { for(c=firstConnection;cinvCntns || ! DXIsElementInvalid(xf->invCntns,c)) { int c1; if (xf->connections) c1 = *(int*)DXGetArrayEntry(xf->connections, c, (Pointer)iscratch); else c1 = c; if(xf->invPositions && DXIsElementInvalid(xf->invPositions, c1)) break; if (odep == dep_connections) translu |= OPACITY(c) < 1.0f; else if (odep == dep_positions) translu |= OPACITY(c1) < 1.0f; if (! translu) { if (i++ == 0) bgnpoint(); if (cdep == dep_connections) GETCOLOR(c1); (*helper)(xf,1,c,&c1,rgba); } } } if (i) endpoint(); } } else { for(c=firstConnection;cinvCntns || ! DXIsElementInvalid(xf->invCntns,c)) { int c1; if (xf->connections) c1 = *(int*)DXGetArrayEntry(xf->connections, c, (Pointer)iscratch); else c1 = c; if(xf->invPositions && DXIsElementInvalid(xf->invPositions, c1)) break; if (i++ == 0) bgnpoint(); if (cdep == dep_connections) GETCOLOR(c1); (*helper)(xf,xf->posPerConn,c,translation,rgba); } } if (i) endpoint(); } ENDPERFIELD(); EXIT(("OK")); return OK; error: return ERROR; } static int noLines = 0; static Error translucentLines (xfieldP xf, helperFunc helper, SortD list, int n, int face, enum approxE approx, int skip) { static int translation[8]; static float fscratch[3]; static int iscratch; int c; dependencyT odep = xf->opacitiesDep; dependencyT cdep = xf->colorsDep; float opacity; float rgba[4]; if (noLines) return OK; PERFIELD(0, 1); for(c = 0; c < n; c++) { if(!xf->invCntns || ! DXIsElementInvalid(xf->invCntns,c)) { bgnline(); GET_CONNECTION(list[c].poly); if (odep == dep_connections) GETOPACITY(list[c].poly); if (cdep == dep_connections) GETCOLOR(list[c].poly); (*helper)(xf,xf->posPerConn,list[c].poly,translation,rgba); endline(); } } ENDPERFIELD(); return OK; } static Error lines (xfieldP xf, helperFunc helper, int firstConnection, int lastConnection,int face, enum approxE approx, int skip) { static int translation[8]; static float fscratch[3]; static int iscratch; int c, translu = 0; int doliting = _dxf_xfieldAttributes(xf)->shade ? 1 : 0; dependencyT odep = xf->opacitiesDep; dependencyT cdep = xf->colorsDep; float opacity; float rgba[4]; if (noLines) return OK; ENTRY(("lines(0x%x, 0x%x, %d, %d, %d, %d, %d)", xf, helper, firstConnection, lastConnection, face, approx, skip)); if (approx == approx_box) { EXIT(("calling bbox")); return bbox(xf); } PERFIELD(doliting, 0); if (doesTrans) { switch(odep = xf->opacitiesDep) { case dep_none: translu = 0; break; case dep_field: translu = OPACITY(0) < 1.0f; break; default: break; } for(c=firstConnection;cinvCntns || ! DXIsElementInvalid(xf->invCntns,c)) { GET_CONNECTION(c); if (odep == dep_connections) translu |= OPACITY(c) < 1.0f; else if (odep == dep_positions) translu |= (OPACITY(translation[0]) < 1.0f) || (OPACITY(translation[1]) < 1.0f); if (! translu) { if (cdep == dep_connections) GETCOLOR(c); bgnline(); (*helper)(xf,xf->posPerConn,c,translation,rgba); endline(); } } } } else { for(c=firstConnection;cinvCntns || ! DXIsElementInvalid(xf->invCntns,c)) { bgnline(); GET_CONNECTION(c); (*helper)(xf,xf->posPerConn,c,translation,rgba); endline(); } } } for(c=firstConnection;cinvCntns || ! DXIsElementInvalid(xf->invCntns,c)) { GET_CONNECTION(c); (*helper)(xf,xf->posPerConn,c,translation,rgba); } } ENDPERFIELD(); EXIT(("")); return OK; error: return ERROR; } #define MAXGLPLINEVERT 100 static Error polylines (xfieldP xf, helperFunc helper, enum approxE approx, int skip) { static float fscratch[3]; static int iscratch; int c, i; int start, end, knt, max, thisknt; int doliting = _dxf_xfieldAttributes(xf)->shade ? 1 : 0; dependencyT cdep = xf->colorsDep; float opacity; float rgba[4]; if (approx == approx_box) { EXIT(("calling bbox")); return bbox(xf); } PERFIELD(doliting, 0); if (skip > 1) { for(c = 0; c < xf->npolylines; c ++) { if(!xf->invCntns || ! DXIsElementInvalid(xf->invCntns,c)) { start = xf->polylines[c]; end = (c == xf->npolylines-1) ? xf->nedges : xf->polylines[c+1]; knt = (end - start) - 1; if (cdep == dep_polylines) GETCOLOR(c); bgnline(); while (knt > 0) { thisknt = (knt > max) ? max : knt; (*helper)(xf, 2, c, xf->edges+start,rgba); start += skip; knt -= skip; } endline(); } } } else { max = MAXGLPLINEVERT; for(c = 0; c < xf->npolylines; c ++) { if(!xf->invCntns || ! DXIsElementInvalid(xf->invCntns,c)) { start = xf->polylines[c]; end = (c == xf->npolylines-1) ? xf->nedges : xf->polylines[c+1]; knt = end - start; if (cdep == dep_polylines) GETCOLOR(c); bgnline(); while (knt) { thisknt = (knt > max) ? max : knt; (*helper)(xf, thisknt, c, xf->edges+start,rgba); start += (thisknt-1); knt -= (thisknt-1); if(thisknt == 1) knt = 0; } endline(); } } } ENDPERFIELD(); EXIT(("")); return OK; } static Error closedlines (xfieldP xf, helperFunc helper, int firstConnection, int lastConnection,int face, enum approxE approx, int skip) { static int translation[8]; static float fscratch[3]; static int iscratch; int c; dependencyT cdep = xf->colorsDep; float opacity; float rgba[4]; ENTRY(("closedlines(0x%x, 0x%x, %d, %d, %d, %d, %d)", xf, helper, firstConnection, lastConnection, face, approx, skip)); if (approx == approx_box) { EXIT(("calling bbox")); return bbox(xf); } PERFIELD(0, 0); #ifdef sgi if(xf->texture) /* (:Q= */ { static float Holder[3] = { 0.5f, 0.7f, 1.0f }; c3f(Holder); } #endif for(c=firstConnection;cinvCntns || ! DXIsElementInvalid(xf->invCntns,c)) { GET_CONNECTION(c); bgnclosedline(); if (cdep == dep_connections) GETCOLOR(c); (*helper)(xf,xf->posPerConn,c,translation,rgba); endclosedline(); } } ENDPERFIELD(); EXIT(("OK")); return OK; } static Error polygons (xfieldP xf, helperFunc helper, int firstConnection, int lastConnection, int face, enum approxE approx, int skip) { static int translation[8]; static float fscratch[3]; static int iscratch; int c; int translu = 0; dependencyT odep = xf->opacitiesDep; dependencyT cdep = xf->colorsDep; float opacity; float rgba[4]; ENTRY(("polygons(0x%x, 0x%x, %d, %d, %d, %d, %d)", xf, helper, firstConnection, lastConnection, face, approx, skip)); switch(approx) { case approx_dots: EXIT(("calling dots")); return dots(xf,approx,skip); break; case approx_box: EXIT(("calling bbox")); return bbox(xf); break; case approx_lines: helper = getHelper(xf->colorsDep,dep_none,dep_none,NULL); EXIT(("calling closedlines")); return closedlines(xf,helper,0,xf->nconnections,face,approx,skip); break; } if (doesTrans) { switch(odep) { case dep_none: translu = 0; break; case dep_field: translu = OPACITY(0) < 1.0f; break; default: break; } for(c=firstConnection;cinvCntns || ! DXIsElementInvalid(xf->invCntns,c)) { GET_CONNECTION(c); if (odep == dep_connections) { translu = OPACITY(c) < 1.0f; } else if (odep == dep_positions) { int i; for (i = 0; !translu && i < xf->posPerConn; i++) if (OPACITY(translation[i]) < 1.0f) translu = 1; } if (! translu) { bgnpolygon(); PERFIELD(1, 0); if (cdep == dep_connections) GETCOLOR(c); (*helper)(xf,xf->posPerConn,c,translation,rgba); endpolygon(); } } } } else { PERFIELD(1, 0); for(c=firstConnection;cinvCntns || ! DXIsElementInvalid(xf->invCntns,c)) { GET_CONNECTION(c); if (cdep == dep_connections) GETCOLOR(c); bgnpolygon(); (*helper)(xf,xf->posPerConn,c,translation,rgba); endpolygon(); } } } ENDPERFIELD(); EXIT(("OK")); return OK; error: return ERROR; } static Error translucentPolygons (xfieldP xf, helperFunc helper, SortD list, int n, int face, enum approxE approx, int skip) { static int translation[8]; static float fscratch[3]; static int iscratch; int c; int translu = 0; dependencyT odep = xf->opacitiesDep; dependencyT cdep = xf->colorsDep; float rgba[4]; float opacity; PERFIELD(1, 1); for(c = 0; c < n; c ++) { if(!xf->invCntns || ! DXIsElementInvalid(xf->invCntns,c)) { GET_CONNECTION(list[c].poly); bgnpolygon(); (*helper)(xf,xf->posPerConn,list[c].poly,translation,rgba); endpolygon(); } } ENDPERFIELD(); EXIT(("OK")); return OK; error: return ERROR; } #define NOTUSED 0 static Error tmeshlines (xfieldP xf, helperFunc helper, enum approxE approx, int skip); static Error tmesh (xfieldP xf, helperFunc helper, enum approxE approx, int skip) { static int *translation,*strip; static float fscratch[3]; static int iscratch; int count; int meshI,i; int skipDelta; InvalidComponentHandle tmpic,tmpip; struct { int start; int count; } *meshes; dependencyT odep = xf->opacitiesDep; dependencyT cdep = xf->colorsDep; float opacity; float rgba[4]; ENTRY(("tmesh(0x%x, 0x%x, %d, %d)", xf, helper, approx, skip)); tmpic = xf->invCntns; tmpip = xf->invPositions; xf->invCntns = NULL; xf->invPositions = NULL; switch(approx) { case approx_dots: if (tmpic || tmpip) { helper = getHelper(xf->colorsDep,dep_none,dep_none,NULL); points (xf, helper,0,xf->nconnections,0,approx,skip); goto done; } else { dots(xf,approx,skip); goto done; } break; case approx_box: bbox(xf); goto done; break; case approx_lines: helper = getHelper(xf->colorsDep,dep_none,dep_none,NULL); tmeshlines(xf, helper, approx, skip); goto done; break; } PERFIELD(1, 0); #ifdef sgi if(xf->texture) glStartTexture(xf); #endif /* NOTE: * The code below is optimized for tmesh. It depends on two * qualities of our tmesh generator. * 1) tmeshes are NOT generated for Npc or Cpc * 2) tmeshes create a regular array in xf->connections_array; */ translation = DXGetArrayData(xf->connections_array); if(!(meshes = DXGetArrayData(xf->meshes))) goto error; /* Not Skipping */ if(skip <= 1) { for(meshI=0;meshInmeshes;meshI++) { bgntmesh(); PERFIELD(1, 0); #if defined(DXD_HW_TMESH_SWAP_OK) { int remainder = meshes[meshI].count; int *startPtr,*endPtr; startPtr = endPtr = &translation[meshes[meshI].start]; { for(i=0;inmeshes;meshI++) { strip = &translation[meshes[meshI].start]; for(count=skipDelta; count < meshes[meshI].count-2; count += skipDelta) { bgnpolygon(); #if defined(DXD_HW_TMESH_SWAP_OK) { int tri[3]; int i,j; for (i=0,j=0;i<3;i++,j++) { /* if we have a swap in the triangle */ if (strip[count+i] < 0) { if(i==1) /* swap in middle of tri requires special treatment */ tri[0] = strip[count-1]; j++; } tri[i] = strip[count+j]; } (*helper)(xf,3,NOTUSED,tri,rgba); } #else (*helper)(xf,3,NOTUSED,&strip[count],rgba); #endif endpolygon(); skipDelta = skip; } skipDelta = count - (meshes[meshI].count-2); } } ENDPERFIELD(); done: #ifdef sgi if(xf->texture) glEndTexture(); #endif xf->invCntns = tmpic; xf->invPositions = tmpip; EXIT(("OK")); return OK; error: /* XXX print error message */ ENDPERFIELD(); xf->invCntns = tmpic; xf->invPositions = tmpip; EXIT(("ERROR")); return ERROR; } static Error tmeshlines (xfieldP xf, helperFunc helper, enum approxE approx, int skip) { static int *translation,*strip; static int edge[MaxTstripSize+1]; static float fscratch[3]; static int iscratch; int count; int meshI; int edgeI; int skipDelta; dependencyT odep; float opacity; struct { int start; int count; } *meshes; float rgba[4]; ENTRY(("tmeshlines(0x%x, 0x%x, %d, %d)", xf, helper, approx, skip)); /* NOTE: * The code below is optimized for tmesh. It depends on two * qualities of our tmesh generator. * 1) tmeshes are NOT generated for Npc or Cpc * 2) tmeshes create a regular array in xf->connections_array; */ translation = DXGetArrayData(xf->connections_array); PERFIELD(0, 0); #ifdef sgi if(xf->texture) /* (:Q= */ { static float Holder[3] = { 0.5f, 0.7f, 1.0f }; c3f(Holder); } #endif if(!(meshes = DXGetArrayData(xf->meshes))) goto error; if(skip <= 1) { /* NOT skipping */ for(meshI=0;meshInmeshes;meshI++) { strip = &translation[meshes[meshI].start]; /* Draw zigzap */ #if defined(DXD_HW_TMESH_SWAP_OK) for(edgeI=0,count=0; count < meshes[meshI].count; count++, edgeI++) { if(strip[count] < 0) /* for swap */ edge[edgeI] = edge[edgeI-2]; else edge[edgeI] = strip[count]; } if(edgeI > 1) { bgnline(); (*helper)(xf,edgeI,NOTUSED,edge,rgba); endline(); } #else bgnline(); (*helper)(xf, meshes[meshI].count, NOTUSED, strip,rgba); endline(); #endif /* close boundary of zigzags with even indices */ for(edgeI=0,count=0; count < meshes[meshI].count; count+=2) { if(strip[count] < 0) continue; /* for swap */ edge[edgeI++] = strip[count]; } if(edgeI > 1){ bgnline(); (*helper)(xf,edgeI,NOTUSED,edge,rgba); endline(); } /* close boundary of zigzags with odd indices */ for(edgeI=0,count=1; count < meshes[meshI].count; count+=2) { if(strip[count] < 0) continue; /* for swap */ edge[edgeI++] = strip[count]; } if(edgeI > 1) { bgnline(); (*helper)(xf,edgeI,NOTUSED,edge,rgba); endline(); } } } else { /* skipping */ skipDelta = 0; for(meshI=0;meshInmeshes;meshI++) { strip = &translation[meshes[meshI].start]; for(count=skipDelta; count < meshes[meshI].count-2; count += skipDelta) { bgnclosedline(); #if defined(DXD_HW_TMESH_SWAP_OK) { int tri[3]; int i,j; for (i=0,j=0;i<3;i++,j++) { /* if we have a swap in the triangle */ if (strip[count+i] < 0) { if(i==1)/* swap in middle of tri requires special treatment */ tri[0] = strip[count-1]; j++; } tri[i] = strip[count+j]; } (*helper)(xf,3,NOTUSED,tri,rgba); } #else (*helper)(xf,3,NOTUSED,&strip[count],rgba); #endif endclosedline(); skipDelta = skip; } skipDelta = count - (meshes[meshI].count-2); } } ENDPERFIELD(); EXIT(("OK")); return OK; error: /* XXX print error message */ ENDPERFIELD(); EXIT(("ERROR")); return ERROR; } static Error plines (xfieldP xf, helperFunc helper, enum approxE approx, int skip) { static int *translation,*strip; static int edge[MaxTstripSize+1]; static float fscratch[3]; static int iscratch; int count; int start; int step; int meshI; int edgeI; int skipDelta; int doliting = _dxf_xfieldAttributes(xf)->shade ? 1 : 0; dependencyT odep; float opacity; struct { int start; int count; } *meshes; float rgba[4]; ENTRY(("plines(0x%x, 0x%x, %d, %d)", xf, helper, approx, skip)); if (approx == approx_box) { EXIT(("calling bbox")); return bbox(xf); } translation = DXGetArrayData(xf->connections_array); PERFIELD(doliting, 0); if(!(meshes = DXGetArrayData(xf->meshes))) goto error; if(skip <= 1) { /* NOT skipping */ for(meshI=0;meshInmeshes;meshI++) { #if 0 count = meshes[meshI].count; start = meshes[meshI].start; for(step = 0; step < count; step += MAXGLPLINEVERT) { bgnline(); (*helper)(xf, step + MAXGLPLINEVERT < count ? MAXGLPLINEVERT : count - step, NOTUSED, &translation[step+start],rgba); endline(); } #else bgnline(); (*helper)(xf, meshes[meshI].count, NOTUSED, &translation[meshes[meshI].start],rgba); endline(); #endif } } else { /* skipping */ skipDelta = 0; for(meshI=0;meshInmeshes;meshI++) { strip = &translation[meshes[meshI].start]; for(count=skipDelta; count < meshes[meshI].count-1; count += skipDelta) { bgnline(); (*helper)(xf,2,NOTUSED,&strip[count],rgba); skipDelta = skip; endline(); } skipDelta = count - (meshes[meshI].count-1); } } ENDPERFIELD(); EXIT(("OK")); return OK; error: /* XXX print error message */ ENDPERFIELD(); EXIT(("ERROR")); return ERROR; } static Error bbox (xfieldP xf) { static float fscratch[3]; static int iscratch; int p,i; static float yellow[] = {1.0, 1.0, 0.0}; dependencyT odep; float opacity; float rgba[4]; ENTRY(("bbox(0x%x)", xf)); PERFIELD(0, 0); lmcolor(LMC_COLOR); c3f((float*)&yellow[0]); bgnline(); v3f((float*)&xf->box[0]); v3f((float*)&xf->box[1]); v3f((float*)&xf->box[3]); v3f((float*)&xf->box[2]); v3f((float*)&xf->box[0]); v3f((float*)&xf->box[4]); v3f((float*)&xf->box[5]); v3f((float*)&xf->box[7]); v3f((float*)&xf->box[6]); v3f((float*)&xf->box[4]); endline(); bgnline(); v3f((float*)&xf->box[2]); v3f((float*)&xf->box[6]); endline(); bgnline(); v3f((float*)&xf->box[3]); v3f((float*)&xf->box[7]); endline(); bgnline(); v3f((float*)&xf->box[1]); v3f((float*)&xf->box[5]); endline(); EXIT(("OK")); return OK; } #ifdef sgi static void TNnone (xfieldP xf, int posPerConn, int ctIndex, int *translation) { static float fscratch[3]; static float uvscratch[2]; static int iscratch; static int p; char c = 0xff; RGBcolor(c,c,c); for(p=0;p drawPrimitives"); if(xf->invCntns) if(! DXInitGetNextInvalidElementIndex(xf->invCntns)) goto error; finish(); /* Flush Geometry Pipeline */ PHASE_START("Primitives"); switch (xf->connectionType) { case ct_none: TIMER("> points"); helper = getHelper(xf->colorsDep,dep_none,dep_none,NULL); points(xf,helper,0,xf->npositions,0,approx,density); TIMER("< points"); break; case ct_lines: if(xf->attributes.linewidth > 0) linewidth((int)xf->attributes.linewidth); if(xf->attributes.aalines) linesmooth(SML_ON); helper = getHelper(xf->colorsDep,dep_none,dep_none,NULL); TIMER("> lines"); lines(xf,helper,0,xf->nconnections,0,approx,density); TIMER("< lines"); linesmooth(SML_OFF); break; case ct_polylines: if(xf->attributes.linewidth > 0) linewidth((int)xf->attributes.linewidth); if(xf->attributes.aalines) linesmooth(SML_ON); helper = getHelper(xf->colorsDep,dep_none,dep_none,NULL); TIMER("> plines"); polylines(xf,helper,approx,density); TIMER("< plines"); linesmooth(SML_OFF); break; case ct_pline: if(xf->attributes.linewidth > 0) linewidth((int)xf->attributes.linewidth); if(xf->attributes.aalines) linesmooth(SML_ON); helper = getHelper(xf->colorsDep,dep_none,dep_none,NULL); TIMER("> plines"); plines(xf,helper,approx,density); TIMER("< plines"); linesmooth(SML_OFF); break; case ct_triangles: helper = getHelper(xf->colorsDep,xf->normalsDep,dep_none, (xf->texture != NULL) && (approx == approx_none)); TIMER("> triangles"); polygons(xf,helper,0,xf->nconnections,0,approx,density); TIMER("< triangles"); break; case ct_quads: helper = getHelper(xf->colorsDep,xf->normalsDep,dep_none, (xf->texture != NULL) && (approx == approx_none)); TIMER("> quads"); polygons(xf,helper,0,xf->nconnections,4,approx,density); TIMER("< quads"); break; /* * XXX NOTE: * The volume code below is very inefficient for screen door rendering. * It draws a vast number of completely obscure faces. This is to make * sure that all the boundary faces are drawn. It would be far better * to do a show boundary and store the result of that in the xfield. * Next pass. */ case ct_tetrahedra: helper = getHelper(xf->colorsDep,xf->normalsDep,dep_none, (xf->texture != NULL) && (approx == approx_none)); TIMER("> tetras"); polygons(xf,helper,0,xf->nconnections,0,approx,density); polygons(xf,helper,0,xf->nconnections,1,approx,density); polygons(xf,helper,0,xf->nconnections,2,approx,density); polygons(xf,helper,0,xf->nconnections,3,approx,density); TIMER("< tetras"); break; case ct_cubes: helper = getHelper(xf->colorsDep,xf->normalsDep,dep_none, (xf->texture != NULL) && (approx == approx_none)); TIMER("> cubes"); polygons(xf,helper,0,xf->nconnections,4,approx,density); polygons(xf,helper,0,xf->nconnections,5,approx,density); polygons(xf,helper,0,xf->nconnections,6,approx,density); polygons(xf,helper,0,xf->nconnections,7,approx,density); polygons(xf,helper,0,xf->nconnections,8,approx,density); polygons(xf,helper,0,xf->nconnections,9,approx,density); TIMER("< cubes"); break; case ct_tmesh: helper = getHelper(xf->colorsDep,xf->normalsDep,dep_none, (xf->texture != NULL) && (approx == approx_none)); TIMER("> tmesh"); tmesh(xf,helper,approx,density); TIMER("< tmesh"); break; case ct_qmesh: helper = getHelper(xf->colorsDep,xf->normalsDep,dep_none, (xf->texture != NULL) && (approx == approx_none)); TIMER("> qmesh"); tmesh(xf,helper,approx,density); TIMER("< qmesh"); break; #if 0 #ifdef DXD_HW_TEXTURE_MAPPING case ct_flatGrid: if((approx == approx_none) && (density == 1)) { TIMER("> texture"); if(!hwTextureDraw(portHandle, xf)) goto error; TIMER("< texture"); break; } else { helper = getHelper(xf->colorsDep,xf->normalsDep,dep_none, xf->texture != NULL); TIMER("> quads"); polygons(xf,helper,0,xf->nconnections,4,approx,density); TIMER("< quads"); break; } #endif #endif default: DXErrorGoto (ERROR_INTERNAL, "invalid xfield connections type") ; break; } PHASE_END("Primitives"); done: TIMER("< drawPrimitives"); EXIT(("OK")); return OK; error: TIMER("< drawPrimitives"); EXIT(("ERROR")); return ERROR; } Error _dxf_DrawOpaque (tdmPortHandleP portHandle, xfieldP xf, RGBColor ambientColor, int buttonUp) { int density; enum approxE approx; dxObject Obj; int DisplayList; DEFPORT(portHandle); ENTRY(("_dxf_DrawOpaque(0x%x, 0x%x, 0x%x, %d)", portHandle, xf, &ambientColor, buttonUp)); TIMER("> DrawOpaque"); PHASE_START("DrawOpaque"); if (_dxf_isFlagsSet(_dxf_SERVICES_FLAGS(), SF_DOES_TRANS)) { if (getgdesc(GD_BLEND)) { doesTrans = 1; doesPattern = 0; } else { doesTrans = 0; doesPattern = 1; } } else { doesTrans = 0; doesPattern = 0; } if(xf->deletePrivate == NULL) xf->deletePrivate = _deleteGLObject; if(xf->normalsDep != dep_none && (buttonUp &&xf->attributes.buttonUp.approx == approx_none) || (!buttonUp &&xf->attributes.buttonDown.approx == approx_none)) { _dxf_SET_GLOBAL_LIGHT_ATTRIBUTES(PORT_CTX ,1); _dxf_SET_MATERIAL_SPECULAR (PORT_CTX, 1.0 /*R*/, 1.0 /*G*/, 1.0 /*B*/, (float) xf->attributes.front.shininess /* specular power */) ; } _dxf_PUSH_MULTIPLY_MATRIX(PORT_CTX,xf->attributes.mm); if(xf->colorsDep == dep_positions || xf->normalsDep == dep_positions) shademodel(GOURAUD); else shademodel(FLAT); blendfunction(BF_ONE, BF_ZERO); if(buttonUp) { density = xf->attributes.buttonUp.density; approx = xf->attributes.buttonUp.approx; } else { density = xf->attributes.buttonDown.density; approx = xf->attributes.buttonDown.approx; } /* * indigos get better performance from globjects, so try to * use one */ PHASE_START("DrawPrimitives"); /* #ifdef DXD_HW_API_DISPLAY_LIST_MEMORY if(Obj = DXGetIntegerAttribute((dxObject)(xf), "hwDisplayList", &DisplayList)) { if(DisplayList) { printf("hwDisplayList Set.\n");fflush(stdout); } else { printf("hwDisplayList !Set.\n");fflush(stdout); } } */ if(xf->UseDisplayList) { /* * Building an object is expensive, so only build one if we think we can * reuse it. i.e. for button down or button up where approx is equal * to button down. */ if(!buttonUp) { if (!xf->glObject) { xf->glObject = genobj(); xf->deletePrivate = _deleteGLObject; TIMER("> makeobj"); printf("A"); makeobj(xf->glObject); if(!_drawPrimitives(portHandle, xf, approx, density)) { closeobj(); _deleteGLObject(xf); goto error; } closeobj(); } TIMER("< makeobj"); TIMER("> callobj"); printf("."); callobj(xf->glObject); TIMER("< callobj"); } /* !buttonUp */ else if(xf->UseFastClip) { if(!xf->glObject) { xf->glObject = genobj(); xf->deletePrivate = _deleteGLObject; TIMER("> makeobj"); printf("B"); makeobj(xf->glObject); if (!_drawPrimitives(portHandle, xf, approx, density)) { closeobj(); _deleteGLObject(xf); goto error; } closeobj(); } printf(","); callobj(xf->glObject); } /* !xf->UseFastClip */ else { if (!_drawPrimitives(portHandle, xf, approx, density)) goto error; } } /* !xf->UseDisplayList */ else if(xf->UseFastClip) { if(!xf->glObject) { xf->glObject = genobj(); xf->deletePrivate = _deleteGLObject; TIMER("> makeobj"); printf("C"); makeobj(xf->glObject); if (!_drawPrimitives(portHandle, xf, approx, density)) { closeobj(); _deleteGLObject(xf); goto error; } closeobj(); } printf("//"); callobj(xf->glObject); } /* !xf->UseFastClip */ /* else { if (!_drawPrimitives(portHandle, xf, approx, density)) goto error; } */ else /* #else */ if (!_drawPrimitives(portHandle, xf, approx, density)) goto error; /* #endif */ PHASE_END("DrawPrimitives"); fflush(stdout); done: /* * Disable lighting, reset matrix stack */ _dxf_SET_GLOBAL_LIGHT_ATTRIBUTES(PORT_CTX ,0); _dxf_POP_MATRIX(PORT_CTX); PHASE_END("DrawOpaque"); TIMER("< DrawOpaque"); EXIT(("OK")); return OK; error: /* * Disable lighting, reset matrix stack */ _dxf_SET_GLOBAL_LIGHT_ATTRIBUTES(PORT_CTX ,0); _dxf_POP_MATRIX(PORT_CTX); PHASE_END("DrawOpaque"); TIMER("< DrawOpaque"); EXIT(("ERROR")); return ERROR; } _drawTranslucentPrimitives(tdmPortHandleP portHandle, xfieldP xf, SortD list, int n, enum approxE approx, int density) { helperFunc helper; ENTRY(("_drawPrimitives(0x%x, 0x%x, %d, %d)", portHandle, xf, approx, density)); TIMER("> drawTranslucentPrimitives"); if(xf->invCntns) if(! DXInitGetNextInvalidElementIndex(xf->invCntns)) goto error; finish(); /* Flush Geometry Pipeline */ PHASE_START("TranslucentPrimitives"); blendfunction(BF_SA, BF_MSA); switch (xf->connectionType) { case ct_none: TIMER("> translucent points"); translucentPolygons(xf,helper,list,n,0,approx,density); TIMER("< dots"); break; case ct_lines: if(xf->attributes.aalines) linesmooth(SML_ON); helper = getHelper(xf->colorsDep,dep_none,xf->opacitiesDep,NULL); TIMER("> lines"); translucentLines(xf,helper,list,n,0,approx,density); TIMER("< lines"); linesmooth(SML_OFF); break; case ct_triangles: helper = getHelper(xf->colorsDep,xf->normalsDep,xf->opacitiesDep, (xf->texture != NULL) && (approx == approx_none)); TIMER("> triangles"); translucentPolygons(xf,helper,list,n,0,approx,density); TIMER("< triangles"); break; case ct_quads: helper = getHelper(xf->colorsDep,xf->normalsDep,xf->opacitiesDep, (xf->texture != NULL) && (approx == approx_none)); TIMER("> quads"); translucentPolygons(xf,helper,list,n,4,approx,density); TIMER("< quads"); break; break; default: DXErrorGoto (ERROR_INTERNAL, "invalid xfield connections type in translucent") ; break; } PHASE_END("TranslucentPrimitives"); done: TIMER("< drawTranslucentPrimitives"); EXIT(("OK")); return OK; error: TIMER("< drawTranslucentPrimitives"); EXIT(("ERROR")); return ERROR; } Error _dxf_DrawTranslucent (void *globals, RGBColor ambientColor, int buttonUp) { int density; enum approxE approx; dxObject Obj; int DisplayList; int i, j; xfieldP xf; DEFGLOBALDATA(globals); DEFPORT(PORT_HANDLE); SortListP sl = (SortListP)SORTLIST; SortD sorted = sl->sortList; int nSorted = sl->itemCount; TIMER("> DrawTranslucent"); for (i = 0; i < nSorted; i = j) { xf = (xfieldP)sorted[i].xfp; if(xf->normalsDep != dep_none && (buttonUp &&xf->attributes.buttonUp.approx == approx_none) || (!buttonUp &&xf->attributes.buttonDown.approx == approx_none)) { _dxf_SET_GLOBAL_LIGHT_ATTRIBUTES(PORT_CTX ,1); _dxf_SET_MATERIAL_SPECULAR (PORT_CTX, 1.0 /*R*/, 1.0 /*G*/, 1.0 /*B*/, (float) xf->attributes.front.shininess /* specular power */) ; } _dxf_PUSH_MULTIPLY_MATRIX(PORT_CTX,xf->attributes.mm); if(xf->colorsDep == dep_positions || xf->normalsDep == dep_positions || xf->opacitiesDep == dep_positions) shademodel(GOURAUD); else shademodel(FLAT); if (xf->nClips) if (! _dxf_ADD_CLIP_PLANES(LWIN, xf->clipPts, xf->clipVecs, xf->nClips)) goto error; if(buttonUp) { density = xf->attributes.buttonUp.density; approx = xf->attributes.buttonUp.approx; } else { density = xf->attributes.buttonDown.density; approx = xf->attributes.buttonDown.approx; } /* * Count the successive primitives from th same xfield */ for (j = i+1; j < nSorted && xf == (xfieldP)sorted[j].xfp; j++); /* * indigos get better performance from globjects, so try to * use one */ if(xf->UseFastClip) { if(!xf->glObject) { xf->glObject = genobj(); xf->deletePrivate = _deleteGLObject; TIMER("> makeobj"); printf("C"); makeobj(xf->glObject); if (!_drawTranslucentPrimitives(PORT_HANDLE, xf, sorted+i, j-i, approx, density)) { closeobj(); _deleteGLObject(xf); goto error; } closeobj(); } printf("//"); callobj(xf->glObject); } else if (!_drawTranslucentPrimitives(PORT_HANDLE, xf, sorted+i, j-i, approx, density)) goto error; if (xf->nClips) if (! _dxf_REMOVE_CLIP_PLANES(LWIN, xf->nClips)) goto error; _dxf_POP_MATRIX(PORT_CTX) ; } PHASE_END("DrawPrimitives"); fflush(stdout); done: /* * Disable lighting, reset matrix stack */ _dxf_SET_GLOBAL_LIGHT_ATTRIBUTES(PORT_CTX ,0); TIMER("< DrawTranslucent"); EXIT(("OK")); return OK; error: /* * Disable lighting, reset matrix stack */ _dxf_SET_GLOBAL_LIGHT_ATTRIBUTES(PORT_CTX ,0); _dxf_POP_MATRIX(PORT_CTX); PHASE_END("DrawOpaque"); TIMER("< DrawOpaque"); EXIT(("ERROR")); return ERROR; } static void _deleteGLObject(xfieldP xf) { ENTRY(("_deleteGLObject(0x%x)", xf)); if(xf->glObject) { delobj(xf->glObject); xf->glObject = NULL; } #ifdef sgi if(xf->FlatGridTexture.Index) { /* (:Q= Only Needed if LRU Paging Is Undesirable if(xf->FlatGridTexture.Index > 0) texbind(TX_TEXTURE_IDLE, xf->FlatGridTexture.Index); */ xf->FlatGridTexture.Index = 0; xf->FlatGridTexture.Address = NULL; } #endif EXIT(("")); } #ifdef sgi Error glStartTexture(xfieldP xf) { unsigned long * Tex = NULL; unsigned char * Char; unsigned char * CharOrig; unsigned long R, G, B; unsigned long CtrWidth, CtrHeight; unsigned long Out; unsigned long Tmp; static float TexType[5] = { TX_MINFILTER, TX_BILINEAR, TX_MAGFILTER, TX_BILINEAR, TX_NULL }; static float TevType[2] = { TV_MODULATE, TV_NULL }; Matrix Ident = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; if((Tex = DXAllocate(xf->textureWidth * xf->textureHeight * 4)) == NULL) { DXSetError(ERROR_NO_MEMORY, "Falied to Allocate Texture Translation Space"); return ERROR; } Char = (unsigned char *)Tex; CharOrig = (unsigned char *)xf->texture; for(CtrHeight = 0; CtrHeight < xf->textureHeight; CtrHeight ++) { for(CtrWidth = 0; CtrWidth < xf->textureWidth; CtrWidth ++) { Out = (*(CharOrig) << 24) + (*(CharOrig + 1) << 16) + (*(CharOrig + 2) << 8) + *(CharOrig + 3); R = ((Out & 0x000000ff)); G = ((Out & 0x0000ff00) >> 8); B = ((Out & 0x00ff0000) >> 16); *Char++ = (char)G; *Char++ = (char)B; *Char++ = (char)R; CharOrig += 3; } for(Tmp = (xf->textureWidth * 3); (Tmp % 4) != 0; Tmp ++) { *Char++ = 0; CharOrig ++; } } texdef2d(1, 3, xf->textureWidth, xf->textureHeight, (unsigned long *)Tex, 5, TexType); DXFree(Tex); tevdef(1, 3, TevType); mmode(MTEXTURE); tevbind(TV_ENV0, 1); texbind(TX_TEXTURE_0, 1); mmode(MVIEWING); return OK; } Error glEndTexture() { tevbind(TV_ENV0, 0); } #endif #else /* * HELPERCODE * code to generate helper routines and table */ #include main() { int i; char c, n, o, tbl[] = {'v', 'e', 'f', 'n'}; for (i = 0; i < 64; i++) { c = tbl[i>>4]; n = tbl[0x3&(i>>2)]; o = tbl[0x3&(i)]; printf("static void\n" "helper_%c%c%c(xfieldP xf, int ppc," " int c, int *t, float *rgba)\n" "{\n" " static float fscratch[3];\n" " static int p, iscratch;\n\n", c, n, o); if (c == 'e') printf(" GETCOLOR(c);\n"); if (o == 'e') printf(" GETOPACITY(c);\n"); if (n == 'e') printf(" SENDNORMAL(c);\n"); if ((o == 'e' || o == 'n') && c == 'e' && (n == 'e' || n == 'n' || n == 'f')) if (n == 'n') printf(" SENDCOLOR(%d);\n", o != 'n' ? 1 : 0); else printf(" SENDLITCOLOR(%d);\n", o != 'n' ? 1 : 0); printf(" for (p = 0; p < ppc; p++) {\n"); if (n == 'v') printf(" SENDNORMAL(t[p]);\n"); #if 0 else if (n == 'f') printf(" SENDNORMAL(0);\n"); #endif if (c == 'v') printf(" GETCOLOR(t[p]);\n"); if (o == 'v') printf(" GETOPACITY(t[p]);\n"); if (c == 'v' || o == 'v' || n == 'v') if (n == 'n') printf(" SENDCOLOR(%d);\n", o != 'n' ? 1 : 0); else printf(" SENDLITCOLOR(%d);\n", o != 'n' ? 1 : 0); printf(" SENDPOSITION(t[p]);\n"); printf(" }\n"); printf(" return;\n"); printf("}\n\n"); } printf("static helperFunc helperTable[] = {\n"); for (i = 0; i < 64; i++) { c = tbl[i>>4]; n = tbl[0x3&(i>>2)]; o = tbl[0x3&(i)]; printf("%shelper_%c%c%c%c%c", ((i%4) == 0) ? " " : " ", c, n, o, (i == 63) ? ' ' : ',', ((i%4) == 3) ? '\n' : ' '); } printf("};\n\n"); } #endif