/* * Mesa 3-D graphics library * Version: 3.3 * * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* * New (3.1) transformation code written by Keith Whitwell. */ static void _XFORMAPI TAG(transform_normalize_normals)( const GLmatrix *mat, GLfloat scale, const GLvector3f *in, const GLfloat *lengths, const GLubyte mask[], GLvector3f *dest ) { GLuint i; const GLfloat *from = in->start; GLuint stride = in->stride; GLuint count = in->count; GLfloat (*out)[3] = (GLfloat (*)[3])dest->start; GLfloat *m = mat->inv; GLfloat m0 = m[0], m4 = m[4], m8 = m[8]; GLfloat m1 = m[1], m5 = m[5], m9 = m[9]; GLfloat m2 = m[2], m6 = m[6], m10 = m[10]; (void) mask; if (!lengths) { STRIDE_LOOP { CULL_CHECK { GLfloat tx, ty, tz; { const GLfloat ux = from[0], uy = from[1], uz = from[2]; tx = ux * m0 + uy * m1 + uz * m2; ty = ux * m4 + uy * m5 + uz * m6; tz = ux * m8 + uy * m9 + uz * m10; } { GLdouble len = tx*tx + ty*ty + tz*tz; if (len > 1e-20) { GLdouble scale = 1.0 / GL_SQRT(len); out[i][0] = (GLfloat) (tx * scale); out[i][1] = (GLfloat) (ty * scale); out[i][2] = (GLfloat) (tz * scale); } else { out[i][0] = out[i][1] = out[i][2] = 0; } } } } } else { /* scale has been snapped to 1.0 if it is close. */ if (scale != 1.0) { m0 *= scale, m4 *= scale, m8 *= scale; m1 *= scale, m5 *= scale, m9 *= scale; m2 *= scale, m6 *= scale, m10 *= scale; } STRIDE_LOOP { CULL_CHECK { GLfloat tx, ty, tz; { const GLfloat ux = from[0], uy = from[1], uz = from[2]; tx = ux * m0 + uy * m1 + uz * m2; ty = ux * m4 + uy * m5 + uz * m6; tz = ux * m8 + uy * m9 + uz * m10; } { GLfloat len = lengths[i]; out[i][0] = tx * len; out[i][1] = ty * len; out[i][2] = tz * len; } } } } dest->count = in->count; } static void _XFORMAPI TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat, GLfloat scale, const GLvector3f *in, const GLfloat *lengths, const GLubyte mask[], GLvector3f *dest ) { GLuint i; const GLfloat *from = in->start; GLuint stride = in->stride; GLuint count = in->count; GLfloat (*out)[3] = (GLfloat (*)[3])dest->start; GLfloat *m = mat->inv; GLfloat m0 = m[0]; GLfloat m5 = m[5]; GLfloat m10 = m[10]; (void) mask; if (!lengths) { STRIDE_LOOP { CULL_CHECK { GLfloat tx, ty, tz; { const GLfloat ux = from[0], uy = from[1], uz = from[2]; tx = ux * m0 ; ty = uy * m5 ; tz = uz * m10; } { GLdouble len = tx*tx + ty*ty + tz*tz; if (len > 1e-20) { GLdouble scale = 1.0 / GL_SQRT(len); out[i][0] = (GLfloat) (tx * scale); out[i][1] = (GLfloat) (ty * scale); out[i][2] = (GLfloat) (tz * scale); } else { out[i][0] = out[i][1] = out[i][2] = 0; } } } } } else { /* scale has been snapped to 1.0 if it is close. */ if (scale != 1.0) { m0 *= scale; m5 *= scale; m10 *= scale; } STRIDE_LOOP { CULL_CHECK { GLfloat tx, ty, tz; { const GLfloat ux = from[0], uy = from[1], uz = from[2]; tx = ux * m0 ; ty = uy * m5 ; tz = uz * m10; } { GLfloat len = lengths[i]; out[i][0] = tx * len; out[i][1] = ty * len; out[i][2] = tz * len; } } } } dest->count = in->count; } static void _XFORMAPI TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat, GLfloat scale, const GLvector3f *in, const GLfloat *lengths, const GLubyte mask[], GLvector3f *dest ) { GLuint i; const GLfloat *from = in->start; GLuint stride = in->stride; GLuint count = in->count; GLfloat (*out)[3] = (GLfloat (*)[3])dest->start; const GLfloat *m = mat->inv; GLfloat m0 = scale*m[0]; GLfloat m5 = scale*m[5]; GLfloat m10 = scale*m[10]; (void) lengths; (void) mask; STRIDE_LOOP { CULL_CHECK { GLfloat ux = from[0], uy = from[1], uz = from[2]; out[i][0] = ux * m0; out[i][1] = uy * m5; out[i][2] = uz * m10; } } dest->count = in->count; } static void _XFORMAPI TAG(transform_rescale_normals)( const GLmatrix *mat, GLfloat scale, const GLvector3f *in, const GLfloat *lengths, const GLubyte mask[], GLvector3f *dest ) { GLuint i; const GLfloat *from = in->start; GLuint stride = in->stride; GLuint count = in->count; GLfloat (*out)[3] = (GLfloat (*)[3])dest->start; /* Since we are unlikely to have < 3 vertices in the buffer, * it makes sense to pre-multiply by scale. */ const GLfloat *m = mat->inv; GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8]; GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9]; GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10]; (void) lengths; (void) mask; STRIDE_LOOP { CULL_CHECK { GLfloat ux = from[0], uy = from[1], uz = from[2]; out[i][0] = ux * m0 + uy * m1 + uz * m2; out[i][1] = ux * m4 + uy * m5 + uz * m6; out[i][2] = ux * m8 + uy * m9 + uz * m10; } } dest->count = in->count; } static void _XFORMAPI TAG(transform_normals_no_rot)(const GLmatrix *mat, GLfloat scale, const GLvector3f *in, const GLfloat *lengths, const GLubyte mask[], GLvector3f *dest ) { GLuint i; const GLfloat *from = in->start; GLuint stride = in->stride; GLuint count = in->count; GLfloat (*out)[3] = (GLfloat (*)[3])dest->start; const GLfloat *m = mat->inv; GLfloat m0 = m[0]; GLfloat m5 = m[5]; GLfloat m10 = m[10]; (void) scale; (void) lengths; (void) mask; STRIDE_LOOP { CULL_CHECK { GLfloat ux = from[0], uy = from[1], uz = from[2]; out[i][0] = ux * m0; out[i][1] = uy * m5; out[i][2] = uz * m10; } } dest->count = in->count; } static void _XFORMAPI TAG(transform_normals)( const GLmatrix *mat, GLfloat scale, const GLvector3f *in, const GLfloat *lengths, const GLubyte mask[], GLvector3f *dest ) { GLuint i; const GLfloat *from = in->start; GLuint stride = in->stride; GLuint count = in->count; GLfloat (*out)[3] = (GLfloat (*)[3])dest->start; const GLfloat *m = mat->inv; GLfloat m0 = m[0], m4 = m[4], m8 = m[8]; GLfloat m1 = m[1], m5 = m[5], m9 = m[9]; GLfloat m2 = m[2], m6 = m[6], m10 = m[10]; (void) scale; (void) lengths; (void) mask; STRIDE_LOOP { CULL_CHECK { GLfloat ux = from[0], uy = from[1], uz = from[2]; out[i][0] = ux * m0 + uy * m1 + uz * m2; out[i][1] = ux * m4 + uy * m5 + uz * m6; out[i][2] = ux * m8 + uy * m9 + uz * m10; } } dest->count = in->count; } static void _XFORMAPI TAG(normalize_normals)( const GLmatrix *mat, GLfloat scale, const GLvector3f *in, const GLfloat *lengths, const GLubyte mask[], GLvector3f *dest ) { GLuint i; const GLfloat *from = in->start; GLuint stride = in->stride; GLuint count = in->count; GLfloat (*out)[3] = (GLfloat (*)[3])dest->start; (void) mat; (void) mask; (void) scale; if (lengths) { STRIDE_LOOP { CULL_CHECK { const GLfloat x = from[0], y = from[1], z = from[2]; GLfloat invlen = lengths[i]; out[i][0] = x * invlen; out[i][1] = y * invlen; out[i][2] = z * invlen; } } } else { STRIDE_LOOP { CULL_CHECK { const GLfloat x = from[0], y = from[1], z = from[2]; GLdouble len = x * x + y * y + z * z; if (len > 1e-50) { len = 1.0 / GL_SQRT(len); out[i][0] = (GLfloat) (x * len); out[i][1] = (GLfloat) (y * len); out[i][2] = (GLfloat) (z * len); } else { out[i][0] = x; out[i][1] = y; out[i][2] = z; } } } } dest->count = in->count; } static void _XFORMAPI TAG(rescale_normals)( const GLmatrix *mat, GLfloat scale, const GLvector3f *in, const GLfloat *lengths, const GLubyte mask[], GLvector3f *dest ) { GLuint i; const GLfloat *from = in->start; GLuint stride = in->stride; GLuint count = in->count; GLfloat (*out)[3] = (GLfloat (*)[3])dest->start; (void) mat; (void) lengths; (void) mask; STRIDE_LOOP { CULL_CHECK { SCALE_SCALAR_3V( out[i], scale, from ); } } dest->count = in->count; } static void _XFORMAPI TAG(init_c_norm_transform)( void ) { gl_normal_tab[NORM_TRANSFORM_NO_ROT][IDX] = TAG(transform_normals_no_rot); gl_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE][IDX] = TAG(transform_rescale_normals_no_rot); gl_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE][IDX] = TAG(transform_normalize_normals_no_rot); gl_normal_tab[NORM_TRANSFORM][IDX] = TAG(transform_normals); gl_normal_tab[NORM_TRANSFORM | NORM_RESCALE][IDX] = TAG(transform_rescale_normals); gl_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE][IDX] = TAG(transform_normalize_normals); gl_normal_tab[NORM_RESCALE][IDX] = TAG(rescale_normals); gl_normal_tab[NORM_NORMALIZE][IDX] = TAG(normalize_normals); }