1 /*
2 * Tux Racer
3 * Copyright (C) 1999-2001 Jasmin F. Patry
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include "tuxracer.h"
21 #include "lights.h"
22 #include "gl_util.h"
23 #include "tcl_util.h"
24
25 static light_t course_lights[NUM_COURSE_LIGHTS];
26
get_course_lights()27 light_t* get_course_lights() {
28 return course_lights;
29 }
30
31
reset_lights()32 void reset_lights()
33 {
34 int i;
35 GLfloat black[] = { 0., 0., 0., 1. };
36 for (i=0; i<NUM_COURSE_LIGHTS; i++) {
37 /* Note: we initialize the lights to default OpenGL values
38 EXCEPT that light 0 isn't treated differently than the
39 others */
40 course_lights[i].is_on = False;
41 init_glfloat_array( 4, course_lights[i].ambient, 0., 0., 0., 1. );
42 init_glfloat_array( 4, course_lights[i].diffuse, 0., 0., 0., 1. );
43 init_glfloat_array( 4, course_lights[i].specular, 0., 0., 0., 1. );
44 init_glfloat_array( 4, course_lights[i].position, 0., 0., 1., 0. );
45 init_glfloat_array( 3, course_lights[i].spot_direction, 0., 0., -1. );
46 course_lights[i].spot_exponent = 0.0;
47 course_lights[i].spot_cutoff = 180.0;
48 course_lights[i].constant_attenuation = 1.0;
49 course_lights[i].linear_attenuation = 0.0;
50 course_lights[i].quadratic_attenuation = 0.0;
51 }
52
53 /* Turn off global ambient light */
54 glLightModelfv( GL_LIGHT_MODEL_AMBIENT, black );
55 }
56
setup_course_lighting()57 void setup_course_lighting()
58 {
59 int i;
60 light_t *course_lights;
61
62 course_lights = get_course_lights();
63
64 for (i=0; i<NUM_COURSE_LIGHTS; i++) {
65 if ( ! course_lights[i].is_on ) {
66 glDisable( GL_LIGHT0 + i );
67 continue;
68 }
69 glEnable( GL_LIGHT0 + i );
70
71 glLightfv( GL_LIGHT0 + i, GL_AMBIENT, course_lights[i].ambient );
72 glLightfv( GL_LIGHT0 + i, GL_DIFFUSE, course_lights[i].diffuse );
73 glLightfv( GL_LIGHT0 + i, GL_SPECULAR, course_lights[i].specular );
74 glLightfv( GL_LIGHT0 + i, GL_POSITION, course_lights[i].position );
75 glLightfv( GL_LIGHT0 + i, GL_SPOT_DIRECTION,
76 course_lights[i].spot_direction );
77 glLightf( GL_LIGHT0 + i, GL_SPOT_EXPONENT,
78 course_lights[i].spot_exponent );
79 glLightf( GL_LIGHT0 + i, GL_SPOT_CUTOFF,
80 course_lights[i].spot_cutoff );
81 glLightf( GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION,
82 course_lights[i].constant_attenuation );
83 glLightf( GL_LIGHT0 + i, GL_LINEAR_ATTENUATION,
84 course_lights[i].linear_attenuation );
85 glLightf( GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION,
86 course_lights[i].quadratic_attenuation );
87 }
88 }
89
course_light_cb(ClientData cd,Tcl_Interp * ip,int argc,char ** argv)90 static int course_light_cb (ClientData cd, Tcl_Interp *ip,
91 int argc, char **argv)
92 {
93 int light_num;
94 scalar_t tmp_arr[4];
95 double tmp_dbl;
96 bool_t error = False;
97
98 if (argc < 3) {
99 error = True;
100 }
101
102 NEXT_ARG;
103
104 if ( Tcl_GetInt( ip, *argv, &light_num ) == TCL_ERROR ) {
105 error = True;
106 }
107
108 if ( light_num < 0 || light_num >= NUM_COURSE_LIGHTS ) {
109 error = True;
110 }
111
112 NEXT_ARG;
113
114 while ( !error && argc > 0 ) {
115 if ( strcmp( "-on", *argv ) == 0 ) {
116 course_lights[light_num].is_on = True;
117 } else if ( strcmp( "-off", *argv ) == 0 ) {
118 course_lights[light_num].is_on = False;
119 } else if ( strcmp( "-ambient", *argv ) == 0 ) {
120 NEXT_ARG;
121 if ( argc == 0 ) {
122 error = True;
123 break;
124 }
125 if ( get_tcl_tuple ( ip, *argv, tmp_arr, 4 ) == TCL_ERROR ) {
126 error = True;
127 break;
128 }
129 copy_to_glfloat_array( course_lights[light_num].ambient,
130 tmp_arr, 4 );
131 } else if ( strcmp( "-diffuse", *argv ) == 0 ) {
132 NEXT_ARG;
133 if ( argc == 0 ) {
134 error = True;
135 break;
136 }
137 if ( get_tcl_tuple ( ip, *argv, tmp_arr, 4 ) == TCL_ERROR ) {
138 error = True;
139 break;
140 }
141 copy_to_glfloat_array( course_lights[light_num].diffuse,
142 tmp_arr, 4 );
143 } else if ( strcmp( "-specular", *argv ) == 0 ) {
144 NEXT_ARG;
145 if ( argc == 0 ) {
146 error = True;
147 break;
148 }
149 if ( get_tcl_tuple ( ip, *argv, tmp_arr, 4 ) == TCL_ERROR ) {
150 error = True;
151 break;
152 }
153 copy_to_glfloat_array( course_lights[light_num].specular,
154 tmp_arr, 4 );
155 } else if ( strcmp( "-position", *argv ) == 0 ) {
156 NEXT_ARG;
157 if ( argc == 0 ) {
158 error = True;
159 break;
160 }
161 if ( get_tcl_tuple ( ip, *argv, tmp_arr, 4 ) == TCL_ERROR ) {
162 error = True;
163 break;
164 }
165 copy_to_glfloat_array( course_lights[light_num].position,
166 tmp_arr, 4 );
167 } else if ( strcmp( "-spot_direction", *argv ) == 0 ) {
168 NEXT_ARG;
169 if ( argc == 0 ) {
170 error = True;
171 break;
172 }
173 if ( get_tcl_tuple ( ip, *argv, tmp_arr, 3 ) == TCL_ERROR ) {
174 error = True;
175 break;
176 }
177 copy_to_glfloat_array( course_lights[light_num].spot_direction,
178 tmp_arr, 3 );
179 } else if ( strcmp( "-spot_exponent", *argv ) == 0 ) {
180 NEXT_ARG;
181 if ( argc == 0 ) {
182 error = True;
183 break;
184 }
185 if ( Tcl_GetDouble ( ip, *argv, &tmp_dbl ) == TCL_ERROR ) {
186 error = True;
187 break;
188 }
189 course_lights[light_num].spot_exponent = tmp_dbl;
190 } else if ( strcmp( "-spot_cutoff", *argv ) == 0 ) {
191 NEXT_ARG;
192 if ( argc == 0 ) {
193 error = True;
194 break;
195 }
196 if ( Tcl_GetDouble ( ip, *argv, &tmp_dbl ) == TCL_ERROR ) {
197 error = True;
198 break;
199 }
200 course_lights[light_num].spot_cutoff = tmp_dbl;
201 } else if ( strcmp( "-constant_attenuation", *argv ) == 0 ) {
202 NEXT_ARG;
203 if ( argc == 0 ) {
204 error = True;
205 break;
206 }
207 if ( Tcl_GetDouble ( ip, *argv, &tmp_dbl ) == TCL_ERROR ) {
208 error = True;
209 break;
210 }
211 course_lights[light_num].constant_attenuation = tmp_dbl;
212 } else if ( strcmp( "-linear_attenuation", *argv ) == 0 ) {
213 NEXT_ARG;
214 if ( argc == 0 ) {
215 error = True;
216 break;
217 }
218 if ( Tcl_GetDouble ( ip, *argv, &tmp_dbl ) == TCL_ERROR ) {
219 error = True;
220 break;
221 }
222 course_lights[light_num].linear_attenuation = tmp_dbl;
223 } else if ( strcmp( "-quadratic_attenuation", *argv ) == 0 ) {
224 NEXT_ARG;
225 if ( argc == 0 ) {
226 error = True;
227 break;
228 }
229 if ( Tcl_GetDouble ( ip, *argv, &tmp_dbl ) == TCL_ERROR ) {
230 error = True;
231 break;
232 }
233 course_lights[light_num].quadratic_attenuation = tmp_dbl;
234 } else {
235 print_warning( TCL_WARNING, "tux_course_light: unrecognized "
236 "parameter `%s'", *argv );
237 }
238
239 NEXT_ARG;
240 }
241
242 if ( error ) {
243 print_warning( TCL_WARNING, "error in call to tux_course_light" );
244 Tcl_AppendResult(
245 ip,
246 "\nUsage: tux_course_light <light_number> [-on|-off] "
247 "[-ambient { r g b a }] "
248 "[-diffuse { r g b a }] "
249 "[-specular { r g b a }] "
250 "[-position { x y z w }] "
251 "[-spot_direction { x y z }] "
252 "[-spot_exponent <value>] "
253 "[-spot_cutoff <value>] "
254 "[-constant_attenuation <value>] "
255 "[-linear_attenuation <value>] "
256 "[-quadratic_attenuation <value>] ",
257 (char *) 0 );
258 return TCL_ERROR;
259 }
260
261 return TCL_OK;
262 }
263
register_course_light_callbacks(Tcl_Interp * ip)264 void register_course_light_callbacks( Tcl_Interp *ip )
265 {
266 Tcl_CreateCommand (ip, "tux_course_light", course_light_cb, 0,0);
267 }
268