X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fcircuit.c;h=e6636c29f2f0a1d6f842200e3360b436d84e73d8;hp=867ccb9279b7958e56388e6177b6acd4885f40fa;hb=ffd8c0873576a9e3065696a624dce6b766b77062;hpb=a1d41b2aa6e18bf9a49b914a99dda8232c5d7762 diff --git a/hacks/glx/circuit.c b/hacks/glx/circuit.c index 867ccb92..e6636c29 100644 --- a/hacks/glx/circuit.c +++ b/hacks/glx/circuit.c @@ -1,12 +1,17 @@ /* * circuit - Random electronic components floating around * - * version 1.3 + * 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 Ben Buxton (bb@cactii.net) + * Copyright (C) 2001,2002 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 @@ -49,6 +54,7 @@ "*seven: " DEF_SEVEN "\n" \ "*light: True \n" \ "*rotate: False\n" \ + "*font: fixed\n" \ "*rotatespeed: 1\n" \ # include "xlockmore.h" /* from the xscreensaver distribution */ @@ -64,7 +70,10 @@ #ifdef USE_GL #include +#include "font-ximage.h" +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) static int maxparts; static int spin; @@ -72,6 +81,7 @@ static int seven; static int rotate; static int rotatespeed; static int uselight; +static char *font; int def_parts = 10; #undef countof @@ -79,24 +89,26 @@ int def_parts = 10; static XrmOptionDescRec opts[] = { {"-parts", ".circuit.parts", XrmoptionSepArg, "10" }, + {"-font", ".circuit.font", XrmoptionSepArg, "fixed" }, {"-rotate-speed", ".circuit.rotatespeed", XrmoptionSepArg, "1" }, - {"+spin", ".circuit.spin", XrmoptionNoArg, (caddr_t) "false" }, - {"-spin", ".circuit.spin", XrmoptionNoArg, (caddr_t) "true" }, - {"+light", ".circuit.light", XrmoptionNoArg, (caddr_t) "false" }, - {"-light", ".circuit.light", XrmoptionNoArg, (caddr_t) "true" }, - {"+seven", ".circuit.seven", XrmoptionNoArg, (caddr_t) "false" }, - {"-seven", ".circuit.seven", XrmoptionNoArg, (caddr_t) "true" }, - {"+rotate", ".circuit.rotate", XrmoptionNoArg, (caddr_t) "false" }, - {"-rotate", ".circuit.rotate", XrmoptionNoArg, (caddr_t) "true" }, + {"+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" }, + {"+rotate", ".circuit.rotate", XrmoptionNoArg, "false" }, + {"-rotate", ".circuit.rotate", XrmoptionNoArg, "true" }, }; static argtype vars[] = { - {(caddr_t *) &maxparts, "parts", "Parts", DEF_PARTS, t_Int}, - {(caddr_t *) &rotatespeed, "rotatespeed", "Rotatespeed", "1", t_Int}, - {(caddr_t *) &spin, "spin", "Spin", DEF_SPIN, t_Bool}, - {(caddr_t *) &rotate, "rotate", "Rotate", "False", t_Bool}, - {(caddr_t *) &uselight, "light", "Light", "True", t_Bool}, - {(caddr_t *) &seven, "seven", "Seven", DEF_SEVEN, t_Bool}, + {&maxparts, "parts", "Parts", DEF_PARTS, t_Int}, + {&font, "font", "Font", "fixed", t_String}, + {&rotatespeed, "rotatespeed", "Rotatespeed", "1", t_Int}, + {&spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&rotate, "rotate", "Rotate", "False", t_Bool}, + {&uselight, "light", "Light", "True", t_Bool}, + {&seven, "seven", "Seven", DEF_SEVEN, t_Bool}, }; ModeSpecOpt circuit_opts = {countof(opts), opts, countof(vars), vars, NULL}; @@ -133,11 +145,11 @@ int win_w, win_h; /* width and height of viewport */ #define XMAX 30 -#define YMAX 30 +static int YMAX = 30; #define MAX_COMPONENTS 30 -#define MOVE_MULT 0.05 +#define MOVE_MULT 0.02 static float f_rand(void) { return ((float)RAND(10000)/(float)10000); @@ -149,6 +161,9 @@ static float f_rand(void) { int light = 0; int lighton = 0; +/* stores refs to textures */ +static int s_refs[50]; + static GLfloat viewer[] = {0.0, 0.0, 14.0}; static GLfloat lightpos[] = {7.0, 7.0, 15, 1.0}; @@ -156,6 +171,14 @@ float sin_table[720]; float cos_table[720]; float tan_table[720]; +ModeInfo *modeinfo; + +/* used for allocating font textures */ +typedef struct { + int num; /* index number */ + int w; /* width */ + int h; /* height */ +} TexNum; /* Represents a band on a resistor/diode/etc */ typedef struct { @@ -174,8 +197,51 @@ typedef struct { GLfloat r, g, b; /* body colour */ } Diode; +static const char * transistortypes[] = { + "TIP2955", + "TIP32C", + "LM 350T", + "IRF730", + "ULN2577", + "7805T", + "7912T", + "TIP120", + "2N6401", + "BD239", + "2SC1590", + "MRF485", + "SC141D" +}; + +static const char * 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 * smctypes[] = { + "1M-", + "1K", + "1F", + "B10", + "S14", + "Q3", + "4A" +}; + typedef struct { int type; /* package type. 0 = to-92, 1 = to-220 */ + GLfloat tw, th; /* texture dimensions */ + GLuint tnum; /* texture binding */ } Transistor; typedef struct { @@ -189,9 +255,68 @@ typedef struct { 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; + float tw, th; /* texture dimensions for markings */ + int tnum; /* texture number */ } IC; /* 7 segment display */ @@ -204,6 +329,11 @@ 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 */ @@ -258,10 +388,18 @@ void DrawIC(IC *); void DrawCapacitor(Capacitor *); void DrawDisp(Disp *); void DrawFuse(Fuse *); +void DrawRCA(RCA *); +void DrawThreeFive(ThreeFive *); +void DrawSwitch(Switch *); +void freetexture(GLuint); void reorder(Component *[]); void circle(float, int,int); void bandedCylinder(float, float , GLfloat, GLfloat , GLfloat, Band **, int); +TexNum *fonttexturealloc(const char *, float *, float *); +void Rect(GLfloat , GLfloat , GLfloat, GLfloat , GLfloat ,GLfloat); +void ICLeg(GLfloat, GLfloat, GLfloat, int); +void HoledRectangle(GLfloat, GLfloat, GLfloat, GLfloat, int); Resistor *NewResistor(void); Diode *NewDiode(void); Transistor *NewTransistor(void); @@ -270,6 +408,9 @@ Capacitor *NewCapacitor(void); IC* NewIC(void); Disp* NewDisp(void); Fuse *NewFuse(void); +RCA *NewRCA(void); +ThreeFive *NewThreeFive(void); +Switch *NewSwitch(void); /* we use trig tables to speed things up - 200 calls to sin() in one frame can be a bit harsh.. @@ -292,18 +433,21 @@ float f; } -void createCylinder (float length, float radius, int endcaps, int half) { -int a; /* current angle around cylinder */ -int angle, norm; -float z1, y1, z2, y2, ex; -int nsegs; +void createCylinder (float length, float radius, int endcaps, int half) +{ + int a; /* current angle around cylinder */ + int angle, norm; + float z1, y1, z2, y2,ex; + int step; + int nsegs; glPushMatrix(); - nsegs = radius*MAX(win_w, win_h)/10; - nsegs = MAX(nsegs, 6); + nsegs = radius*MAX(win_w, win_h)/20; + nsegs = MAX(nsegs, 4); if (nsegs % 2) nsegs += 1; angle = (half) ? (180 - 90/nsegs) : 374; + step = angle/nsegs; z1 = radius; y1 = 0; glBegin(GL_QUADS); for (a = 0 ; a <= angle ; a+= angle/nsegs) { @@ -312,6 +456,7 @@ int nsegs; glNormal3f(0, y1, z1); glVertex3f(0,y1,z1); glVertex3f(length,y1,z1); + glNormal3f(0, y2, z2); glVertex3f(length,y2,z2); glVertex3f(0,y2,z2); z1=z2; @@ -331,27 +476,28 @@ int nsegs; 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)sin_table[(int)a]; z2=radius*(float)cos_table[(int)a]; - glBegin(GL_TRIANGLES); - glNormal3f(norm, 0, 0); glVertex3f(ex,0, 0); glVertex3f(ex,y1,z1); glVertex3f(ex,y2,z2); - glEnd(); z1=z2; y1=y2; } + glEnd(); } } glPopMatrix(); } -void circle(float radius, int segments, int half) { -float x1 = 0, x2 = 0; -float y1 = 0, y2 = 0; -int i, t, s; +void circle(float radius, int segments, int half) +{ + float x1 = 0, x2 = 0; + float y1 = 0, y2 = 0; + int i, t, s; if (half) { t = 270; s = 90; @@ -375,12 +521,13 @@ int i, t, s; glEnd(); } -void wire(float len) { -static GLfloat col[] = {0.3, 0.3, 0.3, 1.0}; -static GLfloat spec[] = {0.9, 0.9, 0.9, 1.0}; -static GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0}; -GLfloat shin = 30; -int n; +void wire(float len) +{ + static GLfloat col[] = {0.3, 0.3, 0.3, 1.0}; + static GLfloat spec[] = {0.9, 0.9, 0.9, 1.0}; + static 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); @@ -392,10 +539,11 @@ int n; glMaterialfv(GL_FRONT, GL_SPECULAR, nospec); } -void ring(GLfloat inner, GLfloat outer, int nsegs) { -GLfloat z1, z2, y1, y2; -GLfloat Z1, Z2, Y1, Y2; -int i; +void ring(GLfloat inner, GLfloat outer, int nsegs) +{ + GLfloat z1, z2, y1, y2; + GLfloat Z1, Z2, Y1, Y2; + int i; z1 = inner; y1 = 0; Z1 = outer; Y1 = 0; @@ -422,55 +570,60 @@ int i; void sphere(GLfloat r, float stacks, float slices, int startstack, int endstack, int startslice, - int endslice) { -GLfloat d, d1, dr, dr1, Dr, Dr1, D, D1, z1, z2, y1, y2, Y1, Z1, Y2, Z2; -int a, a1, b, b1, c, c1; -GLfloat step, sstep; - - step = 180/stacks; - sstep = 360/slices; - a1 = startstack * step; - b1 = startslice * sstep; - y1 = z1 = Y1 = Z1 = 0; - c = (endslice / slices) * 360; - c1 = (endstack/stacks)*180; - glBegin(GL_QUADS); - for (a = startstack * step ; a <= c1 ; a+= step) { - d=sin_table[a]; - d1=sin_table[a1]; - D=cos_table[a]; - D1=cos_table[a1]; - dr = d * r; - dr1 = d1 * r; - Dr = D * r; - Dr1 = D1 * r; - for (b = b1 ; b <= c ; b+= sstep) { - y2=dr*sin_table[b]; - z2=dr*cos_table[b]; - Y2=dr1*sin_table[b]; - Z2=dr1*cos_table[b]; - glNormal3f(D, y1, z1); - glVertex3f(Dr,y1,z1); - glVertex3f(Dr,y2,z2); - glVertex3f(Dr1,Y2,Z2); - glVertex3f(Dr1,Y1,Z1); - z1=z2; - y1=y2; - Z1=Z2; - Y1=Y2; - } - a1 = a; - } - glEnd(); + int endslice) +{ + GLfloat d, d1, dr, dr1, Dr, Dr1, D, D1, z1, z2, y1, y2, Y1, Z1, Y2, Z2; + int a, a1, b, b1, c, c1; + GLfloat step, sstep; + + step = 180/stacks; + sstep = 360/slices; + a1 = startstack * step; + b1 = startslice * sstep; + y1 = z1 = Y1 = Z1 = 0; + c = (endslice / slices) * 360; + c1 = (endstack/stacks)*180; + glBegin(GL_QUADS); + for (a = startstack * step ; a <= c1 ; a+= step) { + d=sin_table[a]; + d1=sin_table[a1]; + D=cos_table[a]; + D1=cos_table[a1]; + dr = d * r; + dr1 = d1 * r; + Dr = D * r; + Dr1 = D1 * r; + for (b = b1 ; b <= c ; b+= sstep) { + y2=dr*sin_table[b]; + z2=dr*cos_table[b]; + Y2=dr1*sin_table[b]; + Z2=dr1*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); + z1=z2; + y1=y2; + Z1=Z2; + Y1=Y2; + } + a1 = a; + } + glEnd(); } -int DrawComponent(Component *c) { -int ret = 0; /* return 1 if component is freed */ +int DrawComponent(Component *c) +{ + int ret = 0; /* return 1 if component is freed */ glPushMatrix(); glTranslatef(c->x, c->y, c->z); if (c->angle > 0) { - glRotatef(c->angle, 0, 0, 1); + glRotatef(c->angle, c->rotx, c->roty, c->rotz); } if (spin) { glRotatef(c->rdeg, c->rotx, c->roty, c->rotz); @@ -504,6 +657,12 @@ int ret = 0; /* return 1 if component is freed */ DrawDisp(c->c); } else if (c->type == 7) { DrawFuse(c->c); + } else if (c->type == 8) { + DrawRCA(c->c); + } else if (c->type == 9) { + DrawThreeFive(c->c); + } else if (c->type == 10) { + DrawSwitch(c->c); } c->x += c->dx * MOVE_MULT; c->y += c->dy * MOVE_MULT; @@ -513,6 +672,16 @@ int ret = 0; /* return 1 if component is freed */ glDisable(GL_LIGHT1); light = 0; lighton = 0; } + if (c->type == 5) { + if (((IC *)c->c)->tnum) + freetexture(((IC *)c->c)->tnum); + } + if (c->type == 2) { + if (((Transistor *)c->c)->tnum) + freetexture(((Transistor *)c->c)->tnum); + } + if (c->type == 1) + free(((Diode *)c->c)->band); /* remember to free diode band */ free(c->c); ret = 1; } @@ -521,13 +690,15 @@ int ret = 0; /* return 1 if component is freed */ glDisable(GL_NORMALIZE); return ret; } + /* draw a resistor */ -void DrawResistor(Resistor *r) { -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; +void DrawResistor(Resistor *r) +{ + 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); wire(3); @@ -546,12 +717,81 @@ GLfloat shine = 30; wire(3); } -void DrawFuse(Fuse *f) { -static GLfloat col[] = {0.5, 0.5, 0.5, 1.0}; /* endcaps */ -static GLfloat glass[] = {0.4, 0.4, 0.4, 0.3}; /* glass */ -static GLfloat spec[] = {1, 1, 1, 1}; /* glass */ +void DrawRCA(RCA *rca) +{ + static GLfloat col[] = {0.6, 0.6, 0.6, 1.0}; /* metal */ + static GLfloat red[] = {1.0, 0.0, 0.0, 1.0}; /* red */ + static GLfloat white[] = {1.0, 1.0, 1.0, 1.0}; /* white */ + static 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); + createCylinder(0.7, 0.45, 0, 0); + glTranslatef(0.4, 0, 0); + createCylinder(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); + createCylinder(1.5, 0.6, 1, 0); + glTranslatef(-0.9, 0, 0); + createCylinder(0.9, 0.25, 0, 0); + glTranslatef(0.1, 0, 0); + createCylinder(0.2, 0.3, 0, 0); + glTranslatef(0.3, 0, 0); + createCylinder(0.2, 0.3, 1, 0); + glTranslatef(0.3, 0, 0); + createCylinder(0.2, 0.3, 1, 0); + glPopMatrix(); +} + +void DrawSwitch(Switch *f) +{ + static GLfloat col[] = {0.6, 0.6, 0.6, 0}; /* metal */ + static GLfloat dark[] = {0.1, 0.1, 0.1, 1.0}; /* dark */ + static GLfloat brown[] = {0.69, 0.32, 0, 1.0}; /* brown */ + static 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); + Rect(-0.25, 0, 0, 1.5, 0.5, 0.75); +/* Rect(-0.5, 0.5, 0, 2, 0.1, 0.75); */ + glPushMatrix(); + glRotatef(90, 1, 0, 0); + glTranslatef(-0.5, -0.4, -0.4); + HoledRectangle(0.5, 0.75, 0.1, 0.15, 8); + glTranslatef(2, 0, 0); + HoledRectangle(0.5, 0.75, 0.1, 0.15, 8); + glPopMatrix(); + Rect(0.1, -0.4, -0.25, 0.1, 0.4, 0.05); + Rect(0.5, -0.4, -0.25, 0.1, 0.4, 0.05); + Rect(0.9, -0.4, -0.25, 0.1, 0.4, 0.05); + Rect(0.1, -0.4, -0.5, 0.1, 0.4, 0.05); + Rect(0.5, -0.4, -0.5, 0.1, 0.4, 0.05); + 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); + Rect(0, 0.5, -0.1, 1, 0.05, 0.5); + Rect(0, 0.6, -0.1, 0.5, 0.6, 0.5); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown); + Rect(-0.2, -0.01, -0.1, 1.4, 0.1, 0.55); + glPopMatrix(); +} + + +void DrawFuse(Fuse *f) +{ + static GLfloat col[] = {0.5, 0.5, 0.5, 1.0}; /* endcaps */ + static GLfloat glass[] = {0.4, 0.4, 0.4, 0.3}; /* glass */ + static 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); @@ -559,7 +799,6 @@ static GLfloat spec[] = {1, 1, 1, 1}; /* glass */ glTranslatef(0.8, 0, 0); glEnable(GL_BLEND); glDepthMask(GL_FALSE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, glass); glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 40); createCylinder(2, 0.4, 0, 0); @@ -578,24 +817,26 @@ static GLfloat spec[] = {1, 1, 1, 1}; /* glass */ } -void DrawCapacitor(Capacitor *c) { -static GLfloat col[] = {0, 0, 0, 0}; -static GLfloat spec[] = {0.8, 0.8, 0.8, 0}; -GLfloat brown[] = {0.84, 0.5, 0}; -static GLfloat shine = 40; +void DrawCapacitor(Capacitor *c) +{ + static GLfloat col[] = {0, 0, 0, 0}; + static GLfloat spec[] = {0.8, 0.8, 0.8, 0}; + GLfloat brown[] = {0.84, 0.5, 0}; + static GLfloat shine = 40; glPushMatrix(); if (c->type) { glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown); - sphere(c->width, 20, 20, 0, 5 ,0, 20); - glTranslatef(1.45*c->width, 0, 0); - sphere(c->width, 20, 20, 15, 20, 0, 20); + sphere(c->width, 15, 15, 0, 4 ,0, 15); + glTranslatef(1.35*c->width, 0, 0); + sphere(c->width, 15, 15, 11, 15, 0, 15); glRotatef(90, 0, 0, 1); glTranslatef(0, 0.7*c->width, 0.3*c->width); wire(3*c->width); glTranslatef(0, 0, -0.6*c->width); wire(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); @@ -605,23 +846,24 @@ static GLfloat shine = 40; glVertex3f(3*c->length, 0.82*c->width, 0.1); glVertex3f(0, 0.82*c->width, 0.1); glEnd(); - col[0] = 0.7; - col[1] = 0.7; - col[2] = 0.7; - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); - circle(0.6*c->width, 30, 0); col[0] = 0.0; col[1] = 0.2; col[2] = 0.9; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); - ring(0.6*c->width, 0.8*c->width, 30); - glTranslatef(0.01, 0.0, 0); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1.0); createCylinder(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); + circle(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.01*c->length, 0.0, 0); + glTranslatef(3.0*c->length, 0.0, 0); circle(0.6*c->width, 30, 0); glTranslatef(0, 0.4*c->width, 0); wire(3*c->length); @@ -631,8 +873,10 @@ static GLfloat shine = 40; glPopMatrix(); } -void DrawLED(LED *l) { -GLfloat col[] = {0, 0, 0, 0.6}; +void DrawLED(LED *l) +{ + 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 && light) { @@ -640,7 +884,8 @@ GLfloat col[] = {0, 0, 0, 0.6}; glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, dir); if (!lighton) { glLightfv(GL_LIGHT1, GL_SPECULAR, col); - glLightfv(GL_LIGHT1, GL_AMBIENT, 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); @@ -658,12 +903,13 @@ GLfloat col[] = {0, 0, 0, 0.6}; glDepthMask(GL_FALSE); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); } + glTranslatef(-0.9, 0, 0); createCylinder(1.2, 0.3, 0, 0); if (l->light && light) { glDisable(GL_LIGHTING); glColor3fv(col); } - sphere(0.3, 10, 10, 5, 10, 0, 10); + sphere(0.3, 7, 7, 3, 7, 0, 7); if (l->light && light) { glEnable(GL_LIGHTING); } else { @@ -686,13 +932,45 @@ GLfloat col[] = {0, 0, 0, 0.6}; } } } + + +void DrawThreeFive(ThreeFive *d) +{ + GLfloat shine = 40; + GLfloat dark[] = {0.3, 0.3, 0.3, 0}; + GLfloat light[] = {0.6, 0.6, 0.6, 0}; + GLfloat cream[] = {0.8, 0.8, 0.6, 0}; + GLfloat 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); + createCylinder(0.7, 0.2, 0, 0); + glTranslatef(0.7, 0, 0); + createCylinder(1.3, 0.4, 1, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light); + glTranslatef(1.3, 0, 0); + createCylinder(1.3, 0.2, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, dark); + glTranslatef(0.65, 0, 0); + createCylinder(0.15, 0.21, 0, 0); + glTranslatef(0.3, 0, 0); + createCylinder(0.15, 0.21, 0, 0); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light); + glTranslatef(0.4, 0, 0); + sphere(0.23, 7, 7, 0, 5, 0, 7); + glPopMatrix(); +} -void DrawDiode(Diode *d) { -GLfloat shine = 40; -GLfloat col[] = {0.3, 0.3, 0.3, 0}; -GLfloat spec[] = {0.7, 0.7, 0.7, 0}; +void DrawDiode(Diode *d) +{ + 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); @@ -708,10 +986,11 @@ GLfloat spec[] = {0.7, 0.7, 0.7, 0}; } void Rect(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h, - GLfloat t) { -GLfloat yh; -GLfloat xw; -GLfloat zt; + GLfloat t) +{ + GLfloat yh; + GLfloat xw; + GLfloat zt; yh = y+h; xw = x+w; zt = z - t; @@ -756,9 +1035,8 @@ GLfloat zt; /* IC pins */ -void ICLeg(GLfloat x, GLfloat y, GLfloat z, int dir) { - - +void ICLeg(GLfloat x, GLfloat y, GLfloat z, int dir) +{ if (dir) { Rect(x-0.1, y, z, 0.1, 0.1, 0.02); Rect(x-0.1, y, z, 0.02, 0.1, 0.1); @@ -772,19 +1050,23 @@ void ICLeg(GLfloat x, GLfloat y, GLfloat z, int dir) { } -void DrawIC(IC *c) { -GLfloat w, h, d; -int z; -GLfloat col[] = {0.1, 0.1, 0.1, 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; +void DrawIC(IC *c) +{ + 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; + float mult, th, size; 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: @@ -802,6 +1084,8 @@ GLfloat lshine = 40; 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); @@ -834,6 +1118,30 @@ GLfloat lshine = 40; glVertex3f(w, h, 0.1); glVertex3f(-w, h, 0.1); glEnd(); + glDisable(GL_POLYGON_OFFSET_FILL); + if (c->tnum) glBindTexture(GL_TEXTURE_2D, c->tnum); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + if (c->pins == 8) + size = 0.4; + else + size = 0.6; + th = size*2/3; + mult = size*c->tw / c->th; + mult /= 2; + glBegin(GL_QUADS); /* text markings */ + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); + glVertex3f(th, mult, 0.1); + glTexCoord2f(1, 1); + glVertex3f(th, -mult, 0.1); + glTexCoord2f(1, 0); + glVertex3f(-th, -mult, 0.1); + glTexCoord2f(0, 0); + glVertex3f(-th, mult, 0.1); + glEnd(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); d = (h*2-0.1) / c->pins; d*=2; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol); @@ -845,64 +1153,65 @@ GLfloat lshine = 40; for (z = 0 ; z < c->pins/2 ; z++) { 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); + circle(0.1, 7, 0); glPopMatrix(); } -void DrawDisp(Disp *d) { -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 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 GLfloat vdata_v[6][2] = +void DrawDisp(Disp *d) { - {0.27, 0}, - {0.35, -0.1}, - {0.2, -0.9}, - {0.1, -1}, - {0, -0.9}, - {0.15, -0.15} -}; - -static 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 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 */ -}; - + 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 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 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 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 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); Rect(0, 0, -0.01, 1.8, 2.6, 0.7); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, front); @@ -953,11 +1262,12 @@ static int nums[10][7] = } } -void HoledRectangle(GLfloat w, GLfloat h, GLfloat d, GLfloat radius, int p) { -int step, a; -GLfloat x1, y1, x2, y2; -GLfloat yr, yr1, xr, xr1, side, side1; -GLfloat nx, ny; +void HoledRectangle(GLfloat w, GLfloat h, GLfloat d, GLfloat radius, int p) +{ + 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; @@ -1020,33 +1330,82 @@ GLfloat nx, ny; glEnd(); } -void DrawTransistor(Transistor *t) { -static GLfloat col[] = {0.3, 0.3, 0.3, 1.0}; -static GLfloat spec[] = {0.9, 0.9, 0.9, 1.0}; -static GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0}; -GLfloat shin = 30; +void DrawTransistor(Transistor *t) +{ + static GLfloat col[] = {0.3, 0.3, 0.3, 1.0}; + static GLfloat spec[] = {0.9, 0.9, 0.9, 1.0}; + static 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); - if (t->type == 1) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (t->type == 1) { /* TO-92 style */ + float mult, y1, y2; + mult = 1.5*t->th/t->tw; + y1 = 0.2+mult/2; + y2 = 0.8-mult/2; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col); glRotatef(90, 0, 1, 0); glRotatef(90, 0, 0, 1); createCylinder(1.0, 0.4, 1, 1); Rect(0, -0.2, 0.4, 1, 0.2, 0.8); +/* Draw the markings */ + glEnable(GL_TEXTURE_2D); + if (t->tnum) glBindTexture(GL_TEXTURE_2D, t->tnum); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBegin (GL_QUADS); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); + glVertex3f(y1, -0.21, 0.3); + glTexCoord2f(1, 1); + glVertex3f(y1, -0.21, -0.3); + glTexCoord2f(1, 0); + glVertex3f(y2, -0.21, -0.3); + glTexCoord2f(0, 0); + glVertex3f(y2, -0.21, 0.3); + glEnd(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glDepthMask(GL_TRUE); glTranslatef(-2, 0, -0.2); wire(2); glTranslatef(0, 0, 0.2); wire(2); glTranslatef(0, 0, 0.2); wire(2); - } else { - Rect(0, 0, 0, 1.5, 1.5, 0.75); - glTranslatef(0.75, 1.875, -0.5); + } else if (t->type == 0) { /* TO-220 Style */ + float mult, y1, y2; + mult = 1.5*t->th/t->tw; + y1 = 0.75+mult/2; + y2 = 0.75-mult/2; + Rect(0, 0, 0, 1.5, 1.5, 0.5); + glEnable(GL_TEXTURE_2D); + if (t->tnum) glBindTexture(GL_TEXTURE_2D, t->tnum); + glEnable(GL_BLEND); + glDepthMask(GL_FALSE); + glBegin (GL_QUADS); + glNormal3f(0, 0, 1); + glTexCoord2f(0, 1); + glVertex3f(0, y1, 0.01); + glTexCoord2f(1, 1); + glVertex3f(1.5, y1, 0.01); + glTexCoord2f(1, 0); + glVertex3f(1.5, y2, 0.01); + glTexCoord2f(0, 0); + glVertex3f(0, y2, 0.01); + glEnd(); + 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); - if (glIsEnabled(GL_NORMALIZE)) glEnable(GL_NORMALIZE); + 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); HoledRectangle(1.5, 0.75, 0.25, 0.2, 8); glMaterialfv(GL_FRONT, GL_SPECULAR, nospec); glTranslatef(-0.375, -1.875, 0); @@ -1056,13 +1415,48 @@ GLfloat shin = 30; wire(2); glTranslatef(0, 0.375, 0); wire(2); + } else { /* SMC transistor */ +/* Draw the body */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col); + glTranslatef(-0.5, -0.25, 0.1); + Rect(0, 0, 0, 1, 0.5, 0.2); +/* Draw the markings */ + glEnable(GL_TEXTURE_2D); + if (t->tnum) glBindTexture(GL_TEXTURE_2D, t->tnum); + 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); + 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); + Rect(0.25, -0.1, -0.05, 0.1, 0.1, 0.2); + Rect(0.75, -0.1, -0.05, 0.1, 0.1, 0.2); + Rect(0.5, 0.5, -0.05, 0.1, 0.1, 0.2); + Rect(0.25, -0.2, -0.2, 0.1, 0.15, 0.1); + Rect(0.75, -0.2, -0.2, 0.1, 0.15, 0.1); + Rect(0.5, 0.5, -0.2, 0.1, 0.15, 0.1); } glPopMatrix(); } -Component * NewComponent(void) { -Component *c; -float rnd; +Component * NewComponent(void) +{ + Component *c; + float rnd; c = malloc(sizeof(Component)); c->angle = RAND_RANGE(0,360); @@ -1104,44 +1498,56 @@ float rnd; c->rotx = f_rand(); c->roty = f_rand(); c->rotz = f_rand(); - c->drot = f_rand() * 7; + 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 = f_rand(); - if (rnd < 0.1) { + 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 < 0.2) { + } else if (rnd < 2) { c->c = NewDiode(); if (f_rand() < 0.4) c->norm = 1; /* some diodes shine */ c->type = 1; - } else if (rnd < 0.3) { + } else if (rnd < 3) { c->c = NewTransistor(); c->norm = 1; c->type = 2; - } else if (rnd < 0.4) { + } else if (rnd < 4) { c->c = NewCapacitor(); - if (f_rand() < 0.4) - c->norm = 1; /* some capacitors shine */ + c->norm = 1; c->type = 4; - } else if (rnd < 0.6) { + } else if (rnd < 5) { c->c = NewIC(); c->type = 5; - } else if (rnd < 0.7) { + c->norm = 1; + } else if (rnd < 6) { c->c = NewLED(); c->type = 3; c->norm = 1; c->alpha = 1; - } else if (rnd < 0.8) { + } else if (rnd < 7) { c->c = NewFuse(); c->norm = 1; c->type = 7; c->alpha = 1; + } else if (rnd < 8) { + c->c = NewRCA(); + c->norm = 1; + c->type = 8; + } else if (rnd < 9) { + c->c = NewThreeFive(); + c->norm = 1; + c->type = 9; + } else if (rnd < 10) { + c->c = NewSwitch(); + c->norm = 1; + c->type = 10; } else { c->c = NewDisp(); c->type = 6; @@ -1149,16 +1555,57 @@ float rnd; return c; } -Transistor *NewTransistor(void) { -Transistor *t; +Transistor *NewTransistor(void) +{ + Transistor *t; + float texfg[] = {0.7, 0.7, 0.7, 1.0}; + float texbg[] = {0.3, 0.3, 0.3, 0.1}; + TexNum *tn; + const char *val; t = malloc(sizeof(Transistor)); - t->type = (f_rand() < 0.5); + t->type = (random() % 3); + if (t->type == 0) { + val = transistortypes[random() % countof(transistortypes)]; + tn = fonttexturealloc(val, texfg, texbg); + if (tn == NULL) { + fprintf(stderr, "Error getting a texture for a string!\n"); + t->tnum = 0; + } else { + t->tnum = tn->num; + t->tw = tn->w; t->th = tn->h; + free(tn); + } + } else if (t->type == 2) { + val = smctypes[random() % countof(smctypes)]; + tn = fonttexturealloc(val, texfg, texbg); + if (tn == NULL) { + fprintf(stderr, "Error getting a texture for a string!\n"); + t->tnum = 0; + } else { + t->tnum = tn->num; + t->tw = tn->w; t->th = tn->h; + free(tn); + } + } else if (t->type == 1) { + val = to92types[random() % countof(to92types)]; + tn = fonttexturealloc(val, texfg, texbg); + if (tn == NULL) { + fprintf(stderr, "Error getting a texture for a string!\n"); + t->tnum = 0; + } else { + t->tnum = tn->num; + t->tw = tn->w; t->th = tn->h; + free(tn); + } + } + return t; } -Capacitor *NewCapacitor(void) { -Capacitor *c; +Capacitor *NewCapacitor(void) +{ + Capacitor *c; c = malloc(sizeof(Capacitor)); c->type = (f_rand() < 0.5); @@ -1166,15 +1613,16 @@ Capacitor *c; c->length = RAND_RANGE(0.5, 1); c->width = RAND_RANGE(0.5, 1); } else { - c->width = RAND_RANGE(1, 2); + c->width = RAND_RANGE(0.3, 1); } return c; } /* 7 segment display */ -Disp *NewDisp(void) { -Disp *d; +Disp *NewDisp(void) +{ + Disp *d; d = malloc(sizeof(Disp)); if (seven) @@ -1185,9 +1633,16 @@ Disp *d; } -IC *NewIC(void) { -IC *c; -int pins; +IC *NewIC(void) +{ + IC *c; + int pins; + TexNum *tn; + float texfg[] = {0.7, 0.7, 0.7, 1.0}; + float texbg[] = {0.1, 0.1, 0.1, 0}; + const char *val; + char *str; + int types[countof(ictypes)], i, n = 0; c = malloc(sizeof(IC)); c->type = 0; @@ -1206,13 +1661,35 @@ int pins; 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; + str = malloc(strlen(val) + 1 + 4 + 1); /* add space for production date */ + sprintf(str, "%s\n%02d%02d", val, (int)RAND_RANGE(80, 100), (int)RAND_RANGE(1,53)); + tn = fonttexturealloc(str, texfg, texbg); + free(str); + if (tn == NULL) { + fprintf(stderr, "Error allocating font texture for '%s'\n", val); + c->tnum = 0; + } else { + c->tw = tn->w; c->th = tn->h; + c->tnum = tn->num; + free(tn); + } c->pins = pins; return c; } -LED *NewLED(void) { -LED *l; -float r; +LED *NewLED(void) +{ + LED *l; + float r; l = malloc(sizeof(LED)); r = f_rand(); @@ -1235,16 +1712,44 @@ float r; return l; } -Fuse *NewFuse(void) { -Fuse *f; +Fuse *NewFuse(void) +{ + Fuse *f; f = malloc(sizeof(Fuse)); return f; } -Diode *NewDiode(void) { -Band *b; -Diode *ret; +RCA *NewRCA(void) +{ + RCA *r; + + r = malloc(sizeof(RCA)); + r->col = (random() % 10 < 5); + return r; +} + +ThreeFive *NewThreeFive(void) +{ + ThreeFive *r; + + r = malloc(sizeof(ThreeFive)); + return r; +} + +Switch *NewSwitch(void) +{ + Switch *s; + + s = malloc(sizeof(Switch)); + s->position = 0; + return s; +} + +Diode *NewDiode(void) +{ + Band *b; + Diode *ret; ret = malloc(sizeof(Diode)); b = malloc(sizeof(Band)); @@ -1266,9 +1771,10 @@ Diode *ret; } -Resistor * NewResistor(void) { -int v, m, t; /* value, multiplier, tolerance */ -Resistor *ret; +Resistor * NewResistor(void) +{ + int v, m, t; /* value, multiplier, tolerance */ + Resistor *ret; v = RAND(9); m = RAND(5); @@ -1287,11 +1793,12 @@ Resistor *ret; return ret; } -void makebandlist(void) { -int i; -GLfloat col[] = {0,0,0,0}; -GLfloat spec[] = {0.8,0.8,0.8,0}; -GLfloat shine = 40; +void makebandlist(void) +{ + 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++) { band_list[i] = glGenLists(i); @@ -1309,10 +1816,11 @@ GLfloat shine = 40; void bandedCylinder(float radius, float l, GLfloat r, GLfloat g, GLfloat bl, - Band **b, int nbands) { -int n; /* band number */ -int p = 0; /* prev number + 1; */ -GLfloat col[] = {0,0,0,0}; + Band **b, int nbands) +{ + int n; /* band number */ + int p = 0; /* prev number + 1; */ + GLfloat col[] = {0,0,0,0}; col[0] = r; col[1] = g; col[2] = bl; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col); @@ -1328,15 +1836,16 @@ GLfloat col[] = {0,0,0,0}; } } -void drawgrid(void) { -GLfloat x, y; -static GLfloat col[] = {0, 0.25, 0.05}; -static GLfloat col2[] = {0, 0.125, 0.05}; -GLfloat col3[] = {0, 0.8, 0}; -static GLfloat sx, sy; /* bright spot co-ords */ -static int sdir; /* 0 = left-right, 1 = right-left, 2 = up->dn, 3 = dn->up */ -static int s = 0; /* if spot is enabled */ -static float ds; /* speed of spot */ +void drawgrid(void) +{ + GLfloat x, y; + static GLfloat col[] = {0, 0.25, 0.05}; + static GLfloat col2[] = {0, 0.125, 0.05}; + GLfloat col3[] = {0, 0.8, 0}; + static GLfloat sx, sy; /* bright spot co-ords */ + static int sdir; /* 0 = left-right, 1 = right-left, 2 = up->dn, 3 = dn->up */ + static int s = 0; /* if spot is enabled */ + static float ds; /* speed of spot */ if (!s) { if (f_rand() < ((rotate) ? 0.05 : 0.01)) { @@ -1438,13 +1947,14 @@ static float ds; /* speed of spot */ glEnable(GL_LIGHTING); } -void display(void) { -static Component *c[MAX_COMPONENTS]; -static int i = 0; -GLfloat light_sp[] = {0.8, 0.8, 0.8, 1.0}; -GLfloat black[] = {0, 0, 0, 1.0}; -static GLfloat rotate_angle = 0; /* when 'rotate' is enabled */ -int j; +void display(void) +{ + static Component *c[MAX_COMPONENTS]; + static int i = 0; + GLfloat light_sp[] = {0.8, 0.8, 0.8, 1.0}; + GLfloat black[] = {0, 0, 0, 1.0}; + static GLfloat rotate_angle = 0; /* when 'rotate' is enabled */ + int j; if (i == 0) { for (i = 0 ; i < maxparts ; i++) { @@ -1492,11 +2002,97 @@ int j; glFlush(); } +void freetexture (GLuint texture) { + s_refs[texture]--; + if (s_refs[texture] < 1) { + glDeleteTextures(1, &texture); + } +} + +TexNum * fonttexturealloc (const char *str, float *fg, float *bg) +{ + static char *strings[50]; /* max of 40 textures */ + static int w[50], h[50]; + int i, status; + static int init; + XImage *ximage; + char *c; + TexNum *t; + + if (init == 0) { + for (i = 0 ; i < 50 ; i++) { + strings[i] = NULL; + s_refs[i] = 0; + w[i] = 0; h[i] = 0; + } + init++; + } + for (i = 0 ; i < 50 ; i++) { + if (!s_refs[i] && strings[i]) { + free (strings[i]); + strings[i] = NULL; + } + if (strings[i] && !strcmp(str, strings[i])) { /* if one matches */ + t = malloc(sizeof(TexNum)); + t->w = w[i]; t->h = h[i]; + t->num = i; + s_refs[i]++; + return t; + } + } + /* at this point we need to make the new texture */ + ximage = text_to_ximage (modeinfo->xgwa.screen, + modeinfo->xgwa.visual, + font, str, + fg, bg); + for (i = 0 ; strings[i] != NULL ; i++) { /* set i to the next unused value */ + if (i > 49) { + fprintf(stderr, "Texture cache full!\n"); + free(ximage->data); + ximage->data = 0; + XFree (ximage); + return NULL; + } + } + glBindTexture(GL_TEXTURE_2D, i); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + clear_gl_error(); + status = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, ximage->width, ximage->height, + GL_RGBA, GL_UNSIGNED_BYTE, ximage->data); + if (status) + { + const char *s = (char *) gluErrorString (status); + fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n", + progname, ximage->width, ximage->height, + (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); + + t = malloc(sizeof(TexNum)); + t->w = ximage->width; + t->h = ximage->height; + w[i] = t->w; h[i] = t->h; + free(ximage->data); + ximage->data = 0; + XFree (ximage); + c = malloc(strlen(str)+1); + strncpy(c, str, strlen(str)+1); + strings[i] = c; + s_refs[i]++; + t->num = i; + return t; +} + /* ensure transparent components are at the end */ -void reorder(Component *c[]) { -int i, j, k; -Component *c1[MAX_COMPONENTS]; -Component *c2[MAX_COMPONENTS]; +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 */ @@ -1530,13 +2126,14 @@ Component *c2[MAX_COMPONENTS]; void reshape_circuit(ModeInfo *mi, int width, int height) { - + GLfloat h = (GLfloat) height / (GLfloat) width; glViewport(0,0,(GLint)width, (GLint) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glFrustum(-1.0,1.0,-1.0,1.0,1.5,35.0); + glFrustum(-1.0,1.0,-h,h,1.5,35.0); glMatrixMode(GL_MODELVIEW); win_h = height; win_w = width; + YMAX = XMAX * h; } @@ -1567,18 +2164,21 @@ Circuit *c; glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); make_tables(); makebandlist(); } -void draw_circuit(ModeInfo *mi) { -Circuit *c = &circuit[MI_SCREEN(mi)]; -Window w = MI_WINDOW(mi); -Display *disp = MI_DISPLAY(mi); +void draw_circuit(ModeInfo *mi) +{ + Circuit *c = &circuit[MI_SCREEN(mi)]; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); if (!c->glx_context) return; + modeinfo = mi; glXMakeCurrent(disp, w, *(c->glx_context)); @@ -1589,8 +2189,8 @@ Display *disp = MI_DISPLAY(mi); glXSwapBuffers(disp, w); } -void release_circuit(ModeInfo *mi) { - +void release_circuit(ModeInfo *mi) +{ if (circuit != NULL) { (void) free((void *) circuit); circuit = NULL;