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
11 * Copyright (C) 2001 Ben Buxton (bb@cactii.net)
13 * Permission to use, copy, modify, distribute, and sell this software and its
14 * documentation for any purpose is hereby granted without fee, provided that
15 * the above copyright notice appear in all copies and that both that
16 * copyright notice and this permission notice appear in supporting
17 * documentation. No representations are made about the suitability of this
18 * software for any purpose. It is provided "as is" without express or
22 /* Written over a few days in a (successful) bid to learn GL coding
24 * -seven option is dedicated to all the Slarkeners
26 * try "-rotate -rotate-speed 0"
28 * This hack uses lookup tables for sin, cos and tan - it can do a lot
32 #include <X11/Intrinsic.h>
35 # define PROGCLASS "Circuit"
36 # define HACK_INIT init_circuit
37 # define HACK_DRAW draw_circuit
38 # define HACK_RESHAPE reshape_circuit
39 # define circuit_opts xlockmore_opts
40 /* insert defaults here */
42 #define DEF_SPIN "True"
43 #define DEF_SEVEN "False"
44 #define DEF_PARTS "10"
47 #define DEFAULTS "*parts: " DEF_PARTS " \n" \
48 "*spin: " DEF_SPIN "\n" \
50 "*showFPS: False \n" \
51 "*seven: " DEF_SEVEN "\n" \
57 # include "xlockmore.h" /* from the xscreensaver distribution */
58 #else /* !STANDALONE */
59 # include "xlock.h" /* from the xlockmore distribution */
60 #endif /* !STANDALONE */
62 /* lifted from lament.c */
63 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
64 #define RANDSIGN() ((random() & 1) ? 1 : -1)
70 #include "font-ximage.h"
73 #define countof(x) (sizeof((x))/sizeof((*x)))
79 static int rotatespeed;
85 #define countof(x) (sizeof((x))/sizeof((*x)))
87 static XrmOptionDescRec opts[] = {
88 {"-parts", ".circuit.parts", XrmoptionSepArg, "10" },
89 {"-font", ".circuit.font", XrmoptionSepArg, "fixed" },
90 {"-rotate-speed", ".circuit.rotatespeed", XrmoptionSepArg, "1" },
91 {"+spin", ".circuit.spin", XrmoptionNoArg, (caddr_t) "false" },
92 {"-spin", ".circuit.spin", XrmoptionNoArg, (caddr_t) "true" },
93 {"+light", ".circuit.light", XrmoptionNoArg, (caddr_t) "false" },
94 {"-light", ".circuit.light", XrmoptionNoArg, (caddr_t) "true" },
95 {"+seven", ".circuit.seven", XrmoptionNoArg, (caddr_t) "false" },
96 {"-seven", ".circuit.seven", XrmoptionNoArg, (caddr_t) "true" },
97 {"+rotate", ".circuit.rotate", XrmoptionNoArg, (caddr_t) "false" },
98 {"-rotate", ".circuit.rotate", XrmoptionNoArg, (caddr_t) "true" },
101 static argtype vars[] = {
102 {(caddr_t *) &maxparts, "parts", "Parts", DEF_PARTS, t_Int},
103 {(caddr_t *) &font, "font", "Font", "fixed", t_String},
104 {(caddr_t *) &rotatespeed, "rotatespeed", "Rotatespeed", "1", t_Int},
105 {(caddr_t *) &spin, "spin", "Spin", DEF_SPIN, t_Bool},
106 {(caddr_t *) &rotate, "rotate", "Rotate", "False", t_Bool},
107 {(caddr_t *) &uselight, "light", "Light", "True", t_Bool},
108 {(caddr_t *) &seven, "seven", "Seven", DEF_SEVEN, t_Bool},
111 ModeSpecOpt circuit_opts = {countof(opts), opts, countof(vars), vars, NULL};
114 ModStruct circuit_description =
115 {"circuit", "init_circuit", "draw_circuit", "release_circuit",
116 "draw_circuit", "init_circuit", NULL, &circuit_opts,
117 1000, 1, 2, 1, 4, 1.0, "",
118 "Flying electronic components", 0, NULL};
124 GLXContext *glx_context;
128 static Circuit *circuit = NULL;
131 #include <sys/time.h>
136 #define M_PI 3.14159265
139 /* window width, height */
142 /* width and height of viewport */
145 static int YMAX = 30;
147 #define MAX_COMPONENTS 30
149 #define MOVE_MULT 0.05
151 static float f_rand(void) {
152 return ((float)RAND(10000)/(float)10000);
155 #define RAND_RANGE(min, max) ((min) + (max - min) * f_rand())
157 /* one lucky led gets to be a light source , unless -no-light*/
161 static GLfloat viewer[] = {0.0, 0.0, 14.0};
162 static GLfloat lightpos[] = {7.0, 7.0, 15, 1.0};
164 float sin_table[720];
165 float cos_table[720];
166 float tan_table[720];
170 /* used for allocating font textures */
172 int num; /* index number */
177 /* Represents a band on a resistor/diode/etc */
179 float pos; /* relative position from start/previous band */
180 GLfloat r, g, b; /* colour of the band */
181 float len; /* length as a fraction of total length */
185 Band *b1, *b2, *b3, *b4; /* bands */
191 GLfloat r, g, b; /* body colour */
194 static const char * transistortypes[] = {
211 int type; /* package type. 0 = to-92, 1 = to-220 */
212 GLfloat tw, th; /* texture dimensions */
213 int tnum; /* texture binding */
217 GLfloat r,g,b; /* LED colour */
218 int light; /* are we the light source? */
222 int type; /* 0 = electro, 1 = ceramic */
223 float width; /* width of an electro/ceramic */
224 float length; /* length of an electro */
232 static const ICTypes ictypes[] = {
275 int type; /* 0 = DIL, 1 = flat square */
277 float tw, th; /* texture dimensions for markings */
278 int tnum; /* texture number */
281 /* 7 segment display */
284 int value; /* displayed number */
292 GLfloat x, y, z; /* current co-ordinates */
293 GLfloat dx, dy, dz; /* current direction */
294 GLfloat rotx, roty, rotz; /* rotation vector */
295 GLfloat drot; /* rotation velocity (degrees per frame) */
296 int norm; /* Normalize this component (for shine) */
297 int rdeg; /* current rotation degrees */
298 int angle; /* angle about the z axis */
299 int alpha; /* 0 if not a transparent component */
300 int type; /* 0 = resistor, 1 = diode, 2 = transistor, 3 = LED, 4 = cap, 5=IC,
302 void * c; /* pointer to the component */
305 static int band_list[12];
307 /* standard colour codes */
309 static GLfloat colorcodes [12][3] = {
310 {0.0,0.0,0.0}, /* black 0 */
311 {0.49,0.25,0.08}, /* brown 1 */
312 {1.0,0.0,0.0}, /* red 2 */
313 {1.0,0.5,0.0}, /* orange 3 */
314 {1.0,1.0,0.0}, /* yellow 4 */
315 {0.0,1.0,0.0}, /* green 5 */
316 {0.0,0.5,1.0}, /* blue 6 */
317 {0.7,0.2,1.0}, /* violet 7 */
318 {0.5,0.5,0.5}, /* grey 8 */
319 {1.0,1.0,1.0}, /* white 9 */
320 {0.66,0.56,0.2}, /* gold 10 */
321 {0.8,0.8,0.8}, /* silver 11 */
324 /* base values for components - we can multiply by 0 - 1M */
325 static int values [9][2] = {
337 void DrawResistor(Resistor *);
338 void DrawDiode(Diode *);
339 void DrawTransistor(Transistor *);
342 void DrawCapacitor(Capacitor *);
343 void DrawDisp(Disp *);
344 void DrawFuse(Fuse *);
346 void reorder(Component *[]);
347 void circle(float, int,int);
348 void bandedCylinder(float, float , GLfloat, GLfloat , GLfloat, Band **, int);
349 TexNum *fonttexturealloc(const char *, float *, float *);
350 Resistor *NewResistor(void);
351 Diode *NewDiode(void);
352 Transistor *NewTransistor(void);
354 Capacitor *NewCapacitor(void);
359 /* we use trig tables to speed things up - 200 calls to sin()
360 in one frame can be a bit harsh..
363 void make_tables(void) {
367 f = 360 / (M_PI * 2);
368 for (i = 0 ; i < 720 ; i++) {
369 sin_table[i] = sin(i/f);
371 for (i = 0 ; i < 720 ; i++) {
372 cos_table[i] = cos(i/f);
374 for (i = 0 ; i < 720 ; i++) {
375 tan_table[i] = tan(i/f);
380 void createCylinder (float length, float radius, int endcaps, int half)
382 int a; /* current angle around cylinder */
384 float z1, y1, z2, y2,ex;
389 nsegs = radius*MAX(win_w, win_h)/20;
390 nsegs = MAX(nsegs, 4);
393 angle = (half) ? (180 - 90/nsegs) : 374;
397 for (a = 0 ; a <= angle ; a+= angle/nsegs) {
398 y2=radius*(float)sin_table[(int)a];
399 z2=radius*(float)cos_table[(int)a];
400 glNormal3f(0, y1, z1);
402 glVertex3f(length,y1,z1);
403 glNormal3f(0, y2, z2);
404 glVertex3f(length,y2,z2);
413 glVertex3f(0, 0, radius);
414 glVertex3f(length, 0, radius);
415 glVertex3f(length, 0, 0 - radius);
416 glVertex3f(0, 0, 0 - radius);
420 for(ex = 0 ; ex <= length ; ex += length) {
422 norm = (ex == length) ? 1 : -1;
423 glBegin(GL_TRIANGLES);
424 glNormal3f(norm, 0, 0);
425 for (a = 0 ; a <= angle ; a+= angle/nsegs) {
426 y2=radius*(float)sin_table[(int)a];
427 z2=radius*(float)cos_table[(int)a];
429 glVertex3f(ex,y1,z1);
430 glVertex3f(ex,y2,z2);
440 void circle(float radius, int segments, int half)
442 float x1 = 0, x2 = 0;
443 float y1 = 0, y2 = 0;
452 glBegin(GL_TRIANGLES);
457 x2=radius*(float)cos_table[(int)angle];
458 y2=radius*(float)sin_table[(int)angle];
470 static GLfloat col[] = {0.3, 0.3, 0.3, 1.0};
471 static GLfloat spec[] = {0.9, 0.9, 0.9, 1.0};
472 static GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0};
476 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
477 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
478 glMaterialfv(GL_FRONT, GL_SHININESS, &shin);
479 n = glIsEnabled(GL_NORMALIZE);
480 if (!n) glEnable(GL_NORMALIZE);
481 createCylinder(len, 0.05, 1, 0);
482 if (!n) glDisable(GL_NORMALIZE);
483 glMaterialfv(GL_FRONT, GL_SPECULAR, nospec);
486 void ring(GLfloat inner, GLfloat outer, int nsegs)
488 GLfloat z1, z2, y1, y2;
489 GLfloat Z1, Z2, Y1, Y2;
496 for(i=0; i <=360 ; i+= 360/nsegs)
499 z2=inner*(float)sin_table[(int)angle];
500 y2=inner*(float)cos_table[(int)angle];
501 Z2=outer*(float)sin_table[(int)angle];
502 Y2=outer*(float)cos_table[(int)angle];
503 glVertex3f(0, Y1, Z1);
504 glVertex3f(0, y1, z1);
505 glVertex3f(0, y2, z2);
506 glVertex3f(0, Y2, Z2);
515 void sphere(GLfloat r, float stacks, float slices,
516 int startstack, int endstack, int startslice,
519 GLfloat d, d1, dr, dr1, Dr, Dr1, D, D1, z1, z2, y1, y2, Y1, Z1, Y2, Z2;
520 int a, a1, b, b1, c, c1;
525 a1 = startstack * step;
526 b1 = startslice * sstep;
527 y1 = z1 = Y1 = Z1 = 0;
528 c = (endslice / slices) * 360;
529 c1 = (endstack/stacks)*180;
531 for (a = startstack * step ; a <= c1 ; a+= step) {
540 for (b = b1 ; b <= c ; b+= sstep) {
545 glNormal3f(Dr, y1, z1);
546 glVertex3f(Dr,y1,z1);
547 glNormal3f(Dr, y2, z2);
548 glVertex3f(Dr,y2,z2);
549 glNormal3f(Dr1, Y2, Z2);
550 glVertex3f(Dr1,Y2,Z2);
551 glNormal3f(Dr1, Y1, Z1);
552 glVertex3f(Dr1,Y1,Z1);
563 int DrawComponent(Component *c)
565 int ret = 0; /* return 1 if component is freed */
568 glTranslatef(c->x, c->y, c->z);
570 glRotatef(c->angle, c->rotx, c->roty, c->rotz);
573 glRotatef(c->rdeg, c->rotx, c->roty, c->rotz);
578 glEnable(GL_NORMALIZE);
580 glDisable(GL_NORMALIZE);
582 /* call object draw routine here */
585 } else if (c->type == 1) {
587 } else if (c->type == 2) {
588 DrawTransistor(c->c);
589 } else if (c->type == 3) {
590 if (((LED *)c->c)->light && light) {
591 GLfloat lp[] = {0.1, 0, 0, 1};
593 glLightfv(GL_LIGHT1, GL_POSITION, lp);
596 } else if (c->type == 4) {
598 } else if (c->type == 5) {
600 } else if (c->type == 6) {
602 } else if (c->type == 7) {
605 c->x += c->dx * MOVE_MULT;
606 c->y += c->dy * MOVE_MULT;
607 if (c->x > XMAX/2 || c->x < 0 - XMAX/2 ||
608 c->y > YMAX/2 || c->y < 0 - YMAX/2) {
609 if (c->type == 3 && ((LED *)c->c)->light && light) {
610 glDisable(GL_LIGHT1);
611 light = 0; lighton = 0;
614 free(((Diode *)c->c)->band); /* remember to free diode band */
620 glDisable(GL_NORMALIZE);
624 /* draw a resistor */
626 void DrawResistor(Resistor *r)
629 GLfloat col[] = {0.74, 0.62, 0.46, 1.0};
630 GLfloat spec[] = {0.8, 0.8, 0.8, 1.0};
633 glTranslatef(-4, 0, 0);
635 glTranslatef(3, 0, 0);
636 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
637 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
638 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
639 createCylinder(1.8, 0.4, 1, 0);
641 for (i = 0 ; i < 4 ; i++) {
642 glTranslatef(0.35, 0, 0);
643 glCallList(band_list[r->b[i]]);
646 glTranslatef(1.8, 0, 0);
650 void DrawFuse(Fuse *f)
652 static GLfloat col[] = {0.5, 0.5, 0.5, 1.0}; /* endcaps */
653 static GLfloat glass[] = {0.4, 0.4, 0.4, 0.3}; /* glass */
654 static GLfloat spec[] = {1, 1, 1, 1}; /* glass */
657 glTranslatef(-1.8, 0, 0);
658 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
659 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
660 glMateriali(GL_FRONT, GL_SHININESS, 40);
661 createCylinder(0.8, 0.45, 1, 0);
662 glTranslatef(0.8, 0, 0);
664 glDepthMask(GL_FALSE);
665 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, glass);
666 glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 40);
667 createCylinder(2, 0.4, 0, 0);
668 createCylinder(2, 0.3, 0, 0);
670 glDepthMask(GL_TRUE);
671 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
672 glMateriali(GL_FRONT, GL_SHININESS, 40);
675 glVertex3f(2, 0. ,0);
677 glTranslatef(2, 0, 0);
678 createCylinder(0.8, 0.45, 1, 0);
683 void DrawCapacitor(Capacitor *c)
685 static GLfloat col[] = {0, 0, 0, 0};
686 static GLfloat spec[] = {0.8, 0.8, 0.8, 0};
687 GLfloat brown[] = {0.84, 0.5, 0};
688 static GLfloat shine = 40;
692 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, brown);
693 sphere(c->width, 15, 15, 0, 4 ,0, 15);
694 glTranslatef(1.35*c->width, 0, 0);
695 sphere(c->width, 15, 15, 11, 15, 0, 15);
696 glRotatef(90, 0, 0, 1);
697 glTranslatef(0, 0.7*c->width, 0.3*c->width);
699 glTranslatef(0, 0, -0.6*c->width);
702 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
703 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
704 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shine);
706 glVertex3f(0, 0.82*c->width, -0.1);
707 glVertex3f(3*c->length, 0.82*c->width, -0.1);
708 glVertex3f(3*c->length, 0.82*c->width, 0.1);
709 glVertex3f(0, 0.82*c->width, 0.1);
714 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
715 glEnable(GL_POLYGON_OFFSET_FILL);
716 glPolygonOffset(1.0, 1.0);
717 createCylinder(3.0*c->length, 0.8*c->width, 1, 0);
718 glDisable(GL_POLYGON_OFFSET_FILL);
722 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
723 circle(0.6*c->width, 30, 0);
727 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
728 glTranslatef(3.0*c->length, 0.0, 0);
729 circle(0.6*c->width, 30, 0);
730 glTranslatef(0, 0.4*c->width, 0);
732 glTranslatef(0.0, -0.8*c->width, 0);
740 GLfloat col[] = {0, 0, 0, 0.6};
742 col[0] = l->r; col[1] = l->g; col[2] = l->b;
743 if (l->light && light) {
744 GLfloat dir[] = {-1, 0, 0};
745 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, dir);
747 glLightfv(GL_LIGHT1, GL_SPECULAR, col);
748 glLightfv(GL_LIGHT1, GL_AMBIENT, col);
749 glLightfv(GL_LIGHT1, GL_DIFFUSE, col);
750 glLighti(GL_LIGHT1, GL_SPOT_CUTOFF, (GLint) 90);
751 glLighti(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (GLfloat)1);
752 glLighti(GL_LIGHT1, GL_LINEAR_ATTENUATION, (GLfloat)0);
753 glLighti(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (GLfloat)0);
754 glLighti(GL_LIGHT1, GL_SPOT_EXPONENT, (GLint) 20);
758 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
759 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col);
760 /* no transparency when LED is lit */
763 glDepthMask(GL_FALSE);
764 glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
766 createCylinder(1.2, 0.3, 0, 0);
767 if (l->light && light) {
768 glDisable(GL_LIGHTING);
771 sphere(0.3, 7, 7, 3, 7, 0, 7);
772 if (l->light && light) {
773 glEnable(GL_LIGHTING);
775 glDepthMask(GL_TRUE);
779 glTranslatef(1.2, 0, 0);
780 createCylinder(0.1, 0.38, 1, 0);
781 glTranslatef(-0.3, 0.15, 0);
783 glTranslatef(0, -0.3, 0);
785 if (random() % 50 == 25) {
787 l->light = 0; light = 0; lighton = 0;
788 glDisable(GL_LIGHT1);
790 l->light = 1; light = 1;
797 void DrawDiode(Diode *d)
800 GLfloat col[] = {0.3, 0.3, 0.3, 0};
801 GLfloat spec[] = {0.7, 0.7, 0.7, 0};
804 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
805 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
806 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
807 glTranslatef(-4, 0, 0);
809 glTranslatef(3, 0, 0);
810 bandedCylinder(0.3, 1.5, d->r, d->g, d->b, &(d->band), 1);
811 glTranslatef(1.5, 0, 0);
816 void Rect(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h,
823 yh = y+h; xw = x+w; zt = z - t;
825 glBegin(GL_QUADS); /* front */
828 glVertex3f(x, yh, z);
829 glVertex3f(xw, yh, z);
830 glVertex3f(xw, y, z);
832 glNormal3f(0, 0, -1);
833 glVertex3f(x, y, zt);
834 glVertex3f(x, yh, zt);
835 glVertex3f(xw, yh, zt);
836 glVertex3f(xw, y, zt);
839 glVertex3f(x, yh, z);
840 glVertex3f(x, yh, zt);
841 glVertex3f(xw, yh, zt);
842 glVertex3f(xw, yh, z);
844 glNormal3f(0, -1, 0);
846 glVertex3f(x, y, zt);
847 glVertex3f(xw, y, zt);
848 glVertex3f(xw, y, z);
850 glNormal3f(-1, 0, 0);
852 glVertex3f(x, y, zt);
853 glVertex3f(x, yh, zt);
854 glVertex3f(x, yh, z);
857 glVertex3f(xw, y, z);
858 glVertex3f(xw, y, zt);
859 glVertex3f(xw, yh, zt);
860 glVertex3f(xw, yh, z);
866 void ICLeg(GLfloat x, GLfloat y, GLfloat z, int dir)
869 Rect(x-0.1, y, z, 0.1, 0.1, 0.02);
870 Rect(x-0.1, y, z, 0.02, 0.1, 0.1);
871 Rect(x-0.1, y+0.03, z-0.1, 0.02, 0.05, 0.3);
873 Rect(x, y, z, 0.1, 0.1, 0.02);
874 Rect(x+0.8*0.1, y, z, 0.02, 0.1, 0.1);
875 Rect(x+0.8*0.1, y+0.03, z-0.1, 0.02, 0.05, 0.3);
885 GLfloat col[] = {0.1, 0.1, 0.1, 0};
886 GLfloat col2[] = {0.2, 0.2, 0.2, 0};
887 GLfloat spec[] = {0.6, 0.6, 0.6, 0};
889 GLfloat lspec[] = {0.6, 0.6, 0.6, 0};
890 GLfloat lcol[] = {0.4, 0.4, 0.4, 0};
892 float mult, th, size;
895 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
896 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
897 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
898 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
915 glEnable(GL_POLYGON_OFFSET_FILL);
916 glPolygonOffset(1.0, 1.0);
919 glVertex3f(w, h, 0.1);
920 glVertex3f(w, -h, 0.1);
921 glVertex3f(-w, -h, 0.1);
922 glVertex3f(-w, h, 0.1);
923 glNormal3f(0, 0, -1);
924 glVertex3f(w, h, -0.1);
925 glVertex3f(w, -h, -0.1);
926 glVertex3f(-w, -h, -0.1);
927 glVertex3f(-w, h, -0.1);
929 glVertex3f(w, h, -0.1);
930 glVertex3f(w, -h, -0.1);
931 glVertex3f(w, -h, 0.1);
932 glVertex3f(w, h, 0.1);
933 glNormal3f(0, -1, 0);
934 glVertex3f(w, -h, -0.1);
935 glVertex3f(w, -h, 0.1);
936 glVertex3f(-w, -h, 0.1);
937 glVertex3f(-w, -h, -0.1);
938 glNormal3f(-1, 0, 0);
939 glVertex3f(-w, h, -0.1);
940 glVertex3f(-w, h, 0.1);
941 glVertex3f(-w, -h, 0.1);
942 glVertex3f(-w, -h, -0.1);
943 glNormal3f(0, -1, 0);
944 glVertex3f(-w, h, -0.1);
945 glVertex3f(w, h, -0.1);
946 glVertex3f(w, h, 0.1);
947 glVertex3f(-w, h, 0.1);
949 glDisable(GL_POLYGON_OFFSET_FILL);
950 glBindTexture(GL_TEXTURE_2D, c->tnum);
951 glEnable(GL_TEXTURE_2D);
958 mult = size*c->tw / c->th;
960 glBegin(GL_QUADS); /* text markings */
963 glVertex3f(th, mult, 0.1);
965 glVertex3f(th, -mult, 0.1);
967 glVertex3f(-th, -mult, 0.1);
969 glVertex3f(-th, mult, 0.1);
971 glDisable(GL_TEXTURE_2D);
973 d = (h*2-0.1) / c->pins;
975 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol);
976 glMaterialfv(GL_FRONT, GL_SPECULAR, lspec);
977 glMaterialfv(GL_FRONT, GL_SHININESS, &lshine);
978 for (z = 0 ; z < c->pins/2 ; z++) {
979 ICLeg(w, -h + z*d + d/2, 0, 0);
981 for (z = 0 ; z < c->pins/2 ; z++) {
982 ICLeg(-w, -h + z*d + d/2, 0, 1);
984 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col2);
985 glTranslatef(-w+0.3, h-0.3, 0.1);
986 glRotatef(90, 0, 1, 0);
991 void DrawDisp(Disp *d)
993 GLfloat col[] = {0.8, 0.8, 0.8, 1.0}; /* body colour */
994 GLfloat front[] = {0.2, 0.2, 0.2, 1.0}; /* front colour */
995 GLfloat on[] = {0.9, 0, 0, 1}; /* 'on' segment */
996 GLfloat off[] = {0.3, 0, 0, 1}; /* 'off' segment */
998 GLfloat x, y; /* for the pins */
999 GLfloat spec[] = {0.6, 0.6, 0.6, 0};
1000 GLfloat lcol[] = {0.4, 0.4, 0.4, 0};
1002 static GLfloat vdata_h[6][2] = {
1010 static GLfloat vdata_v[6][2] = {
1019 static GLfloat seg_start[7][2] = {
1029 static int nums[10][7] = {
1030 {1, 1, 1, 1, 1, 1, 0}, /* 0 */
1031 {0, 1, 1, 0, 0, 0, 0}, /* 1 */
1032 {1, 1, 0, 1, 1, 0, 1}, /* 2 */
1033 {1, 1, 1, 1, 0, 0, 1}, /* 3 */
1034 {0, 1, 1, 0, 0, 1, 1}, /* 4 */
1035 {1, 0, 1, 1, 0, 1, 1}, /* 5 */
1036 {1, 0, 1, 1, 1, 1, 1}, /* 6 */
1037 {1, 1, 1, 0, 0, 0, 0}, /* 7 */
1038 {1, 1, 1, 1, 1, 1, 1}, /* 8 */
1039 {1, 1, 1, 0, 0, 1, 1} /* 9 */
1042 glTranslatef(-0.9, -1.8, 0);
1043 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1044 Rect(0, 0, -0.01, 1.8, 2.6, 0.7);
1045 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, front);
1047 glVertex2f(-0.05, -0.05);
1048 glVertex2f(-0.05, 2.65);
1049 glVertex2f(1.85, 2.65);
1050 glVertex2f(1.85, -0.05);
1052 glDisable(GL_LIGHTING); /* lit segments dont need light */
1053 if (!seven && (random() % 30) == 19) { /* randomly change value */
1054 d->value = random() % 10;
1056 for (j = 0 ; j < 7 ; j++) { /* draw the segments */
1057 GLfloat xx[6], yy[6];
1058 if (nums[d->value][j])
1062 for (k = 0 ; k < 6 ; k++) {
1063 if (j == 0 || j == 3 || j == 6) {
1064 xx[k] = seg_start[j][0] + vdata_h[k][0];
1065 yy[k] = seg_start[j][1] + vdata_h[k][1];
1067 xx[k] = seg_start[j][0] + vdata_v[k][0];
1068 yy[k] = seg_start[j][1] + vdata_v[k][1];
1071 glBegin(GL_POLYGON);
1072 for(i = 0 ; i < 6 ; i++) {
1073 glVertex3f(xx[i], yy[i], 0.01);
1080 glVertex3f(1.5, 0.2, 0.01);
1082 glEnable(GL_LIGHTING);
1083 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lcol);
1084 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
1085 glMaterialfv(GL_FRONT, GL_SHININESS, &shine);
1086 for (x = 0.35 ; x <= 1.5 ; x+= 1.15) {
1087 for ( y = 0.2 ; y <= 2.4 ; y += 0.3) {
1088 ICLeg(x, y, -0.7, 1);
1093 void HoledRectangle(GLfloat w, GLfloat h, GLfloat d, GLfloat radius, int p)
1096 GLfloat x1, y1, x2, y2;
1097 GLfloat yr, yr1, xr, xr1, side, side1;
1101 x1 = radius; y1 = 0;
1106 for (a = 0 ; a <= 360 ; a+= step) {
1107 y2=radius*(float)sin_table[(int)a];
1108 x2=radius*(float)cos_table[(int)a];
1110 if (a < 45 || a > 315) {
1112 yr = side1 * tan_table[a];
1114 } else if (a <= 135 || a >= 225) {
1115 xr = side/tan_table[a];
1126 yr = -side1 * tan_table[a];
1130 glNormal3f(-x1, -y1, 0); /* cylinder */
1131 glVertex3f(x1,y1,0);
1132 glVertex3f(x1,y1,-d);
1133 glVertex3f(x2,y2,-d);
1134 glVertex3f(x2,y2,0);
1136 glNormal3f(0, 0, 1); /* front face */
1137 glVertex3f(x1,y1,0);
1138 glVertex3f(xr1, yr1, 0);
1139 glVertex3f(xr, yr, 0);
1140 glVertex3f(x2, y2, 0);
1142 glNormal3f(nx, ny, 0); /* side */
1143 glVertex3f(xr, yr, 0);
1144 glVertex3f(xr, yr, -d);
1145 glVertex3f(xr1, yr1, -d);
1146 glVertex3f(xr1, yr1, 0);
1148 glNormal3f(0, 0, -1); /* back */
1149 glVertex3f(xr, yr, -d);
1150 glVertex3f(x2, y2, -d);
1151 glVertex3f(x1, y1, -d);
1152 glVertex3f(xr1, yr1, -d);
1161 void DrawTransistor(Transistor *t)
1163 static GLfloat col[] = {0.3, 0.3, 0.3, 1.0};
1164 static GLfloat spec[] = {0.9, 0.9, 0.9, 1.0};
1165 static GLfloat nospec[] = {0.4, 0.4, 0.4, 1.0};
1169 glMaterialfv(GL_FRONT, GL_SHININESS, &shin);
1170 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
1171 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1173 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col);
1174 glRotatef(90, 0, 1, 0);
1175 glRotatef(90, 0, 0, 1);
1176 createCylinder(1.0, 0.4, 1, 1);
1177 Rect(0, -0.2, 0.4, 1, 0.2, 0.8);
1178 glTranslatef(-2, 0, -0.2);
1180 glTranslatef(0, 0, 0.2);
1182 glTranslatef(0, 0, 0.2);
1186 mult = 1.5*t->th/t->tw;
1189 Rect(0, 0, 0, 1.5, 1.5, 0.5);
1190 glEnable(GL_TEXTURE_2D);
1191 glBindTexture(GL_TEXTURE_2D, t->tnum);
1193 glDepthMask(GL_FALSE);
1195 glNormal3f(0, 0, 1);
1197 glVertex3f(0, y1, 0.01);
1199 glVertex3f(1.5, y1, 0.01);
1201 glVertex3f(1.5, y2, 0.01);
1203 glVertex3f(0, y2, 0.01);
1205 glDisable(GL_TEXTURE_2D);
1206 glDisable(GL_BLEND);
1207 glDepthMask(GL_TRUE);
1208 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1209 glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
1210 glMaterialfv(GL_FRONT, GL_SHININESS, &shin);
1211 Rect(0, 0, -0.5, 1.5, 1.5, 0.30);
1212 if (!glIsEnabled(GL_NORMALIZE)) glEnable(GL_NORMALIZE);
1213 glTranslatef(0.75, 1.875, -0.55);
1214 HoledRectangle(1.5, 0.75, 0.25, 0.2, 8);
1215 glMaterialfv(GL_FRONT, GL_SPECULAR, nospec);
1216 glTranslatef(-0.375, -1.875, 0);
1217 glRotatef(90, 0, 0, -1);
1219 glTranslatef(0, 0.375, 0);
1221 glTranslatef(0, 0.375, 0);
1227 Component * NewComponent(void)
1232 c = malloc(sizeof(Component));
1233 c->angle = RAND_RANGE(0,360);
1235 if (rnd < 0.25) { /* come from the top */
1237 c->x = RAND_RANGE(0, XMAX) - XMAX/2;
1239 c->dx = 0 - RAND_RANGE(0.5, 2);
1241 c->dx = RAND_RANGE(0.5, 2);
1242 c->dy = 0 - RAND_RANGE(0.5, 2);
1243 } else if (rnd < 0.5) { /* come from the bottom */
1245 c->x = RAND_RANGE(0, XMAX) - XMAX/2;
1247 c->dx = 0 - RAND_RANGE(0.5, 2);
1249 c->dx = RAND_RANGE(0.5, 2);
1250 c->dy = RAND_RANGE(0.5, 2);
1251 } else if (rnd < 0.75) { /* come from the left */
1253 c->y = RAND_RANGE(0, YMAX) - YMAX/2;
1254 c->dx = RAND_RANGE(0.5, 2);
1256 c->dy = 0 - RAND_RANGE(0.5, 2);
1258 c->dy = RAND_RANGE(0.5, 2);
1259 } else { /* come from the right */
1261 c->y = RAND_RANGE(0, YMAX) - YMAX/2;
1262 c->dx = 0 - RAND_RANGE(0.5, 2);
1264 c->dy = 0 - RAND_RANGE(0.5, 2);
1266 c->dy = RAND_RANGE(0.5, 2);
1268 c->z = RAND_RANGE(0, 7) - 9;
1272 c->drot = f_rand() * 7;
1274 c->dz = f_rand()*2 - 1;
1276 c->alpha = 0; /* explicitly set to 1 later */
1279 c->c = NewResistor();
1282 c->norm = 1; /* some resistors shine */
1283 } else if (rnd < 0.2) {
1286 c->norm = 1; /* some diodes shine */
1288 } else if (rnd < 0.3) {
1289 c->c = NewTransistor();
1292 } else if (rnd < 0.4) {
1293 c->c = NewCapacitor();
1296 } else if (rnd < 0.6) {
1300 } else if (rnd < 0.7) {
1305 } else if (rnd < 0.8) {
1317 Transistor *NewTransistor(void)
1320 float texfg[] = {0.7, 0.7, 0.7, 1.0};
1321 float texbg[] = {0.3, 0.3, 0.3, 0.1};
1325 t = malloc(sizeof(Transistor));
1326 t->type = (f_rand() < 0.5);
1328 val = transistortypes[random() % countof(transistortypes)];
1329 tn = fonttexturealloc(val, texfg, texbg);
1331 fprintf(stderr, "Error getting a texture for a string!\n");
1334 t->tw = tn->w; t->th = tn->h;
1341 Capacitor *NewCapacitor(void)
1345 c = malloc(sizeof(Capacitor));
1346 c->type = (f_rand() < 0.5);
1348 c->length = RAND_RANGE(0.5, 1);
1349 c->width = RAND_RANGE(0.5, 1);
1351 c->width = RAND_RANGE(0.3, 1);
1356 /* 7 segment display */
1362 d = malloc(sizeof(Disp));
1366 d->value = RAND_RANGE(0, 10);
1376 float texfg[] = {0.7, 0.7, 0.7, 1.0};
1377 float texbg[] = {0.1, 0.1, 0.1, 0};
1380 int types[countof(ictypes)], i, n = 0;
1382 c = malloc(sizeof(IC));
1384 switch((int)RAND_RANGE(0,4)) {
1399 for (i = 0 ; i < countof(ictypes) ; i++) {
1400 if (ictypes[i].pins == pins) {
1406 if (n > countof(types)) abort();
1407 val = ictypes[types[random() % n]].val;
1408 str = malloc(strlen(val) + 1 + 4 + 1); /* add space for production date */
1409 sprintf(str, "%s\n%02d%02d", val, (int)RAND_RANGE(80, 100), (int)RAND_RANGE(1,53));
1410 tn = fonttexturealloc(str, texfg, texbg);
1413 fprintf(stderr, "Error allocating font texture for '%s'\n", val);
1415 c->tw = tn->w; c->th = tn->h;
1428 l = malloc(sizeof(LED));
1431 if (!light && (f_rand() < 0.4)) {
1436 l->r = 0.9; l->g = 0; l->b = 0;
1437 } else if (r < 0.4) {
1438 l->r = 0.3; l->g = 0.9; l->b = 0;
1439 } else if (r < 0.6) {
1440 l->r = 0.8; l->g = 0.9; l->b = 0;
1441 } else if (r < 0.8) {
1442 l->r = 0.0; l->g = 0.2; l->b = 0.8;
1444 l->r = 0.9, l->g = 0.55, l->b = 0;
1453 f = malloc(sizeof(Fuse));
1457 Diode *NewDiode(void)
1462 ret = malloc(sizeof(Diode));
1463 b = malloc(sizeof(Band));
1466 if (f_rand() < 0.5) {
1470 ret->r = 0.7; ret->g = 0.1 ; ret->b = 0.1;
1475 ret->r = 0.2; ret->g = 0.2 ; ret->b = 0.2;
1482 Resistor * NewResistor(void)
1484 int v, m, t; /* value, multiplier, tolerance */
1489 t = (RAND(10) < 5) ? 10 : 11;
1490 ret = malloc(sizeof(Resistor));
1493 ret->b[0] = ret->b[1] = ret->b[2] = 7;
1495 ret->b[0] = values[v][0];
1496 ret->b[1] = values[v][1];
1504 void makebandlist(void)
1507 GLfloat col[] = {0,0,0,0};
1508 GLfloat spec[] = {0.8,0.8,0.8,0};
1511 for (i = 0 ; i < 12 ; i++) {
1512 band_list[i] = glGenLists(i);
1513 glNewList(band_list[i], GL_COMPILE);
1514 col[0] = colorcodes[i][0];
1515 col[1] = colorcodes[i][1];
1516 col[2] = colorcodes[i][2];
1517 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
1518 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
1519 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shine);
1520 createCylinder(0.1, 0.42, 0, 0);
1526 void bandedCylinder(float radius, float l, GLfloat r, GLfloat g, GLfloat bl,
1527 Band **b, int nbands)
1529 int n; /* band number */
1530 int p = 0; /* prev number + 1; */
1531 GLfloat col[] = {0,0,0,0};
1533 col[0] = r; col[1] = g; col[2] = bl;
1534 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1535 createCylinder(l, radius, 1, 0); /* body */
1536 for (n = 0 ; n < nbands ; n++) {
1538 glTranslatef(b[n]->pos*l, 0, 0);
1539 col[0] = b[n]->r; col[1] = b[n]->g; col[2] = b[n]->b;
1540 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, col);
1541 createCylinder(b[n]->len*l, radius*1.05, 0, 0); /* band */
1550 static GLfloat col[] = {0, 0.25, 0.05};
1551 static GLfloat col2[] = {0, 0.125, 0.05};
1552 GLfloat col3[] = {0, 0.8, 0};
1553 static GLfloat sx, sy; /* bright spot co-ords */
1554 static int sdir; /* 0 = left-right, 1 = right-left, 2 = up->dn, 3 = dn->up */
1555 static int s = 0; /* if spot is enabled */
1556 static float ds; /* speed of spot */
1559 if (f_rand() < ((rotate) ? 0.05 : 0.01)) {
1560 sdir = RAND_RANGE(0, 4);
1561 ds = RAND_RANGE(0.4, 0.8);
1565 sy = ((int)RAND_RANGE(0, YMAX/2))*2 - YMAX/2;
1569 sy = ((int)RAND_RANGE(0, YMAX/2))*2 - YMAX/2;
1573 sx = ((int)RAND_RANGE(0, XMAX/2))*2 - XMAX/2;
1577 sx = ((int)RAND_RANGE(0, XMAX/2))*2 - XMAX/2;
1582 } else if (!rotate) {
1583 if (col[1] < 0.25) {
1584 col[1] += 0.025; col[2] += 0.005;
1585 col2[1] += 0.015 ; col2[2] += 0.005;
1589 glDisable(GL_LIGHTING);
1593 glTranslatef(sx, sy, -10);
1594 sphere(0.1, 10, 10, 0, 10, 0, 10);
1596 glTranslatef(-ds, 0, 0);
1598 glTranslatef(ds, 0, 0);
1600 glTranslatef(0, ds, 0);
1602 glTranslatef(0, -ds, 0);
1603 sphere(0.05, 10, 10, 0, 10, 0, 10);
1625 } else if (!rotate) {
1627 col[1] -= 0.0025; col[2] -= 0.0005;
1628 col2[1] -= 0.0015 ; col2[2] -= 0.0005;
1631 for (x = -XMAX/2 ; x <= XMAX/2 ; x+= 2) {
1634 glVertex3f(x, YMAX/2, -10);
1635 glVertex3f(x, -YMAX/2, -10);
1637 glVertex3f(x-0.02, YMAX/2, -10);
1638 glVertex3f(x-0.02, -YMAX/2, -10);
1639 glVertex3f(x+0.02, YMAX/2, -10);
1640 glVertex3f(x+0.02, -YMAX/2, -10);
1643 for (y = -YMAX/2 ; y <= YMAX/2 ; y+= 2) {
1646 glVertex3f(-XMAX/2, y, -10);
1647 glVertex3f(XMAX/2, y, -10);
1649 glVertex3f(-XMAX/2, y-0.02, -10);
1650 glVertex3f(XMAX/2, y-0.02, -10);
1651 glVertex3f(-XMAX/2, y+0.02, -10);
1652 glVertex3f(XMAX/2, y+0.02, -10);
1655 glEnable(GL_LIGHTING);
1660 static Component *c[MAX_COMPONENTS];
1662 GLfloat light_sp[] = {0.8, 0.8, 0.8, 1.0};
1663 GLfloat black[] = {0, 0, 0, 1.0};
1664 static GLfloat rotate_angle = 0; /* when 'rotate' is enabled */
1668 for (i = 0 ; i < maxparts ; i++) {
1672 glEnable(GL_LIGHTING);
1673 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1675 gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
1678 glRotatef(rotate_angle, 0, 0, 1);
1679 rotate_angle += 0.01 * (float)rotatespeed;
1680 if (rotate_angle >= 360) rotate_angle = 0;
1682 glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
1683 glLightfv(GL_LIGHT0, GL_SPECULAR, light_sp);
1684 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_sp);
1685 glLighti(GL_LIGHT0, GL_CONSTANT_ATTENUATION, (GLfloat)1);
1686 glLighti(GL_LIGHT0, GL_LINEAR_ATTENUATION, (GLfloat)0.5);
1687 glLighti(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, (GLfloat)0);
1689 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, light_sp);
1690 if (f_rand() < 0.05) {
1691 for (j = 0 ; j < maxparts ; j++) {
1693 c[j] = NewComponent();
1699 for (j = 0 ; j < maxparts ; j++) {
1700 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, black);
1701 glMaterialfv(GL_FRONT, GL_EMISSION, black);
1702 glMaterialfv(GL_FRONT, GL_SPECULAR, black);
1704 if (DrawComponent(c[j])) {
1705 free(c[j]); c[j] = NULL;
1713 TexNum * fonttexturealloc (const char *str, float *fg, float *bg)
1715 static char *strings[50]; /* max of 40 textures */
1716 static int w[50], h[50];
1724 for (i = 1 ; i < 50 ; i++) {
1730 for (i = 1 ; i < 50 ; i++) {
1731 if (strings[i] && !strcmp(str, strings[i])) { /* if one matches */
1732 t = malloc(sizeof(TexNum));
1733 t->w = w[i]; t->h = h[i];
1738 /* at this point we need to make the new texture */
1739 ximage = text_to_ximage (modeinfo->xgwa.screen,
1740 modeinfo->xgwa.visual,
1743 for (i = 1 ; strings[i] != NULL ; i++); /* set i to the next unused value */
1744 glBindTexture(GL_TEXTURE_2D, i);
1745 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1746 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1747 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1750 status = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, ximage->width, ximage->height,
1751 GL_RGBA, GL_UNSIGNED_BYTE, ximage->data);
1754 const char *s = gluErrorString (status);
1755 fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
1756 progname, ximage->width, ximage->height,
1757 (s ? s : "(unknown)"));
1760 check_gl_error("mipmapping");
1762 t = malloc(sizeof(TexNum));
1763 t->w = ximage->width;
1764 t->h = ximage->height;
1765 w[i] = t->w; h[i] = t->h;
1769 c = malloc(strlen(str)+1);
1770 strncpy(c, str, strlen(str)+1);
1776 /* ensure transparent components are at the end */
1777 void reorder(Component *c[])
1780 Component *c1[MAX_COMPONENTS];
1781 Component *c2[MAX_COMPONENTS];
1784 for (i = 0 ; i < maxparts ; i++) { /* clear old matrix */
1788 for (i = 0 ; i < maxparts ; i++) {
1789 if (c[i] == NULL) continue;
1790 if (c[i]->alpha) { /* transparent parts go to c1 */
1793 } else { /* opaque parts go to c2 */
1797 for (i = 0 ; i < maxparts ; i++) { /* clear old matrix */
1801 for (i = 0 ; i < maxparts ; i++) { /* insert opaque part */
1802 if (c2[i] != NULL) {
1807 for (i = 0 ; i < j ; i++) { /* insert transparent parts */
1813 void reshape_circuit(ModeInfo *mi, int width, int height)
1815 GLfloat h = (GLfloat) height / (GLfloat) width;
1816 glViewport(0,0,(GLint)width, (GLint) height);
1817 glMatrixMode(GL_PROJECTION);
1819 glFrustum(-1.0,1.0,-h,h,1.5,35.0);
1820 glMatrixMode(GL_MODELVIEW);
1821 win_h = height; win_w = width;
1826 void init_circuit(ModeInfo *mi)
1828 int screen = MI_SCREEN(mi);
1831 if (circuit == NULL) {
1832 if ((circuit = (Circuit *) calloc(MI_NUM_SCREENS(mi),
1833 sizeof(Circuit))) == NULL)
1836 c = &circuit[screen];
1837 c->window = MI_WINDOW(mi);
1840 if ((c->glx_context = init_GL(mi)) != NULL) {
1841 reshape_circuit(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1847 glClearColor(0.0,0.0,0.0,0.0);
1848 glShadeModel(GL_SMOOTH);
1849 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
1850 glEnable(GL_DEPTH_TEST);
1851 glEnable(GL_LIGHTING);
1852 glEnable(GL_LIGHT0);
1853 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1859 void draw_circuit(ModeInfo *mi)
1861 Circuit *c = &circuit[MI_SCREEN(mi)];
1862 Window w = MI_WINDOW(mi);
1863 Display *disp = MI_DISPLAY(mi);
1865 if (!c->glx_context)
1869 glXMakeCurrent(disp, w, *(c->glx_context));
1873 if(mi->fps_p) do_fps(mi);
1875 glXSwapBuffers(disp, w);
1878 void release_circuit(ModeInfo *mi)
1880 if (circuit != NULL) {
1881 (void) free((void *) circuit);