mirror of https://github.com/inolen/redream.git
properly calculate missing z, u, v coordinates for sprites
This commit is contained in:
parent
7d2e9cf3e6
commit
8140daecfe
|
@ -13,17 +13,9 @@
|
|||
#define ALIGN_UP(v, alignment) (((v) + (alignment)-1) & ~((alignment)-1))
|
||||
#define ALIGN_DOWN(v, alignment) ((v) & ~((alignment)-1))
|
||||
|
||||
static inline uint32_t npow2(uint32_t v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* bitwise ops
|
||||
*/
|
||||
static inline uint32_t bswap24(uint32_t v) {
|
||||
return ((v & 0xff) << 16) | (v & 0x00ff00) | ((v & 0xff0000) >> 16);
|
||||
}
|
||||
|
@ -95,4 +87,66 @@ static inline uint32_t bswap32(uint32_t v) {
|
|||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* scalar ops
|
||||
*/
|
||||
static inline uint32_t npow2(uint32_t v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* vector ops
|
||||
*/
|
||||
static inline float vec3_dot(float *a, float *b) {
|
||||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||||
}
|
||||
|
||||
static inline float vec3_len(float *a) {
|
||||
return sqrtf(vec3_dot(a, a));
|
||||
}
|
||||
|
||||
static inline float vec3_normalize(float *a) {
|
||||
float len = vec3_len(a);
|
||||
if (len) {
|
||||
a[0] /= len;
|
||||
a[1] /= len;
|
||||
a[2] /= len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline void vec3_add(float *out, float *a, float *b) {
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
out[2] = a[2] + b[2];
|
||||
}
|
||||
static inline void vec3_sub(float *out, float *a, float *b) {
|
||||
out[0] = a[0] - b[0];
|
||||
out[1] = a[1] - b[1];
|
||||
out[2] = a[2] - b[2];
|
||||
}
|
||||
|
||||
static inline void vec3_cross(float *out, float *a, float *b) {
|
||||
out[0] = a[1] * b[2] - a[2] * b[1];
|
||||
out[1] = a[2] * b[0] - a[0] * b[2];
|
||||
out[2] = a[0] * b[1] - a[1] * b[0];
|
||||
}
|
||||
|
||||
static inline void vec2_add(float *out, float *a, float *b) {
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
}
|
||||
|
||||
static inline void vec2_sub(float *out, float *a, float *b) {
|
||||
out[0] = a[0] - b[0];
|
||||
out[1] = a[1] - b[1];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -263,7 +263,7 @@ union vert_param {
|
|||
struct {
|
||||
union pcw pcw;
|
||||
float xyz[3];
|
||||
uint16_t vu[2];
|
||||
uint16_t uv[2];
|
||||
uint32_t ignore_0;
|
||||
uint32_t base_color;
|
||||
uint32_t offset_color;
|
||||
|
@ -288,7 +288,7 @@ union vert_param {
|
|||
struct {
|
||||
union pcw pcw;
|
||||
float xyz[3];
|
||||
uint16_t vu[2];
|
||||
uint16_t uv[2];
|
||||
uint32_t ignore_0;
|
||||
uint32_t ignore_1;
|
||||
uint32_t ignore_2;
|
||||
|
@ -313,7 +313,7 @@ union vert_param {
|
|||
struct {
|
||||
union pcw pcw;
|
||||
float xyz[3];
|
||||
uint16_t vu[2];
|
||||
uint16_t uv[2];
|
||||
uint32_t ignore_0;
|
||||
float base_intensity;
|
||||
float offset_intensity;
|
||||
|
@ -412,7 +412,7 @@ union vert_param {
|
|||
struct {
|
||||
union pcw pcw;
|
||||
float xyz[4][3];
|
||||
uint32_t uv[3];
|
||||
uint16_t uv[3][2];
|
||||
} sprite1;
|
||||
};
|
||||
|
||||
|
|
|
@ -277,10 +277,10 @@ static inline uint8_t fmulu8(uint8_t a, uint8_t b) {
|
|||
(out)[1] = (uv)[1]; \
|
||||
}
|
||||
|
||||
#define PARSE_UV16(vu, out) \
|
||||
#define PARSE_UV16(uv, out) \
|
||||
{ \
|
||||
uint32_t u = (vu)[1] << 16; \
|
||||
uint32_t v = (vu)[0] << 16; \
|
||||
uint32_t u = (uv)[1] << 16; \
|
||||
uint32_t v = (uv)[0] << 16; \
|
||||
(out)[0] = *(float *)&u; \
|
||||
(out)[1] = *(float *)&v; \
|
||||
}
|
||||
|
@ -364,38 +364,38 @@ static void tr_parse_bg(struct tr *tr, const struct ta_context *ctx,
|
|||
surf->params.dst_blend = BLEND_NONE;
|
||||
|
||||
/* translate the first 3 vertices */
|
||||
struct ta_vertex *v0 = tr_reserve_vert(tr, rc);
|
||||
struct ta_vertex *v1 = tr_reserve_vert(tr, rc);
|
||||
struct ta_vertex *v2 = tr_reserve_vert(tr, rc);
|
||||
struct ta_vertex *v3 = tr_reserve_vert(tr, rc);
|
||||
struct ta_vertex *va = tr_reserve_vert(tr, rc);
|
||||
struct ta_vertex *vb = tr_reserve_vert(tr, rc);
|
||||
struct ta_vertex *vc = tr_reserve_vert(tr, rc);
|
||||
struct ta_vertex *vd = tr_reserve_vert(tr, rc);
|
||||
|
||||
int offset = 0;
|
||||
offset = tr_parse_bg_vert(ctx, rc, offset, v0);
|
||||
offset = tr_parse_bg_vert(ctx, rc, offset, v1);
|
||||
offset = tr_parse_bg_vert(ctx, rc, offset, v2);
|
||||
offset = tr_parse_bg_vert(ctx, rc, offset, va);
|
||||
offset = tr_parse_bg_vert(ctx, rc, offset, vb);
|
||||
offset = tr_parse_bg_vert(ctx, rc, offset, vc);
|
||||
|
||||
/* override xyz values supplied by ISP_BACKGND_T. while the hardware docs act
|
||||
like they should be correct, they're most definitely not in most cases */
|
||||
v0->xyz[0] = 0.0f;
|
||||
v0->xyz[1] = (float)ctx->video_height;
|
||||
v0->xyz[2] = ctx->bg_depth;
|
||||
va->xyz[0] = 0.0f;
|
||||
va->xyz[1] = (float)ctx->video_height;
|
||||
va->xyz[2] = ctx->bg_depth;
|
||||
|
||||
v1->xyz[0] = 0.0f;
|
||||
v1->xyz[1] = 0.0f;
|
||||
v1->xyz[2] = ctx->bg_depth;
|
||||
vb->xyz[0] = 0.0f;
|
||||
vb->xyz[1] = 0.0f;
|
||||
vb->xyz[2] = ctx->bg_depth;
|
||||
|
||||
v2->xyz[0] = (float)ctx->video_width;
|
||||
v2->xyz[1] = (float)ctx->video_height;
|
||||
v2->xyz[2] = ctx->bg_depth;
|
||||
vc->xyz[0] = (float)ctx->video_width;
|
||||
vc->xyz[1] = (float)ctx->video_height;
|
||||
vc->xyz[2] = ctx->bg_depth;
|
||||
|
||||
/* 4th vertex isn't supplied, fill it out automatically */
|
||||
v3->xyz[0] = v2->xyz[0];
|
||||
v3->xyz[1] = v1->xyz[1];
|
||||
v3->xyz[2] = ctx->bg_depth;
|
||||
v3->uv[0] = v2->uv[0];
|
||||
v3->uv[1] = v1->uv[1];
|
||||
v3->color = v0->color;
|
||||
v3->offset_color = v0->offset_color;
|
||||
vd->xyz[0] = vc->xyz[0];
|
||||
vd->xyz[1] = vb->xyz[1];
|
||||
vd->xyz[2] = ctx->bg_depth;
|
||||
vd->uv[0] = vc->uv[0];
|
||||
vd->uv[1] = vb->uv[1];
|
||||
vd->color = va->color;
|
||||
vd->offset_color = va->offset_color;
|
||||
|
||||
tr_commit_surf(tr, rc);
|
||||
|
||||
|
@ -534,7 +534,7 @@ static void tr_parse_vert_param(struct tr *tr, const struct ta_context *ctx,
|
|||
case 4: {
|
||||
struct ta_vertex *vert = tr_reserve_vert(tr, rc);
|
||||
PARSE_XYZ(param->type4.xyz, vert->xyz);
|
||||
PARSE_UV16(param->type4.vu, vert->uv);
|
||||
PARSE_UV16(param->type4.uv, vert->uv);
|
||||
PARSE_PACKED_COLOR(param->type4.base_color, &vert->color);
|
||||
PARSE_PACKED_COLOR(param->type4.offset_color, &vert->offset_color);
|
||||
} break;
|
||||
|
@ -550,7 +550,7 @@ static void tr_parse_vert_param(struct tr *tr, const struct ta_context *ctx,
|
|||
case 6: {
|
||||
struct ta_vertex *vert = tr_reserve_vert(tr, rc);
|
||||
PARSE_XYZ(param->type6.xyz, vert->xyz);
|
||||
PARSE_UV16(param->type6.vu, vert->uv);
|
||||
PARSE_UV16(param->type6.uv, vert->uv);
|
||||
PARSE_FLOAT_COLOR(param->type6.base_color, &vert->color);
|
||||
PARSE_FLOAT_COLOR(param->type6.offset_color, &vert->offset_color);
|
||||
} break;
|
||||
|
@ -567,56 +567,88 @@ static void tr_parse_vert_param(struct tr *tr, const struct ta_context *ctx,
|
|||
case 8: {
|
||||
struct ta_vertex *vert = tr_reserve_vert(tr, rc);
|
||||
PARSE_XYZ(param->type8.xyz, vert->xyz);
|
||||
PARSE_UV16(param->type8.vu, vert->uv);
|
||||
PARSE_UV16(param->type8.uv, vert->uv);
|
||||
PARSE_BASE_INTENSITY(param->type8.base_intensity, &vert->color);
|
||||
PARSE_OFFSET_INTENSITY(param->type8.offset_intensity,
|
||||
&vert->offset_color);
|
||||
} break;
|
||||
|
||||
case 15: {
|
||||
CHECK(param->type0.pcw.end_of_strip);
|
||||
|
||||
static const int indices[] = {0, 1, 3, 2};
|
||||
|
||||
for (int i = 0, l = ARRAY_SIZE(indices); i < l; i++) {
|
||||
int idx = indices[i];
|
||||
struct ta_vertex *vert = tr_reserve_vert(tr, rc);
|
||||
|
||||
/* FIXME this is assuming all sprites are billboards */
|
||||
vert->xyz[0] = param->sprite0.xyz[idx][0];
|
||||
vert->xyz[1] = param->sprite0.xyz[idx][1];
|
||||
vert->xyz[2] = param->sprite0.xyz[0][2];
|
||||
vert->color = *(uint32_t *)&tr->sprite_color;
|
||||
vert->offset_color = *(uint32_t *)&tr->sprite_offset_color;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 15:
|
||||
case 16: {
|
||||
CHECK(param->type0.pcw.end_of_strip);
|
||||
|
||||
static const int indices[] = {0, 1, 3, 2};
|
||||
/*
|
||||
* sprites are input as a quad in a clockwise order:
|
||||
*
|
||||
* b (x,y,z,u,v) ---> c (x,y,z,u,v)
|
||||
* ^ |
|
||||
* | |
|
||||
* | |
|
||||
* | v
|
||||
* a (x,y,z,u,v) <--- d (x,y,0,0,0)
|
||||
*
|
||||
* note that the z, u, v components aren't specified for the final vertex.
|
||||
* these need to be calculated, and the quad needs to be converted into a
|
||||
* tristrip to match the rest of the ta input
|
||||
*/
|
||||
struct ta_vertex *va = tr_reserve_vert(tr, rc); /* bottom left */
|
||||
struct ta_vertex *vb = tr_reserve_vert(tr, rc); /* top left */
|
||||
struct ta_vertex *vd = tr_reserve_vert(tr, rc); /* bottom right */
|
||||
struct ta_vertex *vc = tr_reserve_vert(tr, rc); /* top right */
|
||||
|
||||
for (int i = 0, l = ARRAY_SIZE(indices); i < l; i++) {
|
||||
int idx = indices[i];
|
||||
struct ta_vertex *vert = tr_reserve_vert(tr, rc);
|
||||
PARSE_XYZ(param->sprite1.xyz[0], va->xyz);
|
||||
PARSE_UV16(param->sprite1.uv[0], va->uv);
|
||||
va->color = *(uint32_t *)&tr->sprite_color;
|
||||
va->offset_color = *(uint32_t *)&tr->sprite_offset_color;
|
||||
|
||||
/* FIXME this is assuming all sprites are billboards */
|
||||
vert->xyz[0] = param->sprite1.xyz[idx][0];
|
||||
vert->xyz[1] = param->sprite1.xyz[idx][1];
|
||||
vert->xyz[2] = param->sprite1.xyz[0][2];
|
||||
uint32_t u, v;
|
||||
if (idx == 3) {
|
||||
u = (param->sprite1.uv[0] & 0xffff0000);
|
||||
v = (param->sprite1.uv[2] & 0x0000ffff) << 16;
|
||||
} else {
|
||||
u = (param->sprite1.uv[idx] & 0xffff0000);
|
||||
v = (param->sprite1.uv[idx] & 0x0000ffff) << 16;
|
||||
}
|
||||
vert->uv[0] = *(float *)&u;
|
||||
vert->uv[1] = *(float *)&v;
|
||||
vert->color = *(uint32_t *)&tr->sprite_color;
|
||||
vert->offset_color = *(uint32_t *)&tr->sprite_offset_color;
|
||||
PARSE_XYZ(param->sprite1.xyz[1], vb->xyz);
|
||||
PARSE_UV16(param->sprite1.uv[1], vb->uv);
|
||||
vb->color = *(uint32_t *)&tr->sprite_color;
|
||||
vb->offset_color = *(uint32_t *)&tr->sprite_offset_color;
|
||||
|
||||
PARSE_XYZ(param->sprite1.xyz[2], vc->xyz);
|
||||
PARSE_UV16(param->sprite1.uv[2], vc->uv);
|
||||
vc->color = *(uint32_t *)&tr->sprite_color;
|
||||
vc->offset_color = *(uint32_t *)&tr->sprite_offset_color;
|
||||
|
||||
vd->xyz[0] = param->sprite1.xyz[3][0];
|
||||
vd->xyz[1] = param->sprite1.xyz[3][1];
|
||||
vd->color = *(uint32_t *)&tr->sprite_color;
|
||||
vd->offset_color = *(uint32_t *)&tr->sprite_offset_color;
|
||||
|
||||
/* calculate the sprite's plane from the three complete vertices */
|
||||
float xyz_ba[3], xyz_bc[3];
|
||||
float n[3], len, d;
|
||||
vec3_sub(xyz_ba, va->xyz, vb->xyz);
|
||||
vec3_sub(xyz_bc, vc->xyz, vb->xyz);
|
||||
vec3_cross(n, xyz_ba, xyz_bc);
|
||||
len = vec3_normalize(n);
|
||||
d = vec3_dot(n, vb->xyz);
|
||||
|
||||
/* don't commit surf if quad is degenerate or perpendicular to our view */
|
||||
if (len == 0.0f || n[2] == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* for all points on a plane, the following must hold true:
|
||||
* dot(n, p) - d = 0
|
||||
*
|
||||
* using this, the missing corner's z can be solved with:
|
||||
* n.x * p.x + n.y * p.y + n.z * p.z - d = 0
|
||||
* n.x * p.x + n.y * p.y + n.z * p.z = d
|
||||
* n.z * p.z = d - n.x * p.x - n.y * p.y
|
||||
* p.z = (d - n.x * p.y - n.y * p.y) / n.z
|
||||
*/
|
||||
vd->xyz[2] = (d - n[0] * vd->xyz[0] - n[1] * vd->xyz[1]) / n[2];
|
||||
|
||||
/* calculate the missing corner's uv */
|
||||
float uv_ba[2], uv_bc[2];
|
||||
vec2_sub(uv_ba, va->uv, vb->uv);
|
||||
vec2_sub(uv_bc, vc->uv, vb->uv);
|
||||
|
||||
vec2_add(vd->uv, vb->uv, uv_ba);
|
||||
vec2_add(vd->uv, vd->uv, uv_bc);
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -431,7 +431,7 @@ static void tracer_param_tooltip(struct tracer *tracer, struct tr_param *rp) {
|
|||
*(uint32_t *)(float *)¶m->type4.xyz[0],
|
||||
*(uint32_t *)(float *)¶m->type4.xyz[1],
|
||||
*(uint32_t *)(float *)¶m->type4.xyz[2]);
|
||||
igText("uv: {0x%x, 0x%x}", param->type4.vu[1], param->type4.vu[0]);
|
||||
igText("uv: {0x%x, 0x%x}", param->type4.uv[1], param->type4.uv[0]);
|
||||
igText("base_color: 0x%x", param->type4.base_color);
|
||||
igText("offset_color: 0x%x", param->type4.offset_color);
|
||||
break;
|
||||
|
@ -453,7 +453,7 @@ static void tracer_param_tooltip(struct tracer *tracer, struct tr_param *rp) {
|
|||
case 6:
|
||||
igText("xyz: {%.2f, %.2f, %f}", param->type6.xyz[0],
|
||||
param->type6.xyz[1], param->type6.xyz[2]);
|
||||
igText("uv: {0x%x, 0x%x}", param->type6.vu[1], param->type6.vu[0]);
|
||||
igText("uv: {0x%x, 0x%x}", param->type6.uv[1], param->type6.uv[0]);
|
||||
igText("base_color_a: %.2f", param->type6.base_color_a);
|
||||
igText("base_color_r: %.2f", param->type6.base_color_r);
|
||||
igText("base_color_g: %.2f", param->type6.base_color_g);
|
||||
|
@ -475,7 +475,7 @@ static void tracer_param_tooltip(struct tracer *tracer, struct tr_param *rp) {
|
|||
case 8:
|
||||
igText("xyz: {%.2f, %.2f, %f}", param->type8.xyz[0],
|
||||
param->type8.xyz[1], param->type8.xyz[2]);
|
||||
igText("uv: {0x%x, 0x%x}", param->type8.vu[1], param->type8.vu[0]);
|
||||
igText("uv: {0x%x, 0x%x}", param->type8.uv[1], param->type8.uv[0]);
|
||||
igText("base_intensity: %.2f", param->type8.base_intensity);
|
||||
igText("offset_intensity: %.2f", param->type8.offset_intensity);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue