From 4db3b9ef897989f6b1bae8eae1b26f7b22e4adca Mon Sep 17 00:00:00 2001
From: SmileTheory <SmileTheory@gmail.com>
Date: Wed, 15 Oct 2014 03:42:29 -0700
Subject: OpenGL2: Interleave vertex data for static MD3s.

---
 src/renderergl2/tr_glsl.c  |  12 ++--
 src/renderergl2/tr_local.h |   3 +-
 src/renderergl2/tr_model.c | 174 +++++++++++++++++++++++++++++----------------
 3 files changed, 119 insertions(+), 70 deletions(-)

diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c
index fb4a0a2d..fd50734e 100644
--- a/src/renderergl2/tr_glsl.c
+++ b/src/renderergl2/tr_glsl.c
@@ -1512,12 +1512,12 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
 	newFrame = glState.vertexAttribsNewFrame;
 	if (glState.vertexAnimation)
 	{
-		extraOffsets[ATTR_INDEX_POSITION]  = newFrame * vao->size_xyz;
-		extraOffsets[ATTR_INDEX_POSITION2] = oldFrame * vao->size_xyz;
-		extraOffsets[ATTR_INDEX_NORMAL]    = newFrame * vao->size_normal;
-		extraOffsets[ATTR_INDEX_NORMAL2]   = oldFrame * vao->size_normal;
-		extraOffsets[ATTR_INDEX_TANGENT]   = newFrame * vao->size_normal;
-		extraOffsets[ATTR_INDEX_TANGENT2]  = oldFrame * vao->size_normal;
+		extraOffsets[ATTR_INDEX_POSITION]  = newFrame * vao->frameSize;
+		extraOffsets[ATTR_INDEX_POSITION2] = oldFrame * vao->frameSize;
+		extraOffsets[ATTR_INDEX_NORMAL]    = newFrame * vao->frameSize;
+		extraOffsets[ATTR_INDEX_NORMAL2]   = oldFrame * vao->frameSize;
+		extraOffsets[ATTR_INDEX_TANGENT]   = newFrame * vao->frameSize;
+		extraOffsets[ATTR_INDEX_TANGENT2]  = oldFrame * vao->frameSize;
 	}
 
 	// this may not be bound if we're using VAOs
diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h
index 50a7589a..ca8c789f 100644
--- a/src/renderergl2/tr_local.h
+++ b/src/renderergl2/tr_local.h
@@ -126,8 +126,7 @@ typedef struct vao_s
 	int             vertexesSize;	// amount of memory data allocated for all vertices in bytes
 	vaoAttrib_t     attribs[VAO_MAX_ATTRIBS];
 
-	uint32_t        size_xyz;
-	uint32_t        size_normal;
+	uint32_t        frameSize;      // bytes to skip per frame when doing vertex animation
 
 	uint32_t        indexesIBO;
 	int             indexesSize;	// amount of memory data allocated for all triangles in bytes
diff --git a/src/renderergl2/tr_model.c b/src/renderergl2/tr_model.c
index c8c74e20..05e859da 100644
--- a/src/renderergl2/tr_model.c
+++ b/src/renderergl2/tr_model.c
@@ -666,68 +666,122 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
 		surf = mdvModel->surfaces;
 		for (i = 0; i < mdvModel->numSurfaces; i++, vaoSurf++, surf++)
 		{
-			vec3_t *verts;
-			vec2_t *texcoords;
-			uint32_t *normals;
+			uint32_t offset_xyz, offset_st, offset_normal, offset_tangent;
+			uint32_t stride_xyz, stride_st, stride_normal, stride_tangent;
+			uint32_t dataSize, dataOfs;
+			uint8_t *data;
+
+			if (mdvModel->numFrames > 1)
+			{
+				// vertex animation, store texcoords first, then position/normal/tangents
+				offset_st      = 0;
+				offset_xyz     = surf->numVerts * sizeof(vec2_t);
+				offset_normal  = offset_xyz + sizeof(vec3_t);
+				offset_tangent = offset_normal + sizeof(uint32_t);
+				stride_st  = sizeof(vec2_t);
+				stride_xyz = sizeof(vec3_t) + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
-			uint32_t *tangents;
+				stride_xyz += sizeof(uint32_t);
 #endif
+				stride_normal = stride_tangent = stride_xyz;
 
-			byte *data;
-			int dataSize;
-
-			int ofs_xyz, ofs_normal, ofs_st;
+				dataSize = offset_xyz + surf->numVerts * mdvModel->numFrames * stride_xyz;
+			}
+			else
+			{
+				// no animation, interleave everything
+				offset_xyz     = 0;
+				offset_st      = offset_xyz + sizeof(vec3_t);
+				offset_normal  = offset_st + sizeof(vec2_t);
+				offset_tangent = offset_normal + sizeof(uint32_t);
 #ifdef USE_VERT_TANGENT_SPACE
-			int ofs_tangent;
+				stride_xyz = offset_tangent + sizeof(uint32_t);
+#else
+				stride_xyz = offset_normal + sizeof(uint32_t);
 #endif
+				stride_st = stride_normal = stride_tangent = stride_xyz;
+
+				dataSize = surf->numVerts * stride_xyz;
+			}
 
-			dataSize = 0;
 
-			ofs_xyz = dataSize;
-			dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*verts);
+			data = ri.Malloc(dataSize);
+			dataOfs = 0;
 
-			ofs_normal = dataSize;
-			dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*normals);
+			if (mdvModel->numFrames > 1)
+			{
+				st = surf->st;
+				for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
+					memcpy(data + dataOfs, &st->st, sizeof(st->st));
+					dataOfs += sizeof(st->st);
+				}
 
+				v = surf->verts;
+				for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ )
+				{
 #ifdef USE_VERT_TANGENT_SPACE
-			ofs_tangent = dataSize;
-			dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*tangents);
+					vec3_t nxt;
+					vec4_t tangent;
 #endif
+					uint32_t *p;
 
-			ofs_st = dataSize;
-			dataSize += surf->numVerts * sizeof(*texcoords);
+					// xyz
+					memcpy(data + dataOfs, &v->xyz, sizeof(v->xyz));
+					dataOfs += sizeof(v->xyz);
 
-			data = ri.Malloc(dataSize);
+					// normal
+					p = (uint32_t *)(data + dataOfs);
+					*p = R_VaoPackNormal(v->normal);
+					dataOfs += sizeof(uint32_t);
 
-			verts =      (void *)(data + ofs_xyz);
-			normals =    (void *)(data + ofs_normal);
 #ifdef USE_VERT_TANGENT_SPACE
-			tangents =   (void *)(data + ofs_tangent);
+					CrossProduct(v->normal, v->tangent, nxt);
+					VectorCopy(v->tangent, tangent);
+					tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
+
+					// tangent
+					p = (uint32_t *)(data + dataOfs);
+					*p = R_VaoPackTangent(tangent);
+					dataOfs += sizeof(uint32_t);
 #endif
-			texcoords =  (void *)(data + ofs_st);
-		
-			v = surf->verts;
-			for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ )
+				}
+			}
+			else
 			{
-				vec3_t nxt;
-				vec4_t tangent;
+				v = surf->verts;
+				st = surf->st;
+				for ( j = 0; j < surf->numVerts; j++, v++, st++ )
+				{
+#ifdef USE_VERT_TANGENT_SPACE
+					vec3_t nxt;
+					vec4_t tangent;
+#endif
+					uint32_t *p;
 
-				VectorCopy(v->xyz,       verts[j]);
+					// xyz
+					memcpy(data + dataOfs, &v->xyz, sizeof(v->xyz));
+					dataOfs += sizeof(v->xyz);
 
-				normals[j] = R_VaoPackNormal(v->normal);
-#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;
+					// st
+					memcpy(data + dataOfs, &st->st, sizeof(st->st));
+					dataOfs += sizeof(st->st);
 
-				tangents[j] = R_VaoPackTangent(tangent);
-#endif
-			}
+					// normal
+					p = (uint32_t *)(data + dataOfs);
+					*p = R_VaoPackNormal(v->normal);
+					dataOfs += sizeof(uint32_t);
 
-			st = surf->st;
-			for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
-				texcoords[j][0] = st->st[0];
-				texcoords[j][1] = st->st[1];
+#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
+					p = (uint32_t *)(data + dataOfs);
+					*p = R_VaoPackTangent(tangent);
+					dataOfs += sizeof(uint32_t);
+#endif
+				}
 			}
 
 			vaoSurf->surfaceType = SF_VAO_MDVMESH;
@@ -775,27 +829,23 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
 			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2  ].normalized = GL_TRUE;
 			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD  ].normalized = GL_FALSE;
 
-			vaoSurf->vao->attribs[ATTR_INDEX_POSITION  ].offset = ofs_xyz;
-			vaoSurf->vao->attribs[ATTR_INDEX_POSITION  ].stride = sizeof(*verts);
-			vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].offset = ofs_xyz;
-			vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].stride = sizeof(*verts);
-
-			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL    ].offset = ofs_normal;
-			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL    ].stride = sizeof(*normals);
-			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2   ].offset = ofs_normal;
-			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2   ].stride = sizeof(*normals);
-
-#ifdef USE_VERT_TANGENT_SPACE
-			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT   ].offset = ofs_tangent;
-			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT   ].stride = sizeof(*tangents);
-			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2  ].offset = ofs_tangent;
-			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2  ].stride = sizeof(*tangents);
-#endif
-			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD  ].offset = ofs_st;
-			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD  ].stride = sizeof(*st);
-
-			vaoSurf->vao->size_xyz    = sizeof(*verts)   * surf->numVerts;
-			vaoSurf->vao->size_normal = sizeof(*normals) * surf->numVerts;
+			vaoSurf->vao->attribs[ATTR_INDEX_POSITION  ].offset = offset_xyz;
+			vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].offset = offset_xyz;
+			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD  ].offset = offset_st;
+			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL    ].offset = offset_normal;
+			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2   ].offset = offset_normal;
+			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT   ].offset = offset_tangent;
+			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2  ].offset = offset_tangent;
+
+			vaoSurf->vao->attribs[ATTR_INDEX_POSITION  ].stride = stride_xyz;
+			vaoSurf->vao->attribs[ATTR_INDEX_POSITION2 ].stride = stride_xyz;
+			vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD  ].stride = stride_st;
+			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL    ].stride = stride_normal;
+			vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2   ].stride = stride_normal;
+			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT   ].stride = stride_tangent;
+			vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2  ].stride = stride_tangent;
+
+			vaoSurf->vao->frameSize = stride_xyz    * surf->numVerts;
 
 			Vao_SetVertexPointers(vaoSurf->vao);
 
-- 
cgit