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