From http://www.jwz.org/xscreensaver/xscreensaver-5.16.tar.gz
[xscreensaver] / hacks / glx / glschool.c
1 /* glschool.c, Copyright (c) 2005-2006 David C. Lambert <dcl@panix.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11 #include "xlockmore.h"
12 #include "glschool.h"
13
14 #define sws_opts                        xlockmore_opts
15 #define DEFAULTS    "*delay:            20000       \n" \
16                     "*showFPS:      False       \n" \
17                     "*wireframe:    False       \n" \
18
19 #define refresh_glschool                (0)
20 #define release_glschool                (0)
21 #define glschool_handle_event   (0)
22
23 #undef countof
24 #define countof(x) (sizeof((x))/sizeof((*x)))
25
26 #define DEF_NFISH       "100"
27 #define DEF_FOG         "False"
28 #define DEF_DRAWBBOX    "True"
29 #define DEF_DRAWGOAL    "False"
30 #define DEF_GOALCHGF    "50"
31 #define DEF_MAXVEL      "7.0"
32 #define DEF_MINVEL      "1.0"
33 #define DEF_ACCLIMIT    "8.0"
34 #define DEF_DISTEXP     "2.2"
35 #define DEF_AVOIDFACT   "1.5"
36 #define DEF_MATCHFACT   "0.15"
37 #define DEF_CENTERFACT  "0.1"
38 #define DEF_TARGETFACT  "80"
39 #define DEF_MINRADIUS   "30.0"
40 #define DEF_MOMENTUM    "0.9"
41 #define DEF_DISTCOMP    "10.0"
42
43 static int                      NFish;
44 static Bool                     DoFog;
45 static Bool                     DoDrawBBox;
46 static Bool                     DoDrawGoal;
47 static int                      GoalChgFreq;
48 static float            MinVel;
49 static float            MaxVel;
50 static float            DistExp;
51 static float            AccLimit;
52 static float            AvoidFact;
53 static float            MatchFact;
54 static float            TargetFact;
55 static float            CenterFact;
56 static float            MinRadius;
57 static float            Momentum;
58 static float            DistComp;
59
60 static XrmOptionDescRec opts[] = {
61         { "-nfish",             ".nfish",               XrmoptionSepArg, 0 },
62         { "-fog",               ".fog",                 XrmoptionNoArg, "True" },
63         { "+fog",               ".fog",                 XrmoptionNoArg, "False" },
64         { "-drawgoal",  ".drawgoal",    XrmoptionNoArg, "True" },
65         { "+drawgoal",  ".drawgoal",    XrmoptionNoArg, "False" },
66         { "-drawbbox",  ".drawbbox",    XrmoptionNoArg, "True" },
67         { "+drawbbox",  ".drawbbox",    XrmoptionNoArg, "False" },
68         { "-goalchgf",  ".goalchgf",    XrmoptionSepArg, 0 },
69         { "-maxvel",    ".maxvel",              XrmoptionSepArg, 0 },
70         { "-minvel",    ".minvel",              XrmoptionSepArg, 0 },
71         { "-acclimit",  ".acclimit",    XrmoptionSepArg, 0 },
72         { "-distexp",   ".distexp",             XrmoptionSepArg, 0 },
73         { "-avoidfact", ".avoidfact",   XrmoptionSepArg, 0 },
74         { "-matchfact", ".matchfact",   XrmoptionSepArg, 0 },
75         { "-centerfact",".centerfact",  XrmoptionSepArg, 0 },
76         { "-targetfact",".targetfact",  XrmoptionSepArg, 0 },
77         { "-minradius", ".minradius",   XrmoptionSepArg, 0 },
78         { "-distcomp",  ".distcomp",    XrmoptionSepArg, 0 },
79         { "-momentum",  ".momentum",    XrmoptionSepArg, 0 },
80 };
81
82 static argtype vars[] = {
83         {&NFish,                "nfish",                "NFish",                DEF_NFISH, t_Int},
84         {&DoFog,                "fog",                  "DoFog",                DEF_FOG, t_Bool},
85         {&DoDrawBBox,   "drawbbox",             "DoDrawBBox",   DEF_DRAWBBOX, t_Bool},
86         {&DoDrawGoal,   "drawgoal",             "DoDrawGoal",   DEF_DRAWGOAL, t_Bool},
87         {&GoalChgFreq,  "goalchgf",             "GoalChgFreq",  DEF_GOALCHGF,  t_Int},
88         {&MaxVel,               "maxvel",               "MaxVel",               DEF_MAXVEL,  t_Float},
89         {&MinVel,               "minvel",               "MinVel",               DEF_MINVEL,     t_Float},
90         {&AccLimit,             "acclimit",             "AccLimit",             DEF_ACCLIMIT,  t_Float},
91         {&DistExp,              "distexp",              "DistExp",              DEF_DISTEXP,  t_Float},
92         {&AvoidFact,    "avoidfact",    "AvoidFact",    DEF_AVOIDFACT,  t_Float},
93         {&MatchFact,    "matchfact",    "MatchFact",    DEF_MATCHFACT,  t_Float},
94         {&CenterFact,   "centerfact",   "CenterFact",   DEF_CENTERFACT,  t_Float},
95         {&TargetFact,   "targetfact",   "TargetFact",   DEF_TARGETFACT,  t_Float},
96         {&MinRadius,    "minradius",    "MinRadius",    DEF_MINRADIUS,  t_Float},
97         {&Momentum,             "momentum",             "Momentum",             DEF_MOMENTUM,  t_Float},
98         {&DistComp,             "distcomp",             "DistComp",             DEF_DISTCOMP,  t_Float},
99 };
100
101 ENTRYPOINT ModeSpecOpt glschool_opts = {countof(opts), opts, countof(vars), vars, NULL};
102
103 typedef struct {
104         int                     nColors;
105         int                     rotCounter;
106         int                     goalCounter;
107         Bool            drawGoal;
108         Bool            drawBBox;                       
109         GLuint          bboxList;
110         GLuint          goalList;
111         GLuint          fishList;
112         int             fish_polys, box_polys;
113         XColor          *colors;
114         School          *school;
115         GLXContext      *context;
116 } glschool_configuration;
117
118 static glschool_configuration   *scs = NULL;
119
120 ENTRYPOINT void
121 reshape_glschool(ModeInfo *mi, int width, int height)
122 {
123         Bool                                    wire = MI_IS_WIREFRAME(mi);
124         double                                  aspect = (double)width/(double)height;
125         glschool_configuration  *sc = &scs[MI_SCREEN(mi)];
126
127         glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sc->context));
128         if (sc->school != (School *)0) {
129                 setBBox(sc->school, -aspect*160, aspect*160, -130, 130, -450, -50.0);
130                 glDeleteLists(sc->bboxList, 1);
131                 createBBoxList(&SCHOOL_BBOX(sc->school), &sc->bboxList, wire);
132         }
133         reshape(width, height);
134 }
135
136 ENTRYPOINT void
137 init_glschool(ModeInfo *mi)
138 {
139         int                                             width = MI_WIDTH(mi);
140         int                                             height = MI_HEIGHT(mi);
141         Bool                                    wire = MI_IS_WIREFRAME(mi);
142         glschool_configuration  *sc;
143
144         if (!scs) {
145                 scs = (glschool_configuration *)calloc(MI_NUM_SCREENS(mi), sizeof(glschool_configuration));
146                 if (!scs) {
147                         perror("init_glschool: ");
148                         exit(1);
149                 }
150         }
151         sc = &scs[MI_SCREEN(mi)];
152
153         sc->drawGoal = DoDrawGoal;
154         sc->drawBBox = DoDrawBBox;
155
156         sc->nColors = 360;
157         sc->context = init_GL(mi);
158         sc->colors = (XColor *)calloc(sc->nColors, sizeof(XColor));
159         make_color_ramp(0, 0,
160                                         0.0, 1.0, 1.0,
161                                         359.0, 1.0, 1.0,
162                                         sc->colors, &sc->nColors,
163                                         False, 0, False);
164
165         sc->school = initSchool(NFish, AccLimit, MaxVel, MinVel, DistExp, Momentum,
166                                                         MinRadius, AvoidFact, MatchFact, CenterFact, TargetFact,
167                                                         DistComp);
168         if (sc->school == (School *)0) {
169                 fprintf(stderr, "couldn't initialize TheSchool, exiting\n");
170                 exit(1);
171         }
172
173         reshape_glschool(mi, width, height);
174
175         initGLEnv(DoFog);
176         initFishes(sc->school);
177         createDrawLists(&SCHOOL_BBOX(sc->school), &sc->bboxList, &sc->goalList, &sc->fishList,
178                         &sc->fish_polys, &sc->box_polys, wire);
179         computeAccelerations(sc->school);
180 }
181
182 ENTRYPOINT void
183 draw_glschool(ModeInfo *mi)
184 {
185         Window                                  window = MI_WINDOW(mi);
186         Display                                 *dpy = MI_DISPLAY(mi);
187         glschool_configuration  *sc = &scs[MI_SCREEN(mi)];
188
189         if (!sc->context) {
190                 fprintf(stderr, "no context\n");
191                 return;
192         }
193
194         glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sc->context));
195
196         mi->polygon_count = 0;
197
198         if ((sc->goalCounter % GoalChgFreq) == 0)
199                 newGoal(sc->school);
200         sc->goalCounter++;
201
202         sc->rotCounter++;
203         sc->rotCounter = (sc->rotCounter%360);
204
205         applyMovements(sc->school);
206         drawSchool(sc->colors, sc->school, sc->bboxList, sc->goalList, sc->fishList, sc->rotCounter, sc->drawGoal, sc->drawBBox, 
207                    sc->fish_polys, sc->box_polys,
208                    &mi->polygon_count);
209         computeAccelerations(sc->school);
210
211         if (mi->fps_p)
212                 do_fps(mi);
213
214         glFinish();
215         glXSwapBuffers(dpy, window);
216 }
217
218 XSCREENSAVER_MODULE("GLSchool", glschool)