This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to branch debian/master
in repository ioquake3.

commit dfbaf5032437426f40599b2a617453511f6d550a
Author: SmileTheory <smilethe...@gmail.com>
Date:   Tue Sep 6 00:57:15 2016 -0700

    OpenGL2: Store normals/tangents as int16_t[4].
---
 code/renderergl2/tr_animation.c  |   2 +-
 code/renderergl2/tr_bsp.c        | 205 +++++++-------------
 code/renderergl2/tr_curve.c      |   6 +-
 code/renderergl2/tr_extensions.c |  17 --
 code/renderergl2/tr_init.c       |   2 -
 code/renderergl2/tr_local.h      |  33 ++--
 code/renderergl2/tr_main.c       | 363 +++--------------------------------
 code/renderergl2/tr_marks.c      |  23 ++-
 code/renderergl2/tr_model.c      |  89 +++++----
 code/renderergl2/tr_model_iqm.c  |  15 +-
 code/renderergl2/tr_shade_calc.c |  24 +--
 code/renderergl2/tr_surface.c    | 398 +++++----------------------------------
 code/renderergl2/tr_vbo.c        | 147 ++++-----------
 13 files changed, 285 insertions(+), 1039 deletions(-)

diff --git a/code/renderergl2/tr_animation.c b/code/renderergl2/tr_animation.c
index 53e5ee9..4f333cb 100644
--- a/code/renderergl2/tr_animation.c
+++ b/code/renderergl2/tr_animation.c
@@ -412,7 +412,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface )
                tess.xyz[baseVertex + j][1] = tempVert[1];
                tess.xyz[baseVertex + j][2] = tempVert[2];
 
-               R_VaoPackNormal((byte *)&tess.normal[baseVertex + j], 
tempNormal);
+               R_VaoPackNormal(tess.normal[baseVertex + j], tempNormal);
 
                tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
                tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c
index 6abfd25..dbd3932 100644
--- a/code/renderergl2/tr_bsp.c
+++ b/code/renderergl2/tr_bsp.c
@@ -667,6 +667,63 @@ static shader_t *ShaderForShaderNum( int shaderNum, int 
lightmapNum ) {
        return shader;
 }
 
+void LoadDrawVertToSrfVert(srfVert_t *s, drawVert_t *d, int realLightmapNum, 
float hdrVertColors[3])
+{
+       vec4_t v;
+
+       s->xyz[0] = LittleFloat(d->xyz[0]);
+       s->xyz[1] = LittleFloat(d->xyz[1]);
+       s->xyz[2] = LittleFloat(d->xyz[2]);
+
+       s->st[0] = LittleFloat(d->st[0]);
+       s->st[1] = LittleFloat(d->st[1]);
+
+       if (realLightmapNum >= 0)
+       {
+               s->lightmap[0] = FatPackU(LittleFloat(d->lightmap[0]), 
realLightmapNum);
+               s->lightmap[1] = FatPackV(LittleFloat(d->lightmap[1]), 
realLightmapNum);
+       }
+       else
+       {
+               s->lightmap[0] = LittleFloat(d->lightmap[0]);
+               s->lightmap[1] = LittleFloat(d->lightmap[1]);
+       }
+
+       v[0] = LittleFloat(d->normal[0]);
+       v[1] = LittleFloat(d->normal[1]);
+       v[2] = LittleFloat(d->normal[2]);
+
+       R_VaoPackNormal(s->normal, v);
+
+       if (hdrVertColors)
+       {
+               v[0] = hdrVertColors[0];
+               v[1] = hdrVertColors[1];
+               v[2] = hdrVertColors[2];
+       }
+       else
+       {
+               //hack: convert LDR vertex colors to HDR
+               if (r_hdr->integer)
+               {
+                       v[0] = MAX(d->color[0], 0.499f);
+                       v[1] = MAX(d->color[1], 0.499f);
+                       v[2] = MAX(d->color[2], 0.499f);
+               }
+               else
+               {
+                       v[0] = d->color[0];
+                       v[1] = d->color[1];
+                       v[2] = d->color[2];
+               }
+
+       }
+       v[3] = d->color[3] / 255.0f;
+
+       R_ColorShiftLightingFloats(v, s->vertexColors, 1.0f / 255.0f);
+}
+
+
 /*
 ===============
 ParseFace
@@ -714,50 +771,7 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, 
float *hdrVertColors,
        ClearBounds(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]);
        verts += LittleLong(ds->firstVert);
        for(i = 0; i < numVerts; i++)
-       {
-               vec4_t color;
-
-               for(j = 0; j < 3; j++)
-               {
-                       cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
-                       cv->verts[i].normal[j] = 
LittleFloat(verts[i].normal[j]);
-               }
-               AddPointToBounds(cv->verts[i].xyz, surf->cullinfo.bounds[0], 
surf->cullinfo.bounds[1]);
-               for(j = 0; j < 2; j++)
-               {
-                       cv->verts[i].st[j] = LittleFloat(verts[i].st[j]);
-                       //cv->verts[i].lightmap[j] = 
LittleFloat(verts[i].lightmap[j]);
-               }
-               cv->verts[i].lightmap[0] = 
FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum);
-               cv->verts[i].lightmap[1] = 
FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum);
-
-               if (hdrVertColors)
-               {
-                       color[0] = hdrVertColors[(ds->firstVert + i) * 3    ];
-                       color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
-                       color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
-               }
-               else
-               {
-                       //hack: convert LDR vertex colors to HDR
-                       if (r_hdr->integer)
-                       {
-                               color[0] = MAX(verts[i].color[0], 0.499f);
-                               color[1] = MAX(verts[i].color[1], 0.499f);
-                               color[2] = MAX(verts[i].color[2], 0.499f);
-                       }
-                       else
-                       {
-                               color[0] = verts[i].color[0];
-                               color[1] = verts[i].color[1];
-                               color[2] = verts[i].color[2];
-                       }
-
-               }
-               color[3] = verts[i].color[3] / 255.0f;
-
-               R_ColorShiftLightingFloats( color, cv->verts[i].vertexColors, 
1.0f / 255.0f );
-       }
+               LoadDrawVertToSrfVert(&cv->verts[i], &verts[i], 
realLightmapNum, hdrVertColors ? hdrVertColors + (ds->firstVert + i) * 3 : 
NULL);
 
        // copy triangles
        badTriangles = 0;
@@ -823,7 +837,7 @@ ParseMesh
 */
 static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float 
*hdrVertColors, msurface_t *surf ) {
        srfBspSurface_t *grid = (srfBspSurface_t *)surf->data;
-       int                             i, j;
+       int                             i;
        int                             width, height, numPoints;
        srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE];
        vec3_t                  bounds[2];
@@ -858,49 +872,7 @@ static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, 
float *hdrVertColors,
        verts += LittleLong( ds->firstVert );
        numPoints = width * height;
        for(i = 0; i < numPoints; i++)
-       {
-               vec4_t color;
-
-               for(j = 0; j < 3; j++)
-               {
-                       points[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
-                       points[i].normal[j] = LittleFloat(verts[i].normal[j]);
-               }
-
-               for(j = 0; j < 2; j++)
-               {
-                       points[i].st[j] = LittleFloat(verts[i].st[j]);
-                       //points[i].lightmap[j] = 
LittleFloat(verts[i].lightmap[j]);
-               }
-               points[i].lightmap[0] = 
FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum);
-               points[i].lightmap[1] = 
FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum);
-
-               if (hdrVertColors)
-               {
-                       color[0] = hdrVertColors[(ds->firstVert + i) * 3    ];
-                       color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
-                       color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
-               }
-               else
-               {
-                       //hack: convert LDR vertex colors to HDR
-                       if (r_hdr->integer)
-                       {
-                               color[0] = MAX(verts[i].color[0], 0.499f);
-                               color[1] = MAX(verts[i].color[1], 0.499f);
-                               color[2] = MAX(verts[i].color[2], 0.499f);
-                       }
-                       else
-                       {
-                               color[0] = verts[i].color[0];
-                               color[1] = verts[i].color[1];
-                               color[2] = verts[i].color[2];
-                       }
-               }
-               color[3] = verts[i].color[3] / 255.0f;
-
-               R_ColorShiftLightingFloats( color, points[i].vertexColors, 1.0f 
/ 255.0f );
-       }
+               LoadDrawVertToSrfVert(&points[i], &verts[i], realLightmapNum, 
hdrVertColors ? hdrVertColors + (ds->firstVert + i) * 3 : NULL);
 
        // pre-tesseleate
        R_SubdividePatchToGrid( grid, width, height, points );
@@ -964,49 +936,7 @@ static void ParseTriSurf( dsurface_t *ds, drawVert_t 
*verts, float *hdrVertColor
        ClearBounds(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]);
        verts += LittleLong(ds->firstVert);
        for(i = 0; i < numVerts; i++)
-       {
-               vec4_t color;
-
-               for(j = 0; j < 3; j++)
-               {
-                       cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
-                       cv->verts[i].normal[j] = 
LittleFloat(verts[i].normal[j]);
-               }
-
-               AddPointToBounds( cv->verts[i].xyz, surf->cullinfo.bounds[0], 
surf->cullinfo.bounds[1] );
-
-               for(j = 0; j < 2; j++)
-               {
-                       cv->verts[i].st[j] = LittleFloat(verts[i].st[j]);
-                       cv->verts[i].lightmap[j] = 
LittleFloat(verts[i].lightmap[j]);
-               }
-
-               if (hdrVertColors)
-               {
-                       color[0] = hdrVertColors[(ds->firstVert + i) * 3    ];
-                       color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
-                       color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
-               }
-               else
-               {
-                       //hack: convert LDR vertex colors to HDR
-                       if (r_hdr->integer)
-                       {
-                               color[0] = MAX(verts[i].color[0], 0.499f);
-                               color[1] = MAX(verts[i].color[1], 0.499f);
-                               color[2] = MAX(verts[i].color[2], 0.499f);
-                       }
-                       else
-                       {
-                               color[0] = verts[i].color[0];
-                               color[1] = verts[i].color[1];
-                               color[2] = verts[i].color[2];
-                       }
-               }
-               color[3] = verts[i].color[3] / 255.0f;
-
-               R_ColorShiftLightingFloats( color, cv->verts[i].vertexColors, 
1.0f / 255.0f );
-       }
+               LoadDrawVertToSrfVert(&cv->verts[i], &verts[i], -1, 
hdrVertColors ? hdrVertColors + (ds->firstVert + i) * 3 : NULL);
 
        // copy triangles
        badTriangles = 0;
@@ -1849,8 +1779,8 @@ static void CopyVert(const srfVert_t * in, srfVert_t * 
out)
 #ifdef USE_VERT_TANGENT_SPACE
        VectorCopy4(in->tangent, out->tangent);
 #endif
-       VectorCopy(in->normal,   out->normal);
-       VectorCopy(in->lightdir, out->lightdir);
+       VectorCopy4(in->normal,   out->normal);
+       VectorCopy4(in->lightdir, out->lightdir);
 
        VectorCopy2(in->st,       out->st);
        VectorCopy2(in->lightmap, out->lightmap);
@@ -3193,7 +3123,14 @@ void R_CalcVertexLightDirs( void )
                        case SF_GRID:
                        case SF_TRIANGLES:
                                for(i = 0; i < bspSurf->numVerts; i++)
-                                       R_LightDirForPoint( 
bspSurf->verts[i].xyz, bspSurf->verts[i].lightdir, bspSurf->verts[i].normal, 
&s_worldData );
+                               {
+                                       vec3_t lightDir;
+                                       vec3_t normal;
+
+                                       R_VaoUnpackNormal(normal, 
bspSurf->verts[i].normal);
+                                       R_LightDirForPoint( 
bspSurf->verts[i].xyz, lightDir, normal, &s_worldData );
+                                       
R_VaoPackNormal(bspSurf->verts[i].lightdir, lightDir);
+                               }
 
                                break;
 
diff --git a/code/renderergl2/tr_curve.c b/code/renderergl2/tr_curve.c
index f9e17cd..c693ae8 100644
--- a/code/renderergl2/tr_curve.c
+++ b/code/renderergl2/tr_curve.c
@@ -207,7 +207,11 @@ static     int     neighbors[8][2] = {
                        //if ( count == 0 ) {
                        //      printf("bad normal\n");
                        //}
-                       VectorNormalize2( sum, dv->normal );
+                       {
+                               vec3_t fNormal;
+                               VectorNormalize2(sum, fNormal);
+                               R_VaoPackNormal(dv->normal, fNormal);
+                       }
                }
        }
 }
diff --git a/code/renderergl2/tr_extensions.c b/code/renderergl2/tr_extensions.c
index 927383a..8058a4b 100644
--- a/code/renderergl2/tr_extensions.c
+++ b/code/renderergl2/tr_extensions.c
@@ -295,23 +295,6 @@ void GLimp_InitExtraExtensions()
                ri.Printf(PRINT_ALL, result[2], extension);
        }
 
-       // GL_ARB_vertex_type_2_10_10_10_rev
-       extension = "GL_ARB_vertex_type_2_10_10_10_rev";
-       glRefConfig.packedNormalDataType = GL_BYTE;
-       if( GLimp_HaveExtension( extension ) )
-       {
-               qboolean useExt = !!r_arb_vertex_type_2_10_10_10_rev->integer;
-
-               if (useExt)
-                       glRefConfig.packedNormalDataType = 
GL_INT_2_10_10_10_REV;
-
-               ri.Printf(PRINT_ALL, result[useExt], extension);
-       }
-       else
-       {
-               ri.Printf(PRINT_ALL, result[2], extension);
-       }
-
        // use float lightmaps?
        glRefConfig.floatLightmap = (glRefConfig.textureFloat && 
glRefConfig.halfFloatPixel && r_floatLightmap->integer && r_hdr->integer);
 
diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c
index 60c62ab..8809039 100644
--- a/code/renderergl2/tr_init.c
+++ b/code/renderergl2/tr_init.c
@@ -106,7 +106,6 @@ cvar_t  *r_arb_half_float_pixel;
 cvar_t  *r_arb_half_float_vertex;
 cvar_t  *r_ext_framebuffer_multisample;
 cvar_t  *r_arb_seamless_cube_map;
-cvar_t  *r_arb_vertex_type_2_10_10_10_rev;
 cvar_t  *r_arb_vertex_array_object;
 cvar_t  *r_ext_direct_state_access;
 
@@ -1168,7 +1167,6 @@ void R_Register( void )
        r_arb_half_float_vertex = ri.Cvar_Get( "r_arb_half_float_vertex", "1", 
CVAR_ARCHIVE | CVAR_LATCH);
        r_ext_framebuffer_multisample = ri.Cvar_Get( 
"r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH);
        r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", 
CVAR_ARCHIVE | CVAR_LATCH);
-       r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( 
"r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH);
        r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", 
"1", CVAR_ARCHIVE | CVAR_LATCH);
        r_ext_direct_state_access = ri.Cvar_Get("r_ext_direct_state_access", 
"1", CVAR_ARCHIVE | CVAR_LATCH);
 
diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h
index 553fcc0..998d981 100644
--- a/code/renderergl2/tr_local.h
+++ b/code/renderergl2/tr_local.h
@@ -895,11 +895,11 @@ typedef struct
        vec3_t          xyz;
        vec2_t          st;
        vec2_t          lightmap;
-       vec3_t          normal;
+       int16_t         normal[4];
 #ifdef USE_VERT_TANGENT_SPACE
-       vec4_t          tangent;
+       int16_t         tangent[4];
 #endif
-       vec3_t          lightdir;
+       int16_t         lightdir[4];
        vec4_t                  vertexColors;
 
 #if DEBUG_OPTIMIZEVERTICES
@@ -908,9 +908,9 @@ typedef struct
 } srfVert_t;
 
 #ifdef USE_VERT_TANGENT_SPACE
-#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 
0, 0}, {0, 0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
+#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 
0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
 #else
-#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 
0, 0}, {0, 0, 0},  {0, 0, 0, 0}}
+#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 
0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
 #endif
 
 // srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VAO_MESH
@@ -1201,10 +1201,9 @@ typedef struct
 typedef struct
 {
        vec3_t          xyz;
-       vec3_t          normal;
+       int16_t         normal[4];
 #ifdef USE_VERT_TANGENT_SPACE
-       vec3_t          tangent;
-       vec3_t          bitangent;
+       int16_t         tangent[4];
 #endif
 } mdvVertex_t;
 
@@ -1411,7 +1410,6 @@ typedef struct {
        qboolean depthClamp;
        qboolean seamlessCubeMap;
 
-       GLenum packedNormalDataType;
        GLenum packedTexcoordDataType;
        GLenum packedColorDataType;
        int packedTexcoordDataSize;
@@ -1718,7 +1716,6 @@ extern  cvar_t  *r_arb_half_float_pixel;
 extern  cvar_t  *r_arb_half_float_vertex;
 extern  cvar_t  *r_ext_framebuffer_multisample;
 extern  cvar_t  *r_arb_seamless_cube_map;
-extern  cvar_t  *r_arb_vertex_type_2_10_10_10_rev;
 extern  cvar_t  *r_arb_vertex_array_object;
 extern  cvar_t  *r_ext_direct_state_access;
 
@@ -1861,7 +1858,7 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t 
*shader,
 
 void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
                                   const vec3_t v3, const vec2_t w1, const 
vec2_t w2, const vec2_t w3);
-void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t 
normal, vec3_t sdir, vec3_t tdir);
+vec_t R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, const vec3_t 
normal, const vec3_t sdir, const vec3_t tdir);
 qboolean R_CalcTangentVectors(srfVert_t * dv[3]);
 
 #define        CULL_IN         0               // completely unclipped
@@ -2008,13 +2005,13 @@ typedef struct shaderCommands_s
 {
        glIndex_t       indexes[SHADER_MAX_INDEXES] QALIGN(16);
        vec4_t          xyz[SHADER_MAX_VERTEXES] QALIGN(16);
-       uint32_t        normal[SHADER_MAX_VERTEXES] QALIGN(16);
+       int16_t         normal[SHADER_MAX_VERTEXES][4] QALIGN(16);
 #ifdef USE_VERT_TANGENT_SPACE
-       uint32_t        tangent[SHADER_MAX_VERTEXES] QALIGN(16);
+       int16_t         tangent[SHADER_MAX_VERTEXES][4] QALIGN(16);
 #endif
        vec2_t          texCoords[SHADER_MAX_VERTEXES][2] QALIGN(16);
        vec4_t          vertexColors[SHADER_MAX_VERTEXES] QALIGN(16);
-       uint32_t    lightdir[SHADER_MAX_VERTEXES] QALIGN(16);
+       int16_t         lightdir[SHADER_MAX_VERTEXES][4] QALIGN(16);
        //int                   vertexDlightBits[SHADER_MAX_VERTEXES] 
QALIGN(16);
 
        void *attribPointers[ATTR_INDEX_COUNT];
@@ -2178,12 +2175,12 @@ VERTEX BUFFER OBJECTS
 ============================================================
 */
 
-int R_VaoPackTangent(byte *out, vec4_t v);
-int R_VaoPackNormal(byte *out, vec3_t v);
+void R_VaoPackTangent(int16_t *out, vec4_t v);
+void R_VaoPackNormal(int16_t *out, vec3_t v);
 int R_VaoPackTexCoord(byte *out, vec2_t st);
 int R_VaoPackColors(byte *out, vec4_t color);
-void R_VaoUnpackTangent(vec4_t v, uint32_t b);
-void R_VaoUnpackNormal(vec3_t v, uint32_t b);
+void R_VaoUnpackTangent(vec4_t v, int16_t *pack);
+void R_VaoUnpackNormal(vec3_t v, int16_t *pack);
 
 vao_t          *R_CreateVao(const char *name, byte *vertexes, int 
vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage);
 vao_t          *R_CreateVao2(const char *name, int numVertexes, srfVert_t 
*verts, int numIndexes, glIndex_t *inIndexes);
diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c
index 24d17e0..6530729 100644
--- a/code/renderergl2/tr_main.c
+++ b/code/renderergl2/tr_main.c
@@ -70,229 +70,10 @@ qboolean R_CompareVert(srfVert_t * v1, srfVert_t * v2, 
qboolean checkST)
 
 /*
 =============
-R_CalcNormalForTriangle
-=============
-*/
-void R_CalcNormalForTriangle(vec3_t normal, const vec3_t v0, const vec3_t v1, 
const vec3_t v2)
-{
-       vec3_t          udir, vdir;
+R_CalcTexDirs
 
-       // compute the face normal based on vertex points
-       VectorSubtract(v2, v0, udir);
-       VectorSubtract(v1, v0, vdir);
-       CrossProduct(udir, vdir, normal);
-
-       VectorNormalize(normal);
-}
-
-/*
+Lengyel, Eric. �Computing Tangent Space Basis Vectors for an Arbitrary Mesh�. 
Terathon Software 3D Graphics Library, 2001. 
http://www.terathon.com/code/tangent.html
 =============
-R_CalcTangentsForTriangle
-http://members.rogers.com/deseric/tangentspace.htm
-=============
-*/
-void R_CalcTangentsForTriangle(vec3_t tangent, vec3_t bitangent,
-                                                          const vec3_t v0, 
const vec3_t v1, const vec3_t v2,
-                                                          const vec2_t t0, 
const vec2_t t1, const vec2_t t2)
-{
-       int             i;
-       vec3_t          planes[3];
-       vec3_t          u, v;
-
-       for(i = 0; i < 3; i++)
-       {
-               VectorSet(u, v1[i] - v0[i], t1[0] - t0[0], t1[1] - t0[1]);
-               VectorSet(v, v2[i] - v0[i], t2[0] - t0[0], t2[1] - t0[1]);
-
-               VectorNormalize(u);
-               VectorNormalize(v);
-
-               CrossProduct(u, v, planes[i]);
-       }
-
-       //So your tangent space will be defined by this :
-       //Normal = Normal of the triangle or Tangent X Bitangent (careful with 
the cross product,
-       // you have to make sure the normal points in the right direction)
-       //Tangent = ( dp(Fx(s,t)) / ds,  dp(Fy(s,t)) / ds, dp(Fz(s,t)) / ds )   
or     ( -Bx/Ax, -By/Ay, - Bz/Az )
-       //Bitangent =  ( dp(Fx(s,t)) / dt,  dp(Fy(s,t)) / dt, dp(Fz(s,t)) / dt 
)  or     ( -Cx/Ax, -Cy/Ay, -Cz/Az )
-
-       // tangent...
-       tangent[0] = -planes[0][1] / planes[0][0];
-       tangent[1] = -planes[1][1] / planes[1][0];
-       tangent[2] = -planes[2][1] / planes[2][0];
-       VectorNormalize(tangent);
-
-       // bitangent...
-       bitangent[0] = -planes[0][2] / planes[0][0];
-       bitangent[1] = -planes[1][2] / planes[1][0];
-       bitangent[2] = -planes[2][2] / planes[2][0];
-       VectorNormalize(bitangent);
-}
-
-
-
-
-/*
-=============
-R_CalcTangentSpace
-=============
-*/
-void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
-                                               const vec3_t v0, const vec3_t 
v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
-{
-       vec3_t          cp, u, v;
-       vec3_t          faceNormal;
-
-       VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
-       VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
-
-       CrossProduct(u, v, cp);
-       if(fabs(cp[0]) > 10e-6)
-       {
-               tangent[0] = -cp[1] / cp[0];
-               bitangent[0] = -cp[2] / cp[0];
-       }
-
-       u[0] = v1[1] - v0[1];
-       v[0] = v2[1] - v0[1];
-
-       CrossProduct(u, v, cp);
-       if(fabs(cp[0]) > 10e-6)
-       {
-               tangent[1] = -cp[1] / cp[0];
-               bitangent[1] = -cp[2] / cp[0];
-       }
-
-       u[0] = v1[2] - v0[2];
-       v[0] = v2[2] - v0[2];
-
-       CrossProduct(u, v, cp);
-       if(fabs(cp[0]) > 10e-6)
-       {
-               tangent[2] = -cp[1] / cp[0];
-               bitangent[2] = -cp[2] / cp[0];
-       }
-
-       VectorNormalize(tangent);
-       VectorNormalize(bitangent);
-
-       // compute the face normal based on vertex points
-       if ( normal[0] == 0.0f && normal[1] == 0.0f && normal[2] == 0.0f )
-       {
-               VectorSubtract(v2, v0, u);
-               VectorSubtract(v1, v0, v);
-               CrossProduct(u, v, faceNormal);
-       }
-       else
-       {
-               VectorCopy(normal, faceNormal);
-       }
-
-       VectorNormalize(faceNormal);
-
-#if 1
-       // Gram-Schmidt orthogonalize
-       //tangent[a] = (t - n * Dot(n, t)).Normalize();
-       VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, 
tangent);
-       VectorNormalize(tangent);
-
-       // compute the cross product B=NxT
-       //CrossProduct(normal, tangent, bitangent);
-#else
-       // normal, compute the cross product N=TxB
-       CrossProduct(tangent, bitangent, normal);
-       VectorNormalize(normal);
-
-       if(DotProduct(normal, faceNormal) < 0)
-       {
-               //VectorInverse(normal);
-               //VectorInverse(tangent);
-               //VectorInverse(bitangent);
-
-               // compute the cross product T=BxN
-               CrossProduct(bitangent, faceNormal, tangent);
-
-               // compute the cross product B=NxT
-               //CrossProduct(normal, tangent, bitangent);
-       }
-#endif
-
-       VectorCopy(faceNormal, normal);
-}
-
-void R_CalcTangentSpaceFast(vec3_t tangent, vec3_t bitangent, vec3_t normal,
-                                               const vec3_t v0, const vec3_t 
v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
-{
-       vec3_t          cp, u, v;
-       vec3_t          faceNormal;
-
-       VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
-       VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
-
-       CrossProduct(u, v, cp);
-       if(fabs(cp[0]) > 10e-6)
-       {
-               tangent[0] = -cp[1] / cp[0];
-               bitangent[0] = -cp[2] / cp[0];
-       }
-
-       u[0] = v1[1] - v0[1];
-       v[0] = v2[1] - v0[1];
-
-       CrossProduct(u, v, cp);
-       if(fabs(cp[0]) > 10e-6)
-       {
-               tangent[1] = -cp[1] / cp[0];
-               bitangent[1] = -cp[2] / cp[0];
-       }
-
-       u[0] = v1[2] - v0[2];
-       v[0] = v2[2] - v0[2];
-
-       CrossProduct(u, v, cp);
-       if(fabs(cp[0]) > 10e-6)
-       {
-               tangent[2] = -cp[1] / cp[0];
-               bitangent[2] = -cp[2] / cp[0];
-       }
-
-       VectorNormalizeFast(tangent);
-       VectorNormalizeFast(bitangent);
-
-       // compute the face normal based on vertex points
-       VectorSubtract(v2, v0, u);
-       VectorSubtract(v1, v0, v);
-       CrossProduct(u, v, faceNormal);
-
-       VectorNormalizeFast(faceNormal);
-
-#if 0
-       // normal, compute the cross product N=TxB
-       CrossProduct(tangent, bitangent, normal);
-       VectorNormalizeFast(normal);
-
-       if(DotProduct(normal, faceNormal) < 0)
-       {
-               VectorInverse(normal);
-               //VectorInverse(tangent);
-               //VectorInverse(bitangent);
-
-               CrossProduct(normal, tangent, bitangent);
-       }
-
-       VectorCopy(faceNormal, normal);
-#else
-       // Gram-Schmidt orthogonalize
-               //tangent[a] = (t - n * Dot(n, t)).Normalize();
-       VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, 
tangent);
-       VectorNormalizeFast(tangent);
-#endif
-
-       VectorCopy(faceNormal, normal);
-}
-
-/*
-http://www.terathon.com/code/tangent.html
 */
 void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
                                   const vec3_t v3, const vec2_t w1, const 
vec2_t w2, const vec2_t w3)
@@ -312,13 +93,21 @@ void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t 
v1, const vec3_t v2,
        t1 = w2[1] - w1[1];
        t2 = w3[1] - w1[1];
 
-       r = 1.0f / (s1 * t2 - s2 * t1);
+       r = s1 * t2 - s2 * t1;
+       if (r) r = 1.0f / r;
 
        VectorSet(sdir, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * 
z1 - t1 * z2) * r);
        VectorSet(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * 
z2 - s2 * z1) * r);
 }
 
-void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t 
normal, vec3_t sdir, vec3_t tdir)
+/*
+=============
+R_CalcTangentSpace
+
+Lengyel, Eric. �Computing Tangent Space Basis Vectors for an Arbitrary Mesh�. 
Terathon Software 3D Graphics Library, 2001. 
http://www.terathon.com/code/tangent.html
+=============
+*/
+vec_t R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, const vec3_t 
normal, const vec3_t sdir, const vec3_t tdir)
 {
        vec3_t n_cross_t;
        vec_t n_dot_t, handedness;
@@ -332,113 +121,13 @@ void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, 
vec3_t bitangent, vec3_t norm
        CrossProduct(normal, sdir, n_cross_t);
        handedness = (DotProduct(n_cross_t, tdir) < 0.0f) ? -1.0f : 1.0f;
 
-       // Calculate bitangent
-       CrossProduct(normal, tangent, bitangent);
-       VectorScale(bitangent, handedness, bitangent);
-}
-
-void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal,
-                                               const vec3_t v1, const vec3_t 
v2, const vec3_t v3, const vec2_t t1, const vec2_t t2, const vec2_t t3)
-{
-       vec3_t                  v2v1;
-       vec3_t                  v3v1;
-
-       float                   c2c1_T;
-       float                   c2c1_B;
-
-       float                   c3c1_T;
-       float                   c3c1_B;
-
-       float                   denominator;
-       float                   scale1, scale2;
-
-       vec3_t                  T, B, N, C;
-
-
-       // Calculate the tangent basis for each vertex of the triangle
-       // UPDATE: In the 3rd edition of the accompanying article, the for-loop 
located here has
-       // been removed as it was redundant (the entire TBN matrix was 
calculated three times
-       // instead of just one).
-       //
-       // Please note, that this function relies on the fact that the input 
geometry are triangles
-       // and the tangent basis for each vertex thus is identical!
-       //
-
-       // Calculate the vectors from the current vertex to the two other 
vertices in the triangle
-       VectorSubtract(v2, v1, v2v1);
-       VectorSubtract(v3, v1, v3v1);
-
-       // The equation presented in the article states that:
-       // c2c1_T = V2.texcoord.x - V1.texcoord.x
-       // c2c1_B = V2.texcoord.y - V1.texcoord.y
-       // c3c1_T = V3.texcoord.x - V1.texcoord.x
-       // c3c1_B = V3.texcoord.y - V1.texcoord.y
-
-       // Calculate c2c1_T and c2c1_B
-       c2c1_T = t2[0] - t1[0];
-       c2c1_B = t2[1] - t2[1];
-
-       // Calculate c3c1_T and c3c1_B
-       c3c1_T = t3[0] - t1[0];
-       c3c1_B = t3[1] - t1[1];
-
-       denominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;
-       //if(ROUNDOFF(fDenominator) == 0.0f)
-       if(denominator == 0.0f)
-       {
-               // We won't risk a divide by zero, so set the tangent matrix to 
the identity matrix
-               VectorSet(tangent, 1, 0, 0);
-               VectorSet(bitangent, 0, 1, 0);
-               VectorSet(normal, 0, 0, 1);
-       }
-       else
-       {
-               // Calculate the reciprocal value once and for all (to achieve 
speed)
-               scale1 = 1.0f / denominator;
-
-               // T and B are calculated just as the equation in the article 
states
-               VectorSet(T, (c3c1_B * v2v1[0] - c2c1_B * v3v1[0]) * scale1,
-                                        (c3c1_B * v2v1[1] - c2c1_B * v3v1[1]) 
* scale1,
-                                        (c3c1_B * v2v1[2] - c2c1_B * v3v1[2]) 
* scale1);
-
-               VectorSet(B, (-c3c1_T * v2v1[0] + c2c1_T * v3v1[0]) * scale1,
-                                        (-c3c1_T * v2v1[1] + c2c1_T * v3v1[1]) 
* scale1,
-                                        (-c3c1_T * v2v1[2] + c2c1_T * v3v1[2]) 
* scale1);
-
-               // The normal N is calculated as the cross product between T 
and B
-               CrossProduct(T, B, N);
-
-#if 0
-               VectorCopy(T, tangent);
-               VectorCopy(B, bitangent);
-               VectorCopy(N, normal);
-#else
-               // Calculate the reciprocal value once and for all (to achieve 
speed)
-               scale2 = 1.0f / ((T[0] * B[1] * N[2] - T[2] * B[1] * N[0]) +
-                                       (B[0] * N[1] * T[2] - B[2] * N[1] * 
T[0]) +
-                                       (N[0] * T[1] * B[2] - N[2] * T[1] * 
B[0]));
-
-               // Calculate the inverse if the TBN matrix using the formula 
described in the article.
-               // We store the basis vectors directly in the provided TBN 
matrix: pvTBNMatrix
-               CrossProduct(B, N, C); tangent[0] = C[0] * scale2;
-               CrossProduct(N, T, C); tangent[1] = -C[0] * scale2;
-               CrossProduct(T, B, C); tangent[2] = C[0] * scale2;
-               VectorNormalize(tangent);
-
-               CrossProduct(B, N, C); bitangent[0] = -C[1] * scale2;
-               CrossProduct(N, T, C); bitangent[1] = C[1] * scale2;
-               CrossProduct(T, B, C); bitangent[2] = -C[1] * scale2;
-               VectorNormalize(bitangent);
+       // Calculate orthogonal bitangent, if necessary
+       if (bitangent)
+               CrossProduct(normal, tangent, bitangent);
 
-               CrossProduct(B, N, C); normal[0] = C[2] * scale2;
-               CrossProduct(N, T, C); normal[1] = -C[2] * scale2;
-               CrossProduct(T, B, C); normal[2] = C[2] * scale2;
-               VectorNormalize(normal);
-#endif
-       }
+       return handedness;
 }
 
-
 #ifdef USE_VERT_TANGENT_SPACE
 qboolean R_CalcTangentVectors(srfVert_t * dv[3])
 {
@@ -455,7 +144,8 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
        /* do each vertex */
        for(i = 0; i < 3; i++)
        {
-               vec3_t bitangent, nxt;
+               vec4_t tangent;
+               vec3_t normal, bitangent, nxt;
 
                // calculate s tangent vector
                s = dv[i]->st[0] + 10.0f;
@@ -464,12 +154,12 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
                bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - 
(dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
                bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - 
(dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
 
-               dv[i]->tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * 
dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
-               dv[i]->tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * 
dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
-               dv[i]->tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * 
dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
+               tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] 
+ bary[2] * dv[2]->xyz[0];
+               tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] 
+ bary[2] * dv[2]->xyz[1];
+               tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] 
+ bary[2] * dv[2]->xyz[2];
 
-               VectorSubtract(dv[i]->tangent, dv[i]->xyz, dv[i]->tangent);
-               VectorNormalize(dv[i]->tangent);
+               VectorSubtract(tangent, dv[i]->xyz, tangent);
+               VectorNormalize(tangent);
 
                // calculate t tangent vector
                s = dv[i]->st[0];
@@ -486,8 +176,11 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
                VectorNormalize(bitangent);
 
                // store bitangent handedness
-               CrossProduct(dv[i]->normal, dv[i]->tangent, nxt);
-               dv[i]->tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f 
: 1.0f;
+               R_VaoUnpackNormal(normal, dv[i]->normal);
+               CrossProduct(normal, tangent, nxt);
+               tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
+
+               R_VaoPackTangent(dv[i]->tangent, tangent);
 
                // debug code
                //% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
diff --git a/code/renderergl2/tr_marks.c b/code/renderergl2/tr_marks.c
index 830d4d2..682c13d 100644
--- a/code/renderergl2/tr_marks.c
+++ b/code/renderergl2/tr_marks.c
@@ -350,17 +350,21 @@ int R_MarkFragments( int numPoints, const vec3_t *points, 
const vec3_t projectio
                                        // The offset is added in the vertex 
normal vector direction
                                        // so all triangles will still fit 
together.
                                        // The 2 unit offset should avoid 
pretty much all LOD problems.
+                                       vec3_t fNormal;
 
                                        numClipPoints = 3;
 
                                        dv = cv->verts + m * cv->width + n;
 
                                        VectorCopy(dv[0].xyz, clipPoints[0][0]);
-                                       VectorMA(clipPoints[0][0], 
MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
+                                       R_VaoUnpackNormal(fNormal, 
dv[0].normal);
+                                       VectorMA(clipPoints[0][0], 
MARKER_OFFSET, fNormal, clipPoints[0][0]);
                                        VectorCopy(dv[cv->width].xyz, 
clipPoints[0][1]);
-                                       VectorMA(clipPoints[0][1], 
MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
+                                       R_VaoUnpackNormal(fNormal, 
dv[cv->width].normal);
+                                       VectorMA(clipPoints[0][1], 
MARKER_OFFSET, fNormal, clipPoints[0][1]);
                                        VectorCopy(dv[1].xyz, clipPoints[0][2]);
-                                       VectorMA(clipPoints[0][2], 
MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
+                                       R_VaoUnpackNormal(fNormal, 
dv[1].normal);
+                                       VectorMA(clipPoints[0][2], 
MARKER_OFFSET, fNormal, clipPoints[0][2]);
                                        // check the normal of this triangle
                                        VectorSubtract(clipPoints[0][0], 
clipPoints[0][1], v1);
                                        VectorSubtract(clipPoints[0][2], 
clipPoints[0][1], v2);
@@ -380,11 +384,14 @@ int R_MarkFragments( int numPoints, const vec3_t *points, 
const vec3_t projectio
                                        }
 
                                        VectorCopy(dv[1].xyz, clipPoints[0][0]);
-                                       VectorMA(clipPoints[0][0], 
MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
+                                       R_VaoUnpackNormal(fNormal, 
dv[1].normal);
+                                       VectorMA(clipPoints[0][0], 
MARKER_OFFSET, fNormal, clipPoints[0][0]);
                                        VectorCopy(dv[cv->width].xyz, 
clipPoints[0][1]);
-                                       VectorMA(clipPoints[0][1], 
MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
+                                       R_VaoUnpackNormal(fNormal, 
dv[cv->width].normal);
+                                       VectorMA(clipPoints[0][1], 
MARKER_OFFSET, fNormal, clipPoints[0][1]);
                                        VectorCopy(dv[cv->width+1].xyz, 
clipPoints[0][2]);
-                                       VectorMA(clipPoints[0][2], 
MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]);
+                                       R_VaoUnpackNormal(fNormal, dv[cv->width 
+ 1].normal);
+                                       VectorMA(clipPoints[0][2], 
MARKER_OFFSET, fNormal, clipPoints[0][2]);
                                        // check the normal of this triangle
                                        VectorSubtract(clipPoints[0][0], 
clipPoints[0][1], v1);
                                        VectorSubtract(clipPoints[0][2], 
clipPoints[0][1], v2);
@@ -441,8 +448,10 @@ int R_MarkFragments( int numPoints, const vec3_t *points, 
const vec3_t projectio
                        {
                                for(j = 0; j < 3; j++)
                                {
+                                       vec3_t fNormal;
                                        v = surf->verts[tri[j]].xyz;
-                                       VectorMA(v, MARKER_OFFSET, 
surf->verts[tri[j]].normal, clipPoints[0][j]);
+                                       R_VaoUnpackNormal(fNormal, 
surf->verts[tri[j]].normal);
+                                       VectorMA(v, MARKER_OFFSET, fNormal, 
clipPoints[0][j]);
                                }
 
                                // add the fragments of this face
diff --git a/code/renderergl2/tr_model.c b/code/renderergl2/tr_model.c
index 897e202..e1faee1 100644
--- a/code/renderergl2/tr_model.c
+++ b/code/renderergl2/tr_model.c
@@ -564,6 +564,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
                {
                        unsigned lat, lng;
                        unsigned short normal;
+                       vec3_t fNormal;
 
                        v->xyz[0] = LittleShort(md3xyz->xyz[0]) * MD3_XYZ_SCALE;
                        v->xyz[1] = LittleShort(md3xyz->xyz[1]) * MD3_XYZ_SCALE;
@@ -580,9 +581,11 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
                        // decode Y as sin( lat ) * sin( long )
                        // decode Z as cos( long )
 
-                       v->normal[0] = 
tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
-                       v->normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
-                       v->normal[2] = 
tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
+                       fNormal[0] = 
tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
+                       fNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
+                       fNormal[2] = 
tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
+
+                       R_VaoPackNormal(v->normal, fNormal);
                }
 
                // swap all the ST
@@ -598,10 +601,13 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
 #ifdef USE_VERT_TANGENT_SPACE
                // calc tangent spaces
                {
+                       vec3_t *sdirs = ri.Malloc(sizeof(*sdirs) * 
surf->numVerts * mdvModel->numFrames);
+                       vec3_t *tdirs = ri.Malloc(sizeof(*tdirs) * 
surf->numVerts * mdvModel->numFrames);
+
                        for(j = 0, v = surf->verts; j < (surf->numVerts * 
mdvModel->numFrames); j++, v++)
                        {
-                               VectorClear(v->tangent);
-                               VectorClear(v->bitangent);
+                               VectorClear(sdirs[j]);
+                               VectorClear(tdirs[j]);
                        }
 
                        for(f = 0; f < mdvModel->numFrames; f++)
@@ -626,27 +632,32 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
 
                                        R_CalcTexDirs(sdir, tdir, v0, v1, v2, 
t0, t1, t2);
 
-                                       VectorAdd(sdir, 
surf->verts[index0].tangent,   surf->verts[index0].tangent);
-                                       VectorAdd(sdir, 
surf->verts[index1].tangent,   surf->verts[index1].tangent);
-                                       VectorAdd(sdir, 
surf->verts[index2].tangent,   surf->verts[index2].tangent);
-                                       VectorAdd(tdir, 
surf->verts[index0].bitangent, surf->verts[index0].bitangent);
-                                       VectorAdd(tdir, 
surf->verts[index1].bitangent, surf->verts[index1].bitangent);
-                                       VectorAdd(tdir, 
surf->verts[index2].bitangent, surf->verts[index2].bitangent);
+                                       VectorAdd(sdir, sdirs[index0], 
sdirs[index0]);
+                                       VectorAdd(sdir, sdirs[index1], 
sdirs[index1]);
+                                       VectorAdd(sdir, sdirs[index2], 
sdirs[index2]);
+                                       VectorAdd(tdir, tdirs[index0], 
tdirs[index0]);
+                                       VectorAdd(tdir, tdirs[index1], 
tdirs[index1]);
+                                       VectorAdd(tdir, tdirs[index2], 
tdirs[index2]);
                                }
                        }
 
                        for(j = 0, v = surf->verts; j < (surf->numVerts * 
mdvModel->numFrames); j++, v++)
                        {
-                               vec3_t sdir, tdir;
+                               vec3_t normal;
+                               vec4_t tangent;
+
+                               VectorNormalize(sdirs[j]);
+                               VectorNormalize(tdirs[j]);
 
-                               VectorCopy(v->tangent,   sdir);
-                               VectorCopy(v->bitangent, tdir);
+                               R_VaoUnpackNormal(normal, v->normal);
 
-                               VectorNormalize(sdir);
-                               VectorNormalize(tdir);
+                               tangent[3] = R_CalcTangentSpace(tangent, NULL, 
normal, sdirs[j], tdirs[j]);
 
-                               R_CalcTbnFromNormalAndTexDirs(v->tangent, 
v->bitangent, v->normal, sdir, tdir);
+                               R_VaoPackTangent(v->tangent, tangent);
                        }
+
+                       ri.Free(sdirs);
+                       ri.Free(tdirs);
                }
 #endif
 
@@ -676,11 +687,11 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
                                offset_st      = 0;
                                offset_xyz     = surf->numVerts * 
glRefConfig.packedTexcoordDataSize;
                                offset_normal  = offset_xyz + sizeof(vec3_t);
-                               offset_tangent = offset_normal + 
sizeof(uint32_t);
+                               offset_tangent = offset_normal + 
sizeof(int16_t) * 4;
                                stride_st  = glRefConfig.packedTexcoordDataSize;
-                               stride_xyz = sizeof(vec3_t) + sizeof(uint32_t);
+                               stride_xyz = sizeof(vec3_t) + sizeof(int16_t) * 
4;
 #ifdef USE_VERT_TANGENT_SPACE
-                               stride_xyz += sizeof(uint32_t);
+                               stride_xyz += sizeof(int16_t) * 4;
 #endif
                                stride_normal = stride_tangent = stride_xyz;
 
@@ -692,11 +703,11 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
                                offset_xyz     = 0;
                                offset_st      = offset_xyz + sizeof(vec3_t);
                                offset_normal  = offset_st + 
glRefConfig.packedTexcoordDataSize;
-                               offset_tangent = offset_normal + 
sizeof(uint32_t);
+                               offset_tangent = offset_normal + 
sizeof(int16_t) * 4;
 #ifdef USE_VERT_TANGENT_SPACE
-                               stride_xyz = offset_tangent + sizeof(uint32_t);
+                               stride_xyz = offset_tangent + sizeof(int16_t) * 
4;
 #else
-                               stride_xyz = offset_normal + sizeof(uint32_t);
+                               stride_xyz = offset_normal + sizeof(int16_t) * 
4;
 #endif
                                stride_st = stride_normal = stride_tangent = 
stride_xyz;
 
@@ -717,24 +728,18 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
                                v = surf->verts;
                                for ( j = 0; j < surf->numVerts * 
mdvModel->numFrames ; j++, v++ )
                                {
-#ifdef USE_VERT_TANGENT_SPACE
-                                       vec3_t nxt;
-                                       vec4_t tangent;
-#endif
                                        // xyz
                                        memcpy(data + dataOfs, &v->xyz, 
sizeof(vec3_t));
                                        dataOfs += sizeof(vec3_t);
 
                                        // normal
-                                       dataOfs += R_VaoPackNormal(data + 
dataOfs, v->normal);
+                                       memcpy(data + dataOfs, &v->normal, 
sizeof(int16_t) * 4);
+                                       dataOfs += sizeof(int16_t) * 4;
 
 #ifdef USE_VERT_TANGENT_SPACE
-                                       CrossProduct(v->normal, v->tangent, 
nxt);
-                                       VectorCopy(v->tangent, tangent);
-                                       tangent[3] = (DotProduct(nxt, 
v->bitangent) < 0.0f) ? -1.0f : 1.0f;
-
                                        // tangent
-                                       dataOfs += R_VaoPackTangent(data + 
dataOfs, tangent);
+                                       memcpy(data + dataOfs, &v->tangent, 
sizeof(int16_t) * 4);
+                                       dataOfs += sizeof(int16_t) * 4;
 #endif
                                }
                        }
@@ -744,10 +749,6 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
                                st = surf->st;
                                for ( j = 0; j < surf->numVerts; j++, v++, st++ 
)
                                {
-#ifdef USE_VERT_TANGENT_SPACE
-                                       vec3_t nxt;
-                                       vec4_t tangent;
-#endif
                                        // xyz
                                        memcpy(data + dataOfs, &v->xyz, 
sizeof(vec3_t));
                                        dataOfs += sizeof(v->xyz);
@@ -756,15 +757,13 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
                                        dataOfs += R_VaoPackTexCoord(data + 
dataOfs, st->st);
 
                                        // normal
-                                       dataOfs += R_VaoPackNormal(data + 
dataOfs, v->normal);
+                                       memcpy(data + dataOfs, &v->normal, 
sizeof(int16_t) * 4);
+                                       dataOfs += sizeof(int16_t) * 4;
 
 #ifdef USE_VERT_TANGENT_SPACE
-                                       CrossProduct(v->normal, v->tangent, 
nxt);
-                                       VectorCopy(v->tangent, tangent);
-                                       tangent[3] = (DotProduct(nxt, 
v->bitangent) < 0.0f) ? -1.0f : 1.0f;
-
                                        // tangent
-                                       dataOfs += R_VaoPackTangent(data + 
dataOfs, tangent);
+                                       memcpy(data + dataOfs, &v->tangent, 
sizeof(int16_t) * 4);
+                                       dataOfs += sizeof(int16_t) * 4;
 #endif
                                }
                        }
@@ -794,8 +793,8 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void 
*buffer, int bufferSize,
 
                        vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = 
GL_FLOAT;
                        vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].type = 
glRefConfig.packedTexcoordDataType;
-                       vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].type = 
glRefConfig.packedNormalDataType;
-                       vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = 
glRefConfig.packedNormalDataType;
+                       vaoSurf->vao->attribs[ATTR_INDEX_NORMAL  ].type = 
GL_SHORT;
+                       vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = 
GL_SHORT;
 
                        vaoSurf->vao->attribs[ATTR_INDEX_POSITION].normalized = 
GL_FALSE;
                        vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].normalized = 
GL_FALSE;
diff --git a/code/renderergl2/tr_model_iqm.c b/code/renderergl2/tr_model_iqm.c
index 3cabca0..e30e706 100644
--- a/code/renderergl2/tr_model_iqm.c
+++ b/code/renderergl2/tr_model_iqm.c
@@ -1024,9 +1024,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
        int             i;
 
        vec4_t          *outXYZ;
-       uint32_t        *outNormal;
+       int16_t *outNormal;
 #ifdef USE_VERT_TANGENT_SPACE
-       uint32_t        *outTangent;
+       int16_t *outTangent;
 #endif
        vec2_t          (*outTexCoord)[2];
        vec4_t  *outColor;
@@ -1042,9 +1042,9 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
        RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 );
 
        outXYZ = &tess.xyz[tess.numVertexes];
-       outNormal = &tess.normal[tess.numVertexes];
+       outNormal = tess.normal[tess.numVertexes];
 #ifdef USE_VERT_TANGENT_SPACE
-       outTangent = &tess.tangent[tess.numVertexes];
+       outTangent = tess.tangent[tess.numVertexes];
 #endif
        outTexCoord = &tess.texCoords[tess.numVertexes];
        outColor = &tess.vertexColors[tess.numVertexes];
@@ -1056,7 +1056,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
 
        // transform vertexes and fill other data
        for( i = 0; i < surf->num_vertexes;
-            i++, outXYZ++, outNormal++, outTexCoord++, outColor++ ) {
+            i++, outXYZ++, outNormal+=4, outTexCoord++, outColor++ ) {
                int     j, k;
                float   vtxMat[12];
                float   nrmMat[9];
@@ -1130,7 +1130,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
                        normal[1] = DotProduct(&nrmMat[3], 
&data->normals[3*vtx]);
                        normal[2] = DotProduct(&nrmMat[6], 
&data->normals[3*vtx]);
 
-                       R_VaoPackNormal((byte *)outNormal, normal);
+                       R_VaoPackNormal(outNormal, normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
                        tangent[0] = DotProduct(&nrmMat[0], 
&data->tangents[4*vtx]);
@@ -1138,7 +1138,8 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
                        tangent[2] = DotProduct(&nrmMat[6], 
&data->tangents[4*vtx]);
                        tangent[3] = data->tangents[4*vtx+3];
 
-                       R_VaoPackTangent((byte *)outTangent++, tangent);
+                       R_VaoPackTangent(outTangent, tangent);
+                       outTangent+=4;
 #endif
                }
 
diff --git a/code/renderergl2/tr_shade_calc.c b/code/renderergl2/tr_shade_calc.c
index dcb9994..898557e 100644
--- a/code/renderergl2/tr_shade_calc.c
+++ b/code/renderergl2/tr_shade_calc.c
@@ -116,16 +116,16 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
        vec3_t  offset;
        float   scale;
        float   *xyz = ( float * ) tess.xyz;
-       uint32_t        *normal = tess.normal;
+       int16_t *normal = tess.normal[0];
        float   *table;
 
        if ( ds->deformationWave.frequency == 0 )
        {
                scale = EvalWaveForm( &ds->deformationWave );
 
-               for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
+               for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
                {
-                       R_VaoUnpackNormal(offset, *normal);
+                       R_VaoUnpackNormal(offset, normal);
                        
                        xyz[0] += offset[0] * scale;
                        xyz[1] += offset[1] * scale;
@@ -136,7 +136,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
        {
                table = TableForFunc( ds->deformationWave.func );
 
-               for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
+               for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
                {
                        float off = ( xyz[0] + xyz[1] + xyz[2] ) * 
ds->deformationSpread;
 
@@ -145,7 +145,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
                                ds->deformationWave.phase + off,
                                ds->deformationWave.frequency );
 
-                       R_VaoUnpackNormal(offset, *normal);
+                       R_VaoUnpackNormal(offset, normal);
 
                        xyz[0] += offset[0] * scale;
                        xyz[1] += offset[1] * scale;
@@ -165,12 +165,12 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
        int i;
        float   scale;
        float   *xyz = ( float * ) tess.xyz;
-       uint32_t *normal = tess.normal;
+       int16_t *normal = tess.normal[0];
 
-       for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) {
+       for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) {
                vec3_t fNormal;
 
-               R_VaoUnpackNormal(fNormal, *normal);
+               R_VaoUnpackNormal(fNormal, normal);
 
                scale = 0.98f;
                scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * 
scale,
@@ -189,7 +189,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
 
                VectorNormalizeFast( fNormal );
 
-               R_VaoPackNormal((byte *)normal, fNormal);
+               R_VaoPackNormal(normal, fNormal);
        }
 }
 
@@ -203,17 +203,17 @@ void RB_CalcBulgeVertexes( deformStage_t *ds ) {
        int i;
        const float *st = ( const float * ) tess.texCoords[0];
        float           *xyz = ( float * ) tess.xyz;
-       uint32_t                *normal = tess.normal;
+       int16_t *normal = tess.normal[0];
        float           now;
 
        now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f;
 
-       for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal++ ) {
+       for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal += 4 
) {
                int             off;
                float scale;
                vec3_t fNormal;
 
-               R_VaoUnpackNormal(fNormal, *normal);
+               R_VaoUnpackNormal(fNormal, normal);
 
                off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * 
ds->bulgeWidth + now );
 
diff --git a/code/renderergl2/tr_surface.c b/code/renderergl2/tr_surface.c
index edaf43d..c19410c 100644
--- a/code/renderergl2/tr_surface.c
+++ b/code/renderergl2/tr_surface.c
@@ -88,7 +88,7 @@ RB_AddQuadStampExt
 */
 void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float 
color[4], float s1, float t1, float s2, float t2 ) {
        vec3_t          normal;
-       uint32_t    pNormal;
+       int16_t     iNormal[4];
        int                     ndx;
 
        RB_CheckVao(tess.vao);
@@ -126,11 +126,12 @@ void RB_AddQuadStampExt( vec3_t origin, vec3_t left, 
vec3_t up, float color[4],
        // constant normal all the way around
        VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal );
 
-       R_VaoPackNormal((byte *)&pNormal, normal);
-       tess.normal[ndx] =
-       tess.normal[ndx+1] =
-       tess.normal[ndx+2] =
-       tess.normal[ndx+3] = pNormal;
+       R_VaoPackNormal(iNormal, normal);
+
+       VectorCopy4(tess.normal[ndx], iNormal);
+       VectorCopy4(tess.normal[ndx+1], iNormal);
+       VectorCopy4(tess.normal[ndx+2], iNormal);
+       VectorCopy4(tess.normal[ndx+3], iNormal);
 
        // standard square texture coordinates
        VectorSet2(tess.texCoords[ndx  ][0], s1, t1);
@@ -320,10 +321,10 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, 
srfVert_t *verts, int numIn
        glIndex_t      *inIndex;
        srfVert_t      *dv;
        float          *xyz, *texCoords, *lightCoords;
-       uint32_t        *lightdir;
-       uint32_t        *normal;
+       int16_t        *lightdir;
+       int16_t        *normal;
 #ifdef USE_VERT_TANGENT_SPACE
-       uint32_t        *tangent;
+       int16_t        *tangent;
 #endif
        glIndex_t      *outIndex;
        float          *color;
@@ -350,18 +351,18 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, 
srfVert_t *verts, int numIn
        if ( tess.shader->vertexAttribs & ATTR_NORMAL )
        {
                dv = verts;
-               normal = &tess.normal[ tess.numVertexes ];
-               for ( i = 0 ; i < numVerts ; i++, dv++, normal++ )
-                       R_VaoPackNormal((byte *)normal, dv->normal);
+               normal = tess.normal[ tess.numVertexes ];
+               for ( i = 0 ; i < numVerts ; i++, dv++, normal+=4 )
+                       VectorCopy4(dv->normal, normal);
        }
 
 #ifdef USE_VERT_TANGENT_SPACE
        if ( tess.shader->vertexAttribs & ATTR_TANGENT )
        {
                dv = verts;
-               tangent = &tess.tangent[ tess.numVertexes ];
-               for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ )
-                       R_VaoPackTangent((byte *)tangent, dv->tangent);
+               tangent = tess.tangent[ tess.numVertexes ];
+               for ( i = 0 ; i < numVerts ; i++, dv++, tangent+=4 )
+                       VectorCopy4(dv->tangent, tangent);
        }
 #endif
 
@@ -392,9 +393,9 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, 
srfVert_t *verts, int numIn
        if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
        {
                dv = verts;
-               lightdir = &tess.lightdir[ tess.numVertexes ];
-               for ( i = 0 ; i < numVerts ; i++, dv++, lightdir++ )
-                       R_VaoPackNormal((byte *)lightdir, dv->lightdir);
+               lightdir = tess.lightdir[ tess.numVertexes ];
+               for ( i = 0 ; i < numVerts ; i++, dv++, lightdir+=4 )
+                       VectorCopy4(dv->lightdir, lightdir);
        }
 
 #if 0  // nothing even uses vertex dlightbits
@@ -841,308 +842,19 @@ static void RB_SurfaceLightningBolt( void ) {
        }
 }
 
-#if 0
-/*
-** VectorArrayNormalize
-*
-* The inputs to this routing seem to always be close to length = 1.0 (about 
0.6 to 2.0)
-* This means that we don't have to worry about zero length or enormously long 
vectors.
-*/
-static void VectorArrayNormalize(vec4_t *normals, unsigned int count)
-{
-//    assert(count);
-        
-#if idppc
-    {
-        register float half = 0.5;
-        register float one  = 1.0;
-        float *components = (float *)normals;
-        
-        // Vanilla PPC code, but since PPC has a reciprocal square root 
estimate instruction,
-        // runs *much* faster than calling sqrt().  We'll use a single 
Newton-Raphson
-        // refinement step to get a little more precision.  This seems to 
yeild results
-        // that are correct to 3 decimal places and usually correct to at 
least 4 (sometimes 5).
-        // (That is, for the given input range of about 0.6 to 2.0).
-        do {
-            float x, y, z;
-            float B, y0, y1;
-            
-            x = components[0];
-            y = components[1];
-            z = components[2];
-            components += 4;
-            B = x*x + y*y + z*z;
-
-#ifdef __GNUC__            
-            asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
-#else
-                       y0 = __frsqrte(B);
-#endif
-            y1 = y0 + half*y0*(one - B*y0*y0);
-
-            x = x * y1;
-            y = y * y1;
-            components[-4] = x;
-            z = z * y1;
-            components[-3] = y;
-            components[-2] = z;
-        } while(count--);
-    }
-#else // No assembly version for this architecture, or C_ONLY defined
-       // given the input, it's safe to call VectorNormalizeFast
-    while (count--) {
-        VectorNormalizeFast(normals[0]);
-        normals++;
-    }
-#endif
-
-}
-#endif
 
-
-
-/*
-** LerpMeshVertexes
-*/
-#if 0
-#if idppc_altivec
-static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp)
-{
-       short   *oldXyz, *newXyz, *oldNormals, *newNormals;
-       float   *outXyz, *outNormal;
-       float   oldXyzScale QALIGN(16);
-       float   newXyzScale QALIGN(16);
-       float   oldNormalScale QALIGN(16);
-       float newNormalScale QALIGN(16);
-       int             vertNum;
-       unsigned lat, lng;
-       int             numVerts;
-
-       outXyz = tess.xyz[tess.numVertexes];
-       outNormal = tess.normal[tess.numVertexes];
-
-       newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
-               + (backEnd.currentEntity->e.frame * surf->numVerts * 4);
-       newNormals = newXyz + 3;
-
-       newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
-       newNormalScale = 1.0 - backlerp;
-
-       numVerts = surf->numVerts;
-
-       if ( backlerp == 0 ) {
-               vector signed short newNormalsVec0;
-               vector signed short newNormalsVec1;
-               vector signed int newNormalsIntVec;
-               vector float newNormalsFloatVec;
-               vector float newXyzScaleVec;
-               vector unsigned char newNormalsLoadPermute;
-               vector unsigned char newNormalsStorePermute;
-               vector float zero;
-               
-               newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec);
-               newXyzScaleVec = *(vector float *)&newXyzScale;
-               newXyzScaleVec = 
vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute);
-               newXyzScaleVec = vec_splat(newXyzScaleVec,0);           
-               newNormalsLoadPermute = vec_lvsl(0,newXyz);
-               newNormalsStorePermute = vec_lvsr(0,outXyz);
-               zero = (vector float)vec_splat_s8(0);
-               //
-               // just copy the vertexes
-               //
-               for (vertNum=0 ; vertNum < numVerts ; vertNum++,
-                       newXyz += 4, newNormals += 4,
-                       outXyz += 4, outNormal += 4) 
-               {
-                       newNormalsLoadPermute = vec_lvsl(0,newXyz);
-                       newNormalsStorePermute = vec_lvsr(0,outXyz);
-                       newNormalsVec0 = vec_ld(0,newXyz);
-                       newNormalsVec1 = vec_ld(16,newXyz);
-                       newNormalsVec0 = 
vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute);
-                       newNormalsIntVec = vec_unpackh(newNormalsVec0);
-                       newNormalsFloatVec = vec_ctf(newNormalsIntVec,0);
-                       newNormalsFloatVec = 
vec_madd(newNormalsFloatVec,newXyzScaleVec,zero);
-                       newNormalsFloatVec = 
vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute);
-                       //outXyz[0] = newXyz[0] * newXyzScale;
-                       //outXyz[1] = newXyz[1] * newXyzScale;
-                       //outXyz[2] = newXyz[2] * newXyzScale;
-
-                       lat = ( newNormals[0] >> 8 ) & 0xff;
-                       lng = ( newNormals[0] & 0xff );
-                       lat *= (FUNCTABLE_SIZE/256);
-                       lng *= (FUNCTABLE_SIZE/256);
-
-                       // decode X as cos( lat ) * sin( long )
-                       // decode Y as sin( lat ) * sin( long )
-                       // decode Z as cos( long )
-
-                       outNormal[0] = 
tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
-                       outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
-                       outNormal[2] = 
tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
-                       vec_ste(newNormalsFloatVec,0,outXyz);
-                       vec_ste(newNormalsFloatVec,4,outXyz);
-                       vec_ste(newNormalsFloatVec,8,outXyz);
-               }
-       } else {
-               //
-               // interpolate and copy the vertex and normal
-               //
-               oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
-                       + (backEnd.currentEntity->e.oldframe * surf->numVerts * 
4);
-               oldNormals = oldXyz + 3;
-
-               oldXyzScale = MD3_XYZ_SCALE * backlerp;
-               oldNormalScale = backlerp;
-
-               for (vertNum=0 ; vertNum < numVerts ; vertNum++,
-                       oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals 
+= 4,
-                       outXyz += 4, outNormal += 4) 
-               {
-                       vec3_t uncompressedOldNormal, uncompressedNewNormal;
-
-                       // interpolate the xyz
-                       outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * 
newXyzScale;
-                       outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * 
newXyzScale;
-                       outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * 
newXyzScale;
-
-                       // FIXME: interpolate lat/long instead?
-                       lat = ( newNormals[0] >> 8 ) & 0xff;
-                       lng = ( newNormals[0] & 0xff );
-                       lat *= 4;
-                       lng *= 4;
-                       uncompressedNewNormal[0] = 
tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
-                       uncompressedNewNormal[1] = tr.sinTable[lat] * 
tr.sinTable[lng];
-                       uncompressedNewNormal[2] = 
tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
-                       lat = ( oldNormals[0] >> 8 ) & 0xff;
-                       lng = ( oldNormals[0] & 0xff );
-                       lat *= 4;
-                       lng *= 4;
-
-                       uncompressedOldNormal[0] = 
tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
-                       uncompressedOldNormal[1] = tr.sinTable[lat] * 
tr.sinTable[lng];
-                       uncompressedOldNormal[2] = 
tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
-                       outNormal[0] = uncompressedOldNormal[0] * 
oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
-                       outNormal[1] = uncompressedOldNormal[1] * 
oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
-                       outNormal[2] = uncompressedOldNormal[2] * 
oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
-
-//                     VectorNormalize (outNormal);
-               }
-       VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
-       }
-}
-#endif
-#endif
-
-static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
+static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
 {
-#if 0
-       short   *oldXyz, *newXyz, *oldNormals, *newNormals;
-       float   *outXyz, *outNormal;
-       float   oldXyzScale, newXyzScale;
-       float   oldNormalScale, newNormalScale;
-       int             vertNum;
-       unsigned lat, lng;
-       int             numVerts;
-
-       outXyz = tess.xyz[tess.numVertexes];
-       outNormal = tess.normal[tess.numVertexes];
-
-       newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
-               + (backEnd.currentEntity->e.frame * surf->numVerts * 4);
-       newNormals = newXyz + 3;
-
-       newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
-       newNormalScale = 1.0 - backlerp;
-
-       numVerts = surf->numVerts;
-
-       if ( backlerp == 0 ) {
-               //
-               // just copy the vertexes
-               //
-               for (vertNum=0 ; vertNum < numVerts ; vertNum++,
-                       newXyz += 4, newNormals += 4,
-                       outXyz += 4, outNormal += 4) 
-               {
-
-                       outXyz[0] = newXyz[0] * newXyzScale;
-                       outXyz[1] = newXyz[1] * newXyzScale;
-                       outXyz[2] = newXyz[2] * newXyzScale;
-
-                       lat = ( newNormals[0] >> 8 ) & 0xff;
-                       lng = ( newNormals[0] & 0xff );
-                       lat *= (FUNCTABLE_SIZE/256);
-                       lng *= (FUNCTABLE_SIZE/256);
-
-                       // decode X as cos( lat ) * sin( long )
-                       // decode Y as sin( lat ) * sin( long )
-                       // decode Z as cos( long )
-
-                       outNormal[0] = 
tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
-                       outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
-                       outNormal[2] = 
tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-               }
-       } else {
-               //
-               // interpolate and copy the vertex and normal
-               //
-               oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
-                       + (backEnd.currentEntity->e.oldframe * surf->numVerts * 
4);
-               oldNormals = oldXyz + 3;
-
-               oldXyzScale = MD3_XYZ_SCALE * backlerp;
-               oldNormalScale = backlerp;
-
-               for (vertNum=0 ; vertNum < numVerts ; vertNum++,
-                       oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals 
+= 4,
-                       outXyz += 4, outNormal += 4) 
-               {
-                       vec3_t uncompressedOldNormal, uncompressedNewNormal;
-
-                       // interpolate the xyz
-                       outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * 
newXyzScale;
-                       outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * 
newXyzScale;
-                       outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * 
newXyzScale;
-
-                       // FIXME: interpolate lat/long instead?
-                       lat = ( newNormals[0] >> 8 ) & 0xff;
-                       lng = ( newNormals[0] & 0xff );
-                       lat *= 4;
-                       lng *= 4;
-                       uncompressedNewNormal[0] = 
tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
-                       uncompressedNewNormal[1] = tr.sinTable[lat] * 
tr.sinTable[lng];
-                       uncompressedNewNormal[2] = 
tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
-                       lat = ( oldNormals[0] >> 8 ) & 0xff;
-                       lng = ( oldNormals[0] & 0xff );
-                       lat *= 4;
-                       lng *= 4;
-
-                       uncompressedOldNormal[0] = 
tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
-                       uncompressedOldNormal[1] = tr.sinTable[lat] * 
tr.sinTable[lng];
-                       uncompressedOldNormal[2] = 
tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
-                       outNormal[0] = uncompressedOldNormal[0] * 
oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
-                       outNormal[1] = uncompressedOldNormal[1] * 
oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
-                       outNormal[2] = uncompressedOldNormal[2] * 
oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
-
-//                     VectorNormalize (outNormal);
-               }
-       VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
-       }
-#endif
        float *outXyz;
-       uint32_t *outNormal;
+       int16_t *outNormal, *outTangent;
        mdvVertex_t *newVerts;
        int             vertNum;
 
        newVerts = surf->verts + backEnd.currentEntity->e.frame * 
surf->numVerts;
 
-       outXyz =    tess.xyz[tess.numVertexes];
-       outNormal = &tess.normal[tess.numVertexes];
+       outXyz =     tess.xyz[tess.numVertexes];
+       outNormal =  tess.normal[tess.numVertexes];
+       outTangent = tess.tangent[tess.numVertexes];
 
        if (backlerp == 0)
        {
@@ -1152,16 +864,14 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, 
float backlerp)
 
                for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
                {
-                       vec3_t normal;
-
                        VectorCopy(newVerts->xyz,    outXyz);
-                       VectorCopy(newVerts->normal, normal);
-
-                       R_VaoPackNormal((byte *)outNormal, normal);
+                       VectorCopy4(newVerts->normal, outNormal);
+                       VectorCopy4(newVerts->tangent, outTangent);
 
                        newVerts++;
                        outXyz += 4;
-                       outNormal++;
+                       outNormal += 4;
+                       outTangent += 4;
                }
        }
        else
@@ -1176,37 +886,28 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, 
float backlerp)
 
                for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
                {
-                       vec3_t normal;
-
                        VectorLerp(newVerts->xyz,    oldVerts->xyz,    
backlerp, outXyz);
-                       VectorLerp(newVerts->normal, oldVerts->normal, 
backlerp, normal);
-                       VectorNormalize(normal);
 
-                       R_VaoPackNormal((byte *)outNormal, normal);
+                       outNormal[0] = (int16_t)(newVerts->normal[0] * (1.0f - 
backlerp) + oldVerts->normal[0] * backlerp);
+                       outNormal[1] = (int16_t)(newVerts->normal[1] * (1.0f - 
backlerp) + oldVerts->normal[1] * backlerp);
+                       outNormal[2] = (int16_t)(newVerts->normal[2] * (1.0f - 
backlerp) + oldVerts->normal[2] * backlerp);
+                       outNormal[3] = 0;
+
+                       outTangent[0] = (int16_t)(newVerts->tangent[0] * (1.0f 
- backlerp) + oldVerts->tangent[0] * backlerp);
+                       outTangent[1] = (int16_t)(newVerts->tangent[1] * (1.0f 
- backlerp) + oldVerts->tangent[1] * backlerp);
+                       outTangent[2] = (int16_t)(newVerts->tangent[2] * (1.0f 
- backlerp) + oldVerts->tangent[2] * backlerp);
+                       outTangent[3] = newVerts->tangent[3];
 
                        newVerts++;
                        oldVerts++;
                        outXyz += 4;
-                       outNormal++;
+                       outNormal += 4;
+                       outTangent += 4;
                }
        }
 
 }
 
-static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
-{
-#if 0
-#if idppc_altivec
-       if (com_altivec->integer) {
-               // must be in a seperate function or G3 systems will crash.
-               LerpMeshVertexes_altivec( surf, backlerp );
-               return;
-       }
-#endif // idppc_altivec
-#endif
-       LerpMeshVertexes_scalar( surf, backlerp );
-}
-
 
 /*
 =============
@@ -1311,12 +1012,12 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
        int             i, j;
        float   *xyz;
        float   *texCoords, *lightCoords;
-       uint32_t *normal;
+       int16_t *normal;
 #ifdef USE_VERT_TANGENT_SPACE
-       uint32_t *tangent;
+       int16_t *tangent;
 #endif
        float   *color;
-       uint32_t *lightdir;
+       int16_t *lightdir;
        srfVert_t       *dv;
        int             rows, irows, vrows;
        int             used;
@@ -1401,14 +1102,14 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
                numVertexes = tess.numVertexes;
 
                xyz = tess.xyz[numVertexes];
-               normal = &tess.normal[numVertexes];
+               normal = tess.normal[numVertexes];
 #ifdef USE_VERT_TANGENT_SPACE
-               tangent = &tess.tangent[numVertexes];
+               tangent = tess.tangent[numVertexes];
 #endif
                texCoords = tess.texCoords[numVertexes][0];
                lightCoords = tess.texCoords[numVertexes][1];
                color = tess.vertexColors[numVertexes];
-               lightdir = &tess.lightdir[numVertexes];
+               lightdir = tess.lightdir[numVertexes];
                //vDlightBits = &tess.vertexDlightBits[numVertexes];
 
                for ( i = 0 ; i < rows ; i++ ) {
@@ -1424,13 +1125,15 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
 
                                if ( tess.shader->vertexAttribs & ATTR_NORMAL )
                                {
-                                       R_VaoPackNormal((byte *)normal++, 
dv->normal);
+                                       VectorCopy4(normal, dv->normal);
+                                       normal += 4;
                                }
 
 #ifdef USE_VERT_TANGENT_SPACE
                                if ( tess.shader->vertexAttribs & ATTR_TANGENT )
                                {
-                                       R_VaoPackTangent((byte *)tangent++, 
dv->tangent);
+                                       VectorCopy4(tangent, dv->tangent);
+                                       tangent += 4;
                                }
 #endif
                                if ( tess.shader->vertexAttribs & ATTR_TEXCOORD 
)
@@ -1453,7 +1156,8 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
 
                                if ( tess.shader->vertexAttribs & 
ATTR_LIGHTDIRECTION )
                                {
-                                       R_VaoPackNormal((byte *)lightdir++, 
dv->lightdir);
+                                       VectorCopy4(lightdir, dv->lightdir);
+                                       lightdir += 4;
                                }
 
                                //*vDlightBits++ = dlightBits;
diff --git a/code/renderergl2/tr_vbo.c b/code/renderergl2/tr_vbo.c
index b1ff3d6..db3d8eb 100644
--- a/code/renderergl2/tr_vbo.c
+++ b/code/renderergl2/tr_vbo.c
@@ -23,73 +23,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
02110-1301  USA
 #include "tr_local.h"
 
 
-union pack10_u {
-       struct {
-               signed int x:10;
-               signed int y:10;
-               signed int z:10;
-               signed int w:2;
-       } pack;
-       uint32_t i;
-};
-
-union pack8_u {
-       struct {
-               signed int x:8;
-               signed int y:8;
-               signed int z:8;
-               signed int w:8;
-       } pack;
-       uint32_t i;
-};
-
-
-int R_VaoPackTangent(byte *out, vec4_t v)
+void R_VaoPackTangent(int16_t *out, vec4_t v)
 {
-       if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
-       {
-               union pack10_u *num = (union pack10_u *)out;
-
-               num->pack.x = v[0] * 511.0f;
-               num->pack.y = v[1] * 511.0f;
-               num->pack.z = v[2] * 511.0f;
-               num->pack.w = v[3];
-       }
-       else
-       {
-               union pack8_u *num = (union pack8_u *)out;
-
-               num->pack.x = v[0] * 127.0f;
-               num->pack.y = v[1] * 127.0f;
-               num->pack.z = v[2] * 127.0f;
-               num->pack.w = v[3] * 127.0f;
-       }
-
-       return 4;
+       out[0] = v[0] * 32767.0f + (v[0] > 0.0f ? 0.5f : -0.5f);
+       out[1] = v[1] * 32767.0f + (v[1] > 0.0f ? 0.5f : -0.5f);
+       out[2] = v[2] * 32767.0f + (v[2] > 0.0f ? 0.5f : -0.5f);
+       out[3] = v[3] * 32767.0f + (v[3] > 0.0f ? 0.5f : -0.5f);
 }
 
-int R_VaoPackNormal(byte *out, vec3_t v)
+void R_VaoPackNormal(int16_t *out, vec3_t v)
 {
-       if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
-       {
-               union pack10_u *num = (union pack10_u *)out;
-
-               num->pack.x = v[0] * 511.0f;
-               num->pack.y = v[1] * 511.0f;
-               num->pack.z = v[2] * 511.0f;
-               num->pack.w = 0;
-       }
-       else
-       {
-               union pack8_u *num = (union pack8_u *)out;
-
-               num->pack.x = v[0] * 127.0f;
-               num->pack.y = v[1] * 127.0f;
-               num->pack.z = v[2] * 127.0f;
-               num->pack.w = 0;
-       }
-
-       return 4;
+       out[0] = v[0] * 32767.0f + (v[0] > 0.0f ? 0.5f : -0.5f);
+       out[1] = v[1] * 32767.0f + (v[1] > 0.0f ? 0.5f : -0.5f);
+       out[2] = v[2] * 32767.0f + (v[2] > 0.0f ? 0.5f : -0.5f);
+       out[3] = 0;
 }
 
 int R_VaoPackTexCoord(byte *out, vec2_t st)
@@ -140,50 +87,21 @@ int R_VaoPackColors(byte *out, vec4_t color)
        }
 }
 
-
-void R_VaoUnpackTangent(vec4_t v, uint32_t b)
+void R_VaoUnpackTangent(vec4_t v, int16_t *pack)
 {
-       if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
-       {
-               union pack10_u *num = (union pack10_u *)&b;
-
-               v[0] = num->pack.x / 511.0f;
-               v[1] = num->pack.y / 511.0f;
-               v[2] = num->pack.z / 511.0f;
-               v[3] = num->pack.w; 
-       }
-       else
-       {
-               union pack8_u *num = (union pack8_u *)&b;
-
-               v[0] = num->pack.x / 127.0f;
-               v[1] = num->pack.y / 127.0f;
-               v[2] = num->pack.z / 127.0f;
-               v[3] = num->pack.w / 127.0f; 
-       }
+       v[0] = pack[0] / 32767.0f;
+       v[1] = pack[1] / 32767.0f;
+       v[2] = pack[2] / 32767.0f;
+       v[3] = pack[3] / 32767.0f;
 }
 
-void R_VaoUnpackNormal(vec3_t v, uint32_t b)
+void R_VaoUnpackNormal(vec3_t v, int16_t *pack)
 {
-       if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV)
-       {
-               union pack10_u *num = (union pack10_u *)&b;
-
-               v[0] = num->pack.x / 511.0f;
-               v[1] = num->pack.y / 511.0f;
-               v[2] = num->pack.z / 511.0f;
-       }
-       else
-       {
-               union pack8_u *num = (union pack8_u *)&b;
-
-               v[0] = num->pack.x / 127.0f;
-               v[1] = num->pack.y / 127.0f;
-               v[2] = num->pack.z / 127.0f;
-       }
+       v[0] = pack[0] / 32767.0f;
+       v[1] = pack[1] / 32767.0f;
+       v[2] = pack[2] / 32767.0f;
 }
 
-
 void Vao_SetVertexPointers(vao_t *vao)
 {
        int attribIndex;
@@ -347,12 +265,12 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, 
srfVert_t *verts, int num
        vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
 
        vao->attribs[ATTR_INDEX_POSITION      ].type = GL_FLOAT;
-       vao->attribs[ATTR_INDEX_NORMAL        ].type = 
glRefConfig.packedNormalDataType;
-       vao->attribs[ATTR_INDEX_TANGENT       ].type = 
glRefConfig.packedNormalDataType;
+       vao->attribs[ATTR_INDEX_NORMAL        ].type = GL_SHORT;
+       vao->attribs[ATTR_INDEX_TANGENT       ].type = GL_SHORT;
        vao->attribs[ATTR_INDEX_TEXCOORD      ].type = 
glRefConfig.packedTexcoordDataType;
        vao->attribs[ATTR_INDEX_LIGHTCOORD    ].type = 
glRefConfig.packedTexcoordDataType;
        vao->attribs[ATTR_INDEX_COLOR         ].type = 
glRefConfig.packedColorDataType;
-       vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = 
glRefConfig.packedNormalDataType;
+       vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = GL_SHORT;
 
        vao->attribs[ATTR_INDEX_POSITION      ].normalized = GL_FALSE;
        vao->attribs[ATTR_INDEX_NORMAL        ].normalized = GL_TRUE;
@@ -363,14 +281,14 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, 
srfVert_t *verts, int num
        vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
 
        vao->attribs[ATTR_INDEX_POSITION      ].offset = 0;        dataSize  = 
sizeof(verts[0].xyz);
-       vao->attribs[ATTR_INDEX_NORMAL        ].offset = dataSize; dataSize += 
sizeof(uint32_t);
+       vao->attribs[ATTR_INDEX_NORMAL        ].offset = dataSize; dataSize += 
sizeof(verts[0].normal);
 #ifdef USE_VERT_TANGENT_SPACE
-       vao->attribs[ATTR_INDEX_TANGENT       ].offset = dataSize; dataSize += 
sizeof(uint32_t);
+       vao->attribs[ATTR_INDEX_TANGENT       ].offset = dataSize; dataSize += 
sizeof(verts[0].tangent);
 #endif
        vao->attribs[ATTR_INDEX_TEXCOORD      ].offset = dataSize; dataSize += 
glRefConfig.packedTexcoordDataSize;
        vao->attribs[ATTR_INDEX_LIGHTCOORD    ].offset = dataSize; dataSize += 
glRefConfig.packedTexcoordDataSize;
        vao->attribs[ATTR_INDEX_COLOR         ].offset = dataSize; dataSize += 
glRefConfig.packedColorDataSize;
-       vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += 
sizeof(uint32_t);
+       vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += 
sizeof(verts[0].lightdir);
 
        vao->attribs[ATTR_INDEX_POSITION      ].stride = dataSize;
        vao->attribs[ATTR_INDEX_NORMAL        ].stride = dataSize;
@@ -400,11 +318,13 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, 
srfVert_t *verts, int num
                dataOfs += sizeof(verts[i].xyz);
 
                // normal
-               dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].normal);
+               memcpy(data + dataOfs, &verts[i].normal, 
sizeof(verts[i].normal));
+               dataOfs += sizeof(verts[i].normal);
 
 #ifdef USE_VERT_TANGENT_SPACE
                // tangent
-               dataOfs += R_VaoPackTangent(data + dataOfs, verts[i].tangent);
+               memcpy(data + dataOfs, &verts[i].tangent, 
sizeof(verts[i].tangent));
+               dataOfs += sizeof(verts[i].tangent);
 #endif
 
                // texcoords
@@ -417,7 +337,8 @@ vao_t *R_CreateVao2(const char *name, int numVertexes, 
srfVert_t *verts, int num
                dataOfs += R_VaoPackColors(data + dataOfs, 
verts[i].vertexColors);
 
                // light directions
-               dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].lightdir);
+               memcpy(data + dataOfs, &verts[i].lightdir, 
sizeof(verts[i].lightdir));
+               dataOfs += sizeof(verts[i].lightdir);
        }
 
        vao->vertexesSize = dataSize;
@@ -581,12 +502,12 @@ void R_InitVaos(void)
        tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4;
 
        tess.vao->attribs[ATTR_INDEX_POSITION      ].type = GL_FLOAT;
-       tess.vao->attribs[ATTR_INDEX_NORMAL        ].type = 
glRefConfig.packedNormalDataType;
-       tess.vao->attribs[ATTR_INDEX_TANGENT       ].type = 
glRefConfig.packedNormalDataType;
+       tess.vao->attribs[ATTR_INDEX_NORMAL        ].type = GL_SHORT;
+       tess.vao->attribs[ATTR_INDEX_TANGENT       ].type = GL_SHORT;
        tess.vao->attribs[ATTR_INDEX_TEXCOORD      ].type = GL_FLOAT;
        tess.vao->attribs[ATTR_INDEX_LIGHTCOORD    ].type = GL_FLOAT;
        tess.vao->attribs[ATTR_INDEX_COLOR         ].type = GL_FLOAT;
-       tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = 
glRefConfig.packedNormalDataType;
+       tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = GL_SHORT;
 
        tess.vao->attribs[ATTR_INDEX_POSITION      ].normalized = GL_FALSE;
        tess.vao->attribs[ATTR_INDEX_NORMAL        ].normalized = GL_TRUE;

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-games/ioquake3.git

_______________________________________________
Pkg-games-commits mailing list
Pkg-games-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to