/* calculate sphere that goes through 4 points */ struct sphere* sphere_circum(struct sphere* rs, const struct vec4f* v0, const struct vec4f* v1, const struct vec4f* v2, const struct vec4f* v3) { struct vec4f a; vec3_sub(&a, v1, v0); struct vec4f b; vec3_sub(&b, v2, v0); struct vec4f c; vec3_sub(&c, v3, v0); struct vec4f o; struct vec4f tmp; struct mat3f m; mat3_setf(&m, a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, 0.0f, 0.0f, 0.0f); float denom = 2.0f * mat3_det(&m); vec3_muls(&o, vec3_cross(&tmp, &a, &b), vec3_dot(&c, &c)); vec3_add(&o, &o, vec3_muls(&tmp, vec3_cross(&tmp, &c, &a), vec3_dot(&b, &b))); vec3_add(&o, &o, vec3_muls(&tmp, vec3_cross(&tmp, &b, &c), vec3_dot(&a, &a))); vec3_muls(&o, &o, 1.0f/denom); return sphere_setf(rs, v0->x + o.x, v0->y + o.y, v0->z + o.z, vec3_len(&o) + EPSILON); }
void cmp_model_drawbone(const struct mat3f* j0, const struct mat3f* j1, float level, float scale) { struct sphere s; sphere_setf(&s, 0.0f, 0.0f, 0.0f, scale * (1.0f/level)); struct vec3f p0; struct vec3f p1; mat3_get_trans(&p0, j0); mat3_get_trans(&p1, j1); gfx_canvas_line3d(&p0, &p1); gfx_canvas_sphere(&s, j0, GFX_SPHERE_LOW); gfx_canvas_sphere(&s, j1, GFX_SPHERE_LOW); }
struct sphere* sphere_xform(struct sphere* rs, const struct sphere* s, const struct mat3f* m) { /* we have to transform radius by scale value of transform matrix * to determine scale value, we find the highest scale component of the matrix */ float xlen = m->m11*m->m11 + m->m12*m->m12 + m->m13*m->m13; float ylen = m->m21*m->m21 + m->m22*m->m22 + m->m23*m->m23; float zlen = m->m31*m->m31 + m->m32*m->m32 + m->m33*m->m33; float isqr_scale = maxf(xlen, ylen); isqr_scale = maxf(isqr_scale, zlen); /* transform center */ struct vec4f c; vec3_setf(&c, s->x, s->y, s->z); vec3_transformsrt(&c, &c, m); return sphere_setf(rs, c.x, c.y, c.z, s->r*sqrtf(isqr_scale)); }
void csm_calc_minsphere(struct sphere* bounds, const struct frustum* f, const struct mat3f* view, const struct mat3f* view_inv) { /* reference: * http://www.gamedev.net/topic/604797-minimum-bounding-sphere-of-a-frustum/ */ struct vec3f a; struct vec3f b; struct vec3f p; struct vec3f tmp; vec3_transformsrt(&a, &f->points[1], view); vec3_transformsrt(&b, &f->points[5], view); float z = (vec3_dot(&b, &b) - vec3_dot(&a, &a))/(2.0f*(b.z - a.z)); vec3_setf(&p, 0.0f, 0.0f, z); vec3_transformsrt(&p, &p, view_inv); sphere_setf(bounds, p.x, p.y, p.z, vec3_len(vec3_sub(&tmp, &f->points[5], &p)) + 0.01f); }
void cmp_model_drawpose(const struct gfx_model_geo* geo, const struct gfx_model_posegpu* pose, const struct gfx_view_params* params, const struct mat3f* world_mat, float scale) { gfx_canvas_setwireframe(FALSE, TRUE); gfx_canvas_setlinecolor(&g_color_yellow); gfx_canvas_setfillcolor_solid(&g_color_red); gfx_canvas_settextcolor(&g_color_grey); struct mat3f j1m; struct mat3f j2m; struct gfx_model_skeleton* sk = geo->skeleton; for (uint i = 0; i < sk->joint_cnt; i++) { cmp_model_calc_jointmat(&j1m, sk, i, pose->mats, world_mat); /* find child for the current joint and draw the bone */ int nochild = FALSE; for (uint k = 0; k < sk->joint_cnt; k++) { struct gfx_model_joint* joint2 = &sk->joints[k]; if (joint2->parent_id == i) { cmp_model_calc_jointmat(&j2m, sk, k, pose->mats, world_mat); float level = cmp_model_calc_jointlevel(sk, i); cmp_model_drawbone(&j1m, &j2m, level, scale); /*gfx_canvas_coords(&j1m, ¶ms->cam_pos, 0.1f);*/ nochild = TRUE; break; } } if (!nochild) { struct sphere s; float level = cmp_model_calc_jointlevel(sk, i); sphere_setf(&s, 0.0f, 0.0f, 0.0f, scale * (1.0f / level)); gfx_canvas_sphere(&s, &j1m, GFX_SPHERE_LOW); /*gfx_canvas_coords(&j1m, ¶ms->cam_pos, 0.1f);*/ } } gfx_canvas_setwireframe(TRUE, TRUE); }