diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 4f4b5d035..f60a760b2 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -6048,8 +6048,10 @@ static struct { {"skel_get_bonerel", PF_skel_get_bonerel, 269},//vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) {"skel_get_boneabs", PF_skel_get_boneabs, 270},//vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) {"skel_set_bone", PF_skel_set_bone, 271},//void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_mul_bone", PF_skel_mul_bone, 272},//void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_mul_bones", PF_skel_mul_bones, 273},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone = #273; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_premul_bone", PF_skel_premul_bone, 272},//void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_premul_bones", PF_skel_premul_bones, 273},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone = #273; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_postmul_bone", PF_skel_postmul_bone, 0},//void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +// {"skel_postmul_bones", PF_skel_postmul_bones, 0},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone = #273; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) {"skel_copybones", PF_skel_copybones, 274},//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS) {"skel_delete", PF_skel_delete, 275},//void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS) {"frameforname", PF_frameforname, 276},//void(float modidx, string framename) frameforname = #276 (FTE_CSQC_SKELETONOBJECTS) diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c index 3eb6ec4c6..8d89d9ff3 100644 --- a/engine/client/pr_skelobj.c +++ b/engine/client/pr_skelobj.c @@ -2175,7 +2175,7 @@ void QCBUILTIN PF_skel_set_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr } //void(float skel, float bonenum, vector org [, vector fwd, vector right, vector up]) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) -void QCBUILTIN PF_skel_mul_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +void QCBUILTIN PF_skel_premul_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { world_t *w = prinst->parms->user; int skelidx = G_FLOAT(OFS_PARM0); @@ -2191,15 +2191,38 @@ void QCBUILTIN PF_skel_mul_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr skelobj = skel_get(w, skelidx); if (!skelobj || boneidx >= skelobj->numbones) return; -//testme + + //this is backwards. it rotates the EXISTING position around the passed position. this makes it hard to work with bones that have existing animation data (even if its a static transform). Vector4Copy(skelobj->bonematrix+12*boneidx+0, temp[0]); Vector4Copy(skelobj->bonematrix+12*boneidx+4, temp[1]); Vector4Copy(skelobj->bonematrix+12*boneidx+8, temp[2]); R_ConcatTransforms(mult, temp, (float(*)[4])(skelobj->bonematrix+12*boneidx)); } +void QCBUILTIN PF_skel_postmul_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + int skelidx = G_FLOAT(OFS_PARM0); + int boneidx = G_FLOAT(OFS_PARM1)-1; + float temp[3][4]; + float mult[3][4]; + skelobject_t *skelobj; + if (prinst->callargc > 5) + bonemat_fromqcvectors((float*)mult, G_VECTOR(OFS_PARM3), G_VECTOR(OFS_PARM4), G_VECTOR(OFS_PARM5), G_VECTOR(OFS_PARM2)); + else + bonemat_fromqcvectors((float*)mult, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_PARM2)); + + skelobj = skel_get(w, skelidx); + if (!skelobj || boneidx >= skelobj->numbones) + return; + + Vector4Copy(skelobj->bonematrix+12*boneidx+0, temp[0]); + Vector4Copy(skelobj->bonematrix+12*boneidx+4, temp[1]); + Vector4Copy(skelobj->bonematrix+12*boneidx+8, temp[2]); + R_ConcatTransforms(temp, mult, (float(*)[4])(skelobj->bonematrix+12*boneidx)); +} //void(float skel, float startbone, float endbone, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) -void QCBUILTIN PF_skel_mul_bones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +void QCBUILTIN PF_skel_premul_bones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { world_t *w = prinst->parms->user; int skelidx = G_FLOAT(OFS_PARM0); diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 59e98c18d..72a439559 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -6540,7 +6540,7 @@ lh_extension_t QSG_Extensions[] = { "resorthostcache", "sethostcachesort", "refreshhostcache", "gethostcachenumber", "gethostcacheindexforkey", "addwantedhostcachekey", "getextresponse"}, "Provides builtins to query the engine's serverbrowser servers list from ssqc. Note that these builtins are always available in menuqc."}, {"FTE_CSQC_SKELETONOBJECTS", 15, NULL, { "skel_create", "skel_build", "skel_get_numbones", "skel_get_bonename", "skel_get_boneparent", "skel_find_bone", - "skel_get_bonerel", "skel_get_boneabs", "skel_set_bone", "skel_mul_bone", "skel_mul_bones", "skel_copybones", + "skel_get_bonerel", "skel_get_boneabs", "skel_set_bone", "skel_premul_bone", "skel_premul_bones", "skel_copybones", "skel_delete", "frameforname", "frameduration"}, "Provides container objects for skeletal bone data, which can be modified on a per bone basis if needed. This allows you to dynamically generate animations (or just blend them with greater customisation) instead of being limited to a single animation or two."}, {"FTE_CSQC_RAWIMAGES", 2, NULL, {"r_uploadimage","r_readimage"}, "Provides raw rgba image access to csqc. With this, the csprogs can read textures into qc-accessible memory, modify it, and then upload it to the renderer."}, {"FTE_CSQC_RENDERTARGETS", 0, NULL, {NULL}, "VF_RT_DESTCOLOUR exists and can be used to redirect any rendering to a texture instead of the screen."}, diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 78c9eb5d4..0eee76405 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -223,8 +223,10 @@ void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_ #define PF_frameforname PF_Fixme #define PF_skel_delete PF_Fixme #define PF_skel_copybones PF_Fixme - #define PF_skel_mul_bones PF_Fixme - #define PF_skel_mul_bone PF_Fixme + #define PF_skel_premul_bones PF_Fixme + #define PF_skel_premul_bone PF_Fixme + #define PF_skel_postmul_bones PF_Fixme + #define PF_skel_postmul_bone PF_Fixme #define PF_skel_set_bone PF_Fixme #define PF_skel_get_boneabs PF_Fixme #define PF_skel_get_bonerel PF_Fixme @@ -252,8 +254,10 @@ void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_ void QCBUILTIN PF_skel_get_bonerel (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_get_boneabs (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_set_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); - void QCBUILTIN PF_skel_mul_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); - void QCBUILTIN PF_skel_mul_bones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); + void QCBUILTIN PF_skel_premul_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); + void QCBUILTIN PF_skel_premul_bones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); + void QCBUILTIN PF_skel_postmul_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); + void QCBUILTIN PF_skel_postmul_bones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_copybones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_skel_delete (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_frametoname (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index c76e19aa4..6c8d5f6e9 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -10333,8 +10333,10 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"skel_get_bonerel",PF_skel_get_bonerel,0, 0, 0, 269, D("vector(float skel, float bonenum)", "Gets the bone position and orientation relative to the bone's parent. Return value is the offset, and v_forward, v_right, v_up contain the orientation.")}, // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) {"skel_get_boneabs",PF_skel_get_boneabs,0, 0, 0, 270, D("vector(float skel, float bonenum)", "Gets the bone position and orientation relative to the entity. Return value is the offset, and v_forward, v_right, v_up contain the orientation.\nUse gettaginfo for world coord+orientation.")}, // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) {"skel_set_bone", PF_skel_set_bone, 0, 0, 0, 271, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Sets a bone position relative to its parent. If the orientation arguments are not specified, v_forward+v_right+v_up are used instead.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_mul_bone", PF_skel_mul_bone, 0, 0, 0, 272, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms a single bone by a matrix. You can use makevectors to generate a rotation matrix from an angle.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_mul_bones", PF_skel_mul_bones, 0, 0, 0, 273, D("void(float skel, float startbone, float endbone, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms an entire consecutive range of bones by a matrix. You can use makevectors to generate a rotation matrix from an angle, but you'll probably want to divide the angle by the number of bones.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_premul_bone",PF_skel_mul_bone, 0, 0, 0, 272, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms a single bone by a matrix. You can use makevectors to generate a rotation matrix from an angle.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_premul_bones",PF_skel_mul_bones, 0, 0, 0, 273, D("void(float skel, float startbone, float endbone, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms an entire consecutive range of bones by a matrix. You can use makevectors to generate a rotation matrix from an angle, but you'll probably want to divide the angle by the number of bones.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_postmul_bone",PF_skel_mul_bone, 0, 0, 0, 0, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms a single bone by a matrix. You can use makevectors to generate a rotation matrix from an angle.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +// {"skel_postmul_bones",PF_skel_mul_bones,0, 0, 0, 0, D("void(float skel, float startbone, float endbone, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms an entire consecutive range of bones by a matrix. You can use makevectors to generate a rotation matrix from an angle, but you'll probably want to divide the angle by the number of bones.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) {"skel_copybones", PF_skel_copybones, 0, 0, 0, 274, D("void(float skeldst, float skelsrc, float startbone, float entbone)", "Copy bone data from one skeleton directly into another.")}, // (FTE_CSQC_SKELETONOBJECTS) {"skel_delete", PF_skel_delete, 0, 0, 0, 275, D("void(float skel)", "Deletes a skeletal object. The actual delete is delayed, allowing the skeletal object to be deleted in an entity's predraw function yet still be valid by the time the addentity+renderscene builtins need it. Also uninstanciates any ragdoll currently in effect on the skeletal object.")}, // (FTE_CSQC_SKELETONOBJECTS) {"frameforname", PF_frameforname, 0, 0, 0, 276, D("float(float modidx, string framename)", "Looks up a framegroup from a model by name, avoiding the need for hardcoding. Returns -1 on error.")},// (FTE_CSQC_SKELETONOBJECTS)