www.pudn.com > CG2Programs.rar > graphics.c
#include#include "graphics.h" #ifndef ROUND #define ROUND(a) ((int)(a+0.5)) #endif PhigsState pState = { SOLID, 1, 0, 0, 0, 1, 0, 0, 0, 1 }; /* ============================================================ */ /* Basic graphics primtives */ /* ============================================================ */ /* ============================================================ lineDDA */ void lineDDA (int xa, int ya, int xb, int yb) { int dx = xb - xa, dy = yb - ya, steps, k; float xIncrement, yIncrement, x = xa, y = ya; if (abs (dx) > abs (dy)) steps = abs (dx); else steps = abs (dy); xIncrement = dx / (float) steps; yIncrement = dy / (float) steps; setPixel (ROUND(x), ROUND(y)); for (k=0; k 0) { y--; py -= twoRx2; if (p > 0) p += Rx2 - py; else { x++; px += twoRy2; p += Rx2 - py + px; } ellipsePlotPoints (xCenter, yCenter, x, y); } } void ellipsePlotPoints (int xCenter, int yCenter, int x, int y) { setPixel (xCenter + x, yCenter + y); setPixel (xCenter - x, yCenter + y); setPixel (xCenter + x, yCenter - y); setPixel (xCenter - x, yCenter - y); } /* ============================================================ scanFill */ typedef struct tEdge { int yUpper; float xIntersect; float dxPerScan; struct tEdge * next; } Edge; /* Inserts edge into list in order of increasing xIntersect field. */ void insertEdge (Edge * list, Edge * edge) { Edge * q = list; Edge * p = q->next; while (p != NULL) { if (edge->xIntersect < p->xIntersect) p = NULL; else { q = p; p = p->next; } } edge->next = q->next; q->next = edge; } /* Given an index, return the y-coordinate of next nonhorizontal line */ int yNext (int k, int cnt, dcPt * pts) { int j; if ((k+1) > (cnt-1)) j = 0; else j = k + 1; while (pts[k].y == pts[j].y) if ((j+1) > (cnt-1)) j = 0; else j++; return (pts[j].y); } void makeEdgeRec (dcPt lower, dcPt upper, int yComp, Edge * edge, Edge * edges[]) { edge->dxPerScan = (float) (upper.x - lower.x) / (upper.y - lower.y); edge->xIntersect = lower.x; if (upper.y < yComp) edge->yUpper = upper.y - 1; else edge->yUpper = upper.y; insertEdge (edges[lower.y], edge); } void buildEdgeList (int cnt, dcPt * pts, Edge * edges[]) { Edge * edge; dcPt v1, v2; int i; int yPrev = pts[cnt - 2].y; v1.x = pts[cnt-1].x; v1.y = pts[cnt-1].y; for (i = 0; i < cnt; i++) { v2 = pts[i]; if (v1.y != v2.y) { /* a nonhorizontal line */ edge = (Edge *) malloc (sizeof (Edge)); if (v1.y < v2.y) makeEdgeRec (v1, v2, yNext (i, cnt, pts), edge, edges); else makeEdgeRec (v2, v1, yPrev, edge, edges); } yPrev = v1.y; v1 = v2; } } void buildActiveList (int scan, Edge * active, Edge * edges[]) { Edge * p, * q; p = edges[scan]->next; while (p) { q = p->next; insertEdge (active, p); p = q; } } void fillScan (int scan, Edge * active) { Edge * p1, * p2; int i; p1 = active->next; while (p1) { p2 = p1->next; for (i = p1->xIntersect; i < p2->xIntersect; i++) setPixel ((int) i, scan); /* Advance to next pair of intersections */ p1 = p2->next; } } void deleteAfter (Edge * q) { Edge * p = q->next; q->next = p->next; free (p); } void updateActiveList (int scan, Edge * active) { Edge * p = active->next; Edge * q = active; while (p) { if (scan >= p->yUpper) { p = p->next; deleteAfter (q); } else { p->xIntersect = p->xIntersect + p->dxPerScan; q = p; p = p->next; } } } void resortActiveList (Edge * active) { Edge * p = active->next; Edge * q; active->next = NULL; while (p) { q = p->next; insertEdge (active, p); p = q; } } void scanFill (int cnt, dcPt * pts) { Edge * edges[WINDOW_HEIGHT]; Edge * active; int i, scan; active = (Edge *) malloc (sizeof (Edge)); for (i = 0; i < WINDOW_HEIGHT; i++) { edges[i] = (Edge *) malloc (sizeof (Edge)); edges[i]->next = NULL; } active->next = NULL; buildEdgeList (cnt, pts, edges); for (scan = 0; scan < WINDOW_HEIGHT; scan++) { buildActiveList (scan, active, edges); if (active->next) { fillScan (scan, active); updateActiveList (scan, active); resortActiveList (active); } } } /* ============================================================ */ /* Data structure convenience functions */ /* ============================================================ */ void setWcPt2 (wcPt2 * pt, float x, float y) { pt->x = x; pt->y = y; } void setWcPt3 (wcPt3 * pt, float x, float y, float z) { pt->x = x; pt->y = y; pt->z = z; } void wcPt2Show (wcPt2 pt) { printf ("(%6.3f, %6.3f)\n", pt.x, pt.y); } void wcPt3Show (wcPt3 pt) { printf ("(%6.3f, %6.3f, %6.3f)\n", pt.x, pt.y, pt.z); } void matrix3x3Show (pMatrix3 m) { int i, j; printf ("\n"); for (i=0; i<3; i++) { for (j=0; j<3; j++) printf ("%6.3f\t", m[i][j]); printf ("\n"); } } void matrix4x4Show (pMatrix4 m) { int i, j; printf ("\n"); for (i=0; i<4; i++) { for (j=0; j<4; j++) printf ("%6.3f\t", m[i][j]); printf ("\n"); } } /* ============================================================ */ /* PHIGS-like graphics primitives */ /* ============================================================ */ void pPoint (float x, float y) { setPixel (ROUND(x), ROUND(y)); } void pSetLineType (pLineType typ) { pState.lineType = typ; } void pPolyline (int nPts, wcPt2 * pts) { int line; int dx, dy, steps, k; double xIncrement, yIncrement, x, y; int on = 0, off = 0; if (pState.lineType == SOLID) { /* We'll round the points and rely on the device-level line drawing routine. */ for (line=0; line abs (dy)) steps = abs (dx); else steps = abs (dy); xIncrement = dx / (float) steps; yIncrement = dy / (float) steps; setPixel ((int) x, (int) y); on++; switch (pState.lineType) { case DASHED: for (k=0; k