Blame onefile/sphere.c

2ed0d1
2ed0d1
#include <math.h></math.h>
2ed0d1
#include <string.h></string.h>
2ed0d1
#include <stdio.h></stdio.h>
2ed0d1
2ed0d1
#include <helianthus.h></helianthus.h>
2ed0d1
2ed0d1
2ed0d1
int printed = 0;
2ed0d1
int started = 0;
2ed0d1
double mx, my, ax, ay;
2ed0d1
2ed0d1
2ed0d1
void vec3set(double *v, double x, double y, double z)
2ed0d1
  { v[0] = x, v[1] = y, v[2] = z; }
2ed0d1
void vec3cpy(double *v, const double *vv)
2ed0d1
  { memcpy(v, vv, sizeof(*v)*3); }
2ed0d1
void vec3add(double *v, const double *vv)
2ed0d1
  { v[0] += vv[0]; v[1] += vv[1]; v[2] += vv[2]; }
2ed0d1
void vec3sub(double *v, const double *vv)
2ed0d1
  { v[0] -= vv[0]; v[1] -= vv[1]; v[2] -= vv[2]; }
2ed0d1
void vec3mul(double *v, double x)
2ed0d1
  { v[0] *= x; v[1] *= x; v[2] *= x; }
2ed0d1
double vec3dot(const double *a, const double *b)
2ed0d1
  { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
2ed0d1
void vec3trans(double *v, const double *m) {
2ed0d1
  vec3set(v, v[0]*m[0] + v[1]*m[3] + v[2]*m[6],
2ed0d1
             v[0]*m[1] + v[1]*m[4] + v[2]*m[7],
2ed0d1
             v[0]*m[2] + v[1]*m[5] + v[2]*m[8] );
2ed0d1
}
2ed0d1
2ed0d1
void mat3cpy(double *m, double *mm)
2ed0d1
  { memcpy(m, mm, sizeof(*m)*9); }
2ed0d1
void mat3one(double *m) {
2ed0d1
  m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0;
2ed0d1
  m[0] = m[4] = m[8] = 1;
2ed0d1
}
2ed0d1
void mat3rotX(double *m, double a) {
2ed0d1
  rotateVector(&m[1], &m[2], a);
2ed0d1
  rotateVector(&m[4], &m[5], a);
2ed0d1
  rotateVector(&m[7], &m[8], a);
2ed0d1
}
2ed0d1
void mat3rotY(double *m, double a) {
2ed0d1
  rotateVector(&m[2], &m[0], a);
2ed0d1
  rotateVector(&m[5], &m[3], a);
2ed0d1
  rotateVector(&m[8], &m[6], a);
2ed0d1
}
2ed0d1
void mat3rotZ(double *m, double a) {
2ed0d1
  rotateVector(&m[0], &m[1], a);
2ed0d1
  rotateVector(&m[3], &m[4], a);
2ed0d1
  rotateVector(&m[6], &m[7], a);
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
void lineTo3d(const double *m, double x, double y, double z) {
2ed0d1
  double v[] = {x, y, z};
2ed0d1
  vec3trans(v, m);
2ed0d1
  lineTo(v[0], v[1]);
2ed0d1
}
2ed0d1
void lineTo3dv(const double *m, const double *v)
2ed0d1
  { lineTo3d(m, v[0], v[1], v[2]); }
2ed0d1
2ed0d1
2ed0d1
void func(double *v, double x, double y) {
2ed0d1
  double angle  = 1.5*PI*y;
2ed0d1
  double radius = 4*(1-y) + 2*y;
2ed0d1
  double size   = (1-y)*0.25;
2ed0d1
2ed0d1
  double ss = sin(angle), cc = cos(angle);
2ed0d1
2ed0d1
  double a = 2*PI*(x-0.5)*size + PI/2, s = sin(a), c = cos(a);
2ed0d1
  vec3set(v, c*radius, s*cc*radius, s*ss*radius);
2ed0d1
  rotateVector(&v[0], &v[1], 45);
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
void tangent(double *v, double x, double y, double dx, double dy) {
2ed0d1
  double p[3];
2ed0d1
  func(p, x-dx, y-dy);
2ed0d1
  func(v, x+dx, y+dy);
2ed0d1
  vec3sub(v, p);
2ed0d1
  double l = sqrt(vec3dot(v, v));
2ed0d1
  vec3mul(v, 1/l);
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
void drawCubic(const double *m, const double *vv) {
2ed0d1
  for(int i = 0; i <= 16; ++i) {
2ed0d1
    double l = i/16.0, k = 1-l;
2ed0d1
    double v[3] = {};
2ed0d1
    double vc[4][3];
2ed0d1
    memcpy(vc, vv, sizeof(vc));
2ed0d1
    vec3mul(vc[0], k*k*k);
2ed0d1
    vec3mul(vc[1], 3*k*k*l);
2ed0d1
    vec3mul(vc[2], 3*l*l*k);
2ed0d1
    vec3mul(vc[3], l*l*l);
2ed0d1
    vec3add(v, vc[0]);
2ed0d1
    vec3add(v, vc[1]);
2ed0d1
    vec3add(v, vc[2]);
2ed0d1
    vec3add(v, vc[3]);
2ed0d1
    lineTo3dv(m, v);
2ed0d1
  }
2ed0d1
  strokePath();
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
void makeCubicBase(double *vv, double *p0, double *t0, double *p1, double *t1) {
2ed0d1
  double d[3], tt0[3], tt1[3];
2ed0d1
  vec3cpy(d, p1);
2ed0d1
  vec3sub(d, p0);
2ed0d1
  double ld = sqrt(vec3dot(d, d));
2ed0d1
2ed0d1
  double l0 = sqrt(vec3dot(t0, t0));
2ed0d1
  double l1 = sqrt(vec3dot(t1, t1));
2ed0d1
  double k = ld/3;
2ed0d1
  vec3cpy(tt0, t0); vec3mul(tt0, k/l0);
2ed0d1
  vec3cpy(tt1, t1); vec3mul(tt1, k/l1);
2ed0d1
2ed0d1
  double pp0[3], pp1[3];
2ed0d1
  vec3cpy(pp0, p0); vec3add(pp0, tt0);
2ed0d1
  vec3cpy(pp1, p1); vec3sub(pp1, tt1);
2ed0d1
2ed0d1
  vec3cpy(&vv[0], p0);
2ed0d1
  vec3cpy(&vv[3], pp0);
2ed0d1
  vec3cpy(&vv[6], pp1);
2ed0d1
  vec3cpy(&vv[9], p1);
2ed0d1
2ed0d1
  if (!printed) {
2ed0d1
    if (started)
2ed0d1
      printf("                   \"");
2ed0d1
    else
2ed0d1
      printf("\" [%.2f][%.2f][%.2f]", vv[0]+4, vv[1]+4, vv[2]+4);
2ed0d1
2ed0d1
    for(int i = 1; i < 4; ++i) {
2ed0d1
      printf("-[%.2f][%.2f][%.2f]", vv[3*i+0]+4, vv[3*i+1]+4, vv[3*i+2]+4);
2ed0d1
    }
2ed0d1
    printf("\"\n");
2ed0d1
  }
2ed0d1
  started = 1;
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
2ed0d1
void makeCubic(
2ed0d1
  double *vv,
2ed0d1
  double x0, double y0, double dx0, double dy0,
2ed0d1
  double x1, double y1, double dx1, double dy1 )
2ed0d1
{
2ed0d1
  double p0[3], t0[3], p1[3], t1[3];
2ed0d1
  func(p0, x0, y0);
2ed0d1
  func(p1, x1, y1);
2ed0d1
  tangent(t0, x0, y0, dx0, dy0);
2ed0d1
  tangent(t1, x1, y1, dx1, dy1);
2ed0d1
  makeCubicBase(vv, p0, t0, p1, t1);
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
void makeCubicBase2(const double *m, double *vv, double *p0, double *t0, double *p1, double *t1) {
2ed0d1
  makeCubicBase(vv, p0, t0, p1, t1);
2ed0d1
  drawCubic(m, vv);
2ed0d1
}
2ed0d1
2ed0d1
void makeCubic2(
2ed0d1
  const double *m, double *vv,
2ed0d1
  double x0, double y0, double dx0, double dy0,
2ed0d1
  double x1, double y1, double dx1, double dy1 )
2ed0d1
{
2ed0d1
  makeCubic(vv, x0, y0, dx0, dy0, x1, y1, dx1, dy1);
2ed0d1
  drawCubic(m, vv);
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
2ed0d1
void init() { }
2ed0d1
2ed0d1
2ed0d1
void draw() {
2ed0d1
  double w = windowGetWidth();
2ed0d1
  double h = windowGetHeight();
2ed0d1
2ed0d1
  saveState();
2ed0d1
  translate(w/2, h/2);
2ed0d1
2ed0d1
  int ml = mouseDown("left");
2ed0d1
  int mr = mouseDown("right");
2ed0d1
2ed0d1
  double pmx = mx, pmy = my;
2ed0d1
  mx = mouseX(), my = mouseY();
2ed0d1
  if (ml || mr) { ax += pmx - mx; ay += my - pmy; }
2ed0d1
  ax = fmod(ax, 360);
2ed0d1
  ay = fmod(ay, 360);
2ed0d1
2ed0d1
  double step = 128/8.0;
2ed0d1
  double mat[9] = {step, 0, 0, 0, 0, step, 0, -step, 0};
2ed0d1
  mat3rotY(mat, ax);
2ed0d1
  mat3rotX(mat, ay);
2ed0d1
2ed0d1
  double axislen = 1;
2ed0d1
  strokeWidth(2);
2ed0d1
  stroke(COLOR_RED);   line(0, 0, mat[0]*axislen, mat[1]*axislen);
2ed0d1
  stroke(COLOR_BLACK); line(0, 0, mat[3]*axislen, mat[4]*axislen);
2ed0d1
  stroke(COLOR_BLUE);  line(0, 0, mat[6]*axislen, mat[7]*axislen);
2ed0d1
  strokeWidth(1);
2ed0d1
  stroke(COLOR_BLACK);
2ed0d1
2ed0d1
  noFill();
2ed0d1
  for(int i = 0; i <= 16; ++i) {
2ed0d1
    for(int j = 0; j <= 16; ++j) {
2ed0d1
      double v[3];
2ed0d1
      func(v, i/16.0, j/16.0);
2ed0d1
      vec3trans(v, mat);
2ed0d1
      point(v[0], v[1]);
2ed0d1
    }
2ed0d1
  }
2ed0d1
2ed0d1
  double curve[12];
2ed0d1
  double p0[3], t0[3], p1[3], t1[3];
2ed0d1
2ed0d1
  started = 0;
2ed0d1
  vec3set(p0, 4, 0, -4); vec3set(t0, 0, 1, 0);
2ed0d1
  func(p1, 0, 0); tangent(t1, 0, 0, 0, 0.001);
2ed0d1
  makeCubicBase2(mat, curve, p0, t0, p1, t1);
2ed0d1
  for(int i = 0; i < 6; ++i)
2ed0d1
    makeCubic2(mat, curve, 0, i/6.0, 0, 0.001, 0, (i+1)/6.0, 0, 0.001 );
2ed0d1
2ed0d1
  for(int i = 0; i < 6; ++i)
2ed0d1
    makeCubic2(mat, curve, 1, 1-i/6.0, 0, -0.001, 1, 1-(i+1)/6.0, 0, -0.001 );
2ed0d1
  func(p0, 1, 0); tangent(t0, 1, 0, 0, -0.001);
2ed0d1
  vec3set(p1, 0, -4, -4); vec3set(t1, 1, 0, 0);
2ed0d1
  makeCubicBase2(mat, curve, p0, t0, p1, t1);
2ed0d1
2ed0d1
  started = 0;
2ed0d1
  makeCubic2(mat, curve, 0, 1/3.0, 0.001, 0, 1, 1/3.0, 0.001, 0);
2ed0d1
  started = 0;
2ed0d1
  makeCubic2(mat, curve, 0, 2/3.0, 0.001, 0, 1, 2/3.0, 0.001, 0);
2ed0d1
2ed0d1
  lineTo3d(mat, 4,  0, -4);
2ed0d1
  lineTo3d(mat, 4, -4, -4);
2ed0d1
  lineTo3d(mat, 0, -4, -4);
2ed0d1
  lineTo3d(mat, 0,  0, -4);
2ed0d1
  closePath();
2ed0d1
2ed0d1
  printed = 1;
2ed0d1
2ed0d1
  restoreState();
2ed0d1
}
2ed0d1
2ed0d1
2ed0d1
int main() {
2ed0d1
  windowSetVariableFrameRate();
2ed0d1
  windowSetResizable(TRUE);
2ed0d1
  windowSetInit(&init);
2ed0d1
  windowSetDraw(&draw);
2ed0d1
  windowRun();
2ed0d1
}