From 729d6181c20f3d1db661d76fe13c71784cc43f98 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 30 Jul 2011 14:14:56 +0000 Subject: [PATCH] Misc bugfixes, including q3bsp-rtlights and bloom. Matrix use clarifications. Working towards skeletal glsl code. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3890 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_ents.c | 17 +- engine/client/cl_input.c | 2 +- engine/client/cl_main.c | 55 +- engine/client/cl_parse.c | 20 +- engine/client/cl_screen.c | 2 +- engine/client/cl_ui.c | 2 +- engine/client/client.h | 15 +- engine/client/m_master.c | 2 +- engine/client/net_master.c | 2 +- engine/client/pr_csqc.c | 89 +-- engine/client/quakedef.h | 3 +- engine/client/r_d3.c | 4 +- engine/client/r_surf.c | 37 +- engine/client/render.h | 4 +- engine/client/sys_win.c | 26 + engine/client/view.c | 2 +- engine/client/wad.c | 2 +- engine/common/bothdefs.h | 6 +- engine/common/bspfile.h | 2 +- engine/common/com_mesh.c | 892 ++++++++++++++++++++++-------- engine/common/com_mesh.h | 22 +- engine/common/com_phys_ode.c | 24 +- engine/common/common.c | 3 +- engine/common/common.h | 1 + engine/common/cvar.c | 4 +- engine/common/fs.c | 16 +- engine/common/gl_q2bsp.c | 14 +- engine/common/mathlib.c | 140 +++-- engine/common/mathlib.h | 52 +- engine/common/md4.c | 13 + engine/common/protocol.h | 2 + engine/common/q1bsp.c | 2 +- engine/common/qvm.c | 10 + engine/common/sys.h | 1 + engine/common/tlout.h | 2 +- engine/common/translate.c | 4 +- engine/common/vm.h | 1 + engine/common/world.h | 2 +- engine/d3d/d3d_backend.c | 6 +- engine/dotnet2005/ftequake.vcproj | 386 ++++++------- engine/gl/gl_alias.c | 15 +- engine/gl/gl_backend.c | 46 +- engine/gl/gl_draw.c | 14 +- engine/gl/gl_font.c | 62 ++- engine/gl/gl_hlmdl.c | 4 - engine/gl/gl_model.c | 67 ++- engine/gl/gl_model.h | 16 + engine/gl/gl_rlight.c | 157 +----- engine/gl/gl_rmain.c | 14 +- engine/gl/gl_rmisc.c | 12 +- engine/gl/gl_shader.c | 40 +- engine/gl/gl_shadow.c | 123 ++-- engine/gl/gl_vidcommon.c | 125 +++-- engine/gl/glquake.h | 11 +- engine/gl/shader.h | 8 +- engine/qclib/initlib.c | 20 +- engine/qclib/pr_exec.c | 10 +- engine/qclib/pr_multi.c | 6 +- engine/qclib/pr_x86.c | 12 +- engine/qclib/progsint.h | 8 +- engine/qclib/qcc_pr_comp.c | 20 +- engine/server/pr_cmds.c | 117 ++-- engine/server/pr_q1qvm.c | 4 + engine/server/server.h | 2 + engine/server/sv_ents.c | 7 + engine/server/sv_main.c | 10 +- engine/server/sv_phys.c | 4 +- engine/server/sv_send.c | 5 +- engine/server/sv_user.c | 530 +++++++++--------- engine/server/svmodel.c | 15 +- 70 files changed, 2062 insertions(+), 1311 deletions(-) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 88fb20885..9fa0538b8 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -114,6 +114,9 @@ static void CL_ClearDlight(dlight_t *dl, int key) dl->axis[2][2] = 1; dl->key = key; dl->flags = LFLAG_DYNAMIC; + dl->color[0] = 1; + dl->color[1] = 1; + dl->color[2] = 1; // if (r_shadow_realtime_dlight_shadowmap.value) // dl->flags |= LFLAG_SHADOWMAP; } @@ -335,7 +338,13 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean #endif if (bits & U_MODEL) + { to->modelindex = MSG_ReadByte (); + if (morebits & U_MODELDBL && cls.fteprotocolextensions & PEXT_MODELDBL) + to->modelindex += 256; + } + else if (morebits & U_MODELDBL && cls.fteprotocolextensions & PEXT_MODELDBL) + to->modelindex = MSG_ReadShort(); if (bits & U_FRAME) to->frame = MSG_ReadByte (); @@ -401,8 +410,6 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean to->number += 512; if (morebits & U_ENTITYDBL2 && cls.fteprotocolextensions & PEXT_ENTITYDBL2) to->number += 1024; - if (morebits & U_MODELDBL && cls.fteprotocolextensions & PEXT_MODELDBL) - to->modelindex += 256; if (morebits & U_DPFLAGS)// && cls.fteprotocolextensions & PEXT_DPFLAGS) { @@ -2961,7 +2968,7 @@ void CL_LinkPlayers (void) } radius += (flicker+j)&31; } - CL_NewDlightRGB(j+1, org, radius, 0.1, colour[0], colour[1], colour[2])->flags &= ~LFLAG_ALLOW_FLASH; + CL_NewDlightRGB(j+1, org, radius, 0.1, colour[0], colour[1], colour[2])->flags &= ~LFLAG_FLASHBLEND; } } @@ -3096,7 +3103,7 @@ void CL_LinkPlayers (void) CL_AddFlagModels (ent, 0); else if (state->effects & QWEF_FLAG2) CL_AddFlagModels (ent, 1); - else if (info->vweapindex) + if (info->vweapindex) CL_AddVWeapModel (ent, cl.model_precache[info->vweapindex]); else if (state->command.impulse) CL_AddVWeapModel (ent, cl.model_precache_vwep[state->command.impulse]); @@ -3108,7 +3115,7 @@ void CL_LinkPlayers (void) { dlight_t *dl; dl = CL_NewDlightRGB(j+1, ent->origin, 300, r_torch.ival, 0.05, 0.05, 0.02); - dl->flags |= LFLAG_SHADOWMAP|LFLAG_ALLOW_FLASH; + dl->flags |= LFLAG_SHADOWMAP|LFLAG_FLASHBLEND; dl->fov = 60; angles[0] *= 3; angles[1] += sin(realtime)*8; diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 8f80acdd0..52873049b 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -755,7 +755,7 @@ void CL_UpdatePrydonCursor(usercmd_t *from, float cursor_screen[2], vec3_t curso temp[2] = 1; VectorCopy(r_origin, cursor_start); - Matrix4_UnProject(temp, cursor_end, cl.viewangles[0], cursor_start, r_refdef.fov_x, r_refdef.fov_y); + Matrix4x4_CM_UnProject(temp, cursor_end, cl.viewangles[0], cursor_start, r_refdef.fov_x, r_refdef.fov_y); CL_SetSolidEntities(); //don't bother with players, they don't exist in NQ... diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 69e89cccc..13dbb12cb 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -412,6 +412,54 @@ void CL_SupportedFTEExtensions(int *pext1, int *pext2) } #endif +char *CL_GUIDString(void) +{ + static qbyte buf[2048]; + static int buflen; + unsigned int digest[4]; + char serveraddr[256]; + void *blocks[2]; + int lens[2]; + if (!buflen) + { + vfsfile_t *f; + f = FS_OpenVFS("qkey", "rb", FS_ROOT); + if (f) + { + buflen = VFS_GETLEN(f); + if (buflen > 2048) + buflen = 2048; + buflen = VFS_READ(f, buf, buflen); + VFS_CLOSE(f); + } + if (buflen < 16) + { + buflen = sizeof(buf); + if (!Sys_RandomBytes(buf, buflen)) + { + int i; + srand(time(NULL)); + for (i = 0; i < buflen; i++) + buf[i] = rand() & 0xff; + } + f = FS_OpenVFS("qkey", "wb", FS_ROOT); + if (f) + { + VFS_WRITE(f, buf, buflen); + VFS_CLOSE(f); + } + } + } + + NET_AdrToString(serveraddr, sizeof(serveraddr), cls.netchan.remote_address); + + blocks[0] = buf;lens[0] = buflen; + blocks[1] = serveraddr;lens[1] = strlen(serveraddr); + Com_BlocksChecksum(2, blocks, lens, (void*)digest); + + return va("%08x%08x%08x%08x", digest[0], digest[1], digest[2], digest[3]); +} + /* ======================= CL_SendConnectPacket @@ -429,6 +477,7 @@ void CL_SendConnectPacket ( extern cvar_t qport; netadr_t adr; char data[2048]; + char *info; double t1, t2; #ifdef PROTOCOL_VERSION_FTE int fteprotextsupported=0; @@ -569,6 +618,10 @@ void CL_SendConnectPacket ( #endif cls.netchan.compress = false; + info = CL_GUIDString(); + if (info) + Q_strncatz(data, va("0x%x \"%s\"\n", PROTOCOL_INFO_GUID, info), sizeof(data)); + NET_SendPacket (NS_CLIENT, strlen(data), data, adr); cl.splitclients = 0; @@ -3844,7 +3897,7 @@ Con_TPrintf (TL_NL); Con_Printf ("%s", version_string()); Con_TPrintf (TL_NL); - Con_TPrintf (TLC_QUAKEWORLD_INITED); + Con_TPrintf (TLC_QUAKEWORLD_INITED, fs_gamename.string); Con_DPrintf("This program is free software; you can redistribute it and/or " "modify it under the terms of the GNU General Public License " diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 36dc1a5a1..6d29dc5b6 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -2067,7 +2067,7 @@ void CL_ClearParseState(void) CL_ParseServerData ================== */ -void CL_ParseServerData (void) +void CLQW_ParseServerData (void) { int pnum; int clnum; @@ -3537,6 +3537,9 @@ void CLNQ_ParseStartSoundPacket(void) channel &= 7; } + /*unpack mangling*/ + channel = (channel & 7) | ((channel & 0x0f1) << 1); + if (field_mask & DPSND_LARGESOUND) sound_num = (unsigned short)MSG_ReadShort(); else @@ -4760,10 +4763,12 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n void CL_ParsePrecache(void) { - int i = (unsigned short)MSG_ReadShort(); + int i, code = (unsigned short)MSG_ReadShort(); char *s = MSG_ReadString(); - if (i < 32768) + i = code & 0x1fff; + switch(code & 0xe000) { + case 0x0000: if (i >= 1 && i < MAX_MODELS) { model_t *model; @@ -4778,10 +4783,8 @@ void CL_ParsePrecache(void) } else Con_Printf("svc_precache: model index %i outside range %i...%i\n", i, 1, MAX_MODELS); - } - else - { - i -= 32768; + break; + case 0x8000: if (i >= 1 && i < MAX_SOUNDS) { sfx_t *sfx; @@ -4795,6 +4798,7 @@ void CL_ParsePrecache(void) } else Con_Printf("svc_precache: sound index %i outside range %i...%i\n", i, 1, MAX_SOUNDS); + break; } } @@ -4985,7 +4989,7 @@ void CL_ParseServerMessage (void) case svc_serverdata: Cbuf_Execute (); // make sure any stuffed commands are done - CL_ParseServerData (); + CLQW_ParseServerData (); vid.recalc_refdef = true; // leave full screen intermission break; #ifdef PEXT_SETVIEW diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index f496749c8..707281203 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1024,7 +1024,7 @@ void SCR_CrosshairPosition(int pnum, int *x, int *y) adj+=v_viewheight.value; start[2]+=adj; - Matrix4_Project(tr.endpos, end, cl.simangles[pnum], start, r_refdef.fov_x, r_refdef.fov_y); + Matrix4x4_CM_Project(tr.endpos, end, cl.simangles[pnum], start, r_refdef.fov_x, r_refdef.fov_y); *x = rect.x+rect.width*end[0]; *y = rect.y+rect.height*(1-end[1]); return; diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 82a04145a..c613fa852 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -582,7 +582,7 @@ void VQ3_RenderView(const q3refdef_t *ref) { dlight_t *dl; dl = CL_NewDlightRGB(0, ref->vieworg, 300, r_torch.ival, 0.05, 0.05, 0.02); - dl->flags |= LFLAG_SHADOWMAP|LFLAG_ALLOW_FLASH; + dl->flags |= LFLAG_SHADOWMAP|LFLAG_FLASHBLEND; dl->fov = 60; VectorCopy(ref->viewaxis[0], dl->axis[0]); VectorCopy(ref->viewaxis[1], dl->axis[1]); diff --git a/engine/client/client.h b/engine/client/client.h index 330965273..d1bc2c8ee 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -240,16 +240,15 @@ typedef struct #define DL_LAST (sizeof(unsigned int)*8-1) #define RTL_FIRST (sizeof(unsigned int)*8) -#define LFLAG_NORMALMODE (1<<0) -#define LFLAG_REALTIMEMODE (1<<1) +#define LFLAG_NORMALMODE (1<<0) /*ppl with r_shadow_realtime_dlight*/ +#define LFLAG_REALTIMEMODE (1<<1) /*ppl with r_shadow_realtime_world*/ +#define LFLAG_LIGHTMAP (1<<2) +#define LFLAG_FLASHBLEND (1<<3) -#define LFLAG_NOSHADOWS (1<<15) -#define LFLAG_ALLOW_LMHACK (1<<16) -#define LFLAG_ALLOW_FLASH (1<<17) -#define LFLAG_ALLOW_PPL (1<<18) -#define LFLAG_SHADOWMAP (1<<19) +#define LFLAG_NOSHADOWS (1<<8) +#define LFLAG_SHADOWMAP (1<<9) -#define LFLAG_DYNAMIC (LFLAG_ALLOW_PPL | LFLAG_ALLOW_LMHACK | LFLAG_ALLOW_FLASH | LFLAG_NORMALMODE | LFLAG_REALTIMEMODE) +#define LFLAG_DYNAMIC (LFLAG_LIGHTMAP | LFLAG_FLASHBLEND | LFLAG_NORMALMODE | LFLAG_REALTIMEMODE) typedef struct dlight_s { diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 5c9e834c9..0a4c46c33 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -558,7 +558,7 @@ void M_DrawSources (void) {"Max ping", &sb_maxping, 1}, {"GameDir", &sb_gamedir, 2}, {"Using map", &sb_mapname, 2}, - {"Game name", &com_gamename, 2} + {"Game", &com_protocolname, 2} }; void M_DrawSListOptions (void) diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 8f340a305..583a40a67 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -1211,7 +1211,7 @@ void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles) case MT_MASTERDP: { char *str; - str = va("%c%c%c%cgetservers %s %u empty full\x0A\n", 255, 255, 255, 255, com_gamename.string, 3); + str = va("%c%c%c%cgetservers %s %u empty full\x0A\n", 255, 255, 255, 255, com_protocolname.string, 3); NET_SendPollPacket (strlen(str), str, mast->adr); } break; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 11664797b..4ba8584af 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -53,7 +53,8 @@ static qboolean csqc_isdarkplaces; static char csqc_printbuffer[8192]; #define CSQCPROGSGROUP "CSQC progs control" -cvar_t pr_csmaxedicts = CVAR("pr_csmaxedicts", "3072"); //not tied to protocol nor server. +cvar_t pr_csqc_maxedicts = CVAR("pr_csqc_maxedicts", "3072"); //not tied to protocol nor server. +cvar_t pr_csqc_memsize = CVAR("pr_csqc_memsize", "-1"); cvar_t cl_csqcdebug = CVAR("cl_csqcdebug", "0"); //prints entity numbers which arrive (so I can tell people not to apply it to players...) cvar_t cl_nocsqc = CVAR("cl_nocsqc", "0"); cvar_t pr_csqc_coreonerror = CVAR("pr_csqc_coreonerror", "1"); @@ -767,8 +768,12 @@ static void QCBUILTIN PF_R_DynamicLight_Set(progfuncs_t *prinst, struct globalva dlight_t *l; unsigned int lno = G_FLOAT(OFS_PARM0); int field = G_FLOAT(OFS_PARM1); - if (lno >= cl_maxdlights) - return; + while (lno >= cl_maxdlights) + { + if (lno > 1000) + return; + CL_AllocSlight(); + } l = cl_dlights+lno; switch (field) { @@ -782,6 +787,8 @@ static void QCBUILTIN PF_R_DynamicLight_Set(progfuncs_t *prinst, struct globalva case 2: l->radius = G_FLOAT(OFS_PARM2); l->rebuildcache = true; + if (lno >= rtlights_max) + rtlights_max = lno+1; break; case 3: l->flags = G_FLOAT(OFS_PARM2); @@ -790,6 +797,12 @@ static void QCBUILTIN PF_R_DynamicLight_Set(progfuncs_t *prinst, struct globalva case 4: l->style = G_FLOAT(OFS_PARM2); break; + case 5: + AngleVectors(G_VECTOR(OFS_PARM2), l->axis[0], l->axis[1], l->axis[2]); + break; + case 6: + l->fov = G_FLOAT(OFS_PARM2); + break; default: break; } @@ -825,6 +838,12 @@ static void QCBUILTIN PF_R_DynamicLight_Get(progfuncs_t *prinst, struct globalva case 4: G_FLOAT(OFS_RETURN) = l->style; break; + case 5: + VectorAngles(l->axis[0], l->axis[2], G_VECTOR(OFS_RETURN)); + break; + case 6: + G_FLOAT(OFS_RETURN) = l->fov; + break; default: G_INT(OFS_RETURN) = 0; break; @@ -907,7 +926,7 @@ static int csqc_startpolyvert; // #306 void(string texturename) R_BeginPolygon (EXT_CSQC_???) static void QCBUILTIN PF_R_PolygonBegin(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - csqc_shadern = R_RegisterSkin(PR_GetStringOfs(prinst, OFS_PARM0)); + csqc_shadern = R_RegisterSkin(PR_GetStringOfs(prinst, OFS_PARM0), NULL); csqc_startpolyvert = cl_numstrisvert; } @@ -984,8 +1003,8 @@ float csqc_proj_matrix_inverse[16]; float proj[16]; /*build modelview and projection*/ - Matrix4_ModelViewMatrix(modelview, r_refdef.viewangles, r_refdef.vieworg); - Matrix4_Projection2(proj, r_refdef.fov_x, r_refdef.fov_y, 4); + Matrix4x4_CM_ModelViewMatrix(modelview, r_refdef.viewangles, r_refdef.vieworg); + Matrix4x4_CM_Projection2(proj, r_refdef.fov_x, r_refdef.fov_y, 4); /*build the project matrix*/ Matrix4_Multiply(proj, modelview, csqc_proj_matrix); @@ -1011,7 +1030,7 @@ static void QCBUILTIN PF_cs_project (progfuncs_t *prinst, struct globalvars_s *p v[2] = in[2]; v[3] = 1; - Matrix4_Transform4(csqc_proj_matrix, v, tempv); + Matrix4x4_CM_Transform4(csqc_proj_matrix, v, tempv); tempv[0] /= tempv[3]; tempv[1] /= tempv[3]; @@ -1052,7 +1071,7 @@ static void QCBUILTIN PF_cs_unproject (progfuncs_t *prinst, struct globalvars_s if (v[2] >= 1) v[2] = 0.999999; - Matrix4_Transform4(csqc_proj_matrix_inverse, v, tempv); + Matrix4x4_CM_Transform4(csqc_proj_matrix_inverse, v, tempv); out[0] = tempv[0]/tempv[3]; out[1] = tempv[1]/tempv[3]; @@ -1529,18 +1548,7 @@ static void QCBUILTIN PF_cs_tracebox(progfuncs_t *prinst, struct globalvars_s *p trace = World_Move (&csqc_world, v1, mins, maxs, v2, nomonsters, (wedict_t*)ent); ent->xv->hull = savedhull; - *csqcg.trace_allsolid = trace.allsolid; - *csqcg.trace_startsolid = trace.startsolid; - *csqcg.trace_fraction = trace.fraction; - *csqcg.trace_inwater = trace.inwater; - *csqcg.trace_inopen = trace.inopen; - VectorCopy (trace.endpos, csqcg.trace_endpos); - VectorCopy (trace.plane.normal, csqcg.trace_plane_normal); - *csqcg.trace_plane_dist = trace.plane.dist; - if (trace.ent) - *csqcg.trace_ent = EDICT_TO_PROG(prinst, (void*)trace.ent); - else - *csqcg.trace_ent = EDICT_TO_PROG(prinst, (void*)csqc_world.edicts); + cs_settracevars(&trace); } static trace_t CS_Trace_Toss (csqcedict_t *tossent, csqcedict_t *ignore) @@ -1598,18 +1606,7 @@ static void QCBUILTIN PF_cs_tracetoss (progfuncs_t *prinst, struct globalvars_s trace = CS_Trace_Toss (ent, ignore); - *csqcg.trace_allsolid = trace.allsolid; - *csqcg.trace_startsolid = trace.startsolid; - *csqcg.trace_fraction = trace.fraction; - *csqcg.trace_inwater = trace.inwater; - *csqcg.trace_inopen = trace.inopen; - VectorCopy (trace.endpos, csqcg.trace_endpos); - VectorCopy (trace.plane.normal, csqcg.trace_plane_normal); - *csqcg.trace_plane_dist = trace.plane.dist; - if (trace.ent) - *csqcg.trace_ent = EDICT_TO_PROG(prinst, trace.ent); - else - *csqcg.trace_ent = EDICT_TO_PROG(prinst, (void*)csqc_world.edicts); + cs_settracevars(&trace); } static int CS_PointContents(vec3_t org) @@ -3412,7 +3409,7 @@ static void QCBUILTIN PF_shaderforname (progfuncs_t *prinst, struct globalvars_s char *str = PF_VarString(prinst, 0, pr_globals); shader_t *shad; - shad = R_RegisterSkin(str); + shad = R_RegisterSkin(str, NULL); if (shad) G_FLOAT(OFS_RETURN) = shad-r_shaders + 1; else @@ -3525,7 +3522,6 @@ static void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s * //float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_build (FTE_CSQC_SKELETONOBJECTS) static void QCBUILTIN PF_skel_build(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - #define MAX_BONES 256 int skelidx = G_FLOAT(OFS_PARM0); csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1); int midx = G_FLOAT(OFS_PARM2); @@ -3955,6 +3951,12 @@ static void QCBUILTIN PF_cs_walkmove (progfuncs_t *prinst, struct globalvars_s * *csqcg.self = oldself; } +void PF_cs_touchtriggers(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + wedict_t *ent = (wedict_t*)PROG_TO_EDICT(prinst, *csqcg.self); + World_LinkEdict (&csqc_world, ent, true); +} + static void QCBUILTIN PF_cs_movetogoal (progfuncs_t *prinst, struct globalvars_s *pr_globals) { wedict_t *ent; @@ -4746,6 +4748,7 @@ static struct { {"frameduration", PF_frameduration, 277},//void(float modidx, float framenum) frameduration = #277 (FTE_CSQC_SKELETONOBJECTS) {"terrain_edit", PF_cs_terrain_edit, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT??) + {"touchtriggers", PF_cs_touchtriggers, 279},//void() touchtriggers = #279; //300 {"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC) {"addentities", PF_R_AddEntityMask, 301}, // #301 void(float mask) addentities (EXT_CSQC) @@ -5355,7 +5358,7 @@ qboolean CSQC_Init (unsigned int checksum) csqcprogs = InitProgs(&csqcprogparms); csqc_world.progs = csqcprogs; csqc_world.usesolidcorpse = true; - PR_Configure(csqcprogs, -1, 16); + PR_Configure(csqcprogs, pr_csqc_memsize.ival, 16); csqc_world.worldmodel = cl.worldmodel; csqc_world.Event_Touch = CSQC_Event_Touch; csqc_world.GetCModel = CSQC_World_ModelForIndex; @@ -5396,7 +5399,7 @@ qboolean CSQC_Init (unsigned int checksum) csqc_fakereadbyte = -1; memset(csqcent, 0, sizeof(*csqcent)*maxcsqcentities); //clear the server->csqc entity translations. - csqcentsize = PR_InitEnts(csqcprogs, pr_csmaxedicts.value); + csqcentsize = PR_InitEnts(csqcprogs, pr_csqc_maxedicts.value); ED_Alloc(csqcprogs); //we need a world entity. @@ -5625,7 +5628,8 @@ void CSQC_RegisterCvarsAndThings(void) Cmd_AddCommand("cl_cmd", CSQC_GameCommand_f); Cmd_AddCommand("breakpoint_csqc", CSQC_Breakpoint_f); - Cvar_Register(&pr_csmaxedicts, CSQCPROGSGROUP); + Cvar_Register(&pr_csqc_memsize, CSQCPROGSGROUP); + Cvar_Register(&pr_csqc_maxedicts, CSQCPROGSGROUP); Cvar_Register(&cl_csqcdebug, CSQCPROGSGROUP); Cvar_Register(&cl_nocsqc, CSQCPROGSGROUP); Cvar_Register(&pr_csqc_coreonerror, CSQCPROGSGROUP); @@ -5685,10 +5689,13 @@ qboolean CSQC_DrawView(void) csqc_resortfrags = true; - if (csqcg.clientcommandframe) - *csqcg.clientcommandframe = cls.netchan.outgoing_sequence; - if (csqcg.servercommandframe) - *csqcg.servercommandframe = cl.ackedinputsequence; + if (!cl.paused) + { + if (csqcg.clientcommandframe) + *csqcg.clientcommandframe = cls.netchan.outgoing_sequence; + if (csqcg.servercommandframe) + *csqcg.servercommandframe = cl.ackedinputsequence; + } if (csqcg.intermission) *csqcg.intermission = cl.intermission; diff --git a/engine/client/quakedef.h b/engine/client/quakedef.h index 0749b3605..154d536e0 100644 --- a/engine/client/quakedef.h +++ b/engine/client/quakedef.h @@ -227,7 +227,8 @@ extern qboolean noclip_anglehack; // extern quakeparms_t host_parms; -extern cvar_t com_gamename; +extern cvar_t fs_gamename; +extern cvar_t com_protocolname; extern cvar_t com_modname; extern cvar_t sys_ticrate; extern cvar_t sys_nostdout; diff --git a/engine/client/r_d3.c b/engine/client/r_d3.c index 1b69426c8..5caf8d96b 100644 --- a/engine/client/r_d3.c +++ b/engine/client/r_d3.c @@ -310,8 +310,8 @@ static qboolean D3_PolyBounds(vec_t result[4], int count, vec4_t *vlist) result[3] = -10000; for (i = 0; i < count; i++) { - Matrix4_Transform4(r_refdef.m_view, vlist[i], tempv); - Matrix4_Transform4(r_refdef.m_projection, tempv, v); + Matrix4x4_CM_Transform4(r_refdef.m_view, vlist[i], tempv); + Matrix4x4_CM_Transform4(r_refdef.m_projection, tempv, v); v[0] /= v[3]; v[1] /= v[3]; diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index cfa681973..aa4b01ec5 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -340,7 +340,7 @@ static void Surf_AddDynamicLights (msurface_t *surf) if ( !(surf->dlightbits & (1<funcs.MarkLights (&cl_dlights[k], 1<lightdata) { - memcpy(lightmap[i]->lightmaps, cl.worldmodel->lightdata+3*LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i, LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3); + if (lightmap_bytes == 4) + { + int j; + if (lightmap_bgra) + { + for (j = 0; j < LMBLOCK_HEIGHT*LMBLOCK_HEIGHT; j++) + { + lightmap[i]->lightmaps[(j<<2)+0] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[2]; + lightmap[i]->lightmaps[(j<<2)+1] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[1]; + lightmap[i]->lightmaps[(j<<2)+2] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[0]; + lightmap[i]->lightmaps[(j<<2)+3] = 255; + } + } + else + { + for (j = 0; j < LMBLOCK_HEIGHT*LMBLOCK_HEIGHT; j++) + { + lightmap[i]->lightmaps[(j<<2)+0] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[0]; + lightmap[i]->lightmaps[(j<<2)+1] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[1]; + lightmap[i]->lightmaps[(j<<2)+2] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[2]; + lightmap[i]->lightmaps[(j<<2)+3] = 255; + } + } + } + else + { + /*BUG: assumes RGB. if its BGR then wrong colours, but whys that going to happen*/ + memcpy(lightmap[i]->lightmaps, cl.worldmodel->lightdata+3*LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i, LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3); + } } else { @@ -2300,7 +2328,6 @@ void Surf_BuildSurfaceDisplayList (model_t *model, msurface_t *fa) int vertpage; float *vec; float s, t; - int lm; // reconstruct the polygon pedges = model->edges; @@ -2361,13 +2388,11 @@ void Surf_BuildSurfaceDisplayList (model_t *model, msurface_t *fa) mesh->st_array[i][1] = t/fa->texinfo->texture->height; s -= fa->texturemins[0]; - lm = s*fa->light_t; s += fa->light_s*16; s += 8; s /= LMBLOCK_WIDTH*16; t -= fa->texturemins[1]; - lm += t; t += fa->light_t*16; t += 8; t /= LMBLOCK_HEIGHT*16; diff --git a/engine/client/render.h b/engine/client/render.h index 7d17e95d7..a9ce0993e 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -179,8 +179,8 @@ void BE_GenModelBatches(struct batch_s **batches); //gl_alias.c void R_GAlias_DrawBatch(struct batch_s *batch); void R_GAlias_GenerateBatches(entity_t *e, struct batch_s **batches); -void R_LightArraysByte_BGR(vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals); -void R_LightArrays(vecV_t *coords, vec4_t *colours, int vertcount, vec3_t *normals); +void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals); +void R_LightArrays(const entity_t *entity, vecV_t *coords, vec4_t *colours, int vertcount, vec3_t *normals); void R_DrawSkyChain (struct batch_s *batch); /*called from the backend, and calls back into it*/ void R_InitSky (struct texnums_s *ret, struct texture_s *mt, qbyte *src); /*generate q1 sky texnums*/ diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 89ce54118..790367c74 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -49,6 +49,32 @@ HWND sys_parentwindow; unsigned int sys_parentwidth; //valid if sys_parentwindow is set unsigned int sys_parentheight; + +/* +================ +Sys_RandomBytes +================ +*/ +#include +qboolean Sys_RandomBytes(qbyte *string, int len) +{ + HCRYPTPROV prov; + + if(!CryptAcquireContext( &prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + { + return false; + } + + if(!CryptGenRandom(prov, len, (BYTE *)string)) + { + CryptReleaseContext( prov, 0); + return false; + } + CryptReleaseContext(prov, 0); + return true; +} + + void Sys_CloseLibrary(dllhandle_t *lib) { FreeLibrary((HMODULE)lib); diff --git a/engine/client/view.c b/engine/client/view.c index 9ccecd87f..129f98407 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1286,7 +1286,7 @@ void R_DrawNameTags(void) { VectorCopy(nametagorg[i], tagcenter); tagcenter[2] += 32; - Matrix4_Project(tagcenter, center, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); + Matrix4x4_CM_Project(tagcenter, center, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); if (center[2] > 1) continue; diff --git a/engine/client/wad.c b/engine/client/wad.c index 34010240f..888b24ac4 100644 --- a/engine/client/wad.c +++ b/engine/client/wad.c @@ -79,7 +79,7 @@ void W_LoadWadFile (char *filename) if (!wad_base) { wad_numlumps = 0; - Con_Printf ("W_LoadWadFile: couldn't load %s\n", filename); + Con_DPrintf ("W_LoadWadFile: couldn't load %s\n", filename); return; } diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 590c14641..d860e4ddb 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -160,7 +160,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define DPMMODELS //darkplaces model format (which I've never seen anyone use) #define PSKMODELS //PSK model format (ActorX stuff from UT, though not the format the game itself uses) #define HALFLIFEMODELS //halflife model support (experimental) -// #define INTERQUAKEMODELS + #define INTERQUAKEMODELS #define HUFFNETWORK //huffman network compression //#define DOOMWADS //doom wad/sprite support @@ -444,8 +444,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_EDICTS 32767 // FIXME: ouch! ouch! ouch! #define MAX_LIGHTSTYLES 255 #define MAX_STANDARDLIGHTSTYLES 64 -#define MAX_MODELS 512 // these are sent over the net as bytes -#define MAX_SOUNDS 512 // so they cannot be blindly increased +#define MAX_MODELS 1024 // these are sent over the net as bytes +#define MAX_SOUNDS 1024 // so they cannot be blindly increased #define MAX_VWEP_MODELS 32 #define MAX_CSQCMODELS 256 // these live entirly clientside diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index f06137964..b68c7010e 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -180,7 +180,7 @@ typedef struct typedef struct { int planenum; - short children[2]; // negative numbers are contents + int children[2]; // negative numbers are contents } mclipnode_t; typedef struct texinfo_s diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 9d74e7624..45cd0a41c 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -211,6 +211,35 @@ void Mod_NormaliseTextureVectors(vec3_t *n, vec3_t *s, vec3_t *t, int v) #ifdef SKELETALMODELS +static void GenMatrixPosQuat4Scale(vec3_t pos, vec4_t quat, vec3_t scale, float result[12]) +{ + float xx, xy, xz, xw, yy, yz, yw, zz, zw; + float x2, y2, z2; + x2 = quat[0] + quat[0]; + y2 = quat[1] + quat[1]; + z2 = quat[2] + quat[2]; + + xx = quat[0] * x2; xy = quat[0] * y2; xz = quat[0] * z2; + yy = quat[1] * y2; yz = quat[1] * z2; zz = quat[2] * z2; + xw = quat[3] * x2; yw = quat[3] * y2; zw = quat[3] * z2; + + result[0*4+0] = 1.0f - (yy + zz); + result[1*4+0] = xy + zw; + result[2*4+0] = xz - yw; + + result[0*4+1] = xy - zw; + result[1*4+1] = 1.0f - (xx + zz); + result[2*4+1] = yz + xw; + + result[0*4+2] = xz + yw; + result[1*4+2] = yz - xw; + result[2*4+2] = 1.0f - (xx + yy); + + result[0*4+3] = pos[0]; + result[1*4+3] = pos[1]; + result[2*4+3] = pos[2]; +} + static void GenMatrix(float x, float y, float z, float qx, float qy, float qz, float result[12]) { float qw; @@ -304,7 +333,132 @@ static void PSKGenMatrix(float x, float y, float z, float qx, float qy, float qz result[2*4+3] = z; } -void Alias_TransformVerticies(float *bonepose, galisskeletaltransforms_t *weights, int numweights, vecV_t *xyzout, vec3_t *normout) +#define restrict + +/*transforms some skeletal vecV_t values*/ +static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout) +{ + int i; + float *matrix; + for (i = 0; i < vertcount; i++, xyzout+=sizeof(vecV_t)/sizeof(vec_t), xyzin+=sizeof(vecV_t)/sizeof(vec_t), bidx+=4, weights+=4) + { + matrix = &bonepose[12*bidx[0]]; + xyzout[0] = weights[0] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + xyzin[3] * matrix[ 3]); + xyzout[1] = weights[0] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + xyzin[3] * matrix[ 7]); + xyzout[2] = weights[0] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + xyzin[3] * matrix[11]); + + if (bidx[1] != ~(qbyte)0) + { + matrix = &bonepose[12*bidx[1]]; + xyzout[0] += weights[1] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + xyzin[3] * matrix[ 3]); + xyzout[1] += weights[1] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + xyzin[3] * matrix[ 7]); + xyzout[2] += weights[1] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + xyzin[3] * matrix[11]); + + if (bidx[2] != ~(qbyte)0) + { + matrix = &bonepose[12*bidx[2]]; + xyzout[0] += weights[2] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + xyzin[3] * matrix[ 3]); + xyzout[1] += weights[2] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + xyzin[3] * matrix[ 7]); + xyzout[2] += weights[2] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + xyzin[3] * matrix[11]); + + if (bidx[3] != ~(qbyte)0) + { + matrix = &bonepose[12*bidx[3]]; + xyzout[0] += weights[3] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + xyzin[3] * matrix[ 3]); + xyzout[1] += weights[3] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + xyzin[3] * matrix[ 7]); + xyzout[2] += weights[3] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + xyzin[3] * matrix[11]); + } + } + } + } +} + +/*transforms some skeletal vecV_t values*/ +static void Alias_TransformVerticies_VN(float *bonepose, int vertcount, qbyte *bidx, float *weights, + float *xyzin, float *restrict xyzout, + float *normin, float *restrict normout) +{ + int i, j; + float *matrix; + float mat[12]; + for (i = 0; i < vertcount; i++, + xyzout+=sizeof(vecV_t)/sizeof(vec_t), xyzin+=sizeof(vecV_t)/sizeof(vec_t), + normout+=sizeof(vec3_t)/sizeof(vec_t), normin+=sizeof(vec3_t)/sizeof(vec_t), + bidx+=4, weights+=4) + { + matrix = &bonepose[12*bidx[0]]; + for (j = 0; j < 12; j++) + mat[j] = weights[0] * matrix[j]; + if (weights[1]) + { + matrix = &bonepose[12*bidx[1]]; + for (j = 0; j < 12; j++) + mat[j] += weights[1] * matrix[j]; + if (weights[2]) + { + matrix = &bonepose[12*bidx[2]]; + for (j = 0; j < 12; j++) + mat[j] += weights[2] * matrix[j]; + if (weights[3]) + { + matrix = &bonepose[12*bidx[3]]; + for (j = 0; j < 12; j++) + mat[j] += weights[3] * matrix[j]; + } + } + } + + matrix = mat; + xyzout[0] = (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + matrix[ 3]); + xyzout[1] = (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + matrix[ 7]); + xyzout[2] = (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + matrix[11]); + + normout[0] = (normin[0] * matrix[0] + normin[1] * matrix[1] + normin[2] * matrix[ 2]); + normout[1] = (normin[0] * matrix[4] + normin[1] * matrix[5] + normin[2] * matrix[ 6]); + normout[2] = (normin[0] * matrix[8] + normin[1] * matrix[9] + normin[2] * matrix[10]); + } +} + + +/*transforms some skeletal vec3_t values*/ +static void Alias_TransformVerticies_3(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout) +{ + int i; + float *matrix; + for (i = 0; i < vertcount; i++, xyzout+=sizeof(vec3_t)/sizeof(vec_t), xyzin+=sizeof(vec3_t)/sizeof(vec_t), bidx+=4, weights+=4) + { + matrix = &bonepose[12*bidx[0]]; + xyzout[0] = weights[0] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + xyzin[3] * matrix[ 3]); + xyzout[1] = weights[0] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + xyzin[3] * matrix[ 7]); + xyzout[2] = weights[0] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + xyzin[3] * matrix[11]); + + if (bidx[1] != ~(qbyte)0) + { + matrix = &bonepose[12*bidx[1]]; + xyzout[0] += weights[1] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + xyzin[3] * matrix[ 3]); + xyzout[1] += weights[1] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + xyzin[3] * matrix[ 7]); + xyzout[2] += weights[1] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + xyzin[3] * matrix[11]); + + if (bidx[2] != ~(qbyte)0) + { + matrix = &bonepose[12*bidx[2]]; + xyzout[0] += weights[2] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + xyzin[3] * matrix[ 3]); + xyzout[1] += weights[2] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + xyzin[3] * matrix[ 7]); + xyzout[2] += weights[2] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + xyzin[3] * matrix[11]); + + if (bidx[3] != ~(qbyte)0) + { + matrix = &bonepose[12*bidx[3]]; + xyzout[0] += weights[3] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + xyzin[3] * matrix[ 3]); + xyzout[1] += weights[3] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + xyzin[3] * matrix[ 7]); + xyzout[2] += weights[3] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + xyzin[3] * matrix[11]); + } + } + } + } +} + +static void Alias_TransformVerticies_SW(float *bonepose, galisskeletaltransforms_t *weights, int numweights, vecV_t *xyzout, vec3_t *normout) { int i; float *out, *matrix; @@ -316,7 +470,7 @@ void Alias_TransformVerticies(float *bonepose, galisskeletaltransforms_t *weight for (i = 0;i < numweights;i++, v++) { out = xyzout[v->vertexindex]; - normo = normout[ + v->vertexindex]; + normo = normout[v->vertexindex]; matrix = bonepose+v->boneindex*12; // FIXME: this can very easily be optimized with SSE or 3DNow out[0] += v->org[0] * matrix[0] + v->org[1] * matrix[1] + v->org[2] * matrix[ 2] + v->org[3] * matrix[ 3]; @@ -370,12 +524,15 @@ static float Alias_CalculateSkeletalNormals(galiasinfo_t *model) float maxvdist = 0, d, maxbdist = 0; float absmatrix[MAX_BONES*12]; float bonedist[MAX_BONES]; + int modnum = 0; + int bcmodnum = -1; + int vcmodnum = -1; while (model) { int numbones = model->numbones; - galisskeletaltransforms_t *v = (galisskeletaltransforms_t*)((char*)model+model->ofstransforms); - int numweights = model->numtransforms; + galisskeletaltransforms_t *v = (galisskeletaltransforms_t*)((char*)model+model->ofsswtransforms); + int numweights = model->numswtransforms; int numverts = model->numverts; if (model->nextsurf) @@ -388,10 +545,11 @@ static float Alias_CalculateSkeletalNormals(galiasinfo_t *model) inversepose = Z_Malloc(numbones*sizeof(float)*9); mvert = Z_Malloc(numverts*sizeof(*mvert)); - if (!model->sharesbones || !bonepose) + if (bcmodnum != model->shares_bones) { galiasgroup_t *g; galiasbone_t *bones = (galiasbone_t *)((char*)model + model->ofsbones); + bcmodnum = model->shares_bones; if (model->baseframeofs) bonepose = (float*)((char*)model + model->baseframeofs); else @@ -450,7 +608,7 @@ static float Alias_CalculateSkeletalNormals(galiasinfo_t *model) } //build the actual base pose positions - Alias_TransformVerticies(bonepose, v, numweights, xyz, NULL); + Alias_TransformVerticies_SW(bonepose, v, numweights, xyz, NULL); //work out which verticies are identical //this is needed as two verts can have same origin but different tex coords @@ -472,36 +630,39 @@ static float Alias_CalculateSkeletalNormals(galiasinfo_t *model) //use that base pose to calculate the normals memset(normals, 0, numverts*sizeof(vec3_t)); + vcmodnum = modnum; + idx = (index_t*)((char*)model + model->ofs_indexes); + + //calculate the triangle normal and accumulate them + for (i = 0; i < model->numindexes; i+=3, idx+=3) + { + TriangleNormal(xyz[idx[0]], xyz[idx[1]], xyz[idx[2]], tn); + //note that tn is relative to the size of the triangle + + //Imagine a cube, each side made of two triangles + + VectorSubtract(xyz[idx[1]], xyz[idx[0]], d1); + VectorSubtract(xyz[idx[2]], xyz[idx[0]], d2); + angle = acos(DotProduct(d1, d2)/(Length(d1)*Length(d2))); + VectorMA(normals[mvert[idx[0]]], angle, tn, normals[mvert[idx[0]]]); + + VectorSubtract(xyz[idx[0]], xyz[idx[1]], d1); + VectorSubtract(xyz[idx[2]], xyz[idx[1]], d2); + angle = acos(DotProduct(d1, d2)/(Length(d1)*Length(d2))); + VectorMA(normals[mvert[idx[1]]], angle, tn, normals[mvert[idx[1]]]); + + VectorSubtract(xyz[idx[0]], xyz[idx[2]], d1); + VectorSubtract(xyz[idx[1]], xyz[idx[2]], d2); + angle = acos(DotProduct(d1, d2)/(Length(d1)*Length(d2))); + VectorMA(normals[mvert[idx[2]]], angle, tn, normals[mvert[idx[2]]]); + } + + /*skip over each additional surface that shares the same verts*/ for(;;) { - idx = (index_t*)((char*)model + model->ofs_indexes); - - //calculate the triangle normal and accumulate them - for (i = 0; i < model->numindexes; i+=3, idx+=3) - { - TriangleNormal(xyz[idx[0]], xyz[idx[1]], xyz[idx[2]], tn); - //note that tn is relative to the size of the triangle - - //Imagine a cube, each side made of two triangles - - VectorSubtract(xyz[idx[1]], xyz[idx[0]], d1); - VectorSubtract(xyz[idx[2]], xyz[idx[0]], d2); - angle = acos(DotProduct(d1, d2)/(Length(d1)*Length(d2))); - VectorMA(normals[mvert[idx[0]]], angle, tn, normals[mvert[idx[0]]]); - - VectorSubtract(xyz[idx[0]], xyz[idx[1]], d1); - VectorSubtract(xyz[idx[2]], xyz[idx[1]], d2); - angle = acos(DotProduct(d1, d2)/(Length(d1)*Length(d2))); - VectorMA(normals[mvert[idx[1]]], angle, tn, normals[mvert[idx[1]]]); - - VectorSubtract(xyz[idx[0]], xyz[idx[2]], d1); - VectorSubtract(xyz[idx[1]], xyz[idx[2]], d2); - angle = acos(DotProduct(d1, d2)/(Length(d1)*Length(d2))); - VectorMA(normals[mvert[idx[2]]], angle, tn, normals[mvert[idx[2]]]); - } - - if (next && next->sharesverts && next->sharesbones) + if (next && next->shares_verts == vcmodnum) { + modnum++; model = next; if (model->nextsurf) next = (galiasinfo_t*)((char*)model + model->nextsurf); @@ -511,6 +672,7 @@ static float Alias_CalculateSkeletalNormals(galiasinfo_t *model) else break; } + //the normals are not normalized yet. for (i = 0; i < numverts; i++) { @@ -524,12 +686,16 @@ static float Alias_CalculateSkeletalNormals(galiasinfo_t *model) v->normal[2] = DotProduct(normals[mvert[v->vertexindex]], inversepose+9*v->boneindex+6) * v->org[3]; } + if (model->ofs_skel_norm) + memcpy((char*)model + model->ofs_skel_norm, normals, numverts*sizeof(vec3_t)); + //FIXME: save off the xyz+normals for this base pose as an optimisation for world objects. Z_Free(inversepose); Z_Free(normals); Z_Free(xyz); model = next; + modnum++; } return maxvdist+maxbdist; #else @@ -880,22 +1046,36 @@ static void R_LerpBones(float *plerp, float **pose, int poses, galiasbone_t *bon #if defined(D3DQUAKE) || defined(GLQUAKE) -extern entity_t *currententity; -int numTempColours; -avec4_t *tempColours; +struct +{ + int numcolours; + avec4_t *colours; -int numTempVertexCoords; -vecV_t *tempVertexCoords; + int numcoords; + vecV_t *coords; -int numTempNormals; -vec3_t *tempNormals; + int numnorm; + vec3_t *norm; + + int surfnum; + entity_t *ent; + + float bonepose[MAX_BONES*12]; + float *usebonepose; + int bonecount; + + vecV_t *acoords; + vec3_t *anorm; + vec3_t *anorms; + vec3_t *anormt; +} meshcache; //#define SSE_INTRINSICS #ifdef SSE_INTRINSICS #include #endif -void R_LightArraysByte_BGR(vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals) +void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals) { //extern cvar_t r_vertexdlights; //unused int i; @@ -904,13 +1084,13 @@ void R_LightArraysByte_BGR(vecV_t *coords, byte_vec4_t *colours, int vertcount, byte_vec4_t ambientlightb; byte_vec4_t shadelightb; - float *lightdir = currententity->light_dir; + const float *lightdir = entity->light_dir; for (i = 0; i < 3; i++) { - l = currententity->light_avg[2-i]*255; + l = entity->light_avg[2-i]*255; ambientlightb[i] = bound(0, l, 255); - l = currententity->light_range[2-i]*255; + l = entity->light_range[2-i]*255; shadelightb[i] = bound(0, l, 255); } @@ -942,7 +1122,7 @@ void R_LightArraysByte_BGR(vecV_t *coords, byte_vec4_t *colours, int vertcount, } } -void R_LightArrays(vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals) +void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals) { extern cvar_t r_vertexdlights; int i; @@ -950,13 +1130,13 @@ void R_LightArrays(vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *norm //float *lightdir = currententity->light_dir; //unused variable - if (!currententity->light_range[0] && !currententity->light_range[1] && !currententity->light_range[2]) + if (!entity->light_range[0] && !entity->light_range[1] && !entity->light_range[2]) { for (i = vertcount-1; i >= 0; i--) { - colours[i][0] = currententity->light_avg[0]; - colours[i][1] = currententity->light_avg[1]; - colours[i][2] = currententity->light_avg[2]; + colours[i][0] = entity->light_avg[0]; + colours[i][1] = entity->light_avg[1]; + colours[i][2] = entity->light_avg[2]; } } else @@ -971,7 +1151,7 @@ void R_LightArrays(vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *norm /*dotproduct will return a value between 1 and -1, so increase the ambient to be correct for normals facing away from the light*/ for (i = vertcount-1; i >= 0; i--) { - l = DotProduct(normals[i], currententity->light_dir); + l = DotProduct(normals[i], entity->light_dir); #ifdef SSE_INTRINSICS vl = _mm_load1_ps(&l); vr = _mm_mul_ss(va,vl); @@ -980,9 +1160,9 @@ void R_LightArrays(vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *norm _mm_storeu_ps(colours[i], vr); //stomp on colour[i][3] (will be set to 1) #else - colours[i][0] = l*currententity->light_range[0]+currententity->light_avg[0]; - colours[i][1] = l*currententity->light_range[1]+currententity->light_avg[1]; - colours[i][2] = l*currententity->light_range[2]+currententity->light_avg[2]; + colours[i][0] = l*entity->light_range[0]+entity->light_avg[0]; + colours[i][1] = l*entity->light_range[1]+entity->light_avg[1]; + colours[i][2] = l*entity->light_range[2]+entity->light_avg[2]; #endif } } @@ -998,14 +1178,14 @@ void R_LightArrays(vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *norm if (cl_dlights[lno].radius) { VectorSubtract (cl_dlights[lno].origin, - currententity->origin, + entity->origin, dir); if (Length(dir)>cl_dlights[lno].radius+256) //far out man! continue; - rel[0] = -DotProduct(dir, currententity->axis[0]); - rel[1] = -DotProduct(dir, currententity->axis[1]); - rel[2] = -DotProduct(dir, currententity->axis[2]); + rel[0] = -DotProduct(dir, entity->axis[0]); + rel[1] = -DotProduct(dir, entity->axis[1]); + rel[2] = -DotProduct(dir, entity->axis[2]); for (v = 0; v < vertcount; v++) { @@ -1029,7 +1209,7 @@ void R_LightArrays(vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *norm } } -static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float lerp, qbyte alpha, float expand, qboolean nolightdir) +static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float lerp, float expand) { extern cvar_t r_nolerp; // r_nolightdir is unused float blerp = 1-lerp; @@ -1080,7 +1260,6 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float { if (mesh->xyz_array == p1v) { - mesh->xyz_array = tempVertexCoords; for (i = 0; i < mesh->numvertexes; i++) { mesh->xyz_array[i][0] = p1v[i][0] + mesh->normals_array[i][0]*expand; @@ -1103,11 +1282,33 @@ static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float #ifdef SKELETALMODELS #ifndef SERVERONLY -static void Alias_BuildSkeletalMesh(mesh_t *mesh, float *bonepose, galisskeletaltransforms_t *weights, int numweights) +static void Alias_BuildSkeletalMesh(mesh_t *mesh, float *bonepose, galiasinfo_t *inf) { - memset(mesh->xyz_array, 0, mesh->numvertexes*sizeof(vecV_t)); - memset(mesh->normals_array, 0, mesh->numvertexes*sizeof(vec3_t)); - Alias_TransformVerticies(bonepose, weights, numweights, mesh->xyz_array, mesh->normals_array); + galisskeletaltransforms_t *weights = (galisskeletaltransforms_t *)((char*)inf+inf->ofsswtransforms); + int numweights = inf->numswtransforms; + + if (inf->ofs_skel_idx) + { + float *restrict xyzout = mesh->xyz_array[0]; + float *restrict normout = mesh->normals_array[0]; + qbyte *restrict bidx = (qbyte*)((char*)inf + inf->ofs_skel_idx); + float *restrict xyzin = (float*)((char*)inf + inf->ofs_skel_xyz); + float *restrict normin = (float*)((char*)inf + inf->ofs_skel_norm); + float *restrict svect = (float*)((char*)inf + inf->ofs_skel_svect); + float *restrict tvect = (float*)((char*)inf + inf->ofs_skel_tvect); + float *restrict weight = (float*)((char*)inf + inf->ofs_skel_weight); + + Alias_TransformVerticies_VN(bonepose, inf->numverts, bidx, weight, xyzin, xyzout, normin, normout); +// Alias_TransformVerticies_3(bonepose, inf->numverts, bidx, weight, svect, mesh->snormals_array[0]); +// Alias_TransformVerticies_3(bonepose, inf->numverts, bidx, weight, tvect, mesh->tnormals_array[0]); + + } + else + { + memset(mesh->xyz_array, 0, mesh->numvertexes*sizeof(vecV_t)); + memset(mesh->normals_array, 0, mesh->numvertexes*sizeof(vec3_t)); + Alias_TransformVerticies_SW(bonepose, weights, numweights, mesh->xyz_array, mesh->normals_array); + } } #ifdef GLQUAKE @@ -1172,9 +1373,12 @@ static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int #endif //!SERVERONLY #endif //SKELETALMODELS -qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, - entity_t *e, - float alpha, qboolean nolightdir) +void Alias_FlushCache(void) +{ + meshcache.ent = NULL; +} + +qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, entity_t *e, qboolean usebones) { galiasgroup_t *g1, *g2; @@ -1186,147 +1390,190 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, if (!inf->groups) { - Con_DPrintf("Model with no frames (%s)\n", currententity->model->name); + Con_DPrintf("Model with no frames (%s)\n", e->model->name); return false; } - if (numTempColours < inf->numverts) + if (meshcache.numcolours < inf->numverts) { - if (tempColours) - BZ_Free(tempColours); - tempColours = BZ_Malloc(sizeof(*tempColours)*inf->numverts); - numTempColours = inf->numverts; + if (meshcache.colours) + BZ_Free(meshcache.colours); + meshcache.colours = BZ_Malloc(sizeof(*meshcache.colours)*inf->numverts); + meshcache.numcolours = inf->numverts; } - if (numTempNormals < inf->numverts) + if (meshcache.numnorm < inf->numverts) { - if (tempNormals) - BZ_Free(tempNormals); - tempNormals = BZ_Malloc(sizeof(*tempNormals)*inf->numverts); - numTempNormals = inf->numverts; + if (meshcache.norm) + BZ_Free(meshcache.norm); + meshcache.norm = BZ_Malloc(sizeof(*meshcache.norm)*inf->numverts*3); + meshcache.numnorm = inf->numverts; } - if (numTempVertexCoords < inf->numverts) + if (meshcache.numcoords < inf->numverts) { - if (tempVertexCoords) - BZ_Free(tempVertexCoords); - tempVertexCoords = BZ_Malloc(sizeof(*tempVertexCoords)*inf->numverts*3); - numTempVertexCoords = inf->numverts; + if (meshcache.coords) + BZ_Free(meshcache.coords); + meshcache.coords = BZ_Malloc(sizeof(*meshcache.coords)*inf->numverts); + meshcache.numcoords = inf->numverts; } mesh->numvertexes = inf->numverts; mesh->indexes = (index_t*)((char *)inf + inf->ofs_indexes); mesh->numindexes = inf->numindexes; - if (inf->sharesverts) + mesh->st_array = (vec2_t*)((char *)inf + inf->ofs_st_array); + mesh->lmst_array = NULL; + mesh->trneighbors = (int *)((char *)inf + inf->ofs_trineighbours); + mesh->colors4f_array = meshcache.colours; + + if (meshcache.surfnum == inf->shares_verts && meshcache.ent == e) + { + mesh->xyz_array = meshcache.acoords; + mesh->normals_array = meshcache.anorm; + mesh->snormals_array = meshcache.anorms; + mesh->tnormals_array = meshcache.anormt; + + if (meshcache.usebonepose) + { + mesh->bonenums = (byte_vec4_t*)((char*)inf + inf->ofs_skel_idx); + mesh->boneweights = (vec4_t*)((char*)inf + inf->ofs_skel_weight); + mesh->bones = meshcache.usebonepose; + mesh->numbones = inf->numbones; + } return false; //don't generate the new vertex positions. We still have them all. + } + meshcache.surfnum = inf->shares_verts; + meshcache.ent = e; + #ifndef SERVERONLY mesh->st_array = (vec2_t*)((char *)inf + inf->ofs_st_array); mesh->lmst_array = NULL; - mesh->colors4f_array = tempColours; mesh->trneighbors = (int *)((char *)inf + inf->ofs_trineighbours); - mesh->normals_array = tempNormals; - mesh->snormals_array = tempNormals+numTempVertexCoords; - mesh->tnormals_array = tempNormals+numTempVertexCoords*2; + mesh->normals_array = meshcache.norm; + mesh->snormals_array = meshcache.norm+meshcache.numnorm; + mesh->tnormals_array = meshcache.norm+meshcache.numnorm*2; #endif - mesh->xyz_array = tempVertexCoords; + mesh->xyz_array = meshcache.coords; //we don't support meshes with one pose skeletal and annother not. //we don't support meshes with one group skeletal and annother not. + meshcache.usebonepose = NULL; #ifdef SKELETALMODELS if (inf->numbones) { - float bonepose[MAX_BONES][12]; - float *usebonepose; - usebonepose = Alias_GetBonePositions(inf, &e->framestate, (float*)bonepose, MAX_BONES); - Alias_BuildSkeletalMesh(mesh, usebonepose, (galisskeletaltransforms_t *)((char*)inf+inf->ofstransforms), inf->numtransforms); + meshcache.usebonepose = Alias_GetBonePositions(inf, &e->framestate, meshcache.bonepose, MAX_BONES); + + if (1)//e->fatness || !inf->ofs_skel_idx || !usebones) + { + Alias_BuildSkeletalMesh(mesh, meshcache.usebonepose, inf); #ifdef PEXT_FATNESS - if (currententity->fatness) - { - if (mesh->xyz_array == tempVertexCoords) + if (e->fatness) { int i; for (i = 0; i < mesh->numvertexes; i++) { - VectorMA(mesh->xyz_array[i], currententity->fatness, mesh->normals_array[i], mesh->xyz_array[i]); + VectorMA(mesh->xyz_array[i], e->fatness, mesh->normals_array[i], meshcache.coords[i]); } + + mesh->xyz_array = meshcache.coords; } - } #endif + #ifdef GLQUAKE - if (!inf->numtransforms && qrenderer == QR_OPENGL) - Alias_GLDrawSkeletalBones((galiasbone_t*)((char*)inf + inf->ofsbones), (float *)usebonepose, inf->numbones); + if (!inf->numswtransforms && qrenderer == QR_OPENGL) + Alias_GLDrawSkeletalBones((galiasbone_t*)((char*)inf + inf->ofsbones), (float *)meshcache.usebonepose, inf->numbones); #endif - - if (mesh->colors4f_array) - R_LightArrays(mesh->xyz_array, mesh->colors4f_array, mesh->numvertexes, mesh->normals_array); - return true; - } -#endif - - frame1 = e->framestate.g[FS_REG].frame[0]; - frame2 = e->framestate.g[FS_REG].frame[1]; - lerp = e->framestate.g[FS_REG].lerpfrac; - fg1time = e->framestate.g[FS_REG].frametime[0]; - fg2time = e->framestate.g[FS_REG].frametime[1]; - - if (frame1 < 0) - { - Con_DPrintf("Negative frame (%s)\n", currententity->model->name); - frame1 = 0; - } - if (frame2 < 0) - { - Con_DPrintf("Negative frame (%s)\n", currententity->model->name); - frame2 = frame1; - } - if (frame1 >= inf->groups) - { - Con_DPrintf("Too high frame %i (%s)\n", frame1, currententity->model->name); - frame1 %= inf->groups; - } - if (frame2 >= inf->groups) - { - Con_DPrintf("Too high frame %i (%s)\n", frame2, currententity->model->name); - frame2 = frame1; - } - - if (lerp <= 0) - frame2 = frame1; - else if (lerp >= 1) - frame1 = frame2; - - g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); - g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); - - if (g1 == g2) //lerping within group is only done if not changing group - { - lerp = fg1time*g1->rate; - if (lerp < 0) lerp = 0; //hrm - frame1=lerp; - frame2=frame1+1; - lerp-=frame1; - if (g1->loop) - { - frame1=frame1%g1->numposes; - frame2=frame2%g1->numposes; + meshcache.usebonepose = NULL; } else { - frame1=(frame1>g1->numposes-1)?g1->numposes-1:frame1; - frame2=(frame2>g1->numposes-1)?g1->numposes-1:frame2; + mesh->xyz_array = (vecV_t*)((char*)inf + inf->ofs_skel_xyz); + mesh->normals_array = (vec3_t*)((char*)inf + inf->ofs_skel_norm); + mesh->snormals_array = (vec3_t*)((char*)inf + inf->ofs_skel_svect); + mesh->tnormals_array = (vec3_t*)((char*)inf + inf->ofs_skel_tvect); } } - else //don't bother with a four way lerp. Yeah, this will produce jerkyness with models with just framegroups. + else +#endif { - frame1=0; - frame2=0; + frame1 = e->framestate.g[FS_REG].frame[0]; + frame2 = e->framestate.g[FS_REG].frame[1]; + lerp = e->framestate.g[FS_REG].lerpfrac; + fg1time = e->framestate.g[FS_REG].frametime[0]; + fg2time = e->framestate.g[FS_REG].frametime[1]; + + if (frame1 < 0) + { + Con_DPrintf("Negative frame (%s)\n", e->model->name); + frame1 = 0; + } + if (frame2 < 0) + { + Con_DPrintf("Negative frame (%s)\n", e->model->name); + frame2 = frame1; + } + if (frame1 >= inf->groups) + { + Con_DPrintf("Too high frame %i (%s)\n", frame1, e->model->name); + frame1 %= inf->groups; + } + if (frame2 >= inf->groups) + { + Con_DPrintf("Too high frame %i (%s)\n", frame2, e->model->name); + frame2 = frame1; + } + + if (lerp <= 0) + frame2 = frame1; + else if (lerp >= 1) + frame1 = frame2; + + g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); + g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); + + if (g1 == g2) //lerping within group is only done if not changing group + { + lerp = fg1time*g1->rate; + if (lerp < 0) lerp = 0; //hrm + frame1=lerp; + frame2=frame1+1; + lerp-=frame1; + if (g1->loop) + { + frame1=frame1%g1->numposes; + frame2=frame2%g1->numposes; + } + else + { + frame1=(frame1>g1->numposes-1)?g1->numposes-1:frame1; + frame2=(frame2>g1->numposes-1)?g1->numposes-1:frame2; + } + } + else //don't bother with a four way lerp. Yeah, this will produce jerkyness with models with just framegroups. + { + frame1=0; + frame2=0; + } + + R_LerpFrames(mesh, (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1), + (galiaspose_t *)((char *)g2 + g2->poseofs + sizeof(galiaspose_t)*frame2), + 1-lerp, e->fatness); } - R_LerpFrames(mesh, (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1), - (galiaspose_t *)((char *)g2 + g2->poseofs + sizeof(galiaspose_t)*frame2), - 1-lerp, (qbyte)(alpha*255), e->fatness, nolightdir); + meshcache.acoords = mesh->xyz_array; + meshcache.anorm = mesh->normals_array; + meshcache.anorms = mesh->snormals_array; + meshcache.anormt = mesh->tnormals_array; + + if (meshcache.usebonepose) + { + mesh->bonenums = (byte_vec4_t*)((char*)inf + inf->ofs_skel_idx); + mesh->boneweights = (vec4_t*)((char*)inf + inf->ofs_skel_weight); + mesh->bones = meshcache.usebonepose; + mesh->numbones = inf->numbones; + } return true; //to allow the mesh to be dlighted. } @@ -1366,6 +1613,8 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vecV_t *posedata; index_t *indexes; + int surfnum = 0; + int cursurfnum = -1; while(mod) { @@ -1374,19 +1623,21 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], pose = (galiaspose_t*)((char*)&group[0] + group[0].poseofs); posedata = (vecV_t*)((char*)pose + pose->ofsverts); #ifdef SKELETALMODELS - if (mod->numbones && !mod->sharesverts) + if (mod->numbones && mod->shares_verts != cursurfnum) { float bonepose[MAX_BONES][12]; posedata = alloca(mod->numverts*sizeof(vecV_t)); frac = 1; if (group->isheirachical) { - if (!mod->sharesbones) + if (mod->shares_bones != cursurfnum) R_LerpBones(&frac, (float**)posedata, 1, (galiasbone_t*)((char*)mod + mod->ofsbones), mod->numbones, bonepose); - Alias_TransformVerticies((float*)bonepose, (galisskeletaltransforms_t*)((char*)mod + mod->ofstransforms), mod->numtransforms, posedata, NULL); + Alias_TransformVerticies_SW((float*)bonepose, (galisskeletaltransforms_t*)((char*)mod + mod->ofsswtransforms), mod->numswtransforms, posedata, NULL); } else - Alias_TransformVerticies((float*)posedata, (galisskeletaltransforms_t*)((char*)mod + mod->ofstransforms), mod->numtransforms, posedata, NULL); + Alias_TransformVerticies_SW((float*)posedata, (galisskeletaltransforms_t*)((char*)mod + mod->ofsswtransforms), mod->numswtransforms, posedata, NULL); + + cursurfnum = mod->shares_verts; } #endif @@ -1442,6 +1693,7 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], mod = (galiasinfo_t*)((char*)mod + mod->nextsurf); else mod = NULL; + surfnum++; } trace->allsolid = false; @@ -1845,7 +2097,7 @@ void Mod_LoadSkinFile(texnums_t *texnum, char *surfacename, int skinnumber, unsi Mod_ParseQ3SkinFile(shadername, surfacename, loadmodel->name, skinnumber, NULL); - texnum->shader = R_RegisterSkin(shadername); + texnum->shader = R_RegisterSkin(shadername, loadmodel->name); R_BuildDefaultTexnums(texnum, texnum->shader); if (texnum->shader->flags & SHADER_NOIMAGE) @@ -2238,7 +2490,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran "}\n" "}\n"); else - texnums->shader = R_RegisterSkin(skinname); + texnums->shader = R_RegisterSkin(skinname, loadmodel->name); R_BuildDefaultTexnums(texnums, texnums->shader); texnums->loweroverlay = r_nulltex; @@ -2334,7 +2586,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran } Q_snprintfz(skinname, sizeof(skinname), "%s_%i_%i", loadname, i, t); - texnums->shader = R_RegisterSkin(skinname); + texnums->shader = R_RegisterSkin(skinname, loadmodel->name); texnums->base = texture; texnums->fullbright = fbtexture; @@ -2720,7 +2972,7 @@ static void Q2_LoadSkins(md2_t *pq2inmodel, char *skins) COM_CleanUpPath(skins); //blooming tanks. texnums->base = R_LoadReplacementTexture(skins, "models", IF_NOALPHA); - texnums->shader = R_RegisterSkin(skins); + texnums->shader = R_RegisterSkin(skins, loadmodel->name); R_BuildDefaultTexnums(texnums, texnums->shader); outskin->skinwidth = 0; @@ -3653,7 +3905,7 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer) if (qrenderer != QR_NONE) { - texnum->shader = R_RegisterSkin(shadname); + texnum->shader = R_RegisterSkin(shadname, mod->name); R_BuildDefaultTexnums(texnum, texnum->shader); if (texnum->shader->flags & SHADER_NOIMAGE) @@ -3885,16 +4137,16 @@ qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer) root = Hunk_AllocName(sizeof(galiasinfo_t)*header->numsurfaces, loadname); - root->numtransforms = header->lump_verts.length/sizeof(zymvertex_t); - transforms = Hunk_Alloc(root->numtransforms*sizeof(*transforms)); - root->ofstransforms = (char*)transforms - (char*)root; + root->numswtransforms = header->lump_verts.length/sizeof(zymvertex_t); + transforms = Hunk_Alloc(root->numswtransforms*sizeof(*transforms)); + root->ofsswtransforms = (char*)transforms - (char*)root; vertbonecounts = (int *)((char*)header + header->lump_vertbonecounts.start); intrans = (zymvertex_t *)((char*)header + header->lump_verts.start); vertbonecounts[0] = BigLong(vertbonecounts[0]); multiplier = 1.0f / vertbonecounts[0]; - for (i = 0, v=0; i < root->numtransforms; i++) + for (i = 0, v=0; i < root->numswtransforms; i++) { while(!vertbonecounts[v]) { @@ -3932,7 +4184,7 @@ qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer) root->numverts = v+1; root->numbones = header->numbones; - bone = Hunk_Alloc(root->numtransforms*sizeof(*transforms)); + bone = Hunk_Alloc(root->numswtransforms*sizeof(*transforms)); inbone = (zymbone_t*)((char*)header + header->lump_bones.start); for (i = 0; i < root->numbones; i++) { @@ -4036,7 +4288,7 @@ qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer) root[i].nextsurf = sizeof(galiasinfo_t); for (i = 1; i < header->numsurfaces; i++) { - root[i].sharesverts = true; + root[i].shares_verts = 0; root[i].numbones = root[0].numbones; root[i].numverts = root[0].numverts; @@ -4223,6 +4475,11 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) int hunkstart, hunkend, hunktotal; //extern cvar_t temp1; //unused variable + vecV_t *skel_xyz; + vec3_t *skel_norm; + byte_vec4_t *skel_idx; + vec4_t *skel_weights; + /*load the psk*/ while (pos < com_filesize && !fail) { @@ -4486,7 +4743,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) basematrix_inverse = Hunk_TempAllocMore(num_boneinfo*sizeof(float)*16); for (i = 0; i < num_boneinfo; i++) { - Matrix4Q_Invert_Simple(basematrix+i*12, basematrix_inverse+i*16); + Matrix3x4_InvertTo4x4_Simple(basematrix+i*12, basematrix_inverse+i*16); } /*expand the translations*/ @@ -4519,10 +4776,45 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) num_trans++; } } -// for (j = 0; j < num_trans-first_trans; j++) -// { -// VectorScale(pnts[rawweights[j].pntsindex].origin, rawweights[j].weight, trans[num_trans].org); -// } + } + + skel_xyz = Hunk_Alloc(sizeof(*skel_xyz) * num_vtxw); + skel_norm = Hunk_Alloc(sizeof(*skel_norm) * num_vtxw); + skel_idx = Hunk_Alloc(sizeof(*skel_idx) * num_vtxw); + skel_weights = Hunk_Alloc(sizeof(*skel_weights) * num_vtxw); + for (i = 0; i < num_vtxw; i++) + { + float t; + *(unsigned int*)skel_idx[i] = ~0; + for (j = 0; j < num_rawweights; j++) + { + if (rawweights[j].pntsindex == vtxw[i].pntsindex) + { + int in, lin = -1; + float liv = rawweights[j].weight; + for (in = 0; in < 4; in++) + { + if (liv > skel_weights[i][in]) + { + liv = skel_weights[i][in]; + lin = in; + if (!liv) + break; + } + } + if (lin >= 0) + { + skel_idx[i][lin] = rawweights[j].boneindex; + skel_weights[i][lin] = rawweights[j].weight; + } + } + } + t = 0; + for (j = 0; j < 4; j++) + t += skel_weights[i][j]; + if (t != 1) + for (j = 0; j < 4; j++) + skel_weights[i][j] *= 1/t; } #ifndef SERVERONLY @@ -4530,6 +4822,9 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) stcoord = Hunk_Alloc(sizeof(vec2_t)*num_vtxw); for (i = 0; i < num_vtxw; i++) { + skel_xyz[i][0] = pnts[vtxw[i].pntsindex].origin[0]; + skel_xyz[i][1] = pnts[vtxw[i].pntsindex].origin[1]; + skel_xyz[i][2] = pnts[vtxw[i].pntsindex].origin[2]; stcoord[i*2+0] = vtxw[i].texcoord[0]; stcoord[i*2+1] = vtxw[i].texcoord[1]; } @@ -4611,7 +4906,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) skin->texnums = 1; skin->skinspeed = 10; Q_strncpyz(skin->name, matt[i].name, sizeof(skin->name)); - gtexnums->shader = R_RegisterSkin(matt[i].name); + gtexnums->shader = R_RegisterSkin(matt[i].name, mod->name); R_BuildDefaultTexnums(gtexnums, gtexnums->shader); if (gtexnums->shader->flags & SHADER_NOIMAGE) Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", gtexnums->shader->name, loadmodel->name); @@ -4644,11 +4939,16 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) gmdl[i].ofsbones = (char*)bones - (char*)&gmdl[i]; gmdl[i].numbones = num_boneinfo; - gmdl[i].ofstransforms = (char*)trans - (char*)&gmdl[i]; - gmdl[i].numtransforms = num_trans; - - gmdl[i].sharesverts = i!=0; - gmdl[i].sharesbones = i!=0; + gmdl[i].ofsswtransforms = (char*)trans - (char*)&gmdl[i]; + gmdl[i].numswtransforms = num_trans; +/* + gmdl[i].ofs_skel_idx = (char*)skel_idx - (char*)&gmdl[i]; + gmdl[i].ofs_skel_weight = (char*)skel_weights - (char*)&gmdl[i]; + gmdl[i].ofs_skel_xyz = (char*)skel_xyz - (char*)&gmdl[i]; + gmdl[i].ofs_skel_norm = (char*)skel_norm - (char*)&gmdl[i]; +*/ + gmdl[i].shares_verts = 0; + gmdl[i].shares_bones = 0; gmdl[i].nextsurf = (i != num_matt-1)?sizeof(*gmdl):0; } @@ -4901,8 +5201,8 @@ qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer) #endif //build the transform list. - m->ofstransforms = (char*)transforms - (char*)m; - m->numtransforms = numtransforms; + m->ofsswtransforms = (char*)transforms - (char*)m; + m->numswtransforms = numtransforms; vert = (dpmvertex_t*)((char *)buffer+mesh->ofs_verts); for (j = 0; j < mesh->num_verts; j++) { @@ -4986,7 +5286,7 @@ qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer) m = &root[i]; if (i < header->num_meshs-1) m->nextsurf = sizeof(galiasinfo_t); - m->sharesbones = true; + m->shares_bones = 0; m->ofsbones = (char*)outbone-(char*)m; m->numbones = header->num_bones; @@ -5014,7 +5314,6 @@ qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer) m->ofsskins = (char *)skin - (char *)m; #endif } - root[0].sharesbones = false; Alias_CalculateSkeletalNormals(root); @@ -5054,7 +5353,8 @@ qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer) #ifdef INTERQUAKEMODELS #define IQM_MAGIC "INTERQUAKEMODEL" -#define IQM_VERSION 1 +#define IQM_VERSION1 1 +#define IQM_VERSION2 2 struct iqmheader { @@ -5112,20 +5412,33 @@ struct iqmtriangle unsigned int vertex[3]; }; -struct iqmjoint +struct iqmjoint1 { unsigned int name; int parent; float translate[3], rotate[3], scale[3]; }; +struct iqmjoint2 +{ + unsigned int name; + int parent; + float translate[3], rotate[4], scale[3]; +}; -struct iqmpose +struct iqmpose1 { int parent; unsigned int mask; float channeloffset[9]; float channelscale[9]; }; +struct iqmpose2 +{ + int parent; + unsigned int mask; + float channeloffset[10]; + float channelscale[10]; +}; struct iqmanim { @@ -5155,6 +5468,7 @@ struct iqmbounds float xyradius, radius; }; +/* galisskeletaltransforms_t *IQM_ImportTransforms(int *resultcount, int inverts, float *vpos, float *tcoord, float *vnorm, float *vtang, unsigned char *vbone, unsigned char *vweight) { galisskeletaltransforms_t *t, *r; @@ -5182,35 +5496,48 @@ galisskeletaltransforms_t *IQM_ImportTransforms(int *resultcount, int inverts, f } return r; } +*/ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) { struct iqmheader *h = (struct iqmheader *)buffer; - struct iqmjoint *joint; struct iqmmesh *mesh; struct iqmvertexarray *varray; struct iqmtriangle *tris; - unsigned int i, t, nt; + struct iqmanim *anim; + unsigned int i, j, t, nt; char *strings; float *vpos = NULL, *tcoord = NULL, *vnorm = NULL, *vtang = NULL; unsigned char *vbone = NULL, *vweight = NULL; unsigned int type, fmt, size, offset; + unsigned short *framedata; + + vecV_t *opos; + vec3_t *onorm; + vec4_t *oweight; + byte_vec4_t *oindex; + float *opose; + galiasinfo_t *gai; galiasskin_t *skin; + galiasgroup_t *fgroup; + galiasbone_t *bones; texnums_t *texnum; index_t *idx; + float basepose[12 * MAX_BONES]; + float invbasepose[12 * MAX_BONES]; if (memcmp(h->magic, IQM_MAGIC, sizeof(h->magic))) { Con_Printf("%s: format not recognised\n", mod->name); return NULL; } - if (h->version != IQM_VERSION) + if (h->version != IQM_VERSION1 && h->version != IQM_VERSION2) { - Con_Printf("%s: unsupported version\n", mod->name); + Con_Printf("%s: unsupported IQM version\n", mod->name); return NULL; } if (h->filesize != com_filesize) @@ -5249,6 +5576,8 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) vbone = (unsigned char *)(buffer + offset); else if (type == IQM_BLENDWEIGHTS && fmt == IQM_UBYTE && size == 4) vweight = (unsigned char *)(buffer + offset); + else + Con_Printf("Unrecognised iqm info\n"); } if (!h->num_meshes) @@ -5256,38 +5585,142 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) strings = buffer + h->ofs_text; - mesh = buffer + h->ofs_meshes; - tris = buffer + h->ofs_triangles; + mesh = (struct iqmmesh*)(buffer + h->ofs_meshes); - gai = Hunk_Alloc(sizeof(*gai)*h->num_meshes + sizeof(*skin)*h->num_meshes + sizeof(*texnum)*h->num_meshes); - skin = (galiasskin_t*)(gai + h->num_meshes); + /*allocate a nice big block of memory and figure out where stuff is*/ + gai = Hunk_Alloc(sizeof(*gai)*h->num_meshes + sizeof(*skin)*h->num_meshes + sizeof(*texnum)*h->num_meshes + + sizeof(*fgroup)*h->num_anims + sizeof(float)*12*h->num_poses*h->num_frames + sizeof(*bones)*h->num_joints + + (sizeof(*opos) + sizeof(*onorm) + sizeof(*oweight) + sizeof(*oindex)) * h->num_vertexes); + bones = (galiasbone_t*)(gai + h->num_meshes); + skin = (galiasskin_t*)(bones + h->num_joints); texnum = (texnums_t*)(skin + h->num_meshes); + opos = (vecV_t*)(texnum + h->num_meshes); + onorm = (vec3_t*)(opos + h->num_vertexes); + oindex = (byte_vec4_t*)(onorm + h->num_vertexes); + oweight = (vec4_t*)(oindex + h->num_vertexes); + fgroup = (galiasgroup_t*)(oweight + h->num_vertexes); + opose = (float*)(fgroup + h->num_anims); + +//no code to load animations or bones + framedata = (unsigned short*)(buffer + h->ofs_frames); + + /*Version 1 supports only normalized quaternions, version 2 uses complete quaternions. Some struct sizes change for this, otherwise functionally identical.*/ + if (h->version == IQM_VERSION1) + { + struct iqmpose1 *p, *ipose = (struct iqmpose1*)(buffer + h->ofs_poses); + struct iqmjoint1 *ijoint = (struct iqmjoint1*)(buffer + h->ofs_joints); + vec3_t pos; + vec4_t quat; + vec3_t scale; + + for (i = 0; i < h->num_joints; i++) + { + Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(ijoint[i].name)); + bones[i].parent = ijoint[i].parent; + + GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]); + } + + for (i = 0; i < h->num_frames; i++) + { + for (j = 0, p = ipose; j < h->num_poses; j++, p++) + { + pos[0] = p->channeloffset[0]; if (p->mask & 1) pos[0] += *framedata++ + p->channelscale[0]; + pos[1] = p->channeloffset[1]; if (p->mask & 2) pos[1] += *framedata++ + p->channelscale[1]; + pos[2] = p->channeloffset[2]; if (p->mask & 4) pos[2] += *framedata++ + p->channelscale[2]; + quat[0] = p->channeloffset[3]; if (p->mask & 8) quat[0] += *framedata++ + p->channelscale[3]; + quat[1] = p->channeloffset[4]; if (p->mask & 16) quat[1] += *framedata++ + p->channelscale[4]; + quat[2] = p->channeloffset[5]; if (p->mask & 32) quat[2] += *framedata++ + p->channelscale[5]; + scale[0] = p->channeloffset[6]; if (p->mask & 64) scale[0] += *framedata++ + p->channelscale[6]; + scale[1] = p->channeloffset[7]; if (p->mask & 128) scale[1] += *framedata++ + p->channelscale[7]; + scale[2] = p->channeloffset[8]; if (p->mask & 256) scale[2] += *framedata++ + p->channelscale[8]; + + quat[3] = -sqrt(max(1.0 - pow(VectorLength(quat),2), 0.0)); + + GenMatrixPosQuat4Scale(pos, quat, scale, opose + (i*h->num_poses+j)*12); + } + } + } + else + { + struct iqmpose2 *p, *ipose = (struct iqmpose2*)(buffer + h->ofs_poses); + struct iqmjoint2 *ijoint = (struct iqmjoint2*)(buffer + h->ofs_joints); + vec3_t pos; + vec4_t quat; + vec3_t scale; + float mat[12]; + + for (i = 0; i < h->num_joints; i++) + { + Q_strncpyz(bones[i].name, strings+ijoint[i].name, sizeof(bones[i].name)); + bones[i].parent = ijoint[i].parent; + + GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]); + +// Mod_Skel_Invert(bones, basepose, h->num_joints, invbonepose); + } + + for (i = 0; i < h->num_frames; i++) + { + for (j = 0, p = ipose; j < h->num_poses; j++, p++) + { + pos[0] = p->channeloffset[0]; if (p->mask & 1) pos[0] += *framedata++ + p->channelscale[0]; + pos[1] = p->channeloffset[1]; if (p->mask & 2) pos[1] += *framedata++ + p->channelscale[1]; + pos[2] = p->channeloffset[2]; if (p->mask & 4) pos[2] += *framedata++ + p->channelscale[2]; + quat[0] = p->channeloffset[3]; if (p->mask & 8) quat[0] += *framedata++ + p->channelscale[3]; + quat[1] = p->channeloffset[4]; if (p->mask & 16) quat[1] += *framedata++ + p->channelscale[4]; + quat[2] = p->channeloffset[5]; if (p->mask & 32) quat[2] += *framedata++ + p->channelscale[5]; + quat[3] = p->channeloffset[6]; if (p->mask & 64) quat[3] += *framedata++ + p->channelscale[6]; + scale[0] = p->channeloffset[7]; if (p->mask & 128) scale[0] += *framedata++ + p->channelscale[7]; + scale[1] = p->channeloffset[8]; if (p->mask & 256) scale[1] += *framedata++ + p->channelscale[8]; + scale[2] = p->channeloffset[9]; if (p->mask & 512) scale[2] += *framedata++ + p->channelscale[9]; + + GenMatrixPosQuat4Scale(pos, quat, scale, &opose[(i*h->num_poses+j)*12]); + } + } + } + +// Mod_Skel_PreSkin(basepose, invbonepose + + /*load the framegroup info*/ + anim = (struct iqmanim*)(buffer + h->ofs_anims); + for (i = 0; i < h->num_anims; i++) + { + fgroup[i].isheirachical = true; + fgroup[i].loop = LittleLong(anim[i].flags) & IQM_LOOP; + Q_strncpyz(fgroup[i].name, strings+anim[i].name, sizeof(fgroup[i].name)); + fgroup[i].numposes = LittleLong(anim[i].num_frames); + fgroup[i].poseofs = (char*)(opose+LittleLong(anim[i].first_frame)*12*h->num_poses) - (char*)&fgroup[i]; + fgroup[i].rate = LittleFloat(anim[i].framerate); + } + for (i = 0; i < h->num_meshes; i++) { gai[i].nextsurf = (i == (h->num_meshes-1))?0:sizeof(*gai); - gai[i].sharesverts = false; //used with models with two shaders using the same vertex - use last mesh's verts - gai[i].sharesbones = i != 0; - gai[i].numverts = LittleLong(mesh[i].num_vertexes); + + /*animation info*/ + gai[i].shares_bones = 0; + gai[i].numbones = h->num_joints; + gai[i].ofsbones = (char*)bones - (char*)&gai[i]; + gai[i].groups = h->num_frames; + gai[i].groupofs = (char*)fgroup - (char*)&gai[i]; + + /*skins*/ gai[i].numskins = 1; gai[i].ofsskins = (char*)&skin[i] - (char*)&gai[i]; - Q_strncpyz(skin[i].name, strings+mesh[i].material, sizeof(skin[i].name)); skin[i].skinwidth = 1; skin[i].skinheight = 1; - skin[i].ofstexels = NULL; /*doesn't support 8bit colourmapping*/ + skin[i].ofstexels = 0; /*doesn't support 8bit colourmapping*/ skin[i].skinspeed = 10; /*something to avoid div by 0*/ skin[i].texnums = 1; skin[i].ofstexnums = (char*)&texnum[i] - (char*)&skin[i]; - texnum[i].shader = R_RegisterSkin(skin[i].name); + texnum[i].shader = R_RegisterSkin(skin[i].name, mod->name); offset = LittleLong(mesh[i].first_vertex); - /*generate transforms for each vertex*/ - gai[i].ofstransforms = (char*)IQM_ImportTransforms(&gai[i].numtransforms, gai[i].numverts, vpos+offset*3, tcoord+offset*2, vnorm+offset*3, vtang+offset*4, vbone+offset*4, vweight+offset*4) - (char*)gai; - - - nt = 0;//LittleLong(mesh[i].num_triangles); - tris = buffer + LittleLong(h->ofs_triangles); + nt = LittleLong(mesh[i].num_triangles); + tris = (struct iqmtriangle*)(buffer + LittleLong(h->ofs_triangles)); tris += LittleLong(mesh[i].first_triangle); gai[i].numindexes = nt*3; idx = Hunk_Alloc(sizeof(*idx)*gai[i].numindexes); @@ -5298,12 +5731,30 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) *idx++ = LittleShort(tris[t].vertex[1]); *idx++ = LittleShort(tris[t].vertex[2]); } + + /*verts*/ + gai[i].shares_verts = i; + gai[i].numverts = LittleLong(mesh[i].num_vertexes); + gai[i].ofs_skel_xyz = (char*)(opos+offset) - (char*)&gai[i]; + gai[i].ofs_skel_norm = (char*)(onorm+offset) - (char*)&gai[i]; + gai[i].ofs_skel_svect = 0; + gai[i].ofs_skel_tvect = 0; + gai[i].ofs_skel_idx = (char*)(oindex+offset) - (char*)&gai[i]; + gai[i].ofs_skel_weight = (char*)(oweight+offset) - (char*)&gai[i]; + } + for (i = 0; i < h->num_vertexes; i++) + { + VectorCopy(vpos+i*3, opos[i]); + VectorCopy(vnorm+i*4, onorm[i]); + VectorCopy(vbone+i*4, oindex[i]); + VectorCopy(vweight+i*4, oweight[i]); } return gai; } qboolean Mod_ParseIQMAnim(char *buffer, galiasinfo_t *prototype, void**poseofs, galiasgroup_t *gat) { + return false; } @@ -5317,7 +5768,10 @@ qboolean Mod_LoadInterQuakeModel(model_t *mod, void *buffer) hunkstart = Hunk_LowMark(); root = Mod_ParseIQMMeshModel(mod, buffer); if (!root) + { + Hunk_FreeToLowMark (hunkstart); return false; + } hunkend = Hunk_LowMark(); mod->flags = h->flags; @@ -5557,7 +6011,7 @@ qboolean Mod_ParseMD5Anim(char *buffer, galiasinfo_t *prototype, void**poseofs, #undef EXPECT } -galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer) +galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer, char *modname) { #define MD5ERROR0PARAM(x) { Con_Printf(CON_ERROR x "\n"); return NULL; } #define MD5ERROR1PARAM(x, y) { Con_Printf(CON_ERROR x "\n", y); return NULL; } @@ -5751,7 +6205,7 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer) { buffer = COM_Parse(buffer); #ifndef SERVERONLY - texnum->shader = R_RegisterSkin(com_token); + texnum->shader = R_RegisterSkin(com_token, modname); R_BuildDefaultTexnums(texnum, texnum->shader); if (texnum->shader->flags & SHADER_NOIMAGE) Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum->shader->name, loadmodel->name); @@ -5871,7 +6325,7 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer) } trans = Hunk_Alloc(sizeof(*trans)*numusableweights); - inf->ofstransforms = (char*)trans - (char*)inf; + inf->ofsswtransforms = (char*)trans - (char*)inf; for (num = 0, vnum = 0; num < numverts; num++) { @@ -5890,7 +6344,7 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer) numweightslist[num]--; } } - inf->numtransforms = vnum; + inf->numswtransforms = vnum; if (firstweightlist) Z_Free(firstweightlist); @@ -5926,7 +6380,7 @@ qboolean Mod_LoadMD5MeshModel(model_t *mod, void *buffer) hunkstart = Hunk_LowMark (); - root = Mod_ParseMD5MeshModel(buffer); + root = Mod_ParseMD5MeshModel(buffer, mod->name); if (root == NULL) { Hunk_FreeToLowMark(hunkstart); @@ -6012,7 +6466,7 @@ qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer) return false; } - root = Mod_ParseMD5MeshModel(file); + root = Mod_ParseMD5MeshModel(file, mod->name); if (root == NULL) { Hunk_FreeToLowMark(hunkstart); diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index 941bb1fb5..73c0f82d7 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -7,8 +7,6 @@ #include #endif -#define MAX_BONES 256 - int HLMod_BoneForName(model_t *mod, char *name); int HLMod_FrameForName(model_t *mod, char *name); @@ -23,8 +21,8 @@ typedef struct { int ofsskins; #endif - qboolean sharesverts; //used with models with two shaders using the same vertex - use last mesh's verts - qboolean sharesbones; //use last mesh's bones (please, never set this on the first mesh!) + int shares_verts; //used with models with two shaders using the same vertex. set to the surface number to inherit from (or itself). + int shares_bones; //use last mesh's bones. set to the surface number to inherit from (or itself). int numverts; @@ -41,8 +39,15 @@ typedef struct { #ifdef SKELETALMODELS int numbones; int ofsbones; - int numtransforms; - int ofstransforms; + int numswtransforms; + int ofsswtransforms; + + int ofs_skel_xyz; + int ofs_skel_norm; + int ofs_skel_svect; + int ofs_skel_tvect; + int ofs_skel_idx; + int ofs_skel_weight; #endif //these exist only in the root mesh. @@ -122,9 +127,8 @@ float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *bu #ifdef SKELETALMODELS void Alias_TransformVerticies(float *bonepose, galisskeletaltransforms_t *weights, int numweights, vecV_t *xyzout, vec3_t *normout); #endif -qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, - entity_t *e, - float alpha, qboolean nolightdir); +qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, entity_t *e, qboolean allowskel); +void Alias_FlushCache(void); void Mod_DoCRC(model_t *mod, char *buffer, int buffersize); diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index 3451f3ae0..2af2301db 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -1405,9 +1405,9 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, wedict_t *ed) up[2] = r[10]; VectorCopy(vel, velocity); VectorCopy(avel, spinvelocity); - Matrix4Q_FromVectors(bodymatrix, forward, left, up, origin); + Matrix4x4_RM_FromVectors(bodymatrix, forward, left, up, origin); Matrix4_Multiply(ed->ode.ode_offsetimatrix, bodymatrix, entitymatrix); - Matrix4Q_ToVectors(entitymatrix, forward, left, up, origin); + Matrix3x4_RM_ToVectors(entitymatrix, forward, left, up, origin); VectorAngles(forward, up, angles); angles[0]*=-1; @@ -1847,7 +1847,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) switch(solid) { case SOLID_BSP: - Matrix4_Identity(ed->ode.ode_offsetmatrix); + Matrix4x4_Identity(ed->ode.ode_offsetmatrix); ed->ode.ode_geom = NULL; if (!model) { @@ -1863,7 +1863,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) return; } - Matrix4Q_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); + Matrix4x4_RM_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); // now create the geom dataID = dGeomTriMeshDataCreate(); dGeomTriMeshDataBuildSingle(dataID, (void*)ed->ode.ode_vertex3f, sizeof(float[3]), ed->ode.ode_numvertices, ed->ode.ode_element3i, ed->ode.ode_numtriangles*3, sizeof(int[3])); @@ -1874,12 +1874,12 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) case SOLID_SLIDEBOX: case SOLID_CORPSE: case SOLID_PHYSICS_BOX: - Matrix4Q_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); + Matrix4x4_RM_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); ed->ode.ode_geom = (void *)dCreateBox(world->ode.ode_space, geomsize[0], geomsize[1], geomsize[2]); dMassSetBoxTotal(&mass, massval, geomsize[0], geomsize[1], geomsize[2]); break; case SOLID_PHYSICS_SPHERE: - Matrix4Q_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); + Matrix4x4_RM_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); ed->ode.ode_geom = (void *)dCreateSphere(world->ode.ode_space, geomsize[0] * 0.5f); dMassSetSphereTotal(&mass, massval, geomsize[0] * 0.5f); break; @@ -1895,11 +1895,11 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) // transform to it memset(capsulerot, 0, sizeof(capsulerot)); if (axisindex == 0) - Matrix4_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 90, 1); + Matrix4x4_CM_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 90, 1); else if (axisindex == 1) - Matrix4_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 90, 0, 0, 1); + Matrix4x4_CM_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 90, 0, 0, 1); else - Matrix4_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 0, 1); + Matrix4x4_CM_ModelMatrix(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 0, 1); radius = geomsize[!axisindex] * 0.5f; // any other axis is the radius length = geomsize[axisindex] - radius*2; // because we want to support more than one axisindex, we have to @@ -1911,7 +1911,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) default: Sys_Error("World_Physics_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid); } - Matrix4Q_Invert_Simple(ed->ode.ode_offsetmatrix, ed->ode.ode_offsetimatrix); + Matrix3x4_InvertTo4x4_Simple(ed->ode.ode_offsetmatrix, ed->ode.ode_offsetimatrix); ed->ode.ode_massbuf = BZ_Malloc(sizeof(dMass)); memcpy(ed->ode.ode_massbuf, &mass, sizeof(dMass)); } @@ -2065,9 +2065,9 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) VectorCopy(avelocity, ed->ode.ode_avelocity); ed->ode.ode_gravity = gravity; - Matrix4Q_FromVectors(entitymatrix, forward, left, up, origin); + Matrix4x4_RM_FromVectors(entitymatrix, forward, left, up, origin); Matrix4_Multiply(ed->ode.ode_offsetmatrix, entitymatrix, bodymatrix); - Matrix4Q_ToVectors(bodymatrix, forward, left, up, origin); + Matrix3x4_RM_ToVectors(bodymatrix, forward, left, up, origin); r[0][0] = forward[0]; r[1][0] = forward[1]; r[2][0] = forward[2]; diff --git a/engine/common/common.c b/engine/common/common.c index 988c3fd06..1491ddbbe 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -92,7 +92,8 @@ cvar_t registered = CVARD("registered","0","Set if quake's pak1.pak is available cvar_t gameversion = CVARFD("gameversion","", CVAR_SERVERINFO, "gamecode version for server browsers"); cvar_t gameversion_min = CVARD("gameversion_min","", "gamecode version for server browsers"); cvar_t gameversion_max = CVARD("gameversion_max","", "gamecode version for server browsers"); -cvar_t com_gamename = CVARD("com_gamename", "", "The game name used for dpmaster queries"); +cvar_t fs_gamename = CVARFD("fs_gamename", "", CVAR_NOSET, "The filesystem is trying to run this game"); +cvar_t com_protocolname = CVARD("com_gamename", "", "The game name used for dpmaster queries"); cvar_t com_modname = CVARD("com_modname", "", "dpmaster information"); cvar_t com_parseutf8 = CVARD("com_parseutf8", "0", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts."); //1 parse. 2 parse, but stop parsing that string if a char was malformed. diff --git a/engine/common/common.h b/engine/common/common.h index 42c767c0b..32fb402de 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -432,6 +432,7 @@ void Info_SetValueForStarKey (char *s, const char *key, const char *value, int m void Info_Print (char *s); void Info_WriteToFile(vfsfile_t *f, char *info, char *commandname, int cvarflags); +void Com_BlocksChecksum (int blocks, void **buffer, int *len, unsigned char *outbuf); unsigned int Com_BlockChecksum (void *buffer, int length); void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf); qbyte COM_BlockSequenceCheckByte (qbyte *base, int length, int sequence, unsigned mapchecksum); diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 345b97c62..3d47c9de0 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -659,8 +659,8 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force) #ifndef CLIENTONLY if (var->flags & CVAR_SERVERINFO) { - char *old = Info_ValueForKey(svs.info, var->name); - if (strcmp(old, value)) //only spam the server if it actually changed +// char *old = Info_ValueForKey(svs.info, var->name); +// if (strcmp(old, value)) //only spam the server if it actually changed { Info_SetValueForKey (svs.info, var->name, value, MAX_SERVERINFO_STRING); SV_SendServerInfoChange(var->name, value); diff --git a/engine/common/fs.c b/engine/common/fs.c index c1f388a27..811cc1ffc 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1665,7 +1665,9 @@ const gamemode_info_t gamemode_info[] = { {"Darkplaces-Rogue", "rogue", "-rogue", {NULL}, NULL, {"id1", "qw", "rogue", "fte"}, "Quake: Dissolution of Eternity"}, {"Nexuiz", "nexuiz", "-nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "ftedata"}, "Nexuiz"}, {"Xonotic", "xonotic", "-xonotic", {"xonotic.exe"}, NEXCFG, {"data", "ftedata"}, "Xonotic"}, - {"DMF", "dmf", "-dmf", {"base/src/progs.src"}, DMFCFG, {"base", }, "DMF"}, + {"DMF", "dmf", "-dmf", {"base/src/progs.src", + "base/qwprogs.dat", + "base/pak0.pak"}, DMFCFG, {"base", }, "DMF"}, //supported commercial mods (some are currently only partially supported) {"FTE-H2MP", "h2mp", "-portals", {"portals/hexen.rc", @@ -1673,12 +1675,14 @@ const gamemode_info_t gamemode_info[] = { {"FTE-Hexen2", "hexen2", "-hexen2", {"data1/pak0.pak"}, HEX2CFG,{"data1", "fteh2"}, "Hexen II"}, {"FTE-Quake2", "q2", "-q2", {"baseq2/pak0.pak"}, NULL, {"baseq2", "fteq2"}, "Quake II"}, {"FTE-Quake3", "q3", "-q3", {"baseq3/pak0.pk3"}, Q3CFG, {"baseq3", "fteq3"}, "Quake III Arena"}, + + //the rest are not officially supported. {"FTE-Quake4", "q4", "-q4", {"q4base/pak00.pk4"}, NULL, {"q4base", "fteq4"}, "Quake 4"}, {"FTE-EnemyTerritory", "et", "-et", {"etmain/pak0.pk3"}, NULL, {"etmain", "fteet"}, "Wolfenstein - Enemy Territory"}, {"FTE-JK2", "jk2", "-jk2", {"base/assets0.pk3"}, NULL, {"base", "fte"}, "Jedi Knight II: Jedi Outcast"}, - {"FTE-HalfLife", "hl", "-halflife", {"valve/liblist.gam"} ,NULL, {"valve", "ftehl"}, "Half-Life"}, + {"FTE-HalfLife", "hl", "-halflife", {"valve/liblist.gam"}, NULL, {"valve", "ftehl"}, "Half-Life"}, {NULL} }; @@ -2145,7 +2149,8 @@ void FS_StartupWithGame(int gamenum) LibZ_Init(); #endif - Cvar_Set(&com_gamename, gamemode_info[gamenum].protocolname); + Cvar_Set(&com_protocolname, gamemode_info[gamenum].protocolname); + Cvar_ForceSet(&fs_gamename, gamemode_info[gamenum].poshname); // // start up with id1 by default @@ -2258,8 +2263,9 @@ void COM_InitFilesystem (void) - Cvar_Register(&com_gamename, "evil hacks"); - Cvar_Register(&com_modname, "evil hacks"); + Cvar_Register(&fs_gamename, "FS"); + Cvar_Register(&com_protocolname, "Server Info"); + Cvar_Register(&com_modname, "Server Info"); //identify the game from a telling file for (i = 0; gamemode_info[i].argname && gamenum==-1; i++) { diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 3fdc54f1e..c7da4221d 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -2230,7 +2230,7 @@ qboolean CModQ3_LoadFaces (lump_t *l) out->patch_cp[1] = LittleLong ( in->patchheight ); } - loadmodel->numsurfaces = i;\ + loadmodel->numsurfaces = i; return true; } @@ -2507,9 +2507,7 @@ qboolean CModQ3_LoadRFaces (lump_t *l) out->light_t = LittleLong(in->lightmap_y); out->extents[0] = (LittleLong(in->lightmap_width)-1)<<4; out->extents[1] = (LittleLong(in->lightmap_height)-1)<<4; - out->samples = loadmodel->lightdata + 3*(out->light_s + out->light_t*128 + out->lightmaptexturenum*128*128); - if (out->lightmaptexturenum<0) - out->samples=NULL; + out->samples=NULL; fv = LittleLong(in->firstvertex); { @@ -2628,8 +2626,8 @@ qboolean CModQ3_LoadRFaces (lump_t *l) Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[2]); Vector4Copy(mesh->colors4b_array[0], mesh->colors4b_array[3]); } - if (out->mesh->numindexes == 0) - Con_Printf("foo\n"); + if (out->mesh->numindexes == 0) + Con_Printf("foo\n"); } Mod_NormaliseTextureVectors(map_normals_array, map_svector_array, map_tvector_array, numvertexes); @@ -2677,9 +2675,7 @@ qboolean CModRBSP_LoadRFaces (lump_t *l) out->light_t = in->lightmap_offs[0][0]; out->extents[0] = (in->lightmap_width-1)<<4; out->extents[1] = (in->lightmap_height-1)<<4; - out->samples = loadmodel->lightdata + 3*(out->light_s + out->light_t*128 + out->lightmaptexturenum*128*128); - if (out->lightmaptexturenum<0) - out->samples=NULL; + out->samples=NULL; fv = LittleLong(in->firstvertex); { diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 83ef6a7f1..0b03ceedc 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -844,7 +844,7 @@ void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) #endif //This function is GL stylie (use as 2nd arg to ML_MultMatrix4). -float *Matrix4_NewRotation(float a, float x, float y, float z) +float *Matrix4x4_CM_NewRotation(float a, float x, float y, float z) { static float ret[16]; float c = cos(a* M_PI / 180.0); @@ -873,7 +873,7 @@ float *Matrix4_NewRotation(float a, float x, float y, float z) } //This function is GL stylie (use as 2nd arg to ML_MultMatrix4). -float *Matrix4_NewTranslation(float x, float y, float z) +float *Matrix4x4_CM_NewTranslation(float x, float y, float z) { static float ret[16]; ret[0] = 1; @@ -923,7 +923,7 @@ void Matrix4_Multiply(const float *a, const float *b, float *out) } //transform 4d vector by a 4d matrix. -void Matrix4_Transform4(const float *matrix, const float *vector, float *product) +void Matrix4x4_CM_Transform4(const float *matrix, const float *vector, float *product) { product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12]*vector[3]; product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]*vector[3]; @@ -931,14 +931,14 @@ void Matrix4_Transform4(const float *matrix, const float *vector, float *product product[3] = matrix[3]*vector[0] + matrix[7]*vector[1] + matrix[11]*vector[2] + matrix[15]*vector[3]; } -void Matrix4_Transform3(const float *matrix, const float *vector, float *product) +void Matrix4x4_CM_Transform3(const float *matrix, const float *vector, float *product) { product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12]; product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]; product[2] = matrix[2]*vector[0] + matrix[6]*vector[1] + matrix[10]*vector[2] + matrix[14]; } -void Matrix4_ModelViewMatrix(float *modelview, const vec3_t viewangles, const vec3_t vieworg) +void Matrix4x4_CM_ModelViewMatrix(float *modelview, const vec3_t viewangles, const vec3_t vieworg) { float tempmat[16]; //load identity. @@ -949,8 +949,8 @@ void Matrix4_ModelViewMatrix(float *modelview, const vec3_t viewangles, const ve modelview[10] = 1; modelview[15] = 1; - Matrix4_Multiply(modelview, Matrix4_NewRotation(-90, 1, 0, 0), tempmat); // put Z going up - Matrix4_Multiply(tempmat, Matrix4_NewRotation(90, 0, 0, 1), modelview); // put Z going up + Matrix4_Multiply(modelview, Matrix4_CM_NewRotation(-90, 1, 0, 0), tempmat); // put Z going up + Matrix4_Multiply(tempmat, Matrix4_CM_NewRotation(90, 0, 0, 1), modelview); // put Z going up #else //use this lame wierd and crazy identity matrix.. modelview[2] = -1; @@ -961,19 +961,37 @@ void Matrix4_ModelViewMatrix(float *modelview, const vec3_t viewangles, const ve //figure out the current modelview matrix //I would if some of these, but then I'd still need a couple of copys - Matrix4_Multiply(modelview, Matrix4_NewRotation(-viewangles[2], 1, 0, 0), tempmat); - Matrix4_Multiply(tempmat, Matrix4_NewRotation(-viewangles[0], 0, 1, 0), modelview); - Matrix4_Multiply(modelview, Matrix4_NewRotation(-viewangles[1], 0, 0, 1), tempmat); + Matrix4_Multiply(modelview, Matrix4x4_CM_NewRotation(-viewangles[2], 1, 0, 0), tempmat); + Matrix4_Multiply(tempmat, Matrix4x4_CM_NewRotation(-viewangles[0], 0, 1, 0), modelview); + Matrix4_Multiply(modelview, Matrix4x4_CM_NewRotation(-viewangles[1], 0, 0, 1), tempmat); - Matrix4_Multiply(tempmat, Matrix4_NewTranslation(-vieworg[0], -vieworg[1], -vieworg[2]), modelview); // put Z going up + Matrix4_Multiply(tempmat, Matrix4x4_CM_NewTranslation(-vieworg[0], -vieworg[1], -vieworg[2]), modelview); // put Z going up } -void Matrix4_CreateTranslate (float *out, float x, float y, float z) +void Matrix4x4_CM_CreateTranslate (float *out, float x, float y, float z) { - memcpy(out, Matrix4_NewTranslation(x, y, z), 16*sizeof(float)); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + + out[12] = x; + out[13] = y; + out[14] = z; + out[15] = 1; } -void Matrix4Q_CreateTranslate (float *out, float x, float y, float z) +void Matrix4x4_RM_CreateTranslate (float *out, float x, float y, float z) { out[0] = 1; out[4] = 0; @@ -996,7 +1014,7 @@ void Matrix4Q_CreateTranslate (float *out, float x, float y, float z) out[15] = 1; } -void Matrix4_ModelViewMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg) +void Matrix4x4_CM_ModelViewMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg) { float tempmat[16]; @@ -1017,11 +1035,11 @@ void Matrix4_ModelViewMatrixFromAxis(float *modelview, const vec3_t pn, const ve tempmat[14] = 0; tempmat[15] = 1; - Matrix4_Multiply(tempmat, Matrix4_NewTranslation(-vieworg[0], -vieworg[1], -vieworg[2]), modelview); // put Z going up + Matrix4_Multiply(tempmat, Matrix4x4_CM_NewTranslation(-vieworg[0], -vieworg[1], -vieworg[2]), modelview); // put Z going up } -void Matrix4Q_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]) +void Matrix3x4_RM_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]) { vx[0] = in[0]; vx[1] = in[4]; @@ -1040,7 +1058,7 @@ void Matrix4Q_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], t [2] = in[11]; } -void Matrix4Q_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]) +void Matrix4x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]) { out[0] = vx[0]; out[1] = vy[0]; @@ -1060,7 +1078,23 @@ void Matrix4Q_FromVectors(float *out, const float vx[3], const float vy[3], cons out[15] = 1.0f; } -void Matrix4_ModelMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg) +void Matrix3x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]) +{ + out[0] = vx[0]; + out[1] = vy[0]; + out[2] = vz[0]; + out[3] = t[0]; + out[4] = vx[1]; + out[5] = vy[1]; + out[6] = vz[1]; + out[7] = t[1]; + out[8] = vx[2]; + out[9] = vy[2]; + out[10] = vz[2]; + out[11] = t[2]; +} + +void Matrix4x4_CM_ModelMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg) { float tempmat[16]; @@ -1081,10 +1115,10 @@ void Matrix4_ModelMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t tempmat[14] = 0; tempmat[15] = 1; - Matrix4_Multiply(Matrix4_NewTranslation(vieworg[0], vieworg[1], vieworg[2]), tempmat, modelview); // put Z going up + Matrix4_Multiply(Matrix4x4_CM_NewTranslation(vieworg[0], vieworg[1], vieworg[2]), tempmat, modelview); // put Z going up } -void Matrix4_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitch, vec_t yaw, vec_t roll, vec_t scale) +void Matrix4x4_CM_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitch, vec_t yaw, vec_t roll, vec_t scale) { float tempmat[16]; //load identity. @@ -1095,8 +1129,8 @@ void Matrix4_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitc modelview[10] = 1; modelview[15] = 1; - Matrix4_Multiply(modelview, Matrix4_NewRotation(-90, 1, 0, 0), tempmat); // put Z going up - Matrix4_Multiply(tempmat, Matrix4_NewRotation(90, 0, 0, 1), modelview); // put Z going up + Matrix4_Multiply(modelview, Matrix4x4_CM_NewRotation(-90, 1, 0, 0), tempmat); // put Z going up + Matrix4_Multiply(tempmat, Matrix4x4_CM_NewRotation(90, 0, 0, 1), modelview); // put Z going up #else //use this lame wierd and crazy identity matrix.. modelview[2] = -1; @@ -1107,14 +1141,14 @@ void Matrix4_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitc //figure out the current modelview matrix //I would if some of these, but then I'd still need a couple of copys - Matrix4_Multiply(modelview, Matrix4_NewRotation(-roll, 1, 0, 0), tempmat); - Matrix4_Multiply(tempmat, Matrix4_NewRotation(-pitch, 0, 1, 0), modelview); - Matrix4_Multiply(modelview, Matrix4_NewRotation(-yaw, 0, 0, 1), tempmat); + Matrix4_Multiply(modelview, Matrix4x4_CM_NewRotation(-roll, 1, 0, 0), tempmat); + Matrix4_Multiply(tempmat, Matrix4x4_CM_NewRotation(-pitch, 0, 1, 0), modelview); + Matrix4_Multiply(modelview, Matrix4x4_CM_NewRotation(-yaw, 0, 0, 1), tempmat); - Matrix4_Multiply(tempmat, Matrix4_NewTranslation(x, y, z), modelview); + Matrix4_Multiply(tempmat, Matrix4x4_CM_NewTranslation(x, y, z), modelview); } -void Matrix4_Identity(float *outm) +void Matrix4x4_Identity(float *outm) { outm[ 0] = 1; outm[ 1] = 0; @@ -1134,7 +1168,7 @@ void Matrix4_Identity(float *outm) outm[15] = 1; } -void Matrix4_Projection_Far(float *proj, float fovx, float fovy, float neard, float fard) +void Matrix4x4_CM_Projection_Far(float *proj, float fovx, float fovy, float neard, float fard) { double xmin, xmax, ymin, ymax; @@ -1174,7 +1208,7 @@ void Matrix4_Projection_Far(float *proj, float fovx, float fovy, float neard, fl proj[15] = 0; } -void Matrix4_Projection_Inf(float *proj, float fovx, float fovy, float neard) +void Matrix4x4_CM_Projection_Inf(float *proj, float fovx, float fovy, float neard) { float xmin, xmax, ymin, ymax; float nudge = 1; @@ -1214,7 +1248,7 @@ void Matrix4_Projection_Inf(float *proj, float fovx, float fovy, float neard) proj[11] = -1; proj[15] = 0; } -void Matrix4_Projection2(float *proj, float fovx, float fovy, float neard) +void Matrix4x4_CM_Projection2(float *proj, float fovx, float fovy, float neard) { float xmin, xmax, ymin, ymax; float nudge = 1; @@ -1247,7 +1281,7 @@ void Matrix4_Projection2(float *proj, float fovx, float fovy, float neard) proj[15] = 0; } -void Matrix4_Orthographic(float *proj, float xmin, float xmax, float ymin, float ymax, +void Matrix4x4_CM_Orthographic(float *proj, float xmin, float xmax, float ymin, float ymax, float znear, float zfar) { proj[0] = 2/(xmax-xmin); @@ -1270,7 +1304,7 @@ void Matrix4_Orthographic(float *proj, float xmin, float xmax, float ymin, float proj[11] = 0; proj[15] = 1; } -void Matrix4_OrthographicD3D(float *proj, float xmin, float xmax, float ymax, float ymin, +void Matrix4x4_CM_OrthographicD3D(float *proj, float xmin, float xmax, float ymax, float ymin, float znear, float zfar) { proj[0] = 2/(xmax-xmin); @@ -1472,7 +1506,7 @@ qboolean Matrix4_Invert(const float *m, float *out) #undef SWAP_ROWS } -void Matrix3_Invert_Simple (const vec3_t in1[3], vec3_t out[3]) +void Matrix3x3_RM_Invert_Simple (const vec3_t in1[3], vec3_t out[3]) { // we only support uniform scaling, so assume the first row is enough // (note the lack of sqrt here, because we're trying to undo the scaling, @@ -1503,7 +1537,7 @@ void Matrix3_Invert_Simple (const vec3_t in1[3], vec3_t out[3]) out[2][2] = in1[2][2] * scale; } -void Matrix4Q_Invert_Simple (const float *in1, float *out) +void Matrix3x4_Invert_Simple (const float *in1, float *out) { // we only support uniform scaling, so assume the first row is enough // (note the lack of sqrt here, because we're trying to undo the scaling, @@ -1531,29 +1565,19 @@ void Matrix4Q_Invert_Simple (const float *in1, float *out) out[9] = in1[6] * scale; out[10] = in1[10] * scale; -#ifdef MATRIX4x4_OPENGLORIENTATION - // invert the translate - out->m[12] = -(in1[12] * out[0] + in1[13] * out[4] + in1[14] * out[8]); - out->m[13] = -(in1[12] * out[1] + in1[13] * out[5] + in1[14] * out[9]); - out->m[14] = -(in1[12] * out[2] + in1[13] * out[6] + in1[14] * out[10]); - - // don't know if there's anything worth doing here - out[3] = 0; - out[7] = 0; - out[11] = 0; - out[15] = 1; -#else // invert the translate out[3] = -(in1[3] * out[0] + in1[7] * out[1] + in1[11] * out[2]); out[7] = -(in1[3] * out[4] + in1[7] * out[5] + in1[11] * out[6]); out[11] = -(in1[3] * out[8] + in1[7] * out[9] + in1[11] * out[10]); +} - // don't know if there's anything worth doing here +void Matrix3x4_InvertTo4x4_Simple (const float *in1, float *out) +{ + Matrix3x4_Invert_Simple(in1, out); out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; -#endif } void Matrix3x4_InvertTo3x3(float *in, float *result) @@ -1590,14 +1614,14 @@ void Matrix3x4_InvertTo3x3(float *in, float *result) //screen->3d -void Matrix4_UnProject(const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy) +void Matrix4x4_CM_UnProject(const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy) { float modelview[16]; float proj[16]; float tempm[16]; - Matrix4_ModelViewMatrix(modelview, viewangles, vieworg); - Matrix4_Projection_Inf(proj, fovx, fovy, 4); + Matrix4x4_CM_ModelViewMatrix(modelview, viewangles, vieworg); + Matrix4x4_CM_Projection_Inf(proj, fovx, fovy, 4); Matrix4_Multiply(proj, modelview, tempm); Matrix4_Invert(tempm, proj); @@ -1613,7 +1637,7 @@ void Matrix4_UnProject(const vec3_t in, vec3_t out, const vec3_t viewangles, con if (v[2] >= 1) v[2] = 0.999999; - Matrix4_Transform4(proj, v, tempv); + Matrix4x4_CM_Transform4(proj, v, tempv); out[0] = tempv[0]/tempv[3]; out[1] = tempv[1]/tempv[3]; @@ -1624,13 +1648,13 @@ void Matrix4_UnProject(const vec3_t in, vec3_t out, const vec3_t viewangles, con //returns fractions of screen. //uses GL style rotations and translations and stuff. //3d -> screen (fixme: offscreen return values needed) -void Matrix4_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy) +void Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy) { float modelview[16]; float proj[16]; - Matrix4_ModelViewMatrix(modelview, viewangles, vieworg); - Matrix4_Projection_Inf(proj, fovx, fovy, 4); + Matrix4x4_CM_ModelViewMatrix(modelview, viewangles, vieworg); + Matrix4x4_CM_Projection_Inf(proj, fovx, fovy, 4); { float v[4], tempv[4]; @@ -1639,8 +1663,8 @@ void Matrix4_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, cons v[2] = in[2]; v[3] = 1; - Matrix4_Transform4(modelview, v, tempv); - Matrix4_Transform4(proj, tempv, v); + Matrix4x4_CM_Transform4(modelview, v, tempv); + Matrix4x4_CM_Transform4(proj, tempv, v); v[0] /= v[3]; v[1] /= v[3]; diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 38d4b4abb..c636a5ecf 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -129,34 +129,46 @@ vec_t Length (vec3_t v); void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up); float Q_rsqrt(float number); -//used for crosshair stuff. +/* +_CM means column major. +_RM means row major +Note that openGL is column-major. +Logical C code uses row-major. +mat3x4 is always row-major (and functions can accept many RM mat4x4) +*/ + void Matrix3_Multiply (vec3_t *in1, vec3_t *in2, vec3_t *out); -void Matrix4_Identity(float *outm); +void Matrix4x4_Identity(float *outm); qboolean Matrix4_Invert(const float *m, float *out); -void Matrix4Q_Invert_Simple (const float *in1, float *out); -void Matrix3_Invert_Simple(const vec3_t in[3], vec3_t out[3]); -void Matrix4_CreateTranslate (float *out, float x, float y, float z); -void Matrix4Q_CreateTranslate (float *out, float x, float y, float z); -void Matrix4_ModelMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); -void Matrix4_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitch, vec_t yaw, vec_t roll, vec_t scale); -void Matrix4_ModelViewMatrix (float *modelview, const vec3_t viewangles, const vec3_t vieworg); -void Matrix4_ModelViewMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); +void Matrix3x4_Invert_Simple (const float *in1, float *out); +void Matrix3x4_InvertTo4x4_Simple (const float *in1, float *out); +void Matrix3x3_RM_Invert_Simple(const vec3_t in[3], vec3_t out[3]); +void Matrix4x4_RM_CreateTranslate (float *out, float x, float y, float z); +void Matrix4x4_CM_CreateTranslate (float *out, float x, float y, float z); +void Matrix4x4_CM_ModelMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); +void Matrix4x4_CM_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitch, vec_t yaw, vec_t roll, vec_t scale); +void Matrix4x4_CM_ModelViewMatrix (float *modelview, const vec3_t viewangles, const vec3_t vieworg); +void Matrix4x4_CM_ModelViewMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); void Matrix4_CreateFromQuakeEntity (float *matrix, float x, float y, float z, float pitch, float yaw, float roll, float scale); void Matrix4_Multiply (const float *a, const float *b, float *out); -void Matrix4_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); -void Matrix4_Transform3 (const float *matrix, const float *vector, float *product); -void Matrix4_Transform4 (const float *matrix, const float *vector, float *product); -void Matrix4_UnProject (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); -void Matrix4Q_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]); -void Matrix4Q_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]); +void Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); +void Matrix4x4_CM_Transform3 (const float *matrix, const float *vector, float *product); +void Matrix4x4_CM_Transform4 (const float *matrix, const float *vector, float *product); +void Matrix4x4_CM_UnProject (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); +void Matrix3x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]); +void Matrix4x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]); +void Matrix3x4_RM_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]); + +float *Matrix4x4_CM_NewRotation(float a, float x, float y, float z); +float *Matrix4x4_CM_NewTranslation(float x, float y, float z); #define AngleVectorsFLU(a,f,l,u) do{AngleVectors(a,f,l,u);VectorNegate(l,l);}while(0) //projection matricies of different types... gesh -void Matrix4_Orthographic (float *proj, float xmin, float xmax, float ymax, float ymin, float znear, float zfar); -void Matrix4_Projection_Far(float *proj, float fovx, float fovy, float neard, float fard); -void Matrix4_Projection2 (float *proj, float fovx, float fovy, float neard); -void Matrix4_Projection_Inf(float *proj, float fovx, float fovy, float neard); +void Matrix4x4_CM_Orthographic (float *proj, float xmin, float xmax, float ymax, float ymin, float znear, float zfar); +void Matrix4x4_CM_Projection_Far(float *proj, float fovx, float fovy, float neard, float fard); +void Matrix4x4_CM_Projection2 (float *proj, float fovx, float fovy, float neard); +void Matrix4x4_CM_Projection_Inf(float *proj, float fovx, float fovy, float neard); fixed16_t Mul16_30 (fixed16_t multiplier, fixed16_t multiplicand); int Q_log2 (int val); diff --git a/engine/common/md4.c b/engine/common/md4.c index 337b8865a..0e08ff9cd 100644 --- a/engine/common/md4.c +++ b/engine/common/md4.c @@ -300,3 +300,16 @@ void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf) MD4Update (&ctx, (unsigned char *)buffer, len); MD4Final ( outbuf, &ctx); } + + +void Com_BlocksChecksum (int blocks, void **buffer, int *len, unsigned char *outbuf) +{ + MD4_CTX ctx; + + MD4Init (&ctx); + while(blocks --> 0) + { + MD4Update (&ctx, (unsigned char *)*buffer++, *len++); + } + MD4Final (outbuf, &ctx); +} diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 06858ac4f..d6bdcda6b 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -99,6 +99,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PROTOCOL_VERSION_HUFFMAN (('H'<<0) + ('U'<<8) + ('F'<<16) + ('F' << 24)) //packet compression #define PROTOCOL_VERSION_VARLENGTH (('v'<<0) + ('l'<<8) + ('e'<<16) + ('n' << 24)) //packet compression +#define PROTOCOL_INFO_GUID (('G'<<0) + ('U'<<8) + ('I'<<16) + ('D' << 24)) //globally 'unique' client id info. + #define PROTOCOL_VERSION_QW 28 #define PROTOCOL_VERSION_Q2_MIN 31 #define PROTOCOL_VERSION_Q2 34 diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 1e509914d..31f36aebe 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -444,7 +444,7 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3] { vec3_t iaxis[3]; vec3_t norm; - Matrix3_Invert_Simple((void *)axis, iaxis); + Matrix3x3_RM_Invert_Simple((void *)axis, iaxis); VectorCopy(trace->plane.normal, norm); trace->plane.normal[0] = DotProduct(norm, iaxis[0]); trace->plane.normal[1] = DotProduct(norm, iaxis[1]); diff --git a/engine/common/qvm.c b/engine/common/qvm.c index d81456639..e1178675d 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -1061,6 +1061,16 @@ void *VM_MemoryBase(vm_t *vm) return NULL; } } +quintptr_t VM_MemoryMask(vm_t *vm) +{ + switch(vm->type) + { + case VM_BYTECODE: + return ((qvm_t*)vm->hInst)->ds_mask; + default: + return ~(quintptr_t)0; + } +} /*returns true if we're running a 32bit vm on a 64bit host (in case we need workarounds)*/ qboolean VM_NonNative(vm_t *vm) diff --git a/engine/common/sys.h b/engine/common/sys.h index 758cb590f..e0b220d17 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -63,6 +63,7 @@ qboolean LibPNG_Init(void); unsigned int Sys_Milliseconds (void); double Sys_DoubleTime (void); +qboolean Sys_RandomBytes(qbyte *string, int len); char *Sys_ConsoleInput (void); diff --git a/engine/common/tlout.h b/engine/common/tlout.h index 8119ccc76..fcb50b11e 100644 --- a/engine/common/tlout.h +++ b/engine/common/tlout.h @@ -65,7 +65,7 @@ "STL_VOTE \"%s casts a vote for '%s'\\n\"\n" "STL_SPEEDCHEATKICKED \"%s was kicked for speedcheating (%s)\\n\"\n" "STL_SPEEDCHEATPOSSIBLE \"Speed cheat possibility, analyzing:\\n %d %.1f %d for: %s\\n\"\n" -"STL_INITED \"======== QuakeWorld Initialized ========\\n\"\n" +"STL_INITED \"======== %s Initialized ========\\n\"\n" "STL_BACKBUFSET \"WARNING %s: [SV_New] Back buffered (%d0, clearing)\\n\"\n" "STL_MESSAGEOVERFLOW \"WARNING: backbuf [%d] reliable overflow for %s\\n\"\n" "STL_BUILDINGPHS \"Building PHS...\\n\"\n" diff --git a/engine/common/translate.c b/engine/common/translate.c index 5f65f619b..c6f011a7f 100644 --- a/engine/common/translate.c +++ b/engine/common/translate.c @@ -74,7 +74,7 @@ static char *defaultlanguagetext = "STL_VOTE \"%s casts a vote for '%s'\\n\"\n" "STL_SPEEDCHEATKICKED \"%s was kicked for speedcheating (%s)\\n\"\n" "STL_SPEEDCHEATPOSSIBLE \"Speed cheat possibility, analyzing:\\n %d %.1f %d for: %s\\n\"\n" -"STL_INITED \"======== FTE QuakeWorld Initialized ========\\n\"\n" +"STL_INITED \"======== %s Initialized ========\\n\"\n" "STL_BACKBUFSET \"WARNING %s: [SV_New] Back buffered (%d0, clearing)\\n\"\n" "STL_MESSAGEOVERFLOW \"WARNING: backbuf [%d] reliable overflow for %s\\n\"\n" "STL_BUILDINGPHS \"Building PHS...\\n\"\n" @@ -230,7 +230,7 @@ static char *defaultlanguagetext = "TLC_HOSTFATALERROR \"Host_Error: %s\\n\"\n" "TLC_CONFIGCFG_WRITEFAILED \"Couldn't write config.cfg.\\n\"\n" "TLC_HOSTSPEEDSOUTPUT \"%3i tot %3i server %3i gfx %3i snd\\n\"\n" -"TLC_QUAKEWORLD_INITED \"^Ue080^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081 QuakeWorld Initialized ^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue082\\n\"\n" +"TLC_QUAKEWORLD_INITED \"^Ue080^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081 %s Initialized ^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue082\\n\"\n" "TLC_DEDICATEDCANNOTCONNECT \"Connect ignored - dedicated. set a renderer first\\n\"\n" "TLC_Q2CONLESSPACKET_UNKNOWN \"unknown connectionless packet for q2: %s\\n\"\n" "TL_NORELATIVEPATHS \"Refusing to download a path with ..\\n\"\n" diff --git a/engine/common/vm.h b/engine/common/vm.h index c73e02e89..35d299ad5 100644 --- a/engine/common/vm.h +++ b/engine/common/vm.h @@ -59,6 +59,7 @@ qboolean VM_Restart(vm_t *vm); qintptr_t VARGS VM_Call(vm_t *vm, qintptr_t instruction, ...); qboolean VM_NonNative(vm_t *vm); void *VM_MemoryBase(vm_t *vm); +quintptr_t VM_MemoryMask(vm_t *vm); diff --git a/engine/common/world.h b/engine/common/world.h index ce024b2aa..7a84a0472 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -91,7 +91,7 @@ typedef struct q2trace_s #define MOVE_HITMODEL 4 #define MOVE_RESERVED 8 //so we are less likly to get into tricky situations when we want to steal annother future DP extension. #define MOVE_TRIGGERS 16 //triggers must be marked with FINDABLE_NONSOLID (an alternative to solid-corpse) -#define MOVE_EVERYTHING 32 //doesn't use the area grid stuff, and can return triggers and non-solid items if they're marked with FINDABLE_NONSOLID +#define MOVE_EVERYTHING 32 //can return triggers and non-solid items if they're marked with FINDABLE_NONSOLID (works even if the items are not properly linked) #define MOVE_LAGGED 64 //trace touches current last-known-state, instead of actual ents (just affects players for now) typedef struct areanode_s diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 0a7adc3c0..7900d1059 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -1,4 +1,5 @@ #include "quakedef.h" +#include "glquake.h" #ifdef D3DQUAKE #include "shader.h" #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) @@ -780,7 +781,7 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, b } else { - R_LightArraysByte_BGR(mesh->xyz_array, dst, cnt, mesh->normals_array); + R_LightArraysByte_BGR(shaderstate.curentity , mesh->xyz_array, dst, cnt, mesh->normals_array); } break; case RGB_GEN_WAVE: @@ -1979,7 +1980,6 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod) if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum>=0) { - float *Matrix4_NewRotation(float a, float x, float y, float z); /*FIXME: no bob*/ float iv[16]; Matrix4_Invert(r_refdef.m_view, iv); @@ -2438,6 +2438,8 @@ void D3DBE_DrawWorld (qbyte *vis) RSpeedEnd(RSPEED_DRAWENTITIES); } + GLR_RenderDlights (); + BE_RotateForEntity(&r_worldentity, NULL); } diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index 2233c9e61..080a51ac3 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -1042,6 +1042,7 @@ UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" CharacterSet="2" + WholeProgramOptimization="1" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -29524,194 +29716,6 @@ /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 7eb666b0d..43000aefe 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -23,8 +23,6 @@ #include #endif -#define MAX_BONES 256 - #include "com_mesh.h" //FIXME @@ -186,7 +184,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, if (e->skinnum >= 100 && e->skinnum < 110) { shader_t *s; - s = R_RegisterSkin(va("gfx/skin%d.lmp", e->skinnum)); + s = R_RegisterSkin(va("gfx/skin%d.lmp", e->skinnum), NULL); if (!TEXVALID(s->defaulttextures.base)) s->defaulttextures.base = R_LoadHiResTexture(va("gfx/skin%d.lmp", e->skinnum), NULL, 0); s->defaulttextures.shader = s; @@ -306,7 +304,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, cm->texnum.base = r_nulltex; cm->texnum.loweroverlay = r_nulltex; cm->texnum.upperoverlay = r_nulltex; - cm->texnum.shader = texnums?texnums->shader:R_RegisterSkin(skinname); + cm->texnum.shader = texnums?texnums->shader:R_RegisterSkin(skinname, NULL); if (!texnums) { //load just the skin @@ -935,7 +933,7 @@ void R_GAlias_DrawBatch(batch_t *batch) { if (batch->surf_first == surfnum) { - needrecolour = Alias_GAliasBuildMesh(&mesh, inf, e, e->shaderRGBAf[3], nolightdir); + needrecolour = Alias_GAliasBuildMesh(&mesh, inf, surfnum, e, true); batch->mesh = &meshl; return; } @@ -1321,6 +1319,7 @@ void R_DrawGAliasShadowVolume(entity_t *e, vec3_t lightpos, float radius) galiasinfo_t *inf; mesh_t mesh; vec3_t lightorg; + int surfnum = 0; if (clmodel->engineflags & (MDLF_FLAME | MDLF_BOLT)) return; @@ -1342,7 +1341,7 @@ void R_DrawGAliasShadowVolume(entity_t *e, vec3_t lightpos, float radius) { if (inf->ofs_trineighbours) { - Alias_GAliasBuildMesh(&mesh, inf, e, 1, true); + Alias_GAliasBuildMesh(&mesh, inf, surfnum, e, false); R_CalcFacing(&mesh, lightorg); R_ProjectShadowVolume(&mesh, lightorg); R_DrawShadowVolume(&mesh); @@ -1352,6 +1351,8 @@ void R_DrawGAliasShadowVolume(entity_t *e, vec3_t lightpos, float radius) inf = (galiasinfo_t*)((char *)inf + inf->nextsurf); else inf = NULL; + + surfnum++; } } #endif @@ -1904,6 +1905,8 @@ void BE_GenModelBatches(batch_t **batches) if (!r_drawentities.ival) return; + Alias_FlushCache(); + #if defined(TERRAIN) if (cl.worldmodel && cl.worldmodel->type == mod_heightmap) GL_DrawHeightmapModel(batches, &r_worldentity); diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 7c7e65b29..4fcaaa770 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -248,6 +248,7 @@ static const char LIGHTPASS_SHADER[] = "\ !!permu SPECULAR\n\ !!permu FULLBRIGHT\n\ !!permu OFFSETMAPPING\n\ + !!permu SKELETAL\n\ #define LIGHTPASS\n\ %s\n\ }\n\ @@ -640,7 +641,7 @@ static void BE_EnableShaderAttributes(unsigned int newm) unsigned int i; if (newm == shaderstate.sha_attr) return; - for (i = 0; i < 8; i++) + for (i = 0; i < 10; i++) { #ifndef FORCESTATE if ((newm^shaderstate.sha_attr) & (1u<xyz_array, dst, cnt, mesh->normals_array); + R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array); } break; case RGB_GEN_WAVE: @@ -2366,6 +2369,14 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned GL_SelectVBO(shaderstate.sourcevbo->vbotvector); qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->tvector); return 1u<handle[perm]; + case SP_ATTR_BONENUMS: + GL_SelectVBO(shaderstate.sourcevbo->vbobonenums); + qglVertexAttribPointer(p->handle[perm], 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(byte_vec4_t), shaderstate.sourcevbo->bonenums); + return 1u<handle[perm]; + case SP_ATTR_BONEWEIGHTS: + GL_SelectVBO(shaderstate.sourcevbo->vboboneweights); + qglVertexAttribPointer(p->handle[perm], 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->boneweights); + return 1u<handle[perm]; case SP_VIEWMATRIX: qglUniformMatrix4fvARB(p->handle[perm], 1, false, r_refdef.m_view); @@ -2383,7 +2394,7 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned case SP_ENTMATRIX: { float m16[16]; - Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); + Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); /* VectorCopy(shaderstate.curentity->axis[0], m16+0); m16[3] = 0; VectorCopy(shaderstate.curentity->axis[1], m16+1); @@ -2396,7 +2407,11 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned qglUniformMatrix4fvARB(p->handle[perm], 1, false, m16); } break; - + case SP_ENTBONEMATRICIES: + { + qglUniformMatrix3x4fv(p->handle[perm], shaderstate.sourcevbo->numbones, false, shaderstate.sourcevbo->bones); + } + break; case SP_ENTCOLOURS: qglUniform4fvARB(p->handle[perm], 1, (GLfloat*)shaderstate.curentity->shaderRGBAf); @@ -2457,8 +2472,8 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned #endif // vec3_t t1; vec3_t t2; - Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); - Matrix4_Transform3(m16, r_origin, t2); + Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); + Matrix4x4_CM_Transform3(m16, r_origin, t2); // VectorSubtract(r_origin, shaderstate.curentity->origin, t1); // Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2); qglUniform3fvARB(p->handle[perm], 1, t2); @@ -2475,9 +2490,9 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned vec3_t t2; qboolean Matrix4_Invert(const float *m, float *out); - Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); + Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); Matrix4_Invert(m16, inv); - Matrix4_Transform3(inv, shaderstate.lightorg, t2); + Matrix4x4_CM_Transform3(inv, shaderstate.lightorg, t2); // VectorSubtract(shaderstate.lightorg, shaderstate.curentity->origin, t1); // Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2); qglUniform3fvARB(p->handle[perm], 1, t2); @@ -2538,6 +2553,13 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas int perm; perm = 0; + if (shaderstate.sourcevbo->numbones) + { + if (p->handle[perm|PERMUTATION_SKELETAL].glsl) + perm |= PERMUTATION_SKELETAL; + else + return; + } if (TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_BUMPMAP].glsl) perm |= PERMUTATION_BUMPMAP; if (TEXVALID(shaderstate.curtexnums->specular) && p->handle[perm|PERMUTATION_SPECULAR].glsl) @@ -3001,6 +3023,10 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ shaderstate.dummyvbo.tvector = m->tnormals_array; shaderstate.dummyvbo.colours4f = m->colors4f_array; shaderstate.dummyvbo.colours4ub = m->colors4b_array; + shaderstate.dummyvbo.bones = m->bones; + shaderstate.dummyvbo.numbones = m->numbones; + shaderstate.dummyvbo.bonenums = m->bonenums; + shaderstate.dummyvbo.boneweights = m->boneweights; shaderstate.meshcount = 1; shaderstate.meshes = &m; @@ -3051,6 +3077,10 @@ void GLBE_SubmitBatch(batch_t *batch) shaderstate.dummyvbo.tvector = batch->mesh[0]->tnormals_array; shaderstate.dummyvbo.colours4f = batch->mesh[0]->colors4f_array; shaderstate.dummyvbo.colours4ub = batch->mesh[0]->colors4b_array; + shaderstate.dummyvbo.bones = batch->mesh[0]->bones; + shaderstate.dummyvbo.numbones = batch->mesh[0]->numbones; + shaderstate.dummyvbo.bonenums = batch->mesh[0]->bonenums; + shaderstate.dummyvbo.boneweights = batch->mesh[0]->boneweights; shaderstate.sourcevbo = &shaderstate.dummyvbo; lm = -1; } diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 14c0cb2e3..b0ad0bd0e 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -445,8 +445,6 @@ void GL_Set2D (void) extern cvar_t gl_screenangle; float rad, ang; float tmp[16], tmp2[16]; - float *Matrix4_NewRotation(float a, float x, float y, float z); - float *Matrix4_NewTranslation(float x, float y, float z); float w = vid.width, h = vid.height; ang = (gl_screenangle.value>0?(gl_screenangle.value+45):(gl_screenangle.value-45))/90; @@ -458,16 +456,16 @@ void GL_Set2D (void) w = fabs(cos(rad)) * (vid.width) + fabs(sin(rad)) * (vid.height); h = fabs(sin(rad)) * (vid.width) + fabs(cos(rad)) * (vid.height); - Matrix4_Orthographic(r_refdef.m_projection, w/-2.0f, w/2.0f, h/2.0f, h/-2.0f, -99999, 99999); + Matrix4x4_CM_Orthographic(r_refdef.m_projection, w/-2.0f, w/2.0f, h/2.0f, h/-2.0f, -99999, 99999); - Matrix4_Identity(tmp); - Matrix4_Multiply(Matrix4_NewTranslation((vid.width/-2.0f), (vid.height/-2.0f), 0), tmp, tmp2); - Matrix4_Multiply(Matrix4_NewRotation(-ang, 0, 0, 1), tmp2, r_refdef.m_view); + Matrix4x4_Identity(tmp); + Matrix4_Multiply(Matrix4x4_CM_NewTranslation((vid.width/-2.0f), (vid.height/-2.0f), 0), tmp, tmp2); + Matrix4_Multiply(Matrix4x4_CM_NewRotation(-ang, 0, 0, 1), tmp2, r_refdef.m_view); } else { - Matrix4_Orthographic(r_refdef.m_projection, 0, vid.width, vid.height, 0, -99999, 99999); - Matrix4_Identity(r_refdef.m_view); + Matrix4x4_CM_Orthographic(r_refdef.m_projection, 0, vid.width, vid.height, 0, -99999, 99999); + Matrix4x4_Identity(r_refdef.m_view); } r_refdef.time = realtime; /*flush that gl state*/ diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 7ff753e73..0150d5de1 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -37,6 +37,7 @@ FT_Error (VARGS *pFT_Init_FreeType) (FT_Library *alibrary); FT_Error (VARGS *pFT_Load_Char) (FT_Face face, FT_ULong char_code, FT_Int32 load_flags); FT_Error (VARGS *pFT_Set_Pixel_Sizes) (FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height); FT_Error (VARGS *pFT_New_Face) (FT_Library library, const char *pathname, FT_Long face_index, FT_Face *aface); +FT_Error (VARGS *pFT_New_Memory_Face) (FT_Library library, const FT_Byte* file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface); FT_Error (VARGS *pFT_Done_Face) (FT_Face face); #endif @@ -185,6 +186,7 @@ typedef struct font_s texid_t singletexture; #ifdef AVAIL_FREETYPE FT_Face face; + void *membuf; #endif } font_t; @@ -601,8 +603,10 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename) { #ifdef AVAIL_FREETYPE - FT_Face face; - int error; + FT_Face face = NULL; + FT_Error error; + flocation_t loc; + void *fbase = NULL; if (!fontlib) { dllfunction_t ft2funcs[] = @@ -611,6 +615,7 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename) {(void**)&pFT_Load_Char, "FT_Load_Char"}, {(void**)&pFT_Set_Pixel_Sizes, "FT_Set_Pixel_Sizes"}, {(void**)&pFT_New_Face, "FT_New_Face"}, + {(void**)&pFT_New_Memory_Face, "FT_New_Memory_Face"}, {(void**)&pFT_Init_FreeType, "FT_Init_FreeType"}, {(void**)&pFT_Done_Face, "FT_Done_Face"}, {NULL, NULL} @@ -631,8 +636,31 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename) /*any other errors leave freetype open*/ } - //fixme: use FT_Open_Face eventually - error = pFT_New_Face(fontlib, fontfilename, 0, &face); + error = FT_Err_Cannot_Open_Resource; + if (FS_FLocateFile(fontfilename, FSLFRT_LENGTH, &loc)>0) + { + if (*loc.rawname && !loc.offset) + { + fbase = NULL; + /*File is directly fopenable with no bias (not in a pk3/pak). Use the system-path form, so we don't have to eat the memory cost*/ + error = pFT_New_Face(fontlib, loc.rawname, 0, &face); + } + else + { + /*File is inside an archive, we need to read it and pass it as memory (and keep it available)*/ + vfsfile_t *f; + f = FS_OpenReadLocation(&loc); + if (f && loc.len > 0) + { + fbase = malloc(loc.len); + VFS_READ(f, fbase, loc.len); + VFS_CLOSE(f); + + error = pFT_New_Memory_Face(fontlib, fbase, loc.len, 0, &face); + } + } + } + #ifdef _WIN32 if (error) { @@ -664,20 +692,22 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename) } } #endif - if (error) - return false; - - error = pFT_Set_Pixel_Sizes(face, 0, height); - if (error) + if (!error) { - return false; + error = pFT_Set_Pixel_Sizes(face, 0, height); + if (!error) + { + /*success!*/ + f->membuf = fbase; + f->face = face; + return true; + } } - - f->face = face; - return true; -#else - return false; + if (fbase) + free(fbase); #endif + + return false; } static texid_t Font_LoadReplacementConchars(void) @@ -958,6 +988,8 @@ void Font_Free(struct font_s *f) #ifdef AVAIL_FREETYPE if (f->face) pFT_Done_Face(f->face); + if (f->membuf) + free(f->membuf); #endif free(f); } diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 7048ee3ef..66c63abf7 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -62,10 +62,6 @@ void QuaternionGLAngle(const vec3_t angles, vec4_t quaternion) quaternion[3] = cosr * cosp * cosy + sinr * sinp * siny; } -#define MAX_BONES 128 - - - matrix3x4 transform_matrix[MAX_BONES]; /* Vertex transformation matrix */ void GL_Draw_HL_AliasFrame(short *order, vec3_t *transformed, float tex_w, float tex_h); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 76dd1b827..9db811799 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -773,7 +773,8 @@ couldntload: if (crash) Host_EndGame ("Mod_NumForName: %s not found or couldn't load", mod->name); - Con_Printf(CON_ERROR "Unable to load or replace %s\n", mod->name); + if (*mod->name != '*') + Con_Printf(CON_ERROR "Unable to load or replace %s\n", mod->name); mod->type = mod_dummy; mod->mins[0] = -16; mod->mins[1] = -16; @@ -1050,7 +1051,15 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); if (!l->filelen) { - loadmodel->textures = NULL; + loadmodel->numtextures = 1; + loadmodel->textures = Hunk_AllocName (1 * sizeof(*loadmodel->textures), loadname); + + i = 0; + tx = Hunk_AllocName (sizeof(texture_t), loadname ); + memcpy(tx, r_notexture_mip, sizeof(texture_t)); + sprintf(tx->name, "unnamed%i", i); + loadmodel->textures[i] = tx; + return true; } m = (dmiptexlump_t *)(mod_base + l->fileofs); @@ -1389,6 +1398,10 @@ void RMod_NowLoadExternal(void) } } } + if (!TEXVALID(tn.base)) + { + tn.base = R_LoadTexture8("notexture", 16, 16, r_notexture_mip+1, IF_NOALPHA, 0); + } Mod_FinishTexture(tx, tn); } } @@ -1910,20 +1923,12 @@ qboolean RMod_LoadTexinfo (lump_t *l) miptex = LittleLong (in->miptex); out->flags = LittleLong (in->flags); - if (!loadmodel->textures || miptex < 0 || miptex >= loadmodel->numtextures) + out->texture = loadmodel->textures[miptex % loadmodel->numtextures]; + if (!out->texture) { - out->texture = r_notexture_mip; // checkerboard texture + out->texture = r_notexture_mip; // texture not found out->flags = 0; } - else - { - out->texture = loadmodel->textures[miptex]; - if (!out->texture) - { - out->texture = r_notexture_mip; // texture not found - out->flags = 0; - } - } } return true; @@ -1977,8 +1982,8 @@ void CalcSurfaceExtents (msurface_t *s); bmins[i] = floor(mins[i]/16); bmaxs[i] = ceil(maxs[i]/16); - s->texturemins[i] = bmins[i] * 16; - s->extents[i] = (bmaxs[i] - bmins[i]) * 16; + s->texturemins[i] = bmins[i]; + s->extents[i] = (bmaxs[i] - bmins[i]); // if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 ) //q2 uses 512. // Sys_Error ("Bad surface extents"); @@ -2310,6 +2315,7 @@ qboolean RMod_LoadClipnodes (lump_t *l) mclipnode_t *out; int i, count; hull_t *hull; + short cn, c; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -2483,11 +2489,34 @@ qboolean RMod_LoadClipnodes (lump_t *l) hull->available = false; } - for (i=0 ; i 32767) { - out->planenum = LittleLong(in->planenum); - out->children[0] = LittleShort(in->children[0]); - out->children[1] = LittleShort(in->children[1]); + /* + if the map contains more than 32767 clipnodes, some of them will overflow + typically this will happen in the second hull, and you thus might not notice it. + + */ + for (i=0 ; iplanenum = LittleLong(in->planenum); + for (c = 0; c < 2; c++) + { + cn = LittleShort(in->children[c]); + if (cn < -10) + out->children[c] = (unsigned short)cn; + else + out->children[c] = cn; + } + } + } + else + { + for (i=0 ; iplanenum = LittleLong(in->planenum); + out->children[0] = LittleShort(in->children[0]); + out->children[1] = LittleShort(in->children[1]); + } } if (numsuplementryclipnodes) //now load the crouch ones. diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index b016ffccc..a82e123c5 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -47,6 +47,8 @@ typedef enum { SHADER_SORT_COUNT } shadersort_t; +#define MAX_BONES 128 + typedef struct mesh_s { int numvertexes; @@ -73,6 +75,10 @@ typedef struct mesh_s vec3_t *trnormals; qboolean istrifan; /*if its a fan/poly/single quad (permits optimisations)*/ + float *bones; + int numbones; + byte_vec4_t *bonenums; + vec4_t *boneweights; } mesh_t; extern mesh_t nullmesh; @@ -235,6 +241,16 @@ typedef struct vbo_s int vbocolours; vec4_t *colours4f; byte_vec4_t *colours4ub; + + int vbobonenums; + byte_vec4_t *bonenums; + + int vboboneweights; + vec4_t *boneweights; + + int vbobones; + float *bones; + int numbones; } vbo_t; void GL_SelectVBO(int vbo); void GL_SelectEBO(int vbo); diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index faabf04fb..0f162ea2b 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -116,7 +116,6 @@ void R_InitBubble(void) } } -#ifdef GLQUAKE #define FLASHBLEND_VERTS 16 avec4_t flashblend_colours[FLASHBLEND_VERTS+1]; vecV_t flashblend_vcoords[FLASHBLEND_VERTS+1]; @@ -238,7 +237,7 @@ void GLR_RenderDlights (void) l = cl_dlights+rtlights_first; for (i=rtlights_first; iradius || !(l->flags & LFLAG_ALLOW_FLASH)) + if (!l->radius || !(l->flags & LFLAG_FLASHBLEND)) continue; //dlights emitting from the local player are not visible as flashblends @@ -255,7 +254,6 @@ void GLR_RenderDlights (void) R_RenderDlight (l, beflags); } } -#endif /* ============================================================================= @@ -265,154 +263,6 @@ DYNAMIC LIGHTS ============================================================================= */ -/* -============= -R_MarkLights -============= -*/ -/*void GLR_MarkLights (dlight_t *light, int bit, mnode_t *node) -{ - mplane_t *splitplane; - float dist; - msurface_t *surf; - int i; - - if (node->contents < 0) - return; - - splitplane = node->plane; - dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; - - if (dist > light->radius) - { - GLR_MarkLights (light, bit, node->children[0]); - return; - } - if (dist < -light->radius) - { - GLR_MarkLights (light, bit, node->children[1]); - return; - } - -// mark the polygons - surf = cl.worldmodel->surfaces + node->firstsurface; - for (i=0 ; inumsurfaces ; i++, surf++) - { - if (surf->dlightframe != r_dlightframecount) - { - surf->dlightbits = 0; - surf->dlightframe = r_dlightframecount; - } - surf->dlightbits |= bit; - } - - GLR_MarkLights (light, bit, node->children[0]); - GLR_MarkLights (light, bit, node->children[1]); -}*/ -/*void Q2BSP_MarkLights (dlight_t *light, int bit, mnode_t *node) -{ - mplane_t *splitplane; - float dist; - msurface_t *surf; - int i; - - if (node->contents != -1) - return; - - splitplane = node->plane; - dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; - - if (dist > light->radius) - { - Q2BSP_MarkLights (light, bit, node->children[0]); - return; - } - if (dist < -light->radius) - { - Q2BSP_MarkLights (light, bit, node->children[1]); - return; - } - -// mark the polygons - surf = cl.worldmodel->surfaces + node->firstsurface; - for (i=0 ; inumsurfaces ; i++, surf++) - { - if (surf->dlightframe != r_dlightframecount) - { - surf->dlightbits = 0; - surf->dlightframe = r_dlightframecount; - } - surf->dlightbits |= bit; - } - - Q2BSP_MarkLights (light, bit, node->children[0]); - Q2BSP_MarkLights (light, bit, node->children[1]); -}*/ - -void GLR_MarkQ3Lights (dlight_t *light, int bit, mnode_t *node) -{ - mplane_t *splitplane; - float dist; - msurface_t *surf; - int i; - - return; //we need to get the texinfos right first. - -/* - //mark all - for (surf = cl.worldmodel->surfaces, i = 0; i < cl.worldmodel->numsurfaces; i++, surf++) - { - if (surf->dlightframe != r_dlightframecount) - { - surf->dlightbits = 0; - surf->dlightframe = r_dlightframecount; - } - surf->dlightbits |= bit; - } - return; -*/ - if (node->contents != -1) - { - msurface_t **mark; - mleaf_t *leaf; - - // mark the polygons - leaf = (mleaf_t *)node; - mark = leaf->firstmarksurface; - for (i=0 ; inummarksurfaces ; i++, surf++) - { - surf = *mark++; - if (surf->dlightframe != r_dlightframecount) - { - surf->dlightbits = 0; - surf->dlightframe = r_dlightframecount; - } - surf->dlightbits |= bit; - } - - return; - } - - splitplane = node->plane; - dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; - - if (dist > light->radius) - { - GLR_MarkQ3Lights (light, bit, node->children[0]); - return; - } - if (dist < -light->radius) - { - GLR_MarkQ3Lights (light, bit, node->children[1]); - return; - } - - GLR_MarkQ3Lights (light, bit, node->children[0]); - GLR_MarkQ3Lights (light, bit, node->children[1]); -} - - - /* ============= R_PushDlights @@ -437,7 +287,7 @@ void R_PushDlights (void) l = cl_dlights+rtlights_first; for (i=rtlights_first ; i <= DL_LAST ; i++, l++) { - if (!l->radius || !(l->flags & LFLAG_ALLOW_LMHACK)) + if (!l->radius || !(l->flags & LFLAG_LIGHTMAP)) continue; currentmodel->funcs.MarkLights( l, 1<nodes ); } @@ -632,8 +482,7 @@ int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; - if (s < surf->texturemins[0] || - t < surf->texturemins[1]) + if (s < surf->texturemins[0] || t < surf->texturemins[1]) continue; ds = s - surf->texturemins[0]; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 365c14e78..13e519184 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -447,7 +447,7 @@ void R_RotateForEntity (float *modelview, const entity_t *e, const model_t *mod) ang[0] = 0; ang[1] = 0; ang[2] = gl_screenangle.value; - Matrix4_ModelViewMatrix(simpleview, ang, vec3_origin); + Matrix4x4_CM_ModelViewMatrix(simpleview, ang, vec3_origin); Matrix4_Multiply(simpleview, m, modelview); } else @@ -529,26 +529,26 @@ void R_SetupGL (void) // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI; // MYgluPerspective (yfov, screenaspect, 4, 4096); - Matrix4_Projection_Far(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value, gl_maxdist.value); + Matrix4x4_CM_Projection_Far(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value, gl_maxdist.value); } else { - Matrix4_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value); + Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value); } } else { if (gl_maxdist.value>=1) - Matrix4_Orthographic(r_refdef.m_projection, -fov_x/2, fov_x/2, fov_y/2, -fov_y/2, -gl_maxdist.value, gl_maxdist.value); + Matrix4x4_CM_Orthographic(r_refdef.m_projection, -fov_x/2, fov_x/2, fov_y/2, -fov_y/2, -gl_maxdist.value, gl_maxdist.value); else - Matrix4_Orthographic(r_refdef.m_projection, 0, r_refdef.vrect.width, 0, r_refdef.vrect.height, -9999, 9999); + Matrix4x4_CM_Orthographic(r_refdef.m_projection, 0, r_refdef.vrect.width, 0, r_refdef.vrect.height, -9999, 9999); } VectorCopy(r_refdef.viewangles, newa); newa[0] = r_refdef.viewangles[0]; newa[1] = r_refdef.viewangles[1]; newa[2] = r_refdef.viewangles[2] + gl_screenangle.value; - Matrix4_ModelViewMatrix(r_refdef.m_view, newa, r_refdef.vieworg); + Matrix4x4_CM_ModelViewMatrix(r_refdef.m_view, newa, r_refdef.vieworg); } if (qglLoadMatrixf) @@ -813,7 +813,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist) TransformDir(vright, paxis, vaxis, vright); TransformDir(vup, paxis, vaxis, vup); } - Matrix4_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg); + Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg); VectorAngles(vpn, vup, r_refdef.viewangles); VectorCopy(r_refdef.vieworg, r_origin); diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 11c313fe7..6b5a1a2ab 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -247,13 +247,6 @@ R_Init */ void GLR_ReInit (void) { -#if 0 - extern int gl_bumpmappingpossible; - if (gl_bumpmappingpossible) - GenerateNormalisationCubeMap(); - else - normalisationCubeMap = 0; -#endif netgraphtexture = GL_AllocNewTexture(0, 0); R_InitBloomTextures(); @@ -717,9 +710,8 @@ static void R_ImportRTLights(char *entlump) VectorCopy(color, dl->color); dl->flags = 0; dl->flags |= LFLAG_REALTIMEMODE; - dl->flags |= (pflags & PFLAGS_CORONA)?LFLAG_ALLOW_FLASH:0; + dl->flags |= (pflags & PFLAGS_CORONA)?LFLAG_FLASHBLEND:0; dl->flags |= (pflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0; - dl->flags |= LFLAG_ALLOW_PPL; dl->style = style+1; //FIXME: cubemaps if skin >= 16 @@ -833,7 +825,7 @@ static void R_LoadRTLights(void) dl->radius = radius; VectorCopy(rgb, dl->color); dl->die = 0; - dl->flags = flags|LFLAG_ALLOW_PPL; + dl->flags = flags; /*if (*cubename) { dl->fov = 90; diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 3fd215201..d08da943a 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -754,6 +754,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i "#define LOWER\n", "#define UPPER\n", "#define OFFSETMAPPING\n", + "#define SKELETAL\n", NULL }; char *permutationdefines[sizeof(permutationname)/sizeof(permutationname[0])]; @@ -1165,6 +1166,7 @@ struct sbuiltin_s "!!permu FULLBRIGHT\n" "!!permu LOWER\n" "!!permu UPPER\n" + "!!permu SKELETAL\n" "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" "varying vec2 tc;\n" @@ -1177,9 +1179,9 @@ struct sbuiltin_s "void main (void)\n" "{\n" + " gl_Position = ftetransform();\n" " light = e_light_ambient + (dot(v_normal,e_light_dir)*e_light_mul);\n" " tc = v_texcoord;\n" - " gl_Position = ftetransform();\n" "}\n" "#endif\n" @@ -1221,10 +1223,11 @@ struct sbuiltin_s "}\n" "#endif\n" }, - {QR_OPENGL, 110, "defaultskin", + {QR_OPENGL, 120, "defaultskin", "!!permu FULLBRIGHT\n" "!!permu LOWER\n" "!!permu UPPER\n" + "!!permu SKELETAL\n" "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" "varying vec2 tc;\n" @@ -1234,12 +1237,12 @@ struct sbuiltin_s "uniform vec3 e_light_mul;\n" "uniform vec3 e_light_ambient;\n" "varying vec3 light;\n" - + "#ifndef SKELETAL\nattribute vec4 v_weight;\n#endif\n" "void main (void)\n" "{\n" + " gl_Position = ftetransform();\n" " light = e_light_ambient + (dot(v_normal,e_light_dir)*e_light_mul);\n" " tc = v_texcoord;\n" - " gl_Position = ftetransform();\n" "}\n" "#endif\n" @@ -1455,6 +1458,8 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) {"v_normal", SP_ATTR_NORMALS}, {"v_svector", SP_ATTR_SNORMALS}, {"v_tvector", SP_ATTR_TNORMALS}, + {"v_bone", SP_ATTR_BONENUMS}, + {"v_weight", SP_ATTR_BONEWEIGHTS}, /*matricies*/ {"m_model", SP_MODELMATRIX}, @@ -1462,6 +1467,7 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) {"m_modelview", SP_MODELVIEWMATRIX}, {"m_projection", SP_PROJECTIONMATRIX}, {"m_modelviewprojection", SP_MODELVIEWPROJECTIONMATRIX}, + {"m_bones", SP_ENTBONEMATRICIES}, /*ent properties*/ {"e_time", SP_TIME}, @@ -3146,7 +3152,7 @@ void Shader_Finish (shader_t *s) if (TEXVALID(s->defaulttextures.base)) s->flags &= ~SHADER_NOIMAGE; - if (!s->numpasses && !(s->flags & (SHADER_NODRAW|SHADER_SKY)) && !s->fog_dist) + if (!s->numpasses && s->sort != SHADER_SORT_PORTAL && !(s->flags & (SHADER_NODRAW|SHADER_SKY)) && !s->fog_dist) { pass = &s->passes[s->numpasses++]; pass = &s->passes[0]; @@ -4350,9 +4356,29 @@ shader_t *R_RegisterShader_Flare (char *name) return &r_shaders[R_LoadShader (name, Shader_DefaultBSPFlare, NULL)]; } -shader_t *R_RegisterSkin (char *name) +shader_t *R_RegisterSkin (char *shadername, char *modname) { - return &r_shaders[R_LoadShader (name, Shader_DefaultSkin, NULL)]; + shader_t *shader; + if (modname && !strchr(shadername, '/')) + { + char newsname[MAX_QPATH]; + char *b = COM_SkipPath(modname); + if (b != modname && b-modname + strlen(shadername)+1 < sizeof(newsname)) + { + memcpy(newsname, modname, b - modname); + memcpy(newsname + (b-modname), shadername, strlen(shadername)+1); + /*if the specified shader does not contain a path, try and load one relative to the name of the model*/ + shader = &r_shaders[R_LoadShader (newsname, Shader_DefaultSkin, NULL)]; + + R_BuildDefaultTexnums(&shader->defaulttextures, shader); + + /*if its a valid shader with valid textures, use it*/ + if (!(shader->flags & SHADER_NOIMAGE)) + return shader; + } + } + shader = &r_shaders[R_LoadShader (shadername, Shader_DefaultSkin, NULL)]; + return shader; } shader_t *R_RegisterCustom (char *name, shader_gen_t *defaultgen, const void *args) { diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 3bc1990b9..b4d51685d 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -114,7 +114,7 @@ static void SHM_Vertex3fv (const GLfloat *v) } } -void SHM_TriangleFan(int numverts, vecV_t *verts, vec3_t lightorg, float pd) +static void SHM_TriangleFan(int numverts, vecV_t *verts, vec3_t lightorg, float pd) { int v, i, idxs; float *v1; @@ -196,7 +196,7 @@ static void SHM_Shadow_Cache_Leaf(mleaf_t *leaf) sh_shmesh->litleaves[i>>3] |= 1<<(i&7); } -void SH_FreeShadowMesh(shadowmesh_t *sm) +static void SH_FreeShadowMesh(shadowmesh_t *sm) { unsigned int i; for (i = 0; i < sm->numsurftextures; i++) @@ -738,7 +738,7 @@ static void SHM_MarkLeavesQ1(dlight_t *dl, unsigned char *lvis) } #ifdef Q3BSPS -void SHM_RecursiveWorldNodeQ3_r (dlight_t *dl, mnode_t *node) +static void SHM_RecursiveWorldNodeQ3_r (dlight_t *dl, mnode_t *node) { mplane_t *splitplane; float dist; @@ -788,6 +788,7 @@ void SHM_RecursiveWorldNodeQ3_r (dlight_t *dl, mnode_t *node) static void SHM_ComposeVolume_BruteForce(dlight_t *dl) { + /*FIXME: This function is not complete*/ shadowmeshsurfs_t *sms; unsigned int tno; unsigned int sno; @@ -859,7 +860,7 @@ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) */ } -static struct shadowmesh_s *SHM_BuildShadowVolumeMesh(dlight_t *dl, unsigned char *lvis, unsigned char *vvis) +static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvis, unsigned char *vvis, qboolean surfonly) { float *v1, *v2; vec3_t v3, v4; @@ -879,7 +880,8 @@ static struct shadowmesh_s *SHM_BuildShadowVolumeMesh(dlight_t *dl, unsigned cha SHM_BeginShadowMesh(dl); sh_shadowframe++; SHM_RecursiveWorldNodeQ3_r(dl, cl.worldmodel->nodes); - SHM_ComposeVolume_BruteForce(dl); + if (!surfonly) + SHM_ComposeVolume_BruteForce(dl); return SHM_FinishShadowMesh(dl); // SHM_RecursiveWorldNodeQ3_r(cl.worldmodel->nodes); @@ -901,41 +903,44 @@ static struct shadowmesh_s *SHM_BuildShadowVolumeMesh(dlight_t *dl, unsigned cha else return NULL; - SHM_BeginQuads(); - while(firstedge) + if (!surfonly) { - //border - v1 = cl.worldmodel->vertexes[cl.worldmodel->edges[firstedge].v[0]].position; - v2 = cl.worldmodel->vertexes[cl.worldmodel->edges[firstedge].v[1]].position; - - //get positions of v3 and v4 based on the light position - v3[0] = v1[0] + ( v1[0]-dl->origin[0] )*PROJECTION_DISTANCE; - v3[1] = v1[1] + ( v1[1]-dl->origin[1] )*PROJECTION_DISTANCE; - v3[2] = v1[2] + ( v1[2]-dl->origin[2] )*PROJECTION_DISTANCE; - - v4[0] = v2[0] + ( v2[0]-dl->origin[0] )*PROJECTION_DISTANCE; - v4[1] = v2[1] + ( v2[1]-dl->origin[1] )*PROJECTION_DISTANCE; - v4[2] = v2[2] + ( v2[2]-dl->origin[2] )*PROJECTION_DISTANCE; - - if (edge[firstedge].count > 0) + SHM_BeginQuads(); + while(firstedge) { - SHM_Vertex3fv(v3); - SHM_Vertex3fv(v4); - SHM_Vertex3fv(v2); - SHM_Vertex3fv(v1); - } - else - { - SHM_Vertex3fv(v1); - SHM_Vertex3fv(v2); - SHM_Vertex3fv(v4); - SHM_Vertex3fv(v3); - } - edge[firstedge].count=0; + //border + v1 = cl.worldmodel->vertexes[cl.worldmodel->edges[firstedge].v[0]].position; + v2 = cl.worldmodel->vertexes[cl.worldmodel->edges[firstedge].v[1]].position; - firstedge = edge[firstedge].next; + //get positions of v3 and v4 based on the light position + v3[0] = v1[0] + ( v1[0]-dl->origin[0] )*PROJECTION_DISTANCE; + v3[1] = v1[1] + ( v1[1]-dl->origin[1] )*PROJECTION_DISTANCE; + v3[2] = v1[2] + ( v1[2]-dl->origin[2] )*PROJECTION_DISTANCE; + + v4[0] = v2[0] + ( v2[0]-dl->origin[0] )*PROJECTION_DISTANCE; + v4[1] = v2[1] + ( v2[1]-dl->origin[1] )*PROJECTION_DISTANCE; + v4[2] = v2[2] + ( v2[2]-dl->origin[2] )*PROJECTION_DISTANCE; + + if (edge[firstedge].count > 0) + { + SHM_Vertex3fv(v3); + SHM_Vertex3fv(v4); + SHM_Vertex3fv(v2); + SHM_Vertex3fv(v1); + } + else + { + SHM_Vertex3fv(v1); + SHM_Vertex3fv(v2); + SHM_Vertex3fv(v4); + SHM_Vertex3fv(v3); + } + edge[firstedge].count=0; + + firstedge = edge[firstedge].next; + } + SHM_End(); } - SHM_End(); firstedge=0; @@ -1082,7 +1087,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) v[1] = (i & 2) ? mins[1] : maxs[1]; v[2] = (i & 4) ? mins[2] : maxs[2]; v[3] = 1.0f; - Matrix4_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); + Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); v2[0]*=r_view_width; v2[1]*=r_view_height; // GL_TransformToScreen(v, v2); @@ -1154,7 +1159,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) v[1] = v2[0] * vright[1] + v2[1] * vup[1] + v2[2] * vpn[1] + r_refdef.vieworg[1]; v[2] = v2[0] * vright[2] + v2[1] * vup[2] + v2[2] * vpn[2] + r_refdef.vieworg[2]; v[3] = 1.0f; - Matrix4_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); + Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); v2[0]*=r_view_width; v2[1]*=r_view_height; //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); @@ -1183,7 +1188,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) v[1] = (i & 2) ? mins[1] : maxs[1]; v[2] = (i & 4) ? mins[2] : maxs[2]; v[3] = 1.0f; - Matrix4_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); + Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); v2[0]*=r_view_width; v2[1]*=r_view_height; //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); @@ -1251,7 +1256,8 @@ void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize) static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float proj[16]) { - float mvm[16]; + qboolean oxv; + float mvm[16], sav[16]; vec3_t t1,t2; int smsize = SHADOWMAP_SIZE; @@ -1270,38 +1276,40 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p { case 0: //forward - Matrix4_ModelViewMatrixFromAxis(mvm, l->axis[0], l->axis[1], l->axis[2], l->origin); + Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, l->axis[0], l->axis[1], l->axis[2], l->origin); break; case 1: //back VectorNegate(l->axis[0], t1); VectorNegate(l->axis[1], t2); - Matrix4_ModelViewMatrixFromAxis(mvm, t1, t2, l->axis[2], l->origin); + Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, t1, t2, l->axis[2], l->origin); break; case 2: //left VectorNegate(l->axis[1], t1); VectorNegate(l->axis[0], t2); - Matrix4_ModelViewMatrixFromAxis(mvm, l->axis[1], t2, l->axis[2], l->origin); + Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, l->axis[1], t2, l->axis[2], l->origin); break; case 3: //right VectorNegate(l->axis[1], t1); - Matrix4_ModelViewMatrixFromAxis(mvm, t1, l->axis[0], l->axis[2], l->origin); + Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, t1, l->axis[0], l->axis[2], l->origin); break; case 4: //up VectorNegate(l->axis[0], t2); - Matrix4_ModelViewMatrixFromAxis(mvm, l->axis[2], l->axis[1], t2, l->origin); + Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, l->axis[2], l->axis[1], t2, l->origin); break; case 5: //down VectorNegate(l->axis[2], t1); - Matrix4_ModelViewMatrixFromAxis(mvm, t1, l->axis[1], l->axis[0], l->origin); + Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, t1, l->axis[1], l->axis[0], l->origin); break; } qglMatrixMode(GL_MODELVIEW); + memcpy(sav, r_refdef.m_view, sizeof(r_refdef.m_view)); + memcpy(r_refdef.m_view, mvm, sizeof(r_refdef.m_view)); qglLoadMatrixf(mvm); R_SetFrustum(proj, mvm); @@ -1317,7 +1325,11 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p } BE_SelectMode(BEM_DEPTHONLY); + /*shadow meshes are always drawn as an external view*/ + oxv = r_refdef.externalview; + r_refdef.externalview = true; BE_BaseEntTextures(); + r_refdef.externalview = oxv; if (0) { @@ -1341,6 +1353,8 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } + + memcpy(r_refdef.m_view, sav, sizeof(r_refdef.m_view)); } void Sh_Shutdown(void) @@ -1373,7 +1387,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } - smesh = SHM_BuildShadowVolumeMesh(l, lvis, NULL); + smesh = SHM_BuildShadowMesh(l, lvis, NULL, true); /*polygon offsets. urgh.*/ qglEnable(GL_POLYGON_OFFSET_FILL); @@ -1386,7 +1400,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) if (l->fov) { - Matrix4_Projection_Far(proj, l->fov, l->fov, nearplane, l->radius); + Matrix4x4_CM_Projection_Far(proj, l->fov, l->fov, nearplane, l->radius); qglMatrixMode(GL_PROJECTION); qglLoadMatrixf(proj); @@ -1395,7 +1409,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) } else { - Matrix4_Projection_Far(proj, 90, 90, nearplane, l->radius); + Matrix4x4_CM_Projection_Far(proj, 90, 90, nearplane, l->radius); qglMatrixMode(GL_PROJECTION); qglLoadMatrixf(proj); @@ -1485,11 +1499,11 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) Sh_GenShadowMap(l, lvis); if (l->fov) - Matrix4_Projection_Far(proj, l->fov, l->fov, nearplane, l->radius); + Matrix4x4_CM_Projection_Far(proj, l->fov, l->fov, nearplane, l->radius); else - Matrix4_Projection_Far(proj, 90, 90, nearplane, l->radius); + Matrix4x4_CM_Projection_Far(proj, 90, 90, nearplane, l->radius); VectorMA(l->origin, 0, l->axis[0], biasorg); - Matrix4_ModelViewMatrixFromAxis(view, l->axis[0], l->axis[1], l->axis[2], l->origin); + Matrix4x4_CM_ModelViewMatrixFromAxis(view, l->axis[0], l->axis[1], l->axis[2], l->origin); //bp = shadowprojectionbias*proj*view; Matrix4_Multiply(shadowprojectionbias, proj, t); @@ -1716,7 +1730,7 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q BE_PushOffsetShadow(false); - sm = SHM_BuildShadowVolumeMesh(dl, lvis, vvis); + sm = SHM_BuildShadowMesh(dl, lvis, vvis, false); if (!sm) Sh_DrawBrushModelShadow(dl, &r_worldentity); else @@ -2009,8 +2023,7 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin); lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); - if (!dl->die) - SHM_BuildShadowVolumeMesh(dl, lvis, vvis); + SHM_BuildShadowMesh(dl, lvis, vvis, false); if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect. { diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index c1e9a3c9a..67f6d7fab 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -155,7 +155,9 @@ FTEPFNGLGETVERTEXATTRIBIV qglGetVertexAttribiv; FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray; FTEPFNGLDISABLEVERTEXATTRIBARRAY qglDisableVertexAttribArray; FTEPFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; -FTEPFNGLUNIFORMMATRIX4FVARBPROC qglUniformMatrix4fvARB; +FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4fvARB; +FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix3x4fv; +FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4x3fv; FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB; FTEPFNGLUNIFORM4FVARBPROC qglUniform4fvARB; FTEPFNGLUNIFORM3FARBPROC qglUniform3fARB; @@ -569,7 +571,42 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) // glslang //the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects. //but our code kinda requires both for clean workings. - if (GL_CheckExtension("GL_ARB_fragment_shader") + if (gl_config.glversion >= 2) + { + /*core names are different from extension names (more functions too)*/ + gl_config.arb_shader_objects = true; + qglCreateProgramObjectARB = (void *)getglext( "glCreateProgram"); + qglDeleteProgramObject_ = (void *)getglext( "glDeleteProgram"); + qglDeleteShaderObject_ = (void *)getglext( "glDeleteShader"); + qglUseProgramObjectARB = (void *)getglext( "glUseProgram"); + qglCreateShaderObjectARB = (void *)getglext( "glCreateShader"); + qglGetProgramParameteriv_ = (void *)getglext( "glGetProgramiv"); + qglGetShaderParameteriv_ = (void *)getglext( "glGetShaderiv"); + qglAttachObjectARB = (void *)getglext( "glAttachShader"); + qglGetProgramInfoLog_ = (void *)getglext( "glGetProgramInfoLog"); + qglGetShaderInfoLog_ = (void *)getglext( "glGetShaderInfoLog"); + qglShaderSourceARB = (void *)getglext("glShaderSource"); + qglCompileShaderARB = (void *)getglext("glCompileShader"); + qglLinkProgramARB = (void *)getglext("glLinkProgram"); + qglBindAttribLocationARB = (void *)getglext("glBindAttribLocation"); + qglGetAttribLocationARB = (void *)getglext("glGetAttribLocation"); + qglVertexAttribPointer = (void *)getglext("glVertexAttribPointer"); + qglGetVertexAttribiv = (void *)getglext("glGetVertexAttribiv"); + qglEnableVertexAttribArray = (void *)getglext("glEnableVertexAttribArray"); + qglDisableVertexAttribArray = (void *)getglext("glDisableVertexAttribArray"); + qglGetUniformLocationARB = (void *)getglext("glGetUniformLocation"); + qglUniformMatrix4fvARB = (void *)getglext("glUniformMatrix4fv"); + qglUniformMatrix3x4fv = (void *)getglext("glUniformMatrix3x4fv"); + qglUniformMatrix4x3fv = (void *)getglext("glUniformMatrix4x3fv"); + qglUniform4fARB = (void *)getglext("glUniform4f"); + qglUniform4fvARB = (void *)getglext("glUniform4fv"); + qglUniform3fARB = (void *)getglext("glUniform3f"); + qglUniform3fvARB = (void *)getglext("glUniform3fv"); + qglUniform1iARB = (void *)getglext("glUniform1i"); + qglUniform1fARB = (void *)getglext("glUniform1f"); + Con_DPrintf("GLSL available\n"); + } + else if (GL_CheckExtension("GL_ARB_fragment_shader") && GL_CheckExtension("GL_ARB_vertex_shader") && GL_CheckExtension("GL_ARB_shader_objects")) { @@ -595,6 +632,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) qglDisableVertexAttribArray = (void *)getglext("glDisableVertexAttribArrayARB"); qglGetUniformLocationARB = (void *)getglext("glGetUniformLocationARB"); qglUniformMatrix4fvARB = (void *)getglext("glUniformMatrix4fvARB"); + qglUniformMatrix3x4fv = (void *)getglext("glUniformMatrix3x4fvARB"); + qglUniformMatrix4x3fv = (void *)getglext("glUniformMatrix4x3fvARB"); qglUniform4fARB = (void *)getglext("glUniform4fARB"); qglUniform4fvARB = (void *)getglext("glUniform4fvARB"); qglUniform3fARB = (void *)getglext("glUniform3fARB"); @@ -604,39 +643,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) Con_DPrintf("GLSL available\n"); } - else if (gl_config.gles && gl_config.glversion >= 2) - { - /*core names are different from extension names (more functions too)*/ - gl_config.arb_shader_objects = true; - qglCreateProgramObjectARB = (void *)getglext( "glCreateProgram"); - qglDeleteProgramObject_ = (void *)getglext( "glDeleteProgram"); - qglDeleteShaderObject_ = (void *)getglext( "glDeleteShader"); - qglUseProgramObjectARB = (void *)getglext( "glUseProgram"); - qglCreateShaderObjectARB = (void *)getglext( "glCreateShader"); - qglGetProgramParameteriv_ = (void *)getglext( "glGetProgramiv"); - qglGetShaderParameteriv_ = (void *)getglext( "glGetShaderiv"); - qglAttachObjectARB = (void *)getglext( "glAttachShader"); - qglGetProgramInfoLog_ = (void *)getglext( "glGetProgramInfoLog"); - qglGetShaderInfoLog_ = (void *)getglext( "glGetShaderInfoLog"); - qglShaderSourceARB = (void *)getglext("glShaderSource"); - qglCompileShaderARB = (void *)getglext("glCompileShader"); - qglLinkProgramARB = (void *)getglext("glLinkProgram"); - qglBindAttribLocationARB = (void *)getglext("glBindAttribLocation"); - qglGetAttribLocationARB = (void *)getglext("glGetAttribLocation"); - qglVertexAttribPointer = (void *)getglext("glVertexAttribPointer"); - qglGetVertexAttribiv = (void *)getglext("glGetVertexAttribiv"); - qglEnableVertexAttribArray = (void *)getglext("glEnableVertexAttribArray"); - qglDisableVertexAttribArray = (void *)getglext("glDisableVertexAttribArray"); - qglGetUniformLocationARB = (void *)getglext("glGetUniformLocation"); - qglUniformMatrix4fvARB = (void *)getglext("glUniformMatrix4fv"); - qglUniform4fARB = (void *)getglext("glUniform4f"); - qglUniform4fvARB = (void *)getglext("glUniform4fv"); - qglUniform3fARB = (void *)getglext("glUniform3f"); - qglUniform3fvARB = (void *)getglext("glUniform3fv"); - qglUniform1iARB = (void *)getglext("glUniform1i"); - qglUniform1fARB = (void *)getglext("glUniform1f"); - Con_DPrintf("GLSL available\n"); - } if (GL_CheckExtension("GL_EXT_framebuffer_object")) { @@ -683,6 +689,9 @@ GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompi if (versionline) prstrings[strings++] = versionline; + while(*precompilerconstants) + prstrings[strings++] = *precompilerconstants++; + prstrings[strings++] = "#define ENGINE_"DISTRIBUTION"\n"; switch (shadertype) { @@ -697,22 +706,44 @@ GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompi prstrings[strings++] = "#define VERTEX_SHADER\n"; if (gl_config.gles) { - prstrings[strings++] = "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" - "precision highp float;\n" - "#else\n" - "precision mediump float;\n" - "#endif\n"; + prstrings[strings++] = + "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" + "precision highp float;\n" + "#else\n" + "precision mediump float;\n" + "#endif\n"; } if (gl_config.nofixedfunc) { - prstrings[strings++] = "#define ftetransform() (m_projection * m_modelview * vec4(v_position, 1.0))\n" - "uniform mat4 m_modelview, m_projection;\n" - "attribute vec3 v_position;\n"; + prstrings[strings++] = + "#define ftetransform() (m_projection * m_modelview * vec4(v_position, 1.0))\n" + "uniform mat4 m_modelview, m_projection;\n" + "attribute vec3 v_position;\n"; } else { - prstrings[strings++] = "#define ftetransform() ftransform()\n" - "#define v_position gl_Vertex\n"; + prstrings[strings++] = + "#ifdef SKELETAL\n" + "attribute vec4 v_bone;\n" + "attribute vec4 v_weight;\n" + "uniform mat4 m_modelview, m_projection;\n" + "uniform mat3x4 m_bones["STRINGIFY(MAX_BONES)"];\n" + "#define v_position gl_Vertex\n" + + "vec4 skeletaltransform()\n" + "{" + " mat3x4 wmat;\n" + " wmat = m_bones[int(v_bone.x)] * v_weight.x;\n" + " wmat += m_bones[int(v_bone.y)] * v_weight.y;\n" + " wmat += m_bones[int(v_bone.z)] * v_weight.z;\n" + " wmat += m_bones[int(v_bone.w)] * v_weight.w;\n" + " return m_projection * m_modelview * vec4(v_position * wmat, v_position.w);\n" + "}\n" + "#define ftetransform() skeletaltransform()\n" + "#else\n" + "#define ftetransform() ftransform()\n" + "#define v_position gl_Vertex\n" + "#endif\n"; } break; @@ -720,8 +751,6 @@ GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompi prstrings[strings++] = "#define UNKNOWN_SHADER\n"; break; } - while(*precompilerconstants) - prstrings[strings++] = *precompilerconstants++; prstrings[strings++] = shadersource; shader = qglCreateShaderObjectARB(shadertype); @@ -789,6 +818,8 @@ GLhandleARB GLSlang_CreateProgramObject (GLhandleARB vert, GLhandleARB frag) qglBindAttribLocationARB(program, 4, "v_normal"); qglBindAttribLocationARB(program, 5, "v_snormal"); qglBindAttribLocationARB(program, 6, "v_tnormal"); + qglBindAttribLocationARB(program, 8, "v_bone"); + qglBindAttribLocationARB(program, 9, "v_weight"); qglLinkProgramARB(program); diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 85925e0de..ad33cb296 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -98,7 +98,7 @@ typedef void (APIENTRYP FTEPFNGLDISABLEVERTEXATTRIBARRAY) (GLuint index); typedef GLint (APIENTRYP FTEPFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); typedef void (APIENTRYP FTEPFNGLGETVERTEXATTRIBIV) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP FTEPFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (APIENTRYP FTEPFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, GLfloat *value); +typedef void (APIENTRYP FTEPFNGLUNIFORMMATRIXPROC) (GLint location, GLsizei count, GLboolean transpose, GLfloat *value); typedef void (APIENTRYP FTEPFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, GLfloat *value); typedef void (APIENTRYP FTEPFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); typedef void (APIENTRYP FTEPFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, GLfloat *value); @@ -332,10 +332,9 @@ void R_DrawHLModel(entity_t *curent); // // gl_rlight.c // -#ifdef GLQUAKE -void GLR_MarkLights (dlight_t *light, int bit, mnode_t *node); -void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node); void GLR_RenderDlights (void); +#ifdef GLQUAKE +void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node); void R_InitFlashblends (void); int GLR_LightPoint (vec3_t p); #endif @@ -781,7 +780,9 @@ extern FTEPFNGLGETVERTEXATTRIBIV qglGetVertexAttribiv; extern FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray; extern FTEPFNGLDISABLEVERTEXATTRIBARRAY qglDisableVertexAttribArray; extern FTEPFNGLGETUNIFORMLOCATIONARBPROC qglGetUniformLocationARB; -extern FTEPFNGLUNIFORMMATRIX4FVARBPROC qglUniformMatrix4fvARB; +extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4fvARB; +extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix4x3fv; +extern FTEPFNGLUNIFORMMATRIXPROC qglUniformMatrix3x4fv; extern FTEPFNGLUNIFORM4FARBPROC qglUniform4fARB; extern FTEPFNGLUNIFORM4FVARBPROC qglUniform4fvARB; extern FTEPFNGLUNIFORM3FARBPROC qglUniform3fARB; diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 53f7ff237..4218038ec 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -253,8 +253,9 @@ enum{ PERMUTATION_LOWER = 8, PERMUTATION_UPPER = 16, PERMUTATION_OFFSET = 32, + PERMUTATION_SKELETAL = 64, - PERMUTATIONS = 64 + PERMUTATIONS = 128 }; typedef struct { @@ -268,6 +269,8 @@ typedef struct { SP_ATTR_NORMALS, SP_ATTR_SNORMALS, SP_ATTR_TNORMALS, + SP_ATTR_BONENUMS, /*skeletal only*/ + SP_ATTR_BONEWEIGHTS, /*skeletal only*/ SP_FIRSTUNIFORM, //never set @@ -281,6 +284,7 @@ typedef struct { SP_E_L_MUL, SP_E_L_AMBIENT, + SP_ENTBONEMATRICIES, SP_EYEPOS, SP_ENTMATRIX, SP_VIEWMATRIX, @@ -405,7 +409,7 @@ shader_t *R_RegisterShader (char *name, const char *shaderscript); shader_t *R_RegisterShader_Lightmap (char *name); shader_t *R_RegisterShader_Vertex (char *name); shader_t *R_RegisterShader_Flare (char *name); -shader_t *R_RegisterSkin (char *name); +shader_t *R_RegisterSkin (char *shadername, char *modname); shader_t *R_RegisterCustom (char *name, shader_gen_t *defaultgen, const void *args); void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader); diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 8ee0f99a2..4115a066f 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -69,12 +69,16 @@ void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount) // return; } - if (addressablehunk) #ifdef _WIN32 - VirtualFree(addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p - addressablehunk = VirtualAlloc (NULL, totalammount, MEM_RESERVE, PAGE_NOACCESS); + if (addressablehunk && addressablesize != totalammount) + { + VirtualFree(addressablehunk, 0, MEM_RELEASE); //doesn't this look complicated? :p + addressablehunk = NULL; + } + addressablehunk = VirtualAlloc (addressablehunk, totalammount, MEM_RESERVE, PAGE_NOACCESS); #else - free(addressablehunk); + if (addressablehunk) + free(addressablehunk); addressablehunk = malloc(totalammount); //linux will allocate-on-use anyway, which is handy. // memset(addressablehunk, 0xff, totalammount); #endif @@ -507,6 +511,7 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) int i = str & ~0x80000000; if (i >= prinst->numallocedstrings) { + printf("invalid string %x\n", str); pr_trace = 1; return ""; } @@ -514,6 +519,7 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) return prinst->allocedstrings[i]; else { + printf("invalid string %x\n", str); pr_trace = 1; return ""; //urm, was freed... } @@ -523,6 +529,7 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) int i = str & ~0x40000000; if (i >= prinst->numtempstrings) { + printf("invalid temp string %x\n", str); pr_trace = 1; return ""; } @@ -532,6 +539,7 @@ char *ASMCALL PR_StringToNative (progfuncs_t *progfuncs, string_t str) if (str >= progfuncs->stringtablesize) { + printf("invalid string offset %x\n", str); pr_trace = 1; return ""; } @@ -774,8 +782,8 @@ void CloseProgs(progfuncs_t *inst) #endif if (inst->prinst->allocedstrings) - f(inst->prinst->allocedstrings); - inst->prinst->allocedstrings = NULL; + f(inst->prinst->allocedstrings); + inst->prinst->allocedstrings = NULL; if (inst->prinst->tempstrings) f(inst->prinst->tempstrings); inst->prinst->tempstrings = NULL; diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index 979560393..edeac8abd 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -436,6 +436,7 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key) int type; ddef32_t fakedef; eval_t fakeval; + edictrun_t *ed; assignment = strchr(key, '='); if (assignment) @@ -478,7 +479,10 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key) if (c)*c = '.'; if (!fdef) return "(Bad string)"; - val = (eval_t *) (((char *)PROG_TO_EDICT(progfuncs, val->_int)->fields) + fdef->ofs*4); + ed = PROG_TO_EDICT(progfuncs, val->_int); + if (!ed) + return "(Invalid Entity)"; + val = (eval_t *) (((char *)ed->fields) + fdef->ofs*4); type = fdef->type; } @@ -859,9 +863,9 @@ void PR_ExecuteCode (progfuncs_t *progfuncs, int s) prinst->continuestatement = -1; #ifdef QCJIT - if (prinst->jit) + if (current_progstate->jit) { - PR_EnterJIT(progfuncs, prinst->jit, s); + PR_EnterJIT(progfuncs, current_progstate->jit, s); return; } #endif diff --git a/engine/qclib/pr_multi.c b/engine/qclib/pr_multi.c index b66b8b5e7..a375e889e 100644 --- a/engine/qclib/pr_multi.c +++ b/engine/qclib/pr_multi.c @@ -94,7 +94,7 @@ progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_ progfuncs->numprogs = a+1; #ifdef QCJIT - prinst->jit = PR_GenerateJit(progfuncs); + current_progstate->jit = PR_GenerateJit(progfuncs); #endif if (oldtype>=0) PR_SwitchProgs(progfuncs, oldtype); @@ -122,6 +122,10 @@ void PR_Clear(progfuncs_t *progfuncs) unsigned int a; for (a = 0; a < maxprogs; a++) { +#ifdef QCJIT + if (pr_progstate[a].jit) + PR_CloseJit(pr_progstate[a].jit); +#endif pr_progstate[a].progs = NULL; } } diff --git a/engine/qclib/pr_x86.c b/engine/qclib/pr_x86.c index c9f04ed9a..a93e44573 100644 --- a/engine/qclib/pr_x86.c +++ b/engine/qclib/pr_x86.c @@ -208,13 +208,17 @@ int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsn void PR_CloseJit(struct jitstate *jit) { - free(jit->statementjumps); - free(jit->statementoffsets); + if (jit) + { + free(jit->statementjumps); + free(jit->statementoffsets); #ifndef _WIN32 - munmap(jit->code, jit->jitstatements * 500); + munmap(jit->code, jit->jitstatements * 500); #else - free(jit->code); + free(jit->code); #endif + free(jit) + } } #define EmitByte(v) EmitByte(jit, v) diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index e0d5cd461..03aa7839a 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -201,6 +201,10 @@ typedef struct progstate_s int *linenums; //debug versions only progstructtype_t structtype; + +#ifdef QCJIT + struct jitstate *jit; +#endif } progstate_t; typedef struct extensionbuiltin_s { @@ -343,9 +347,6 @@ void PR_SetBuiltins(int type); #define vars(type, name, size) type name[size] typedef struct prinst_s { -#ifdef QCJIT - struct jitstate *jit; -#endif char **tempstrings; int maxtempstrings; int numtempstrings; @@ -481,6 +482,7 @@ pbool CompileFile(progfuncs_t *progfuncs, char *filename); struct jitstate; struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs); void PR_EnterJIT(progfuncs_t *progfuncs, struct jitstate *jitstate, int statement); +void PR_CloseJit(struct jitstate *jit); char *QCC_COM_Parse (char *data); extern char qcc_token[1024]; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index f37ef7368..f1993eb85 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -2581,8 +2581,19 @@ QCC_def_t *QCC_PR_ParseImmediate (void) if (pr_immediate_type == type_string) { - cn = QCC_MakeStringDef(pr_immediate_string); - QCC_PR_Lex (); + char tmp[8192]; + strcpy(tmp, pr_immediate_string); + + for(;;) + { + QCC_PR_Lex (); + if (pr_token_type == tt_immediate && pr_token_type == tt_immediate) + strcat(tmp, pr_immediate_string); + else + break; + } + + cn = QCC_MakeStringDef(tmp); return cn; } @@ -9396,6 +9407,11 @@ void QCC_PR_ParseDefs (char *classname) G_FUNCTION(def->ofs+arraypart*type->size+parttype->ofs) = G_FUNCTION(d->ofs); } break; + case ev_struct: + case ev_union: + QCC_PR_ParseError(ERR_TYPEINVALIDINSTRUCT, "nested struct intializers are not supported"); + QCC_PR_Lex(); + break; default: QCC_PR_ParseError(ERR_TYPEINVALIDINSTRUCT, "type %i not valid in a struct", parttype->type); QCC_PR_Lex(); diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 6b0388612..686c0b760 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -36,46 +36,47 @@ void ED_Print (struct progfuncs_s *progfuncs, struct edict_s *ed); int PR_EnableEBFSBuiltin(char *name, int binum); /*cvars for the gamecode only*/ -cvar_t nomonsters = SCVAR("nomonsters", "0"); -cvar_t gamecfg = SCVAR("gamecfg", "0"); -cvar_t scratch1 = SCVAR("scratch1", "0"); -cvar_t scratch2 = SCVAR("scratch2", "0"); -cvar_t scratch3 = SCVAR("scratch3", "0"); -cvar_t scratch4 = SCVAR("scratch4", "0"); -cvar_t savedgamecfg = SCVARF("savedgamecfg", "0", CVAR_ARCHIVE); -cvar_t saved1 = SCVARF("saved1", "0", CVAR_ARCHIVE); -cvar_t saved2 = SCVARF("saved2", "0", CVAR_ARCHIVE); -cvar_t saved3 = SCVARF("saved3", "0", CVAR_ARCHIVE); -cvar_t saved4 = SCVARF("saved4", "0", CVAR_ARCHIVE); -cvar_t temp1 = SCVARF("temp1", "0", CVAR_ARCHIVE); -cvar_t noexit = SCVAR("noexit", "0"); +cvar_t nomonsters = CVAR("nomonsters", "0"); +cvar_t gamecfg = CVAR("gamecfg", "0"); +cvar_t scratch1 = CVAR("scratch1", "0"); +cvar_t scratch2 = CVAR("scratch2", "0"); +cvar_t scratch3 = CVAR("scratch3", "0"); +cvar_t scratch4 = CVAR("scratch4", "0"); +cvar_t savedgamecfg = CVARF("savedgamecfg", "0", CVAR_ARCHIVE); +cvar_t saved1 = CVARF("saved1", "0", CVAR_ARCHIVE); +cvar_t saved2 = CVARF("saved2", "0", CVAR_ARCHIVE); +cvar_t saved3 = CVARF("saved3", "0", CVAR_ARCHIVE); +cvar_t saved4 = CVARF("saved4", "0", CVAR_ARCHIVE); +cvar_t temp1 = CVARF("temp1", "0", CVAR_ARCHIVE); +cvar_t noexit = CVAR("noexit", "0"); +cvar_t pr_ssqc_memsize = CVAR("pr_ssqc_memsize", "-1"); /*cvars purely for compat with others*/ -cvar_t dpcompat_trailparticles = SCVAR("dpcompat_trailparticles", "0"); -cvar_t pr_imitatemvdsv = SCVARF("pr_imitatemvdsv", "0", CVAR_LATCH); +cvar_t dpcompat_trailparticles = CVAR("dpcompat_trailparticles", "0"); +cvar_t pr_imitatemvdsv = CVARF("pr_imitatemvdsv", "0", CVAR_LATCH); /*compat with frikqcc's arrays (ensures that unknown fields are at the same offsets*/ -cvar_t pr_fixbrokenqccarrays = SCVARF("pr_fixbrokenqccarrays", "1", CVAR_LATCH); +cvar_t pr_fixbrokenqccarrays = CVARF("pr_fixbrokenqccarrays", "1", CVAR_LATCH); /*other stuff*/ -cvar_t pr_maxedicts = SCVARF("pr_maxedicts", "2048", CVAR_LATCH); +cvar_t pr_maxedicts = CVARF("pr_maxedicts", "2048", CVAR_LATCH); -cvar_t pr_no_playerphysics = SCVARF("pr_no_playerphysics", "0", CVAR_LATCH); -cvar_t pr_no_parsecommand = SCVARF("pr_no_parsecommand", "0", 0); +cvar_t pr_no_playerphysics = CVARF("pr_no_playerphysics", "0", CVAR_LATCH); +cvar_t pr_no_parsecommand = CVARF("pr_no_parsecommand", "0", 0); cvar_t progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER); -cvar_t qc_nonetaccess = SCVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc. +cvar_t qc_nonetaccess = CVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc. -cvar_t pr_overridebuiltins = SCVAR("pr_overridebuiltins", "1"); +cvar_t pr_overridebuiltins = CVAR("pr_overridebuiltins", "1"); -cvar_t pr_compatabilitytest = SCVARF("pr_compatabilitytest", "0", CVAR_LATCH); +cvar_t pr_compatabilitytest = CVARF("pr_compatabilitytest", "0", CVAR_LATCH); -cvar_t pr_ssqc_coreonerror = SCVAR("pr_coreonerror", "1"); +cvar_t pr_ssqc_coreonerror = CVAR("pr_coreonerror", "1"); -cvar_t pr_droptofloorunits = SCVAR("pr_droptofloorunits", ""); +cvar_t pr_droptofloorunits = CVAR("pr_droptofloorunits", ""); -cvar_t sv_gameplayfix_honest_tracelines = SCVAR("sv_gameplayfix_honest_tracelines", "1"); -cvar_t sv_gameplayfix_blowupfallenzombies = SCVAR("sv_gameplayfix_blowupfallenzombies", "0"); +cvar_t sv_gameplayfix_honest_tracelines = CVAR("sv_gameplayfix_honest_tracelines", "1"); +cvar_t sv_gameplayfix_blowupfallenzombies = CVAR("sv_gameplayfix_blowupfallenzombies", "0"); extern cvar_t sv_gameplayfix_noairborncorpse; cvar_t sv_addon[MAXADDONS]; @@ -525,6 +526,10 @@ void PR_LoadGlabalStruct(void) static float dimension_send_default; static float zero_default; //static vec3_t vecwriteonly; // 523:16: warning: unused variable ‘vecwriteonly’ + static float input_buttons_default; + static float input_timelength_default; + static vec3_t input_angles_default; + static vec3_t input_movevalues_default; int i; int *v; nqglobalvars_t *pr_globals = pr_nqglobal_struct; @@ -593,12 +598,17 @@ void PR_LoadGlabalStruct(void) for (i = 0; i < NUM_SPAWN_PARMS; i++) spawnparamglobals[i] = (float *)PR_FindGlobal(svprogfuncs, va("parm%i", i+1), 0, NULL); -#define ensurefloat(name,var) if (!((nqglobalvars_t*)pr_globals)->name) ((nqglobalvars_t*)pr_globals)->name = &var; +#define ensureglobal(name,var) if (!((nqglobalvars_t*)pr_globals)->name) ((nqglobalvars_t*)pr_globals)->name = &var; // make sure these entries are always valid pointers - ensurefloat(dimension_send, dimension_send_default); - ensurefloat(trace_endcontents, writeonly); - ensurefloat(trace_surfaceflags, writeonly); + ensureglobal(dimension_send, dimension_send_default); + ensureglobal(trace_endcontents, writeonly); + ensureglobal(trace_surfaceflags, writeonly); + + ensureglobal(input_timelength, input_timelength_default); + ensureglobal(input_angles, input_angles_default); + ensureglobal(input_movevalues, input_movevalues_default); + ensureglobal(input_buttons, input_buttons_default); // qtest renames and missing variables if (!((nqglobalvars_t*)pr_globals)->V_trace_plane_normal) @@ -619,16 +629,16 @@ void PR_LoadGlabalStruct(void) if (!((nqglobalvars_t*)pr_globals)->trace_fraction) SV_Error("Could not find export trace_fraction in progs\n"); } - ensurefloat(serverflags, zero_default); - ensurefloat(total_secrets, zero_default); - ensurefloat(total_monsters, zero_default); - ensurefloat(found_secrets, zero_default); - ensurefloat(killed_monsters, zero_default); - ensurefloat(trace_allsolid, writeonly); - ensurefloat(trace_startsolid, writeonly); - ensurefloat(trace_plane_dist, writeonly); - ensurefloat(trace_inopen, writeonly); - ensurefloat(trace_inwater, writeonly); + ensureglobal(serverflags, zero_default); + ensureglobal(total_secrets, zero_default); + ensureglobal(total_monsters, zero_default); + ensureglobal(found_secrets, zero_default); + ensureglobal(killed_monsters, zero_default); + ensureglobal(trace_allsolid, writeonly); + ensureglobal(trace_startsolid, writeonly); + ensureglobal(trace_plane_dist, writeonly); + ensureglobal(trace_inopen, writeonly); + ensureglobal(trace_inwater, writeonly); pr_global_struct->dimension_send = 255; pr_global_struct->serverflags = 0; @@ -871,7 +881,7 @@ void PR_Decompile_f(void) if (!svprogfuncs) { Q_SetProgsParms(false); - PR_Configure(svprogfuncs, -1, MAX_PROGS); + PR_Configure(svprogfuncs, pr_ssqc_memsize.ival, MAX_PROGS); } @@ -884,7 +894,7 @@ void PR_Compile_f(void) { int argc=3; double time = Sys_DoubleTime(); - char *argv[64] = {"", "-src", "src", "-srcfile", "qwprogs.src"}; + char *argv[64] = {"", "-src", "src", "-srcfile", "progs.src"}; if (Cmd_Argc()>2) { @@ -943,7 +953,7 @@ void PR_ApplyCompilation_f (void) s = PR_SaveEnts(svprogfuncs, NULL, &len, 1); - PR_Configure(svprogfuncs, -1, MAX_PROGS); + PR_Configure(svprogfuncs, pr_ssqc_memsize.ival, MAX_PROGS); PR_RegisterFields(); PR_InitEnts(svprogfuncs, sv.world.max_edicts); @@ -1093,6 +1103,7 @@ void PR_Init(void) Cvar_Register (&pr_overridebuiltins, cvargroup_progs); Cvar_Register (&pr_ssqc_coreonerror, cvargroup_progs); + Cvar_Register (&pr_ssqc_memsize, cvargroup_progs); Cvar_Register (&pr_droptofloorunits, cvargroup_progs); @@ -1131,7 +1142,7 @@ void Q_InitProgs(void) // load progs to get entity field count - PR_Configure(svprogfuncs, -1, MAX_PROGS); + PR_Configure(svprogfuncs, pr_ssqc_memsize.ival, MAX_PROGS); PR_RegisterFields(); @@ -3683,6 +3694,12 @@ static void QCBUILTIN PF_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_ pr_global_struct->self = oldself; } +void PF_sv_touchtriggers(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + wedict_t *ent = (wedict_t*)PROG_TO_EDICT(prinst, pr_global_struct->self); + World_LinkEdict (&sv.world, ent, true); +} + /* =============== PF_droptofloor @@ -4953,6 +4970,8 @@ char *PF_infokey_Internal (int entnum, char *key) sprintf(ov, "%d", SV_CalcPing (&svs.clients[entnum-1], false)); else if (!strcmp(key, "svping")) sprintf(ov, "%d", SV_CalcPing (&svs.clients[entnum-1], true)); + else if (!strcmp(key, "guid")) + sprintf(ov, "%s", svs.clients[entnum-1].guid); else if (!strcmp(key, "*userid")) sprintf(ov, "%d", svs.clients[entnum-1].userid); else if (!strcmp(key, "download")) @@ -8424,9 +8443,9 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) if (host_client->state && host_client->protocol != SCP_BAD) { - sv_player->xv->movement[0] = ucmd->forwardmove * host_frametime; - sv_player->xv->movement[1] = ucmd->sidemove * host_frametime; - sv_player->xv->movement[2] = ucmd->upmove * host_frametime; + sv_player->xv->movement[0] = ucmd->forwardmove; + sv_player->xv->movement[1] = ucmd->sidemove; + sv_player->xv->movement[2] = ucmd->upmove; } SV_CheckVelocity(sv_player); @@ -9106,6 +9125,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"frameduration", PF_frameduration, 0, 0, 0, 277},//float(float modidx, float framenum) frameduration = #277 (FTE_CSQC_SKELETONOBJECTS) {"terrain_edit", PF_sv_terrain_edit, 0, 0, 0, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT?? + {"touchtriggers", PF_sv_touchtriggers,0, 0, 0, 279},//void() touchtriggers = #279; //EXT_CSQC // {"setmodelindex", PF_sv_SetModelIndex,0, 0, 0, 333}, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) @@ -9470,7 +9490,8 @@ void PR_ResetBuiltins(progstype_t type) //fix all nulls to PF_FIXME and add any if (type == PROG_QW && pr_imitatemvdsv.value>0) //pretend to be mvdsv for a bit. { - if (PR_EnableEBFSBuiltin("executecommand", 83) != 83 || + if ( + PR_EnableEBFSBuiltin("executecommand", 83) != 83 || PR_EnableEBFSBuiltin("mvdtokenize", 84) != 84 || PR_EnableEBFSBuiltin("mvdargc", 85) != 85 || PR_EnableEBFSBuiltin("mvdargv", 86) != 86 || diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 2589a951e..866d43cf9 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define GAME_API_VERSION 13 #define MAX_Q1QVM_EDICTS 768 //according to ktx at api version 12 (fte's protocols go to 2048) +#define MAPNAME_LEN 64 #define VMFSID_Q1QVM 57235 //a cookie @@ -1452,6 +1453,9 @@ qboolean PR_LoadQ1QVM(void) sv.world.progs = &q1qvmprogfuncs; sv.world.edicts = (wedict_t*)EDICT_NUM(svprogfuncs, 0); sv.world.usesolidcorpse = true; + + if ((unsigned)gd->global->mapname && (unsigned)gd->global->mapname+MAPNAME_LEN < VM_MemoryMask(q1qvm)) + Q_strncpyz((char*)VM_MemoryBase(q1qvm) + gd->global->mapname, sv.mapname, MAPNAME_LEN); return true; } diff --git a/engine/server/server.h b/engine/server/server.h index a3798f220..ec6e999f6 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -370,6 +370,7 @@ typedef struct client_s char *name; char namebuf[32]; // for printing to other people // extracted from userinfo + char guid[32]; int messagelevel; // for filtering printed messages // the datagram is written to after every frame, but only cleared @@ -504,6 +505,7 @@ typedef struct client_s #endif unsigned long zquake_extensions; unsigned int max_net_ents; + unsigned int maxmodels; /*max models supported by whatever the protocol is*/ enum { SCP_BAD, //don't send (a bot) diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index fe6316998..10a224f0a 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -503,7 +503,11 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb if (to->modelindex > 255) { if (protext & PEXT_MODELDBL) + { + if (to->modelindex > 512) + bits &= ~U_MODEL; evenmorebits |= U_MODELDBL; + } else return; } @@ -602,6 +606,9 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb if (bits & U_MODEL) MSG_WriteByte (msg, to->modelindex&255); + else if (evenmorebits & U_MODELDBL) + MSG_WriteShort(msg, to->modelindex); + if (bits & U_FRAME) MSG_WriteByte (msg, to->frame); if (bits & U_COLORMAP) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 04d90aa49..5347b399f 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1116,7 +1116,7 @@ void SVC_GetInfo (char *challenge, int fullstatus) //this is a DP protocol, so some QW fields are not needed Info_RemoveKey(resp, "maxclients"); Info_RemoveKey(resp, "map"); - Info_SetValueForKey(resp, "gamename", com_gamename.string, sizeof(response) - (resp-response)); + Info_SetValueForKey(resp, "gamename", com_protocolname.string, sizeof(response) - (resp-response)); Info_SetValueForKey(resp, "modname", com_modname.string, sizeof(response) - (resp-response)); Info_SetValueForKey(resp, "protocol", va("%d", NET_PROTOCOL_VERSION), sizeof(response) - (resp-response)); Info_SetValueForKey(resp, "clients", va("%d", numclients), sizeof(response) - (resp-response)); @@ -1673,6 +1673,7 @@ client_t *SVC_DirectConnect(void) int version; int challenge; int huffcrc = 0; + char guid[128] = ""; int maxpacketentities; @@ -1838,6 +1839,10 @@ client_t *SVC_DirectConnect(void) huffcrc = Q_atoi(Cmd_Argv(1)); Con_DPrintf("Client supports huffman compression. crc 0x%x\n", huffcrc); break; + case PROTOCOL_INFO_GUID: + Q_strncpyz(guid, Cmd_Argv(1), sizeof(guid)); + Con_DPrintf("GUID %s\n", Cmd_Argv(1)); + break; } } msg_badread=false; @@ -1914,6 +1919,7 @@ client_t *SVC_DirectConnect(void) newcl->fteprotocolextensions = protextsupported; newcl->fteprotocolextensions2 = protextsupported2; newcl->protocol = protocol; + Q_strncpyz(newcl->guid, guid, sizeof(newcl->guid)); if (protocol == SCP_QUAKEWORLD) //readd? { @@ -4681,7 +4687,7 @@ void SV_Init (quakeparms_t *parms) Con_Printf ("%s\n", version_string()); - Con_TPrintf (STL_INITED); + Con_TPrintf (STL_INITED, fs_gamename.string); i = COM_CheckParm("+gamedir"); if (i) diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 612615b83..d3727e00e 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -2176,8 +2176,8 @@ qboolean SV_Physics (void) SV_RunEntity(ent); SV_RunNewmis (); } - else - World_LinkEdict(&sv.world, (wedict_t*)ent, true); +// else +// World_LinkEdict(&sv.world, (wedict_t*)ent, true); continue; // clients are run directly from packets } diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 9560b7ae3..9c5e3ee6e 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -840,11 +840,12 @@ void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sam if (channel & 8) reliable = true; // sounds that break the phs are reliable use_phs = false; - channel &= 7; } else use_phs = attenuation!=0; + channel = (channel & 7) | ((channel & 0x1f0) >> 1); + // if (channel == CHAN_BODY || channel == CHAN_VOICE) // reliable = true; @@ -1491,7 +1492,7 @@ void SV_UpdateClientStats (client_t *client, int pnum) statsi[STAT_WEAPON] = SV_ModelIndex(PR_GetString(svprogfuncs, ent->v->weaponmodel)); if (host_client->fteprotocolextensions & PEXT_MODELDBL) { - if ((unsigned)statsi[STAT_WEAPON] >= 512) + if ((unsigned)statsi[STAT_WEAPON] >= MAX_MODELS) statsi[STAT_WEAPON] = 0; } else diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index c6687d349..8641e2b3b 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -957,7 +957,6 @@ void SV_Modellist_f (void) { unsigned int i; unsigned int n; - unsigned int maxclientsupportedmodels; if (host_client->state != cs_connected) { @@ -1041,10 +1040,10 @@ void SV_Modellist_f (void) MSG_WriteByte (&host_client->netchan.message, n); } - maxclientsupportedmodels = 256; + host_client->maxmodels = 256; #ifdef PEXT_MODELDBL if (host_client->fteprotocolextensions & PEXT_MODELDBL) - maxclientsupportedmodels *= 2; + host_client->maxmodels = MAX_MODELS; #endif #ifdef SERVER_DEMO_PLAYBACK @@ -1062,7 +1061,7 @@ void SV_Modellist_f (void) #endif { for (i = 1+n; - i < maxclientsupportedmodels && sv.strings.model_precache[i] && (((i-1)&255)==0 || host_client->netchan.message.cursize < (MAX_QWMSGLEN/2)); //make sure we don't send a 0 next... + i < host_client->maxmodels && sv.strings.model_precache[i] && (((i-1)&255)==0 || host_client->netchan.message.cursize < (MAX_QWMSGLEN/2)); //make sure we don't send a 0 next... i++) { MSG_WriteString (&host_client->netchan.message, sv.strings.model_precache[i]); @@ -1073,7 +1072,7 @@ void SV_Modellist_f (void) n = 0; } - if (i == maxclientsupportedmodels) + if (i == host_client->maxmodels) n = 0; //doh! MSG_WriteByte (&host_client->netchan.message, 0); @@ -4188,242 +4187,6 @@ void SV_STFU_f(void) ClientReliableWrite_String(host_client, msg); } -void SV_MVDList_f (void); -void SV_MVDInfo_f (void); -typedef struct -{ - char *name; - void (*func) (void); - qboolean noqchandling; -} ucmd_t; - -ucmd_t ucmds[] = -{ - {"new", SV_New_f, true}, - {"pk3list", SV_PK3List_f, true}, - {"modellist", SV_Modellist_f, true}, - {"soundlist", SV_Soundlist_f, true}, - {"prespawn", SV_PreSpawn_f, true}, - {"spawn", SV_Spawn_f, true}, - {"begin", SV_Begin_f, true}, - - {"al", SV_STFU_f, true}, - - {"join", Cmd_Join_f}, - {"observe", Cmd_Observe_f}, - - {"drop", SV_Drop_f}, - {"disconnect", SV_Drop_f}, - {"pings", SV_Pings_f}, - -// issued by hand at client consoles - {"rate", SV_Rate_f}, - {"kill", SV_Kill_f}, - {"pause", SV_Pause_f}, - {"msg", SV_Msg_f}, - - {"sayone", SV_SayOne_f}, - {"say", SV_Say_f}, - {"say_team", SV_Say_Team_f}, - - {"setinfo", SV_SetInfo_f}, - - {"serverinfo", SV_ShowServerinfo_f}, - - {"dlsize", SV_DownloadSize_f}, - {"download", SV_BeginDownload_f}, - {"nextdl", SV_NextDownload_f}, - - {"ptrack", SV_PTrack_f}, //ZOID - used with autocam - {"enablecsqc", SV_EnableClientsCSQC}, - {"disablecsqc", SV_DisableClientsCSQC}, - - {"snap", SV_NoSnap_f}, - {"vote", SV_Vote_f}, - -#ifdef SVRANKING - {"topten", Rank_ListTop10_f}, -#endif - - {"efpslist", Cmd_FPSList_f}, //don't conflict with the ktpro one - {"god", Cmd_God_f}, - {"give", Cmd_Give_f}, - {"noclip", Cmd_Noclip_f}, - {"fly", Cmd_Fly_f}, - {"notarget", Cmd_Notarget_f}, - {"setpos", Cmd_SetPos_f}, - - {"stopdownload", SV_StopDownload_f}, - {"demolist", SV_UserCmdMVDList_f}, - {"demoinfo", SV_MVDInfo_f}, - -#ifdef VOICECHAT - {"voicetarg", SV_Voice_Target_f}, - {"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/ - {"muteall", SV_Voice_MuteAll_f}, /*disables*/ - {"unmuteall", SV_Voice_UnmuteAll_f}, /*reenables*/ -#endif - - {NULL, NULL} -}; - -#ifdef Q2SERVER -ucmd_t ucmdsq2[] = { - {"new", SV_New_f, true}, - {"configstrings", SVQ2_ConfigStrings_f, true}, - {"baselines", SVQ2_BaseLines_f, true}, - {"begin", SV_Begin_f, true}, - -// {"setinfo", SV_SetInfo_f, true}, - - {"serverinfo", SV_ShowServerinfo_f, true}, - {"info", SV_ShowServerinfo_f, true}, - - {"download", SV_BeginDownload_f, true}, - {"nextdl", SV_NextDownload_f, true}, - - {"nextserver", SVQ2_NextServer_f, true}, - - {"vote", SV_Vote_f, true}, - -//#ifdef SVRANKING -// {"topten", Rank_ListTop10_f, true}, -//#endif - - {"drop", SV_Drop_f, true}, - {"disconnect", SV_Drop_f, true}, - - {NULL, NULL} -}; -#endif - -extern ucmd_t nqucmds[]; -/* -================== -SV_ExecuteUserCommand -================== -*/ -void SV_ExecuteUserCommand (char *s, qboolean fromQC) -{ - ucmd_t *u; - client_t *oldhost = host_client; - char adr[MAX_ADR_SIZE]; - - Con_DPrintf("Client command: %s\n", s); - - Cmd_TokenizeString (s, false, false); - sv_player = host_client->edict; - - Cmd_ExecLevel=1; - - if (host_client->controlled && atoi(Cmd_Argv(0))>0) //now see if it's meant to be from a slave client - { - int pnum = atoi(Cmd_Argv(0)); - client_t *s; - for (s = host_client; s; s = s->controlled) - { - if (!--pnum) - { - host_client = s; - break; - } - } - sv_player = host_client->edict; - Cmd_ShiftArgs(1, false); - } - -#ifdef Q2SERVER - if (ISQ2CLIENT(host_client)) - u = ucmdsq2; - else -#endif -#ifdef NQPROT - if (ISNQCLIENT(host_client)) - u = nqucmds; - else -#endif - u=ucmds; - - for ( ; u->name ; u++) - if (!strcmp (Cmd_Argv(0), u->name) ) - { - if (!fromQC && !u->noqchandling) - if (PR_KrimzonParseCommand(s)) //KRIMZON_SV_PARSECLIENTCOMMAND has the opertunity to parse out certain commands. - { - host_client = oldhost; - return; - } -// SV_BeginRedirect (RD_CLIENT, host_client->language); - if (u->func) - u->func (); - host_client = oldhost; -// SV_EndRedirect (); - return; - } - - if (!u->name) - { -#ifdef HLSERVER - if (HLSV_ClientCommand(host_client)) - { - host_client = oldhost; - return; - } -#endif - - if (!fromQC) - if (PR_UserCmd(s)) //Q2 and MVDSV command handling only happens if the engine didn't recognise it. - { - host_client = oldhost; - return; - } -#ifdef SVRANKING - if (sv_cmdlikercon.value && host_client->rankid) - { - char remaining[1024]; - int i; - rankstats_t stats; - - if (!Rank_GetPlayerStats(host_client->rankid, &stats)) - { - host_client = oldhost; - return; - } - - Con_Printf ("cmd from %s:\n%s\n" - , host_client->name, net_message.data+4); - - SV_BeginRedirect (RD_CLIENT, host_client->language); - - remaining[0] = 0; - - for (i=0 ; i=sizeof(remaining)-1) - { - Con_Printf("cmd was too long\n"); - host_client = oldhost; - SV_EndRedirect (); - Con_Printf ("cmd from %s:\n%s\n" - , NET_AdrToString (adr, sizeof(adr), net_from), "Was too long - possible buffer overflow attempt"); - return; - } - strcat (remaining, Cmd_Argv(i) ); - strcat (remaining, " "); - } - - Cmd_ExecuteString (remaining, stats.trustlevel); - host_client = oldhost; - SV_EndRedirect (); - return; - } -#endif - Con_Printf ("Bad user command: %s\n", Cmd_Argv(0)); - } - - host_client = oldhost; - SV_EndRedirect (); -} #ifdef NQPROT void SVNQ_Spawn_f (void) { @@ -4822,6 +4585,163 @@ void SV_Pext_f(void) SV_New_f(); } +/* +void SVNQ_ExecuteUserCommand (char *s) +{ + client_t *oldhost = host_client; + ucmd_t *u; + + Cmd_TokenizeString (s, false, false); + sv_player = host_client->edict; + + Cmd_ExecLevel=1; + + for (u=nqucmds ; u->name ; u++) + { + if (!strcmp (Cmd_Argv(0), u->name) ) + { + if (/ *!fromQC && * /!u->noqchandling) + if (PR_UserCmd(s)) + { + host_client = oldhost; + return; + } + + if (!u->func) + { + SV_BeginRedirect (RD_CLIENT, host_client->language); + Con_Printf("Command was disabled\n"); + SV_EndRedirect (); + } + else + { + SV_BeginRedirect (RD_CLIENT, host_client->language); + u->func (); + SV_EndRedirect (); + } + + host_client = oldhost; + return; + } + } + + if (!u->name) + Con_Printf("%s tried to \"%s\"\n", host_client->name, s); +} +*/ +#endif + + +void SV_MVDList_f (void); +void SV_MVDInfo_f (void); +typedef struct +{ + char *name; + void (*func) (void); + qboolean noqchandling; +} ucmd_t; + +ucmd_t ucmds[] = +{ + {"new", SV_New_f, true}, + {"pk3list", SV_PK3List_f, true}, + {"modellist", SV_Modellist_f, true}, + {"soundlist", SV_Soundlist_f, true}, + {"prespawn", SV_PreSpawn_f, true}, + {"spawn", SV_Spawn_f, true}, + {"begin", SV_Begin_f, true}, + + {"al", SV_STFU_f, true}, + + {"join", Cmd_Join_f}, + {"observe", Cmd_Observe_f}, + + {"drop", SV_Drop_f}, + {"disconnect", SV_Drop_f}, + {"pings", SV_Pings_f}, + +// issued by hand at client consoles + {"rate", SV_Rate_f}, + {"kill", SV_Kill_f}, + {"pause", SV_Pause_f}, + {"msg", SV_Msg_f}, + + {"sayone", SV_SayOne_f}, + {"say", SV_Say_f}, + {"say_team", SV_Say_Team_f}, + + {"setinfo", SV_SetInfo_f}, + + {"serverinfo", SV_ShowServerinfo_f}, + + {"dlsize", SV_DownloadSize_f}, + {"download", SV_BeginDownload_f}, + {"nextdl", SV_NextDownload_f}, + + {"ptrack", SV_PTrack_f}, //ZOID - used with autocam + {"enablecsqc", SV_EnableClientsCSQC}, + {"disablecsqc", SV_DisableClientsCSQC}, + + {"snap", SV_NoSnap_f}, + {"vote", SV_Vote_f}, + +#ifdef SVRANKING + {"topten", Rank_ListTop10_f}, +#endif + + {"efpslist", Cmd_FPSList_f}, //don't conflict with the ktpro one + {"god", Cmd_God_f}, + {"give", Cmd_Give_f}, + {"noclip", Cmd_Noclip_f}, + {"fly", Cmd_Fly_f}, + {"notarget", Cmd_Notarget_f}, + {"setpos", Cmd_SetPos_f}, + + {"stopdownload", SV_StopDownload_f}, + {"demolist", SV_UserCmdMVDList_f}, + {"demoinfo", SV_MVDInfo_f}, + +#ifdef VOICECHAT + {"voicetarg", SV_Voice_Target_f}, + {"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/ + {"muteall", SV_Voice_MuteAll_f}, /*disables*/ + {"unmuteall", SV_Voice_UnmuteAll_f}, /*reenables*/ +#endif + + {NULL, NULL} +}; + +#ifdef Q2SERVER +ucmd_t ucmdsq2[] = { + {"new", SV_New_f, true}, + {"configstrings", SVQ2_ConfigStrings_f, true}, + {"baselines", SVQ2_BaseLines_f, true}, + {"begin", SV_Begin_f, true}, + +// {"setinfo", SV_SetInfo_f, true}, + + {"serverinfo", SV_ShowServerinfo_f, true}, + {"info", SV_ShowServerinfo_f, true}, + + {"download", SV_BeginDownload_f, true}, + {"nextdl", SV_NextDownload_f, true}, + + {"nextserver", SVQ2_NextServer_f, true}, + + {"vote", SV_Vote_f, true}, + +//#ifdef SVRANKING +// {"topten", Rank_ListTop10_f, true}, +//#endif + + {"drop", SV_Drop_f, true}, + {"disconnect", SV_Drop_f, true}, + + {NULL, NULL} +}; +#endif + +#ifdef NQPROT ucmd_t nqucmds[] = { {"new", SVNQ_New_f, true}, @@ -4874,52 +4794,134 @@ ucmd_t nqucmds[] = {NULL, NULL} }; +#endif + /* -void SVNQ_ExecuteUserCommand (char *s) +================== +SV_ExecuteUserCommand +================== +*/ +void SV_ExecuteUserCommand (char *s, qboolean fromQC) { - client_t *oldhost = host_client; ucmd_t *u; + client_t *oldhost = host_client; + char adr[MAX_ADR_SIZE]; + + Con_DPrintf("Client command: %s\n", s); Cmd_TokenizeString (s, false, false); sv_player = host_client->edict; Cmd_ExecLevel=1; - for (u=nqucmds ; u->name ; u++) + if (host_client->controlled && atoi(Cmd_Argv(0))>0) //now see if it's meant to be from a slave client { + int pnum = atoi(Cmd_Argv(0)); + client_t *s; + for (s = host_client; s; s = s->controlled) + { + if (!--pnum) + { + host_client = s; + break; + } + } + sv_player = host_client->edict; + Cmd_ShiftArgs(1, false); + } + +#ifdef Q2SERVER + if (ISQ2CLIENT(host_client)) + u = ucmdsq2; + else +#endif +#ifdef NQPROT + if (ISNQCLIENT(host_client)) + u = nqucmds; + else +#endif + u=ucmds; + + for ( ; u->name ; u++) if (!strcmp (Cmd_Argv(0), u->name) ) { - if (/ *!fromQC && * /!u->noqchandling) - if (PR_UserCmd(s)) + if (!fromQC && !u->noqchandling) + if (PR_KrimzonParseCommand(s)) //KRIMZON_SV_PARSECLIENTCOMMAND has the opertunity to parse out certain commands. { host_client = oldhost; return; } - - if (!u->func) - { - SV_BeginRedirect (RD_CLIENT, host_client->language); - Con_Printf("Command was disabled\n"); - SV_EndRedirect (); - } - else - { - SV_BeginRedirect (RD_CLIENT, host_client->language); +// SV_BeginRedirect (RD_CLIENT, host_client->language); + if (u->func) u->func (); - SV_EndRedirect (); - } + host_client = oldhost; +// SV_EndRedirect (); + return; + } + if (!u->name) + { +#ifdef HLSERVER + if (HLSV_ClientCommand(host_client)) + { host_client = oldhost; return; } - } - - if (!u->name) - Con_Printf("%s tried to \"%s\"\n", host_client->name, s); -} -*/ #endif + if (!fromQC) + if (PR_UserCmd(s)) //Q2 and MVDSV command handling only happens if the engine didn't recognise it. + { + host_client = oldhost; + return; + } +#ifdef SVRANKING + if (sv_cmdlikercon.value && host_client->rankid) + { + char remaining[1024]; + int i; + rankstats_t stats; + + if (!Rank_GetPlayerStats(host_client->rankid, &stats)) + { + host_client = oldhost; + return; + } + + Con_Printf ("cmd from %s:\n%s\n" + , host_client->name, net_message.data+4); + + SV_BeginRedirect (RD_CLIENT, host_client->language); + + remaining[0] = 0; + + for (i=0 ; i=sizeof(remaining)-1) + { + Con_Printf("cmd was too long\n"); + host_client = oldhost; + SV_EndRedirect (); + Con_Printf ("cmd from %s:\n%s\n" + , NET_AdrToString (adr, sizeof(adr), net_from), "Was too long - possible buffer overflow attempt"); + return; + } + strcat (remaining, Cmd_Argv(i) ); + strcat (remaining, " "); + } + + Cmd_ExecuteString (remaining, stats.trustlevel); + host_client = oldhost; + SV_EndRedirect (); + return; + } +#endif + Con_Printf ("Bad user command: %s\n", Cmd_Argv(0)); + } + + host_client = oldhost; + SV_EndRedirect (); +} int implevels[256]; qboolean SV_FilterImpulse(int imp, int level) diff --git a/engine/server/svmodel.c b/engine/server/svmodel.c index 98f19b445..1347d1af6 100644 --- a/engine/server/svmodel.c +++ b/engine/server/svmodel.c @@ -111,7 +111,7 @@ int SVQ1_RecursiveLightPoint3C (model_t *model, mnode_t *node, vec3_t start, vec tex = surf->texinfo; s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; - t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; + t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3]; if (s < surf->texturemins[0] || t < surf->texturemins[1]) @@ -126,23 +126,20 @@ int SVQ1_RecursiveLightPoint3C (model_t *model, mnode_t *node, vec3_t start, vec if (!surf->samples) return 0; - ds >>= 4; - dt >>= 4; - lightmap = surf->samples; r = 0; if (lightmap) { - lightmap += (dt * ((surf->extents[0]>>4)+1) + ds)*3; + lightmap += (dt * ((surf->extents[0])+1) + ds)*3; for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; maps++) { scale = sv.strings.lightstyles[surf->styles[maps]][0]; r += (lightmap[0]+lightmap[1]+lightmap[2])/3 * scale; - lightmap += ((surf->extents[0]>>4)+1) * - ((surf->extents[1]>>4)+1)*3; + lightmap += ((surf->extents[0])+1) * + ((surf->extents[1])+1)*3; } r >>= 8; @@ -1018,8 +1015,8 @@ void CalcSurfaceExtents (msurface_t *s); bmins[i] = floor(mins[i]/16); bmaxs[i] = ceil(maxs[i]/16); - s->texturemins[i] = bmins[i] * 16; - s->extents[i] = (bmaxs[i] - bmins[i]) * 16; + s->texturemins[i] = bmins[i]; + s->extents[i] = (bmaxs[i] - bmins[i]); // if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256) // SV_Error ("Bad surface extents"); }