- mod->sortedmodelsurfaces = (int *)Mem_Alloc(loadmodel->mempool, mod->nummodelsurfaces * sizeof(*mod->sortedmodelsurfaces));
- Mod_MakeSortedSurfaces(mod);
-
- 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 = 0;j < mod->nummodelsurfaces;j++)
- {
- const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
- 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;
-
- // this gets altered below if sky or water is used
- mod->DrawSky = NULL;
- mod->DrawAddWaterPlanes = NULL;
-
- for (j = 0;j < mod->nummodelsurfaces;j++)
- if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_SKY)
- break;
- if (j < mod->nummodelsurfaces)
- mod->DrawSky = R_Q1BSP_DrawSky;
-
- for (j = 0;j < mod->nummodelsurfaces;j++)
- if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- break;
- if (j < mod->nummodelsurfaces)
- mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
-
- 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();
- }
-
- 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(dp_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);
-}
-
-void Mod_MAP_Load(dp_model_t *mod, void *buffer, void *bufferend)
-{
- Host_Error("Mod_MAP_Load: not yet implemented");
-}
-
-#define OBJASMODEL
-
-#ifdef OBJASMODEL
-typedef struct objvertex_s
-{
- int nextindex;
- int submodelindex;
- int textureindex;
- float v[3];
- float vt[2];
- float vn[3];
-}
-objvertex_t;
-
-static unsigned char nobsp_pvs[1] = {1};
-
-void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
-{
- const char *textbase = (char *)buffer, *text = textbase;
- char *s;
- char *argv[512];
- char line[1024];
- char materialname[MAX_QPATH];
- int i, j, l, numvertices, firstvertex, firsttriangle, elementindex, vertexindex, surfacevertices, surfacetriangles, surfaceelements, submodelindex = 0;
- int index1, index2, index3;
- objvertex_t vfirst, vprev, vcurrent;
- int argc;
- int linelen;
- int numtriangles = 0;
- int maxtriangles = 0;
- objvertex_t *vertices = NULL;
- int linenumber = 0;
- int maxtextures = 0, numtextures = 0, textureindex = 0;
- int maxv = 0, numv = 1;
- int maxvt = 0, numvt = 1;
- int maxvn = 0, numvn = 1;
- char *texturenames = NULL;
- float dist, modelradius, modelyawradius, yawradius;
- float *v = NULL;
- float *vt = NULL;
- float *vn = NULL;
- float mins[3];
- float maxs[3];
- float corner[3];
- objvertex_t *thisvertex = NULL;
- int vertexhashindex;
- int *vertexhashtable = NULL;
- objvertex_t *vertexhashdata = NULL;
- objvertex_t *vdata = NULL;
- int vertexhashsize = 0;
- int vertexhashcount = 0;
- skinfile_t *skinfiles = NULL;
- unsigned char *data = NULL;
- int *submodelfirstsurface;
- msurface_t *surface;
- msurface_t *tempsurfaces;
-
- memset(&vfirst, 0, sizeof(vfirst));
- memset(&vprev, 0, sizeof(vprev));
- memset(&vcurrent, 0, sizeof(vcurrent));
-
- dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
-
- loadmodel->modeldatatypestring = "OBJ";
-
- loadmodel->type = mod_obj;
- loadmodel->soundfromcenter = true;
- loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
- loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
- loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
- loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
- loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
- loadmodel->brush.TraceLineOfSight = NULL;
- loadmodel->brush.SuperContentsFromNativeContents = NULL;
- loadmodel->brush.NativeContentsFromSuperContents = NULL;
- loadmodel->brush.GetPVS = NULL;
- loadmodel->brush.FatPVS = NULL;
- loadmodel->brush.BoxTouchingPVS = NULL;
- loadmodel->brush.BoxTouchingLeafPVS = NULL;
- loadmodel->brush.BoxTouchingVisibleLeafs = NULL;
- loadmodel->brush.FindBoxClusters = NULL;
- loadmodel->brush.LightPoint = NULL;
- loadmodel->brush.FindNonSolidLocation = NULL;
- loadmodel->brush.AmbientSoundLevelsForPoint = NULL;
- loadmodel->brush.RoundUpToHullSize = NULL;
- loadmodel->brush.PointInLeaf = NULL;
- loadmodel->Draw = R_Q1BSP_Draw;
- loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
- loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
- loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
- loadmodel->GetLightInfo = R_Q1BSP_GetLightInfo;
- loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
- loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
- loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
- loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
- loadmodel->DrawLight = R_Q1BSP_DrawLight;
-
- skinfiles = Mod_LoadSkinFiles();
- if (loadmodel->numskins < 1)
- loadmodel->numskins = 1;
-
- // make skinscenes for the skins (no groups)
- loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
- for (i = 0;i < loadmodel->numskins;i++)
- {
- loadmodel->skinscenes[i].firstframe = i;
- loadmodel->skinscenes[i].framecount = 1;
- loadmodel->skinscenes[i].loop = true;
- loadmodel->skinscenes[i].framerate = 10;
- }
-
- VectorClear(mins);
- VectorClear(maxs);
-
- // parse the OBJ text now
- for(;;)
- {
- static char emptyarg[1] = "";
- if (!*text)
- break;
- linenumber++;
- linelen = 0;
- for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
- line[linelen] = text[linelen];
- line[linelen] = 0;
- for (argc = 0;argc < 4;argc++)
- argv[argc] = emptyarg;
- argc = 0;
- s = line;
- while (*s == ' ' || *s == '\t')
- s++;
- while (*s)
- {
- argv[argc++] = s;
- while (*s > ' ')
- s++;
- if (!*s)
- break;
- *s++ = 0;
- while (*s == ' ' || *s == '\t')
- s++;
- }
- text += linelen;
- if (*text == '\r')
- text++;
- if (*text == '\n')
- text++;
- if (!argc)
- continue;
- if (argv[0][0] == '#')
- continue;
- if (!strcmp(argv[0], "v"))
- {
- if (maxv <= numv)
- {
- maxv = max(maxv * 2, 1024);
- v = (float *)Mem_Realloc(tempmempool, v, maxv * sizeof(float[3]));
- }
- v[numv*3+0] = atof(argv[1]);
- v[numv*3+2] = atof(argv[2]);
- v[numv*3+1] = atof(argv[3]);
- numv++;
- }
- else if (!strcmp(argv[0], "vt"))
- {
- if (maxvt <= numvt)
- {
- maxvt = max(maxvt * 2, 1024);
- vt = (float *)Mem_Realloc(tempmempool, vt, maxvt * sizeof(float[2]));
- }
- vt[numvt*2+0] = atof(argv[1]);
- vt[numvt*2+1] = 1-atof(argv[2]);
- numvt++;
- }
- else if (!strcmp(argv[0], "vn"))
- {
- if (maxvn <= numvn)
- {
- maxvn = max(maxvn * 2, 1024);
- vn = (float *)Mem_Realloc(tempmempool, vn, maxvn * sizeof(float[3]));
- }
- vn[numvn*3+0] = atof(argv[1]);
- vn[numvn*3+2] = atof(argv[2]);
- vn[numvn*3+1] = atof(argv[3]);
- numvn++;
- }
- else if (!strcmp(argv[0], "f"))
- {
- if (!numtextures)
- {
- if (maxtextures <= numtextures)
- {
- maxtextures = max(maxtextures * 2, 256);
- texturenames = (char *)Mem_Realloc(loadmodel->mempool, texturenames, maxtextures * MAX_QPATH);
- }
- textureindex = numtextures++;
- strlcpy(texturenames + textureindex*MAX_QPATH, loadmodel->name, MAX_QPATH);
- }
- for (j = 1;j < argc;j++)
- {
- index1 = atoi(argv[j]);
- while(argv[j][0] && argv[j][0] != '/')
- argv[j]++;
- if (argv[j][0])
- argv[j]++;
- index2 = atoi(argv[j]);
- while(argv[j][0] && argv[j][0] != '/')
- argv[j]++;
- if (argv[j][0])
- argv[j]++;
- index3 = atoi(argv[j]);
- // negative refers to a recent vertex
- // zero means not specified
- // positive means an absolute vertex index
- if (index1 < 0)
- index1 = numv - index1;
- if (index2 < 0)
- index2 = numvt - index2;
- if (index3 < 0)
- index3 = numvn - index3;
- vcurrent.nextindex = -1;
- vcurrent.textureindex = textureindex;
- vcurrent.submodelindex = submodelindex;
- VectorCopy(v + 3*index1, vcurrent.v);
- Vector2Copy(vt + 2*index2, vcurrent.vt);
- VectorCopy(vn + 3*index3, vcurrent.vn);
- if (numtriangles == 0)
- {
- VectorCopy(vcurrent.v, mins);
- VectorCopy(vcurrent.v, maxs);
- }
- else
- {
- mins[0] = min(mins[0], vcurrent.v[0]);
- mins[1] = min(mins[1], vcurrent.v[1]);
- mins[2] = min(mins[2], vcurrent.v[2]);
- maxs[0] = max(maxs[0], vcurrent.v[0]);
- maxs[1] = max(maxs[1], vcurrent.v[1]);
- maxs[2] = max(maxs[2], vcurrent.v[2]);
- }
- if (j == 1)
- vfirst = vcurrent;
- else if (j >= 3)
- {
- if (maxtriangles <= numtriangles)
- {
- maxtriangles = max(maxtriangles * 2, 32768);
- vertices = (objvertex_t*)Mem_Realloc(loadmodel->mempool, vertices, maxtriangles * sizeof(objvertex_t[3]));
- }
- vertices[numtriangles*3+0] = vfirst;
- vertices[numtriangles*3+1] = vprev;
- vertices[numtriangles*3+2] = vcurrent;
- numtriangles++;
- }
- vprev = vcurrent;
- }
- }
- else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
- {
- submodelindex = atof(argv[1]);
- loadmodel->brush.numsubmodels = max(submodelindex + 1, loadmodel->brush.numsubmodels);
- }
- else if (!strcmp(argv[0], "usemtl"))
- {
- for (i = 0;i < numtextures;i++)
- if (!strcmp(texturenames+i*MAX_QPATH, argv[1]))
- break;
- if (i < numtextures)
- textureindex = i;
- else
- {
- if (maxtextures <= numtextures)
- {
- maxtextures = max(maxtextures * 2, 256);
- texturenames = (char *)Mem_Realloc(loadmodel->mempool, texturenames, maxtextures * MAX_QPATH);
- }
- textureindex = numtextures++;
- strlcpy(texturenames + textureindex*MAX_QPATH, argv[1], MAX_QPATH);
- }
- }
- }
-
- // now that we have the OBJ data loaded as-is, we can convert it
-
- // copy the model bounds, then enlarge the yaw and rotated bounds according to radius
- VectorCopy(mins, loadmodel->normalmins);
- VectorCopy(maxs, loadmodel->normalmaxs);
- dist = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
- modelyawradius = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
- modelyawradius = dist*dist+modelyawradius*modelyawradius;
- modelradius = max(fabs(loadmodel->normalmins[2]), fabs(loadmodel->normalmaxs[2]));
- modelradius = modelyawradius + modelradius * modelradius;
- modelyawradius = sqrt(modelyawradius);
- modelradius = sqrt(modelradius);
- loadmodel->yawmins[0] = loadmodel->yawmins[1] = -modelyawradius;
- loadmodel->yawmins[2] = loadmodel->normalmins[2];
- loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelyawradius;
- loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
- loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -modelradius;
- loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = modelradius;
- loadmodel->radius = modelradius;
- loadmodel->radius2 = modelradius * modelradius;
-
- // allocate storage for triangles
- loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, numtriangles * sizeof(int[3]));
- // allocate vertex hash structures to build an optimal vertex subset
- vertexhashsize = numtriangles*2;
- vertexhashtable = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int) * vertexhashsize);
- memset(vertexhashtable, 0xFF, sizeof(int) * vertexhashsize);
- vertexhashdata = (objvertex_t *)Mem_Alloc(loadmodel->mempool, sizeof(*vertexhashdata) * numtriangles*3);
- vertexhashcount = 0;
-
- // gather surface stats for assigning vertex/triangle ranges
- firstvertex = 0;
- firsttriangle = 0;
- elementindex = 0;
- loadmodel->num_surfaces = 0;
- // allocate storage for the worst case number of surfaces, later we resize
- tempsurfaces = (msurface_t *)Mem_Alloc(loadmodel->mempool, numtextures * loadmodel->brush.numsubmodels * sizeof(msurface_t));
- submodelfirstsurface = (int *)Mem_Alloc(loadmodel->mempool, (loadmodel->brush.numsubmodels+1) * sizeof(int));
- surface = tempsurfaces;
- for (submodelindex = 0;submodelindex < loadmodel->brush.numsubmodels;submodelindex++)
- {
- submodelfirstsurface[submodelindex] = loadmodel->num_surfaces;
- for (textureindex = 0;textureindex < numtextures;textureindex++)
- {
- for (vertexindex = 0;vertexindex < numtriangles*3;vertexindex++)
- {
- thisvertex = vertices + vertexindex;
- if (thisvertex->submodelindex == submodelindex && thisvertex->textureindex == textureindex)
- break;
- }
- // skip the surface creation if there are no triangles for it
- if (vertexindex == numtriangles*3)
- continue;
- // create a surface for these vertices
- surfacevertices = 0;
- surfaceelements = 0;
- // we hack in a texture index in the surface to be fixed up later...
- surface->texture = (texture_t *)((size_t)textureindex);
- // calculate bounds as we go
- VectorCopy(thisvertex->v, surface->mins);
- VectorCopy(thisvertex->v, surface->maxs);
- for (;vertexindex < numtriangles*3;vertexindex++)
- {
- thisvertex = vertices + vertexindex;
- if (thisvertex->submodelindex != submodelindex)
- continue;
- if (thisvertex->textureindex != textureindex)
- continue;
- // add vertex to surface bounds
- surface->mins[0] = min(surface->mins[0], thisvertex->v[0]);
- surface->mins[1] = min(surface->mins[1], thisvertex->v[1]);
- surface->mins[2] = min(surface->mins[2], thisvertex->v[2]);
- surface->maxs[0] = max(surface->maxs[0], thisvertex->v[0]);
- surface->maxs[1] = max(surface->maxs[1], thisvertex->v[1]);
- surface->maxs[2] = max(surface->maxs[2], thisvertex->v[2]);
- // add the vertex if it is not found in the merged set, and
- // get its index (triangle element) for the surface
- vertexhashindex = (unsigned int)(thisvertex->v[0] * 3571 + thisvertex->v[0] * 1777 + thisvertex->v[0] * 457) % (unsigned int)vertexhashsize;
- for (i = vertexhashtable[vertexhashindex];i >= 0;i = vertexhashdata[i].nextindex)
- {
- vdata = vertexhashdata + i;
- if (vdata->submodelindex == thisvertex->submodelindex && vdata->textureindex == thisvertex->textureindex && VectorCompare(thisvertex->v, vdata->v) && VectorCompare(thisvertex->vn, vdata->vn) && Vector2Compare(thisvertex->vt, vdata->vt))
- break;
- }
- if (i < 0)
- {
- i = vertexhashcount++;
- vdata = vertexhashdata + i;
- *vdata = *thisvertex;
- vdata->nextindex = vertexhashtable[vertexhashindex];
- vertexhashtable[vertexhashindex] = i;
- surfacevertices++;
- }
- loadmodel->surfmesh.data_element3i[elementindex++] = i;
- surfaceelements++;
- }
- surfacetriangles = surfaceelements / 3;
- surface->num_vertices = surfacevertices;
- surface->num_triangles = surfacetriangles;
- surface->num_firstvertex = firstvertex;
- surface->num_firsttriangle = firsttriangle;
- firstvertex += surface->num_vertices;
- firsttriangle += surface->num_triangles;
- surface++;
- loadmodel->num_surfaces++;
- }
- }
- submodelfirstsurface[submodelindex] = loadmodel->num_surfaces;
- numvertices = firstvertex;
- loadmodel->data_surfaces = (msurface_t *)Mem_Realloc(loadmodel->mempool, tempsurfaces, loadmodel->num_surfaces * sizeof(msurface_t));
- tempsurfaces = NULL;
-
- // allocate storage for final mesh data
- loadmodel->num_textures = numtextures * loadmodel->numskins;
- loadmodel->num_texturesperskin = numtextures;
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + numtriangles * sizeof(int[3]) + (numvertices <= 65536 ? numtriangles * sizeof(unsigned short[3]) : 0) + numvertices * sizeof(float[14]) + loadmodel->brush.numsubmodels * sizeof(dp_model_t *));
- loadmodel->brush.submodels = (dp_model_t **)data;data += loadmodel->brush.numsubmodels * sizeof(dp_model_t *);
- loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
- loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
- loadmodel->surfmesh.num_vertices = numvertices;
- loadmodel->surfmesh.num_triangles = numtriangles;
- loadmodel->surfmesh.data_neighbor3i = (int *)data;data += numtriangles * sizeof(int[3]);
- loadmodel->surfmesh.data_vertex3f = (float *)data;data += numvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_svector3f = (float *)data;data += numvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_tvector3f = (float *)data;data += numvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_normal3f = (float *)data;data += numvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += numvertices * sizeof(float[2]);
- if (loadmodel->surfmesh.num_vertices <= 65536)
- loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
-
- for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
- {
- VectorCopy(vertexhashdata[j].v, loadmodel->surfmesh.data_vertex3f + 3*j);
- VectorCopy(vertexhashdata[j].vn, loadmodel->surfmesh.data_normal3f + 3*j);
- Vector2Copy(vertexhashdata[j].vt, loadmodel->surfmesh.data_texcoordtexture2f + 2*j);
- }
-
- // load the textures
- for (textureindex = 0;textureindex < numtextures;textureindex++)
- Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + textureindex, skinfiles, texturenames + textureindex*MAX_QPATH, texturenames + textureindex*MAX_QPATH);
- Mod_FreeSkinFiles(skinfiles);
-
- // set the surface textures to their real values now that we loaded them...
- for (i = 0;i < loadmodel->num_surfaces;i++)
- loadmodel->data_surfaces[i].texture = loadmodel->data_textures + (size_t)loadmodel->data_surfaces[i].texture;
-
- // free data
- Mem_Free(vertices);
- Mem_Free(texturenames);
- Mem_Free(v);
- Mem_Free(vt);
- Mem_Free(vn);
- Mem_Free(vertexhashtable);
- Mem_Free(vertexhashdata);
-
- // make a single combined shadow mesh to allow optimized shadow volume creation
- Mod_Q1BSP_CreateShadowMesh(loadmodel);
-
- // compute all the mesh information that was not loaded from the file
- if (loadmodel->surfmesh.data_element3s)
- for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
- loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
- Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
- // generate normals if the file did not have them
- if (!VectorLength2(loadmodel->surfmesh.data_normal3f))
- Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
- Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
- Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
-
- // if this is a worldmodel and has no BSP tree, create a fake one for the purpose
- loadmodel->brush.num_visleafs = 1;
- loadmodel->brush.num_leafs = 1;
- loadmodel->brush.num_nodes = 0;
- loadmodel->brush.num_leafsurfaces = loadmodel->num_surfaces;
- loadmodel->brush.data_leafs = (mleaf_t *)Mem_Alloc(loadmodel->mempool, loadmodel->brush.num_leafs * sizeof(mleaf_t));
- loadmodel->brush.data_nodes = (mnode_t *)loadmodel->brush.data_leafs;
- loadmodel->brush.num_pvsclusters = 1;
- loadmodel->brush.num_pvsclusterbytes = 1;
- loadmodel->brush.data_pvsclusters = nobsp_pvs;
- //if (loadmodel->num_nodes) loadmodel->data_nodes = (mnode_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_nodes * sizeof(mnode_t));
- //loadmodel->data_leafsurfaces = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->num_leafsurfaces * sizeof(int));
- loadmodel->brush.data_leafsurfaces = loadmodel->sortedmodelsurfaces;
- VectorCopy(loadmodel->normalmins, loadmodel->brush.data_leafs->mins);
- VectorCopy(loadmodel->normalmaxs, loadmodel->brush.data_leafs->maxs);
- loadmodel->brush.data_leafs->combinedsupercontents = 0; // FIXME?
- loadmodel->brush.data_leafs->clusterindex = 0;
- loadmodel->brush.data_leafs->areaindex = 0;
- loadmodel->brush.data_leafs->numleafsurfaces = loadmodel->brush.num_leafsurfaces;
- loadmodel->brush.data_leafs->firstleafsurface = loadmodel->brush.data_leafsurfaces;
- loadmodel->brush.data_leafs->numleafbrushes = 0;
- loadmodel->brush.data_leafs->firstleafbrush = NULL;
- loadmodel->brush.supportwateralpha = true;
-
- if (loadmodel->brush.numsubmodels)
- loadmodel->brush.submodels = (dp_model_t **)Mem_Alloc(loadmodel->mempool, loadmodel->brush.numsubmodels * sizeof(dp_model_t *));
-
- mod = loadmodel;
- 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;