]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_alias.c
Fix a typo in DrawQ_RotPic which broke it badly.
[xonotic/darkplaces.git] / model_alias.c
index 68f19b8db914fadc0cbe76128bb7c1131a2d44f6..cdf0edeee0928722f85bf5373004f98fd1353929 100644 (file)
@@ -752,32 +752,46 @@ static void Mod_Alias_MorphMesh_CompileFrames(void)
        }
 }
 
-static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 {
        int i;
        float segmentmins[3], segmentmaxs[3];
        msurface_t *surface;
-       float vertex3fbuf[1024*3];
+       float vertex3fbuf[1024 * 3];
        float *vertex3f = vertex3fbuf;
+       float *freevertex3f = NULL;
+       // for static cases we can just call CollisionBIH which is much faster
+       if ((frameblend == NULL || (frameblend[0].subframe == 0 && frameblend[1].lerp == 0)) && (skeleton == NULL || skeleton->relativetransforms == NULL))
+       {
+               Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
+               return;
+       }
        memset(trace, 0, sizeof(*trace));
        trace->fraction = 1;
        trace->hitsupercontentsmask = hitsupercontentsmask;
-       if (model->surfmesh.num_vertices > 1024)
-               vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
+       trace->skipsupercontentsmask = skipsupercontentsmask;
+       trace->skipmaterialflagsmask = skipmaterialflagsmask;
        segmentmins[0] = min(start[0], end[0]) - 1;
        segmentmins[1] = min(start[1], end[1]) - 1;
        segmentmins[2] = min(start[2], end[2]) - 1;
        segmentmaxs[0] = max(start[0], end[0]) + 1;
        segmentmaxs[1] = max(start[1], end[1]) + 1;
        segmentmaxs[2] = max(start[2], end[2]) + 1;
-       model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
+       if (frameblend == NULL || frameblend[0].subframe != 0 || frameblend[0].lerp != 0 || skeleton != NULL)
+       {
+               if (model->surfmesh.num_vertices > 1024)
+                       vertex3f = freevertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
+               model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
+       }
+       else
+               vertex3f = model->surfmesh.data_vertex3f;
        for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
                Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
-       if (vertex3f != vertex3fbuf)
-               Mem_Free(vertex3f);
+       if (freevertex3f)
+               Mem_Free(freevertex3f);
 }
 
-static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 {
        int i;
        vec3_t shiftstart, shiftend;
@@ -792,15 +806,24 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameb
        {
                VectorAdd(start, boxmins, shiftstart);
                VectorAdd(end, boxmins, shiftend);
-               Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
+               Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
                VectorSubtract(trace->endpos, boxmins, trace->endpos);
                return;
        }
 
+       // for static cases we can just call CollisionBIH which is much faster
+       if ((frameblend == NULL || (frameblend[0].subframe == 0 && frameblend[1].lerp == 0)) && (skeleton == NULL || skeleton->relativetransforms == NULL))
+       {
+               Mod_CollisionBIH_TraceBox(model, frameblend, skeleton, trace, start, boxmins, boxmaxs, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
+               return;
+       }
+
        // box trace, performed as brush trace
        memset(trace, 0, sizeof(*trace));
        trace->fraction = 1;
        trace->hitsupercontentsmask = hitsupercontentsmask;
+       trace->skipsupercontentsmask = skipsupercontentsmask;
+       trace->skipmaterialflagsmask = skipmaterialflagsmask;
        if (model->surfmesh.num_vertices > 1024)
                vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
        segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
@@ -899,45 +922,6 @@ static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *ve
        }
 }
 
-static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
-{
-       if (cls.state == ca_dedicated)
-               return;
-       // hack
-       if (!skinframe)
-               skinframe = R_SkinFrame_LoadMissing();
-       memset(texture, 0, sizeof(*texture));
-       texture->currentframe = texture;
-       //texture->animated = false;
-       texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(skinframe);
-       texture->currentskinframe = skinframe;
-       //texture->backgroundnumskinframes = 0;
-       //texture->customblendfunc[0] = 0;
-       //texture->customblendfunc[1] = 0;
-       //texture->surfaceflags = 0;
-       //texture->supercontents = 0;
-       //texture->surfaceparms = 0;
-       //texture->textureflags = 0;
-
-       texture->basematerialflags = MATERIALFLAG_WALL;
-       texture->basealpha = 1.0f;
-       if (texture->currentskinframe->hasalpha)
-               texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
-       texture->currentmaterialflags = texture->basematerialflags;
-       texture->offsetmapping = OFFSETMAPPING_DEFAULT;
-       texture->offsetscale = 1;
-       texture->offsetbias = 0;
-       texture->specularscalemod = 1;
-       texture->specularpowermod = 1;
-       texture->surfaceflags = 0;
-       texture->supercontents = SUPERCONTENTS_SOLID;
-       if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
-               texture->supercontents |= SUPERCONTENTS_OPAQUE;
-       texture->transparentsort = TRANSPARENTSORT_DISTANCE;
-       // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
-       // JUST GREP FOR "specularscalemod = 1".
-}
-
 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
 {
        int i;
@@ -960,14 +944,14 @@ void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, con
                                        Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
                                        if(developer_extra.integer)
                                                Con_DPrintf("--> got %s from skin file\n", stripbuf);
-                                       Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
+                                       Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL);
                                        break;
                                }
                        }
                        if (!skinfileitem)
                        {
                                // don't render unmentioned meshes
-                               Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
+                               Mod_LoadCustomMaterial(loadmodel->mempool, skin, meshname, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadMissing());
                                if(developer_extra.integer)
                                        Con_DPrintf("--> skipping\n");
                                skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
@@ -979,7 +963,7 @@ void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, con
                if(developer_extra.integer)
                        Con_DPrintf("--> using default\n");
                Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
-               Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
+               Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL);
        }
 }
 
@@ -1007,7 +991,6 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
        float *vertst;
        int *vertonseam, *vertremap;
        skinfile_t *skinfiles;
-       char vabuf[1024];
 
        datapointer = (unsigned char *)buffer;
        pinmodel = (mdl_t *)datapointer;
@@ -1276,8 +1259,8 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                                        dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
                                else
                                        dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
-                               if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
-                                       Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
+                               if (!Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL))
+                                       Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
                                datapointer += skinwidth * skinheight;
                                totalskins++;
                        }
@@ -1285,8 +1268,12 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                // check for skins that don't exist in the model, but do exist as external images
                // (this was added because yummyluv kept pestering me about support for it)
                // TODO: support shaders here?
-               while ((tempskinframe = R_SkinFrame_LoadExternal(va(vabuf, sizeof(vabuf), "%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
+               for (;;)
                {
+                       dpsnprintf(name, sizeof(name), "%s_%i", loadmodel->name, loadmodel->numskins);
+                       tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false, false);
+                       if (!tempskinframe)
+                               break;
                        // expand the arrays to make room
                        tempskinscenes = loadmodel->skinscenes;
                        loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
@@ -1299,7 +1286,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                        Mem_Free(tempaliasskins);
 
                        // store the info about the new skin
-                       Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
+                       Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, tempskinframe);
                        strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
                        loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
                        loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
@@ -1307,6 +1294,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                        loadmodel->skinscenes[loadmodel->numskins].loop = true;
 
                        //increase skin counts
+                       loadmodel->num_textures++;
                        loadmodel->numskins++;
                        totalskins++;
 
@@ -1327,9 +1315,10 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if(mod_alias_force_animated.string[0])
                loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
 
+       // Always make a BIH for the first frame, we can use it where possible.
+       Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
        if (!loadmodel->surfmesh.isanimated)
        {
-               Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
                loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
                loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
                loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
@@ -1462,7 +1451,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
                loadmodel->num_texturesperskin = loadmodel->num_surfaces;
                loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
                for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
-                       Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
+                       Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL);
        }
        else
        {
@@ -1471,7 +1460,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
                loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
                loadmodel->num_texturesperskin = loadmodel->num_surfaces;
                loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
-               Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
+               Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures, loadmodel->name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadMissing());
        }
 
        loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
@@ -1598,9 +1587,10 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
        surface->num_firstvertex = 0;
        surface->num_vertices = loadmodel->surfmesh.num_vertices;
 
+       // Always make a BIH for the first frame, we can use it where possible.
+       Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
        if (!loadmodel->surfmesh.isanimated)
        {
-               Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
                loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
                loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
                loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
@@ -1793,9 +1783,10 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if(mod_alias_force_animated.string[0])
                loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
 
+       // Always make a BIH for the first frame, we can use it where possible.
+       Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
        if (!loadmodel->surfmesh.isanimated)
        {
-               Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
                loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
                loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
                loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
@@ -2193,9 +2184,10 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if(mod_alias_force_animated.string[0])
                loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
 
+       // Always make a BIH for the first frame, we can use it where possible.
+       Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
        if (!loadmodel->surfmesh.isanimated)
        {
-               Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
                loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
                loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
                loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
@@ -2571,9 +2563,10 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if(mod_alias_force_animated.string[0])
                loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
 
+       // Always make a BIH for the first frame, we can use it where possible.
+       Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
        if (!loadmodel->surfmesh.isanimated)
        {
-               Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
                loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
                loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
                loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
@@ -3249,9 +3242,10 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if(mod_alias_force_animated.string[0])
                loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
 
+       // Always make a BIH for the first frame, we can use it where possible.
+       Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
        if (!loadmodel->surfmesh.isanimated)
        {
-               Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
                loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
                loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
                loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
@@ -4015,9 +4009,10 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if (!header.ofs_bounds)
                Mod_Alias_CalculateBoundingBox();
 
-       if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
+       // Always make a BIH for the first frame, we can use it where possible.
+       Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
+       if (!loadmodel->surfmesh.isanimated)
        {
-               Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
                loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
                loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
                loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;