]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_shared.c
removed detail texturing (it only worked in q1bsp and hlbsp maps, did not work proper...
[xonotic/darkplaces.git] / model_shared.c
index bcc813aaa08fc64e78c9fe6368fc283d319beda3..40967880f6238a691c0d54c1cc108bc19ed61809 100644 (file)
@@ -63,7 +63,7 @@ static void mod_newmap(void)
        {
                if (mod_known[i].name[0])
                {
-                       for (surfacenum = 0, surface = mod_known[i].brush.data_surfaces;surfacenum < mod_known[i].brush.num_surfaces;surfacenum++, surface++)
+                       for (surfacenum = 0, surface = mod_known[i].data_surfaces;surfacenum < mod_known[i].num_surfaces;surfacenum++, surface++)
                        {
                                if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
                                {
@@ -131,7 +131,7 @@ Mod_LoadModel
 Loads a model
 ==================
 */
-static model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolean isworldmodel)
+model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolean isworldmodel)
 {
        int num;
        unsigned int crc;
@@ -189,19 +189,23 @@ static model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk,
 
        if (buf)
        {
+               char *bufend = (char *)buf + fs_filesize;
                num = LittleLong(*((int *)buf));
                // call the apropriate loader
                loadmodel = mod;
-                    if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf);
-               else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf);
-               else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf);
-               else if (!memcmp(buf, "IDSP", 4)) Mod_IDSP_Load(mod, buf);
-               else if (!memcmp(buf, "IDS2", 4)) Mod_IDS2_Load(mod, buf);
-               else if (!memcmp(buf, "IBSP", 4)) Mod_IBSP_Load(mod, buf);
-               else if (!memcmp(buf, "ZYMOTICMODEL", 12)) Mod_ZYMOTICMODEL_Load(mod, buf);
-               else if (strlen(mod->name) >= 4 && !strcmp(mod->name - 4, ".map")) Mod_MAP_Load(mod, buf);
-               else if (num == BSPVERSION || num == 30) Mod_Q1BSP_Load(mod, buf);
-               else Host_Error("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
+                    if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "IDSP", 4)) Mod_IDSP_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "IDS2", 4)) Mod_IDS2_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "IBSP", 4)) Mod_IBSP_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "ZYMOTICMODEL", 12)) Mod_ZYMOTICMODEL_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "DARKPLACESMODEL", 16)) Mod_DARKPLACESMODEL_Load(mod, buf, bufend);
+               else if (!strcmp(buf, "ACTRHEAD")) Mod_PSKMODEL_Load(mod, buf, bufend);
+               else if (strlen(mod->name) >= 4 && !strcmp(mod->name - 4, ".map")) Mod_MAP_Load(mod, buf, bufend);
+               else if (!memcmp(buf, "MCBSP", 5)) Mod_Q1BSP_Load(mod, buf, bufend);
+               else if (num == BSPVERSION || num == 30) Mod_Q1BSP_Load(mod, buf, bufend);
+               else Con_Printf("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
                Mem_Free(buf);
        }
        else if (crash)
@@ -215,22 +219,6 @@ static model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk,
        return mod;
 }
 
-void Mod_CheckLoaded(model_t *mod)
-{
-       if (mod)
-       {
-               if (!mod->loaded)
-                       Mod_LoadModel(mod, true, true, mod->isworldmodel);
-               else
-               {
-                       //if (mod->type == mod_invalid)
-                       //      Host_Error("Mod_CheckLoaded: invalid model\n");
-                       mod->used = true;
-                       return;
-               }
-       }
-}
-
 /*
 ===================
 Mod_ClearAll
@@ -386,7 +374,7 @@ int Mod_BuildVertexRemapTableFromElements(int numelements, const int *elements,
 
 #if 1
 // fast way, using an edge hash
-#define TRIANGLEEDGEHASH 16384
+#define TRIANGLEEDGEHASH 8192
 void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtriangles)
 {
        int i, j, p, e1, e2, *n, hashindex, count, match;
@@ -493,51 +481,69 @@ void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtria
 }
 #endif
 
-void Mod_ValidateElements(const int *elements, int numtriangles, int numverts, const char *filename, int fileline)
+void Mod_ValidateElements(int *elements, int numtriangles, int numverts, const char *filename, int fileline)
 {
-       int i;
+       int i, warned = false;
        for (i = 0;i < numtriangles * 3;i++)
+       {
                if ((unsigned int)elements[i] >= (unsigned int)numverts)
-                       Con_Printf("Mod_ValidateElements: out of bounds element detected at %s:%d\n", filename, fileline);
+               {
+                       if (!warned)
+                       {
+                               warned = true;
+                               Con_Printf("Mod_ValidateElements: out of bounds elements detected at %s:%d\n", filename, fileline);
+                       }
+                       elements[i] = 0;
+               }
+       }
 }
 
 // warning: this is an expensive function!
-void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f)
+void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qboolean areaweighting)
 {
-       int i, tnum;
-       float normal[3], *v;
-       const int *e;
+       int i, j;
+       const int *element;
+       float *vectorNormal;
+       float areaNormal[3];
        // clear the vectors
        memset(normal3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
        // process each vertex of each triangle and accumulate the results
-       for (tnum = 0, e = elements;tnum < numtriangles;tnum++, e += 3)
+       // use area-averaging, to make triangles with a big area have a bigger
+       // weighting on the vertex normal than triangles with a small area
+       // to do so, just add the 'normals' together (the bigger the area
+       // the greater the length of the normal is
+       element = elements;
+       for (i = 0; i < numtriangles; i++, element += 3)
        {
-               TriangleNormal(vertex3f + e[0] * 3, vertex3f + e[1] * 3, vertex3f + e[2] * 3, normal);
-               VectorNormalize(normal);
-               v = normal3f + e[0] * 3;
-               v[0] += normal[0];
-               v[1] += normal[1];
-               v[2] += normal[2];
-               v = normal3f + e[1] * 3;
-               v[0] += normal[0];
-               v[1] += normal[1];
-               v[2] += normal[2];
-               v = normal3f + e[2] * 3;
-               v[0] += normal[0];
-               v[1] += normal[1];
-               v[2] += normal[2];
+               TriangleNormal(
+                       vertex3f + element[0] * 3,
+                       vertex3f + element[1] * 3,
+                       vertex3f + element[2] * 3,
+                       areaNormal
+                       );
+
+               if (!areaweighting)
+                       VectorNormalize(areaNormal);
+
+               for (j = 0;j < 3;j++)
+               {
+                       vectorNormal = normal3f + element[j] * 3;
+                       vectorNormal[0] += areaNormal[0];
+                       vectorNormal[1] += areaNormal[1];
+                       vectorNormal[2] += areaNormal[2];
+               }
        }
-       // now we could divide the vectors by the number of averaged values on
-       // each vertex...  but instead normalize them
-       for (i = 0, v = normal3f + 3 * firstvertex;i < numvertices;i++, v += 3)
-               VectorNormalize(v);
+       // and just normalize the accumulated vertex normal in the end
+       vectorNormal = normal3f + 3 * firstvertex;
+       for (i = 0; i < numvertices; i++, vectorNormal += 3)
+               VectorNormalize(vectorNormal);
 }
 
 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, 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
+       // 79 add/sub/negate/multiply (1 cycle), 1 compare (3 cycle?), total cycles not counting load/store/exchange roughly 82 cycles
+       // 6 add, 28 subtract, 39 multiply, 1 compare, 50% chance of 6 negates
 
        // 6 multiply, 9 subtract
        VectorSubtract(v1, v0, v10);
@@ -545,8 +551,6 @@ void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, con
        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];
-       // 1 sqrt, 1 divide, 6 multiply, 2 add, 1 compare
-       VectorNormalize(normal3f);
        // 12 multiply, 10 subtract
        tc10[1] = tc1[1] - tc0[1];
        tc20[1] = tc2[1] - tc0[1];
@@ -567,9 +571,6 @@ void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, con
        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
@@ -583,7 +584,7 @@ void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, con
 }
 
 // warning: this is a very expensive function!
-void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const int *elements, float *svector3f, float *tvector3f, float *normal3f)
+void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const int *elements, float *svector3f, float *tvector3f, float *normal3f, qboolean areaweighting)
 {
        int i, tnum;
        float sdir[3], tdir[3], normal[3], *v;
@@ -599,33 +600,21 @@ void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int num
        for (tnum = 0, e = elements;tnum < numtriangles;tnum++, e += 3)
        {
                Mod_BuildBumpVectors(vertex3f + e[0] * 3, vertex3f + e[1] * 3, vertex3f + e[2] * 3, texcoord2f + e[0] * 2, texcoord2f + e[1] * 2, texcoord2f + e[2] * 2, sdir, tdir, normal);
-               if (svector3f)
+               if (!areaweighting)
                {
-                       for (i = 0;i < 3;i++)
-                       {
-                               svector3f[e[i]*3  ] += sdir[0];
-                               svector3f[e[i]*3+1] += sdir[1];
-                               svector3f[e[i]*3+2] += sdir[2];
-                       }
+                       VectorNormalize(sdir);
+                       VectorNormalize(tdir);
+                       VectorNormalize(normal);
                }
+               if (svector3f)
+                       for (i = 0;i < 3;i++)
+                               VectorAdd(svector3f + e[i]*3, sdir, svector3f + e[i]*3);
                if (tvector3f)
-               {
                        for (i = 0;i < 3;i++)
-                       {
-                               tvector3f[e[i]*3  ] += tdir[0];
-                               tvector3f[e[i]*3+1] += tdir[1];
-                               tvector3f[e[i]*3+2] += tdir[2];
-                       }
-               }
+                               VectorAdd(tvector3f + e[i]*3, tdir, tvector3f + e[i]*3);
                if (normal3f)
-               {
                        for (i = 0;i < 3;i++)
-                       {
-                               normal3f[e[i]*3  ] += normal[0];
-                               normal3f[e[i]*3+1] += normal[1];
-                               normal3f[e[i]*3+2] += normal[2];
-                       }
-               }
+                               VectorAdd(normal3f + e[i]*3, normal, normal3f + e[i]*3);
        }
        // now we could divide the vectors by the number of averaged values on
        // each vertex...  but instead normalize them
@@ -643,11 +632,11 @@ void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int num
                        VectorNormalize(v);
 }
 
-surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean detailtexcoords, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors)
+surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors)
 {
        surfmesh_t *mesh;
        qbyte *data;
-       mesh = Mem_Alloc(mempool, sizeof(surfmesh_t) + numvertices * (3 + 3 + 3 + 3 + 2 + 2 + (detailtexcoords ? 2 : 0) + (vertexcolors ? 4 : 0)) * sizeof(float) + numvertices * (lightmapoffsets ? 1 : 0) * sizeof(int) + numtriangles * (3 + 3 + (neighbors ? 3 : 0)) * sizeof(int));
+       mesh = Mem_Alloc(mempool, sizeof(surfmesh_t) + numvertices * (3 + 3 + 3 + 3 + 2 + 2 + (vertexcolors ? 4 : 0)) * sizeof(float) + numvertices * (lightmapoffsets ? 1 : 0) * sizeof(int) + numtriangles * (3 + 3 + (neighbors ? 3 : 0)) * sizeof(int));
        mesh->num_vertices = numvertices;
        mesh->num_triangles = numtriangles;
        data = (qbyte *)(mesh + 1);
@@ -659,8 +648,6 @@ surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriang
                mesh->data_normal3f = (float *)data, data += sizeof(float[3]) * mesh->num_vertices;
                mesh->data_texcoordtexture2f = (float *)data, data += sizeof(float[2]) * mesh->num_vertices;
                mesh->data_texcoordlightmap2f = (float *)data, data += sizeof(float[2]) * mesh->num_vertices;
-               if (detailtexcoords)
-                       mesh->data_texcoorddetail2f = (float *)data, data += sizeof(float[2]) * mesh->num_vertices;
                if (vertexcolors)
                        mesh->data_lightmapcolor4f = (float *)data, data += sizeof(float[4]) * mesh->num_vertices;
                if (lightmapoffsets)
@@ -925,15 +912,12 @@ static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height
        return NULL;
 }
 
-static int detailtexturecycle = 0;
-int Mod_LoadSkinFrame(skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture)
+int Mod_LoadSkinFrame(skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture)
 {
        imageskin_t s;
        memset(skinframe, 0, sizeof(*skinframe));
        if (!image_loadskin(&s, basename))
                return false;
-       if (usedetailtexture)
-               skinframe->detail = r_texture_detailtextures[(detailtexturecycle++) % NUM_DETAILTEXTURES];
        skinframe->base = R_LoadTexture2D (loadmodel->texturepool, basename, s.basepixels_width, s.basepixels_height, s.basepixels, TEXTYPE_RGBA, textureflags, NULL);
        if (s.nmappixels != NULL)
                skinframe->nmap = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", basename), s.nmappixels_width, s.nmappixels_height, s.nmappixels, TEXTYPE_RGBA, textureflags, NULL);
@@ -950,18 +934,20 @@ int Mod_LoadSkinFrame(skinframe_t *skinframe, char *basename, int textureflags,
                if (s.shirtpixels != NULL)
                        skinframe->shirt = R_LoadTexture2D (loadmodel->texturepool, va("%s_shirt", basename), s.shirtpixels_width, s.shirtpixels_height, s.shirtpixels, TEXTYPE_RGBA, textureflags, NULL);
        }
+       if (!skinframe->base)
+               skinframe->base = r_texture_notexture;
+       if (!skinframe->nmap)
+               skinframe->nmap = r_texture_blanknormalmap;
        image_freeskin(&s);
        return true;
 }
 
-int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture, qbyte *skindata, int width, int height)
+int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture, qbyte *skindata, int width, int height)
 {
        qbyte *temp1, *temp2;
        memset(skinframe, 0, sizeof(*skinframe));
        if (!skindata)
                return false;
-       if (usedetailtexture)
-               skinframe->detail = r_texture_detailtextures[(detailtexturecycle++) % NUM_DETAILTEXTURES];
        if (r_shadow_bumpscale_basetexture.value > 0)
        {
                temp1 = Mem_Alloc(loadmodel->mempool, width * height * 8);
@@ -994,6 +980,8 @@ int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, char *basename, int textu
                                skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename), palette_nocolormap, textureflags); // no pants or shirt
                }
        }
+       if (!skinframe->nmap)
+               skinframe->nmap = r_texture_blanknormalmap;
        return true;
 }