+ // build the lower quality collision geometry
+ xlevel = QuadraticBSplinePatchSubdivisionLevelOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value, 10);
+ ylevel = QuadraticBSplinePatchSubdivisionLevelOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value, 10);
+ // bound to user settings
+ xlevel = bound(r_subdivisions_collision_minlevel.integer, xlevel, r_subdivisions_collision_maxlevel.integer);
+ ylevel = bound(r_subdivisions_collision_minlevel.integer, ylevel, r_subdivisions_collision_maxlevel.integer);
+ // bound to sanity settings
+ xlevel = bound(0, xlevel, 10);
+ ylevel = bound(0, ylevel, 10);
+ // bound to user limit on vertices
+ while ((xlevel > 0 || ylevel > 0) && (((patchsize[0] - 1) << xlevel) + 1) * (((patchsize[1] - 1) << ylevel) + 1) > min(r_subdivisions_collision_maxvertices.integer, 262144))
+ {
+ if (xlevel > ylevel)
+ xlevel--;
+ else
+ ylevel--;
+ }
+ finalwidth = ((patchsize[0] - 1) << xlevel) + 1;
+ finalheight = ((patchsize[1] - 1) << ylevel) + 1;
+ finalvertices = finalwidth * finalheight;
+ finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
+ out->data_collisionvertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * finalvertices);
+ out->data_collisionelement3i = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * finaltriangles);
+ out->num_collisionvertices = finalvertices;
+ out->num_collisiontriangles = finaltriangles;
+ QuadraticBSplinePatchSubdivideFloatBuffer(patchsize[0], patchsize[1], xlevel, ylevel, 3, originalvertex3f, out->data_collisionvertex3f);
+ // generate elements
+ e = out->data_collisionelement3i;
+ for (y = 0;y < finalheight - 1;y++)
+ {
+ row0 = (y + 0) * finalwidth;
+ row1 = (y + 1) * finalwidth;
+ for (x = 0;x < finalwidth - 1;x++)
+ {
+ *e++ = row0;
+ *e++ = row1;
+ *e++ = row0 + 1;
+ *e++ = row1;
+ *e++ = row1 + 1;
+ *e++ = row0 + 1;
+ row0++;
+ row1++;
+ }
+ }
+ out->num_collisiontriangles = Mod_RemoveDegenerateTriangles(out->num_collisiontriangles, out->data_collisionelement3i, out->data_collisionelement3i, out->data_collisionvertex3f);
+ if (developer.integer)
+ {
+ if (out->num_collisiontriangles < finaltriangles)
+ Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided for collisions to %i vertices / %i triangles, %i degenerate triangles removed (leaving %i)\n", patchsize[0], patchsize[1], out->num_collisionvertices, finaltriangles, finaltriangles - out->num_collisiontriangles, out->num_collisiontriangles);
+ else
+ Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided for collisions to %i vertices / %i triangles\n", patchsize[0], patchsize[1], out->num_collisionvertices, out->num_collisiontriangles);
+ }