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