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