From: divverent Date: Thu, 17 Jun 2010 21:39:09 +0000 (+0000) Subject: user (csqc) controllable wavefuncs X-Git-Tag: xonotic-v0.1.0preview~418 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=ee73f9d9298dfa6cc3230aa7b2c0229acd999d54;p=xonotic%2Fdarkplaces.git user (csqc) controllable wavefuncs From: Rudolf Polzer git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10236 d7cf8633-e32d-0410-b094-e92efae38249 ::stable-branch::merge=311b10bf7c30a704b06423e603b8264e95cdb442 --- diff --git a/client.h b/client.h index d9f58717..39df09f0 100644 --- a/client.h +++ b/client.h @@ -382,6 +382,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 ba58be6a..6297a23b 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -9156,12 +9156,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: @@ -9186,7 +9196,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) @@ -9596,6 +9609,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; @@ -9678,6 +9692,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; @@ -10226,6 +10241,8 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta 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); @@ -10266,6 +10283,8 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta 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 (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) diff --git a/model_shared.c b/model_shared.c index 5405648e..a74df82d 100644 --- a/model_shared.c +++ b/model_shared.c @@ -1482,16 +1482,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 e02b49e4..81ea62ee 100644 --- a/model_shared.h +++ b/model_shared.h @@ -232,7 +232,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 50d55482..0a5ea298 100644 --- a/render.h +++ b/render.h @@ -378,6 +378,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)