first attempt at webvr support. probably totally crap.
fix hitmodel with skeletal models(can also now support lerps, skeletal objects, etc). more hlmdl fixes for eukara, including hitboxes. modelviewer can now display bones. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5033 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
ebd1f75634
commit
03d96bff72
27 changed files with 961 additions and 267 deletions
|
@ -565,7 +565,6 @@ D3DGL_OBJS = \
|
|||
gl_shader.o \
|
||||
gl_shadow.o \
|
||||
gl_rlight.o \
|
||||
gl_hlmdl.o \
|
||||
gl_warp.o \
|
||||
ltface.o \
|
||||
r_surf.o \
|
||||
|
@ -655,6 +654,7 @@ WINDOWS_OBJS = \
|
|||
|
||||
COMMON_OBJS = \
|
||||
gl_alias.o \
|
||||
gl_hlmdl.o \
|
||||
gl_heightmap.o \
|
||||
gl_model.o \
|
||||
com_mesh.o \
|
||||
|
|
|
@ -5257,6 +5257,10 @@ double Host_Frame (double time)
|
|||
scr_chatmode = 0;
|
||||
|
||||
r_refdef.stereomethod = r_stereo_method.ival;
|
||||
#ifdef FTE_TARGET_WEB
|
||||
if (emscriptenfte_getvrframedata())
|
||||
r_refdef.stereomethod = STEREO_WEBVR;
|
||||
#endif
|
||||
CL_UpdateHeadAngles();
|
||||
|
||||
{
|
||||
|
|
|
@ -2759,11 +2759,13 @@ typedef struct
|
|||
MV_NONE,
|
||||
MV_BONES,
|
||||
MV_SHADER,
|
||||
MV_TEXTURE
|
||||
MV_TEXTURE,
|
||||
MV_COLLISION
|
||||
} mode;
|
||||
int surfaceidx;
|
||||
int skingroup;
|
||||
int framegroup;
|
||||
int boneidx;
|
||||
double framechangetime;
|
||||
double skinchangetime;
|
||||
float pitch;
|
||||
|
@ -2805,7 +2807,7 @@ static unsigned int genhsv(float h_, float s, float v)
|
|||
|
||||
#include "com_mesh.h"
|
||||
#ifdef SKELETALMODELS
|
||||
static void M_BoneDisplayLame(entity_t *e, int *y, int depth, int parent, int first, int last)
|
||||
static void M_BoneDisplayLame(entity_t *e, int *y, int depth, int parent, int first, int last, int sel)
|
||||
{
|
||||
int i;
|
||||
for (i = first; i < last; i++)
|
||||
|
@ -2819,11 +2821,17 @@ static void M_BoneDisplayLame(entity_t *e, int *y, int depth, int parent, int fi
|
|||
bname = "NULL";
|
||||
memset(result, 0, sizeof(result));
|
||||
if (Mod_GetTag(e->model, i+1, &e->framestate, result))
|
||||
Draw_FunString(depth*16, *y, va("%i: %s (%g %g %g)", i, bname, result[3], result[7], result[11]));
|
||||
{
|
||||
#if 0//def _DEBUG
|
||||
Draw_FunString(depth*16, *y, va("%s%i: %s (%g %g %g)", (i==sel)?"^1":"", i, bname, result[3], result[7], result[11]));
|
||||
#else
|
||||
Draw_FunString(depth*16, *y, va("%s%i: %s", (i==sel)?"^1":"", i, bname));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
Draw_FunString(depth*16, *y, va("%i: %s", i, bname));
|
||||
Draw_FunString(depth*16, *y, va("%s%i: %s (err)", (i==sel)?"^1":"", i, bname));
|
||||
*y += 8;
|
||||
M_BoneDisplayLame(e, y, depth+1, i+1, i+1, last);
|
||||
M_BoneDisplayLame(e, y, depth+1, i+1, i+1, last, sel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2893,33 +2901,166 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
ent.framestate.g[FS_REG].lerpweight[0] = 1;
|
||||
ent.framestate.g[FS_REG].frame[0] = mods->framegroup;
|
||||
ent.framestate.g[FS_REG].frametime[0] = ent.framestate.g[FS_REG].frametime[1] = realtime - mods->framechangetime;
|
||||
ent.framestate.g[FS_REG].endbone = 0x7fffffff;
|
||||
ent.customskin = Mod_RegisterSkinFile(va("%s_0.skin", mods->modelname));
|
||||
|
||||
// ent.framestate.bonecount = Mod_GetNumBones(ent.model, false);
|
||||
// ent.framestate.bonestate = bones;
|
||||
// ent.framestate.bonecount = Mod_GetBoneRelations(ent.model, 0, MAX_BONES, &ent.framestate, ent.framestate.bonestate);
|
||||
// ent.framestate.skeltype = SKEL_RELATIVE;
|
||||
|
||||
ent.light_avg[0] = ent.light_avg[1] = ent.light_avg[2] = 0.66;
|
||||
ent.light_range[0] = ent.light_range[1] = ent.light_range[2] = 0.33;
|
||||
ent.light_dir[0] = 0; ent.light_dir[1] = 1; ent.light_dir[2] = 0;
|
||||
ent.light_known = 2;
|
||||
|
||||
|
||||
// ent.angles[0]*=-1;
|
||||
AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]);
|
||||
VectorInverse(ent.axis[1]);
|
||||
// ent.angles[0]*=-1;
|
||||
|
||||
if (ent.model->type == mod_dummy)
|
||||
{
|
||||
Draw_FunString(0, 0, va("model \"%s\" not loaded", ent.model->name));
|
||||
return;
|
||||
}
|
||||
switch(ent.model->loadstate)
|
||||
{
|
||||
case MLS_LOADED:
|
||||
break;
|
||||
case MLS_NOTLOADED:
|
||||
Draw_FunString(0, 0, va("%s not loaded", ent.model->name));
|
||||
Draw_FunString(0, 0, va("\"%s\" not loaded", ent.model->name));
|
||||
return;
|
||||
case MLS_LOADING:
|
||||
Draw_FunString(0, 0, va("%s still loading", ent.model->name));
|
||||
Draw_FunString(0, 0, va("\"%s\" still loading", ent.model->name));
|
||||
return;
|
||||
case MLS_FAILED:
|
||||
Draw_FunString(0, 0, va("Unable to load %s", ent.model->name));
|
||||
Draw_FunString(0, 0, va("Unable to load \"%s\"", ent.model->name));
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
ent.framestate.bonestate = bones;
|
||||
ent.framestate.bonecount = Mod_GetBoneRelations(ent.model, 0, MAX_BONES, &ent.framestate, ent.framestate.bonestate);
|
||||
ent.framestate.skeltype = SKEL_RELATIVE;
|
||||
#endif
|
||||
|
||||
|
||||
if (mods->mode == MV_COLLISION)
|
||||
{
|
||||
shader_t *s = R_RegisterShader("bboxshader_nodepth", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
"map $whiteimage\n"
|
||||
"blendfunc gl_src_alpha gl_one\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"nodepthtest\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
|
||||
#ifdef HALFLIFEMODELS
|
||||
if (ent.model->type == mod_halflife)
|
||||
HLMDL_DrawHitBoxes(&ent);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
vec3_t mins, maxs;
|
||||
VectorAdd(ent.model->mins, ent.origin, mins);
|
||||
VectorAdd(ent.model->maxs, ent.origin, maxs);
|
||||
CLQ1_AddOrientedCube(s, mins, maxs, NULL, 1, 1, 1, 0.2);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
trace_t tr;
|
||||
vec3_t v1, v2;
|
||||
VectorSet(v1, 1000*sin(realtime*2*M_PI/180), 1000*cos(realtime*2*M_PI/180), -ent.origin[2]);
|
||||
VectorScale(v1, -1, v2);
|
||||
v2[2] = v1[2];
|
||||
s = R_RegisterShader("bboxshader", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
"map $whiteimage\n"
|
||||
"blendfunc gl_src_alpha gl_one\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
|
||||
if (ent.model->funcs.NativeTrace(ent.model, 0, &ent.framestate, NULL, v1, v2, vec3_origin, vec3_origin, false, ~0, &tr))
|
||||
{
|
||||
vec3_t dir;
|
||||
float f;
|
||||
|
||||
VectorAdd(v1, ent.origin, v1);
|
||||
VectorAdd(v2, ent.origin, v2);
|
||||
VectorAdd(tr.endpos, ent.origin, tr.endpos);
|
||||
|
||||
VectorSubtract(tr.endpos, v1, dir);
|
||||
f = DotProduct(dir, tr.plane.normal) * -2;
|
||||
VectorMA(dir, f, tr.plane.normal, v2);
|
||||
VectorAdd(v2, tr.endpos, v2);
|
||||
|
||||
CLQ1_DrawLine(s, v1, tr.endpos, 0, 1, 0, 1);
|
||||
CLQ1_DrawLine(s, tr.endpos, v2, 1, 0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorAdd(v1, ent.origin, v1);
|
||||
VectorAdd(v2, ent.origin, v2);
|
||||
CLQ1_DrawLine(s, v1, v2, 0, 1, 0, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (mods->mode == MV_BONES)
|
||||
{
|
||||
shader_t *lineshader;
|
||||
int tags = Mod_GetNumBones(ent.model, true);
|
||||
int b;
|
||||
//if (ragdoll)
|
||||
// ent->frame[] |= 0x8000;
|
||||
//rag_updatedeltaent(&ent, le);
|
||||
|
||||
lineshader = R_RegisterShader("lineshader_nodepth", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
"map $whiteimage\n"
|
||||
"blendfunc add\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"nodepthtest\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
for (b = 1; b <= tags; b++)
|
||||
{
|
||||
int p = Mod_GetBoneParent(ent.model, b);
|
||||
vec3_t start, end;
|
||||
float boneinfo[12];
|
||||
|
||||
Mod_GetTag(ent.model, b, &ent.framestate, boneinfo);
|
||||
VectorSet(start, boneinfo[3], boneinfo[7], boneinfo[11]);
|
||||
VectorAdd(start, ent.origin, start);
|
||||
|
||||
if (p)
|
||||
{
|
||||
Mod_GetTag(ent.model, p, &ent.framestate, boneinfo);
|
||||
VectorSet(end, boneinfo[3], boneinfo[7], boneinfo[11]);
|
||||
VectorAdd(end, ent.origin, end);
|
||||
CLQ1_DrawLine(lineshader, start, end, 1, (b-1 == mods->boneidx)?0:1, 1, 1);
|
||||
}
|
||||
if (b-1 == mods->boneidx)
|
||||
{
|
||||
VectorSet(end, start[0]+1, start[1], start[2]);
|
||||
CLQ1_DrawLine(lineshader, start, end, 1, 0, 0, 1);
|
||||
VectorSet(end, start[0], start[1]+1, start[2]);
|
||||
CLQ1_DrawLine(lineshader, start, end, 0, 1, 0, 1);
|
||||
VectorSet(end, start[0], start[1], start[2]+1);
|
||||
CLQ1_DrawLine(lineshader, start, end, 0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
V_AddEntity(&ent);
|
||||
|
||||
V_ApplyRefdef();
|
||||
|
@ -2966,15 +3107,24 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
"mins: %g %g %g, maxs: %g %g %g\n", ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2])
|
||||
, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs);
|
||||
break;
|
||||
case MV_COLLISION:
|
||||
if (ent.model->type != mod_halflife)
|
||||
{
|
||||
R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+y, r_refdef.grect.width, r_refdef.grect.height-y,
|
||||
va("mins: %g %g %g, maxs: %g %g %g\n", ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2])
|
||||
, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs);
|
||||
break;
|
||||
}
|
||||
//fallthrough
|
||||
case MV_BONES:
|
||||
#ifdef SKELETALMODELS
|
||||
{
|
||||
int bonecount = Mod_GetNumBones(ent.model, false);
|
||||
int bonecount = Mod_GetNumBones(ent.model, true);
|
||||
if (bonecount)
|
||||
{
|
||||
Draw_FunString(0, y, va("Bones: "));
|
||||
y+=8;
|
||||
M_BoneDisplayLame(&ent, &y, 0, 0, 0, bonecount);
|
||||
M_BoneDisplayLame(&ent, &y, 0, 0, 0, bonecount, mods->boneidx);
|
||||
}
|
||||
else
|
||||
R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+y, r_refdef.grect.width, r_refdef.grect.height-y, "No bones in model", CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs);
|
||||
|
@ -3030,10 +3180,11 @@ static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int k
|
|||
mods->shadertext = NULL;
|
||||
switch (mods->mode)
|
||||
{
|
||||
case MV_NONE: mods->mode = MV_BONES; break;
|
||||
case MV_BONES: mods->mode = MV_SHADER; break;
|
||||
case MV_SHADER: mods->mode = MV_TEXTURE;break;
|
||||
case MV_TEXTURE: mods->mode = MV_NONE; break;
|
||||
case MV_NONE: mods->mode = MV_BONES; break;
|
||||
case MV_BONES: mods->mode = MV_SHADER; break;
|
||||
case MV_SHADER: mods->mode = MV_TEXTURE; break;
|
||||
case MV_TEXTURE: mods->mode = MV_COLLISION; break;
|
||||
case MV_COLLISION: mods->mode = MV_NONE; break;
|
||||
}
|
||||
}
|
||||
else if (key == 'r')
|
||||
|
@ -3041,6 +3192,10 @@ static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int k
|
|||
mods->framechangetime = realtime;
|
||||
mods->skinchangetime = realtime;
|
||||
}
|
||||
else if (key == '[')
|
||||
mods->boneidx--;
|
||||
else if (key == ']')
|
||||
mods->boneidx++;
|
||||
else if (key == K_UPARROW)
|
||||
mods->pitch += 5;
|
||||
else if (key == K_DOWNARROW)
|
||||
|
|
|
@ -973,7 +973,7 @@ return;
|
|||
D3_RecursiveSurfCheck (node->child[side^1], midf, p2f, mid, p2);
|
||||
}
|
||||
|
||||
static qboolean D3_Trace (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int hitcontentsmask, struct trace_s *trace)
|
||||
static qboolean D3_Trace (struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int hitcontentsmask, struct trace_s *trace)
|
||||
{
|
||||
int i;
|
||||
float e1,e2;
|
||||
|
|
|
@ -845,7 +845,7 @@ entity_t *TraceLineR (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal)
|
|||
|
||||
VectorSubtract(start, pe->origin, ts);
|
||||
VectorSubtract(end, pe->origin, te);
|
||||
pe->model->funcs.NativeTrace(pe->model, 0, pe->framestate.g[FS_REG].frame[pe->framestate.g[FS_REG].lerpweight[1] > pe->framestate.g[FS_REG].lerpweight[0]], pe->axis, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace);
|
||||
pe->model->funcs.NativeTrace(pe->model, 0, &pe->framestate, pe->axis, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace);
|
||||
if (trace.fraction<1)
|
||||
{
|
||||
VectorSubtract(trace.endpos, ts, delta);
|
||||
|
|
|
@ -215,6 +215,10 @@ typedef enum {
|
|||
STEREO_RED_GREEN,
|
||||
STEREO_CROSSEYED,
|
||||
|
||||
#ifdef FTE_TARGET_WEB
|
||||
STEREO_WEBVR,
|
||||
#endif
|
||||
|
||||
//these are internal methods and do not form part of any public API
|
||||
STEREO_LEFTONLY,
|
||||
STEREO_RIGHTONLY
|
||||
|
|
|
@ -1178,6 +1178,10 @@ void V_ApplyAFov(playerview_t *pv)
|
|||
afov = bound(0.001, afov, 170);
|
||||
|
||||
ws = 1;
|
||||
#ifdef FTE_TARGET_WEB
|
||||
if (r_refdef.stereomethod == STEREO_WEBVR)
|
||||
ws = 0.5;
|
||||
#endif
|
||||
if (r_refdef.stereomethod == STEREO_CROSSEYED && r_stereo_separation.value)
|
||||
ws = 0.5;
|
||||
|
||||
|
|
|
@ -460,7 +460,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#undef Q2CLIENT
|
||||
#undef Q3CLIENT
|
||||
#undef HLCLIENT
|
||||
#undef HALFLIFEMODELS
|
||||
#undef VM_UI
|
||||
#undef VM_CG
|
||||
#undef TEXTEDITOR
|
||||
|
|
|
@ -335,39 +335,76 @@ static void PSKGenMatrix(float x, float y, float z, float qx, float qy, float qz
|
|||
/*transforms some skeletal vecV_t values*/
|
||||
static void Alias_TransformVerticies_V(const float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *fte_restrict xyzout)
|
||||
{
|
||||
int i;
|
||||
const 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)
|
||||
#if 1
|
||||
int i, j;
|
||||
const float *matrix, *matrix1;
|
||||
float mat[12];
|
||||
for (i = 0; i < vertcount; i++, 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 (weights[1])
|
||||
{
|
||||
matrix1 = &bonepose[12*bidx[1]];
|
||||
for (j = 0; j < 12; j++)
|
||||
mat[j] = (weights[0] * matrix[j]) + (weights[1] * matrix1[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]);
|
||||
xyzout+=sizeof(vecV_t)/sizeof(vec_t);
|
||||
xyzin+=sizeof(vecV_t)/sizeof(vec_t);
|
||||
}
|
||||
#else
|
||||
int i;
|
||||
const float *matrix;
|
||||
for (i = 0; i < vertcount; i++, 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] + matrix[ 3]);
|
||||
xyzout[1] = weights[0] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + matrix[ 7]);
|
||||
xyzout[2] = weights[0] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + matrix[11]);
|
||||
|
||||
if (weights[1])
|
||||
{
|
||||
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]);
|
||||
xyzout[0] += weights[1] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + matrix[ 3]);
|
||||
xyzout[1] += weights[1] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + matrix[ 7]);
|
||||
xyzout[2] += weights[1] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + matrix[11]);
|
||||
|
||||
if (weights[2])
|
||||
{
|
||||
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]);
|
||||
xyzout[0] += weights[2] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + matrix[ 3]);
|
||||
xyzout[1] += weights[2] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + matrix[ 7]);
|
||||
xyzout[2] += weights[2] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + matrix[11]);
|
||||
|
||||
if (weights[3])
|
||||
{
|
||||
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]);
|
||||
xyzout[0] += weights[3] * (xyzin[0] * matrix[0] + xyzin[1] * matrix[1] + xyzin[2] * matrix[ 2] + matrix[ 3]);
|
||||
xyzout[1] += weights[3] * (xyzin[0] * matrix[4] + xyzin[1] * matrix[5] + xyzin[2] * matrix[ 6] + matrix[ 7]);
|
||||
xyzout[2] += weights[3] * (xyzin[0] * matrix[8] + xyzin[1] * matrix[9] + xyzin[2] * matrix[10] + matrix[11]);
|
||||
}
|
||||
}
|
||||
}
|
||||
xyzout+=sizeof(vecV_t)/sizeof(vec_t);
|
||||
xyzin+=sizeof(vecV_t)/sizeof(vec_t);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*transforms some skeletal vecV_t values*/
|
||||
|
@ -1214,16 +1251,15 @@ static void Alias_BuildSkeletalMesh(mesh_t *mesh, framestate_t *framestate, gali
|
|||
);
|
||||
}
|
||||
|
||||
static void Alias_BuildSkeletalVPositionsPose(float *xyzout, skeltype_t bonetype, const float *bonepose, galiasinfo_t *inf)
|
||||
static void Alias_BuildSkeletalVerts(float *xyzout, framestate_t *framestate, galiasinfo_t *inf)
|
||||
{
|
||||
float buffer[MAX_BONES*12];
|
||||
float bufferalt[MAX_BONES*12];
|
||||
qbyte *fte_restrict bidx = inf->ofs_skel_idx[0];
|
||||
float *fte_restrict xyzin = inf->ofs_skel_xyz[0];
|
||||
float *fte_restrict weight = inf->ofs_skel_weight[0];
|
||||
bonepose = Alias_ConvertBoneData(bonetype, bonepose, inf->numbones, inf->ofsbones, SKEL_INVERSE_ABSOLUTE, buffer, bufferalt, MAX_BONES);
|
||||
const float *bonepose = Alias_GetBoneInformation(inf, framestate, SKEL_INVERSE_ABSOLUTE, buffer, bufferalt, MAX_BONES);
|
||||
|
||||
Alias_TransformVerticies_V(bonepose, inf->numverts, bidx, weight, xyzin, xyzout);
|
||||
Alias_TransformVerticies_V(bonepose, inf->numverts, bidx, weight, inf->ofs_skel_xyz[0], xyzout);
|
||||
}
|
||||
|
||||
#if defined(MD5MODELS) || defined(ZYMOTICMODELS) || defined(DPMMODELS)
|
||||
|
@ -1908,21 +1944,34 @@ qboolean Mod_Trace_Trisoup(vecV_t *posedata, index_t *indexes, int numindexes, v
|
|||
float frac;
|
||||
|
||||
vec3_t impactpoint;
|
||||
// shader_t *lineshader = NULL;
|
||||
|
||||
for (i = 0; i < numindexes; i+=3)
|
||||
{
|
||||
p1 = posedata[indexes[i+0]];
|
||||
p2 = posedata[indexes[i+1]];
|
||||
p3 = posedata[indexes[i+2]];
|
||||
/*
|
||||
VectorAdd(p1, r_refdef.pvsorigin, edge1);
|
||||
VectorAdd(p2, r_refdef.pvsorigin, edge2);
|
||||
VectorAdd(p3, r_refdef.pvsorigin, edge3);
|
||||
CLQ1_DrawLine(lineshader, edge1, edge2, 0, 0, 1, 1);
|
||||
CLQ1_DrawLine(lineshader, edge2, edge3, 0, 0, 1, 1);
|
||||
CLQ1_DrawLine(lineshader, edge3, edge1, 0, 0, 1, 1);
|
||||
*/
|
||||
|
||||
#if 0
|
||||
{
|
||||
shader_t *lineshader = R_RegisterShader("lineshader", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
"map $whiteimage\n"
|
||||
"blendfunc add\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
VectorAdd(p1, r_refdef.pvsorigin, edge1);
|
||||
VectorAdd(p2, r_refdef.pvsorigin, edge2);
|
||||
VectorAdd(p3, r_refdef.pvsorigin, edge3);
|
||||
CLQ1_DrawLine(lineshader, edge1, edge2, 0, 1, 0, 1);
|
||||
CLQ1_DrawLine(lineshader, edge2, edge3, 0, 1, 0, 1);
|
||||
CLQ1_DrawLine(lineshader, edge3, edge1, 0, 1, 0, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
VectorSubtract(p1, p2, edge1);
|
||||
VectorSubtract(p3, p2, edge2);
|
||||
CrossProduct(edge1, edge2, normal);
|
||||
|
@ -2029,30 +2078,32 @@ qboolean Mod_Trace_Trisoup(vecV_t *posedata, index_t *indexes, int numindexes, v
|
|||
// if (fabs(normal[0]) != 1 && fabs(normal[1]) != 1 && fabs(normal[2]) != 1)
|
||||
// Con_Printf("Non-axial impact\n");
|
||||
|
||||
/* if (!lineshader)
|
||||
lineshader = R_RegisterShader("lineshader", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
"map $whiteimage\n"
|
||||
"blendfunc add\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
VectorAdd(p1, r_refdef.pvsorigin, edge1);
|
||||
VectorAdd(p2, r_refdef.pvsorigin, edge2);
|
||||
VectorAdd(p3, r_refdef.pvsorigin, edge3);
|
||||
CLQ1_DrawLine(lineshader, edge1, edge2, 0, 1, 0, 1);
|
||||
CLQ1_DrawLine(lineshader, edge2, edge3, 0, 1, 0, 1);
|
||||
CLQ1_DrawLine(lineshader, edge3, edge1, 0, 1, 0, 1);
|
||||
*/
|
||||
#if 0
|
||||
{
|
||||
shader_t *lineshader = R_RegisterShader("lineshader", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
"map $whiteimage\n"
|
||||
"blendfunc add\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
VectorAdd(p1, r_refdef.pvsorigin, edge1);
|
||||
VectorAdd(p2, r_refdef.pvsorigin, edge2);
|
||||
VectorAdd(p3, r_refdef.pvsorigin, edge3);
|
||||
CLQ1_DrawLine(lineshader, edge1, edge2, 0, 1, 0, 1);
|
||||
CLQ1_DrawLine(lineshader, edge2, edge3, 0, 1, 0, 1);
|
||||
CLQ1_DrawLine(lineshader, edge3, edge1, 0, 1, 0, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return impacted;
|
||||
}
|
||||
|
||||
//The whole reason why model loading is supported in the server.
|
||||
qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contentsmask, trace_t *trace)
|
||||
qboolean Mod_Trace(model_t *model, int forcehullnum, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contentsmask, trace_t *trace)
|
||||
{
|
||||
galiasinfo_t *mod = Mod_Extradata(model);
|
||||
galiasanimation_t *group;
|
||||
|
@ -2089,36 +2140,33 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3],
|
|||
for(; mod; mod = mod->nextsurf, surfnum++)
|
||||
{
|
||||
indexes = mod->ofs_indexes;
|
||||
if (!mod->numanimations)
|
||||
{
|
||||
#ifdef SKELETALMODELS
|
||||
//certain models have no possibility of animation.
|
||||
//fixme: skeletal objects...
|
||||
if (mod->ofs_skel_xyz)
|
||||
posedata = mod->ofs_skel_xyz;
|
||||
else
|
||||
#endif
|
||||
continue;
|
||||
if (mod->numbones)
|
||||
{
|
||||
if (!mod->ofs_skel_idx)
|
||||
posedata = mod->ofs_skel_xyz; //if there's no weights, don't try animating anything.
|
||||
else if (mod->shares_verts != cursurfnum)
|
||||
{
|
||||
cursurfnum = mod->shares_verts;
|
||||
|
||||
posedata = alloca(mod->numverts*sizeof(vecV_t));
|
||||
Alias_BuildSkeletalVerts((float*)posedata, framestate, mod);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!mod->numanimations)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
group = mod->ofsanimations;
|
||||
group += frame % mod->numanimations;
|
||||
group += framestate->g[FS_REG].frame[0] % mod->numanimations;
|
||||
//FIXME: no support for frame blending.
|
||||
if (!group->numposes)
|
||||
continue;
|
||||
pose = group->poseofs;
|
||||
pose += 0%group->numposes; //FIXME: no framegroup support
|
||||
pose += (int)(framestate->g[FS_REG].frametime[0] * group->rate)%group->numposes;
|
||||
posedata = pose->ofsverts;
|
||||
#ifdef SKELETALMODELS
|
||||
if (mod->numbones && mod->shares_verts != cursurfnum)
|
||||
{
|
||||
posedata = alloca(mod->numverts*sizeof(vecV_t));
|
||||
Alias_BuildSkeletalVPositionsPose((float*)posedata, group->skeltype, group->boneofs, mod);
|
||||
|
||||
cursurfnum = mod->shares_verts;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
trace->truefraction = 1;
|
||||
|
@ -3878,7 +3926,7 @@ int Mod_GetNumBones(model_t *model, qboolean allowtags)
|
|||
}
|
||||
#ifdef HALFLIFEMODELS
|
||||
if (model && model->type == mod_halflife)
|
||||
return HLMDL_GetNumBones(model);
|
||||
return HLMDL_GetNumBones(model, allowtags);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -3970,13 +4018,14 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res
|
|||
#ifdef HALFLIFEMODELS
|
||||
if (model && model->type == mod_halflife)
|
||||
{
|
||||
int numbones = Mod_GetNumBones(model, false);
|
||||
int numbones = Mod_GetNumBones(model, true);
|
||||
if (tagnum > 0 && tagnum <= numbones)
|
||||
{
|
||||
float relatives[MAX_BONES*12];
|
||||
float tempmatrix[12]; //flipped between this and bonematrix
|
||||
float *matrix; //the matrix for a single bone in a single pose.
|
||||
float *lerps = relatives;
|
||||
int k;
|
||||
|
||||
if (tagnum <= 0 || tagnum > numbones)
|
||||
return false;
|
||||
|
@ -3985,7 +4034,10 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res
|
|||
//data comes from skeletal object, if possible
|
||||
if (fstate->bonestate)
|
||||
{
|
||||
if (tagnum >= fstate->bonecount)
|
||||
numbones = fstate->bonecount;
|
||||
lerps = fstate->bonestate;
|
||||
|
||||
if (tagnum >= numbones)
|
||||
return false;
|
||||
|
||||
if (fstate->skeltype == SKEL_ABSOLUTE)
|
||||
|
@ -3993,19 +4045,21 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res
|
|||
memcpy(result, fstate->bonestate + 12 * tagnum, 12*sizeof(*result));
|
||||
return true;
|
||||
}
|
||||
|
||||
lerps = fstate->bonestate;
|
||||
}
|
||||
else //try getting the data from the frame state
|
||||
{
|
||||
numbones = Mod_GetBoneRelations(model, 0, tagnum+1, fstate, relatives);
|
||||
lerps = relatives;
|
||||
|
||||
//make sure it was all okay.
|
||||
if (tagnum >= numbones)
|
||||
return false;
|
||||
}
|
||||
|
||||
//set up the identity matrix
|
||||
for (k = 0;k < 12;k++)
|
||||
result[k] = 0;
|
||||
result[0] = 1;
|
||||
result[5] = 1;
|
||||
result[10] = 1;
|
||||
if (tagnum >= numbones)
|
||||
tagnum = HLMDL_GetAttachment(model, tagnum-numbones, result);
|
||||
while(tagnum >= 0)
|
||||
{
|
||||
//set up the per-bone transform matrix
|
||||
|
@ -6952,7 +7006,7 @@ qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *prototype, v
|
|||
{
|
||||
#define MD5ERROR0PARAM(x) { Con_Printf(CON_ERROR x "\n"); return false; }
|
||||
#define MD5ERROR1PARAM(x, y) { Con_Printf(CON_ERROR x "\n", y); return false; }
|
||||
#define EXPECT(x) buffer = COM_Parse(buffer); if (strcmp(com_token, x)) MD5ERROR1PARAM("MD5ANIM: expected %s", x);
|
||||
#define EXPECT(x) buffer = COM_ParseOut(buffer, token, sizeof(token)); if (strcmp(token, x)) MD5ERROR1PARAM("MD5ANIM: expected %s", x);
|
||||
unsigned int i, j;
|
||||
|
||||
galiasanimation_t grp;
|
||||
|
@ -6973,29 +7027,29 @@ qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *prototype, v
|
|||
float tx, ty, tz, qx, qy, qz;
|
||||
int fac, flags;
|
||||
float f;
|
||||
char com_token[8192];
|
||||
char token[8192];
|
||||
|
||||
EXPECT("MD5Version");
|
||||
EXPECT("10");
|
||||
|
||||
EXPECT("commandline");
|
||||
buffer = COM_Parse(buffer);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
|
||||
EXPECT("numFrames");
|
||||
buffer = COM_Parse(buffer);
|
||||
numframes = atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
numframes = atoi(token);
|
||||
|
||||
EXPECT("numJoints");
|
||||
buffer = COM_Parse(buffer);
|
||||
numjoints = atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
numjoints = atoi(token);
|
||||
|
||||
EXPECT("frameRate");
|
||||
buffer = COM_Parse(buffer);
|
||||
framespersecond = atof(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
framespersecond = atof(token);
|
||||
|
||||
EXPECT("numAnimatedComponents");
|
||||
buffer = COM_Parse(buffer);
|
||||
numanimatedparts = atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
numanimatedparts = atoi(token);
|
||||
|
||||
firstanimatedcomponents = BZ_Malloc(sizeof(int)*numjoints);
|
||||
animatedcomponents = BZ_Malloc(sizeof(float)*numanimatedparts);
|
||||
|
@ -7020,28 +7074,28 @@ qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *prototype, v
|
|||
EXPECT("{");
|
||||
for (i = 0; i < numjoints; i++, bonelist++)
|
||||
{
|
||||
buffer = COM_Parse(buffer);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
if (prototype->numbones)
|
||||
{
|
||||
if (strcmp(bonelist->name, com_token))
|
||||
MD5ERROR1PARAM("MD5ANIM: bone name doesn't match (%s)", com_token);
|
||||
if (strcmp(bonelist->name, token))
|
||||
MD5ERROR1PARAM("MD5ANIM: bone name doesn't match (%s)", token);
|
||||
}
|
||||
else
|
||||
Q_strncpyz(bonelist->name, com_token, sizeof(bonelist->name));
|
||||
buffer = COM_Parse(buffer);
|
||||
parent = atoi(com_token);
|
||||
Q_strncpyz(bonelist->name, token, sizeof(bonelist->name));
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
parent = atoi(token);
|
||||
if (prototype->numbones)
|
||||
{
|
||||
if (bonelist->parent != parent)
|
||||
MD5ERROR1PARAM("MD5ANIM: bone name doesn't match (%s)", com_token);
|
||||
MD5ERROR1PARAM("MD5ANIM: bone name doesn't match (%s)", token);
|
||||
}
|
||||
else
|
||||
bonelist->parent = parent;
|
||||
|
||||
buffer = COM_Parse(buffer);
|
||||
boneflags[i] = atoi(com_token);
|
||||
buffer = COM_Parse(buffer);
|
||||
firstanimatedcomponents[i] = atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
boneflags[i] = atoi(token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
firstanimatedcomponents[i] = atoi(token);
|
||||
}
|
||||
EXPECT("}");
|
||||
|
||||
|
@ -7053,19 +7107,19 @@ qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *prototype, v
|
|||
for (i = 0; i < numframes; i++)
|
||||
{
|
||||
EXPECT("(");
|
||||
buffer = COM_Parse(buffer);f=atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));f=atoi(token);
|
||||
if (f < mod->mins[0]) mod->mins[0] = f;
|
||||
buffer = COM_Parse(buffer);f=atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));f=atoi(token);
|
||||
if (f < mod->mins[1]) mod->mins[1] = f;
|
||||
buffer = COM_Parse(buffer);f=atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));f=atoi(token);
|
||||
if (f < mod->mins[2]) mod->mins[2] = f;
|
||||
EXPECT(")");
|
||||
EXPECT("(");
|
||||
buffer = COM_Parse(buffer);f=atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));f=atoi(token);
|
||||
if (f > mod->maxs[0]) mod->maxs[0] = f;
|
||||
buffer = COM_Parse(buffer);f=atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));f=atoi(token);
|
||||
if (f > mod->maxs[1]) mod->maxs[1] = f;
|
||||
buffer = COM_Parse(buffer);f=atoi(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));f=atoi(token);
|
||||
if (f > mod->maxs[2]) mod->maxs[2] = f;
|
||||
EXPECT(")");
|
||||
}
|
||||
|
@ -7076,20 +7130,20 @@ qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *prototype, v
|
|||
for (i = 0; i < numjoints; i++)
|
||||
{
|
||||
EXPECT("(");
|
||||
buffer = COM_Parse(buffer);
|
||||
baseframe[i*6+0] = atof(com_token);
|
||||
buffer = COM_Parse(buffer);
|
||||
baseframe[i*6+1] = atof(com_token);
|
||||
buffer = COM_Parse(buffer);
|
||||
baseframe[i*6+2] = atof(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
baseframe[i*6+0] = atof(token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
baseframe[i*6+1] = atof(token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
baseframe[i*6+2] = atof(token);
|
||||
EXPECT(")");
|
||||
EXPECT("(");
|
||||
buffer = COM_Parse(buffer);
|
||||
baseframe[i*6+3] = atof(com_token);
|
||||
buffer = COM_Parse(buffer);
|
||||
baseframe[i*6+4] = atof(com_token);
|
||||
buffer = COM_Parse(buffer);
|
||||
baseframe[i*6+5] = atof(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
baseframe[i*6+3] = atof(token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
baseframe[i*6+4] = atof(token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
baseframe[i*6+5] = atof(token);
|
||||
EXPECT(")");
|
||||
}
|
||||
EXPECT("}");
|
||||
|
@ -7101,8 +7155,8 @@ qboolean Mod_ParseMD5Anim(model_t *mod, char *buffer, galiasinfo_t *prototype, v
|
|||
EXPECT("{");
|
||||
for (j = 0; j < numanimatedparts; j++)
|
||||
{
|
||||
buffer = COM_Parse(buffer);
|
||||
animatedcomponents[j] = atof(com_token);
|
||||
buffer = COM_ParseOut(buffer, token, sizeof(token));
|
||||
animatedcomponents[j] = atof(token);
|
||||
}
|
||||
EXPECT("}");
|
||||
|
||||
|
@ -7177,7 +7231,6 @@ galiasinfo_t *Mod_ParseMD5MeshModel(model_t *mod, char *buffer, char *modname)
|
|||
skinframe_t *frames;
|
||||
#endif
|
||||
char *filestart = buffer;
|
||||
const int com_token = 4;
|
||||
char token[1024];
|
||||
|
||||
float x, y, z, qx, qy, qz;
|
||||
|
@ -7468,7 +7521,7 @@ galiasinfo_t *Mod_ParseMD5MeshModel(model_t *mod, char *buffer, char *modname)
|
|||
else if (!strcmp(token, "}"))
|
||||
break;
|
||||
else
|
||||
MD5ERROR1PARAM("MD5MESH: Unrecognised token inside mesh (%s)", com_token);
|
||||
MD5ERROR1PARAM("MD5MESH: Unrecognised token inside mesh (%s)", token);
|
||||
|
||||
}
|
||||
|
||||
|
@ -7505,7 +7558,7 @@ galiasinfo_t *Mod_ParseMD5MeshModel(model_t *mod, char *buffer, char *modname)
|
|||
Z_Free(rawweightbone);
|
||||
}
|
||||
else
|
||||
MD5ERROR1PARAM("Unrecognised token in MD5 model (%s)", com_token);
|
||||
MD5ERROR1PARAM("Unrecognised token in MD5 model (%s)", token);
|
||||
}
|
||||
|
||||
if (!lastsurf)
|
||||
|
|
|
@ -61,8 +61,8 @@ void Mod_LoadEntities (model_t *loadmodel, qbyte *mod_base, lump_t *l);
|
|||
extern void BuildLightMapGammaTable (float g, float c);
|
||||
|
||||
#ifdef Q2BSPS
|
||||
static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace);
|
||||
static unsigned int CM_NativeContents(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
|
||||
static qboolean CM_NativeTrace(model_t *model, int forcehullnum, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace);
|
||||
static unsigned int CM_NativeContents(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
|
||||
static unsigned int Q2BSP_PointContents(model_t *mod, vec3_t axis[3], vec3_t p);
|
||||
static int CM_PointCluster (model_t *mod, vec3_t p);
|
||||
#endif
|
||||
|
@ -4423,8 +4423,8 @@ mplane_t box_planes[6];
|
|||
model_t box_model;
|
||||
q2cbrush_t box_brush;
|
||||
q2cbrushside_t box_sides[6];
|
||||
static qboolean BM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace);
|
||||
static unsigned int BM_NativeContents(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs)
|
||||
static qboolean BM_NativeTrace(model_t *model, int forcehullnum, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace);
|
||||
static unsigned int BM_NativeContents(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
unsigned int j;
|
||||
q2cbrushside_t *brushside = box_sides;
|
||||
|
@ -4694,7 +4694,7 @@ int CM_PointContents (model_t *mod, vec3_t p)
|
|||
return contents;
|
||||
}
|
||||
|
||||
unsigned int CM_NativeContents(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs)
|
||||
unsigned int CM_NativeContents(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
cminfo_t *prv = (cminfo_t*)model->meshinfo;
|
||||
int contents;
|
||||
|
@ -5861,7 +5861,7 @@ static trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end,
|
|||
return trace_trace;
|
||||
}
|
||||
|
||||
static qboolean BM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace)
|
||||
static qboolean BM_NativeTrace(model_t *model, int forcehullnum, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace)
|
||||
{
|
||||
int i;
|
||||
memset (trace, 0, sizeof(*trace));
|
||||
|
@ -5905,7 +5905,7 @@ static qboolean BM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3
|
|||
}
|
||||
return trace->fraction != 1;
|
||||
}
|
||||
static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace)
|
||||
static qboolean CM_NativeTrace(model_t *model, int forcehullnum, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contents, trace_t *trace)
|
||||
{
|
||||
if (axis)
|
||||
{
|
||||
|
@ -5923,7 +5923,7 @@ static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3
|
|||
if (model->terrain)
|
||||
{
|
||||
trace_t hmt;
|
||||
Heightmap_Trace(model, forcehullnum, frame, NULL, start, end, mins, maxs, capsule, contents, &hmt);
|
||||
Heightmap_Trace(model, forcehullnum, framestate, NULL, start, end, mins, maxs, capsule, contents, &hmt);
|
||||
if (hmt.fraction < trace->fraction)
|
||||
*trace = hmt;
|
||||
}
|
||||
|
@ -5955,7 +5955,7 @@ static qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3
|
|||
if (model->terrain)
|
||||
{
|
||||
trace_t hmt;
|
||||
Heightmap_Trace(model, forcehullnum, frame, NULL, start, end, mins, maxs, capsule, contents, &hmt);
|
||||
Heightmap_Trace(model, forcehullnum, framestate, NULL, start, end, mins, maxs, capsule, contents, &hmt);
|
||||
if (hmt.fraction < trace->fraction)
|
||||
*trace = hmt;
|
||||
}
|
||||
|
|
|
@ -552,7 +552,6 @@ void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
|
|||
in1[2][2] * in2[2][2];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_ConcatTransforms
|
||||
|
@ -586,24 +585,36 @@ void QDECL R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]
|
|||
in1[2][2] * in2[2][3] + in1[2][3];
|
||||
}
|
||||
|
||||
void Matrix3x4_Multiply(const float *a, const float *b, float *out)
|
||||
//R_ConcatTransforms where there's no offset values
|
||||
void R_ConcatTransformsAxis (float in1[3][3], float in2[3][4], float out[3][4])
|
||||
{
|
||||
out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2];
|
||||
out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2];
|
||||
out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2];
|
||||
out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + b[3];
|
||||
|
||||
out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6];
|
||||
out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6];
|
||||
out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6];
|
||||
out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + b[7];
|
||||
|
||||
out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10];
|
||||
out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10];
|
||||
out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10];
|
||||
out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + b[11];
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
|
||||
in1[0][2] * in2[2][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
|
||||
in1[0][2] * in2[2][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
|
||||
in1[0][2] * in2[2][2];
|
||||
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
|
||||
in1[0][2] * in2[2][3];
|
||||
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
|
||||
in1[1][2] * in2[2][0];
|
||||
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
|
||||
in1[1][2] * in2[2][1];
|
||||
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
|
||||
in1[1][2] * in2[2][2];
|
||||
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
|
||||
in1[1][2] * in2[2][3];
|
||||
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
|
||||
in1[2][2] * in2[2][0];
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
|
||||
in1[2][2] * in2[2][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
|
||||
in1[2][2] * in2[2][2];
|
||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
|
||||
in1[2][2] * in2[2][3];
|
||||
}
|
||||
|
||||
//R_ConcatTransforms where we don't care about the resulting offsets.
|
||||
void R_ConcatRotationsPad (float in1[3][4], float in2[3][4], float out[3][4])
|
||||
{
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
|
||||
|
@ -628,6 +639,24 @@ void R_ConcatRotationsPad (float in1[3][4], float in2[3][4], float out[3][4])
|
|||
in1[2][2] * in2[2][2];
|
||||
}
|
||||
|
||||
void Matrix3x4_Multiply(const float *a, const float *b, float *out)
|
||||
{
|
||||
out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2];
|
||||
out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2];
|
||||
out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2];
|
||||
out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + b[3];
|
||||
|
||||
out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6];
|
||||
out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6];
|
||||
out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6];
|
||||
out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + b[7];
|
||||
|
||||
out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10];
|
||||
out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10];
|
||||
out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10];
|
||||
out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + b[11];
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
FloorDivMod
|
||||
|
@ -1005,6 +1034,12 @@ void Matrix3x4_RM_Transform3(const float *matrix, const float *vector, float *pr
|
|||
product[1] = matrix[4]*vector[0] + matrix[5]*vector[1] + matrix[6]*vector[2] + matrix[7];
|
||||
product[2] = matrix[8]*vector[0] + matrix[9]*vector[1] + matrix[10]*vector[2] + matrix[11];
|
||||
}
|
||||
void Matrix3x4_RM_Transform3x3(const float *matrix, const float *vector, float *product)
|
||||
{
|
||||
product[0] = matrix[0]*vector[0] + matrix[1]*vector[1] + matrix[2]*vector[2];
|
||||
product[1] = matrix[4]*vector[0] + matrix[5]*vector[1] + matrix[6]*vector[2];
|
||||
product[2] = matrix[8]*vector[0] + matrix[9]*vector[1] + matrix[10]*vector[2];
|
||||
}
|
||||
|
||||
//transform 4d vector by a 4d matrix.
|
||||
void Matrix4x4_CM_Transform4(const float *matrix, const float *vector, float *product)
|
||||
|
|
|
@ -171,6 +171,7 @@ void Matrix3x4_RM_FromVectors(float *out, const float vx[3], const float vy[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]);
|
||||
void Matrix3x4_RM_Transform3(const float *matrix, const float *vector, float *product);
|
||||
void Matrix3x4_RM_Transform3x3(const float *matrix, const float *vector, float *product);
|
||||
|
||||
float *Matrix4x4_CM_NewRotation(float a, float x, float y, float z);
|
||||
float *Matrix4x4_CM_NewTranslation(float x, float y, float z);
|
||||
|
@ -198,6 +199,7 @@ int Q_log2 (int val);
|
|||
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
|
||||
void R_ConcatRotationsPad (float in1[3][4], float in2[3][4], float out[3][4]);
|
||||
void QDECL R_ConcatTransforms (matrix3x4 in1, matrix3x4 in2, matrix3x4 out);
|
||||
void R_ConcatTransformsAxis (float in1[3][3], float in2[3][4], float out[3][4]);
|
||||
void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees);
|
||||
void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lightpoint, vec3_t result);
|
||||
int VectorCompare (const vec3_t v1, const vec3_t v2);
|
||||
|
|
|
@ -885,7 +885,7 @@ hull_t *Q1BSP_ChooseHull(model_t *model, int forcehullnum, vec3_t mins, vec3_t m
|
|||
VectorSubtract (hull->clip_mins, mins, offset);
|
||||
return hull;
|
||||
}
|
||||
qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int hitcontentsmask, trace_t *trace)
|
||||
qboolean Q1BSP_Trace(model_t *model, int forcehullnum, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int hitcontentsmask, trace_t *trace)
|
||||
{
|
||||
hull_t *hull;
|
||||
vec3_t start_l, end_l;
|
||||
|
@ -1007,7 +1007,7 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3]
|
|||
if (model->terrain && trace->fraction)
|
||||
{
|
||||
trace_t hmt;
|
||||
Heightmap_Trace(model, forcehullnum, frame, axis, start, end, mins, maxs, capsule, hitcontentsmask, &hmt);
|
||||
Heightmap_Trace(model, forcehullnum, framestate, axis, start, end, mins, maxs, capsule, hitcontentsmask, &hmt);
|
||||
if (hmt.fraction < trace->fraction)
|
||||
*trace = hmt;
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ int World_PointContents (world_t *w, vec3_t p);
|
|||
|
||||
wedict_t *World_TestEntityPosition (world_t *w, wedict_t *ent);
|
||||
|
||||
qboolean World_TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask);
|
||||
qboolean World_TransformedTrace (struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask);
|
||||
|
||||
/*
|
||||
World_Move:
|
||||
|
|
|
@ -25246,7 +25246,6 @@
|
|||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug Dedicated Server|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
|
|
|
@ -3269,7 +3269,7 @@ unsigned int Heightmap_PointContents(model_t *model, vec3_t axis[3], vec3_t org)
|
|||
|
||||
return cont;
|
||||
}
|
||||
unsigned int Heightmap_NativeBoxContents(model_t *model, int hulloverride, int frame, vec3_t axis[3], vec3_t org, vec3_t mins, vec3_t maxs)
|
||||
unsigned int Heightmap_NativeBoxContents(model_t *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t org, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
heightmap_t *hm = model->terrain;
|
||||
return Heightmap_PointContentsHM(hm, mins[2], org);
|
||||
|
@ -3706,12 +3706,10 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
vec3_t start_l, end_l;
|
||||
trace_t etr;
|
||||
model_t *model;
|
||||
int frame;
|
||||
if (s->ents[i]->traceseq == tr->hm->traceseq)
|
||||
continue;
|
||||
s->ents[i]->traceseq = tr->hm->traceseq;
|
||||
model = s->ents[i]->ent.model;
|
||||
frame = s->ents[i]->ent.framestate.g[FS_REG].frame[0];
|
||||
//FIXME: IGNORE the entity if it isn't loaded yet? surely that's bad?
|
||||
if (!model || model->loadstate != MLS_LOADED || !model->funcs.NativeTrace)
|
||||
continue;
|
||||
|
@ -3735,7 +3733,7 @@ static void Heightmap_Trace_Square(hmtrace_t *tr, int tx, int ty)
|
|||
//do the trace
|
||||
memset(&etr, 0, sizeof(etr));
|
||||
etr.fraction = 1;
|
||||
model->funcs.NativeTrace (model, 0, frame, s->ents[i]->ent.axis, start_l, end_l, tr->mins, tr->maxs, tr->shape == iscapsule, tr->hitcontentsmask, &etr);
|
||||
model->funcs.NativeTrace (model, 0, &s->ents[i]->ent.framestate, s->ents[i]->ent.axis, start_l, end_l, tr->mins, tr->maxs, tr->shape == iscapsule, tr->hitcontentsmask, &etr);
|
||||
|
||||
if (etr.startsolid)
|
||||
{ //many many bsp objects are not enclosed 'properly' (qbsp strips any surfaces outside the world).
|
||||
|
@ -3935,7 +3933,7 @@ Why is recursion good?
|
|||
|
||||
Obviously, we don't care all that much about 1
|
||||
*/
|
||||
qboolean Heightmap_Trace(struct model_s *model, int hulloverride, int frame, vec3_t mataxis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
|
||||
qboolean Heightmap_Trace(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t mataxis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
|
||||
{
|
||||
vec2_t pos;
|
||||
vec2_t frac;
|
||||
|
@ -4201,14 +4199,14 @@ qboolean Heightmap_Trace(struct model_s *model, int hulloverride, int frame, vec
|
|||
return trace->fraction < 1;
|
||||
}
|
||||
|
||||
qboolean Heightmap_Trace_Test(struct model_s *model, int hulloverride, int frame, vec3_t mataxis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
|
||||
qboolean Heightmap_Trace_Test(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t mataxis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
|
||||
{
|
||||
qboolean ret = Heightmap_Trace(model, hulloverride, frame, mataxis, start, end, mins, maxs, capsule, against, trace);
|
||||
qboolean ret = Heightmap_Trace(model, hulloverride, framestate, mataxis, start, end, mins, maxs, capsule, against, trace);
|
||||
|
||||
if (!trace->startsolid)
|
||||
{
|
||||
trace_t testtrace;
|
||||
Heightmap_Trace(model, hulloverride, frame, mataxis, trace->endpos, trace->endpos, mins, maxs, capsule, against, &testtrace);
|
||||
Heightmap_Trace(model, hulloverride, framestate, mataxis, trace->endpos, trace->endpos, mins, maxs, capsule, against, &testtrace);
|
||||
if (testtrace.startsolid)
|
||||
{
|
||||
Con_DPrintf("Trace became solid\n");
|
||||
|
|
|
@ -6,17 +6,18 @@
|
|||
#include "com_mesh.h"
|
||||
/*
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Half-Life Model Renderer (Experimental) Copyright (C) 2001 James 'Ender' Brown [ender@quakesrc.org] This program is
|
||||
free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details. You should have received a copy of the GNU General Public License along with this program; if not, write
|
||||
to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. fromquake.h -
|
||||
Half-Life Model Renderer (Experimental) Copyright (C) 2001 James 'Ender' Brown [ender@quakesrc.org] This program is
|
||||
free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details. You should have received a copy of the GNU General Public License along with this program; if not, write
|
||||
to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. fromquake.h -
|
||||
|
||||
render.c - apart from calculations (mostly range checking or value conversion code is a mix of standard Quake 1
|
||||
meshing, and vertex deforms. The rendering loop uses standard Quake 1 drawing, after SetupBones deforms the vertex.
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Note: this code has since been greatly modified to fix skin, submodels, hitboxes, attachments, etc.
|
||||
|
||||
|
||||
|
||||
|
@ -24,6 +25,9 @@
|
|||
Nor will it work 100%
|
||||
*/
|
||||
|
||||
qboolean HLMDL_Trace (struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace);
|
||||
unsigned int HLMDL_Contents (struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
|
||||
|
||||
void QuaternionGLMatrix(float x, float y, float z, float w, vec4_t *GLM)
|
||||
{
|
||||
GLM[0][0] = 1 - 2 * y * y - 2 * z * z;
|
||||
|
@ -64,6 +68,7 @@ void QuaternionGLAngle(const vec3_t angles, vec4_t quaternion)
|
|||
|
||||
matrix3x4 transform_matrix[MAX_BONES]; /* Vertex transformation matrix */
|
||||
|
||||
#ifndef SERVERONLY
|
||||
void GL_Draw_HL_AliasFrame(short *order, vec3_t *transformed, float tex_w, float tex_h);
|
||||
|
||||
struct hlvremaps
|
||||
|
@ -218,6 +223,7 @@ static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel,
|
|||
//treat this as the base pose, and calculate the sdir+tdir for bumpmaps.
|
||||
R_Generate_Mesh_ST_Vectors(mesh);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=======================================================================================================================
|
||||
|
@ -226,7 +232,11 @@ static void HLMDL_PrepareVerticies (hlmodel_t *model, hlmdl_submodel_t *amodel,
|
|||
*/
|
||||
qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
int i;
|
||||
int body;
|
||||
struct hlmodelshaders_s *shaders;
|
||||
#endif
|
||||
|
||||
hlmodel_t *model;
|
||||
hlmdl_header_t *header;
|
||||
|
@ -234,9 +244,7 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
|
|||
hlmdl_tex_t *tex;
|
||||
hlmdl_bone_t *bones;
|
||||
hlmdl_bonecontroller_t *bonectls;
|
||||
struct hlmodelshaders_s *shaders;
|
||||
void *texmem = NULL;
|
||||
int body;
|
||||
|
||||
|
||||
//load the model into hunk
|
||||
|
@ -247,7 +255,7 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
|
|||
memcpy(header, buffer, fsize);
|
||||
|
||||
#if defined(HLSERVER) && (defined(__powerpc__) || defined(__ppc__))
|
||||
//this is to let bigfoot know when he comes to port it all... And I'm lazy.
|
||||
//this is to let anyone who tries porting it know that there is a serious issue. And I'm lazy.
|
||||
#ifdef warningmsg
|
||||
#pragma warningmsg("-----------------------------------------")
|
||||
#pragma warningmsg("FIXME: No byteswapping on halflife models") //hah, yeah, good luck with that, you'll need it.
|
||||
|
@ -301,6 +309,7 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
|
|||
model->bones = bones;
|
||||
model->bonectls = bonectls;
|
||||
|
||||
#ifndef SERVERONLY
|
||||
shaders = ZG_Malloc(&mod->memgroup, texheader->numtextures*sizeof(shader_t));
|
||||
model->shaders = shaders;
|
||||
for(i = 0; i < texheader->numtextures; i++)
|
||||
|
@ -316,18 +325,21 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
|
|||
model->numskingroups = texheader->skingroups;
|
||||
model->skinref = ZG_Malloc(&mod->memgroup, model->numskinrefs*model->numskingroups*sizeof(*model->skinref));
|
||||
memcpy(model->skinref, (short *) ((qbyte *) texheader + texheader->skins), model->numskinrefs*model->numskingroups*sizeof(*model->skinref));
|
||||
|
||||
#endif
|
||||
|
||||
if (texmem)
|
||||
Z_Free(texmem);
|
||||
|
||||
mod->funcs.NativeContents = HLMDL_Contents;
|
||||
mod->funcs.NativeTrace = HLMDL_Trace;
|
||||
mod->type = mod_halflife;
|
||||
mod->numframes = model->header->numseq;
|
||||
mod->meshinfo = model;
|
||||
|
||||
#ifndef SERVERONLY
|
||||
model->numgeomsets = model->header->numbodyparts;
|
||||
model->geomset = ZG_Malloc(&mod->memgroup, sizeof(*model->geomset) * model->numgeomsets);
|
||||
for (body = 0; body < model->header->numbodyparts; body++)
|
||||
for (body = 0; body < model->numgeomsets; body++)
|
||||
{
|
||||
hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model->header + model->header->bodypartindex) + body;
|
||||
int bodyindex;
|
||||
|
@ -341,6 +353,8 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize)
|
|||
HLMDL_PrepareVerticies(model, amodel, &model->geomset[body].alternatives[bodyindex]);
|
||||
}
|
||||
}
|
||||
//FIXME: No VBOs used.
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -557,17 +571,18 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
|
|||
|
||||
if (!sequence->numframes)
|
||||
return;
|
||||
//halflife seems to dupe the last frame in looping animations, so don't use it.
|
||||
if(frame1 >= sequence->numframes)
|
||||
{
|
||||
if (sequence->loop)
|
||||
frame1 %= sequence->numframes;
|
||||
frame1 %= sequence->numframes-1;
|
||||
else
|
||||
frame1 = sequence->numframes-1;
|
||||
}
|
||||
if(frame2 >= sequence->numframes)
|
||||
{
|
||||
if (sequence->loop)
|
||||
frame2 %= sequence->numframes;
|
||||
frame2 %= sequence->numframes-1;
|
||||
else
|
||||
frame2 = sequence->numframes-1;
|
||||
}
|
||||
|
@ -691,13 +706,15 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
|
|||
}
|
||||
}
|
||||
|
||||
int HLMDL_GetNumBones(model_t *mod)
|
||||
int HLMDL_GetNumBones(model_t *mod, qboolean tags)
|
||||
{
|
||||
hlmodel_t *mc;
|
||||
if (!mod || mod->type != mod_halflife)
|
||||
return -1; //halflife models only, please
|
||||
|
||||
mc = Mod_Extradata(mod);
|
||||
if (tags)
|
||||
return mc->header->numbones + mc->header->num_attachments;
|
||||
return mc->header->numbones;
|
||||
}
|
||||
|
||||
|
@ -707,6 +724,12 @@ int HLMDL_GetBoneParent(model_t *mod, int bonenum)
|
|||
|
||||
if (bonenum >= 0 && bonenum < model->header->numbones)
|
||||
return model->bones[bonenum].parent;
|
||||
bonenum -= model->header->numbones;
|
||||
if (bonenum >= 0 && bonenum < model->header->num_attachments)
|
||||
{
|
||||
hlmdl_attachment_t *attachments = bonenum+(hlmdl_attachment_t*)((char*)model->header + model->header->ofs_attachments);
|
||||
return attachments->bone;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -716,13 +739,34 @@ const char *HLMDL_GetBoneName(model_t *mod, int bonenum)
|
|||
|
||||
if (bonenum >= 0 && bonenum < model->header->numbones)
|
||||
return model->bones[bonenum].name;
|
||||
bonenum -= model->header->numbones;
|
||||
if (bonenum >= 0 && bonenum < model->header->num_attachments)
|
||||
{
|
||||
hlmdl_attachment_t *attachments = bonenum+(hlmdl_attachment_t*)((char*)model->header + model->header->ofs_attachments);
|
||||
if (*attachments->name)
|
||||
return attachments->name;
|
||||
return "Unnamed Attachment";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int HLMDL_GetBoneData(model_t *mod, int firstbone, int lastbone, framestate_t *fstate, float *result)
|
||||
int HLMDL_GetAttachment(model_t *mod, int tagnum, float *resultmatrix)
|
||||
{
|
||||
hlmodel_t *model = Mod_Extradata(mod);
|
||||
if (tagnum >= 0 && tagnum < model->header->num_attachments)
|
||||
{
|
||||
hlmdl_attachment_t *attachments = tagnum+(hlmdl_attachment_t*)((char*)model->header + model->header->ofs_attachments);
|
||||
resultmatrix[3] = attachments->org[0];
|
||||
resultmatrix[7] = attachments->org[1];
|
||||
resultmatrix[11] = attachments->org[2];
|
||||
return attachments->bone;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int HLMDL_GetBoneData_Internal(hlmodel_t *model, int firstbone, int lastbone, framestate_t *fstate, float *result)
|
||||
{
|
||||
int b, cbone, bgroup;
|
||||
hlmodel_t *model = Mod_Extradata(mod);
|
||||
|
||||
for (b = 0; b < MAX_BONE_CONTROLLERS; b++)
|
||||
model->controller[b] = fstate->bonecontrols[b];
|
||||
|
@ -738,6 +782,10 @@ int HLMDL_GetBoneData(model_t *mod, int firstbone, int lastbone, framestate_t *f
|
|||
}
|
||||
return cbone;
|
||||
}
|
||||
int HLMDL_GetBoneData(model_t *mod, int firstbone, int lastbone, framestate_t *fstate, float *result)
|
||||
{
|
||||
return HLMDL_GetBoneData_Internal(Mod_Extradata(mod), firstbone, lastbone, fstate, result);
|
||||
}
|
||||
|
||||
const char *HLMDL_FrameNameForNum(model_t *mod, int surfaceidx, int seqnum)
|
||||
{
|
||||
|
@ -754,17 +802,205 @@ qboolean HLMDL_FrameInfoForNum(model_t *mod, int surfaceidx, int seqnum, char **
|
|||
|
||||
*name = sequence->name;
|
||||
*numframes = sequence->numframes;
|
||||
*duration = sequence->numframes/sequence->timing;
|
||||
*duration = (sequence->numframes-1)/sequence->timing;
|
||||
*loop = sequence->loop;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
qboolean HLMDL_Trace (model_t *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
|
||||
{
|
||||
hlmodel_t *hm = Mod_Extradata(model);
|
||||
float *relbones;
|
||||
float calcrelbones[MAX_BONES*12];
|
||||
int bonecount;
|
||||
int b, i;
|
||||
vec3_t norm, p1l, p2l;
|
||||
float inverse[12];
|
||||
hlmdl_hitbox_t *hitbox = (hlmdl_hitbox_t*)((char*)hm->header+hm->header->ofs_hitboxes);
|
||||
float dist, d1, d2, f, enterfrac, enterdist, exitfrac;
|
||||
qboolean startout, endout;
|
||||
int enterplane;
|
||||
|
||||
extern cvar_t temp1;
|
||||
p1[2] += temp1.value;
|
||||
p2[2] += temp1.value;
|
||||
|
||||
memset (trace, 0, sizeof(trace_t));
|
||||
trace->fraction = trace->truefraction = 1;
|
||||
if (!(against & FTECONTENTS_BODY))
|
||||
return false;
|
||||
|
||||
if (framestate->bonestate && framestate->skeltype == SKEL_ABSOLUTE)
|
||||
{
|
||||
relbones = framestate->bonestate;
|
||||
bonecount = framestate->bonecount;
|
||||
if (axis)
|
||||
{
|
||||
for (b = 0; b < bonecount; b++)
|
||||
R_ConcatTransformsAxis(axis, (void*)(relbones+b*12), transform_matrix[b]);
|
||||
}
|
||||
else
|
||||
memcpy(transform_matrix, relbones, bonecount * 12 * sizeof(float));
|
||||
}
|
||||
else
|
||||
{
|
||||
//get relative bones from th emodel.
|
||||
if (framestate->bonestate)
|
||||
{
|
||||
relbones = framestate->bonestate;
|
||||
bonecount = framestate->bonecount;
|
||||
}
|
||||
else
|
||||
{
|
||||
relbones = calcrelbones;
|
||||
bonecount = HLMDL_GetBoneData(model, 0, MAX_BONES, framestate, calcrelbones);
|
||||
}
|
||||
|
||||
//convert relative to absolutes
|
||||
for (b = 0; b < bonecount; b++)
|
||||
{
|
||||
/* If we have a parent, take the addition. Otherwise just copy the values */
|
||||
if(hm->bones[b].parent>=0)
|
||||
R_ConcatTransforms(transform_matrix[hm->bones[b].parent], (void*)(relbones+b*12), transform_matrix[b]);
|
||||
else if (axis)
|
||||
R_ConcatTransformsAxis(axis, (void*)(relbones+b*12), transform_matrix[b]);
|
||||
else
|
||||
memcpy(transform_matrix[b], relbones+b*12, 12 * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
for (b = 0; b < hm->header->num_hitboxes; b++, hitbox++)
|
||||
{
|
||||
startout = false;
|
||||
endout = false;
|
||||
enterplane= 0;
|
||||
enterfrac = -1;
|
||||
exitfrac = 10;
|
||||
|
||||
//fixme: would be nice to check if there's a possible collision a bit faster, without needing to do lots of excess maths.
|
||||
|
||||
//transform start+end into the bbox, so everything is axial and simple.
|
||||
Matrix3x4_Invert_Simple((void*)transform_matrix[hitbox->bone], inverse);
|
||||
Matrix3x4_RM_Transform3(inverse, p1, p1l);
|
||||
Matrix3x4_RM_Transform3(inverse, p2, p2l);
|
||||
//fixme: would it be faster to just generate the plane and transform that, colliding non-axially? would probably be better for sized impactors.
|
||||
|
||||
//clip against the 6 axial faces
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (i < 3)
|
||||
{ //normal>0
|
||||
dist = hitbox->maxs[i] - mins[i];
|
||||
d1 = p1l[i] - dist;
|
||||
d2 = p2l[i] - dist;
|
||||
}
|
||||
else
|
||||
{//normal<0
|
||||
dist = maxs[i-3] - hitbox->mins[i-3];
|
||||
d1 = -p1l[i-3] - dist;
|
||||
d2 = -p2l[i-3] - dist;
|
||||
}
|
||||
//FIXME: if the trace has size, we should insert 6 extra planes for the shape of the impactor
|
||||
//FIXME: capsules
|
||||
|
||||
if (d1 >= 0)
|
||||
startout = true;
|
||||
if (d2 > 0)
|
||||
endout = true;
|
||||
|
||||
//if we're fully outside any plane, then we cannot possibly enter the brush, skip to the next one
|
||||
if (d1 > 0 && d2 >= 0)
|
||||
goto nextbrush;
|
||||
|
||||
//if we're fully inside the plane, then whatever is happening is not relevent for this plane
|
||||
if (d1 < 0 && d2 <= 0)
|
||||
continue;
|
||||
|
||||
f = d1 / (d1-d2);
|
||||
if (d1 > d2)
|
||||
{
|
||||
//entered the brush. favour the furthest fraction to avoid extended edges (yay for convex shapes)
|
||||
if (enterfrac < f)
|
||||
{
|
||||
enterfrac = f;
|
||||
enterplane = i;
|
||||
enterdist = dist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//left the brush, favour the nearest plane (smallest frac)
|
||||
if (exitfrac > f)
|
||||
{
|
||||
exitfrac = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!startout)
|
||||
{
|
||||
trace->startsolid = true;
|
||||
if (!endout)
|
||||
trace->allsolid = true;
|
||||
trace->contents = FTECONTENTS_BODY;
|
||||
|
||||
trace->brush_face = 0;
|
||||
trace->bone_id = hitbox->bone+1;
|
||||
trace->brush_id = b+1;
|
||||
trace->surface_id = hitbox->body;
|
||||
break;
|
||||
}
|
||||
if (enterfrac != -1 && enterfrac < exitfrac)
|
||||
{
|
||||
//impact!
|
||||
if (enterfrac < trace->fraction)
|
||||
{
|
||||
trace->fraction = trace->truefraction = enterfrac;
|
||||
trace->plane.dist = enterdist;
|
||||
trace->contents = FTECONTENTS_BODY;
|
||||
|
||||
trace->brush_face = enterplane+1;
|
||||
trace->bone_id = hitbox->bone+1;
|
||||
trace->brush_id = b+1;
|
||||
trace->surface_id = hitbox->body;
|
||||
}
|
||||
}
|
||||
nextbrush:
|
||||
;
|
||||
}
|
||||
|
||||
if (trace->brush_face)
|
||||
{
|
||||
VectorClear(norm);
|
||||
if (trace->brush_face < 4)
|
||||
norm[trace->brush_face-1] = 1;
|
||||
else
|
||||
norm[trace->brush_face-4] = -1;
|
||||
Matrix3x4_RM_Transform3x3((void*)transform_matrix[trace->bone_id-1], norm, trace->plane.normal);
|
||||
}
|
||||
else
|
||||
VectorClear(trace->plane.normal);
|
||||
VectorInterpolate(p1, trace->fraction, p2, trace->endpos);
|
||||
|
||||
return trace->truefraction != 1;
|
||||
}
|
||||
unsigned int HLMDL_Contents (model_t *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
trace_t tr;
|
||||
HLMDL_Trace(model, hulloverride, framestate, axis, p, p, mins, maxs, false, ~0, &tr);
|
||||
return tr.contents;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SERVERONLY
|
||||
void R_HL_BuildFrame(hlmodel_t *model, hlmdl_submodel_t *amodel, entity_t *curent, int bodypart, int bodyidx, int meshidx, float tex_s, float tex_t, mesh_t *mesh, qboolean gpubones)
|
||||
{
|
||||
int b;
|
||||
int cbone;
|
||||
int bgroup;
|
||||
int lastbone;
|
||||
// int bgroup;
|
||||
// int lastbone;
|
||||
int v;
|
||||
|
||||
*mesh = model->geomset[bodypart].alternatives[bodyidx].mesh;
|
||||
|
@ -801,7 +1037,7 @@ void R_HL_BuildFrame(hlmodel_t *model, hlmdl_submodel_t *amodel, entity_t *curen
|
|||
mesh->bones = transform_matrix[0][0];
|
||||
mesh->numbones = model->header->numbones;
|
||||
|
||||
//FIXME: needs caching.
|
||||
/* //FIXME: needs caching.
|
||||
for (b = 0; b < MAX_BONE_CONTROLLERS; b++)
|
||||
model->controller[b] = curent->framestate.bonecontrols[b];
|
||||
for (cbone = 0, bgroup = 0; bgroup < FS_COUNT; bgroup++)
|
||||
|
@ -811,9 +1047,11 @@ void R_HL_BuildFrame(hlmodel_t *model, hlmdl_submodel_t *amodel, entity_t *curen
|
|||
lastbone = model->header->numbones;
|
||||
if (cbone >= lastbone)
|
||||
continue;
|
||||
HL_SetupBones(model, curent->framestate.g[bgroup].frame[0], cbone, lastbone, (curent->framestate.g[bgroup].subblendfrac+1)*0.5, curent->framestate.g[bgroup].frametime[0], relatives); /* Setup the bones */
|
||||
HL_SetupBones(model, curent->framestate.g[bgroup].frame[0], cbone, lastbone, (curent->framestate.g[bgroup].subblendfrac+1)*0.5, curent->framestate.g[bgroup].frametime[0], relatives); // Setup the bones
|
||||
cbone = lastbone;
|
||||
}
|
||||
*/
|
||||
cbone = HLMDL_GetBoneData_Internal(model, 0, model->header->numbones, &curent->framestate, relatives);
|
||||
|
||||
//convert relative to absolutes
|
||||
for (b = 0; b < cbone; b++)
|
||||
|
@ -867,13 +1105,13 @@ void R_HL_BuildFrame(hlmodel_t *model, hlmdl_submodel_t *amodel, entity_t *curen
|
|||
}
|
||||
}
|
||||
|
||||
void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches);
|
||||
void R_HL_BuildMesh(struct batch_s *b)
|
||||
static void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches);
|
||||
static void R_HL_BuildMesh(struct batch_s *b)
|
||||
{
|
||||
R_HalfLife_WalkMeshes(b->ent, b, NULL);
|
||||
}
|
||||
|
||||
void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
|
||||
static void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
|
||||
{
|
||||
hlmodel_t *model = Mod_Extradata(rent->model);
|
||||
int body, m;
|
||||
|
@ -887,7 +1125,7 @@ void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
|
|||
sk = Mod_LookupSkin(rent->customskin);
|
||||
//entity_body = rent->body; //hey, if its there, lets use it.
|
||||
|
||||
for (body = 0; body < model->header->numbodyparts; body++)
|
||||
for (body = 0; body < model->numgeomsets; body++)
|
||||
{
|
||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
||||
hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model->header + model->header->bodypartindex) + body;
|
||||
|
@ -1007,4 +1245,48 @@ void R_HalfLife_GenerateBatches(entity_t *e, batch_t **batches)
|
|||
R_HalfLife_WalkMeshes(e, NULL, batches);
|
||||
}
|
||||
|
||||
void HLMDL_DrawHitBoxes(entity_t *rent)
|
||||
{
|
||||
hlmodel_t *model = Mod_Extradata(rent->model);
|
||||
hlmdl_hitbox_t *hitbox = (hlmdl_hitbox_t*)((char*)model->header+model->header->ofs_hitboxes);
|
||||
matrix3x4 entitymatrix;
|
||||
|
||||
shader_t *shader = R_RegisterShader("hitbox_nodepth", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
"map $whiteimage\n"
|
||||
"blendfunc gl_src_alpha gl_one\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"nodepthtest\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
|
||||
float relbones[MAX_BONES*12];
|
||||
int bonecount = HLMDL_GetBoneData(rent->model, 0, MAX_BONES, &rent->framestate, relbones);
|
||||
int b;
|
||||
|
||||
VectorCopy(rent->axis[0], entitymatrix[0]);
|
||||
VectorCopy(rent->axis[1], entitymatrix[1]);
|
||||
VectorCopy(rent->axis[2], entitymatrix[2]);
|
||||
entitymatrix[0][3] = rent->origin[0];
|
||||
entitymatrix[1][3] = rent->origin[1];
|
||||
entitymatrix[2][3] = rent->origin[2];
|
||||
|
||||
//convert relative to absolutes
|
||||
for (b = 0; b < bonecount; b++)
|
||||
{
|
||||
//If we have a parent, take the addition. Otherwise just copy the values
|
||||
if(model->bones[b].parent>=0)
|
||||
R_ConcatTransforms(transform_matrix[model->bones[b].parent], (void*)(relbones+b*12), transform_matrix[b]);
|
||||
else
|
||||
R_ConcatTransforms(entitymatrix, (void*)(relbones+b*12), transform_matrix[b]);
|
||||
}
|
||||
|
||||
for (b = 0; b < model->header->num_hitboxes; b++, hitbox++)
|
||||
CLQ1_AddOrientedCube(shader, hitbox->mins, hitbox->maxs, transform_matrix[hitbox->bone][0], 1, 1, 1, 0.2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -216,11 +216,11 @@ typedef struct {
|
|||
void (*PurgeModel) (struct model_s *mod);
|
||||
|
||||
unsigned int (*PointContents) (struct model_s *model, vec3_t axis[3], vec3_t p);
|
||||
unsigned int (*BoxContents) (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
|
||||
unsigned int (*BoxContents) (struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
|
||||
|
||||
//deals with whatever is native for the bsp (gamecode is expected to distinguish this).
|
||||
qboolean (*NativeTrace) (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace);
|
||||
unsigned int (*NativeContents)(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
|
||||
qboolean (*NativeTrace) (struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace);
|
||||
unsigned int (*NativeContents)(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
|
||||
|
||||
unsigned int (*FatPVS) (struct model_s *model, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean merge);
|
||||
qboolean (*EdictInFatPVS) (struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer);
|
||||
|
@ -1030,7 +1030,7 @@ void Terr_FinishTerrain(model_t *model);
|
|||
void Terr_PurgeTerrainModel(model_t *hm, qboolean lightmapsonly, qboolean lightmapreusable);
|
||||
void *Mod_LoadTerrainInfo(model_t *mod, char *loadname, qboolean force); //call this after loading a bsp
|
||||
qboolean Terrain_LocateSection(char *name, flocation_t *loc); //used on servers to generate sections for download.
|
||||
qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contentmask, struct trace_s *trace);
|
||||
qboolean Heightmap_Trace(model_t *model, int forcehullnum, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int contentmask, struct trace_s *trace);
|
||||
unsigned int Heightmap_PointContents(model_t *model, vec3_t axis[3], vec3_t org);
|
||||
struct fragmentdecal_s;
|
||||
void Terrain_ClipDecal(struct fragmentdecal_s *dec, float *center, float radius, model_t *model);
|
||||
|
|
|
@ -418,7 +418,7 @@ qboolean R_GameRectIsFullscreen(void);
|
|||
R_SetupGL
|
||||
=============
|
||||
*/
|
||||
void R_SetupGL (float stereooffset)
|
||||
void R_SetupGL (float stereooffset, int i)
|
||||
{
|
||||
int x, x2, y2, y, w, h;
|
||||
vec3_t newa;
|
||||
|
@ -430,8 +430,8 @@ void R_SetupGL (float stereooffset)
|
|||
newa[0] = r_refdef.viewangles[0];
|
||||
newa[1] = r_refdef.viewangles[1];
|
||||
newa[2] = r_refdef.viewangles[2] + gl_screenangle.value;
|
||||
if (stereooffset)
|
||||
newa[1] += r_stereo_convergence.value * ((stereooffset>0)?-0.5:0.5); //can we get away with this cheapness? rip 6dof
|
||||
if (r_refdef.stereomethod)
|
||||
newa[1] += r_stereo_convergence.value * (i?0.5:-0.5); //can we get away with this cheapness? rip 6dof
|
||||
if (0)
|
||||
{
|
||||
vec3_t paxis[3];
|
||||
|
@ -507,10 +507,14 @@ void R_SetupGL (float stereooffset)
|
|||
w = x2 - x;
|
||||
h = y2 - y;
|
||||
|
||||
if (stereooffset && r_refdef.stereomethod == STEREO_CROSSEYED)
|
||||
if (r_refdef.stereomethod == STEREO_CROSSEYED
|
||||
#ifdef FTE_TARGET_WEB
|
||||
|| r_refdef.stereomethod == STEREO_WEBVR
|
||||
#endif
|
||||
)
|
||||
{
|
||||
w /= 2;
|
||||
if (stereooffset < 0)
|
||||
if (i)
|
||||
x += vid.fbpwidth/2;
|
||||
}
|
||||
|
||||
|
@ -537,31 +541,47 @@ void R_SetupGL (float stereooffset)
|
|||
|
||||
GL_ViewportUpdate();
|
||||
|
||||
|
||||
if (r_refdef.useperspective)
|
||||
#ifdef FTE_TARGET_WEB
|
||||
if (r_refdef.stereomethod == STEREO_WEBVR)
|
||||
{
|
||||
int stencilshadows = Sh_StencilShadowsActive();
|
||||
float vm[16], em[16];
|
||||
emscriptenfte_getvreyedata(i, r_refdef.m_projection, em);
|
||||
Matrix4x4_Identity(em);
|
||||
|
||||
if ((!stencilshadows || !gl_stencilbits) && r_refdef.maxdist)//gl_nv_range_clamp)
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(vm, vpn, vright, vup, r_origin);
|
||||
Matrix4_Multiply(vm, em, r_refdef.m_view);
|
||||
//fixme: read the axis+org back out...
|
||||
|
||||
// Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_origin);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (r_refdef.useperspective)
|
||||
{
|
||||
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
|
||||
// yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect;
|
||||
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI;
|
||||
// MYgluPerspective (yfov, screenaspect, 4, 4096);
|
||||
int stencilshadows = Sh_StencilShadowsActive();
|
||||
|
||||
Matrix4x4_CM_Projection_Far(r_refdef.m_projection, fov_x, fov_y, r_refdef.mindist, r_refdef.maxdist);
|
||||
if ((!stencilshadows || !gl_stencilbits) && r_refdef.maxdist)//gl_nv_range_clamp)
|
||||
{
|
||||
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
|
||||
// yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect;
|
||||
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI;
|
||||
// MYgluPerspective (yfov, screenaspect, 4, 4096);
|
||||
|
||||
Matrix4x4_CM_Projection_Far(r_refdef.m_projection, fov_x, fov_y, r_refdef.mindist, r_refdef.maxdist);
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, r_refdef.mindist);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, r_refdef.mindist);
|
||||
Matrix4x4_CM_Orthographic(r_refdef.m_projection, -fov_x/2, fov_x/2, -fov_y/2, fov_y/2, r_refdef.mindist, r_refdef.maxdist?r_refdef.maxdist:9999);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix4x4_CM_Orthographic(r_refdef.m_projection, -fov_x/2, fov_x/2, -fov_y/2, fov_y/2, r_refdef.mindist, r_refdef.maxdist?r_refdef.maxdist:9999);
|
||||
}
|
||||
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_origin);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_origin);
|
||||
}
|
||||
}
|
||||
|
||||
if (qglLoadMatrixf)
|
||||
|
@ -691,6 +711,11 @@ void R_RenderScene (void)
|
|||
else
|
||||
qglColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
|
||||
break;
|
||||
#ifdef FTE_TARGET_WEB
|
||||
case STEREO_WEBVR:
|
||||
stereooffset[i] = 0; //webgl overrides our separation.
|
||||
break;
|
||||
#endif
|
||||
case STEREO_CROSSEYED: //eyestrain
|
||||
break;
|
||||
case STEREO_LEFTONLY:
|
||||
|
@ -710,7 +735,7 @@ void R_RenderScene (void)
|
|||
}
|
||||
|
||||
TRACE(("dbg: calling R_SetupGL\n"));
|
||||
R_SetupGL (stereooffset[i]);
|
||||
R_SetupGL (stereooffset[i], i);
|
||||
|
||||
TRACE(("dbg: calling R_SetFrustrum\n"));
|
||||
if (!r_refdef.recurse)
|
||||
|
|
|
@ -31,7 +31,8 @@ typedef struct
|
|||
int boneindex;
|
||||
int numcontrollers;
|
||||
int controllerindex;
|
||||
int unknown5[2]; //hitboxes
|
||||
int num_hitboxes;
|
||||
int ofs_hitboxes;
|
||||
int numseq;
|
||||
int seqindex;
|
||||
int unknown6; //external sequences
|
||||
|
@ -44,7 +45,9 @@ typedef struct
|
|||
int skins;
|
||||
int numbodyparts;
|
||||
int bodypartindex;
|
||||
int unknown9[8]; //attachments, sounds, transitions
|
||||
int num_attachments;
|
||||
int ofs_attachments;
|
||||
int unknown9[6]; //sounds, transitions
|
||||
} hlmdl_header_t;
|
||||
|
||||
/*
|
||||
|
@ -103,6 +106,23 @@ typedef struct
|
|||
float scale[6];
|
||||
} hlmdl_bone_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[32]; //I assume
|
||||
int unk;
|
||||
int bone;
|
||||
vec3_t org;
|
||||
vec3_t unk2[3];
|
||||
} hlmdl_attachment_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int bone;
|
||||
int body; //value reported to gamecode on impact
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
} hlmdl_hitbox_t;
|
||||
|
||||
/*
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
bone controllers
|
||||
|
@ -259,9 +279,7 @@ void QuaternionGLAngle(const vec3_t angles, vec4_t quaternion);
|
|||
void QuaternionGLMatrix(float x, float y, float z, float w, vec4_t *GLM);
|
||||
//void UploadTexture(hlmdl_tex_t *ptexture, qbyte *data, qbyte *pal);
|
||||
|
||||
/* HL drawing */
|
||||
qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer, size_t fsize);
|
||||
void R_DrawHLModel(entity_t *curent);
|
||||
|
||||
/* physics stuff */
|
||||
void *Mod_GetHalfLifeModelData(model_t *mod);
|
||||
|
@ -271,7 +289,14 @@ int HLMDL_BoneForName(model_t *mod, const char *name);
|
|||
int HLMDL_FrameForName(model_t *mod, const char *name);
|
||||
const char *HLMDL_FrameNameForNum(model_t *model, int surfaceidx, int num);
|
||||
qboolean HLMDL_FrameInfoForNum(model_t *model, int surfaceidx, int num, char **name, int *numframes, float *duration, qboolean *loop);
|
||||
int HLMDL_GetNumBones(model_t *mod);
|
||||
int HLMDL_GetNumBones(model_t *mod, qboolean tagstoo);
|
||||
int HLMDL_GetBoneParent(model_t *mod, int bonenum);
|
||||
const char *HLMDL_GetBoneName(model_t *mod, int bonenum);
|
||||
int HLMDL_GetBoneData(model_t *model, int firstbone, int lastbone, framestate_t *fstate, float *result);
|
||||
int HLMDL_GetAttachment(model_t *model, int tagnum, float *resultmatrix);
|
||||
|
||||
#ifndef SERVERONLY
|
||||
//stuff only useful for clients that need to draw stuff
|
||||
void R_DrawHLModel(entity_t *curent);
|
||||
void HLMDL_DrawHitBoxes(entity_t *ent);
|
||||
#endif
|
||||
|
|
|
@ -861,4 +861,11 @@ struct shader_field_names_s
|
|||
extern struct shader_field_names_s shader_field_names[];
|
||||
extern struct shader_field_names_s shader_unif_names[];
|
||||
extern struct shader_field_names_s shader_attr_names[];
|
||||
|
||||
|
||||
void CLQ1_DrawLine(shader_t *shader, vec3_t v1, vec3_t v2, float r, float g, float b, float a);
|
||||
void CLQ1_AddOrientedCube(shader_t *shader, vec3_t mins, vec3_t maxs, float *matrix, float r, float g, float b, float a);
|
||||
void CL_DrawDebugPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue);
|
||||
void CLQ1_AddOrientedCylinder(shader_t *shader, float radius, float height, qboolean capsule, float *matrix, float r, float g, float b, float a);
|
||||
void CLQ1_AddOrientedHalfSphere(shader_t *shader, float radius, float gap, float *matrix, float r, float g, float b, float a);
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "progsint.h"
|
||||
#include "qcc.h"
|
||||
|
||||
#ifndef NO_ZLIB
|
||||
#if !defined(NO_ZLIB) && !defined(FTE_TARGET_WEB)
|
||||
#define AVAIL_ZLIB
|
||||
#endif
|
||||
|
||||
|
|
|
@ -519,6 +519,12 @@ static void QDECL SVPR_Get_FrameState(world_t *w, wedict_t *ent, framestate_t *f
|
|||
fstate->g[FS_REG].frame[0] = ent->v->frame;
|
||||
fstate->g[FS_REG].frametime[0] = ent->xv->frame1time;
|
||||
fstate->g[FS_REG].lerpweight[0] = 1;
|
||||
fstate->g[FS_REG].endbone = 0x7fffffff;
|
||||
|
||||
fstate->g[FST_BASE].frame[0] = ent->xv->baseframe;
|
||||
fstate->g[FST_BASE].frametime[0] = ent->xv->/*base*/frame1time;
|
||||
fstate->g[FST_BASE].lerpweight[0] = 1;
|
||||
fstate->g[FST_BASE].endbone = ent->xv->basebone;
|
||||
|
||||
#if defined(SKELETALOBJECTS) || defined(RAGDOLL)
|
||||
if (ent->xv->skeletonindex)
|
||||
|
|
|
@ -135,7 +135,7 @@ qboolean World_BoxTrace(struct model_s *model, int hulloverride, int frame, vec3
|
|||
VectorCopy (p2, trace->endpos);
|
||||
return Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, p1, p2, trace);
|
||||
}
|
||||
qboolean World_CapsuleTrace(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
|
||||
qboolean World_CapsuleTrace(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace)
|
||||
{
|
||||
//bbox vs capsule (NYI)
|
||||
//capsule vs capsule (NYI)
|
||||
|
@ -1016,7 +1016,7 @@ qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
|
|||
|
||||
//wrapper function. Rotates the start and end positions around the angles if needed.
|
||||
//qboolean TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_t *trace, vec3_t angles)
|
||||
qboolean World_TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask)
|
||||
qboolean World_TransformedTrace (struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask)
|
||||
{
|
||||
vec3_t start_l, end_l;
|
||||
vec3_t axis[3];
|
||||
|
@ -1045,11 +1045,11 @@ qboolean World_TransformedTrace (struct model_s *model, int hulloverride, int fr
|
|||
{
|
||||
AngleVectors (angles, axis[0], axis[1], axis[2]);
|
||||
VectorNegate(axis[1], axis[1]);
|
||||
result = model->funcs.NativeTrace (model, hulloverride, frame, axis, start_l, end_l, mins, maxs, capsule, hitcontentsmask, trace);
|
||||
result = model->funcs.NativeTrace (model, hulloverride, framestate, axis, start_l, end_l, mins, maxs, capsule, hitcontentsmask, trace);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = model->funcs.NativeTrace (model, hulloverride, frame, NULL, start_l, end_l, mins, maxs, capsule, hitcontentsmask, trace);
|
||||
result = model->funcs.NativeTrace (model, hulloverride, framestate, NULL, start_l, end_l, mins, maxs, capsule, hitcontentsmask, trace);
|
||||
}
|
||||
|
||||
VectorAdd (trace->endpos, origin, trace->endpos);
|
||||
|
@ -1083,6 +1083,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
trace_t trace;
|
||||
model_t *model;
|
||||
int mdlidx = ent->v->modelindex;
|
||||
framestate_t framestate;
|
||||
|
||||
// get the clipping hull
|
||||
if ((ent->v->solid == SOLID_BSP || ent->v->solid == SOLID_PORTAL) && mdlidx)
|
||||
|
@ -1109,11 +1110,13 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
World_HullForBox(boxmins, boxmaxs);
|
||||
}
|
||||
|
||||
w->Get_FrameState(w, ent, &framestate);
|
||||
|
||||
// trace a line through the apropriate clipping hull
|
||||
if (ent->v->solid == SOLID_PORTAL)
|
||||
{
|
||||
//solid_portal cares only about origins and as such has no mins/max
|
||||
World_TransformedTrace(model, 0, ent->v->frame, start, end, vec3_origin, vec3_origin, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
World_TransformedTrace(model, 0, &framestate, start, end, vec3_origin, vec3_origin, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
if (trace.startsolid) //portals should not block traces. this prevents infinite looping
|
||||
trace.startsolid = false;
|
||||
hitmodel = false;
|
||||
|
@ -1121,12 +1124,12 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
else if (ent->v->solid != SOLID_BSP)
|
||||
{
|
||||
ent->v->angles[0]*=-1; //carmack made bsp models rotate wrongly.
|
||||
World_TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
ent->v->angles[0]*=-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
World_TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
}
|
||||
|
||||
// if using hitmodel, we know it hit the bounding box, so try a proper trace now.
|
||||
|
@ -1138,7 +1141,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
if (model && model->funcs.NativeTrace && model->loadstate == MLS_LOADED)
|
||||
{
|
||||
//do the second trace, using the actual mesh.
|
||||
World_TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,3 +54,6 @@ int emscriptenfte_setupcanvas(
|
|||
int (*ShouldSwitchToFullscreen)(void)
|
||||
);
|
||||
|
||||
int emscriptenfte_getvrframedata(void);
|
||||
int emscriptenfte_getvreyedata(int eye, float *projectionmatrix, float *viewmatrix);
|
||||
|
||||
|
|
|
@ -151,6 +151,12 @@ mergeInto(LibraryManager.library,
|
|||
FTEC.pointerislocked = -1; //don't repeat the request on every click. firefox has a fit at that, so require the mouse to leave the element or something before we retry.
|
||||
Module['canvas'].requestPointerLock();
|
||||
}
|
||||
|
||||
if (FTEC.usevr)
|
||||
if (FTEC.vrDisplay)
|
||||
if (!FTEC.vrDisplay.isPresenting)
|
||||
FTEC.vrDisplay.requestPresent([{ source: Module['canvas'] }]).then(function (){console.log("zomg, presenting!");}, function (err){FTEC.usevr = false;console.log("cannot vrdisplay!");});
|
||||
|
||||
//fallthrough
|
||||
case 'mouseup':
|
||||
if (FTEC.evcb.button != 0)
|
||||
|
@ -272,12 +278,65 @@ mergeInto(LibraryManager.library,
|
|||
document.webkitPointerLockElement === Module['canvas'];
|
||||
console.log("Pointer lock now " + FTEC.pointerislocked);
|
||||
break;
|
||||
|
||||
case 'vrdisplaypresentchange':
|
||||
console.log("vr present changed");
|
||||
console.log(event);
|
||||
break;
|
||||
case 'vrdisplayactivate':
|
||||
console.log("vr display active");
|
||||
if (event.display == FTEC.vrDisplay)
|
||||
{
|
||||
FTEC.usevr = true;
|
||||
if (!FTEC.vrDisplay.isPresenting)
|
||||
FTEC.vrDisplay.requestPresent([{ source: Module['canvas'] }]).then(function (){console.log("zomg, presenting!");}, function (err){FTEC.usevr = false;console.log("cannot vrdisplay!");});
|
||||
}
|
||||
break;
|
||||
case 'vrdisplaydeactivate':
|
||||
console.log("vr display inactive");
|
||||
if (event.display == FTEC.vrDisplay)
|
||||
{
|
||||
FTEC.vrDisplay.exitPresent()
|
||||
FTEC.usevr = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
emscriptenfte_getvrframedata : function()
|
||||
{
|
||||
if (!FTEC.vrDisplay)
|
||||
return 0;
|
||||
return FTEC.vrDisplay.isPresenting;
|
||||
// FTEC.vrframeData
|
||||
},
|
||||
emscriptenfte_getvreyedata : function (eye, ptr_proj, ptr_view)
|
||||
{
|
||||
var pm;
|
||||
var vm;
|
||||
if (eye)
|
||||
{
|
||||
pm = FTEC.vrframeData.leftProjectionMatrix;
|
||||
vm = FTEC.vrframeData.leftViewMatrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
pm = FTEC.vrframeData.rightProjectionMatrix;
|
||||
vm = FTEC.vrframeData.rightViewMatrix;
|
||||
}
|
||||
|
||||
var i;
|
||||
ptr_proj /= 4;
|
||||
ptr_view /= 4;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
HEAPF32[ptr_proj + i] = pm[i];
|
||||
HEAPF32[ptr_view + i] = vm[i];
|
||||
}
|
||||
},
|
||||
emscriptenfte_updatepointerlock : function(wantlock, softcursor)
|
||||
{
|
||||
FTEC.pointerwantlock = wantlock;
|
||||
|
@ -312,6 +371,8 @@ mergeInto(LibraryManager.library,
|
|||
var gp = gamepads[i];
|
||||
if (gp === undefined)
|
||||
continue;
|
||||
if (gp == null)
|
||||
continue;
|
||||
for (var j = 0; j < gp.buttons.length; j+=1)
|
||||
{
|
||||
var b = gp.buttons[j];
|
||||
|
@ -348,6 +409,20 @@ mergeInto(LibraryManager.library,
|
|||
FTEC.evcb.jaxis = evjaxis;
|
||||
FTEC.evcb.wantfullscreen = evwantfullscreen;
|
||||
|
||||
if (navigator.getVRDisplays)
|
||||
{
|
||||
FTEC.vrframeData = new VRFrameData();
|
||||
navigator.getVRDisplays().then(function (displays)
|
||||
{
|
||||
if (displays.length > 0)
|
||||
{
|
||||
FTEC.vrDisplay = displays[0];
|
||||
// if (vrDisplay.capabilities.canPresent)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
if ('GamepadEvent' in window)
|
||||
FTEH.gamepads = []; //don't bother ever trying to poll if we can use gamepad events. this will hopefully avoid weirdness.
|
||||
|
||||
|
@ -374,7 +449,7 @@ mergeInto(LibraryManager.library,
|
|||
document.addEventListener(event, FTEC.handleevent, true);
|
||||
});
|
||||
|
||||
var windowevents = ['message'];
|
||||
var windowevents = ['message','vrdisplaypresentchange','vrdisplayactivate','vrdisplaydeactivate'];
|
||||
windowevents.forEach(function(event)
|
||||
{
|
||||
window.addEventListener(event, FTEC.handleevent, true);
|
||||
|
@ -446,8 +521,16 @@ mergeInto(LibraryManager.library,
|
|||
Module["sched"] = function()
|
||||
{
|
||||
var dovsync = false;
|
||||
var vr = false;
|
||||
if (ABORT)
|
||||
return;
|
||||
|
||||
if (FTEC.vrDisplay)
|
||||
{
|
||||
vr = FTEC.vrDisplay.isPresenting;
|
||||
FTEC.vrDisplay.getFrameData(FTEC.vrframeData);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
dovsync = Runtime.dynCall('i', fnc, []);
|
||||
|
@ -456,8 +539,15 @@ mergeInto(LibraryManager.library,
|
|||
{
|
||||
console.log(err);
|
||||
}
|
||||
if (vr)
|
||||
FTEC.vrDisplay.submitFrame();
|
||||
if (dovsync)
|
||||
Browser.requestAnimationFrame(Module["sched"]);
|
||||
{
|
||||
if (FTEC.vrDisplay)
|
||||
FTEC.vrDisplay.requestAnimationFrame(Module["sched"]);
|
||||
else
|
||||
Browser.requestAnimationFrame(Module["sched"]);
|
||||
}
|
||||
else
|
||||
setTimeout(Module["sched"], 0);
|
||||
};
|
||||
|
|
|
@ -40,24 +40,24 @@ static void AVEnc_End (void *ctx);
|
|||
|
||||
static AVFrame *alloc_frame(enum AVPixelFormat pix_fmt, int width, int height)
|
||||
{
|
||||
AVFrame *picture;
|
||||
uint8_t *picture_buf;
|
||||
int size;
|
||||
AVFrame *picture;
|
||||
uint8_t *picture_buf;
|
||||
int size;
|
||||
|
||||
picture = av_frame_alloc();
|
||||
if(!picture)
|
||||
return NULL;
|
||||
size = av_image_get_buffer_size(pix_fmt, width, height, 1);
|
||||
picture_buf = (uint8_t*)(av_malloc(size));
|
||||
if (!picture_buf)
|
||||
{
|
||||
av_free(picture);
|
||||
return NULL;
|
||||
}
|
||||
av_image_fill_arrays(picture->data, picture->linesize, picture_buf, pix_fmt, width, height, 1/*fixme: align*/);
|
||||
picture->width = width;
|
||||
picture->height = height;
|
||||
return picture;
|
||||
picture = av_frame_alloc();
|
||||
if(!picture)
|
||||
return NULL;
|
||||
size = av_image_get_buffer_size(pix_fmt, width, height, 1);
|
||||
picture_buf = (uint8_t*)(av_malloc(size));
|
||||
if (!picture_buf)
|
||||
{
|
||||
av_free(picture);
|
||||
return NULL;
|
||||
}
|
||||
av_image_fill_arrays(picture->data, picture->linesize, picture_buf, pix_fmt, width, height, 1/*fixme: align*/);
|
||||
picture->width = width;
|
||||
picture->height = height;
|
||||
return picture;
|
||||
}
|
||||
AVStream *add_video_stream(struct encctx *ctx, AVCodec *codec, int fps, int width, int height)
|
||||
{
|
||||
|
@ -502,7 +502,7 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
|
|||
Con_DPrintf("avplug: Using Audio Codec \"%s\"\n", audiocodec->name);
|
||||
else
|
||||
Con_DPrintf("avplug: Not encoding audio\n");
|
||||
|
||||
|
||||
if (!videocodec && !audiocodec)
|
||||
{
|
||||
Con_DPrintf("avplug: Nothing to encode!\n");
|
||||
|
|
Loading…
Reference in a new issue