]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_shared.c
don't apply host_sleep when in a timedemo
[xonotic/darkplaces.git] / model_shared.c
index 23a1d3d0ae8016223e96fbc4cfd1ce248d24edaa..664f0dab4c5d1eaf97397e870e58149cf8af4030 100644 (file)
@@ -320,7 +320,8 @@ dp_model_t *Mod_LoadModel(dp_model_t *mod, qboolean crash, qboolean checkdisk, q
                num = LittleLong(*((int *)buf));
                // call the apropriate loader
                loadmodel = mod;
-                    if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf, bufend);
+                    if (!strcasecmp(FS_FileExtension(mod->name), "obj")) Mod_OBJ_Load(mod, buf, bufend);
+               else 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);
@@ -2168,6 +2169,39 @@ void Mod_VertexRangeFromElements(int numelements, const int *elements, int *firs
                *lastvertexpointer = lastvertex;
 }
 
+void Mod_MakeSortedSurfaces(dp_model_t *mod)
+{
+       // make an optimal set of texture-sorted batches to draw...
+       int j, t;
+       int *firstsurfacefortexture;
+       int *numsurfacesfortexture;
+       if (!mod->sortedmodelsurfaces)
+               mod->sortedmodelsurfaces = Mem_Alloc(loadmodel->mempool, mod->nummodelsurfaces * sizeof(*mod->sortedmodelsurfaces));
+       firstsurfacefortexture = Mem_Alloc(tempmempool, mod->num_textures * sizeof(*firstsurfacefortexture));
+       numsurfacesfortexture = Mem_Alloc(tempmempool, mod->num_textures * sizeof(*numsurfacesfortexture));
+       memset(numsurfacesfortexture, 0, mod->num_textures * sizeof(*numsurfacesfortexture));
+       for (j = 0;j < mod->nummodelsurfaces;j++)
+       {
+               const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
+               int t = (int)(surface->texture - mod->data_textures);
+               numsurfacesfortexture[t]++;
+       }
+       j = 0;
+       for (t = 0;t < mod->num_textures;t++)
+       {
+               firstsurfacefortexture[t] = j;
+               j += numsurfacesfortexture[t];
+       }
+       for (j = 0;j < mod->nummodelsurfaces;j++)
+       {
+               const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
+               int t = (int)(surface->texture - mod->data_textures);
+               mod->sortedmodelsurfaces[firstsurfacefortexture[t]++] = j + mod->firstmodelsurface;
+       }
+       Mem_Free(firstsurfacefortexture);
+       Mem_Free(numsurfacesfortexture);
+}
+
 static void Mod_BuildVBOs(void)
 {
        if (!gl_support_arb_vertex_buffer_object)
@@ -2217,25 +2251,58 @@ static void Mod_BuildVBOs(void)
        }
 }
 
-static void Mod_Decompile_OBJ(dp_model_t *model, const char *filename, const char *originalfilename)
+static void Mod_Decompile_OBJ(dp_model_t *model, const char *filename, const char *mtlfilename, const char *originalfilename)
 {
-       int vertexindex, surfaceindex, triangleindex, countvertices = 0, countsurfaces = 0, countfaces = 0;
+       int vertexindex, surfaceindex, triangleindex, textureindex, countvertices = 0, countsurfaces = 0, countfaces = 0, counttextures = 0;
+       int a, b, c;
+       const char *texname;
        const int *e;
        const float *v, *vn, *vt;
        size_t l;
        size_t outbufferpos = 0;
-       size_t outbuffermax = 0x10000;
-       char *outbuffer = Z_Malloc(outbuffermax), *oldbuffer;
+       size_t outbuffermax = 0x100000;
+       char *outbuffer = (char *) Z_Malloc(outbuffermax), *oldbuffer;
        const msurface_t *surface;
+       const int maxtextures = 256;
+       char *texturenames = (char *) Z_Malloc(maxtextures * MAX_QPATH);
 
+       // construct the mtllib file
+       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "# mtllib for %s exported by darkplaces engine\n", originalfilename);
+       if (l > 0)
+               outbufferpos += l;
        for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->num_surfaces;surfaceindex++, surface++)
        {
-               countmaterials++;
+               countsurfaces++;
                countvertices += surface->num_vertices;
                countfaces += surface->num_triangles;
+               texname = (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default";
+               for (textureindex = 0;textureindex < maxtextures && texturenames[textureindex*MAX_QPATH];textureindex++)
+                       if (!strcmp(texturenames + textureindex * MAX_QPATH, texname))
+                               break;
+               if (textureindex >= maxtextures)
+                       continue; // just a precaution
+               if (counttextures < textureindex + 1)
+                       counttextures = textureindex + 1;
+               strlcpy(texturenames + textureindex * MAX_QPATH, texname, MAX_QPATH);
+               if (outbufferpos >= outbuffermax >> 1)
+               {
+                       outbuffermax *= 2;
+                       oldbuffer = outbuffer;
+                       outbuffer = (char *) Z_Malloc(outbuffermax);
+                       memcpy(outbuffer, oldbuffer, outbufferpos);
+                       Z_Free(oldbuffer);
+               }
+               l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "newmtl %s\nNs 96.078431\nKa 0 0 0\nKd 0.64 0.64 0.64\nKs 0.5 0.5 0.5\nNi 1\nd 1\nillum 2\nmap_Kd %s%s\n\n", texname, texname, strstr(texname, ".tga") ? "" : ".tga");
+               if (l > 0)
+                       outbufferpos += l;
        }
 
-       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "# model exported from %s by darkplaces engine\n# %i vertices, %i faces, %i surfaces\n", originalfilename, countvertices, countfaces, countsurfaces);
+       // write the mtllib file
+       FS_WriteFile(mtlfilename, outbuffer, outbufferpos);
+       outbufferpos = 0;
+
+       // construct the obj file
+       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "# model exported from %s by darkplaces engine\n# %i vertices, %i faces, %i surfaces\nmtllib %s\n", originalfilename, countvertices, countfaces, countsurfaces, mtlfilename);
        if (l > 0)
                outbufferpos += l;
        for (vertexindex = 0, v = model->surfmesh.data_vertex3f, vn = model->surfmesh.data_normal3f, vt = model->surfmesh.data_texcoordtexture2f;vertexindex < model->surfmesh.num_vertices;vertexindex++, v += 3, vn += 3, vt += 2)
@@ -2244,21 +2311,17 @@ static void Mod_Decompile_OBJ(dp_model_t *model, const char *filename, const cha
                {
                        outbuffermax *= 2;
                        oldbuffer = outbuffer;
-                       outbuffer = Z_Malloc(outbuffermax);
+                       outbuffer = (char *) Z_Malloc(outbuffermax);
                        memcpy(outbuffer, oldbuffer, outbufferpos);
                        Z_Free(oldbuffer);
                }
-               l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "v %f %f %f\nvn %f %f %f\nvt %f %f\n", v[0], v[2], v[1], vn[0], vn[2], vn[1], vt[0], vt[1]);
+               l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "v %f %f %f\nvn %f %f %f\nvt %f %f\n", v[0], v[2], -v[1], vn[0], vn[2], -vn[1], vt[0], 1-vt[1]);
                if (l > 0)
                        outbufferpos += l;
        }
-
        for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->num_surfaces;surfaceindex++, surface++)
        {
-               if (surface->texture && surface->texture->name[0])
-                       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl %s\n", surface->texture->name);
-               else
-                       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl default\n");
+               l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl %s\n", (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default");
                if (l > 0)
                        outbufferpos += l;
                for (triangleindex = 0, e = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
@@ -2267,20 +2330,28 @@ static void Mod_Decompile_OBJ(dp_model_t *model, const char *filename, const cha
                        {
                                outbuffermax *= 2;
                                oldbuffer = outbuffer;
-                               outbuffer = Z_Malloc(outbuffermax);
+                               outbuffer = (char *) Z_Malloc(outbuffermax);
                                memcpy(outbuffer, oldbuffer, outbufferpos);
                                Z_Free(oldbuffer);
                        }
-                       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", e[0], e[0], e[0], e[2], e[2], e[2], e[1], e[1], e[1]);
+                       a = e[0]+1;
+                       b = e[2]+1;
+                       c = e[1]+1;
+                       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", a,a,a,b,b,b,c,c,c);
                        if (l > 0)
                                outbufferpos += l;
                }
        }
 
+       // write the obj file
        FS_WriteFile(filename, outbuffer, outbufferpos);
+
+       // clean up
        Z_Free(outbuffer);
+       Z_Free(texturenames);
 
-       Con_Printf("Wrote %s (%i bytes, %i vertices, %i faces, %i surfaces)\n", filename, (int)outbufferpos, countvertices, countfaces, countsurfaces);
+       // print some stats
+       Con_Printf("Wrote %s (%i bytes, %i vertices, %i faces, %i surfaces with %i distinct textures)\n", filename, (int)outbufferpos, countvertices, countfaces, countsurfaces, counttextures);
 }
 
 static void Mod_Decompile_SMD(dp_model_t *model, const char *filename, int firstpose, int numposes, qboolean writetriangles)
@@ -2291,23 +2362,34 @@ static void Mod_Decompile_SMD(dp_model_t *model, const char *filename, int first
        int transformindex;
        int poseindex;
        int cornerindex;
+       float modelscale;
        const int *e;
        const float *pose;
        size_t l;
        size_t outbufferpos = 0;
-       size_t outbuffermax = 0x10000;
-       char *outbuffer = Z_Malloc(outbuffermax), *oldbuffer;
+       size_t outbuffermax = 0x100000;
+       char *outbuffer = (char *) Z_Malloc(outbuffermax), *oldbuffer;
        const msurface_t *surface;
        l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "version 1\nnodes\n");
        if (l > 0)
                outbufferpos += l;
+       modelscale = 1;
+       if(model->num_poses >= 0)
+               modelscale = sqrt(model->data_poses[0] * model->data_poses[0] + model->data_poses[1] * model->data_poses[1] + model->data_poses[2] * model->data_poses[2]);
+       if(fabs(modelscale - 1) > 1e-4)
+       {
+               if(firstpose == 0) // only print the when writing the reference pose
+                       Con_Printf("The model has an old-style model scale of %f\n", modelscale);
+       }
+       else
+               modelscale = 1;
        for (transformindex = 0;transformindex < model->num_bones;transformindex++)
        {
                if (outbufferpos >= outbuffermax >> 1)
                {
                        outbuffermax *= 2;
                        oldbuffer = outbuffer;
-                       outbuffer = Z_Malloc(outbuffermax);
+                       outbuffer = (char *) Z_Malloc(outbuffermax);
                        memcpy(outbuffer, oldbuffer, outbufferpos);
                        Z_Free(oldbuffer);
                }
@@ -2334,7 +2416,7 @@ static void Mod_Decompile_SMD(dp_model_t *model, const char *filename, int first
                        {
                                outbuffermax *= 2;
                                oldbuffer = outbuffer;
-                               outbuffer = Z_Malloc(outbuffermax);
+                               outbuffer = (char *) Z_Malloc(outbuffermax);
                                memcpy(outbuffer, oldbuffer, outbufferpos);
                                Z_Free(oldbuffer);
                        }
@@ -2388,7 +2470,7 @@ static void Mod_Decompile_SMD(dp_model_t *model, const char *filename, int first
                        test[2][3] = pose[11];
 }
 #endif
-                       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f\n", transformindex, pose[3], pose[7], pose[11], DEG2RAD(angles[ROLL]), DEG2RAD(angles[PITCH]), DEG2RAD(angles[YAW]));
+                       l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f\n", transformindex, pose[3] * modelscale, pose[7] * modelscale, pose[11] * modelscale, DEG2RAD(angles[ROLL]), DEG2RAD(angles[PITCH]), DEG2RAD(angles[YAW]));
                        if (l > 0)
                                outbufferpos += l;
                }
@@ -2410,7 +2492,7 @@ static void Mod_Decompile_SMD(dp_model_t *model, const char *filename, int first
                                {
                                        outbuffermax *= 2;
                                        oldbuffer = outbuffer;
-                                       outbuffer = Z_Malloc(outbuffermax);
+                                       outbuffer = (char *) Z_Malloc(outbuffermax);
                                        memcpy(outbuffer, oldbuffer, outbufferpos);
                                        Z_Free(oldbuffer);
                                }
@@ -2458,11 +2540,14 @@ static void Mod_Decompile_f(void)
        dp_model_t *mod;
        char inname[MAX_QPATH];
        char outname[MAX_QPATH];
+       char mtlname[MAX_QPATH];
        char basename[MAX_QPATH];
        char animname[MAX_QPATH];
        char animname2[MAX_QPATH];
-       char textbuffer[32768];
-       int textsize = 0;
+       char zymtextbuffer[16384];
+       char dpmtextbuffer[16384];
+       int zymtextsize = 0;
+       int dpmtextsize = 0;
 
        if (Cmd_Argc() != 2)
        {
@@ -2489,16 +2574,19 @@ static void Mod_Decompile_f(void)
        if (mod->surfmesh.num_triangles)
        {
                dpsnprintf(outname, sizeof(outname), "%s_decompiled.obj", basename);
-               Mod_Decompile_OBJ(mod, outname, inname);
+               dpsnprintf(mtlname, sizeof(mtlname), "%s_decompiled.mtl", basename);
+               Mod_Decompile_OBJ(mod, outname, mtlname, inname);
        }
 
        // export SMD if possible (only for skeletal models)
-       if (mod->surfmesh.num_triangles && mod->num_poses)
+       if (mod->surfmesh.num_triangles && mod->num_bones)
        {
                dpsnprintf(outname, sizeof(outname), "%s_decompiled/ref1.smd", basename);
                Mod_Decompile_SMD(mod, outname, 0, 1, true);
-               l = dpsnprintf(textbuffer + textsize, sizeof(textbuffer) - textsize, "outputdir .\nmodel out\nscale 1\norigin 0 0 0\nscene ref1.smd\n");
-               if (l > 0) textsize += l;
+               l = dpsnprintf(zymtextbuffer + zymtextsize, sizeof(zymtextbuffer) - zymtextsize, "output out.zym\nscale 1\norigin 0 0 0\nmesh ref1.smd\n");
+               if (l > 0) zymtextsize += l;
+               l = dpsnprintf(dpmtextbuffer + dpmtextsize, sizeof(dpmtextbuffer) - dpmtextsize, "outputdir .\nmodel out\nscale 1\norigin 0 0 0\nscene ref1.smd\n");
+               if (l > 0) dpmtextsize += l;
                for (i = 0;i < mod->numframes;i = j)
                {
                        strlcpy(animname, mod->animscenes[i].name, sizeof(animname));
@@ -2538,14 +2626,21 @@ static void Mod_Decompile_f(void)
                        }
                        dpsnprintf(outname, sizeof(outname), "%s_decompiled/%s.smd", basename, animname);
                        Mod_Decompile_SMD(mod, outname, first, count, false);
-                       if (textsize < (int)sizeof(textbuffer) - 100)
+                       if (zymtextsize < (int)sizeof(zymtextbuffer) - 100)
+                       {
+                               l = dpsnprintf(zymtextbuffer + zymtextsize, sizeof(zymtextbuffer) - zymtextsize, "scene %s.smd fps %g\n", animname, mod->animscenes[i].framerate);
+                               if (l > 0) zymtextsize += l;
+                       }
+                       if (dpmtextsize < (int)sizeof(dpmtextbuffer) - 100)
                        {
-                               l = dpsnprintf(textbuffer + textsize, sizeof(textbuffer) - textsize, "scene %s.smd\n", animname);
-                               if (l > 0) textsize += l;
+                               l = dpsnprintf(dpmtextbuffer + dpmtextsize, sizeof(dpmtextbuffer) - dpmtextsize, "scene %s.smd\n", animname);
+                               if (l > 0) dpmtextsize += l;
                        }
                }
-               if (textsize)
-                       FS_WriteFile(va("%s_decompiled/out.txt", basename), textbuffer, (fs_offset_t)textsize);
+               if (zymtextsize)
+                       FS_WriteFile(va("%s_decompiled/out_zym.txt", basename), zymtextbuffer, (fs_offset_t)zymtextsize);
+               if (dpmtextsize)
+                       FS_WriteFile(va("%s_decompiled/out_dpm.txt", basename), dpmtextbuffer, (fs_offset_t)dpmtextsize);
        }
 }