mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 05:11:35 +00:00
smoother console scrolling (at least with the mouse)
support RLE+luminance+alpha tga files. support half-float tga files. recognise hdr astc images. added appropriate fallbacks for astc support. load mip-less .astc files (mostly just for debugging stuff). allow packages to warn about required engine/gpu features. catch when stdin flags get changed to blocking by external libraries, to avoid fatal stalls. basic support for .mdx files (kingpin models) sort packages loaded via wildcards, by datetime then name, to avoid random ordering from certain filesystems. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5531 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
d561772bb0
commit
41b0d993f2
48 changed files with 5118 additions and 1466 deletions
|
@ -93,7 +93,7 @@ cvar_t ignore_spec = CVAR("ignore_spec", "0");
|
|||
cvar_t ignore_qizmo_spec = CVAR("ignore_qizmo_spec", "0");
|
||||
cvar_t ignore_mode = CVAR("ignore_mode", "0");
|
||||
cvar_t ignore_flood_duration = CVARD("ignore_flood_duration", "4", "Time limit for inbound messages to be considered duplicates.");
|
||||
cvar_t ignore_flood = CVARD("ignore_flood", "0", "Provides a way to reduce inbound spam from flooding out your chat (dupe messages are ignored).\n0: No inbound flood protection.\n1: Duplicate non-team messages will be filtered.\n2: ALL duplicate messages will be filtered\n");
|
||||
cvar_t ignore_flood = CVARD("ignore_flood", "0", "Provides a way to reduce inbound spam from flooding out your chat (dupe messages are ignored).\n0: No inbound flood protection.\n1: Duplicate non-team messages will be filtered.\n2: ALL duplicate messages will be filtered");
|
||||
cvar_t ignore_opponents = CVAR("ignore_opponents", "0");
|
||||
|
||||
char ignoreteamlist[MAX_TEAMIGNORELIST][16 + 1];
|
||||
|
|
|
@ -3052,13 +3052,18 @@ void CL_ConnectionlessPacket (void)
|
|||
Con_TPrintf ("redirect to %s\n", data);
|
||||
if (NET_StringToAdr(data, PORT_DEFAULTSERVER, &adr))
|
||||
{
|
||||
data = "\xff\xff\xff\xffgetchallenge\n";
|
||||
|
||||
if (NET_CompareAdr(&connectinfo.adr, &net_from))
|
||||
{
|
||||
connectinfo.istransfer = true;
|
||||
connectinfo.adr = adr;
|
||||
NET_SendPacket (cls.sockets, strlen(data), data, &adr);
|
||||
if (!NET_EnsureRoute(cls.sockets, "redir", cls.servername, &connectinfo.adr))
|
||||
Con_Printf ("Unable to redirect to %s\n", data);
|
||||
else
|
||||
{
|
||||
connectinfo.istransfer = true;
|
||||
connectinfo.adr = adr;
|
||||
|
||||
data = "\xff\xff\xff\xffgetchallenge\n";
|
||||
NET_SendPacket (cls.sockets, strlen(data), data, &adr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -33,7 +33,7 @@ console_t *con_chat; // points to a chat console
|
|||
#define Font_ScreenWidth() (vid.pixelwidth)
|
||||
|
||||
static int Con_DrawProgress(int left, int right, int y);
|
||||
static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, int y, int top, int selactive, int selsx, int selex, int selsy, int seley, float lineagelimit);
|
||||
static int Con_DrawConsoleLines(console_t *con, conline_t *l, float displayscroll, int sx, int ex, int y, int top, int selactive, int selsx, int selex, int selsy, int seley, float lineagelimit);
|
||||
|
||||
#ifdef QTERM
|
||||
#include <windows.h>
|
||||
|
@ -971,7 +971,7 @@ void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags)
|
|||
con->current->newer = reuse;
|
||||
con->current = reuse;
|
||||
con->current->length = 0;
|
||||
if (con->display == con->current->older)
|
||||
if (con->display == con->current->older && con->displayscroll==0)
|
||||
con->display = con->current;
|
||||
break;
|
||||
default:
|
||||
|
@ -980,6 +980,8 @@ void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags)
|
|||
con->current->length = 0;
|
||||
con->cr = false;
|
||||
}
|
||||
if (!con->current->numlines)
|
||||
con->current->numlines = 1;
|
||||
|
||||
if (!con->current->length && con_timestamps.ival && !(parseflags & PFS_CENTERED))
|
||||
{
|
||||
|
@ -1394,7 +1396,7 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
|
|||
{
|
||||
if (con->footerline)
|
||||
{
|
||||
y = Con_DrawConsoleLines(con, con->footerline, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0);
|
||||
y = Con_DrawConsoleLines(con, con->footerline, 0, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0);
|
||||
}
|
||||
return y; //fixme: draw any unfinished lines of the current console instead.
|
||||
}
|
||||
|
@ -1553,7 +1555,7 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
|
|||
/*if its getting completed to something, show some help about the command that is going to be used*/
|
||||
if (con->footerline)
|
||||
{
|
||||
y = Con_DrawConsoleLines(con, con->footerline, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0);
|
||||
y = Con_DrawConsoleLines(con, con->footerline, 0, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0);
|
||||
}
|
||||
|
||||
/*just above that, we have the tab completion list*/
|
||||
|
@ -1601,7 +1603,7 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
|
|||
}
|
||||
|
||||
if (con->completionline->length)
|
||||
y = Con_DrawConsoleLines(con, con->completionline, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0);
|
||||
y = Con_DrawConsoleLines(con, con->completionline, 0, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0);
|
||||
}
|
||||
|
||||
return y;
|
||||
|
@ -2079,9 +2081,21 @@ int Con_DrawAlternateConsoles(int lines)
|
|||
return y;
|
||||
}
|
||||
|
||||
static void Con_DrawImageClip(float x, float y, float w, float h, float bottom, shader_t *pic)
|
||||
{
|
||||
if (bottom < y+h)
|
||||
{
|
||||
if (bottom <= y)
|
||||
return;
|
||||
R2D_Image(x,y,w,bottom-y,0,0,1,(bottom-y)/h,pic);
|
||||
}
|
||||
else
|
||||
R2D_Image(x,y,w,h,0,0,1,1,pic);
|
||||
}
|
||||
|
||||
//draws the conline_t list bottom-up within the width of the screen until the top of the screen is reached.
|
||||
//if text is selected, the selstartline globals will be updated, so make sure the lines persist or check them.
|
||||
static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, int y, int top, int selactive, int selsx, int selex, int selsy, int seley, float lineagelimit)
|
||||
static int Con_DrawConsoleLines(console_t *con, conline_t *l, float displayscroll, int sx, int ex, int y, int top, int selactive, int selsx, int selex, int selsy, int seley, float lineagelimit)
|
||||
{
|
||||
int linecount;
|
||||
conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])];
|
||||
|
@ -2090,17 +2104,28 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
|
|||
int charh = Font_CharHeight();
|
||||
unsigned int codeflags, codepoint;
|
||||
float alphaval = 1;
|
||||
float chop;
|
||||
|
||||
chop = displayscroll * Font_CharHeight();
|
||||
|
||||
if (l != con->completionline)
|
||||
if (l != con->footerline)
|
||||
if (l != con->current)
|
||||
{
|
||||
y -= 8;
|
||||
y -= Font_CharHeight();
|
||||
// draw arrows to show the buffer is backscrolled
|
||||
for (x = sx ; x<ex; )
|
||||
x = (Font_DrawChar (x, y, CON_WHITEMASK, '^')-x)*4+x;
|
||||
|
||||
if (chop)
|
||||
{
|
||||
y -= Font_CharHeight();
|
||||
chop += 2*Font_CharHeight();
|
||||
}
|
||||
}
|
||||
|
||||
y += chop;
|
||||
|
||||
if (selactive != -1)
|
||||
{
|
||||
if (!selactive)
|
||||
|
@ -2199,6 +2224,31 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
|
|||
{
|
||||
char *imgname;
|
||||
linkinfo[linkinfolen] = 0;
|
||||
|
||||
imgname = Info_ValueForKey(linkinfo, "imgptr");
|
||||
if (*imgname)
|
||||
{
|
||||
pic = R2D_SafeCachePic("tiprawimg");
|
||||
pic->defaulttextures->base = Image_TextureIsValid(strtoull(imgname, NULL, 0));
|
||||
if (pic && pic->defaulttextures->base)
|
||||
{
|
||||
if (!pic->defaulttextures->base->width || !pic->defaulttextures->base->height || !TEXLOADED(pic->defaulttextures->base))
|
||||
picw = pich = 64;
|
||||
else if (pic->defaulttextures->base->width > pic->defaulttextures->base->height)
|
||||
{
|
||||
picw = 64;
|
||||
pich = (64.0*pic->defaulttextures->base->height)/pic->defaulttextures->base->width;
|
||||
}
|
||||
else
|
||||
{
|
||||
picw = (64.0*pic->defaulttextures->base->width)/pic->defaulttextures->base->height;
|
||||
pich = 64;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
imgname = Info_ValueForKey(linkinfo, "img");
|
||||
if (*imgname)
|
||||
{
|
||||
|
@ -2305,23 +2355,27 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
|
|||
if (texth > pich)
|
||||
{
|
||||
texth = pich + (texth-pich)/2;
|
||||
R2D_Image(sx*szx, (y-texth)*szy, picw*szx, pich*szy, 0, 0, 1, 1, pic);
|
||||
Con_DrawImageClip(sx*szx, (y-texth)*szy, picw*szx, pich*szy, (y-chop+Font_CharHeight())*szy, pic);
|
||||
pich = 0; //don't pad the text...
|
||||
}
|
||||
else
|
||||
{
|
||||
R2D_Image(sx*szx, (y-pich)*szy, picw*szx, pich*szy, 0, 0, 1, 1, pic);
|
||||
Con_DrawImageClip(sx*szx, (y-pich)*szy, picw*szx, pich*szy, (y-chop+Font_CharHeight())*szy, pic);
|
||||
pich -= texth;
|
||||
y-= pich/2; //skip some space above and below the text block, to keep the text and image aligned.
|
||||
|
||||
if (chop)
|
||||
chop -= pich/2;
|
||||
}
|
||||
if (R2D_Flush)
|
||||
R2D_Flush();
|
||||
|
||||
// if (selsx < picw && selex < picw)
|
||||
|
||||
l->numlines = ceil((texth+pich)/Font_CharHeight());
|
||||
}
|
||||
|
||||
l->numlines = linecount;
|
||||
else
|
||||
l->numlines = linecount;
|
||||
|
||||
while(linecount-- > 0)
|
||||
{
|
||||
|
@ -2330,6 +2384,15 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
|
|||
|
||||
y -= Font_CharHeight();
|
||||
|
||||
if (chop)
|
||||
{
|
||||
chop -= Font_CharHeight();
|
||||
if (chop < 0)
|
||||
chop = 0;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
if (top && y < top)
|
||||
break;
|
||||
|
||||
|
@ -2526,6 +2589,8 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
|
|||
break;
|
||||
}
|
||||
y -= pich/2;
|
||||
if (chop)
|
||||
chop -= pich/2;
|
||||
if (y < top)
|
||||
break;
|
||||
}
|
||||
|
@ -2799,7 +2864,7 @@ void Con_DrawConsole (int lines, qboolean noback)
|
|||
|
||||
l = con_current->display;
|
||||
|
||||
y = Con_DrawConsoleLines(con_current, l, sx, ex, y, top, selactive, selsx, selex, selsy, seley, 0);
|
||||
y = Con_DrawConsoleLines(con_current, l, con_current->displayscroll, sx, ex, y, top, selactive, selsx, selex, selsy, seley, 0);
|
||||
|
||||
if (!haveprogress && lines == vid.height)
|
||||
{
|
||||
|
@ -3163,7 +3228,7 @@ void Con_DrawOneConsole(console_t *con, qboolean focused, struct font_s *font, f
|
|||
|
||||
if (!con->display)
|
||||
con->display = con->current;
|
||||
Con_DrawConsoleLines(con, con->display, x, sx, sy, y, selactive, selsx, selex, selsy, seley, lineagelimit);
|
||||
Con_DrawConsoleLines(con, con->display, con->displayscroll, x, sx, sy, y, selactive, selsx, selex, selsy, seley, lineagelimit);
|
||||
|
||||
Font_EndString(font);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
1567
engine/client/image_astc.h
Normal file
1567
engine/client/image_astc.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -673,8 +673,38 @@ qboolean Key_GetConsoleSelectionBox(console_t *con, int *sx, int *sy, int *ex, i
|
|||
|
||||
if (con->buttonsdown == CB_SCROLL || con->buttonsdown == CB_SCROLL_R)
|
||||
{
|
||||
float lineheight = Font_CharVHeight(font_console);
|
||||
//left-mouse.
|
||||
//scroll the console with the mouse. trigger links on release.
|
||||
con->displayscroll += (con->mousecursor[1] - con->mousedown[1])/lineheight;
|
||||
con->mousedown[1] = con->mousecursor[1];
|
||||
while (con->displayscroll > con->display->numlines)
|
||||
{
|
||||
if (con->display->older)
|
||||
{
|
||||
con->displayscroll -= con->display->numlines;
|
||||
con->display = con->display->older;
|
||||
}
|
||||
else
|
||||
{
|
||||
con->displayscroll = con->display->numlines;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (con->displayscroll <= 0)
|
||||
{
|
||||
if (con->display->newer)
|
||||
{
|
||||
con->display = con->display->newer;
|
||||
con->displayscroll += con->display->numlines;
|
||||
}
|
||||
else
|
||||
{
|
||||
con->displayscroll = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
while (con->mousecursor[1] - con->mousedown[1] > 8 && con->display->older)
|
||||
{
|
||||
con->mousedown[1] += 8;
|
||||
|
@ -685,7 +715,7 @@ qboolean Key_GetConsoleSelectionBox(console_t *con, int *sx, int *sy, int *ex, i
|
|||
con->mousedown[1] -= 8;
|
||||
con->display = con->display->newer;
|
||||
}
|
||||
|
||||
*/
|
||||
*sx = con->mousecursor[0];
|
||||
*sy = con->mousecursor[1];
|
||||
*ex = con->mousecursor[0];
|
||||
|
@ -1585,12 +1615,26 @@ qboolean Key_EntryLine(console_t *con, unsigned char **line, int lineoffset, int
|
|||
Sys_Clipboard_PasteText(CBT_SELECTION, Key_ConsolePaste, line);
|
||||
return true;
|
||||
}
|
||||
if (((unicode=='V' || unicode=='v' || unicode==22) && ctrl) || (shift && key == K_INS))
|
||||
if (((unicode=='V' || unicode=='v' || unicode==22/*sync*/) && ctrl) || (shift && key == K_INS))
|
||||
{ //ctrl+v to paste from the windows-style clipboard.
|
||||
Sys_Clipboard_PasteText(CBT_CLIPBOARD, Key_ConsolePaste, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((unicode=='X' || unicode=='x' || unicode==24/*cancel*/) && ctrl)
|
||||
{ //cut - copy-to-clipboard-and-delete
|
||||
Sys_SaveClipboard(CBT_CLIPBOARD, *line);
|
||||
(*line)[lineoffset] = 0;
|
||||
*linepos = strlen(*line);
|
||||
return true;
|
||||
}
|
||||
if ((unicode=='U' || unicode=='u' || unicode==21/*nak*/) && ctrl)
|
||||
{ //clear line
|
||||
(*line)[lineoffset] = 0;
|
||||
*linepos = strlen(*line);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (unicode < ' ')
|
||||
{
|
||||
//if the user is entering control codes, then the ctrl+foo mechanism is probably unsupported by the unicode input stuff, so give best-effort replacements.
|
||||
|
@ -1820,14 +1864,16 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
|
|||
i = 8;
|
||||
if (!con->display)
|
||||
return true;
|
||||
if (con->display == con->current)
|
||||
i+=2; //skip over the blank input line, and extra so we actually move despite the addition of the ^^^^^ line
|
||||
// if (con->display == con->current)
|
||||
// i+=2; //skip over the blank input line, and extra so we actually move despite the addition of the ^^^^^ line
|
||||
if (con->display->older != NULL)
|
||||
{
|
||||
while (i-->0)
|
||||
con->displayscroll += i;
|
||||
while (con->displayscroll >= con->display->numlines)
|
||||
{
|
||||
if (con->display->older == NULL)
|
||||
break;
|
||||
con->displayscroll -= con->display->numlines;
|
||||
con->display = con->display->older;
|
||||
con->display->time = realtime;
|
||||
}
|
||||
|
@ -1845,15 +1891,20 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
|
|||
return true;
|
||||
if (con->display->newer != NULL)
|
||||
{
|
||||
while (i-->0)
|
||||
con->displayscroll -= i;
|
||||
while (con->displayscroll < 0)
|
||||
{
|
||||
if (con->display->newer == NULL)
|
||||
break;
|
||||
con->display = con->display->newer;
|
||||
con->display->time = realtime;
|
||||
con->displayscroll += con->display->numlines;
|
||||
}
|
||||
if (con->display->newer && con->display->newer == con->current)
|
||||
{
|
||||
con->display = con->current;
|
||||
con->displayscroll = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1862,6 +1913,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
|
|||
{
|
||||
if (con->display != con->oldest)
|
||||
{
|
||||
con->displayscroll = 0;
|
||||
con->display = con->oldest;
|
||||
return true;
|
||||
}
|
||||
|
@ -1871,6 +1923,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode)
|
|||
{
|
||||
if (con->display != con->current)
|
||||
{
|
||||
con->displayscroll = 0;
|
||||
con->display = con->current;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//provides both a package manager and downloads menu.
|
||||
//FIXME: block downloads of exe/dll/so/etc if not an https url (even if inside zips). also block such files from package lists over http.
|
||||
#include "quakedef.h"
|
||||
#include "shader.h"
|
||||
|
||||
#ifdef PACKAGEMANAGER
|
||||
#if !defined(NOBUILTINMENUS) && !defined(SERVERONLY)
|
||||
|
@ -161,15 +162,16 @@ typedef struct package_s {
|
|||
struct packagedep_s *next;
|
||||
enum
|
||||
{
|
||||
DEP_CONFLICT,
|
||||
DEP_CONFLICT, //don't install if we have the named package installed.
|
||||
DEP_FILECONFLICT, //don't install if this file already exists.
|
||||
DEP_REQUIRE,
|
||||
DEP_RECOMMEND, //like depend, but uninstalling will not bubble.
|
||||
DEP_SUGGEST, //like recommend, but will not force install (ie: only prevents auto-uninstall)
|
||||
DEP_REQUIRE, //don't install unless we have the named package installed.
|
||||
DEP_RECOMMEND, //like depend, but uninstalling will not bubble.
|
||||
DEP_SUGGEST, //like recommend, but will not force install (ie: only prevents auto-uninstall)
|
||||
DEP_NEEDFEATURE, //requires a specific feature to be available (typically controlled via a cvar)
|
||||
// DEP_MIRROR,
|
||||
// DEP_FAILEDMIRROR,
|
||||
|
||||
DEP_FILE
|
||||
DEP_FILE //a file that will be installed
|
||||
} dtype;
|
||||
char name[1];
|
||||
} *deps;
|
||||
|
@ -549,6 +551,57 @@ static void PM_InsertPackage(package_t *p)
|
|||
numpackages++;
|
||||
}
|
||||
|
||||
static qboolean PM_CheckFeature(const char *feature, const char **featurename, const char **concommand)
|
||||
{
|
||||
#ifdef HAVE_CLIENT
|
||||
extern cvar_t r_replacemodels;
|
||||
#endif
|
||||
*featurename = NULL;
|
||||
*concommand = NULL;
|
||||
#ifdef HAVE_CLIENT
|
||||
//check for compressed texture formats, to warn when not supported.
|
||||
if (!strcmp(feature, "bc1") || !strcmp(feature, "bc2") || !strcmp(feature, "bc3") || !strcmp(feature, "s3tc"))
|
||||
return *featurename="S3 Texture Compression", sh_config.hw_bc>=1;
|
||||
if (!strcmp(feature, "bc4") || !strcmp(feature, "bc5") || !strcmp(feature, "rgtc"))
|
||||
return *featurename="Red/Green Texture Compression", sh_config.hw_bc>=2;
|
||||
if (!strcmp(feature, "bc6") || !strcmp(feature, "bc7") || !strcmp(feature, "bptc"))
|
||||
return *featurename="Block Partitioned Texture Compression", sh_config.hw_bc>=3;
|
||||
if (!strcmp(feature, "etc1"))
|
||||
return *featurename="Ericson Texture Compression, Original", sh_config.hw_etc>=1;
|
||||
if (!strcmp(feature, "etc2") || !strcmp(feature, "eac"))
|
||||
return *featurename="Ericson Texture Compression, Revision 2", sh_config.hw_etc>=2;
|
||||
if (!strcmp(feature, "astcldr") || !strcmp(feature, "astc"))
|
||||
return *featurename="Adaptive Scalable Texture Compression (LDR)", sh_config.hw_astc>=1;
|
||||
if (!strcmp(feature, "astchdr"))
|
||||
return *featurename="Adaptive Scalable Texture Compression (HDR)", sh_config.hw_astc>=2;
|
||||
|
||||
if (!strcmp(feature, "24bit"))
|
||||
return *featurename="24bit Textures", *concommand="seta gl_load24bit 1\n", gl_load24bit.ival;
|
||||
if (!strcmp(feature, "md3"))
|
||||
return *featurename="Replacement Models", *concommand="seta r_replacemodels md3 md2\n", !!strstr(r_replacemodels.string, "md3");
|
||||
if (!strcmp(feature, "rtlights"))
|
||||
return *featurename="Realtime Dynamic Lights", *concommand="seta r_shadow_realtime_dlight 1\n", r_shadow_realtime_dlight.ival||r_shadow_realtime_world.ival;
|
||||
if (!strcmp(feature, "rtworld"))
|
||||
return *featurename="Realtime World Lights", *concommand="seta r_shadow_realtime_dlight 1\nseta r_shadow_realtime_world 1\n", r_shadow_realtime_world.ival;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
static qboolean PM_CheckPackageFeatures(package_t *p)
|
||||
{
|
||||
struct packagedep_s *dep;
|
||||
const char *featname, *enablecmd;
|
||||
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype == DEP_NEEDFEATURE)
|
||||
{
|
||||
if (!PM_CheckFeature(dep->name, &featname, &enablecmd))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean PM_CheckFile(const char *filename, enum fs_relative base)
|
||||
{
|
||||
|
@ -916,6 +969,8 @@ static qboolean PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *ur
|
|||
PM_AddDep(p, DEP_RECOMMEND, val);
|
||||
else if (!strcmp(key, "suggest"))
|
||||
PM_AddDep(p, DEP_SUGGEST, val);
|
||||
else if (!strcmp(key, "need"))
|
||||
PM_AddDep(p, DEP_NEEDFEATURE, val);
|
||||
else if (!strcmp(key, "test"))
|
||||
flags |= DPF_TESTING;
|
||||
else if (!strcmp(key, "stale") && version==2)
|
||||
|
@ -1486,7 +1541,12 @@ static void PM_MarkPackage(package_t *package, unsigned int markflag)
|
|||
{
|
||||
d = PM_FindPackage(dep->name);
|
||||
if (d)
|
||||
PM_MarkPackage(d, DPF_AUTOMARKED);
|
||||
{
|
||||
if (dep->dtype == DEP_RECOMMEND && !PM_CheckPackageFeatures(d))
|
||||
Con_DPrintf("Skipping recommendation \"%s\"\n", dep->name);
|
||||
else
|
||||
PM_MarkPackage(d, DPF_AUTOMARKED);
|
||||
}
|
||||
else
|
||||
Con_DPrintf("Couldn't find dependancy \"%s\"\n", dep->name);
|
||||
}
|
||||
|
@ -1995,6 +2055,11 @@ static void PM_WriteInstalledPackages(void)
|
|||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("recommend=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
else if (dep->dtype == DEP_NEEDFEATURE)
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("need=%s", dep->name), buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
if (p->flags & DPF_TESTING)
|
||||
|
@ -2025,6 +2090,31 @@ static void PM_WriteInstalledPackages(void)
|
|||
}
|
||||
}
|
||||
|
||||
//package has been downloaded and installed, but some packages need to be enabled
|
||||
//(plugins might have other dll dependancies, so this can only happen AFTER the entire package was extracted)
|
||||
static void PM_PackageEnabled(package_t *p)
|
||||
{
|
||||
char ext[8];
|
||||
struct packagedep_s *dep;
|
||||
FS_FlushFSHashFull();
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype != DEP_FILE)
|
||||
continue;
|
||||
COM_FileExtension(dep->name, ext, sizeof(ext));
|
||||
if (!stricmp(ext, "pak") || !stricmp(ext, "pk3"))
|
||||
FS_ReloadPackFiles();
|
||||
#ifdef PLUGINS
|
||||
if ((p->flags & DPF_PLUGIN) && !Q_strncasecmp(dep->name, PLUGINPREFIX, strlen(PLUGINPREFIX)))
|
||||
Cmd_ExecuteString(va("plug_load %s\n", dep->name), RESTRICT_LOCAL);
|
||||
#endif
|
||||
#ifdef MENU_DAT
|
||||
if (!Q_strcasecmp(dep->name, "menu.dat"))
|
||||
Cmd_ExecuteString("menu_restart\n", RESTRICT_LOCAL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WEBCLIENT
|
||||
//callback from PM_Download_Got, extracts each file from an archive
|
||||
static int QDECL PM_ExtractFiles(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath)
|
||||
|
@ -2057,31 +2147,6 @@ static int QDECL PM_ExtractFiles(const char *fname, qofs_t fsize, time_t mtime,
|
|||
return 1;
|
||||
}
|
||||
|
||||
//package has been downloaded and installed, but some packages need to be enabled
|
||||
//(plugins might have other dll dependancies, so this can only happen AFTER the entire package was extracted)
|
||||
static void PM_PackageEnabled(package_t *p)
|
||||
{
|
||||
char ext[8];
|
||||
struct packagedep_s *dep;
|
||||
FS_FlushFSHashFull();
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype != DEP_FILE)
|
||||
continue;
|
||||
COM_FileExtension(dep->name, ext, sizeof(ext));
|
||||
if (!stricmp(ext, "pak") || !stricmp(ext, "pk3"))
|
||||
FS_ReloadPackFiles();
|
||||
#ifdef PLUGINS
|
||||
if ((p->flags & DPF_PLUGIN) && !Q_strncasecmp(dep->name, PLUGINPREFIX, strlen(PLUGINPREFIX)))
|
||||
Cmd_ExecuteString(va("plug_load %s\n", dep->name), RESTRICT_LOCAL);
|
||||
#endif
|
||||
#ifdef MENU_DAT
|
||||
if (!Q_strcasecmp(dep->name, "menu.dat"))
|
||||
Cmd_ExecuteString("menu_restart\n", RESTRICT_LOCAL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void PM_StartADownload(void);
|
||||
//callback from PM_StartADownload
|
||||
static void PM_Download_Got(struct dl_download *dl)
|
||||
|
@ -2334,10 +2399,10 @@ int PM_IsApplying(qboolean listsonly)
|
|||
return count;
|
||||
}
|
||||
|
||||
#ifdef WEBCLIENT
|
||||
//looks for the next package that needs downloading, and grabs it
|
||||
static void PM_StartADownload(void)
|
||||
{
|
||||
#ifdef WEBCLIENT
|
||||
vfsfile_t *tmpfile;
|
||||
char *temp;
|
||||
package_t *p;
|
||||
|
@ -2466,8 +2531,8 @@ static void PM_StartADownload(void)
|
|||
|
||||
//clear the updating flag once there's no more activity needed
|
||||
pkg_updating = downloading;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
//'just' starts doing all the things needed to remove/install selected packages
|
||||
void PM_ApplyChanges(void)
|
||||
{
|
||||
|
@ -2611,8 +2676,45 @@ void PM_ApplyChanges(void)
|
|||
if ((p->flags&DPF_MARKED) && !(p->flags&DPF_ENABLED) && !p->download)
|
||||
p->trymirrors = ~0u;
|
||||
}
|
||||
#endif
|
||||
PM_StartADownload(); //and try to do those downloads.
|
||||
#else
|
||||
for (p = availablepackages; p; p=p->next)
|
||||
{
|
||||
if ((p->flags&DPF_MARKED) && !(p->flags&DPF_ENABLED))
|
||||
{ //flagged for a (re?)download
|
||||
int i;
|
||||
struct packagedep_s *dep;
|
||||
for (i = 0; i < countof(p->mirror); i++)
|
||||
if (p->mirror[i])
|
||||
break;
|
||||
for (dep = p->deps; dep; dep=dep->next)
|
||||
if (dep->dtype == DEP_FILE)
|
||||
break;
|
||||
if (!dep && i == countof(p->mirror))
|
||||
{ //this appears to be a meta package with no download
|
||||
//just directly install it.
|
||||
p->flags &= ~(DPF_NATIVE|DPF_CACHED|DPF_CORRUPT);
|
||||
p->flags |= DPF_ENABLED;
|
||||
|
||||
Con_Printf("Enabled meta package %s\n", p->name);
|
||||
PM_WriteInstalledPackages();
|
||||
PM_PackageEnabled(p);
|
||||
}
|
||||
|
||||
if ((p->flags & DPF_PRESENT) && !PM_PurgeOnDisable(p))
|
||||
{ //its in our cache directory, so lets just use that
|
||||
p->flags |= DPF_ENABLED;
|
||||
|
||||
Con_Printf("Enabled cached package %s\n", p->name);
|
||||
PM_WriteInstalledPackages();
|
||||
PM_PackageEnabled(p);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
p->flags &= ~DPF_MARKED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(M_Menu_Prompt) || defined(SERVERONLY)
|
||||
|
@ -3202,8 +3304,12 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct emenu_s *m)
|
|||
|
||||
if (p->flags & DPF_TESTING) //hide testing updates
|
||||
n = va("^h%s", n);
|
||||
// if (!(p->flags & (DPF_ENABLED|DPF_MARKED|DPF_PRESENT))
|
||||
// continue;
|
||||
|
||||
if (!PM_CheckPackageFeatures(p))
|
||||
Draw_FunStringWidth(0, y, "!", x+8, true, true);
|
||||
|
||||
// if (!(p->flags & (DPF_ENABLED|DPF_MARKED|DPF_PRESENT))
|
||||
// continue;
|
||||
|
||||
// if (&m->selecteditem->common == &c->common)
|
||||
// Draw_AltFunString (x+48, y, n);
|
||||
|
@ -3404,6 +3510,7 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix)
|
|||
char *slash;
|
||||
menuoption_t *mo;
|
||||
int prefixlen = strlen(pathprefix);
|
||||
struct packagedep_s *dep;
|
||||
|
||||
//add all packages in this dir
|
||||
for (p = availablepackages; p; p = p->next)
|
||||
|
@ -3420,10 +3527,26 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix)
|
|||
desc = va("^aauthor: ^a%s\n^alicense: ^a%s\n^awebsite: ^a%s\n%s", p->author?p->author:"^hUnknown^h", p->license?p->license:"^hUnknown^h", p->website?p->website:"^hUnknown^h", p->description);
|
||||
else
|
||||
desc = p->description;
|
||||
|
||||
for (dep = p->deps; dep; dep = dep->next)
|
||||
{
|
||||
if (dep->dtype == DEP_NEEDFEATURE)
|
||||
{
|
||||
const char *featname, *enablecmd;
|
||||
if (!PM_CheckFeature(dep->name, &featname, &enablecmd))
|
||||
{
|
||||
if (enablecmd)
|
||||
desc = va("^aDisabled: ^a%s\n%s", featname, desc);
|
||||
else
|
||||
desc = va("^aUnavailable: ^a%s\n%s", featname, desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c = MC_AddCustom(m, 0, y, p, downloadablessequence, desc);
|
||||
c->draw = MD_Draw;
|
||||
c->key = MD_Key;
|
||||
c->common.width = 320;
|
||||
c->common.width = 320-16;
|
||||
c->common.height = 8;
|
||||
y += 8;
|
||||
|
||||
|
|
|
@ -479,7 +479,7 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *men
|
|||
if (option->common.ishidden)
|
||||
continue;
|
||||
|
||||
if (&menu->menu == topmenu && menu->mouseitem == option)
|
||||
if (&menu->menu == topmenu && menu->mouseitem == option && option->common.type != mt_frameend)
|
||||
{
|
||||
float alphamax = 0.5, alphamin = 0.2;
|
||||
R2D_ImageColours(.5,.4,0,(sin(realtime*2)+1)*0.5*(alphamax-alphamin)+alphamin);
|
||||
|
|
|
@ -241,7 +241,7 @@ typedef struct image_s
|
|||
int status; //TEX_
|
||||
unsigned int flags;
|
||||
struct image_s *next;
|
||||
struct image_s *prev;
|
||||
// struct image_s *prev;
|
||||
struct image_s *aliasof;
|
||||
union
|
||||
{
|
||||
|
@ -371,16 +371,16 @@ typedef struct
|
|||
|
||||
typedef struct texnums_s {
|
||||
char mapname[MAX_QPATH]; //the 'official' name of the diffusemap. used to generate filenames for other textures.
|
||||
texid_t base; //regular diffuse texture. may have alpha if surface is transparent
|
||||
texid_t base; //regular diffuse texture. may have alpha if surface is transparent.
|
||||
texid_t bump; //normalmap. height values packed in alpha.
|
||||
texid_t specular; //specular lighting values.
|
||||
texid_t upperoverlay; //diffuse texture for the upper body(shirt colour). no alpha channel. added to base.rgb
|
||||
texid_t loweroverlay; //diffuse texture for the lower body(trouser colour). no alpha channel. added to base.rgb
|
||||
texid_t specular; //specular lighting values. alpha contains exponent multiplier
|
||||
texid_t upperoverlay; //diffuse texture for the upper body(shirt colour). no alpha channel. added to base.rgb. ideally an l8 texture
|
||||
texid_t loweroverlay; //diffuse texture for the lower body(trouser colour). no alpha channel. added to base.rgb. ideally an l8 texture
|
||||
texid_t paletted; //8bit paletted data, just because.
|
||||
texid_t fullbright;
|
||||
texid_t reflectcube;
|
||||
texid_t reflectmask;
|
||||
texid_t displacement;
|
||||
texid_t fullbright; //emissive texture. alpha should be 1.
|
||||
texid_t reflectcube; //for fake reflections
|
||||
texid_t reflectmask; //defines how reflective it is (for cubemap reflections)
|
||||
texid_t displacement; //alternative to bump.a, eg R16[F] for offsetmapping or tessellation
|
||||
texid_t occlusion; //occlusion map...
|
||||
|
||||
//the material's pushconstants. vulkan guarentees only 128 bytes. so 8 vec4s. note that lmscales should want 4 of them...
|
||||
|
|
|
@ -727,7 +727,8 @@ static void QCBUILTIN PF_cs_remove (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
return;
|
||||
}
|
||||
|
||||
pe->DelinkTrailstate(&ed->trailstate);
|
||||
if (pe)
|
||||
pe->DelinkTrailstate(&ed->trailstate);
|
||||
World_UnlinkEdict((wedict_t*)ed);
|
||||
ED_Free (prinst, (void*)ed);
|
||||
}
|
||||
|
@ -7362,7 +7363,7 @@ void ASMCALL CSQC_ThinkTimeOp(pubprogfuncs_t *progs, edict_t *ed, float var)
|
|||
vars->nextthink = *w->g.time+var;
|
||||
}
|
||||
|
||||
pbool PDECL CSQC_CheckHeaderCrc(pubprogfuncs_t *progs, progsnum_t num, int crc)
|
||||
pbool PDECL CSQC_CheckHeaderCrc(pubprogfuncs_t *progs, progsnum_t num, int crc, const char *filename)
|
||||
{
|
||||
if (!num)
|
||||
{
|
||||
|
|
|
@ -2686,11 +2686,11 @@ void MP_CvarChanged(cvar_t *var)
|
|||
}
|
||||
}
|
||||
|
||||
pbool PDECL Menu_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc)
|
||||
pbool PDECL Menu_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc, const char *filename)
|
||||
{
|
||||
if (crc == 10020)
|
||||
return true; //its okay
|
||||
Con_Printf("progs crc is invalid for menuqc\n");
|
||||
Con_Printf("progs crc is invalid for %s\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -3686,7 +3686,7 @@ uploadfmt_t Surf_LightmapMode(model_t *model)
|
|||
fmt = PTI_RGBA32F;
|
||||
else if (sh_config.texfmt[PTI_A2BGR10] && rgb)
|
||||
fmt = PTI_A2BGR10;
|
||||
else if (sh_config.texfmt[PTI_L8] && !rgb && !r_deluxemapping)
|
||||
else if (sh_config.texfmt[PTI_L8] && !rgb && !r_deluxemapping && r_dynamic.ival<=0)
|
||||
fmt = PTI_L8;
|
||||
else if (sh_config.texfmt[PTI_BGRX8])
|
||||
fmt = PTI_BGRX8;
|
||||
|
|
|
@ -423,6 +423,7 @@ enum imageflags
|
|||
IF_NOGAMMA = 1<<9, /*do not apply texture-based gamma*/
|
||||
IF_3DMAP = 1<<10, /*waning - don't test directly*/
|
||||
IF_CUBEMAP = 1<<11, /*waning - don't test directly*/
|
||||
IF_2DARRAY = IF_3DMAP|IF_CUBEMAP,
|
||||
IF_TEXTYPE = (1<<10) | (1<<11), /*0=2d, 1=3d, 2=cubeface, 3=2d array texture*/
|
||||
IF_TEXTYPESHIFT = 10, /*0=2d, 1=3d, 2-7=cubeface*/
|
||||
IF_MIPCAP = 1<<12, //allow the use of d_mipcap
|
||||
|
@ -593,7 +594,7 @@ void RQ_Shutdown(void);
|
|||
|
||||
void WritePCXfile (const char *filename, enum fs_relative fsroot, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit.
|
||||
qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height);
|
||||
qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_t *format, qboolean greyonly, uploadfmt_t forceformat);
|
||||
void *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_t *format, qboolean greyonly, uploadfmt_t forceformat);
|
||||
qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height);
|
||||
qbyte *ReadPNGFile(const char *fname, qbyte *buf, int length, int *width, int *height, uploadfmt_t *format);
|
||||
qbyte *ReadPCXPalette(qbyte *buf, int len, qbyte *out);
|
||||
|
|
|
@ -36,7 +36,6 @@ qboolean vid_isfullscreen;
|
|||
|
||||
#define GLRENDEREROPTIONS "GL Renderer Options" //fixme: often used for generic cvars that apply to more than just gl...
|
||||
#define D3DRENDEREROPTIONS "D3D Renderer Options"
|
||||
#define VKRENDEREROPTIONS "Vulkan-Specific Renderer Options"
|
||||
|
||||
unsigned int d_8to24rgbtable[256];
|
||||
unsigned int d_8to24srgbtable[256];
|
||||
|
@ -239,7 +238,7 @@ cvar_t scr_allowsnap = CVARF ("scr_allowsnap", "1",
|
|||
CVAR_NOTFROMSERVER);
|
||||
cvar_t scr_centersbar = CVAR ("scr_centersbar", "2");
|
||||
cvar_t scr_centertime = CVAR ("scr_centertime", "2");
|
||||
cvar_t scr_logcenterprint = CVARD ("con_logcenterprint", "1", "Specifies whether to print centerprints on the console.\n0: never\n1: single-player or coop only.\n2: always.\n");
|
||||
cvar_t scr_logcenterprint = CVARD ("con_logcenterprint", "1", "Specifies whether to print centerprints on the console.\n0: never\n1: single-player or coop only.\n2: always.");
|
||||
cvar_t scr_conalpha = CVARC ("scr_conalpha", "0.7",
|
||||
Cvar_Limiter_ZeroToOne_Callback);
|
||||
cvar_t scr_consize = CVAR ("scr_consize", "0.5");
|
||||
|
@ -455,7 +454,7 @@ cvar_t r_glsl_offsetmapping_reliefmapping = CVARFD("r_glsl_offsetmapping_reliefm
|
|||
cvar_t r_glsl_turbscale_reflect = CVARFD ("r_glsl_turbscale_reflect", "1", CVAR_ARCHIVE, "Controls the strength of the water reflection ripples (used by the altwater glsl code).");
|
||||
cvar_t r_glsl_turbscale_refract = CVARFD ("r_glsl_turbscale_refract", "1", CVAR_ARCHIVE, "Controls the strength of the underwater ripples (used by the altwater glsl code).");
|
||||
|
||||
cvar_t r_fastturbcolour = CVARFD ("r_fastturbcolour", "0.1 0.2 0.3", CVAR_ARCHIVE, "The colour to use for water surfaces draw with r_waterstyle 0.\n");
|
||||
cvar_t r_fastturbcolour = CVARFD ("r_fastturbcolour", "0.1 0.2 0.3", CVAR_ARCHIVE, "The colour to use for water surfaces draw with r_waterstyle 0.");
|
||||
cvar_t r_waterstyle = CVARFD ("r_waterstyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Changes how water, and teleporters are drawn. Possible values are:\n0: fastturb-style block colour.\n1: regular q1-style water.\n2: refraction(ripply and transparent)\n3: refraction with reflection at an angle\n4: ripplemapped without reflections (requires particle effects)\n5: ripples+reflections");
|
||||
cvar_t r_slimestyle = CVARFD ("r_slimestyle", "", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "See r_waterstyle, but affects only slime. If empty, defers to r_waterstyle.");
|
||||
cvar_t r_lavastyle = CVARFD ("r_lavastyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "See r_waterstyle, but affects only lava. If empty, defers to r_waterstyle.");
|
||||
|
@ -477,21 +476,6 @@ extern cvar_t gl_dither;
|
|||
cvar_t gl_screenangle = CVAR("gl_screenangle", "0");
|
||||
#endif
|
||||
|
||||
#ifdef VKQUAKE
|
||||
cvar_t vk_stagingbuffers = CVARFD ("vk_stagingbuffers", "", CVAR_RENDERERLATCH, "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u(niform), e(lements), v(ertex), 0(none).");
|
||||
cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
|
||||
cvar_t vk_debug = CVARFD("vk_debug", "0", CVAR_VIDEOLATCH, "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
|
||||
cvar_t vk_dualqueue = CVARFD("vk_dualqueue", "", CVAR_VIDEOLATCH, "Attempt to use a separate queue for presentation. Blank for default.");
|
||||
cvar_t vk_busywait = CVARD ("vk_busywait", "", "Force busy waiting until the GPU finishes doing its thing.");
|
||||
cvar_t vk_waitfence = CVARD ("vk_waitfence", "", "Waits on fences, instead of semaphores. This is more likely to result in gpu stalls while the cpu waits.");
|
||||
cvar_t vk_usememorypools = CVARFD("vk_usememorypools", "", CVAR_VIDEOLATCH, "Allocates memory pools for sub allocations. Vulkan has a limit to the number of memory allocations allowed so this should always be enabled, however at this time FTE is unable to reclaim pool memory, and would require periodic vid_restarts to flush them.");
|
||||
cvar_t vk_nv_glsl_shader = CVARFD("vk_loadglsl", "", CVAR_VIDEOLATCH, "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after.");
|
||||
cvar_t vk_khr_get_memory_requirements2 = CVARFD("vk_khr_get_memory_requirements2", "", CVAR_VIDEOLATCH, "Enable extended memory info querires");
|
||||
cvar_t vk_khr_dedicated_allocation = CVARFD("vk_khr_dedicated_allocation", "", CVAR_VIDEOLATCH, "Flag vulkan memory allocations as dedicated, where applicable.");
|
||||
cvar_t vk_khr_push_descriptor = CVARFD("vk_khr_push_descriptor", "", CVAR_VIDEOLATCH, "Enables better descriptor streaming.");
|
||||
cvar_t vk_amd_rasterization_order = CVARFD("vk_amd_rasterization_order", "", CVAR_VIDEOLATCH, "Enables the use of relaxed rasterization ordering, for a small speedup at the minor risk of a little zfighting.");
|
||||
#endif
|
||||
|
||||
#ifdef D3D9QUAKE
|
||||
cvar_t d3d9_hlsl = CVAR("d3d_hlsl", "1");
|
||||
#endif
|
||||
|
@ -506,6 +490,8 @@ void GLD3DRenderer_Init(void)
|
|||
#endif
|
||||
|
||||
#if defined(GLQUAKE)
|
||||
extern cvar_t gl_blacklist_texture_compression;
|
||||
extern cvar_t gl_blacklist_generatemipmap;
|
||||
void GLRenderer_Init(void)
|
||||
{
|
||||
//gl-specific video vars
|
||||
|
@ -567,6 +553,8 @@ void GLRenderer_Init(void)
|
|||
|
||||
Cvar_Register (&r_shaderblobs, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&gl_compress, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&gl_blacklist_texture_compression, "gl blacklists");
|
||||
Cvar_Register (&gl_blacklist_generatemipmap, "gl blacklists");
|
||||
// Cvar_Register (&gl_detail, GRAPHICALNICETIES);
|
||||
// Cvar_Register (&gl_detailscale, GRAPHICALNICETIES);
|
||||
Cvar_Register (&gl_overbright, GRAPHICALNICETIES);
|
||||
|
@ -1023,19 +1011,7 @@ void Renderer_Init(void)
|
|||
Cvar_Register (&dpcompat_nopremulpics, GLRENDEREROPTIONS);
|
||||
#endif
|
||||
#ifdef VKQUAKE
|
||||
Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_debug, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_busywait, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_waitfence, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_usememorypools, VKRENDEREROPTIONS);
|
||||
|
||||
Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_get_memory_requirements2,VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_dedicated_allocation,VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_push_descriptor, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_amd_rasterization_order, VKRENDEREROPTIONS);
|
||||
VK_RegisterVulkanCvars();
|
||||
#endif
|
||||
|
||||
// misc
|
||||
|
@ -1870,6 +1846,7 @@ void R_ReloadRenderer_f (void)
|
|||
BZ_Free(portalblob);
|
||||
}
|
||||
#endif
|
||||
Con_DPrintf("vid_reload time: %f\n", Sys_DoubleTime() - time);
|
||||
}
|
||||
|
||||
static int R_PriorityForRenderer(rendererinfo_t *r)
|
||||
|
|
|
@ -115,7 +115,7 @@ typedef enum uploadfmt
|
|||
//floating point formats
|
||||
PTI_R16F,
|
||||
PTI_R32F,
|
||||
PTI_RGBA16F, //consider using e5bgr9
|
||||
PTI_RGBA16F, //consider using e5bgr9 or bc6/astc
|
||||
PTI_RGBA32F, //usually overkill
|
||||
//packed/misaligned formats: these are specified in native endian order (high bits listed first because that's how things are represented in hex), so may need byte swapping...
|
||||
PTI_A2BGR10, //mostly for rendertargets, might also be useful for overbight lightmaps.
|
||||
|
@ -126,63 +126,79 @@ typedef enum uploadfmt
|
|||
PTI_RGBA5551, //16bit alpha format (gl).
|
||||
PTI_ARGB1555, //16bit alpha format (d3d).
|
||||
//(desktop/tegra) compressed formats
|
||||
PTI_BC1_RGB,
|
||||
PTI_BC1_RGB_SRGB,
|
||||
PTI_BC1_RGBA,
|
||||
PTI_BC1_RGBA_SRGB,
|
||||
PTI_BC2_RGBA,
|
||||
PTI_BC2_RGBA_SRGB,
|
||||
PTI_BC3_RGBA, //maybe add a bc3 normalmapswizzle type for d3d9?
|
||||
PTI_BC3_RGBA_SRGB,
|
||||
PTI_BC4_R8, //greyscale, kinda
|
||||
PTI_BC4_R8_SNORM,
|
||||
PTI_BC5_RG8, //useful for normalmaps
|
||||
PTI_BC5_RG8_SNORM, //useful for normalmaps
|
||||
PTI_BC6_RGB_UFLOAT, //unsigned (half) floats!
|
||||
PTI_BC6_RGB_SFLOAT, //signed (half) floats!
|
||||
PTI_BC7_RGBA, //multimode compression, using as many bits as bc2/bc3
|
||||
PTI_BC7_RGBA_SRGB,
|
||||
PTI_BC1_RGB, /*4bpp*/
|
||||
PTI_BC1_RGB_SRGB, /*4bpp*/
|
||||
PTI_BC1_RGBA, /*4bpp*/
|
||||
PTI_BC1_RGBA_SRGB, /*4bpp*/
|
||||
PTI_BC2_RGBA, /*8bpp*/
|
||||
PTI_BC2_RGBA_SRGB, /*8bpp*/
|
||||
PTI_BC3_RGBA, /*8bpp*/ //maybe add a bc3 normalmapswizzle type for d3d9?
|
||||
PTI_BC3_RGBA_SRGB, /*8bpp*/
|
||||
PTI_BC4_R8, /*4bpp*/ //greyscale, kinda
|
||||
PTI_BC4_R8_SNORM, /*4bpp*/
|
||||
PTI_BC5_RG8, /*8bpp*/ //useful for normalmaps
|
||||
PTI_BC5_RG8_SNORM, /*8bpp*/ //useful for normalmaps
|
||||
PTI_BC6_RGB_UFLOAT, /*8bpp*/ //unsigned (half) floats!
|
||||
PTI_BC6_RGB_SFLOAT, /*8bpp*/ //signed (half) floats!
|
||||
PTI_BC7_RGBA, /*8bpp*/ //multimode compression, using as many bits as bc2/bc3
|
||||
PTI_BC7_RGBA_SRGB, /*8bpp*/
|
||||
//(mobile/intel) compressed formats
|
||||
PTI_ETC1_RGB8, //limited form
|
||||
PTI_ETC2_RGB8, //extended form
|
||||
PTI_ETC2_RGB8A1,
|
||||
PTI_ETC2_RGB8A8,
|
||||
PTI_ETC2_RGB8_SRGB,
|
||||
PTI_ETC2_RGB8A1_SRGB,
|
||||
PTI_ETC2_RGB8A8_SRGB,
|
||||
PTI_EAC_R11, //might be useful for overlays, with swizzles.
|
||||
PTI_EAC_R11_SNORM, //no idea what this might be used for, whatever
|
||||
PTI_EAC_RG11, //useful for normalmaps (calculate blue)
|
||||
PTI_EAC_RG11_SNORM, //useful for normalmaps (calculate blue)
|
||||
//astc... zomg
|
||||
PTI_ASTC_4X4,
|
||||
PTI_ETC1_RGB8, /*4bpp*/ //limited form
|
||||
PTI_ETC2_RGB8, /*4bpp*/ //extended form
|
||||
PTI_ETC2_RGB8A1, /*4bpp*/
|
||||
PTI_ETC2_RGB8A8, /*8bpp*/
|
||||
PTI_ETC2_RGB8_SRGB, /*4bpp*/
|
||||
PTI_ETC2_RGB8A1_SRGB,/*4bpp*/
|
||||
PTI_ETC2_RGB8A8_SRGB,/*8bpp*/
|
||||
PTI_EAC_R11, /*4bpp*/ //might be useful for overlays, with swizzles.
|
||||
PTI_EAC_R11_SNORM, /*4bpp*/ //no idea what this might be used for, whatever
|
||||
PTI_EAC_RG11, /*8bpp*/ //useful for normalmaps (calculate blue)
|
||||
PTI_EAC_RG11_SNORM, /*8bpp*/ //useful for normalmaps (calculate blue)
|
||||
//astc... zomg.
|
||||
PTI_ASTC_4X4_LDR, /*8bpp*/ //ldr/srgb/hdr formats are technically all the same.
|
||||
PTI_ASTC_5X4_LDR, /*6.40*/ //srgb formats are different because of an extra srgb lookup step
|
||||
PTI_ASTC_5X5_LDR, /*5.12*/ //ldr formats are identical to hdr except for the extended colour modes disabled.
|
||||
PTI_ASTC_6X5_LDR, /*4.17*/
|
||||
PTI_ASTC_6X6_LDR, /*3.56*/
|
||||
PTI_ASTC_8X5_LDR, /*3.20*/
|
||||
PTI_ASTC_8X6_LDR, /*2.67*/
|
||||
PTI_ASTC_10X5_LDR, /*2.56*/
|
||||
PTI_ASTC_10X6_LDR, /*2.13*/
|
||||
PTI_ASTC_8X8_LDR, /*2bpp*/
|
||||
PTI_ASTC_10X8_LDR, /*1.60*/
|
||||
PTI_ASTC_10X10_LDR, /*1.28*/
|
||||
PTI_ASTC_12X10_LDR, /*1.07*/
|
||||
PTI_ASTC_12X12_LDR, /*0.89*/
|
||||
PTI_ASTC_4X4_SRGB,
|
||||
PTI_ASTC_5X4,
|
||||
PTI_ASTC_5X4_SRGB,
|
||||
PTI_ASTC_5X5,
|
||||
PTI_ASTC_5X5_SRGB,
|
||||
PTI_ASTC_6X5,
|
||||
PTI_ASTC_6X5_SRGB,
|
||||
PTI_ASTC_6X6,
|
||||
PTI_ASTC_6X6_SRGB,
|
||||
PTI_ASTC_8X5,
|
||||
PTI_ASTC_8X5_SRGB,
|
||||
PTI_ASTC_8X6,
|
||||
PTI_ASTC_8X6_SRGB,
|
||||
PTI_ASTC_10X5,
|
||||
PTI_ASTC_10X5_SRGB,
|
||||
PTI_ASTC_10X6,
|
||||
PTI_ASTC_10X6_SRGB,
|
||||
PTI_ASTC_8X8,
|
||||
PTI_ASTC_8X8_SRGB,
|
||||
PTI_ASTC_10X8,
|
||||
PTI_ASTC_10X8_SRGB,
|
||||
PTI_ASTC_10X10,
|
||||
PTI_ASTC_10X10_SRGB,
|
||||
PTI_ASTC_12X10,
|
||||
PTI_ASTC_12X10_SRGB,
|
||||
PTI_ASTC_12X12,
|
||||
PTI_ASTC_12X12_SRGB,
|
||||
PTI_ASTC_4X4_HDR, //these are not strictly necessary, and are likely to be treated identically to the ldr versions, but they may use extra features that the hardware does not support
|
||||
PTI_ASTC_5X4_HDR,
|
||||
PTI_ASTC_5X5_HDR,
|
||||
PTI_ASTC_6X5_HDR,
|
||||
PTI_ASTC_6X6_HDR,
|
||||
PTI_ASTC_8X5_HDR,
|
||||
PTI_ASTC_8X6_HDR,
|
||||
PTI_ASTC_10X5_HDR,
|
||||
PTI_ASTC_10X6_HDR,
|
||||
PTI_ASTC_8X8_HDR,
|
||||
PTI_ASTC_10X8_HDR,
|
||||
PTI_ASTC_10X10_HDR,
|
||||
PTI_ASTC_12X10_HDR,
|
||||
PTI_ASTC_12X12_HDR,
|
||||
#define PTI_ASTC_FIRST PTI_ASTC_4X4_LDR
|
||||
#define PTI_ASTC_LAST PTI_ASTC_12X12_HDR
|
||||
|
||||
//depth formats
|
||||
PTI_DEPTH16,
|
||||
|
@ -200,12 +216,12 @@ typedef enum uploadfmt
|
|||
TF_TRANS8, /*8bit quake-palette image, index 255=transparent*/
|
||||
TF_TRANS8_FULLBRIGHT, /*fullbright 8 - fullbright texels have alpha 255, everything else 0*/
|
||||
TF_HEIGHT8, /*image data is greyscale, convert to a normalmap and load that, uploaded alpha contains the original heights*/
|
||||
TF_HEIGHT8PAL, /*source data is palette values rather than actual heights, generate a fallback heightmap*/
|
||||
TF_HEIGHT8PAL, /*source data is palette values rather than actual heights, generate a fallback heightmap. actual palette is ignored...*/
|
||||
TF_H2_T7G1, /*8bit data, odd indexes give greyscale transparence*/
|
||||
TF_H2_TRANS8_0, /*8bit data, 0 is transparent, not 255*/
|
||||
TF_H2_T4A4, /*8bit data, weird packing*/
|
||||
|
||||
PTI_LLLX8, /*RGB data where the RGB values were all the same. we can convert to L8 to use less memory (common with shirt/pants/reflection)*/
|
||||
PTI_LLLX8, /*RGBX data where the RGB values were all the same. we can convert to L8 to use less memory (common with shirt/pants/reflection)*/
|
||||
PTI_LLLA8, /*RGBA data where the RGB values were all the same. we can convert to LA8 to use less memory (common with gloss)*/
|
||||
|
||||
/*this block requires an explicit (separate) palette*/
|
||||
|
|
|
@ -202,6 +202,46 @@ static qboolean Alsa_InitAlsa(void)
|
|||
{
|
||||
static qboolean tried;
|
||||
static qboolean alsaworks;
|
||||
|
||||
static dllfunction_t funcs[] =
|
||||
{
|
||||
{(void**)&psnd_pcm_open, "snd_pcm_open"},
|
||||
{(void**)&psnd_pcm_close, "snd_pcm_close"},
|
||||
{(void**)&psnd_config_update_free_global, "snd_config_update_free_global"},
|
||||
{(void**)&psnd_strerror, "snd_strerror"},
|
||||
{(void**)&psnd_pcm_hw_params_any, "snd_pcm_hw_params_any"},
|
||||
{(void**)&psnd_pcm_hw_params_set_access, "snd_pcm_hw_params_set_access"},
|
||||
{(void**)&psnd_pcm_hw_params_set_format, "snd_pcm_hw_params_set_format"},
|
||||
{(void**)&psnd_pcm_hw_params_set_channels, "snd_pcm_hw_params_set_channels"},
|
||||
{(void**)&psnd_pcm_hw_params_set_rate_near, "snd_pcm_hw_params_set_rate_near"},
|
||||
{(void**)&psnd_pcm_hw_params_set_period_size_near, "snd_pcm_hw_params_set_period_size_near"},
|
||||
{(void**)&psnd_pcm_hw_params, "snd_pcm_hw_params"},
|
||||
{(void**)&psnd_pcm_sw_params_current, "snd_pcm_sw_params_current"},
|
||||
{(void**)&psnd_pcm_sw_params_set_start_threshold, "snd_pcm_sw_params_set_start_threshold"},
|
||||
{(void**)&psnd_pcm_sw_params_set_stop_threshold, "snd_pcm_sw_params_set_stop_threshold"},
|
||||
{(void**)&psnd_pcm_sw_params, "snd_pcm_sw_params"},
|
||||
{(void**)&psnd_pcm_hw_params_get_buffer_size, "snd_pcm_hw_params_get_buffer_size"},
|
||||
{(void**)&psnd_pcm_avail_update, "snd_pcm_avail_update"},
|
||||
{(void**)&psnd_pcm_state, "snd_pcm_state"},
|
||||
{(void**)&psnd_pcm_start, "snd_pcm_start"},
|
||||
{(void**)&psnd_pcm_recover, "snd_pcm_recover"},
|
||||
{(void**)&psnd_pcm_set_params, "snd_pcm_set_params"},
|
||||
{(void**)&psnd_pcm_hw_params_sizeof, "snd_pcm_hw_params_sizeof"},
|
||||
{(void**)&psnd_pcm_sw_params_sizeof, "snd_pcm_sw_params_sizeof"},
|
||||
{(void**)&psnd_pcm_hw_params_set_buffer_size_near, "snd_pcm_hw_params_set_buffer_size_near"},
|
||||
|
||||
{(void**)&psnd_pcm_mmap_begin, "snd_pcm_mmap_begin"},
|
||||
{(void**)&psnd_pcm_mmap_commit, "snd_pcm_mmap_commit"},
|
||||
|
||||
{(void**)&psnd_pcm_writei, "snd_pcm_writei"},
|
||||
{(void**)&psnd_pcm_prepare, "snd_pcm_prepare"},
|
||||
|
||||
{(void**)&psnd_device_name_hint, "snd_device_name_hint"},
|
||||
{(void**)&psnd_device_name_get_hint, "snd_device_name_get_hint"},
|
||||
{(void**)&psnd_device_name_free_hint, "snd_device_name_free_hint"},
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
if (tried)
|
||||
return alsaworks;
|
||||
tried = true;
|
||||
|
@ -211,80 +251,13 @@ static qboolean Alsa_InitAlsa(void)
|
|||
return false;
|
||||
|
||||
// Try alternative names of libasound, sometimes it is not linked correctly.
|
||||
alsasharedobject = dlopen("libasound.so.2", RTLD_LAZY|RTLD_LOCAL);
|
||||
alsasharedobject = Sys_LoadLibrary("libasound.so.2", funcs);
|
||||
if (!alsasharedobject)
|
||||
{
|
||||
alsasharedobject = dlopen("libasound.so", RTLD_LAZY|RTLD_LOCAL);
|
||||
if (!alsasharedobject)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
psnd_pcm_open = dlsym(alsasharedobject, "snd_pcm_open");
|
||||
psnd_pcm_close = dlsym(alsasharedobject, "snd_pcm_close");
|
||||
psnd_config_update_free_global = dlsym(alsasharedobject, "snd_config_update_free_global");
|
||||
psnd_strerror = dlsym(alsasharedobject, "snd_strerror");
|
||||
psnd_pcm_hw_params_any = dlsym(alsasharedobject, "snd_pcm_hw_params_any");
|
||||
psnd_pcm_hw_params_set_access = dlsym(alsasharedobject, "snd_pcm_hw_params_set_access");
|
||||
psnd_pcm_hw_params_set_format = dlsym(alsasharedobject, "snd_pcm_hw_params_set_format");
|
||||
psnd_pcm_hw_params_set_channels = dlsym(alsasharedobject, "snd_pcm_hw_params_set_channels");
|
||||
psnd_pcm_hw_params_set_rate_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_rate_near");
|
||||
psnd_pcm_hw_params_set_period_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_period_size_near");
|
||||
psnd_pcm_hw_params = dlsym(alsasharedobject, "snd_pcm_hw_params");
|
||||
psnd_pcm_sw_params_current = dlsym(alsasharedobject, "snd_pcm_sw_params_current");
|
||||
psnd_pcm_sw_params_set_start_threshold = dlsym(alsasharedobject, "snd_pcm_sw_params_set_start_threshold");
|
||||
psnd_pcm_sw_params_set_stop_threshold = dlsym(alsasharedobject, "snd_pcm_sw_params_set_stop_threshold");
|
||||
psnd_pcm_sw_params = dlsym(alsasharedobject, "snd_pcm_sw_params");
|
||||
psnd_pcm_hw_params_get_buffer_size = dlsym(alsasharedobject, "snd_pcm_hw_params_get_buffer_size");
|
||||
psnd_pcm_avail_update = dlsym(alsasharedobject, "snd_pcm_avail_update");
|
||||
psnd_pcm_state = dlsym(alsasharedobject, "snd_pcm_state");
|
||||
psnd_pcm_start = dlsym(alsasharedobject, "snd_pcm_start");
|
||||
psnd_pcm_recover = dlsym(alsasharedobject, "snd_pcm_recover");
|
||||
psnd_pcm_set_params = dlsym(alsasharedobject, "snd_pcm_set_params");
|
||||
psnd_pcm_hw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_hw_params_sizeof");
|
||||
psnd_pcm_sw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_sw_params_sizeof");
|
||||
psnd_pcm_hw_params_set_buffer_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_buffer_size_near");
|
||||
|
||||
psnd_pcm_mmap_begin = dlsym(alsasharedobject, "snd_pcm_mmap_begin");
|
||||
psnd_pcm_mmap_commit = dlsym(alsasharedobject, "snd_pcm_mmap_commit");
|
||||
|
||||
psnd_pcm_writei = dlsym(alsasharedobject, "snd_pcm_writei");
|
||||
psnd_pcm_prepare = dlsym(alsasharedobject, "snd_pcm_prepare");
|
||||
|
||||
psnd_device_name_hint = dlsym(alsasharedobject, "snd_device_name_hint");
|
||||
psnd_device_name_get_hint = dlsym(alsasharedobject, "snd_device_name_get_hint");
|
||||
psnd_device_name_free_hint = dlsym(alsasharedobject, "snd_device_name_free_hint");
|
||||
|
||||
alsaworks = psnd_pcm_open
|
||||
&& psnd_pcm_close
|
||||
&& psnd_config_update_free_global
|
||||
&& psnd_strerror
|
||||
&& psnd_pcm_hw_params_any
|
||||
&& psnd_pcm_hw_params_set_access
|
||||
&& psnd_pcm_hw_params_set_format
|
||||
&& psnd_pcm_hw_params_set_channels
|
||||
&& psnd_pcm_hw_params_set_rate_near
|
||||
&& psnd_pcm_hw_params_set_period_size_near
|
||||
&& psnd_pcm_hw_params
|
||||
&& psnd_pcm_sw_params_current
|
||||
&& psnd_pcm_sw_params_set_start_threshold
|
||||
&& psnd_pcm_sw_params_set_stop_threshold
|
||||
&& psnd_pcm_sw_params
|
||||
&& psnd_pcm_hw_params_get_buffer_size
|
||||
&& psnd_pcm_avail_update
|
||||
&& psnd_pcm_state
|
||||
&& psnd_pcm_start
|
||||
&& psnd_pcm_hw_params_sizeof
|
||||
&& psnd_pcm_sw_params_sizeof
|
||||
&& psnd_pcm_hw_params_set_buffer_size_near
|
||||
&& psnd_pcm_mmap_begin
|
||||
&& psnd_pcm_mmap_commit
|
||||
&& psnd_pcm_writei && psnd_pcm_prepare
|
||||
&& psnd_device_name_hint && psnd_device_name_get_hint && psnd_device_name_free_hint
|
||||
;
|
||||
alsasharedobject = Sys_LoadLibrary("libasound.so", funcs);
|
||||
if (!alsasharedobject)
|
||||
return false;
|
||||
|
||||
alsaworks = true;
|
||||
return alsaworks;
|
||||
}
|
||||
|
||||
|
|
|
@ -3143,12 +3143,13 @@ float S_GetChannelLevel(int entnum, int entchannel)
|
|||
if (sc->channel[i].entnum == entnum && sc->channel[i].entchannel == entchannel && sc->channel[i].sfx)
|
||||
{
|
||||
ssamplepos_t spos = sc->GetChannelPos?sc->GetChannelPos(sc, &sc->channel[i]):(sc->channel[i].pos>>PITCHSHIFT);
|
||||
if (sc->channel[i].sfx->decoder.decodedata)scache = sc->channel[i].sfx->decoder.decodedata(sc->channel[i].sfx, &scachebuf, spos, 1);
|
||||
if (sc->channel[i].sfx->decoder.decodedata)
|
||||
scache = sc->channel[i].sfx->decoder.decodedata(sc->channel[i].sfx, &scachebuf, spos, 1);
|
||||
else
|
||||
scache = NULL;
|
||||
|
||||
if (!scache)
|
||||
scache = sc->channel[i].sfx->decoder.buf;
|
||||
|
||||
if (scache && spos >= scache->soundoffset && spos < scache->soundoffset+scache->length)
|
||||
{
|
||||
spos -= scache->soundoffset;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "quakedef.h"
|
||||
#ifdef HAVE_MIXER
|
||||
#if defined(HAVE_MIXER) && defined(MULTITHREAD)
|
||||
|
||||
#if 0
|
||||
#include <pulse/simple.h>
|
||||
|
|
|
@ -128,13 +128,13 @@ static qboolean SSDL_InitAudio(void)
|
|||
#endif
|
||||
|
||||
if (!inited)
|
||||
if(SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE))
|
||||
{
|
||||
{
|
||||
if(0==SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE))
|
||||
inited = true;
|
||||
else
|
||||
Con_Printf("Couldn't initialize SDL audio subsystem (%s)\n", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
inited = true;
|
||||
return true;
|
||||
}
|
||||
return inited;
|
||||
}
|
||||
#else
|
||||
#define SDL_VERSION_ATLEAST(x,y,z) 0
|
||||
|
|
|
@ -99,7 +99,7 @@ qboolean isDedicated;
|
|||
|
||||
#if 1
|
||||
static int ansiremap[8] = {0, 4, 2, 6, 1, 5, 3, 7};
|
||||
static void ApplyColour(unsigned int chrflags)
|
||||
static void ApplyColour(FILE *out, unsigned int chrflags)
|
||||
{
|
||||
static int oldflags = CON_WHITEMASK;
|
||||
int bg, fg;
|
||||
|
@ -108,10 +108,10 @@ static void ApplyColour(unsigned int chrflags)
|
|||
return;
|
||||
oldflags = chrflags;
|
||||
|
||||
printf("\e[0;"); // reset
|
||||
fprintf(out, "\e[0;"); // reset
|
||||
|
||||
if (chrflags & CON_BLINKTEXT)
|
||||
printf("5;"); // set blink
|
||||
fprintf(out, "5;"); // set blink
|
||||
|
||||
bg = (chrflags & CON_BGMASK) >> CON_BGSHIFT;
|
||||
fg = (chrflags & CON_FGMASK) >> CON_FGSHIFT;
|
||||
|
@ -124,12 +124,12 @@ static void ApplyColour(unsigned int chrflags)
|
|||
{
|
||||
if (fg & 0x8) // intensive bit set for foreground
|
||||
{
|
||||
printf("1;"); // set bold/intensity ansi flag
|
||||
fprintf(out, "1;"); // set bold/intensity ansi flag
|
||||
fg &= 0x7; // strip intensive bit
|
||||
}
|
||||
|
||||
// set foreground and background colors
|
||||
printf("3%i;4%im", ansiremap[fg], ansiremap[bg]);
|
||||
fprintf(out, "3%i;4%im", ansiremap[fg], ansiremap[bg]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -137,22 +137,22 @@ static void ApplyColour(unsigned int chrflags)
|
|||
{
|
||||
//to get around wierd defaults (like a white background) we have these special hacks for colours 0 and 7
|
||||
case COLOR_BLACK:
|
||||
printf("7m"); // set inverse
|
||||
fprintf(out, "7m"); // set inverse
|
||||
break;
|
||||
case COLOR_GREY:
|
||||
printf("1;30m"); // treat as dark grey
|
||||
fprintf(out, "1;30m"); // treat as dark grey
|
||||
break;
|
||||
case COLOR_WHITE:
|
||||
printf("m"); // set nothing else
|
||||
fprintf(out, "m"); // set nothing else
|
||||
break;
|
||||
default:
|
||||
if (fg & 0x8) // intensive bit set for foreground
|
||||
{
|
||||
printf("1;"); // set bold/intensity ansi flag
|
||||
fprintf(out, "1;"); // set bold/intensity ansi flag
|
||||
fg &= 0x7; // strip intensive bit
|
||||
}
|
||||
|
||||
printf("3%im", ansiremap[fg]); // set foreground
|
||||
fprintf(out, "3%im", ansiremap[fg]); // set foreground
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -167,9 +167,16 @@ void Sys_Printf (char *fmt, ...)
|
|||
conchar_t *c, *e;
|
||||
wchar_t w;
|
||||
unsigned int codeflags, codepoint;
|
||||
FILE *out = stdout;
|
||||
|
||||
if (nostdout)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
out = stderr;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (text,sizeof(text)-1, fmt,argptr);
|
||||
|
@ -188,26 +195,26 @@ void Sys_Printf (char *fmt, ...)
|
|||
|
||||
if ((codeflags&CON_RICHFORECOLOUR) || (codepoint == '\n' && (codeflags&CON_NONCLEARBG)))
|
||||
codeflags = CON_WHITEMASK; //make sure we don't get annoying backgrounds on other lines.
|
||||
ApplyColour(codeflags);
|
||||
ApplyColour(out, codeflags);
|
||||
w = codepoint;
|
||||
if (w >= 0xe000 && w < 0xe100)
|
||||
{
|
||||
/*not all quake chars are ascii compatible, so map those control chars to safe ones so we don't mess up anyone's xterm*/
|
||||
if ((w & 0x7f) > 0x20)
|
||||
putc(w&0x7f, stdout);
|
||||
putc(w&0x7f, out);
|
||||
else if (w & 0x80)
|
||||
{
|
||||
static char tab[32] = "---#@.@@@@ # >.." "[]0123456789.---";
|
||||
putc(tab[w&31], stdout);
|
||||
putc(tab[w&31], out);
|
||||
}
|
||||
else
|
||||
{
|
||||
static char tab[32] = ".####.#### # >.." "[]0123456789.---";
|
||||
putc(tab[w&31], stdout);
|
||||
putc(tab[w&31], out);
|
||||
}
|
||||
}
|
||||
else if (w < ' ' && w != '\t' && w != '\r' && w != '\n')
|
||||
putc('?', stdout); //don't let anyone print escape codes or other things that could crash an xterm.
|
||||
putc('?', out); //don't let anyone print escape codes or other things that could crash an xterm.
|
||||
else
|
||||
{
|
||||
/*putwc doesn't like me. force it in utf8*/
|
||||
|
@ -215,20 +222,20 @@ void Sys_Printf (char *fmt, ...)
|
|||
{
|
||||
if (w > 0x800)
|
||||
{
|
||||
putc(0xe0 | ((w>>12)&0x0f), stdout);
|
||||
putc(0x80 | ((w>>6)&0x3f), stdout);
|
||||
putc(0xe0 | ((w>>12)&0x0f), out);
|
||||
putc(0x80 | ((w>>6)&0x3f), out);
|
||||
}
|
||||
else
|
||||
putc(0xc0 | ((w>>6)&0x1f), stdout);
|
||||
putc(0x80 | (w&0x3f), stdout);
|
||||
putc(0xc0 | ((w>>6)&0x1f), out);
|
||||
putc(0x80 | (w&0x3f), out);
|
||||
}
|
||||
else
|
||||
putc(w, stdout);
|
||||
putc(w, out);
|
||||
}
|
||||
}
|
||||
|
||||
ApplyColour(CON_WHITEMASK);
|
||||
fflush(stdout);
|
||||
ApplyColour(out, CON_WHITEMASK);
|
||||
fflush(out);
|
||||
}
|
||||
#else
|
||||
void Sys_Printf (char *fmt, ...)
|
||||
|
@ -736,9 +743,9 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
|
|||
|
||||
lib = NULL;
|
||||
if (!lib)
|
||||
lib = dlopen (name, RTLD_LAZY);
|
||||
lib = dlopen (name, RTLD_LOCAL|RTLD_LAZY);
|
||||
if (!lib && !strstr(name, ".so"))
|
||||
lib = dlopen (va("%s.so", name), RTLD_LAZY);
|
||||
lib = dlopen (va("%s.so", name), RTLD_LOCAL|RTLD_LAZY);
|
||||
if (!lib)
|
||||
{
|
||||
Con_DLPrintf(2,"%s\n", dlerror());
|
||||
|
@ -884,6 +891,17 @@ char *Sys_ConsoleInput(void)
|
|||
if (noconinput)
|
||||
return NULL;
|
||||
|
||||
#if defined(__linux__) && defined(_DEBUG)
|
||||
{
|
||||
int fl = fcntl (STDIN_FILENO, F_GETFL, 0);
|
||||
if (!(fl & FNDELAY))
|
||||
{
|
||||
fcntl(STDIN_FILENO, F_SETFL, fl | FNDELAY);
|
||||
Sys_Printf(CON_WARNING "stdin flags became blocking - gdb bug?\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// if (!qrenderer)
|
||||
{
|
||||
if (!fgets(text, sizeof(text), stdin))
|
||||
|
@ -1001,7 +1019,7 @@ int main (int c, const char **v)
|
|||
noconinput = COM_CheckParm("-noconinput");
|
||||
#ifndef __DJGPP__
|
||||
if (!noconinput)
|
||||
fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
|
||||
fcntl(STDIN_FILENO, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
|
||||
#endif
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
|
|
|
@ -4432,7 +4432,377 @@ static qboolean QDECL Mod_LoadQ2Model (model_t *mod, void *buffer, size_t fsize)
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef MODELFMT_MDX
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Kingpin model loading
|
||||
//basically md2, but with toggleable subobjects and object bounding boxes (fixme: use those for hitmesh instead of the mesh itself)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float scale[3]; // multiply qbyte verts by this
|
||||
float translate[3]; // then add this
|
||||
char name[16]; // frame name from grabbing
|
||||
dtrivertx_t verts[1]; // variable sized
|
||||
} dmdxframe_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int cmd;
|
||||
int obj;
|
||||
struct dmdxcommandvert_s
|
||||
{
|
||||
float s, t;
|
||||
int origvert;
|
||||
} vert[1];
|
||||
} dmdxcommand_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int magic;
|
||||
int version;
|
||||
int skinWidth;
|
||||
int skinHeight;
|
||||
int frameSize;
|
||||
int numSkins;
|
||||
int numVertices;
|
||||
int numTriangles_Unusable;
|
||||
int numGlCommands;
|
||||
int numFrames;
|
||||
int numSfxDefines_Unsupported;
|
||||
int numSfxEntries_Unsupported;
|
||||
int numSubObjects;
|
||||
int offsetSkins;
|
||||
int offsetTriangles_Unusable;
|
||||
int offsetFrames;
|
||||
int offsetGlCommands;
|
||||
int offsetVertexInfo_Whatever;
|
||||
int offsetSfxDefines_Unsupported;
|
||||
int offsetSfxEntries_Unsupported;
|
||||
int offsetBBoxFrames_HitmeshInstead;
|
||||
int offsetMaybeST_Bugged;
|
||||
int offsetEnd;
|
||||
} dmdxheader_t;
|
||||
|
||||
#define MDX_IDENT ('I'<<0)+('D'<<8)+('P'<<16)+('X'<<24)
|
||||
#define MDX_VERSION 4
|
||||
|
||||
#define Q2NUMVERTEXNORMALS 162
|
||||
extern vec3_t bytedirs[Q2NUMVERTEXNORMALS];
|
||||
|
||||
#ifndef SERVERONLY
|
||||
static void MDX_LoadSkins(galiasinfo_t *galias, model_t *mod, dmdxheader_t *pinmodel, char *skins)
|
||||
{
|
||||
int i;
|
||||
skinframe_t *frames;
|
||||
galiasskin_t *outskin = galias->ofsskins;
|
||||
|
||||
for (i = 0; i < LittleLong(pinmodel->numSkins); i++, outskin++)
|
||||
{
|
||||
frames = ZG_Malloc(&mod->memgroup, sizeof(*frames));
|
||||
outskin->frame = frames;
|
||||
outskin->numframes=1;
|
||||
|
||||
COM_CleanUpPath(skins); //blooming tanks.
|
||||
Q_strncpyz(frames->shadername, skins, sizeof(frames->shadername));
|
||||
|
||||
outskin->skinwidth = 0;
|
||||
outskin->skinheight = 0;
|
||||
outskin->skinspeed = 0;
|
||||
|
||||
skins += MD2MAX_SKINNAME;
|
||||
}
|
||||
galias->numskins = LittleLong(pinmodel->numSkins);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MDX_MAX_TRIANGLES 4096
|
||||
#define MDX_MAX_VERTS MDX_MAX_TRIANGLES*3
|
||||
static int MDX_MatchVert(struct dmdxcommandvert_s *list, int *count, struct dmdxcommandvert_s *newvert)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < *count; i++)
|
||||
{
|
||||
if (list[i].origvert == newvert->origvert &&
|
||||
list[i].s == newvert->s &&
|
||||
list[i].t == newvert->t)
|
||||
return i; //its a dupe!
|
||||
}
|
||||
if (i == MDX_MAX_VERTS)
|
||||
return 0;
|
||||
list[i] = *newvert;
|
||||
*count+=1;
|
||||
return i;
|
||||
}
|
||||
|
||||
static qboolean QDECL Mod_LoadKingpinModel (model_t *mod, void *buffer, size_t fsize)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
vec2_t *st_array;
|
||||
vec3_t *normals;
|
||||
#endif
|
||||
dmdxheader_t *pinmodel;
|
||||
|
||||
int version;
|
||||
int i, j, subobj;
|
||||
index_t *indexes;
|
||||
|
||||
vec3_t min;
|
||||
vec3_t max;
|
||||
|
||||
galiaspose_t *pose;
|
||||
galiasanimation_t *poutframe;
|
||||
dmdxframe_t *pinframe;
|
||||
int framesize;
|
||||
vecV_t *verts;
|
||||
dmdxcommand_t *pincmd, *pincmdend;
|
||||
|
||||
struct dmdxcommandvert_s tmpvert[MDX_MAX_VERTS];
|
||||
int numverts;
|
||||
struct
|
||||
{
|
||||
int newidx[3];
|
||||
} tri[MDX_MAX_TRIANGLES];
|
||||
int numtri;
|
||||
|
||||
int size;
|
||||
galiasinfo_t *galias, *root;
|
||||
|
||||
mod->engineflags |= MDLF_NEEDOVERBRIGHT;
|
||||
|
||||
pinmodel = (dmdxheader_t *)buffer;
|
||||
|
||||
if (fsize < sizeof(*pinmodel))
|
||||
{
|
||||
Con_Printf (CON_ERROR "%s is truncated\n", mod->name);
|
||||
return false;
|
||||
}
|
||||
version = LittleLong (pinmodel->version);
|
||||
if (version != MDX_VERSION)
|
||||
{
|
||||
Con_Printf (CON_ERROR "%s has wrong version number (%i should be %i)\n",
|
||||
mod->name, version, MDX_VERSION);
|
||||
return false;
|
||||
}
|
||||
if (LittleLong(pinmodel->offsetEnd) != fsize)
|
||||
{
|
||||
Con_Printf (CON_ERROR "%s is truncated\n", mod->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LittleLong(pinmodel->numFrames) < 1 ||
|
||||
LittleLong(pinmodel->numSkins) < 0 ||
|
||||
LittleLong(pinmodel->numTriangles_Unusable) < 1 ||
|
||||
LittleLong(pinmodel->numVertices) < 3 ||
|
||||
LittleLong(pinmodel->skinHeight) < 1 ||
|
||||
LittleLong(pinmodel->skinWidth) < 1 ||
|
||||
LittleLong(pinmodel->numSubObjects) < 1)
|
||||
{
|
||||
Con_Printf(CON_ERROR "Model %s has an invalid quantity\n", mod->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
mod->flags = 0;
|
||||
|
||||
mod->numframes = LittleLong(pinmodel->numFrames);
|
||||
|
||||
size = sizeof(galiasinfo_t)*pinmodel->numSubObjects
|
||||
+ LittleLong(pinmodel->numFrames)*sizeof(galiasanimation_t)*pinmodel->numSubObjects
|
||||
#ifndef SERVERONLY
|
||||
+ LittleLong(pinmodel->numSkins)*sizeof(galiasskin_t)
|
||||
#endif
|
||||
;
|
||||
|
||||
root = galias = ZG_Malloc(&mod->memgroup, size);
|
||||
|
||||
#ifndef SERVERONLY
|
||||
//skins
|
||||
galias->ofsskins = (galiasskin_t*)((galiasanimation_t*)(galias+pinmodel->numSubObjects) + LittleLong(pinmodel->numFrames)*pinmodel->numSubObjects);
|
||||
MDX_LoadSkins(galias, mod, pinmodel, ((char *)pinmodel+LittleLong(pinmodel->offsetSkins)));
|
||||
#else
|
||||
galias->numskins = LittleLong(pinmodel->numSkins);
|
||||
#endif
|
||||
|
||||
ClearBounds (mod->mins, mod->maxs);
|
||||
for (subobj = 0; subobj < pinmodel->numSubObjects; subobj++)
|
||||
{
|
||||
galias = &root[subobj];
|
||||
Mod_DefaultMesh(galias, mod->name, subobj);
|
||||
galias->ofsanimations = (galiasanimation_t*)(root+pinmodel->numSubObjects) + subobj*pinmodel->numFrames;
|
||||
galias->ofsskins = root->ofsskins;
|
||||
galias->numskins = root->numskins;
|
||||
galias->shares_verts = subobj;
|
||||
if (subobj > 0)
|
||||
root[subobj-1].nextsurf = galias;
|
||||
|
||||
//process the strips+fans, and split the verts into the appropriate submesh
|
||||
pincmd = (dmdxcommand_t *)((char *)pinmodel + LittleLong(pinmodel->offsetGlCommands));
|
||||
pincmdend = (dmdxcommand_t *)((char *)pinmodel + LittleLong(pinmodel->offsetGlCommands) + LittleLong(pinmodel->numGlCommands)*4);
|
||||
numverts = 0;
|
||||
numtri = 0;
|
||||
while (pincmd < pincmdend)
|
||||
{
|
||||
int n = LittleLong(pincmd->cmd);
|
||||
if (!n)
|
||||
break; //no more commands
|
||||
if (n < 0)
|
||||
{ //fan club
|
||||
n = -n;
|
||||
if (n > 2 && LittleLong(pincmd->obj) == subobj)
|
||||
{
|
||||
int first = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[0]);
|
||||
int prev = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[1]);
|
||||
for (i = 2; i < n && numtri < countof(tri); i++)
|
||||
{
|
||||
tri[numtri].newidx[0] = first;
|
||||
tri[numtri].newidx[1] = prev;
|
||||
tri[numtri].newidx[2] = prev = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[i]);
|
||||
numtri++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //stripper
|
||||
if (n > 2 && LittleLong(pincmd->obj) == subobj)
|
||||
{
|
||||
int first = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[0]);
|
||||
int prev = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[1]);
|
||||
for (i = 2; i < n && numtri < countof(tri); i++)
|
||||
{
|
||||
tri[numtri].newidx[2] = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[i]);
|
||||
if (i&1)
|
||||
{
|
||||
tri[numtri].newidx[0] = prev;
|
||||
tri[numtri].newidx[1] = first;
|
||||
}
|
||||
else
|
||||
{
|
||||
tri[numtri].newidx[0] = first;
|
||||
tri[numtri].newidx[1] = prev;
|
||||
}
|
||||
first = prev;
|
||||
prev = tri[numtri].newidx[2];
|
||||
|
||||
if (tri[numtri].newidx[0] == tri[numtri].newidx[1] ||
|
||||
tri[numtri].newidx[0] == tri[numtri].newidx[2] ||
|
||||
tri[numtri].newidx[1] == tri[numtri].newidx[2])
|
||||
continue; //degenerate... I doubt we'll see any though.
|
||||
numtri++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pincmd = (dmdxcommand_t*)&pincmd->vert[n];
|
||||
}
|
||||
for (i = 0; i < numverts; i++)
|
||||
{ //might as well byteswap that stuff now...
|
||||
tmpvert[i].origvert = LittleLong(tmpvert[i].origvert);
|
||||
tmpvert[i].s = LittleFloat(tmpvert[i].s);
|
||||
tmpvert[i].t = LittleFloat(tmpvert[i].t);
|
||||
}
|
||||
|
||||
galias->numverts = numverts;
|
||||
galias->numindexes = numtri*3;
|
||||
indexes = ZG_Malloc(&mod->memgroup, galias->numindexes*sizeof(*indexes));
|
||||
galias->ofs_indexes = indexes;
|
||||
|
||||
for (i = 0; i < numtri; i++, indexes+=3)
|
||||
{
|
||||
indexes[0] = tri[i].newidx[0];
|
||||
indexes[1] = tri[i].newidx[1];
|
||||
indexes[2] = tri[i].newidx[2];
|
||||
}
|
||||
|
||||
// s and t vertices
|
||||
#ifndef SERVERONLY
|
||||
st_array = ZG_Malloc(&mod->memgroup, sizeof(*st_array)*(numverts));
|
||||
galias->ofs_st_array = st_array;
|
||||
|
||||
for (j=0 ; j<numverts; j++)
|
||||
{
|
||||
st_array[j][0] = tmpvert[j].s;
|
||||
st_array[j][1] = tmpvert[j].t;
|
||||
}
|
||||
#endif
|
||||
|
||||
//frames
|
||||
poutframe = galias->ofsanimations;
|
||||
framesize = LittleLong (pinmodel->frameSize);
|
||||
|
||||
size = sizeof(galiaspose_t) + sizeof(vecV_t)*numverts;
|
||||
#ifndef SERVERONLY
|
||||
size += 3*sizeof(vec3_t)*numverts;
|
||||
#endif
|
||||
size *= pinmodel->numFrames;
|
||||
pose = (galiaspose_t *)ZG_Malloc(&mod->memgroup, size);
|
||||
verts = (vecV_t*)(pose+pinmodel->numFrames);
|
||||
#ifndef SERVERONLY
|
||||
normals = (vec3_t*)(verts+pinmodel->numFrames*numverts);
|
||||
#endif
|
||||
|
||||
for (i=0 ; i<LittleLong(pinmodel->numFrames) ; i++)
|
||||
{
|
||||
poutframe->poseofs = pose;
|
||||
poutframe->numposes = 1;
|
||||
galias->numanimations++;
|
||||
|
||||
#ifndef SERVERONLY
|
||||
pose->ofsnormals = normals;
|
||||
pose->ofssvector = &normals[galias->numverts];
|
||||
pose->ofstvector = &normals[galias->numverts*2];
|
||||
#endif
|
||||
|
||||
pinframe = ( dmdxframe_t * )( ( qbyte * )pinmodel + LittleLong (pinmodel->offsetFrames) + i * framesize );
|
||||
Q_strncpyz(poutframe->name, pinframe->name, sizeof(poutframe->name));
|
||||
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
pose->scale[j] = LittleFloat (pinframe->scale[j]);
|
||||
pose->scale_origin[j] = LittleFloat (pinframe->translate[j]);
|
||||
}
|
||||
|
||||
pose->ofsverts = verts;
|
||||
for (j=0 ; j<numverts; j++)
|
||||
{
|
||||
// verts are all 8 bit, so no swapping needed
|
||||
verts[j][0] = pose->scale_origin[0]+pose->scale[0]*pinframe->verts[tmpvert[j].origvert].v[0];
|
||||
verts[j][1] = pose->scale_origin[1]+pose->scale[1]*pinframe->verts[tmpvert[j].origvert].v[1];
|
||||
verts[j][2] = pose->scale_origin[2]+pose->scale[2]*pinframe->verts[tmpvert[j].origvert].v[2];
|
||||
#ifndef SERVERONLY
|
||||
VectorCopy(bytedirs[pinframe->verts[tmpvert[j].origvert].lightnormalindex], normals[j]);
|
||||
#endif
|
||||
}
|
||||
|
||||
VectorCopy ( pose->scale_origin, min );
|
||||
VectorMA ( pose->scale_origin, 255, pose->scale, max );
|
||||
|
||||
AddPointToBounds ( min, mod->mins, mod->maxs );
|
||||
AddPointToBounds ( max, mod->mins, mod->maxs );
|
||||
|
||||
poutframe++;
|
||||
pose++;
|
||||
verts += numverts;
|
||||
#ifndef SERVERONLY
|
||||
normals += numverts*3;
|
||||
#endif
|
||||
}
|
||||
|
||||
Mod_CompileTriangleNeighbours(mod, galias);
|
||||
Mod_BuildTextureVectors(galias);
|
||||
}
|
||||
|
||||
mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
|
||||
Mod_ClampModelSize(mod);
|
||||
Mod_ParseModelEvents(mod, root->ofsanimations, root->numanimations);
|
||||
|
||||
mod->meshinfo = root;
|
||||
mod->numframes = root->numanimations;
|
||||
mod->type = mod_alias;
|
||||
|
||||
mod->funcs.NativeTrace = Mod_Trace;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -8807,6 +9177,9 @@ void Alias_Register(void)
|
|||
#ifdef MD2MODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake2 Model (md2)", MD2IDALIASHEADER, Mod_LoadQ2Model);
|
||||
#endif
|
||||
#ifdef MODELFMT_MDX
|
||||
Mod_RegisterModelFormatMagic(NULL, "Kingpin Model (mdx)", MDX_IDENT, Mod_LoadKingpinModel);
|
||||
#endif
|
||||
#ifdef MD3MODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake3 Model (md3)", MD3_IDENT, Mod_LoadQ3Model);
|
||||
#endif
|
||||
|
|
|
@ -5228,7 +5228,7 @@ static void COM_ErrorMe_f(void)
|
|||
#ifdef LOADERTHREAD
|
||||
static void QDECL COM_WorkerCount_Change(cvar_t *var, char *oldvalue);
|
||||
cvar_t worker_flush = CVARD("worker_flush", "1", "If set, process the entire load queue, loading stuff faster but at the risk of stalling the main thread.");
|
||||
static cvar_t worker_count = CVARFCD("worker_count", "0", CVAR_NOTFROMSERVER, COM_WorkerCount_Change, "Specifies the number of worker threads to utilise.");
|
||||
static cvar_t worker_count = CVARFCD("worker_count", "", CVAR_NOTFROMSERVER, COM_WorkerCount_Change, "Specifies the number of worker threads to utilise.");
|
||||
static cvar_t worker_sleeptime = CVARFD("worker_sleeptime", "0", CVAR_NOTFROMSERVER, "Causes workers to sleep for a period of time after each job.");
|
||||
|
||||
#define WORKERTHREADS 16 //max
|
||||
|
@ -5475,7 +5475,9 @@ static int COM_WorkerThread(void *arg)
|
|||
thread->request = WR_NONE;
|
||||
thread->ackseq = com_workeracksequence;
|
||||
Sys_UnlockConditional(com_workercondition[group]);
|
||||
Sys_LockConditional(com_workercondition[WG_MAIN]);
|
||||
Sys_ConditionBroadcast(com_workercondition[WG_MAIN]); //try to wake up whoever wanted us to ack them
|
||||
Sys_UnlockConditional(com_workercondition[WG_MAIN]);
|
||||
Sys_LockConditional(com_workercondition[group]);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -83,11 +83,13 @@
|
|||
#define PSKMODELS //unreal's interchange format. Undesirable in terms of load times.
|
||||
#define HALFLIFEMODELS //horrible format that doesn't interact well with the rest of FTE's code. Unusable tools (due to license reasons).
|
||||
#define INTERQUAKEMODELS //Preferred model format, at least from an idealism perspective.
|
||||
#define MODELFMT_MDX //kingpin's format (for hitboxes+geomsets).
|
||||
#define RAGDOLL //ragdoll support. requires RBE support (via a plugin...).
|
||||
|
||||
//Image formats
|
||||
#define IMAGEFMT_KTX //Khronos TeXture. common on gles3 devices for etc2 compression
|
||||
#define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips.
|
||||
#define IMAGEFMT_ASTC //lame simple header around a single astc image. not needed for astc in ktx files etc. its better to use ktx files.
|
||||
#define IMAGEFMT_PBM //pbm/ppm/pgm/pfm family formats.
|
||||
#define IMAGEFMT_PSD //baselayer only.
|
||||
#define IMAGEFMT_HDR //an RGBE format.
|
||||
|
@ -104,6 +106,7 @@
|
|||
#define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet...
|
||||
#define DECOMPRESS_RGTC //bc4+bc5
|
||||
#define DECOMPRESS_BPTC //bc6+bc7
|
||||
#define DECOMPRESS_ASTC //ASTC, for drivers that don't support it properly.
|
||||
|
||||
// Game/Gamecode Support
|
||||
#define CSQC_DAT
|
||||
|
|
|
@ -170,8 +170,9 @@ typedef struct console_s
|
|||
conline_t *oldest;
|
||||
conline_t *current; // line where next message will be printed
|
||||
int x; // offset in current line for next print
|
||||
int cr;
|
||||
int cr; // last char printed was a carrage return so the next char printed will wipe the line.
|
||||
conline_t *display; // bottom of console displays this line
|
||||
float displayscroll; // to try to handle smoother scrolling.
|
||||
int displayoffset; // horizontal offset
|
||||
int vislines; // pixel lines
|
||||
int linesprinted; // for notify times
|
||||
|
@ -194,9 +195,9 @@ typedef struct console_s
|
|||
conline_t *footerline; //temp text at the bottom of the console
|
||||
conline_t *selstartline, *selendline;
|
||||
unsigned int selstartoffset, selendoffset;
|
||||
int mousedown[2]; //x,y position that the current buttons were clicked.
|
||||
float mousedown[2]; //x,y position that the current buttons were clicked.
|
||||
unsigned int buttonsdown;
|
||||
int mousecursor[2]; //x,y
|
||||
float mousecursor[2]; //x,y
|
||||
float mousedowntime; //time mouse1 last went down, to detect double-clicks
|
||||
|
||||
struct console_s *next;
|
||||
|
|
|
@ -810,6 +810,7 @@ static int QDECL COM_Dir_List(const char *name, qofs_t size, time_t mtime, void
|
|||
}
|
||||
else if (!Q_strcasecmp(link, "bsp") || !Q_strcasecmp(link, "spr") || !Q_strcasecmp(link, "mdl") || !Q_strcasecmp(link, "md3") || !Q_strcasecmp(link, "iqm") ||
|
||||
!Q_strcasecmp(link, "vvm") || !Q_strcasecmp(link, "psk") || !Q_strcasecmp(link, "dpm") || !Q_strcasecmp(link, "zym") || !Q_strcasecmp(link, "md5mesh") ||
|
||||
!Q_strcasecmp(link, "mdx") || !Q_strcasecmp(link, "md2") ||
|
||||
!Q_strcasecmp(link, "md5anim") || !Q_strcasecmp(link, "gltf") || !Q_strcasecmp(link, "glb") || !Q_strcasecmp(link, "ase") || !Q_strcasecmp(link, "lwo"))
|
||||
Q_snprintfz(link, sizeof(link), "\\tip\\Open in Model Viewer\\modelviewer\\%s", name);
|
||||
else if (!Q_strcasecmp(link, "qc") || !Q_strcasecmp(link, "src") || !Q_strcasecmp(link, "qh") || !Q_strcasecmp(link, "h") || !Q_strcasecmp(link, "c")
|
||||
|
@ -2417,10 +2418,8 @@ typedef struct {
|
|||
const char *puredesc;
|
||||
unsigned int inheritflags;
|
||||
} wildpaks_t;
|
||||
|
||||
static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_t mtime, void *vparam, searchpathfuncs_t *funcs)
|
||||
static void FS_AddSingleDataFile (const char *descriptor, wildpaks_t *param, searchpathfuncs_t *funcs)
|
||||
{
|
||||
wildpaks_t *param = vparam;
|
||||
vfsfile_t *vfs;
|
||||
searchpath_t *search;
|
||||
searchpathfuncs_t *newpak;
|
||||
|
@ -2434,7 +2433,7 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_
|
|||
for (search = com_searchpaths; search; search = search->next)
|
||||
{
|
||||
if (!Q_strcasecmp(search->logicalpath, pakfile)) //assumption: first member of structure is a char array
|
||||
return true; //already loaded (base paths?)
|
||||
return; //already loaded (base paths?)
|
||||
}
|
||||
|
||||
newpak = FS_GetOldPath(param->oldpaths, pakfile, &keptflags);
|
||||
|
@ -2448,16 +2447,16 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_
|
|||
{
|
||||
fs_finds++;
|
||||
if (!funcs->FindFile(funcs, &loc, descriptor, NULL))
|
||||
return true; //not found..
|
||||
return; //not found..
|
||||
vfs = funcs->OpenVFS(funcs, &loc, "rb");
|
||||
if (!vfs)
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
newpak = param->OpenNew (vfs, funcs, descriptor, pakfile, "");
|
||||
if (!newpak)
|
||||
{
|
||||
VFS_CLOSE(vfs);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2467,8 +2466,78 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_
|
|||
else
|
||||
Q_strncpyz(purefile, descriptor, sizeof(purefile));
|
||||
FS_AddPathHandle(param->oldpaths, purefile, pakfile, newpak, "", ((!Q_strncasecmp(descriptor, "pak", 3))?SPF_COPYPROTECTED:0)|keptflags|param->inheritflags, (unsigned int)-1);
|
||||
}
|
||||
typedef struct
|
||||
{
|
||||
//name table, to avoid too many reallocs
|
||||
char *names;
|
||||
size_t numnames;
|
||||
size_t maxnames;
|
||||
|
||||
return true;
|
||||
//file table, again to avoid excess reallocs
|
||||
struct wilddatafile_s
|
||||
{
|
||||
size_t nameofs;
|
||||
size_t size;
|
||||
time_t mtime;
|
||||
searchpathfuncs_t *source;
|
||||
} *files;
|
||||
size_t numfiles;
|
||||
size_t maxfiles;
|
||||
} filelist_t;
|
||||
static int QDECL FS_FindWildDataFiles (const char *descriptor, qofs_t size, time_t mtime, void *vparam, searchpathfuncs_t *funcs)
|
||||
{
|
||||
filelist_t *list = vparam;
|
||||
size_t name = list->numnames;
|
||||
size_t file = list->numfiles;
|
||||
|
||||
size_t dlen = strlen(descriptor);
|
||||
|
||||
if (list->numnames + dlen+1 > list->maxnames)
|
||||
Z_ReallocElements((void**)&list->names, &list->maxnames, list->numnames+dlen+1+8192, sizeof(*list->names));
|
||||
strcpy(list->names + name, descriptor);
|
||||
list->numnames += dlen+1;
|
||||
|
||||
if (list->numfiles + 1 > list->maxfiles)
|
||||
Z_ReallocElements((void**)&list->files, &list->maxfiles, list->numfiles+1+128, sizeof(*list->files));
|
||||
list->files[file].nameofs = name;
|
||||
list->files[file].size = size;
|
||||
list->files[file].mtime = mtime;
|
||||
list->files[file].source = funcs;
|
||||
list->numfiles += 1;
|
||||
|
||||
return true; //keep looking for more
|
||||
}
|
||||
static const char *qsortsucks;
|
||||
static int QDECL FS_SortWildDataFiles(const void *va, const void *vb)
|
||||
{
|
||||
const struct wilddatafile_s *a=va, *b=vb;
|
||||
const char *na=qsortsucks+a->nameofs, *nb=qsortsucks+b->nameofs;
|
||||
|
||||
//sort by modification time...
|
||||
if (a->mtime != b->mtime && a->mtime && b->mtime)
|
||||
return a->mtime > b->mtime;
|
||||
|
||||
//then fall back and sort by name
|
||||
return strcasecmp(na, nb);
|
||||
}
|
||||
static void FS_LoadWildDataFiles (filelist_t *list, wildpaks_t *wp)
|
||||
{
|
||||
size_t f;
|
||||
//sort them
|
||||
qsortsucks = list->names;
|
||||
qsort(list->files, list->numfiles, sizeof(*list->files), FS_SortWildDataFiles);
|
||||
qsortsucks = NULL;
|
||||
|
||||
for (f = 0; f < list->numfiles; f++)
|
||||
FS_AddSingleDataFile(list->names+list->files[f].nameofs, wp, list->files[f].source);
|
||||
list->numfiles = list->numnames = 0;
|
||||
|
||||
Z_Free(list->files);
|
||||
list->files = NULL;
|
||||
Z_Free(list->names);
|
||||
list->names = NULL;
|
||||
list->maxfiles = list->maxnames = 0;
|
||||
}
|
||||
|
||||
static searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname)
|
||||
|
@ -2645,6 +2714,7 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
|
|||
vfsfile_t *vfs;
|
||||
flocation_t loc;
|
||||
wildpaks_t wp;
|
||||
filelist_t list = {0};
|
||||
|
||||
Q_strncpyz(logicalpaths, logicalpath, sizeof(logicalpaths));
|
||||
FS_CleanDir(logicalpaths, sizeof(logicalpaths));
|
||||
|
@ -2680,7 +2750,7 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
|
|||
if (loadstuff & (1<<j))
|
||||
{
|
||||
wp.OpenNew = searchpathformats[j].OpenNew;
|
||||
FS_AddWildDataFiles(filename, 0, 0, &wp, search->handle);
|
||||
FS_AddSingleDataFile(filename, &wp, search->handle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2754,7 +2824,8 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
|
|||
wp.OpenNew = searchpathformats[j].OpenNew;
|
||||
|
||||
Q_snprintfz (pakfile, sizeof(pakfile), "*.%s", extension);
|
||||
search->handle->EnumerateFiles(search->handle, pakfile, FS_AddWildDataFiles, &wp);
|
||||
search->handle->EnumerateFiles(search->handle, pakfile, FS_FindWildDataFiles, &list);
|
||||
FS_LoadWildDataFiles(&list, &wp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2194,6 +2194,8 @@ neterr_t NET_SendLoopPacket (int sock, int length, const void *data, netadr_t *t
|
|||
{
|
||||
int i;
|
||||
loopback_t *loop;
|
||||
if (!length && !data) //NET_EnsureRoute tests.
|
||||
return NETERR_SENT;
|
||||
|
||||
sock &= 1;
|
||||
|
||||
|
|
|
@ -275,9 +275,6 @@ void Sys_Sleep (double seconds)
|
|||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#define STDIN 0
|
||||
#define STDOUT 1
|
||||
#define STDERR 2
|
||||
|
||||
typedef struct slaveserver_s
|
||||
{
|
||||
|
@ -386,10 +383,10 @@ pubsubserver_t *Sys_ForkServer(void)
|
|||
|
||||
if (!pid)
|
||||
{ //this is the child
|
||||
dup2(toslave[0], STDIN);
|
||||
dup2(toslave[0], STDIN_FILENO);
|
||||
close(toslave[1]);
|
||||
close(toslave[0]);
|
||||
dup2(tomaster[1], STDOUT);
|
||||
dup2(tomaster[1], STDOUT_FILENO);
|
||||
|
||||
isClusterSlave = true;
|
||||
|
||||
|
@ -459,9 +456,9 @@ pubsubserver_t *Sys_ForkServer(void)
|
|||
posix_spawn_file_actions_addclose(&action, toslave[1]);
|
||||
posix_spawn_file_actions_addclose(&action, tomaster[0]);
|
||||
|
||||
posix_spawn_file_actions_adddup2(&action, toslave[0], STDIN);
|
||||
posix_spawn_file_actions_adddup2(&action, tomaster[1], STDOUT);
|
||||
// posix_spawn_file_actions_adddup2(&action, tomaster[1], STDERR);
|
||||
posix_spawn_file_actions_adddup2(&action, toslave[0], STDIN_FILENO);
|
||||
posix_spawn_file_actions_adddup2(&action, tomaster[1], STDOUT_FILENO);
|
||||
// posix_spawn_file_actions_adddup2(&action, tomaster[1], STDERR_FILENO);
|
||||
|
||||
posix_spawn_file_actions_addclose(&action, toslave[0]);
|
||||
posix_spawn_file_actions_addclose(&action, tomaster[1]);
|
||||
|
@ -481,7 +478,7 @@ pubsubserver_t *Sys_ForkServer(void)
|
|||
|
||||
void Sys_InstructMaster(sizebuf_t *cmd)
|
||||
{
|
||||
write(STDOUT, cmd->data, cmd->cursize);
|
||||
write(STDOUT_FILENO, cmd->data, cmd->cursize);
|
||||
|
||||
//FIXME: handle partial writes.
|
||||
}
|
||||
|
@ -490,6 +487,16 @@ void SSV_CheckFromMaster(void)
|
|||
{
|
||||
static char inbuffer[1024];
|
||||
static int inbufsize;
|
||||
|
||||
#if defined(__linux__) && defined(_DEBUG)
|
||||
int fl = fcntl (STDIN_FILENO, F_GETFL, 0);
|
||||
if (!(fl & FNDELAY))
|
||||
{
|
||||
fcntl(STDIN_FILENO, F_SETFL, fl | FNDELAY);
|
||||
Sys_Printf(CON_WARNING "stdin flags became blocking - gdb bug?\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(inbufsize >= 2)
|
||||
|
@ -517,7 +524,7 @@ void SSV_CheckFromMaster(void)
|
|||
}
|
||||
|
||||
{
|
||||
ssize_t avail = read(STDIN, inbuffer+inbufsize, sizeof(inbuffer)-inbufsize);
|
||||
ssize_t avail = read(STDIN_FILENO, inbuffer+inbufsize, sizeof(inbuffer)-inbufsize);
|
||||
if (!avail)
|
||||
{ //eof
|
||||
SV_FinalMessage("Cluster shut down\n");
|
||||
|
|
|
@ -1770,6 +1770,8 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
|
|||
|
||||
for(surfnum=0; inf; inf=inf->nextsurf, surfnum++)
|
||||
{
|
||||
if (!inf->numindexes)
|
||||
continue;
|
||||
if (lod < inf->mindist || (inf->maxdist && lod >= inf->maxdist))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ extern cvar_t gl_picmip2d;
|
|||
extern cvar_t gl_compress;
|
||||
extern cvar_t gl_smoothcrosshair;
|
||||
extern cvar_t gl_texturemode, gl_texture_anisotropic_filtering;
|
||||
cvar_t gl_blacklist_texture_compression = CVARFD("gl_blacklist_texture_compression", "0", CVAR_RENDERERLATCH, "When enabled, blocks recognition of all compressed-texture formats. Does NOT block support for gl3 texture types like e5bgr9 nor rgba16f.");
|
||||
cvar_t gl_blacklist_generatemipmap = CVARFD("gl_blacklist_generatemipmap", "1", CVAR_RENDERERLATCH, "Self-generate mipmaps, instead of letting the graphics driver do it.");
|
||||
|
||||
float gl_anisotropy_factor;
|
||||
|
||||
|
@ -83,6 +85,10 @@ void GL_SetupFormats(void)
|
|||
float ver = gl_config.glversion;
|
||||
qboolean srgb = (gl_config.glversion >= (gl_config_gles?3.0:2.1)) || GL_CheckExtension("GL_EXT_texture_sRGB");
|
||||
|
||||
memset(&gl_config.formatinfo, 0, sizeof(gl_config.formatinfo));
|
||||
memset(&sh_config.texfmt, 0, sizeof(sh_config.texfmt));
|
||||
sh_config.hw_bc = sh_config.hw_etc = sh_config.hw_astc = 0;
|
||||
|
||||
if (gl_config_gles && ver >= 3.0 && ver <= 3.3)
|
||||
ver = 3.3; //treat gles3.0 as desktop 3.3, they're roughly equivelent in feature set.
|
||||
|
||||
|
@ -90,7 +96,7 @@ void GL_SetupFormats(void)
|
|||
bc1=bc2=bc3=true;
|
||||
if ((!gl_config_gles && ver >= 3.0) || GL_CheckExtension("GL_ARB_texture_compression_rgtc") || GL_CheckExtension("GL_EXT_texture_compression_rgtc"))
|
||||
bc45 = true;
|
||||
if ((!gl_config.gles && ver >= 4.2) || GL_CheckExtension("GL_ARB_texture_compression_bptc"))
|
||||
if ((!gl_config_gles && ver >= 4.2) || GL_CheckExtension("GL_ARB_texture_compression_bptc") || GL_CheckExtension("GL_EXT_texture_compression_bptc"))
|
||||
bc67 = true;
|
||||
|
||||
if (bc45)
|
||||
|
@ -119,6 +125,15 @@ void GL_SetupFormats(void)
|
|||
bc2 |= GL_CheckExtension("GL_ANGLE_texture_compression_dxt3"); //WARNING: can only use these if mip0 is a multiple of 4
|
||||
bc3 |= GL_CheckExtension("GL_ANGLE_texture_compression_dxt5");
|
||||
|
||||
#ifdef FTE_TARGET_WEB
|
||||
if (GL_CheckExtension("GL_WEBGL_compressed_texture_s3tc"))
|
||||
bc1 = bc2 = bc3 = true;
|
||||
if (GL_CheckExtension("GL_WEBGL_compressed_texture_s3tc"))
|
||||
bc1 = bc2 = bc3 = true;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*else if (sh_config.texfmt[PTI_ETC2_RGB8A8])
|
||||
{ //these are probably a bad choice...
|
||||
tc_ru = GL_COMPRESSED_R11_EAC;
|
||||
|
@ -271,6 +286,27 @@ void GL_SetupFormats(void)
|
|||
}
|
||||
}
|
||||
|
||||
//provide a cvar for ignoring all texture compression extensions.
|
||||
//this is more so that I can debug fallbacks.
|
||||
if (gl_blacklist_texture_compression.ival)
|
||||
{
|
||||
Con_Printf("gl_blacklist_texture_compression: driver/hardware texture compression is "CON_WARNING"blocked"CON_DEFAULT".\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bc1&&bc2&&bc3)
|
||||
{
|
||||
if (bc45)
|
||||
{
|
||||
if (bc67)
|
||||
sh_config.hw_bc = 3;
|
||||
else
|
||||
sh_config.hw_bc = 2;
|
||||
}
|
||||
else
|
||||
sh_config.hw_bc = 1;
|
||||
}
|
||||
|
||||
//block compresion formats.
|
||||
if (bc1)
|
||||
{
|
||||
|
@ -309,12 +345,14 @@ void GL_SetupFormats(void)
|
|||
glfmtb(PTI_BC7_RGBA_SRGB, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB);
|
||||
}
|
||||
|
||||
if (gl_config_gles && gl_config.glversion >= 3.0 && !sh_config.hw_bc)
|
||||
sh_config.hw_etc = 2; //assume that mobile chips have actual support. the bc1 check prevents this from being true on desktop chips.
|
||||
#ifdef FTE_TARGET_WEB
|
||||
if (GL_CheckExtension("WEBGL_compressed_texture_etc"))
|
||||
#else
|
||||
if ((gl_config.gles && gl_config.glversion >= 3.0) || (!gl_config.gles && (gl_config.glversion >= 4.3 || GL_CheckExtension("GL_ARB_ES3_compatibility"))))
|
||||
else if (GL_CheckExtension("GL_WEBGL_compressed_texture_etc"))
|
||||
sh_config.hw_etc = 2; //full etc2+eac
|
||||
#endif
|
||||
{
|
||||
if (sh_config.hw_etc>=2 || (!gl_config_gles && (gl_config.glversion >= 4.3 || GL_CheckExtension("GL_ARB_ES3_compatibility"))))
|
||||
{ //note that desktop drivers will not necessarily support these in hardware, but are required to at least pretend that they do.
|
||||
glfmtb(PTI_ETC1_RGB8, GL_COMPRESSED_RGB8_ETC2);
|
||||
glfmtb(PTI_ETC2_RGB8, GL_COMPRESSED_RGB8_ETC2);
|
||||
glfmtb(PTI_ETC2_RGB8A1, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
|
||||
|
@ -351,39 +389,73 @@ void GL_SetupFormats(void)
|
|||
glfmtb(PTI_EAC_RG11, GL_COMPRESSED_RG11_EAC);
|
||||
if (GL_CheckExtension("GL_OES_compressed_EAC_RG11_signed_texture"))
|
||||
glfmtb(PTI_EAC_RG11_SNORM, GL_COMPRESSED_SIGNED_RG11_EAC);
|
||||
|
||||
if (gl_config.formatinfo[PTI_ETC2_RGB8].internalformat && gl_config.formatinfo[PTI_EAC_RG11].internalformat &&
|
||||
gl_config.formatinfo[PTI_ETC2_RGB8A1].internalformat && gl_config.formatinfo[PTI_ETC2_RGB8A8].internalformat)
|
||||
sh_config.hw_etc = 2;
|
||||
else if (gl_config.formatinfo[PTI_ETC2_RGB8].internalformat || gl_config.formatinfo[PTI_ETC1_RGB8].internalformat)
|
||||
sh_config.hw_etc = 1;
|
||||
}
|
||||
|
||||
if (GL_CheckExtension("GL_KHR_texture_compression_astc_ldr") || (gl_config_gles && gl_config.glversion >= 3.2) || GL_CheckExtension("GL_ARB_ES3_2_compatibility"))
|
||||
if (GL_CheckExtension("GL_OES_texture_compression_astc"))
|
||||
sh_config.hw_astc = 3; //3d textures
|
||||
else if (GL_CheckExtension("GL_KHR_texture_compression_astc_hdr"))
|
||||
sh_config.hw_astc = 2; //hdr textures
|
||||
else if (GL_CheckExtension("GL_KHR_texture_compression_astc_ldr"))
|
||||
sh_config.hw_astc = 1; //ldr textures only.
|
||||
#ifdef FTE_TARGET_WEB
|
||||
else if (GL_CheckExtension("GL_WEBGL_compressed_texture_astc"))
|
||||
sh_config.hw_astc = 1; //need to use js getSupportedProfiles() to find the profiles, which is outside of our scope
|
||||
#endif
|
||||
if (sh_config.hw_astc || (gl_config_gles && gl_config.glversion >= 3.2) || GL_CheckExtension("GL_ARB_ES3_2_compatibility"))
|
||||
{ //astc ldr profile is a core part of gles 3.2
|
||||
glfmtb(PTI_ASTC_4X4, GL_COMPRESSED_RGBA_ASTC_4x4_KHR);
|
||||
//note that this does not necessarily mean the hardware itself supports it.
|
||||
glfmtb(PTI_ASTC_4X4_LDR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR);
|
||||
glfmtb(PTI_ASTC_5X4_LDR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR);
|
||||
glfmtb(PTI_ASTC_5X5_LDR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR);
|
||||
glfmtb(PTI_ASTC_6X5_LDR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR);
|
||||
glfmtb(PTI_ASTC_6X6_LDR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR);
|
||||
glfmtb(PTI_ASTC_8X5_LDR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR);
|
||||
glfmtb(PTI_ASTC_8X6_LDR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR);
|
||||
glfmtb(PTI_ASTC_10X5_LDR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR);
|
||||
glfmtb(PTI_ASTC_10X6_LDR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR);
|
||||
glfmtb(PTI_ASTC_8X8_LDR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR);
|
||||
glfmtb(PTI_ASTC_10X8_LDR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR);
|
||||
glfmtb(PTI_ASTC_10X10_LDR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR);
|
||||
glfmtb(PTI_ASTC_12X10_LDR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR);
|
||||
glfmtb(PTI_ASTC_12X12_LDR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR);
|
||||
glfmtb(PTI_ASTC_4X4_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
|
||||
glfmtb(PTI_ASTC_5X4, GL_COMPRESSED_RGBA_ASTC_5x4_KHR);
|
||||
glfmtb(PTI_ASTC_5X4_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
|
||||
glfmtb(PTI_ASTC_5X5, GL_COMPRESSED_RGBA_ASTC_5x5_KHR);
|
||||
glfmtb(PTI_ASTC_5X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
|
||||
glfmtb(PTI_ASTC_6X5, GL_COMPRESSED_RGBA_ASTC_6x5_KHR);
|
||||
glfmtb(PTI_ASTC_6X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
|
||||
glfmtb(PTI_ASTC_6X6, GL_COMPRESSED_RGBA_ASTC_6x6_KHR);
|
||||
glfmtb(PTI_ASTC_6X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
|
||||
glfmtb(PTI_ASTC_8X5, GL_COMPRESSED_RGBA_ASTC_8x5_KHR);
|
||||
glfmtb(PTI_ASTC_8X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
|
||||
glfmtb(PTI_ASTC_8X6, GL_COMPRESSED_RGBA_ASTC_8x6_KHR);
|
||||
glfmtb(PTI_ASTC_8X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
|
||||
glfmtb(PTI_ASTC_10X5, GL_COMPRESSED_RGBA_ASTC_10x5_KHR);
|
||||
glfmtb(PTI_ASTC_10X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
|
||||
glfmtb(PTI_ASTC_10X6, GL_COMPRESSED_RGBA_ASTC_10x6_KHR);
|
||||
glfmtb(PTI_ASTC_10X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
|
||||
glfmtb(PTI_ASTC_8X8, GL_COMPRESSED_RGBA_ASTC_8x8_KHR);
|
||||
glfmtb(PTI_ASTC_8X8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
|
||||
glfmtb(PTI_ASTC_10X8, GL_COMPRESSED_RGBA_ASTC_10x8_KHR);
|
||||
glfmtb(PTI_ASTC_10X8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
|
||||
glfmtb(PTI_ASTC_10X10, GL_COMPRESSED_RGBA_ASTC_10x10_KHR);
|
||||
glfmtb(PTI_ASTC_10X10_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
|
||||
glfmtb(PTI_ASTC_12X10, GL_COMPRESSED_RGBA_ASTC_12x10_KHR);
|
||||
glfmtb(PTI_ASTC_12X10_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
|
||||
glfmtb(PTI_ASTC_12X12, GL_COMPRESSED_RGBA_ASTC_12x12_KHR);
|
||||
glfmtb(PTI_ASTC_12X12_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
|
||||
}
|
||||
if (sh_config.hw_astc >= 2)
|
||||
{ //astc hdr profile uses the same texture formats, which is kinda annoying...
|
||||
glfmtb(PTI_ASTC_4X4_HDR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR);
|
||||
glfmtb(PTI_ASTC_5X4_HDR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR);
|
||||
glfmtb(PTI_ASTC_5X5_HDR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR);
|
||||
glfmtb(PTI_ASTC_6X5_HDR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR);
|
||||
glfmtb(PTI_ASTC_6X6_HDR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR);
|
||||
glfmtb(PTI_ASTC_8X5_HDR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR);
|
||||
glfmtb(PTI_ASTC_8X6_HDR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR);
|
||||
glfmtb(PTI_ASTC_10X5_HDR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR);
|
||||
glfmtb(PTI_ASTC_10X6_HDR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR);
|
||||
glfmtb(PTI_ASTC_8X8_HDR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR);
|
||||
glfmtb(PTI_ASTC_10X8_HDR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR);
|
||||
glfmtb(PTI_ASTC_10X10_HDR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR);
|
||||
glfmtb(PTI_ASTC_12X10_HDR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR);
|
||||
glfmtb(PTI_ASTC_12X12_HDR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -414,6 +486,7 @@ void GLDraw_Init (void)
|
|||
vid.flags &= ~VID_SRGBAWARE;
|
||||
|
||||
|
||||
sh_config.can_genmips = qglGenerateMipmap && !gl_blacklist_generatemipmap.ival;
|
||||
//figure out which extra features we can support on these drivers.
|
||||
r_deluxemapping = r_deluxemapping_cvar.ival;
|
||||
r_lightprepass = r_lightprepass_cvar.ival && sh_config.progs_supported;
|
||||
|
@ -644,6 +717,8 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
qboolean compress;
|
||||
qboolean storage = true;
|
||||
unsigned int bb, bw, bh;
|
||||
int levels = 0, genlevels;
|
||||
int layers = 1;
|
||||
|
||||
if (gl_config.gles)
|
||||
{
|
||||
|
@ -662,17 +737,27 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
default:
|
||||
case 0:
|
||||
targ = GL_TEXTURE_2D;
|
||||
layers = 1;
|
||||
break;
|
||||
case 1:
|
||||
targ = GL_TEXTURE_3D;
|
||||
layers = 1;
|
||||
break;
|
||||
case 2:
|
||||
targ = GL_TEXTURE_CUBE_MAP_ARB;
|
||||
layers = 1*6;
|
||||
break;
|
||||
case 3:
|
||||
targ = GL_TEXTURE_2D_ARRAY;
|
||||
layers = 1; //TODO
|
||||
break;
|
||||
}
|
||||
genlevels = levels = mips->mipcount / layers;
|
||||
if (!(tex->flags & IF_NOMIPMAP) && sh_config.can_genmips && gl_config.formatinfo[encoding].type && genlevels == 1 && mips->mip[0].data && mips->encoding != PTI_P8)
|
||||
{
|
||||
while ((mips->mip[0].width>>genlevels) || (mips->mip[0].height>>genlevels))
|
||||
genlevels++;
|
||||
}
|
||||
|
||||
GL_MTBind(0, targ, tex);
|
||||
|
||||
|
@ -690,6 +775,10 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
GL_MTBind(0, targ, tex);
|
||||
}
|
||||
|
||||
//this is annoying.
|
||||
if (mips->encoding >= PTI_ASTC_4X4_LDR && mips->encoding <= PTI_ASTC_12X12_LDR && gl_config.astc_decodeprecision)
|
||||
qglTexParameteri(targ, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, GL_RGBA8);
|
||||
|
||||
if (tex->flags&IF_CLAMP)
|
||||
{
|
||||
if (gl_config.glversion < 1.2 && !gl_config_gles)
|
||||
|
@ -739,13 +828,13 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
{
|
||||
if (tex->flags & IF_MIPCAP)
|
||||
{
|
||||
qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, min(nummips-1, gl_mipcap_min));
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, min(nummips-1, gl_mipcap_max));
|
||||
qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, min(genlevels-1, gl_mipcap_min));
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, min(genlevels-1, gl_mipcap_max));
|
||||
}
|
||||
else
|
||||
{
|
||||
qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, nummips-1);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, genlevels-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -822,10 +911,7 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
//FIXME: support array textures properly
|
||||
if (qglTexStorage3D && storage)
|
||||
{
|
||||
if (tex->flags & IF_TEXTYPE)
|
||||
qglTexStorage3D(targ, nummips/countof(cubeface), ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth);
|
||||
else
|
||||
qglTexStorage3D(targ, nummips, ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth);
|
||||
qglTexStorage3D(targ, genlevels, ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth);
|
||||
|
||||
for (i = 0; i < nummips; i++)
|
||||
{
|
||||
|
@ -848,15 +934,15 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
qglCompressedTexImage3D (targ, i, ifmt, mips->mip[i].width, mips->mip[i].height, mips->mip[0].depth, 0, mips->mip[i].datasize, mips->mip[i].data);
|
||||
}
|
||||
}
|
||||
|
||||
if (genlevels > levels)
|
||||
qglGenerateMipmap(targ);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (qglTexStorage2D && storage)
|
||||
{ //FIXME: destroy the old texture
|
||||
if (tex->flags & IF_TEXTYPE)
|
||||
qglTexStorage2D(targ, nummips/countof(cubeface), ifmt, mips->mip[0].width, mips->mip[0].height);
|
||||
else
|
||||
qglTexStorage2D(targ, nummips, ifmt, mips->mip[0].width, mips->mip[0].height);
|
||||
qglTexStorage2D(targ, genlevels, ifmt, mips->mip[0].width, mips->mip[0].height);
|
||||
|
||||
for (i = 0; i < nummips; i++)
|
||||
{
|
||||
|
@ -902,6 +988,9 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
}
|
||||
}
|
||||
|
||||
if (genlevels > levels)
|
||||
qglGenerateMipmap(targ);
|
||||
|
||||
#ifdef IMAGEFMT_KTX
|
||||
if (compress && gl_compress.ival>1 && gl_config.formatinfo[encoding].type)
|
||||
{
|
||||
|
@ -944,33 +1033,33 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
case GL_COMPRESSED_SIGNED_R11_EAC: out.encoding = PTI_EAC_R11_SNORM; break;
|
||||
case GL_COMPRESSED_RG11_EAC: out.encoding = PTI_EAC_RG11; break;
|
||||
case GL_COMPRESSED_SIGNED_RG11_EAC: out.encoding = PTI_EAC_RG11_SNORM; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: out.encoding = PTI_ASTC_4X4; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: out.encoding = PTI_ASTC_4X4_HDR; break; //play it safe and assume hdr.
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: out.encoding = PTI_ASTC_4X4_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: out.encoding = PTI_ASTC_5X4; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: out.encoding = PTI_ASTC_5X4_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: out.encoding = PTI_ASTC_5X4_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: out.encoding = PTI_ASTC_5X5; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: out.encoding = PTI_ASTC_5X5_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: out.encoding = PTI_ASTC_5X5_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: out.encoding = PTI_ASTC_6X5; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: out.encoding = PTI_ASTC_6X5_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: out.encoding = PTI_ASTC_6X5_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: out.encoding = PTI_ASTC_6X6; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: out.encoding = PTI_ASTC_6X6_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: out.encoding = PTI_ASTC_6X6_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: out.encoding = PTI_ASTC_8X5; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: out.encoding = PTI_ASTC_8X5_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: out.encoding = PTI_ASTC_8X5_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: out.encoding = PTI_ASTC_8X6; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: out.encoding = PTI_ASTC_8X6_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: out.encoding = PTI_ASTC_8X6_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: out.encoding = PTI_ASTC_10X5; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: out.encoding = PTI_ASTC_10X5_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: out.encoding = PTI_ASTC_10X5_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: out.encoding = PTI_ASTC_10X6; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: out.encoding = PTI_ASTC_10X6_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: out.encoding = PTI_ASTC_10X6_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: out.encoding = PTI_ASTC_8X8; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: out.encoding = PTI_ASTC_8X8_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: out.encoding = PTI_ASTC_8X8_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: out.encoding = PTI_ASTC_10X8; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: out.encoding = PTI_ASTC_10X8_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: out.encoding = PTI_ASTC_10X8_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: out.encoding = PTI_ASTC_10X10; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: out.encoding = PTI_ASTC_10X10_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: out.encoding = PTI_ASTC_10X10_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: out.encoding = PTI_ASTC_12X10; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: out.encoding = PTI_ASTC_12X10_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: out.encoding = PTI_ASTC_12X10_SRGB; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: out.encoding = PTI_ASTC_12X12; break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: out.encoding = PTI_ASTC_12X12_HDR; break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: out.encoding = PTI_ASTC_12X12_SRGB; break;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ cvar_t mod_terrain_sundir = CVARD("mod_terrain_sundir", "0.4 0.7 2", "The direct
|
|||
cvar_t mod_terrain_ambient = CVARD("mod_terrain_ambient", "0.5", "Proportion of ambient light.");
|
||||
cvar_t mod_terrain_shadows = CVARD("mod_terrain_shadows", "0", "Cast rays to determine whether parts of the terrain should be in shadow.");
|
||||
cvar_t mod_terrain_shadow_dist = CVARD("mod_terrain_shadow_dist", "2048", "How far rays should be cast in order to look for occlusing geometry.");
|
||||
cvar_t mod_terrain_brushlights = CVARD("mod_map_lights", "0", "Calculates lighting on brushes/patches.");
|
||||
cvar_t mod_terrain_brushtexscale = CVARD("mod_map_texscale", "1", "Defines the scale of texture texels. Use 1 for quake+quake2 maps, and 0.5 for quake3 maps.");
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -5546,7 +5548,8 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e)
|
|||
if (mod->submodelof)
|
||||
mod = mod->submodelof;
|
||||
hm->entsdirty = false;
|
||||
LightReloadEntities(hm->relightcontext, Mod_GetEntitiesString(mod), true);
|
||||
if (hm->relightcontext)
|
||||
LightReloadEntities(hm->relightcontext, Mod_GetEntitiesString(mod), true);
|
||||
|
||||
//FIXME: figure out some way to hint this without having to relight the entire frigging world.
|
||||
for (bt = hm->brushtextures; bt; bt = bt->next)
|
||||
|
@ -5835,11 +5838,15 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e)
|
|||
const miptex_t *tx = NULL;
|
||||
#endif
|
||||
|
||||
if (!Q_strcasecmp(bt->shadername, "clip") || !Q_strcasecmp(bt->shadername, "hint") || !Q_strcasecmp(bt->shadername, "skip"))
|
||||
bt->shader = R_RegisterShader(bt->shadername, SUF_LIGHTMAP, "{\nsurfaceparm nodraw\n}");
|
||||
else
|
||||
bt->shader = R_RegisterCustom (bt->shadername, SUF_LIGHTMAP, Shader_DefaultBSPQ1, NULL);
|
||||
// bt->shader = R_RegisterShader_Lightmap(bt->shadername);
|
||||
bt->shader = R_RegisterCustom (va("textures/%s", bt->shadername), SUF_LIGHTMAP, NULL, NULL);
|
||||
if (!bt->shader)
|
||||
{
|
||||
if (!Q_strcasecmp(bt->shadername, "clip") || !Q_strcasecmp(bt->shadername, "hint") || !Q_strcasecmp(bt->shadername, "skip"))
|
||||
bt->shader = R_RegisterShader(bt->shadername, SUF_LIGHTMAP, "{\nsurfaceparm nodraw\n}");
|
||||
else
|
||||
bt->shader = R_RegisterCustom (bt->shadername, SUF_LIGHTMAP, Shader_DefaultBSPQ1, NULL);
|
||||
// bt->shader = R_RegisterShader_Lightmap(bt->shadername);
|
||||
}
|
||||
|
||||
if (!Q_strncasecmp(bt->shadername, "sky", 3) && tx)
|
||||
R_InitSky (bt->shader, bt->shadername, (qbyte*)tx + tx->offsets[0], tx->width, tx->height);
|
||||
|
@ -5871,8 +5878,8 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e)
|
|||
|
||||
if (w<1) w = 64;
|
||||
if (h<1) h = 64;
|
||||
scale[0] = 1.0/w; //I hate needing this.
|
||||
scale[1] = 1.0/h;
|
||||
scale[0] = mod_terrain_brushtexscale.value/w; //I hate needing this.
|
||||
scale[1] = mod_terrain_brushtexscale.value/h;
|
||||
|
||||
while(bt->batches)
|
||||
{
|
||||
|
@ -7411,7 +7418,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
|||
|
||||
#ifdef RUNTIMELIGHTING
|
||||
hm->entsdirty = true;
|
||||
hm->relightcontext = LightStartup(NULL, mod, false, false);
|
||||
hm->relightcontext = mod_terrain_brushlights.ival?LightStartup(NULL, mod, mod_terrain_brushlights.ival>1, false):NULL;
|
||||
hm->lightthreadmem = BZ_Malloc(lightthreadctxsize);
|
||||
hm->inheritedlightthreadmem = false;
|
||||
#endif
|
||||
|
@ -8480,6 +8487,8 @@ void Terr_Init(void)
|
|||
Cvar_Register(&mod_terrain_ambient, "Terrain");
|
||||
Cvar_Register(&mod_terrain_shadows, "Terrain");
|
||||
Cvar_Register(&mod_terrain_shadow_dist, "Terrain");
|
||||
Cvar_Register(&mod_terrain_brushlights, "Terrain");
|
||||
Cvar_Register(&mod_terrain_brushtexscale, "Terrain");
|
||||
#endif
|
||||
|
||||
Mod_RegisterModelFormatText(NULL, "FTE Heightmap Map (hmp)", "terrain", Terr_LoadTerrainModel);
|
||||
|
|
|
@ -681,8 +681,12 @@ static void Shader_ParseFunc (shader_t *shader, char **ptr, shaderfunc_t *func)
|
|||
func->type = SHADER_FUNC_INVERSESAWTOOTH;
|
||||
else if (!Q_stricmp (token, "noise"))
|
||||
func->type = SHADER_FUNC_NOISE;
|
||||
else if (!Q_stricmp (token, "distanceramp")) //QFusion
|
||||
else
|
||||
{
|
||||
if (!Q_stricmp (token, "distanceramp")) //QFusion
|
||||
;
|
||||
else
|
||||
Con_Printf("Shader_ParseFunc: %s: unknown func %s\n", shader->name, token);
|
||||
func->type = SHADER_FUNC_CONSTANT; //not supported...
|
||||
Shader_ParseFloat (shader, ptr, 0);
|
||||
Shader_ParseFloat (shader, ptr, 0);
|
||||
|
|
|
@ -2939,7 +2939,7 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e)
|
|||
//front face
|
||||
qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), surf->mesh->xyz_array);
|
||||
qglDrawArrays(GL_POLYGON, 0, surf->mesh->numvertexes);
|
||||
// qglDrawRangeElements(GL_TRIANGLES, 0, surf->mesh->numvertexes, surf->mesh->numindexes, GL_INDEX_TYPE, surf->mesh->indexes);
|
||||
// qglDrawRangeElements(GL_TRIANGLES, 0, surf->mesh->numvertexes-1, surf->mesh->numindexes, GL_INDEX_TYPE, surf->mesh->indexes);
|
||||
RQuantAdd(RQUANT_SHADOWINDICIES, surf->mesh->numvertexes);
|
||||
|
||||
for (v = 0; v < surf->mesh->numvertexes; v++)
|
||||
|
|
|
@ -50,6 +50,7 @@ void (APIENTRY *qglEnable) (GLenum cap);
|
|||
void (APIENTRY *qglFinish) (void);
|
||||
void (APIENTRY *qglFlush) (void);
|
||||
void (APIENTRY *qglGenTextures) (GLsizei n, GLuint *textures);
|
||||
void (APIENTRY *qglGenerateMipmap)(GLenum target);
|
||||
void (APIENTRY *qglGetBooleanv) (GLenum pname, GLboolean *params);
|
||||
GLenum (APIENTRY *qglGetError) (void);
|
||||
void (APIENTRY *qglGetFloatv) (GLenum pname, GLfloat *params);
|
||||
|
@ -862,6 +863,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
|||
gl_config.arb_texture_compression = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
gl_config.astc_decodeprecision = GL_CheckExtension("GL_EXT_texture_compression_astc_decode_mode");
|
||||
/*
|
||||
if (GL_CheckExtension("GL_EXT_depth_bounds_test"))
|
||||
qglDepthBoundsEXT = (void *)getglext("glDepthBoundsEXT");
|
||||
|
@ -3349,6 +3352,11 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
|
|||
|
||||
GL_CheckExtensions (getglfunction);
|
||||
|
||||
if (gl_config.glversion >= 3.0)
|
||||
qglGenerateMipmap = (void *)getglext("glGenerateMipmap");
|
||||
else
|
||||
qglGenerateMipmap = NULL;
|
||||
|
||||
#ifndef FTE_TARGET_WEB
|
||||
if (!gl_config.gles)
|
||||
{
|
||||
|
|
|
@ -195,7 +195,7 @@ qboolean R_DrawSkyroom(shader_t *skyshader)
|
|||
|
||||
//q3 mustn't mask sky (breaks q3map2's invisible skyportals), whereas q1 must (or its a cheat). halflife doesn't normally expect masking.
|
||||
//we also MUST mask any sky inside skyrooms, or you'll see all the entities outside of the skyroom through the room's own sky (q3map2 skyportals are hopefully irrelevant in this case).
|
||||
#define SKYMUSTBEMASKED (r_worldentity.model->fromgame != fg_quake3 || ((r_refdef.flags & RDF_DISABLEPARTICLES) && !r_ignoreentpvs.ival))
|
||||
#define SKYMUSTBEMASKED (r_worldentity.model->fromgame != fg_quake3 || ((r_refdef.flags & RDF_DISABLEPARTICLES) && r_ignoreentpvs.ival))
|
||||
|
||||
/*
|
||||
=================
|
||||
|
|
|
@ -235,6 +235,7 @@ typedef struct {
|
|||
qboolean arb_texture_env_dot3;
|
||||
|
||||
qboolean arb_texture_compression; //means we support dynamic compression, rather than any specific compressed texture formats
|
||||
qboolean astc_decodeprecision; //means we can tell the gpu that our astc textures actually are ldr.
|
||||
|
||||
qboolean geometryshaders;
|
||||
qboolean arb_tessellation_shader;
|
||||
|
@ -652,6 +653,7 @@ extern void (APIENTRY *qglFinish) (void);
|
|||
extern void (APIENTRY *qglFlush) (void);
|
||||
extern void (APIENTRY *qglFrontFace) (GLenum mode);
|
||||
extern void (APIENTRY *qglGenTextures) (GLsizei n, GLuint *textures);
|
||||
extern void (APIENTRY *qglGenerateMipmap)(GLenum target);
|
||||
extern void (APIENTRY *qglGetBooleanv) (GLenum pname, GLboolean *params);
|
||||
extern GLenum (APIENTRY *qglGetError) (void);
|
||||
extern void (APIENTRY *qglGetFloatv) (GLenum pname, GLfloat *params);
|
||||
|
|
|
@ -682,9 +682,11 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei
|
|||
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
|
||||
#endif /* GL_EXT_texture_sRGB */
|
||||
|
||||
#ifndef GL_RGB9_E5
|
||||
#define GL_RGB9_E5 0x8C3D /*opengl 3.0*/
|
||||
#endif
|
||||
#ifndef GL_RG
|
||||
#define GL_RG 0x8227
|
||||
#define GL_RGB9_E5 0x8C3D /*opengl 3.0*/
|
||||
#define GL_R8 0x8229 /*opengl 3.0*/
|
||||
#define GL_R16 0x822A /*opengl 3.0*/
|
||||
#define GL_RG8 0x822B /*opengl 3.0*/
|
||||
|
@ -811,7 +813,9 @@ typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef GL_EXT_texture_compression_astc_decode_mode
|
||||
#define GL_TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69
|
||||
#endif
|
||||
|
||||
#ifndef GL_EXT_framebuffer_object
|
||||
#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -542,6 +542,12 @@ typedef struct programshared_s
|
|||
unsigned int supportedpermutations;
|
||||
unsigned char *cvardata;
|
||||
unsigned int cvardatasize;
|
||||
int shaderver; //glsl version
|
||||
char *preshade; //general prefixed #defines
|
||||
char *shadertext; //the glsl text
|
||||
unsigned char failed[(PERMUTATIONS+7)/8]; //so we don't try recompiling endlessly
|
||||
struct programpermu_s *permu[PERMUTATIONS]; //set once compiled.
|
||||
|
||||
#ifdef VKQUAKE
|
||||
qVkShaderModule vert; //for slightly faster regeneration
|
||||
qVkShaderModule frag;
|
||||
|
@ -549,14 +555,6 @@ typedef struct programshared_s
|
|||
qVkDescriptorSetLayout desclayout;
|
||||
struct pipeline_s *pipelines;
|
||||
#endif
|
||||
#define DELAYEDSHADERCOMPILE
|
||||
#ifdef DELAYEDSHADERCOMPILE
|
||||
int shaderver; //glsl version
|
||||
char *preshade; //general prefixed #defines
|
||||
char *shadertext; //the glsl text
|
||||
unsigned char failed[(PERMUTATIONS+7)/8]; //so we don't try recompiling endlessly
|
||||
struct programpermu_s *permu[PERMUTATIONS]; //set once compiled.
|
||||
#endif
|
||||
} program_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -798,6 +796,7 @@ typedef struct
|
|||
unsigned int maxver; //highest glsl version usable
|
||||
unsigned int max_gpu_bones; //max number of bones supported by uniforms.
|
||||
|
||||
int hw_bc, hw_etc, hw_astc; //these are set only if the hardware actually supports the format, and not if we think the drivers are software-decoding them (unlike texfmt).
|
||||
qboolean texfmt[PTI_MAX]; //which texture formats are supported (renderable not implied)
|
||||
unsigned int texture2d_maxsize; //max size of a 2d texture
|
||||
unsigned int texture3d_maxsize; //max size of a 3d texture
|
||||
|
@ -812,6 +811,7 @@ typedef struct
|
|||
qboolean env_add;
|
||||
qboolean can_mipcap; //gl1.2+
|
||||
qboolean can_mipbias; //gl1.4+
|
||||
qboolean can_genmips; //gl3.0+
|
||||
qboolean havecubemaps; //since gl1.3, so pretty much everyone will have this... should probably only be set if we also have seamless or clamp-to-edge.
|
||||
|
||||
void (*pDeleteProg) (program_t *prog);
|
||||
|
@ -841,6 +841,7 @@ extern const struct sh_defaultsamplers_s
|
|||
|
||||
#ifdef VKQUAKE
|
||||
qboolean VK_LoadBlob(program_t *prog, void *blobdata, const char *name);
|
||||
void VK_RegisterVulkanCvars(void);
|
||||
#endif
|
||||
|
||||
#ifdef GLQUAKE
|
||||
|
|
|
@ -2743,7 +2743,7 @@ retry:
|
|||
if (!trysleft) //the progs exists, let's just be happy about it.
|
||||
externs->Printf("Progs is out of date and uncompilable\n");
|
||||
|
||||
if (externs->CheckHeaderCrc && !externs->CheckHeaderCrc(&progfuncs->funcs, prinst.pr_typecurrent, pr_progs->crc))
|
||||
if (externs->CheckHeaderCrc && !externs->CheckHeaderCrc(&progfuncs->funcs, prinst.pr_typecurrent, pr_progs->crc, filename))
|
||||
{
|
||||
// externs->Printf ("%s system vars have been modified, progdefs.h is out of date\n", filename);
|
||||
PRHunkFree(progfuncs, hmark);
|
||||
|
|
|
@ -212,7 +212,7 @@ typedef struct progexterns_s {
|
|||
int (VARGS *DPrintf) (const char *, ...) LIKEPRINTF(1);
|
||||
void (VARGS *Sys_Error) (const char *, ...) LIKEPRINTF(1);
|
||||
void (VARGS *Abort) (char *, ...) LIKEPRINTF(1);
|
||||
pbool (PDECL *CheckHeaderCrc) (pubprogfuncs_t *inst, progsnum_t idx, int crc);
|
||||
pbool (PDECL *CheckHeaderCrc) (pubprogfuncs_t *inst, progsnum_t idx, int crc, const char *filename);
|
||||
|
||||
void (PDECL *entspawn) (struct edict_s *ent, int loading); //ent has been spawned, but may not have all the extra variables (that may need to be set) set
|
||||
pbool (PDECL *entcanfree) (struct edict_s *ent); //return true to stop ent from being freed
|
||||
|
|
|
@ -711,7 +711,7 @@ static qboolean QDECL SVPR_Event_ContentsTransition(world_t *w, wedict_t *ent, i
|
|||
#define H2MP_PROGHEADER_CRC 26905 //hexen2 mission pack uses slightly different defs... *sigh*...
|
||||
#define H2DEMO_PROGHEADER_CRC 14046 //I'm guessing this is from the original release or something
|
||||
|
||||
pbool PDECL PR_SSQC_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc)
|
||||
pbool PDECL PR_SSQC_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc, const char *filename)
|
||||
{
|
||||
progstype_t modtype;
|
||||
if (crc == QW_PROGHEADER_CRC)
|
||||
|
@ -734,7 +734,10 @@ pbool PDECL PR_SSQC_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc
|
|||
progstype = modtype;
|
||||
//if the new one differs from the main module, reject it, unless it has crc 0, which we'll allow as a universal mutator (good luck guessing the correct arguments, but hey).
|
||||
if (progstype != modtype && crc != 0)
|
||||
{
|
||||
Con_Printf("Unable to load \"%s\" due to mismatched gametype/progdefs\n", filename);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static void *PDECL SSQC_PRReadFile (const char *path, qbyte *(PDECL *buf_get)(void *buf_ctx, size_t size), void *buf_ctx, size_t *size, pbool issource)
|
||||
|
|
|
@ -1260,10 +1260,12 @@ qboolean MSV_ClusterLoginSQLResult(queryrequest_t *req, int firstrow, int numrow
|
|||
}
|
||||
#endif
|
||||
|
||||
qboolean MSV_IgnoreSQLResult(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof)
|
||||
#if 0
|
||||
static qboolean MSV_IgnoreSQLResult(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
void MSV_OpenUserDatabase(void)
|
||||
{
|
||||
#if 0
|
||||
|
|
|
@ -1132,7 +1132,7 @@ static void SVC_Status (void)
|
|||
int ping;
|
||||
int top, bottom;
|
||||
char frags[64];
|
||||
char *skin, *team, *botpre;
|
||||
char *skin, *team, *botpre, *specpre;
|
||||
|
||||
int slots=0;
|
||||
|
||||
|
@ -1170,6 +1170,7 @@ static void SVC_Status (void)
|
|||
else
|
||||
botpre = "";
|
||||
|
||||
specpre = "";
|
||||
if (cl->spectator)
|
||||
{ //silly mvdsv stuff
|
||||
if (displayflags & STATUS_SPECTATORS_AS_PLAYERS)
|
||||
|
@ -1181,7 +1182,7 @@ static void SVC_Status (void)
|
|||
{
|
||||
ping = -ping;
|
||||
sprintf(frags, "%i", -9999);
|
||||
name = va("\\s\\%s", name);
|
||||
specpre = "\\s\\";
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1189,15 +1190,15 @@ static void SVC_Status (void)
|
|||
|
||||
if (displayflags & STATUS_SHOWTEAMS)
|
||||
{
|
||||
Con_Printf ("%i %s %i %i \"%s%s\" \"%s\" %i %i \"%s\"\n", cl->userid,
|
||||
Con_Printf ("%i %s %i %i \"%s%s%s\" \"%s\" %i %i \"%s\"\n", cl->userid,
|
||||
frags, (int)(realtime - cl->connection_started)/60,
|
||||
ping, botpre, name, skin, top, bottom, team);
|
||||
ping, specpre, botpre, name, skin, top, bottom, team);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf ("%i %s %i %i \"%s%s\" \"%s\" %i %i\n", cl->userid,
|
||||
Con_Printf ("%i %s %i %i \"%s%s%s\" \"%s\" %i %i\n", cl->userid,
|
||||
frags, (int)(realtime - cl->connection_started)/60,
|
||||
ping, botpre, name, skin, top, bottom);
|
||||
ping, specpre, botpre, name, skin, top, bottom);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
!!cvardf r_tessellation_level=5
|
||||
!!samps !EIGHTBIT diffuse normalmap specular fullbright upper lower reflectmask reflectcube
|
||||
!!samps =EIGHTBIT paletted 1
|
||||
!!samps =OCCLUDE occlusion
|
||||
//!!permu VC // adds rgba vertex colour multipliers
|
||||
//!!permu SPECULAR // auto-added when gl_specular>0
|
||||
//!!permu OFFSETMAPPING // auto-added when r_glsl_offsetmapping is set
|
||||
|
@ -21,6 +22,7 @@
|
|||
//!!permu SG // specularmap is rgb:F0, a:Roughness (instead of exponent)
|
||||
//!!permu PBR // an attempt at pbr logic (enabled from ORM or SG)
|
||||
//!!permu NOOCCLUDE // ignores the use of ORM's occlusion... yeah, stupid.
|
||||
//!!permu OCCLUDE // use an explicit occlusion texturemap (separate from roughness+metalness).
|
||||
//!!permu EIGHTBIT // uses software-style paletted colourmap lookups
|
||||
//!!permu ALPHATEST // if defined, this is the required alpha level (more versatile than doing it at the q3shader level)
|
||||
|
||||
|
@ -329,12 +331,12 @@ void main ()
|
|||
#define ambientrgb (specrgb+col.rgb)
|
||||
vec3 specrgb = mix(vec3(dielectricSpecular), col.rgb, metalness);
|
||||
col.rgb = col.rgb * (1.0 - dielectricSpecular) * (1.0-metalness);
|
||||
#elif defined(SG) //pbr-style specular+glossiness
|
||||
#elif defined(SG) //pbr-style specular+glossiness, without occlusion
|
||||
//occlusion needs to be baked in. :(
|
||||
#define roughness (1.0-specs.a)
|
||||
#define gloss (specs.a)
|
||||
#define specrgb specs.rgb
|
||||
#define ambientrgb (specs.rgb+col.rgb)
|
||||
#define ambientrgb (specrgb+col.rgb)
|
||||
#else //blinn-phong
|
||||
#define roughness (1.0-specs.a)
|
||||
#define gloss specs.a
|
||||
|
@ -378,7 +380,9 @@ void main ()
|
|||
col.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;
|
||||
#endif
|
||||
|
||||
#if defined(occlusion) && !defined(NOOCCLUDE)
|
||||
#ifdef OCCLUDE
|
||||
col.rgb *= texture2D(s_occlusion, tc).r;
|
||||
#elif defined(occlusion) && !defined(NOOCCLUDE)
|
||||
col.rgb *= occlusion;
|
||||
#endif
|
||||
col *= light * e_colourident;
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
!!samps diffuse normalmap specular fullbright lightmap
|
||||
!!samps deluxmap reflectmask reflectcube
|
||||
!!argb vertexlit=0
|
||||
!!samps paletted 1
|
||||
!!argb eightbit=0
|
||||
//!!samps =EIGHTBIT paletted 1
|
||||
//!!argb eightbit=0
|
||||
!!argf mask=1.0
|
||||
!!argb masklt=false
|
||||
!!permu FOG
|
||||
|
@ -114,7 +114,7 @@ void main ()
|
|||
lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb;
|
||||
}
|
||||
#else
|
||||
if (arg_eightbit)
|
||||
/*if (arg_eightbit)
|
||||
{
|
||||
//optional: round the lightmap coords to ensure all pixels within a texel have different lighting values either. it just looks wrong otherwise.
|
||||
//don't bother if its lightstyled, such cases will have unpredictable correlations anyway.
|
||||
|
@ -122,7 +122,7 @@ void main ()
|
|||
vec2 nearestlm0 = floor(lm0 * 256.0*8.0)/(256.0*8.0);
|
||||
lightmaps = (texture2D(s_lightmap, nearestlm0) * e_lmscale).rgb;
|
||||
}
|
||||
else
|
||||
else*/
|
||||
lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb;
|
||||
//modulate by the bumpmap dot light
|
||||
if (DELUXE)
|
||||
|
@ -165,7 +165,7 @@ void main ()
|
|||
gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;
|
||||
}
|
||||
|
||||
if (arg_eightbit)
|
||||
/*if (arg_eightbit)
|
||||
{
|
||||
//FIXME: with this extra flag, half the permutations are redundant.
|
||||
lightmaps *= 0.5; //counter the fact that the colourmap contains overbright values and logically ranges from 0 to 2 intead of to 1.
|
||||
|
@ -175,7 +175,7 @@ void main ()
|
|||
gl_FragColor.g = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.g)).g; //its not very softwarey, but re-palettizing is ugly.
|
||||
gl_FragColor.b = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.b)).b; //without lits, it should be identical.
|
||||
}
|
||||
else
|
||||
else*/
|
||||
{
|
||||
//now we have our diffuse+specular terms, modulate by lightmap values.
|
||||
gl_FragColor.rgb *= lightmaps.rgb;
|
||||
|
|
|
@ -6,18 +6,45 @@
|
|||
#include "renderque.h" //is anything still using this?
|
||||
|
||||
extern qboolean vid_isfullscreen;
|
||||
extern cvar_t vk_submissionthread;
|
||||
extern cvar_t vk_debug;
|
||||
extern cvar_t vk_dualqueue;
|
||||
extern cvar_t vk_busywait;
|
||||
extern cvar_t vk_waitfence;
|
||||
extern cvar_t vk_nv_glsl_shader;
|
||||
extern cvar_t vk_khr_get_memory_requirements2;
|
||||
extern cvar_t vk_khr_dedicated_allocation;
|
||||
extern cvar_t vk_khr_push_descriptor;
|
||||
extern cvar_t vk_amd_rasterization_order;
|
||||
extern cvar_t vk_usememorypools;
|
||||
|
||||
cvar_t vk_stagingbuffers = CVARFD ("vk_stagingbuffers", "", CVAR_RENDERERLATCH, "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u(niform), e(lements), v(ertex), 0(none).");
|
||||
static cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
|
||||
static cvar_t vk_debug = CVARFD("vk_debug", "0", CVAR_VIDEOLATCH, "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
|
||||
static cvar_t vk_dualqueue = CVARFD("vk_dualqueue", "", CVAR_VIDEOLATCH, "Attempt to use a separate queue for presentation. Blank for default.");
|
||||
static cvar_t vk_busywait = CVARD ("vk_busywait", "", "Force busy waiting until the GPU finishes doing its thing.");
|
||||
static cvar_t vk_waitfence = CVARD ("vk_waitfence", "", "Waits on fences, instead of semaphores. This is more likely to result in gpu stalls while the cpu waits.");
|
||||
static cvar_t vk_usememorypools = CVARFD("vk_usememorypools", "", CVAR_VIDEOLATCH, "Allocates memory pools for sub allocations. Vulkan has a limit to the number of memory allocations allowed so this should always be enabled, however at this time FTE is unable to reclaim pool memory, and would require periodic vid_restarts to flush them.");
|
||||
static cvar_t vk_nv_glsl_shader = CVARFD("vk_loadglsl", "", CVAR_VIDEOLATCH, "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after.");
|
||||
static cvar_t vk_khr_get_memory_requirements2 = CVARFD("vk_khr_get_memory_requirements2", "", CVAR_VIDEOLATCH, "Enable extended memory info querires");
|
||||
static cvar_t vk_khr_dedicated_allocation = CVARFD("vk_khr_dedicated_allocation", "", CVAR_VIDEOLATCH, "Flag vulkan memory allocations as dedicated, where applicable.");
|
||||
static cvar_t vk_khr_push_descriptor = CVARFD("vk_khr_push_descriptor", "", CVAR_VIDEOLATCH, "Enables better descriptor streaming.");
|
||||
static cvar_t vk_amd_rasterization_order = CVARFD("vk_amd_rasterization_order", "", CVAR_VIDEOLATCH, "Enables the use of relaxed rasterization ordering, for a small speedup at the minor risk of a little zfighting.");
|
||||
#ifdef VK_EXT_astc_decode_mode
|
||||
static cvar_t vk_ext_astc_decode_mode = CVARFD("vk_ext_astc_decode_mode", "", CVAR_VIDEOLATCH, "Enables reducing texture cache sizes for LDR ASTC-compressed textures.");
|
||||
#endif
|
||||
extern cvar_t vid_srgb, vid_vsync, vid_triplebuffer, r_stereo_method, vid_multisample, vid_bpp;
|
||||
|
||||
|
||||
void VK_RegisterVulkanCvars(void)
|
||||
{
|
||||
#define VKRENDEREROPTIONS "Vulkan-Specific Renderer Options"
|
||||
Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_debug, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_busywait, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_waitfence, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_usememorypools, VKRENDEREROPTIONS);
|
||||
|
||||
Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_get_memory_requirements2,VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_dedicated_allocation,VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_push_descriptor, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_amd_rasterization_order, VKRENDEREROPTIONS);
|
||||
#ifdef VK_EXT_astc_decode_mode
|
||||
Cvar_Register (&vk_ext_astc_decode_mode, VKRENDEREROPTIONS);
|
||||
#endif
|
||||
}
|
||||
void R2D_Console_Resize(void);
|
||||
|
||||
extern qboolean scr_con_forcedraw;
|
||||
|
@ -1299,7 +1326,10 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
|
|||
vk_image_t ret;
|
||||
VkImageViewCreateInfo viewInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;;
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
#ifdef VK_EXT_astc_decode_mode
|
||||
VkImageViewASTCDecodeModeEXT astcmode;
|
||||
#endif
|
||||
|
||||
ret.width = width;
|
||||
ret.height = height;
|
||||
|
@ -1370,34 +1400,65 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
|
|||
case PTI_EAC_RG11: format = VK_FORMAT_EAC_R11G11_UNORM_BLOCK; break;
|
||||
case PTI_EAC_RG11_SNORM: format = VK_FORMAT_EAC_R11G11_SNORM_BLOCK; break;
|
||||
|
||||
case PTI_ASTC_4X4: format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_4X4_LDR: format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_4X4_SRGB: format = VK_FORMAT_ASTC_4x4_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_5X4: format = VK_FORMAT_ASTC_5x4_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_5X4_LDR: format = VK_FORMAT_ASTC_5x4_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_5X4_SRGB: format = VK_FORMAT_ASTC_5x4_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_5X5: format = VK_FORMAT_ASTC_5x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_5X5_LDR: format = VK_FORMAT_ASTC_5x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_5X5_SRGB: format = VK_FORMAT_ASTC_5x5_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_6X5: format = VK_FORMAT_ASTC_6x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_6X5_LDR: format = VK_FORMAT_ASTC_6x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_6X5_SRGB: format = VK_FORMAT_ASTC_6x5_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_6X6: format = VK_FORMAT_ASTC_6x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_6X6_LDR: format = VK_FORMAT_ASTC_6x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_6X6_SRGB: format = VK_FORMAT_ASTC_6x6_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_8X5: format = VK_FORMAT_ASTC_8x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X5_LDR: format = VK_FORMAT_ASTC_8x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X5_SRGB: format = VK_FORMAT_ASTC_8x5_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_8X6: format = VK_FORMAT_ASTC_8x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X6_LDR: format = VK_FORMAT_ASTC_8x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X6_SRGB: format = VK_FORMAT_ASTC_8x6_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_8X8: format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X8_LDR: format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X8_SRGB: format = VK_FORMAT_ASTC_8x8_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_10X5: format = VK_FORMAT_ASTC_10x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X5_LDR: format = VK_FORMAT_ASTC_10x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X5_SRGB: format = VK_FORMAT_ASTC_10x5_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_10X6: format = VK_FORMAT_ASTC_10x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X6_LDR: format = VK_FORMAT_ASTC_10x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X6_SRGB: format = VK_FORMAT_ASTC_10x6_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_10X8: format = VK_FORMAT_ASTC_10x8_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X8_LDR: format = VK_FORMAT_ASTC_10x8_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X8_SRGB: format = VK_FORMAT_ASTC_10x8_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_10X10: format = VK_FORMAT_ASTC_10x10_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X10_LDR: format = VK_FORMAT_ASTC_10x10_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X10_SRGB: format = VK_FORMAT_ASTC_10x10_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_12X10: format = VK_FORMAT_ASTC_12x10_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_12X10_LDR: format = VK_FORMAT_ASTC_12x10_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_12X10_SRGB: format = VK_FORMAT_ASTC_12x10_SRGB_BLOCK; break;
|
||||
case PTI_ASTC_12X12: format = VK_FORMAT_ASTC_12x12_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_12X12_LDR: format = VK_FORMAT_ASTC_12x12_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_12X12_SRGB: format = VK_FORMAT_ASTC_12x12_SRGB_BLOCK; break;
|
||||
#ifdef VK_EXT_texture_compression_astc_hdr
|
||||
case PTI_ASTC_4X4_HDR: format = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_5X4_HDR: format = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_5X5_HDR: format = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_6X5_HDR: format = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_6X6_HDR: format = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_8X5_HDR: format = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_8X6_HDR: format = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_8X8_HDR: format = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_10X5_HDR: format = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_10X6_HDR: format = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_10X8_HDR: format = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_10X10_HDR: format = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_12X10_HDR: format = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT; break;
|
||||
case PTI_ASTC_12X12_HDR: format = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT; break;
|
||||
#else //better than crashing.
|
||||
case PTI_ASTC_4X4_HDR: format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_5X4_HDR: format = VK_FORMAT_ASTC_5x4_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_5X5_HDR: format = VK_FORMAT_ASTC_5x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_6X5_HDR: format = VK_FORMAT_ASTC_6x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_6X6_HDR: format = VK_FORMAT_ASTC_6x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X5_HDR: format = VK_FORMAT_ASTC_8x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X6_HDR: format = VK_FORMAT_ASTC_8x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_8X8_HDR: format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X5_HDR: format = VK_FORMAT_ASTC_10x5_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X6_HDR: format = VK_FORMAT_ASTC_10x6_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X8_HDR: format = VK_FORMAT_ASTC_10x8_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_10X10_HDR: format = VK_FORMAT_ASTC_10x10_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_12X10_HDR: format = VK_FORMAT_ASTC_12x10_UNORM_BLOCK; break;
|
||||
case PTI_ASTC_12X12_HDR: format = VK_FORMAT_ASTC_12x12_UNORM_BLOCK; break;
|
||||
#endif
|
||||
|
||||
//depth formats
|
||||
case PTI_DEPTH16: format = VK_FORMAT_D16_UNORM; break;
|
||||
|
@ -1473,7 +1534,8 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
|
|||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_ONE;
|
||||
break;
|
||||
case PTI_L8: //must be an R8 texture
|
||||
case PTI_L8: //must be an R8 texture
|
||||
case PTI_L8_SRGB: //must be an R8 texture
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_R;
|
||||
|
@ -1491,6 +1553,35 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
|
|||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
break;
|
||||
|
||||
#ifdef VK_EXT_astc_decode_mode
|
||||
case PTI_ASTC_4X4: //set these to use rgba8 decoding, because we know they're not hdr and the format is basically 8bit anyway.
|
||||
case PTI_ASTC_5X4: //we do NOT do this for the hdr, as that would cause data loss.
|
||||
case PTI_ASTC_5X5: //we do NOT do this for sRGB because its pointless.
|
||||
case PTI_ASTC_6X5:
|
||||
case PTI_ASTC_6X6:
|
||||
case PTI_ASTC_8X5:
|
||||
case PTI_ASTC_8X6:
|
||||
case PTI_ASTC_8X8:
|
||||
case PTI_ASTC_10X5:
|
||||
case PTI_ASTC_10X6:
|
||||
case PTI_ASTC_10X8:
|
||||
case PTI_ASTC_10X10:
|
||||
case PTI_ASTC_12X10:
|
||||
case PTI_ASTC_12X12:
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
if (vk.ext_astc_decode_mode)
|
||||
{
|
||||
astcmode.pNext = viewInfo.pNext;
|
||||
astcmode.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT;
|
||||
astcmode.decodeMode = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
viewInfo.pNext = &astcmode;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||
|
@ -3994,7 +4085,9 @@ void VK_CheckTextureFormats(void)
|
|||
{PTI_ARGB1555, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_RGBA16F, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT},
|
||||
{PTI_RGBA32F, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT},
|
||||
{PTI_P8, VK_FORMAT_R8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
|
||||
{PTI_L8, VK_FORMAT_R8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
|
||||
{PTI_L8A8, VK_FORMAT_R8G8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
|
||||
{PTI_L8_SRGB, VK_FORMAT_R8_SRGB, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
|
||||
{PTI_R8, VK_FORMAT_R8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
|
||||
{PTI_RG8, VK_FORMAT_R8G8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
|
||||
{PTI_R8_SNORM, VK_FORMAT_R8_SNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
|
||||
|
@ -4036,34 +4129,51 @@ void VK_CheckTextureFormats(void)
|
|||
{PTI_EAC_R11_SNORM, VK_FORMAT_EAC_R11_SNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_EAC_RG11, VK_FORMAT_EAC_R11G11_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_EAC_RG11_SNORM, VK_FORMAT_EAC_R11G11_SNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_4X4, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_4X4_LDR, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_5X4_LDR, VK_FORMAT_ASTC_5x4_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_5X5_LDR, VK_FORMAT_ASTC_5x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_6X5_LDR, VK_FORMAT_ASTC_6x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_6X6_LDR, VK_FORMAT_ASTC_6x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X5_LDR, VK_FORMAT_ASTC_8x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X6_LDR, VK_FORMAT_ASTC_8x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X8_LDR, VK_FORMAT_ASTC_8x8_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X5_LDR, VK_FORMAT_ASTC_10x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X6_LDR, VK_FORMAT_ASTC_10x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X8_LDR, VK_FORMAT_ASTC_10x8_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X10_LDR, VK_FORMAT_ASTC_10x10_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_12X10_LDR, VK_FORMAT_ASTC_12x10_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_12X12_LDR, VK_FORMAT_ASTC_12x12_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_4X4_SRGB, VK_FORMAT_ASTC_4x4_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_5X4, VK_FORMAT_ASTC_5x4_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_5X4_SRGB, VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_5X5, VK_FORMAT_ASTC_5x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_5X5_SRGB, VK_FORMAT_ASTC_5x5_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_6X5, VK_FORMAT_ASTC_6x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_6X5_SRGB, VK_FORMAT_ASTC_6x5_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_6X6, VK_FORMAT_ASTC_6x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_6X6_SRGB, VK_FORMAT_ASTC_6x6_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X5, VK_FORMAT_ASTC_8x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X5_SRGB, VK_FORMAT_ASTC_8x5_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X6, VK_FORMAT_ASTC_8x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X6_SRGB, VK_FORMAT_ASTC_8x6_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X8, VK_FORMAT_ASTC_8x8_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X8_SRGB, VK_FORMAT_ASTC_8x8_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X5, VK_FORMAT_ASTC_10x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X5_SRGB, VK_FORMAT_ASTC_10x5_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X6, VK_FORMAT_ASTC_10x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X6_SRGB, VK_FORMAT_ASTC_10x6_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X8, VK_FORMAT_ASTC_10x8_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X8_SRGB, VK_FORMAT_ASTC_10x8_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X10, VK_FORMAT_ASTC_10x10_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X10_SRGB, VK_FORMAT_ASTC_10x10_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_12X10, VK_FORMAT_ASTC_12x10_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_12X10_SRGB, VK_FORMAT_ASTC_12x10_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_12X12, VK_FORMAT_ASTC_12x12_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_12X12_SRGB, VK_FORMAT_ASTC_12x12_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
|
||||
#ifdef VK_EXT_texture_compression_astc_hdr
|
||||
{PTI_ASTC_4X4_HDR, VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_5X4_HDR, VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_5X5_HDR, VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_6X5_HDR, VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_6X6_HDR, VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X5_HDR, VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X6_HDR, VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_8X8_HDR, VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X5_HDR, VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X6_HDR, VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X8_HDR, VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_10X10_HDR, VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_12X10_HDR, VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
{PTI_ASTC_12X12_HDR, VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT},
|
||||
#endif
|
||||
};
|
||||
unsigned int i;
|
||||
VkPhysicalDeviceProperties props;
|
||||
|
@ -4083,6 +4193,15 @@ void VK_CheckTextureFormats(void)
|
|||
if ((fmt.optimalTilingFeatures & need) == need)
|
||||
sh_config.texfmt[texfmt[i].pti] = true;
|
||||
}
|
||||
|
||||
if (sh_config.texfmt[PTI_BC1_RGBA] && sh_config.texfmt[PTI_BC2_RGBA] && sh_config.texfmt[PTI_BC3_RGBA] && sh_config.texfmt[PTI_BC5_RG8] && sh_config.texfmt[PTI_BC7_RGBA])
|
||||
sh_config.hw_bc = 3;
|
||||
if (sh_config.texfmt[PTI_ETC2_RGB8] && sh_config.texfmt[PTI_ETC2_RGB8A1] && sh_config.texfmt[PTI_ETC2_RGB8A8] && sh_config.texfmt[PTI_EAC_RG11])
|
||||
sh_config.hw_etc = 2;
|
||||
if (sh_config.texfmt[PTI_ASTC_4X4_LDR])
|
||||
sh_config.hw_astc = 1; //the core vulkan formats refer to the ldr profile. hdr is a separate extension, which is still not properly specified..
|
||||
if (sh_config.texfmt[PTI_ASTC_4X4_HDR])
|
||||
sh_config.hw_astc = 2; //the core vulkan formats refer to the ldr profile. hdr is a separate extension, which is still not properly specified..
|
||||
}
|
||||
|
||||
//initialise the vulkan instance, context, device, etc.
|
||||
|
@ -4115,6 +4234,9 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
{&vk.khr_dedicated_allocation, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_khr_dedicated_allocation, true, NULL, NULL},
|
||||
{&vk.khr_push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, &vk_khr_push_descriptor, true, NULL, NULL},
|
||||
{&vk.amd_rasterization_order, VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME, &vk_amd_rasterization_order, false, NULL, NULL},
|
||||
#ifdef VK_EXT_astc_decode_mode
|
||||
{&vk.ext_astc_decode_mode, VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, &vk_ext_astc_decode_mode, true, NULL, NULL},
|
||||
#endif
|
||||
};
|
||||
size_t e;
|
||||
|
||||
|
|
|
@ -280,6 +280,7 @@ extern struct vulkaninfo_s
|
|||
qboolean khr_dedicated_allocation; //standardised version of the above where the driver decides whether a resource is worth a dedicated allocation.
|
||||
qboolean khr_push_descriptor; //more efficient descriptor streaming
|
||||
qboolean amd_rasterization_order; //allows primitives to draw in any order
|
||||
qboolean ext_astc_decode_mode; //small perf boost
|
||||
|
||||
VkInstance instance;
|
||||
VkDevice device;
|
||||
|
|
660
plugins/models/exportiqm.c
Normal file
660
plugins/models/exportiqm.c
Normal file
|
@ -0,0 +1,660 @@
|
|||
#ifndef GLQUAKE
|
||||
#define GLQUAKE //this is shit.
|
||||
#endif
|
||||
#include "quakedef.h"
|
||||
#include "../plugin.h"
|
||||
#include "com_mesh.h"
|
||||
extern plugmodfuncs_t *modfuncs;
|
||||
extern plugfsfuncs_t *filefuncs;
|
||||
|
||||
#define IQM_MAGIC "INTERQUAKEMODEL"
|
||||
#define IQM_VERSION2 2
|
||||
|
||||
struct iqmheader
|
||||
{
|
||||
char magic[16];
|
||||
unsigned int version;
|
||||
unsigned int filesize;
|
||||
unsigned int flags;
|
||||
unsigned int num_text, ofs_text;
|
||||
unsigned int num_meshes, ofs_meshes;
|
||||
unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
|
||||
unsigned int num_triangles, ofs_triangles, ofs_adjacency;
|
||||
unsigned int num_joints, ofs_joints;
|
||||
unsigned int num_poses, ofs_poses;
|
||||
unsigned int num_anims, ofs_anims;
|
||||
unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
|
||||
unsigned int num_comment, ofs_comment;
|
||||
unsigned int num_extensions, ofs_extensions;
|
||||
};
|
||||
struct iqmmesh
|
||||
{
|
||||
unsigned int name;
|
||||
unsigned int material;
|
||||
unsigned int first_vertex, num_vertexes;
|
||||
unsigned int first_triangle, num_triangles;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IQM_POSITION = 0,
|
||||
IQM_TEXCOORD = 1,
|
||||
IQM_NORMAL = 2,
|
||||
IQM_TANGENT = 3,
|
||||
IQM_BLENDINDEXES = 4,
|
||||
IQM_BLENDWEIGHTS = 5,
|
||||
IQM_COLOR = 6,
|
||||
IQM_CUSTOM = 0x10
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IQM_BYTE = 0,
|
||||
IQM_UBYTE = 1,
|
||||
IQM_SHORT = 2,
|
||||
IQM_USHORT = 3,
|
||||
IQM_INT = 4,
|
||||
IQM_UINT = 5,
|
||||
IQM_HALF = 6,
|
||||
IQM_FLOAT = 7,
|
||||
IQM_DOUBLE = 8,
|
||||
};
|
||||
|
||||
struct iqmtriangle
|
||||
{
|
||||
unsigned int vertex[3];
|
||||
};
|
||||
|
||||
struct iqmjoint2
|
||||
{
|
||||
unsigned int name;
|
||||
int parent;
|
||||
float translate[3], rotate[4], scale[3];
|
||||
};
|
||||
|
||||
struct iqmpose2
|
||||
{
|
||||
int parent;
|
||||
unsigned int mask;
|
||||
float channeloffset[10];
|
||||
float channelscale[10];
|
||||
};
|
||||
|
||||
struct iqmanim
|
||||
{
|
||||
unsigned int name;
|
||||
unsigned int first_frame, num_frames;
|
||||
float framerate;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IQM_LOOP = 1<<0
|
||||
};
|
||||
|
||||
struct iqmvertexarray
|
||||
{
|
||||
unsigned int type;
|
||||
unsigned int flags;
|
||||
unsigned int format;
|
||||
unsigned int size;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
struct iqmbounds
|
||||
{
|
||||
float bbmin[3], bbmax[3];
|
||||
float xyradius, radius;
|
||||
};
|
||||
|
||||
struct iqmextension
|
||||
{
|
||||
unsigned int name;
|
||||
unsigned int num_data, ofs_data;
|
||||
unsigned int ofs_extensions; // pointer to next extension. wtf is up with this? how is this not redundant due to ofs_data?
|
||||
};
|
||||
|
||||
|
||||
struct iqmext_fte_mesh
|
||||
{
|
||||
unsigned int contents; //default CONTENTS_BODY
|
||||
unsigned int surfaceflags; //propagates to trace_surfaceflags
|
||||
unsigned int surfaceid; //the body reported to qc via trace_surface
|
||||
unsigned int geomset;
|
||||
unsigned int geomid;
|
||||
float mindist;
|
||||
float maxdist;
|
||||
};
|
||||
struct iqmext_fte_event
|
||||
{
|
||||
unsigned int anim;
|
||||
float timestamp;
|
||||
unsigned int evcode;
|
||||
unsigned int evdata_str; //stringtable
|
||||
};
|
||||
static void CrossProduct_ (const vec3_t v1, const vec3_t v2, vec3_t cross)
|
||||
{
|
||||
cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||||
cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
|
||||
cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
||||
}
|
||||
static void Bone_To_PosQuat4(const float *matrix, float *pos, float *quat4, float *scale)
|
||||
{ //I originally ripped this function out of DP. tweaked slightly.
|
||||
//http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
|
||||
float origininvscale = 1;
|
||||
float origin[3];
|
||||
float quat[4];
|
||||
float quatscale;
|
||||
|
||||
float trace = matrix[0*4+0] + matrix[1*4+1] + matrix[2*4+2];
|
||||
|
||||
origin[0] = matrix[0*4+0];
|
||||
origin[1] = matrix[1*4+0];
|
||||
origin[2] = matrix[2*4+0];
|
||||
scale [0] = sqrt(DotProduct(origin,origin));
|
||||
origin[0] = matrix[0*4+1];
|
||||
origin[1] = matrix[1*4+1];
|
||||
origin[2] = matrix[2*4+1];
|
||||
scale [1] = sqrt(DotProduct(origin,origin));
|
||||
origin[1] = matrix[0*4+2];
|
||||
origin[1] = matrix[1*4+2];
|
||||
origin[2] = matrix[2*4+2];
|
||||
scale [2] = sqrt(DotProduct(origin,origin));
|
||||
|
||||
origin[0] = matrix[0*4+3];
|
||||
origin[1] = matrix[1*4+3];
|
||||
origin[2] = matrix[2*4+3];
|
||||
if(trace > 0)
|
||||
{
|
||||
float r = sqrt(1.0f + trace), inv = 0.5f / r;
|
||||
quat[0] = (matrix[2*4+1] - matrix[1*4+2]) * inv;
|
||||
quat[1] = (matrix[0*4+2] - matrix[2*4+0]) * inv;
|
||||
quat[2] = (matrix[1*4+0] - matrix[0*4+1]) * inv;
|
||||
quat[3] = 0.5f * r;
|
||||
}
|
||||
else if(matrix[0*4+0] > matrix[1*4+1] && matrix[0*4+0] > matrix[2*4+2])
|
||||
{
|
||||
float r = sqrt(1.0f + matrix[0*4+0] - matrix[1*4+1] - matrix[2*4+2]), inv = 0.5f / r;
|
||||
quat[0] = 0.5f * r;
|
||||
quat[1] = (matrix[1*4+0] + matrix[0*4+1]) * inv;
|
||||
quat[2] = (matrix[0*4+2] + matrix[2*4+0]) * inv;
|
||||
quat[3] = (matrix[2*4+1] - matrix[1*4+2]) * inv;
|
||||
}
|
||||
else if(matrix[1*4+1] > matrix[2*4+2])
|
||||
{
|
||||
float r = sqrt(1.0f + matrix[1*4+1] - matrix[0*4+0] - matrix[2*4+2]), inv = 0.5f / r;
|
||||
quat[0] = (matrix[1*4+0] + matrix[0*4+1]) * inv;
|
||||
quat[1] = 0.5f * r;
|
||||
quat[2] = (matrix[2*4+1] + matrix[1*4+2]) * inv;
|
||||
quat[3] = (matrix[0*4+2] - matrix[2*4+0]) * inv;
|
||||
}
|
||||
else
|
||||
{
|
||||
float r = sqrt(1.0f + matrix[2*4+2] - matrix[0*4+0] - matrix[1*4+1]), inv = 0.5f / r;
|
||||
quat[0] = (matrix[0*4+2] + matrix[2*4+0]) * inv;
|
||||
quat[1] = (matrix[2*4+1] + matrix[1*4+2]) * inv;
|
||||
quat[2] = 0.5f * r;
|
||||
quat[3] = (matrix[1*4+0] - matrix[0*4+1]) * inv;
|
||||
}
|
||||
// normalize quaternion so that it is unit length
|
||||
quatscale = quat[0]*quat[0]+quat[1]*quat[1]+quat[2]*quat[2]+quat[3]*quat[3];
|
||||
if (quatscale)
|
||||
quatscale = (quat[3] >= 0 ? -1.0f : 1.0f) / sqrt(quatscale);
|
||||
|
||||
// use a negative scale on the quat because the above function produces a
|
||||
// positive quat[3] and canonical quaternions have negative quat[3]
|
||||
VectorScale(origin, origininvscale, pos);
|
||||
Vector4Scale(quat, quatscale, quat4);
|
||||
}
|
||||
void Mod_ExportIQM(char *fname, int flags, galiasinfo_t *mesh)
|
||||
{
|
||||
int i, j, k;
|
||||
vfsfile_t *f;
|
||||
galiasinfo_t *m;
|
||||
qbyte *data = NULL;
|
||||
char *otext;
|
||||
struct iqmvertexarray *ovarr;
|
||||
struct iqmtriangle *otri;
|
||||
struct iqmmesh *omesh;
|
||||
struct iqmjoint2 *ojoint;
|
||||
struct iqmanim *oanim;
|
||||
struct iqmpose2 *opose;
|
||||
struct
|
||||
{
|
||||
float min[10], max[10], scale[10];
|
||||
int flags;
|
||||
} *poseinfo = NULL, *pi; //per bone
|
||||
struct
|
||||
{ //pos3, quat4, scale3
|
||||
float posquatscale[10]; //raw values, used to calibrate ranges
|
||||
} *posedata = NULL, *pd; //per bone*joint
|
||||
avec4_t *ivert;
|
||||
vec2_t *ist;
|
||||
vec3_t *overt;
|
||||
vec3_t *onorm = NULL;
|
||||
vec4_t *otang = NULL;
|
||||
vec2_t *ost;
|
||||
bone_vec4_t *oboneidx;
|
||||
byte_vec4_t *oboneweight;
|
||||
unsigned short *oposedata;
|
||||
struct iqmheader hdr = {IQM_MAGIC, IQM_VERSION2}, *oh;
|
||||
hdr.flags = flags;
|
||||
hdr.num_vertexarrays = 4;
|
||||
hdr.num_triangles = 0;
|
||||
hdr.ofs_adjacency = 0; //noone actually uses this...
|
||||
hdr.num_poses = 0;
|
||||
// hdr.ofs_poses = 0;
|
||||
hdr.num_anims = 0;
|
||||
// hdr.ofs_anims = 0;
|
||||
hdr.num_frames = 0;
|
||||
hdr.num_framechannels = 0;
|
||||
// hdr.ofs_frames = 0;
|
||||
// hdr.ofs_bounds = 0;
|
||||
hdr.num_comment = 0;
|
||||
// hdr.ofs_comment = 0;
|
||||
hdr.num_extensions = 0;
|
||||
// hdr.ofs_extensions = 0;
|
||||
|
||||
|
||||
hdr.num_joints = mesh->numbones;
|
||||
if (hdr.num_joints)
|
||||
{
|
||||
float *matrix;
|
||||
hdr.num_vertexarrays+= 2;
|
||||
hdr.num_anims = mesh->numanimations;
|
||||
for (i = 0; i < hdr.num_anims; i++)
|
||||
{
|
||||
hdr.num_text += strlen(mesh->ofsanimations[i].name)+1;
|
||||
hdr.num_frames += mesh->ofsanimations[i].numposes;
|
||||
}
|
||||
if (hdr.num_frames)
|
||||
{
|
||||
poseinfo = malloc(sizeof(*poseinfo)*hdr.num_joints);
|
||||
hdr.num_poses = hdr.num_joints;
|
||||
posedata = malloc(sizeof(*posedata)*hdr.num_joints*hdr.num_poses);
|
||||
//pull out the raw data and convert to the quats that we need
|
||||
for (i = 0, pd = posedata; i < hdr.num_anims; i++)
|
||||
for (j = 0, matrix = mesh->ofsanimations[i].boneofs; j < mesh->ofsanimations[i].numposes; j++)
|
||||
for (k = 0; k < hdr.num_joints; k++)
|
||||
{
|
||||
Bone_To_PosQuat4(matrix, &pd->posquatscale[0], &pd->posquatscale[3], &pd->posquatscale[7]);
|
||||
pd++;
|
||||
matrix+=12;
|
||||
}
|
||||
//now figure out each poseinfo's min+max
|
||||
for (i = 0, pi = poseinfo; i < hdr.num_joints; i++, pi++)
|
||||
for (j = 0, pd = posedata+i; j < hdr.num_poses; j++, pd+=hdr.num_joints)
|
||||
for (k = 0; k < 10; k++)
|
||||
{
|
||||
if (!i || pd->posquatscale[k] < pi->min[k])
|
||||
pi->min[k] = pd->posquatscale[k];
|
||||
if (!i || pi[i].max[k] < pd->posquatscale[k])
|
||||
pi->max[k] = pd->posquatscale[k];
|
||||
}
|
||||
//figure out the offset+range+flags
|
||||
for (i = 0, pi = poseinfo; i < hdr.num_joints; i++, pi++)
|
||||
for (k = 0; k < 10; k++)
|
||||
{
|
||||
pi->scale[k] = pi->max[k]-pi->min[k];
|
||||
if (pi->scale[k] < 1e-10f)
|
||||
; //total range is tiny and won't make any real difference, drop this channel for a small saving.
|
||||
else
|
||||
{
|
||||
pi->scale[k] /= 0xffffu; //compensate for the datatype's max
|
||||
pi->flags |= 1u<<k;
|
||||
hdr.num_framechannels++;
|
||||
}
|
||||
}
|
||||
hdr.num_framechannels *= hdr.num_frames; //there'll be one for each pose*channel*frame
|
||||
}
|
||||
}
|
||||
hdr.num_text += hdr.num_joints*32; //gah
|
||||
|
||||
//count needed data
|
||||
for (m = mesh; m; m = m->nextsurf)
|
||||
{
|
||||
//can't handle the surface if its verts are weird.
|
||||
if (m->shares_verts && m->shares_verts != hdr.num_meshes)
|
||||
continue;
|
||||
//can only handle one set of bones.
|
||||
if (m->shares_bones != 0)
|
||||
continue;
|
||||
//and must have the same number of bones.
|
||||
if (hdr.num_joints != m->numbones)
|
||||
continue;
|
||||
|
||||
hdr.num_text += strlen(m->surfacename)+1;
|
||||
if (m->ofsskins && m->ofsskins->frame)
|
||||
hdr.num_text += strlen(m->ofsskins->frame->shadername)+1;
|
||||
hdr.num_triangles += m->numindexes/3;
|
||||
hdr.num_vertexes += m->numverts;
|
||||
hdr.num_meshes++;
|
||||
}
|
||||
|
||||
//allocate our output buffer
|
||||
#define ALLOCSPACE hdr.filesize = 0; \
|
||||
ALLOC(oh, sizeof(*oh)); \
|
||||
ALLOC(otext, sizeof(*otext)*hdr.num_text); \
|
||||
ALLOC(ovarr, sizeof(*ovarr)*hdr.num_vertexarrays); \
|
||||
ALLOC(otri, sizeof(*otri)*hdr.num_triangles); \
|
||||
ALLOC(overt, sizeof(*overt)*hdr.num_vertexes); \
|
||||
ALLOC(ost, sizeof(*ost)*hdr.num_vertexes); \
|
||||
if (mesh->ofs_skel_norm) {ALLOC(onorm, sizeof(*onorm)*hdr.num_vertexes);} \
|
||||
if (mesh->ofs_skel_svect && mesh->ofs_skel_tvect) {ALLOC(otang, sizeof(*otang)*hdr.num_vertexes);} \
|
||||
if (hdr.num_joints) {ALLOC(oboneweight, sizeof(*oboneweight)*hdr.num_vertexes);} \
|
||||
if (hdr.num_joints) {ALLOC(oboneidx, sizeof(*oboneidx)*hdr.num_vertexes);} \
|
||||
if (hdr.num_joints) {ALLOC(ojoint, sizeof(*ojoint)*hdr.num_joints);} \
|
||||
if (hdr.num_anims) {ALLOC(oanim, sizeof(*oanim)*hdr.num_anims);} \
|
||||
if (hdr.num_poses) {ALLOC(opose, sizeof(*opose)*hdr.num_poses);} \
|
||||
if (hdr.num_framechannels) {ALLOC(oposedata, sizeof(*oposedata)*hdr.num_framechannels);} \
|
||||
ALLOC(omesh, sizeof(*omesh)*hdr.num_meshes);
|
||||
#define ALLOC(p,s) p=(void*)(data+hdr.filesize);hdr.filesize+=s;
|
||||
ALLOCSPACE; //figure out how much space we need
|
||||
data = malloc(hdr.filesize);
|
||||
memset(data, 0xFE, hdr.filesize);
|
||||
ALLOCSPACE; //and assign everything to the right offsets.
|
||||
#undef ALLOC
|
||||
#undef ALLOCSPACE
|
||||
|
||||
//copy over the preliminary header
|
||||
*oh = hdr;
|
||||
|
||||
#define hdr hdr
|
||||
|
||||
if (omesh) oh->ofs_meshes = (qbyte*)omesh-data;
|
||||
if (otext) oh->ofs_text = (qbyte*)otext-data;
|
||||
if (ovarr) oh->ofs_vertexarrays = (qbyte*)ovarr-data;
|
||||
if (otri) oh->ofs_triangles = (qbyte*)otri-data;
|
||||
if (ojoint) oh->ofs_joints = (qbyte*)ojoint-data;
|
||||
if (opose) oh->ofs_poses = (qbyte*)opose-data;
|
||||
if (oposedata) oh->ofs_frames = (qbyte*)oposedata-data;
|
||||
if (oanim) oh->ofs_anims = (qbyte*)oanim-data;
|
||||
|
||||
//set up vertex array data. we might add some padding here, in case the extra data isn't availble.
|
||||
memset(ovarr, 0, sizeof(*ovarr)*oh->num_vertexarrays);
|
||||
oh->num_vertexarrays=0;
|
||||
ovarr->type = IQM_POSITION;
|
||||
ovarr->flags = 0;
|
||||
ovarr->format = IQM_FLOAT;
|
||||
ovarr->size = 3;
|
||||
ovarr->offset = (qbyte*)overt - data;
|
||||
ovarr++;
|
||||
oh->num_vertexarrays++;
|
||||
|
||||
ovarr->type = IQM_TEXCOORD;
|
||||
ovarr->flags = 0;
|
||||
ovarr->format = IQM_FLOAT;
|
||||
ovarr->size = 2;
|
||||
ovarr->offset = (qbyte*)ost - data;
|
||||
ovarr++;
|
||||
oh->num_vertexarrays++;
|
||||
|
||||
if (onorm)
|
||||
{
|
||||
ovarr->type = IQM_NORMAL;
|
||||
ovarr->flags = 0;
|
||||
ovarr->format = IQM_FLOAT;
|
||||
ovarr->size = 3;
|
||||
ovarr->offset = (qbyte*)onorm - data;
|
||||
ovarr++;
|
||||
oh->num_vertexarrays++;
|
||||
}
|
||||
if (otang)
|
||||
{
|
||||
ovarr->type = IQM_TANGENT;
|
||||
ovarr->flags = 0;
|
||||
ovarr->format = IQM_FLOAT;
|
||||
ovarr->size = 4;
|
||||
ovarr->offset = (qbyte*)otang - data;
|
||||
ovarr++;
|
||||
oh->num_vertexarrays++;
|
||||
}
|
||||
if (oboneidx)
|
||||
{
|
||||
ovarr->type = IQM_BLENDINDEXES;
|
||||
ovarr->flags = 0;
|
||||
ovarr->format = (MAX_BONES>65536)?IQM_UINT:((MAX_BONES>256)?IQM_USHORT:IQM_UBYTE);
|
||||
ovarr->size = 4;
|
||||
ovarr->offset = (qbyte*)oboneidx - data;
|
||||
ovarr++;
|
||||
oh->num_vertexarrays++;
|
||||
}
|
||||
if (oboneweight)
|
||||
{
|
||||
ovarr->type = IQM_BLENDWEIGHTS;
|
||||
ovarr->flags = 0;
|
||||
ovarr->format = IQM_BYTE;
|
||||
ovarr->size = 4;
|
||||
ovarr->offset = (qbyte*)oboneweight - data;
|
||||
ovarr++;
|
||||
oh->num_vertexarrays++;
|
||||
}
|
||||
/*if (orgba)
|
||||
{
|
||||
ovarr->type = IQM_COLOR;
|
||||
ovarr->flags = 0;
|
||||
ovarr->format = IQM_FLOAT;
|
||||
ovarr->size = 4;
|
||||
ovarr->offset = (qbyte*)orgba - data;
|
||||
ovarr++;
|
||||
oh->num_vertexarrays++;
|
||||
}*/
|
||||
|
||||
if (ojoint)
|
||||
{
|
||||
for (i = 0; i < hdr.num_joints; i++)
|
||||
{
|
||||
ojoint[i].parent = mesh->ofsbones[i].parent;
|
||||
ojoint[i].name = (qbyte*)otext-(data+oh->ofs_text);
|
||||
strcpy(otext, mesh->ofsbones[i].name);
|
||||
otext += strlen(otext)+1;
|
||||
|
||||
Bone_To_PosQuat4(mesh->ofsbones[i].inverse, ojoint[i].translate, ojoint[i].rotate, ojoint[i].scale);
|
||||
}
|
||||
}
|
||||
if (opose)
|
||||
{
|
||||
int c;
|
||||
for (i = 0, pi=poseinfo; i < hdr.num_joints; i++, pi++)
|
||||
{
|
||||
opose[i].parent = mesh->ofsbones[i].parent;
|
||||
opose[i].mask = pi->flags;
|
||||
for (k = 0; k < 10; k++)
|
||||
{
|
||||
opose[i].channeloffset[k] = pi->min[k];
|
||||
opose[i].channelscale[k] = pi->scale[k];
|
||||
}
|
||||
|
||||
for (j = 0, pd = posedata+i; j < hdr.num_frames; j++, pd+=hdr.num_joints)
|
||||
{
|
||||
for (k = 0; k < 10; k++)
|
||||
{
|
||||
if (opose[i].mask & (1<<k))
|
||||
{
|
||||
c = (pd->posquatscale[k]-pi->min[k])/pi->scale[k];
|
||||
c = bound(0, c, 0xffff); //clamp it just in case (floats can be annoying)
|
||||
*oposedata++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oposedata)
|
||||
{
|
||||
for (i = 0; i < hdr.num_joints; i++)
|
||||
{
|
||||
opose[i].parent = mesh->ofsbones[i].parent;
|
||||
opose[i].mask = poseinfo[i].flags;
|
||||
for (k = 0; k < 10; k++)
|
||||
{
|
||||
opose[i].channeloffset[k] = poseinfo[i].min[k];
|
||||
opose[i].channelscale[k] = poseinfo[i].scale[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hdr.num_frames = 0;
|
||||
for (i = 0; i < hdr.num_anims; i++, oanim++)
|
||||
{
|
||||
oanim->first_frame = hdr.num_frames;
|
||||
oanim->num_frames = mesh->ofsanimations[i].numposes;
|
||||
oanim->framerate = mesh->ofsanimations[i].rate;
|
||||
oanim->flags = mesh->ofsanimations[i].loop?IQM_LOOP:0;
|
||||
oanim->name = (qbyte*)otext-(data+oh->ofs_text);
|
||||
strcpy(otext, mesh->ofsanimations[i].name);
|
||||
otext += strlen(otext)+1;
|
||||
hdr.num_frames += mesh->ofsanimations[i].numposes;
|
||||
}
|
||||
oh->num_anims = i;
|
||||
oh->num_frames = hdr.num_frames;
|
||||
|
||||
//count needed data
|
||||
hdr.num_triangles = 0;
|
||||
hdr.num_vertexes = 0;
|
||||
for (m = mesh; m; m = m->nextsurf)
|
||||
{
|
||||
//can't handle the surface if its verts are weird.
|
||||
if (m->shares_verts && m->shares_verts != hdr.num_meshes)
|
||||
continue;
|
||||
//can only handle one set of bones.
|
||||
if (m->shares_bones != 0)
|
||||
continue;
|
||||
if (hdr.num_joints != m->numbones)
|
||||
continue;
|
||||
|
||||
omesh->name = (qbyte*)otext-(data+oh->ofs_text);
|
||||
strcpy(otext, m->surfacename);
|
||||
otext += strlen(otext)+1;
|
||||
|
||||
omesh->material = (qbyte*)otext-(data+oh->ofs_text);
|
||||
if (m->ofsskins && m->ofsskins->frame)
|
||||
strcpy(otext, m->ofsskins->frame->shadername);
|
||||
else
|
||||
strcpy(otext, "");
|
||||
otext += strlen(otext)+1;
|
||||
|
||||
omesh->first_vertex = hdr.num_vertexes;
|
||||
omesh->num_vertexes = m->numverts;
|
||||
omesh->first_triangle = hdr.num_triangles;
|
||||
omesh->num_triangles = m->numindexes/3;
|
||||
|
||||
if (m->ofs_skel_xyz)
|
||||
ivert = m->ofs_skel_xyz;
|
||||
else if (m->numanimations && m->ofsanimations->numposes)
|
||||
ivert = m->ofsanimations->poseofs->ofsverts;
|
||||
else
|
||||
ivert = NULL;
|
||||
if (ivert)
|
||||
{
|
||||
for (i = 0; i < omesh->num_vertexes; i++)
|
||||
VectorCopy (ivert[i], overt[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < omesh->num_vertexes; i++)
|
||||
VectorClear (overt[i]);
|
||||
|
||||
}
|
||||
overt += i;
|
||||
|
||||
if (oboneidx)
|
||||
{
|
||||
bone_vec4_t *iidx = m->ofs_skel_idx;
|
||||
vec4_t *iweight = m->ofs_skel_weight;
|
||||
for (i = 0; i < omesh->num_vertexes; i++)
|
||||
{
|
||||
Vector4Copy(iidx[i], oboneidx[i]);
|
||||
Vector4Scale(iweight[i], 255, oboneweight[i]);
|
||||
}
|
||||
oboneidx += i;
|
||||
oboneweight += i;
|
||||
}
|
||||
|
||||
if (ost)
|
||||
{
|
||||
ist = m->ofs_st_array;
|
||||
for (i = 0; i < omesh->num_vertexes; i++)
|
||||
Vector2Copy(ist[i], ost[i]);
|
||||
ost += i;
|
||||
}
|
||||
|
||||
if (onorm)
|
||||
{
|
||||
vec3_t *inorm, *isdir, *itdir, t;
|
||||
if (m->ofs_skel_norm)
|
||||
{
|
||||
inorm = m->ofs_skel_norm;
|
||||
isdir = m->ofs_skel_svect;
|
||||
itdir = m->ofs_skel_tvect;
|
||||
}
|
||||
else if (m->numanimations && m->ofsanimations->numposes)
|
||||
{
|
||||
inorm = m->ofsanimations->poseofs->ofsnormals;
|
||||
isdir = m->ofsanimations->poseofs->ofssvector;
|
||||
itdir = m->ofsanimations->poseofs->ofstvector;
|
||||
}
|
||||
else
|
||||
{
|
||||
inorm = NULL;
|
||||
isdir = NULL;
|
||||
itdir = NULL;
|
||||
}
|
||||
if (otang)
|
||||
{
|
||||
if (inorm && isdir && itdir)
|
||||
{
|
||||
for (i = 0; i < omesh->num_vertexes; i++)
|
||||
{
|
||||
VectorCopy (isdir[i], otang[i]);
|
||||
CrossProduct_(isdir[i], inorm[i], t);
|
||||
otang[i][3] = DotProduct(itdir[i], t)<0; //fourth part is simply a flag that says which direction the bitangent is in, should otherwise be a nice crossproduct result.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < omesh->num_vertexes; i++)
|
||||
{
|
||||
VectorClear (otang[i]);
|
||||
otang[i][3] = 0;
|
||||
}
|
||||
}
|
||||
otang += i;
|
||||
}
|
||||
if (inorm)
|
||||
{
|
||||
for (i = 0; i < omesh->num_vertexes; i++)
|
||||
VectorCopy (ivert[i], onorm[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < omesh->num_vertexes; i++)
|
||||
VectorClear (onorm[i]);
|
||||
}
|
||||
otang += i;
|
||||
onorm += i;
|
||||
}
|
||||
|
||||
for (i = 0; i < omesh->num_triangles; i++)
|
||||
{
|
||||
otri[i].vertex[0] = m->ofs_indexes[i*3+0]+hdr.num_vertexes;
|
||||
otri[i].vertex[1] = m->ofs_indexes[i*3+1]+hdr.num_vertexes;
|
||||
otri[i].vertex[2] = m->ofs_indexes[i*3+2]+hdr.num_vertexes;
|
||||
}
|
||||
otri += i;
|
||||
|
||||
hdr.num_vertexes += omesh->num_vertexes;
|
||||
hdr.num_triangles += omesh->num_triangles;
|
||||
}
|
||||
|
||||
//and write it out
|
||||
f = filefuncs->OpenVFS(fname, "wb", FS_GAMEONLY);
|
||||
if (f)
|
||||
{
|
||||
VFS_WRITE(f, oh, oh->filesize);
|
||||
VFS_CLOSE(f);
|
||||
}
|
||||
free(data);
|
||||
free(poseinfo);
|
||||
#undef hdr
|
||||
}
|
Loading…
Reference in a new issue