From http://www.jwz.org/xscreensaver/xscreensaver-5.22.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                 glschool_setBBox(sc->school, -aspect*160, aspect*160, -130, 130, -450, -50.0);
130                 glDeleteLists(sc->bboxList, 1);
131                 glschool_createBBoxList(&SCHOOL_BBOX(sc->school),
132                                         &sc->bboxList, wire);
133         }
134         glschool_reshape(width, height);
135 }
136
137 ENTRYPOINT void
138 init_glschool(ModeInfo *mi)
139 {
140         int                                             width = MI_WIDTH(mi);
141         int                                             height = MI_HEIGHT(mi);
142         Bool                                    wire = MI_IS_WIREFRAME(mi);
143         glschool_configuration  *sc;
144
145         if (!scs) {
146                 scs = (glschool_configuration *)calloc(MI_NUM_SCREENS(mi), sizeof(glschool_configuration));
147                 if (!scs) {
148                         perror("init_glschool: ");
149                         exit(1);
150                 }
151         }
152         sc = &scs[MI_SCREEN(mi)];
153
154         sc->drawGoal = DoDrawGoal;
155         sc->drawBBox = DoDrawBBox;
156
157         sc->nColors = 360;
158         sc->context = init_GL(mi);
159         sc->colors = (XColor *)calloc(sc->nColors, sizeof(XColor));
160         make_color_ramp(0, 0, 0,
161                                         0.0, 1.0, 1.0,
162                                         359.0, 1.0, 1.0,
163                                         sc->colors, &sc->nColors,
164                                         False, 0, False);
165
166         sc->school = glschool_initSchool(NFish, AccLimit, MaxVel, MinVel, DistExp, Momentum,
167                                                         MinRadius, AvoidFact, MatchFact, CenterFact, TargetFact,
168                                                         DistComp);
169         if (sc->school == (School *)0) {
170                 fprintf(stderr, "couldn't initialize TheSchool, exiting\n");
171                 exit(1);
172         }
173
174         reshape_glschool(mi, width, height);
175
176         glschool_initGLEnv(DoFog);
177         glschool_initFishes(sc->school);
178         glschool_createDrawLists(&SCHOOL_BBOX(sc->school), 
179                                  &sc->bboxList, &sc->goalList, &sc->fishList,
180                                  &sc->fish_polys, &sc->box_polys, wire);
181         glschool_computeAccelerations(sc->school);
182 }
183
184 ENTRYPOINT void
185 draw_glschool(ModeInfo *mi)
186 {
187         Window                                  window = MI_WINDOW(mi);
188         Display                                 *dpy = MI_DISPLAY(mi);
189         glschool_configuration  *sc = &scs[MI_SCREEN(mi)];
190
191         if (!sc->context) {
192                 fprintf(stderr, "no context\n");
193                 return;
194         }
195
196         glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sc->context));
197
198         mi->polygon_count = 0;
199
200         if ((sc->goalCounter % GoalChgFreq) == 0)
201                 glschool_newGoal(sc->school);
202         sc->goalCounter++;
203
204         sc->rotCounter++;
205         sc->rotCounter = (sc->rotCounter%360);
206
207         glschool_applyMovements(sc->school);
208         glschool_drawSchool(sc->colors, sc->school, sc->bboxList, 
209                             sc->goalList, sc->fishList, sc->rotCounter, 
210                               sc->drawGoal, sc->drawBBox, 
211                             sc->fish_polys, sc->box_polys,
212                             &mi->polygon_count);
213         glschool_computeAccelerations(sc->school);
214
215         if (mi->fps_p)
216                 do_fps(mi);
217
218         glFinish();
219         glXSwapBuffers(dpy, window);
220 }
221
222 XSCREENSAVER_MODULE("GLSchool", glschool)