+ // the MakePortals code works fine on the q3bsp data as well
+ if (mod_bsp_portalize.integer)
+ Mod_BSP_MakePortals();
+
+ // FIXME: shader alpha should replace r_wateralpha support in q3bsp
+ loadmodel->brush.supportwateralpha = true;
+
+ loadmodel->brush.num_leafs = 0;
+ Mod_Q3BSP_RecursiveFindNumLeafs(loadmodel->brush.data_nodes);
+
+ if (loadmodel->brush.numsubmodels)
+ loadmodel->brush.submodels = (model_t **)Mem_Alloc(loadmodel->mempool, loadmodel->brush.numsubmodels * sizeof(model_t *));
+
+ mod = loadmodel;
+ mod->modelsurfaces_sorted = (int*)Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
+ for (i = 0;i < loadmodel->brush.numsubmodels;i++)
+ {
+ if (i > 0)
+ {
+ char name[10];
+ // duplicate the basic information
+ dpsnprintf(name, sizeof(name), "*%i", i);
+ mod = Mod_FindName(name, loadmodel->name);
+ // copy the base model to this one
+ *mod = *loadmodel;
+ // rename the clone back to its proper name
+ strlcpy(mod->name, name, sizeof(mod->name));
+ mod->brush.parentmodel = loadmodel;
+ // textures and memory belong to the main model
+ mod->texturepool = NULL;
+ mod->mempool = NULL;
+ mod->brush.GetPVS = NULL;
+ mod->brush.FatPVS = NULL;
+ mod->brush.BoxTouchingPVS = NULL;
+ mod->brush.BoxTouchingLeafPVS = NULL;
+ mod->brush.BoxTouchingVisibleLeafs = NULL;
+ mod->brush.FindBoxClusters = NULL;
+ mod->brush.LightPoint = NULL;
+ mod->brush.AmbientSoundLevelsForPoint = NULL;
+ }
+ mod->brush.submodel = i;
+ if (loadmodel->brush.submodels)
+ loadmodel->brush.submodels[i] = mod;
+
+ // make the model surface list (used by shadowing/lighting)
+ mod->submodelsurfaces_start = mod->brushq3.data_models[i].firstface;
+ mod->submodelsurfaces_end = mod->brushq3.data_models[i].firstface + mod->brushq3.data_models[i].numfaces;
+ mod->firstmodelbrush = mod->brushq3.data_models[i].firstbrush;
+ mod->nummodelbrushes = mod->brushq3.data_models[i].numbrushes;
+
+ VectorCopy(mod->brushq3.data_models[i].mins, mod->normalmins);
+ VectorCopy(mod->brushq3.data_models[i].maxs, mod->normalmaxs);
+ // enlarge the bounding box to enclose all geometry of this model,
+ // because q3map2 sometimes lies (mostly to affect the lightgrid),
+ // which can in turn mess up the farclip (as well as culling when
+ // outside the level - an unimportant concern)
+
+ //printf("Editing model %d... BEFORE re-bounding: %f %f %f - %f %f %f\n", i, mod->normalmins[0], mod->normalmins[1], mod->normalmins[2], mod->normalmaxs[0], mod->normalmaxs[1], mod->normalmaxs[2]);
+ for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
+ {
+ const msurface_t *surface = mod->data_surfaces + j;
+ const float *v = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
+ int k;
+ if (!surface->num_vertices)
+ continue;
+ for (k = 0;k < surface->num_vertices;k++, v += 3)
+ {
+ mod->normalmins[0] = min(mod->normalmins[0], v[0]);
+ mod->normalmins[1] = min(mod->normalmins[1], v[1]);
+ mod->normalmins[2] = min(mod->normalmins[2], v[2]);
+ mod->normalmaxs[0] = max(mod->normalmaxs[0], v[0]);
+ mod->normalmaxs[1] = max(mod->normalmaxs[1], v[1]);
+ mod->normalmaxs[2] = max(mod->normalmaxs[2], v[2]);
+ }
+ }
+ //printf("Editing model %d... AFTER re-bounding: %f %f %f - %f %f %f\n", i, mod->normalmins[0], mod->normalmins[1], mod->normalmins[2], mod->normalmaxs[0], mod->normalmaxs[1], mod->normalmaxs[2]);
+ corner[0] = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
+ corner[1] = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
+ corner[2] = max(fabs(mod->normalmins[2]), fabs(mod->normalmaxs[2]));
+ modelradius = sqrt(corner[0]*corner[0]+corner[1]*corner[1]+corner[2]*corner[2]);
+ yawradius = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
+ mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
+ mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
+ mod->yawmaxs[0] = mod->yawmaxs[1] = yawradius;
+ mod->yawmins[0] = mod->yawmins[1] = -yawradius;
+ mod->yawmins[2] = mod->normalmins[2];
+ mod->yawmaxs[2] = mod->normalmaxs[2];
+ mod->radius = modelradius;
+ mod->radius2 = modelradius * modelradius;
+
+ Mod_SetDrawSkyAndWater(mod);
+ Mod_MakeCollisionBIH(mod, false, &mod->collision_bih);
+ Mod_MakeCollisionBIH(mod, true, &mod->render_bih);
+
+ // generate VBOs and other shared data before cloning submodels
+ if (i == 0)
+ Mod_BuildVBOs();
+ }
+ mod = loadmodel;
+
+ // make the model surface list (used by shadowing/lighting)
+ Mod_MakeSortedSurfaces(loadmodel);
+
+ if (mod_q3bsp_sRGBlightmaps.integer)
+ {
+ if (vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
+ {
+ // actually we do in sRGB fallback with sRGB lightmaps: Image_sRGBFloatFromLinear_Lightmap(Image_LinearFloatFromsRGBFloat(x))
+ // neutral point is at Image_sRGBFloatFromLinearFloat(0.5)
+ // so we need to map Image_sRGBFloatFromLinearFloat(0.5) to 0.5
+ // factor is 0.5 / Image_sRGBFloatFromLinearFloat(0.5)
+ //loadmodel->lightmapscale *= 0.679942f; // fixes neutral level
+ }
+ else // if this is NOT set, regular rendering looks right by this requirement anyway
+ {
+ /*
+ // we want color 1 to do the same as without sRGB
+ // so, we want to map 1 to Image_LinearFloatFromsRGBFloat(2) instead of to 2
+ loadmodel->lightmapscale *= 2.476923f; // fixes max level
+ */
+
+ // neutral level 0.5 gets uploaded as sRGB and becomes Image_LinearFloatFromsRGBFloat(0.5)
+ // we need to undo that
+ loadmodel->lightmapscale *= 2.336f; // fixes neutral level
+ }
+ }
+
+ Con_DPrintf("Stats for q3bsp model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
+}
+
+void Mod_IBSP_Load(model_t *mod, void *buffer, void *bufferend)
+{
+ int i = LittleLong(((int *)buffer)[1]);
+ if (i == Q3BSPVERSION || i == Q3BSPVERSION_IG || i == Q3BSPVERSION_LIVE)
+ Mod_Q3BSP_Load(mod,buffer, bufferend);
+ else if (i == Q2BSPVERSION)
+ Mod_Q2BSP_Load(mod,buffer, bufferend);
+ else
+ Host_Error("Mod_IBSP_Load: unknown/unsupported version %i", i);
+}
+
+static void Mod_VBSP_LoadEntities(sizebuf_t *sb)
+{
+ loadmodel->brush.entities = NULL;
+ if (!sb->cursize)
+ return;
+ loadmodel->brush.entities = (char *)Mem_Alloc(loadmodel->mempool, sb->cursize + 1);
+ MSG_ReadBytes(sb, sb->cursize, (unsigned char *)loadmodel->brush.entities);
+ loadmodel->brush.entities[sb->cursize] = 0;
+}
+
+static void Mod_VBSP_LoadVertexes(sizebuf_t *sb)
+{
+ mvertex_t *out;
+ int i, count;
+ int structsize = 12;
+
+ if (sb->cursize % structsize)
+ Host_Error("Mod_VBSP_LoadVertexes: funny lump size in %s",loadmodel->name);
+ count = sb->cursize / structsize;
+ out = (mvertex_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
+
+ loadmodel->brushq1.vertexes = out;
+ loadmodel->brushq1.numvertexes = count;
+
+ for ( i=0 ; i<count ; i++, out++)
+ {
+ out->position[0] = MSG_ReadLittleFloat(sb);
+ out->position[1] = MSG_ReadLittleFloat(sb);
+ out->position[2] = MSG_ReadLittleFloat(sb);
+ }
+}
+
+static void Mod_VBSP_LoadEdges(sizebuf_t *sb)
+{
+ medge_t *out;
+ int i, count;
+ int structsize = 4;
+
+ if (sb->cursize % structsize)
+ Host_Error("Mod_VBSP_LoadEdges: funny lump size in %s",loadmodel->name);
+ count = sb->cursize / structsize;
+ out = (medge_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
+
+ loadmodel->brushq1.edges = out;
+ loadmodel->brushq1.numedges = count;
+
+ for ( i=0 ; i<count ; i++, out++)
+ {
+ out->v[0] = (unsigned short)MSG_ReadLittleShort(sb);
+ out->v[1] = (unsigned short)MSG_ReadLittleShort(sb);
+
+ if ((int)out->v[0] >= loadmodel->brushq1.numvertexes || (int)out->v[1] >= loadmodel->brushq1.numvertexes)
+ {
+ Con_Printf("Mod_VBSP_LoadEdges: %s has invalid vertex indices in edge %i (vertices %i %i >= numvertices %i)\n", loadmodel->name, i, out->v[0], out->v[1], loadmodel->brushq1.numvertexes);
+ if(!loadmodel->brushq1.numvertexes)
+ Host_Error("Mod_VBSP_LoadEdges: %s has edges but no vertexes, cannot fix\n", loadmodel->name);
+
+ out->v[0] = 0;
+ out->v[1] = 0;
+ }
+ }
+}
+
+static void Mod_VBSP_LoadSurfedges(sizebuf_t *sb)
+{
+ int i;
+ int structsize = 4;
+
+ if (sb->cursize % structsize)
+ Host_Error("Mod_VBSP_LoadSurfedges: funny lump size in %s",loadmodel->name);
+ loadmodel->brushq1.numsurfedges = sb->cursize / structsize;
+ loadmodel->brushq1.surfedges = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->brushq1.numsurfedges * sizeof(int));
+
+ for (i = 0;i < loadmodel->brushq1.numsurfedges;i++)
+ loadmodel->brushq1.surfedges[i] = MSG_ReadLittleLong(sb);
+}
+
+static void Mod_VBSP_LoadTextures(sizebuf_t *sb)
+{
+ Con_Printf(CON_WARN "Mod_VBSP_LoadTextures: Don't know how to do this yet\n");
+}
+
+static void Mod_VBSP_LoadPlanes(sizebuf_t *sb)
+{
+ int i;
+ mplane_t *out;
+ int structsize = 20;
+
+ if (sb->cursize % structsize)
+ Host_Error("Mod_VBSP_LoadPlanes: funny lump size in %s", loadmodel->name);
+ loadmodel->brush.num_planes = sb->cursize / structsize;
+ loadmodel->brush.data_planes = out = (mplane_t *)Mem_Alloc(loadmodel->mempool, loadmodel->brush.num_planes * sizeof(*out));
+
+ for (i = 0;i < loadmodel->brush.num_planes;i++, out++)
+ {
+ out->normal[0] = MSG_ReadLittleFloat(sb);
+ out->normal[1] = MSG_ReadLittleFloat(sb);
+ out->normal[2] = MSG_ReadLittleFloat(sb);
+ out->dist = MSG_ReadLittleFloat(sb);
+ MSG_ReadLittleLong(sb); // type is not used, we use PlaneClassify
+ PlaneClassify(out);
+ }
+}
+
+static void Mod_VBSP_LoadTexinfo(sizebuf_t *sb)
+{
+ mtexinfo_t *out;
+ int i, j, k, count, miptex;
+ int structsize = 72;
+
+ if (sb->cursize % structsize)
+ Host_Error("Mod_VBSP_LoadTexinfo: funny lump size in %s",loadmodel->name);
+ count = sb->cursize / structsize;
+ out = (mtexinfo_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
+
+ loadmodel->brushq1.texinfo = out;
+ loadmodel->brushq1.numtexinfo = count;
+
+ for (i = 0;i < count;i++, out++)
+ {
+ for (k = 0;k < 2;k++)
+ for (j = 0;j < 4;j++)
+ out->vecs[k][j] = MSG_ReadLittleFloat(sb);
+
+ for (k = 0;k < 2;k++)
+ for (j = 0;j < 4;j++)
+ MSG_ReadLittleFloat(sb); // TODO lightmapVecs
+
+ out->q1flags = MSG_ReadLittleLong(sb);
+ miptex = MSG_ReadLittleLong(sb);
+
+ if (out->q1flags & TEX_SPECIAL)
+ {
+ // if texture chosen is NULL or the shader needs a lightmap,
+ // force to notexture water shader
+ out->textureindex = loadmodel->num_textures - 1;
+ }
+ else
+ {
+ // if texture chosen is NULL, force to notexture
+ out->textureindex = loadmodel->num_textures - 2;
+ }
+ // see if the specified miptex is valid and try to use it instead
+ if (loadmodel->data_textures)
+ {
+ if ((unsigned int) miptex >= (unsigned int) loadmodel->num_textures)
+ Con_Printf("error in model \"%s\": invalid miptex index %i(of %i)\n", loadmodel->name, miptex, loadmodel->num_textures);
+ else
+ out->textureindex = miptex;
+ }
+ }
+}
+
+static void Mod_VBSP_LoadFaces(sizebuf_t *sb)
+{
+ msurface_t *surface;
+ int i, j, count, surfacenum, planenum, smax, tmax, ssize, tsize, firstedge, numedges, totalverts, totaltris, lightmapnumber, lightmapsize, totallightmapsamples, lightmapoffset, texinfoindex;
+ float texmins[2], texmaxs[2], val;
+ rtexture_t *lightmaptexture, *deluxemaptexture;
+ char vabuf[1024];
+ int structsize = 56;
+
+ if (sb->cursize % structsize)
+ Host_Error("Mod_VBSP_LoadFaces: funny lump size in %s",loadmodel->name);
+ count = sb->cursize / structsize;
+ loadmodel->data_surfaces = (msurface_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_t));
+ loadmodel->data_surfaces_lightmapinfo = (msurface_lightmapinfo_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_lightmapinfo_t));
+
+ loadmodel->num_surfaces = count;
+
+ loadmodel->brushq1.firstrender = true;
+ loadmodel->brushq1.lightmapupdateflags = (unsigned char *)Mem_Alloc(loadmodel->mempool, count*sizeof(unsigned char));
+
+ totalverts = 0;
+ totaltris = 0;
+ for (surfacenum = 0;surfacenum < count;surfacenum++)
+ {
+ numedges = BuffLittleShort(sb->data + structsize * surfacenum + 8);
+ totalverts += numedges;
+ totaltris += numedges - 2;
+ }
+
+ Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, true, false);
+
+ lightmaptexture = NULL;
+ deluxemaptexture = r_texture_blanknormalmap;
+ lightmapnumber = 0;
+ lightmapsize = bound(256, gl_max_lightmapsize.integer, (int)vid.maxtexturesize_2d);
+ totallightmapsamples = 0;
+
+ totalverts = 0;
+ totaltris = 0;
+ for (surfacenum = 0, surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, surface++)
+ {
+ surface->lightmapinfo = loadmodel->data_surfaces_lightmapinfo + surfacenum;
+ planenum = (unsigned short)MSG_ReadLittleShort(sb);
+ /*side = */MSG_ReadLittleShort(sb); // TODO support onNode?
+ firstedge = MSG_ReadLittleLong(sb);
+ numedges = (unsigned short)MSG_ReadLittleShort(sb);
+ texinfoindex = (unsigned short)MSG_ReadLittleShort(sb);
+ MSG_ReadLittleLong(sb); // skipping over dispinfo and surfaceFogVolumeID, both short
+ for (i = 0;i < MAXLIGHTMAPS;i++)
+ surface->lightmapinfo->styles[i] = MSG_ReadByte(sb);
+ lightmapoffset = MSG_ReadLittleLong(sb);
+
+ // FIXME: validate edges, texinfo, etc?
+ if ((unsigned int) firstedge > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges || (unsigned int) firstedge + (unsigned int) numedges > (unsigned int) loadmodel->brushq1.numsurfedges)
+ Host_Error("Mod_VBSP_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)", firstedge, numedges, loadmodel->brushq1.numsurfedges);
+ if ((unsigned int) texinfoindex >= (unsigned int) loadmodel->brushq1.numtexinfo)
+ Host_Error("Mod_VBSP_LoadFaces: invalid texinfo index %i(model has %i texinfos)", texinfoindex, loadmodel->brushq1.numtexinfo);
+ if ((unsigned int) planenum >= (unsigned int) loadmodel->brush.num_planes)
+ Host_Error("Mod_VBSP_LoadFaces: invalid plane index %i (model has %i planes)", planenum, loadmodel->brush.num_planes);
+
+ surface->lightmapinfo->texinfo = loadmodel->brushq1.texinfo + texinfoindex;
+ surface->texture = loadmodel->data_textures + surface->lightmapinfo->texinfo->textureindex;
+
+ // Q2BSP doesn't use lightmaps on sky or warped surfaces (water), but still has a lightofs of 0
+ if (lightmapoffset == 0 && (surface->texture->q2flags & (Q2SURF_SKY | Q2SURF_WARP)))
+ lightmapoffset = -1;
+
+ //surface->flags = surface->texture->flags;
+ //if (LittleShort(in->side))
+ // surface->flags |= SURF_PLANEBACK;
+ //surface->plane = loadmodel->brush.data_planes + planenum;
+
+ surface->num_firstvertex = totalverts;
+ surface->num_vertices = numedges;
+ surface->num_firsttriangle = totaltris;
+ surface->num_triangles = numedges - 2;
+ totalverts += numedges;
+ totaltris += numedges - 2;
+
+ // convert edges back to a normal polygon
+ for (i = 0;i < surface->num_vertices;i++)
+ {
+ int lindex = loadmodel->brushq1.surfedges[firstedge + i];
+ float s, t;
+ // note: the q1bsp format does not allow a 0 surfedge (it would have no negative counterpart)
+ if (lindex >= 0)
+ VectorCopy(loadmodel->brushq1.vertexes[loadmodel->brushq1.edges[lindex].v[0]].position, (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3);
+ else
+ VectorCopy(loadmodel->brushq1.vertexes[loadmodel->brushq1.edges[-lindex].v[1]].position, (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3);
+ s = DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3];
+ t = DotProduct(((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3), surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3];
+ (loadmodel->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[i * 2 + 0] = s / surface->texture->width;
+ (loadmodel->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[i * 2 + 1] = t / surface->texture->height;
+ (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 0] = 0;
+ (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[i * 2 + 1] = 0;
+ (loadmodel->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i] = 0;
+ }
+
+ for (i = 0;i < surface->num_triangles;i++)
+ {
+ (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 0] = 0 + surface->num_firstvertex;
+ (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 1] = i + 1 + surface->num_firstvertex;
+ (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle)[i * 3 + 2] = i + 2 + surface->num_firstvertex;
+ }
+
+ // compile additional data about the surface geometry
+ Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
+ Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
+ BoxFromPoints(surface->mins, surface->maxs, surface->num_vertices, (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex));
+
+ // generate surface extents information
+ texmins[0] = texmaxs[0] = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3];
+ texmins[1] = texmaxs[1] = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3];
+ for (i = 1;i < surface->num_vertices;i++)
+ {
+ for (j = 0;j < 2;j++)
+ {
+ val = DotProduct((loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + i * 3, surface->lightmapinfo->texinfo->vecs[j]) + surface->lightmapinfo->texinfo->vecs[j][3];
+ texmins[j] = min(texmins[j], val);
+ texmaxs[j] = max(texmaxs[j], val);
+ }
+ }
+ for (i = 0;i < 2;i++)
+ {
+ surface->lightmapinfo->texturemins[i] = (int) floor(texmins[i] / 16.0) * 16;
+ surface->lightmapinfo->extents[i] = (int) ceil(texmaxs[i] / 16.0) * 16 - surface->lightmapinfo->texturemins[i];
+ }
+
+ smax = surface->lightmapinfo->extents[0] >> 4;
+ tmax = surface->lightmapinfo->extents[1] >> 4;
+ ssize = (surface->lightmapinfo->extents[0] >> 4) + 1;
+ tsize = (surface->lightmapinfo->extents[1] >> 4) + 1;