Okay, so here's a quick patch for the FSO side of things. Be aware I haven't been able to test it yet due to a lack of matching PCS2:
Index: code/model/model.h
===================================================================
--- code/model/model.h (revision 10471)
+++ code/model/model.h (working copy)
@@ -265,6 +265,13 @@
float u,v;
} model_tmap_vert;
+// The E: This struct is used by POF models version 2118 and up, for models with subobjects that have >2^16 vertices
+typedef struct model_tmap_vert_large {
+ uint vertnum;
+ uint normnum;
+ float u, v;
+} model_tmap_vert_large;
+
struct bsp_collision_node {
vec3d min;
vec3d max;
Index: code/model/modelinterp.cpp
===================================================================
--- code/model/modelinterp.cpp (revision 10471)
+++ code/model/modelinterp.cpp (working copy)
@@ -68,7 +68,7 @@
// Local variables
//
-static int Num_interp_verts_allocated = 0;
+static uint Num_interp_verts_allocated = 0;
vec3d **Interp_verts = NULL;
static vertex *Interp_points = NULL;
static vertex *Interp_splode_points = NULL;
@@ -97,7 +97,7 @@
// -------------------------------------------------------------------
-static int Num_interp_norms_allocated = 0;
+static uint Num_interp_norms_allocated = 0;
static vec3d **Interp_norms = NULL;
static ubyte *Interp_light_applied = NULL;
static int Interp_num_norms = 0;
@@ -217,7 +217,7 @@
extern void model_collide_allocate_point_list(int n_points);
extern void model_collide_free_point_list();
-void model_allocate_interp_data(int n_verts = 0, int n_norms = 0, int n_list_verts = 0)
+void model_allocate_interp_data(uint n_verts = 0, uint n_norms = 0, int n_list_verts = 0)
{
static ubyte dealloc = 0;
@@ -746,11 +746,17 @@
ubyte Interp_subspace_g = 255;
ubyte Interp_subspace_b = 255;
+#define GET_VERT_NUM(i) verts != NULL ? verts[i].vertnum : vert_large[i].vertnum
+#define GET_NORM_NUM(i) verts != NULL ? verts[i].normnum : vert_large[i].normnum
+#define GET_TEXCO_U(i) verts != NULL ? verts[i].u : vert_large[i].u
+#define GET_TEXCO_V(i) verts != NULL ? verts[i].v : vert_large[i].v
+
void model_interp_tmappoly(ubyte * p,polymodel * pm)
{
int i;
int nv;
model_tmap_vert *verts;
+ model_tmap_vert_large *vert_large;
int cull = 0;
// Goober5000
@@ -793,14 +799,23 @@
if ( nv < 0 )
return;
- verts = (model_tmap_vert *)(p+44);
+ if (pm->version < 2118) {
+ verts = (model_tmap_vert *) (p + 44);
+ vert_large = NULL;
+ }
+ else {
+ vert_large = (model_tmap_vert_large *) (p + 44);
+ verts = NULL;
+ }
- int max_n_verts = 0;
- int max_n_norms = 0;
+ Assertion(verts != NULL || vert_large != NULL, "No valid vertex data found in pof file!\n");
+ uint max_n_verts = 0;
+ uint max_n_norms = 0;
+
for (i = 0; i < nv; i++) {
- max_n_verts = MAX(verts[i].vertnum + 1, max_n_verts);
- max_n_norms = MAX(verts[i].normnum + 1, max_n_norms);
+ max_n_verts = MAX(GET_VERT_NUM(i) + 1, max_n_verts);
+ max_n_norms = MAX(GET_NORM_NUM(i) + 1, max_n_norms);
}
model_allocate_interp_data(max_n_verts, max_n_norms, nv);
@@ -814,14 +829,14 @@
if(splodeing){
float salpha = 1.0f - splode_level;
- for (i=0;i<nv;i++){
+ for (i = 0; i < nv; i++){
Interp_list[i] = &Interp_splode_points[verts[i].vertnum];
- Interp_list[i]->texture_position.u = verts[i].u*2;
- Interp_list[i]->texture_position.v = verts[i].v*2;
- Interp_list[i]->r = (unsigned char)(255*salpha);
- Interp_list[i]->g = (unsigned char)(250*salpha);
- Interp_list[i]->b = (unsigned char)(200*salpha);
- model_interp_edge_alpha(&Interp_list[i]->r, &Interp_list[i]->g, &Interp_list[i]->b, Interp_verts[verts[i].vertnum], Interp_norms[verts[i].normnum], salpha, false);
+ Interp_list[i]->texture_position.u = verts[i].u * 2;
+ Interp_list[i]->texture_position.v = verts[i].v * 2;
+ Interp_list[i]->r = (unsigned char) (255 * salpha);
+ Interp_list[i]->g = (unsigned char) (250 * salpha);
+ Interp_list[i]->b = (unsigned char) (200 * salpha);
+ model_interp_edge_alpha(&Interp_list[i]->r, &Interp_list[i]->g, &Interp_list[i]->b, Interp_verts[GET_VERT_NUM(i)], Interp_norms[GET_NORM_NUM(i)], salpha, false);
}
cull = gr_set_cull(0);
gr_set_bitmap( splodeingtexture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, salpha );
@@ -832,11 +847,13 @@
}
for (i=0;i<nv;i++) {
- Interp_list[i] = &Interp_points[verts[i].vertnum];
+
+ Interp_list[i] = &Interp_points[GET_VERT_NUM(i)];
- Interp_list[i]->texture_position.u = verts[i].u;
- Interp_list[i]->texture_position.v = verts[i].v;
+ Interp_list[i]->texture_position.u = GET_TEXCO_U(i);
+ Interp_list[i]->texture_position.v = GET_TEXCO_V(i);
+
if ( Interp_subspace ) {
Interp_list[i]->texture_position.v += Interp_subspace_offset_u;
Interp_list[i]->texture_position.u += Interp_subspace_offset_v;
@@ -854,11 +871,11 @@
Interp_list[i]->spec_b = 0;
if (Interp_flags & MR_EDGE_ALPHA) {
- model_interp_edge_alpha(&Interp_list[i]->r, &Interp_list[i]->g, &Interp_list[i]->b, Interp_verts[verts[i].vertnum], Interp_norms[verts[i].normnum], Interp_warp_alpha, false);
+ model_interp_edge_alpha(&Interp_list[i]->r, &Interp_list[i]->g, &Interp_list[i]->b, Interp_verts[GET_VERT_NUM(i)], Interp_norms[GET_NORM_NUM(i)], Interp_warp_alpha, false);
}
if (Interp_flags & MR_CENTER_ALPHA) {
- model_interp_edge_alpha(&Interp_list[i]->r, &Interp_list[i]->g, &Interp_list[i]->b, Interp_verts[verts[i].vertnum], Interp_norms[verts[i].normnum], Interp_warp_alpha, true);
+ model_interp_edge_alpha(&Interp_list[i]->r, &Interp_list[i]->g, &Interp_list[i]->b, Interp_verts[GET_VERT_NUM(i)], Interp_norms[GET_NORM_NUM(i)], Interp_warp_alpha, true);
}
SPECMAP = -1;
@@ -867,8 +884,8 @@
MISCMAP = -1;
} else {
- int vertnum = verts[i].vertnum;
- int norm = verts[i].normnum;
+ uint vertnum = GET_VERT_NUM(i);
+ uint norm = GET_NORM_NUM(i);
if ( Interp_flags & MR_NO_SMOOTHING ) {
light_apply_rgb( &Interp_list[i]->r, &Interp_list[i]->g, &Interp_list[i]->b, Interp_verts[vertnum], vp(p+8), Interp_light );
Index: code/model/modeloctant.cpp
===================================================================
--- code/model/modeloctant.cpp (revision 10471)
+++ code/model/modeloctant.cpp (working copy)
@@ -19,7 +19,7 @@
#include "model/modelsinc.h"
#include "cmdline/cmdline.h"
-extern void model_allocate_interp_data(int n_verts, int n_norms, int n_list_verts = 0);
+extern void model_allocate_interp_data(uint n_verts, uint n_norms, int n_list_verts = 0);
// returns 1 if a point is in an octant.
Index: code/model/modelread.cpp
===================================================================
--- code/model/modelread.cpp (revision 10471)
+++ code/model/modelread.cpp (working copy)
@@ -5076,7 +5076,7 @@
}
#if BYTE_ORDER == BIG_ENDIAN
-extern void model_allocate_interp_data(int, int, int);
+extern void model_allocate_interp_data(uint, uint, int);
// tigital -
void swap_bsp_defpoints(ubyte * p)
Now, here's the changes that still need to be made on the PCS2 side of things:
1. Introduce a corresponding vert_large structure in PCS2's BSP writer
2. Switch to using it when necessary (by default would be kinda bad, I think)
This, however, requires setting up to build PCS2, which as I am discovering right now is not exactly trivial

But that should not be an insurmountable hurdle, I think.