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