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 release_glschool (0)
20 #define glschool_handle_event (xlockmore_no_events)
21
22 #undef countof
23 #define countof(x) (sizeof((x))/sizeof((*x)))
24
25 #define DEF_NFISH "100"
26 #define DEF_FOG "False"
27 #define DEF_DRAWBBOX "True"
28 #define DEF_DRAWGOAL "False"
29 #define DEF_GOALCHGF "50"
30 #define DEF_MAXVEL "7.0"
31 #define DEF_MINVEL "1.0"
32 #define DEF_ACCLIMIT "8.0"
33 #define DEF_DISTEXP "2.2"
34 #define DEF_AVOIDFACT "1.5"
35 #define DEF_MATCHFACT "0.15"
36 #define DEF_CENTERFACT "0.1"
37 #define DEF_TARGETFACT "80"
38 #define DEF_MINRADIUS "30.0"
39 #define DEF_MOMENTUM "0.9"
40 #define DEF_DISTCOMP "10.0"
41
42 static int NFish;
43 static Bool DoFog;
44 static Bool DoDrawBBox;
45 static Bool DoDrawGoal;
46 static int GoalChgFreq;
47 static float MinVel;
48 static float MaxVel;
49 static float DistExp;
50 static float AccLimit;
51 static float AvoidFact;
52 static float MatchFact;
53 static float TargetFact;
54 static float CenterFact;
55 static float MinRadius;
56 static float Momentum;
57 static float DistComp;
58
59 static XrmOptionDescRec opts[] = {
60 { "-nfish", ".nfish", XrmoptionSepArg, 0 },
61 { "-fog", ".fog", XrmoptionNoArg, "True" },
62 { "+fog", ".fog", XrmoptionNoArg, "False" },
63 { "-drawgoal", ".drawgoal", XrmoptionNoArg, "True" },
64 { "+drawgoal", ".drawgoal", XrmoptionNoArg, "False" },
65 { "-drawbbox", ".drawbbox", XrmoptionNoArg, "True" },
66 { "+drawbbox", ".drawbbox", XrmoptionNoArg, "False" },
67 { "-goalchgf", ".goalchgf", XrmoptionSepArg, 0 },
68 { "-maxvel", ".maxvel", XrmoptionSepArg, 0 },
69 { "-minvel", ".minvel", XrmoptionSepArg, 0 },
70 { "-acclimit", ".acclimit", XrmoptionSepArg, 0 },
71 { "-distexp", ".distexp", XrmoptionSepArg, 0 },
72 { "-avoidfact", ".avoidfact", XrmoptionSepArg, 0 },
73 { "-matchfact", ".matchfact", XrmoptionSepArg, 0 },
74 { "-centerfact",".centerfact", XrmoptionSepArg, 0 },
75 { "-targetfact",".targetfact", XrmoptionSepArg, 0 },
76 { "-minradius", ".minradius", XrmoptionSepArg, 0 },
77 { "-distcomp", ".distcomp", XrmoptionSepArg, 0 },
78 { "-momentum", ".momentum", XrmoptionSepArg, 0 },
79 };
80
81 static argtype vars[] = {
82 {&NFish, "nfish", "NFish", DEF_NFISH, t_Int},
83 {&DoFog, "fog", "DoFog", DEF_FOG, t_Bool},
84 {&DoDrawBBox, "drawbbox", "DoDrawBBox", DEF_DRAWBBOX, t_Bool},
85 {&DoDrawGoal, "drawgoal", "DoDrawGoal", DEF_DRAWGOAL, t_Bool},
86 {&GoalChgFreq, "goalchgf", "GoalChgFreq", DEF_GOALCHGF, t_Int},
87 {&MaxVel, "maxvel", "MaxVel", DEF_MAXVEL, t_Float},
88 {&MinVel, "minvel", "MinVel", DEF_MINVEL, t_Float},
89 {&AccLimit, "acclimit", "AccLimit", DEF_ACCLIMIT, t_Float},
90 {&DistExp, "distexp", "DistExp", DEF_DISTEXP, t_Float},
91 {&AvoidFact, "avoidfact", "AvoidFact", DEF_AVOIDFACT, t_Float},
92 {&MatchFact, "matchfact", "MatchFact", DEF_MATCHFACT, t_Float},
93 {&CenterFact, "centerfact", "CenterFact", DEF_CENTERFACT, t_Float},
94 {&TargetFact, "targetfact", "TargetFact", DEF_TARGETFACT, t_Float},
95 {&MinRadius, "minradius", "MinRadius", DEF_MINRADIUS, t_Float},
96 {&Momentum, "momentum", "Momentum", DEF_MOMENTUM, t_Float},
97 {&DistComp, "distcomp", "DistComp", DEF_DISTCOMP, t_Float},
98 };
99
100 ENTRYPOINT ModeSpecOpt glschool_opts = {countof(opts), opts, countof(vars), vars, NULL};
101
102 typedef struct {
103 int nColors;
104 int rotCounter;
105 int goalCounter;
106 Bool drawGoal;
107 Bool drawBBox;
108 GLuint bboxList;
109 GLuint goalList;
110 GLuint fishList;
111 int fish_polys, box_polys;
112 XColor *colors;
113 School *school;
114 GLXContext *context;
115 } glschool_configuration;
116
117 static glschool_configuration *scs = NULL;
118
119 ENTRYPOINT void
reshape_glschool(ModeInfo * mi,int width,int height)120 reshape_glschool(ModeInfo *mi, int width, int height)
121 {
122 Bool wire = MI_IS_WIREFRAME(mi);
123 double aspect = (double)width/(double)height;
124 glschool_configuration *sc = &scs[MI_SCREEN(mi)];
125
126 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *sc->context);
127 if (sc->school != (School *)0) {
128 glschool_setBBox(sc->school, -aspect*160, aspect*160, -130, 130, -450, -50.0);
129 glDeleteLists(sc->bboxList, 1);
130 glschool_createBBoxList(&SCHOOL_BBOX(sc->school),
131 &sc->bboxList, wire);
132 }
133 glschool_reshape(width, height);
134 }
135
136 ENTRYPOINT void
init_glschool(ModeInfo * mi)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 MI_INIT (mi, scs);
145 sc = &scs[MI_SCREEN(mi)];
146
147 sc->drawGoal = DoDrawGoal;
148 sc->drawBBox = DoDrawBBox;
149
150 sc->nColors = 360;
151 sc->context = init_GL(mi);
152 sc->colors = (XColor *)calloc(sc->nColors, sizeof(XColor));
153 make_color_ramp(0, 0, 0,
154 0.0, 1.0, 1.0,
155 359.0, 1.0, 1.0,
156 sc->colors, &sc->nColors,
157 False, 0, False);
158
159 sc->school = glschool_initSchool(NFish, AccLimit, MaxVel, MinVel, DistExp, Momentum,
160 MinRadius, AvoidFact, MatchFact, CenterFact, TargetFact,
161 DistComp);
162 if (sc->school == (School *)0) {
163 fprintf(stderr, "couldn't initialize TheSchool, exiting\n");
164 exit(1);
165 }
166
167 reshape_glschool(mi, width, height);
168
169 glschool_initGLEnv(DoFog);
170 glschool_initFishes(sc->school);
171 glschool_createDrawLists(&SCHOOL_BBOX(sc->school),
172 &sc->bboxList, &sc->goalList, &sc->fishList,
173 &sc->fish_polys, &sc->box_polys, wire);
174 glschool_computeAccelerations(sc->school);
175 }
176
177 ENTRYPOINT void
draw_glschool(ModeInfo * mi)178 draw_glschool(ModeInfo *mi)
179 {
180 Window window = MI_WINDOW(mi);
181 Display *dpy = MI_DISPLAY(mi);
182 glschool_configuration *sc = &scs[MI_SCREEN(mi)];
183
184 if (!sc->context) {
185 fprintf(stderr, "no context\n");
186 return;
187 }
188
189 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *sc->context);
190
191 mi->polygon_count = 0;
192
193 if ((sc->goalCounter % GoalChgFreq) == 0)
194 glschool_newGoal(sc->school);
195 sc->goalCounter++;
196
197 sc->rotCounter++;
198 sc->rotCounter = (sc->rotCounter%360);
199
200 glschool_applyMovements(sc->school);
201 glschool_drawSchool(sc->colors, sc->school, sc->bboxList,
202 sc->goalList, sc->fishList, sc->rotCounter,
203 sc->drawGoal, sc->drawBBox,
204 sc->fish_polys, sc->box_polys,
205 &mi->polygon_count);
206 glschool_computeAccelerations(sc->school);
207
208 if (mi->fps_p)
209 do_fps(mi);
210
211 glFinish();
212 glXSwapBuffers(dpy, window);
213 }
214
215
216 ENTRYPOINT void
free_glschool(ModeInfo * mi)217 free_glschool(ModeInfo *mi)
218 {
219 glschool_configuration *sc = &scs[MI_SCREEN(mi)];
220
221 if (!sc->context) return;
222 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *sc->context);
223
224 if (sc->school) glschool_freeSchool (sc->school);
225 if (sc->colors) free (sc->colors);
226 if (glIsList(sc->bboxList)) glDeleteLists(sc->bboxList, 1);
227 if (glIsList(sc->goalList)) glDeleteLists(sc->goalList, 1);
228 if (glIsList(sc->fishList)) glDeleteLists(sc->fishList, 1);
229 }
230
231 XSCREENSAVER_MODULE("GLSchool", glschool)
232