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 "tux_shadow.h"
21 #include "gl_util.h"
22 #include "tux.h"
23 #include "hier.h"
24 #include "phys_sim.h"
25 #include "textures.h"
26
27 #define SHADOW_HEIGHT 0.1
28
29
30 /*
31 * Make the shadow darker if the stencil buffer is active
32 */
33 #ifdef USE_STENCIL_BUFFER
34
35 static colour_t shadow_colour = { 0.0, 0.0, 0.0, 0.3 };
36
37 #else
38
39 static colour_t shadow_colour = { 0.0, 0.0, 0.0, 0.1 };
40
41 #endif /* USE_STENCIL_BUFFER */
42
draw_tux_shadow()43 void draw_tux_shadow()
44 {
45 matrixgl_t model_matrix;
46 char *tux_root_node_name;
47 scene_node_t *tux_root_node;
48
49 if ( ! getparam_draw_tux_shadow() )
50 return;
51
52 set_gl_options( TUX_SHADOW );
53
54 glColor4f( shadow_colour.r, shadow_colour.g, shadow_colour.b,
55 shadow_colour.a );
56
57 make_identity_matrix( model_matrix );
58
59 tux_root_node_name = get_tux_root_node();
60
61 if ( get_scene_node( tux_root_node_name, &tux_root_node ) != TCL_OK ) {
62 check_assertion( 0, "couldn't find tux's root node" );
63 }
64
65 traverse_dag_for_shadow( tux_root_node, model_matrix );
66 }
67
traverse_dag_for_shadow(scene_node_t * node,matrixgl_t model_matrix)68 void traverse_dag_for_shadow( scene_node_t *node, matrixgl_t model_matrix )
69 {
70 matrixgl_t new_model_matrix;
71 scene_node_t *child;
72
73 check_assertion( node != NULL, "node is NULL" );
74
75 multiply_matrices(new_model_matrix, model_matrix, node->trans);
76
77 if ( node->geom == Sphere && node->render_shadow ) {
78 draw_shadow_sphere( new_model_matrix );
79 }
80
81 child = node->child;
82 while (child != NULL) {
83
84 traverse_dag_for_shadow(child, new_model_matrix);
85
86 child = child->next;
87 }
88 }
89
draw_shadow_sphere(matrixgl_t model_matrix)90 void draw_shadow_sphere( matrixgl_t model_matrix )
91 {
92 scalar_t theta, phi, d_theta, d_phi, eps, twopi;
93 scalar_t x, y, z;
94 int div = getparam_tux_shadow_sphere_divisions();
95
96 eps = 1e-15;
97 twopi = M_PI * 2.0;
98
99 d_theta = d_phi = M_PI / div;
100
101 for ( phi = 0.0; phi + eps < M_PI; phi += d_phi ) {
102 scalar_t cos_theta, sin_theta;
103 scalar_t sin_phi, cos_phi;
104 scalar_t sin_phi_d_phi, cos_phi_d_phi;
105
106 sin_phi = sin( phi );
107 cos_phi = cos( phi );
108 sin_phi_d_phi = sin( phi + d_phi );
109 cos_phi_d_phi = cos( phi + d_phi );
110
111 if ( phi <= eps ) {
112
113 glBegin( GL_TRIANGLE_FAN );
114 draw_shadow_vertex( 0., 0., 1., model_matrix );
115
116 for ( theta = 0.0; theta + eps < twopi; theta += d_theta ) {
117 sin_theta = sin( theta );
118 cos_theta = cos( theta );
119
120 x = cos_theta * sin_phi_d_phi;
121 y = sin_theta * sin_phi_d_phi;
122 z = cos_phi_d_phi;
123 draw_shadow_vertex( x, y, z, model_matrix );
124 }
125
126 x = sin_phi_d_phi;
127 y = 0.0;
128 z = cos_phi_d_phi;
129 draw_shadow_vertex( x, y, z, model_matrix );
130 glEnd();
131
132 } else if ( phi + d_phi + eps >= M_PI ) {
133
134 glBegin( GL_TRIANGLE_FAN );
135 draw_shadow_vertex( 0., 0., -1., model_matrix );
136
137 for ( theta = twopi; theta - eps > 0; theta -= d_theta ) {
138 sin_theta = sin( theta );
139 cos_theta = cos( theta );
140
141 x = cos_theta * sin_phi;
142 y = sin_theta * sin_phi;
143 z = cos_phi;
144 draw_shadow_vertex( x, y, z, model_matrix );
145 }
146 x = sin_phi;
147 y = 0.0;
148 z = cos_phi;
149 draw_shadow_vertex( x, y, z, model_matrix );
150 glEnd();
151
152 } else {
153
154 glBegin( GL_TRIANGLE_STRIP );
155
156 for ( theta = 0.0; theta + eps < twopi; theta += d_theta ) {
157 sin_theta = sin( theta );
158 cos_theta = cos( theta );
159
160 x = cos_theta * sin_phi;
161 y = sin_theta * sin_phi;
162 z = cos_phi;
163 draw_shadow_vertex( x, y, z, model_matrix );
164
165 x = cos_theta * sin_phi_d_phi;
166 y = sin_theta * sin_phi_d_phi;
167 z = cos_phi_d_phi;
168 draw_shadow_vertex( x, y, z, model_matrix );
169 }
170 x = sin_phi;
171 y = 0.0;
172 z = cos_phi;
173 draw_shadow_vertex( x, y, z, model_matrix );
174
175 x = sin_phi_d_phi;
176 y = 0.0;
177 z = cos_phi_d_phi;
178 draw_shadow_vertex( x, y, z, model_matrix );
179
180 glEnd();
181
182 }
183 }
184
185 }
186
draw_shadow_vertex(scalar_t x,scalar_t y,scalar_t z,matrixgl_t model_matrix)187 void draw_shadow_vertex( scalar_t x, scalar_t y, scalar_t z,
188 matrixgl_t model_matrix )
189 {
190 point_t pt;
191 scalar_t old_y;
192 vector_t nml;
193
194 pt = make_point( x, y, z );
195 pt = transform_point( model_matrix, pt );
196
197 old_y = pt.y;
198
199 nml = find_course_normal( pt.x, pt.z );
200 pt.y = find_y_coord( pt.x, pt.z ) + SHADOW_HEIGHT;
201
202 if ( pt.y > old_y )
203 pt.y = old_y;
204
205 glNormal3f( nml.x, nml.y, nml.z );
206 glVertex3f( pt.x, pt.y, pt.z );
207 }
208