]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_shared.c
Renamed mod_brush to mod_brushq1.
[xonotic/darkplaces.git] / model_shared.c
index 369802d5a76536b3eff49993dddc6f97ab2d8039..3420ae5901766b22f1c839d70ca1e796d546f7b2 100644 (file)
@@ -194,6 +194,34 @@ static void mod_shutdown(void)
 
 static void mod_newmap(void)
 {
+       msurface_t *surf;
+       int i, surfnum, ssize, tsize;
+
+       if (!cl_stainmapsclearonload.integer)
+               return;
+
+       for (i=0; i<MAX_MOD_KNOWN; i++)
+       {
+               if (mod_known[i].name[0] && mod_known[i].type == mod_brushq1)
+               {
+                       for (surfnum=0, surf=mod_known[i].brushq1.surfaces; surfnum<mod_known[i].brushq1.numsurfaces;surfnum++, surf++)
+                       {
+                               if (surf->texinfo->texture->flags & SURF_LIGHTMAP)
+                               {
+                                       ssize = (surf->extents[0] >> 4) + 1;
+                                       tsize = (surf->extents[1] >> 4) + 1;
+                                       
+                                       if (ssize > 256 || tsize > 256)
+                                               Host_Error("Bad surface extents");
+
+                                       if (surf->stainsamples)
+                                               memset(surf->stainsamples, 255, ssize * tsize * 3);
+
+                                       surf->cached_dlight = true;
+                               }
+                       }
+               }
+       }
 }
 
 /*
@@ -297,7 +325,7 @@ static model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk,
        VectorSet(mod->rotatedmaxs, mod->radius, mod->radius, mod->radius);
 
        // all models use memory, so allocate a memory pool
-       mod->mempool = Mem_AllocPool(mod->name);
+       mod->mempool = Mem_AllocPool(mod->name, 0, NULL);
        // all models load textures, so allocate a texture pool
        if (cls.state != ca_dedicated)
                mod->texturepool = R_AllocTexturePool();
@@ -489,6 +517,20 @@ static void Mod_Precache(void)
                Con_Print("usage: modelprecache <filename>\n");
 }
 
+int Mod_BuildVertexRemapTableFromElements(int numelements, const int *elements, int numvertices, int *remapvertices)
+{
+       int i, count;
+       qbyte *used;
+       used = Mem_Alloc(tempmempool, numvertices);
+       memset(used, 0, numvertices);
+       for (i = 0;i < numelements;i++)
+               used[elements[i]] = 1;
+       for (i = 0, count = 0;i < numvertices;i++)
+               remapvertices[i] = used[i] ? count++ : -1;
+       Mem_Free(used);
+       return count;
+}
+
 #if 1
 // fast way, using an edge hash
 #define TRIANGLEEDGEHASH 1024
@@ -608,24 +650,50 @@ void Mod_ValidateElements(const int *elements, int numtriangles, int numverts, c
 
 void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f, float *normal3f)
 {
-       float f;
-       normal3f[0] = (v1[1] - v0[1]) * (v2[2] - v0[2]) - (v1[2] - v0[2]) * (v2[1] - v0[1]);
-       normal3f[1] = (v1[2] - v0[2]) * (v2[0] - v0[0]) - (v1[0] - v0[0]) * (v2[2] - v0[2]);
-       normal3f[2] = (v1[0] - v0[0]) * (v2[1] - v0[1]) - (v1[1] - v0[1]) * (v2[0] - v0[0]);
+       float f, tangentcross[3], v10[3], v20[3], tc10[2], tc20[2];
+       // 103 add/sub/negate/multiply (1 cycle), 3 divide (20 cycle), 3 sqrt (22 cycle), 4 compare (3 cycle?), total cycles not counting load/store/exchange roughly 241 cycles
+       // 12 add, 28 subtract, 57 multiply, 3 divide, 3 sqrt, 4 compare, 50% chance of 6 negates
+
+       // 18 multiply, 19 subtract
+       VectorSubtract(v1, v0, v10);
+       VectorSubtract(v2, v0, v20);
+       normal3f[0] = v10[1] * v20[2] - v10[2] * v20[1];
+       normal3f[1] = v10[2] * v20[0] - v10[0] * v20[2];
+       normal3f[2] = v10[0] * v20[1] - v10[1] * v20[0];
+       tc10[1] = tc1[1] - tc0[1];
+       tc20[1] = tc2[1] - tc0[1];
+       svector3f[0] = tc10[1] * v20[0] - tc20[1] * v10[0];
+       svector3f[1] = tc10[1] * v20[1] - tc20[1] * v10[1];
+       svector3f[2] = tc10[1] * v20[2] - tc20[1] * v10[2];
+       tc10[0] = tc1[0] - tc0[0];
+       tc20[0] = tc2[0] - tc0[0];
+       tvector3f[0] = tc10[0] * v20[0] - tc20[0] * v10[0];
+       tvector3f[1] = tc10[0] * v20[1] - tc20[0] * v10[1];
+       tvector3f[2] = tc10[0] * v20[2] - tc20[0] * v10[2];
+       // 1 sqrt, 1 divide, 6 multiply, 2 add, 1 compare
        VectorNormalize(normal3f);
-       tvector3f[0] = ((tc1[0] - tc0[0]) * (v2[0] - v0[0]) - (tc2[0] - tc0[0]) * (v1[0] - v0[0]));
-       tvector3f[1] = ((tc1[0] - tc0[0]) * (v2[1] - v0[1]) - (tc2[0] - tc0[0]) * (v1[1] - v0[1]));
-       tvector3f[2] = ((tc1[0] - tc0[0]) * (v2[2] - v0[2]) - (tc2[0] - tc0[0]) * (v1[2] - v0[2]));
-       f = -DotProduct(tvector3f, normal3f);
-       VectorMA(tvector3f, f, normal3f, tvector3f);
-       VectorNormalize(tvector3f);
-       // note: can't be a CrossProduct as that sometimes flips the texture
-       svector3f[0] = ((tc1[1] - tc0[1]) * (v2[0] - v0[0]) - (tc2[1] - tc0[1]) * (v1[0] - v0[0]));
-       svector3f[1] = ((tc1[1] - tc0[1]) * (v2[1] - v0[1]) - (tc2[1] - tc0[1]) * (v1[1] - v0[1]));
-       svector3f[2] = ((tc1[1] - tc0[1]) * (v2[2] - v0[2]) - (tc2[1] - tc0[1]) * (v1[2] - v0[2]));
-       f = -DotProduct(svector3f, normal3f);
-       VectorMA(svector3f, f, normal3f, svector3f);
+       // 12 multiply, 4 add, 6 subtract
+       f = DotProduct(svector3f, normal3f);
+       svector3f[0] -= f * normal3f[0];
+       svector3f[1] -= f * normal3f[1];
+       svector3f[2] -= f * normal3f[2];
+       f = DotProduct(tvector3f, normal3f);
+       tvector3f[0] -= f * normal3f[0];
+       tvector3f[1] -= f * normal3f[1];
+       tvector3f[2] -= f * normal3f[2];
+       // 2 sqrt, 2 divide, 12 multiply, 4 add, 2 compare
        VectorNormalize(svector3f);
+       VectorNormalize(tvector3f);
+       // if texture is mapped the wrong way (counterclockwise), the tangents
+       // have to be flipped, this is detected by calculating a normal from the
+       // two tangents, and seeing if it is opposite the surface normal
+       // 9 multiply, 2 add, 3 subtract, 1 compare, 50% chance of: 6 negates
+       CrossProduct(tvector3f, svector3f, tangentcross);
+       if (DotProduct(tangentcross, normal3f) < 0)
+       {
+               VectorNegate(svector3f, svector3f);
+               VectorNegate(tvector3f, tvector3f);
+       }
 }
 
 // warning: this is an expensive function!
@@ -1078,7 +1146,7 @@ skinfile_t *Mod_LoadSkinFiles(void)
        int i, words, numtags, line, tagsetsused = false, wordsoverflow;
        char *text;
        const char *data;
-       skinfile_t *skinfile, *first = NULL;
+       skinfile_t *skinfile = NULL, *first = NULL;
        skinfileitem_t *skinfileitem;
        char word[10][MAX_QPATH];
        overridetagnameset_t tagsets[MAX_SKINS];
@@ -1104,9 +1172,20 @@ tag_torso,
        for (i = 0;i < MAX_SKINS && (data = text = FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true));i++)
        {
                numtags = 0;
-               skinfile = Mem_Alloc(tempmempool, sizeof(skinfile_t));
-               skinfile->next = first;
-               first = skinfile;
+
+               // If it's the first file we parse
+               if (skinfile == NULL)
+               {
+                       skinfile = Mem_Alloc(tempmempool, sizeof(skinfile_t));
+                       first = skinfile;
+               }
+               else
+               {
+                       skinfile->next = Mem_Alloc(tempmempool, sizeof(skinfile_t));
+                       skinfile = skinfile->next;
+               }
+               skinfile->next = NULL;
+
                for(line = 0;;line++)
                {
                        // parse line