|
|
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 |
}
|