model_t *mod;
for (i = 0, mod = mod_known;i < mod_numknown;i++, mod++)
- if (mod->name[0])
+ if (mod->name[0] && mod->name[0] != '*')
if (mod->used)
Mod_LoadModel(mod, true, false, mod->isworldmodel);
}
model_t *mod;
for (i = 0, mod = mod_known;i < mod_numknown;i++, mod++)
- if (mod->loaded)
+ if (mod->loaded || mod->mempool)
Mod_UnloadModel(mod);
}
*/
static void Mod_Print(void);
static void Mod_Precache (void);
+static void Mod_BuildVBOs(void);
void Mod_Init (void)
{
Mod_BrushInit();
char name[MAX_QPATH];
qboolean isworldmodel;
qboolean used;
- strcpy(name, mod->name);
+ strlcpy(name, mod->name, sizeof(name));
isworldmodel = mod->isworldmodel;
used = mod->used;
+ if (mod->surfmesh.ebo)
+ R_Mesh_DestroyEBO(mod->surfmesh.ebo);
+ if (mod->surfmesh.vbo)
+ R_Mesh_DestroyVBO(mod->surfmesh.vbo);
// free textures/memory attached to the model
R_FreeTexturePool(&mod->texturepool);
Mem_FreePool(&mod->mempool);
// clear the struct to make it available
memset(mod, 0, sizeof(model_t));
// restore the fields we want to preserve
- strcpy(mod->name, name);
+ strlcpy(mod->name, name, sizeof(mod->name));
mod->isworldmodel = isworldmodel;
mod->used = used;
mod->loaded = false;
crc = 0;
buf = NULL;
+
+ // even if the model is loaded it still may need reloading...
+
+ // if the model is a worldmodel and is being referred to as a
+ // non-worldmodel here, then it needs reloading to get rid of the
+ // submodels
if (mod->isworldmodel != isworldmodel)
mod->loaded = false;
+
+ // if it is not loaded or checkdisk is true we need to calculate the crc
if (!mod->loaded || checkdisk)
{
if (checkdisk && mod->loaded)
if (buf)
{
crc = CRC_Block((unsigned char *)buf, filesize);
+ // we need to reload the model if the crc does not match
if (mod->crc != crc)
mod->loaded = false;
}
}
+
+ // if the model is already loaded and checks passed, just return
if (mod->loaded)
{
- // already loaded
if (buf)
Mem_Free(buf);
return mod;
Con_DPrintf("loading model %s\n", mod->name);
// LordHavoc: unload the existing model in this slot (if there is one)
- if (mod->loaded)
+ if (mod->loaded || mod->mempool)
Mod_UnloadModel(mod);
// load the model
VectorSet(mod->rotatedmins, -mod->radius, -mod->radius, -mod->radius);
VectorSet(mod->rotatedmaxs, mod->radius, mod->radius, mod->radius);
- // all models use memory, so allocate a memory pool
- mod->mempool = Mem_AllocPool(mod->name, 0, NULL);
- // all models load textures, so allocate a texture pool
- if (cls.state != ca_dedicated)
- mod->texturepool = R_AllocTexturePool();
-
if (buf)
{
char *bufend = (char *)buf + filesize;
+
+ // all models use memory, so allocate a memory pool
+ mod->mempool = Mem_AllocPool(mod->name, 0, NULL);
+ // all models load textures, so allocate a texture pool
+ if (cls.state != ca_dedicated)
+ mod->texturepool = R_AllocTexturePool();
+
num = LittleLong(*((int *)buf));
// call the apropriate loader
loadmodel = mod;
else if (num == BSPVERSION || num == 30) Mod_Q1BSP_Load(mod, buf, bufend);
else Con_Printf("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
Mem_Free(buf);
+
+ Mod_BuildVBOs();
+
+ // no fatal errors occurred, so this model is ready to use.
+ mod->loaded = true;
}
else if (crash)
{
// LordHavoc: Sys_Error was *ANNOYING*
Con_Printf ("Mod_LoadModel: %s not found\n", mod->name);
}
-
- // no errors occurred
- mod->loaded = true;
return mod;
}
if (mod_numknown == i)
mod_numknown++;
mod = mod_known + i;
- strcpy (mod->name, name);
+ strlcpy (mod->name, name, sizeof(mod->name));
mod->loaded = false;
mod->used = true;
return mod;
return model;
}
+/*
+==================
+Mod_Reload
+
+Reloads all models if they have changed
+==================
+*/
+void Mod_Reload()
+{
+ int i;
+ model_t *mod;
+
+ for (i = 0, mod = mod_known;i < mod_numknown;i++, mod++)
+ if (mod->name[0] && mod->name[0] != '*')
+ if (mod->used)
+ Mod_LoadModel(mod, true, true, mod->isworldmodel);
+}
+
unsigned char *mod_base;
Con_Print("Loaded models:\n");
for (i = 0, mod = mod_known;i < mod_numknown;i++, mod++)
if (mod->name[0])
- Con_Printf("%4iK %s\n", mod->mempool ? (mod->mempool->totalsize + 1023) / 1024 : 0, mod->name);
+ Con_Printf("%4iK %s\n", mod->mempool ? (int)((mod->mempool->totalsize + 1023) / 1024) : 0, mod->name);
}
/*
}
#endif
-void Mod_ValidateElements(int *elements, int numtriangles, int numverts, const char *filename, int fileline)
+void Mod_ValidateElements(int *elements, int numtriangles, int firstvertex, int numverts, const char *filename, int fileline)
{
- int i, warned = false;
+ int i, warned = false, endvertex = firstvertex + numverts;
for (i = 0;i < numtriangles * 3;i++)
{
- if ((unsigned int)elements[i] >= (unsigned int)numverts)
+ if (elements[i] < firstvertex || elements[i] >= endvertex)
{
if (!warned)
{
warned = true;
Con_Printf("Mod_ValidateElements: out of bounds elements detected at %s:%d\n", filename, fileline);
}
- elements[i] = 0;
+ elements[i] = firstvertex;
}
}
}
}
// warning: this is a very expensive function!
-void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const int *elements, float *svector3f, float *tvector3f, float *normal3f, qboolean areaweighting)
+void Mod_BuildTextureVectorsFromNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const float *normal3f, const int *elements, float *svector3f, float *tvector3f, qboolean areaweighting)
{
int i, tnum;
- float sdir[3], tdir[3], normal[3], *v;
- const float *v0, *v1, *v2, *tc0, *tc1, *tc2;
+ float sdir[3], tdir[3], normal[3], *sv, *tv;
+ const float *v0, *v1, *v2, *tc0, *tc1, *tc2, *n;
float f, tangentcross[3], v10[3], v20[3], tc10[2], tc20[2];
const int *e;
// clear the vectors
- if (svector3f)
- memset(svector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
- if (tvector3f)
- memset(tvector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
- if (normal3f)
- memset(normal3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
+ memset(svector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
+ memset(tvector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
// process each vertex of each triangle and accumulate the results
for (tnum = 0, e = elements;tnum < numtriangles;tnum++, e += 3)
{
tdir[1] = tc10[0] * v20[1] - tc20[0] * v10[1];
tdir[2] = tc10[0] * v20[2] - tc20[0] * v10[2];
- // make the tangents completely perpendicular to the surface normal
- // 12 multiply, 4 add, 6 subtract
- f = DotProduct(sdir, normal);
- sdir[0] -= f * normal[0];
- sdir[1] -= f * normal[1];
- sdir[2] -= f * normal[2];
- f = DotProduct(tdir, normal);
- tdir[0] -= f * normal[0];
- tdir[1] -= f * normal[1];
- tdir[2] -= f * normal[2];
-
// if texture is mapped the wrong way (counterclockwise), the tangents
// have to be flipped, this is detected by calculating a normal from the
// two tangents, and seeing if it is opposite the surface normal
{
VectorNormalize(sdir);
VectorNormalize(tdir);
- VectorNormalize(normal);
}
- if (svector3f)
- for (i = 0;i < 3;i++)
- VectorAdd(svector3f + e[i]*3, sdir, svector3f + e[i]*3);
- if (tvector3f)
- for (i = 0;i < 3;i++)
- VectorAdd(tvector3f + e[i]*3, tdir, tvector3f + e[i]*3);
- if (normal3f)
- for (i = 0;i < 3;i++)
- VectorAdd(normal3f + e[i]*3, normal, normal3f + e[i]*3);
+ for (i = 0;i < 3;i++)
+ {
+ VectorAdd(svector3f + e[i]*3, sdir, svector3f + e[i]*3);
+ VectorAdd(tvector3f + e[i]*3, tdir, tvector3f + e[i]*3);
+ }
+ }
+ // make the tangents completely perpendicular to the surface normal, and
+ // then normalize them
+ // 16 assignments, 2 divide, 2 sqrt, 2 negates, 14 adds, 24 multiplies
+ for (i = 0, sv = svector3f + 3 * firstvertex, tv = tvector3f + 3 * firstvertex, n = normal3f + 3 * firstvertex;i < numvertices;i++, sv += 3, tv += 3, n += 3)
+ {
+ f = -DotProduct(sv, n);
+ VectorMA(sv, f, n, sv);
+ VectorNormalize(sv);
+ f = -DotProduct(tv, n);
+ VectorMA(tv, f, n, tv);
+ VectorNormalize(tv);
}
- // now we could divide the vectors by the number of averaged values on
- // each vertex... but instead normalize them
- // 4 assignments, 1 divide, 1 sqrt, 2 adds, 6 multiplies
- if (svector3f)
- for (i = 0, v = svector3f + 3 * firstvertex;i < numvertices;i++, v += 3)
- VectorNormalize(v);
- // 4 assignments, 1 divide, 1 sqrt, 2 adds, 6 multiplies
- if (tvector3f)
- for (i = 0, v = tvector3f + 3 * firstvertex;i < numvertices;i++, v += 3)
- VectorNormalize(v);
- // 4 assignments, 1 divide, 1 sqrt, 2 adds, 6 multiplies
- if (normal3f)
- for (i = 0, v = normal3f + 3 * firstvertex;i < numvertices;i++, v += 3)
- VectorNormalize(v);
}
-surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors)
+void Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors)
{
- surfmesh_t *mesh;
unsigned char *data;
- mesh = (surfmesh_t *)Mem_Alloc(mempool, sizeof(surfmesh_t) + numvertices * (3 + 3 + 3 + 3 + 2 + 2 + (vertexcolors ? 4 : 0)) * sizeof(float) + numvertices * (lightmapoffsets ? 1 : 0) * sizeof(int) + numtriangles * (3 + (neighbors ? 3 : 0)) * sizeof(int));
- mesh->num_vertices = numvertices;
- mesh->num_triangles = numtriangles;
- data = (unsigned char *)(mesh + 1);
- if (mesh->num_vertices)
+ data = (unsigned char *)Mem_Alloc(mempool, numvertices * (3 + 3 + 3 + 3 + 2 + 2 + (vertexcolors ? 4 : 0)) * sizeof(float) + numvertices * (lightmapoffsets ? 1 : 0) * sizeof(int) + numtriangles * (3 + (neighbors ? 3 : 0)) * sizeof(int));
+ loadmodel->surfmesh.num_vertices = numvertices;
+ loadmodel->surfmesh.num_triangles = numtriangles;
+ if (loadmodel->surfmesh.num_vertices)
{
- mesh->data_vertex3f = (float *)data, data += sizeof(float[3]) * mesh->num_vertices;
- mesh->data_svector3f = (float *)data, data += sizeof(float[3]) * mesh->num_vertices;
- mesh->data_tvector3f = (float *)data, data += sizeof(float[3]) * mesh->num_vertices;
- mesh->data_normal3f = (float *)data, data += sizeof(float[3]) * mesh->num_vertices;
- mesh->data_texcoordtexture2f = (float *)data, data += sizeof(float[2]) * mesh->num_vertices;
- mesh->data_texcoordlightmap2f = (float *)data, data += sizeof(float[2]) * mesh->num_vertices;
+ loadmodel->surfmesh.data_vertex3f = (float *)data, data += sizeof(float[3]) * loadmodel->surfmesh.num_vertices;
+ loadmodel->surfmesh.data_svector3f = (float *)data, data += sizeof(float[3]) * loadmodel->surfmesh.num_vertices;
+ loadmodel->surfmesh.data_tvector3f = (float *)data, data += sizeof(float[3]) * loadmodel->surfmesh.num_vertices;
+ loadmodel->surfmesh.data_normal3f = (float *)data, data += sizeof(float[3]) * loadmodel->surfmesh.num_vertices;
+ loadmodel->surfmesh.data_texcoordtexture2f = (float *)data, data += sizeof(float[2]) * loadmodel->surfmesh.num_vertices;
+ loadmodel->surfmesh.data_texcoordlightmap2f = (float *)data, data += sizeof(float[2]) * loadmodel->surfmesh.num_vertices;
if (vertexcolors)
- mesh->data_lightmapcolor4f = (float *)data, data += sizeof(float[4]) * mesh->num_vertices;
+ loadmodel->surfmesh.data_lightmapcolor4f = (float *)data, data += sizeof(float[4]) * loadmodel->surfmesh.num_vertices;
if (lightmapoffsets)
- mesh->data_lightmapoffsets = (int *)data, data += sizeof(int) * mesh->num_vertices;
+ loadmodel->surfmesh.data_lightmapoffsets = (int *)data, data += sizeof(int) * loadmodel->surfmesh.num_vertices;
}
- if (mesh->num_triangles)
+ if (loadmodel->surfmesh.num_triangles)
{
- mesh->data_element3i = (int *)data, data += sizeof(int[3]) * mesh->num_triangles;
+ loadmodel->surfmesh.data_element3i = (int *)data, data += sizeof(int[3]) * loadmodel->surfmesh.num_triangles;
if (neighbors)
- mesh->data_neighbor3i = (int *)data, data += sizeof(int[3]) * mesh->num_triangles;
+ loadmodel->surfmesh.data_neighbor3i = (int *)data, data += sizeof(int[3]) * loadmodel->surfmesh.num_triangles;
}
- return mesh;
}
shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int neighbors, int expandable)
return Mod_ShadowMesh_Alloc(mempool, maxverts, maxtriangles, map_diffuse, map_specular, map_normal, light, neighbors, expandable);
}
-shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh, int light, int neighbors)
+static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh)
+{
+ if (!gl_support_arb_vertex_buffer_object)
+ return;
+
+ // element buffer is easy because it's just one array
+ if (mesh->numtriangles)
+ mesh->ebo = R_Mesh_CreateStaticEBO(mesh->element3i, mesh->numtriangles * sizeof(int[3]));
+
+ // vertex buffer is several arrays and we put them in the same buffer
+ //
+ // is this wise? the texcoordtexture2f array is used with dynamic
+ // vertex/svector/tvector/normal when rendering animated models, on the
+ // other hand animated models don't use a lot of vertices anyway...
+ if (mesh->numverts)
+ {
+ size_t size;
+ unsigned char *mem;
+ size = 0;
+ mesh->vbooffset_vertex3f = size;if (mesh->vertex3f ) size += mesh->numverts * sizeof(float[3]);
+ mesh->vbooffset_svector3f = size;if (mesh->svector3f ) size += mesh->numverts * sizeof(float[3]);
+ mesh->vbooffset_tvector3f = size;if (mesh->tvector3f ) size += mesh->numverts * sizeof(float[3]);
+ mesh->vbooffset_normal3f = size;if (mesh->normal3f ) size += mesh->numverts * sizeof(float[3]);
+ mesh->vbooffset_texcoord2f = size;if (mesh->texcoord2f ) size += mesh->numverts * sizeof(float[2]);
+ mem = (unsigned char *)Mem_Alloc(tempmempool, size);
+ if (mesh->vertex3f ) memcpy(mem + mesh->vbooffset_vertex3f , mesh->vertex3f , mesh->numverts * sizeof(float[3]));
+ if (mesh->svector3f ) memcpy(mem + mesh->vbooffset_svector3f , mesh->svector3f , mesh->numverts * sizeof(float[3]));
+ if (mesh->tvector3f ) memcpy(mem + mesh->vbooffset_tvector3f , mesh->tvector3f , mesh->numverts * sizeof(float[3]));
+ if (mesh->normal3f ) memcpy(mem + mesh->vbooffset_normal3f , mesh->normal3f , mesh->numverts * sizeof(float[3]));
+ if (mesh->texcoord2f ) memcpy(mem + mesh->vbooffset_texcoord2f , mesh->texcoord2f , mesh->numverts * sizeof(float[2]));
+ mesh->vbo = R_Mesh_CreateStaticVBO(mem, size);
+ Mem_Free(mem);
+ }
+}
+
+shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh, qboolean light, qboolean neighbors, qboolean createvbo)
{
shadowmesh_t *mesh, *newmesh, *nextmesh;
// reallocate meshs to conserve space
newmesh = Mod_ShadowMesh_ReAlloc(mempool, mesh, light, neighbors);
newmesh->next = firstmesh;
firstmesh = newmesh;
+ if (createvbo)
+ Mod_ShadowMesh_CreateVBOs(newmesh);
}
Mem_Free(mesh);
}
shadowmesh_t *nextmesh;
for (;mesh;mesh = nextmesh)
{
+ if (mesh->ebo)
+ R_Mesh_DestroyEBO(mesh->ebo);
+ if (mesh->vbo)
+ R_Mesh_DestroyVBO(mesh->vbo);
nextmesh = mesh->next;
Mem_Free(mesh);
}
}
-static rtexture_t *GL_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags)
+static rtexture_t *GL_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
{
int i;
- for (i = 0;i < width*height;i++)
- if (((unsigned char *)&palette[in[i]])[3] > 0)
- return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
- return NULL;
+ if (!force)
+ {
+ for (i = 0;i < width*height;i++)
+ if (((unsigned char *)&palette[in[i]])[3] > 0)
+ break;
+ if (i == width*height)
+ return NULL;
+ }
+ return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
}
int Mod_LoadSkinFrame(skinframe_t *skinframe, const char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture)
{
imageskin_t s;
memset(skinframe, 0, sizeof(*skinframe));
+ skinframe->base = r_texture_notexture;
if (cls.state == ca_dedicated)
return false;
if (!image_loadskin(&s, basename))
break;
if (i < width * height * 4)
{
- unsigned char *fogpixels = Mem_Alloc(loadmodel->mempool, width * height * 4);
+ unsigned char *fogpixels = (unsigned char *)Mem_Alloc(loadmodel->mempool, width * height * 4);
memcpy(fogpixels, skindata, width * height * 4);
for (i = 0;i < width * height * 4;i += 4)
fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
Mem_Free(temp1);
}
// use either a custom palette, or the quake palette
- skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags); // all
+ skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags, true); // all
if (!palette && loadglowtexture)
- skinframe->glow = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, textureflags); // glow
+ skinframe->glow = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, textureflags, false); // glow
if (!palette && loadpantsandshirt)
{
- skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, textureflags); // pants
- skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, textureflags); // shirt
+ skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, textureflags, false); // pants
+ skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, textureflags, false); // shirt
}
if (skinframe->pants || skinframe->shirt)
- skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags); // no special colors
+ skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
if (textureflags & TEXF_ALPHA)
{
// if not using a custom alphapalette, use the quake one
if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
break;
if (i < width * height)
- skinframe->fog = GL_TextureForSkinLayer(skindata, width, height, va("%s_fog", basename), alphapalette, textureflags); // fog mask
+ skinframe->fog = GL_TextureForSkinLayer(skindata, width, height, va("%s_fog", basename), alphapalette, textureflags, true); // fog mask
}
}
else
return outtriangles;
}
+void Mod_VertexRangeFromElements(int numelements, const int *elements, int *firstvertexpointer, int *lastvertexpointer)
+{
+ int i, e;
+ int firstvertex, lastvertex;
+ if (numelements > 0 && elements)
+ {
+ firstvertex = lastvertex = elements[0];
+ for (i = 1;i < numelements;i++)
+ {
+ e = elements[i];
+ firstvertex = min(firstvertex, e);
+ lastvertex = max(lastvertex, e);
+ }
+ }
+ else
+ firstvertex = lastvertex = 0;
+ if (firstvertexpointer)
+ *firstvertexpointer = firstvertex;
+ if (lastvertexpointer)
+ *lastvertexpointer = lastvertex;
+}
+
+static void Mod_BuildVBOs(void)
+{
+ if (!gl_support_arb_vertex_buffer_object)
+ return;
+
+ // element buffer is easy because it's just one array
+ if (loadmodel->surfmesh.num_triangles)
+ loadmodel->surfmesh.ebo = R_Mesh_CreateStaticEBO(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
+
+ // vertex buffer is several arrays and we put them in the same buffer
+ //
+ // is this wise? the texcoordtexture2f array is used with dynamic
+ // vertex/svector/tvector/normal when rendering animated models, on the
+ // other hand animated models don't use a lot of vertices anyway...
+ if (loadmodel->surfmesh.num_vertices)
+ {
+ size_t size;
+ unsigned char *mem;
+ size = 0;
+ loadmodel->surfmesh.vbooffset_vertex3f = size;if (loadmodel->surfmesh.data_vertex3f ) size += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.vbooffset_svector3f = size;if (loadmodel->surfmesh.data_svector3f ) size += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.vbooffset_tvector3f = size;if (loadmodel->surfmesh.data_tvector3f ) size += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.vbooffset_normal3f = size;if (loadmodel->surfmesh.data_normal3f ) size += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.vbooffset_texcoordtexture2f = size;if (loadmodel->surfmesh.data_texcoordtexture2f ) size += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
+ loadmodel->surfmesh.vbooffset_texcoordlightmap2f = size;if (loadmodel->surfmesh.data_texcoordlightmap2f) size += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
+ loadmodel->surfmesh.vbooffset_lightmapcolor4f = size;if (loadmodel->surfmesh.data_lightmapcolor4f ) size += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
+ mem = (unsigned char *)Mem_Alloc(tempmempool, size);
+ if (loadmodel->surfmesh.data_vertex3f ) memcpy(mem + loadmodel->surfmesh.vbooffset_vertex3f , loadmodel->surfmesh.data_vertex3f , loadmodel->surfmesh.num_vertices * sizeof(float[3]));
+ if (loadmodel->surfmesh.data_svector3f ) memcpy(mem + loadmodel->surfmesh.vbooffset_svector3f , loadmodel->surfmesh.data_svector3f , loadmodel->surfmesh.num_vertices * sizeof(float[3]));
+ if (loadmodel->surfmesh.data_tvector3f ) memcpy(mem + loadmodel->surfmesh.vbooffset_tvector3f , loadmodel->surfmesh.data_tvector3f , loadmodel->surfmesh.num_vertices * sizeof(float[3]));
+ if (loadmodel->surfmesh.data_normal3f ) memcpy(mem + loadmodel->surfmesh.vbooffset_normal3f , loadmodel->surfmesh.data_normal3f , loadmodel->surfmesh.num_vertices * sizeof(float[3]));
+ if (loadmodel->surfmesh.data_texcoordtexture2f ) memcpy(mem + loadmodel->surfmesh.vbooffset_texcoordtexture2f , loadmodel->surfmesh.data_texcoordtexture2f , loadmodel->surfmesh.num_vertices * sizeof(float[2]));
+ if (loadmodel->surfmesh.data_texcoordlightmap2f) memcpy(mem + loadmodel->surfmesh.vbooffset_texcoordlightmap2f, loadmodel->surfmesh.data_texcoordlightmap2f, loadmodel->surfmesh.num_vertices * sizeof(float[2]));
+ if (loadmodel->surfmesh.data_lightmapcolor4f ) memcpy(mem + loadmodel->surfmesh.vbooffset_lightmapcolor4f , loadmodel->surfmesh.data_lightmapcolor4f , loadmodel->surfmesh.num_vertices * sizeof(float[4]));
+ loadmodel->surfmesh.vbo = R_Mesh_CreateStaticVBO(mem, size);
+ Mem_Free(mem);
+ }
+}