*/
static void Mod_Print(void);
static void Mod_Precache (void);
+static void Mod_BuildVBOs(void);
void Mod_Init (void)
{
Mod_BrushInit();
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);
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;
}
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);
}
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);
+ }
+}