]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_shared.c
prevent creation of a cvar named "", as that breaks cvar()
[xonotic/darkplaces.git] / model_shared.c
index 653c715c70cbea9157dfba5ba47f7def3ed1f1e5..6ea5a859889fd9dd68b48a6686907b446259baee 100644 (file)
@@ -91,21 +91,23 @@ static void mod_newmap(void)
        int nummodels = Mem_ExpandableArray_IndexRange(&models);
        dp_model_t *mod;
 
-       R_SkinFrame_PrepareForPurge();
        for (i = 0;i < nummodels;i++)
        {
-               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool && mod->data_textures)
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool)
                {
-                       for (j = 0;j < mod->num_textures;j++)
+                       for (j = 0;j < mod->num_textures && mod->data_textures;j++)
                        {
                                for (k = 0;k < mod->data_textures[j].numskinframes;k++)
                                        R_SkinFrame_MarkUsed(mod->data_textures[j].skinframes[k]);
                                for (k = 0;k < mod->data_textures[j].backgroundnumskinframes;k++)
                                        R_SkinFrame_MarkUsed(mod->data_textures[j].backgroundskinframes[k]);
                        }
+                       if (mod->brush.solidskyskinframe)
+                               R_SkinFrame_MarkUsed(mod->brush.solidskyskinframe);
+                       if (mod->brush.alphaskyskinframe)
+                               R_SkinFrame_MarkUsed(mod->brush.alphaskyskinframe);
                }
        }
-       R_SkinFrame_Purge();
 
        if (!cl_stainmaps_clearonload.integer)
                return;
@@ -1254,6 +1256,35 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh)
        }
 }
 
+void Mod_CreateCollisionMesh(dp_model_t *mod)
+{
+       int k;
+       int numcollisionmeshtriangles;
+       const msurface_t *surface;
+       mempool_t *mempool = mod->mempool;
+       if (!mempool && mod->brush.parentmodel)
+               mempool = mod->brush.parentmodel->mempool;
+       // make a single combined collision mesh for physics engine use
+       // TODO rewrite this to use the collision brushes as source, to fix issues with e.g. common/caulk which creates no drawsurface
+       numcollisionmeshtriangles = 0;
+       for (k = 0;k < mod->nummodelsurfaces;k++)
+       {
+               surface = mod->data_surfaces + mod->firstmodelsurface + k;
+               if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID))
+                       continue;
+               numcollisionmeshtriangles += surface->num_triangles;
+       }
+       mod->brush.collisionmesh = Mod_ShadowMesh_Begin(mempool, numcollisionmeshtriangles * 3, numcollisionmeshtriangles, NULL, NULL, NULL, false, false, true);
+       for (k = 0;k < mod->nummodelsurfaces;k++)
+       {
+               surface = mod->data_surfaces + mod->firstmodelsurface + k;
+               if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID))
+                       continue;
+               Mod_ShadowMesh_AddMesh(mempool, mod->brush.collisionmesh, NULL, NULL, NULL, mod->surfmesh.data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
+       }
+       mod->brush.collisionmesh = Mod_ShadowMesh_Finish(mempool, mod->brush.collisionmesh, false, true, false);
+}
+
 void Mod_GetTerrainVertex3fTexCoord2fFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
 {
        float v[3], tc[3];
@@ -1317,6 +1348,86 @@ void Mod_ConstructTerrainPatchFromBGRA(const unsigned char *imagepixels, int ima
                        Mod_GetTerrainVertexFromBGRA(imagepixels, imagewidth, imageheight, ix, iy, vertex3f, texcoord2f, svector3f, tvector3f, normal3f, pixelstepmatrix, pixeltexturestepmatrix);
 }
 
+#if 0
+void Mod_Terrain_SurfaceRecurseChunk(dp_model_t *model, int stepsize, int x, int y)
+{
+       float mins[3];
+       float maxs[3];
+       float chunkwidth = min(stepsize, model->terrain.width - 1 - x);
+       float chunkheight = min(stepsize, model->terrain.height - 1 - y);
+       float viewvector[3];
+       unsigned int firstvertex;
+       unsigned int *e;
+       float *v;
+       if (chunkwidth < 2 || chunkheight < 2)
+               return;
+       VectorSet(mins, model->terrain.mins[0] +  x    * stepsize * model->terrain.scale[0], model->terrain.mins[1] +  y    * stepsize * model->terrain.scale[1], model->terrain.mins[2]);
+       VectorSet(maxs, model->terrain.mins[0] + (x+1) * stepsize * model->terrain.scale[0], model->terrain.mins[1] + (y+1) * stepsize * model->terrain.scale[1], model->terrain.maxs[2]);
+       viewvector[0] = bound(mins[0], localvieworigin, maxs[0]) - model->terrain.vieworigin[0];
+       viewvector[1] = bound(mins[1], localvieworigin, maxs[1]) - model->terrain.vieworigin[1];
+       viewvector[2] = bound(mins[2], localvieworigin, maxs[2]) - model->terrain.vieworigin[2];
+       if (stepsize > 1 && VectorLength(viewvector) < stepsize*model->terrain.scale[0]*r_terrain_lodscale.value)
+       {
+               // too close for this stepsize, emit as 4 chunks instead
+               stepsize /= 2;
+               Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x, y);
+               Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x+stepsize, y);
+               Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x, y+stepsize);
+               Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x+stepsize, y+stepsize);
+               return;
+       }
+       // emit the geometry at stepsize into our vertex buffer / index buffer
+       // we add two columns and two rows for skirt
+       outwidth = chunkwidth+2;
+       outheight = chunkheight+2;
+       outwidth2 = outwidth-1;
+       outheight2 = outheight-1;
+       outwidth3 = outwidth+1;
+       outheight3 = outheight+1;
+       firstvertex = numvertices;
+       e = model->terrain.element3i + numtriangles;
+       numtriangles += chunkwidth*chunkheight*2+chunkwidth*2*2+chunkheight*2*2;
+       v = model->terrain.vertex3f + numvertices;
+       numvertices += (chunkwidth+1)*(chunkheight+1)+(chunkwidth+1)*2+(chunkheight+1)*2;
+       // emit the triangles (note: the skirt is treated as two extra rows and two extra columns)
+       for (ty = 0;ty < outheight;ty++)
+       {
+               for (tx = 0;tx < outwidth;tx++)
+               {
+                       *e++ = firstvertex + (ty  )*outwidth3+(tx  );
+                       *e++ = firstvertex + (ty  )*outwidth3+(tx+1);
+                       *e++ = firstvertex + (ty+1)*outwidth3+(tx+1);
+                       *e++ = firstvertex + (ty  )*outwidth3+(tx  );
+                       *e++ = firstvertex + (ty+1)*outwidth3+(tx+1);
+                       *e++ = firstvertex + (ty+1)*outwidth3+(tx  );
+               }
+       }
+       // TODO: emit surface vertices (x+tx*stepsize, y+ty*stepsize)
+       for (ty = 0;ty <= outheight;ty++)
+       {
+               skirtrow = ty == 0 || ty == outheight;
+               ry = y+bound(1, ty, outheight)*stepsize;
+               for (tx = 0;tx <= outwidth;tx++)
+               {
+                       skirt = skirtrow || tx == 0 || tx == outwidth;
+                       rx = x+bound(1, tx, outwidth)*stepsize;
+                       v[0] = rx*scale[0];
+                       v[1] = ry*scale[1];
+                       v[2] = heightmap[ry*terrainwidth+rx]*scale[2];
+                       v += 3;
+               }
+       }
+       // TODO: emit skirt vertices
+}
+
+void Mod_Terrain_UpdateSurfacesForViewOrigin(dp_model_t *model)
+{
+       for (y = 0;y < model->terrain.size[1];y += model->terrain.
+       Mod_Terrain_SurfaceRecurseChunk(model, model->terrain.maxstepsize, x, y);
+       Mod_Terrain_BuildChunk(model, 
+}
+#endif
+
 q3wavefunc_t Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s)
 {
        if (!strcasecmp(s, "sin"))             return Q3WAVEFUNC_SIN;
@@ -2426,13 +2537,14 @@ static void Mod_Decompile_OBJ(dp_model_t *model, const char *filename, const cha
                countvertices += surface->num_vertices;
                countfaces += surface->num_triangles;
                texname = (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default";
-               for (textureindex = 0;textureindex < maxtextures && texturenames[textureindex*MAX_QPATH];textureindex++)
+               for (textureindex = 0;textureindex < counttextures;textureindex++)
                        if (!strcmp(texturenames + textureindex * MAX_QPATH, texname))
                                break;
+               if (textureindex < counttextures)
+                       continue; // already wrote this material entry
                if (textureindex >= maxtextures)
                        continue; // just a precaution
-               if (counttextures < textureindex + 1)
-                       counttextures = textureindex + 1;
+               textureindex = counttextures++;
                strlcpy(texturenames + textureindex * MAX_QPATH, texname, MAX_QPATH);
                if (outbufferpos >= outbuffermax >> 1)
                {