Mod_UnloadModel(mod);
Mod_FreeQ3Shaders();
+ Mod_Skeletal_FreeBuffers();
}
static void mod_newmap(void)
strlcpy(name, mod->name, sizeof(name));
parentmodel = mod->brush.parentmodel;
used = mod->used;
- if (mod->surfmesh.ebo3i)
- R_Mesh_DestroyBufferObject(mod->surfmesh.ebo3i);
- if (mod->surfmesh.ebo3s)
- R_Mesh_DestroyBufferObject(mod->surfmesh.ebo3s);
- if (mod->surfmesh.vbo)
- R_Mesh_DestroyBufferObject(mod->surfmesh.vbo);
+ if (mod->mempool)
+ {
+ if (mod->surfmesh.vertexpositionbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertexpositionbuffer);
+ mod->surfmesh.vertexpositionbuffer = NULL;
+ if (mod->surfmesh.vertexmeshbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertexmeshbuffer);
+ mod->surfmesh.vertexmeshbuffer = NULL;
+ if (mod->surfmesh.data_element3i_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_element3i_indexbuffer);
+ mod->surfmesh.data_element3i_indexbuffer = NULL;
+ if (mod->surfmesh.data_element3s_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_element3s_indexbuffer);
+ mod->surfmesh.data_element3s_indexbuffer = NULL;
+ if (mod->surfmesh.vbo_vertexbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.vbo_vertexbuffer);
+ mod->surfmesh.vbo_vertexbuffer = NULL;
+ }
// free textures/memory attached to the model
R_FreeTexturePool(&mod->texturepool);
Mem_FreePool(&mod->mempool);
{
dp_model_t *mod = (dp_model_t *) pass;
animscene_t *anim = &mod->animscenes[i];
- dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d", i);
+ dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d_anim", i);
anim->firstframe = bound(0, start, mod->num_poses - 1);
anim->framecount = bound(1, len, mod->num_poses - anim->firstframe);
anim->framerate = max(1, fps);
num = LittleLong(*((int *)buf));
// call the apropriate loader
loadmodel = mod;
- if (!strcasecmp(FS_FileExtension(mod->name), "obj")) Mod_OBJ_Load(mod, buf, bufend);
+ if (!strcasecmp(FS_FileExtension(mod->name), "obj")) Mod_OBJ_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf, bufend);
else if (!memcmp(buf, "ZYMOTICMODEL", 12)) Mod_ZYMOTICMODEL_Load(mod, buf, bufend);
else if (!memcmp(buf, "DARKPLACESMODEL", 16)) Mod_DARKPLACESMODEL_Load(mod, buf, bufend);
else if (!memcmp(buf, "ACTRHEAD", 8)) Mod_PSKMODEL_Load(mod, buf, bufend);
+ else if (!memcmp(buf, "INTERQUAKEMODEL", 16)) Mod_INTERQUAKEMODEL_Load(mod, buf, bufend);
else if (strlen(mod->name) >= 4 && !strcmp(mod->name + strlen(mod->name) - 4, ".map")) Mod_MAP_Load(mod, buf, bufend);
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);
static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh)
{
- if (!vid.support.arb_vertex_buffer_object)
- return;
- if (mesh->vbo)
+ if (!mesh->numverts)
return;
- // element buffer is easy because it's just one array
- if (mesh->numtriangles)
+ // build r_vertexmesh_t array
+ // (compressed interleaved array for faster rendering)
+ if (!mesh->vertexmesh && mesh->texcoord2f)
{
- if (mesh->element3s)
- mesh->ebo3s = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->element3s, mesh->numtriangles * sizeof(unsigned short[3]), "shadowmesh");
- else
- mesh->ebo3i = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->element3i, mesh->numtriangles * sizeof(unsigned int[3]), "shadowmesh");
+ int vertexindex;
+ int numvertices = mesh->numverts;
+ r_vertexmesh_t *vertexmesh;
+ mesh->vertexmesh = vertexmesh = (r_vertexmesh_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*mesh->vertexmesh));
+ for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexmesh++)
+ {
+ VectorCopy(mesh->vertex3f + 3*vertexindex, vertexmesh->vertex3f);
+ VectorScale(mesh->svector3f + 3*vertexindex, 1.0f, vertexmesh->svector3f);
+ VectorScale(mesh->tvector3f + 3*vertexindex, 1.0f, vertexmesh->tvector3f);
+ VectorScale(mesh->normal3f + 3*vertexindex, 1.0f, vertexmesh->normal3f);
+ Vector2Copy(mesh->texcoord2f + 2*vertexindex, vertexmesh->texcoordtexture2f);
+ }
}
+ // build r_vertexposition_t array
+ if (!mesh->vertexposition)
+ {
+ int vertexindex;
+ int numvertices = mesh->numverts;
+ r_vertexposition_t *vertexposition;
+ mesh->vertexposition = vertexposition = (r_vertexposition_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*mesh->vertexposition));
+ for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexposition++)
+ VectorCopy(mesh->vertex3f + 3*vertexindex, vertexposition->vertex3f);
+ }
+
+ // upload r_vertexmesh_t array as a buffer
+ if (mesh->vertexmesh && !mesh->vertexmeshbuffer)
+ mesh->vertexmeshbuffer = R_Mesh_CreateMeshBuffer(mesh->vertexmesh, mesh->numverts * sizeof(*mesh->vertexmesh), loadmodel->name, false, false);
+
+ // upload r_vertexposition_t array as a buffer
+ if (mesh->vertexposition && !mesh->vertexpositionbuffer)
+ mesh->vertexpositionbuffer = R_Mesh_CreateMeshBuffer(mesh->vertexposition, mesh->numverts * sizeof(*mesh->vertexposition), loadmodel->name, false, false);
+
+ // upload short indices as a buffer
+ if (mesh->element3s && !mesh->element3s_indexbuffer)
+ mesh->element3s_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3s, mesh->numtriangles * sizeof(short[3]), loadmodel->name, true, false);
+
+ // upload int indices as a buffer
+ if (mesh->element3i && !mesh->element3i_indexbuffer && !mesh->element3s)
+ mesh->element3i_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3i, mesh->numtriangles * sizeof(int[3]), loadmodel->name, true, false);
+
// 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)
+ if (!mesh->vbo_vertexbuffer)
{
size_t size;
unsigned char *mem;
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_CreateStaticBufferObject(GL_ARRAY_BUFFER_ARB, mem, size, "shadowmesh");
+ mesh->vbo_vertexbuffer = R_Mesh_CreateMeshBuffer(mem, size, "shadowmesh", false, false);
Mem_Free(mem);
}
}
shadowmesh_t *nextmesh;
for (;mesh;mesh = nextmesh)
{
- if (mesh->ebo3i)
- R_Mesh_DestroyBufferObject(mesh->ebo3i);
- if (mesh->ebo3s)
- R_Mesh_DestroyBufferObject(mesh->ebo3s);
- if (mesh->vbo)
- R_Mesh_DestroyBufferObject(mesh->vbo);
+ if (mesh->vertexpositionbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->vertexpositionbuffer);
+ if (mesh->vertexmeshbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->vertexmeshbuffer);
+ if (mesh->element3i_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->element3i_indexbuffer);
+ if (mesh->element3s_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->element3s_indexbuffer);
+ if (mesh->vbo_vertexbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->vbo_vertexbuffer);
nextmesh = mesh->next;
Mem_Free(mesh);
}
}
extern cvar_t r_picmipworld;
+extern cvar_t mod_q3shader_default_offsetmapping;
void Mod_LoadQ3Shaders(void)
{
int j;
shader.reflectfactor = 1;
Vector4Set(shader.reflectcolor4f, 1, 1, 1, 1);
shader.r_water_wateralpha = 1;
+ shader.offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
+ shader.offsetscale = 1;
shader.specularscalemod = 1;
shader.specularpowermod = 1;
if (j < TEXTURE_MAXFRAMES + 4)
{
// remap dp_water to dpwater, dp_reflect to dpreflect, etc.
- if(j == 0 && !strncasecmp(com_token, "dp_"))
+ if(j == 0 && !strncasecmp(com_token, "dp_", 3))
dpsnprintf(parameter[j], sizeof(parameter[j]), "dp%s", &com_token[3]);
else
strlcpy(parameter[j], com_token, sizeof(parameter[j]));
{
if (j < TEXTURE_MAXFRAMES + 4)
{
- strlcpy(parameter[j], com_token, sizeof(parameter[j]));
+ // remap dp_water to dpwater, dp_reflect to dpreflect, etc.
+ if(j == 0 && !strncasecmp(com_token, "dp_", 3))
+ dpsnprintf(parameter[j], sizeof(parameter[j]), "dp%s", &com_token[3]);
+ else
+ strlcpy(parameter[j], com_token, sizeof(parameter[j]));
numparameters = j + 1;
}
if (!COM_ParseToken_QuakeC(&text, true))
shader.dpnoshadow = true;
else if (!strcasecmp(parameter[0], "dpreflectcube"))
strlcpy(shader.dpreflectcube, parameter[1], sizeof(shader.dpreflectcube));
+ else if (!strcasecmp(parameter[0], "dpmeshcollisions"))
+ shader.dpmeshcollisions = true;
else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
{
// some q3 skies don't have the sky parm set
shader.reflectfactor = atof(parameter[1]);
Vector4Set(shader.reflectcolor4f, atof(parameter[2]), atof(parameter[3]), atof(parameter[4]), atof(parameter[5]));
}
+ else if (!strcasecmp(parameter[0], "dpcamera"))
+ {
+ shader.textureflags |= Q3TEXTUREFLAG_CAMERA;
+ }
else if (!strcasecmp(parameter[0], "dpwater") && numparameters >= 12)
{
shader.textureflags |= Q3TEXTUREFLAG_WATERSHADER;
{
shader.specularpowermod = atof(parameter[1]);
}
+ else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 3)
+ {
+ if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "off"))
+ shader.offsetmapping = OFFSETMAPPING_OFF;
+ else if (!strcasecmp(parameter[1], "default"))
+ shader.offsetmapping = OFFSETMAPPING_DEFAULT;
+ else if (!strcasecmp(parameter[1], "linear"))
+ shader.offsetmapping = OFFSETMAPPING_LINEAR;
+ else if (!strcasecmp(parameter[1], "relief"))
+ shader.offsetmapping = OFFSETMAPPING_RELIEF;
+ shader.offsetscale = atof(parameter[2]);
+ }
else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
{
int i, deformindex;
}
// fix up multiple reflection types
if(shader.textureflags & Q3TEXTUREFLAG_WATERSHADER)
- shader.textureflags &= ~(Q3TEXTUREFLAG_REFRACTION | Q3TEXTUREFLAG_REFLECTION);
+ shader.textureflags &= ~(Q3TEXTUREFLAG_REFRACTION | Q3TEXTUREFLAG_REFLECTION | Q3TEXTUREFLAG_CAMERA);
Q3Shader_AddToHash (&shader);
}
texflagsmask &= ~TEXF_PICMIP;
if(!(defaulttexflags & TEXF_COMPRESS))
texflagsmask &= ~TEXF_COMPRESS;
- texture->specularscalemod = 1; // unless later loaded from the shader
- texture->specularpowermod = 1; // unless later loaded from the shader
+ // unless later loaded from the shader
+ texture->offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
+ texture->offsetscale = 1;
+ texture->specularscalemod = 1;
+ texture->specularpowermod = 1;
// WHEN ADDING DEFAULTS HERE, REMEMBER TO SYNC TO SHADER LOADING ABOVE
// HERE, AND Q1BSP LOADING
// JUST GREP FOR "specularscalemod = 1".
texture->basematerialflags |= MATERIALFLAG_REFLECTION;
if (shader->textureflags & Q3TEXTUREFLAG_WATERSHADER)
texture->basematerialflags |= MATERIALFLAG_WATERSHADER;
+ if (shader->textureflags & Q3TEXTUREFLAG_CAMERA)
+ texture->basematerialflags |= MATERIALFLAG_CAMERA;
texture->customblendfunc[0] = GL_ONE;
texture->customblendfunc[1] = GL_ZERO;
if (shader->numlayers > 0)
texture->reflectfactor = shader->reflectfactor;
Vector4Copy(shader->reflectcolor4f, texture->reflectcolor4f);
texture->r_water_wateralpha = shader->r_water_wateralpha;
+ texture->offsetmapping = shader->offsetmapping;
+ texture->offsetscale = shader->offsetscale;
texture->specularscalemod = shader->specularscalemod;
texture->specularpowermod = shader->specularpowermod;
if (shader->dpreflectcube[0])
texture->reflectcubetexture = R_GetCubemap(shader->dpreflectcube);
+
+ // set up default supercontents (on q3bsp this is overridden by the q3bsp loader)
+ texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
+ if (shader->surfaceparms & Q3SURFACEPARM_LAVA ) texture->supercontents = SUPERCONTENTS_LAVA ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SLIME ) texture->supercontents = SUPERCONTENTS_SLIME ;
+ if (shader->surfaceparms & Q3SURFACEPARM_WATER ) texture->supercontents = SUPERCONTENTS_WATER ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NONSOLID ) texture->supercontents = 0 ;
+ if (shader->surfaceparms & Q3SURFACEPARM_PLAYERCLIP ) texture->supercontents = SUPERCONTENTS_PLAYERCLIP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_BOTCLIP ) texture->supercontents = SUPERCONTENTS_MONSTERCLIP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SKY ) texture->supercontents = SUPERCONTENTS_SKY ;
+
+ // if (shader->surfaceparms & Q3SURFACEPARM_ALPHASHADOW ) texture->supercontents |= SUPERCONTENTS_ALPHASHADOW ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_AREAPORTAL ) texture->supercontents |= SUPERCONTENTS_AREAPORTAL ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_CLUSTERPORTAL) texture->supercontents |= SUPERCONTENTS_CLUSTERPORTAL;
+ // if (shader->surfaceparms & Q3SURFACEPARM_DETAIL ) texture->supercontents |= SUPERCONTENTS_DETAIL ;
+ if (shader->surfaceparms & Q3SURFACEPARM_DONOTENTER ) texture->supercontents |= SUPERCONTENTS_DONOTENTER ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_FOG ) texture->supercontents |= SUPERCONTENTS_FOG ;
+ if (shader->surfaceparms & Q3SURFACEPARM_LAVA ) texture->supercontents |= SUPERCONTENTS_LAVA ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_LIGHTFILTER ) texture->supercontents |= SUPERCONTENTS_LIGHTFILTER ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_METALSTEPS ) texture->supercontents |= SUPERCONTENTS_METALSTEPS ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NODAMAGE ) texture->supercontents |= SUPERCONTENTS_NODAMAGE ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NODLIGHT ) texture->supercontents |= SUPERCONTENTS_NODLIGHT ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NODRAW ) texture->supercontents |= SUPERCONTENTS_NODRAW ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NODROP ) texture->supercontents |= SUPERCONTENTS_NODROP ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOIMPACT ) texture->supercontents |= SUPERCONTENTS_NOIMPACT ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOLIGHTMAP ) texture->supercontents |= SUPERCONTENTS_NOLIGHTMAP ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOMARKS ) texture->supercontents |= SUPERCONTENTS_NOMARKS ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOMIPMAPS ) texture->supercontents |= SUPERCONTENTS_NOMIPMAPS ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NONSOLID ) texture->supercontents &=~SUPERCONTENTS_SOLID ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_ORIGIN ) texture->supercontents |= SUPERCONTENTS_ORIGIN ;
+ if (shader->surfaceparms & Q3SURFACEPARM_PLAYERCLIP ) texture->supercontents |= SUPERCONTENTS_PLAYERCLIP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SKY ) texture->supercontents |= SUPERCONTENTS_SKY ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_SLICK ) texture->supercontents |= SUPERCONTENTS_SLICK ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SLIME ) texture->supercontents |= SUPERCONTENTS_SLIME ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_STRUCTURAL ) texture->supercontents |= SUPERCONTENTS_STRUCTURAL ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_TRANS ) texture->supercontents |= SUPERCONTENTS_TRANS ;
+ if (shader->surfaceparms & Q3SURFACEPARM_WATER ) texture->supercontents |= SUPERCONTENTS_WATER ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_POINTLIGHT ) texture->supercontents |= SUPERCONTENTS_POINTLIGHT ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_HINT ) texture->supercontents |= SUPERCONTENTS_HINT ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_DUST ) texture->supercontents |= SUPERCONTENTS_DUST ;
+ if (shader->surfaceparms & Q3SURFACEPARM_BOTCLIP ) texture->supercontents |= SUPERCONTENTS_BOTCLIP | SUPERCONTENTS_MONSTERCLIP;
+ // if (shader->surfaceparms & Q3SURFACEPARM_LIGHTGRID ) texture->supercontents |= SUPERCONTENTS_LIGHTGRID ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_ANTIPORTAL ) texture->supercontents |= SUPERCONTENTS_ANTIPORTAL ;
+
+ if (shader->dpmeshcollisions)
+ texture->basematerialflags |= MATERIALFLAG_MESHCOLLISIONS;
}
else if (!strcmp(texture->name, "noshader") || !texture->name[0])
{
if (developer_extra.integer)
Con_DPrintf("^1%s:^7 using fallback noshader material for ^3\"%s\"\n", loadmodel->name, name);
texture->surfaceparms = 0;
+ texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
}
else if (!strcmp(texture->name, "common/nodraw") || !strcmp(texture->name, "textures/common/nodraw"))
{
Con_DPrintf("^1%s:^7 using fallback nodraw material for ^3\"%s\"\n", loadmodel->name, name);
texture->surfaceparms = 0;
texture->basematerialflags = MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
+ texture->supercontents = SUPERCONTENTS_SOLID;
}
else
{
Con_DPrintf("^1%s:^7 No shader found for texture ^3\"%s\"\n", loadmodel->name, texture->name);
texture->surfaceparms = 0;
if (texture->surfaceflags & Q3SURFACEFLAG_NODRAW)
+ {
texture->basematerialflags |= MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
+ texture->supercontents = SUPERCONTENTS_SOLID;
+ }
else if (texture->surfaceflags & Q3SURFACEFLAG_SKY)
+ {
texture->basematerialflags |= MATERIALFLAG_SKY | MATERIALFLAG_NOSHADOW;
+ texture->supercontents = SUPERCONTENTS_SKY;
+ }
else
+ {
texture->basematerialflags |= MATERIALFLAG_WALL;
+ texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
+ }
texture->numskinframes = 1;
if(cls.state == ca_dedicated)
{
void Mod_BuildVBOs(void)
{
+ if (!loadmodel->surfmesh.num_vertices)
+ return;
+
if (gl_paranoid.integer && loadmodel->surfmesh.data_element3s && loadmodel->surfmesh.data_element3i)
{
int i;
}
}
- if (!vid.support.arb_vertex_buffer_object)
- return;
- // only build a vbo if one has not already been created (this is important for brush models which load specially)
- if (loadmodel->surfmesh.vbo)
- return;
+ // build r_vertexmesh_t array
+ // (compressed interleaved array for faster rendering)
+ if (!loadmodel->surfmesh.vertexmesh)
+ {
+ int vertexindex;
+ int numvertices = loadmodel->surfmesh.num_vertices;
+ r_vertexmesh_t *vertexmesh;
+ loadmodel->surfmesh.vertexmesh = vertexmesh = (r_vertexmesh_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*loadmodel->surfmesh.vertexmesh));
+ for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexmesh++)
+ {
+ VectorCopy(loadmodel->surfmesh.data_vertex3f + 3*vertexindex, vertexmesh->vertex3f);
+ VectorScale(loadmodel->surfmesh.data_svector3f + 3*vertexindex, 1.0f, vertexmesh->svector3f);
+ VectorScale(loadmodel->surfmesh.data_tvector3f + 3*vertexindex, 1.0f, vertexmesh->tvector3f);
+ VectorScale(loadmodel->surfmesh.data_normal3f + 3*vertexindex, 1.0f, vertexmesh->normal3f);
+ if (loadmodel->surfmesh.data_lightmapcolor4f)
+ Vector4Scale(loadmodel->surfmesh.data_lightmapcolor4f + 4*vertexindex, 255.0f, vertexmesh->color4ub);
+ Vector2Copy(loadmodel->surfmesh.data_texcoordtexture2f + 2*vertexindex, vertexmesh->texcoordtexture2f);
+ if (loadmodel->surfmesh.data_texcoordlightmap2f)
+ Vector2Scale(loadmodel->surfmesh.data_texcoordlightmap2f + 2*vertexindex, 1.0f, vertexmesh->texcoordlightmap2f);
+ }
+ }
- // element buffer is easy because it's just one array
- if (loadmodel->surfmesh.num_triangles)
+ // build r_vertexposition_t array
+ if (!loadmodel->surfmesh.vertexposition)
{
- if (loadmodel->surfmesh.data_element3s)
- loadmodel->surfmesh.ebo3s = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]), loadmodel->name);
- else
- loadmodel->surfmesh.ebo3i = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles * sizeof(unsigned int[3]), loadmodel->name);
+ int vertexindex;
+ int numvertices = loadmodel->surfmesh.num_vertices;
+ r_vertexposition_t *vertexposition;
+ loadmodel->surfmesh.vertexposition = vertexposition = (r_vertexposition_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*loadmodel->surfmesh.vertexposition));
+ for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexposition++)
+ VectorCopy(loadmodel->surfmesh.data_vertex3f + 3*vertexindex, vertexposition->vertex3f);
}
+ // upload r_vertexmesh_t array as a buffer
+ if (loadmodel->surfmesh.vertexmesh && !loadmodel->surfmesh.vertexmeshbuffer)
+ loadmodel->surfmesh.vertexmeshbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.vertexmesh, loadmodel->surfmesh.num_vertices * sizeof(*loadmodel->surfmesh.vertexmesh), loadmodel->name, false, false);
+
+ // upload r_vertexposition_t array as a buffer
+ if (loadmodel->surfmesh.vertexposition && !loadmodel->surfmesh.vertexpositionbuffer)
+ loadmodel->surfmesh.vertexpositionbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.vertexposition, loadmodel->surfmesh.num_vertices * sizeof(*loadmodel->surfmesh.vertexposition), loadmodel->name, false, false);
+
+ // upload short indices as a buffer
+ if (loadmodel->surfmesh.data_element3s && !loadmodel->surfmesh.data_element3s_indexbuffer)
+ loadmodel->surfmesh.data_element3s_indexbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles * sizeof(short[3]), loadmodel->name, true, false);
+
+ // upload int indices as a buffer
+ if (loadmodel->surfmesh.data_element3i && !loadmodel->surfmesh.data_element3i_indexbuffer && !loadmodel->surfmesh.data_element3s)
+ loadmodel->surfmesh.data_element3i_indexbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles * sizeof(int[3]), loadmodel->name, true, false);
+
+ // only build a vbo if one has not already been created (this is important for brush models which load specially)
// 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)
+ if (!loadmodel->surfmesh.vbo_vertexbuffer)
{
size_t size;
unsigned char *mem;
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_CreateStaticBufferObject(GL_ARRAY_BUFFER_ARB, mem, size, loadmodel->name);
+ loadmodel->surfmesh.vbo_vertexbuffer = R_Mesh_CreateMeshBuffer(mem, size, loadmodel->name, false, false);
Mem_Free(mem);
}
}
const float *v = model->surfmesh.data_vertex3f + index * 3;
const float *vn = model->surfmesh.data_normal3f + index * 3;
const float *vt = model->surfmesh.data_texcoordtexture2f + index * 2;
- const int *wi = model->surfmesh.data_vertexweightindex4i + index * 4;
- const float *wf = model->surfmesh.data_vertexweightinfluence4f + index * 4;
- if (wf[3]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 4 %i %f %i %f %i %f %i %f\n", wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1], wi[2], wf[2], wi[3], wf[3]);
- else if (wf[2]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 3 %i %f %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1], wi[2], wf[2]);
- else if (wf[1]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 2 %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1]);
- else l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1]);
+ const int b = model->surfmesh.blends[index];
+ if (b < model->num_bones)
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f\n" , b, v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1]);
+ else
+ {
+ const blendweights_t *w = model->surfmesh.data_blendweights + b - model->num_bones;
+ const unsigned char *wi = w->index;
+ const unsigned char *wf = w->influence;
+ if (wf[3]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 4 %i %f %i %f %i %f %i %f\n", wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0]/255.0f, wi[1], wf[1]/255.0f, wi[2], wf[2]/255.0f, wi[3], wf[3]/255.0f);
+ else if (wf[2]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 3 %i %f %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0]/255.0f, wi[1], wf[1]/255.0f, wi[2], wf[2]/255.0f);
+ else if (wf[1]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 2 %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0]/255.0f, wi[1], wf[1]/255.0f);
+ else l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1]);
+ }
if (l > 0)
outbufferpos += l;
}
char animname2[MAX_QPATH];
char zymtextbuffer[16384];
char dpmtextbuffer[16384];
+ char framegroupstextbuffer[16384];
int zymtextsize = 0;
int dpmtextsize = 0;
+ int framegroupstextsize = 0;
if (Cmd_Argc() != 2)
{
// individual frame
// check for additional frames with same name
for (l = 0, k = strlen(animname);animname[l];l++)
- if ((animname[l] < '0' || animname[l] > '9') && animname[l] != '_')
+ if(animname[l] < '0' || animname[l] > '9')
k = l + 1;
+ if(k > 0 && animname[k-1] == '_')
+ --k;
animname[k] = 0;
count = mod->num_poses - first;
for (j = i + 1;j < mod->numframes;j++)
{
strlcpy(animname2, mod->animscenes[j].name, sizeof(animname2));
for (l = 0, k = strlen(animname2);animname2[l];l++)
- if ((animname2[l] < '0' || animname2[l] > '9') && animname2[l] != '_')
+ if(animname2[l] < '0' || animname2[l] > '9')
k = l + 1;
+ if(k > 0 && animname[k-1] == '_')
+ --k;
animname2[k] = 0;
if (strcmp(animname2, animname) || mod->animscenes[j].framecount > 1)
{
Mod_Decompile_SMD(mod, outname, first, count, false);
if (zymtextsize < (int)sizeof(zymtextbuffer) - 100)
{
- l = dpsnprintf(zymtextbuffer + zymtextsize, sizeof(zymtextbuffer) - zymtextsize, "scene %s.smd fps %g\n", animname, mod->animscenes[i].framerate);
+ l = dpsnprintf(zymtextbuffer + zymtextsize, sizeof(zymtextbuffer) - zymtextsize, "scene %s.smd fps %g %s\n", animname, mod->animscenes[i].framerate, mod->animscenes[i].loop ? "" : " noloop");
if (l > 0) zymtextsize += l;
}
if (dpmtextsize < (int)sizeof(dpmtextbuffer) - 100)
{
- l = dpsnprintf(dpmtextbuffer + dpmtextsize, sizeof(dpmtextbuffer) - dpmtextsize, "scene %s.smd\n", animname);
+ l = dpsnprintf(dpmtextbuffer + dpmtextsize, sizeof(dpmtextbuffer) - dpmtextsize, "scene %s.smd fps %g %s\n", animname, mod->animscenes[i].framerate, mod->animscenes[i].loop ? "" : " noloop");
if (l > 0) dpmtextsize += l;
}
+ if (framegroupstextsize < (int)sizeof(framegroupstextbuffer) - 100)
+ {
+ l = dpsnprintf(framegroupstextbuffer + framegroupstextsize, sizeof(framegroupstextbuffer) - framegroupstextsize, "%d %d %f %d // %s\n", first, count, mod->animscenes[i].framerate, mod->animscenes[i].loop, animname);
+ if (l > 0) framegroupstextsize += l;
+ }
}
if (zymtextsize)
FS_WriteFile(va("%s_decompiled/out_zym.txt", basename), zymtextbuffer, (fs_offset_t)zymtextsize);
if (dpmtextsize)
FS_WriteFile(va("%s_decompiled/out_dpm.txt", basename), dpmtextbuffer, (fs_offset_t)dpmtextsize);
+ if (framegroupstextsize)
+ FS_WriteFile(va("%s_decompiled.framegroups", basename), framegroupstextbuffer, (fs_offset_t)framegroupstextsize);
}
}
if (model->surfmesh.num_vertices > 65536)
model->surfmesh.data_element3s = NULL;
- if (model->surfmesh.vbo)
- R_Mesh_DestroyBufferObject(model->surfmesh.vbo);
- model->surfmesh.vbo = 0;
- if (model->surfmesh.ebo3i)
- R_Mesh_DestroyBufferObject(model->surfmesh.ebo3i);
- model->surfmesh.ebo3i = 0;
- if (model->surfmesh.ebo3s)
- R_Mesh_DestroyBufferObject(model->surfmesh.ebo3s);
- model->surfmesh.ebo3s = 0;
+ if (model->surfmesh.vertexposition)
+ Mem_Free(model->surfmesh.vertexposition);
+ model->surfmesh.vertexposition = NULL;
+ if (model->surfmesh.vertexmesh)
+ Mem_Free(model->surfmesh.vertexmesh);
+ model->surfmesh.vertexmesh = NULL;
+ if (model->surfmesh.vertexpositionbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.vertexpositionbuffer);
+ model->surfmesh.vertexpositionbuffer = NULL;
+ if (model->surfmesh.vertexmeshbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.vertexmeshbuffer);
+ model->surfmesh.vertexmeshbuffer = NULL;
+ if (model->surfmesh.data_element3i_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.data_element3i_indexbuffer);
+ model->surfmesh.data_element3i_indexbuffer = NULL;
+ if (model->surfmesh.data_element3s_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.data_element3s_indexbuffer);
+ model->surfmesh.data_element3s_indexbuffer = NULL;
+ if (model->surfmesh.vbo_vertexbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.vbo_vertexbuffer);
+ model->surfmesh.vbo_vertexbuffer = 0;
// convert all triangles to unique vertex data
outvertexindex = 0;