[iqm] Use 32-bit indices for large models

That is, those with more than 65520 vertices. Not properly supported for
sw or gl, and glsl isn't rendering properly for some reason (renderdoc
does see the meshes, though, so maybe depth or winding issues).
This commit is contained in:
Bill Currie 2024-01-09 13:36:46 +09:00
parent 834587f102
commit 119e9766b9
9 changed files with 48 additions and 23 deletions

View file

@ -135,7 +135,10 @@ typedef struct iqm_s {
byte *vertices;
int stride;
int num_elements;
uint16_t *elements;
union {
uint16_t *elements16;
uint32_t *elements32;
};
int num_arrays;
iqmvertexarray *vertexarrays;
int num_joints;

View file

@ -130,15 +130,16 @@ glsl_iqm_load_arrays (iqm_t *iqm)
qfeglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, glsl->element_array);
qfeglBufferData (GL_ARRAY_BUFFER, iqm->num_verts * iqm->stride,
iqm->vertices, GL_STATIC_DRAW);
int esize = iqm->num_verts > 0xfff0 ? sizeof (uint32_t) : sizeof (uint16_t);
qfeglBufferData (GL_ELEMENT_ARRAY_BUFFER,
iqm->num_elements * sizeof (uint16_t), iqm->elements,
iqm->num_elements * esize, iqm->elements16,
GL_STATIC_DRAW);
qfeglBindBuffer (GL_ARRAY_BUFFER, 0);
qfeglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
free (iqm->vertices);
iqm->vertices = 0;
free (iqm->elements);
iqm->elements = 0;
free (iqm->elements16);
iqm->elements16 = 0;
}
void

View file

@ -344,9 +344,15 @@ load_iqm_meshes (model_t *mod, const iqmheader *hdr, byte *buffer)
if (!(tris = get_triangles (hdr, buffer)))
return false;
iqm->num_elements = hdr->num_triangles * 3;
iqm->elements = malloc (hdr->num_triangles * 3 * sizeof (uint16_t));
for (i = 0; i < hdr->num_triangles; i++)
VectorCopy (tris[i].vertex, iqm->elements + i * 3);
if (iqm->num_verts > 0xfff0) {
iqm->elements32 = malloc (hdr->num_triangles * 3 * sizeof (uint32_t));
for (i = 0; i < hdr->num_triangles; i++)
VectorCopy (tris[i].vertex, iqm->elements32 + i * 3);
} else {
iqm->elements16 = malloc (hdr->num_triangles * 3 * sizeof (uint16_t));
for (i = 0; i < hdr->num_triangles; i++)
VectorCopy (tris[i].vertex, iqm->elements16 + i * 3);
}
if (!(meshes = get_meshes (hdr, buffer)))
return false;
iqm->num_meshes = hdr->num_meshes;
@ -528,8 +534,8 @@ Mod_FreeIQM (iqm_t *iqm)
if (iqm->vertices)
free (iqm->vertices);
free (iqm->vertexarrays);
if (iqm->elements)
free (iqm->elements);
if (iqm->elements16)
free (iqm->elements16);
free (iqm->meshes);
free (iqm->joints);
free (iqm->baseframe);

View file

@ -124,7 +124,7 @@ sw_iqm_load_textures (iqm_t *iqm)
tex = sw->skins[i] = &null_texture;
for (j = 0; j < (int) iqm->meshes[i].num_triangles * 3; j++) {
int ind = iqm->meshes[i].first_triangle * 3 + j;
int vind = iqm->elements[ind];
int vind = iqm->elements16[ind];
byte *vert = iqm->vertices + iqm->stride * vind;
byte *tc = vert + sw->texcoord->offset;
@ -150,10 +150,10 @@ sw_iqm_convert_tris (iqm_t *iqm)
tris = malloc (num_tris * sizeof (mtriangle_t));
for (i = 0; i < num_tris; i++) {
tris[i].facesfront = 1;
VectorCopy (iqm->elements + i * 3, tris[i].vertindex);
VectorCopy (iqm->elements16 + i * 3, tris[i].vertindex);
}
free (iqm->elements);
iqm->elements = (uint16_t *) tris;
free (iqm->elements16);
iqm->elements16 = (uint16_t *) tris;
}
void

View file

@ -225,6 +225,9 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
size_t geom_size = iqm->num_verts * sizeof (iqmgvert_t);
size_t rend_size = iqm->num_verts * sizeof (iqmrvert_t);
size_t elem_size = iqm->num_elements * sizeof (uint16_t);
if (iqm->num_verts > 0xfff0) {
elem_size = iqm->num_elements * sizeof (uint32_t);
}
size_t buff_size = geom_size + rend_size + elem_size + 1024;
qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device,
va (ctx->va_ctx, "iqm:%s",
@ -282,7 +285,7 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
data += size;
}
}
memcpy (elements, iqm->elements, elem_size);
memcpy (elements, iqm->elements16, elem_size);
qfv_bufferbarrier_t bb[] = {
bufferBarriers[qfv_BB_Unknown_to_TransferWrite],
@ -417,11 +420,15 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
},
};
size_t elem_size = iqm->num_elements * sizeof (uint16_t);
if (iqm->num_verts > 0xfff0) {
elem_size = iqm->num_elements * sizeof (uint32_t);
}
mesh->mesh->objects[2] = (qfv_resobj_t) {
.name = "index",
.type = qfv_res_buffer,
.buffer = {
.size = iqm->num_elements * sizeof (uint16_t),
.size = elem_size,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
},

View file

@ -65,7 +65,7 @@ gl_draw_iqm_frame (iqm_t *iqm, gliqm_t *gl, iqmframe_t *frame, iqmmesh *mesh)
for (i = 0; i < mesh->num_triangles; i++) {
int vind = (mesh->first_triangle + i) * 3;
for (j = 0; j < 3; j++) {
vert = iqm->vertices + iqm->elements[vind + j] * iqm->stride;
vert = iqm->vertices + iqm->elements16[vind + j] * iqm->stride;
if (gl->texcoord)
qfglTexCoord2fv ((float *) (vert + gl->texcoord->offset));
if (gl->color)

View file

@ -269,9 +269,16 @@ glsl_R_DrawIQM (entity_t ent)
qfeglBindTexture (GL_TEXTURE_2D, glsl->textures[i]);
qfeglActiveTexture (GL_TEXTURE0 + 1);
qfeglBindTexture (GL_TEXTURE_2D, glsl->normmaps[i]);
qfeglDrawElements (GL_TRIANGLES, 3 * iqm->meshes[i].num_triangles,
GL_UNSIGNED_SHORT,
iqm->elements + 3 * iqm->meshes[i].first_triangle);
int firstElement = 3 * iqm->meshes[i].first_triangle;
if (iqm->num_verts > 0xfff0) {
qfeglDrawElements (GL_TRIANGLES, 3 * iqm->meshes[i].num_triangles,
GL_UNSIGNED_INT,
iqm->elements32 + firstElement);
} else {
qfeglDrawElements (GL_TRIANGLES, 3 * iqm->meshes[i].num_triangles,
GL_UNSIGNED_SHORT,
iqm->elements16 + firstElement);
}
}
}

View file

@ -145,7 +145,7 @@ R_IQMPrepareUnclippedPoints (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame)
iqm_setup_skin (sw, i);
tris = iqm->elements + mesh->first_triangle;
tris = iqm->elements16 + mesh->first_triangle;
r_affinetridesc.ptriangles = (mtriangle_t *) tris;
r_affinetridesc.numtriangles = mesh->num_triangles;
D_PolysetDraw ();
@ -187,7 +187,7 @@ R_IQMPreparePoints (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame)
iqm_setup_skin (sw, i);
mtri = (mtriangle_t *) iqm->elements + mesh->first_triangle;
mtri = (mtriangle_t *) iqm->elements16 + mesh->first_triangle;
r_affinetridesc.numtriangles = 1;
for (j = 0; j < mesh->num_triangles; j++, mtri++) {
pfv[0] = &pfinalverts[mtri->vertindex[0]];

View file

@ -86,8 +86,9 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
Vulkan_BeginEntityLabel (ctx, cmd, ent);
dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets);
dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0,
VK_INDEX_TYPE_UINT16);
VkIndexType indexType = iqm->num_verts > 0xfff0 ? VK_INDEX_TYPE_UINT32
: VK_INDEX_TYPE_UINT16;
dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, indexType);
QFV_PushConstants (device, cmd, layout, numPC, constants);
for (int i = 0; i < iqm->num_meshes; i++) {
if (skins) {