3 #include "cgmath/cgmath.h"
8 static void upd_sflake(struct mobject *mobj, float t);
9 static float eval_sflake(struct mobject *mobj, cgm_vec3 *pos);
10 static int num_balls(int depth);
11 static int gen_sflake(cgm_vec4 *sarr, int num, int depth, float x, float y, float z, float rad);
13 static void upd_sgi(struct mobject *mobj, float t);
14 static float eval_sgi(struct mobject *mobj, cgm_vec3 *pos);
15 static float capsule_distsq(struct mcapsule *c, cgm_vec3 *pos);
17 /* ---- sphereflake ---- */
18 #define SF_MAX_DEPTH 2
19 static cgm_vec4 *sfsph;
21 struct mobject *metaobj_sflake(void)
25 mobj = calloc_nf(1, sizeof *mobj);
27 mobj->num_balls = num_balls(SF_MAX_DEPTH);
28 mobj->balls = malloc_nf(mobj->num_balls * sizeof *mobj->balls);
29 sfsph = malloc_nf(mobj->num_balls * sizeof *sfsph);
31 gen_sflake(sfsph, 0, SF_MAX_DEPTH, 0, 0, 0, 20);
33 mobj->update = upd_sflake;
34 mobj->eval = eval_sflake;
38 static void upd_sflake(struct mobject *mobj, float t)
41 struct mball *ball = mobj->balls;
45 cgm_mrotate_x(mat, t);
46 cgm_mrotate_y(mat, t);
47 cgm_mtranslate(mat, mobj->pos.x, mobj->pos.y, mobj->pos.z);
49 for(i=0; i<mobj->num_balls; i++) {
50 cgm_vcons(&ball->pos, sfsph[i].x, sfsph[i].y, sfsph[i].z);
51 cgm_vmul_m4v3(&ball->pos, mat);
52 ball->energy = sfsph[i].w;
57 static float eval_sflake(struct mobject *mobj, cgm_vec3 *pos)
60 float dsq, energy = 0.0f;
61 struct mball *ball = mobj->balls;
63 for(i=0; i<mobj->num_balls; i++) {
64 dsq = cgm_vdist_sq(&ball->pos, pos);
65 energy += ball->energy / dsq;
71 static int num_balls(int depth)
74 return num_balls(depth - 1) * 6 + 1;
77 static int gen_sflake(cgm_vec4 *sarr, int num, int depth, float x, float y, float z, float rad)
94 subnum += gen_sflake(sarr, num + subnum, depth - 1, x + offs, y, z, subrad);
95 subnum += gen_sflake(sarr, num + subnum, depth - 1, x - offs, y, z, subrad);
96 subnum += gen_sflake(sarr, num + subnum, depth - 1, x, y + offs, z, subrad);
97 subnum += gen_sflake(sarr, num + subnum, depth - 1, x, y - offs, z, subrad);
98 subnum += gen_sflake(sarr, num + subnum, depth - 1, x, y, z + offs, subrad);
99 subnum += gen_sflake(sarr, num + subnum, depth - 1, x, y, z - offs, subrad);
103 /* ---- SGI logo ---- */
105 static const cgm_vec3 sgiv[] = {
106 {2.794170, 4.254175, 2.738066},
107 {2.794170, 4.254174, -4.358471},
108 {-2.173414, 4.254174, -4.358471},
109 {-2.173414, -2.842363, -4.358470},
110 {4.923134, -2.842363, -4.358471},
111 {4.923134, 2.125212, -4.358471},
112 {4.923134, 2.125212, 2.738066},
113 {4.923134, -4.971326, 2.738067},
114 {4.923134, -4.971326, -2.229511},
115 {-2.173413, -4.971326, -2.229511},
116 {-2.173413, -4.971325, 4.867042},
117 {2.794170, -4.971325, 4.867042},
118 {2.794170, 2.125213, 4.867042},
119 {-4.302382, 2.125213, 4.867042},
120 {-4.302383, -2.842362, 4.867042},
121 {-4.302382, -2.842363, -2.229511},
122 {-4.302382, 4.254175, -2.229512},
123 {-4.302383, 4.254175, 2.738066}
125 #define NUM_SGI_VERTS (sizeof sgiv / sizeof *sgiv)
126 static float sgimat[16];
128 struct mobject *metaobj_sgi(void)
131 struct mobject *mobj;
133 mobj = calloc_nf(1, sizeof *mobj);
135 cgm_midentity(sgimat);
136 cgm_mrotate_y(sgimat, -M_PI / 4.0f);
137 cgm_mrotate_x(sgimat, M_PI / 4.0f);
138 cgm_mtranslate(sgimat, 0, -4, 0);
140 mobj->num_caps = NUM_SGI_VERTS;
141 mobj->caps = calloc_nf(mobj->num_caps, sizeof *mobj->caps);
143 for(i=0; i<mobj->num_caps; i++) {
144 mobj->caps[i].energy = 0.7;
147 mobj->update = upd_sgi;
148 mobj->eval = eval_sgi;
152 static void upd_sgi(struct mobject *mobj, float t)
156 cgm_vec3 vpos[NUM_SGI_VERTS];
158 cgm_mcopy(mat, sgimat);
159 cgm_mrotate_y(mat, t);
160 cgm_mtranslate(mat, mobj->pos.x, mobj->pos.y, mobj->pos.z);
162 for(i=0; i<NUM_SGI_VERTS; i++) {
164 cgm_vscale(vpos + i, 0.5);
165 cgm_vmul_m4v3(vpos + i, mat);
168 for(i=0; i<NUM_SGI_VERTS; i++) {
169 mobj->caps[i].end[0] = vpos[i];
170 mobj->caps[i].end[1] = vpos[(i + 1) % NUM_SGI_VERTS];
171 mobj->caps[i].len = cgm_vdist(mobj->caps[i].end, mobj->caps[i].end + 1);
175 static float eval_sgi(struct mobject *mobj, cgm_vec3 *pos)
178 float dsq, val = 0.0f;
180 for(i=0; i<mobj->num_caps; i++) {
181 dsq = capsule_distsq(mobj->caps + i, pos);
182 val += mobj->caps[i].energy / dsq;
188 static float capsule_distsq(struct mcapsule *c, cgm_vec3 *pos)
191 cgm_vec3 pp, dir, pdir;
193 dir = c->end[1]; cgm_vsub(&dir, c->end);
195 float s = 1.0f / c->len;
200 pdir = *pos; cgm_vsub(&pdir, c->end);
201 t = cgm_vdot(&dir, &pdir);
204 return cgm_vdist_sq(c->end, pos);
207 return cgm_vdist_sq(c->end + 1, pos);
211 cgm_vadd_scaled(&pp, &dir, t);
212 return cgm_vdist_sq(&pp, pos);