2 * circuit - Random electronic components floating around
6 * Since version 1.1: added to-220 transistor, added fuse
7 * Since version 1.2: random display digits, LED improvements (flickering)
8 * Since version 1.3: ICs look better, font textures, improved normals to
9 * eliminate segmenting on curved surfaces, speedups
10 * Since version 1.4: Added RCA connector, 3.5mm connector, slide switch,
11 * surface mount, to-92 markings. Fixed ~5min crash.
12 * Better LED illumination. Other minor changes.
14 * Copyright (C) 2001-2015 Ben Buxton (bb@cactii.net)
16 * Permission to use, copy, modify, distribute, and sell this software and its
17 * documentation for any purpose is hereby granted without fee, provided that
18 * the above copyright notice appear in all copies and that both that
19 * copyright notice and this permission notice appear in supporting
20 * documentation. No representations are made about the suitability of this
21 * software for any purpose. It is provided "as is" without express or
25 /* Written over a few days in a (successful) bid to learn GL coding
27 * -seven option is dedicated to all the Slarkeners
29 * This hack uses lookup tables for sin, cos and tan - it can do a lot
33 #define DEFAULTS "*delay: 20000 \n" \
34 "*showFPS: False \n" \
35 "*suppressRotationAnimation: True\n" \
36 "*componentFont: -*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*"
38 # define refresh_circuit 0
39 # define release_circuit 0
40 # define circuit_handle_event 0
41 # include "xlockmore.h" /* from the xscreensaver distribution */
42 #else /* !STANDALONE */
43 # include "xlock.h" /* from the xlockmore distribution */
44 #endif /* !STANDALONE */
46 #define DEF_SPIN "True"
47 #define DEF_SEVEN "False"
48 #define DEF_PARTS "10"
49 #define DEF_ROTATESPEED "1"
50 #define DEF_LIGHT "True"
52 /* lifted from lament.c */
53 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
54 #define RANDSIGN() ((random() & 1) ? 1 : -1)
62 #define countof(x) (sizeof((x))/sizeof((*x)))
65 static int rotatespeed;
71 #define countof(x) (sizeof((x))/sizeof((*x)))
73 static XrmOptionDescRec opts[] = {
74 {"-parts", ".circuit.parts", XrmoptionSepArg, 0 },
75 {"-rotate-speed", ".circuit.rotatespeed", XrmoptionSepArg, 0 },
76 {"+spin", ".circuit.spin", XrmoptionNoArg, "false" },
77 {"-spin", ".circuit.spin", XrmoptionNoArg, "true" },
78 {"+light", ".circuit.light", XrmoptionNoArg, "false" },
79 {"-light", ".circuit.light", XrmoptionNoArg, "true" },
80 {"+seven", ".circuit.seven", XrmoptionNoArg, "false" },
81 {"-seven", ".circuit.seven", XrmoptionNoArg, "true" },
84 static argtype vars[] = {
85 {&maxparts, "parts", "Parts", DEF_PARTS, t_Int},
86 {&rotatespeed, "rotatespeed", "Rotatespeed", DEF_ROTATESPEED, t_Int},
87 {&spin, "spin", "Spin", DEF_SPIN, t_Bool},
88 {&uselight, "light", "Light", DEF_LIGHT, t_Bool},
89 {&seven, "seven", "Seven", DEF_SEVEN, t_Bool},
92 ENTRYPOINT ModeSpecOpt circuit_opts = {countof(opts), opts, countof(vars), vars, NULL};
95 ModStruct circuit_description =
96 {"circuit", "init_circuit", "draw_circuit", NULL,
97 "draw_circuit", "init_circuit", NULL, &circuit_opts,
98 1000, 1, 2, 1, 4, 1.0, "",
99 "Flying electronic components", 0, NULL};
103 #define MAX_COMPONENTS 400
104 #define MOVE_MULT 0.02
106 static float f_rand(void)
108 return ((float)RAND(10000)/(float)10000);
111 #define RAND_RANGE(min, max) ((min) + (max - min) * f_rand())
113 /* Represents a band on a resistor/diode/etc */
115 float pos; /* relative position from start/previous band */
116 GLfloat r, g, b; /* colour of the band */
117 float len; /* length as a fraction of total length */
121 Band *b1, *b2, *b3, *b4; /* bands */
127 GLfloat r, g, b; /* body colour */
130 static const char * const transistortypes[] = {
146 static const char * const to92types[] = {
161 static const char * const smctypes[] = {
172 int type; /* package type. 0 = to-92, 1 = to-220 */
177 GLfloat r,g,b; /* LED colour */
178 int light; /* are we the light source? */
182 int type; /* 0 = electro, 1 = ceramic */
183 float width; /* width of an electro/ceramic */
184 float length; /* length of an electro */
202 static const ICTypes ictypes[] = {
245 int type; /* 0 = DIL, 1 = flat square */
250 /* 7 segment display */
253 int value; /* displayed number */
266 GLfloat x, y, z; /* current co-ordinates */
267 GLfloat dx, dy, dz; /* current direction */
268 GLfloat rotx, roty, rotz; /* rotation vector */
269 GLfloat drot; /* rotation velocity (degrees per frame) */
270 int norm; /* Normalize this component (for shine) */
271 int rdeg; /* current rotation degrees */
272 int angle; /* angle about the z axis */
273 int alpha; /* 0 if not a transparent component */
274 int type; /* 0 = resistor, 1 = diode, 2 = transistor, 3 = LED, 4 = cap, 5=IC,
276 void * c; /* pointer to the component */
279 /* standard colour codes */
281 static const GLfloat colorcodes [12][3] = {
282 {0.0,0.0,0.0}, /* black 0 */
283 {0.49,0.25,0.08}, /* brown 1 */
284 {1.0,0.0,0.0}, /* red 2 */
285 {1.0,0.5,0.0}, /* orange 3 */
286 {1.0,1.0,0.0}, /* yellow 4 */
287 {0.0,1.0,0.0}, /* green 5 */
288 {0.0,0.5,1.0}, /* blue 6 */
289 {0.7,0.2,1.0}, /* violet 7 */
290 {0.5,0.5,0.5}, /* grey 8 */
291 {1.0,1.0,1.0}, /* white 9 */
292 {0.66,0.56,0.2}, /* gold 10 */
293 {0.8,0.8,0.8}, /* silver 11 */
296 /* base values for components - we can multiply by 0 - 1M */
297 static const int values [9][2] = {
310 GLXContext *glx_context;
316 /* one lucky led gets to be a light source , unless -no-light*/
320 /* stores refs to textures */
326 float sin_table[720];
327 float cos_table[720];
328 float tan_table[720];
330 Component *components[MAX_COMPONENTS];
332 int band_list_polys[12];
334 GLfloat grid_col[3], grid_col2[3];
337 GLfloat rotate_angle;
339 texture_font_data *font;
340 char *font_strings[50]; /* max of 40 textures */
341 int font_w[50], font_h[50];
344 GLfloat draw_sx, draw_sy; /* bright spot co-ords */
345 int draw_sdir; /* 0 = left-right, 1 = right-left, 2 = up->dn, 3 = dn->up */
346 int draw_s; /* if spot is enabled */
347 float draw_ds; /* speed of spot */
351 static Circuit *circuit = NULL;
354 static int DrawResistor(Circuit *, Resistor *);
355 static int DrawDiode(Circuit *, Diode *);
356 static int DrawTransistor(Circuit *, Transistor *);
357 static int DrawLED(Circuit *, LED *);
358 static int DrawIC(Circuit *, IC *);
359 static int DrawCapacitor(Circuit *, Capacitor *);
360 static int DrawDisp(Circuit *, Disp *);
361 static int DrawFuse(Circuit *, Fuse *);
362 static int DrawRCA(Circuit *, RCA *);
363 static int DrawThreeFive(Circuit *, ThreeFive *);
364 static int DrawSwitch(Circuit *, Switch *);
366 static void reorder(Component *[]);
367 static int circle(Circuit *, float, int,int);
368 static int bandedCylinder(Circuit *,
369 float, float , GLfloat, GLfloat , GLfloat,
371 static int Rect(GLfloat , GLfloat , GLfloat, GLfloat , GLfloat ,GLfloat);
372 static int ICLeg(GLfloat, GLfloat, GLfloat, int);
373 static int HoledRectangle(Circuit *ci,
374 GLfloat, GLfloat, GLfloat, GLfloat, int);
375 static Resistor *NewResistor(void);
376 static Diode *NewDiode(void);
377 static Transistor *NewTransistor(ModeInfo *);
378 static LED * NewLED(Circuit *);
379 static Capacitor *NewCapacitor(Circuit *);
380 static IC* NewIC(ModeInfo *);
381 static Disp* NewDisp(Circuit *);
382 static Fuse *NewFuse(Circuit *);
383 static RCA *NewRCA(Circuit *);
384 static ThreeFive *NewThreeFive(Circuit *);
385 static Switch *NewSwitch(Circuit *);
387 /* we use trig tables to speed things up - 200 calls to sin()
388 in one frame can be a bit harsh..
391 static void make_tables(Circuit *ci)
396 f = 360 / (M_PI * 2);
397 for (i = 0 ; i < 720 ; i++) {
398 ci->sin_table[i] = sin(i/f);
400 for (i = 0 ; i < 720 ; i++) {
401 ci->cos_table[i] = cos(i/f);
403 for (i = 0 ; i < 720 ; i++) {
404 ci->tan_table[i] = tan(i/f);
409 static int createCylinder (Circuit *ci,
410 float length, float radius, int endcaps, int half)
413 int a; /* current angle around cylinder */
415 float z1, y1, z2, y2,ex;
419 nsegs = radius*MAX(ci->win_w, ci->win_h)/20;
420 nsegs = MAX(nsegs, 4);
423 angle = (half) ? (180 - 90/nsegs) : 374;
426 for (a = 0 ; a <= angle ; a+= angle/nsegs) {
427 y2=radius*(float)ci->sin_table[(int)a];
428 z2=radius*(float)ci->cos_table[(int)a];
429 glNormal3f(0, y1, z1);
431 glVertex3f(length,y1,z1);
432 glNormal3f(0, y2, z2);
433 glVertex3f(length,y2,z2);
443 glVertex3f(0, 0, radius);
444 glVertex3f(length, 0, radius);
445 glVertex3f(length, 0, 0 - radius);
446 glVertex3f(0, 0, 0 - radius);
451 for(ex = 0 ; ex <= length ; ex += length) {
453 norm = (ex == length) ? 1 : -1;
454 glBegin(GL_TRIANGLES);
455 glNormal3f(norm, 0, 0);
456 for (a = 0 ; a <= angle ; a+= angle/nsegs) {
457 y2=radius*(float)ci->sin_table[(int)a];
458 z2=radius*(float)ci->cos_table[(int)a];
460 glVertex3f(ex,y1,z1);
461 glVertex3f(ex,y2,z2);
473 static int circle(Circuit *ci, float radius, int segments, int half)
476 float x1 = 0, x2 = 0;
477 float y1 = 0, y2 = 0;
486 glBegin(GL_TRIANGLES);
491 x2=radius*(float)ci->cos_table[(int)angle];
492 y2=radius*(float)ci->sin_table[(int)angle];
504 static int wire(Circuit *ci, float len)
507 GLfloat col[] = {0.3, 0.3, 0.3, 1.0};
508 GLfloat spec[] = {0.9, 0.9, 0.9, 1.0};
509 GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0};
513 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
514 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
515 glMaterialfv(GL_FRONT, GL_SHININESS, &shin);
516 n = glIsEnabled(GL_NORMALIZE);
517 if (!n) glEnable(GL_NORMALIZE);
518 polys += createCylinder(ci, len, 0.05, 1, 0);
519 if (!n) glDisable(GL_NORMALIZE);
520 glMaterialfv(GL_FRONT, GL_SPECULAR, nospec);
524 static int sphere(Circuit *ci, GLfloat r, float stacks, float slices,
525 int startstack, int endstack, int startslice,
529 GLfloat d, d1, dr, dr1, Dr, Dr1, D, D1, z1, z2, y1, y2, Y1, Z1, Y2, Z2;
530 int a, a1, b, b1, c0, c1;
535 a1 = startstack * step;
536 b1 = startslice * sstep;
537 y1 = z1 = Y1 = Z1 = 0;
538 c0 = (endslice / slices) * 360;
539 c1 = (endstack/stacks)*180;
541 for (a = startstack * step ; a <= c1 ; a+= step) {
543 d1=ci->sin_table[a1];
545 D1=ci->cos_table[a1];
550 for (b = b1 ; b <= c0 ; b+= sstep) {
551 y2=dr*ci->sin_table[b];
552 z2=dr*ci->cos_table[b];
553 Y2=dr1*ci->sin_table[b];
554 Z2=dr1*ci->cos_table[b];
555 glNormal3f(Dr, y1, z1);
556 glVertex3f(Dr,y1,z1);
557 glNormal3f(Dr, y2, z2);
558 glVertex3f(Dr,y2,z2);
559 glNormal3f(Dr1, Y2, Z2);
560 glVertex3f(Dr1,Y2,Z2);
561 glNormal3f(Dr1, Y1, Z1);
562 glVertex3f(Dr1,Y1,Z1);
575 static int DrawComponent(Circuit *ci, Component *c, unsigned long *polysP)
578 int ret = 0; /* return 1 if component is freed */
581 glTranslatef(c->x, c->y, c->z);
583 glRotatef(c->angle, c->rotx, c->roty, c->rotz);
586 glRotatef(c->rdeg, c->rotx, c->roty, c->rotz);
591 glEnable(GL_NORMALIZE);
593 glDisable(GL_NORMALIZE);
595 /* call object draw routine here */
597 polys += DrawResistor(ci, c->c);
598 } else if (c->type == 1) {
599 polys += DrawDiode(ci, c->c);
600 } else if (c->type == 2) {
601 polys += DrawTransistor(ci, c->c);
602 } else if (c->type == 3) {
603 if (((LED *)c->c)->light && ci->light) {
604 GLfloat lp[] = {0.1, 0, 0, 1};
606 glLightfv(GL_LIGHT1, GL_POSITION, lp);
608 polys += DrawLED(ci, c->c);
609 } else if (c->type == 4) {
610 polys += DrawCapacitor(ci, c->c);
611 } else if (c->type == 5) {
612 polys += DrawIC(ci, c->c);
613 } else if (c->type == 6) {
614 polys += DrawDisp(ci, c->c);
615 } else if (c->type == 7) {
616 polys += DrawFuse(ci, c->c);
617 } else if (c->type == 8) {
618 polys += DrawRCA(ci, c->c);
619 } else if (c->type == 9) {
620 polys += DrawThreeFive(ci, c->c);
621 } else if (c->type == 10) {
622 polys += DrawSwitch(ci, c->c);
624 c->x += c->dx * MOVE_MULT;
625 c->y += c->dy * MOVE_MULT;
626 if (c->x > ci->XMAX/2 || c->x < 0 - ci->XMAX/2 ||
627 c->y > ci->YMAX/2 || c->y < 0 - ci->YMAX/2) {
628 if (c->type == 3 && ((LED *)c->c)->light && ci->light) {
629 glDisable(GL_LIGHT1);
630 ci->light = 0; ci->lighton = 0;
633 free(((Diode *)c->c)->band); /* remember to free diode band */
639 glDisable(GL_NORMALIZE);
644 /* draw a resistor */
646 static int DrawResistor(Circuit *ci, Resistor *r)
650 GLfloat col[] = {0.74, 0.62, 0.46, 1.0};
651 GLfloat spec[] = {0.8, 0.8, 0.8, 1.0};
654 glTranslatef(-4, 0, 0);
655 polys += wire(ci, 3);
656 glTranslatef(3, 0, 0);
657 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
658 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
659 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
660 polys += createCylinder(ci, 1.8, 0.4, 1, 0);
662 for (i = 0 ; i < 4 ; i++) {
663 glTranslatef(0.35, 0, 0);
664 glCallList(ci->band_list[r->b[i]]);
665 polys += ci->band_list_polys[r->b[i]];
668 glTranslatef(1.8, 0, 0);
669 polys += wire(ci, 3);
673 static int DrawRCA(Circuit *ci, RCA *rca)
676 GLfloat col[] = {0.6, 0.6, 0.6, 1.0}; /* metal */
677 GLfloat red[] = {1.0, 0.0, 0.0, 1.0}; /* red */
678 GLfloat white[] = {1.0, 1.0, 1.0, 1.0}; /* white */
679 GLfloat spec[] = {1, 1, 1, 1}; /* glass */
682 glTranslatef(0.3, 0, 0);
683 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
684 glMateriali(GL_FRONT, GL_SHININESS, 40);
685 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
686 polys += createCylinder(ci, 0.7, 0.45, 0, 0);
687 glTranslatef(0.4, 0, 0);
688 polys += createCylinder(ci, 0.9, 0.15, 1, 0);
689 glTranslatef(-1.9, 0, 0);
690 glMateriali(GL_FRONT, GL_SHININESS, 20);
691 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, rca->col ? white : red);
692 polys += createCylinder(ci, 1.5, 0.6, 1, 0);
693 glTranslatef(-0.9, 0, 0);
694 polys += createCylinder(ci, 0.9, 0.25, 0, 0);
695 glTranslatef(0.1, 0, 0);
696 polys += createCylinder(ci, 0.2, 0.3, 0, 0);
697 glTranslatef(0.3, 0, 0);
698 polys += createCylinder(ci, 0.2, 0.3, 1, 0);
699 glTranslatef(0.3, 0, 0);
700 polys += createCylinder(ci, 0.2, 0.3, 1, 0);
705 static int DrawSwitch(Circuit *ci, Switch *f)
708 GLfloat col[] = {0.6, 0.6, 0.6, 0}; /* metal */
709 GLfloat dark[] = {0.1, 0.1, 0.1, 1.0}; /* dark */
710 GLfloat brown[] = {0.69, 0.32, 0, 1.0}; /* brown */
711 GLfloat spec[] = {0.9, 0.9, 0.9, 1}; /* shiny */
714 glMaterialfv(GL_FRONT, GL_DIFFUSE, col);
715 glMaterialfv(GL_FRONT, GL_AMBIENT, dark);
716 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
717 glMateriali(GL_FRONT, GL_SHININESS, 90);
718 polys += Rect(-0.25, 0, 0, 1.5, 0.5, 0.75);
719 /* polys += Rect(-0.5, 0.5, 0, 2, 0.1, 0.75); */
721 glRotatef(90, 1, 0, 0);
722 glTranslatef(-0.5, -0.4, -0.4);
723 polys += HoledRectangle(ci, 0.5, 0.75, 0.1, 0.15, 8);
724 glTranslatef(2, 0, 0);
725 polys += HoledRectangle(ci, 0.5, 0.75, 0.1, 0.15, 8);
727 polys += Rect(0.1, -0.4, -0.25, 0.1, 0.4, 0.05);
728 polys += Rect(0.5, -0.4, -0.25, 0.1, 0.4, 0.05);
729 polys += Rect(0.9, -0.4, -0.25, 0.1, 0.4, 0.05);
730 polys += Rect(0.1, -0.4, -0.5, 0.1, 0.4, 0.05);
731 polys += Rect(0.5, -0.4, -0.5, 0.1, 0.4, 0.05);
732 polys += Rect(0.9, -0.4, -0.5, 0.1, 0.4, 0.05);
733 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, dark);
734 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
735 polys += Rect(0, 0.5, -0.1, 1, 0.05, 0.5);
736 polys += Rect(0, 0.6, -0.1, 0.5, 0.6, 0.5);
737 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown);
738 polys += Rect(-0.2, -0.01, -0.1, 1.4, 0.1, 0.55);
744 static int DrawFuse(Circuit *ci, Fuse *f)
747 GLfloat col[] = {0.5, 0.5, 0.5, 1.0}; /* endcaps */
748 GLfloat glass[] = {0.4, 0.4, 0.4, 0.3}; /* glass */
749 GLfloat spec[] = {1, 1, 1, 1}; /* glass */
752 glTranslatef(-1.8, 0, 0);
753 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
754 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
755 glMateriali(GL_FRONT, GL_SHININESS, 40);
756 polys += createCylinder(ci, 0.8, 0.45, 1, 0);
757 glTranslatef(0.8, 0, 0);
759 glDepthMask(GL_FALSE);
760 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, glass);
761 glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 40);
762 polys += createCylinder(ci, 2, 0.4, 0, 0);
763 polys += createCylinder(ci, 2, 0.3, 0, 0);
765 glDepthMask(GL_TRUE);
766 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
767 glMateriali(GL_FRONT, GL_SHININESS, 40);
770 glVertex3f(2, 0. ,0);
772 glTranslatef(2, 0, 0);
773 polys += createCylinder(ci, 0.8, 0.45, 1, 0);
779 static int DrawCapacitor(Circuit *ci, Capacitor *c)
782 GLfloat col[] = {0, 0, 0, 0};
783 GLfloat spec[] = {0.8, 0.8, 0.8, 0};
784 GLfloat brown[] = {0.84, 0.5, 0};
789 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown);
790 polys += sphere(ci, c->width, 15, 15, 0, 4 ,0, 15);
791 glTranslatef(1.35*c->width, 0, 0);
792 polys += sphere(ci, c->width, 15, 15, 11, 15, 0, 15);
793 glRotatef(90, 0, 0, 1);
794 glTranslatef(0, 0.7*c->width, 0.3*c->width);
795 polys += wire(ci, 3*c->width);
796 glTranslatef(0, 0, -0.6*c->width);
797 polys += wire(ci, 3*c->width);
799 glTranslatef(0-c->length*2, 0, 0);
800 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
801 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
802 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shine);
804 glVertex3f(0, 0.82*c->width, -0.1);
805 glVertex3f(3*c->length, 0.82*c->width, -0.1);
806 glVertex3f(3*c->length, 0.82*c->width, 0.1);
807 glVertex3f(0, 0.82*c->width, 0.1);
812 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
813 glEnable(GL_POLYGON_OFFSET_FILL);
814 glPolygonOffset(1.0, 1.0);
815 polys += createCylinder(ci, 3.0*c->length, 0.8*c->width, 1, 0);
816 glDisable(GL_POLYGON_OFFSET_FILL);
820 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
821 polys += circle(ci, 0.6*c->width, 30, 0);
825 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
826 glTranslatef(3.0*c->length, 0.0, 0);
827 polys += circle(ci, 0.6*c->width, 30, 0);
828 glTranslatef(0, 0.4*c->width, 0);
829 polys += wire(ci, 3*c->length);
830 glTranslatef(0.0, -0.8*c->width, 0);
831 polys += wire(ci, 3.3*c->length);
837 static int DrawLED(Circuit *ci, LED *l)
840 GLfloat col[] = {0, 0, 0, 0.6};
841 GLfloat black[] = {0, 0, 0, 0.6};
843 col[0] = l->r; col[1] = l->g; col[2] = l->b;
844 if (l->light && ci->light) {
845 GLfloat dir[] = {-1, 0, 0};
846 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, dir);
848 glLightfv(GL_LIGHT1, GL_SPECULAR, col);
849 glLightfv(GL_LIGHT1, GL_AMBIENT, black);
850 col[0] /= 1.5; col[1] /= 1.5; col[2] /= 1.5;
851 glLightfv(GL_LIGHT1, GL_DIFFUSE, col);
852 glLighti(GL_LIGHT1, GL_SPOT_CUTOFF, (GLint) 90);
853 glLighti(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (GLfloat)1);
854 glLighti(GL_LIGHT1, GL_LINEAR_ATTENUATION, (GLfloat)0);
855 glLighti(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (GLfloat)0);
856 glLighti(GL_LIGHT1, GL_SPOT_EXPONENT, (GLint) 20);
860 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
861 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col);
862 /* no transparency when LED is lit */
865 glDepthMask(GL_FALSE);
866 glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
868 glTranslatef(-0.9, 0, 0);
869 polys += createCylinder(ci, 1.2, 0.3, 0, 0);
870 if (l->light && ci->light) {
871 glDisable(GL_LIGHTING);
874 polys += sphere(ci, 0.3, 7, 7, 3, 7, 0, 7);
875 if (l->light && ci->light) {
876 glEnable(GL_LIGHTING);
878 glDepthMask(GL_TRUE);
882 glTranslatef(1.2, 0, 0);
883 polys += createCylinder(ci, 0.1, 0.38, 1, 0);
884 glTranslatef(-0.3, 0.15, 0);
885 polys += wire(ci, 3);
886 glTranslatef(0, -0.3, 0);
887 polys += wire(ci, 3.3);
888 if (random() % 50 == 25) {
890 l->light = 0; ci->light = 0; ci->lighton = 0;
891 glDisable(GL_LIGHT1);
892 } else if (!ci->light) {
901 static int DrawThreeFive(Circuit *ci, ThreeFive *d)
905 GLfloat const dark[] = {0.3, 0.3, 0.3, 0};
906 GLfloat const light[] = {0.6, 0.6, 0.6, 0};
907 GLfloat const cream[] = {0.8, 0.8, 0.6, 0};
908 GLfloat const spec[] = {0.7, 0.7, 0.7, 0};
911 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
912 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cream);
913 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
915 glTranslatef(-2.0, 0, 0);
916 polys += createCylinder(ci, 0.7, 0.2, 0, 0);
917 glTranslatef(0.7, 0, 0);
918 polys += createCylinder(ci, 1.3, 0.4, 1, 0);
919 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light);
920 glTranslatef(1.3, 0, 0);
921 polys += createCylinder(ci, 1.3, 0.2, 0, 0);
922 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, dark);
923 glTranslatef(0.65, 0, 0);
924 polys += createCylinder(ci, 0.15, 0.21, 0, 0);
925 glTranslatef(0.3, 0, 0);
926 polys += createCylinder(ci, 0.15, 0.21, 0, 0);
927 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light);
928 glTranslatef(0.4, 0, 0);
929 polys += sphere(ci, 0.23, 7, 7, 0, 5, 0, 7);
935 static int DrawDiode(Circuit *ci, Diode *d)
939 GLfloat col[] = {0.3, 0.3, 0.3, 0};
940 GLfloat spec[] = {0.7, 0.7, 0.7, 0};
943 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
944 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
945 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
946 glTranslatef(-4, 0, 0);
947 polys += wire(ci, 3);
948 glTranslatef(3, 0, 0);
949 polys += bandedCylinder(ci, 0.3, 1.5, d->r, d->g, d->b, &(d->band), 1);
950 glTranslatef(1.5, 0, 0);
951 polys += wire(ci, 3);
956 static int Rect(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h,
964 yh = y+h; xw = x+w; zt = z - t;
966 glBegin(GL_QUADS); /* front */
969 glVertex3f(x, yh, z);
970 glVertex3f(xw, yh, z);
971 glVertex3f(xw, y, z);
974 glNormal3f(0, 0, -1);
975 glVertex3f(x, y, zt);
976 glVertex3f(x, yh, zt);
977 glVertex3f(xw, yh, zt);
978 glVertex3f(xw, y, zt);
982 glVertex3f(x, yh, z);
983 glVertex3f(x, yh, zt);
984 glVertex3f(xw, yh, zt);
985 glVertex3f(xw, yh, z);
988 glNormal3f(0, -1, 0);
990 glVertex3f(x, y, zt);
991 glVertex3f(xw, y, zt);
992 glVertex3f(xw, y, z);
995 glNormal3f(-1, 0, 0);
997 glVertex3f(x, y, zt);
998 glVertex3f(x, yh, zt);
999 glVertex3f(x, yh, z);
1002 glNormal3f(1, 0, 0);
1003 glVertex3f(xw, y, z);
1004 glVertex3f(xw, y, zt);
1005 glVertex3f(xw, yh, zt);
1006 glVertex3f(xw, yh, z);
1014 static int ICLeg(GLfloat x, GLfloat y, GLfloat z, int dir)
1018 polys += Rect(x-0.1, y, z, 0.1, 0.1, 0.02);
1019 polys += Rect(x-0.1, y, z, 0.02, 0.1, 0.1);
1020 polys += Rect(x-0.1, y+0.03, z-0.1, 0.02, 0.05, 0.3);
1022 polys += Rect(x, y, z, 0.1, 0.1, 0.02);
1023 polys += Rect(x+0.8*0.1, y, z, 0.02, 0.1, 0.1);
1024 polys += Rect(x+0.8*0.1, y+0.03, z-0.1, 0.02, 0.05, 0.3);
1030 static int DrawIC(Circuit *ci, IC *c)
1035 GLfloat col[] = {0.1, 0.1, 0.1, 0};
1036 GLfloat col2[] = {0.2, 0.2, 0.2, 0};
1037 GLfloat spec[] = {0.6, 0.6, 0.6, 0};
1039 GLfloat lspec[] = {0.6, 0.6, 0.6, 0};
1040 GLfloat lcol[] = {0.4, 0.4, 0.4, 0};
1041 GLfloat lshine = 40;
1044 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1045 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
1046 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1047 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
1064 glEnable(GL_POLYGON_OFFSET_FILL);
1065 glPolygonOffset(1.0, 1.0);
1067 glNormal3f(0, 0, 1);
1068 glVertex3f(w, h, 0.1);
1069 glVertex3f(w, -h, 0.1);
1070 glVertex3f(-w, -h, 0.1);
1071 glVertex3f(-w, h, 0.1);
1073 glNormal3f(0, 0, -1);
1074 glVertex3f(w, h, -0.1);
1075 glVertex3f(w, -h, -0.1);
1076 glVertex3f(-w, -h, -0.1);
1077 glVertex3f(-w, h, -0.1);
1079 glNormal3f(1, 0, 0);
1080 glVertex3f(w, h, -0.1);
1081 glVertex3f(w, -h, -0.1);
1082 glVertex3f(w, -h, 0.1);
1083 glVertex3f(w, h, 0.1);
1085 glNormal3f(0, -1, 0);
1086 glVertex3f(w, -h, -0.1);
1087 glVertex3f(w, -h, 0.1);
1088 glVertex3f(-w, -h, 0.1);
1089 glVertex3f(-w, -h, -0.1);
1091 glNormal3f(-1, 0, 0);
1092 glVertex3f(-w, h, -0.1);
1093 glVertex3f(-w, h, 0.1);
1094 glVertex3f(-w, -h, 0.1);
1095 glVertex3f(-w, -h, -0.1);
1097 glNormal3f(0, -1, 0);
1098 glVertex3f(-w, h, -0.1);
1099 glVertex3f(w, h, -0.1);
1100 glVertex3f(w, h, 0.1);
1101 glVertex3f(-w, h, 0.1);
1104 glDisable(GL_POLYGON_OFFSET_FILL);
1105 glEnable(GL_TEXTURE_2D);
1109 GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0};
1112 texture_string_metrics (ci->font, c->text, &e, 0, 0);
1115 glTranslatef (0, 0, 0.1);
1116 glRotatef (90, 0, 0, 1);
1118 glTranslatef (-w/2, 0, 0);
1120 print_texture_string (ci->font, c->text);
1124 glDisable(GL_TEXTURE_2D);
1125 glDisable(GL_BLEND);
1126 d = (h*2-0.1) / c->pins;
1128 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol);
1129 glMaterialfv(GL_FRONT, GL_SPECULAR, lspec);
1130 glMaterialfv(GL_FRONT, GL_SHININESS, &lshine);
1131 for (z = 0 ; z < c->pins/2 ; z++) {
1132 polys += ICLeg(w, -h + z*d + d/2, 0, 0);
1134 for (z = 0 ; z < c->pins/2 ; z++) {
1135 polys += ICLeg(-w, -h + z*d + d/2, 0, 1);
1137 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col2);
1138 glTranslatef(-w+0.3, h-0.3, 0.1);
1139 glRotatef(90, 0, 1, 0);
1140 polys += circle(ci, 0.1, 7, 0);
1145 static int DrawDisp(Circuit *ci, Disp *d)
1148 GLfloat col[] = {0.8, 0.8, 0.8, 1.0}; /* body colour */
1149 GLfloat front[] = {0.2, 0.2, 0.2, 1.0}; /* front colour */
1150 GLfloat on[] = {0.9, 0, 0, 1}; /* 'on' segment */
1151 GLfloat off[] = {0.3, 0, 0, 1}; /* 'off' segment */
1153 GLfloat x, y; /* for the pins */
1154 GLfloat spec[] = {0.6, 0.6, 0.6, 0};
1155 GLfloat lcol[] = {0.4, 0.4, 0.4, 0};
1157 static const GLfloat vdata_h[6][2] = {
1165 static const GLfloat vdata_v[6][2] = {
1174 static const GLfloat seg_start[7][2] = {
1184 static const int nums[10][7] = {
1185 {1, 1, 1, 1, 1, 1, 0}, /* 0 */
1186 {0, 1, 1, 0, 0, 0, 0}, /* 1 */
1187 {1, 1, 0, 1, 1, 0, 1}, /* 2 */
1188 {1, 1, 1, 1, 0, 0, 1}, /* 3 */
1189 {0, 1, 1, 0, 0, 1, 1}, /* 4 */
1190 {1, 0, 1, 1, 0, 1, 1}, /* 5 */
1191 {1, 0, 1, 1, 1, 1, 1}, /* 6 */
1192 {1, 1, 1, 0, 0, 0, 0}, /* 7 */
1193 {1, 1, 1, 1, 1, 1, 1}, /* 8 */
1194 {1, 1, 1, 0, 0, 1, 1} /* 9 */
1197 glTranslatef(-0.9, -1.8, 0);
1198 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1199 polys += Rect(0, 0, -0.01, 1.8, 2.6, 0.7);
1200 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, front);
1202 glVertex2f(-0.05, -0.05);
1203 glVertex2f(-0.05, 2.65);
1204 glVertex2f(1.85, 2.65);
1205 glVertex2f(1.85, -0.05);
1208 glDisable(GL_LIGHTING); /* lit segments dont need light */
1209 if (!seven && (random() % 30) == 19) { /* randomly change value */
1210 d->value = random() % 10;
1212 for (j = 0 ; j < 7 ; j++) { /* draw the segments */
1213 GLfloat xx[6], yy[6];
1214 if (nums[d->value][j])
1218 for (k = 0 ; k < 6 ; k++) {
1219 if (j == 0 || j == 3 || j == 6) {
1220 xx[k] = seg_start[j][0] + vdata_h[k][0];
1221 yy[k] = seg_start[j][1] + vdata_h[k][1];
1223 xx[k] = seg_start[j][0] + vdata_v[k][0];
1224 yy[k] = seg_start[j][1] + vdata_v[k][1];
1227 glBegin(GL_POLYGON);
1228 for(i = 0 ; i < 6 ; i++) {
1229 glVertex3f(xx[i], yy[i], 0.01);
1237 glVertex3f(1.5, 0.2, 0.01);
1240 glEnable(GL_LIGHTING);
1241 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol);
1242 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
1243 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
1244 for (x = 0.35 ; x <= 1.5 ; x+= 1.15) {
1245 for ( y = 0.2 ; y <= 2.4 ; y += 0.3) {
1246 polys += ICLeg(x, y, -0.7, 1);
1252 static int HoledRectangle(Circuit *ci,
1253 GLfloat w, GLfloat h, GLfloat d, GLfloat radius,
1258 GLfloat x1, y1, x2, y2;
1259 GLfloat yr, yr1, xr, xr1, side, side1;
1263 x1 = radius; y1 = 0;
1268 for (a = 0 ; a <= 360 ; a+= step) {
1269 y2=radius*(float)ci->sin_table[(int)a];
1270 x2=radius*(float)ci->cos_table[(int)a];
1272 if (a < 45 || a > 315) {
1274 yr = side1 * ci->tan_table[a];
1276 } else if (a <= 135 || a >= 225) {
1277 xr = side/ci->tan_table[a];
1288 yr = -side1 * ci->tan_table[a];
1292 glNormal3f(-x1, -y1, 0); /* cylinder */
1293 glVertex3f(x1,y1,0);
1294 glVertex3f(x1,y1,-d);
1295 glVertex3f(x2,y2,-d);
1296 glVertex3f(x2,y2,0);
1299 glNormal3f(0, 0, 1); /* front face */
1300 glVertex3f(x1,y1,0);
1301 glVertex3f(xr1, yr1, 0);
1302 glVertex3f(xr, yr, 0);
1303 glVertex3f(x2, y2, 0);
1306 glNormal3f(nx, ny, 0); /* side */
1307 glVertex3f(xr, yr, 0);
1308 glVertex3f(xr, yr, -d);
1309 glVertex3f(xr1, yr1, -d);
1310 glVertex3f(xr1, yr1, 0);
1313 glNormal3f(0, 0, -1); /* back */
1314 glVertex3f(xr, yr, -d);
1315 glVertex3f(x2, y2, -d);
1316 glVertex3f(x1, y1, -d);
1317 glVertex3f(xr1, yr1, -d);
1328 static int DrawTransistor(Circuit *ci, Transistor *t)
1331 GLfloat col[] = {0.3, 0.3, 0.3, 1.0};
1332 GLfloat spec[] = {0.9, 0.9, 0.9, 1.0};
1333 GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0};
1337 glMaterialfv(GL_FRONT, GL_SHININESS, &shin);
1338 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
1339 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1340 if (t->type == 1) { /* TO-92 style */
1341 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col);
1342 glRotatef(90, 0, 1, 0);
1343 glRotatef(90, 0, 0, 1);
1344 polys += createCylinder(ci, 1.0, 0.4, 1, 1);
1345 polys += Rect(0, -0.2, 0.4, 1, 0.2, 0.8);
1346 /* Draw the markings */
1349 GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0};
1353 texture_string_metrics (ci->font, t->text, &e, 0, 0);
1356 glRotatef (90, 1, 0, 0);
1357 glTranslatef (0.5, -0.05, 0.21);
1359 glTranslatef (-w/2, 0, 0);
1361 print_texture_string (ci->font, t->text);
1365 glDisable(GL_TEXTURE_2D);
1366 glDisable(GL_BLEND);
1367 glDepthMask(GL_TRUE);
1368 glTranslatef(-2, 0, -0.2);
1369 polys += wire(ci, 2);
1370 glTranslatef(0, 0, 0.2);
1371 polys += wire(ci, 2);
1372 glTranslatef(0, 0, 0.2);
1373 polys += wire(ci, 2);
1374 } else if (t->type == 0) { /* TO-220 Style */
1375 polys += Rect(0, 0, 0, 1.5, 1.5, 0.5);
1377 GLfloat texfg[] = {0.7, 0.7, 0.7, 1.0};
1381 texture_string_metrics (ci->font, t->text, &e, 0, 0);
1384 glTranslatef (0.75, 0.75, 0.01);
1386 glTranslatef (-w/2, 0, 0);
1388 print_texture_string (ci->font, t->text);
1391 glDisable(GL_TEXTURE_2D);
1392 glDisable(GL_BLEND);
1393 glDepthMask(GL_TRUE);
1394 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1395 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
1396 glMaterialfv(GL_FRONT, GL_SHININESS, &shin);
1397 polys += Rect(0, 0, -0.5, 1.5, 1.5, 0.30);
1398 if (!glIsEnabled(GL_NORMALIZE)) glEnable(GL_NORMALIZE);
1399 glTranslatef(0.75, 1.875, -0.55);
1400 polys += HoledRectangle(ci, 1.5, 0.75, 0.25, 0.2, 8);
1401 glMaterialfv(GL_FRONT, GL_SPECULAR, nospec);
1402 glTranslatef(-0.375, -1.875, 0);
1403 glRotatef(90, 0, 0, -1);
1404 polys += wire(ci, 2);
1405 glTranslatef(0, 0.375, 0);
1406 polys += wire(ci, 2);
1407 glTranslatef(0, 0.375, 0);
1408 polys += wire(ci, 2);
1409 } else { /* SMC transistor */
1411 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col);
1412 glTranslatef(-0.5, -0.25, 0.1);
1413 polys += Rect(0, 0, 0, 1, 0.5, 0.2);
1414 /* Draw the markings */
1415 glEnable(GL_TEXTURE_2D);
1417 glDepthMask(GL_FALSE);
1419 glNormal3f(0, 0, 1);
1421 glVertex3f(0.2, 0, 0.01);
1423 glVertex3f(0.8, 0, 0.01);
1425 glVertex3f(0.8, 0.5, 0.01);
1427 glVertex3f(0.2, 0.5, 0.01);
1430 glDisable(GL_TEXTURE_2D);
1431 glDisable(GL_BLEND);
1432 glDepthMask(GL_TRUE);
1433 /* Now draw the legs */
1434 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1435 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
1436 glMaterialfv(GL_FRONT, GL_SHININESS, &shin);
1437 polys += Rect(0.25, -0.1, -0.05, 0.1, 0.1, 0.2);
1438 polys += Rect(0.75, -0.1, -0.05, 0.1, 0.1, 0.2);
1439 polys += Rect(0.5, 0.5, -0.05, 0.1, 0.1, 0.2);
1440 polys += Rect(0.25, -0.2, -0.2, 0.1, 0.15, 0.1);
1441 polys += Rect(0.75, -0.2, -0.2, 0.1, 0.15, 0.1);
1442 polys += Rect(0.5, 0.5, -0.2, 0.1, 0.15, 0.1);
1448 static Component * NewComponent(ModeInfo *mi)
1450 Circuit *ci = &circuit[MI_SCREEN(mi)];
1454 c = malloc(sizeof(Component));
1455 c->angle = RAND_RANGE(0,360);
1457 if (rnd < 0.25) { /* come from the top */
1459 c->x = RAND_RANGE(0, ci->XMAX) - ci->XMAX/2;
1461 c->dx = 0 - RAND_RANGE(0.5, 2);
1463 c->dx = RAND_RANGE(0.5, 2);
1464 c->dy = 0 - RAND_RANGE(0.5, 2);
1465 } else if (rnd < 0.5) { /* come from the bottom */
1466 c->y = 0 - ci->YMAX/2;
1467 c->x = RAND_RANGE(0, ci->XMAX) - ci->XMAX/2;
1469 c->dx = 0 - RAND_RANGE(0.5, 2);
1471 c->dx = RAND_RANGE(0.5, 2);
1472 c->dy = RAND_RANGE(0.5, 2);
1473 } else if (rnd < 0.75) { /* come from the left */
1474 c->x = 0 - ci->XMAX/2;
1475 c->y = RAND_RANGE(0, ci->YMAX) - ci->YMAX/2;
1476 c->dx = RAND_RANGE(0.5, 2);
1478 c->dy = 0 - RAND_RANGE(0.5, 2);
1480 c->dy = RAND_RANGE(0.5, 2);
1481 } else { /* come from the right */
1483 c->y = RAND_RANGE(0, ci->YMAX) - ci->YMAX/2;
1484 c->dx = 0 - RAND_RANGE(0.5, 2);
1486 c->dy = 0 - RAND_RANGE(0.5, 2);
1488 c->dy = RAND_RANGE(0.5, 2);
1490 c->z = RAND_RANGE(0, 7) - 9;
1494 c->drot = f_rand() * 3;
1496 c->dz = f_rand()*2 - 1;
1498 c->alpha = 0; /* explicitly set to 1 later */
1499 rnd = random() % 11;
1501 c->c = NewResistor();
1504 c->norm = 1; /* some resistors shine */
1505 } else if (rnd < 2) {
1508 c->norm = 1; /* some diodes shine */
1510 } else if (rnd < 3) {
1511 c->c = NewTransistor(mi);
1514 } else if (rnd < 4) {
1515 c->c = NewCapacitor(ci);
1518 } else if (rnd < 5) {
1522 } else if (rnd < 6) {
1527 } else if (rnd < 7) {
1532 } else if (rnd < 8) {
1536 } else if (rnd < 9) {
1537 c->c = NewThreeFive(ci);
1540 } else if (rnd < 10) {
1541 c->c = NewSwitch(ci);
1551 static Transistor *NewTransistor(ModeInfo *mi)
1555 t = malloc(sizeof(Transistor));
1556 t->type = (random() % 3);
1558 t->text = transistortypes[random() % countof(transistortypes)];
1559 } else if (t->type == 2) {
1560 t->text = smctypes[random() % countof(smctypes)];
1561 } else if (t->type == 1) {
1562 t->text = to92types[random() % countof(to92types)];
1567 static Capacitor *NewCapacitor(Circuit *ci)
1571 c = malloc(sizeof(Capacitor));
1572 c->type = (f_rand() < 0.5);
1574 c->length = RAND_RANGE(0.5, 1);
1575 c->width = RAND_RANGE(0.5, 1);
1577 c->width = RAND_RANGE(0.3, 1);
1582 /* 7 segment display */
1584 static Disp *NewDisp(Circuit *ci)
1588 d = malloc(sizeof(Disp));
1592 d->value = RAND_RANGE(0, 10);
1597 static IC *NewIC(ModeInfo *mi)
1602 int types[countof(ictypes)], i, n = 0;
1604 c = malloc(sizeof(IC));
1606 switch((int)RAND_RANGE(0,4)) {
1621 for (i = 0 ; i < countof(ictypes) ; i++) {
1622 if (ictypes[i].pins == pins) {
1628 if (n > countof(types)) abort();
1629 val = ictypes[types[random() % n]].val;
1630 sprintf(c->text, "%s\n%02d%02d", val,
1631 (int)RAND_RANGE(80, 100), (int)RAND_RANGE(1,53));
1636 static LED *NewLED(Circuit *ci)
1641 l = malloc(sizeof(LED));
1644 if (!ci->light && (f_rand() < 0.4)) {
1649 l->r = 0.9; l->g = 0; l->b = 0;
1650 } else if (r < 0.4) {
1651 l->r = 0.3; l->g = 0.9; l->b = 0;
1652 } else if (r < 0.6) {
1653 l->r = 0.8; l->g = 0.9; l->b = 0;
1654 } else if (r < 0.8) {
1655 l->r = 0.0; l->g = 0.2; l->b = 0.8;
1657 l->r = 0.9, l->g = 0.55, l->b = 0;
1662 static Fuse *NewFuse(Circuit *ci)
1666 f = malloc(sizeof(Fuse));
1670 static RCA *NewRCA(Circuit *ci)
1674 r = malloc(sizeof(RCA));
1675 r->col = (random() % 10 < 5);
1679 static ThreeFive *NewThreeFive(Circuit *ci)
1683 r = malloc(sizeof(ThreeFive));
1687 static Switch *NewSwitch(Circuit *ci)
1691 s = malloc(sizeof(Switch));
1696 static Diode *NewDiode(void)
1701 ret = malloc(sizeof(Diode));
1702 b = malloc(sizeof(Band));
1705 if (f_rand() < 0.5) {
1709 ret->r = 0.7; ret->g = 0.1 ; ret->b = 0.1;
1714 ret->r = 0.2; ret->g = 0.2 ; ret->b = 0.2;
1721 static Resistor * NewResistor(void)
1723 int v, m, t; /* value, multiplier, tolerance */
1728 t = (RAND(10) < 5) ? 10 : 11;
1729 ret = malloc(sizeof(Resistor));
1732 ret->b[0] = ret->b[1] = ret->b[2] = 7;
1734 ret->b[0] = values[v][0];
1735 ret->b[1] = values[v][1];
1743 static void makebandlist(Circuit *ci)
1746 GLfloat col[] = {0,0,0,0};
1747 GLfloat spec[] = {0.8,0.8,0.8,0};
1750 for (i = 0 ; i < 12 ; i++) {
1751 ci->band_list[i] = glGenLists(1);
1752 glNewList(ci->band_list[i], GL_COMPILE);
1753 col[0] = colorcodes[i][0];
1754 col[1] = colorcodes[i][1];
1755 col[2] = colorcodes[i][2];
1756 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
1757 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
1758 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shine);
1759 ci->band_list_polys[i] = createCylinder(ci, 0.1, 0.42, 0, 0);
1765 static int bandedCylinder(Circuit *ci,
1766 float radius, float l,
1767 GLfloat r, GLfloat g, GLfloat bl,
1768 Band **b, int nbands)
1771 int n; /* band number */
1772 GLfloat col[] = {0,0,0,0};
1774 col[0] = r; col[1] = g; col[2] = bl;
1775 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1776 polys += createCylinder(ci, l, radius, 1, 0); /* body */
1777 for (n = 0 ; n < nbands ; n++) {
1779 glTranslatef(b[n]->pos*l, 0, 0);
1780 col[0] = b[n]->r; col[1] = b[n]->g; col[2] = b[n]->b;
1781 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1782 polys += createCylinder(ci, b[n]->len*l, radius*1.05, 0, 0); /* band */
1788 static int drawgrid(Circuit *ci)
1792 GLfloat col3[] = {0, 0.8, 0};
1795 if (f_rand() < ((rotatespeed > 0) ? 0.05 : 0.01)) {
1796 ci->draw_sdir = RAND_RANGE(0, 4);
1797 ci->draw_ds = RAND_RANGE(0.4, 0.8);
1798 switch (ci->draw_sdir) {
1800 ci->draw_sx = -ci->XMAX/2;
1801 ci->draw_sy = ((int)RAND_RANGE(0, ci->YMAX/2))*2 - ci->YMAX/2;
1804 ci->draw_sx = ci->XMAX/2;
1805 ci->draw_sy = ((int)RAND_RANGE(0, ci->YMAX/2))*2 - ci->YMAX/2;
1808 ci->draw_sy = ci->YMAX/2;
1809 ci->draw_sx = ((int)RAND_RANGE(0, ci->XMAX/2))*2 - ci->XMAX/2;
1812 ci->draw_sy = -ci->YMAX/2;
1813 ci->draw_sx = ((int)RAND_RANGE(0, ci->XMAX/2))*2 - ci->XMAX/2;
1818 } else if (rotatespeed <= 0) {
1819 if (ci->grid_col[1] < 0.25) {
1820 ci->grid_col[1] += 0.025; ci->grid_col[2] += 0.005;
1821 ci->grid_col2[1] += 0.015 ; ci->grid_col2[2] += 0.005;
1825 glDisable(GL_LIGHTING);
1829 glTranslatef(ci->draw_sx, ci->draw_sy, -10);
1830 polys += sphere(ci, 0.1, 10, 10, 0, 10, 0, 10);
1831 if (ci->draw_sdir == 0)
1832 glTranslatef(-ci->draw_ds, 0, 0);
1833 if (ci->draw_sdir == 1)
1834 glTranslatef(ci->draw_ds, 0, 0);
1835 if (ci->draw_sdir == 2)
1836 glTranslatef(0, ci->draw_ds, 0);
1837 if (ci->draw_sdir == 3)
1838 glTranslatef(0, -ci->draw_ds, 0);
1839 polys += sphere(ci, 0.05, 10, 10, 0, 10, 0, 10);
1841 if (ci->draw_sdir == 0) {
1842 ci->draw_sx += ci->draw_ds;
1843 if (ci->draw_sx > ci->XMAX/2)
1846 if (ci->draw_sdir == 1) {
1847 ci->draw_sx -= ci->draw_ds;
1848 if (ci->draw_sx < -ci->XMAX/2)
1851 if (ci->draw_sdir == 2) {
1852 ci->draw_sy -= ci->draw_ds;
1853 if (ci->draw_sy < ci->YMAX/2)
1856 if (ci->draw_sdir == 3) {
1857 ci->draw_sy += ci->draw_ds;
1858 if (ci->draw_sy > ci->YMAX/2)
1861 } else if (rotatespeed <= 0) {
1862 if (ci->grid_col[1] > 0) {
1863 ci->grid_col[1] -= 0.0025; ci->grid_col[2] -= 0.0005;
1864 ci->grid_col2[1] -= 0.0015 ; ci->grid_col2[2] -= 0.0005;
1867 for (x = -ci->XMAX/2 ; x <= ci->XMAX/2 ; x+= 2) {
1868 glColor3fv(ci->grid_col);
1870 glVertex3f(x, ci->YMAX/2, -10);
1871 glVertex3f(x, -ci->YMAX/2, -10);
1872 glColor3fv(ci->grid_col2);
1873 glVertex3f(x-0.02, ci->YMAX/2, -10);
1874 glVertex3f(x-0.02, -ci->YMAX/2, -10);
1875 glVertex3f(x+0.02, ci->YMAX/2, -10);
1876 glVertex3f(x+0.02, -ci->YMAX/2, -10);
1879 for (y = -ci->YMAX/2 ; y <= ci->YMAX/2 ; y+= 2) {
1880 glColor3fv(ci->grid_col);
1882 glVertex3f(-ci->XMAX/2, y, -10);
1883 glVertex3f(ci->XMAX/2, y, -10);
1884 glColor3fv(ci->grid_col2);
1885 glVertex3f(-ci->XMAX/2, y-0.02, -10);
1886 glVertex3f(ci->XMAX/2, y-0.02, -10);
1887 glVertex3f(-ci->XMAX/2, y+0.02, -10);
1888 glVertex3f(ci->XMAX/2, y+0.02, -10);
1891 glEnable(GL_LIGHTING);
1895 static void display(ModeInfo *mi)
1897 Circuit *ci = &circuit[MI_SCREEN(mi)];
1898 GLfloat light_sp[] = {0.8, 0.8, 0.8, 1.0};
1899 GLfloat black[] = {0, 0, 0, 1.0};
1902 mi->polygon_count = 0;
1904 if (ci->display_i == 0) {
1905 for (ci->display_i = 0 ; ci->display_i < maxparts ; ci->display_i++) {
1906 ci->components[ci->display_i] = NULL;
1909 glEnable(GL_LIGHTING);
1910 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1912 gluLookAt(ci->viewer[0], ci->viewer[1], ci->viewer[2],
1916 glRotatef(ci->rotate_angle, 0, 0, 1);
1917 ci->rotate_angle += 0.01 * (float)rotatespeed;
1918 if (ci->rotate_angle >= 360) ci->rotate_angle = 0;
1920 glLightfv(GL_LIGHT0, GL_POSITION, ci->lightpos);
1921 glLightfv(GL_LIGHT0, GL_SPECULAR, light_sp);
1922 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_sp);
1923 glLighti(GL_LIGHT0, GL_CONSTANT_ATTENUATION, (GLfloat)1);
1924 glLighti(GL_LIGHT0, GL_LINEAR_ATTENUATION, (GLfloat)0.5);
1925 glLighti(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, (GLfloat)0);
1927 # ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
1929 GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
1930 int o = (int) current_device_rotation();
1931 if (o != 0 && o != 180 && o != -180)
1938 mi->polygon_count += drawgrid(ci);
1939 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light_sp);
1940 if (f_rand() < 0.05) {
1941 for (j = 0 ; j < maxparts ; j++) {
1942 if (ci->components[j] == NULL) {
1943 ci->components[j] = NewComponent(mi);
1947 reorder(&ci->components[0]);
1949 for (j = 0 ; j < maxparts ; j++) {
1950 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, black);
1951 glMaterialfv(GL_FRONT, GL_EMISSION, black);
1952 glMaterialfv(GL_FRONT, GL_SPECULAR, black);
1953 if (ci->components[j] != NULL) {
1954 if (DrawComponent(ci, ci->components[j], &mi->polygon_count)) {
1955 free(ci->components[j]); ci->components[j] = NULL;
1963 /* ensure transparent components are at the end */
1964 static void reorder(Component *c[])
1967 Component *c1[MAX_COMPONENTS];
1968 Component *c2[MAX_COMPONENTS];
1971 for (i = 0 ; i < maxparts ; i++) { /* clear old matrix */
1975 for (i = 0 ; i < maxparts ; i++) {
1976 if (c[i] == NULL) continue;
1977 if (c[i]->alpha) { /* transparent parts go to c1 */
1980 } else { /* opaque parts go to c2 */
1984 for (i = 0 ; i < maxparts ; i++) { /* clear old matrix */
1988 for (i = 0 ; i < maxparts ; i++) { /* insert opaque part */
1989 if (c2[i] != NULL) {
1994 for (i = 0 ; i < j ; i++) { /* insert transparent parts */
2000 ENTRYPOINT void reshape_circuit(ModeInfo *mi, int width, int height)
2002 Circuit *ci = &circuit[MI_SCREEN(mi)];
2003 GLfloat h = (GLfloat) height / (GLfloat) width;
2004 glViewport(0,0,(GLint)width, (GLint) height);
2005 glMatrixMode(GL_PROJECTION);
2007 glFrustum(-1.0,1.0,-h,h,1.5,35.0);
2008 glMatrixMode(GL_MODELVIEW);
2011 ci->YMAX = ci->XMAX * h;
2015 static void free_circuit(ModeInfo *mi);
2017 ENTRYPOINT void init_circuit(ModeInfo *mi)
2019 int screen = MI_SCREEN(mi);
2022 MI_INIT(mi, circuit, free_circuit);
2023 ci = &circuit[screen];
2024 ci->window = MI_WINDOW(mi);
2026 ci->XMAX = ci->YMAX = 50;
2028 ci->lightpos[0] = 7;
2029 ci->lightpos[1] = 7;
2030 ci->lightpos[2] = 15;
2031 ci->lightpos[3] = 1;
2033 ci->grid_col[1] = 0.25;
2034 ci->grid_col[2] = 0.05;
2035 ci->grid_col2[1] = 0.125;
2036 ci->grid_col2[2] = 0.05;
2038 ci->font = load_texture_font (MI_DISPLAY(mi), "componentFont");
2040 if (maxparts >= MAX_COMPONENTS)
2041 maxparts = MAX_COMPONENTS-1;
2043 if ((ci->glx_context = init_GL(mi)) != NULL) {
2044 reshape_circuit(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
2050 glShadeModel(GL_SMOOTH);
2051 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
2052 glEnable(GL_DEPTH_TEST);
2053 glEnable(GL_LIGHTING);
2054 glEnable(GL_LIGHT0);
2055 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2061 ENTRYPOINT void draw_circuit(ModeInfo *mi)
2063 Circuit *ci = &circuit[MI_SCREEN(mi)];
2064 Window w = MI_WINDOW(mi);
2065 Display *disp = MI_DISPLAY(mi);
2067 if (!ci->glx_context)
2070 glXMakeCurrent(disp, w, *(ci->glx_context));
2074 if(mi->fps_p) do_fps(mi);
2076 glXSwapBuffers(disp, w);
2079 static void free_circuit(ModeInfo *mi)
2081 Circuit *ci = &circuit[MI_SCREEN(mi)];
2083 free_texture_font (ci->font);
2087 XSCREENSAVER_MODULE ("Circuit", circuit)