Fix problems with last commit.
Fix rbsp not responding to lightstyle0 consistently. Fix q2 not responding to any lightstyles. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5599 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
bfea433dff
commit
73f92fb799
16 changed files with 621 additions and 175 deletions
|
@ -37,7 +37,7 @@ IF (NOT "${FTE_REVISON}" STREQUAL "")
|
||||||
OUTPUT_VARIABLE FTE_DATE
|
OUTPUT_VARIABLE FTE_DATE
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(FTE_REVISON SVNREVISION="${FTE_REVISON}" SVNDATE="${FTE_DATE}")
|
SET(FTE_REVISON SVNREVISION=${FTE_REVISON} SVNDATE="${FTE_DATE}")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ IF(BZIP2_FOUND)
|
||||||
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};AVAIL_BZLIB;BZLIB_STATIC)
|
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};AVAIL_BZLIB;BZLIB_STATIC)
|
||||||
SET(FTE_LIBS ${FTE_LIBS} bz2)
|
SET(FTE_LIBS ${FTE_LIBS} bz2)
|
||||||
SET(FTESV_LIBS ${FTESV_LIBS} bz2)
|
SET(FTESV_LIBS ${FTESV_LIBS} bz2)
|
||||||
MESSAGE(STATUS "bzip2 library found. bz2-compressed pk3s will work for the price of extra bloat! yay!")
|
# MESSAGE(STATUS "bzip2 library found. bz2-compressed pk3s will work for the price of extra bloat! yay!")
|
||||||
ELSE()
|
ELSE()
|
||||||
MESSAGE(WARNING "bzip2 library NOT available. bz2-compressed pk3s will not be available, as if anyone cares.")
|
MESSAGE(WARNING "bzip2 library NOT available. bz2-compressed pk3s will not be available, as if anyone cares.")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
@ -262,6 +262,10 @@ ELSEIF(${UNIX}) #linux(ish)
|
||||||
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11_CURSOR)
|
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11_CURSOR)
|
||||||
MESSAGE(WARNING "Xcursor library NOT available.")
|
MESSAGE(WARNING "Xcursor library NOT available.")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
IF (NOT X11_Xrandr_FOUND)
|
||||||
|
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11_RANDR)
|
||||||
|
MESSAGE(WARNING "Xrandr library NOT available.")
|
||||||
|
ENDIF()
|
||||||
ELSE()
|
ELSE()
|
||||||
MESSAGE(WARNING "x11 library NOT available.")
|
MESSAGE(WARNING "x11 library NOT available.")
|
||||||
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11)
|
SET(FTE_LIB_DEFINES ${FTE_LIB_DEFINES};NO_X11)
|
||||||
|
|
|
@ -4461,7 +4461,7 @@ static void CLQ2_ParseConfigString (void)
|
||||||
}
|
}
|
||||||
else if (i >= Q2CS_LIGHTS && i < Q2CS_LIGHTS+Q2MAX_LIGHTSTYLES)
|
else if (i >= Q2CS_LIGHTS && i < Q2CS_LIGHTS+Q2MAX_LIGHTSTYLES)
|
||||||
{
|
{
|
||||||
R_UpdateLightStyle(i, s, 1, 1, 1);
|
R_UpdateLightStyle(i-Q2CS_LIGHTS, s, 1, 1, 1);
|
||||||
}
|
}
|
||||||
else if (i == Q2CS_CDTRACK)
|
else if (i == Q2CS_CDTRACK)
|
||||||
{
|
{
|
||||||
|
|
|
@ -236,9 +236,9 @@ static qboolean Mod_LoadMap_Proc(model_t *model, char *data)
|
||||||
b[surf].lightmap[2] = -1;
|
b[surf].lightmap[2] = -1;
|
||||||
b[surf].lightmap[3] = -1;
|
b[surf].lightmap[3] = -1;
|
||||||
b[surf].lmlightstyle[0] = 0;
|
b[surf].lmlightstyle[0] = 0;
|
||||||
b[surf].lmlightstyle[1] = 255;
|
b[surf].lmlightstyle[1] = INVALID_LIGHTSTYLE;
|
||||||
b[surf].lmlightstyle[2] = 255;
|
b[surf].lmlightstyle[2] = INVALID_LIGHTSTYLE;
|
||||||
b[surf].lmlightstyle[3] = 255;
|
b[surf].lmlightstyle[3] = INVALID_LIGHTSTYLE;
|
||||||
|
|
||||||
data = COM_ParseOut(data, token, sizeof(token));
|
data = COM_ParseOut(data, token, sizeof(token));
|
||||||
b[surf].shader = R_RegisterShader_Vertex(token);
|
b[surf].shader = R_RegisterShader_Vertex(token);
|
||||||
|
|
|
@ -3199,12 +3199,16 @@ static qboolean CModQ3_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
|
||||||
|
|
||||||
out->light_s[0] = LittleLong(in->lightmap_x);
|
out->light_s[0] = LittleLong(in->lightmap_x);
|
||||||
out->light_t[0] = LittleLong(in->lightmap_y);
|
out->light_t[0] = LittleLong(in->lightmap_y);
|
||||||
out->styles[0] = 255;
|
out->styles[0] = INVALID_LIGHTSTYLE;
|
||||||
|
out->vlstyles[0] = 255;
|
||||||
for (sty = 1; sty < MAXRLIGHTMAPS; sty++)
|
for (sty = 1; sty < MAXRLIGHTMAPS; sty++)
|
||||||
{
|
{
|
||||||
out->styles[sty] = 255;
|
out->styles[sty] = INVALID_LIGHTSTYLE;
|
||||||
|
out->vlstyles[sty] = 255;
|
||||||
out->lightmaptexturenums[sty] = -1;
|
out->lightmaptexturenums[sty] = -1;
|
||||||
}
|
}
|
||||||
|
for (; sty < MAXQ1LIGHTMAPS; sty++)
|
||||||
|
out->styles[sty] = INVALID_LIGHTSTYLE;
|
||||||
out->lmshift = LMSHIFT_DEFAULT;
|
out->lmshift = LMSHIFT_DEFAULT;
|
||||||
//fixme: determine texturemins from lightmap_origin
|
//fixme: determine texturemins from lightmap_origin
|
||||||
out->extents[0] = (LittleLong(in->lightmap_width)-1)<<out->lmshift;
|
out->extents[0] = (LittleLong(in->lightmap_width)-1)<<out->lmshift;
|
||||||
|
@ -3315,11 +3319,14 @@ static qboolean CModRBSP_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
|
||||||
out->lightmaptexturenums[j] = LittleLong(in->lightmapnum[j]);
|
out->lightmaptexturenums[j] = LittleLong(in->lightmapnum[j]);
|
||||||
out->light_s[j] = LittleLong(in->lightmap_offs[0][j]);
|
out->light_s[j] = LittleLong(in->lightmap_offs[0][j]);
|
||||||
out->light_t[j] = LittleLong(in->lightmap_offs[1][j]);
|
out->light_t[j] = LittleLong(in->lightmap_offs[1][j]);
|
||||||
out->styles[j] = in->lm_styles[j];
|
out->styles[j] = (in->lm_styles[j]!=255)?in->lm_styles[j]:INVALID_LIGHTSTYLE;
|
||||||
|
out->vlstyles[j] = in->vt_styles[j];
|
||||||
|
|
||||||
if (mod->lightmaps.count < out->lightmaptexturenums[j]+1)
|
if (mod->lightmaps.count < out->lightmaptexturenums[j]+1)
|
||||||
mod->lightmaps.count = out->lightmaptexturenums[j]+1;
|
mod->lightmaps.count = out->lightmaptexturenums[j]+1;
|
||||||
}
|
}
|
||||||
|
for (; j < MAXQ1LIGHTMAPS; j++)
|
||||||
|
out->styles[j] = INVALID_LIGHTSTYLE;
|
||||||
if (facetype == MST_FLARE)
|
if (facetype == MST_FLARE)
|
||||||
out->texinfo = mod->texinfo + mod->numtexinfo*2;
|
out->texinfo = mod->texinfo + mod->numtexinfo*2;
|
||||||
else if (out->lightmaptexturenums[0]<0 || r_vertexlight.value)
|
else if (out->lightmaptexturenums[0]<0 || r_vertexlight.value)
|
||||||
|
|
|
@ -3641,7 +3641,7 @@ static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu
|
||||||
for (j = 0; j < MAXRLIGHTMAPS ; j++)
|
for (j = 0; j < MAXRLIGHTMAPS ; j++)
|
||||||
{
|
{
|
||||||
s = shaderstate.curbatch->lmlightstyle[j];
|
s = shaderstate.curbatch->lmlightstyle[j];
|
||||||
if (s == 255)
|
if (s == INVALID_LIGHTSTYLE)
|
||||||
{
|
{
|
||||||
for (; j < MAXRLIGHTMAPS ; j++)
|
for (; j < MAXRLIGHTMAPS ; j++)
|
||||||
{
|
{
|
||||||
|
@ -3672,6 +3672,7 @@ static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
unsigned short s;
|
||||||
if (shaderstate.curentity->model && (shaderstate.curentity->model->engineflags & MDLF_NEEDOVERBRIGHT) && !shaderstate.force2d)
|
if (shaderstate.curentity->model && (shaderstate.curentity->model->engineflags & MDLF_NEEDOVERBRIGHT) && !shaderstate.force2d)
|
||||||
{
|
{
|
||||||
float sc = (1<<bound(0, gl_overbright.ival, 2)) * shaderstate.identitylighting;
|
float sc = (1<<bound(0, gl_overbright.ival, 2)) * shaderstate.identitylighting;
|
||||||
|
@ -3682,6 +3683,10 @@ static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu
|
||||||
Vector4Set(param4, shaderstate.identitylighting, shaderstate.identitylighting, shaderstate.identitylighting, 1);
|
Vector4Set(param4, shaderstate.identitylighting, shaderstate.identitylighting, shaderstate.identitylighting, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s = shaderstate.curbatch->lmlightstyle[0]; //only one style.
|
||||||
|
if (s != INVALID_LIGHTSTYLE)
|
||||||
|
VectorScale(param4, d_lightstylevalue[s]/256.0f, param4);
|
||||||
|
|
||||||
qglUniform4fvARB(ph, 1, (GLfloat*)param4);
|
qglUniform4fvARB(ph, 1, (GLfloat*)param4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -161,10 +161,8 @@ static void Mod_BatchList_f(void)
|
||||||
else if (batch->lightmap[1] >= 0)
|
else if (batch->lightmap[1] >= 0)
|
||||||
Con_Printf("^2 lm=(%i:%i %i:%i)", batch->lightmap[0], batch->lmlightstyle[0], batch->lightmap[1], batch->lmlightstyle[1]);
|
Con_Printf("^2 lm=(%i:%i %i:%i)", batch->lightmap[0], batch->lmlightstyle[0], batch->lightmap[1], batch->lmlightstyle[1]);
|
||||||
else
|
else
|
||||||
if (batch->lightmap[1] >= 0)
|
|
||||||
#else
|
|
||||||
if (batch->lmlightstyle[0] != 255)
|
|
||||||
#endif
|
#endif
|
||||||
|
if (batch->lmlightstyle[0] != INVALID_LIGHTSTYLE)
|
||||||
Con_Printf("^2 lm=(%i:%i)", batch->lightmap[0], batch->lmlightstyle[0]);
|
Con_Printf("^2 lm=(%i:%i)", batch->lightmap[0], batch->lmlightstyle[0]);
|
||||||
else
|
else
|
||||||
Con_Printf("^2 lm=%i", batch->lightmap[0]);
|
Con_Printf("^2 lm=%i", batch->lightmap[0]);
|
||||||
|
@ -3255,7 +3253,7 @@ static void Mod_Batches_AllocLightmaps(model_t *mod)
|
||||||
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
|
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
|
||||||
{
|
{
|
||||||
batch->lightmap[sty] = surf->lightmaptexturenums[sty];
|
batch->lightmap[sty] = surf->lightmaptexturenums[sty];
|
||||||
batch->lmlightstyle[sty] = 255;//don't do special backend rendering of lightstyles.
|
batch->lmlightstyle[sty] = INVALID_LIGHTSTYLE;//don't do special backend rendering of lightstyles.
|
||||||
batch->vtlightstyle[sty] = 255;//don't do special backend rendering of lightstyles.
|
batch->vtlightstyle[sty] = 255;//don't do special backend rendering of lightstyles.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -731,6 +731,7 @@ reeval:
|
||||||
st = &pr_statements[s];
|
st = &pr_statements[s];
|
||||||
if (prinst.pr_depth == prinst.exitdepth)
|
if (prinst.pr_depth == prinst.exitdepth)
|
||||||
{
|
{
|
||||||
|
prinst.pr_xstatement = s;
|
||||||
return -1; // all done
|
return -1; // all done
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
|
|
@ -1552,7 +1552,7 @@ void PR_Init(void)
|
||||||
Cmd_AddCommand ("extensionlist_ssqc", PR_SVExtensionList_f);
|
Cmd_AddCommand ("extensionlist_ssqc", PR_SVExtensionList_f);
|
||||||
Cmd_AddCommand ("pr_dumpplatform", PR_DumpPlatform_f);
|
Cmd_AddCommand ("pr_dumpplatform", PR_DumpPlatform_f);
|
||||||
|
|
||||||
Cmd_AddCommand ("sv_lightstyle", PR_Lightstyle_f);
|
Cmd_AddCommandD ("sv_lightstyle", PR_Lightstyle_f, "Overrides lightstyles from the server's console, mostly for debug use.");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
@ -4721,11 +4721,31 @@ static void QCBUILTIN PF_lightstyle (pubprogfuncs_t *prinst, struct globalvars_s
|
||||||
static void PR_Lightstyle_f(void)
|
static void PR_Lightstyle_f(void)
|
||||||
{
|
{
|
||||||
int style = atoi(Cmd_Argv(1));
|
int style = atoi(Cmd_Argv(1));
|
||||||
if (svs.gametype != GT_PROGS && svs.gametype != GT_Q1QVM)
|
|
||||||
Con_TPrintf ("not supported in the current game mode.\n");
|
if (!SV_MayCheat())
|
||||||
else if (!SV_MayCheat())
|
|
||||||
Con_TPrintf ("Please set sv_cheats 1 and restart the map first.\n");
|
Con_TPrintf ("Please set sv_cheats 1 and restart the map first.\n");
|
||||||
else if (Cmd_Argc() <= 2)
|
else switch(svs.gametype)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
Con_TPrintf ("not supported in the current game mode.\n");
|
||||||
|
break;
|
||||||
|
#ifdef Q2SERVER
|
||||||
|
case GT_QUAKE2:
|
||||||
|
if (Cmd_Argc() <= 2)
|
||||||
|
{
|
||||||
|
if ((unsigned)style < (unsigned)Q2MAX_LIGHTSTYLES && Cmd_Argc() >= 2)
|
||||||
|
Con_Printf ("Style %i: %s\n", style, sv.strings.configstring[Q2CS_LIGHTS+style]);
|
||||||
|
else for (style = 0; style < Q2MAX_LIGHTSTYLES; style++)
|
||||||
|
if (sv.strings.configstring[Q2CS_LIGHTS+style])
|
||||||
|
Con_Printf("Style %i: %s\n", style, sv.strings.configstring[Q2CS_LIGHTS+style]);
|
||||||
|
}
|
||||||
|
else if ((unsigned)style < (unsigned)Q2MAX_LIGHTSTYLES)
|
||||||
|
PFQ2_Configstring (Q2CS_LIGHTS+style, Cmd_Argv(2));
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case GT_PROGS:
|
||||||
|
case GT_Q1QVM:
|
||||||
|
if (Cmd_Argc() <= 2)
|
||||||
{
|
{
|
||||||
if (style >= 0 && style < sv.maxlightstyles && Cmd_Argc() >= 2)
|
if (style >= 0 && style < sv.maxlightstyles && Cmd_Argc() >= 2)
|
||||||
Con_Printf("Style %i: %s %g %g %g\n", style, sv.lightstyles[style].str, sv.lightstyles[style].colours[0], sv.lightstyles[style].colours[1], sv.lightstyles[style].colours[2]);
|
Con_Printf("Style %i: %s %g %g %g\n", style, sv.lightstyles[style].str, sv.lightstyles[style].colours[0], sv.lightstyles[style].colours[1], sv.lightstyles[style].colours[2]);
|
||||||
|
@ -4746,6 +4766,8 @@ static void PR_Lightstyle_f(void)
|
||||||
rgb[0] = rgb[1] = rgb[2] = atof(Cmd_Argv(3));
|
rgb[0] = rgb[1] = rgb[2] = atof(Cmd_Argv(3));
|
||||||
PF_applylightstyle(style, Cmd_Argv(2), rgb);
|
PF_applylightstyle(style, Cmd_Argv(2), rgb);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void QCBUILTIN PF_getlightstyle (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
static void QCBUILTIN PF_getlightstyle (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
|
|
@ -1270,6 +1270,7 @@ qboolean SV_FilterImpulse(int imp, int level);
|
||||||
//svq2_game.c
|
//svq2_game.c
|
||||||
qboolean SVQ2_InitGameProgs(void);
|
qboolean SVQ2_InitGameProgs(void);
|
||||||
void VARGS SVQ2_ShutdownGameProgs (void);
|
void VARGS SVQ2_ShutdownGameProgs (void);
|
||||||
|
void VARGS PFQ2_Configstring (int i, const char *val); //for engine cheats.
|
||||||
|
|
||||||
//svq2_ents.c
|
//svq2_ents.c
|
||||||
void SVQ2_BuildClientFrame (client_t *client);
|
void SVQ2_BuildClientFrame (client_t *client);
|
||||||
|
|
|
@ -1538,7 +1538,7 @@ void SV_SendLightstyle(client_t *cl, sizebuf_t *forcemsg, int style, qboolean in
|
||||||
|
|
||||||
if (!(cl->fteprotocolextensions & PEXT_LIGHTSTYLECOL))
|
if (!(cl->fteprotocolextensions & PEXT_LIGHTSTYLECOL))
|
||||||
{ //if they don't support it then just drop the extra colours, so long as it still makes sense.
|
{ //if they don't support it then just drop the extra colours, so long as it still makes sense.
|
||||||
if ((flags & ~0x87u) || (ISNQCLIENT(cl) && !ISDPCLIENT(cl) && !cl->fteprotocolextensions2))
|
if ((flags & ~0x87u) && (ISNQCLIENT(cl) && !ISDPCLIENT(cl) && cl->fteprotocolextensions2))
|
||||||
{
|
{
|
||||||
char *text = va("//ls %i \"%s\" %g %g %g\n", style, sv.lightstyles[style].str, sv.lightstyles[style].colours[0], sv.lightstyles[style].colours[1], sv.lightstyles[style].colours[2]);
|
char *text = va("//ls %i \"%s\" %g %g %g\n", style, sv.lightstyles[style].str, sv.lightstyles[style].colours[0], sv.lightstyles[style].colours[1], sv.lightstyles[style].colours[2]);
|
||||||
if (forcemsg)
|
if (forcemsg)
|
||||||
|
@ -1551,7 +1551,9 @@ void SV_SendLightstyle(client_t *cl, sizebuf_t *forcemsg, int style, qboolean in
|
||||||
ClientReliable_FinishWrite(cl);
|
ClientReliable_FinishWrite(cl);
|
||||||
return; //erk, can't handle this!
|
return; //erk, can't handle this!
|
||||||
}
|
}
|
||||||
flags = 7;
|
if (style >= ((cl->fteprotocolextensions2||ISDPCLIENT(cl))?255:64))
|
||||||
|
return; //client probably doesn't support this lightstyle.
|
||||||
|
flags = 7; //force vanilla protocol as fallback.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forcemsg)
|
if (forcemsg)
|
||||||
|
|
|
@ -291,7 +291,7 @@ PF_Configstring
|
||||||
|
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
static void VARGS PFQ2_Configstring (int i, const char *val)
|
void VARGS PFQ2_Configstring (int i, const char *val)
|
||||||
{
|
{
|
||||||
if (i < 0 || i >= Q2MAX_CONFIGSTRINGS)
|
if (i < 0 || i >= Q2MAX_CONFIGSTRINGS)
|
||||||
Sys_Error ("configstring: bad index %i\n", i);
|
Sys_Error ("configstring: bad index %i\n", i);
|
||||||
|
|
356
imgtool.c
356
imgtool.c
|
@ -4,6 +4,7 @@
|
||||||
#define stderr stdout
|
#define stderr stdout
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <ctype.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -348,11 +349,29 @@ static void ImgTool_FreeMips(struct pendingtextureinfo *mips)
|
||||||
|
|
||||||
sh_config_t sh_config;
|
sh_config_t sh_config;
|
||||||
viddef_t vid;
|
viddef_t vid;
|
||||||
static const char *imagetypename[] = {"2D", "3D", "Cube", "2DArray", "CubemapArray", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"};
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int offset; // Position of the entry in WAD
|
||||||
|
unsigned int dsize; // Size of the entry in WAD file
|
||||||
|
unsigned int size; // Size of the entry in memory
|
||||||
|
char type; // type of entry
|
||||||
|
char cmprs; // Compression. 0 if none.
|
||||||
|
short dummy; // Not used
|
||||||
|
char name[16]; // we use only first 8
|
||||||
|
} wad2entry_t;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char magic[4]; //should be WAD2
|
||||||
|
unsigned int num; //number of entries
|
||||||
|
unsigned int offset; //location of directory
|
||||||
|
} wad2_t;
|
||||||
|
|
||||||
|
static const char *imagetypename[] = {"2D", "3D", "Cube", "2DArray", "CubemapArray", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"};
|
||||||
struct opts_s
|
struct opts_s
|
||||||
{
|
{
|
||||||
int textype;
|
int textype;
|
||||||
|
const char *defaultext; //.dds or whatever when the output's extension is not explicitly given.
|
||||||
unsigned int flags; //image flags to use (affects how textures get interpreted a little)
|
unsigned int flags; //image flags to use (affects how textures get interpreted a little)
|
||||||
unsigned int mipnum; //when exporting to a mipless format, this is the mip level that is actually written. default 0.
|
unsigned int mipnum; //when exporting to a mipless format, this is the mip level that is actually written. default 0.
|
||||||
uploadfmt_t newpixelformat; //try to convert to this pixel format on export.
|
uploadfmt_t newpixelformat; //try to convert to this pixel format on export.
|
||||||
|
@ -376,23 +395,16 @@ static enum uploadfmt ImgTool_ASTCToLDR(uploadfmt_t fmt)
|
||||||
return fmt;
|
return fmt;
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <io.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
static void FS_MakeTempName(char *out, size_t outsize, char *prefix, char *suffix)
|
static void FS_MakeTempName(char *out, size_t outsize, char *prefix, char *suffix)
|
||||||
{
|
{
|
||||||
int fd;
|
static char temp_path[MAX_PATH];
|
||||||
unsigned int n;
|
char temp_file_name[MAX_PATH];
|
||||||
unsigned int s = rand();
|
if (!*temp_path && !GetTempPathA(sizeof(temp_path), temp_path))
|
||||||
for (n = 0; n < 0xffffff; n++)
|
Sys_Error("FS_MakeTempName failed to get temp path\n");
|
||||||
{
|
if (!GetTempFileNameA(temp_path, prefix, 0, temp_file_name))
|
||||||
Q_snprintfz(out, outsize, "/tmp/%s%06x%s", prefix, (n+s)&0xffffff, suffix);
|
|
||||||
fd = _open(out, _O_CREAT | _O_EXCL, _S_IREAD | _S_IWRITE);
|
|
||||||
if (fd == -1)
|
|
||||||
continue;
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Sys_Error("FS_MakeTempName failed\n");
|
Sys_Error("FS_MakeTempName failed\n");
|
||||||
|
|
||||||
|
Q_snprintfz(out, outsize, "%s%s", temp_file_name, suffix);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -402,6 +414,58 @@ static void FS_MakeTempName(char *out, size_t outsize, char *prefix, char *suffi
|
||||||
close(mkstemps(out, strlen(suffix))); //bsd4.3/posix1-2001
|
close(mkstemps(out, strlen(suffix))); //bsd4.3/posix1-2001
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static qboolean ImgTool_HasAlpha(struct pendingtextureinfo *mips)
|
||||||
|
{
|
||||||
|
if (mips->encoding == PTI_RGBA8 || mips->encoding == PTI_BGRA8 || mips->encoding == PTI_LLLA8 || mips->encoding == PTI_RGBA8_SRGB || mips->encoding == PTI_BGRA8_SRGB)
|
||||||
|
{
|
||||||
|
size_t l = 0, pixels, p;
|
||||||
|
qbyte *d;
|
||||||
|
for (l = 0; l < mips->mipcount; l++)
|
||||||
|
{
|
||||||
|
pixels = mips->mip[l].width * mips->mip[l].height * mips->mip[l].depth * 4;
|
||||||
|
d = mips->mip[l].data;
|
||||||
|
d+=3;
|
||||||
|
for (p = 0; p < pixels; p+=4)
|
||||||
|
if (d[p] != 255)
|
||||||
|
return true; //a transparent pixel!
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (mips->encoding == PTI_L8A8 || mips->encoding == PTI_L8A8_SRGB)
|
||||||
|
{
|
||||||
|
size_t l = 0, pixels, p;
|
||||||
|
qbyte *d;
|
||||||
|
for (l = 0; l < mips->mipcount; l++)
|
||||||
|
{
|
||||||
|
pixels = mips->mip[l].width * mips->mip[l].height * mips->mip[l].depth * 2;
|
||||||
|
d = mips->mip[l].data;
|
||||||
|
d+=1;
|
||||||
|
for (p = 0; p < pixels; p+=2)
|
||||||
|
if (d[p] != 255)
|
||||||
|
return true; //a transparent pixel!
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (mips->encoding == PTI_RGBA16)
|
||||||
|
{
|
||||||
|
size_t l = 0, pixels, p;
|
||||||
|
unsigned short *d;
|
||||||
|
for (l = 0; l < mips->mipcount; l++)
|
||||||
|
{
|
||||||
|
pixels = mips->mip[l].width * mips->mip[l].height * mips->mip[l].depth * 4;
|
||||||
|
d = mips->mip[l].data;
|
||||||
|
d+=3;
|
||||||
|
for (p = 0; p < pixels; p+=4)
|
||||||
|
if (d[p] != 0xffff)
|
||||||
|
return true; //a transparent pixel!
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Image_FormatHasAlpha(mips->encoding);
|
||||||
|
}
|
||||||
|
|
||||||
static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inname, struct pendingtextureinfo *mips)
|
static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inname, struct pendingtextureinfo *mips)
|
||||||
{
|
{
|
||||||
struct pendingtextureinfo tmp, *ret;
|
struct pendingtextureinfo tmp, *ret;
|
||||||
|
@ -415,10 +479,10 @@ static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inna
|
||||||
int bb,bw,bh;
|
int bb,bw,bh;
|
||||||
qboolean canktx = false;
|
qboolean canktx = false;
|
||||||
uploadfmt_t targfmt = args->newpixelformat;
|
uploadfmt_t targfmt = args->newpixelformat;
|
||||||
int d,l, layers;
|
int d,l, layers, r;
|
||||||
|
|
||||||
//force it to bc1 if bc2 or bc3 with no alpha channel.
|
//force it to bc1 if bc2 or bc3 with no alpha channel.
|
||||||
if ((targfmt == PTI_BC2_RGBA || targfmt == PTI_BC3_RGBA) && !Image_FormatHasAlpha(mips->encoding))
|
if ((targfmt == PTI_BC2_RGBA || targfmt == PTI_BC3_RGBA) && !ImgTool_HasAlpha(mips))
|
||||||
targfmt = PTI_BC1_RGB;
|
targfmt = PTI_BC1_RGB;
|
||||||
|
|
||||||
if (targfmt >= PTI_ASTC_FIRST && targfmt <= PTI_ASTC_LAST)
|
if (targfmt >= PTI_ASTC_FIRST && targfmt <= PTI_ASTC_LAST)
|
||||||
|
@ -428,12 +492,20 @@ static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inna
|
||||||
}
|
}
|
||||||
else if (targfmt == PTI_BC1_RGB)
|
else if (targfmt == PTI_BC1_RGB)
|
||||||
Q_snprintfz(command, sizeof(command), "nvcompress -bc1%s", (args->flags&IF_TRYBUMP)?"n":"");
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc1%s", (args->flags&IF_TRYBUMP)?"n":"");
|
||||||
|
else if (targfmt == PTI_BC1_RGB_SRGB)
|
||||||
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc1%s -srgb -dds10", (args->flags&IF_TRYBUMP)?"n":"");
|
||||||
else if (targfmt == PTI_BC1_RGBA)
|
else if (targfmt == PTI_BC1_RGBA)
|
||||||
Q_snprintfz(command, sizeof(command), "nvcompress -bc1a");
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc1a");
|
||||||
|
else if (targfmt == PTI_BC1_RGBA_SRGB)
|
||||||
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc1a -srgb -dds10");
|
||||||
else if (targfmt == PTI_BC2_RGBA)
|
else if (targfmt == PTI_BC2_RGBA)
|
||||||
Q_snprintfz(command, sizeof(command), "nvcompress -bc2");
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc2");
|
||||||
|
else if (targfmt == PTI_BC2_RGBA_SRGB)
|
||||||
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc2 -srgb -dds10");
|
||||||
else if (targfmt == PTI_BC3_RGBA)
|
else if (targfmt == PTI_BC3_RGBA)
|
||||||
Q_snprintfz(command, sizeof(command), "nvcompress -bc3%s", (args->flags&IF_TRYBUMP)?"n":"");
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc3%s", (args->flags&IF_TRYBUMP)?"n":"");
|
||||||
|
else if (targfmt == PTI_BC3_RGBA_SRGB)
|
||||||
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc3%s -srgb -dds10", (args->flags&IF_TRYBUMP)?"n":"");
|
||||||
else if (targfmt == PTI_BC4_R8)
|
else if (targfmt == PTI_BC4_R8)
|
||||||
Q_snprintfz(command, sizeof(command), "nvcompress -bc4");
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc4");
|
||||||
else if (targfmt == PTI_BC5_RG8)
|
else if (targfmt == PTI_BC5_RG8)
|
||||||
|
@ -442,6 +514,8 @@ static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inna
|
||||||
Q_snprintfz(command, sizeof(command), "nvcompress -bc6");
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc6");
|
||||||
else if (targfmt == PTI_BC7_RGBA)
|
else if (targfmt == PTI_BC7_RGBA)
|
||||||
Q_snprintfz(command, sizeof(command), "nvcompress -bc7");
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc7");
|
||||||
|
else if (targfmt == PTI_BC7_RGBA_SRGB)
|
||||||
|
Q_snprintfz(command, sizeof(command), "nvcompress -bc7 -srgb");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mips->encoding != targfmt)
|
if (mips->encoding != targfmt)
|
||||||
|
@ -487,8 +561,12 @@ static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inna
|
||||||
Q_strncatz(command, " -hdr", sizeof(command));
|
Q_strncatz(command, " -hdr", sizeof(command));
|
||||||
if (targfmt >= PTI_BC1_RGB && targfmt <= PTI_BC7_RGBA_SRGB && (strstr(inname, "_n.")||strstr(inname, "_norm.")))
|
if (targfmt >= PTI_BC1_RGB && targfmt <= PTI_BC7_RGBA_SRGB && (strstr(inname, "_n.")||strstr(inname, "_norm.")))
|
||||||
Q_strncatz(command, " -normal", sizeof(command)); //looks like a normalmap... tweak metrics to favour normalised results.
|
Q_strncatz(command, " -normal", sizeof(command)); //looks like a normalmap... tweak metrics to favour normalised results.
|
||||||
Q_strncatz(command, ">> /dev/null", sizeof(command));
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
Q_strncatz(command, "> NUL 2>&1", sizeof(command));
|
||||||
|
#else
|
||||||
|
Q_strncatz(command, ">> /dev/null", sizeof(command));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!canktx)
|
if (!canktx)
|
||||||
{
|
{
|
||||||
|
@ -549,7 +627,12 @@ static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inna
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
system(command);
|
r = system(command);
|
||||||
|
if (r != EXIT_SUCCESS)
|
||||||
|
{
|
||||||
|
Con_Printf("The following system command failed with code %i: %s\n", r, command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fdata = FS_LoadMallocFile(comp, &fsize);
|
fdata = FS_LoadMallocFile(comp, &fsize);
|
||||||
ret = Image_LoadMipsFromMemory(IF_NOMIPMAP, comp, comp, fdata, fsize);
|
ret = Image_LoadMipsFromMemory(IF_NOMIPMAP, comp, comp, fdata, fsize);
|
||||||
|
@ -608,7 +691,7 @@ const char *COM_GetFileExtension (const char *in, const char *term)
|
||||||
if (*dot == '.')
|
if (*dot == '.')
|
||||||
return dot;
|
return dot;
|
||||||
}
|
}
|
||||||
return "";
|
return term+strlen(term);
|
||||||
}
|
}
|
||||||
static struct pendingtextureinfo *ImgTool_Read(struct opts_s *args, const char *inname)
|
static struct pendingtextureinfo *ImgTool_Read(struct opts_s *args, const char *inname)
|
||||||
{
|
{
|
||||||
|
@ -845,9 +928,21 @@ static struct pendingtextureinfo *ImgTool_Combine(struct opts_s *args, const cha
|
||||||
static void ImgTool_Convert(struct opts_s *args, struct pendingtextureinfo *in, const char *inname, const char *outname)
|
static void ImgTool_Convert(struct opts_s *args, struct pendingtextureinfo *in, const char *inname, const char *outname)
|
||||||
{
|
{
|
||||||
size_t k;
|
size_t k;
|
||||||
const char *outext = COM_GetFileExtension(outname, NULL);
|
const char *outext;
|
||||||
qboolean allowcompressed = false;
|
qboolean allowcompressed = false;
|
||||||
|
char newout[MAX_OSPATH];
|
||||||
|
|
||||||
|
if (!outname)
|
||||||
|
{
|
||||||
|
outext = COM_GetFileExtension(inname, NULL);
|
||||||
|
k = min(MAX_OSPATH-2-strlen(args->defaultext), outext-inname);
|
||||||
|
memcpy(newout, inname, k);
|
||||||
|
newout[k++] = '.';
|
||||||
|
strcpy(newout+k, args->defaultext);
|
||||||
|
outname = newout;
|
||||||
|
}
|
||||||
|
|
||||||
|
outext = COM_GetFileExtension(outname, NULL);
|
||||||
if (!strcmp(outext, ".dds") || !strcmp(outext, ".ktx"))
|
if (!strcmp(outext, ".dds") || !strcmp(outext, ".ktx"))
|
||||||
allowcompressed = true;
|
allowcompressed = true;
|
||||||
|
|
||||||
|
@ -918,7 +1013,7 @@ static void ImgTool_Convert(struct opts_s *args, struct pendingtextureinfo *in,
|
||||||
/*(k == PTI_L16) ||*/
|
/*(k == PTI_L16) ||*/
|
||||||
(k == PTI_BGR8) || (k == PTI_BGR8) ||
|
(k == PTI_BGR8) || (k == PTI_BGR8) ||
|
||||||
0;
|
0;
|
||||||
if (!sh_config.texfmt[in->encoding])
|
if (!outformats[in->encoding])
|
||||||
{
|
{
|
||||||
Image_ChangeFormat(in, outformats, PTI_INVALID, outname);
|
Image_ChangeFormat(in, outformats, PTI_INVALID, outname);
|
||||||
printf("\t(Exporting as %s)\n", Image_FormatName(in->encoding));
|
printf("\t(Exporting as %s)\n", Image_FormatName(in->encoding));
|
||||||
|
@ -974,6 +1069,35 @@ static void ImgTool_Info(struct opts_s *args, const char *inname)
|
||||||
indata = FS_LoadMallocFile(inname, &fsize);
|
indata = FS_LoadMallocFile(inname, &fsize);
|
||||||
if (!indata)
|
if (!indata)
|
||||||
printf("%s: unable to read\n", inname);
|
printf("%s: unable to read\n", inname);
|
||||||
|
else if (fsize >= sizeof(wad2_t) && indata[0] == 'W' && indata[1] == 'A' && indata[2] == 'D')
|
||||||
|
{
|
||||||
|
const wad2_t *w = (const wad2_t *)indata;
|
||||||
|
const wad2entry_t *e = (const wad2entry_t *)(indata+w->offset);
|
||||||
|
printf("%s: wad%c file with %i entries\n", inname, w->magic[3], w->num);
|
||||||
|
for (m = 0; m < w->num; m++, e++)
|
||||||
|
{
|
||||||
|
switch(e->type)
|
||||||
|
{
|
||||||
|
case 67: //hl...
|
||||||
|
case TYP_MIPTEX:
|
||||||
|
{
|
||||||
|
const miptex_t *mip = (const miptex_t *)(indata+e->offset);
|
||||||
|
/*mip name SHOULD match entry name... but gah!*/
|
||||||
|
if (strcasecmp(e->name, mip->name))
|
||||||
|
printf("\t%16.16s (%s): %u*%u%s\n", e->name, mip->name, mip->width, mip->height, mip->offsets[0]?"":" (external data)");
|
||||||
|
else
|
||||||
|
printf("\t%16.16s: %u*%u%s\n", mip->name, mip->width, mip->height, mip->offsets[0]?"":" (external data)");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYP_PALETTE:
|
||||||
|
printf("\t%16.16s: palette - %u bytes\n", e->name, e->size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("\t%16.16s: ENTRY TYPE %u (%u bytes)\n", e->name, e->type, e->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
in = Image_LoadMipsFromMemory(args->flags, inname, inname, indata, fsize);
|
in = Image_LoadMipsFromMemory(args->flags, inname, inname, indata, fsize);
|
||||||
|
@ -996,6 +1120,7 @@ struct filelist_s
|
||||||
const char **exts;
|
const char **exts;
|
||||||
size_t numfiles;
|
size_t numfiles;
|
||||||
struct {
|
struct {
|
||||||
|
const char *rootpath; //the basepath that was passed to the filelist scan.
|
||||||
char *name;
|
char *name;
|
||||||
size_t baselen; //length up to but not including the filename extension.
|
size_t baselen; //length up to but not including the filename extension.
|
||||||
} *file;
|
} *file;
|
||||||
|
@ -1010,7 +1135,7 @@ static void FileList_Release(struct filelist_s *list)
|
||||||
list->numfiles = 0;
|
list->numfiles = 0;
|
||||||
list->maxfiles = 0;
|
list->maxfiles = 0;
|
||||||
}
|
}
|
||||||
static void FileList_Add(struct filelist_s *list, char *fname)
|
static void FileList_Add(struct filelist_s *list, const char *rootpath, char *fname)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t baselen;
|
size_t baselen;
|
||||||
|
@ -1036,15 +1161,47 @@ static void FileList_Add(struct filelist_s *list, char *fname)
|
||||||
list->maxfiles += 64;
|
list->maxfiles += 64;
|
||||||
list->file = realloc(list->file, sizeof(*list->file)*list->maxfiles);
|
list->file = realloc(list->file, sizeof(*list->file)*list->maxfiles);
|
||||||
}
|
}
|
||||||
|
list->file[i].rootpath = rootpath;
|
||||||
list->file[i].name = strdup(fname);
|
list->file[i].name = strdup(fname);
|
||||||
list->file[i].baselen = baselen;
|
list->file[i].baselen = baselen;
|
||||||
list->numfiles++;
|
list->numfiles++;
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static void ImgTool_TreeScan(struct filelist_s *list, const char *basepath, const char *subpath)
|
static void ImgTool_TreeScan(struct filelist_s *list, const char *rootpath, const char *subpath)
|
||||||
|
{ //FIXME: convert to utf-8.
|
||||||
|
HANDLE h;
|
||||||
|
WIN32_FIND_DATAA fd;
|
||||||
|
char file[MAX_OSPATH];
|
||||||
|
|
||||||
|
if (subpath && *subpath)
|
||||||
|
Q_snprintfz(file, sizeof(file), "%s/%s", rootpath, subpath);
|
||||||
|
else
|
||||||
|
Q_snprintfz(file, sizeof(file), "%s", rootpath);
|
||||||
|
if (GetFileAttributesA(file) & FILE_ATTRIBUTE_DIRECTORY) //if its a directory then scan it.
|
||||||
|
Q_snprintfz(file+strlen(file), sizeof(file)-strlen(file), "/*");
|
||||||
|
|
||||||
|
h = FindFirstFileA(file, &fd);
|
||||||
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
(void)FileList_Add;
|
do
|
||||||
Con_Printf("ImgTool_TreeScan not implemented on windows.\n");
|
{
|
||||||
|
if (*fd.cFileName == '.')
|
||||||
|
continue; //skip .. (and unix hidden files, because urgh)
|
||||||
|
|
||||||
|
if (subpath && *subpath)
|
||||||
|
Q_snprintfz(file, sizeof(file), "%s/%s", subpath, fd.cFileName);
|
||||||
|
else
|
||||||
|
Q_snprintfz(file, sizeof(file), "%s", fd.cFileName);
|
||||||
|
|
||||||
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||||
|
; //don't report hidden entries.
|
||||||
|
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
ImgTool_TreeScan(list, rootpath, file);
|
||||||
|
else
|
||||||
|
FileList_Add(list, rootpath, file);
|
||||||
|
} while(FindNextFileA(h, &fd));
|
||||||
|
FindClose(h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
@ -1088,13 +1245,13 @@ static void ImgTool_TreeScan(struct filelist_s *list, const char *basepath, cons
|
||||||
Q_snprintfz(file, sizeof(file), "%s/%s", subpath, ent->d_name);
|
Q_snprintfz(file, sizeof(file), "%s/%s", subpath, ent->d_name);
|
||||||
else
|
else
|
||||||
Q_snprintfz(file, sizeof(file), "%s", ent->d_name);
|
Q_snprintfz(file, sizeof(file), "%s", ent->d_name);
|
||||||
FileList_Add(list, file);
|
FileList_Add(list, basepath, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
static void ImgTool_TreeConvert(struct opts_s *args, const char *srcpath, const char *destpath)
|
static void ImgTool_TreeConvert(struct opts_s *args, const char *destpath, const char *srcpath)
|
||||||
{
|
{
|
||||||
size_t newfiles=0, skippedfiles=0, processedfiles=0;
|
size_t newfiles=0, skippedfiles=0, processedfiles=0;
|
||||||
char file[MAX_OSPATH];
|
char file[MAX_OSPATH];
|
||||||
|
@ -1145,25 +1302,55 @@ static void ImgTool_TreeConvert(struct opts_s *args, const char *srcpath, const
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void ImgTool_WadExtract(struct opts_s *args, const char *wadname)
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
unsigned int offset; // Position of the entry in WAD
|
qbyte *indata;
|
||||||
unsigned int dsize; // Size of the entry in WAD file
|
size_t fsize;
|
||||||
unsigned int size; // Size of the entry in memory
|
size_t m;
|
||||||
char type; // type of entry
|
indata = FS_LoadMallocFile(wadname, &fsize);
|
||||||
char cmprs; // Compression. 0 if none.
|
if (!indata)
|
||||||
short dummy; // Not used
|
printf("%s: unable to read\n", wadname);
|
||||||
char name[16]; // we use only first 8
|
else if (fsize >= sizeof(wad2_t) && indata[0] == 'W' && indata[1] == 'A' && indata[2] == 'D')
|
||||||
} wad2entry_t;
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
char magic[4]; //should be WAD2
|
const wad2_t *w = (const wad2_t *)indata;
|
||||||
unsigned int num; //number of entries
|
const wad2entry_t *e = (const wad2entry_t *)(indata+w->offset);
|
||||||
unsigned int offset; //location of directory
|
|
||||||
} wad2_t;
|
for (m = 0; m < w->num; m++, e++)
|
||||||
static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const char *destpath, int wadtype/*x,2,3*/)
|
{
|
||||||
|
switch(e->type)
|
||||||
|
{
|
||||||
|
case 67: //hl...
|
||||||
|
case TYP_MIPTEX:
|
||||||
|
{
|
||||||
|
miptex_t *mip = (miptex_t *)(indata+e->offset);
|
||||||
|
struct pendingtextureinfo *out = Z_Malloc(sizeof(*out));
|
||||||
|
|
||||||
|
out->encoding = PTI_P8;
|
||||||
|
out->type = PTI_2D;
|
||||||
|
for (out->mipcount = 0; out->mipcount < 4 && mip->offsets[out->mipcount]; out->mipcount++)
|
||||||
|
{
|
||||||
|
out->mip[out->mipcount].width = mip->width>>out->mipcount;
|
||||||
|
out->mip[out->mipcount].height = mip->height>>out->mipcount;
|
||||||
|
out->mip[out->mipcount].depth = 1;
|
||||||
|
out->mip[out->mipcount].datasize = out->mip[out->mipcount].width*out->mip[out->mipcount].height*out->mip[out->mipcount].depth;
|
||||||
|
out->mip[out->mipcount].data = (char*)mip + mip->offsets[out->mipcount];
|
||||||
|
}
|
||||||
|
if (*mip->name == '*')
|
||||||
|
*mip->name = '#'; //convert from * to #, so its a valid file name.
|
||||||
|
ImgTool_Convert(args, out, mip->name, NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYP_PALETTE:
|
||||||
|
default:
|
||||||
|
printf("skipping %s\n", e->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("%s: does not appear to be a wad file\n", wadname);
|
||||||
|
}
|
||||||
|
static void ImgTool_WadConvert(struct opts_s *args, const char *destpath, const char **srcpaths, size_t numpaths, int wadtype/*x,2,3*/)
|
||||||
{
|
{
|
||||||
char file[MAX_OSPATH];
|
char file[MAX_OSPATH];
|
||||||
const char *exts[] = {".png", ".bmp", ".tga", ".exr", ".hdr", ".dds", ".ktx", ".xcf", ".pcx", ".jpg", NULL};
|
const char *exts[] = {".png", ".bmp", ".tga", ".exr", ".hdr", ".dds", ".ktx", ".xcf", ".pcx", ".jpg", NULL};
|
||||||
|
@ -1179,7 +1366,16 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
||||||
miptex_t mip;
|
miptex_t mip;
|
||||||
qboolean wadpixelformats[PTI_MAX] = {0};
|
qboolean wadpixelformats[PTI_MAX] = {0};
|
||||||
wadpixelformats[PTI_P8] = true;
|
wadpixelformats[PTI_P8] = true;
|
||||||
ImgTool_TreeScan(&list, srcpath, NULL);
|
if (!numpaths)
|
||||||
|
ImgTool_TreeScan(&list, ".", NULL);
|
||||||
|
else while(numpaths --> 0)
|
||||||
|
ImgTool_TreeScan(&list, *srcpaths++, NULL);
|
||||||
|
|
||||||
|
if (!list.numfiles)
|
||||||
|
{
|
||||||
|
printf("%s: No files specified\n", destpath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
f = FS_OpenVFS(destpath, "wb", FS_SYSTEM);
|
f = FS_OpenVFS(destpath, "wb", FS_SYSTEM);
|
||||||
wad2.magic[0] = 'W';
|
wad2.magic[0] = 'W';
|
||||||
|
@ -1194,9 +1390,26 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
||||||
for (u = 1; u < countof(sh_config.texfmt); u++)
|
for (u = 1; u < countof(sh_config.texfmt); u++)
|
||||||
sh_config.texfmt[u] = (u==PTI_RGBA8)||(u==PTI_RGBX8)||(u==PTI_P8);
|
sh_config.texfmt[u] = (u==PTI_RGBA8)||(u==PTI_RGBX8)||(u==PTI_P8);
|
||||||
|
|
||||||
|
if (wadtype == 2)
|
||||||
|
{ //WAD2 files generally have a palette lump.
|
||||||
|
if (wad2.num == maxentries)
|
||||||
|
{
|
||||||
|
maxentries += 64;
|
||||||
|
wadentries = realloc(wadentries, sizeof(*wadentries)*maxentries);
|
||||||
|
}
|
||||||
|
entry = &wadentries[wad2.num++];
|
||||||
|
memset(entry, 0, sizeof(*entry));
|
||||||
|
Q_strncpyz(entry->name, "PALETTE", 16);
|
||||||
|
entry->type = TYP_PALETTE;
|
||||||
|
entry->offset = VFS_TELL(f);
|
||||||
|
|
||||||
|
//and the lump data.
|
||||||
|
VFS_WRITE(f, host_basepal, 256*3);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < list.numfiles; i++)
|
for (i = 0; i < list.numfiles; i++)
|
||||||
{
|
{
|
||||||
Q_snprintfz(file, sizeof(file), "%s/%s", srcpath, list.file[i].name);
|
Q_snprintfz(file, sizeof(file), "%s/%s", list.file[i].rootpath, list.file[i].name);
|
||||||
inname = list.file[i].name;
|
inname = list.file[i].name;
|
||||||
if (list.file[i].baselen > 15)
|
if (list.file[i].baselen > 15)
|
||||||
{
|
{
|
||||||
|
@ -1204,7 +1417,9 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
indata = FS_LoadMallocFile(file, &fsize);
|
indata = FS_LoadMallocFile(file, &fsize);
|
||||||
if (indata)
|
if (!indata)
|
||||||
|
printf("Unable to open %s\n", inname);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
struct pendingtextureinfo *in = Image_LoadMipsFromMemory(args->flags, inname, file, indata, fsize);
|
struct pendingtextureinfo *in = Image_LoadMipsFromMemory(args->flags, inname, file, indata, fsize);
|
||||||
Image_GenerateMips(in, args->flags);
|
Image_GenerateMips(in, args->flags);
|
||||||
|
@ -1276,6 +1491,13 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
||||||
entry->name[list.file[i].baselen] = 0; //kill any .tga
|
entry->name[list.file[i].baselen] = 0; //kill any .tga
|
||||||
if (*entry->name == '#')
|
if (*entry->name == '#')
|
||||||
*entry->name = '*'; //* is not valid in a filename, yet needed for turbs, so by convention # is used instead. this is only relevant for the first char.
|
*entry->name = '*'; //* is not valid in a filename, yet needed for turbs, so by convention # is used instead. this is only relevant for the first char.
|
||||||
|
if (wadtype == 3)
|
||||||
|
{
|
||||||
|
for (u = 0; u < sizeof(entry->name); u++)
|
||||||
|
entry->name[u] = toupper(entry->name[u]);
|
||||||
|
entry->type = 67;
|
||||||
|
}
|
||||||
|
else
|
||||||
entry->type = TYP_MIPTEX;
|
entry->type = TYP_MIPTEX;
|
||||||
entry->cmprs = 0;
|
entry->cmprs = 0;
|
||||||
entry->dummy = 0;
|
entry->dummy = 0;
|
||||||
|
@ -1326,6 +1548,7 @@ int main(int argc, const char **argv)
|
||||||
mode_genwadx,
|
mode_genwadx,
|
||||||
mode_genwad2,
|
mode_genwad2,
|
||||||
mode_genwad3,
|
mode_genwad3,
|
||||||
|
mode_extractwad,
|
||||||
} mode = mode_info;
|
} mode = mode_info;
|
||||||
size_t u, f;
|
size_t u, f;
|
||||||
qboolean nomoreopts = false;
|
qboolean nomoreopts = false;
|
||||||
|
@ -1338,6 +1561,7 @@ int main(int argc, const char **argv)
|
||||||
args.newpixelformat = PTI_INVALID;
|
args.newpixelformat = PTI_INVALID;
|
||||||
args.mipnum = 0;
|
args.mipnum = 0;
|
||||||
args.textype = -1;
|
args.textype = -1;
|
||||||
|
args.defaultext = NULL;
|
||||||
|
|
||||||
sh_config.texture2d_maxsize = 1u<<31;
|
sh_config.texture2d_maxsize = 1u<<31;
|
||||||
sh_config.texture3d_maxsize = 1u<<31;
|
sh_config.texture3d_maxsize = 1u<<31;
|
||||||
|
@ -1368,9 +1592,10 @@ showhelp:
|
||||||
Con_Printf("compress : %s --astc_6x6_ldr [--nomips] in.png out.ktx [in2.png out2.ktx]\n", argv[0]);
|
Con_Printf("compress : %s --astc_6x6_ldr [--nomips] in.png out.ktx [in2.png out2.ktx]\n", argv[0]);
|
||||||
Con_Printf("compress : %s --bc3_rgba [--premul] [--nomips] in.png out.dds\n\tConvert pixel format (to bc3 aka dxt5) before writing to output file.\n", argv[0]);
|
Con_Printf("compress : %s --bc3_rgba [--premul] [--nomips] in.png out.dds\n\tConvert pixel format (to bc3 aka dxt5) before writing to output file.\n", argv[0]);
|
||||||
Con_Printf("convert : %s --convert in.exr out.dds\n\tConvert to different file format, while trying to preserve pixel formats.\n", argv[0]);
|
Con_Printf("convert : %s --convert in.exr out.dds\n\tConvert to different file format, while trying to preserve pixel formats.\n", argv[0]);
|
||||||
Con_Printf("recursive : %s --astc_6x6_ldr -r srcdir destdir\n", argv[0]);
|
Con_Printf("recursive : %s --auto --astc_6x6_ldr destdir srcdir\n\tCompresses the files to dds (writing to an optionally different directory)", argv[0]);
|
||||||
Con_Printf("decompress : %s --decompress [--exportmip 0] [--nomips] in.ktx out.png\n\tDecompresses any block-compressed pixel data.\n", argv[0]);
|
Con_Printf("decompress : %s --decompress [--exportmip 0] [--nomips] in.ktx out.png\n\tDecompresses any block-compressed pixel data.\n", argv[0]);
|
||||||
Con_Printf("gen wad : %s --genwad3 [--exportmip 2] srcdir out.wad\n", argv[0]);
|
Con_Printf("create wad : %s -w [--exportmip 2] out.wad srcdir\n", argv[0]);
|
||||||
|
Con_Printf("extract wad: %s -x [--ext png] src.wad\n", argv[0]);
|
||||||
|
|
||||||
Image_PrintInputFormatVersions();
|
Image_PrintInputFormatVersions();
|
||||||
Con_Printf("Supported compressed/interesting pixelformats are:\n");
|
Con_Printf("Supported compressed/interesting pixelformats are:\n");
|
||||||
|
@ -1426,6 +1651,8 @@ showhelp:
|
||||||
mode = mode_genwad2;
|
mode = mode_genwad2;
|
||||||
else if (!files && (!strcmp(argv[u], "-w") || !strcmp(argv[u], "--genwadx")))
|
else if (!files && (!strcmp(argv[u], "-w") || !strcmp(argv[u], "--genwadx")))
|
||||||
mode = mode_genwadx;
|
mode = mode_genwadx;
|
||||||
|
else if (!files && (!strcmp(argv[u], "-x") || !strcmp(argv[u], "--extractwad")))
|
||||||
|
mode = mode_extractwad;
|
||||||
else if (!strcmp(argv[u], "--2d"))
|
else if (!strcmp(argv[u], "--2d"))
|
||||||
args.textype = PTI_2D;
|
args.textype = PTI_2D;
|
||||||
else if (!strcmp(argv[u], "--3d"))
|
else if (!strcmp(argv[u], "--3d"))
|
||||||
|
@ -1444,6 +1671,16 @@ showhelp:
|
||||||
args.flags |= IF_PREMULTIPLYALPHA;
|
args.flags |= IF_PREMULTIPLYALPHA;
|
||||||
else if (!strcmp(argv[u], "--nopremul"))
|
else if (!strcmp(argv[u], "--nopremul"))
|
||||||
args.flags &= ~IF_PREMULTIPLYALPHA;
|
args.flags &= ~IF_PREMULTIPLYALPHA;
|
||||||
|
else if (!strcmp(argv[u], "--ext"))
|
||||||
|
{
|
||||||
|
if (u+1 < argc)
|
||||||
|
args.defaultext = argv[++u];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_Printf("--exportmip requires trailing numeric argument\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (!strcmp(argv[u], "--exportmip"))
|
else if (!strcmp(argv[u], "--exportmip"))
|
||||||
{
|
{
|
||||||
char *e = "erk";
|
char *e = "erk";
|
||||||
|
@ -1480,6 +1717,14 @@ showhelp:
|
||||||
argv[files++] = argv[u];
|
argv[files++] = argv[u];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!args.defaultext)
|
||||||
|
{
|
||||||
|
if (mode == mode_extractwad)
|
||||||
|
args.defaultext = "png"; //something the user expects to be able to view easily (and lossless)
|
||||||
|
else
|
||||||
|
args.defaultext = "ktx";
|
||||||
|
}
|
||||||
|
|
||||||
if (mode == mode_info)
|
if (mode == mode_info)
|
||||||
{ //just print info about each listed file.
|
{ //just print info about each listed file.
|
||||||
for (u = 0; u < files; u++)
|
for (u = 0; u < files; u++)
|
||||||
|
@ -1500,10 +1745,15 @@ showhelp:
|
||||||
}
|
}
|
||||||
else if (mode == mode_autotree && files == 2)
|
else if (mode == mode_autotree && files == 2)
|
||||||
ImgTool_TreeConvert(&args, argv[0], argv[1]);
|
ImgTool_TreeConvert(&args, argv[0], argv[1]);
|
||||||
else if ((mode == mode_genwad2 || mode == mode_genwad3 || mode == mode_genwadx) && files == 2)
|
else if ((mode == mode_genwad2 || mode == mode_genwad3 || mode == mode_genwadx))
|
||||||
ImgTool_WadConvert(&args, argv[0], argv[1], mode-mode_genwadx);
|
ImgTool_WadConvert(&args, argv[0], argv+1, files-1, mode-mode_genwadx);
|
||||||
|
else if ((mode == mode_extractwad) && files == 1)
|
||||||
|
ImgTool_WadExtract(&args, argv[0]);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
printf("%u files\n", (int)files);
|
||||||
|
printf("unsupported arg count for mode\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,6 +326,6 @@ NATIVE_PLUGINS+=ezhud
|
||||||
|
|
||||||
$(PLUG_PREFIX)models$(PLUG_NATIVE_EXT): models/gltf.c models/exportiqm.c models/models.c plugin.c
|
$(PLUG_PREFIX)models$(PLUG_NATIVE_EXT): models/gltf.c models/exportiqm.c models/models.c plugin.c
|
||||||
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Imodels $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
|
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -o $@ -shared $(PLUG_CFLAGS) -Imodels $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
|
||||||
#NATIVE_PLUGINS+=models
|
NATIVE_PLUGINS+=models
|
||||||
|
|
||||||
all: $(foreach FOO,$(NATIVE_PLUGINS), $(PLUG_PREFIX)$(FOO)$(PLUG_NATIVE_EXT))
|
all: $(foreach FOO,$(NATIVE_PLUGINS), $(PLUG_PREFIX)$(FOO)$(PLUG_NATIVE_EXT))
|
||||||
|
|
|
@ -116,17 +116,19 @@ static AVStream *add_video_stream(struct encctx *ctx, AVCodec *codec, int fps, i
|
||||||
int forcewidth = ffmpeg_videoforcewidth->value;
|
int forcewidth = ffmpeg_videoforcewidth->value;
|
||||||
int forceheight = ffmpeg_videoforceheight->value;
|
int forceheight = ffmpeg_videoforceheight->value;
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
|
||||||
|
st = avformat_new_stream(ctx->fc, NULL);
|
||||||
|
if (!st)
|
||||||
|
return NULL;
|
||||||
|
st->id = ctx->fc->nb_streams-1;
|
||||||
|
c = avcodec_alloc_context3(codec);
|
||||||
|
#else
|
||||||
st = avformat_new_stream(ctx->fc, codec);
|
st = avformat_new_stream(ctx->fc, codec);
|
||||||
if (!st)
|
if (!st)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
st->id = ctx->fc->nb_streams-1;
|
|
||||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
|
|
||||||
c = st->codec;
|
c = st->codec;
|
||||||
#else
|
st->id = ctx->fc->nb_streams-1;
|
||||||
c = avcodec_alloc_context3(codec);
|
|
||||||
if(avcodec_parameters_to_context(c, st->codecpar))
|
|
||||||
return NULL;
|
|
||||||
#endif
|
#endif
|
||||||
ctx->video_codec = c;
|
ctx->video_codec = c;
|
||||||
c->codec_id = codec->id;
|
c->codec_id = codec->id;
|
||||||
|
@ -166,7 +168,6 @@ static AVStream *add_video_stream(struct encctx *ctx, AVCodec *codec, int fps, i
|
||||||
if (*ffmpeg_video_crf->string)
|
if (*ffmpeg_video_crf->string)
|
||||||
av_opt_set(c->priv_data, "crf", ffmpeg_video_crf->string, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set(c->priv_data, "crf", ffmpeg_video_crf->string, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
|
||||||
|
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
static void close_video(struct encctx *ctx)
|
static void close_video(struct encctx *ctx)
|
||||||
|
@ -301,18 +302,22 @@ static AVStream *add_audio_stream(struct encctx *ctx, AVCodec *codec, int *sampl
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
int bitrate = ffmpeg_audiobitrate->value;
|
int bitrate = ffmpeg_audiobitrate->value;
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
|
||||||
st = avformat_new_stream(ctx->fc, codec);
|
st = avformat_new_stream(ctx->fc, codec);
|
||||||
if (!st)
|
if (!st)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
st->id = ctx->fc->nb_streams-1;
|
|
||||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
|
|
||||||
c = st->codec;
|
c = st->codec;
|
||||||
#else
|
#else
|
||||||
|
st = avformat_new_stream(ctx->fc, NULL);
|
||||||
|
if (!st)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
c = avcodec_alloc_context3(codec);
|
c = avcodec_alloc_context3(codec);
|
||||||
if(avcodec_parameters_to_context(c, st->codecpar))
|
if(avcodec_parameters_to_context(c, st->codecpar))
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
|
st->id = ctx->fc->nb_streams-1;
|
||||||
ctx->audio_codec = c;
|
ctx->audio_codec = c;
|
||||||
c->codec_id = codec->id;
|
c->codec_id = codec->id;
|
||||||
c->codec_type = codec->type;
|
c->codec_type = codec->type;
|
||||||
|
@ -645,6 +650,16 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
|
||||||
ctx->video_outbuf = av_malloc(ctx->video_outbuf_size);
|
ctx->video_outbuf = av_malloc(ctx->video_outbuf_size);
|
||||||
if (!ctx->video_outbuf)
|
if (!ctx->video_outbuf)
|
||||||
ctx->video_outbuf_size = 0;
|
ctx->video_outbuf_size = 0;
|
||||||
|
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
|
||||||
|
//copy the avcodec parameters over to avformat
|
||||||
|
err = avcodec_parameters_from_context(ctx->video_st->codecpar, c);
|
||||||
|
if(err < 0)
|
||||||
|
{
|
||||||
|
AVEnc_End(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (ctx->audio_st)
|
if (ctx->audio_st)
|
||||||
{
|
{
|
||||||
|
@ -717,9 +732,6 @@ static void AVEnc_End (void *vctx)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
close_video(ctx);
|
|
||||||
close_audio(ctx);
|
|
||||||
|
|
||||||
//don't write trailers if this is an error case and we never even wrote the headers.
|
//don't write trailers if this is an error case and we never even wrote the headers.
|
||||||
if (ctx->doneheaders)
|
if (ctx->doneheaders)
|
||||||
{
|
{
|
||||||
|
@ -728,12 +740,15 @@ static void AVEnc_End (void *vctx)
|
||||||
Con_Printf("Finished writing %s\n", ctx->abspath);
|
Con_Printf("Finished writing %s\n", ctx->abspath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close_video(ctx);
|
||||||
|
close_audio(ctx);
|
||||||
|
|
||||||
for(i = 0; i < ctx->fc->nb_streams; i++)
|
for(i = 0; i < ctx->fc->nb_streams; i++)
|
||||||
av_freep(&ctx->fc->streams[i]);
|
av_freep(&ctx->fc->streams[i]);
|
||||||
// if (!(fmt->flags & AVFMT_NOFILE))
|
// if (!(fmt->flags & AVFMT_NOFILE))
|
||||||
avio_close(ctx->fc->pb);
|
avio_close(ctx->fc->pb);
|
||||||
av_free(ctx->audio_outbuf);
|
av_free(ctx->audio_outbuf);
|
||||||
av_free(ctx->fc);
|
avformat_free_context(ctx->fc);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
static media_encoder_funcs_t encoderfuncs =
|
static media_encoder_funcs_t encoderfuncs =
|
||||||
|
@ -741,7 +756,7 @@ static media_encoder_funcs_t encoderfuncs =
|
||||||
sizeof(media_encoder_funcs_t),
|
sizeof(media_encoder_funcs_t),
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
"Use ffmpeg's various codecs. Various settings are configured with the "ENCODERNAME"_* cvars.",
|
"Use ffmpeg's various codecs. Various settings are configured with the "ENCODERNAME"_* cvars.",
|
||||||
".mp4",
|
".mp4;.*",
|
||||||
AVEnc_Begin,
|
AVEnc_Begin,
|
||||||
AVEnc_Video,
|
AVEnc_Video,
|
||||||
AVEnc_Audio,
|
AVEnc_Audio,
|
||||||
|
|
|
@ -42,7 +42,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "ezquakeisms.h"
|
#include "ezquakeisms.h"
|
||||||
#include "hud.h"
|
#include "hud.h"
|
||||||
|
|
||||||
//#define WITH_PNG
|
//#define WITH_PNG //more WITH_RADAR than anything else.
|
||||||
|
|
||||||
#define draw_disc draw_disc2
|
#define draw_disc draw_disc2
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef GLQUAKE
|
#ifndef GLQUAKE
|
||||||
//#define GLQUAKE //this is shit.
|
#define GLQUAKE //this is shit, but ensures index sizes come out the right size
|
||||||
#endif
|
#endif
|
||||||
#include "quakedef.h"
|
#include "quakedef.h"
|
||||||
#include "../plugin.h"
|
#include "../plugin.h"
|
||||||
|
@ -7,10 +7,38 @@
|
||||||
extern plugmodfuncs_t *modfuncs;
|
extern plugmodfuncs_t *modfuncs;
|
||||||
extern plugfsfuncs_t *filefuncs;
|
extern plugfsfuncs_t *filefuncs;
|
||||||
|
|
||||||
|
#if MAX_INDICIES == 0xffffu
|
||||||
|
#warning 16bit indexes
|
||||||
|
#else
|
||||||
|
#warning 32bit indexes
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SKELETALMODELS
|
#ifdef SKELETALMODELS
|
||||||
#define GLTFMODELS
|
#define GLTFMODELS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*Limitations:
|
||||||
|
materials:
|
||||||
|
material names (when present) are assumed to be either globally unique, or the material attributes must match those of all other materials with the same name.
|
||||||
|
texture modes (like clamp) must match on both axis (either both clamp or both wrap, no mixing)
|
||||||
|
mirrored-repeat not supported
|
||||||
|
mip-mag-mip filters must match (all linear, or all nearest)
|
||||||
|
animations:
|
||||||
|
input framerates are not well-defined. this can result in issues when converting to other formats (especially with stepping anims).
|
||||||
|
morph targets are not supported.
|
||||||
|
total nodes(+joints) must be < MAX_BONES, and ideally <MAX_GPU_BONES too but it is sufficient for that to be per-mesh.
|
||||||
|
meshes:
|
||||||
|
multiple texture coord sets are not supported.
|
||||||
|
additional colours/weights attributes are not supported.
|
||||||
|
multiple meshes with the same material will not be merged.
|
||||||
|
scene:
|
||||||
|
cameras can be parsed, but are not necessarily useful as they are not exposed to the gamecode.
|
||||||
|
extensions:
|
||||||
|
no KHR_draco_mesh_compression
|
||||||
|
unknown extensions will result in warning spam for each occurence.
|
||||||
|
gltf1 is NOT supported, only gltf2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
//'The units for all linear distances are meters.'
|
//'The units for all linear distances are meters.'
|
||||||
//'feh: 1 metre is approx. 26.24671916 qu.'
|
//'feh: 1 metre is approx. 26.24671916 qu.'
|
||||||
|
@ -536,9 +564,6 @@ static size_t JSON_ReadBody(json_t *t, char *out, size_t outsize)
|
||||||
//glTF 1.0 and 2.0 differ in that 1 uses names and 2 uses indexes. There's also some significant differences with materials.
|
//glTF 1.0 and 2.0 differ in that 1 uses names and 2 uses indexes. There's also some significant differences with materials.
|
||||||
//we only support 2.0
|
//we only support 2.0
|
||||||
|
|
||||||
//articulated models are handled by loading them as skeletal (should probably optimise the engine for this usecase)
|
|
||||||
//we don't support skeletal models either right now.
|
|
||||||
|
|
||||||
//buffers are raw blobs that can come from multiple different sources
|
//buffers are raw blobs that can come from multiple different sources
|
||||||
struct gltf_buffer
|
struct gltf_buffer
|
||||||
{
|
{
|
||||||
|
@ -820,6 +845,7 @@ static void GLTF_AccessorToTangents(gltf_t *gltf, vec3_t *norm, vec3_t **sdir, v
|
||||||
char *in = a->data;
|
char *in = a->data;
|
||||||
|
|
||||||
size_t v, c;
|
size_t v, c;
|
||||||
|
float side;
|
||||||
*sdir = os;
|
*sdir = os;
|
||||||
*tdir = ot;
|
*tdir = ot;
|
||||||
if ((a->type&0xff) != 4)
|
if ((a->type&0xff) != 4)
|
||||||
|
@ -833,9 +859,37 @@ static void GLTF_AccessorToTangents(gltf_t *gltf, vec3_t *norm, vec3_t **sdir, v
|
||||||
memset(os, 0, sizeof(*os) * outverts);
|
memset(os, 0, sizeof(*os) * outverts);
|
||||||
memset(ot, 0, sizeof(*ot) * outverts);
|
memset(ot, 0, sizeof(*ot) * outverts);
|
||||||
break;
|
break;
|
||||||
// case 5120: //BYTE
|
case 5120: //BYTE KHR_mesh_quantization (always normalized)
|
||||||
|
for (v = 0; v < outverts; v++)
|
||||||
|
{
|
||||||
|
for (c = 0; c < 3; c++)
|
||||||
|
os[v][c] = max(-1.0, ((signed char*)in)[c] / 127.0); //negative values are larger, but we want to allow 1.0
|
||||||
|
side = max(-1.0, ((signed char*)in)[3] / 127.0);
|
||||||
|
|
||||||
|
//bitangent = cross(normal, tangent.xyz) * tangent.w
|
||||||
|
ot[v][0] = (norm[v][1]*os[v][2] - norm[v][2]*os[v][1]) * side;
|
||||||
|
ot[v][1] = (norm[v][2]*os[v][0] - norm[v][0]*os[v][2]) * side;
|
||||||
|
ot[v][2] = (norm[v][0]*os[v][1] - norm[v][1]*os[v][0]) * side;
|
||||||
|
|
||||||
|
in += a->bytestride;
|
||||||
|
}
|
||||||
|
break;
|
||||||
// case 5121: //UNSIGNED_BYTE
|
// case 5121: //UNSIGNED_BYTE
|
||||||
// case 5122: //SHORT
|
case 5122: //SHORT KHR_mesh_quantization (always normalized)
|
||||||
|
for (v = 0; v < outverts; v++)
|
||||||
|
{
|
||||||
|
for (c = 0; c < 3; c++)
|
||||||
|
os[v][c] = max(-1.0, ((signed short*)in)[c] / 32767.0);
|
||||||
|
side = max(-1.0, ((signed short*)in)[3] / 32767.0);
|
||||||
|
|
||||||
|
//bitangent = cross(normal, tangent.xyz) * tangent.w
|
||||||
|
ot[v][0] = (norm[v][1]*os[v][2] - norm[v][2]*os[v][1]) * side;
|
||||||
|
ot[v][1] = (norm[v][2]*os[v][0] - norm[v][0]*os[v][2]) * side;
|
||||||
|
ot[v][2] = (norm[v][0]*os[v][1] - norm[v][1]*os[v][0]) * side;
|
||||||
|
|
||||||
|
in += a->bytestride;
|
||||||
|
}
|
||||||
|
break;
|
||||||
// case 5123: //UNSIGNED_SHORT
|
// case 5123: //UNSIGNED_SHORT
|
||||||
// case 5125: //UNSIGNED_INT
|
// case 5125: //UNSIGNED_INT
|
||||||
case 5126: //FLOAT
|
case 5126: //FLOAT
|
||||||
|
@ -843,17 +897,19 @@ static void GLTF_AccessorToTangents(gltf_t *gltf, vec3_t *norm, vec3_t **sdir, v
|
||||||
{
|
{
|
||||||
for (c = 0; c < 3; c++)
|
for (c = 0; c < 3; c++)
|
||||||
os[v][c] = ((float*)in)[c];
|
os[v][c] = ((float*)in)[c];
|
||||||
|
side = ((float*)in)[3];
|
||||||
|
|
||||||
//bitangent = cross(normal, tangent.xyz) * tangent.w
|
//bitangent = cross(normal, tangent.xyz) * tangent.w
|
||||||
ot[v][0] = (norm[v][1]*os[v][2] - norm[v][2]*os[v][1]) * ((float*)in)[3];
|
ot[v][0] = (norm[v][1]*os[v][2] - norm[v][2]*os[v][1]) * side;
|
||||||
ot[v][1] = (norm[v][2]*os[v][0] - norm[v][0]*os[v][2]) * ((float*)in)[3];
|
ot[v][1] = (norm[v][2]*os[v][0] - norm[v][0]*os[v][2]) * side;
|
||||||
ot[v][2] = (norm[v][0]*os[v][1] - norm[v][1]*os[v][0]) * ((float*)in)[3];
|
ot[v][2] = (norm[v][0]*os[v][1] - norm[v][1]*os[v][0]) * side;
|
||||||
|
|
||||||
in += a->bytestride;
|
in += a->bytestride;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *GLTF_AccessorToDataF(gltf_t *gltf, size_t outverts, unsigned int outcomponents, struct gltf_accessor *a)
|
static void *GLTF_AccessorToDataF(gltf_t *gltf, size_t outverts, unsigned int outcomponents, struct gltf_accessor *a)
|
||||||
{
|
{
|
||||||
float *ret = modfuncs->ZG_Malloc(&gltf->mod->memgroup, sizeof(*ret) * outcomponents * outverts), *o;
|
float *ret = modfuncs->ZG_Malloc(&gltf->mod->memgroup, sizeof(*ret) * outcomponents * outverts), *o;
|
||||||
|
@ -872,17 +928,46 @@ static void *GLTF_AccessorToDataF(gltf_t *gltf, size_t outverts, unsigned int ou
|
||||||
memset(ret, 0, sizeof(*ret) * outcomponents * outverts);
|
memset(ret, 0, sizeof(*ret) * outcomponents * outverts);
|
||||||
break;
|
break;
|
||||||
case 5120: //BYTE
|
case 5120: //BYTE
|
||||||
|
if (!a->normalized)
|
||||||
|
{ //KHR_mesh_quantization
|
||||||
while(outverts --> 0)
|
while(outverts --> 0)
|
||||||
{
|
{
|
||||||
for (c = 0; c < ic; c++)
|
for (c = 0; c < ic; c++)
|
||||||
o[c] = max(-1.0, ((char*)in)[c] / 127.0); //negative values are larger, but we want to allow 1.0
|
o[c] = ((signed char*)in)[c];
|
||||||
for (; c < outcomponents; c++)
|
for (; c < outcomponents; c++)
|
||||||
o[c] = 0;
|
o[c] = 0;
|
||||||
o += outcomponents;
|
o += outcomponents;
|
||||||
in += a->bytestride;
|
in += a->bytestride;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while(outverts --> 0)
|
||||||
|
{
|
||||||
|
for (c = 0; c < ic; c++)
|
||||||
|
o[c] = max(-1.0, ((signed char*)in)[c] / 127.0); //negative values are larger, but we want to allow 1.0
|
||||||
|
for (; c < outcomponents; c++)
|
||||||
|
o[c] = 0;
|
||||||
|
o += outcomponents;
|
||||||
|
in += a->bytestride;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 5121: //UNSIGNED_BYTE
|
case 5121: //UNSIGNED_BYTE
|
||||||
|
if (!a->normalized)
|
||||||
|
{ //KHR_mesh_quantization
|
||||||
|
while(outverts --> 0)
|
||||||
|
{
|
||||||
|
for (c = 0; c < ic; c++)
|
||||||
|
o[c] = ((unsigned char*)in)[c];
|
||||||
|
for (; c < outcomponents; c++)
|
||||||
|
o[c] = 0;
|
||||||
|
o += outcomponents;
|
||||||
|
in += a->bytestride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
while(outverts --> 0)
|
while(outverts --> 0)
|
||||||
{
|
{
|
||||||
for (c = 0; c < ic; c++)
|
for (c = 0; c < ic; c++)
|
||||||
|
@ -892,8 +977,23 @@ static void *GLTF_AccessorToDataF(gltf_t *gltf, size_t outverts, unsigned int ou
|
||||||
o += outcomponents;
|
o += outcomponents;
|
||||||
in += a->bytestride;
|
in += a->bytestride;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 5122: //SHORT
|
case 5122: //SHORT
|
||||||
|
if (!a->normalized)
|
||||||
|
{ //KHR_mesh_quantization
|
||||||
|
while(outverts --> 0)
|
||||||
|
{
|
||||||
|
for (c = 0; c < ic; c++)
|
||||||
|
o[c] = ((signed short*)in)[c];
|
||||||
|
for (; c < outcomponents; c++)
|
||||||
|
o[c] = 0;
|
||||||
|
o += outcomponents;
|
||||||
|
in += a->bytestride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
while(outverts --> 0)
|
while(outverts --> 0)
|
||||||
{
|
{
|
||||||
for (c = 0; c < ic; c++)
|
for (c = 0; c < ic; c++)
|
||||||
|
@ -903,8 +1003,23 @@ static void *GLTF_AccessorToDataF(gltf_t *gltf, size_t outverts, unsigned int ou
|
||||||
o += outcomponents;
|
o += outcomponents;
|
||||||
in += a->bytestride;
|
in += a->bytestride;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 5123: //UNSIGNED_SHORT
|
case 5123: //UNSIGNED_SHORT
|
||||||
|
if (!a->normalized)
|
||||||
|
{ //KHR_mesh_quantization
|
||||||
|
while(outverts --> 0)
|
||||||
|
{
|
||||||
|
for (c = 0; c < ic; c++)
|
||||||
|
o[c] = ((unsigned short*)in)[c];
|
||||||
|
for (; c < outcomponents; c++)
|
||||||
|
o[c] = 0;
|
||||||
|
o += outcomponents;
|
||||||
|
in += a->bytestride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
while(outverts --> 0)
|
while(outverts --> 0)
|
||||||
{
|
{
|
||||||
for (c = 0; c < ic; c++)
|
for (c = 0; c < ic; c++)
|
||||||
|
@ -914,8 +1029,23 @@ static void *GLTF_AccessorToDataF(gltf_t *gltf, size_t outverts, unsigned int ou
|
||||||
o += outcomponents;
|
o += outcomponents;
|
||||||
in += a->bytestride;
|
in += a->bytestride;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 5125: //UNSIGNED_INT
|
case 5125: //UNSIGNED_INT
|
||||||
|
if (!a->normalized)
|
||||||
|
{ //?!?!?!?!
|
||||||
|
while(outverts --> 0)
|
||||||
|
{
|
||||||
|
for (c = 0; c < ic; c++)
|
||||||
|
o[c] = ((unsigned int*)in)[c];
|
||||||
|
for (; c < outcomponents; c++)
|
||||||
|
o[c] = 0;
|
||||||
|
o += outcomponents;
|
||||||
|
in += a->bytestride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
while(outverts --> 0)
|
while(outverts --> 0)
|
||||||
{
|
{
|
||||||
for (c = 0; c < ic; c++)
|
for (c = 0; c < ic; c++)
|
||||||
|
@ -925,6 +1055,7 @@ static void *GLTF_AccessorToDataF(gltf_t *gltf, size_t outverts, unsigned int ou
|
||||||
o += outcomponents;
|
o += outcomponents;
|
||||||
in += a->bytestride;
|
in += a->bytestride;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 5126: //FLOAT
|
case 5126: //FLOAT
|
||||||
while(outverts --> 0)
|
while(outverts --> 0)
|
||||||
|
@ -997,15 +1128,18 @@ static void *GLTF_AccessorToDataBone(gltf_t *gltf, size_t outverts, struct gltf_
|
||||||
if (ic > outcomponents)
|
if (ic > outcomponents)
|
||||||
ic = outcomponents;
|
ic = outcomponents;
|
||||||
o = ret;
|
o = ret;
|
||||||
|
if (a->normalized)
|
||||||
|
if (gltf->warnlimit --> 0)
|
||||||
|
Con_Printf(CON_WARNING"GLTF_AccessorToDataBone: %s: normalised input\n", gltf->mod->name);
|
||||||
switch(a->componentType)
|
switch(a->componentType)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
if (gltf->warnlimit --> 0)
|
if (gltf->warnlimit --> 0)
|
||||||
Con_Printf(CON_WARNING"GLTF_AccessorToDataUB: %s: glTF2 unsupported componentType (%i)\n", gltf->mod->name, a->componentType);
|
Con_Printf(CON_WARNING"GLTF_AccessorToDataBone: %s: glTF2 unsupported componentType (%i)\n", gltf->mod->name, a->componentType);
|
||||||
case 0:
|
case 0:
|
||||||
memset(ret, 0, sizeof(*ret) * outcomponents * outverts);
|
memset(ret, 0, sizeof(*ret) * outcomponents * outverts);
|
||||||
break;
|
break;
|
||||||
// case 5120: //BYTE
|
case 5120: //BYTE - should not be negative, so ignore sign bit
|
||||||
case 5121: //UNSIGNED_BYTE
|
case 5121: //UNSIGNED_BYTE
|
||||||
while(outverts --> 0)
|
while(outverts --> 0)
|
||||||
{
|
{
|
||||||
|
@ -1021,7 +1155,7 @@ static void *GLTF_AccessorToDataBone(gltf_t *gltf, size_t outverts, struct gltf_
|
||||||
in += a->bytestride;
|
in += a->bytestride;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5122: //SHORT
|
case 5122: //SHORT - should not be negative, so ignore sign bit
|
||||||
case 5123: //UNSIGNED_SHORT
|
case 5123: //UNSIGNED_SHORT
|
||||||
while(outverts --> 0)
|
while(outverts --> 0)
|
||||||
{
|
{
|
||||||
|
@ -1256,8 +1390,10 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert
|
||||||
JSON_ReadBody(nam, ret->frame->shadername, sizeof(ret->frame->shadername));
|
JSON_ReadBody(nam, ret->frame->shadername, sizeof(ret->frame->shadername));
|
||||||
else if (mat)
|
else if (mat)
|
||||||
JSON_GetPath(mat, false, ret->frame->shadername, sizeof(ret->frame->shadername));
|
JSON_GetPath(mat, false, ret->frame->shadername, sizeof(ret->frame->shadername));
|
||||||
|
else if (material == -1) //explicit invalid material
|
||||||
|
Q_snprintf(ret->frame->shadername, sizeof(ret->frame->shadername), "%s", gltf->mod->name);
|
||||||
else
|
else
|
||||||
Q_snprintf(ret->frame->shadername, sizeof(ret->frame->shadername), "%i", material);
|
Q_snprintf(ret->frame->shadername, sizeof(ret->frame->shadername), "%.100s/%i", gltf->mod->name, material);
|
||||||
|
|
||||||
if (alphaMode == 1)
|
if (alphaMode == 1)
|
||||||
Q_snprintf(alphaCutoffmodifier, sizeof(alphaCutoffmodifier), "#ALPHATEST=>%f", alphaCutoff);
|
Q_snprintf(alphaCutoffmodifier, sizeof(alphaCutoffmodifier), "#ALPHATEST=>%f", alphaCutoff);
|
||||||
|
@ -1374,8 +1510,9 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, int material, qboolean vert
|
||||||
JSON_GetFloat(mat, "emissiveFactor.2", 0)
|
JSON_GetFloat(mat, "emissiveFactor.2", 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (pbrmr)
|
else// if (pbrmr)
|
||||||
{ //this is the standard lighting model for gltf2
|
{ //this is the standard lighting model for gltf2
|
||||||
|
//'When not specified, all the default values of pbrMetallicRoughness apply'
|
||||||
int albedo = JSON_GetInteger(pbrmr, "baseColorTexture.index", -1); //.rgba
|
int albedo = JSON_GetInteger(pbrmr, "baseColorTexture.index", -1); //.rgba
|
||||||
int mrt = JSON_GetInteger(pbrmr, "metallicRoughnessTexture.index", -1); //.r = unused, .g = roughness, .b = metalic, .a = unused
|
int mrt = JSON_GetInteger(pbrmr, "metallicRoughnessTexture.index", -1); //.r = unused, .g = roughness, .b = metalic, .a = unused
|
||||||
int occ = JSON_GetInteger(mat, "occlusionTexture.index", -1); //.r
|
int occ = JSON_GetInteger(mat, "occlusionTexture.index", -1); //.r
|
||||||
|
@ -2197,16 +2334,18 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize,
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
qboolean supported; //unsupported extensions don't really need to be listed, but they do prevent warnings from unkown-but-used extensions
|
qboolean supported; //unsupported extensions don't really need to be listed, but they do prevent warnings from unknown-but-used extensions
|
||||||
|
qboolean draft; //true when our implementation is probably buggy on account of the spec maybe changing.
|
||||||
} extensions[] =
|
} extensions[] =
|
||||||
{
|
{
|
||||||
{"KHR_materials_pbrSpecularGlossiness", true},
|
{"KHR_materials_pbrSpecularGlossiness", true, false},
|
||||||
//draft {"KHR_materials_cmnBlinnPhong", true},
|
// {"KHR_materials_cmnBlinnPhong", true, true},
|
||||||
{"KHR_materials_unlit", true},
|
{"KHR_materials_unlit", true, false},
|
||||||
{"KHR_texture_transform", false},
|
{"KHR_texture_transform", false, true}, //probably not fatal
|
||||||
{"KHR_draco_mesh_compression", false},
|
{"KHR_draco_mesh_compression", false, true}, //probably fatal
|
||||||
{"MSFT_texture_dds", true},
|
{"KHR_mesh_quantization", true, true},
|
||||||
{"MSFT_packing_occlusionRoughnessMetallic", true},
|
{"MSFT_texture_dds", true, false},
|
||||||
|
{"MSFT_packing_occlusionRoughnessMetallic", true, false},
|
||||||
};
|
};
|
||||||
gltf_t gltf;
|
gltf_t gltf;
|
||||||
int pos=0, j, k;
|
int pos=0, j, k;
|
||||||
|
@ -2267,6 +2406,8 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize,
|
||||||
}
|
}
|
||||||
if (j==countof(extensions) || !extensions[j].supported)
|
if (j==countof(extensions) || !extensions[j].supported)
|
||||||
Con_Printf(CON_WARNING "%s: gltf2 extension \"%s\" not known\n", mod->name, extname);
|
Con_Printf(CON_WARNING "%s: gltf2 extension \"%s\" not known\n", mod->name, extname);
|
||||||
|
else if (extensions[j].draft)
|
||||||
|
Con_Printf(CON_WARNING "%s: gltf2 extension \"%s\" follows draft implementation, and may be non-standard/buggy\n", mod->name, extname);
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorClear(mod->maxs);
|
VectorClear(mod->maxs);
|
||||||
|
|
Loading…
Reference in a new issue