rastpos.c revision b5d3f2c52103c6bd834838695cd753ca26991bd6
1/* $Id: rastpos.c,v 1.25 2001/05/30 15:22:04 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
6 *
7 * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28#ifdef PC_HEADER
29#include "all.h"
30#else
31#include "glheader.h"
32#include "clip.h"
33#include "colormac.h"
34#include "context.h"
35#include "feedback.h"
36#include "light.h"
37#include "macros.h"
38#include "mmath.h"
39#include "rastpos.h"
40#include "state.h"
41#include "simple_list.h"
42#include "mtypes.h"
43
44#include "math/m_matrix.h"
45#include "math/m_xform.h"
46#endif
47
48
49/*
50 * Clip a point against the view volume.
51 * Input:  v - vertex-vector describing the point to clip
52 * Return:  0 = outside view volume
53 *          1 = inside view volume
54 */
55static GLuint
56viewclip_point( const GLfloat v[] )
57{
58   if (   v[0] > v[3] || v[0] < -v[3]
59       || v[1] > v[3] || v[1] < -v[3]
60       || v[2] > v[3] || v[2] < -v[3] ) {
61      return 0;
62   }
63   else {
64      return 1;
65   }
66}
67
68
69/*
70 * Clip a point against the user clipping planes.
71 * Input:  v - vertex-vector describing the point to clip.
72 * Return:  0 = point was clipped
73 *          1 = point not clipped
74 */
75static GLuint
76userclip_point( GLcontext* ctx, const GLfloat v[] )
77{
78   GLuint p;
79
80   for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
81      if (ctx->Transform.ClipEnabled[p]) {
82	 GLfloat dot = v[0] * ctx->Transform._ClipUserPlane[p][0]
83		     + v[1] * ctx->Transform._ClipUserPlane[p][1]
84		     + v[2] * ctx->Transform._ClipUserPlane[p][2]
85		     + v[3] * ctx->Transform._ClipUserPlane[p][3];
86         if (dot < 0.0F) {
87            return 0;
88         }
89      }
90   }
91
92   return 1;
93}
94
95
96/* This has been split off to allow the normal shade routines to
97 * get a little closer to the vertex buffer, and to use the
98 * GLvector objects directly.
99 */
100static void
101shade_rastpos(GLcontext *ctx,
102              const GLfloat vertex[4],
103              const GLfloat normal[3],
104              GLfloat Rcolor[4],
105              GLuint *index)
106{
107   GLfloat (*base)[3] = ctx->Light._BaseColor;
108   const GLfloat *sumA = ctx->Light._BaseAlpha;
109   struct gl_light *light;
110   GLfloat color[4];
111   GLfloat diffuse = 0, specular = 0;
112
113   COPY_3V(color, base[0]);
114   color[3] = sumA[0];
115
116   foreach (light, &ctx->Light.EnabledList) {
117      GLfloat n_dot_h;
118      GLfloat attenuation = 1.0;
119      GLfloat VP[3];
120      GLfloat n_dot_VP;
121      GLfloat *h;
122      GLfloat contrib[3];
123      GLboolean normalized;
124
125      if (!(light->_Flags & LIGHT_POSITIONAL)) {
126	 COPY_3V(VP, light->_VP_inf_norm);
127	 attenuation = light->_VP_inf_spot_attenuation;
128      }
129      else {
130	 GLfloat d;
131
132	 SUB_3V(VP, light->_Position, vertex);
133	 d = LEN_3FV( VP );
134
135	 if ( d > 1e-6) {
136	    GLfloat invd = 1.0F / d;
137	    SELF_SCALE_SCALAR_3V(VP, invd);
138	 }
139	 attenuation = 1.0F / (light->ConstantAttenuation + d *
140			       (light->LinearAttenuation + d *
141				light->QuadraticAttenuation));
142
143	 if (light->_Flags & LIGHT_SPOT) {
144	    GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
145
146	    if (PV_dot_dir<light->_CosCutoff) {
147	       continue;
148	    }
149	    else {
150	       double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
151	       int k = (int) x;
152	       GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
153			       + (x-k)*light->_SpotExpTable[k][1]);
154	       attenuation *= spot;
155	    }
156	 }
157      }
158
159      if (attenuation < 1e-3)
160	 continue;
161
162      n_dot_VP = DOT3( normal, VP );
163
164      if (n_dot_VP < 0.0F) {
165	 ACC_SCALE_SCALAR_3V(color, attenuation, light->_MatAmbient[0]);
166	 continue;
167      }
168
169      COPY_3V(contrib, light->_MatAmbient[0]);
170      ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[0]);
171      diffuse += n_dot_VP * light->_dli * attenuation;
172
173      {
174	 if (ctx->Light.Model.LocalViewer) {
175	    GLfloat v[3];
176	    COPY_3V(v, vertex);
177	    NORMALIZE_3FV(v);
178	    SUB_3V(VP, VP, v);
179	    h = VP;
180	    normalized = 0;
181	 }
182	 else if (light->_Flags & LIGHT_POSITIONAL) {
183	    h = VP;
184	    ACC_3V(h, ctx->_EyeZDir);
185	    normalized = 0;
186	 }
187         else {
188	    h = light->_h_inf_norm;
189	    normalized = 1;
190	 }
191
192	 n_dot_h = DOT3(normal, h);
193
194	 if (n_dot_h > 0.0F) {
195	    struct gl_material *mat = &ctx->Light.Material[0];
196	    GLfloat spec_coef;
197	    GLfloat shininess = mat->Shininess;
198
199	    if (!normalized) {
200	       n_dot_h *= n_dot_h;
201	       n_dot_h /= LEN_SQUARED_3FV( h );
202	       shininess *= .5;
203	    }
204
205	    GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec_coef );
206
207	    if (spec_coef > 1.0e-10) {
208	       ACC_SCALE_SCALAR_3V( contrib, spec_coef,
209				    light->_MatSpecular[0]);
210	       specular += spec_coef * light->_sli * attenuation;
211	    }
212	 }
213      }
214
215      ACC_SCALE_SCALAR_3V( color, attenuation, contrib );
216   }
217
218   if (ctx->Visual.rgbMode) {
219      Rcolor[0] = CLAMP(color[0], 0.0F, 1.0F);
220      Rcolor[1] = CLAMP(color[1], 0.0F, 1.0F);
221      Rcolor[2] = CLAMP(color[2], 0.0F, 1.0F);
222      Rcolor[3] = CLAMP(color[3], 0.0F, 1.0F);
223   }
224   else {
225      struct gl_material *mat = &ctx->Light.Material[0];
226      GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
227      GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
228      GLfloat ind = mat->AmbientIndex
229                  + diffuse * (1.0F-specular) * d_a
230                  + specular * s_a;
231      if (ind > mat->SpecularIndex) {
232	 ind = mat->SpecularIndex;
233      }
234      *index = (GLuint) (GLint) ind;
235   }
236
237}
238
239/*
240 * Caller:  context->API.RasterPos4f
241 */
242static void
243raster_pos4f(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
244{
245   GLfloat v[4], eye[4], clip[4], ndc[3], d;
246   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
247   FLUSH_CURRENT(ctx, 0);
248
249   if (ctx->NewState)
250      _mesa_update_state( ctx );
251
252   ASSIGN_4V( v, x, y, z, w );
253   TRANSFORM_POINT( eye, ctx->ModelView.m, v );
254
255   /* raster color */
256   if (ctx->Light.Enabled) {
257      GLfloat *norm, eyenorm[3];
258      GLfloat *objnorm = ctx->Current.Normal;
259
260      if (ctx->_NeedEyeCoords) {
261	 GLfloat *inv = ctx->ModelView.inv;
262	 TRANSFORM_NORMAL( eyenorm, objnorm, inv );
263	 norm = eyenorm;
264      }
265      else {
266	 norm = objnorm;
267      }
268
269      shade_rastpos( ctx, v, norm,
270                     ctx->Current.RasterColor,
271                     &ctx->Current.RasterIndex );
272
273   }
274   else {
275      /* use current color or index */
276      if (ctx->Visual.rgbMode) {
277         ctx->Current.RasterColor[0] = (ctx->Current.Color[0]);
278         ctx->Current.RasterColor[1] = (ctx->Current.Color[1]);
279         ctx->Current.RasterColor[2] = (ctx->Current.Color[2]);
280         ctx->Current.RasterColor[3] = (ctx->Current.Color[3]);
281      }
282      else {
283	 ctx->Current.RasterIndex = ctx->Current.Index;
284      }
285   }
286
287   /* compute raster distance */
288   ctx->Current.RasterDistance = (GLfloat)
289                      GL_SQRT( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
290
291   /* apply projection matrix:  clip = Proj * eye */
292   TRANSFORM_POINT( clip, ctx->ProjectionMatrix.m, eye );
293
294   /* clip to view volume */
295   if (viewclip_point( clip )==0) {
296      ctx->Current.RasterPosValid = GL_FALSE;
297      return;
298   }
299
300   /* clip to user clipping planes */
301   if (ctx->Transform._AnyClip &&
302       userclip_point(ctx, clip) == 0) {
303      ctx->Current.RasterPosValid = GL_FALSE;
304      return;
305   }
306
307   /* ndc = clip / W */
308   ASSERT( clip[3]!=0.0 );
309   d = 1.0F / clip[3];
310   ndc[0] = clip[0] * d;
311   ndc[1] = clip[1] * d;
312   ndc[2] = clip[2] * d;
313
314   ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport._WindowMap.m[MAT_SX] +
315				ctx->Viewport._WindowMap.m[MAT_TX]);
316   ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport._WindowMap.m[MAT_SY] +
317				ctx->Viewport._WindowMap.m[MAT_TY]);
318   ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport._WindowMap.m[MAT_SZ] +
319				ctx->Viewport._WindowMap.m[MAT_TZ]) / ctx->DepthMaxF;
320   ctx->Current.RasterPos[3] = clip[3];
321   ctx->Current.RasterPosValid = GL_TRUE;
322
323   ctx->Current.RasterFogCoord = ctx->Current.FogCoord;
324
325   {
326      GLuint texSet;
327      for (texSet = 0; texSet < ctx->Const.MaxTextureUnits; texSet++) {
328         COPY_4FV( ctx->Current.RasterMultiTexCoord[texSet],
329                  ctx->Current.Texcoord[texSet] );
330      }
331   }
332
333   if (ctx->RenderMode==GL_SELECT) {
334      _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
335   }
336
337}
338
339
340
341void
342_mesa_RasterPos2d(GLdouble x, GLdouble y)
343{
344   _mesa_RasterPos4f(x, y, 0.0F, 1.0F);
345}
346
347void
348_mesa_RasterPos2f(GLfloat x, GLfloat y)
349{
350   _mesa_RasterPos4f(x, y, 0.0F, 1.0F);
351}
352
353void
354_mesa_RasterPos2i(GLint x, GLint y)
355{
356   _mesa_RasterPos4f(x, y, 0.0F, 1.0F);
357}
358
359void
360_mesa_RasterPos2s(GLshort x, GLshort y)
361{
362   _mesa_RasterPos4f(x, y, 0.0F, 1.0F);
363}
364
365void
366_mesa_RasterPos3d(GLdouble x, GLdouble y, GLdouble z)
367{
368   _mesa_RasterPos4f(x, y, z, 1.0F);
369}
370
371void
372_mesa_RasterPos3f(GLfloat x, GLfloat y, GLfloat z)
373{
374   _mesa_RasterPos4f(x, y, z, 1.0F);
375}
376
377void
378_mesa_RasterPos3i(GLint x, GLint y, GLint z)
379{
380   _mesa_RasterPos4f(x, y, z, 1.0F);
381}
382
383void
384_mesa_RasterPos3s(GLshort x, GLshort y, GLshort z)
385{
386   _mesa_RasterPos4f(x, y, z, 1.0F);
387}
388
389void
390_mesa_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
391{
392   _mesa_RasterPos4f(x, y, z, w);
393}
394
395void
396_mesa_RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
397{
398   GET_CURRENT_CONTEXT(ctx);
399   raster_pos4f(ctx, x, y, z, w);
400}
401
402void
403_mesa_RasterPos4i(GLint x, GLint y, GLint z, GLint w)
404{
405   _mesa_RasterPos4f(x, y, z, w);
406}
407
408void
409_mesa_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
410{
411   _mesa_RasterPos4f(x, y, z, w);
412}
413
414void
415_mesa_RasterPos2dv(const GLdouble *v)
416{
417   _mesa_RasterPos4f(v[0], v[1], 0.0F, 1.0F);
418}
419
420void
421_mesa_RasterPos2fv(const GLfloat *v)
422{
423   _mesa_RasterPos4f(v[0], v[1], 0.0F, 1.0F);
424}
425
426void
427_mesa_RasterPos2iv(const GLint *v)
428{
429   _mesa_RasterPos4f(v[0], v[1], 0.0F, 1.0F);
430}
431
432void
433_mesa_RasterPos2sv(const GLshort *v)
434{
435   _mesa_RasterPos4f(v[0], v[1], 0.0F, 1.0F);
436}
437
438void
439_mesa_RasterPos3dv(const GLdouble *v)
440{
441   _mesa_RasterPos4f(v[0], v[1], v[2], 1.0F);
442}
443
444void
445_mesa_RasterPos3fv(const GLfloat *v)
446{
447   _mesa_RasterPos4f(v[0], v[1], v[2], 1.0F);
448}
449
450void
451_mesa_RasterPos3iv(const GLint *v)
452{
453   _mesa_RasterPos4f(v[0], v[1], v[2], 1.0F);
454}
455
456void
457_mesa_RasterPos3sv(const GLshort *v)
458{
459   _mesa_RasterPos4f(v[0], v[1], v[2], 1.0F);
460}
461
462void
463_mesa_RasterPos4dv(const GLdouble *v)
464{
465   _mesa_RasterPos4f(v[0], v[1], v[2], v[3]);
466}
467
468void
469_mesa_RasterPos4fv(const GLfloat *v)
470{
471   _mesa_RasterPos4f(v[0], v[1], v[2], v[3]);
472}
473
474void
475_mesa_RasterPos4iv(const GLint *v)
476{
477   _mesa_RasterPos4f(v[0], v[1], v[2], v[3]);
478}
479
480void
481_mesa_RasterPos4sv(const GLshort *v)
482{
483   _mesa_RasterPos4f(v[0], v[1], v[2], v[3]);
484}
485