diff -urN wf-/Makefile wf/Makefile --- wf-/Makefile 2015-12-10 00:00:00.000000000 +0900 +++ wf/Makefile 2015-12-11 00:00:00.000000000 +0900 @@ -3,7 +3,7 @@ LIBS = -lm -lX11 -L/usr/X11R6/lib CFLAGS += -Wall -I/usr/X11R6/include -WF_OBJS = wf_ex.o x.o util.o +WF_OBJS = wf_ex.o eye.o d3.o x.o util.o all: wf_ex diff -urN wf-/d3.c wf/d3.c --- wf-/d3.c 1970-01-01 09:00:00.000000000 +0900 +++ wf/d3.c 2015-12-11 00:00:00.000000000 +0900 @@ -0,0 +1,350 @@ +#include +#include "d3.h" + +double +linear(double v, double sa, double sb, double da, double db) +{ + double s; + + if((s = sb - sa) == 0) return v; + return (v - sa) * (db - da ) / s + da; +} + +void +d_info_get(struct d_info *inf) +{ + double d, exp; + + if(inf->d == 0.0 || inf->d == -0.0){ + inf->sign = 0; + return; + } + inf->sign = (inf->d < 0 ? -1 : 1); + d = (inf->d < 0 ? -inf->d : inf->d); + exp = log(d) / log(2.0); + inf->exp = (int)(exp + 1024) - 1024; + inf->fract = pow(2, (exp - inf->exp)); +} + +void +d_info_prn(struct d_info *inf) +{ + printf("d = %e\n", inf->d); + printf(" sign = %d\n", inf->sign); + printf(" exp = %d\n", inf->exp); + printf(" fract = %e\n", inf->fract); +} + +int +d_eq(double a, double b) +{ + struct d_info ai, bi; + double dif; + + ai.d = a; + d_info_get(&ai); + + bi.d = b; + d_info_get(&bi); + + if(ai.sign != bi.sign) return 0; + if(ai.exp != bi.exp) return 0; + + dif = ai.fract - bi.fract; + if(dif < 0) dif = -dif; + return dif < pow(2, -48); /* -50 !!! */ +} + + +void +d3_set(d3_t *p, double x, double y, double z) +{ + p->x = x; + p->y = y; + p->z = z; +} + +void +d3_mul(d3_t *p, double n) +{ + d3_set(p, p->x * n, p->y * n, p->z * n); +} + +void +d3_add(d3_t *d, const d3_t *s) +{ + d3_set(d, d->x + s->x, d->y + s->y, d->z + s->z); +} + +void +d3_sub(d3_t *d, const d3_t *s) +{ + d3_set(d, d->x - s->x, d->y - s->y, d->z - s->z); +} + +void +d3_zoom(d3_t *d, const d3_t *s) +{ + d3_set(d, d->x * s->x, d->y * s->y, d->z * s->z); +} + +void +d3_cen(d3_t *ret_cen, const d3_t *a, const d3_t *b) +{ + *ret_cen = *a; + d3_add(ret_cen, b); + d3_mul(ret_cen, 0.5); +} + +void +d3_side(d3_t *ret_side, const d3_t *cen, const d3_t *side) +{ + *ret_side = *cen; + d3_mul(ret_side, 2); + d3_sub(ret_side, side); +} + +int +d3_eq(const d3_t *a, const d3_t *b) +{ + return d_eq(a->x, b->x) && + d_eq(a->y, b->y) && + d_eq(a->z, b->z); +} + +int +d3_eq_zero(const d3_t *p) +{ + return p->x == 0 && p->y == 0 && p->z == 0; +} + + +double +pos_distance(const pos_t *a, const pos_t *b) +{ + vec_t v; + + vec_set(&v, a, b); + return vec_len(&v); +} + +void +pos_rot(pos_t *p, const line_t *l, double deg) +{ + axis_t ax; + double r, s, c, x, z; + + axis_set(&ax, &l->p, &l->v); + axis_conv(&ax, p); + r = 2 * M_PI * deg / 360; + s = sin(r); + c = cos(r); + z = c * p->z - s * p->x; + x = s * p->z + c * p->x; + p->x = x; + p->z = z; + axis_rconv(&ax, p); +} + + +void +vec_set(vec_t *r, const pos_t *s, const pos_t *e) +{ + *r = *e; + d3_sub(r, s); +} + +/* inner_product */ +double +vec_in_prd(const vec_t *a, const vec_t *b) +{ + return a->x * b->x + a->y * b->y + a->z * b->z; +} + +/* exterior product */ +void +vec_ex_prd(vec_t *r, const vec_t *a, const vec_t *b) +{ + d3_set(r, + a->y * b->z - a->z * b->y, + a->z * b->x - a->x * b->z, + a->x * b->y - a->y * b->x); +} + +double +vec_len(const vec_t *v) +{ + return sqrt(vec_in_prd(v, v)); +} + +void +vec_unit(vec_t *v) +{ + double l; + + if((l = vec_len(v)) == 0) d3_set(v, 1, 0, 0); + else d3_mul(v, 1/l); +} + +void +vec_arot(const vec_t *s, const vec_t *e, line_t *ret_l, double *ret_deg) +{ + vec_t s1, e1, ex; + double v_sin, v_cos; + + s1 = *s; + vec_unit(&s1); + + e1 = *e; + vec_unit(&e1); + + v_cos = vec_in_prd(&s1, &e1); + vec_ex_prd(&ex, &s1, &e1); + v_sin = vec_len(&ex); + + ret_l->v = ex; + vec_unit(&ret_l->v); + d3_set(&ret_l->p, 0, 0, 0); + + *ret_deg = ( v_cos == 0 ? 90 : atan(v_sin/v_cos) * 360 / (2 * M_PI) ); + if(v_cos < 0) *ret_deg += 180; +} + + +void +line_set(line_t *l, const pos_t *s, const pos_t *e) +{ + l->p = *s; + vec_set(&l->v, s, e); +} + +void +line_pos(const line_t *l, double t, pos_t *r) +{ + *r = l->v; + d3_mul(r, t); + d3_add(r, &l->p); +} + + +void +plane_set(plane_t *pl, const pos_t *a, const pos_t *b, const pos_t *c) +{ + vec_t v1, v2; + + pl->p = *a; + vec_set(&v1, a, b); + vec_set(&v2, a, c); + vec_ex_prd(&pl->v, &v1, &v2); +} + +int +plane_side(const plane_t *pl, const pos_t *p) +{ + vec_t v; + double in; + + vec_set(&v, &pl->p, p); + in = vec_in_prd(&pl->v, &v); + return in == 0 ? 0 : (in > 0 ? 1 : -1); +} + +int +plane_cross(const plane_t *pl, const line_t *l, pos_t *r) +{ + /* + vec_in_prd(l.p + l.v * t - pl.p , pl.v) == 0 + + (l.p.x - pl.p.x + l.v.x * t) * pl.v.x + + (l.p.y - pl.p.y + l.v.y * t) * pl.v.y + + (l.p.z - pl.p.z + l.v.z * t) * pl.v.z == 0 + + l.v.x * pl.v.x * t + + l.v.y * pl.v.y * t + + l.v.z * pl.v.z * t + == + (pl.p.x - l.p.x) * pl.v.x + + (pl.p.y - l.p.y) * pl.v.y + + (pl.p.z - l.p.z) * pl.v.z + + t = + ( + (pl.p.x - l.p.x) * pl.v.x + + (pl.p.x - l.p.x) * pl.v.y + + (pl.p.x - l.p.x) * pl.v.z + ) / ( + l.v.x * pl.v.x + + l.v.y * pl.v.y + + l.v.z * pl.v.z + ) + */ + + vec_t s; + double d, t; + + if((d = vec_in_prd(&l->v, &pl->v)) == 0) return -1; + s = pl->p; + d3_sub(&s, &l->p); + t = vec_in_prd(&s, &pl->v) / d; + line_pos(l, t, r); + return 0; +} + +int +plane_clip(const plane_t *pl, pos_t *a, pos_t *b) +{ + int sa, sb; + line_t l; + pos_t r; + + sa = plane_side(pl, a); + sb = plane_side(pl, b); + if(sa <= 0 && sb <= 0) return -1; /* not visible */ + if(sa >= 0 && sb >= 0) return 0; /* not need clip */ + + /* (sa > 0 , sb < 0) or (sa < 0 , sb > 0) */ + line_set(&l, a, b); + plane_cross(pl, &l, &r); + if(sa < 0) *a = r; + else *b = r; + return sa < 0 ? 1 : 2; /* 1 : a clip -> r , 2 : b clip -> r */ +} + + +void +axis_set(axis_t *ax, const pos_t *o, const vec_t *y) +{ + ax->o = *o; + ax->y = *y; + vec_unit(&ax->y); + d3_set(&ax->z, 0, 0, 1); + vec_ex_prd(&ax->x, &ax->y, &ax->z); + vec_unit(&ax->x); + vec_ex_prd(&ax->z, &ax->x, &ax->y); + vec_unit(&ax->z); +} + +void +axis_conv(const axis_t *ax, pos_t *p) +{ + d3_sub(p, &ax->o); + d3_set(p, + vec_in_prd(p, &ax->x), + vec_in_prd(p, &ax->y), + vec_in_prd(p, &ax->z)); +} + +void +axis_rconv(const axis_t *ax, pos_t *p) +{ + axis_t t; + + t = *ax; + d3_mul(&t.x, p->x); + d3_mul(&t.y, p->y); + d3_mul(&t.z, p->z); + *p = ax->o; + d3_add(p, &t.x); + d3_add(p, &t.y); + d3_add(p, &t.z); +} diff -urN wf-/d3.h wf/d3.h --- wf-/d3.h 1970-01-01 09:00:00.000000000 +0900 +++ wf/d3.h 2015-12-11 00:00:00.000000000 +0900 @@ -0,0 +1,86 @@ +#ifndef __D3_H__ +#define __D3_H__ + +#include + +double linear(double v, double sa, double sb, double da, double db); + +struct d_info{ + double d; /* input */ + + int sign; /* 0 or 1 or -1 */ + int exp; /* -1024 .. 1024 */ + double fract; /* 1.0 .. 2.0 */ + /* d = sign * (2^exp) * fract */ +}; + +void d_info_get(struct d_info *inf); +int d_eq(double a, double b); + + +typedef struct{ + double x, y, z; +} d3_t, pos_t, vec_t; + +#define D3_O {0,0,0} +#define D3_I {1,1,1} +#define D3_X {1,0,0} +#define D3_Y {0,1,0} +#define D3_Z {0,0,1} +#define D3_X_NEG {-1,0,0} +#define D3_Y_NEG {0,-1,0} +#define D3_Z_NEG {0,0,-1} +#define D3_ALL(v) {v,v,v} + +void d3_set(d3_t *p, double x, double y, double z); +void d3_mul(d3_t *p, double n); +void d3_add(d3_t *d, const d3_t *s); +void d3_sub(d3_t *d, const d3_t *s); +void d3_zoom(d3_t *d, const d3_t *s); +void d3_cen(d3_t *ret_cen, const d3_t *a, const d3_t *b); +void d3_side(d3_t *ret_side, const d3_t *cen, const d3_t *side); +int d3_eq(const d3_t *a, const d3_t *b); +int d3_eq_zero(const d3_t *p); + + +typedef struct{ + pos_t p; + vec_t v; +} line_t, plane_t; + +#define LINE_X {D3_O, D3_X} +#define LINE_Y {D3_O, D3_Y} +#define LINE_Z {D3_O, D3_Z} +#define LINE_X_NEG {D3_O, D3_X_NEG} +#define LINE_Y_NEG {D3_O, D3_Y_NEG} +#define LINE_Z_NEG {D3_O, D3_Z_NEG} + +typedef struct{ + pos_t o; + vec_t x, y, z; +} axis_t; + + +double pos_distance(const pos_t *a, const pos_t *b); +void pos_rot(pos_t *p, const line_t *l, double deg); + +void vec_set(vec_t *r, const pos_t *s, const pos_t *e); +double vec_in_prd(const vec_t *a, const vec_t *b); +void vec_ex_prd(vec_t *r, const vec_t *a, const vec_t *b); +double vec_len(const vec_t *v); +void vec_unit(vec_t *v); +void vec_arot(const vec_t *s, const vec_t *e, line_t *ret_l, double *ret_deg); + +void line_set(line_t *l, const pos_t *s, const pos_t *e); +void line_pos(const line_t *l, double t, pos_t *r); + +void plane_set(plane_t *pl, const pos_t *a, const pos_t *b, const pos_t *c); +int plane_side(const plane_t *pl, const pos_t *p); +int plane_cross(const plane_t *pl, const line_t *l, pos_t *r); +int plane_clip(const plane_t *pl, pos_t *a, pos_t *b); + +void axis_set(axis_t *ax, const pos_t *o, const vec_t *y); +void axis_conv(const axis_t *ax, pos_t *p); +void axis_rconv(const axis_t *ax, pos_t *p); + +#endif diff -urN wf-/eye.c wf/eye.c --- wf-/eye.c 1970-01-01 09:00:00.000000000 +0900 +++ wf/eye.c 2015-12-11 00:00:00.000000000 +0900 @@ -0,0 +1,60 @@ +#include "eye.h" + +void +eye_init(eye_t *e, int w, int h) +{ + pos_t o, wh[4]; + int i; + + e->w = e->len = w; + e->h = h; + e->sx = e->ey = 0; + e->ex = w - 1; + e->sy = h - 1; + + d3_set(&wh[0], -e->w/2, e->len, e->h/2); + d3_set(&wh[1], e->w/2, e->len, e->h/2); + d3_set(&wh[2], e->w/2, e->len, -e->h/2); + d3_set(&wh[3], -e->w/2, e->len, -e->h/2); + d3_set(&o, 0,0,0); + for(i=0; i<4; i++) plane_set(&e->clip[i], &o, &wh[i], &wh[(i+1)%4]); +} + +void +eye_update(eye_t *e) +{ + vec_t y; + + vec_set(&y, &e->p, &e->t); + axis_set(&e->ax, &e->p, &y); +} + +int +eye_conv(const eye_t *e, const pos_t *p, int *rx, int *ry) +{ + pos_t t; + double x, y; + + t = *p; + if(t.y <= 0) return -1; + + x = t.x * e->len / t.y; + y = t.z * e->len / t.y; + + *rx = linear(x, -e->w / 2, e->w / 2, e->sx, e->ex); + *ry = linear(y, -e->h / 2, e->h / 2, e->sy, e->ey); + return 0; +} + +int +eye_clip(const eye_t *e, pos_t *a, pos_t *b) +{ + int i, chg, ret; + + chg = 0; + for(i=0; i<4; i++){ + if((ret = plane_clip(&e->clip[i], a, b)) < 0) return -1; /* not visible */ + chg |= ret; + } + return chg; /* bit 0 : a moved , bit 1 : b moved */ +} diff -urN wf-/eye.h wf/eye.h --- wf-/eye.h 1970-01-01 09:00:00.000000000 +0900 +++ wf/eye.h 2015-12-11 00:00:00.000000000 +0900 @@ -0,0 +1,20 @@ +#ifndef __EYE_H__ +#define __EYE_H__ + +#include "d3.h" + +typedef struct{ + double len, w, h; + int sx, ex, sy, ey; + pos_t p, t; + + plane_t clip[4]; + axis_t ax; +} eye_t; + +void eye_init(eye_t *e, int w, int h); +void eye_update(eye_t *e); +int eye_conv(const eye_t *e, const pos_t *p, int *rx, int *ry); +int eye_clip(const eye_t *e, pos_t *a, pos_t *b); + +#endif diff -urN wf-/wf_ex.c wf/wf_ex.c --- wf-/wf_ex.c 2015-12-10 00:00:00.000000000 +0900 +++ wf/wf_ex.c 2015-12-11 00:00:00.000000000 +0900 @@ -1,21 +1,43 @@ #include "x.h" +#include "eye.h" + +void +draw_line(eye_t *e, pos_t *p) +{ + int i, x[2], y[2]; + + for(i=0; i<2; i++) axis_conv(&e->ax, &p[i]); + if(eye_clip(e, &p[0], &p[1]) < 0) return; + for(i=0; i<2; i++) eye_conv(e, &p[i], &x[i], &y[i]); + if(x[0] == x[1] && y[0] == y[1]) return; + xline(x[0], y[0], x[1], y[1]); +} int main(int ac, char **av) { int w, h, i, n = opt_int("-n", ac, av, 10); + eye_t eye; xinit(ac, av, &w, &h); if(opt_idx("-ximg", ac, av) > 0) ximg_curr = ximg_alloc(); + eye_init(&eye, w, h); + d3_set(&eye.p, 0, -n, n); + d3_set(&eye.t, n/2, n/2, 0); + eye_update(&eye); + xclear(); for(i=0; i