]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_shared.c
more fullscreen cleanup
[xonotic/darkplaces.git] / model_shared.c
index f54b6da0de902b7d33c755b50d0601501e8cd9b8..eac0865badb3468fbce1e2de18665989cedbde85 100644 (file)
@@ -58,7 +58,7 @@ static void mod_start(void)
        Mod_LoadQ3Shaders();
 
        for (i = 0;i < nummodels;i++)
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*')
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*')
                        if (mod->used)
                                Mod_LoadModel(mod, true, false, mod->isworldmodel);
 }
@@ -70,7 +70,7 @@ static void mod_shutdown(void)
        dp_model_t *mod;
 
        for (i = 0;i < nummodels;i++)
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && (mod->loaded || mod->mempool))
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && (mod->loaded || mod->mempool))
                        Mod_UnloadModel(mod);
 
        Mem_FreePool (&q3shaders_mem);
@@ -86,7 +86,7 @@ static void mod_newmap(void)
        R_SkinFrame_PrepareForPurge();
        for (i = 0;i < nummodels;i++)
        {
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool && mod->data_textures)
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool && mod->data_textures)
                {
                        for (j = 0;j < mod->num_textures;j++)
                        {
@@ -104,7 +104,7 @@ static void mod_newmap(void)
 
        for (i = 0;i < nummodels;i++)
        {
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool && mod->data_surfaces)
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool && mod->data_surfaces)
                {
                        for (surfacenum = 0, surface = mod->data_surfaces;surfacenum < mod->num_surfaces;surfacenum++, surface++)
                        {
@@ -113,7 +113,7 @@ static void mod_newmap(void)
                                        ssize = (surface->lightmapinfo->extents[0] >> 4) + 1;
                                        tsize = (surface->lightmapinfo->extents[1] >> 4) + 1;
                                        memset(surface->lightmapinfo->stainsamples, 255, ssize * tsize * 3);
-                                       surface->cached_dlight = true;
+                                       mod->brushq1.lightmapupdateflags[surfacenum] = true;
                                }
                        }
                }
@@ -177,6 +177,11 @@ void Mod_UnloadModel (dp_model_t *mod)
        mod->loaded = false;
 }
 
+void R_Model_Null_Draw(entity_render_t *ent)
+{
+       return;
+}
+
 /*
 ==================
 Mod_LoadModel
@@ -195,6 +200,44 @@ dp_model_t *Mod_LoadModel(dp_model_t *mod, qboolean crash, qboolean checkdisk, q
 
        if (mod->name[0] == '*') // submodel
                return mod;
+       
+       if (!strcmp(mod->name, "null"))
+       {
+               if (mod->isworldmodel != isworldmodel)
+                       mod->loaded = false;
+
+               if(mod->loaded)
+                       return mod;
+
+               if (mod->loaded || mod->mempool)
+                       Mod_UnloadModel(mod);
+
+               if (developer_loading.integer)
+                       Con_Printf("loading model %s\n", mod->name);
+
+               mod->isworldmodel = isworldmodel;
+               mod->used = true;
+               mod->crc = -1;
+               mod->loaded = false;
+
+               VectorClear(mod->normalmins);
+               VectorClear(mod->normalmaxs);
+               VectorClear(mod->yawmins);
+               VectorClear(mod->yawmaxs);
+               VectorClear(mod->rotatedmins);
+               VectorClear(mod->rotatedmaxs);
+
+               mod->modeldatatypestring = "null";
+               mod->type = mod_null;
+               mod->Draw = R_Model_Null_Draw;
+               mod->numframes = 2;
+               mod->numskins = 1;
+
+               // no fatal errors occurred, so this model is ready to use.
+               mod->loaded = true;
+
+               return mod;
+       }
 
        crc = 0;
        buf = NULL;
@@ -308,7 +351,7 @@ void Mod_ClearUsed(void)
        int nummodels = Mem_ExpandableArray_IndexRange(&models);
        dp_model_t *mod;
        for (i = 0;i < nummodels;i++)
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0])
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0])
                        mod->used = false;
 }
 
@@ -319,7 +362,7 @@ void Mod_PurgeUnused(void)
        dp_model_t *mod;
        for (i = 0;i < nummodels;i++)
        {
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && !mod->used)
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && !mod->used)
                {
                        Mod_UnloadModel(mod);
                        Mem_ExpandableArray_FreeRecord(&models, mod);
@@ -335,7 +378,7 @@ void Mod_RemoveStaleWorldModels(dp_model_t *skip)
        dp_model_t *mod;
        for (i = 0;i < nummodels;i++)
        {
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->isworldmodel && mod->loaded && skip != mod)
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->isworldmodel && mod->loaded && skip != mod)
                {
                        Mod_UnloadModel(mod);
                        mod->isworldmodel = false;
@@ -362,7 +405,7 @@ dp_model_t *Mod_FindName(const char *name)
        // search the currently loaded models
        for (i = 0;i < nummodels;i++)
        {
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && !strcmp(mod->name, name))
+               if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && !strcmp(mod->name, name))
                {
                        mod->used = true;
                        return mod;
@@ -370,7 +413,7 @@ dp_model_t *Mod_FindName(const char *name)
        }
 
        // no match found, create a new one
-       mod = Mem_ExpandableArray_AllocRecord(&models);
+       mod = (dp_model_t *) Mem_ExpandableArray_AllocRecord(&models);
        strlcpy(mod->name, name, sizeof(mod->name));
        mod->loaded = false;
        mod->used = true;
@@ -406,7 +449,7 @@ void Mod_Reload(void)
        int nummodels = Mem_ExpandableArray_IndexRange(&models);
        dp_model_t *mod;
        for (i = 0;i < nummodels;i++)
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*' && mod->used)
+               if ((mod = (dp_model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*' && mod->used)
                        Mod_LoadModel(mod, true, true, mod->isworldmodel);
 }
 
@@ -428,7 +471,7 @@ static void Mod_Print(void)
 
        Con_Print("Loaded models:\n");
        for (i = 0;i < nummodels;i++)
-               if ((mod = Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0])
+               if ((mod = (dp_model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0])
                        Con_Printf("%4iK %s\n", mod->mempool ? (int)((mod->mempool->totalsize + 1023) / 1024) : 0, mod->name);
 }
 
@@ -1360,7 +1403,7 @@ void Mod_LoadQ3Shaders(void)
                                                        int i;
                                                        layer->numframes = min(numparameters - 2, TEXTURE_MAXFRAMES);
                                                        layer->framerate = atof(parameter[1]);
-                                                       layer->texturename = Mem_Alloc (q3shaders_mem, sizeof (char*) * layer->numframes);
+                                                       layer->texturename = (char **) Mem_Alloc (q3shaders_mem, sizeof (char*) * layer->numframes);
                                                        for (i = 0;i < layer->numframes;i++)
                                                                layer->texturename[i] = Mem_strdup (q3shaders_mem, parameter[i + 2]);
                                                }
@@ -1402,7 +1445,7 @@ void Mod_LoadQ3Shaders(void)
                                                        else if (!strcasecmp(parameter[1], "vertex"))           layer->alphagen.alphagen = Q3ALPHAGEN_VERTEX;
                                                        else if (!strcasecmp(parameter[1], "wave"))
                                                        {
-                                                               layer->alphagen.alphagen = Q3RGBGEN_WAVE;
+                                                               layer->alphagen.alphagen = Q3ALPHAGEN_WAVE;
                                                                layer->alphagen.wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]);
                                                                for (i = 0;i < numparameters - 3 && i < Q3WAVEPARMS;i++)
                                                                        layer->alphagen.waveparms[i] = atof(parameter[i+3]);
@@ -1447,6 +1490,7 @@ void Mod_LoadQ3Shaders(void)
                                                                else if (!strcasecmp(parameter[1], "rotate"))          layer->tcmods[tcmodindex].tcmod = Q3TCMOD_ROTATE;
                                                                else if (!strcasecmp(parameter[1], "scale"))           layer->tcmods[tcmodindex].tcmod = Q3TCMOD_SCALE;
                                                                else if (!strcasecmp(parameter[1], "scroll"))          layer->tcmods[tcmodindex].tcmod = Q3TCMOD_SCROLL;
+                                                               else if (!strcasecmp(parameter[1], "page"))            layer->tcmods[tcmodindex].tcmod = Q3TCMOD_PAGE;
                                                                else if (!strcasecmp(parameter[1], "stretch"))
                                                                {
                                                                        layer->tcmods[tcmodindex].tcmod = Q3TCMOD_STRETCH;
@@ -1483,7 +1527,7 @@ void Mod_LoadQ3Shaders(void)
                                        layer->texflags = TEXF_ALPHA | TEXF_PRECACHE;
                                        if (!(shader.surfaceparms & Q3SURFACEPARM_NOMIPMAPS))
                                                layer->texflags |= TEXF_MIPMAP;
-                                       if (!(shader.textureflags & Q3TEXTUREFLAG_NOPICMIP) && (r_picmipworld.integer || (layer->texturename && layer->texturename[0] && strncmp(layer->texturename[0], "textures/", 9))))
+                                       if (!(shader.textureflags & Q3TEXTUREFLAG_NOPICMIP))
                                                layer->texflags |= TEXF_PICMIP | TEXF_COMPRESS;
                                        if (layer->clampmap)
                                                layer->texflags |= TEXF_CLAMP;
@@ -1582,6 +1626,10 @@ void Mod_LoadQ3Shaders(void)
                                        else
                                                Con_DPrintf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[fileindex], parameter[1]);
                                }
+                               else if (!strcasecmp(parameter[0], "dpshadow"))
+                                       shader.dpshadow = true;
+                               else if (!strcasecmp(parameter[0], "dpnoshadow"))
+                                       shader.dpnoshadow = true;
                                else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
                                {
                                        // some q3 skies don't have the sky parm set
@@ -1731,6 +1779,13 @@ qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qbool
                        Con_Printf("%s: loaded shader for %s\n", loadmodel->name, name);
                texture->surfaceparms = shader->surfaceparms;
                texture->textureflags = shader->textureflags;
+
+               // allow disabling of picmip or compression by defaulttexflags
+               if(!(defaulttexflags & TEXF_PICMIP))
+                       texture->textureflags &= ~TEXF_PICMIP;
+               if(!(defaulttexflags & TEXF_COMPRESS))
+                       texture->textureflags &= ~TEXF_COMPRESS;
+
                texture->basematerialflags = 0;
                if (shader->surfaceparms & Q3SURFACEPARM_SKY)
                {
@@ -1811,7 +1866,11 @@ nothing                GL_ZERO GL_ONE
                        texture->skinframerate = primarylayer->framerate;
                        for (j = 0;j < primarylayer->numframes;j++)
                        {
-                               if (!(texture->skinframes[j] = R_SkinFrame_LoadExternal(primarylayer->texturename[j], primarylayer->texflags, false)))
+                               if(cls.state == ca_dedicated)
+                               {
+                                       texture->skinframes[j] = NULL;
+                               }
+                               else if (!(texture->skinframes[j] = R_SkinFrame_LoadExternal(primarylayer->texturename[j], primarylayer->texflags, false)))
                                {
                                        Con_Printf("^1%s:^7 could not load texture ^3\"%s\"^7 (frame %i) for shader ^2\"%s\"\n", loadmodel->name, primarylayer->texturename[j], j, texture->name);
                                        texture->skinframes[j] = R_SkinFrame_LoadMissing();
@@ -1825,13 +1884,21 @@ nothing                GL_ZERO GL_ONE
                        texture->backgroundskinframerate = backgroundlayer->framerate;
                        for (j = 0;j < backgroundlayer->numframes;j++)
                        {
-                               if (!(texture->backgroundskinframes[j] = R_SkinFrame_LoadExternal(backgroundlayer->texturename[j], backgroundlayer->texflags, false)))
+                               if(cls.state == ca_dedicated)
+                               {
+                                       texture->skinframes[j] = NULL;
+                               }
+                               else if (!(texture->backgroundskinframes[j] = R_SkinFrame_LoadExternal(backgroundlayer->texturename[j], backgroundlayer->texflags, false)))
                                {
                                        Con_Printf("^1%s:^7 could not load texture ^3\"%s\"^7 (background frame %i) for shader ^2\"%s\"\n", loadmodel->name, backgroundlayer->texturename[j], j, texture->name);
                                        texture->backgroundskinframes[j] = R_SkinFrame_LoadMissing();
                                }
                        }
                }
+               if (shader->dpshadow)
+                       texture->basematerialflags &= ~MATERIALFLAG_NOSHADOW;
+               if (shader->dpnoshadow)
+                       texture->basematerialflags |= MATERIALFLAG_NOSHADOW;
                memcpy(texture->deforms, shader->deforms, sizeof(texture->deforms));
                texture->reflectmin = shader->reflectmin;
                texture->reflectmax = shader->reflectmax;
@@ -1866,15 +1933,28 @@ nothing                GL_ZERO GL_ONE
                else
                        texture->basematerialflags |= MATERIALFLAG_WALL;
                texture->numskinframes = 1;
-               if (fallback)
+               if(cls.state == ca_dedicated)
                {
-                       if (!(texture->skinframes[0] = R_SkinFrame_LoadExternal(texture->name, defaulttexflags, false)))
-                               success = false;
+                       texture->skinframes[0] = NULL;
                }
                else
-                       success = false;
-               if (!success && warnmissing)
-                       Con_Printf("^1%s:^7 could not load texture ^3\"%s\"\n", loadmodel->name, texture->name);
+               {
+                       if (fallback)
+                       {
+                               qboolean has_alpha;
+                               if ((texture->skinframes[0] = R_SkinFrame_LoadExternal_CheckAlpha(texture->name, defaulttexflags, false, &has_alpha)))
+                               {
+                                       if(has_alpha && (defaulttexflags & TEXF_ALPHA))
+                                               texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
+                               }
+                               else
+                                       success = false;
+                       }
+                       else
+                               success = false;
+                       if (!success && warnmissing)
+                               Con_Printf("^1%s:^7 could not load texture ^3\"%s\"\n", loadmodel->name, texture->name);
+               }
        }
        // init the animation variables
        texture->currentframe = texture;
@@ -2025,23 +2105,20 @@ void Mod_SnapVertices(int numcomponents, int numvertices, float *vertices, float
 int Mod_RemoveDegenerateTriangles(int numtriangles, const int *inelement3i, int *outelement3i, const float *vertex3f)
 {
        int i, outtriangles;
-       float d, edgedir[3], temp[3];
+       float edgedir1[3], edgedir2[3], temp[3];
        // a degenerate triangle is one with no width (thickness, surface area)
        // these are characterized by having all 3 points colinear (along a line)
        // or having two points identical
+       // the simplest check is to calculate the triangle's area
        for (i = 0, outtriangles = 0;i < numtriangles;i++, inelement3i += 3)
        {
                // calculate first edge
-               VectorSubtract(vertex3f + inelement3i[1] * 3, vertex3f + inelement3i[0] * 3, edgedir);
-               if (VectorLength2(edgedir) < 0.0001f)
-                       continue; // degenerate first edge (no length)
-               VectorNormalize(edgedir);
-               // check if third point is on the edge (colinear)
-               d = -DotProduct(vertex3f + inelement3i[2] * 3, edgedir);
-               VectorMA(vertex3f + inelement3i[2] * 3, d, edgedir, temp);
-               if (VectorLength2(temp) < 0.0001f)
-                       continue; // third point colinear with first edge
-               // valid triangle (no colinear points, no duplicate points)
+               VectorSubtract(vertex3f + inelement3i[1] * 3, vertex3f + inelement3i[0] * 3, edgedir1);
+               VectorSubtract(vertex3f + inelement3i[2] * 3, vertex3f + inelement3i[0] * 3, edgedir2);
+               CrossProduct(edgedir1, edgedir2, temp);
+               if (VectorLength2(temp) < 0.001f)
+                       continue; // degenerate triangle (no area)
+               // valid triangle (has area)
                VectorCopy(inelement3i, outelement3i);
                outelement3i += 3;
                outtriangles++;