This is vbxform.c in view mode; [Download] [Up]
/* $Id: vbxform.c,v 1.12 1997/06/20 02:57:59 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 2.3 * Copyright (C) 1995-1997 Brian Paul * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * $Log: vbxform.c,v $ * Revision 1.12 1997/06/20 02:57:59 brianp * changed color components from GLfixed to GLubyte * * Revision 1.11 1997/05/28 03:26:49 brianp * added precompiled header (PCH) support * * Revision 1.10 1997/05/23 03:01:45 brianp * commented out a few const keywords because IRIX cc chokes on them * * Revision 1.9 1997/04/29 01:31:07 brianp * added RasterSetup() function to device driver * * Revision 1.8 1997/04/21 01:21:52 brianp * added MATRIX_2D_NO_ROT * * Revision 1.7 1997/04/20 19:47:27 brianp * added RenderVB to device driver * * Revision 1.6 1997/04/20 15:59:30 brianp * removed VERTEX2_BIT stuff * * Revision 1.5 1997/04/14 02:12:53 brianp * small optimization in transform_texcoords() * * Revision 1.4 1997/04/12 16:22:22 brianp * removed gl_init_vb() * * Revision 1.3 1997/04/12 12:28:39 brianp * fixed <= material_update bug, removed some unused vars * * Revision 1.2 1997/04/07 03:01:11 brianp * optimized vertex[234] code * * Revision 1.1 1997/04/02 03:14:29 brianp * Initial revision * */ /* * This file implements transformation, clip testing, and lighting of * vertices in the vertex buffer. * * The entry points to this file are the functions: * gl_init_vb() - initialize the vertex buffer * gl_transform_vb_part1() - first stage of vertex transformation * gl_transform_vb_part2() - second stage of vertex transformation */ #ifdef PCH #include "all.h" #else #include <stdlib.h> #include "context.h" #include "fog.h" #include "light.h" #include "macros.h" #include "matrix.h" #include "shade.h" #include "texture.h" #include "types.h" #include "vb.h" #include "vbrender.h" #include "vbxform.h" #include "xform.h" #endif #if 0 /* * Use the current modelview matrix to transform XY vertices from object * to eye coordinates. * Input: ctx - the context * n - number of vertices to transform * vObj - array [n][4] of object coordinates * In/Out; vEye - array [n][4] of eye coordinates */ static void transform_points2( GLcontext *ctx, GLuint n, const GLfloat vObj[][4], GLfloat vEye[][4] ) { switch (ctx->ModelViewMatrixType) { case MATRIX_GENERAL: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m4 = m[4], m12 = m[12]; GLfloat m1 = m[1], m5 = m[5], m13 = m[13]; GLfloat m2 = m[2], m6 = m[6], m14 = m[14]; GLfloat m3 = m[3], m7 = m[7], m15 = m[15]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1]; vEye[i][0] = m0 * ox + m4 * oy + m12; vEye[i][1] = m1 * ox + m5 * oy + m13; vEye[i][2] = m2 * ox + m6 * oy + m14; vEye[i][3] = m3 * ox + m7 * oy + m15; } } break; case MATRIX_IDENTITY: { GLuint i; for (i=0;i<n;i++) { vEye[i][0] = vObj[i][0]; vEye[i][1] = vObj[i][1]; vEye[i][2] = 0.0F; vEye[i][3] = 1.0F; } } break; case MATRIX_2D: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; GLfloat m12 = m[12], m13 = m[13]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1]; vEye[i][0] = m0 * ox + m4 * oy + m12; vEye[i][1] = m1 * ox + m5 * oy + m13; vEye[i][2] = 0.0F; vEye[i][3] = 1.0F; } } break; case MATRIX_2D_NO_ROT: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1]; vEye[i][0] = m0 * ox + m12; vEye[i][1] = m5 * oy + m13; vEye[i][2] = 0.0F; vEye[i][3] = 1.0F; } } break; case MATRIX_3D: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1]; vEye[i][0] = m0 * ox + m4 * oy + m12; vEye[i][1] = m1 * ox + m5 * oy + m13; vEye[i][2] = m2 * ox + m6 * oy + m14; vEye[i][3] = 1.0F; } } break; default: /* should never get here */ gl_problem( NULL, "invalid matrix type in transform_points3()" ); return; } } #endif /* * Use the current modelview matrix to transform XYZ vertices from object * to eye coordinates. * Input: ctx - the context * n - number of vertices to transform * vObj - array [n][4] of object coordinates * In/Out; vEye - array [n][4] of eye coordinates */ static void transform_points3( GLcontext *ctx, GLuint n, /*const*/ GLfloat vObj[][4], GLfloat vEye[][4] ) { switch (ctx->ModelViewMatrixType) { case MATRIX_GENERAL: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12]; GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13]; GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14]; GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2]; vEye[i][0] = m0 * ox + m4 * oy + m8 * oz + m12; vEye[i][1] = m1 * ox + m5 * oy + m9 * oz + m13; vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14; vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15; } } break; case MATRIX_IDENTITY: { GLuint i; for (i=0;i<n;i++) { vEye[i][0] = vObj[i][0]; vEye[i][1] = vObj[i][1]; vEye[i][2] = vObj[i][2]; vEye[i][3] = 1.0F; } } break; case MATRIX_2D: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; GLfloat m12 = m[12], m13 = m[13]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2]; vEye[i][0] = m0 * ox + m4 * oy + m12 ; vEye[i][1] = m1 * ox + m5 * oy + m13 ; vEye[i][2] = + oz ; vEye[i][3] = 1.0F; } } break; case MATRIX_2D_NO_ROT: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2]; vEye[i][0] = m0 * ox + m12 ; vEye[i][1] = m5 * oy + m13 ; vEye[i][2] = + oz ; vEye[i][3] = 1.0F; } } break; case MATRIX_3D: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10]; GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1], oz = vObj[i][2]; vEye[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 ; vEye[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 ; vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 ; vEye[i][3] = 1.0F; } } break; default: /* should never get here */ gl_problem( NULL, "invalid matrix type in transform_points3()" ); return; } } /* * Use the current modelview matrix to transform XYZW vertices from object * to eye coordinates. * Input: ctx - the context * n - number of vertices to transform * vObj - array [n][4] of object coordinates * In/Out; vEye - array [n][4] of eye coordinates */ static void transform_points4( GLcontext *ctx, GLuint n, /*const*/ GLfloat vObj[][4], GLfloat vEye[][4] ) { switch (ctx->ModelViewMatrixType) { case MATRIX_GENERAL: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12]; GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13]; GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14]; GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1]; GLfloat oz = vObj[i][2], ow = vObj[i][3]; vEye[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow; vEye[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow; vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow; vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow; } } break; case MATRIX_IDENTITY: { GLuint i; for (i=0;i<n;i++) { vEye[i][0] = vObj[i][0]; vEye[i][1] = vObj[i][1]; vEye[i][2] = vObj[i][2]; vEye[i][3] = vObj[i][3]; } } break; case MATRIX_2D: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; GLfloat m12 = m[12], m13 = m[13]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1]; GLfloat oz = vObj[i][2], ow = vObj[i][3]; vEye[i][0] = m0 * ox + m4 * oy + m12 * ow; vEye[i][1] = m1 * ox + m5 * oy + m13 * ow; vEye[i][2] = + oz ; vEye[i][3] = ow; } } break; case MATRIX_2D_NO_ROT: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1]; GLfloat oz = vObj[i][2], ow = vObj[i][3]; vEye[i][0] = m0 * ox + m12 * ow; vEye[i][1] = m5 * oy + m13 * ow; vEye[i][2] = + oz ; vEye[i][3] = ow; } } break; case MATRIX_3D: { const GLfloat *m = ctx->ModelViewMatrix; GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10]; GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; GLuint i; for (i=0;i<n;i++) { GLfloat ox = vObj[i][0], oy = vObj[i][1]; GLfloat oz = vObj[i][2], ow = vObj[i][3]; vEye[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow; vEye[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow; vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow; vEye[i][3] = ow; } } break; default: /* should never get here */ gl_problem( NULL, "invalid matrix type in transform_points4()" ); return; } } /* * Transform an array of texture coordinates by the current texture matrix. * Input: ctx - the context * n - number of texture coordinates in array * In/Out: t - array [n][4] of texture coordinates to transform */ static void transform_texcoords( GLcontext *ctx, GLuint n, GLfloat t[][4] ) { switch (ctx->TextureMatrixType) { case MATRIX_GENERAL: { const GLfloat *m = ctx->TextureMatrix; GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12]; GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13]; GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14]; GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15]; GLuint i; for (i=0;i<n;i++) { GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3]; t[i][0] = m0 * t0 + m4 * t1 + m8 * t2 + m12 * t3; t[i][1] = m1 * t0 + m5 * t1 + m9 * t2 + m13 * t3; t[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3; t[i][3] = m3 * t0 + m7 * t1 + m11 * t2 + m15 * t3; } } break; case MATRIX_IDENTITY: /* Do nothing */ break; case MATRIX_2D: { const GLfloat *m = ctx->TextureMatrix; GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; GLfloat m12 = m[12], m13 = m[13]; GLuint i; for (i=0;i<n;i++) { GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3]; t[i][0] = m0 * t0 + m4 * t1 + m12 * t3; t[i][1] = m1 * t0 + m5 * t1 + m13 * t3; t[i][2] = + t2 ; /*t[i][3] unchanged*/ } } break; case MATRIX_3D: { const GLfloat *m = ctx->TextureMatrix; GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10]; GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; GLuint i; for (i=0;i<n;i++) { GLfloat t0 = t[i][0], t1 = t[i][1], t2 = t[i][2], t3 = t[i][3]; t[i][0] = m0 * t0 + m4 * t1 + m8 * t2 + m12 * t3; t[i][1] = m1 * t0 + m5 * t1 + m9 * t2 + m13 * t3; t[i][2] = m2 * t0 + m6 * t1 + m10 * t2 + m14 * t3; /*t[i][3] unchanged*/ } } break; default: /* should never get here */ gl_problem( NULL, "invalid matrix type in transform_texcoords()" ); return; } } /* * Apply the projection matrix to an array of vertices in Eye coordinates * resulting in Clip coordinates. Also, compute the ClipMask bitfield for * each vertex. * Input: ctx - the context * n - number of vertices * vEye - array [n][4] of Eye coordinates * Output: vClip - array [n][4] of Clip coordinates * clipMask - array [n] of clip masks */ static void project_and_cliptest( GLcontext *ctx, GLuint n, /*const*/ GLfloat vEye[][4], GLfloat vClip[][4], GLubyte clipMask[], GLubyte *orMask, GLubyte *andMask ) { GLubyte tmpOrMask = *orMask; GLubyte tmpAndMask = *andMask; switch (ctx->ProjectionMatrixType) { case MATRIX_GENERAL: { const GLfloat *m = ctx->ProjectionMatrix; GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12]; GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13]; GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14]; GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15]; GLuint i; for (i=0;i<n;i++) { GLfloat ex = vEye[i][0], ey = vEye[i][1]; GLfloat ez = vEye[i][2], ew = vEye[i][3]; GLfloat cx = m0 * ex + m4 * ey + m8 * ez + m12 * ew; GLfloat cy = m1 * ex + m5 * ey + m9 * ez + m13 * ew; GLfloat cz = m2 * ex + m6 * ey + m10 * ez + m14 * ew; GLfloat cw = m3 * ex + m7 * ey + m11 * ez + m15 * ew; GLubyte mask = 0; vClip[i][0] = cx; vClip[i][1] = cy; vClip[i][2] = cz; vClip[i][3] = cw; if (cx > cw) mask |= CLIP_RIGHT_BIT; else if (cx < -cw) mask |= CLIP_LEFT_BIT; if (cy > cw) mask |= CLIP_TOP_BIT; else if (cy < -cw) mask |= CLIP_BOTTOM_BIT; if (cz > cw) mask |= CLIP_FAR_BIT; else if (cz < -cw) mask |= CLIP_NEAR_BIT; if (mask) { clipMask[i] |= mask; tmpOrMask |= mask; } tmpAndMask &= mask; } } break; case MATRIX_IDENTITY: { GLuint i; for (i=0;i<n;i++) { GLfloat cx = vClip[i][0] = vEye[i][0]; GLfloat cy = vClip[i][1] = vEye[i][1]; GLfloat cz = vClip[i][2] = vEye[i][2]; GLfloat cw = vClip[i][3] = vEye[i][3]; GLubyte mask = 0; if (cx > cw) mask |= CLIP_RIGHT_BIT; else if (cx < -cw) mask |= CLIP_LEFT_BIT; if (cy > cw) mask |= CLIP_TOP_BIT; else if (cy < -cw) mask |= CLIP_BOTTOM_BIT; if (cz > cw) mask |= CLIP_FAR_BIT; else if (cz < -cw) mask |= CLIP_NEAR_BIT; if (mask) { clipMask[i] |= mask; tmpOrMask |= mask; } tmpAndMask &= mask; } } break; case MATRIX_ORTHO: { const GLfloat *m = ctx->ProjectionMatrix; GLfloat m0 = m[0], m5 = m[5], m10 = m[10], m12 = m[12]; GLfloat m13 = m[13], m14 = m[14]; GLuint i; for (i=0;i<n;i++) { GLfloat ex = vEye[i][0], ey = vEye[i][1]; GLfloat ez = vEye[i][2], ew = vEye[i][3]; GLfloat cx = m0 * ex + m12 * ew; GLfloat cy = m5 * ey + m13 * ew; GLfloat cz = m10 * ez + m14 * ew; GLfloat cw = ew; GLubyte mask = 0; vClip[i][0] = cx; vClip[i][1] = cy; vClip[i][2] = cz; vClip[i][3] = cw; if (cx > cw) mask |= CLIP_RIGHT_BIT; else if (cx < -cw) mask |= CLIP_LEFT_BIT; if (cy > cw) mask |= CLIP_TOP_BIT; else if (cy < -cw) mask |= CLIP_BOTTOM_BIT; if (cz > cw) mask |= CLIP_FAR_BIT; else if (cz < -cw) mask |= CLIP_NEAR_BIT; if (mask) { clipMask[i] |= mask; tmpOrMask |= mask; } tmpAndMask &= mask; } } break; case MATRIX_PERSPECTIVE: { const GLfloat *m = ctx->ProjectionMatrix; GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9]; GLfloat m10 = m[10], m14 = m[14]; GLuint i; for (i=0;i<n;i++) { GLfloat ex = vEye[i][0], ey = vEye[i][1]; GLfloat ez = vEye[i][2], ew = vEye[i][3]; GLfloat cx = m0 * ex + m8 * ez ; GLfloat cy = m5 * ey + m9 * ez ; GLfloat cz = m10 * ez + m14 * ew; GLfloat cw = -ez ; GLubyte mask = 0; vClip[i][0] = cx; vClip[i][1] = cy; vClip[i][2] = cz; vClip[i][3] = cw; if (cx > cw) mask |= CLIP_RIGHT_BIT; else if (cx < -cw) mask |= CLIP_LEFT_BIT; if (cy > cw) mask |= CLIP_TOP_BIT; else if (cy < -cw) mask |= CLIP_BOTTOM_BIT; if (cz > cw) mask |= CLIP_FAR_BIT; else if (cz < -cw) mask |= CLIP_NEAR_BIT; if (mask) { clipMask[i] |= mask; tmpOrMask |= mask; } tmpAndMask &= mask; } } break; default: /* should never get here */ gl_problem( NULL, "invalid matrix type in project_and_cliptest()" ); return; } *orMask = tmpOrMask; *andMask = tmpAndMask; } /* * Test an array of vertices against the user-defined clipping planes. * Input: ctx - the context * n - number of vertices * vEye - array [n] of vertices, in eye coordinate system * Output: clipMask - array [n] of clip values: 0=not clipped, !0=clipped * Return: CLIP_ALL - if all vertices are clipped by one of the planes * CLIP_NONE - if no vertices were clipped * CLIP_SOME - if some vertices were clipped */ static GLuint userclip_vertices( GLcontext *ctx, GLuint n, /*const*/ GLfloat vEye[][4], GLubyte clipMask[] ) { GLboolean anyClipped = GL_FALSE; GLuint p; ASSERT(ctx->Transform.AnyClip); for (p=0;p<MAX_CLIP_PLANES;p++) { if (ctx->Transform.ClipEnabled[p]) { GLfloat a = ctx->Transform.ClipEquation[p][0]; GLfloat b = ctx->Transform.ClipEquation[p][1]; GLfloat c = ctx->Transform.ClipEquation[p][2]; GLfloat d = ctx->Transform.ClipEquation[p][3]; GLboolean allClipped = GL_TRUE; GLuint i; for (i=0;i<n;i++) { GLfloat dot = vEye[i][0] * a + vEye[i][1] * b + vEye[i][2] * c + vEye[i][3] * d; if (dot < 0.0F) { /* this vertex is clipped */ clipMask[i] = CLIP_USER_BIT; anyClipped = GL_TRUE; } else { /* vertex not clipped */ allClipped = GL_FALSE; } } if (allClipped) { return CLIP_ALL; } } } return anyClipped ? CLIP_SOME : CLIP_NONE; } /* * Transform an array of vertices from clip coordinate space to window * coordinates. * Input: ctx - the context * n - number of vertices to transform * vClip - array [n] of input vertices * clipMask - array [n] of vertex clip masks. NULL = no clipped verts * Output: vWin - array [n] of vertices in window coordinate system */ static void viewport_map_vertices( GLcontext *ctx, GLuint n, /*const*/ GLfloat vClip[][4], const GLubyte clipMask[], GLfloat vWin[][3]) { GLfloat sx = ctx->Viewport.Sx; GLfloat tx = ctx->Viewport.Tx; GLfloat sy = ctx->Viewport.Sy; GLfloat ty = ctx->Viewport.Ty; GLfloat sz = ctx->Viewport.Sz; GLfloat tz = ctx->Viewport.Tz; if (ctx->ProjectionMatrixType==MATRIX_ORTHO || ctx->ProjectionMatrixType==MATRIX_IDENTITY) { /* don't need to divide by W */ if (clipMask) { /* one or more vertices are clipped */ GLuint i; for (i=0;i<n;i++) { if (clipMask[i]==0) { vWin[i][0] = vClip[i][0] * sx + tx; vWin[i][1] = vClip[i][1] * sy + ty; vWin[i][2] = vClip[i][2] * sz + tz; } } } else { /* no vertices are clipped */ GLuint i; for (i=0;i<n;i++) { vWin[i][0] = vClip[i][0] * sx + tx; vWin[i][1] = vClip[i][1] * sy + ty; vWin[i][2] = vClip[i][2] * sz + tz; } } } else { /* need to divide by W */ if (clipMask) { /* one or more vertices are clipped */ GLuint i; for (i=0;i<n;i++) { if (clipMask[i]==0) { GLfloat wInv = 1.0F / vClip[i][3]; vWin[i][0] = vClip[i][0] * wInv * sx + tx; vWin[i][1] = vClip[i][1] * wInv * sy + ty; vWin[i][2] = vClip[i][2] * wInv * sz + tz; } } } else { /* no vertices are clipped */ GLuint i; for (i=0;i<n;i++) { GLfloat wInv = 1.0F / vClip[i][3]; vWin[i][0] = vClip[i][0] * wInv * sx + tx; vWin[i][1] = vClip[i][1] * wInv * sy + ty; vWin[i][2] = vClip[i][2] * wInv * sz + tz; } } } } /* * Check if the global material has to be updated with info that was * associated with a vertex via glMaterial. * This function is used when any material values get changed between * glBegin/glEnd either by calling glMaterial() or by calling glColor() * when GL_COLOR_MATERIAL is enabled. */ static void update_material( GLcontext *ctx, GLuint i ) { struct vertex_buffer *VB = ctx->VB; if (VB->MaterialMask[i]) { if (VB->MaterialMask[i] & FRONT_AMBIENT_BIT) { COPY_4V( ctx->Light.Material[0].Ambient, VB->Material[i][0].Ambient ); } if (VB->MaterialMask[i] & BACK_AMBIENT_BIT) { COPY_4V( ctx->Light.Material[1].Ambient, VB->Material[i][1].Ambient ); } if (VB->MaterialMask[i] & FRONT_DIFFUSE_BIT) { COPY_4V( ctx->Light.Material[0].Diffuse, VB->Material[i][0].Diffuse ); } if (VB->MaterialMask[i] & BACK_DIFFUSE_BIT) { COPY_4V( ctx->Light.Material[1].Diffuse, VB->Material[i][1].Diffuse ); } if (VB->MaterialMask[i] & FRONT_SPECULAR_BIT) { COPY_4V( ctx->Light.Material[0].Specular, VB->Material[i][0].Specular ); } if (VB->MaterialMask[i] & BACK_SPECULAR_BIT) { COPY_4V( ctx->Light.Material[1].Specular, VB->Material[i][1].Specular ); } if (VB->MaterialMask[i] & FRONT_EMISSION_BIT) { COPY_4V( ctx->Light.Material[0].Emission, VB->Material[i][0].Emission ); } if (VB->MaterialMask[i] & BACK_EMISSION_BIT) { COPY_4V( ctx->Light.Material[1].Emission, VB->Material[i][1].Emission ); } if (VB->MaterialMask[i] & FRONT_SHININESS_BIT) { ctx->Light.Material[0].Shininess = VB->Material[i][0].Shininess; gl_compute_material_shine_table( &ctx->Light.Material[0] ); } if (VB->MaterialMask[i] & BACK_SHININESS_BIT) { ctx->Light.Material[1].Shininess = VB->Material[i][1].Shininess; gl_compute_material_shine_table( &ctx->Light.Material[1] ); } if (VB->MaterialMask[i] & FRONT_INDEXES_BIT) { ctx->Light.Material[0].AmbientIndex = VB->Material[i][0].AmbientIndex; ctx->Light.Material[0].DiffuseIndex = VB->Material[i][0].DiffuseIndex; ctx->Light.Material[0].SpecularIndex = VB->Material[i][0].SpecularIndex; } if (VB->MaterialMask[i] & BACK_INDEXES_BIT) { ctx->Light.Material[1].AmbientIndex = VB->Material[i][1].AmbientIndex; ctx->Light.Material[1].DiffuseIndex = VB->Material[i][1].DiffuseIndex; ctx->Light.Material[1].SpecularIndex = VB->Material[i][1].SpecularIndex; } VB->MaterialMask[i] = 0; /* reset now */ } } /* * Compute the shading (lighting) for the vertices in the vertex buffer. */ static void shade_vertices( GLcontext *ctx ) { struct vertex_buffer *VB = ctx->VB; if (ctx->Visual->RGBAflag) { if (!VB->MonoMaterial) { /* Material may change with each vertex */ GLuint i; for (i=VB->Start; i<VB->Count; i++) { update_material( ctx, i ); gl_color_shade_vertices( ctx, 0, 1, &VB->Eye[i], &VB->Normal[i], &VB->Fcolor[i]); if (ctx->Light.Model.TwoSide) { gl_color_shade_vertices( ctx, 1, 1, &VB->Eye[i], &VB->Normal[i], &VB->Bcolor[i]); } } /* Need this in case a glColor/glMaterial is called after the * last vertex between glBegin/glEnd. */ update_material( ctx, VB->Count ); } else { if (ctx->Light.Fast) { if (VB->MonoNormal) { /* call optimized shader */ GLubyte color[1][4]; GLuint i; gl_color_shade_vertices_fast( ctx, 0, /* front side */ 1, VB->Normal + VB->Start, color ); for (i=VB->Start; i<VB->Count; i++) { COPY_4V( VB->Fcolor[i], color[0] ); } if (ctx->Light.Model.TwoSide) { gl_color_shade_vertices_fast( ctx, 1, /* back side */ 1, VB->Normal + VB->Start, color ); for (i=VB->Start; i<VB->Count; i++) { COPY_4V( VB->Bcolor[i], color[0] ); } } } else { /* call optimized shader */ gl_color_shade_vertices_fast( ctx, 0, /* front side */ VB->Count - VB->Start, VB->Normal + VB->Start, VB->Fcolor + VB->Start ); if (ctx->Light.Model.TwoSide) { gl_color_shade_vertices_fast( ctx, 1, /* back side */ VB->Count - VB->Start, VB->Normal + VB->Start, VB->Bcolor + VB->Start ); } } } else { /* call slower, full-featured shader */ gl_color_shade_vertices( ctx, 0, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Normal + VB->Start, VB->Fcolor + VB->Start ); if (ctx->Light.Model.TwoSide) { gl_color_shade_vertices( ctx, 1, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Normal + VB->Start, VB->Bcolor + VB->Start ); } } } } else { /* Color index mode */ if (!VB->MonoMaterial) { /* Material may change with each vertex */ GLuint i; /* NOTE the <= here. This is needed in case glColor/glMaterial * is called after the last glVertex inside a glBegin/glEnd pair. */ for (i=VB->Start; i<VB->Count; i++) { update_material( ctx, i ); gl_index_shade_vertices( ctx, 0, 1, &VB->Eye[i], &VB->Normal[i], &VB->Findex[i] ); if (ctx->Light.Model.TwoSide) { gl_index_shade_vertices( ctx, 1, 1, &VB->Eye[i], &VB->Normal[i], &VB->Bindex[i] ); } } /* Need this in case a glColor/glMaterial is called after the * last vertex between glBegin/glEnd. */ update_material( ctx, VB->Count ); } else { gl_index_shade_vertices( ctx, 0, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Normal + VB->Start, VB->Findex + VB->Start ); if (ctx->Light.Model.TwoSide) { gl_index_shade_vertices( ctx, 1, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Normal + VB->Start, VB->Bindex + VB->Start ); } } } } /* * Compute fog for the vertices in the vertex buffer. */ static void fog_vertices( GLcontext *ctx ) { struct vertex_buffer *VB = ctx->VB; if (ctx->Visual->RGBAflag) { /* Fog RGB colors */ gl_fog_color_vertices( ctx, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Fcolor + VB->Start ); if (ctx->LightTwoSide) { gl_fog_color_vertices( ctx, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Bcolor + VB->Start ); } } else { /* Fog color indexes */ gl_fog_index_vertices( ctx, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Findex + VB->Start ); if (ctx->LightTwoSide) { gl_fog_index_vertices( ctx, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Bindex + VB->Start ); } } } /* * When the Vertex Buffer is full, this function applies the modelview * matrix to transform vertices and normals from object coordinates to * eye coordinates. Next, we'll call gl_transform_vb_part2()... * This function might not be called when using vertex arrays. */ void gl_transform_vb_part1( GLcontext *ctx, GLboolean allDone ) { struct vertex_buffer *VB = ctx->VB; #ifdef PROFILE GLdouble t0 = gl_time(); #endif ASSERT( VB->Count>0 ); /* Apply the modelview matrix to transform vertexes from Object * to Eye coords. */ if (VB->VertexSizeMask==VERTEX4_BIT) { transform_points4( ctx, VB->Count - VB->Start, VB->Obj + VB->Start, VB->Eye + VB->Start ); } else { transform_points3( ctx, VB->Count - VB->Start, VB->Obj + VB->Start, VB->Eye + VB->Start ); } /* Now transform the normal vectors */ if (ctx->NeedNormals) { gl_xform_normals_3fv( VB->Count - VB->Start, VB->Normal + VB->Start, ctx->ModelViewInv, VB->Normal + VB->Start, ctx->Transform.Normalize ); } #ifdef PROFILE ctx->VertexTime += gl_time() - t0; #endif /* lighting, project, etc */ gl_transform_vb_part2( ctx, allDone ); } /* * Part 2 of Vertex Buffer transformation: compute lighting, clipflags, * fog, texture coords, etc. * Before this function is called the VB->Eye coordinates must have * already been computed. * Callers: gl_transform_vb_part1(), glDrawArraysEXT() */ void gl_transform_vb_part2( GLcontext *ctx, GLboolean allDone ) { struct vertex_buffer *VB = ctx->VB; #ifdef PROFILE GLdouble t0 = gl_time(); #endif ASSERT( VB->Count>0 ); /* Test vertices in eye coordinate space against user clipping planes */ if (ctx->Transform.AnyClip) { GLuint result = userclip_vertices( ctx, VB->Count - VB->Start, VB->Eye + VB->Start, VB->ClipMask + VB->Start ); if (result==CLIP_ALL) { /* All vertices were outside one of the clip planes! */ gl_reset_vb( ctx, allDone ); return; } else if (result==CLIP_SOME) { VB->ClipOrMask = CLIP_USER_BIT; } else { VB->ClipAndMask = 0; } } /* Apply the projection matrix to the Eye coordinates, resulting in * Clip coordinates. Also, compute the ClipMask for each vertex. */ project_and_cliptest( ctx, VB->Count - VB->Start, VB->Eye + VB->Start, VB->Clip + VB->Start, VB->ClipMask + VB->Start, &VB->ClipOrMask, &VB->ClipAndMask ); if (VB->ClipAndMask) { /* All vertices clipped by one plane, all done! */ gl_reset_vb( ctx, allDone ); return; } /* Lighting */ if (ctx->Light.Enabled) { shade_vertices(ctx); } /* Per-vertex fog */ if (ctx->Fog.Enabled && ctx->Hint.Fog!=GL_NICEST) { fog_vertices(ctx); } /* Generate/transform texture coords */ if (ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) { if (ctx->Texture.TexGenEnabled) { gl_texgen( ctx, VB->Count - VB->Start, VB->Obj + VB->Start, VB->Eye + VB->Start, VB->Normal + VB->Start, VB->TexCoord + VB->Start ); } if (ctx->NewTextureMatrix) { gl_analyze_texture_matrix(ctx); } if (ctx->TextureMatrixType!=MATRIX_IDENTITY) { transform_texcoords( ctx, VB->Count - VB->Start, VB->TexCoord + VB->Start ); } } /* Use the viewport parameters to transform vertices from Clip * coordinates to Window coordinates. */ viewport_map_vertices( ctx, VB->Count - VB->Start, VB->Clip + VB->Start, VB->ClipOrMask ? VB->ClipMask + VB->Start : NULL, VB->Win + VB->Start ); /* Device driver rasterization setup. 3Dfx driver, for example. */ if (ctx->Driver.RasterSetup) { (*ctx->Driver.RasterSetup)( ctx, 0, VB->Count ); } #ifdef PROFILE ctx->VertexTime += gl_time() - t0; ctx->VertexCount += VB->Count - VB->Start; #endif /* * Now we're ready to rasterize the Vertex Buffer!!! * * If the device driver can't rasterize the vertex buffer then we'll * do it ourselves. */ if (!ctx->Driver.RenderVB || !(*ctx->Driver.RenderVB)(ctx,allDone)) { gl_render_vb( ctx, allDone ); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.