/contrib/sdk/sources/Mesa/src/mesa/math/m_clip_tmp.h |
---|
0,0 → 1,257 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2004 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/* KW: a clever asm implementation would nestle integer versions |
* of the outcode calculation underneath the division. Gcc won't |
* do this, strangely enough, so I only do the divide in |
* the case where the cliptest passes. This isn't essential, |
* and an asm implementation needn't replicate that behaviour. |
* |
* \param clip_vec vector of incoming clip-space coords |
* \param proj_vec vector of resultant NDC-space projected coords |
* \param clipMask resulting array of clip flags |
* \param orMask bitwise-OR of clipMask values |
* \param andMask bitwise-AND of clipMask values |
* \return proj_vec pointer |
*/ |
static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask, |
GLboolean viewport_z_clip ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
const GLuint count = clip_vec->count; |
GLuint c = 0; |
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start; |
GLubyte tmpAndMask = *andMask; |
GLubyte tmpOrMask = *orMask; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat cx = from[0]; |
const GLfloat cy = from[1]; |
const GLfloat cz = from[2]; |
const GLfloat cw = from[3]; |
#if defined(macintosh) || defined(__powerpc__) |
/* on powerpc cliptest is 17% faster in this way. */ |
GLuint mask; |
mask = (((cw < cx) << CLIP_RIGHT_SHIFT)); |
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT)); |
mask |= (((cw < cy) << CLIP_TOP_SHIFT)); |
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT)); |
if (viewport_z_clip) { |
mask |= (((cw < cz) << CLIP_FAR_SHIFT)); |
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT)); |
} |
#else /* !defined(macintosh)) */ |
GLubyte mask = 0; |
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT; |
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT; |
if (-cy + cw < 0) mask |= CLIP_TOP_BIT; |
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT; |
if (viewport_z_clip) { |
if (-cz + cw < 0) mask |= CLIP_FAR_BIT; |
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT; |
} |
#endif /* defined(macintosh) */ |
clipMask[i] = mask; |
if (mask) { |
c++; |
tmpAndMask &= mask; |
tmpOrMask |= mask; |
vProj[i][0] = 0; |
vProj[i][1] = 0; |
vProj[i][2] = 0; |
vProj[i][3] = 1; |
} else { |
GLfloat oow = 1.0F / cw; |
vProj[i][0] = cx * oow; |
vProj[i][1] = cy * oow; |
vProj[i][2] = cz * oow; |
vProj[i][3] = oow; |
} |
} |
*orMask = tmpOrMask; |
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask); |
proj_vec->flags |= VEC_SIZE_4; |
proj_vec->size = 4; |
proj_vec->count = clip_vec->count; |
return proj_vec; |
} |
/* |
* \param clip_vec vector of incoming clip-space coords |
* \param proj_vec vector of resultant NDC-space projected coords |
* \param clipMask resulting array of clip flags |
* \param orMask bitwise-OR of clipMask values |
* \param andMask bitwise-AND of clipMask values |
* \return clip_vec pointer |
*/ |
static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask, |
GLboolean viewport_z_clip ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLuint c = 0; |
GLubyte tmpAndMask = *andMask; |
GLubyte tmpOrMask = *orMask; |
GLuint i; |
(void) proj_vec; |
STRIDE_LOOP { |
const GLfloat cx = from[0]; |
const GLfloat cy = from[1]; |
const GLfloat cz = from[2]; |
const GLfloat cw = from[3]; |
#if defined(macintosh) || defined(__powerpc__) |
/* on powerpc cliptest is 17% faster in this way. */ |
GLuint mask; |
mask = (((cw < cx) << CLIP_RIGHT_SHIFT)); |
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT)); |
mask |= (((cw < cy) << CLIP_TOP_SHIFT)); |
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT)); |
if (viewport_z_clip) { |
mask |= (((cw < cz) << CLIP_FAR_SHIFT)); |
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT)); |
} |
#else /* !defined(macintosh)) */ |
GLubyte mask = 0; |
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT; |
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT; |
if (-cy + cw < 0) mask |= CLIP_TOP_BIT; |
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT; |
if (viewport_z_clip) { |
if (-cz + cw < 0) mask |= CLIP_FAR_BIT; |
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT; |
} |
#endif /* defined(macintosh) */ |
clipMask[i] = mask; |
if (mask) { |
c++; |
tmpAndMask &= mask; |
tmpOrMask |= mask; |
} |
} |
*orMask = tmpOrMask; |
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask); |
return clip_vec; |
} |
static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask, |
GLboolean viewport_z_clip ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLubyte tmpOrMask = *orMask; |
GLubyte tmpAndMask = *andMask; |
GLuint i; |
(void) proj_vec; |
STRIDE_LOOP { |
const GLfloat cx = from[0], cy = from[1], cz = from[2]; |
GLubyte mask = 0; |
if (cx > 1.0) mask |= CLIP_RIGHT_BIT; |
else if (cx < -1.0) mask |= CLIP_LEFT_BIT; |
if (cy > 1.0) mask |= CLIP_TOP_BIT; |
else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT; |
if (viewport_z_clip) { |
if (cz > 1.0) mask |= CLIP_FAR_BIT; |
else if (cz < -1.0) mask |= CLIP_NEAR_BIT; |
} |
clipMask[i] = mask; |
tmpOrMask |= mask; |
tmpAndMask &= mask; |
} |
*orMask = tmpOrMask; |
*andMask = tmpAndMask; |
return clip_vec; |
} |
static GLvector4f * _XFORMAPI TAG(cliptest_points2)( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask, |
GLboolean viewport_z_clip ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLubyte tmpOrMask = *orMask; |
GLubyte tmpAndMask = *andMask; |
GLuint i; |
(void) proj_vec; |
STRIDE_LOOP { |
const GLfloat cx = from[0], cy = from[1]; |
GLubyte mask = 0; |
if (cx > 1.0) mask |= CLIP_RIGHT_BIT; |
else if (cx < -1.0) mask |= CLIP_LEFT_BIT; |
if (cy > 1.0) mask |= CLIP_TOP_BIT; |
else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT; |
clipMask[i] = mask; |
tmpOrMask |= mask; |
tmpAndMask &= mask; |
} |
*orMask = tmpOrMask; |
*andMask = tmpAndMask; |
return clip_vec; |
} |
void TAG(init_c_cliptest)( void ) |
{ |
_mesa_clip_tab[4] = TAG(cliptest_points4); |
_mesa_clip_tab[3] = TAG(cliptest_points3); |
_mesa_clip_tab[2] = TAG(cliptest_points2); |
_mesa_clip_np_tab[4] = TAG(cliptest_np_points4); |
_mesa_clip_np_tab[3] = TAG(cliptest_points3); |
_mesa_clip_np_tab[2] = TAG(cliptest_points2); |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_copy_tmp.h |
---|
0,0 → 1,86 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2001 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
#define COPY_FUNC( BITS ) \ |
static void TAG2(copy, BITS)( GLvector4f *to, const GLvector4f *f ) \ |
{ \ |
GLfloat (*t)[4] = (GLfloat (*)[4])to->start; \ |
GLfloat *from = f->start; \ |
GLuint stride = f->stride; \ |
GLuint count = to->count; \ |
GLuint i; \ |
\ |
if (BITS) \ |
STRIDE_LOOP { \ |
if (BITS&1) t[i][0] = from[0]; \ |
if (BITS&2) t[i][1] = from[1]; \ |
if (BITS&4) t[i][2] = from[2]; \ |
if (BITS&8) t[i][3] = from[3]; \ |
} \ |
} |
/* We got them all here: |
*/ |
COPY_FUNC( 0x0 ) /* noop */ |
COPY_FUNC( 0x1 ) |
COPY_FUNC( 0x2 ) |
COPY_FUNC( 0x3 ) |
COPY_FUNC( 0x4 ) |
COPY_FUNC( 0x5 ) |
COPY_FUNC( 0x6 ) |
COPY_FUNC( 0x7 ) |
COPY_FUNC( 0x8 ) |
COPY_FUNC( 0x9 ) |
COPY_FUNC( 0xa ) |
COPY_FUNC( 0xb ) |
COPY_FUNC( 0xc ) |
COPY_FUNC( 0xd ) |
COPY_FUNC( 0xe ) |
COPY_FUNC( 0xf ) |
static void TAG2(init_copy, 0)( void ) |
{ |
_mesa_copy_tab[0x0] = TAG2(copy, 0x0); |
_mesa_copy_tab[0x1] = TAG2(copy, 0x1); |
_mesa_copy_tab[0x2] = TAG2(copy, 0x2); |
_mesa_copy_tab[0x3] = TAG2(copy, 0x3); |
_mesa_copy_tab[0x4] = TAG2(copy, 0x4); |
_mesa_copy_tab[0x5] = TAG2(copy, 0x5); |
_mesa_copy_tab[0x6] = TAG2(copy, 0x6); |
_mesa_copy_tab[0x7] = TAG2(copy, 0x7); |
_mesa_copy_tab[0x8] = TAG2(copy, 0x8); |
_mesa_copy_tab[0x9] = TAG2(copy, 0x9); |
_mesa_copy_tab[0xa] = TAG2(copy, 0xa); |
_mesa_copy_tab[0xb] = TAG2(copy, 0xb); |
_mesa_copy_tab[0xc] = TAG2(copy, 0xc); |
_mesa_copy_tab[0xd] = TAG2(copy, 0xd); |
_mesa_copy_tab[0xe] = TAG2(copy, 0xe); |
_mesa_copy_tab[0xf] = TAG2(copy, 0xf); |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_debug.h |
---|
0,0 → 1,42 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2001 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
* |
* Authors: |
* Gareth Hughes |
*/ |
#ifndef __M_DEBUG_H__ |
#define __M_DEBUG_H__ |
extern void _math_test_all_transform_functions( char *description ); |
extern void _math_test_all_normal_transform_functions( char *description ); |
extern void _math_test_all_cliptest_functions( char *description ); |
/* Deprecated? |
*/ |
extern void _math_test_all_vertex_functions( char *description ); |
extern char *mesa_profile; |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/math/m_debug_clip.c |
---|
0,0 → 1,409 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2005 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
* |
* Authors: |
* Gareth Hughes |
*/ |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/imports.h" |
#include "m_matrix.h" |
#include "m_xform.h" |
#include "m_debug.h" |
#include "m_debug_util.h" |
#ifdef __UNIXOS2__ |
/* The linker doesn't like empty files */ |
static char dummy; |
#endif |
#ifdef DEBUG_MATH /* This code only used for debugging */ |
static clip_func *clip_tab[2] = { |
_mesa_clip_tab, |
_mesa_clip_np_tab |
}; |
static char *cnames[2] = { |
"_mesa_clip_tab", |
"_mesa_clip_np_tab" |
}; |
#ifdef RUN_DEBUG_BENCHMARK |
static char *cstrings[2] = { |
"clip, perspective divide", |
"clip, no divide" |
}; |
#endif |
/* ============================================================= |
* Reference cliptests |
*/ |
static GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask, |
GLboolean viewport_z_clip ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLuint c = 0; |
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start; |
GLubyte tmpAndMask = *andMask; |
GLubyte tmpOrMask = *orMask; |
GLuint i; |
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
const GLfloat cx = from[0]; |
const GLfloat cy = from[1]; |
const GLfloat cz = from[2]; |
const GLfloat cw = from[3]; |
GLubyte mask = 0; |
if ( -cx + cw < 0 ) mask |= CLIP_RIGHT_BIT; |
if ( cx + cw < 0 ) mask |= CLIP_LEFT_BIT; |
if ( -cy + cw < 0 ) mask |= CLIP_TOP_BIT; |
if ( cy + cw < 0 ) mask |= CLIP_BOTTOM_BIT; |
if (viewport_z_clip) { |
if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT; |
if ( cz + cw < 0 ) mask |= CLIP_NEAR_BIT; |
} |
clipMask[i] = mask; |
if ( mask ) { |
c++; |
tmpAndMask &= mask; |
tmpOrMask |= mask; |
vProj[i][0] = 0; |
vProj[i][1] = 0; |
vProj[i][2] = 0; |
vProj[i][3] = 1; |
} else { |
GLfloat oow = 1.0F / cw; |
vProj[i][0] = cx * oow; |
vProj[i][1] = cy * oow; |
vProj[i][2] = cz * oow; |
vProj[i][3] = oow; |
} |
} |
*orMask = tmpOrMask; |
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask); |
proj_vec->flags |= VEC_SIZE_4; |
proj_vec->size = 4; |
proj_vec->count = clip_vec->count; |
return proj_vec; |
} |
/* Keep these here for now, even though we don't use them... |
*/ |
static GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask, |
GLboolean viewport_z_clip ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLubyte tmpOrMask = *orMask; |
GLubyte tmpAndMask = *andMask; |
GLuint i; |
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
const GLfloat cx = from[0], cy = from[1], cz = from[2]; |
GLubyte mask = 0; |
if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT; |
else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT; |
if ( cy > 1.0 ) mask |= CLIP_TOP_BIT; |
else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT; |
if (viewport_z_clip) { |
if ( cz > 1.0 ) mask |= CLIP_FAR_BIT; |
else if ( cz < -1.0 ) mask |= CLIP_NEAR_BIT; |
} |
clipMask[i] = mask; |
tmpOrMask |= mask; |
tmpAndMask &= mask; |
} |
*orMask = tmpOrMask; |
*andMask = tmpAndMask; |
return clip_vec; |
} |
static GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask, |
GLboolean viewport_z_clip ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLubyte tmpOrMask = *orMask; |
GLubyte tmpAndMask = *andMask; |
GLuint i; |
(void) viewport_z_clip; |
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
const GLfloat cx = from[0], cy = from[1]; |
GLubyte mask = 0; |
if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT; |
else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT; |
if ( cy > 1.0 ) mask |= CLIP_TOP_BIT; |
else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT; |
clipMask[i] = mask; |
tmpOrMask |= mask; |
tmpAndMask &= mask; |
} |
*orMask = tmpOrMask; |
*andMask = tmpAndMask; |
return clip_vec; |
} |
static clip_func ref_cliptest[5] = { |
0, |
0, |
ref_cliptest_points2, |
ref_cliptest_points3, |
ref_cliptest_points4 |
}; |
/* ============================================================= |
* Cliptest tests |
*/ |
ALIGN16(static GLfloat, s[TEST_COUNT][4]); |
ALIGN16(static GLfloat, d[TEST_COUNT][4]); |
ALIGN16(static GLfloat, r[TEST_COUNT][4]); |
/** |
* Check if X, Y or Z component of the coordinate is close to W, in terms |
* of the clip test. |
*/ |
static GLboolean |
xyz_close_to_w(const GLfloat c[4]) |
{ |
float k = 0.0001; |
return (fabs(c[0] - c[3]) < k || |
fabs(c[1] - c[3]) < k || |
fabs(c[2] - c[3]) < k || |
fabs(-c[0] - c[3]) < k || |
fabs(-c[1] - c[3]) < k || |
fabs(-c[2] - c[3]) < k); |
} |
static int test_cliptest_function( clip_func func, int np, |
int psize, long *cycles ) |
{ |
GLvector4f source[1], dest[1], ref[1]; |
GLubyte dm[TEST_COUNT], dco, dca; |
GLubyte rm[TEST_COUNT], rco, rca; |
int i, j; |
#ifdef RUN_DEBUG_BENCHMARK |
int cycle_i; /* the counter for the benchmarks we run */ |
#endif |
GLboolean viewport_z_clip = GL_TRUE; |
(void) cycles; |
if ( psize > 4 ) { |
_mesa_problem( NULL, "test_cliptest_function called with psize > 4\n" ); |
return 0; |
} |
for ( i = 0 ; i < TEST_COUNT ; i++) { |
ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 ); |
ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 ); |
for ( j = 0 ; j < psize ; j++ ) |
s[i][j] = rnd(); |
} |
source->data = (GLfloat(*)[4])s; |
source->start = (GLfloat *)s; |
source->count = TEST_COUNT; |
source->stride = sizeof(s[0]); |
source->size = 4; |
source->flags = 0; |
dest->data = (GLfloat(*)[4])d; |
dest->start = (GLfloat *)d; |
dest->count = TEST_COUNT; |
dest->stride = sizeof(float[4]); |
dest->size = 0; |
dest->flags = 0; |
ref->data = (GLfloat(*)[4])r; |
ref->start = (GLfloat *)r; |
ref->count = TEST_COUNT; |
ref->stride = sizeof(float[4]); |
ref->size = 0; |
ref->flags = 0; |
dco = rco = 0; |
dca = rca = CLIP_FRUSTUM_BITS; |
ref_cliptest[psize]( source, ref, rm, &rco, &rca, viewport_z_clip ); |
if ( mesa_profile ) { |
BEGIN_RACE( *cycles ); |
func( source, dest, dm, &dco, &dca, viewport_z_clip ); |
END_RACE( *cycles ); |
} |
else { |
func( source, dest, dm, &dco, &dca, viewport_z_clip ); |
} |
if ( dco != rco ) { |
printf( "\n-----------------------------\n" ); |
printf( "dco = 0x%02x rco = 0x%02x\n", dco, rco ); |
return 0; |
} |
if ( dca != rca ) { |
printf( "\n-----------------------------\n" ); |
printf( "dca = 0x%02x rca = 0x%02x\n", dca, rca ); |
return 0; |
} |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
if ( dm[i] != rm[i] ) { |
GLfloat *c = source->start; |
STRIDE_F(c, source->stride * i); |
if (psize == 4 && xyz_close_to_w(c)) { |
/* The coordinate is very close to the clip plane. The clipmask |
* may vary depending on code path, but that's OK. |
*/ |
continue; |
} |
printf( "\n-----------------------------\n" ); |
printf( "mask[%d] = 0x%02x ref mask[%d] = 0x%02x\n", i, dm[i], i,rm[i] ); |
printf(" coord = %f, %f, %f, %f\n", |
c[0], c[1], c[2], c[3]); |
return 0; |
} |
} |
/* Only verify output on projected points4 case. FIXME: Do we need |
* to test other cases? |
*/ |
if ( np || psize < 4 ) |
return 1; |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
for ( j = 0 ; j < 4 ; j++ ) { |
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { |
printf( "\n-----------------------------\n" ); |
printf( "(i = %i, j = %i) dm = 0x%02x rm = 0x%02x\n", |
i, j, dm[i], rm[i] ); |
printf( "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][0], r[i][0], r[i][0]-d[i][0], |
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); |
printf( "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][1], r[i][1], r[i][1]-d[i][1], |
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); |
printf( "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][2], r[i][2], r[i][2]-d[i][2], |
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); |
printf( "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][3], r[i][3], r[i][3]-d[i][3], |
MAX_PRECISION - significand_match( d[i][3], r[i][3] ) ); |
return 0; |
} |
} |
} |
return 1; |
} |
void _math_test_all_cliptest_functions( char *description ) |
{ |
int np, psize; |
long benchmark_tab[2][4]; |
static int first_time = 1; |
if ( first_time ) { |
first_time = 0; |
mesa_profile = _mesa_getenv( "MESA_PROFILE" ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
if ( !counter_overhead ) { |
INIT_COUNTER(); |
printf( "counter overhead: %ld cycles\n\n", counter_overhead ); |
} |
printf( "cliptest results after hooking in %s functions:\n", description ); |
} |
#endif |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
printf( "\n\t" ); |
for ( psize = 2 ; psize <= 4 ; psize++ ) { |
printf( " p%d\t", psize ); |
} |
printf( "\n--------------------------------------------------------\n\t" ); |
} |
#endif |
for ( np = 0 ; np < 2 ; np++ ) { |
for ( psize = 2 ; psize <= 4 ; psize++ ) { |
clip_func func = clip_tab[np][psize]; |
long *cycles = &(benchmark_tab[np][psize-1]); |
if ( test_cliptest_function( func, np, psize, cycles ) == 0 ) { |
char buf[100]; |
sprintf( buf, "%s[%d] failed test (%s)", |
cnames[np], psize, description ); |
_mesa_problem( NULL, "%s", buf ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
printf( " %li\t", benchmark_tab[np][psize-1] ); |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
printf( " | [%s]\n\t", cstrings[np] ); |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
printf( "\n" ); |
#endif |
} |
#endif /* DEBUG_MATH */ |
/contrib/sdk/sources/Mesa/src/mesa/math/m_debug_norm.c |
---|
0,0 → 1,383 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2003 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
* |
* Authors: |
* Gareth Hughes |
*/ |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/imports.h" |
#include "m_matrix.h" |
#include "m_xform.h" |
#include "m_debug.h" |
#include "m_debug_util.h" |
#ifdef __UNIXOS2__ |
/* The linker doesn't like empty files */ |
static char dummy; |
#endif |
#ifdef DEBUG_MATH /* This code only used for debugging */ |
static int m_norm_identity[16] = { |
ONE, NIL, NIL, NIL, |
NIL, ONE, NIL, NIL, |
NIL, NIL, ONE, NIL, |
NIL, NIL, NIL, NIL |
}; |
static int m_norm_general[16] = { |
VAR, VAR, VAR, NIL, |
VAR, VAR, VAR, NIL, |
VAR, VAR, VAR, NIL, |
NIL, NIL, NIL, NIL |
}; |
static int m_norm_no_rot[16] = { |
VAR, NIL, NIL, NIL, |
NIL, VAR, NIL, NIL, |
NIL, NIL, VAR, NIL, |
NIL, NIL, NIL, NIL |
}; |
static int *norm_templates[8] = { |
m_norm_no_rot, |
m_norm_no_rot, |
m_norm_no_rot, |
m_norm_general, |
m_norm_general, |
m_norm_general, |
m_norm_identity, |
m_norm_identity |
}; |
static int norm_types[8] = { |
NORM_TRANSFORM_NO_ROT, |
NORM_TRANSFORM_NO_ROT | NORM_RESCALE, |
NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE, |
NORM_TRANSFORM, |
NORM_TRANSFORM | NORM_RESCALE, |
NORM_TRANSFORM | NORM_NORMALIZE, |
NORM_RESCALE, |
NORM_NORMALIZE |
}; |
static int norm_scale_types[8] = { /* rescale factor */ |
NIL, /* NIL disables rescaling */ |
VAR, |
NIL, |
NIL, |
VAR, |
NIL, |
VAR, |
NIL |
}; |
static int norm_normalize_types[8] = { /* normalizing ?? (no = 0) */ |
0, |
0, |
1, |
0, |
0, |
1, |
0, |
1 |
}; |
static char *norm_strings[8] = { |
"NORM_TRANSFORM_NO_ROT", |
"NORM_TRANSFORM_NO_ROT | NORM_RESCALE", |
"NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE", |
"NORM_TRANSFORM", |
"NORM_TRANSFORM | NORM_RESCALE", |
"NORM_TRANSFORM | NORM_NORMALIZE", |
"NORM_RESCALE", |
"NORM_NORMALIZE" |
}; |
/* ============================================================= |
* Reference transformations |
*/ |
static void ref_norm_transform_rescale( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLuint i; |
const GLfloat *s = in->start; |
const GLfloat *m = mat->inv; |
GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start; |
(void) lengths; |
for ( i = 0 ; i < in->count ; i++ ) { |
GLfloat t[3]; |
TRANSFORM_NORMAL( t, s, m ); |
SCALE_SCALAR_3V( out[i], scale, t ); |
s = (GLfloat *)((char *)s + in->stride); |
} |
} |
static void ref_norm_transform_normalize( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLuint i; |
const GLfloat *s = in->start; |
const GLfloat *m = mat->inv; |
GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start; |
for ( i = 0 ; i < in->count ; i++ ) { |
GLfloat t[3]; |
TRANSFORM_NORMAL( t, s, m ); |
if ( !lengths ) { |
GLfloat len = LEN_SQUARED_3FV( t ); |
if ( len > 1e-20 ) { |
/* Hmmm, don't know how we could test the precalculated |
* length case... |
*/ |
scale = INV_SQRTF( len ); |
SCALE_SCALAR_3V( out[i], scale, t ); |
} else { |
out[i][0] = out[i][1] = out[i][2] = 0; |
} |
} else { |
scale = lengths[i];; |
SCALE_SCALAR_3V( out[i], scale, t ); |
} |
s = (GLfloat *)((char *)s + in->stride); |
} |
} |
/* ============================================================= |
* Normal transformation tests |
*/ |
static void init_matrix( GLfloat *m ) |
{ |
m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0; |
m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0; |
m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0; |
m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0; |
} |
static int test_norm_function( normal_func func, int mtype, long *cycles ) |
{ |
GLvector4f source[1], dest[1], dest2[1], ref[1], ref2[1]; |
GLmatrix mat[1]; |
GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4]; |
GLfloat d2[TEST_COUNT][4], r2[TEST_COUNT][4], length[TEST_COUNT]; |
GLfloat scale; |
GLfloat *m; |
int i, j; |
#ifdef RUN_DEBUG_BENCHMARK |
int cycle_i; /* the counter for the benchmarks we run */ |
#endif |
(void) cycles; |
mat->m = _mesa_align_malloc( 16 * sizeof(GLfloat), 16 ); |
mat->inv = m = mat->m; |
init_matrix( m ); |
scale = 1.0F + rnd () * norm_scale_types[mtype]; |
for ( i = 0 ; i < 4 ; i++ ) { |
for ( j = 0 ; j < 4 ; j++ ) { |
switch ( norm_templates[mtype][i * 4 + j] ) { |
case NIL: |
m[j * 4 + i] = 0.0; |
break; |
case ONE: |
m[j * 4 + i] = 1.0; |
break; |
case NEG: |
m[j * 4 + i] = -1.0; |
break; |
case VAR: |
break; |
default: |
exit(1); |
} |
} |
} |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
ASSIGN_3V( d[i], 0.0, 0.0, 0.0 ); |
ASSIGN_3V( s[i], 0.0, 0.0, 0.0 ); |
ASSIGN_3V( d2[i], 0.0, 0.0, 0.0 ); |
for ( j = 0 ; j < 3 ; j++ ) |
s[i][j] = rnd(); |
length[i] = INV_SQRTF( LEN_SQUARED_3FV( s[i] ) ); |
} |
source->data = (GLfloat(*)[4]) s; |
source->start = (GLfloat *) s; |
source->count = TEST_COUNT; |
source->stride = sizeof(s[0]); |
source->flags = 0; |
dest->data = d; |
dest->start = (GLfloat *) d; |
dest->count = TEST_COUNT; |
dest->stride = sizeof(float[4]); |
dest->flags = 0; |
dest2->data = d2; |
dest2->start = (GLfloat *) d2; |
dest2->count = TEST_COUNT; |
dest2->stride = sizeof(float[4]); |
dest2->flags = 0; |
ref->data = r; |
ref->start = (GLfloat *) r; |
ref->count = TEST_COUNT; |
ref->stride = sizeof(float[4]); |
ref->flags = 0; |
ref2->data = r2; |
ref2->start = (GLfloat *) r2; |
ref2->count = TEST_COUNT; |
ref2->stride = sizeof(float[4]); |
ref2->flags = 0; |
if ( norm_normalize_types[mtype] == 0 ) { |
ref_norm_transform_rescale( mat, scale, source, NULL, ref ); |
} else { |
ref_norm_transform_normalize( mat, scale, source, NULL, ref ); |
ref_norm_transform_normalize( mat, scale, source, length, ref2 ); |
} |
if ( mesa_profile ) { |
BEGIN_RACE( *cycles ); |
func( mat, scale, source, NULL, dest ); |
END_RACE( *cycles ); |
func( mat, scale, source, length, dest2 ); |
} else { |
func( mat, scale, source, NULL, dest ); |
func( mat, scale, source, length, dest2 ); |
} |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
for ( j = 0 ; j < 3 ; j++ ) { |
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { |
printf( "-----------------------------\n" ); |
printf( "(i = %i, j = %i)\n", i, j ); |
printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d[i][0], r[i][0], r[i][0]/d[i][0], |
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); |
printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d[i][1], r[i][1], r[i][1]/d[i][1], |
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); |
printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d[i][2], r[i][2], r[i][2]/d[i][2], |
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); |
return 0; |
} |
if ( norm_normalize_types[mtype] != 0 ) { |
if ( significand_match( d2[i][j], r2[i][j] ) < REQUIRED_PRECISION ) { |
printf( "------------------- precalculated length case ------\n" ); |
printf( "(i = %i, j = %i)\n", i, j ); |
printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d2[i][0], r2[i][0], r2[i][0]/d2[i][0], |
MAX_PRECISION - significand_match( d2[i][0], r2[i][0] ) ); |
printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d2[i][1], r2[i][1], r2[i][1]/d2[i][1], |
MAX_PRECISION - significand_match( d2[i][1], r2[i][1] ) ); |
printf( "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d2[i][2], r2[i][2], r2[i][2]/d2[i][2], |
MAX_PRECISION - significand_match( d2[i][2], r2[i][2] ) ); |
return 0; |
} |
} |
} |
} |
_mesa_align_free( mat->m ); |
return 1; |
} |
void _math_test_all_normal_transform_functions( char *description ) |
{ |
int mtype; |
long benchmark_tab[0xf]; |
static int first_time = 1; |
if ( first_time ) { |
first_time = 0; |
mesa_profile = _mesa_getenv( "MESA_PROFILE" ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
if ( !counter_overhead ) { |
INIT_COUNTER(); |
printf( "counter overhead: %ld cycles\n\n", counter_overhead ); |
} |
printf( "normal transform results after hooking in %s functions:\n", |
description ); |
printf( "\n-------------------------------------------------------\n" ); |
} |
#endif |
for ( mtype = 0 ; mtype < 8 ; mtype++ ) { |
normal_func func = _mesa_normal_tab[norm_types[mtype]]; |
long *cycles = &benchmark_tab[mtype]; |
if ( test_norm_function( func, mtype, cycles ) == 0 ) { |
char buf[100]; |
sprintf( buf, "_mesa_normal_tab[0][%s] failed test (%s)", |
norm_strings[mtype], description ); |
_mesa_problem( NULL, "%s", buf ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
printf( " %li\t", benchmark_tab[mtype] ); |
printf( " | [%s]\n", norm_strings[mtype] ); |
} |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
printf( "\n" ); |
} |
#endif |
} |
#endif /* DEBUG_MATH */ |
/contrib/sdk/sources/Mesa/src/mesa/math/m_debug_util.h |
---|
0,0 → 1,320 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2004 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
* |
* Authors: |
* Gareth Hughes |
*/ |
#ifndef __M_DEBUG_UTIL_H__ |
#define __M_DEBUG_UTIL_H__ |
#ifdef DEBUG_MATH /* This code only used for debugging */ |
/* Comment this out to deactivate the cycle counter. |
* NOTE: it works only on CPUs which know the 'rdtsc' command (586 or higher) |
* (hope, you don't try to debug Mesa on a 386 ;) |
*/ |
#if defined(__GNUC__) && \ |
((defined(__i386__) && defined(USE_X86_ASM)) || \ |
(defined(__sparc__) && defined(USE_SPARC_ASM))) |
#define RUN_DEBUG_BENCHMARK |
#endif |
#define TEST_COUNT 128 /* size of the tested vector array */ |
#define REQUIRED_PRECISION 10 /* allow 4 bits to miss */ |
#define MAX_PRECISION 24 /* max. precision possible */ |
#ifdef RUN_DEBUG_BENCHMARK |
/* Overhead of profiling counter in cycles. Automatically adjusted to |
* your machine at run time - counter initialization should give very |
* consistent results. |
*/ |
extern long counter_overhead; |
/* This is the value of the environment variable MESA_PROFILE, and is |
* used to determine if we should benchmark the functions as well as |
* verify their correctness. |
*/ |
extern char *mesa_profile; |
/* Modify the number of tests if you like. |
* We take the minimum of all results, because every error should be |
* positive (time used by other processes, task switches etc). |
* It is assumed that all calculations are done in the cache. |
*/ |
#if defined(__i386__) |
#if 1 /* PPro, PII, PIII version */ |
/* Profiling on the P6 architecture requires a little more work, due to |
* the internal out-of-order execution. We must perform a serializing |
* 'cpuid' instruction before and after the 'rdtsc' instructions to make |
* sure no other uops are executed when we sample the timestamp counter. |
*/ |
#define INIT_COUNTER() \ |
do { \ |
int cycle_i; \ |
counter_overhead = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 8 ; cycle_i++ ) { \ |
long cycle_tmp1 = 0, cycle_tmp2 = 0; \ |
__asm__ __volatile__ ( "push %%ebx \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"rdtsc \n" \ |
"mov %%eax, %0 \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"pop %%ebx \n" \ |
"push %%ebx \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"rdtsc \n" \ |
"mov %%eax, %1 \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"pop %%ebx \n" \ |
: "=m" (cycle_tmp1), "=m" (cycle_tmp2) \ |
: : "eax", "ecx", "edx" ); \ |
if ( counter_overhead > (cycle_tmp2 - cycle_tmp1) ) { \ |
counter_overhead = cycle_tmp2 - cycle_tmp1; \ |
} \ |
} \ |
} while (0) |
#define BEGIN_RACE(x) \ |
x = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 10 ; cycle_i++ ) { \ |
long cycle_tmp1 = 0, cycle_tmp2 = 0; \ |
__asm__ __volatile__ ( "push %%ebx \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"rdtsc \n" \ |
"mov %%eax, %0 \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"pop %%ebx \n" \ |
: "=m" (cycle_tmp1) \ |
: : "eax", "ecx", "edx" ); |
#define END_RACE(x) \ |
__asm__ __volatile__ ( "push %%ebx \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"rdtsc \n" \ |
"mov %%eax, %0 \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"pop %%ebx \n" \ |
: "=m" (cycle_tmp2) \ |
: : "eax", "ecx", "edx" ); \ |
if ( x > (cycle_tmp2 - cycle_tmp1) ) { \ |
x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
} \ |
x -= counter_overhead; |
#else /* PPlain, PMMX version */ |
/* To ensure accurate results, we stall the pipelines with the |
* non-pairable 'cdq' instruction. This ensures all the code being |
* profiled is complete when the 'rdtsc' instruction executes. |
*/ |
#define INIT_COUNTER(x) \ |
do { \ |
int cycle_i; \ |
x = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 32 ; cycle_i++ ) { \ |
long cycle_tmp1, cycle_tmp2, dummy; \ |
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp1) ); \ |
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp2) ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "rdtsc" : "=a" (cycle_tmp1), "=d" (dummy) ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "rdtsc" : "=a" (cycle_tmp2), "=d" (dummy) ); \ |
if ( x > (cycle_tmp2 - cycle_tmp1) ) \ |
x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
} while (0) |
#define BEGIN_RACE(x) \ |
x = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 16 ; cycle_i++ ) { \ |
long cycle_tmp1, cycle_tmp2, dummy; \ |
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp1) ); \ |
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp2) ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "rdtsc" : "=a" (cycle_tmp1), "=d" (dummy) ); |
#define END_RACE(x) \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "rdtsc" : "=a" (cycle_tmp2), "=d" (dummy) ); \ |
if ( x > (cycle_tmp2 - cycle_tmp1) ) \ |
x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
x -= counter_overhead; |
#endif |
#elif defined(__x86_64__) |
#define rdtscll(val) do { \ |
unsigned int a,d; \ |
__asm__ volatile("rdtsc" : "=a" (a), "=d" (d)); \ |
(val) = ((unsigned long)a) | (((unsigned long)d)<<32); \ |
} while(0) |
/* Copied from i386 PIII version */ |
#define INIT_COUNTER() \ |
do { \ |
int cycle_i; \ |
counter_overhead = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 16 ; cycle_i++ ) { \ |
unsigned long cycle_tmp1, cycle_tmp2; \ |
rdtscll(cycle_tmp1); \ |
rdtscll(cycle_tmp2); \ |
if ( counter_overhead > (cycle_tmp2 - cycle_tmp1) ) { \ |
counter_overhead = cycle_tmp2 - cycle_tmp1; \ |
} \ |
} \ |
} while (0) |
#define BEGIN_RACE(x) \ |
x = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 10 ; cycle_i++ ) { \ |
unsigned long cycle_tmp1, cycle_tmp2; \ |
rdtscll(cycle_tmp1); \ |
#define END_RACE(x) \ |
rdtscll(cycle_tmp2); \ |
if ( x > (cycle_tmp2 - cycle_tmp1) ) { \ |
x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
} \ |
x -= counter_overhead; |
#elif defined(__sparc__) |
#define INIT_COUNTER() \ |
do { counter_overhead = 5; } while(0) |
#define BEGIN_RACE(x) \ |
x = LONG_MAX; \ |
for (cycle_i = 0; cycle_i <10; cycle_i++) { \ |
register long cycle_tmp1 __asm__("l0"); \ |
register long cycle_tmp2 __asm__("l1"); \ |
/* rd %tick, %l0 */ \ |
__asm__ __volatile__ (".word 0xa1410000" : "=r" (cycle_tmp1)); /* save timestamp */ |
#define END_RACE(x) \ |
/* rd %tick, %l1 */ \ |
__asm__ __volatile__ (".word 0xa3410000" : "=r" (cycle_tmp2)); \ |
if (x > (cycle_tmp2-cycle_tmp1)) x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
x -= counter_overhead; |
#else |
#error Your processor is not supported for RUN_XFORM_BENCHMARK |
#endif |
#else |
#define BEGIN_RACE(x) |
#define END_RACE(x) |
#endif |
/* ============================================================= |
* Helper functions |
*/ |
static GLfloat rnd( void ) |
{ |
GLfloat f = (GLfloat)rand() / (GLfloat)RAND_MAX; |
GLfloat gran = (GLfloat)(1 << 13); |
f = (GLfloat)(GLint)(f * gran) / gran; |
return f * 2.0 - 1.0; |
} |
static int significand_match( GLfloat a, GLfloat b ) |
{ |
GLfloat d = a - b; |
int a_ex, b_ex, d_ex; |
if ( d == 0.0F ) { |
return MAX_PRECISION; /* Exact match */ |
} |
if ( a == 0.0F || b == 0.0F ) { |
/* It would probably be better to check if the |
* non-zero number is denormalized and return |
* the index of the highest set bit here. |
*/ |
return 0; |
} |
FREXPF( a, &a_ex ); |
FREXPF( b, &b_ex ); |
FREXPF( d, &d_ex ); |
if ( a_ex < b_ex ) { |
return a_ex - d_ex; |
} else { |
return b_ex - d_ex; |
} |
} |
enum { NIL = 0, ONE = 1, NEG = -1, VAR = 2 }; |
/* Ensure our arrays are correctly aligned. |
*/ |
#if defined(__GNUC__) |
# define ALIGN16(type, array) type array __attribute__ ((aligned (16))) |
#elif defined(_MSC_VER) |
# define ALIGN16(type, array) type array __declspec(align(16)) /* GH: Does this work? */ |
#elif defined(__WATCOMC__) |
# define ALIGN16(type, array) /* Watcom does not support this */ |
#elif defined(__xlC__) |
# define ALIGN16(type, array) type __align (16) array |
#else |
# warning "ALIGN16 will not 16-byte align!\n" |
# define ALIGN16 |
#endif |
#endif /* DEBUG_MATH */ |
#endif /* __M_DEBUG_UTIL_H__ */ |
/contrib/sdk/sources/Mesa/src/mesa/math/m_debug_xform.c |
---|
0,0 → 1,339 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2004 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/* |
* Updated for P6 architecture by Gareth Hughes. |
*/ |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/imports.h" |
#include "m_matrix.h" |
#include "m_xform.h" |
#include "m_debug.h" |
#include "m_debug_util.h" |
#ifdef __UNIXOS2__ |
/* The linker doesn't like empty files */ |
static char dummy; |
#endif |
#ifdef DEBUG_MATH /* This code only used for debugging */ |
/* Overhead of profiling counter in cycles. Automatically adjusted to |
* your machine at run time - counter initialization should give very |
* consistent results. |
*/ |
long counter_overhead = 0; |
/* This is the value of the environment variable MESA_PROFILE, and is |
* used to determine if we should benchmark the functions as well as |
* verify their correctness. |
*/ |
char *mesa_profile = NULL; |
static int m_general[16] = { |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR |
}; |
static int m_identity[16] = { |
ONE, NIL, NIL, NIL, |
NIL, ONE, NIL, NIL, |
NIL, NIL, ONE, NIL, |
NIL, NIL, NIL, ONE |
}; |
static int m_2d[16] = { |
VAR, VAR, NIL, VAR, |
VAR, VAR, NIL, VAR, |
NIL, NIL, ONE, NIL, |
NIL, NIL, NIL, ONE |
}; |
static int m_2d_no_rot[16] = { |
VAR, NIL, NIL, VAR, |
NIL, VAR, NIL, VAR, |
NIL, NIL, ONE, NIL, |
NIL, NIL, NIL, ONE |
}; |
static int m_3d[16] = { |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR, |
NIL, NIL, NIL, ONE |
}; |
static int m_3d_no_rot[16] = { |
VAR, NIL, NIL, VAR, |
NIL, VAR, NIL, VAR, |
NIL, NIL, VAR, VAR, |
NIL, NIL, NIL, ONE |
}; |
static int m_perspective[16] = { |
VAR, NIL, VAR, NIL, |
NIL, VAR, VAR, NIL, |
NIL, NIL, VAR, VAR, |
NIL, NIL, NEG, NIL |
}; |
static int *templates[7] = { |
m_general, |
m_identity, |
m_3d_no_rot, |
m_perspective, |
m_2d, |
m_2d_no_rot, |
m_3d |
}; |
static enum GLmatrixtype mtypes[7] = { |
MATRIX_GENERAL, |
MATRIX_IDENTITY, |
MATRIX_3D_NO_ROT, |
MATRIX_PERSPECTIVE, |
MATRIX_2D, |
MATRIX_2D_NO_ROT, |
MATRIX_3D |
}; |
static char *mstrings[7] = { |
"MATRIX_GENERAL", |
"MATRIX_IDENTITY", |
"MATRIX_3D_NO_ROT", |
"MATRIX_PERSPECTIVE", |
"MATRIX_2D", |
"MATRIX_2D_NO_ROT", |
"MATRIX_3D" |
}; |
/* ============================================================= |
* Reference transformations |
*/ |
static void ref_transform( GLvector4f *dst, |
const GLmatrix *mat, |
const GLvector4f *src ) |
{ |
GLuint i; |
GLfloat *s = (GLfloat *)src->start; |
GLfloat (*d)[4] = (GLfloat (*)[4])dst->start; |
const GLfloat *m = mat->m; |
for ( i = 0 ; i < src->count ; i++ ) { |
TRANSFORM_POINT( d[i], m, s ); |
s = (GLfloat *)((char *)s + src->stride); |
} |
} |
/* ============================================================= |
* Vertex transformation tests |
*/ |
static void init_matrix( GLfloat *m ) |
{ |
m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0; |
m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0; |
m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0; |
m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0; |
} |
ALIGN16(static GLfloat, s[TEST_COUNT][4]); |
ALIGN16(static GLfloat, d[TEST_COUNT][4]); |
ALIGN16(static GLfloat, r[TEST_COUNT][4]); |
static int test_transform_function( transform_func func, int psize, |
int mtype, unsigned long *cycles ) |
{ |
GLvector4f source[1], dest[1], ref[1]; |
GLmatrix mat[1]; |
GLfloat *m; |
int i, j; |
#ifdef RUN_DEBUG_BENCHMARK |
int cycle_i; /* the counter for the benchmarks we run */ |
#endif |
(void) cycles; |
if ( psize > 4 ) { |
_mesa_problem( NULL, "test_transform_function called with psize > 4\n" ); |
return 0; |
} |
mat->m = _mesa_align_malloc( 16 * sizeof(GLfloat), 16 ); |
mat->type = mtypes[mtype]; |
m = mat->m; |
ASSERT( ((long)m & 15) == 0 ); |
init_matrix( m ); |
for ( i = 0 ; i < 4 ; i++ ) { |
for ( j = 0 ; j < 4 ; j++ ) { |
switch ( templates[mtype][i * 4 + j] ) { |
case NIL: |
m[j * 4 + i] = 0.0; |
break; |
case ONE: |
m[j * 4 + i] = 1.0; |
break; |
case NEG: |
m[j * 4 + i] = -1.0; |
break; |
case VAR: |
break; |
default: |
ASSERT(0); |
return 0; |
} |
} |
} |
for ( i = 0 ; i < TEST_COUNT ; i++) { |
ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 ); |
ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 ); |
for ( j = 0 ; j < psize ; j++ ) |
s[i][j] = rnd(); |
} |
source->data = (GLfloat(*)[4])s; |
source->start = (GLfloat *)s; |
source->count = TEST_COUNT; |
source->stride = sizeof(s[0]); |
source->size = 4; |
source->flags = 0; |
dest->data = (GLfloat(*)[4])d; |
dest->start = (GLfloat *)d; |
dest->count = TEST_COUNT; |
dest->stride = sizeof(float[4]); |
dest->size = 0; |
dest->flags = 0; |
ref->data = (GLfloat(*)[4])r; |
ref->start = (GLfloat *)r; |
ref->count = TEST_COUNT; |
ref->stride = sizeof(float[4]); |
ref->size = 0; |
ref->flags = 0; |
ref_transform( ref, mat, source ); |
if ( mesa_profile ) { |
BEGIN_RACE( *cycles ); |
func( dest, mat->m, source ); |
END_RACE( *cycles ); |
} |
else { |
func( dest, mat->m, source ); |
} |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
for ( j = 0 ; j < 4 ; j++ ) { |
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { |
printf("-----------------------------\n" ); |
printf("(i = %i, j = %i)\n", i, j ); |
printf("%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][0], r[i][0], r[i][0]-d[i][0], |
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); |
printf("%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][1], r[i][1], r[i][1]-d[i][1], |
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); |
printf("%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][2], r[i][2], r[i][2]-d[i][2], |
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); |
printf("%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][3], r[i][3], r[i][3]-d[i][3], |
MAX_PRECISION - significand_match( d[i][3], r[i][3] ) ); |
return 0; |
} |
} |
} |
_mesa_align_free( mat->m ); |
return 1; |
} |
void _math_test_all_transform_functions( char *description ) |
{ |
int psize, mtype; |
unsigned long benchmark_tab[4][7]; |
static int first_time = 1; |
if ( first_time ) { |
first_time = 0; |
mesa_profile = _mesa_getenv( "MESA_PROFILE" ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
if ( !counter_overhead ) { |
INIT_COUNTER(); |
printf("counter overhead: %lu cycles\n\n", counter_overhead ); |
} |
printf("transform results after hooking in %s functions:\n", description ); |
} |
#endif |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
printf("\n" ); |
for ( psize = 1 ; psize <= 4 ; psize++ ) { |
printf(" p%d\t", psize ); |
} |
printf("\n--------------------------------------------------------\n" ); |
} |
#endif |
for ( mtype = 0 ; mtype < 7 ; mtype++ ) { |
for ( psize = 1 ; psize <= 4 ; psize++ ) { |
transform_func func = _mesa_transform_tab[psize][mtypes[mtype]]; |
unsigned long *cycles = &(benchmark_tab[psize-1][mtype]); |
if ( test_transform_function( func, psize, mtype, cycles ) == 0 ) { |
char buf[100]; |
sprintf(buf, "_mesa_transform_tab[0][%d][%s] failed test (%s)", |
psize, mstrings[mtype], description ); |
_mesa_problem( NULL, "%s", buf ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
printf(" %li\t", benchmark_tab[psize-1][mtype] ); |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
printf(" | [%s]\n", mstrings[mtype] ); |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
printf( "\n" ); |
#endif |
} |
#endif /* DEBUG_MATH */ |
/contrib/sdk/sources/Mesa/src/mesa/math/m_dotprod_tmp.h |
---|
0,0 → 1,102 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2001 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/* Note - respects the stride of the output vector. |
*/ |
static void TAG(dotprod_vec2)( GLfloat *out, |
GLuint outstride, |
const GLvector4f *coord_vec, |
const GLfloat plane[4] ) |
{ |
GLuint stride = coord_vec->stride; |
GLfloat *coord = coord_vec->start; |
GLuint count = coord_vec->count; |
GLuint i; |
const GLfloat plane0 = plane[0], plane1 = plane[1], plane3 = plane[3]; |
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) { |
*out = (coord[0] * plane0 + |
coord[1] * plane1 + |
plane3); |
} |
} |
static void TAG(dotprod_vec3)( GLfloat *out, |
GLuint outstride, |
const GLvector4f *coord_vec, |
const GLfloat plane[4] ) |
{ |
GLuint stride = coord_vec->stride; |
GLfloat *coord = coord_vec->start; |
GLuint count = coord_vec->count; |
GLuint i; |
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2]; |
const GLfloat plane3 = plane[3]; |
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) { |
*out = (coord[0] * plane0 + |
coord[1] * plane1 + |
coord[2] * plane2 + |
plane3); |
} |
} |
static void TAG(dotprod_vec4)( GLfloat *out, |
GLuint outstride, |
const GLvector4f *coord_vec, |
const GLfloat plane[4] ) |
{ |
GLuint stride = coord_vec->stride; |
GLfloat *coord = coord_vec->start; |
GLuint count = coord_vec->count; |
GLuint i; |
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2]; |
const GLfloat plane3 = plane[3]; |
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) { |
*out = (coord[0] * plane0 + |
coord[1] * plane1 + |
coord[2] * plane2 + |
coord[3] * plane3); |
} |
} |
static void TAG(init_dotprod)( void ) |
{ |
_mesa_dotprod_tab[2] = TAG(dotprod_vec2); |
_mesa_dotprod_tab[3] = TAG(dotprod_vec3); |
_mesa_dotprod_tab[4] = TAG(dotprod_vec4); |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_eval.c |
---|
0,0 → 1,461 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2001 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/* |
* eval.c was written by |
* Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and |
* Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de). |
* |
* My original implementation of evaluators was simplistic and didn't |
* compute surface normal vectors properly. Bernd and Volker applied |
* used more sophisticated methods to get better results. |
* |
* Thanks guys! |
*/ |
#include "main/glheader.h" |
#include "main/config.h" |
#include "m_eval.h" |
static GLfloat inv_tab[MAX_EVAL_ORDER]; |
/* |
* Horner scheme for Bezier curves |
* |
* Bezier curves can be computed via a Horner scheme. |
* Horner is numerically less stable than the de Casteljau |
* algorithm, but it is faster. For curves of degree n |
* the complexity of Horner is O(n) and de Casteljau is O(n^2). |
* Since stability is not important for displaying curve |
* points I decided to use the Horner scheme. |
* |
* A cubic Bezier curve with control points b0, b1, b2, b3 can be |
* written as |
* |
* (([3] [3] ) [3] ) [3] |
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3 |
* |
* [n] |
* where s=1-t and the binomial coefficients [i]. These can |
* be computed iteratively using the identity: |
* |
* [n] [n ] [n] |
* [i] = (n-i+1)/i * [i-1] and [0] = 1 |
*/ |
void |
_math_horner_bezier_curve(const GLfloat * cp, GLfloat * out, GLfloat t, |
GLuint dim, GLuint order) |
{ |
GLfloat s, powert, bincoeff; |
GLuint i, k; |
if (order >= 2) { |
bincoeff = (GLfloat) (order - 1); |
s = 1.0F - t; |
for (k = 0; k < dim; k++) |
out[k] = s * cp[k] + bincoeff * t * cp[dim + k]; |
for (i = 2, cp += 2 * dim, powert = t * t; i < order; |
i++, powert *= t, cp += dim) { |
bincoeff *= (GLfloat) (order - i); |
bincoeff *= inv_tab[i]; |
for (k = 0; k < dim; k++) |
out[k] = s * out[k] + bincoeff * powert * cp[k]; |
} |
} |
else { /* order=1 -> constant curve */ |
for (k = 0; k < dim; k++) |
out[k] = cp[k]; |
} |
} |
/* |
* Tensor product Bezier surfaces |
* |
* Again the Horner scheme is used to compute a point on a |
* TP Bezier surface. First a control polygon for a curve |
* on the surface in one parameter direction is computed, |
* then the point on the curve for the other parameter |
* direction is evaluated. |
* |
* To store the curve control polygon additional storage |
* for max(uorder,vorder) points is needed in the |
* control net cn. |
*/ |
void |
_math_horner_bezier_surf(GLfloat * cn, GLfloat * out, GLfloat u, GLfloat v, |
GLuint dim, GLuint uorder, GLuint vorder) |
{ |
GLfloat *cp = cn + uorder * vorder * dim; |
GLuint i, uinc = vorder * dim; |
if (vorder > uorder) { |
if (uorder >= 2) { |
GLfloat s, poweru, bincoeff; |
GLuint j, k; |
/* Compute the control polygon for the surface-curve in u-direction */ |
for (j = 0; j < vorder; j++) { |
GLfloat *ucp = &cn[j * dim]; |
/* Each control point is the point for parameter u on a */ |
/* curve defined by the control polygons in u-direction */ |
bincoeff = (GLfloat) (uorder - 1); |
s = 1.0F - u; |
for (k = 0; k < dim; k++) |
cp[j * dim + k] = s * ucp[k] + bincoeff * u * ucp[uinc + k]; |
for (i = 2, ucp += 2 * uinc, poweru = u * u; i < uorder; |
i++, poweru *= u, ucp += uinc) { |
bincoeff *= (GLfloat) (uorder - i); |
bincoeff *= inv_tab[i]; |
for (k = 0; k < dim; k++) |
cp[j * dim + k] = |
s * cp[j * dim + k] + bincoeff * poweru * ucp[k]; |
} |
} |
/* Evaluate curve point in v */ |
_math_horner_bezier_curve(cp, out, v, dim, vorder); |
} |
else /* uorder=1 -> cn defines a curve in v */ |
_math_horner_bezier_curve(cn, out, v, dim, vorder); |
} |
else { /* vorder <= uorder */ |
if (vorder > 1) { |
GLuint i; |
/* Compute the control polygon for the surface-curve in u-direction */ |
for (i = 0; i < uorder; i++, cn += uinc) { |
/* For constant i all cn[i][j] (j=0..vorder) are located */ |
/* on consecutive memory locations, so we can use */ |
/* horner_bezier_curve to compute the control points */ |
_math_horner_bezier_curve(cn, &cp[i * dim], v, dim, vorder); |
} |
/* Evaluate curve point in u */ |
_math_horner_bezier_curve(cp, out, u, dim, uorder); |
} |
else /* vorder=1 -> cn defines a curve in u */ |
_math_horner_bezier_curve(cn, out, u, dim, uorder); |
} |
} |
/* |
* The direct de Casteljau algorithm is used when a point on the |
* surface and the tangent directions spanning the tangent plane |
* should be computed (this is needed to compute normals to the |
* surface). In this case the de Casteljau algorithm approach is |
* nicer because a point and the partial derivatives can be computed |
* at the same time. To get the correct tangent length du and dv |
* must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1. |
* Since only the directions are needed, this scaling step is omitted. |
* |
* De Casteljau needs additional storage for uorder*vorder |
* values in the control net cn. |
*/ |
void |
_math_de_casteljau_surf(GLfloat * cn, GLfloat * out, GLfloat * du, |
GLfloat * dv, GLfloat u, GLfloat v, GLuint dim, |
GLuint uorder, GLuint vorder) |
{ |
GLfloat *dcn = cn + uorder * vorder * dim; |
GLfloat us = 1.0F - u, vs = 1.0F - v; |
GLuint h, i, j, k; |
GLuint minorder = uorder < vorder ? uorder : vorder; |
GLuint uinc = vorder * dim; |
GLuint dcuinc = vorder; |
/* Each component is evaluated separately to save buffer space */ |
/* This does not drasticaly decrease the performance of the */ |
/* algorithm. If additional storage for (uorder-1)*(vorder-1) */ |
/* points would be available, the components could be accessed */ |
/* in the innermost loop which could lead to less cache misses. */ |
#define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)] |
#define DCN(I, J) dcn[(I)*dcuinc+(J)] |
if (minorder < 3) { |
if (uorder == vorder) { |
for (k = 0; k < dim; k++) { |
/* Derivative direction in u */ |
du[k] = vs * (CN(1, 0, k) - CN(0, 0, k)) + |
v * (CN(1, 1, k) - CN(0, 1, k)); |
/* Derivative direction in v */ |
dv[k] = us * (CN(0, 1, k) - CN(0, 0, k)) + |
u * (CN(1, 1, k) - CN(1, 0, k)); |
/* bilinear de Casteljau step */ |
out[k] = us * (vs * CN(0, 0, k) + v * CN(0, 1, k)) + |
u * (vs * CN(1, 0, k) + v * CN(1, 1, k)); |
} |
} |
else if (minorder == uorder) { |
for (k = 0; k < dim; k++) { |
/* bilinear de Casteljau step */ |
DCN(1, 0) = CN(1, 0, k) - CN(0, 0, k); |
DCN(0, 0) = us * CN(0, 0, k) + u * CN(1, 0, k); |
for (j = 0; j < vorder - 1; j++) { |
/* for the derivative in u */ |
DCN(1, j + 1) = CN(1, j + 1, k) - CN(0, j + 1, k); |
DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1); |
/* for the `point' */ |
DCN(0, j + 1) = us * CN(0, j + 1, k) + u * CN(1, j + 1, k); |
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); |
} |
/* remaining linear de Casteljau steps until the second last step */ |
for (h = minorder; h < vorder - 1; h++) |
for (j = 0; j < vorder - h; j++) { |
/* for the derivative in u */ |
DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1); |
/* for the `point' */ |
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); |
} |
/* derivative direction in v */ |
dv[k] = DCN(0, 1) - DCN(0, 0); |
/* derivative direction in u */ |
du[k] = vs * DCN(1, 0) + v * DCN(1, 1); |
/* last linear de Casteljau step */ |
out[k] = vs * DCN(0, 0) + v * DCN(0, 1); |
} |
} |
else { /* minorder == vorder */ |
for (k = 0; k < dim; k++) { |
/* bilinear de Casteljau step */ |
DCN(0, 1) = CN(0, 1, k) - CN(0, 0, k); |
DCN(0, 0) = vs * CN(0, 0, k) + v * CN(0, 1, k); |
for (i = 0; i < uorder - 1; i++) { |
/* for the derivative in v */ |
DCN(i + 1, 1) = CN(i + 1, 1, k) - CN(i + 1, 0, k); |
DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1); |
/* for the `point' */ |
DCN(i + 1, 0) = vs * CN(i + 1, 0, k) + v * CN(i + 1, 1, k); |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
} |
/* remaining linear de Casteljau steps until the second last step */ |
for (h = minorder; h < uorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
/* for the derivative in v */ |
DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1); |
/* for the `point' */ |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
} |
/* derivative direction in u */ |
du[k] = DCN(1, 0) - DCN(0, 0); |
/* derivative direction in v */ |
dv[k] = us * DCN(0, 1) + u * DCN(1, 1); |
/* last linear de Casteljau step */ |
out[k] = us * DCN(0, 0) + u * DCN(1, 0); |
} |
} |
} |
else if (uorder == vorder) { |
for (k = 0; k < dim; k++) { |
/* first bilinear de Casteljau step */ |
for (i = 0; i < uorder - 1; i++) { |
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); |
for (j = 0; j < vorder - 1; j++) { |
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* remaining bilinear de Casteljau steps until the second last step */ |
for (h = 2; h < minorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
for (j = 0; j < vorder - h; j++) { |
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* derivative direction in u */ |
du[k] = vs * (DCN(1, 0) - DCN(0, 0)) + v * (DCN(1, 1) - DCN(0, 1)); |
/* derivative direction in v */ |
dv[k] = us * (DCN(0, 1) - DCN(0, 0)) + u * (DCN(1, 1) - DCN(1, 0)); |
/* last bilinear de Casteljau step */ |
out[k] = us * (vs * DCN(0, 0) + v * DCN(0, 1)) + |
u * (vs * DCN(1, 0) + v * DCN(1, 1)); |
} |
} |
else if (minorder == uorder) { |
for (k = 0; k < dim; k++) { |
/* first bilinear de Casteljau step */ |
for (i = 0; i < uorder - 1; i++) { |
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); |
for (j = 0; j < vorder - 1; j++) { |
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* remaining bilinear de Casteljau steps until the second last step */ |
for (h = 2; h < minorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
for (j = 0; j < vorder - h; j++) { |
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* last bilinear de Casteljau step */ |
DCN(2, 0) = DCN(1, 0) - DCN(0, 0); |
DCN(0, 0) = us * DCN(0, 0) + u * DCN(1, 0); |
for (j = 0; j < vorder - 1; j++) { |
/* for the derivative in u */ |
DCN(2, j + 1) = DCN(1, j + 1) - DCN(0, j + 1); |
DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1); |
/* for the `point' */ |
DCN(0, j + 1) = us * DCN(0, j + 1) + u * DCN(1, j + 1); |
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); |
} |
/* remaining linear de Casteljau steps until the second last step */ |
for (h = minorder; h < vorder - 1; h++) |
for (j = 0; j < vorder - h; j++) { |
/* for the derivative in u */ |
DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1); |
/* for the `point' */ |
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); |
} |
/* derivative direction in v */ |
dv[k] = DCN(0, 1) - DCN(0, 0); |
/* derivative direction in u */ |
du[k] = vs * DCN(2, 0) + v * DCN(2, 1); |
/* last linear de Casteljau step */ |
out[k] = vs * DCN(0, 0) + v * DCN(0, 1); |
} |
} |
else { /* minorder == vorder */ |
for (k = 0; k < dim; k++) { |
/* first bilinear de Casteljau step */ |
for (i = 0; i < uorder - 1; i++) { |
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); |
for (j = 0; j < vorder - 1; j++) { |
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* remaining bilinear de Casteljau steps until the second last step */ |
for (h = 2; h < minorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
for (j = 0; j < vorder - h; j++) { |
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* last bilinear de Casteljau step */ |
DCN(0, 2) = DCN(0, 1) - DCN(0, 0); |
DCN(0, 0) = vs * DCN(0, 0) + v * DCN(0, 1); |
for (i = 0; i < uorder - 1; i++) { |
/* for the derivative in v */ |
DCN(i + 1, 2) = DCN(i + 1, 1) - DCN(i + 1, 0); |
DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2); |
/* for the `point' */ |
DCN(i + 1, 0) = vs * DCN(i + 1, 0) + v * DCN(i + 1, 1); |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
} |
/* remaining linear de Casteljau steps until the second last step */ |
for (h = minorder; h < uorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
/* for the derivative in v */ |
DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2); |
/* for the `point' */ |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
} |
/* derivative direction in u */ |
du[k] = DCN(1, 0) - DCN(0, 0); |
/* derivative direction in v */ |
dv[k] = us * DCN(0, 2) + u * DCN(1, 2); |
/* last linear de Casteljau step */ |
out[k] = us * DCN(0, 0) + u * DCN(1, 0); |
} |
} |
#undef DCN |
#undef CN |
} |
/* |
* Do one-time initialization for evaluators. |
*/ |
void |
_math_init_eval(void) |
{ |
GLuint i; |
/* KW: precompute 1/x for useful x. |
*/ |
for (i = 1; i < MAX_EVAL_ORDER; i++) |
inv_tab[i] = 1.0F / i; |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_eval.h |
---|
0,0 → 1,103 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2001 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
#ifndef _M_EVAL_H |
#define _M_EVAL_H |
#include "main/glheader.h" |
void _math_init_eval( void ); |
/* |
* Horner scheme for Bezier curves |
* |
* Bezier curves can be computed via a Horner scheme. |
* Horner is numerically less stable than the de Casteljau |
* algorithm, but it is faster. For curves of degree n |
* the complexity of Horner is O(n) and de Casteljau is O(n^2). |
* Since stability is not important for displaying curve |
* points I decided to use the Horner scheme. |
* |
* A cubic Bezier curve with control points b0, b1, b2, b3 can be |
* written as |
* |
* (([3] [3] ) [3] ) [3] |
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3 |
* |
* [n] |
* where s=1-t and the binomial coefficients [i]. These can |
* be computed iteratively using the identity: |
* |
* [n] [n ] [n] |
* [i] = (n-i+1)/i * [i-1] and [0] = 1 |
*/ |
void |
_math_horner_bezier_curve(const GLfloat *cp, GLfloat *out, GLfloat t, |
GLuint dim, GLuint order); |
/* |
* Tensor product Bezier surfaces |
* |
* Again the Horner scheme is used to compute a point on a |
* TP Bezier surface. First a control polygon for a curve |
* on the surface in one parameter direction is computed, |
* then the point on the curve for the other parameter |
* direction is evaluated. |
* |
* To store the curve control polygon additional storage |
* for max(uorder,vorder) points is needed in the |
* control net cn. |
*/ |
void |
_math_horner_bezier_surf(GLfloat *cn, GLfloat *out, GLfloat u, GLfloat v, |
GLuint dim, GLuint uorder, GLuint vorder); |
/* |
* The direct de Casteljau algorithm is used when a point on the |
* surface and the tangent directions spanning the tangent plane |
* should be computed (this is needed to compute normals to the |
* surface). In this case the de Casteljau algorithm approach is |
* nicer because a point and the partial derivatives can be computed |
* at the same time. To get the correct tangent length du and dv |
* must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1. |
* Since only the directions are needed, this scaling step is omitted. |
* |
* De Casteljau needs additional storage for uorder*vorder |
* values in the control net cn. |
*/ |
void |
_math_de_casteljau_surf(GLfloat *cn, GLfloat *out, GLfloat *du, GLfloat *dv, |
GLfloat u, GLfloat v, GLuint dim, |
GLuint uorder, GLuint vorder); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/math/m_matrix.c |
---|
0,0 → 1,1611 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2005 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/** |
* \file m_matrix.c |
* Matrix operations. |
* |
* \note |
* -# 4x4 transformation matrices are stored in memory in column major order. |
* -# Points/vertices are to be thought of as column vectors. |
* -# Transformation of a point p by a matrix M is: p' = M * p |
*/ |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "m_matrix.h" |
/** |
* \defgroup MatFlags MAT_FLAG_XXX-flags |
* |
* Bitmasks to indicate different kinds of 4x4 matrices in GLmatrix::flags |
*/ |
/*@{*/ |
#define MAT_FLAG_IDENTITY 0 /**< is an identity matrix flag. |
* (Not actually used - the identity |
* matrix is identified by the absense |
* of all other flags.) |
*/ |
#define MAT_FLAG_GENERAL 0x1 /**< is a general matrix flag */ |
#define MAT_FLAG_ROTATION 0x2 /**< is a rotation matrix flag */ |
#define MAT_FLAG_TRANSLATION 0x4 /**< is a translation matrix flag */ |
#define MAT_FLAG_UNIFORM_SCALE 0x8 /**< is an uniform scaling matrix flag */ |
#define MAT_FLAG_GENERAL_SCALE 0x10 /**< is a general scaling matrix flag */ |
#define MAT_FLAG_GENERAL_3D 0x20 /**< general 3D matrix flag */ |
#define MAT_FLAG_PERSPECTIVE 0x40 /**< is a perspective proj matrix flag */ |
#define MAT_FLAG_SINGULAR 0x80 /**< is a singular matrix flag */ |
#define MAT_DIRTY_TYPE 0x100 /**< matrix type is dirty */ |
#define MAT_DIRTY_FLAGS 0x200 /**< matrix flags are dirty */ |
#define MAT_DIRTY_INVERSE 0x400 /**< matrix inverse is dirty */ |
/** angle preserving matrix flags mask */ |
#define MAT_FLAGS_ANGLE_PRESERVING (MAT_FLAG_ROTATION | \ |
MAT_FLAG_TRANSLATION | \ |
MAT_FLAG_UNIFORM_SCALE) |
/** geometry related matrix flags mask */ |
#define MAT_FLAGS_GEOMETRY (MAT_FLAG_GENERAL | \ |
MAT_FLAG_ROTATION | \ |
MAT_FLAG_TRANSLATION | \ |
MAT_FLAG_UNIFORM_SCALE | \ |
MAT_FLAG_GENERAL_SCALE | \ |
MAT_FLAG_GENERAL_3D | \ |
MAT_FLAG_PERSPECTIVE | \ |
MAT_FLAG_SINGULAR) |
/** length preserving matrix flags mask */ |
#define MAT_FLAGS_LENGTH_PRESERVING (MAT_FLAG_ROTATION | \ |
MAT_FLAG_TRANSLATION) |
/** 3D (non-perspective) matrix flags mask */ |
#define MAT_FLAGS_3D (MAT_FLAG_ROTATION | \ |
MAT_FLAG_TRANSLATION | \ |
MAT_FLAG_UNIFORM_SCALE | \ |
MAT_FLAG_GENERAL_SCALE | \ |
MAT_FLAG_GENERAL_3D) |
/** dirty matrix flags mask */ |
#define MAT_DIRTY (MAT_DIRTY_TYPE | \ |
MAT_DIRTY_FLAGS | \ |
MAT_DIRTY_INVERSE) |
/*@}*/ |
/** |
* Test geometry related matrix flags. |
* |
* \param mat a pointer to a GLmatrix structure. |
* \param a flags mask. |
* |
* \returns non-zero if all geometry related matrix flags are contained within |
* the mask, or zero otherwise. |
*/ |
#define TEST_MAT_FLAGS(mat, a) \ |
((MAT_FLAGS_GEOMETRY & (~(a)) & ((mat)->flags) ) == 0) |
/** |
* Names of the corresponding GLmatrixtype values. |
*/ |
static const char *types[] = { |
"MATRIX_GENERAL", |
"MATRIX_IDENTITY", |
"MATRIX_3D_NO_ROT", |
"MATRIX_PERSPECTIVE", |
"MATRIX_2D", |
"MATRIX_2D_NO_ROT", |
"MATRIX_3D" |
}; |
/** |
* Identity matrix. |
*/ |
static GLfloat Identity[16] = { |
1.0, 0.0, 0.0, 0.0, |
0.0, 1.0, 0.0, 0.0, |
0.0, 0.0, 1.0, 0.0, |
0.0, 0.0, 0.0, 1.0 |
}; |
/**********************************************************************/ |
/** \name Matrix multiplication */ |
/*@{*/ |
#define A(row,col) a[(col<<2)+row] |
#define B(row,col) b[(col<<2)+row] |
#define P(row,col) product[(col<<2)+row] |
/** |
* Perform a full 4x4 matrix multiplication. |
* |
* \param a matrix. |
* \param b matrix. |
* \param product will receive the product of \p a and \p b. |
* |
* \warning Is assumed that \p product != \p b. \p product == \p a is allowed. |
* |
* \note KW: 4*16 = 64 multiplications |
* |
* \author This \c matmul was contributed by Thomas Malik |
*/ |
static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b ) |
{ |
GLint i; |
for (i = 0; i < 4; i++) { |
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); |
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); |
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); |
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); |
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); |
} |
} |
/** |
* Multiply two matrices known to occupy only the top three rows, such |
* as typical model matrices, and orthogonal matrices. |
* |
* \param a matrix. |
* \param b matrix. |
* \param product will receive the product of \p a and \p b. |
*/ |
static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b ) |
{ |
GLint i; |
for (i = 0; i < 3; i++) { |
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); |
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0); |
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1); |
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2); |
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3; |
} |
P(3,0) = 0; |
P(3,1) = 0; |
P(3,2) = 0; |
P(3,3) = 1; |
} |
#undef A |
#undef B |
#undef P |
/** |
* Multiply a matrix by an array of floats with known properties. |
* |
* \param mat pointer to a GLmatrix structure containing the left multiplication |
* matrix, and that will receive the product result. |
* \param m right multiplication matrix array. |
* \param flags flags of the matrix \p m. |
* |
* Joins both flags and marks the type and inverse as dirty. Calls matmul34() |
* if both matrices are 3D, or matmul4() otherwise. |
*/ |
static void matrix_multf( GLmatrix *mat, const GLfloat *m, GLuint flags ) |
{ |
mat->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE); |
if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) |
matmul34( mat->m, mat->m, m ); |
else |
matmul4( mat->m, mat->m, m ); |
} |
/** |
* Matrix multiplication. |
* |
* \param dest destination matrix. |
* \param a left matrix. |
* \param b right matrix. |
* |
* Joins both flags and marks the type and inverse as dirty. Calls matmul34() |
* if both matrices are 3D, or matmul4() otherwise. |
*/ |
void |
_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b ) |
{ |
dest->flags = (a->flags | |
b->flags | |
MAT_DIRTY_TYPE | |
MAT_DIRTY_INVERSE); |
if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D)) |
matmul34( dest->m, a->m, b->m ); |
else |
matmul4( dest->m, a->m, b->m ); |
} |
/** |
* Matrix multiplication. |
* |
* \param dest left and destination matrix. |
* \param m right matrix array. |
* |
* Marks the matrix flags with general flag, and type and inverse dirty flags. |
* Calls matmul4() for the multiplication. |
*/ |
void |
_math_matrix_mul_floats( GLmatrix *dest, const GLfloat *m ) |
{ |
dest->flags |= (MAT_FLAG_GENERAL | |
MAT_DIRTY_TYPE | |
MAT_DIRTY_INVERSE | |
MAT_DIRTY_FLAGS); |
matmul4( dest->m, dest->m, m ); |
} |
/*@}*/ |
/**********************************************************************/ |
/** \name Matrix output */ |
/*@{*/ |
/** |
* Print a matrix array. |
* |
* \param m matrix array. |
* |
* Called by _math_matrix_print() to print a matrix or its inverse. |
*/ |
static void print_matrix_floats( const GLfloat m[16] ) |
{ |
int i; |
for (i=0;i<4;i++) { |
_mesa_debug(NULL,"\t%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] ); |
} |
} |
/** |
* Dumps the contents of a GLmatrix structure. |
* |
* \param m pointer to the GLmatrix structure. |
*/ |
void |
_math_matrix_print( const GLmatrix *m ) |
{ |
GLfloat prod[16]; |
_mesa_debug(NULL, "Matrix type: %s, flags: %x\n", types[m->type], m->flags); |
print_matrix_floats(m->m); |
_mesa_debug(NULL, "Inverse: \n"); |
print_matrix_floats(m->inv); |
matmul4(prod, m->m, m->inv); |
_mesa_debug(NULL, "Mat * Inverse:\n"); |
print_matrix_floats(prod); |
} |
/*@}*/ |
/** |
* References an element of 4x4 matrix. |
* |
* \param m matrix array. |
* \param c column of the desired element. |
* \param r row of the desired element. |
* |
* \return value of the desired element. |
* |
* Calculate the linear storage index of the element and references it. |
*/ |
#define MAT(m,r,c) (m)[(c)*4+(r)] |
/**********************************************************************/ |
/** \name Matrix inversion */ |
/*@{*/ |
/** |
* Swaps the values of two floating point variables. |
* |
* Used by invert_matrix_general() to swap the row pointers. |
*/ |
#define SWAP_ROWS(a, b) { GLfloat *_tmp = a; (a)=(b); (b)=_tmp; } |
/** |
* Compute inverse of 4x4 transformation matrix. |
* |
* \param mat pointer to a GLmatrix structure. The matrix inverse will be |
* stored in the GLmatrix::inv attribute. |
* |
* \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). |
* |
* \author |
* Code contributed by Jacques Leroy jle@star.be |
* |
* Calculates the inverse matrix by performing the gaussian matrix reduction |
* with partial pivoting followed by back/substitution with the loops manually |
* unrolled. |
*/ |
static GLboolean invert_matrix_general( GLmatrix *mat ) |
{ |
const GLfloat *m = mat->m; |
GLfloat *out = mat->inv; |
GLfloat wtmp[4][8]; |
GLfloat m0, m1, m2, m3, s; |
GLfloat *r0, *r1, *r2, *r3; |
r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3]; |
r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1), |
r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3), |
r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0, |
r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1), |
r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3), |
r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0, |
r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1), |
r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3), |
r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0, |
r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1), |
r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3), |
r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0; |
/* choose pivot - or die */ |
if (FABSF(r3[0])>FABSF(r2[0])) SWAP_ROWS(r3, r2); |
if (FABSF(r2[0])>FABSF(r1[0])) SWAP_ROWS(r2, r1); |
if (FABSF(r1[0])>FABSF(r0[0])) SWAP_ROWS(r1, r0); |
if (0.0 == r0[0]) return GL_FALSE; |
/* eliminate first variable */ |
m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0]; |
s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s; |
s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s; |
s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s; |
s = r0[4]; |
if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; } |
s = r0[5]; |
if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; } |
s = r0[6]; |
if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; } |
s = r0[7]; |
if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; } |
/* choose pivot - or die */ |
if (FABSF(r3[1])>FABSF(r2[1])) SWAP_ROWS(r3, r2); |
if (FABSF(r2[1])>FABSF(r1[1])) SWAP_ROWS(r2, r1); |
if (0.0 == r1[1]) return GL_FALSE; |
/* eliminate second variable */ |
m2 = r2[1]/r1[1]; m3 = r3[1]/r1[1]; |
r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2]; |
r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3]; |
s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; } |
s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; } |
s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; } |
s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; } |
/* choose pivot - or die */ |
if (FABSF(r3[2])>FABSF(r2[2])) SWAP_ROWS(r3, r2); |
if (0.0 == r2[2]) return GL_FALSE; |
/* eliminate third variable */ |
m3 = r3[2]/r2[2]; |
r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4], |
r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], |
r3[7] -= m3 * r2[7]; |
/* last check */ |
if (0.0 == r3[3]) return GL_FALSE; |
s = 1.0F/r3[3]; /* now back substitute row 3 */ |
r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s; |
m2 = r2[3]; /* now back substitute row 2 */ |
s = 1.0F/r2[2]; |
r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2), |
r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2); |
m1 = r1[3]; |
r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1, |
r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1; |
m0 = r0[3]; |
r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0, |
r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0; |
m1 = r1[2]; /* now back substitute row 1 */ |
s = 1.0F/r1[1]; |
r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1), |
r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1); |
m0 = r0[2]; |
r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0, |
r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0; |
m0 = r0[1]; /* now back substitute row 0 */ |
s = 1.0F/r0[0]; |
r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0), |
r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0); |
MAT(out,0,0) = r0[4]; MAT(out,0,1) = r0[5], |
MAT(out,0,2) = r0[6]; MAT(out,0,3) = r0[7], |
MAT(out,1,0) = r1[4]; MAT(out,1,1) = r1[5], |
MAT(out,1,2) = r1[6]; MAT(out,1,3) = r1[7], |
MAT(out,2,0) = r2[4]; MAT(out,2,1) = r2[5], |
MAT(out,2,2) = r2[6]; MAT(out,2,3) = r2[7], |
MAT(out,3,0) = r3[4]; MAT(out,3,1) = r3[5], |
MAT(out,3,2) = r3[6]; MAT(out,3,3) = r3[7]; |
return GL_TRUE; |
} |
#undef SWAP_ROWS |
/** |
* Compute inverse of a general 3d transformation matrix. |
* |
* \param mat pointer to a GLmatrix structure. The matrix inverse will be |
* stored in the GLmatrix::inv attribute. |
* |
* \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). |
* |
* \author Adapted from graphics gems II. |
* |
* Calculates the inverse of the upper left by first calculating its |
* determinant and multiplying it to the symmetric adjust matrix of each |
* element. Finally deals with the translation part by transforming the |
* original translation vector using by the calculated submatrix inverse. |
*/ |
static GLboolean invert_matrix_3d_general( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
GLfloat pos, neg, t; |
GLfloat det; |
/* Calculate the determinant of upper left 3x3 submatrix and |
* determine if the matrix is singular. |
*/ |
pos = neg = 0.0; |
t = MAT(in,0,0) * MAT(in,1,1) * MAT(in,2,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = MAT(in,1,0) * MAT(in,2,1) * MAT(in,0,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = MAT(in,2,0) * MAT(in,0,1) * MAT(in,1,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = -MAT(in,2,0) * MAT(in,1,1) * MAT(in,0,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = -MAT(in,1,0) * MAT(in,0,1) * MAT(in,2,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = -MAT(in,0,0) * MAT(in,2,1) * MAT(in,1,2); |
if (t >= 0.0) pos += t; else neg += t; |
det = pos + neg; |
if (FABSF(det) < 1e-25) |
return GL_FALSE; |
det = 1.0F / det; |
MAT(out,0,0) = ( (MAT(in,1,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,1,2) )*det); |
MAT(out,0,1) = (- (MAT(in,0,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,0,2) )*det); |
MAT(out,0,2) = ( (MAT(in,0,1)*MAT(in,1,2) - MAT(in,1,1)*MAT(in,0,2) )*det); |
MAT(out,1,0) = (- (MAT(in,1,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,1,2) )*det); |
MAT(out,1,1) = ( (MAT(in,0,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,0,2) )*det); |
MAT(out,1,2) = (- (MAT(in,0,0)*MAT(in,1,2) - MAT(in,1,0)*MAT(in,0,2) )*det); |
MAT(out,2,0) = ( (MAT(in,1,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,1,1) )*det); |
MAT(out,2,1) = (- (MAT(in,0,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,0,1) )*det); |
MAT(out,2,2) = ( (MAT(in,0,0)*MAT(in,1,1) - MAT(in,1,0)*MAT(in,0,1) )*det); |
/* Do the translation part */ |
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) + |
MAT(in,1,3) * MAT(out,0,1) + |
MAT(in,2,3) * MAT(out,0,2) ); |
MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) + |
MAT(in,1,3) * MAT(out,1,1) + |
MAT(in,2,3) * MAT(out,1,2) ); |
MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) + |
MAT(in,1,3) * MAT(out,2,1) + |
MAT(in,2,3) * MAT(out,2,2) ); |
return GL_TRUE; |
} |
/** |
* Compute inverse of a 3d transformation matrix. |
* |
* \param mat pointer to a GLmatrix structure. The matrix inverse will be |
* stored in the GLmatrix::inv attribute. |
* |
* \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). |
* |
* If the matrix is not an angle preserving matrix then calls |
* invert_matrix_3d_general for the actual calculation. Otherwise calculates |
* the inverse matrix analyzing and inverting each of the scaling, rotation and |
* translation parts. |
*/ |
static GLboolean invert_matrix_3d( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING)) { |
return invert_matrix_3d_general( mat ); |
} |
if (mat->flags & MAT_FLAG_UNIFORM_SCALE) { |
GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) + |
MAT(in,0,1) * MAT(in,0,1) + |
MAT(in,0,2) * MAT(in,0,2)); |
if (scale == 0.0) |
return GL_FALSE; |
scale = 1.0F / scale; |
/* Transpose and scale the 3 by 3 upper-left submatrix. */ |
MAT(out,0,0) = scale * MAT(in,0,0); |
MAT(out,1,0) = scale * MAT(in,0,1); |
MAT(out,2,0) = scale * MAT(in,0,2); |
MAT(out,0,1) = scale * MAT(in,1,0); |
MAT(out,1,1) = scale * MAT(in,1,1); |
MAT(out,2,1) = scale * MAT(in,1,2); |
MAT(out,0,2) = scale * MAT(in,2,0); |
MAT(out,1,2) = scale * MAT(in,2,1); |
MAT(out,2,2) = scale * MAT(in,2,2); |
} |
else if (mat->flags & MAT_FLAG_ROTATION) { |
/* Transpose the 3 by 3 upper-left submatrix. */ |
MAT(out,0,0) = MAT(in,0,0); |
MAT(out,1,0) = MAT(in,0,1); |
MAT(out,2,0) = MAT(in,0,2); |
MAT(out,0,1) = MAT(in,1,0); |
MAT(out,1,1) = MAT(in,1,1); |
MAT(out,2,1) = MAT(in,1,2); |
MAT(out,0,2) = MAT(in,2,0); |
MAT(out,1,2) = MAT(in,2,1); |
MAT(out,2,2) = MAT(in,2,2); |
} |
else { |
/* pure translation */ |
memcpy( out, Identity, sizeof(Identity) ); |
MAT(out,0,3) = - MAT(in,0,3); |
MAT(out,1,3) = - MAT(in,1,3); |
MAT(out,2,3) = - MAT(in,2,3); |
return GL_TRUE; |
} |
if (mat->flags & MAT_FLAG_TRANSLATION) { |
/* Do the translation part */ |
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) + |
MAT(in,1,3) * MAT(out,0,1) + |
MAT(in,2,3) * MAT(out,0,2) ); |
MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) + |
MAT(in,1,3) * MAT(out,1,1) + |
MAT(in,2,3) * MAT(out,1,2) ); |
MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) + |
MAT(in,1,3) * MAT(out,2,1) + |
MAT(in,2,3) * MAT(out,2,2) ); |
} |
else { |
MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0; |
} |
return GL_TRUE; |
} |
/** |
* Compute inverse of an identity transformation matrix. |
* |
* \param mat pointer to a GLmatrix structure. The matrix inverse will be |
* stored in the GLmatrix::inv attribute. |
* |
* \return always GL_TRUE. |
* |
* Simply copies Identity into GLmatrix::inv. |
*/ |
static GLboolean invert_matrix_identity( GLmatrix *mat ) |
{ |
memcpy( mat->inv, Identity, sizeof(Identity) ); |
return GL_TRUE; |
} |
/** |
* Compute inverse of a no-rotation 3d transformation matrix. |
* |
* \param mat pointer to a GLmatrix structure. The matrix inverse will be |
* stored in the GLmatrix::inv attribute. |
* |
* \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). |
* |
* Calculates the |
*/ |
static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0 || MAT(in,2,2) == 0 ) |
return GL_FALSE; |
memcpy( out, Identity, 16 * sizeof(GLfloat) ); |
MAT(out,0,0) = 1.0F / MAT(in,0,0); |
MAT(out,1,1) = 1.0F / MAT(in,1,1); |
MAT(out,2,2) = 1.0F / MAT(in,2,2); |
if (mat->flags & MAT_FLAG_TRANSLATION) { |
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0)); |
MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1)); |
MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2)); |
} |
return GL_TRUE; |
} |
/** |
* Compute inverse of a no-rotation 2d transformation matrix. |
* |
* \param mat pointer to a GLmatrix structure. The matrix inverse will be |
* stored in the GLmatrix::inv attribute. |
* |
* \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). |
* |
* Calculates the inverse matrix by applying the inverse scaling and |
* translation to the identity matrix. |
*/ |
static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0) |
return GL_FALSE; |
memcpy( out, Identity, 16 * sizeof(GLfloat) ); |
MAT(out,0,0) = 1.0F / MAT(in,0,0); |
MAT(out,1,1) = 1.0F / MAT(in,1,1); |
if (mat->flags & MAT_FLAG_TRANSLATION) { |
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0)); |
MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1)); |
} |
return GL_TRUE; |
} |
#if 0 |
/* broken */ |
static GLboolean invert_matrix_perspective( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
if (MAT(in,2,3) == 0) |
return GL_FALSE; |
memcpy( out, Identity, 16 * sizeof(GLfloat) ); |
MAT(out,0,0) = 1.0F / MAT(in,0,0); |
MAT(out,1,1) = 1.0F / MAT(in,1,1); |
MAT(out,0,3) = MAT(in,0,2); |
MAT(out,1,3) = MAT(in,1,2); |
MAT(out,2,2) = 0; |
MAT(out,2,3) = -1; |
MAT(out,3,2) = 1.0F / MAT(in,2,3); |
MAT(out,3,3) = MAT(in,2,2) * MAT(out,3,2); |
return GL_TRUE; |
} |
#endif |
/** |
* Matrix inversion function pointer type. |
*/ |
typedef GLboolean (*inv_mat_func)( GLmatrix *mat ); |
/** |
* Table of the matrix inversion functions according to the matrix type. |
*/ |
static inv_mat_func inv_mat_tab[7] = { |
invert_matrix_general, |
invert_matrix_identity, |
invert_matrix_3d_no_rot, |
#if 0 |
/* Don't use this function for now - it fails when the projection matrix |
* is premultiplied by a translation (ala Chromium's tilesort SPU). |
*/ |
invert_matrix_perspective, |
#else |
invert_matrix_general, |
#endif |
invert_matrix_3d, /* lazy! */ |
invert_matrix_2d_no_rot, |
invert_matrix_3d |
}; |
/** |
* Compute inverse of a transformation matrix. |
* |
* \param mat pointer to a GLmatrix structure. The matrix inverse will be |
* stored in the GLmatrix::inv attribute. |
* |
* \return GL_TRUE for success, GL_FALSE for failure (\p singular matrix). |
* |
* Calls the matrix inversion function in inv_mat_tab corresponding to the |
* given matrix type. In case of failure, updates the MAT_FLAG_SINGULAR flag, |
* and copies the identity matrix into GLmatrix::inv. |
*/ |
static GLboolean matrix_invert( GLmatrix *mat ) |
{ |
if (inv_mat_tab[mat->type](mat)) { |
mat->flags &= ~MAT_FLAG_SINGULAR; |
return GL_TRUE; |
} else { |
mat->flags |= MAT_FLAG_SINGULAR; |
memcpy( mat->inv, Identity, sizeof(Identity) ); |
return GL_FALSE; |
} |
} |
/*@}*/ |
/**********************************************************************/ |
/** \name Matrix generation */ |
/*@{*/ |
/** |
* Generate a 4x4 transformation matrix from glRotate parameters, and |
* post-multiply the input matrix by it. |
* |
* \author |
* This function was contributed by Erich Boleyn (erich@uruk.org). |
* Optimizations contributed by Rudolf Opalla (rudi@khm.de). |
*/ |
void |
_math_matrix_rotate( GLmatrix *mat, |
GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) |
{ |
GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c; |
GLfloat m[16]; |
GLboolean optimized; |
s = (GLfloat) sin( angle * DEG2RAD ); |
c = (GLfloat) cos( angle * DEG2RAD ); |
memcpy(m, Identity, sizeof(GLfloat)*16); |
optimized = GL_FALSE; |
#define M(row,col) m[col*4+row] |
if (x == 0.0F) { |
if (y == 0.0F) { |
if (z != 0.0F) { |
optimized = GL_TRUE; |
/* rotate only around z-axis */ |
M(0,0) = c; |
M(1,1) = c; |
if (z < 0.0F) { |
M(0,1) = s; |
M(1,0) = -s; |
} |
else { |
M(0,1) = -s; |
M(1,0) = s; |
} |
} |
} |
else if (z == 0.0F) { |
optimized = GL_TRUE; |
/* rotate only around y-axis */ |
M(0,0) = c; |
M(2,2) = c; |
if (y < 0.0F) { |
M(0,2) = -s; |
M(2,0) = s; |
} |
else { |
M(0,2) = s; |
M(2,0) = -s; |
} |
} |
} |
else if (y == 0.0F) { |
if (z == 0.0F) { |
optimized = GL_TRUE; |
/* rotate only around x-axis */ |
M(1,1) = c; |
M(2,2) = c; |
if (x < 0.0F) { |
M(1,2) = s; |
M(2,1) = -s; |
} |
else { |
M(1,2) = -s; |
M(2,1) = s; |
} |
} |
} |
if (!optimized) { |
const GLfloat mag = sqrtf(x * x + y * y + z * z); |
if (mag <= 1.0e-4) { |
/* no rotation, leave mat as-is */ |
return; |
} |
x /= mag; |
y /= mag; |
z /= mag; |
/* |
* Arbitrary axis rotation matrix. |
* |
* This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied |
* like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation |
* (which is about the X-axis), and the two composite transforms |
* Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary |
* from the arbitrary axis to the X-axis then back. They are |
* all elementary rotations. |
* |
* Rz' is a rotation about the Z-axis, to bring the axis vector |
* into the x-z plane. Then Ry' is applied, rotating about the |
* Y-axis to bring the axis vector parallel with the X-axis. The |
* rotation about the X-axis is then performed. Ry and Rz are |
* simply the respective inverse transforms to bring the arbitrary |
* axis back to its original orientation. The first transforms |
* Rz' and Ry' are considered inverses, since the data from the |
* arbitrary axis gives you info on how to get to it, not how |
* to get away from it, and an inverse must be applied. |
* |
* The basic calculation used is to recognize that the arbitrary |
* axis vector (x, y, z), since it is of unit length, actually |
* represents the sines and cosines of the angles to rotate the |
* X-axis to the same orientation, with theta being the angle about |
* Z and phi the angle about Y (in the order described above) |
* as follows: |
* |
* cos ( theta ) = x / sqrt ( 1 - z^2 ) |
* sin ( theta ) = y / sqrt ( 1 - z^2 ) |
* |
* cos ( phi ) = sqrt ( 1 - z^2 ) |
* sin ( phi ) = z |
* |
* Note that cos ( phi ) can further be inserted to the above |
* formulas: |
* |
* cos ( theta ) = x / cos ( phi ) |
* sin ( theta ) = y / sin ( phi ) |
* |
* ...etc. Because of those relations and the standard trigonometric |
* relations, it is pssible to reduce the transforms down to what |
* is used below. It may be that any primary axis chosen will give the |
* same results (modulo a sign convention) using thie method. |
* |
* Particularly nice is to notice that all divisions that might |
* have caused trouble when parallel to certain planes or |
* axis go away with care paid to reducing the expressions. |
* After checking, it does perform correctly under all cases, since |
* in all the cases of division where the denominator would have |
* been zero, the numerator would have been zero as well, giving |
* the expected result. |
*/ |
xx = x * x; |
yy = y * y; |
zz = z * z; |
xy = x * y; |
yz = y * z; |
zx = z * x; |
xs = x * s; |
ys = y * s; |
zs = z * s; |
one_c = 1.0F - c; |
/* We already hold the identity-matrix so we can skip some statements */ |
M(0,0) = (one_c * xx) + c; |
M(0,1) = (one_c * xy) - zs; |
M(0,2) = (one_c * zx) + ys; |
/* M(0,3) = 0.0F; */ |
M(1,0) = (one_c * xy) + zs; |
M(1,1) = (one_c * yy) + c; |
M(1,2) = (one_c * yz) - xs; |
/* M(1,3) = 0.0F; */ |
M(2,0) = (one_c * zx) - ys; |
M(2,1) = (one_c * yz) + xs; |
M(2,2) = (one_c * zz) + c; |
/* M(2,3) = 0.0F; */ |
/* |
M(3,0) = 0.0F; |
M(3,1) = 0.0F; |
M(3,2) = 0.0F; |
M(3,3) = 1.0F; |
*/ |
} |
#undef M |
matrix_multf( mat, m, MAT_FLAG_ROTATION ); |
} |
/** |
* Apply a perspective projection matrix. |
* |
* \param mat matrix to apply the projection. |
* \param left left clipping plane coordinate. |
* \param right right clipping plane coordinate. |
* \param bottom bottom clipping plane coordinate. |
* \param top top clipping plane coordinate. |
* \param nearval distance to the near clipping plane. |
* \param farval distance to the far clipping plane. |
* |
* Creates the projection matrix and multiplies it with \p mat, marking the |
* MAT_FLAG_PERSPECTIVE flag. |
*/ |
void |
_math_matrix_frustum( GLmatrix *mat, |
GLfloat left, GLfloat right, |
GLfloat bottom, GLfloat top, |
GLfloat nearval, GLfloat farval ) |
{ |
GLfloat x, y, a, b, c, d; |
GLfloat m[16]; |
x = (2.0F*nearval) / (right-left); |
y = (2.0F*nearval) / (top-bottom); |
a = (right+left) / (right-left); |
b = (top+bottom) / (top-bottom); |
c = -(farval+nearval) / ( farval-nearval); |
d = -(2.0F*farval*nearval) / (farval-nearval); /* error? */ |
#define M(row,col) m[col*4+row] |
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F; |
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F; |
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d; |
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F; |
#undef M |
matrix_multf( mat, m, MAT_FLAG_PERSPECTIVE ); |
} |
/** |
* Apply an orthographic projection matrix. |
* |
* \param mat matrix to apply the projection. |
* \param left left clipping plane coordinate. |
* \param right right clipping plane coordinate. |
* \param bottom bottom clipping plane coordinate. |
* \param top top clipping plane coordinate. |
* \param nearval distance to the near clipping plane. |
* \param farval distance to the far clipping plane. |
* |
* Creates the projection matrix and multiplies it with \p mat, marking the |
* MAT_FLAG_GENERAL_SCALE and MAT_FLAG_TRANSLATION flags. |
*/ |
void |
_math_matrix_ortho( GLmatrix *mat, |
GLfloat left, GLfloat right, |
GLfloat bottom, GLfloat top, |
GLfloat nearval, GLfloat farval ) |
{ |
GLfloat m[16]; |
#define M(row,col) m[col*4+row] |
M(0,0) = 2.0F / (right-left); |
M(0,1) = 0.0F; |
M(0,2) = 0.0F; |
M(0,3) = -(right+left) / (right-left); |
M(1,0) = 0.0F; |
M(1,1) = 2.0F / (top-bottom); |
M(1,2) = 0.0F; |
M(1,3) = -(top+bottom) / (top-bottom); |
M(2,0) = 0.0F; |
M(2,1) = 0.0F; |
M(2,2) = -2.0F / (farval-nearval); |
M(2,3) = -(farval+nearval) / (farval-nearval); |
M(3,0) = 0.0F; |
M(3,1) = 0.0F; |
M(3,2) = 0.0F; |
M(3,3) = 1.0F; |
#undef M |
matrix_multf( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION)); |
} |
/** |
* Multiply a matrix with a general scaling matrix. |
* |
* \param mat matrix. |
* \param x x axis scale factor. |
* \param y y axis scale factor. |
* \param z z axis scale factor. |
* |
* Multiplies in-place the elements of \p mat by the scale factors. Checks if |
* the scales factors are roughly the same, marking the MAT_FLAG_UNIFORM_SCALE |
* flag, or MAT_FLAG_GENERAL_SCALE. Marks the MAT_DIRTY_TYPE and |
* MAT_DIRTY_INVERSE dirty flags. |
*/ |
void |
_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ) |
{ |
GLfloat *m = mat->m; |
m[0] *= x; m[4] *= y; m[8] *= z; |
m[1] *= x; m[5] *= y; m[9] *= z; |
m[2] *= x; m[6] *= y; m[10] *= z; |
m[3] *= x; m[7] *= y; m[11] *= z; |
if (FABSF(x - y) < 1e-8 && FABSF(x - z) < 1e-8) |
mat->flags |= MAT_FLAG_UNIFORM_SCALE; |
else |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
mat->flags |= (MAT_DIRTY_TYPE | |
MAT_DIRTY_INVERSE); |
} |
/** |
* Multiply a matrix with a translation matrix. |
* |
* \param mat matrix. |
* \param x translation vector x coordinate. |
* \param y translation vector y coordinate. |
* \param z translation vector z coordinate. |
* |
* Adds the translation coordinates to the elements of \p mat in-place. Marks |
* the MAT_FLAG_TRANSLATION flag, and the MAT_DIRTY_TYPE and MAT_DIRTY_INVERSE |
* dirty flags. |
*/ |
void |
_math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ) |
{ |
GLfloat *m = mat->m; |
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12]; |
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13]; |
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14]; |
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15]; |
mat->flags |= (MAT_FLAG_TRANSLATION | |
MAT_DIRTY_TYPE | |
MAT_DIRTY_INVERSE); |
} |
/** |
* Set matrix to do viewport and depthrange mapping. |
* Transforms Normalized Device Coords to window/Z values. |
*/ |
void |
_math_matrix_viewport(GLmatrix *m, GLint x, GLint y, GLint width, GLint height, |
GLfloat zNear, GLfloat zFar, GLfloat depthMax) |
{ |
m->m[MAT_SX] = (GLfloat) width / 2.0F; |
m->m[MAT_TX] = m->m[MAT_SX] + x; |
m->m[MAT_SY] = (GLfloat) height / 2.0F; |
m->m[MAT_TY] = m->m[MAT_SY] + y; |
m->m[MAT_SZ] = depthMax * ((zFar - zNear) / 2.0F); |
m->m[MAT_TZ] = depthMax * ((zFar - zNear) / 2.0F + zNear); |
m->flags = MAT_FLAG_GENERAL_SCALE | MAT_FLAG_TRANSLATION; |
m->type = MATRIX_3D_NO_ROT; |
} |
/** |
* Set a matrix to the identity matrix. |
* |
* \param mat matrix. |
* |
* Copies ::Identity into \p GLmatrix::m, and into GLmatrix::inv if not NULL. |
* Sets the matrix type to identity, and clear the dirty flags. |
*/ |
void |
_math_matrix_set_identity( GLmatrix *mat ) |
{ |
memcpy( mat->m, Identity, 16*sizeof(GLfloat) ); |
memcpy( mat->inv, Identity, 16*sizeof(GLfloat) ); |
mat->type = MATRIX_IDENTITY; |
mat->flags &= ~(MAT_DIRTY_FLAGS| |
MAT_DIRTY_TYPE| |
MAT_DIRTY_INVERSE); |
} |
/*@}*/ |
/**********************************************************************/ |
/** \name Matrix analysis */ |
/*@{*/ |
#define ZERO(x) (1<<x) |
#define ONE(x) (1<<(x+16)) |
#define MASK_NO_TRX (ZERO(12) | ZERO(13) | ZERO(14)) |
#define MASK_NO_2D_SCALE ( ONE(0) | ONE(5)) |
#define MASK_IDENTITY ( ONE(0) | ZERO(4) | ZERO(8) | ZERO(12) |\ |
ZERO(1) | ONE(5) | ZERO(9) | ZERO(13) |\ |
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_2D_NO_ROT ( ZERO(4) | ZERO(8) | \ |
ZERO(1) | ZERO(9) | \ |
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_2D ( ZERO(8) | \ |
ZERO(9) | \ |
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_3D_NO_ROT ( ZERO(4) | ZERO(8) | \ |
ZERO(1) | ZERO(9) | \ |
ZERO(2) | ZERO(6) | \ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_3D ( \ |
\ |
\ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_PERSPECTIVE ( ZERO(4) | ZERO(12) |\ |
ZERO(1) | ZERO(13) |\ |
ZERO(2) | ZERO(6) | \ |
ZERO(3) | ZERO(7) | ZERO(15) ) |
#define SQ(x) ((x)*(x)) |
/** |
* Determine type and flags from scratch. |
* |
* \param mat matrix. |
* |
* This is expensive enough to only want to do it once. |
*/ |
static void analyse_from_scratch( GLmatrix *mat ) |
{ |
const GLfloat *m = mat->m; |
GLuint mask = 0; |
GLuint i; |
for (i = 0 ; i < 16 ; i++) { |
if (m[i] == 0.0) mask |= (1<<i); |
} |
if (m[0] == 1.0F) mask |= (1<<16); |
if (m[5] == 1.0F) mask |= (1<<21); |
if (m[10] == 1.0F) mask |= (1<<26); |
if (m[15] == 1.0F) mask |= (1<<31); |
mat->flags &= ~MAT_FLAGS_GEOMETRY; |
/* Check for translation - no-one really cares |
*/ |
if ((mask & MASK_NO_TRX) != MASK_NO_TRX) |
mat->flags |= MAT_FLAG_TRANSLATION; |
/* Do the real work |
*/ |
if (mask == (GLuint) MASK_IDENTITY) { |
mat->type = MATRIX_IDENTITY; |
} |
else if ((mask & MASK_2D_NO_ROT) == (GLuint) MASK_2D_NO_ROT) { |
mat->type = MATRIX_2D_NO_ROT; |
if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE) |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
} |
else if ((mask & MASK_2D) == (GLuint) MASK_2D) { |
GLfloat mm = DOT2(m, m); |
GLfloat m4m4 = DOT2(m+4,m+4); |
GLfloat mm4 = DOT2(m,m+4); |
mat->type = MATRIX_2D; |
/* Check for scale */ |
if (SQ(mm-1) > SQ(1e-6) || |
SQ(m4m4-1) > SQ(1e-6)) |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
/* Check for rotation */ |
if (SQ(mm4) > SQ(1e-6)) |
mat->flags |= MAT_FLAG_GENERAL_3D; |
else |
mat->flags |= MAT_FLAG_ROTATION; |
} |
else if ((mask & MASK_3D_NO_ROT) == (GLuint) MASK_3D_NO_ROT) { |
mat->type = MATRIX_3D_NO_ROT; |
/* Check for scale */ |
if (SQ(m[0]-m[5]) < SQ(1e-6) && |
SQ(m[0]-m[10]) < SQ(1e-6)) { |
if (SQ(m[0]-1.0) > SQ(1e-6)) { |
mat->flags |= MAT_FLAG_UNIFORM_SCALE; |
} |
} |
else { |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
} |
} |
else if ((mask & MASK_3D) == (GLuint) MASK_3D) { |
GLfloat c1 = DOT3(m,m); |
GLfloat c2 = DOT3(m+4,m+4); |
GLfloat c3 = DOT3(m+8,m+8); |
GLfloat d1 = DOT3(m, m+4); |
GLfloat cp[3]; |
mat->type = MATRIX_3D; |
/* Check for scale */ |
if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) { |
if (SQ(c1-1.0) > SQ(1e-6)) |
mat->flags |= MAT_FLAG_UNIFORM_SCALE; |
/* else no scale at all */ |
} |
else { |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
} |
/* Check for rotation */ |
if (SQ(d1) < SQ(1e-6)) { |
CROSS3( cp, m, m+4 ); |
SUB_3V( cp, cp, (m+8) ); |
if (LEN_SQUARED_3FV(cp) < SQ(1e-6)) |
mat->flags |= MAT_FLAG_ROTATION; |
else |
mat->flags |= MAT_FLAG_GENERAL_3D; |
} |
else { |
mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */ |
} |
} |
else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) { |
mat->type = MATRIX_PERSPECTIVE; |
mat->flags |= MAT_FLAG_GENERAL; |
} |
else { |
mat->type = MATRIX_GENERAL; |
mat->flags |= MAT_FLAG_GENERAL; |
} |
} |
/** |
* Analyze a matrix given that its flags are accurate. |
* |
* This is the more common operation, hopefully. |
*/ |
static void analyse_from_flags( GLmatrix *mat ) |
{ |
const GLfloat *m = mat->m; |
if (TEST_MAT_FLAGS(mat, 0)) { |
mat->type = MATRIX_IDENTITY; |
} |
else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION | |
MAT_FLAG_UNIFORM_SCALE | |
MAT_FLAG_GENERAL_SCALE))) { |
if ( m[10]==1.0F && m[14]==0.0F ) { |
mat->type = MATRIX_2D_NO_ROT; |
} |
else { |
mat->type = MATRIX_3D_NO_ROT; |
} |
} |
else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) { |
if ( m[ 8]==0.0F |
&& m[ 9]==0.0F |
&& m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F) { |
mat->type = MATRIX_2D; |
} |
else { |
mat->type = MATRIX_3D; |
} |
} |
else if ( m[4]==0.0F && m[12]==0.0F |
&& m[1]==0.0F && m[13]==0.0F |
&& m[2]==0.0F && m[6]==0.0F |
&& m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) { |
mat->type = MATRIX_PERSPECTIVE; |
} |
else { |
mat->type = MATRIX_GENERAL; |
} |
} |
/** |
* Analyze and update a matrix. |
* |
* \param mat matrix. |
* |
* If the matrix type is dirty then calls either analyse_from_scratch() or |
* analyse_from_flags() to determine its type, according to whether the flags |
* are dirty or not, respectively. If the matrix has an inverse and it's dirty |
* then calls matrix_invert(). Finally clears the dirty flags. |
*/ |
void |
_math_matrix_analyse( GLmatrix *mat ) |
{ |
if (mat->flags & MAT_DIRTY_TYPE) { |
if (mat->flags & MAT_DIRTY_FLAGS) |
analyse_from_scratch( mat ); |
else |
analyse_from_flags( mat ); |
} |
if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) { |
matrix_invert( mat ); |
mat->flags &= ~MAT_DIRTY_INVERSE; |
} |
mat->flags &= ~(MAT_DIRTY_FLAGS | MAT_DIRTY_TYPE); |
} |
/*@}*/ |
/** |
* Test if the given matrix preserves vector lengths. |
*/ |
GLboolean |
_math_matrix_is_length_preserving( const GLmatrix *m ) |
{ |
return TEST_MAT_FLAGS( m, MAT_FLAGS_LENGTH_PRESERVING); |
} |
/** |
* Test if the given matrix does any rotation. |
* (or perhaps if the upper-left 3x3 is non-identity) |
*/ |
GLboolean |
_math_matrix_has_rotation( const GLmatrix *m ) |
{ |
if (m->flags & (MAT_FLAG_GENERAL | |
MAT_FLAG_ROTATION | |
MAT_FLAG_GENERAL_3D | |
MAT_FLAG_PERSPECTIVE)) |
return GL_TRUE; |
else |
return GL_FALSE; |
} |
GLboolean |
_math_matrix_is_general_scale( const GLmatrix *m ) |
{ |
return (m->flags & MAT_FLAG_GENERAL_SCALE) ? GL_TRUE : GL_FALSE; |
} |
GLboolean |
_math_matrix_is_dirty( const GLmatrix *m ) |
{ |
return (m->flags & MAT_DIRTY) ? GL_TRUE : GL_FALSE; |
} |
/**********************************************************************/ |
/** \name Matrix setup */ |
/*@{*/ |
/** |
* Copy a matrix. |
* |
* \param to destination matrix. |
* \param from source matrix. |
* |
* Copies all fields in GLmatrix, creating an inverse array if necessary. |
*/ |
void |
_math_matrix_copy( GLmatrix *to, const GLmatrix *from ) |
{ |
memcpy( to->m, from->m, sizeof(Identity) ); |
memcpy(to->inv, from->inv, 16 * sizeof(GLfloat)); |
to->flags = from->flags; |
to->type = from->type; |
} |
/** |
* Loads a matrix array into GLmatrix. |
* |
* \param m matrix array. |
* \param mat matrix. |
* |
* Copies \p m into GLmatrix::m and marks the MAT_FLAG_GENERAL and MAT_DIRTY |
* flags. |
*/ |
void |
_math_matrix_loadf( GLmatrix *mat, const GLfloat *m ) |
{ |
memcpy( mat->m, m, 16*sizeof(GLfloat) ); |
mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY); |
} |
/** |
* Matrix constructor. |
* |
* \param m matrix. |
* |
* Initialize the GLmatrix fields. |
*/ |
void |
_math_matrix_ctr( GLmatrix *m ) |
{ |
m->m = _mesa_align_malloc( 16 * sizeof(GLfloat), 16 ); |
if (m->m) |
memcpy( m->m, Identity, sizeof(Identity) ); |
m->inv = _mesa_align_malloc( 16 * sizeof(GLfloat), 16 ); |
if (m->inv) |
memcpy( m->inv, Identity, sizeof(Identity) ); |
m->type = MATRIX_IDENTITY; |
m->flags = 0; |
} |
/** |
* Matrix destructor. |
* |
* \param m matrix. |
* |
* Frees the data in a GLmatrix. |
*/ |
void |
_math_matrix_dtr( GLmatrix *m ) |
{ |
if (m->m) { |
_mesa_align_free( m->m ); |
m->m = NULL; |
} |
if (m->inv) { |
_mesa_align_free( m->inv ); |
m->inv = NULL; |
} |
} |
/*@}*/ |
/**********************************************************************/ |
/** \name Matrix transpose */ |
/*@{*/ |
/** |
* Transpose a GLfloat matrix. |
* |
* \param to destination array. |
* \param from source array. |
*/ |
void |
_math_transposef( GLfloat to[16], const GLfloat from[16] ) |
{ |
to[0] = from[0]; |
to[1] = from[4]; |
to[2] = from[8]; |
to[3] = from[12]; |
to[4] = from[1]; |
to[5] = from[5]; |
to[6] = from[9]; |
to[7] = from[13]; |
to[8] = from[2]; |
to[9] = from[6]; |
to[10] = from[10]; |
to[11] = from[14]; |
to[12] = from[3]; |
to[13] = from[7]; |
to[14] = from[11]; |
to[15] = from[15]; |
} |
/** |
* Transpose a GLdouble matrix. |
* |
* \param to destination array. |
* \param from source array. |
*/ |
void |
_math_transposed( GLdouble to[16], const GLdouble from[16] ) |
{ |
to[0] = from[0]; |
to[1] = from[4]; |
to[2] = from[8]; |
to[3] = from[12]; |
to[4] = from[1]; |
to[5] = from[5]; |
to[6] = from[9]; |
to[7] = from[13]; |
to[8] = from[2]; |
to[9] = from[6]; |
to[10] = from[10]; |
to[11] = from[14]; |
to[12] = from[3]; |
to[13] = from[7]; |
to[14] = from[11]; |
to[15] = from[15]; |
} |
/** |
* Transpose a GLdouble matrix and convert to GLfloat. |
* |
* \param to destination array. |
* \param from source array. |
*/ |
void |
_math_transposefd( GLfloat to[16], const GLdouble from[16] ) |
{ |
to[0] = (GLfloat) from[0]; |
to[1] = (GLfloat) from[4]; |
to[2] = (GLfloat) from[8]; |
to[3] = (GLfloat) from[12]; |
to[4] = (GLfloat) from[1]; |
to[5] = (GLfloat) from[5]; |
to[6] = (GLfloat) from[9]; |
to[7] = (GLfloat) from[13]; |
to[8] = (GLfloat) from[2]; |
to[9] = (GLfloat) from[6]; |
to[10] = (GLfloat) from[10]; |
to[11] = (GLfloat) from[14]; |
to[12] = (GLfloat) from[3]; |
to[13] = (GLfloat) from[7]; |
to[14] = (GLfloat) from[11]; |
to[15] = (GLfloat) from[15]; |
} |
/*@}*/ |
/** |
* Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix. This |
* function is used for transforming clipping plane equations and spotlight |
* directions. |
* Mathematically, u = v * m. |
* Input: v - input vector |
* m - transformation matrix |
* Output: u - transformed vector |
*/ |
void |
_mesa_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] ) |
{ |
const GLfloat v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; |
#define M(row,col) m[row + col*4] |
u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0); |
u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1); |
u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2); |
u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3); |
#undef M |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_matrix.h |
---|
0,0 → 1,218 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2005 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/** |
* \file math/m_matrix.h |
* Defines basic structures for matrix-handling. |
*/ |
#ifndef _M_MATRIX_H |
#define _M_MATRIX_H |
#include "main/glheader.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
/** |
* \name Symbolic names to some of the entries in the matrix |
* |
* These are handy for the viewport mapping, which is expressed as a matrix. |
*/ |
/*@{*/ |
#define MAT_SX 0 |
#define MAT_SY 5 |
#define MAT_SZ 10 |
#define MAT_TX 12 |
#define MAT_TY 13 |
#define MAT_TZ 14 |
/*@}*/ |
/** |
* Different kinds of 4x4 transformation matrices. |
* We use these to select specific optimized vertex transformation routines. |
*/ |
enum GLmatrixtype { |
MATRIX_GENERAL, /**< general 4x4 matrix */ |
MATRIX_IDENTITY, /**< identity matrix */ |
MATRIX_3D_NO_ROT, /**< orthogonal projection and others... */ |
MATRIX_PERSPECTIVE, /**< perspective projection matrix */ |
MATRIX_2D, /**< 2-D transformation */ |
MATRIX_2D_NO_ROT, /**< 2-D scale & translate only */ |
MATRIX_3D /**< 3-D transformation */ |
} ; |
/** |
* Matrix type to represent 4x4 transformation matrices. |
*/ |
typedef struct { |
GLfloat *m; /**< 16 matrix elements (16-byte aligned) */ |
GLfloat *inv; /**< 16-element inverse (16-byte aligned) */ |
GLuint flags; /**< possible values determined by (of \link |
* MatFlags MAT_FLAG_* flags\endlink) |
*/ |
enum GLmatrixtype type; |
} GLmatrix; |
extern void |
_math_matrix_ctr( GLmatrix *m ); |
extern void |
_math_matrix_dtr( GLmatrix *m ); |
extern void |
_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b ); |
extern void |
_math_matrix_mul_floats( GLmatrix *dest, const GLfloat *b ); |
extern void |
_math_matrix_loadf( GLmatrix *mat, const GLfloat *m ); |
extern void |
_math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ); |
extern void |
_math_matrix_rotate( GLmatrix *m, GLfloat angle, |
GLfloat x, GLfloat y, GLfloat z ); |
extern void |
_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ); |
extern void |
_math_matrix_ortho( GLmatrix *mat, |
GLfloat left, GLfloat right, |
GLfloat bottom, GLfloat top, |
GLfloat nearval, GLfloat farval ); |
extern void |
_math_matrix_frustum( GLmatrix *mat, |
GLfloat left, GLfloat right, |
GLfloat bottom, GLfloat top, |
GLfloat nearval, GLfloat farval ); |
extern void |
_math_matrix_viewport(GLmatrix *m, GLint x, GLint y, GLint width, GLint height, |
GLfloat zNear, GLfloat zFar, GLfloat depthMax); |
extern void |
_math_matrix_set_identity( GLmatrix *dest ); |
extern void |
_math_matrix_copy( GLmatrix *to, const GLmatrix *from ); |
extern void |
_math_matrix_analyse( GLmatrix *mat ); |
extern void |
_math_matrix_print( const GLmatrix *m ); |
extern GLboolean |
_math_matrix_is_length_preserving( const GLmatrix *m ); |
extern GLboolean |
_math_matrix_has_rotation( const GLmatrix *m ); |
extern GLboolean |
_math_matrix_is_general_scale( const GLmatrix *m ); |
extern GLboolean |
_math_matrix_is_dirty( const GLmatrix *m ); |
/** |
* \name Related functions that don't actually operate on GLmatrix structs |
*/ |
/*@{*/ |
extern void |
_math_transposef( GLfloat to[16], const GLfloat from[16] ); |
extern void |
_math_transposed( GLdouble to[16], const GLdouble from[16] ); |
extern void |
_math_transposefd( GLfloat to[16], const GLdouble from[16] ); |
/* |
* Transform a point (column vector) by a matrix: Q = M * P |
*/ |
#define TRANSFORM_POINT( Q, M, P ) \ |
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3]; \ |
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3]; \ |
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3]; \ |
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3]; |
#define TRANSFORM_POINT3( Q, M, P ) \ |
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12]; \ |
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13]; \ |
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14]; \ |
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15]; |
/* |
* Transform a normal (row vector) by a matrix: [NX NY NZ] = N * MAT |
*/ |
#define TRANSFORM_NORMAL( TO, N, MAT ) \ |
do { \ |
TO[0] = N[0] * MAT[0] + N[1] * MAT[1] + N[2] * MAT[2]; \ |
TO[1] = N[0] * MAT[4] + N[1] * MAT[5] + N[2] * MAT[6]; \ |
TO[2] = N[0] * MAT[8] + N[1] * MAT[9] + N[2] * MAT[10]; \ |
} while (0) |
/** |
* Transform a direction by a matrix. |
*/ |
#define TRANSFORM_DIRECTION( TO, DIR, MAT ) \ |
do { \ |
TO[0] = DIR[0] * MAT[0] + DIR[1] * MAT[4] + DIR[2] * MAT[8]; \ |
TO[1] = DIR[0] * MAT[1] + DIR[1] * MAT[5] + DIR[2] * MAT[9]; \ |
TO[2] = DIR[0] * MAT[2] + DIR[1] * MAT[6] + DIR[2] * MAT[10];\ |
} while (0) |
extern void |
_mesa_transform_vector(GLfloat u[4], const GLfloat v[4], const GLfloat m[16]); |
/*@}*/ |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/math/m_norm_tmp.h |
---|
0,0 → 1,390 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2003 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/* Functions to tranform a vector of normals. This includes applying |
* the transformation matrix, rescaling and normalization. |
*/ |
/* |
* mat - the 4x4 transformation matrix |
* scale - uniform scale factor of the transformation matrix (not always used) |
* in - the source vector of normals |
* lengths - length of each incoming normal (may be NULL) (a display list |
* optimization) |
* dest - the destination vector of normals |
*/ |
static void _XFORMAPI |
TAG(transform_normalize_normals)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
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]; |
GLuint i; |
if (!lengths) { |
STRIDE_LOOP { |
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) { |
GLfloat scale = INV_SQRTF(len); |
out[i][0] = tx * scale; |
out[i][1] = ty * scale; |
out[i][2] = tz * scale; |
} |
else { |
out[i][0] = out[i][1] = out[i][2] = 0; |
} |
} |
} |
} |
else { |
if (scale != 1.0) { |
m0 *= scale, m4 *= scale, m8 *= scale; |
m1 *= scale, m5 *= scale, m9 *= scale; |
m2 *= scale, m6 *= scale, m10 *= scale; |
} |
STRIDE_LOOP { |
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 GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
GLfloat m0 = m[0]; |
GLfloat m5 = m[5]; |
GLfloat m10 = m[10]; |
GLuint i; |
if (!lengths) { |
STRIDE_LOOP { |
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) { |
GLfloat scale = INV_SQRTF(len); |
out[i][0] = tx * scale; |
out[i][1] = ty * scale; |
out[i][2] = tz * scale; |
} |
else { |
out[i][0] = out[i][1] = out[i][2] = 0; |
} |
} |
} |
} |
else { |
m0 *= scale; |
m5 *= scale; |
m10 *= scale; |
STRIDE_LOOP { |
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 GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
const GLfloat m0 = scale*m[0]; |
const GLfloat m5 = scale*m[5]; |
const GLfloat m10 = scale*m[10]; |
GLuint i; |
(void) lengths; |
STRIDE_LOOP { |
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 GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
/* Since we are unlikely to have < 3 vertices in the buffer, |
* it makes sense to pre-multiply by scale. |
*/ |
const GLfloat *m = mat->inv; |
const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8]; |
const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9]; |
const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10]; |
GLuint i; |
(void) lengths; |
STRIDE_LOOP { |
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 GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
const GLfloat m0 = m[0]; |
const GLfloat m5 = m[5]; |
const GLfloat m10 = m[10]; |
GLuint i; |
(void) scale; |
(void) lengths; |
STRIDE_LOOP { |
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 GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8]; |
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9]; |
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10]; |
GLuint i; |
(void) scale; |
(void) lengths; |
STRIDE_LOOP { |
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 GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
GLuint i; |
(void) mat; |
(void) scale; |
if (lengths) { |
STRIDE_LOOP { |
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 { |
const GLfloat x = from[0], y = from[1], z = from[2]; |
GLdouble len = x * x + y * y + z * z; |
if (len > 1e-50) { |
len = INV_SQRTF(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 GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
GLuint i; |
(void) mat; |
(void) lengths; |
STRIDE_LOOP { |
SCALE_SCALAR_3V( out[i], scale, from ); |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(init_c_norm_transform)( void ) |
{ |
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT] = |
TAG(transform_normals_no_rot); |
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] = |
TAG(transform_rescale_normals_no_rot); |
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] = |
TAG(transform_normalize_normals_no_rot); |
_mesa_normal_tab[NORM_TRANSFORM] = |
TAG(transform_normals); |
_mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] = |
TAG(transform_rescale_normals); |
_mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] = |
TAG(transform_normalize_normals); |
_mesa_normal_tab[NORM_RESCALE] = |
TAG(rescale_normals); |
_mesa_normal_tab[NORM_NORMALIZE] = |
TAG(normalize_normals); |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_trans_tmp.h |
---|
0,0 → 1,281 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2006 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/** |
* \brief Templates for vector conversions. |
* \author Keith Whitwell. |
*/ |
#ifdef DEST_4F |
static void DEST_4F( GLfloat (*t)[4], |
const void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) first; |
(void) start; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
if (SZ >= 1) t[i][0] = TRX_4F(f, 0); |
if (SZ >= 2) t[i][1] = TRX_4F(f, 1); |
if (SZ >= 3) t[i][2] = TRX_4F(f, 2); |
if (SZ == 4) t[i][3] = TRX_4F(f, 3); else t[i][3] = 1.0; |
} |
} |
} |
#endif |
#ifdef DEST_4FN |
static void DEST_4FN( GLfloat (*t)[4], |
const void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) first; |
(void) start; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
if (SZ >= 1) t[i][0] = TRX_4FN(f, 0); |
if (SZ >= 2) t[i][1] = TRX_4FN(f, 1); |
if (SZ >= 3) t[i][2] = TRX_4FN(f, 2); |
if (SZ == 4) t[i][3] = TRX_4FN(f, 3); else t[i][3] = 1.0; |
} |
} |
} |
#endif |
#ifdef DEST_3FN |
static void DEST_3FN( GLfloat (*t)[3], |
const void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) first; |
(void) start; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
t[i][0] = TRX_3FN(f, 0); |
t[i][1] = TRX_3FN(f, 1); |
t[i][2] = TRX_3FN(f, 2); |
} |
} |
} |
#endif |
#ifdef DEST_1F |
static void DEST_1F( GLfloat *t, |
const void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) first; |
(void) start; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
t[i] = TRX_1F(f, 0); |
} |
} |
} |
#endif |
#ifdef DEST_4UB |
static void DEST_4UB( GLubyte (*t)[4], |
const void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
(void) first; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
if (SZ >= 1) TRX_UB(t[i][0], f, 0); |
if (SZ >= 2) TRX_UB(t[i][1], f, 1); |
if (SZ >= 3) TRX_UB(t[i][2], f, 2); |
if (SZ == 4) TRX_UB(t[i][3], f, 3); else t[i][3] = 255; |
} |
} |
} |
#endif |
#ifdef DEST_4US |
static void DEST_4US( GLushort (*t)[4], |
const void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ((GLubyte *) ptr + SRC_START * stride); |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
(void) first; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
if (SZ >= 1) TRX_US(t[i][0], f, 0); |
if (SZ >= 2) TRX_US(t[i][1], f, 1); |
if (SZ >= 3) TRX_US(t[i][2], f, 2); |
if (SZ == 4) TRX_US(t[i][3], f, 3); else t[i][3] = 65535; |
} |
} |
} |
#endif |
#ifdef DEST_1UB |
static void DEST_1UB( GLubyte *t, |
const void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
(void) first; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
TRX_UB(t[i], f, 0); |
} |
} |
} |
#endif |
#ifdef DEST_1UI |
static void DEST_1UI( GLuint *t, |
const void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
(void) first; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
t[i] = TRX_UI(f, 0); |
} |
} |
} |
#endif |
static void INIT(void) |
{ |
#ifdef DEST_1UI |
ASSERT(SZ == 1); |
TAB(_1ui)[SRC_IDX] = DEST_1UI; |
#endif |
#ifdef DEST_1UB |
ASSERT(SZ == 1); |
TAB(_1ub)[SRC_IDX] = DEST_1UB; |
#endif |
#ifdef DEST_1F |
ASSERT(SZ == 1); |
TAB(_1f)[SRC_IDX] = DEST_1F; |
#endif |
#ifdef DEST_3FN |
ASSERT(SZ == 3); |
TAB(_3fn)[SRC_IDX] = DEST_3FN; |
#endif |
#ifdef DEST_4UB |
TAB(_4ub)[SZ][SRC_IDX] = DEST_4UB; |
#endif |
#ifdef DEST_4US |
TAB(_4us)[SZ][SRC_IDX] = DEST_4US; |
#endif |
#ifdef DEST_4F |
TAB(_4f)[SZ][SRC_IDX] = DEST_4F; |
#endif |
#ifdef DEST_4FN |
TAB(_4fn)[SZ][SRC_IDX] = DEST_4FN; |
#endif |
} |
#ifdef INIT |
#undef INIT |
#endif |
#ifdef DEST_1UI |
#undef DEST_1UI |
#endif |
#ifdef DEST_1UB |
#undef DEST_1UB |
#endif |
#ifdef DEST_4UB |
#undef DEST_4UB |
#endif |
#ifdef DEST_4US |
#undef DEST_4US |
#endif |
#ifdef DEST_3FN |
#undef DEST_3FN |
#endif |
#ifdef DEST_4F |
#undef DEST_4F |
#endif |
#ifdef DEST_4FN |
#undef DEST_4FN |
#endif |
#ifdef DEST_1F |
#undef DEST_1F |
#endif |
#ifdef SZ |
#undef SZ |
#endif |
#ifdef TAG |
#undef TAG |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/math/m_translate.c |
---|
0,0 → 1,751 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2006 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/** |
* \brief Translate vectors of numbers between various types. |
* \author Keith Whitwell. |
*/ |
#include "main/glheader.h" |
#include "main/macros.h" |
#include "main/mtypes.h" /* GLchan hack */ |
#include "m_translate.h" |
typedef void (*trans_1f_func)(GLfloat *to, |
const void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_1ui_func)(GLuint *to, |
const void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_1ub_func)(GLubyte *to, |
const void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_4ub_func)(GLubyte (*to)[4], |
const void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_4us_func)(GLushort (*to)[4], |
const void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_4f_func)(GLfloat (*to)[4], |
const void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_3fn_func)(GLfloat (*to)[3], |
const void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
#define TYPE_IDX(t) ((t) & 0xf) |
#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */ |
/* This macro is used on other systems, so undefine it for this module */ |
#undef CHECK |
static trans_1f_func _math_trans_1f_tab[MAX_TYPES]; |
static trans_1ui_func _math_trans_1ui_tab[MAX_TYPES]; |
static trans_1ub_func _math_trans_1ub_tab[MAX_TYPES]; |
static trans_3fn_func _math_trans_3fn_tab[MAX_TYPES]; |
static trans_4ub_func _math_trans_4ub_tab[5][MAX_TYPES]; |
static trans_4us_func _math_trans_4us_tab[5][MAX_TYPES]; |
static trans_4f_func _math_trans_4f_tab[5][MAX_TYPES]; |
static trans_4f_func _math_trans_4fn_tab[5][MAX_TYPES]; |
#define PTR_ELT(ptr, elt) (((SRC *)ptr)[elt]) |
#define TAB(x) _math_trans##x##_tab |
#define ARGS GLuint start, GLuint n |
#define SRC_START start |
#define DST_START 0 |
#define STRIDE stride |
#define NEXT_F f += stride |
#define NEXT_F2 |
#define CHECK |
/** |
* Translate from GL_BYTE. |
*/ |
#define SRC GLbyte |
#define SRC_IDX TYPE_IDX(GL_BYTE) |
#define TRX_3FN(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#if 1 |
#define TRX_4F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#else |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#endif |
#define TRX_4FN(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = BYTE_TO_UBYTE( PTR_ELT(f,n) ) |
#define TRX_US(ch, f,n) ch = BYTE_TO_USHORT( PTR_ELT(f,n) ) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLbyte_raw |
#define DEST_4F trans_4_GLbyte_4f_raw |
#define DEST_4FN trans_4_GLbyte_4fn_raw |
#define DEST_4UB trans_4_GLbyte_4ub_raw |
#define DEST_4US trans_4_GLbyte_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLbyte_raw |
#define DEST_4F trans_3_GLbyte_4f_raw |
#define DEST_4FN trans_3_GLbyte_4fn_raw |
#define DEST_4UB trans_3_GLbyte_4ub_raw |
#define DEST_4US trans_3_GLbyte_4us_raw |
#define DEST_3FN trans_3_GLbyte_3fn_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLbyte_raw |
#define DEST_4F trans_2_GLbyte_4f_raw |
#define DEST_4FN trans_2_GLbyte_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLbyte_raw |
#define DEST_4F trans_1_GLbyte_4f_raw |
#define DEST_4FN trans_1_GLbyte_4fn_raw |
#define DEST_1UB trans_1_GLbyte_1ub_raw |
#define DEST_1UI trans_1_GLbyte_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef TRX_3FN |
#undef TRX_4F |
#undef TRX_4FN |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
#undef SRC_IDX |
/** |
* Translate from GL_UNSIGNED_BYTE. |
*/ |
#define SRC GLubyte |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_BYTE) |
#define TRX_3FN(f,n) UBYTE_TO_FLOAT(PTR_ELT(f,n)) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_4FN(f,n) UBYTE_TO_FLOAT(PTR_ELT(f,n)) |
#define TRX_UB(ub, f,n) ub = PTR_ELT(f,n) |
#define TRX_US(us, f,n) us = UBYTE_TO_USHORT(PTR_ELT(f,n)) |
#define TRX_UI(f,n) (GLuint)PTR_ELT(f,n) |
/* 4ub->4ub handled in special case below. |
*/ |
#define SZ 4 |
#define INIT init_trans_4_GLubyte_raw |
#define DEST_4F trans_4_GLubyte_4f_raw |
#define DEST_4FN trans_4_GLubyte_4fn_raw |
#define DEST_4US trans_4_GLubyte_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLubyte_raw |
#define DEST_4UB trans_3_GLubyte_4ub_raw |
#define DEST_4US trans_3_GLubyte_4us_raw |
#define DEST_3FN trans_3_GLubyte_3fn_raw |
#define DEST_4F trans_3_GLubyte_4f_raw |
#define DEST_4FN trans_3_GLubyte_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLubyte_raw |
#define DEST_1UI trans_1_GLubyte_1ui_raw |
#define DEST_1UB trans_1_GLubyte_1ub_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3FN |
#undef TRX_4F |
#undef TRX_4FN |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_SHORT |
*/ |
#define SRC GLshort |
#define SRC_IDX TYPE_IDX(GL_SHORT) |
#define TRX_3FN(f,n) SHORT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_4FN(f,n) SHORT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = SHORT_TO_UBYTE(PTR_ELT(f,n)) |
#define TRX_US(us, f,n) us = SHORT_TO_USHORT(PTR_ELT(f,n)) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLshort_raw |
#define DEST_4F trans_4_GLshort_4f_raw |
#define DEST_4FN trans_4_GLshort_4fn_raw |
#define DEST_4UB trans_4_GLshort_4ub_raw |
#define DEST_4US trans_4_GLshort_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLshort_raw |
#define DEST_4F trans_3_GLshort_4f_raw |
#define DEST_4FN trans_3_GLshort_4fn_raw |
#define DEST_4UB trans_3_GLshort_4ub_raw |
#define DEST_4US trans_3_GLshort_4us_raw |
#define DEST_3FN trans_3_GLshort_3fn_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLshort_raw |
#define DEST_4F trans_2_GLshort_4f_raw |
#define DEST_4FN trans_2_GLshort_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLshort_raw |
#define DEST_4F trans_1_GLshort_4f_raw |
#define DEST_4FN trans_1_GLshort_4fn_raw |
#define DEST_1UB trans_1_GLshort_1ub_raw |
#define DEST_1UI trans_1_GLshort_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3FN |
#undef TRX_4F |
#undef TRX_4FN |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_UNSIGNED_SHORT |
*/ |
#define SRC GLushort |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_SHORT) |
#define TRX_3FN(f,n) USHORT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_4FN(f,n) USHORT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_UB(ub,f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 8) |
#define TRX_US(us,f,n) us = PTR_ELT(f,n) |
#define TRX_UI(f,n) (GLuint) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLushort_raw |
#define DEST_4F trans_4_GLushort_4f_raw |
#define DEST_4FN trans_4_GLushort_4fn_raw |
#define DEST_4UB trans_4_GLushort_4ub_raw |
#define DEST_4US trans_4_GLushort_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLushort_raw |
#define DEST_4F trans_3_GLushort_4f_raw |
#define DEST_4FN trans_3_GLushort_4fn_raw |
#define DEST_4UB trans_3_GLushort_4ub_raw |
#define DEST_4US trans_3_GLushort_4us_raw |
#define DEST_3FN trans_3_GLushort_3fn_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLushort_raw |
#define DEST_4F trans_2_GLushort_4f_raw |
#define DEST_4FN trans_2_GLushort_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLushort_raw |
#define DEST_4F trans_1_GLushort_4f_raw |
#define DEST_4FN trans_1_GLushort_4fn_raw |
#define DEST_1UB trans_1_GLushort_1ub_raw |
#define DEST_1UI trans_1_GLushort_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3FN |
#undef TRX_4F |
#undef TRX_4FN |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_INT |
*/ |
#define SRC GLint |
#define SRC_IDX TYPE_IDX(GL_INT) |
#define TRX_3FN(f,n) INT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_4FN(f,n) INT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = INT_TO_UBYTE(PTR_ELT(f,n)) |
#define TRX_US(us, f,n) us = INT_TO_USHORT(PTR_ELT(f,n)) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLint_raw |
#define DEST_4F trans_4_GLint_4f_raw |
#define DEST_4FN trans_4_GLint_4fn_raw |
#define DEST_4UB trans_4_GLint_4ub_raw |
#define DEST_4US trans_4_GLint_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLint_raw |
#define DEST_4F trans_3_GLint_4f_raw |
#define DEST_4FN trans_3_GLint_4fn_raw |
#define DEST_4UB trans_3_GLint_4ub_raw |
#define DEST_4US trans_3_GLint_4us_raw |
#define DEST_3FN trans_3_GLint_3fn_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLint_raw |
#define DEST_4F trans_2_GLint_4f_raw |
#define DEST_4FN trans_2_GLint_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLint_raw |
#define DEST_4F trans_1_GLint_4f_raw |
#define DEST_4FN trans_1_GLint_4fn_raw |
#define DEST_1UB trans_1_GLint_1ub_raw |
#define DEST_1UI trans_1_GLint_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3FN |
#undef TRX_4F |
#undef TRX_4FN |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_UNSIGNED_INT |
*/ |
#define SRC GLuint |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_INT) |
#define TRX_3FN(f,n) INT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_4FN(f,n) UINT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 24) |
#define TRX_US(us, f,n) us = (GLshort) (PTR_ELT(f,n) >> 16) |
#define TRX_UI(f,n) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLuint_raw |
#define DEST_4F trans_4_GLuint_4f_raw |
#define DEST_4FN trans_4_GLuint_4fn_raw |
#define DEST_4UB trans_4_GLuint_4ub_raw |
#define DEST_4US trans_4_GLuint_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLuint_raw |
#define DEST_4F trans_3_GLuint_4f_raw |
#define DEST_4FN trans_3_GLuint_4fn_raw |
#define DEST_4UB trans_3_GLuint_4ub_raw |
#define DEST_4US trans_3_GLuint_4us_raw |
#define DEST_3FN trans_3_GLuint_3fn_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLuint_raw |
#define DEST_4F trans_2_GLuint_4f_raw |
#define DEST_4FN trans_2_GLuint_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLuint_raw |
#define DEST_4F trans_1_GLuint_4f_raw |
#define DEST_4FN trans_1_GLuint_4fn_raw |
#define DEST_1UB trans_1_GLuint_1ub_raw |
#define DEST_1UI trans_1_GLuint_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3FN |
#undef TRX_4F |
#undef TRX_4FN |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_DOUBLE |
*/ |
#define SRC GLdouble |
#define SRC_IDX TYPE_IDX(GL_DOUBLE) |
#define TRX_3FN(f,n) (GLfloat) PTR_ELT(f,n) |
#define TRX_4F(f,n) (GLfloat) PTR_ELT(f,n) |
#define TRX_4FN(f,n) (GLfloat) PTR_ELT(f,n) |
#define TRX_UB(ub,f,n) UNCLAMPED_FLOAT_TO_UBYTE(ub, PTR_ELT(f,n)) |
#define TRX_US(us,f,n) UNCLAMPED_FLOAT_TO_USHORT(us, PTR_ELT(f,n)) |
#define TRX_UI(f,n) (GLuint) (GLint) PTR_ELT(f,n) |
#define TRX_1F(f,n) (GLfloat) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLdouble_raw |
#define DEST_4F trans_4_GLdouble_4f_raw |
#define DEST_4FN trans_4_GLdouble_4fn_raw |
#define DEST_4UB trans_4_GLdouble_4ub_raw |
#define DEST_4US trans_4_GLdouble_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLdouble_raw |
#define DEST_4F trans_3_GLdouble_4f_raw |
#define DEST_4FN trans_3_GLdouble_4fn_raw |
#define DEST_4UB trans_3_GLdouble_4ub_raw |
#define DEST_4US trans_3_GLdouble_4us_raw |
#define DEST_3FN trans_3_GLdouble_3fn_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLdouble_raw |
#define DEST_4F trans_2_GLdouble_4f_raw |
#define DEST_4FN trans_2_GLdouble_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLdouble_raw |
#define DEST_4F trans_1_GLdouble_4f_raw |
#define DEST_4FN trans_1_GLdouble_4fn_raw |
#define DEST_1UB trans_1_GLdouble_1ub_raw |
#define DEST_1UI trans_1_GLdouble_1ui_raw |
#define DEST_1F trans_1_GLdouble_1f_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
/* GL_FLOAT |
*/ |
#define SRC GLfloat |
#define SRC_IDX TYPE_IDX(GL_FLOAT) |
#define SZ 4 |
#define INIT init_trans_4_GLfloat_raw |
#define DEST_4UB trans_4_GLfloat_4ub_raw |
#define DEST_4US trans_4_GLfloat_4us_raw |
#define DEST_4F trans_4_GLfloat_4f_raw |
#define DEST_4FN trans_4_GLfloat_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLfloat_raw |
#define DEST_4F trans_3_GLfloat_4f_raw |
#define DEST_4FN trans_3_GLfloat_4fn_raw |
#define DEST_4UB trans_3_GLfloat_4ub_raw |
#define DEST_4US trans_3_GLfloat_4us_raw |
#define DEST_3FN trans_3_GLfloat_3fn_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLfloat_raw |
#define DEST_4F trans_2_GLfloat_4f_raw |
#define DEST_4FN trans_2_GLfloat_4fn_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLfloat_raw |
#define DEST_4F trans_1_GLfloat_4f_raw |
#define DEST_4FN trans_1_GLfloat_4fn_raw |
#define DEST_1UB trans_1_GLfloat_1ub_raw |
#define DEST_1UI trans_1_GLfloat_1ui_raw |
#define DEST_1F trans_1_GLfloat_1f_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3FN |
#undef TRX_4F |
#undef TRX_4FN |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
static void trans_4_GLubyte_4ub_raw(GLubyte (*t)[4], |
const void *Ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) Ptr + SRC_START * stride; |
GLuint i; |
if (((((uintptr_t) f | (uintptr_t) stride)) & 3L) == 0L) { |
/* Aligned. |
*/ |
for (i = DST_START ; i < n ; i++, f += stride) { |
COPY_4UBV( t[i], f ); |
} |
} else { |
for (i = DST_START ; i < n ; i++, f += stride) { |
t[i][0] = f[0]; |
t[i][1] = f[1]; |
t[i][2] = f[2]; |
t[i][3] = f[3]; |
} |
} |
} |
static void init_translate_raw(void) |
{ |
memset( TAB(_1ui), 0, sizeof(TAB(_1ui)) ); |
memset( TAB(_1ub), 0, sizeof(TAB(_1ub)) ); |
memset( TAB(_3fn), 0, sizeof(TAB(_3fn)) ); |
memset( TAB(_4ub), 0, sizeof(TAB(_4ub)) ); |
memset( TAB(_4us), 0, sizeof(TAB(_4us)) ); |
memset( TAB(_4f), 0, sizeof(TAB(_4f)) ); |
memset( TAB(_4fn), 0, sizeof(TAB(_4fn)) ); |
init_trans_4_GLbyte_raw(); |
init_trans_3_GLbyte_raw(); |
init_trans_2_GLbyte_raw(); |
init_trans_1_GLbyte_raw(); |
init_trans_1_GLubyte_raw(); |
init_trans_3_GLubyte_raw(); |
init_trans_4_GLubyte_raw(); |
init_trans_4_GLshort_raw(); |
init_trans_3_GLshort_raw(); |
init_trans_2_GLshort_raw(); |
init_trans_1_GLshort_raw(); |
init_trans_4_GLushort_raw(); |
init_trans_3_GLushort_raw(); |
init_trans_2_GLushort_raw(); |
init_trans_1_GLushort_raw(); |
init_trans_4_GLint_raw(); |
init_trans_3_GLint_raw(); |
init_trans_2_GLint_raw(); |
init_trans_1_GLint_raw(); |
init_trans_4_GLuint_raw(); |
init_trans_3_GLuint_raw(); |
init_trans_2_GLuint_raw(); |
init_trans_1_GLuint_raw(); |
init_trans_4_GLdouble_raw(); |
init_trans_3_GLdouble_raw(); |
init_trans_2_GLdouble_raw(); |
init_trans_1_GLdouble_raw(); |
init_trans_4_GLfloat_raw(); |
init_trans_3_GLfloat_raw(); |
init_trans_2_GLfloat_raw(); |
init_trans_1_GLfloat_raw(); |
TAB(_4ub)[4][TYPE_IDX(GL_UNSIGNED_BYTE)] = trans_4_GLubyte_4ub_raw; |
} |
#undef TAB |
#ifdef CLASS |
#undef CLASS |
#endif |
#undef ARGS |
#undef CHECK |
#undef SRC_START |
#undef DST_START |
#undef NEXT_F |
#undef NEXT_F2 |
void _math_init_translate( void ) |
{ |
init_translate_raw(); |
} |
/** |
* Translate vector of values to GLfloat [1]. |
*/ |
void _math_trans_1f(GLfloat *to, |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_1f_tab[TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/** |
* Translate vector of values to GLuint [1]. |
*/ |
void _math_trans_1ui(GLuint *to, |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_1ui_tab[TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/** |
* Translate vector of values to GLubyte [1]. |
*/ |
void _math_trans_1ub(GLubyte *to, |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_1ub_tab[TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/** |
* Translate vector of values to GLubyte [4]. |
*/ |
void _math_trans_4ub(GLubyte (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_4ub_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/** |
* Translate vector of values to GLchan [4]. |
*/ |
void _math_trans_4chan( GLchan (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
#if CHAN_TYPE == GL_UNSIGNED_BYTE |
_math_trans_4ub( to, ptr, stride, type, size, start, n ); |
#elif CHAN_TYPE == GL_UNSIGNED_SHORT |
_math_trans_4us( to, ptr, stride, type, size, start, n ); |
#elif CHAN_TYPE == GL_FLOAT |
_math_trans_4fn( to, ptr, stride, type, size, start, n ); |
#endif |
} |
/** |
* Translate vector of values to GLushort [4]. |
*/ |
void _math_trans_4us(GLushort (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_4us_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/** |
* Translate vector of values to GLfloat [4]. |
*/ |
void _math_trans_4f(GLfloat (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_4f_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/** |
* Translate vector of values to GLfloat[4], normalized to [-1, 1]. |
*/ |
void _math_trans_4fn(GLfloat (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_4fn_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/** |
* Translate vector of values to GLfloat[3], normalized to [-1, 1]. |
*/ |
void _math_trans_3fn(GLfloat (*to)[3], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_3fn_tab[TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_translate.h |
---|
0,0 → 1,123 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2006 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
#ifndef _M_TRANSLATE_H_ |
#define _M_TRANSLATE_H_ |
#include "main/compiler.h" |
#include "main/glheader.h" |
#include "main/mtypes.h" /* hack for GLchan */ |
#include "swrast/s_chan.h" |
/** |
* Array translation. |
* For example, convert array of GLushort[3] to GLfloat[4]. |
* The function name specifies the destination format/size. |
* \param to the destination address |
* \param ptr the source address |
* \param stride the source stride (in bytes) between elements |
* \param type the source datatype (GL_SHORT, GL_UNSIGNED_INT, etc) |
* \param size number of values per element in source array (1,2,3 or 4) |
* \param start first element in source array to convert |
* \param n number of elements to convert |
* |
* Note: "element" means a tuple like GLfloat[3] or GLubyte[4]. |
*/ |
extern void _math_trans_1f(GLfloat *to, |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ); |
extern void _math_trans_1ui(GLuint *to, |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ); |
extern void _math_trans_1ub(GLubyte *to, |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ); |
extern void _math_trans_4ub(GLubyte (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
extern void _math_trans_4chan( GLchan (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
extern void _math_trans_4us(GLushort (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
/** Convert to floats w/out normalization (i.e. just cast) */ |
extern void _math_trans_4f(GLfloat (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
/** Convert to normalized floats in [0,1] or [-1, 1] */ |
extern void _math_trans_4fn(GLfloat (*to)[4], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
extern void _math_trans_3fn(GLfloat (*to)[3], |
const void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ); |
extern void _math_init_translate( void ); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/math/m_vector.c |
---|
0,0 → 1,184 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2001 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "m_vector.h" |
/** |
* Given a vector [count][4] of floats, set all the [][elt] values |
* to 0 (if elt = 0, 1, 2) or 1.0 (if elt = 3). |
*/ |
void |
_mesa_vector4f_clean_elem( GLvector4f *vec, GLuint count, GLuint elt ) |
{ |
static const GLubyte elem_bits[4] = { |
VEC_DIRTY_0, |
VEC_DIRTY_1, |
VEC_DIRTY_2, |
VEC_DIRTY_3 |
}; |
static const GLfloat clean[4] = { 0, 0, 0, 1 }; |
const GLfloat v = clean[elt]; |
GLfloat (*data)[4] = (GLfloat (*)[4])vec->start; |
GLuint i; |
for (i = 0; i < count; i++) |
data[i][elt] = v; |
vec->flags &= ~elem_bits[elt]; |
} |
static const GLubyte size_bits[5] = { |
0, |
VEC_SIZE_1, |
VEC_SIZE_2, |
VEC_SIZE_3, |
VEC_SIZE_4, |
}; |
/** |
* Initialize GLvector objects. |
* \param v the vector object to initialize. |
* \param flags bitwise-OR of VEC_* flags |
* \param storage pointer to storage for the vector's data |
*/ |
void |
_mesa_vector4f_init( GLvector4f *v, GLbitfield flags, GLfloat (*storage)[4] ) |
{ |
v->stride = 4 * sizeof(GLfloat); |
v->size = 2; /* may change: 2-4 for vertices and 1-4 for texcoords */ |
v->data = storage; |
v->start = (GLfloat *) storage; |
v->count = 0; |
v->flags = size_bits[4] | flags; |
} |
/** |
* Initialize GLvector objects and allocate storage. |
* \param v the vector object |
* \param flags bitwise-OR of VEC_* flags |
* \param count number of elements to allocate in vector |
* \param alignment desired memory alignment for the data (in bytes) |
*/ |
void |
_mesa_vector4f_alloc( GLvector4f *v, GLbitfield flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = 4 * sizeof(GLfloat); |
v->size = 2; |
v->storage = _mesa_align_malloc( count * 4 * sizeof(GLfloat), alignment ); |
v->storage_count = count; |
v->start = (GLfloat *) v->storage; |
v->data = (GLfloat (*)[4]) v->storage; |
v->count = 0; |
v->flags = size_bits[4] | flags | VEC_MALLOC; |
} |
/** |
* Vector deallocation. Free whatever memory is pointed to by the |
* vector's storage field if the VEC_MALLOC flag is set. |
* DO NOT free the GLvector object itself, though. |
*/ |
void |
_mesa_vector4f_free( GLvector4f *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
_mesa_align_free( v->storage ); |
v->data = NULL; |
v->start = NULL; |
v->storage = NULL; |
v->flags &= ~VEC_MALLOC; |
} |
} |
/** |
* For debugging |
*/ |
void |
_mesa_vector4f_print( const GLvector4f *v, const GLubyte *cullmask, |
GLboolean culling ) |
{ |
static const GLfloat c[4] = { 0, 0, 0, 1 }; |
static const char *templates[5] = { |
"%d:\t0, 0, 0, 1\n", |
"%d:\t%f, 0, 0, 1\n", |
"%d:\t%f, %f, 0, 1\n", |
"%d:\t%f, %f, %f, 1\n", |
"%d:\t%f, %f, %f, %f\n" |
}; |
const char *t = templates[v->size]; |
GLfloat *d = (GLfloat *)v->data; |
GLuint j, i = 0, count; |
printf("data-start\n"); |
for (; d != v->start; STRIDE_F(d, v->stride), i++) |
printf(t, i, d[0], d[1], d[2], d[3]); |
printf("start-count(%u)\n", v->count); |
count = i + v->count; |
if (culling) { |
for (; i < count; STRIDE_F(d, v->stride), i++) |
if (cullmask[i]) |
printf(t, i, d[0], d[1], d[2], d[3]); |
} |
else { |
for (; i < count; STRIDE_F(d, v->stride), i++) |
printf(t, i, d[0], d[1], d[2], d[3]); |
} |
for (j = v->size; j < 4; j++) { |
if ((v->flags & (1<<j)) == 0) { |
printf("checking col %u is clean as advertised ", j); |
for (i = 0, d = (GLfloat *) v->data; |
i < count && d[j] == c[j]; |
i++, STRIDE_F(d, v->stride)) { |
/* no-op */ |
} |
if (i == count) |
printf(" --> ok\n"); |
else |
printf(" --> Failed at %u ******\n", i); |
} |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_vector.h |
---|
0,0 → 1,92 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2008 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
#ifndef _M_VECTOR_H_ |
#define _M_VECTOR_H_ |
#include "main/glheader.h" |
#define VEC_DIRTY_0 0x1 |
#define VEC_DIRTY_1 0x2 |
#define VEC_DIRTY_2 0x4 |
#define VEC_DIRTY_3 0x8 |
#define VEC_MALLOC 0x10 /* storage field points to self-allocated mem*/ |
#define VEC_NOT_WRITEABLE 0x40 /* writable elements to hold clipped data */ |
#define VEC_BAD_STRIDE 0x100 /* matches tnl's prefered stride */ |
#define VEC_SIZE_1 VEC_DIRTY_0 |
#define VEC_SIZE_2 (VEC_DIRTY_0|VEC_DIRTY_1) |
#define VEC_SIZE_3 (VEC_DIRTY_0|VEC_DIRTY_1|VEC_DIRTY_2) |
#define VEC_SIZE_4 (VEC_DIRTY_0|VEC_DIRTY_1|VEC_DIRTY_2|VEC_DIRTY_3) |
/** |
* Wrap all the information about vectors up in a struct. Has |
* additional fields compared to the other vectors to help us track of |
* different vertex sizes, and whether we need to clean columns out |
* because they contain non-(0,0,0,1) values. |
* |
* The start field is used to reserve data for copied vertices at the |
* end of _mesa_transform_vb, and avoids the need for a multiplication in |
* the transformation routines. |
*/ |
typedef struct { |
GLfloat (*data)[4]; /**< may be malloc'd or point to client data */ |
GLfloat *start; /**< points somewhere inside of <data> */ |
GLuint count; /**< size of the vector (in elements) */ |
GLuint stride; /**< stride from one element to the next (in bytes) */ |
GLuint size; /**< 2-4 for vertices and 1-4 for texcoords */ |
GLbitfield flags; /**< bitmask of VEC_x flags */ |
void *storage; /**< self-allocated storage */ |
GLuint storage_count; /**< storage size in elements */ |
} GLvector4f; |
extern void _mesa_vector4f_init( GLvector4f *v, GLbitfield flags, |
GLfloat (*storage)[4] ); |
extern void _mesa_vector4f_alloc( GLvector4f *v, GLbitfield flags, |
GLuint count, GLuint alignment ); |
extern void _mesa_vector4f_free( GLvector4f *v ); |
extern void _mesa_vector4f_print( const GLvector4f *v, const GLubyte *, GLboolean ); |
extern void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint nr, GLuint elt ); |
/** |
* Given vector <v>, return a pointer (cast to <type *> to the <i>-th element. |
* |
* End up doing a lot of slow imuls if not careful. |
*/ |
#define VEC_ELT( v, type, i ) \ |
( (type *) ( ((GLbyte *) ((v)->data)) + (i) * (v)->stride) ) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/math/m_xform.c |
---|
0,0 → 1,122 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2003 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/* |
* Matrix/vertex/vector transformation stuff |
* |
* |
* NOTES: |
* 1. 4x4 transformation matrices are stored in memory in column major order. |
* 2. Points/vertices are to be thought of as column vectors. |
* 3. Transformation of a point p by a matrix M is: p' = M * p |
*/ |
#include "main/glheader.h" |
#include "main/macros.h" |
#include "m_eval.h" |
#include "m_matrix.h" |
#include "m_translate.h" |
#include "m_xform.h" |
#ifdef DEBUG_MATH |
#include "m_debug.h" |
#endif |
#ifdef USE_X86_ASM |
#include "x86/common_x86_asm.h" |
#endif |
#ifdef USE_X86_64_ASM |
#include "x86-64/x86-64.h" |
#endif |
#ifdef USE_SPARC_ASM |
#include "sparc/sparc.h" |
#endif |
clip_func _mesa_clip_tab[5]; |
clip_func _mesa_clip_np_tab[5]; |
dotprod_func _mesa_dotprod_tab[5]; |
vec_copy_func _mesa_copy_tab[0x10]; |
normal_func _mesa_normal_tab[0xf]; |
transform_func *_mesa_transform_tab[5]; |
/* Raw data format used for: |
* - Object-to-eye transform prior to culling, although this too |
* could be culled under some circumstances. |
* - Eye-to-clip transform (via the function above). |
* - Cliptesting |
* - And everything else too, if culling happens to be disabled. |
* |
* GH: It's used for everything now, as clipping/culling is done |
* elsewhere (most often by the driver itself). |
*/ |
#define TAG(x) x |
#define TAG2(x,y) x##y |
#define STRIDE_LOOP for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) |
#define LOOP for ( i = 0 ; i < n ; i++ ) |
#define ARGS |
#include "m_xform_tmp.h" |
#include "m_clip_tmp.h" |
#include "m_norm_tmp.h" |
#include "m_dotprod_tmp.h" |
#include "m_copy_tmp.h" |
#undef TAG |
#undef TAG2 |
#undef LOOP |
#undef ARGS |
/* |
* This is called only once. It initializes several tables with pointers |
* to optimized transformation functions. This is where we can test for |
* AMD 3Dnow! capability, Intel SSE, etc. and hook in the right code. |
*/ |
void |
_math_init_transformation( void ) |
{ |
init_c_transformations(); |
init_c_norm_transform(); |
init_c_cliptest(); |
init_copy0(); |
init_dotprod(); |
#ifdef DEBUG_MATH |
_math_test_all_transform_functions( "default" ); |
_math_test_all_normal_transform_functions( "default" ); |
_math_test_all_cliptest_functions( "default" ); |
#endif |
#ifdef USE_X86_ASM |
_mesa_init_all_x86_transform_asm(); |
#elif defined( USE_SPARC_ASM ) |
_mesa_init_all_sparc_transform_asm(); |
#elif defined( USE_X86_64_ASM ) |
_mesa_init_all_x86_64_transform_asm(); |
#endif |
} |
/contrib/sdk/sources/Mesa/src/mesa/math/m_xform.h |
---|
0,0 → 1,168 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2008 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
#ifndef _M_XFORM_H |
#define _M_XFORM_H |
#include "main/compiler.h" |
#include "main/glheader.h" |
#include "math/m_matrix.h" |
#include "math/m_vector.h" |
#ifdef USE_X86_ASM |
#define _XFORMAPI _ASMAPI |
#define _XFORMAPIP _ASMAPIP |
#else |
#define _XFORMAPI |
#define _XFORMAPIP * |
#endif |
extern void |
_math_init_transformation(void); |
extern void |
init_c_cliptest(void); |
/* KW: Clip functions now do projective divide as well. The projected |
* coordinates are very useful to us because they let us cull |
* backfaces and eliminate vertices from lighting, fogging, etc |
* calculations. Despite the fact that this divide could be done one |
* day in hardware, we would still have a reason to want to do it here |
* as long as those other calculations remain in software. |
* |
* Clipping is a convenient place to do the divide on x86 as it should be |
* possible to overlap with integer outcode calculations. |
* |
* There are two cases where we wouldn't want to do the divide in cliptest: |
* - When we aren't clipping. We still might want to cull backfaces |
* so the divide should be done elsewhere. This currently never |
* happens. |
* |
* - When culling isn't likely to help us, such as when the GL culling |
* is disabled and we not lighting or are only lighting |
* one-sided. In this situation, backface determination provides |
* us with no useful information. A tricky case to detect is when |
* all input data is already culled, although hopefully the |
* application wouldn't turn on culling in such cases. |
* |
* We supply a buffer to hold the [x/w,y/w,z/w,1/w] values which |
* are the result of the projection. This is only used in the |
* 4-vector case - in other cases, we just use the clip coordinates |
* as the projected coordinates - they are identical. |
* |
* This is doubly convenient because it means the Win[] array is now |
* of the same stride as all the others, so I can now turn map_vertices |
* into a straight-forward matrix transformation, with asm acceleration |
* automatically available. |
*/ |
/* Vertex buffer clipping flags |
*/ |
#define CLIP_RIGHT_SHIFT 0 |
#define CLIP_LEFT_SHIFT 1 |
#define CLIP_TOP_SHIFT 2 |
#define CLIP_BOTTOM_SHIFT 3 |
#define CLIP_NEAR_SHIFT 4 |
#define CLIP_FAR_SHIFT 5 |
#define CLIP_RIGHT_BIT 0x01 |
#define CLIP_LEFT_BIT 0x02 |
#define CLIP_TOP_BIT 0x04 |
#define CLIP_BOTTOM_BIT 0x08 |
#define CLIP_NEAR_BIT 0x10 |
#define CLIP_FAR_BIT 0x20 |
#define CLIP_USER_BIT 0x40 |
#define CLIP_CULL_BIT 0x80 |
#define CLIP_FRUSTUM_BITS 0x3f |
typedef GLvector4f * (_XFORMAPIP clip_func)( GLvector4f *vClip, |
GLvector4f *vProj, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask, |
GLboolean viewport_z_clip ); |
typedef void (*dotprod_func)( GLfloat *out, |
GLuint out_stride, |
const GLvector4f *coord_vec, |
const GLfloat plane[4] ); |
typedef void (*vec_copy_func)( GLvector4f *to, |
const GLvector4f *from ); |
/* |
* Functions for transformation of normals in the VB. |
*/ |
typedef void (_NORMAPIP normal_func)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat lengths[], |
GLvector4f *dest ); |
/* Flags for selecting a normal transformation function. |
*/ |
#define NORM_RESCALE 0x1 /* apply the scale factor */ |
#define NORM_NORMALIZE 0x2 /* normalize */ |
#define NORM_TRANSFORM 0x4 /* apply the transformation matrix */ |
#define NORM_TRANSFORM_NO_ROT 0x8 /* apply the transformation matrix */ |
/* KW: New versions of the transform function allow a mask array |
* specifying that individual vector transform should be skipped |
* when the mask byte is zero. This is always present as a |
* parameter, to allow a unified interface. |
*/ |
typedef void (_XFORMAPIP transform_func)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ); |
extern dotprod_func _mesa_dotprod_tab[5]; |
extern vec_copy_func _mesa_copy_tab[0x10]; |
extern vec_copy_func _mesa_copy_clean_tab[5]; |
extern clip_func _mesa_clip_tab[5]; |
extern clip_func _mesa_clip_np_tab[5]; |
extern normal_func _mesa_normal_tab[0xf]; |
/* Use of 2 layers of linked 1-dimensional arrays to reduce |
* cost of lookup. |
*/ |
extern transform_func *_mesa_transform_tab[5]; |
#define TransformRaw( to, mat, from ) \ |
( _mesa_transform_tab[(from)->size][(mat)->type]( to, (mat)->m, from ), \ |
(to) ) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/math/m_xform_tmp.h |
---|
0,0 → 1,810 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2001 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 |
* THE AUTHORS OR COPYRIGHT HOLDERS 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. |
*/ |
/*---------------------------------------------------------------------- |
* Begin Keith's new code |
* |
*---------------------------------------------------------------------- |
*/ |
/* KW: Fixed stride, now measured in bytes as is the OpenGL array stride. |
*/ |
/* KW: These are now parameterized to produce two versions, one |
* which transforms all incoming points, and a second which |
* takes notice of a cullmask array, and only transforms |
* unculled vertices. |
*/ |
/* KW: 1-vectors can sneak into the texture pipeline via the array |
* interface. These functions are here because I want consistant |
* treatment of the vertex sizes and a lazy strategy for |
* cleaning unused parts of the vector, and so as not to exclude |
* them from the vertex array interface. |
* |
* Under our current analysis of matrices, there is no way that |
* the product of a matrix and a 1-vector can remain a 1-vector, |
* with the exception of the identity transform. |
*/ |
/* KW: No longer zero-pad outgoing vectors. Now that external |
* vectors can get into the pipeline we cannot ever assume |
* that there is more to a vector than indicated by its |
* size. |
*/ |
/* KW: Now uses clipmask and a flag to allow us to skip both/either |
* cliped and/or culled vertices. |
*/ |
/* GH: Not any more -- it's easier (and faster) to just process the |
* entire vector. Clipping and culling are handled further down |
* the pipe, most often during or after the conversion to some |
* driver-specific vertex format. |
*/ |
static void _XFORMAPI |
TAG(transform_points1_general)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m12 = m[12]; |
const GLfloat m1 = m[1], m13 = m[13]; |
const GLfloat m2 = m[2], m14 = m[14]; |
const GLfloat m3 = m[3], m15 = m[15]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m1 * ox + m13; |
to[i][2] = m2 * ox + m14; |
to[i][3] = m3 * ox + m15; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_identity)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLuint count = from_vec->count; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint i; |
(void) m; |
if (to_vec == from_vec) return; |
STRIDE_LOOP { |
to[i][0] = from[0]; |
} |
to_vec->size = 1; |
to_vec->flags |= VEC_SIZE_1; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_2d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1]; |
const GLfloat m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m1 * ox + m13; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m13; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_3d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m1 * ox + m13; |
to[i][2] = m2 * ox + m14; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m13; |
to[i][2] = m14; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_perspective)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox ; |
to[i][1] = 0 ; |
to[i][2] = m14; |
to[i][3] = 0; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
/* 2-vectors, which are a lot more relevant than 1-vectors, are |
* present early in the geometry pipeline and throughout the |
* texture pipeline. |
*/ |
static void _XFORMAPI |
TAG(transform_points2_general)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m4 = m[4], m12 = m[12]; |
const GLfloat m1 = m[1], m5 = m[5], m13 = m[13]; |
const GLfloat m2 = m[2], m6 = m[6], m14 = m[14]; |
const GLfloat m3 = m[3], m7 = m[7], m15 = m[15]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m4 * oy + m12; |
to[i][1] = m1 * ox + m5 * oy + m13; |
to[i][2] = m2 * ox + m6 * oy + m14; |
to[i][3] = m3 * ox + m7 * oy + m15; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_identity)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
GLuint i; |
(void) m; |
if (to_vec == from_vec) return; |
STRIDE_LOOP { |
to[i][0] = from[0]; |
to[i][1] = from[1]; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_2d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; |
const GLfloat m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m4 * oy + m12; |
to[i][1] = m1 * ox + m5 * oy + m13; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m5 * oy + m13; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_3d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; |
const GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m4 * oy + m12; |
to[i][1] = m1 * ox + m5 * oy + m13; |
to[i][2] = m2 * ox + m6 * oy + m14; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
/* I would actually say this was a fairly important function, from |
* a texture transformation point of view. |
*/ |
static void _XFORMAPI |
TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m5 * oy + m13; |
to[i][2] = m14; |
} |
if (m14 == 0) { |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
} else { |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
} |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_perspective)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox ; |
to[i][1] = m5 * oy ; |
to[i][2] = m14; |
to[i][3] = 0; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_general)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12]; |
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13]; |
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14]; |
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12; |
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13; |
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14; |
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_identity)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
GLuint i; |
(void) m; |
if (to_vec == from_vec) return; |
STRIDE_LOOP { |
to[i][0] = from[0]; |
to[i][1] = from[1]; |
to[i][2] = from[2]; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_2d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; |
const GLfloat m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m4 * oy + m12 ; |
to[i][1] = m1 * ox + m5 * oy + m13 ; |
to[i][2] = + oz ; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m12 ; |
to[i][1] = m5 * oy + m13 ; |
to[i][2] = + oz ; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_3d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; |
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 ; |
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 ; |
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 ; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
/* previously known as ortho... |
*/ |
static void _XFORMAPI |
TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5]; |
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m12 ; |
to[i][1] = m5 * oy + m13 ; |
to[i][2] = m10 * oz + m14 ; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_perspective)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9]; |
const GLfloat m10 = m[10], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m8 * oz ; |
to[i][1] = m5 * oy + m9 * oz ; |
to[i][2] = m10 * oz + m14 ; |
to[i][3] = -oz ; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_general)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12]; |
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13]; |
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14]; |
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow; |
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow; |
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow; |
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_identity)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
GLuint i; |
(void) m; |
if (to_vec == from_vec) return; |
STRIDE_LOOP { |
to[i][0] = from[0]; |
to[i][1] = from[1]; |
to[i][2] = from[2]; |
to[i][3] = from[3]; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_2d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; |
const GLfloat m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m4 * oy + m12 * ow; |
to[i][1] = m1 * ox + m5 * oy + m13 * ow; |
to[i][2] = + oz ; |
to[i][3] = ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m12 * ow; |
to[i][1] = m5 * oy + m13 * ow; |
to[i][2] = + oz ; |
to[i][3] = ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_3d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; |
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow; |
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow; |
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow; |
to[i][3] = ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5]; |
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m12 * ow; |
to[i][1] = m5 * oy + m13 * ow; |
to[i][2] = m10 * oz + m14 * ow; |
to[i][3] = ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_perspective)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9]; |
const GLfloat m10 = m[10], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m8 * oz ; |
to[i][1] = m5 * oy + m9 * oz ; |
to[i][2] = m10 * oz + m14 * ow ; |
to[i][3] = -oz ; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static transform_func TAG(transform_tab_1)[7]; |
static transform_func TAG(transform_tab_2)[7]; |
static transform_func TAG(transform_tab_3)[7]; |
static transform_func TAG(transform_tab_4)[7]; |
/* Similar functions could be called several times, with more highly |
* optimized routines overwriting the arrays. This only occurs during |
* startup. |
*/ |
static void _XFORMAPI TAG(init_c_transformations)( void ) |
{ |
#define TAG_TAB _mesa_transform_tab |
#define TAG_TAB_1 TAG(transform_tab_1) |
#define TAG_TAB_2 TAG(transform_tab_2) |
#define TAG_TAB_3 TAG(transform_tab_3) |
#define TAG_TAB_4 TAG(transform_tab_4) |
TAG_TAB[1] = TAG_TAB_1; |
TAG_TAB[2] = TAG_TAB_2; |
TAG_TAB[3] = TAG_TAB_3; |
TAG_TAB[4] = TAG_TAB_4; |
/* 1-D points (ie texcoords) */ |
TAG_TAB_1[MATRIX_GENERAL] = TAG(transform_points1_general); |
TAG_TAB_1[MATRIX_IDENTITY] = TAG(transform_points1_identity); |
TAG_TAB_1[MATRIX_3D_NO_ROT] = TAG(transform_points1_3d_no_rot); |
TAG_TAB_1[MATRIX_PERSPECTIVE] = TAG(transform_points1_perspective); |
TAG_TAB_1[MATRIX_2D] = TAG(transform_points1_2d); |
TAG_TAB_1[MATRIX_2D_NO_ROT] = TAG(transform_points1_2d_no_rot); |
TAG_TAB_1[MATRIX_3D] = TAG(transform_points1_3d); |
/* 2-D points */ |
TAG_TAB_2[MATRIX_GENERAL] = TAG(transform_points2_general); |
TAG_TAB_2[MATRIX_IDENTITY] = TAG(transform_points2_identity); |
TAG_TAB_2[MATRIX_3D_NO_ROT] = TAG(transform_points2_3d_no_rot); |
TAG_TAB_2[MATRIX_PERSPECTIVE] = TAG(transform_points2_perspective); |
TAG_TAB_2[MATRIX_2D] = TAG(transform_points2_2d); |
TAG_TAB_2[MATRIX_2D_NO_ROT] = TAG(transform_points2_2d_no_rot); |
TAG_TAB_2[MATRIX_3D] = TAG(transform_points2_3d); |
/* 3-D points */ |
TAG_TAB_3[MATRIX_GENERAL] = TAG(transform_points3_general); |
TAG_TAB_3[MATRIX_IDENTITY] = TAG(transform_points3_identity); |
TAG_TAB_3[MATRIX_3D_NO_ROT] = TAG(transform_points3_3d_no_rot); |
TAG_TAB_3[MATRIX_PERSPECTIVE] = TAG(transform_points3_perspective); |
TAG_TAB_3[MATRIX_2D] = TAG(transform_points3_2d); |
TAG_TAB_3[MATRIX_2D_NO_ROT] = TAG(transform_points3_2d_no_rot); |
TAG_TAB_3[MATRIX_3D] = TAG(transform_points3_3d); |
/* 4-D points */ |
TAG_TAB_4[MATRIX_GENERAL] = TAG(transform_points4_general); |
TAG_TAB_4[MATRIX_IDENTITY] = TAG(transform_points4_identity); |
TAG_TAB_4[MATRIX_3D_NO_ROT] = TAG(transform_points4_3d_no_rot); |
TAG_TAB_4[MATRIX_PERSPECTIVE] = TAG(transform_points4_perspective); |
TAG_TAB_4[MATRIX_2D] = TAG(transform_points4_2d); |
TAG_TAB_4[MATRIX_2D_NO_ROT] = TAG(transform_points4_2d_no_rot); |
TAG_TAB_4[MATRIX_3D] = TAG(transform_points4_3d); |
#undef TAG_TAB |
#undef TAG_TAB_1 |
#undef TAG_TAB_2 |
#undef TAG_TAB_3 |
#undef TAG_TAB_4 |
} |