mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-12-11 13:21:10 +00:00
[util] Add vector swizzles to cexpr
That turned out to be a lot easier than expected: needed only 4 ifs per vector "type" (xyzw vs rgba) instead of 340.
This commit is contained in:
parent
4562e0b876
commit
619fe15367
1 changed files with 73 additions and 0 deletions
|
@ -391,6 +391,78 @@ vector_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result,
|
|||
*c = a - b * vfloorf (a / b);
|
||||
}
|
||||
|
||||
static void
|
||||
vector_swizzle (const exprval_t *val1, const exprval_t *val2,
|
||||
exprval_t *result, exprctx_t *ctx)
|
||||
{
|
||||
#define m(x) (1 << ((x) - 'a'))
|
||||
#define v(x, mask) (((x) & 0x60) == 0x60 && (m(x) & (mask)))
|
||||
#define vind(x) ((x) & 3)
|
||||
#define cind(x) (-(((x) >> 3) ^ (x)) & 3)
|
||||
const int color = m('r') | m('g') | m('b') | m('a');
|
||||
const int vector = m('x') | m('y') | m('z') | m('w');
|
||||
float *vec = val1->value;
|
||||
const char *name = val2->value;
|
||||
exprval_t *val = 0;
|
||||
|
||||
if (v (name[0], vector) && v (name[1], vector)
|
||||
&& v (name[2], vector) && v (name[3], vector) && !name[4]) {
|
||||
val = cexpr_value (&cexpr_vector, ctx);
|
||||
float *res = val->value;
|
||||
res[0] = vec[vind (name[0])];
|
||||
res[1] = vec[vind (name[1])];
|
||||
res[2] = vec[vind (name[2])];
|
||||
res[3] = vec[vind (name[3])];
|
||||
} else if (v (name[0], color) && v (name[1], color)
|
||||
&& v (name[2], color) && v (name[3], color) && !name[4]) {
|
||||
val = cexpr_value (&cexpr_vector, ctx);
|
||||
float *res = val->value;
|
||||
res[0] = vec[cind (name[0])];
|
||||
res[1] = vec[cind (name[1])];
|
||||
res[2] = vec[cind (name[2])];
|
||||
res[3] = vec[cind (name[3])];
|
||||
} else if (v (name[0], vector) && v (name[1], vector)
|
||||
&& v (name[2], vector) && !name[3]) {
|
||||
val = cexpr_value (&cexpr_vector, ctx);
|
||||
float *res = val->value;
|
||||
res[0] = vec[vind (name[0])];
|
||||
res[1] = vec[vind (name[1])];
|
||||
res[2] = vec[vind (name[2])];
|
||||
res[3] = 0;
|
||||
} else if (v (name[0], color) && v (name[1], color)
|
||||
&& v (name[2], color) && !name[3]) {
|
||||
val = cexpr_value (&cexpr_vector, ctx);
|
||||
float *res = val->value;
|
||||
res[0] = vec[cind (name[0])];
|
||||
res[1] = vec[cind (name[1])];
|
||||
res[2] = vec[cind (name[2])];
|
||||
res[3] = 0;
|
||||
} else if (v (name[0], vector) && v (name[1], vector) && !name[2]) {
|
||||
val = cexpr_value (&cexpr_vector, ctx);
|
||||
float *res = val->value;
|
||||
res[0] = vec[vind (name[0])];
|
||||
res[1] = vec[vind (name[1])];
|
||||
res[2] = 0;
|
||||
res[3] = 0;
|
||||
} else if (v (name[0], color) && v (name[1], color) && !name[2]) {
|
||||
val = cexpr_value (&cexpr_vector, ctx);
|
||||
float *res = val->value;
|
||||
res[0] = vec[cind (name[0])];
|
||||
res[1] = vec[cind (name[1])];
|
||||
res[2] = 0;
|
||||
res[3] = 0;
|
||||
} else if (v (name[0], vector) && !name[1]) {
|
||||
val = cexpr_value (&cexpr_float, ctx);
|
||||
float *res = val->value;
|
||||
res[0] = vec[vind (name[0])];
|
||||
} else if (v (name[0], color) && !name[1]) {
|
||||
val = cexpr_value (&cexpr_float, ctx);
|
||||
float *res = val->value;
|
||||
res[0] = vec[cind (name[0])];
|
||||
}
|
||||
*(exprval_t **) result->value = val;
|
||||
}
|
||||
|
||||
UNOP(vector, pos, vec4f_t, +)
|
||||
UNOP(vector, neg, vec4f_t, -)
|
||||
|
||||
|
@ -410,6 +482,7 @@ binop_t vector_binops[] = {
|
|||
{ '/', &cexpr_vector, &cexpr_vector, vector_div },
|
||||
{ '%', &cexpr_vector, &cexpr_vector, vector_rem },
|
||||
{ MOD, &cexpr_vector, &cexpr_vector, vector_mod },
|
||||
{ '.', &cexpr_field, &cexpr_exprval, vector_swizzle },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue