diff options
author | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
---|---|---|
committer | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
commit | d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch) | |
tree | cbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/glx/circuit.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'hacks/glx/circuit.c')
-rw-r--r-- | hacks/glx/circuit.c | 2094 |
1 files changed, 2094 insertions, 0 deletions
diff --git a/hacks/glx/circuit.c b/hacks/glx/circuit.c new file mode 100644 index 0000000..744e4b6 --- /dev/null +++ b/hacks/glx/circuit.c @@ -0,0 +1,2094 @@ +/* + * circuit - Random electronic components floating around + * + * version 1.4 + * + * Since version 1.1: added to-220 transistor, added fuse + * Since version 1.2: random display digits, LED improvements (flickering) + * Since version 1.3: ICs look better, font textures, improved normals to + * eliminate segmenting on curved surfaces, speedups + * Since version 1.4: Added RCA connector, 3.5mm connector, slide switch, + * surface mount, to-92 markings. Fixed ~5min crash. + * Better LED illumination. Other minor changes. + * + * Copyright (C) 2001-2015 Ben Buxton (bb@cactii.net) + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +/* Written over a few days in a (successful) bid to learn GL coding + * + * -seven option is dedicated to all the Slarkeners + * + * This hack uses lookup tables for sin, cos and tan - it can do a lot + */ + +#ifdef STANDALONE +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*suppressRotationAnimation: True\n" \ + "*componentFont: -*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*" + +# define release_circuit 0 +# define circuit_handle_event xlockmore_no_events +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#define DEF_SPIN "True" +#define DEF_SEVEN "False" +#define DEF_PARTS "10" +#define DEF_ROTATESPEED "1" +#define DEF_LIGHT "True" + +/* lifted from lament.c */ +#define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n)))) +#define RANDSIGN() ((random() & 1) ? 1 : -1) + + +#ifdef USE_GL + +#include "texfont.h" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static int maxparts; +static int rotatespeed; +static int spin; +static int uselight; +static int seven; + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +static XrmOptionDescRec opts[] = { + {"-parts", ".circuit.parts", XrmoptionSepArg, 0 }, + {"-rotate-speed", ".circuit.rotatespeed", XrmoptionSepArg, 0 }, + {"+spin", ".circuit.spin", XrmoptionNoArg, "false" }, + {"-spin", ".circuit.spin", XrmoptionNoArg, "true" }, + {"+light", ".circuit.light", XrmoptionNoArg, "false" }, + {"-light", ".circuit.light", XrmoptionNoArg, "true" }, + {"+seven", ".circuit.seven", XrmoptionNoArg, "false" }, + {"-seven", ".circuit.seven", XrmoptionNoArg, "true" }, +}; + +static argtype vars[] = { + {&maxparts, "parts", "Parts", DEF_PARTS, t_Int}, + {&rotatespeed, "rotatespeed", "Rotatespeed", DEF_ROTATESPEED, t_Int}, + {&spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&uselight, "light", "Light", DEF_LIGHT, t_Bool}, + {&seven, "seven", "Seven", DEF_SEVEN, t_Bool}, +}; + +ENTRYPOINT ModeSpecOpt circuit_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +#ifdef USE_MODULES +ModStruct circuit_description = +{"circuit", "init_circuit", "draw_circuit", NULL, + "draw_circuit", "init_circuit", "free_circuit", &circuit_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Flying electronic components", 0, NULL}; + +#endif + +#define MAX_COMPONENTS 400 +#define MOVE_MULT 0.02 + +static float f_rand(void) +{ + return ((float)RAND(10000)/(float)10000); +} + +#define RAND_RANGE(min, max) ((min) + (max - min) * f_rand()) + +/* Represents a band on a resistor/diode/etc */ +typedef struct { + float pos; /* relative position from start/previous band */ + GLfloat r, g, b; /* colour of the band */ + float len; /* length as a fraction of total length */ +} Band; + +typedef struct { + Band *b1, *b2, *b3, *b4; /* bands */ + int b[4]; +} Resistor; + +typedef struct { + Band *band; + GLfloat r, g, b; /* body colour */ +} Diode; + +static const char * const transistortypes[] = { + "TIP2955", + "TIP32C", + "LM 350T", + "IRF730", + "ULN2577", + "7805T", + "7912T", + "TIP120", + "2N6401", + "BD239", + "2SC1590", + "MRF485", + "SC141D" +}; + +static const char * const to92types[] = { + "C\n548", + "C\n848", + "74\nL05", + "C\n858", + "BC\n212L", + "BC\n640", + "BC\n337", + "BC\n338", + "S817", + "78\nL12", + "TL\n431", + "LM\n35DZ", +}; + +static const char * const smctypes[] = { + "1M-", + "1K", + "1F", + "B10", + "S14", + "Q3", + "4A" +}; + +typedef struct { + int type; /* package type. 0 = to-92, 1 = to-220 */ + const char *text; +} Transistor; + +typedef struct { + GLfloat r,g,b; /* LED colour */ + int light; /* are we the light source? */ +} LED; + +typedef struct { + int type; /* 0 = electro, 1 = ceramic */ + float width; /* width of an electro/ceramic */ + float length; /* length of an electro */ +} Capacitor; + +/* 3.5 mm plug */ +typedef struct { + int blah; +} ThreeFive; + +/* slide switch */ +typedef struct { + int position; +} Switch; + +typedef struct { + int pins; + const char *val; +} ICTypes; + +static const ICTypes ictypes[] = { + {8, "NE 555"}, + {8, "LM 386N"}, + {8, "ADC0831"}, + {8, "LM 383T"}, + {8, "TL071"}, + {8, "LM 311"}, + {8, "LM393"}, + {8, "LM 3909"}, + + {14, "LM 380N"}, + {14, "NE 556"}, + {14, "TL074"}, + {14, "LM324"}, + {14, "LM339"}, + {14, "MC1488"}, + {14, "MC1489"}, + {14, "LM1877-9"}, + {14, "4011"}, + {14, "4017"}, + {14, "4013"}, + {14, "4024"}, + {14, "4066"}, + + {16, "4076"}, + {16, "4049"}, + {16, "4094"}, + {16, "4043"}, + {16, "4510"}, + {16, "4511"}, + {16, "4035"}, + {16, "RS232"}, + {16, "MC1800"}, + {16, "ULN2081"}, + {16, "UDN2953"}, + + {24, "ISD1416P"}, + {24, "4515"}, + {24, "TMS6264L"}, + {24, "MC146818"} +}; + +typedef struct { + int type; /* 0 = DIL, 1 = flat square */ + int pins; + char text[100]; +} IC; + +/* 7 segment display */ + +typedef struct { + int value; /* displayed number */ +} Disp; + +typedef struct { + GLfloat l, w; +} Fuse; + +typedef struct { + GLfloat l, w; + int col; +} RCA; + +typedef struct { + GLfloat x, y, z; /* current co-ordinates */ + GLfloat dx, dy, dz; /* current direction */ + GLfloat rotx, roty, rotz; /* rotation vector */ + GLfloat drot; /* rotation velocity (degrees per frame) */ + int norm; /* Normalize this component (for shine) */ + int rdeg; /* current rotation degrees */ + int angle; /* angle about the z axis */ + int alpha; /* 0 if not a transparent component */ + int type; /* 0 = resistor, 1 = diode, 2 = transistor, 3 = LED, 4 = cap, 5=IC, + 6 = 7 seg disp */ + void * c; /* pointer to the component */ +} Component; + +/* standard colour codes */ + +static const GLfloat colorcodes [12][3] = { + {0.0,0.0,0.0}, /* black 0 */ + {0.49,0.25,0.08}, /* brown 1 */ + {1.0,0.0,0.0}, /* red 2 */ + {1.0,0.5,0.0}, /* orange 3 */ + {1.0,1.0,0.0}, /* yellow 4 */ + {0.0,1.0,0.0}, /* green 5 */ + {0.0,0.5,1.0}, /* blue 6 */ + {0.7,0.2,1.0}, /* violet 7 */ + {0.5,0.5,0.5}, /* grey 8 */ + {1.0,1.0,1.0}, /* white 9 */ + {0.66,0.56,0.2}, /* gold 10 */ + {0.8,0.8,0.8}, /* silver 11 */ +}; + +/* base values for components - we can multiply by 0 - 1M */ +static const int values [9][2] = { + {1,0}, + {2,2}, + {3,3}, + {4,7}, + {5,6}, + {6,8}, + {7,5}, + {8,2}, + {9,1} +}; + +typedef struct { + GLXContext *glx_context; + Window window; + + int XMAX, YMAX; + int win_w, win_h; + + /* one lucky led gets to be a light source , unless -no-light*/ + int light; + int lighton; + + /* stores refs to textures */ + int s_refs[50]; + + GLfloat viewer[3]; + GLfloat lightpos[4]; + + float sin_table[720]; + float cos_table[720]; + float tan_table[720]; + + Component *components[MAX_COMPONENTS]; + int band_list[12]; + int band_list_polys[12]; + + GLfloat grid_col[3], grid_col2[3]; + + int display_i; + GLfloat rotate_angle; + + texture_font_data *font; + char *font_strings[50]; /* max of 40 textures */ + int font_w[50], font_h[50]; + int font_init; + + GLfloat draw_sx, draw_sy; /* bright spot co-ords */ + int draw_sdir; /* 0 = left-right, 1 = right-left, 2 = up->dn, 3 = dn->up */ + int draw_s; /* if spot is enabled */ + float draw_ds; /* speed of spot */ + +} Circuit; + +static Circuit *circuit = NULL; + + +static int DrawResistor(Circuit *, Resistor *); +static int DrawDiode(Circuit *, Diode *); +static int DrawTransistor(Circuit *, Transistor *); +static int DrawLED(Circuit *, LED *); +static int DrawIC(Circuit *, IC *); +static int DrawCapacitor(Circuit *, Capacitor *); +static int DrawDisp(Circuit *, Disp *); +static int DrawFuse(Circuit *, Fuse *); +static int DrawRCA(Circuit *, RCA *); +static int DrawThreeFive(Circuit *, ThreeFive *); +static int DrawSwitch(Circuit *, Switch *); + +static void reorder(Component *[]); +static int circle(Circuit *, float, int,int); +static int bandedCylinder(Circuit *, + float, float , GLfloat, GLfloat , GLfloat, + Band **, int); +static int Rect(GLfloat , GLfloat , GLfloat, GLfloat , GLfloat ,GLfloat); +static int ICLeg(GLfloat, GLfloat, GLfloat, int); +static int HoledRectangle(Circuit *ci, + GLfloat, GLfloat, GLfloat, GLfloat, int); +static Resistor *NewResistor(void); +static Diode *NewDiode(void); +static Transistor *NewTransistor(ModeInfo *); +static LED * NewLED(Circuit *); +static Capacitor *NewCapacitor(Circuit *); +static IC* NewIC(ModeInfo *); +static Disp* NewDisp(Circuit *); +static Fuse *NewFuse(Circuit *); +static RCA *NewRCA(Circuit *); +static ThreeFive *NewThreeFive(Circuit *); +static Switch *NewSwitch(Circuit *); + +/* we use trig tables to speed things up - 200 calls to sin() + in one frame can be a bit harsh.. +*/ + +static void make_tables(Circuit *ci) +{ +int i; +float f; + + f = 360 / (M_PI * 2); + for (i = 0 ; i < 720 ; i++) { + ci->sin_table[i] = sin(i/f); + } + for (i = 0 ; i < 720 ; i++) { + ci->cos_table[i] = cos(i/f); + } + for (i = 0 ; i < 720 ; i++) { + ci->tan_table[i] = tan(i/f); + } +} + + +static int createCylinder (Circuit *ci, + float length, float radius, int endcaps, int half) +{ + int polys = 0; + int a; /* current angle around cylinder */ + int angle, norm; + float z1, y1, z2, y2,ex; + int nsegs; + + glPushMatrix(); + nsegs = radius*MAX(ci->win_w, ci->win_h)/20; + nsegs = MAX(nsegs, 4); + if (nsegs % 2) + nsegs += 1; + angle = (half) ? (180 - 90/nsegs) : 374; + z1 = radius; y1 = 0; + glBegin(GL_QUADS); + for (a = 0 ; a <= angle ; a+= angle/nsegs) { + y2=radius*(float)ci->sin_table[(int)a]; + z2=radius*(float)ci->cos_table[(int)a]; + glNormal3f(0, y1, z1); + glVertex3f(0,y1,z1); + glVertex3f(length,y1,z1); + glNormal3f(0, y2, z2); + glVertex3f(length,y2,z2); + glVertex3f(0,y2,z2); + polys++; + z1=z2; + y1=y2; + } + glEnd(); + if (half) { + glBegin(GL_POLYGON); + glNormal3f(0, 1, 0); + glVertex3f(0, 0, radius); + glVertex3f(length, 0, radius); + glVertex3f(length, 0, 0 - radius); + glVertex3f(0, 0, 0 - radius); + polys++; + glEnd(); + } + if (endcaps) { + for(ex = 0 ; ex <= length ; ex += length) { + z1 = radius; y1 = 0; + norm = (ex == length) ? 1 : -1; + glBegin(GL_TRIANGLES); + glNormal3f(norm, 0, 0); + for (a = 0 ; a <= angle ; a+= angle/nsegs) { + y2=radius*(float)ci->sin_table[(int)a]; + z2=radius*(float)ci->cos_table[(int)a]; + glVertex3f(ex,0, 0); + glVertex3f(ex,y1,z1); + glVertex3f(ex,y2,z2); + polys++; + z1=z2; + y1=y2; + } + glEnd(); + } + } + glPopMatrix(); + return polys; +} + +static int circle(Circuit *ci, float radius, int segments, int half) +{ + int polys = 0; + float x1 = 0, x2 = 0; + float y1 = 0, y2 = 0; + int i, t, s; + + if (half) { + t = 270; s = 90; + x1 = radius, y1 = 0; + } else { + t = 360, s = 0; + } + glBegin(GL_TRIANGLES); + glNormal3f(1, 0, 0); + for(i=s;i<=t;i+=10) + { + float angle=i; + x2=radius*(float)ci->cos_table[(int)angle]; + y2=radius*(float)ci->sin_table[(int)angle]; + glVertex3f(0,0,0); + glVertex3f(0,y1,x1); + glVertex3f(0,y2,x2); + polys++; + x1=x2; + y1=y2; + } + glEnd(); + return polys; +} + +static int wire(Circuit *ci, float len) +{ + int polys = 0; + GLfloat col[] = {0.3, 0.3, 0.3, 1.0}; + GLfloat spec[] = {0.9, 0.9, 0.9, 1.0}; + GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0}; + GLfloat shin = 30; + int n; + + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shin); + n = glIsEnabled(GL_NORMALIZE); + if (!n) glEnable(GL_NORMALIZE); + polys += createCylinder(ci, len, 0.05, 1, 0); + if (!n) glDisable(GL_NORMALIZE); + glMaterialfv(GL_FRONT, GL_SPECULAR, nospec); + return polys; +} + +static int sphere(Circuit *ci, GLfloat r, float stacks, float slices, + int startstack, int endstack, int startslice, + int endslice) +{ + int polys = 0; + GLfloat d, d1, dr, dr1, Dr, Dr1, D, D1, z1, z2, y1, y2, Y1, Z1, Y2, Z2; + int a, a1, b, b1, c0, c1; + GLfloat step, sstep; + + step = 180/stacks; + sstep = 360/slices; + a1 = startstack * step; + b1 = startslice * sstep; + y1 = z1 = Y1 = Z1 = 0; + c0 = (endslice / slices) * 360; + c1 = (endstack/stacks)*180; + glBegin(GL_QUADS); + for (a = startstack * step ; a <= c1 ; a+= step) { + d=ci->sin_table[a]; + d1=ci->sin_table[a1]; + D=ci->cos_table[a]; + D1=ci->cos_table[a1]; + dr = d * r; + dr1 = d1 * r; + Dr = D * r; + Dr1 = D1 * r; + for (b = b1 ; b <= c0 ; b+= sstep) { + y2=dr*ci->sin_table[b]; + z2=dr*ci->cos_table[b]; + Y2=dr1*ci->sin_table[b]; + Z2=dr1*ci->cos_table[b]; + glNormal3f(Dr, y1, z1); + glVertex3f(Dr,y1,z1); + glNormal3f(Dr, y2, z2); + glVertex3f(Dr,y2,z2); + glNormal3f(Dr1, Y2, Z2); + glVertex3f(Dr1,Y2,Z2); + glNormal3f(Dr1, Y1, Z1); + glVertex3f(Dr1,Y1,Z1); + polys++; + z1=z2; + y1=y2; + Z1=Z2; + Y1=Y2; + } + a1 = a; + } + glEnd(); + return polys; +} + +static int DrawComponent(Circuit *ci, Component *c, unsigned long *polysP) +{ + int polys = *polysP; + int ret = 0; /* return 1 if component is freed */ + + glPushMatrix(); + glTranslatef(c->x, c->y, c->z); + if (c->angle > 0) { + glRotatef(c->angle, c->rotx, c->roty, c->rotz); + } + if (spin) { + glRotatef(c->rdeg, c->rotx, c->roty, c->rotz); + c->rdeg += c->drot; + } + + if (c->norm) + glEnable(GL_NORMALIZE); + else + glDisable(GL_NORMALIZE); + + /* call object draw routine here */ + if (c->type == 0) { + polys += DrawResistor(ci, c->c); + } else if (c->type == 1) { + polys += DrawDiode(ci, c->c); + } else if (c->type == 2) { + polys += DrawTransistor(ci, c->c); + } else if (c->type == 3) { + if (((LED *)c->c)->light && ci->light) { + GLfloat lp[] = {0.1, 0, 0, 1}; + glEnable(GL_LIGHT1); + glLightfv(GL_LIGHT1, GL_POSITION, lp); + } + polys += DrawLED(ci, c->c); + } else if (c->type == 4) { + polys += DrawCapacitor(ci, c->c); + } else if (c->type == 5) { + polys += DrawIC(ci, c->c); + } else if (c->type == 6) { + polys += DrawDisp(ci, c->c); + } else if (c->type == 7) { + polys += DrawFuse(ci, c->c); + } else if (c->type == 8) { + polys += DrawRCA(ci, c->c); + } else if (c->type == 9) { + polys += DrawThreeFive(ci, c->c); + } else if (c->type == 10) { + polys += DrawSwitch(ci, c->c); + } + c->x += c->dx * MOVE_MULT; + c->y += c->dy * MOVE_MULT; + if (c->x > ci->XMAX/2 || c->x < 0 - ci->XMAX/2 || + c->y > ci->YMAX/2 || c->y < 0 - ci->YMAX/2) { + if (c->type == 3 && ((LED *)c->c)->light && ci->light) { + glDisable(GL_LIGHT1); + ci->light = 0; ci->lighton = 0; + } + if (c->type == 1) + free(((Diode *)c->c)->band); /* remember to free diode band */ + free(c->c); + ret = 1; + } + + glPopMatrix(); + glDisable(GL_NORMALIZE); + *polysP = polys; + return ret; +} + +/* draw a resistor */ + +static int DrawResistor(Circuit *ci, Resistor *r) +{ + int polys = 0; + int i; + GLfloat col[] = {0.74, 0.62, 0.46, 1.0}; + GLfloat spec[] = {0.8, 0.8, 0.8, 1.0}; + GLfloat shine = 30; + + glTranslatef(-4, 0, 0); + polys += wire(ci, 3); + glTranslatef(3, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + polys += createCylinder(ci, 1.8, 0.4, 1, 0); + glPushMatrix(); + for (i = 0 ; i < 4 ; i++) { + glTranslatef(0.35, 0, 0); + glCallList(ci->band_list[r->b[i]]); + polys += ci->band_list_polys[r->b[i]]; + } + glPopMatrix(); + glTranslatef(1.8, 0, 0); + polys += wire(ci, 3); + return polys; +} + +static int DrawRCA(Circuit *ci, RCA *rca) +{ + int polys = 0; + GLfloat col[] = {0.6, 0.6, 0.6, 1.0}; /* metal */ + GLfloat red[] = {1.0, 0.0, 0.0, 1.0}; /* red */ + GLfloat white[] = {1.0, 1.0, 1.0, 1.0}; /* white */ + GLfloat spec[] = {1, 1, 1, 1}; /* glass */ + + glPushMatrix(); + glTranslatef(0.3, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMateriali(GL_FRONT, GL_SHININESS, 40); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + polys += createCylinder(ci, 0.7, 0.45, 0, 0); + glTranslatef(0.4, 0, 0); + polys += createCylinder(ci, 0.9, 0.15, 1, 0); + glTranslatef(-1.9, 0, 0); + glMateriali(GL_FRONT, GL_SHININESS, 20); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, rca->col ? white : red); + polys += createCylinder(ci, 1.5, 0.6, 1, 0); + glTranslatef(-0.9, 0, 0); + polys += createCylinder(ci, 0.9, 0.25, 0, 0); + glTranslatef(0.1, 0, 0); + polys += createCylinder(ci, 0.2, 0.3, 0, 0); + glTranslatef(0.3, 0, 0); + polys += createCylinder(ci, 0.2, 0.3, 1, 0); + glTranslatef(0.3, 0, 0); + polys += createCylinder(ci, 0.2, 0.3, 1, 0); + glPopMatrix(); + return polys; +} + +static int DrawSwitch(Circuit *ci, Switch *f) +{ + int polys = 0; + GLfloat col[] = {0.6, 0.6, 0.6, 0}; /* metal */ + GLfloat dark[] = {0.1, 0.1, 0.1, 1.0}; /* dark */ + GLfloat brown[] = {0.69, 0.32, 0, 1.0}; /* brown */ + GLfloat spec[] = {0.9, 0.9, 0.9, 1}; /* shiny */ + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_AMBIENT, dark); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMateriali(GL_FRONT, GL_SHININESS, 90); + polys += Rect(-0.25, 0, 0, 1.5, 0.5, 0.75); +/* polys += Rect(-0.5, 0.5, 0, 2, 0.1, 0.75); */ + glPushMatrix(); + glRotatef(90, 1, 0, 0); + glTranslatef(-0.5, -0.4, -0.4); + polys += HoledRectangle(ci, 0.5, 0.75, 0.1, 0.15, 8); + glTranslatef(2, 0, 0); + polys += HoledRectangle(ci, 0.5, 0.75, 0.1, 0.15, 8); + glPopMatrix(); + polys += Rect(0.1, -0.4, -0.25, 0.1, 0.4, 0.05); + polys += Rect(0.5, -0.4, -0.25, 0.1, 0.4, 0.05); + polys += Rect(0.9, -0.4, -0.25, 0.1, 0.4, 0.05); + polys += Rect(0.1, -0.4, -0.5, 0.1, 0.4, 0.05); + polys += Rect(0.5, -0.4, -0.5, 0.1, 0.4, 0.05); + polys += Rect(0.9, -0.4, -0.5, 0.1, 0.4, 0.05); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, dark); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + polys += Rect(0, 0.5, -0.1, 1, 0.05, 0.5); + polys += Rect(0, 0.6, -0.1, 0.5, 0.6, 0.5); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown); + polys += Rect(-0.2, -0.01, -0.1, 1.4, 0.1, 0.55); + glPopMatrix(); + return polys; +} + + +static int DrawFuse(Circuit *ci, Fuse *f) +{ + int polys = 0; + GLfloat col[] = {0.5, 0.5, 0.5, 1.0}; /* endcaps */ + GLfloat glass[] = {0.4, 0.4, 0.4, 0.3}; /* glass */ + GLfloat spec[] = {1, 1, 1, 1}; /* glass */ + + glPushMatrix(); + glTranslatef(-1.8, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMateriali(GL_FRONT, GL_SHININESS, 40); + polys += createCylinder(ci, 0.8, 0.45, 1, 0); + glTranslatef(0.8, 0, 0); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, glass); + glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 40); + polys += createCylinder(ci, 2, 0.4, 0, 0); + polys += createCylinder(ci, 2, 0.3, 0, 0); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMateriali(GL_FRONT, GL_SHININESS, 40); + glBegin(GL_LINES); + glVertex3f(0, 0, 0); + glVertex3f(2, 0. ,0); + glEnd(); + glTranslatef(2, 0, 0); + polys += createCylinder(ci, 0.8, 0.45, 1, 0); + glPopMatrix(); + return polys; +} + + +static int DrawCapacitor(Circuit *ci, Capacitor *c) +{ + int polys = 0; + GLfloat col[] = {0, 0, 0, 0}; + GLfloat spec[] = {0.8, 0.8, 0.8, 0}; + GLfloat brown[] = {0.84, 0.5, 0}; + GLfloat shine = 40; + + glPushMatrix(); + if (c->type) { + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown); + polys += sphere(ci, c->width, 15, 15, 0, 4 ,0, 15); + glTranslatef(1.35*c->width, 0, 0); + polys += sphere(ci, c->width, 15, 15, 11, 15, 0, 15); + glRotatef(90, 0, 0, 1); + glTranslatef(0, 0.7*c->width, 0.3*c->width); + polys += wire(ci, 3*c->width); + glTranslatef(0, 0, -0.6*c->width); + polys += wire(ci, 3*c->width); + } else { + glTranslatef(0-c->length*2, 0, 0); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shine); + glBegin(GL_POLYGON); + glVertex3f(0, 0.82*c->width, -0.1); + glVertex3f(3*c->length, 0.82*c->width, -0.1); + glVertex3f(3*c->length, 0.82*c->width, 0.1); + glVertex3f(0, 0.82*c->width, 0.1); + glEnd(); + col[0] = 0.0; + col[1] = 0.2; + col[2] = 0.9; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1.0); + polys += createCylinder(ci, 3.0*c->length, 0.8*c->width, 1, 0); + glDisable(GL_POLYGON_OFFSET_FILL); + col[0] = 0.7; + col[1] = 0.7; + col[2] = 0.7; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + polys += circle(ci, 0.6*c->width, 30, 0); + col[0] = 0; + col[1] = 0; + col[2] = 0; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glTranslatef(3.0*c->length, 0.0, 0); + polys += circle(ci, 0.6*c->width, 30, 0); + glTranslatef(0, 0.4*c->width, 0); + polys += wire(ci, 3*c->length); + glTranslatef(0.0, -0.8*c->width, 0); + polys += wire(ci, 3.3*c->length); + } + glPopMatrix(); + return polys; +} + +static int DrawLED(Circuit *ci, LED *l) +{ + int polys = 0; + GLfloat col[] = {0, 0, 0, 0.6}; + GLfloat black[] = {0, 0, 0, 0.6}; + + col[0] = l->r; col[1] = l->g; col[2] = l->b; + if (l->light && ci->light) { + GLfloat dir[] = {-1, 0, 0}; + glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, dir); + if (!ci->lighton) { + glLightfv(GL_LIGHT1, GL_SPECULAR, col); + glLightfv(GL_LIGHT1, GL_AMBIENT, black); + col[0] /= 1.5; col[1] /= 1.5; col[2] /= 1.5; + glLightfv(GL_LIGHT1, GL_DIFFUSE, col); + glLighti(GL_LIGHT1, GL_SPOT_CUTOFF, (GLint) 90); + glLighti(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (GLfloat)1); + glLighti(GL_LIGHT1, GL_LINEAR_ATTENUATION, (GLfloat)0); + glLighti(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (GLfloat)0); + glLighti(GL_LIGHT1, GL_SPOT_EXPONENT, (GLint) 20); + ci->lighton = 1; + } + } + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col); + /* no transparency when LED is lit */ + if (!l->light) { + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); + } + glTranslatef(-0.9, 0, 0); + polys += createCylinder(ci, 1.2, 0.3, 0, 0); + if (l->light && ci->light) { + glDisable(GL_LIGHTING); + glColor3fv(col); + } + polys += sphere(ci, 0.3, 7, 7, 3, 7, 0, 7); + if (l->light && ci->light) { + glEnable(GL_LIGHTING); + } else { + glDepthMask(GL_TRUE); + glDisable(GL_BLEND); + } + + glTranslatef(1.2, 0, 0); + polys += createCylinder(ci, 0.1, 0.38, 1, 0); + glTranslatef(-0.3, 0.15, 0); + polys += wire(ci, 3); + glTranslatef(0, -0.3, 0); + polys += wire(ci, 3.3); + if (random() % 50 == 25) { + if (l->light) { + l->light = 0; ci->light = 0; ci->lighton = 0; + glDisable(GL_LIGHT1); + } else if (!ci->light) { + l->light = 1; + ci->light = 1; + } + } + return polys; +} + + +static int DrawThreeFive(Circuit *ci, ThreeFive *d) +{ + int polys = 0; + GLfloat shine = 40; + GLfloat const dark[] = {0.3, 0.3, 0.3, 0}; + GLfloat const light[] = {0.6, 0.6, 0.6, 0}; + GLfloat const cream[] = {0.8, 0.8, 0.6, 0}; + GLfloat const spec[] = {0.7, 0.7, 0.7, 0}; + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cream); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + + glTranslatef(-2.0, 0, 0); + polys += createCylinder(ci, 0.7, 0.2, 0, 0); + glTranslatef(0.7, 0, 0); + polys += createCylinder(ci, 1.3, 0.4, 1, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light); + glTranslatef(1.3, 0, 0); + polys += createCylinder(ci, 1.3, 0.2, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, dark); + glTranslatef(0.65, 0, 0); + polys += createCylinder(ci, 0.15, 0.21, 0, 0); + glTranslatef(0.3, 0, 0); + polys += createCylinder(ci, 0.15, 0.21, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light); + glTranslatef(0.4, 0, 0); + polys += sphere(ci, 0.23, 7, 7, 0, 5, 0, 7); + + glPopMatrix(); + return polys; +} + +static int DrawDiode(Circuit *ci, Diode *d) +{ + int polys = 0; + GLfloat shine = 40; + GLfloat col[] = {0.3, 0.3, 0.3, 0}; + GLfloat spec[] = {0.7, 0.7, 0.7, 0}; + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glTranslatef(-4, 0, 0); + polys += wire(ci, 3); + glTranslatef(3, 0, 0); + polys += bandedCylinder(ci, 0.3, 1.5, d->r, d->g, d->b, &(d->band), 1); + glTranslatef(1.5, 0, 0); + polys += wire(ci, 3); + glPopMatrix(); + return polys; +} + +static int Rect(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h, + GLfloat t) +{ + int polys = 0; + GLfloat yh; + GLfloat xw; + GLfloat zt; + + yh = y+h; xw = x+w; zt = z - t; + + glBegin(GL_QUADS); /* front */ + glNormal3f(0, 0, 1); + glVertex3f(x, y, z); + glVertex3f(x, yh, z); + glVertex3f(xw, yh, z); + glVertex3f(xw, y, z); + polys++; + /* back */ + glNormal3f(0, 0, -1); + glVertex3f(x, y, zt); + glVertex3f(x, yh, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, y, zt); + polys++; + /* top */ + glNormal3f(0, 1, 0); + glVertex3f(x, yh, z); + glVertex3f(x, yh, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, yh, z); + polys++; + /* bottom */ + glNormal3f(0, -1, 0); + glVertex3f(x, y, z); + glVertex3f(x, y, zt); + glVertex3f(xw, y, zt); + glVertex3f(xw, y, z); + polys++; + /* left */ + glNormal3f(-1, 0, 0); + glVertex3f(x, y, z); + glVertex3f(x, y, zt); + glVertex3f(x, yh, zt); + glVertex3f(x, yh, z); + polys++; + /* right */ + glNormal3f(1, 0, 0); + glVertex3f(xw, y, z); + glVertex3f(xw, y, zt); + glVertex3f(xw, yh, zt); + glVertex3f(xw, yh, z); + polys++; + glEnd(); + return polys; +} + +/* IC pins */ + +static int ICLeg(GLfloat x, GLfloat y, GLfloat z, int dir) +{ + int polys = 0; + if (dir) { + polys += Rect(x-0.1, y, z, 0.1, 0.1, 0.02); + polys += Rect(x-0.1, y, z, 0.02, 0.1, 0.1); + polys += Rect(x-0.1, y+0.03, z-0.1, 0.02, 0.05, 0.3); + } else { + polys += Rect(x, y, z, 0.1, 0.1, 0.02); + polys += Rect(x+0.8*0.1, y, z, 0.02, 0.1, 0.1); + polys += Rect(x+0.8*0.1, y+0.03, z-0.1, 0.02, 0.05, 0.3); + } + return polys; +} + + +static int DrawIC(Circuit *ci, IC *c) +{ + int polys = 0; + GLfloat w, h, d; + int z; + GLfloat col[] = {0.1, 0.1, 0.1, 0}; + GLfloat col2[] = {0.2, 0.2, 0.2, 0}; + GLfloat spec[] = {0.6, 0.6, 0.6, 0}; + GLfloat shine = 40; + GLfloat lspec[] = {0.6, 0.6, 0.6, 0}; + GLfloat lcol[] = {0.4, 0.4, 0.4, 0}; + GLfloat lshine = 40; + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + switch(c->pins) { + case 8: + w = 1.0; h = 1.5; + break; + case 14: + w = 1.0; h = 3; + break; + case 16: + w = 1.0; h = 3; + break; + case 24: + default: + w = 1.5; h = 3.5; + break; + } + w = w/2; h = h/2; + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1.0); + glBegin(GL_QUADS); + glNormal3f(0, 0, 1); + glVertex3f(w, h, 0.1); + glVertex3f(w, -h, 0.1); + glVertex3f(-w, -h, 0.1); + glVertex3f(-w, h, 0.1); + polys++; + glNormal3f(0, 0, -1); + glVertex3f(w, h, -0.1); + glVertex3f(w, -h, -0.1); + glVertex3f(-w, -h, -0.1); + glVertex3f(-w, h, -0.1); + polys++; + glNormal3f(1, 0, 0); + glVertex3f(w, h, -0.1); + glVertex3f(w, -h, -0.1); + glVertex3f(w, -h, 0.1); + glVertex3f(w, h, 0.1); + polys++; + glNormal3f(0, -1, 0); + glVertex3f(w, -h, -0.1); + glVertex3f(w, -h, 0.1); + glVertex3f(-w, -h, 0.1); + glVertex3f(-w, -h, -0.1); + polys++; + glNormal3f(-1, 0, 0); + glVertex3f(-w, h, -0.1); + glVertex3f(-w, h, 0.1); + glVertex3f(-w, -h, 0.1); + glVertex3f(-w, -h, -0.1); + polys++; + glNormal3f(0, -1, 0); + glVertex3f(-w, h, -0.1); + glVertex3f(w, h, -0.1); + glVertex3f(w, h, 0.1); + glVertex3f(-w, h, 0.1); + polys++; + glEnd(); + glDisable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + { + GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0}; + GLfloat s = 0.015; + XCharStruct e; + texture_string_metrics (ci->font, c->text, &e, 0, 0); + + glPushMatrix(); + glTranslatef (0, 0, 0.1); + glRotatef (90, 0, 0, 1); + glScalef (s, s, s); + glTranslatef (-w/2, 0, 0); + glColor4fv (texfg); + print_texture_string (ci->font, c->text); + glPopMatrix(); + } + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + d = (h*2-0.1) / c->pins; + d*=2; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol); + glMaterialfv(GL_FRONT, GL_SPECULAR, lspec); + glMaterialfv(GL_FRONT, GL_SHININESS, &lshine); + for (z = 0 ; z < c->pins/2 ; z++) { + polys += ICLeg(w, -h + z*d + d/2, 0, 0); + } + for (z = 0 ; z < c->pins/2 ; z++) { + polys += ICLeg(-w, -h + z*d + d/2, 0, 1); + } + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col2); + glTranslatef(-w+0.3, h-0.3, 0.1); + glRotatef(90, 0, 1, 0); + polys += circle(ci, 0.1, 7, 0); + glPopMatrix(); + return polys; +} + +static int DrawDisp(Circuit *ci, Disp *d) +{ + int polys = 0; + GLfloat col[] = {0.8, 0.8, 0.8, 1.0}; /* body colour */ + GLfloat front[] = {0.2, 0.2, 0.2, 1.0}; /* front colour */ + GLfloat on[] = {0.9, 0, 0, 1}; /* 'on' segment */ + GLfloat off[] = {0.3, 0, 0, 1}; /* 'off' segment */ + int i, j, k; + GLfloat x, y; /* for the pins */ + GLfloat spec[] = {0.6, 0.6, 0.6, 0}; + GLfloat lcol[] = {0.4, 0.4, 0.4, 0}; + GLfloat shine = 40; + static const GLfloat vdata_h[6][2] = { + {0, 0}, + {0.1, 0.1}, + {0.9, 0.1}, + {1, 0}, + {0.9, -0.1}, + {0.1, -0.1} + }; + static const GLfloat vdata_v[6][2] = { + {0.27, 0}, + {0.35, -0.1}, + {0.2, -0.9}, + {0.1, -1}, + {0, -0.9}, + {0.15, -0.15} + }; + + static const GLfloat seg_start[7][2] = { + {0.55, 2.26}, + {1.35, 2.26}, + {1.2, 1.27}, + {0.25, 0.25}, + {0.06, 1.25}, + {0.25, 2.25}, + {0.39, 1.24} + }; + + static const int nums[10][7] = { + {1, 1, 1, 1, 1, 1, 0}, /* 0 */ + {0, 1, 1, 0, 0, 0, 0}, /* 1 */ + {1, 1, 0, 1, 1, 0, 1}, /* 2 */ + {1, 1, 1, 1, 0, 0, 1}, /* 3 */ + {0, 1, 1, 0, 0, 1, 1}, /* 4 */ + {1, 0, 1, 1, 0, 1, 1}, /* 5 */ + {1, 0, 1, 1, 1, 1, 1}, /* 6 */ + {1, 1, 1, 0, 0, 0, 0}, /* 7 */ + {1, 1, 1, 1, 1, 1, 1}, /* 8 */ + {1, 1, 1, 0, 0, 1, 1} /* 9 */ + }; + + glTranslatef(-0.9, -1.8, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + polys += Rect(0, 0, -0.01, 1.8, 2.6, 0.7); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, front); + glBegin(GL_QUADS); + glVertex2f(-0.05, -0.05); + glVertex2f(-0.05, 2.65); + glVertex2f(1.85, 2.65); + glVertex2f(1.85, -0.05); + polys++; + glEnd(); + glDisable(GL_LIGHTING); /* lit segments dont need light */ + if (!seven && (random() % 30) == 19) { /* randomly change value */ + d->value = random() % 10; + } + for (j = 0 ; j < 7 ; j++) { /* draw the segments */ + GLfloat xx[6], yy[6]; + if (nums[d->value][j]) + glColor3fv(on); + else + glColor3fv(off); + for (k = 0 ; k < 6 ; k++) { + if (j == 0 || j == 3 || j == 6) { + xx[k] = seg_start[j][0] + vdata_h[k][0]; + yy[k] = seg_start[j][1] + vdata_h[k][1]; + } else { + xx[k] = seg_start[j][0] + vdata_v[k][0]; + yy[k] = seg_start[j][1] + vdata_v[k][1]; + } + } + glBegin(GL_POLYGON); + for(i = 0 ; i < 6 ; i++) { + glVertex3f(xx[i], yy[i], 0.01); + } + polys++; + glEnd(); + } + glColor3fv(on); + glPointSize(4); + glBegin(GL_POINTS); + glVertex3f(1.5, 0.2, 0.01); + polys++; + glEnd(); + glEnable(GL_LIGHTING); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shine); + for (x = 0.35 ; x <= 1.5 ; x+= 1.15) { + for ( y = 0.2 ; y <= 2.4 ; y += 0.3) { + polys += ICLeg(x, y, -0.7, 1); + } + } + return polys; +} + +static int HoledRectangle(Circuit *ci, + GLfloat w, GLfloat h, GLfloat d, GLfloat radius, + int p) +{ + int polys = 0; + int step, a; + GLfloat x1, y1, x2, y2; + GLfloat yr, yr1, xr, xr1, side, side1; + GLfloat nx, ny; + + step = 360 / p; + x1 = radius; y1 = 0; + xr1 = w/2; yr1 = 0; + side = w/2; + side1 = h/2; + glBegin(GL_QUADS); + for (a = 0 ; a <= 360 ; a+= step) { + y2=radius*(float)ci->sin_table[(int)a]; + x2=radius*(float)ci->cos_table[(int)a]; + + if (a < 45 || a > 315) { + xr = side; + yr = side1 * ci->tan_table[a]; + nx = 1; ny = 0; + } else if (a <= 135 || a >= 225) { + xr = side/ci->tan_table[a]; + if (a >= 225) { + yr = -side1; + xr = 0 - xr; + nx = 0; ny = -1; + } else { + yr = side1; + nx = 0; ny = 1; + } + } else { + xr = -side; + yr = -side1 * ci->tan_table[a]; + nx = -1; ny = 0; + } + + glNormal3f(-x1, -y1, 0); /* cylinder */ + glVertex3f(x1,y1,0); + glVertex3f(x1,y1,-d); + glVertex3f(x2,y2,-d); + glVertex3f(x2,y2,0); + polys++; + + glNormal3f(0, 0, 1); /* front face */ + glVertex3f(x1,y1,0); + glVertex3f(xr1, yr1, 0); + glVertex3f(xr, yr, 0); + glVertex3f(x2, y2, 0); + polys++; + + glNormal3f(nx, ny, 0); /* side */ + glVertex3f(xr, yr, 0); + glVertex3f(xr, yr, -d); + glVertex3f(xr1, yr1, -d); + glVertex3f(xr1, yr1, 0); + polys++; + + glNormal3f(0, 0, -1); /* back */ + glVertex3f(xr, yr, -d); + glVertex3f(x2, y2, -d); + glVertex3f(x1, y1, -d); + glVertex3f(xr1, yr1, -d); + polys++; + + x1=x2; + y1=y2; + xr1 = xr; yr1 = yr; + } + glEnd(); + return polys; +} + +static int DrawTransistor(Circuit *ci, Transistor *t) +{ + int polys = 0; + GLfloat col[] = {0.3, 0.3, 0.3, 1.0}; + GLfloat spec[] = {0.9, 0.9, 0.9, 1.0}; + GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0}; + GLfloat shin = 30; + + glPushMatrix(); + glMaterialfv(GL_FRONT, GL_SHININESS, &shin); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (t->type == 1) { /* TO-92 style */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col); + glRotatef(90, 0, 1, 0); + glRotatef(90, 0, 0, 1); + polys += createCylinder(ci, 1.0, 0.4, 1, 1); + polys += Rect(0, -0.2, 0.4, 1, 0.2, 0.8); +/* Draw the markings */ + + { + GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0}; + GLfloat s = 0.015; + XCharStruct e; + int w; + texture_string_metrics (ci->font, t->text, &e, 0, 0); + w = e.width; + glPushMatrix(); + glRotatef (90, 1, 0, 0); + glTranslatef (0.5, -0.05, 0.21); + glScalef (s, s, s); + glTranslatef (-w/2, 0, 0); + glColor4fv (texfg); + print_texture_string (ci->font, t->text); + glPopMatrix(); + } + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + glTranslatef(-2, 0, -0.2); + polys += wire(ci, 2); + glTranslatef(0, 0, 0.2); + polys += wire(ci, 2); + glTranslatef(0, 0, 0.2); + polys += wire(ci, 2); + } else if (t->type == 0) { /* TO-220 Style */ + polys += Rect(0, 0, 0, 1.5, 1.5, 0.5); + { + GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0}; + GLfloat s = 0.015; + XCharStruct e; + int w; + texture_string_metrics (ci->font, t->text, &e, 0, 0); + w = e.width; + glPushMatrix(); + glTranslatef (0.75, 0.75, 0.01); + glScalef (s, s, s); + glTranslatef (-w/2, 0, 0); + glColor4fv (texfg); + print_texture_string (ci->font, t->text); + glPopMatrix(); + } + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shin); + polys += Rect(0, 0, -0.5, 1.5, 1.5, 0.30); + if (!glIsEnabled(GL_NORMALIZE)) glEnable(GL_NORMALIZE); + glTranslatef(0.75, 1.875, -0.55); + polys += HoledRectangle(ci, 1.5, 0.75, 0.25, 0.2, 8); + glMaterialfv(GL_FRONT, GL_SPECULAR, nospec); + glTranslatef(-0.375, -1.875, 0); + glRotatef(90, 0, 0, -1); + polys += wire(ci, 2); + glTranslatef(0, 0.375, 0); + polys += wire(ci, 2); + glTranslatef(0, 0.375, 0); + polys += wire(ci, 2); + } else { /* SMC transistor */ +/* Draw the body */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col); + glTranslatef(-0.5, -0.25, 0.1); + polys += Rect(0, 0, 0, 1, 0.5, 0.2); +/* Draw the markings */ + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBegin (GL_QUADS); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); + glVertex3f(0.2, 0, 0.01); + glTexCoord2f(1, 1); + glVertex3f(0.8, 0, 0.01); + glTexCoord2f(1, 0); + glVertex3f(0.8, 0.5, 0.01); + glTexCoord2f(0, 0); + glVertex3f(0.2, 0.5, 0.01); + polys++; + glEnd(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); +/* Now draw the legs */ + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT, GL_SHININESS, &shin); + polys += Rect(0.25, -0.1, -0.05, 0.1, 0.1, 0.2); + polys += Rect(0.75, -0.1, -0.05, 0.1, 0.1, 0.2); + polys += Rect(0.5, 0.5, -0.05, 0.1, 0.1, 0.2); + polys += Rect(0.25, -0.2, -0.2, 0.1, 0.15, 0.1); + polys += Rect(0.75, -0.2, -0.2, 0.1, 0.15, 0.1); + polys += Rect(0.5, 0.5, -0.2, 0.1, 0.15, 0.1); + } + glPopMatrix(); + return polys; +} + +static Component * NewComponent(ModeInfo *mi) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + Component *c; + float rnd; + + c = malloc(sizeof(Component)); + c->angle = RAND_RANGE(0,360); + rnd = f_rand(); + if (rnd < 0.25) { /* come from the top */ + c->y = ci->YMAX/2; + c->x = RAND_RANGE(0, ci->XMAX) - ci->XMAX/2; + if (c->x > 0) + c->dx = 0 - RAND_RANGE(0.5, 2); + else + c->dx = RAND_RANGE(0.5, 2); + c->dy = 0 - RAND_RANGE(0.5, 2); + } else if (rnd < 0.5) { /* come from the bottom */ + c->y = 0 - ci->YMAX/2; + c->x = RAND_RANGE(0, ci->XMAX) - ci->XMAX/2; + if (c->x > 0) + c->dx = 0 - RAND_RANGE(0.5, 2); + else + c->dx = RAND_RANGE(0.5, 2); + c->dy = RAND_RANGE(0.5, 2); + } else if (rnd < 0.75) { /* come from the left */ + c->x = 0 - ci->XMAX/2; + c->y = RAND_RANGE(0, ci->YMAX) - ci->YMAX/2; + c->dx = RAND_RANGE(0.5, 2); + if (c->y > 0) + c->dy = 0 - RAND_RANGE(0.5, 2); + else + c->dy = RAND_RANGE(0.5, 2); + } else { /* come from the right */ + c->x = ci->XMAX/2; + c->y = RAND_RANGE(0, ci->YMAX) - ci->YMAX/2; + c->dx = 0 - RAND_RANGE(0.5, 2); + if (c->y > 0) + c->dy = 0 - RAND_RANGE(0.5, 2); + else + c->dy = RAND_RANGE(0.5, 2); + } + c->z = RAND_RANGE(0, 7) - 9; + c->rotx = f_rand(); + c->roty = f_rand(); + c->rotz = f_rand(); + c->drot = f_rand() * 3; + c->rdeg = 0; + c->dz = f_rand()*2 - 1; + c->norm = 0; + c->alpha = 0; /* explicitly set to 1 later */ + rnd = random() % 11; + if (rnd < 1) { + c->c = NewResistor(); + c->type = 0; + if (f_rand() < 0.4) + c->norm = 1; /* some resistors shine */ + } else if (rnd < 2) { + c->c = NewDiode(); + if (f_rand() < 0.4) + c->norm = 1; /* some diodes shine */ + c->type = 1; + } else if (rnd < 3) { + c->c = NewTransistor(mi); + c->norm = 1; + c->type = 2; + } else if (rnd < 4) { + c->c = NewCapacitor(ci); + c->norm = 1; + c->type = 4; + } else if (rnd < 5) { + c->c = NewIC(mi); + c->type = 5; + c->norm = 1; + } else if (rnd < 6) { + c->c = NewLED(ci); + c->type = 3; + c->norm = 1; + c->alpha = 1; + } else if (rnd < 7) { + c->c = NewFuse(ci); + c->norm = 1; + c->type = 7; + c->alpha = 1; + } else if (rnd < 8) { + c->c = NewRCA(ci); + c->norm = 1; + c->type = 8; + } else if (rnd < 9) { + c->c = NewThreeFive(ci); + c->norm = 1; + c->type = 9; + } else if (rnd < 10) { + c->c = NewSwitch(ci); + c->norm = 1; + c->type = 10; + } else { + c->c = NewDisp(ci); + c->type = 6; + } + return c; +} + +static Transistor *NewTransistor(ModeInfo *mi) +{ + Transistor *t; + + t = malloc(sizeof(Transistor)); + t->type = (random() % 3); + if (t->type == 0) { + t->text = transistortypes[random() % countof(transistortypes)]; + } else if (t->type == 2) { + t->text = smctypes[random() % countof(smctypes)]; + } else if (t->type == 1) { + t->text = to92types[random() % countof(to92types)]; + } + return t; +} + +static Capacitor *NewCapacitor(Circuit *ci) +{ + Capacitor *c; + + c = malloc(sizeof(Capacitor)); + c->type = (f_rand() < 0.5); + if (!c->type) { + c->length = RAND_RANGE(0.5, 1); + c->width = RAND_RANGE(0.5, 1); + } else { + c->width = RAND_RANGE(0.3, 1); + } + return c; +} + +/* 7 segment display */ + +static Disp *NewDisp(Circuit *ci) +{ + Disp *d; + + d = malloc(sizeof(Disp)); + if (seven) + d->value = 7; + else + d->value = RAND_RANGE(0, 10); + return d; +} + + +static IC *NewIC(ModeInfo *mi) +{ + IC *c; + int pins; + const char *val; + int types[countof(ictypes)], i, n = 0; + + c = malloc(sizeof(IC)); + c->type = 0; + switch((int)RAND_RANGE(0,4)) { + case 0: + pins = 8; + break; + case 1: + pins = 14; + break; + case 2: + pins = 16; + break; + case 3: + default: + pins = 24; + break; + } + for (i = 0 ; i < countof(ictypes) ; i++) { + if (ictypes[i].pins == pins) { + types[n] = i; + n++; + } + } + + if (n > countof(types)) abort(); + val = ictypes[types[random() % n]].val; + sprintf(c->text, "%s\n%02d%02d", val, + (int)RAND_RANGE(80, 100), (int)RAND_RANGE(1,53)); + c->pins = pins; + return c; +} + +static LED *NewLED(Circuit *ci) +{ + LED *l; + float r; + + l = malloc(sizeof(LED)); + r = f_rand(); + l->light = 0; + if (!ci->light && (f_rand() < 0.4)) { + ci->light = 1; + l->light = 1; + } + if (r < 0.2) { + l->r = 0.9; l->g = 0; l->b = 0; + } else if (r < 0.4) { + l->r = 0.3; l->g = 0.9; l->b = 0; + } else if (r < 0.6) { + l->r = 0.8; l->g = 0.9; l->b = 0; + } else if (r < 0.8) { + l->r = 0.0; l->g = 0.2; l->b = 0.8; + } else { + l->r = 0.9, l->g = 0.55, l->b = 0; + } + return l; +} + +static Fuse *NewFuse(Circuit *ci) +{ + Fuse *f; + + f = malloc(sizeof(Fuse)); + return f; +} + +static RCA *NewRCA(Circuit *ci) +{ + RCA *r; + + r = malloc(sizeof(RCA)); + r->col = (random() % 10 < 5); + return r; +} + +static ThreeFive *NewThreeFive(Circuit *ci) +{ + ThreeFive *r; + + r = malloc(sizeof(ThreeFive)); + return r; +} + +static Switch *NewSwitch(Circuit *ci) +{ + Switch *s; + + s = malloc(sizeof(Switch)); + s->position = 0; + return s; +} + +static Diode *NewDiode(void) +{ + Band *b; + Diode *ret; + + ret = malloc(sizeof(Diode)); + b = malloc(sizeof(Band)); + b->pos = 0.8; + b->len = 0.1; + if (f_rand() < 0.5) { + b->r = 1; + b->g = 1; + b->b = 1; + ret->r = 0.7; ret->g = 0.1 ; ret->b = 0.1; + } else { + b->r = 1; + b->g = 1; + b->b = 1; + ret->r = 0.2; ret->g = 0.2 ; ret->b = 0.2; + } + ret->band = b; + return ret; +} + + +static Resistor * NewResistor(void) +{ + int v, m, t; /* value, multiplier, tolerance */ + Resistor *ret; + + v = RAND(9); + m = RAND(5); + t = (RAND(10) < 5) ? 10 : 11; + ret = malloc(sizeof(Resistor)); + + if (seven) { + ret->b[0] = ret->b[1] = ret->b[2] = 7; + } else { + ret->b[0] = values[v][0]; + ret->b[1] = values[v][1]; + ret->b[2] = m; + } + ret->b[3] = t; + + return ret; +} + +static void makebandlist(Circuit *ci) +{ + int i; + GLfloat col[] = {0,0,0,0}; + GLfloat spec[] = {0.8,0.8,0.8,0}; + GLfloat shine = 40; + + for (i = 0 ; i < 12 ; i++) { + ci->band_list[i] = glGenLists(1); + glNewList(ci->band_list[i], GL_COMPILE); + col[0] = colorcodes[i][0]; + col[1] = colorcodes[i][1]; + col[2] = colorcodes[i][2]; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shine); + ci->band_list_polys[i] = createCylinder(ci, 0.1, 0.42, 0, 0); + glEndList(); + } +} + + +static int bandedCylinder(Circuit *ci, + float radius, float l, + GLfloat r, GLfloat g, GLfloat bl, + Band **b, int nbands) +{ + int polys = 0; + int n; /* band number */ + GLfloat col[] = {0,0,0,0}; + + col[0] = r; col[1] = g; col[2] = bl; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + polys += createCylinder(ci, l, radius, 1, 0); /* body */ + for (n = 0 ; n < nbands ; n++) { + glPushMatrix(); + glTranslatef(b[n]->pos*l, 0, 0); + col[0] = b[n]->r; col[1] = b[n]->g; col[2] = b[n]->b; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); + polys += createCylinder(ci, b[n]->len*l, radius*1.05, 0, 0); /* band */ + glPopMatrix(); + } + return polys; +} + +static int drawgrid(Circuit *ci) +{ + int polys = 0; + GLfloat x, y; + GLfloat col3[] = {0, 0.8, 0}; + + if (!ci->draw_s) { + if (f_rand() < ((rotatespeed > 0) ? 0.05 : 0.01)) { + ci->draw_sdir = RAND_RANGE(0, 4); + ci->draw_ds = RAND_RANGE(0.4, 0.8); + switch (ci->draw_sdir) { + case 0: + ci->draw_sx = -ci->XMAX/2; + ci->draw_sy = ((int)RAND_RANGE(0, ci->YMAX/2))*2 - ci->YMAX/2; + break; + case 1: + ci->draw_sx = ci->XMAX/2; + ci->draw_sy = ((int)RAND_RANGE(0, ci->YMAX/2))*2 - ci->YMAX/2; + break; + case 2: + ci->draw_sy = ci->YMAX/2; + ci->draw_sx = ((int)RAND_RANGE(0, ci->XMAX/2))*2 - ci->XMAX/2; + break; + case 3: + ci->draw_sy = -ci->YMAX/2; + ci->draw_sx = ((int)RAND_RANGE(0, ci->XMAX/2))*2 - ci->XMAX/2; + break; + } + ci->draw_s = 1; + } + } else if (rotatespeed <= 0) { + if (ci->grid_col[1] < 0.25) { + ci->grid_col[1] += 0.025; ci->grid_col[2] += 0.005; + ci->grid_col2[1] += 0.015 ; ci->grid_col2[2] += 0.005; + } + } + + glDisable(GL_LIGHTING); + if (ci->draw_s) { + glColor3fv(col3); + glPushMatrix(); + glTranslatef(ci->draw_sx, ci->draw_sy, -10); + polys += sphere(ci, 0.1, 10, 10, 0, 10, 0, 10); + if (ci->draw_sdir == 0) + glTranslatef(-ci->draw_ds, 0, 0); + if (ci->draw_sdir == 1) + glTranslatef(ci->draw_ds, 0, 0); + if (ci->draw_sdir == 2) + glTranslatef(0, ci->draw_ds, 0); + if (ci->draw_sdir == 3) + glTranslatef(0, -ci->draw_ds, 0); + polys += sphere(ci, 0.05, 10, 10, 0, 10, 0, 10); + glPopMatrix(); + if (ci->draw_sdir == 0) { + ci->draw_sx += ci->draw_ds; + if (ci->draw_sx > ci->XMAX/2) + ci->draw_s = 0; + } + if (ci->draw_sdir == 1) { + ci->draw_sx -= ci->draw_ds; + if (ci->draw_sx < -ci->XMAX/2) + ci->draw_s = 0; + } + if (ci->draw_sdir == 2) { + ci->draw_sy -= ci->draw_ds; + if (ci->draw_sy < ci->YMAX/2) + ci->draw_s = 0; + } + if (ci->draw_sdir == 3) { + ci->draw_sy += ci->draw_ds; + if (ci->draw_sy > ci->YMAX/2) + ci->draw_s = 0; + } + } else if (rotatespeed <= 0) { + if (ci->grid_col[1] > 0) { + ci->grid_col[1] -= 0.0025; ci->grid_col[2] -= 0.0005; + ci->grid_col2[1] -= 0.0015 ; ci->grid_col2[2] -= 0.0005; + } + } + for (x = -ci->XMAX/2 ; x <= ci->XMAX/2 ; x+= 2) { + glColor3fv(ci->grid_col); + glBegin(GL_LINES); + glVertex3f(x, ci->YMAX/2, -10); + glVertex3f(x, -ci->YMAX/2, -10); + glColor3fv(ci->grid_col2); + glVertex3f(x-0.02, ci->YMAX/2, -10); + glVertex3f(x-0.02, -ci->YMAX/2, -10); + glVertex3f(x+0.02, ci->YMAX/2, -10); + glVertex3f(x+0.02, -ci->YMAX/2, -10); + glEnd(); + } + for (y = -ci->YMAX/2 ; y <= ci->YMAX/2 ; y+= 2) { + glColor3fv(ci->grid_col); + glBegin(GL_LINES); + glVertex3f(-ci->XMAX/2, y, -10); + glVertex3f(ci->XMAX/2, y, -10); + glColor3fv(ci->grid_col2); + glVertex3f(-ci->XMAX/2, y-0.02, -10); + glVertex3f(ci->XMAX/2, y-0.02, -10); + glVertex3f(-ci->XMAX/2, y+0.02, -10); + glVertex3f(ci->XMAX/2, y+0.02, -10); + glEnd(); + } + glEnable(GL_LIGHTING); + return polys; +} + +static void display(ModeInfo *mi) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + GLfloat light_sp[] = {0.8, 0.8, 0.8, 1.0}; + GLfloat black[] = {0, 0, 0, 1.0}; + int j; + + mi->polygon_count = 0; + + if (ci->display_i == 0) { + for (ci->display_i = 0 ; ci->display_i < maxparts ; ci->display_i++) { + ci->components[ci->display_i] = NULL; + } + } + glEnable(GL_LIGHTING); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + gluLookAt(ci->viewer[0], ci->viewer[1], ci->viewer[2], + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + glPushMatrix(); + glRotatef(ci->rotate_angle, 0, 0, 1); + ci->rotate_angle += 0.01 * (float)rotatespeed; + if (ci->rotate_angle >= 360) ci->rotate_angle = 0; + + glLightfv(GL_LIGHT0, GL_POSITION, ci->lightpos); + glLightfv(GL_LIGHT0, GL_SPECULAR, light_sp); + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_sp); + glLighti(GL_LIGHT0, GL_CONSTANT_ATTENUATION, (GLfloat)1); + glLighti(GL_LIGHT0, GL_LINEAR_ATTENUATION, (GLfloat)0.5); + glLighti(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, (GLfloat)0); + +# ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */ + { + GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi); + int o = (int) current_device_rotation(); + if (o != 0 && o != 180 && o != -180) + glScalef (h, h, h); + h = 2; + glScalef (h, h, h); + } +# endif + + mi->polygon_count += drawgrid(ci); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light_sp); + if (f_rand() < 0.05) { + for (j = 0 ; j < maxparts ; j++) { + if (ci->components[j] == NULL) { + ci->components[j] = NewComponent(mi); + j = maxparts; + } + } + reorder(&ci->components[0]); + } + for (j = 0 ; j < maxparts ; j++) { + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, black); + glMaterialfv(GL_FRONT, GL_EMISSION, black); + glMaterialfv(GL_FRONT, GL_SPECULAR, black); + if (ci->components[j] != NULL) { + if (DrawComponent(ci, ci->components[j], &mi->polygon_count)) { + free(ci->components[j]); ci->components[j] = NULL; + } + } + } + glPopMatrix(); + glFlush(); +} + +/* ensure transparent components are at the end */ +static void reorder(Component *c[]) +{ + int i, j, k; + Component *c1[MAX_COMPONENTS]; + Component *c2[MAX_COMPONENTS]; + + j = 0; + for (i = 0 ; i < maxparts ; i++) { /* clear old matrix */ + c1[i] = NULL; + c2[i] = NULL; + } + for (i = 0 ; i < maxparts ; i++) { + if (c[i] == NULL) continue; + if (c[i]->alpha) { /* transparent parts go to c1 */ + c1[j] = c[i]; + j++; + } else { /* opaque parts go to c2 */ + c2[i] = c[i]; + } + } + for (i = 0 ; i < maxparts ; i++) { /* clear old matrix */ + c[i] = NULL; + } + k = 0; + for (i = 0 ; i < maxparts ; i++) { /* insert opaque part */ + if (c2[i] != NULL) { + c[k] = c2[i]; + k++; + } + } + for (i = 0 ; i < j ; i++) { /* insert transparent parts */ + c[k] = c1[i]; + k++; + } +} + +ENTRYPOINT void reshape_circuit(ModeInfo *mi, int width, int height) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + int y = 0; + GLfloat h = (GLfloat) height / (GLfloat) width; + + if (width > height * 5) { /* tiny window: show middle */ + height = width * 9/16; + y = -height/2; + h = height / (GLfloat) width; + } + + glViewport(0,y,(GLint)width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0,1.0,-h,h,1.5,35.0); + glMatrixMode(GL_MODELVIEW); + ci->win_h = height; + ci->win_w = width; + ci->YMAX = ci->XMAX * h; +} + + +ENTRYPOINT void init_circuit(ModeInfo *mi) +{ +int screen = MI_SCREEN(mi); +Circuit *ci; + + MI_INIT(mi, circuit); + ci = &circuit[screen]; + ci->window = MI_WINDOW(mi); + + ci->XMAX = ci->YMAX = 50; + ci->viewer[2] = 14; + ci->lightpos[0] = 7; + ci->lightpos[1] = 7; + ci->lightpos[2] = 15; + ci->lightpos[3] = 1; + + ci->grid_col[1] = 0.25; + ci->grid_col[2] = 0.05; + ci->grid_col2[1] = 0.125; + ci->grid_col2[2] = 0.05; + + ci->font = load_texture_font (MI_DISPLAY(mi), "componentFont"); + + if (maxparts >= MAX_COMPONENTS) + maxparts = MAX_COMPONENTS-1; + + if ((ci->glx_context = init_GL(mi)) != NULL) { + reshape_circuit(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + } else { + MI_CLEARWINDOW(mi); + } + if (uselight == 0) + ci->light = 1; + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + make_tables(ci); + makebandlist(ci); + +} + +ENTRYPOINT void draw_circuit(ModeInfo *mi) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + + if (!ci->glx_context) + return; + + glXMakeCurrent(disp, w, *(ci->glx_context)); + + display(mi); + + if(mi->fps_p) do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); +} + +ENTRYPOINT void free_circuit(ModeInfo *mi) +{ + Circuit *ci = &circuit[MI_SCREEN(mi)]; + if (ci->font) + free_texture_font (ci->font); + FreeAllGL(mi); +} + +XSCREENSAVER_MODULE ("Circuit", circuit) + +#endif |