]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_alias.c
added r_smoothnormals_areaweighting cvar (default 1, suggested by Black as a better...
[xonotic/darkplaces.git] / model_alias.c
index c6b8492ae88fbfe88b723037c81e62e3244186dc..ca95999cb6f74f539d6f8bde7309b8543c8722b4 100644 (file)
@@ -70,6 +70,8 @@ void Mod_Alias_GetMesh_Vertex3f(const model_t *model, const frameblend_t *frameb
                float lerp1, lerp2, lerp3, lerp4;
                const float *vertsbase, *verts1, *verts2, *verts3, *verts4;
                // vertex morph
+               if (!mesh->data_morphvertex3f)
+                       Host_Error("model %s has no skeletal or vertex morph animation data\n", model->name);
                vertsbase = mesh->data_morphvertex3f;
                vertcount = mesh->num_vertices;
                verts1 = vertsbase + frameblend[0].frame * vertcount * 3;
@@ -175,14 +177,14 @@ static void Mod_Alias_Mesh_CompileFrameZero(surfmesh_t *mesh)
        mesh->data_tvector3f = mesh->data_vertex3f + mesh->num_vertices * 6;
        mesh->data_normal3f = mesh->data_vertex3f + mesh->num_vertices * 9;
        Mod_Alias_GetMesh_Vertex3f(loadmodel, frameblend, mesh, mesh->data_vertex3f);
-       Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, mesh->data_vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f);
+       Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, mesh->data_vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f, true);
 }
 
 static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
 {
-       int i, framenum, linetrace;
-       float *vertex3f;
+       int i, linetrace;
        float segmentmins[3], segmentmaxs[3];
+       frameblend_t frameblend[4];
        msurface_t *surface;
        surfmesh_t *mesh;
        colbrushf_t *thisbrush_start = NULL, *thisbrush_end = NULL;
@@ -206,23 +208,17 @@ static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, co
                thisbrush_start = Collision_BrushForBox(&startmatrix, boxstartmins, boxstartmaxs);
                thisbrush_end = Collision_BrushForBox(&endmatrix, boxendmins, boxendmaxs);
        }
+       memset(frameblend, 0, sizeof(frameblend));
+       frameblend[0].frame = frame;
+       frameblend[0].lerp = 1;
        for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
        {
                mesh = surface->groupmesh;
-               framenum = frame;
-               if (framenum < 0 || framenum > mesh->num_morphframes)
-                       framenum = 0;
-               if (mesh->data_morphvertex3f)
-                       vertex3f = mesh->data_morphvertex3f + framenum * mesh->num_vertices * 3;
-               else
-               {
-                       vertex3f = varray_vertex3f;
-                       continue; // FIXME!!!  this needs to handle skeletal!
-               }
+               Mod_Alias_GetMesh_Vertex3f(model, frameblend, mesh, varray_vertex3f);
                if (linetrace)
-                       Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, mesh->num_triangles, mesh->data_element3i, vertex3f, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs);
+                       Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, mesh->num_triangles, mesh->data_element3i, varray_vertex3f, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs);
                else
-                       Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, mesh->num_triangles, mesh->data_element3i, vertex3f, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs);
+                       Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, mesh->num_triangles, mesh->data_element3i, varray_vertex3f, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs);
        }
 }
 
@@ -385,13 +381,13 @@ static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfi
                                if (!strcmp(skinfileitem->name, meshname) && strcmp(skinfileitem->replacement, "common/nodraw") && strcmp(skinfileitem->replacement, "textures/common/nodraw"))
                                {
                                        memset(&tempskinframe, 0, sizeof(tempskinframe));
-                                       if (Mod_LoadSkinFrame(&tempskinframe, skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_CLAMP | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
+                                       if (Mod_LoadSkinFrame(&tempskinframe, skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
                                                Mod_BuildAliasSkinFromSkinFrame(skin, &tempskinframe);
                                        else
                                        {
                                                if (cls.state != ca_dedicated)
                                                        Con_Printf("mesh \"%s\": failed to load skin #%i \"%s\", falling back to mesh's internal shader name \"%s\"\n", meshname, i, skinfileitem->replacement, shadername);
-                                               if (Mod_LoadSkinFrame(&tempskinframe, shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_CLAMP | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
+                                               if (Mod_LoadSkinFrame(&tempskinframe, shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
                                                        Mod_BuildAliasSkinFromSkinFrame(skin, &tempskinframe);
                                                else
                                                {
@@ -407,7 +403,7 @@ static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfi
        else
        {
                memset(&tempskinframe, 0, sizeof(tempskinframe));
-               if (Mod_LoadSkinFrame(&tempskinframe, shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_CLAMP | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
+               if (Mod_LoadSkinFrame(&tempskinframe, shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
                        Mod_BuildAliasSkinFromSkinFrame(skin, &tempskinframe);
                else
                {
@@ -687,8 +683,8 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
                                        sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
                                else
                                        sprintf (name, "%s_%i", loadmodel->name, i);
-                               if (!Mod_LoadSkinFrame(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_CLAMP | TEXF_ALPHA | TEXF_PICMIP, true, false, true))
-                                       Mod_LoadSkinFrame_Internal(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_CLAMP | TEXF_ALPHA | TEXF_PICMIP, true, false, r_fullbrights.integer, (qbyte *)datapointer, skinwidth, skinheight);
+                               if (!Mod_LoadSkinFrame(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP, true, false, true))
+                                       Mod_LoadSkinFrame_Internal(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP, true, false, r_fullbrights.integer, (qbyte *)datapointer, skinwidth, skinheight);
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, &tempskinframe);
                                datapointer += skinwidth * skinheight;
                                totalskins++;
@@ -696,7 +692,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
                }
                // 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)
-               while (Mod_LoadSkinFrame(&tempskinframe, va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_CLAMP | TEXF_ALPHA | TEXF_PICMIP, true, false, true))
+               while (Mod_LoadSkinFrame(&tempskinframe, va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP, true, false, true))
                {
                        // expand the arrays to make room
                        tempskinscenes = loadmodel->skinscenes;
@@ -844,7 +840,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
                loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
                for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
                {
-                       if (Mod_LoadSkinFrame(&tempskinframe, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_CLAMP | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
+                       if (Mod_LoadSkinFrame(&tempskinframe, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, &tempskinframe);
                        else
                        {
@@ -1154,7 +1150,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
        loadmodel->Draw = R_Q1BSP_Draw;
        loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
        loadmodel->DrawLight = R_Q1BSP_DrawLight;
-       //loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; // FIXME: implement collisions
+       loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
        loadmodel->flags = 0; // there are no flags on zym models
        loadmodel->synctype = ST_RAND;
 
@@ -1350,6 +1346,8 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
                         || (unsigned int)outelements[1] >= (unsigned int)pheader->numverts
                         || (unsigned int)outelements[2] >= (unsigned int)pheader->numverts)
                                Host_Error("%s corrupt renderlist (out of bounds index)\n", loadmodel->name);
+                       if (vertbonecounts[outelements[0]] == 0 || vertbonecounts[outelements[1]] == 0 || vertbonecounts[outelements[2]] == 0)
+                               Host_Error("%s corrupt renderlist (references vertex with no bone weights\n", loadmodel->name);
                        renderlist += 3;
                        outelements += 3;
                }
@@ -1368,14 +1366,14 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
                        }
                }
                mesh->num_vertexboneweights = 0;
-               for (j = 0;j < mesh->num_vertices;j++)
+               for (j = 0;j < pheader->numverts;j++)
                        if (remapvertices[j] >= 0)
                                mesh->num_vertexboneweights += vertbonecounts[remapvertices[j]];
                mesh->data_vertexboneweights = Mem_Alloc(loadmodel->mempool, mesh->num_vertexboneweights * sizeof(surfmeshvertexboneweight_t));
                mesh->num_vertexboneweights = 0;
                // note this vertexboneweight ordering requires that the remapvertices array is sequential numbers (separated by -1 values for omitted vertices)
                l = 0;
-               for (j = 0;j < mesh->num_vertices;j++)
+               for (j = 0;j < pheader->numverts;j++)
                {
                        if (remapvertices[j] < 0)
                        {
@@ -1395,20 +1393,19 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
                                l++;
                        }
                }
-
-               Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
-               Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
-               Mod_Alias_Mesh_CompileFrameZero(mesh);
-
+               shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
                // since zym models do not have named sections, reuse their shader
                // name as the section name
-               shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
                if (shadername[0])
                        Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
                else
                        for (j = 0;j < loadmodel->numskins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
+               Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
+               Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
+               Mod_Alias_Mesh_CompileFrameZero(mesh);
+
                surface = loadmodel->data_surfaces + i;
                surface->groupmesh = mesh;
                surface->texture = loadmodel->data_textures + i;