From 311b10bf7c30a704b06423e603b8264e95cdb442 Mon Sep 17 00:00:00 2001 From: divverent Date: Thu, 17 Jun 2010 21:39:09 +0000 Subject: [PATCH] user (csqc) controllable wavefuncs From: Rudolf Polzer git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10236 d7cf8633-e32d-0410-b094-e92efae38249 --- client.h | 3 +++ csprogs.c | 5 +++++ gl_rmain.c | 23 +++++++++++++++++++++-- model_shared.c | 26 ++++++++++++++++++-------- model_shared.h | 5 ++++- progsvm.h | 5 +++++ prvm_edict.c | 4 ++++ render.h | 3 +++ 8 files changed, 63 insertions(+), 11 deletions(-) diff --git a/client.h b/client.h index 270db45b..633335bb 100644 --- a/client.h +++ b/client.h @@ -387,6 +387,9 @@ typedef struct entity_render_s // FIELDS UPDATED BY RENDERER: // last time visible during trace culling double last_trace_visibility; + + // user wavefunc parameters (from csqc) + float userwavefunc_param[Q3WAVEFUNC_USER_COUNT]; } entity_render_t; diff --git a/csprogs.c b/csprogs.c index d417fa97..3e82840f 100644 --- a/csprogs.c +++ b/csprogs.c @@ -190,6 +190,11 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum) return false; } + if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.userwavefunc_param0))) entrender->userwavefunc_param[0] = val->_float; + if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.userwavefunc_param1))) entrender->userwavefunc_param[1] = val->_float; + if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.userwavefunc_param2))) entrender->userwavefunc_param[2] = val->_float; + if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.userwavefunc_param3))) entrender->userwavefunc_param[3] = val->_float; + entrender->model = model; entrender->skinnum = (int)ed->fields.client->skin; entrender->effects |= entrender->model->effects; diff --git a/gl_rmain.c b/gl_rmain.c index 2e83774b..fc88e5bb 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -9109,12 +9109,22 @@ static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, layer->color[3] = a; } +static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms) +{ + if(parms[0] == 0 && parms[1] == 0) + return false; + if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set! + if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0); + return false; + return true; +} + static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) { double index, f; index = parms[2] + r_refdef.scene.time * parms[3]; index -= floor(index); - switch (func) + switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1)) { default: case Q3WAVEFUNC_NONE: @@ -9139,7 +9149,10 @@ static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms) f = -(1 - f); break; } - return (float)(parms[0] + parms[1] * f); + f = parms[0] + parms[1] * f; + if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set! + f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)]; + return (float) f; } void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags) @@ -9576,6 +9589,7 @@ void RSurf_ActiveWorldEntity(void) // return; rsurface.entity = r_refdef.scene.worldentity; rsurface.skeleton = NULL; + memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param)); rsurface.ent_skinnum = 0; rsurface.ent_qwskin = -1; rsurface.ent_shadertime = 0; @@ -9690,6 +9704,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q // return; rsurface.entity = (entity_render_t *)ent; rsurface.skeleton = ent->skeleton; + memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param)); rsurface.ent_skinnum = ent->skinnum; rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1; rsurface.ent_shadertime = ent->shadertime; @@ -10691,6 +10706,8 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const waveparms[1] = deform->waveparms[1]; waveparms[2] = deform->waveparms[2]; waveparms[3] = deform->waveparms[3]; + if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms)) + break; // if wavefunc is a nop, don't make a dynamic vertex array // this is how a divisor of vertex influence on deformation animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f; scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms); @@ -10743,6 +10760,8 @@ void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const break; case Q3DEFORM_MOVE: // deform vertex array + if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms)) + break; // if wavefunc is a nop, don't make a dynamic vertex array scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms); VectorScale(deform->parms, scale, waveparms); for (j = 0;j < rsurface.batchnumvertices;j++) diff --git a/model_shared.c b/model_shared.c index 0269989b..97c4dea8 100644 --- a/model_shared.c +++ b/model_shared.c @@ -1532,16 +1532,26 @@ void Mod_Terrain_UpdateSurfacesForViewOrigin(dp_model_t *model) } #endif -q3wavefunc_t Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s) +int Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s) { - if (!strcasecmp(s, "sin")) return Q3WAVEFUNC_SIN; - if (!strcasecmp(s, "square")) return Q3WAVEFUNC_SQUARE; - if (!strcasecmp(s, "triangle")) return Q3WAVEFUNC_TRIANGLE; - if (!strcasecmp(s, "sawtooth")) return Q3WAVEFUNC_SAWTOOTH; - if (!strcasecmp(s, "inversesawtooth")) return Q3WAVEFUNC_INVERSESAWTOOTH; - if (!strcasecmp(s, "noise")) return Q3WAVEFUNC_NOISE; + int offset = 0; + if (!strncasecmp(s, "user", 4)) // parse stuff like "user1sin", always userfunc + { + offset = bound(0, s[4] - '0', 9); + offset = (offset + 1) << Q3WAVEFUNC_USER_SHIFT; + s += 4; + if(*s) + ++s; + } + if (!strcasecmp(s, "sin")) return offset | Q3WAVEFUNC_SIN; + if (!strcasecmp(s, "square")) return offset | Q3WAVEFUNC_SQUARE; + if (!strcasecmp(s, "triangle")) return offset | Q3WAVEFUNC_TRIANGLE; + if (!strcasecmp(s, "sawtooth")) return offset | Q3WAVEFUNC_SAWTOOTH; + if (!strcasecmp(s, "inversesawtooth")) return offset | Q3WAVEFUNC_INVERSESAWTOOTH; + if (!strcasecmp(s, "noise")) return offset | Q3WAVEFUNC_NOISE; + if (!strcasecmp(s, "none")) return offset | Q3WAVEFUNC_NONE; Con_DPrintf("Mod_LoadQ3Shaders: unknown wavefunc %s\n", s); - return Q3WAVEFUNC_NONE; + return offset | Q3WAVEFUNC_NONE; } void Mod_FreeQ3Shaders(void) diff --git a/model_shared.h b/model_shared.h index eca7ef39..f8a8dabe 100644 --- a/model_shared.h +++ b/model_shared.h @@ -283,7 +283,10 @@ typedef enum q3wavefunc_e Q3WAVEFUNC_TRIANGLE, Q3WAVEFUNC_COUNT } -q3wavefunc_t; +q3wavefunc_e; +typedef int q3wavefunc_t; +#define Q3WAVEFUNC_USER_COUNT 4 +#define Q3WAVEFUNC_USER_SHIFT 8 // use 8 bits for wave func type typedef enum q3deform_e { diff --git a/progsvm.h b/progsvm.h index fd9af609..a5a5a981 100644 --- a/progsvm.h +++ b/progsvm.h @@ -269,6 +269,11 @@ typedef struct prvm_prog_fieldoffsets_s int movedir; // ssqc / csqc (physics) int camera_transform; // csqc (warpzones) + + int userwavefunc_param0; // csqc (userwavefunc) + int userwavefunc_param1; // csqc (userwavefunc) + int userwavefunc_param2; // csqc (userwavefunc) + int userwavefunc_param3; // csqc (userwavefunc) } prvm_prog_fieldoffsets_t; diff --git a/prvm_edict.c b/prvm_edict.c index ceb0e3cb..5a51babb 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -1656,6 +1656,10 @@ void PRVM_FindOffsets(void) prog->fieldoffsets.movedir = PRVM_ED_FindFieldOffset("movedir"); prog->fieldoffsets.camera_transform = PRVM_ED_FindFieldOffset("camera_transform"); + prog->fieldoffsets.userwavefunc_param0 = PRVM_ED_FindFieldOffset("userwavefunc_param0"); + prog->fieldoffsets.userwavefunc_param1 = PRVM_ED_FindFieldOffset("userwavefunc_param1"); + prog->fieldoffsets.userwavefunc_param2 = PRVM_ED_FindFieldOffset("userwavefunc_param2"); + prog->fieldoffsets.userwavefunc_param3 = PRVM_ED_FindFieldOffset("userwavefunc_param3"); prog->funcoffsets.CSQC_ConsoleCommand = PRVM_ED_FindFunctionOffset("CSQC_ConsoleCommand"); prog->funcoffsets.CSQC_Ent_Remove = PRVM_ED_FindFunctionOffset("CSQC_Ent_Remove"); diff --git a/render.h b/render.h index aa90252b..7cc1ae22 100644 --- a/render.h +++ b/render.h @@ -410,6 +410,9 @@ typedef struct rsurfacestate_s // this transforms only the Z to S, and T is always 0.5 matrix4x4_t entitytoattenuationz; + // user wavefunc parameters (from csqc) + float userwavefunc_param[Q3WAVEFUNC_USER_COUNT]; + // pointer to an entity_render_t used only by R_GetCurrentTexture and // RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity as a unique id within // each frame (see r_frame also) -- 2.39.2