nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: nuclear@0: struct quat { nuclear@0: float x, y, z, w; nuclear@0: }; nuclear@0: nuclear@0: int init(void); nuclear@0: void cleanup(void); nuclear@0: void display(void); nuclear@0: void reshape(int x, int y); nuclear@0: void keypress(unsigned char key, int x, int y); nuclear@0: void mouse(int bn, int st, int x, int y); nuclear@0: void motion(int x, int y); nuclear@0: nuclear@0: float eval(struct metasurface *ms, float x, float y, float z); nuclear@0: void vertex(struct metasurface *ms, float x, float y, float z); nuclear@0: nuclear@0: int julia(struct quat *qres, struct quat *qprime, struct quat *q, struct quat *seed, int max_iter); nuclear@0: float julia_dist(struct quat *z, struct quat *seed, int max_iter); nuclear@1: void julia_grad(float *grad, struct quat *q, struct quat *seed, int max_iter); nuclear@0: nuclear@0: void show_waitscr(void); nuclear@0: nuclear@0: float cam_theta, cam_phi = 25, cam_dist = 5; nuclear@1: int grid_size = 300; nuclear@0: float grid_scale = 1.7; nuclear@0: struct quat seed = {0.4, 0.0, 0.0, -0.8}; nuclear@1: int max_iter = 10; nuclear@0: nuclear@0: struct metasurface *msurf; nuclear@0: int dlist; nuclear@0: FILE *fp; nuclear@0: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@1: int i; nuclear@1: nuclear@1: for(i=1; i 90) cam_phi = 90; nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: if(bnstate[2]) { nuclear@0: cam_dist += dy * 0.1; nuclear@0: nuclear@0: if(cam_dist < 0.0) cam_dist = 0.0; nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: float eval(struct metasurface *ms, float x, float y, float z) nuclear@0: { nuclear@0: struct quat q; nuclear@0: nuclear@0: q.w = grid_scale * x; nuclear@0: q.x = grid_scale * y; nuclear@0: q.y = grid_scale * z; nuclear@0: q.z = 0.0f; nuclear@0: nuclear@0: return julia_dist(&q, &seed, max_iter); nuclear@0: } nuclear@0: nuclear@0: void vertex(struct metasurface *ms, float x, float y, float z) nuclear@0: { nuclear@0: struct quat q; nuclear@0: float norm[3]; nuclear@0: float norm_len, nscale = 1.0; nuclear@0: nuclear@0: q.w = grid_scale * x; nuclear@0: q.x = grid_scale * y; nuclear@0: q.y = grid_scale * z; nuclear@0: q.z = 0.0f; nuclear@0: nuclear@1: julia_grad(norm, &q, &seed, max_iter); nuclear@0: norm_len = sqrt(norm[0] * norm[0] + norm[1] * norm[1] + norm[2] * norm[2]); nuclear@0: nuclear@1: if(norm_len != 0.0) { nuclear@1: nscale = 1.0 / norm_len; nuclear@0: } nuclear@0: nuclear@0: glNormal3f(norm[0] * nscale, norm[1] * nscale, norm[2] * nscale); nuclear@0: glVertex3f(x, y, z); nuclear@0: nuclear@0: if(fp) { nuclear@0: static int nverts; nuclear@0: nuclear@0: fprintf(fp, "v %f %f %f\n", x, y, z); nuclear@0: nuclear@0: if((++nverts) % 3 == 0) { nuclear@0: fprintf(fp, "f %d %d %d\n", nverts - 2, nverts - 1, nverts); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void quat_mul(struct quat *res, struct quat *a, struct quat *b) nuclear@0: { nuclear@0: float w = a->w * b->w - (a->x * b->x + a->y * b->y + a->z * b->z); nuclear@0: float x = a->w * b->x + b->w * a->x + (a->y * b->z - a->z * b->y); nuclear@0: float y = a->w * b->y + b->w * a->y + (a->z * b->x - a->x * b->z); nuclear@0: res->z = a->w * b->z + b->w * a->z + (a->x * b->y - a->y * b->x); nuclear@0: res->x = x; nuclear@0: res->y = y; nuclear@0: res->w = w; nuclear@0: } nuclear@0: nuclear@0: void quat_sq(struct quat *q) nuclear@0: { nuclear@0: float w = q->w * q->w - (q->x * q->x + q->y * q->y + q->z * q->z); nuclear@0: float x = 2.0 * q->w * q->x; nuclear@0: float y = 2.0 * q->w * q->y; nuclear@0: q->z = 2.0 * q->w * q->z; nuclear@0: q->x = x; nuclear@0: q->y = y; nuclear@0: q->w = w; nuclear@0: } nuclear@0: nuclear@0: float quat_lensq(struct quat *q) nuclear@0: { nuclear@0: return q->x * q->x + q->y * q->y + q->z * q->z + q->w * q->w; nuclear@0: } nuclear@0: nuclear@0: int julia(struct quat *qres, struct quat *qprime, struct quat *q, struct quat *seed, int max_iter) nuclear@0: { nuclear@0: int i; nuclear@0: nuclear@0: *qres = *q; nuclear@0: qprime->x = qprime->y = qprime->z = 0.0f; nuclear@0: qprime->w = 1.0f; nuclear@0: nuclear@0: for(i=0; ix *= 2.0; nuclear@0: qprime->y *= 2.0; nuclear@0: qprime->z *= 2.0; nuclear@0: qprime->w *= 2.0; nuclear@0: nuclear@0: quat_sq(qres); nuclear@0: qres->x += seed->x; nuclear@0: qres->y += seed->y; nuclear@0: qres->z += seed->z; nuclear@0: qres->w += seed->w; nuclear@0: nuclear@0: if(quat_lensq(qres) > 8.0) { nuclear@0: return 0; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: float julia_dist(struct quat *z, struct quat *seed, int max_iter) nuclear@0: { nuclear@0: struct quat qprime, q; nuclear@0: nuclear@0: /* calc julia at z */ nuclear@0: /*int inside = */julia(&q, &qprime, z, seed, max_iter); nuclear@0: nuclear@0: float lenq = sqrt(quat_lensq(&q)); nuclear@0: float lenqp = sqrt(quat_lensq(&qprime)); nuclear@0: return 0.5 * lenq * log(lenq) / lenqp; nuclear@0: } nuclear@0: nuclear@1: #define OFFS 1e-5 nuclear@1: void julia_grad(float *grad, struct quat *q, struct quat *seed, int max_iter) nuclear@0: { nuclear@0: struct quat qnext = *q; nuclear@0: struct quat qprev = *q; nuclear@0: nuclear@0: qnext.w += OFFS; nuclear@0: qprev.w -= OFFS; nuclear@0: grad[0] = julia_dist(&qnext, seed, max_iter) - julia_dist(&qprev, seed, max_iter); nuclear@0: qnext.w = qprev.w = q->w; nuclear@0: nuclear@0: qnext.x += OFFS; nuclear@0: qprev.x -= OFFS; nuclear@0: grad[1] = julia_dist(&qnext, seed, max_iter) - julia_dist(&qprev, seed, max_iter); nuclear@0: qnext.x = qprev.x = q->x; nuclear@0: nuclear@0: qnext.y += OFFS; nuclear@0: qprev.y -= OFFS; nuclear@0: grad[2] = julia_dist(&qnext, seed, max_iter) - julia_dist(&qprev, seed, max_iter); nuclear@0: } nuclear@0: nuclear@0: void show_waitscr(void) nuclear@0: { nuclear@0: const char *text = "Please wait, generating fractal..."; nuclear@0: glClear(GL_COLOR_BUFFER_BIT); nuclear@0: nuclear@0: glPushAttrib(GL_ENABLE_BIT); nuclear@0: glDisable(GL_LIGHTING); nuclear@0: glDisable(GL_DEPTH_TEST); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glPushMatrix(); nuclear@0: glLoadIdentity(); nuclear@0: glTranslatef(-0.75, 0, 0); nuclear@0: glScalef(0.00075, 0.00075, 0.00075); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: nuclear@0: glEnable(GL_LINE_SMOOTH); nuclear@0: glEnable(GL_BLEND); nuclear@0: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); nuclear@0: nuclear@0: glLineWidth(1.5); nuclear@0: nuclear@0: glColor3f(1, 1, 1); nuclear@0: while(*text) { nuclear@0: glutStrokeCharacter(GLUT_STROKE_ROMAN, *text++); nuclear@0: } nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glPopMatrix(); nuclear@0: nuclear@0: glPopAttrib(); nuclear@0: nuclear@0: glutSwapBuffers(); nuclear@0: }