mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-11 20:03:11 +00:00
[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:
parent
834587f102
commit
119e9766b9
9 changed files with 48 additions and 23 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]];
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue