X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fcircuit.c;h=e6636c29f2f0a1d6f842200e3360b436d84e73d8;hp=faa30df2c63099b24fa0754be0c39aa1ff7faf78;hb=ffd8c0873576a9e3065696a624dce6b766b77062;hpb=cccbddbc4140cf9a06d7d95cc5c0ca36eb5d6e28 diff --git a/hacks/glx/circuit.c b/hacks/glx/circuit.c index faa30df2..e6636c29 100644 --- a/hacks/glx/circuit.c +++ b/hacks/glx/circuit.c @@ -7,8 +7,11 @@ * 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 @@ -88,24 +91,24 @@ 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 *) &font, "font", "Font", "fixed", t_String}, - {(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}; @@ -142,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); @@ -158,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}; @@ -207,10 +213,35 @@ static const char * transistortypes[] = { "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 */ - int tnum; /* texture binding */ + GLuint tnum; /* texture binding */ } Transistor; typedef struct { @@ -224,6 +255,16 @@ 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; @@ -288,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 */ @@ -342,11 +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); @@ -355,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.. @@ -601,6 +657,12 @@ int DrawComponent(Component *c) 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; @@ -610,6 +672,14 @@ int DrawComponent(Component *c) 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); @@ -647,6 +717,73 @@ void DrawResistor(Resistor *r) wire(3); } +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 */ @@ -699,6 +836,7 @@ void DrawCapacitor(Capacitor *c) 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); @@ -708,23 +846,24 @@ void DrawCapacitor(Capacitor *c) 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); @@ -737,6 +876,7 @@ void DrawCapacitor(Capacitor *c) 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) { @@ -744,7 +884,8 @@ void DrawLED(LED *l) 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); @@ -762,6 +903,7 @@ void DrawLED(LED *l) 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); @@ -792,6 +934,37 @@ void DrawLED(LED *l) } +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) { @@ -911,6 +1084,8 @@ void DrawIC(IC *c) 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); @@ -943,31 +1118,30 @@ void DrawIC(IC *c) glVertex3f(w, h, 0.1); glVertex3f(-w, h, 0.1); glEnd(); - glBindTexture(GL_TEXTURE_2D, c->tnum); + glDisable(GL_POLYGON_OFFSET_FILL); + if (c->tnum) glBindTexture(GL_TEXTURE_2D, c->tnum); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); - glDepthMask(GL_FALSE); if (c->pins == 8) size = 0.4; else size = 0.6; - th = size/2; + 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.11); + glVertex3f(th, mult, 0.1); glTexCoord2f(1, 1); - glVertex3f(th, -mult, 0.11); + glVertex3f(th, -mult, 0.1); glTexCoord2f(1, 0); - glVertex3f(-th, -mult, 0.11); + glVertex3f(-th, -mult, 0.1); glTexCoord2f(0, 0); - glVertex3f(-th, mult, 0.11); + glVertex3f(-th, mult, 0.1); glEnd(); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); - glDepthMask(GL_TRUE); d = (h*2-0.1) / c->pins; d*=2; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol); @@ -980,7 +1154,7 @@ void DrawIC(IC *c) 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.11); + glTranslatef(-w+0.3, h-0.3, 0.1); glRotatef(90, 0, 1, 0); circle(0.1, 7, 0); glPopMatrix(); @@ -1167,26 +1341,49 @@ void DrawTransistor(Transistor *t) 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) { + 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 { + } 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); - glBindTexture(GL_TEXTURE_2D, t->tnum); + if (t->tnum) glBindTexture(GL_TEXTURE_2D, t->tnum); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBegin (GL_QUADS); @@ -1218,6 +1415,40 @@ void DrawTransistor(Transistor *t) 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(); } @@ -1267,44 +1498,56 @@ Component * NewComponent(void) 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(); c->norm = 1; c->type = 4; - } else if (rnd < 0.6) { + } else if (rnd < 5) { c->c = NewIC(); c->type = 5; c->norm = 1; - } else if (rnd < 0.7) { + } 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; @@ -1321,18 +1564,42 @@ Transistor *NewTransistor(void) 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; } @@ -1374,6 +1641,7 @@ IC *NewIC(void) 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)); @@ -1402,9 +1670,13 @@ IC *NewIC(void) if (n > countof(types)) abort(); val = ictypes[types[random() % n]].val; - tn = fonttexturealloc(val, texfg, texbg); + 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; @@ -1448,6 +1720,32 @@ Fuse *NewFuse(void) return f; } +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; @@ -1704,6 +2002,13 @@ void display(void) 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 */ @@ -1715,17 +2020,23 @@ TexNum * fonttexturealloc (const char *str, float *fg, float *bg) TexNum *t; if (init == 0) { - for (i = 1 ; i < 50 ; i++) { + for (i = 0 ; i < 50 ; i++) { strings[i] = NULL; + s_refs[i] = 0; w[i] = 0; h[i] = 0; } init++; } - for (i = 1 ; i < 50 ; i++) { + 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; } } @@ -1734,16 +2045,26 @@ TexNum * fonttexturealloc (const char *str, float *fg, float *bg) modeinfo->xgwa.visual, font, str, fg, bg); - for (i = 1 ; strings[i] != NULL ; i++); /* set i to the next unused value */ + 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 = gluErrorString (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)")); @@ -1761,6 +2082,7 @@ TexNum * fonttexturealloc (const char *str, float *fg, float *bg) c = malloc(strlen(str)+1); strncpy(c, str, strlen(str)+1); strings[i] = c; + s_refs[i]++; t->num = i; return t; } @@ -1804,12 +2126,14 @@ void reorder(Component *c[]) 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; }