Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5098 | clevermous | 1 | #include "zgl.h" |
2 | #include "msghandling.h" |
||
3 | |||
4 | void glopMaterial(GLContext *c,GLParam *p) |
||
5 | { |
||
6 | int mode=p[1].i; |
||
7 | int type=p[2].i; |
||
8 | float *v=&p[3].f; |
||
9 | int i; |
||
10 | GLMaterial *m; |
||
11 | |||
12 | if (mode == GL_FRONT_AND_BACK) { |
||
13 | p[1].i=GL_FRONT; |
||
14 | glopMaterial(c,p); |
||
15 | mode=GL_BACK; |
||
16 | } |
||
17 | if (mode == GL_FRONT) m=&c->materials[0]; |
||
18 | else m=&c->materials[1]; |
||
19 | |||
20 | switch(type) { |
||
21 | case GL_EMISSION: |
||
22 | for(i=0;i<4;i++) |
||
23 | m->emission.v[i]=v[i]; |
||
24 | break; |
||
25 | case GL_AMBIENT: |
||
26 | for(i=0;i<4;i++) |
||
27 | m->ambient.v[i]=v[i]; |
||
28 | break; |
||
29 | case GL_DIFFUSE: |
||
30 | for(i=0;i<4;i++) |
||
31 | m->diffuse.v[i]=v[i]; |
||
32 | break; |
||
33 | case GL_SPECULAR: |
||
34 | for(i=0;i<4;i++) |
||
35 | m->specular.v[i]=v[i]; |
||
36 | break; |
||
37 | case GL_SHININESS: |
||
38 | m->shininess=v[0]; |
||
39 | m->shininess_i = (v[0]/128.0f)*SPECULAR_BUFFER_RESOLUTION; |
||
40 | break; |
||
41 | case GL_AMBIENT_AND_DIFFUSE: |
||
42 | for(i=0;i<4;i++) |
||
43 | m->diffuse.v[i]=v[i]; |
||
44 | for(i=0;i<4;i++) |
||
45 | m->ambient.v[i]=v[i]; |
||
46 | break; |
||
47 | default: |
||
48 | assert(0); |
||
49 | } |
||
50 | } |
||
51 | |||
52 | void glopColorMaterial(GLContext *c,GLParam *p) |
||
53 | { |
||
54 | int mode=p[1].i; |
||
55 | int type=p[2].i; |
||
56 | |||
57 | c->current_color_material_mode=mode; |
||
58 | c->current_color_material_type=type; |
||
59 | } |
||
60 | |||
61 | void glopLight(GLContext *c,GLParam *p) |
||
62 | { |
||
63 | int light=p[1].i; |
||
64 | int type=p[2].i; |
||
65 | V4 v; |
||
66 | GLLight *l; |
||
67 | int i; |
||
68 | |||
69 | assert(light >= GL_LIGHT0 && light < GL_LIGHT0+MAX_LIGHTS ); |
||
70 | |||
71 | l=&c->lights[light-GL_LIGHT0]; |
||
72 | |||
73 | for(i=0;i<4;i++) v.v[i]=p[3+i].f; |
||
74 | |||
75 | switch(type) { |
||
76 | case GL_AMBIENT: |
||
77 | l->ambient=v; |
||
78 | break; |
||
79 | case GL_DIFFUSE: |
||
80 | l->diffuse=v; |
||
81 | break; |
||
82 | case GL_SPECULAR: |
||
83 | l->specular=v; |
||
84 | break; |
||
85 | case GL_POSITION: |
||
86 | { |
||
87 | V4 pos; |
||
88 | gl_M4_MulV4(&pos,c->matrix_stack_ptr[0],&v); |
||
89 | |||
90 | l->position=pos; |
||
91 | |||
92 | if (l->position.v[3] == 0) { |
||
93 | l->norm_position.X=pos.X; |
||
94 | l->norm_position.Y=pos.Y; |
||
95 | l->norm_position.Z=pos.Z; |
||
96 | |||
97 | gl_V3_Norm(&l->norm_position); |
||
98 | } |
||
99 | } |
||
100 | break; |
||
101 | case GL_SPOT_DIRECTION: |
||
102 | for(i=0;i<3;i++) { |
||
103 | l->spot_direction.v[i]=v.v[i]; |
||
104 | l->norm_spot_direction.v[i]=v.v[i]; |
||
105 | } |
||
106 | gl_V3_Norm(&l->norm_spot_direction); |
||
107 | break; |
||
108 | case GL_SPOT_EXPONENT: |
||
109 | l->spot_exponent=v.v[0]; |
||
110 | break; |
||
111 | case GL_SPOT_CUTOFF: |
||
112 | { |
||
113 | float a=v.v[0]; |
||
114 | assert(a == 180 || (a>=0 && a<=90)); |
||
115 | l->spot_cutoff=a; |
||
116 | if (a != 180) l->cos_spot_cutoff=cos(a * M_PI / 180.0); |
||
117 | } |
||
118 | break; |
||
119 | case GL_CONSTANT_ATTENUATION: |
||
120 | l->attenuation[0]=v.v[0]; |
||
121 | break; |
||
122 | case GL_LINEAR_ATTENUATION: |
||
123 | l->attenuation[1]=v.v[0]; |
||
124 | break; |
||
125 | case GL_QUADRATIC_ATTENUATION: |
||
126 | l->attenuation[2]=v.v[0]; |
||
127 | break; |
||
128 | default: |
||
129 | assert(0); |
||
130 | } |
||
131 | } |
||
132 | |||
133 | |||
134 | void glopLightModel(GLContext *c,GLParam *p) |
||
135 | { |
||
136 | int pname=p[1].i; |
||
137 | float *v=&p[2].f; |
||
138 | int i; |
||
139 | |||
140 | switch(pname) { |
||
141 | case GL_LIGHT_MODEL_AMBIENT: |
||
142 | for(i=0;i<4;i++) |
||
143 | c->ambient_light_model.v[i]=v[i]; |
||
144 | break; |
||
145 | case GL_LIGHT_MODEL_LOCAL_VIEWER: |
||
146 | c->local_light_model=(int)v[0]; |
||
147 | break; |
||
148 | case GL_LIGHT_MODEL_TWO_SIDE: |
||
149 | c->light_model_two_side = (int)v[0]; |
||
150 | break; |
||
151 | default: |
||
152 | tgl_warning("glopLightModel: illegal pname: 0x%x\n", pname); |
||
153 | //assert(0); |
||
154 | break; |
||
155 | } |
||
156 | } |
||
157 | |||
158 | |||
159 | static inline float clampf(float a,float min,float max) |
||
160 | { |
||
161 | if (a |
||
162 | else if (a>max) return max; |
||
163 | else return a; |
||
164 | } |
||
165 | |||
166 | void gl_enable_disable_light(GLContext *c,int light,int v) |
||
167 | { |
||
168 | GLLight *l=&c->lights[light]; |
||
169 | if (v && !l->enabled) { |
||
170 | l->enabled=1; |
||
171 | l->next=c->first_light; |
||
172 | c->first_light=l; |
||
173 | l->prev=NULL; |
||
174 | } else if (!v && l->enabled) { |
||
175 | l->enabled=0; |
||
176 | if (l->prev == NULL) c->first_light=l->next; |
||
177 | else l->prev->next=l->next; |
||
178 | if (l->next != NULL) l->next->prev=l->prev; |
||
179 | } |
||
180 | } |
||
181 | |||
182 | /* non optimized lightening model */ |
||
183 | void gl_shade_vertex(GLContext *c,GLVertex *v) |
||
184 | { |
||
185 | float R,G,B,A; |
||
186 | GLMaterial *m; |
||
187 | GLLight *l; |
||
188 | V3 n,s,d; |
||
189 | float dist,tmp,att,dot,dot_spot,dot_spec; |
||
190 | int twoside = c->light_model_two_side; |
||
191 | |||
192 | m=&c->materials[0]; |
||
193 | |||
194 | n.X=v->normal.X; |
||
195 | n.Y=v->normal.Y; |
||
196 | n.Z=v->normal.Z; |
||
197 | |||
198 | R=m->emission.v[0]+m->ambient.v[0]*c->ambient_light_model.v[0]; |
||
199 | G=m->emission.v[1]+m->ambient.v[1]*c->ambient_light_model.v[1]; |
||
200 | B=m->emission.v[2]+m->ambient.v[2]*c->ambient_light_model.v[2]; |
||
201 | A=clampf(m->diffuse.v[3],0,1); |
||
202 | |||
203 | for(l=c->first_light;l!=NULL;l=l->next) { |
||
204 | float lR,lB,lG; |
||
205 | |||
206 | /* ambient */ |
||
207 | lR=l->ambient.v[0] * m->ambient.v[0]; |
||
208 | lG=l->ambient.v[1] * m->ambient.v[1]; |
||
209 | lB=l->ambient.v[2] * m->ambient.v[2]; |
||
210 | |||
211 | if (l->position.v[3] == 0) { |
||
212 | /* light at infinity */ |
||
213 | d.X=l->position.v[0]; |
||
214 | d.Y=l->position.v[1]; |
||
215 | d.Z=l->position.v[2]; |
||
216 | att=1; |
||
217 | } else { |
||
218 | /* distance attenuation */ |
||
219 | d.X=l->position.v[0]-v->ec.v[0]; |
||
220 | d.Y=l->position.v[1]-v->ec.v[1]; |
||
221 | d.Z=l->position.v[2]-v->ec.v[2]; |
||
222 | dist=sqrt(d.X*d.X+d.Y*d.Y+d.Z*d.Z); |
||
223 | if (dist>1E-3) { |
||
224 | tmp=1/dist; |
||
225 | d.X*=tmp; |
||
226 | d.Y*=tmp; |
||
227 | d.Z*=tmp; |
||
228 | } |
||
229 | att=1.0f/(l->attenuation[0]+dist*(l->attenuation[1]+ |
||
230 | dist*l->attenuation[2])); |
||
231 | } |
||
232 | dot=d.X*n.X+d.Y*n.Y+d.Z*n.Z; |
||
233 | if (twoside && dot < 0) dot = -dot; |
||
234 | if (dot>0) { |
||
235 | /* diffuse light */ |
||
236 | lR+=dot * l->diffuse.v[0] * m->diffuse.v[0]; |
||
237 | lG+=dot * l->diffuse.v[1] * m->diffuse.v[1]; |
||
238 | lB+=dot * l->diffuse.v[2] * m->diffuse.v[2]; |
||
239 | |||
240 | /* spot light */ |
||
241 | if (l->spot_cutoff != 180) { |
||
242 | dot_spot=-(d.X*l->norm_spot_direction.v[0]+ |
||
243 | d.Y*l->norm_spot_direction.v[1]+ |
||
244 | d.Z*l->norm_spot_direction.v[2]); |
||
245 | if (twoside && dot_spot < 0) dot_spot = -dot_spot; |
||
246 | if (dot_spot < l->cos_spot_cutoff) { |
||
247 | /* no contribution */ |
||
248 | continue; |
||
249 | } else { |
||
250 | /* TODO: optimize */ |
||
251 | if (l->spot_exponent > 0) { |
||
252 | att=att*pow(dot_spot,l->spot_exponent); |
||
253 | } |
||
254 | } |
||
255 | } |
||
256 | |||
257 | /* specular light */ |
||
258 | |||
259 | if (c->local_light_model) { |
||
260 | V3 vcoord; |
||
261 | vcoord.X=v->ec.X; |
||
262 | vcoord.Y=v->ec.Y; |
||
263 | vcoord.Z=v->ec.Z; |
||
264 | gl_V3_Norm(&vcoord); |
||
265 | s.X=d.X-vcoord.X; |
||
266 | s.Y=d.Y-vcoord.X; |
||
267 | s.Z=d.Z-vcoord.X; |
||
268 | } else { |
||
269 | s.X=d.X; |
||
270 | s.Y=d.Y; |
||
271 | s.Z=d.Z+1.0; |
||
272 | } |
||
273 | dot_spec=n.X*s.X+n.Y*s.Y+n.Z*s.Z; |
||
274 | if (twoside && dot_spec < 0) dot_spec = -dot_spec; |
||
275 | if (dot_spec>0) { |
||
276 | GLSpecBuf *specbuf; |
||
277 | int idx; |
||
278 | tmp=sqrt(s.X*s.X+s.Y*s.Y+s.Z*s.Z); |
||
279 | if (tmp > 1E-3) { |
||
280 | dot_spec=dot_spec / tmp; |
||
281 | } |
||
282 | |||
283 | /* TODO: optimize */ |
||
284 | /* testing specular buffer code */ |
||
285 | /* dot_spec= pow(dot_spec,m->shininess);*/ |
||
286 | specbuf = specbuf_get_buffer(c, m->shininess_i, m->shininess); |
||
287 | idx = (int)(dot_spec*SPECULAR_BUFFER_SIZE); |
||
288 | if (idx > SPECULAR_BUFFER_SIZE) idx = SPECULAR_BUFFER_SIZE; |
||
289 | dot_spec = specbuf->buf[idx]; |
||
290 | lR+=dot_spec * l->specular.v[0] * m->specular.v[0]; |
||
291 | lG+=dot_spec * l->specular.v[1] * m->specular.v[1]; |
||
292 | lB+=dot_spec * l->specular.v[2] * m->specular.v[2]; |
||
293 | } |
||
294 | } |
||
295 | |||
296 | R+=att * lR; |
||
297 | G+=att * lG; |
||
298 | B+=att * lB; |
||
299 | } |
||
300 | |||
301 | v->color.v[0]=clampf(R,0,1); |
||
302 | v->color.v[1]=clampf(G,0,1); |
||
303 | v->color.v[2]=clampf(B,0,1); |
||
304 | v->color.v[3]=A; |
||
305 | }>>>>4;i++)>=90)); |
||
306 |