Ejemplo n.º 1
0
Vector3 refract_dir(Vector3 d, Vector3 n, Real eta)
{
  Real c1, c2;

  if ((c1 = v3_dot(d, n)) < 0)
    c1 = -c1;
  else
    n = v3_scale(-1.0, n);

  if ((c2 = 1 - SQR(eta) * (1 - SQR(c1))) < 0)
    return v3_make(0,0,0);
  else
    return v3_add(v3_scale(eta, d), v3_scale(eta*c1 - sqrt(c2), n));
}
Ejemplo n.º 2
0
Archivo: main.c Proyecto: mattjakob/s3d
int main(int argc, char **argv)
{
  Poly *l, *p, *c = poly_alloc(3);
  Item *i;

  init_sdl();
  s = scene_read();
  init_render();

  for (o = s->objs; o != NULL; o = o->next) {
    for (l = prim_uv_decomp(o->u.prim, 1.); l != NULL; l = l->next) {
      p = poly_transform(prim_polys(o->u.prim, l), mclip);
      if (!is_backfacing(p, v3_unit(v3_scale(-1, poly_centr(p)))))
	hither_clip(VIEW_ZMIN(s->view), p, z_store, plist_free);
    }
  }
  z = z_sort(z);

  for (i = z->head; i != NULL; i = i->next) { 
    gouraud_shade(c, P(i), N(i), s->view->center, rc, M(i));
    p = poly_homoxform(S(i),mdpy);
    scan_poly(p, gouraud_paint, gouraud_set(g,c,s->img));
  }
  img_write(s->img, "stdout", 0);
  exit(0);
}
Ejemplo n.º 3
0
vec3_t get_mouse_hit(float x, float y)
{
	double mv[16], proj[16];
	int vp[4];
	double res_x, res_y, res_z;
	float t;
	vec3_t res, pnear, pfar;

	glGetDoublev(GL_MODELVIEW_MATRIX, mv);
	glGetDoublev(GL_PROJECTION_MATRIX, proj);
	glGetIntegerv(GL_VIEWPORT, vp);

	y = vp[3] - y;

	gluUnProject(x, y, 0, mv, proj, vp, &res_x, &res_y, &res_z);
	pnear.x = res_x;
	pnear.y = res_y;
	pnear.z = res_z;

	gluUnProject(x, y, 1, mv, proj, vp, &res_x, &res_y, &res_z);
	pfar.x = res_x;
	pfar.y = res_y;
	pfar.z = res_z;

	t = fabs(pnear.z) / fabs(pfar.z - pnear.z);
	res = v3_add(pnear, v3_scale(v3_sub(pfar, pnear), t));

	return res;
}
Ejemplo n.º 4
0
Archivo: main.c Proyecto: mattjakob/s3d
int main(int argc, char **argv)
{
  Poly *l, *p, *q = poly_alloc(3);
  Hpoly *t = hpoly_alloc(3);
  Item *i;

  init_sdl();
  s = scene_read();
  init_render();

  for (o = s->objs; o != NULL; o = o->next) {
    for (l = prim_uv_decomp(o->u.prim, 1.); l != NULL; l = l->next) {
      p = poly_transform(prim_polys(o->u.prim, l), mclip);
      if (!is_backfacing(p, v3_unit(v3_scale(-1, poly_centr(p)))))
	hither_clip(0, p, z_store, plist_free);
    }
  }
  z = z_sort(z);

  for (i = z->head; i != NULL; i = i->next) {
    t = hpoly_polyxform(t, S(i), mdpy);
    q = poly_wz_hpoly(q, W(i), t);
    texture_wscale(W(i), T(i));
    scan_spoly3(q, 2, texture_shadepaint,
             texture_set(td,W(i),T(i),P(i),N(i),DU(i),DV(i),rc,M(i)));
  }
  img_write(s->img, "stdout", 0);
  exit(0);
}
Ejemplo n.º 5
0
Sprite* sprite_create(const char* texture_path) {
    Sprite* sprite = malloc(sizeof(*sprite));
    if(sprite == NULL) {
        perror("Sprite creation");
        return NULL;
    }

    strcpy(sprite->path, texture_path);

    sprite->texture = texture_load(sprite->path);
    sprite->width = texture_get_param(sprite->texture, GL_TEXTURE_WIDTH);
    sprite->height = texture_get_param(sprite->texture, GL_TEXTURE_HEIGHT);
    sprite->transform = m4_identity();

    vec3 vertices[num_vertices];
    vec3 scale = {sprite->width, sprite->height, 1};
    int i;
    for(i = 0; i < num_vertices; ++i) {
        v3_scale(&vertices[i], &quad_vertices[i], &scale);
    }

    sprite->attributes[0].buffer = buffer_create(&vertices, sizeof(vertices));
    sprite->attributes[0].size = 3;
    sprite->attributes[1].buffer = buffer_create(&quad_uv, sizeof(quad_uv));
    sprite->attributes[1].size = 2;

    return sprite;
}
Ejemplo n.º 6
0
Archivo: misc.c Proyecto: cheque/s3d
int dir_coupling(Cone a, Vector3 v)
{
  if (v3_dot(a.d, v3_scale(-1, v)) > a.cosa)
    return TRUE;
  else
    return FALSE;
}
Ejemplo n.º 7
0
Archivo: map.c Proyecto: cheque/s3d
Color bump_map(void *info, Vector3 t, Vector3 n, Vector3 ds, Vector3 dt)
{
  TextureSrc *src = info;
  Real h = 0.0005;

  Real fo = texture_c1((*src->texfunc)(src->texdata, t));
  Real fu = texture_c1((*src->texfunc)(src->texdata, v3_add(t,v3_make(h,0,0))));
  Real fv = texture_c1((*src->texfunc)(src->texdata, v3_add(t,v3_make(0,h,0))));

  Real du = fderiv(fo, fu, h);
  Real dv = fderiv(fo, fv, h);
  
  Vector3 u = v3_scale(du, v3_cross(n, dt));
  Vector3 v = v3_scale(-dv, v3_cross(n, ds));

  return v3_add(u, v);
}
Ejemplo n.º 8
0
v3_t v3_unit(const v3_t v) {
    double mag = v3_mag(v);

    if (mag == 0) 
        return v;
    
    return v3_scale(1.0 / mag, v);
}
Ejemplo n.º 9
0
/* Compute the mean of a set of vectors */
v3_t v3_mean(int n, const v3_t *v) {
    int i;
    v3_t mean = v3_new(0.0, 0.0, 0.0);
    
    for (i = 0; i < n; i++) {
	mean = v3_add(mean, v[i]);
    }

    return v3_scale(1.0 / n, mean);
}
Ejemplo n.º 10
0
Archivo: mesh.c Proyecto: mattjakob/s3d
static void tri_refine(Vector3 v0, Vector3 v1, Vector3 v2, Real s, int maxrec)
{
    Real l1 = v3_norm(v3_sub(v0, v1));
    Real l2 = v3_norm(v3_sub(v1, v2));
    Real l3 = v3_norm(v3_sub(v2, v0));

    if ((MAX(l1, MAX(l2, l3))) <= s || --maxrec < 0) {
        plist = poly_insert(plist, poly3_make(v0, v1, v2));
    } else {
        Vector3 m1 = v3_scale(0.5, v3_add(v0, v1));
        Vector3 m2 = v3_scale(0.5, v3_add(v1, v2));
        Vector3 m3 = v3_scale(0.5, v3_add(v2, v0));

        tri_refine(m1, v1, m2, s, maxrec);
        tri_refine(m2, v2, m3, s, maxrec);
        tri_refine(m3, v0, m1, s, maxrec);
        tri_refine(m1, m2, m3, s, maxrec);
    }
}
Ejemplo n.º 11
0
Archivo: set.c Proyecto: cheque/s3d
void makeviewVi(void)
{
  Vector3 n,u,v,t;

  n = view->normal;
  v = v3_sub(view->up, v3_scale(v3_dot(view->up, n), n));
  if (v3_norm(v) < ROUNDOFF)
    error("view up parallel to view normal");
  v = v3_unit(v);
  u = v3_cross(n, v);
  v = v3_cross(u, n);
  n = v3_scale(-1.0, n);
  t = view->center;

  view->Vinv = m4_ident();
  view->Vinv.r1.x = u.x; view->Vinv.r2.x = u.y; view->Vinv.r3.x = u.z;
  view->Vinv.r1.y = v.x; view->Vinv.r2.y = v.y; view->Vinv.r3.y = v.z;
  view->Vinv.r1.z = n.x; view->Vinv.r2.z = n.y; view->Vinv.r3.z = n.z;
  view->Vinv.r1.w = t.x; view->Vinv.r2.w = t.y; view->Vinv.r3.w = t.z;
}
Ejemplo n.º 12
0
void subdiv_line(Vector3 p, Vector3 q, void (*paint)())
{
  Box3d bb = bound(p, q);

  if ((bb.ur.x - bb.ll.x) <= 1 && (bb.ur.y - bb.ll.y) <= 1) {
    paint(bb.ll.x, bb.ll.y);
  } else {
    Vector3 m = v3_scale(0.5, v3_add(p,q));
    subdiv_line(p, m, paint);
    subdiv_line(m, q, paint);
  }
}
Ejemplo n.º 13
0
static Real formfactor(int i, int j, int n, Poly **p, Real *a)
{
  Vector3 vi, vj, vji, d;
  Real r2, ci, cj;
 
  vi = poly_centr(p[i]);
  vj = poly_centr(p[j]);
  vji = v3_sub(vi, vj);
  if ((r2 = v3_sqrnorm(vji)) < REL_EPS)
    return 0;    
  d = v3_scale(1.0/sqrt(r2), vji);
  if ((cj =  v3_dot(poly_normal(p[j]), d)) < REL_EPS)
    return 0;
  if ((ci = -v3_dot(poly_normal(p[i]), d)) < REL_EPS)
    return 0;
  if (vis_flag  && visible(n, p, vj, vji) < REL_EPS)
    return 0;
  return a[i] * ((cj * ci) / (PI * r2 + a[i])); 
}
Ejemplo n.º 14
0
/* Assumes unit_normal is normalized */
v3_t v3_project(const v3_t v, const v3_t unit_normal) {
    double dot = v3_dotp(v, unit_normal);
    v3_t par = v3_scale(dot, unit_normal);
    v3_t perp = v3_sub(v, par);
    return perp;
}
Ejemplo n.º 15
0
void GLWidget::keyPressEvent(QKeyEvent *event)
{
    Matrix4 M;
    Vector3 Dir;
    switch (event->key()) {
    case Qt::Key_Q:
    case Qt::Key_A:
        M = m4_rotate('y', 0.5);
        scene->view->center = v3_m4mult(scene->view->center,M);
        scene->view->normal = v3_m4mult(scene->view->normal,M);
        makeviewV();
        setview(scene->view);
        break;
    case Qt::Key_D:
        M = m4_rotate('y', -0.5);
        scene->view->center = v3_m4mult(scene->view->center,M);
        scene->view->normal = v3_m4mult(scene->view->normal,M);
        makeviewV();
        setview(scene->view);
        break;
    case Qt::Key_W:
        M = m4_rotate('x', 0.5);
        scene->view->center = v3_m4mult(scene->view->center,M);
        scene->view->up = v3_m4mult(scene->view->up,M);
        scene->view->normal = v3_m4mult(scene->view->normal,M);
        makeviewV();
        setview(scene->view);
        break;
    case Qt::Key_S:
        M = m4_rotate('x', -0.5);
        scene->view->center = v3_m4mult(scene->view->center,M);
        scene->view->up = v3_m4mult(scene->view->up,M);
        scene->view->normal = v3_m4mult(scene->view->normal,M);
        makeviewV();
        setview(scene->view);
        break;
    case Qt::Key_Left:
        Dir = v3_cross(scene->view->up,scene->view->normal);
        scene->view->center = v3_add(scene->view->center,v3_scale(0.5,Dir));
        makeviewV();
        setview(scene->view);
        break;
    case Qt::Key_Right:
        Dir = v3_cross(scene->view->up,scene->view->normal);
        scene->view->center = v3_sub(scene->view->center,v3_scale(0.5,Dir));
        makeviewV();
        setview(scene->view);
        break;
    case Qt::Key_Up:
        scene->view->center = v3_add(scene->view->center,v3_scale(0.5,scene->view->up));
        makeviewV();
        setview(scene->view);
        break;
    case Qt::Key_Down:
        scene->view->center = v3_sub(scene->view->center,v3_scale(0.5,scene->view->up));
        makeviewV();
        setview(scene->view);
        break;

    case Qt::Key_Escape:
           exit(0);
           break;
    case Qt::Key_R:
        if (!lastfile.isEmpty())
            load_scene_file(lastfile.toLatin1().data());
        break;
    }
    update();
}
Ejemplo n.º 16
0
/* Computes the closed-form least-squares solution to a rigid
 * body alignment.
 *
 * n: the number of points
 * right_pts: Target set of n points 
 * left_pts:  Source set of n points */
double align_horn_3D(int n, v3_t *right_pts, v3_t *left_pts, int scale_xform, 
		     double *Tout) {
    int i;
    v3_t right_centroid = v3_new(0.0, 0.0, 0.0);
    v3_t left_centroid = v3_new(0.0, 0.0, 0.0);
    double M[3][3] = { { 0.0, 0.0, 0.0, }, 
                       { 0.0, 0.0, 0.0, },
		       { 0.0, 0.0, 0.0, } };
    double MT[3][3];
    double MTM[3][3];
    double eval[3], sqrteval_inv[3];
    double evec[3][3], evec_tmp[3][3];
    double Sinv[3][3], U[3][3];
    double Tcenter[4][4] = { { 1.0, 0.0, 0.0, 0.0 },
			     { 0.0, 1.0, 0.0, 0.0 },
			     { 0.0, 0.0, 1.0, 0.0 },
			     { 0.0, 0.0, 0.0, 1.0 } };

    double Ttmp[4][4];
    double T[16], R[16];

    double sum_num, sum_den, scale, RMS_sum;

    int perm[3];

    /* Compute the centroid of both point sets */
    right_centroid = v3_mean(n, right_pts);
    left_centroid  = v3_mean(n, left_pts);

    /* Compute the scale */
    sum_num = sum_den = 0.0;

    for (i = 0; i < n; i++) {
        v3_t r = v3_sub(right_centroid, right_pts[i]);
        v3_t l = v3_sub(left_centroid, left_pts[i]);
	
	sum_num += v3_magsq(r);
	sum_den += v3_magsq(l);
    }

    scale = sqrt(sum_num / sum_den);

    /* Fill in the matrix M */
    for (i = 0; i < n; i++) {
        v3_t r = v3_sub(right_centroid, right_pts[i]);
        v3_t l = v3_sub(left_centroid, left_pts[i]);

	M[0][0] += Vx(r) * Vx(l);
	M[0][1] += Vx(r) * Vy(l);
	M[0][2] += Vx(r) * Vz(l);

	M[1][0] += Vy(r) * Vx(l);
	M[1][1] += Vy(r) * Vy(l);
	M[1][2] += Vy(r) * Vz(l);

	M[2][0] += Vz(r) * Vx(l);
	M[2][1] += Vz(r) * Vy(l);
	M[2][2] += Vz(r) * Vz(l);
    }

    /* Compute MTM */
    matrix_transpose(3, 3, (double *)M, (double *)MT);
    matrix_product(3, 3, 3, 3, (double *)MT, (double *)M, (double *)MTM);

    /* Calculate Sinv, the inverse of the square root of MTM */
    dgeev_driver(3, (double *)MTM, (double *)evec, eval);

    /* Sort the eigenvalues */
    qsort_descending();
    qsort_perm(3, eval, perm);
    
    memcpy(evec_tmp[0], evec[perm[0]], sizeof(double) * 3);
    memcpy(evec_tmp[1], evec[perm[1]], sizeof(double) * 3);
    memcpy(evec_tmp[2], evec[perm[2]], sizeof(double) * 3);
    memcpy(evec, evec_tmp, sizeof(double) * 9);

    sqrteval_inv[0] = 1.0 / sqrt(eval[0]);
    sqrteval_inv[1] = 1.0 / sqrt(eval[1]);

    if (eval[2] < 1.0e-8 * eval[0]) {
        sqrteval_inv[2] = 0.0;
    } else {
        sqrteval_inv[2] = 1.0 / sqrt(eval[2]);
    }

    Sinv[0][0] = 
        sqrteval_inv[0] * evec[0][0] * evec[0][0] +
        sqrteval_inv[1] * evec[1][0] * evec[1][0] + 
        sqrteval_inv[2] * evec[2][0] * evec[2][0];
    Sinv[0][1] = 
        sqrteval_inv[0] * evec[0][0] * evec[0][1] +
        sqrteval_inv[1] * evec[1][0] * evec[1][1] + 
        sqrteval_inv[2] * evec[2][0] * evec[2][1];
    Sinv[0][2] = 
        sqrteval_inv[0] * evec[0][0] * evec[0][2] +
        sqrteval_inv[1] * evec[1][0] * evec[1][2] + 
        sqrteval_inv[2] * evec[2][0] * evec[2][2];

    Sinv[1][0] = 
        sqrteval_inv[0] * evec[0][1] * evec[0][0] +
        sqrteval_inv[1] * evec[1][1] * evec[1][0] +
        sqrteval_inv[2] * evec[2][1] * evec[2][0];
    Sinv[1][1] = 
        sqrteval_inv[0] * evec[0][1] * evec[0][1] +
        sqrteval_inv[1] * evec[1][1] * evec[1][1] +
        sqrteval_inv[2] * evec[2][1] * evec[2][1];
    Sinv[1][2] = 
        sqrteval_inv[0] * evec[0][1] * evec[0][2] +
        sqrteval_inv[1] * evec[1][1] * evec[1][2] +
        sqrteval_inv[2] * evec[2][1] * evec[2][2];
    
    Sinv[2][0] = 
        sqrteval_inv[0] * evec[0][2] * evec[0][0] +
        sqrteval_inv[1] * evec[1][2] * evec[1][0] +
        sqrteval_inv[2] * evec[2][2] * evec[2][0];
    Sinv[2][1] = 
        sqrteval_inv[0] * evec[0][2] * evec[0][1] +
        sqrteval_inv[1] * evec[1][2] * evec[1][1] +
        sqrteval_inv[2] * evec[2][2] * evec[2][1];
    Sinv[2][2] = 
        sqrteval_inv[0] * evec[0][2] * evec[0][2] +
        sqrteval_inv[1] * evec[1][2] * evec[1][2] +
        sqrteval_inv[2] * evec[2][2] * evec[2][2];

    /* U = M * Sinv */
    matrix_product(3, 3, 3, 3, (double *)M, (double *)Sinv, (double *)U);

    if (eval[2] < 1.0e-8 * eval[0]) {    
        double u3u3[9], Utmp[9];
        matrix_transpose_product2(3, 1, 3, 1, evec[2], evec[2], u3u3);

        matrix_sum(3, 3, 3, 3, (double *) U, u3u3, Utmp);
        
        if (matrix_determinant3(Utmp) < 0.0) {
            printf("[align_horn_3D] Recomputing matrix...\n");
            matrix_diff(3, 3, 3, 3, (double *) U, u3u3, Utmp);
        }

        memcpy(U, Utmp, 9 * sizeof(double));
    }
    
    /* Fill in the rotation matrix */
    R[0]  = U[0][0]; R[1]  = U[0][1]; R[2]  = U[0][2]; R[3]  = 0.0;
    R[4]  = U[1][0]; R[5]  = U[1][1]; R[6]  = U[1][2]; R[7]  = 0.0;
    R[8]  = U[2][0]; R[9]  = U[2][1]; R[10] = U[2][2]; R[11] = 0.0;
    R[12] = 0.0;     R[13] = 0.0;     R[14] = 0.0;     R[15] = 1.0;
    
    /* Fill in the translation matrix */
    matrix_ident(4, T);
    T[3]  = Vx(right_centroid);
    T[7]  = Vy(right_centroid);
    T[11] = Vz(right_centroid);

    if (scale_xform == 0)
	scale = 1.0;

    Tcenter[0][0] = scale;
    Tcenter[1][1] = scale;
    Tcenter[2][2] = scale;
    
    Tcenter[0][3] = -scale * Vx(left_centroid);
    Tcenter[1][3] = -scale * Vy(left_centroid);
    Tcenter[2][3] = -scale * Vz(left_centroid);

    matrix_product(4, 4, 4, 4, T, R, (double *) Ttmp);
    matrix_product(4, 4, 4, 4, (double *)Ttmp, (double *)Tcenter, Tout);

#if 0
    T[2] = Vx(v3_sub(right_centroid, left_centroid));
    T[5] = Vy(v3_sub(right_centroid, left_centroid));
    T[8] = Vz(v3_sub(right_centroid, left_centroid));
#endif

    /* Now compute the RMS error between the points */
    RMS_sum = 0.0;

    for (i = 0; i < n; i++) {
	double left[4] = { Vx(left_pts[i]), 
			   Vy(left_pts[i]), 
			   Vz(left_pts[i]), 1.0 };
	double left_prime[3];
	double dx, dy, dz;

	matrix_product(4, 4, 4, 1, Tout, left, left_prime);

	dx = left_prime[0] - Vx(right_pts[i]);
	dy = left_prime[1] - Vy(right_pts[i]);
	dz = left_prime[2] - Vz(right_pts[i]);

	RMS_sum += dx * dx + dy * dy + dz * dz;
#if 0
        v3_t r = v3_sub(right_centroid, right_pts[i]);
        v3_t l = v3_sub(left_centroid, left_pts[i]);
	v3_t resid;

	/* Rotate, scale l */
	v3_t Rl, SRl;

	Vx(Rl) = R[0] * Vx(l) + R[1] * Vy(l) + R[2] * Vz(l);
	Vy(Rl) = R[3] * Vx(l) + R[4] * Vy(l) + R[5] * Vz(l);
	Vz(Rl) = R[6] * Vx(l) + R[7] * Vy(l) + R[8] * Vz(l);

	SRl = v3_scale(scale, Rl);
	
	resid = v3_sub(r, SRl);
	RMS_sum += v3_magsq(resid);
#endif
    }
    
    return sqrt(RMS_sum / n);
}
Ejemplo n.º 17
0
/* Computes the closed-form least-squares solution to a rigid
 * body alignment.
 *
 * n: the number of points
 * right_pts: Target set of n points 
 * left_pts:  Source set of n points */
double align_horn(int n, v3_t *right_pts, v3_t *left_pts, 
		  double *R, double *T, 
		  double *Tout, double *scale, double *weight) {
    int i;
    v3_t right_centroid = v3_new(0.0, 0.0, 0.0);
    v3_t left_centroid = v3_new(0.0, 0.0, 0.0);
    double M[2][2] = { { 0.0, 0.0 }, 
                       { 0.0, 0.0 } };
    double MT[2][2];
    double MTM[2][2];
    double eval[2], sqrteval[2];
    double evec[2][2];
    double S[2][2], Sinv[2][2], U[2][2];
    double Tcenter[3][3] = { { 1.0, 0.0, 0.0 },
			     { 0.0, 1.0, 0.0 },
			     { 0.0, 0.0, 1.0 } };

    double Ttmp[3][3];

    double sum_num, sum_den, RMS_sum;

#if 1
    double weight_sum = 0.0;

    if (weight == NULL) {
        weight_sum = n;

        for (i = 0; i < n; i++) {
            right_centroid = 
                v3_add(right_centroid, right_pts[i]);
            left_centroid = 
                v3_add(left_centroid, left_pts[i]);
        }
        
        right_centroid = v3_scale(1.0 / weight_sum, right_centroid);
        left_centroid = v3_scale(1.0 / weight_sum, left_centroid);        
    } else {
        /* Compute the weighted centroid of both point sets */
        for (i = 0; i < n; i++) {
            right_centroid = 
                v3_add(right_centroid, v3_scale(weight[i], right_pts[i]));
            left_centroid = 
                v3_add(left_centroid, v3_scale(weight[i], left_pts[i]));
            weight_sum += weight[i];
        }

        right_centroid = v3_scale(1.0 / weight_sum, right_centroid);
        left_centroid = v3_scale(1.0 / weight_sum, left_centroid);
    }
#else
    /* Calculate the centroid of both sets of points */
    for (i = 0; i < n; i++) {
        right_centroid = v3_add(right_centroid, right_pts[i]);
        left_centroid = v3_add(left_centroid, left_pts[i]);
    }

    right_centroid = v3_scale(1.0 / n, right_centroid);
    left_centroid = v3_scale(1.0 / n, left_centroid);
#endif

    /* Compute the scale */
    sum_num = sum_den = 0.0;

    for (i = 0; i < n; i++) {
        v3_t r = v3_sub(right_centroid, right_pts[i]);
        v3_t l = v3_sub(left_centroid, left_pts[i]);
	
	sum_num = v3_magsq(r);
	sum_den = v3_magsq(l);
    }

    *scale = sqrt(sum_num / sum_den);

    /* Fill in the matrix M */
    for (i = 0; i < n; i++) {
        v3_t r = v3_sub(right_centroid, right_pts[i]);
        v3_t l = v3_sub(left_centroid, left_pts[i]);

	if (weight != NULL) {
	    M[0][0] += Vx(r) * Vx(l);
	    M[0][1] += Vx(r) * Vy(l);
	    M[1][0] += Vy(r) * Vx(l);
	    M[1][1] += Vy(r) * Vy(l);
	} else {
	    M[0][0] += Vx(r) * Vx(l);
	    M[0][1] += Vx(r) * Vy(l);
	    M[1][0] += Vy(r) * Vx(l);
	    M[1][1] += Vy(r) * Vy(l);
	}
    }

    /* Compute MTM */
    matrix_transpose(2, 2, (double *)M, (double *)MT);
    matrix_product(2, 2, 2, 2, (double *)MT, (double *)M, (double *)MTM);

    /* Calculate Sinv, the inverse of the square root of MTM */
    dgeev_driver(2, (double *)MTM, (double *)evec, eval);
    
    /* MTM = eval[0] * evec[0]T * evec[0] + eval[1] * evec[1]T * evec[1] */
    /* S = sqrt(eval[0]) * evec[0]T * evec[0] + sqrt(eval[1]) * evec[1]T * evec[1] */
    sqrteval[0] = sqrt(eval[0]);
    sqrteval[1] = sqrt(eval[1]);

    S[0][0] = 
        (sqrteval[0]) * evec[0][0] * evec[0][0] +
        (sqrteval[1]) * evec[1][0] * evec[1][0];
    S[0][1] = 
        (sqrteval[0]) * evec[0][0] * evec[0][1] +
        (sqrteval[1]) * evec[1][0] * evec[1][1];
    S[1][0] = 
        (sqrteval[0]) * evec[0][1] * evec[0][0] +
        (sqrteval[1]) * evec[1][1] * evec[1][0];
    S[1][1] = 
        (sqrteval[0]) * evec[0][1] * evec[0][1] +
        (sqrteval[1]) * evec[1][1] * evec[1][1];
    
    Sinv[0][0] = 
        (1.0 / sqrteval[0]) * evec[0][0] * evec[0][0] +
        (1.0 / sqrteval[1]) * evec[1][0] * evec[1][0];
    Sinv[0][1] = 
        (1.0 / sqrteval[0]) * evec[0][0] * evec[0][1] +
        (1.0 / sqrteval[1]) * evec[1][0] * evec[1][1];
    Sinv[1][0] = 
        (1.0 / sqrteval[0]) * evec[0][1] * evec[0][0] +
        (1.0 / sqrteval[1]) * evec[1][1] * evec[1][0];
    Sinv[1][1] = 
        (1.0 / sqrteval[0]) * evec[0][1] * evec[0][1] +
        (1.0 / sqrteval[1]) * evec[1][1] * evec[1][1];
    
    // matrix_product(2, 2, 2, 2, (double *)S, (double *)Sinv, (double *)U);

    /* U = M * Sinv */
    matrix_product(2, 2, 2, 2, (double *)M, (double *)Sinv, (double *)U);

    /* Fill in the rotation matrix */
    R[0] = U[0][0]; R[1] = U[0][1]; R[2] = 0.0;
    R[3] = U[1][0], R[4] = U[1][1]; R[5] = 0.0;
    R[6] = 0.0;     R[7] = 0.0;     R[8] = 1.0;

    // memcpy(R, U, sizeof(double) * 4);

    /* Fill in the translation matrix */
    T[0] = T[4] = T[8] = 1.0;
    T[1] = T[3] = T[6] = T[7] = 0.0;
    T[2] = Vx(right_centroid);
    T[5] = Vy(right_centroid);

    Tcenter[0][0] = *scale;
    Tcenter[1][1] = *scale;
    Tcenter[0][2] = -*scale * Vx(left_centroid);
    Tcenter[1][2] = -*scale * Vy(left_centroid);

    matrix_product(3, 3, 3, 3, T, R, (double *)Ttmp);

#if 0
#if 0
    /* Do the scaling */
    Ttmp[0][0] *= *scale;
    Ttmp[0][1] *= *scale;
    Ttmp[0][2] *= *scale;
    Ttmp[1][0] *= *scale;
    Ttmp[1][1] *= *scale;
    Ttmp[1][2] *= *scale;
#else
    Tcenter[0][0] *= *scale;
    Tcenter[0][2] *= *scale;
    Tcenter[1][1] *= *scale;
    Tcenter[1][2] *= *scale;
#endif
#endif

    matrix_product(3, 3, 3, 3, (double *)Ttmp, (double *)Tcenter, Tout);

    T[2] = Vx(v3_sub(right_centroid, left_centroid));
    T[5] = Vy(v3_sub(right_centroid, left_centroid));


    /* Now compute the RMS error between the points */
    RMS_sum = 0.0;

    for (i = 0; i < n; i++) {
        v3_t r = v3_sub(right_centroid, right_pts[i]);
        v3_t l = v3_sub(left_centroid, left_pts[i]);
	v3_t resid;

	/* Rotate, scale l */
	v3_t Rl, SRl;

	Vx(Rl) = R[0] * Vx(l) + R[1] * Vy(l) + R[2] * Vz(l);
	Vy(Rl) = R[3] * Vx(l) + R[4] * Vy(l) + R[5] * Vz(l);
	Vz(Rl) = R[6] * Vx(l) + R[7] * Vy(l) + R[8] * Vz(l);

	SRl = v3_scale(*scale, Rl);
	
	resid = v3_sub(r, SRl);
	RMS_sum += v3_magsq(resid);
    }
    
    return sqrt(RMS_sum / n);
}
Ejemplo n.º 18
0
/* Computes the closed-form least-squares solution to a rigid
 * body alignment.
 *
 * n: the number of points
 * right_pts: Target set of n points 
 * left_pts:  Source set of n points */
double align_horn_3D_2(int n, v3_t *right_pts, v3_t *left_pts, int scale_xform,
                       double *Tout) 
{
    int i;
    v3_t right_centroid = v3_new(0.0, 0.0, 0.0);
    v3_t left_centroid = v3_new(0.0, 0.0, 0.0);
    double Tcenter[16] = { 1.0, 0.0, 0.0, 0.0,
                           0.0, 1.0, 0.0, 0.0,
                           0.0, 0.0, 1.0, 0.0,
                           0.0, 0.0, 0.0, 1.0 };

    double Ttmp[4][4];
    double T[16], R[16], R3x3[9];

    double sum_num, sum_den, scale, RMS_sum;

    v3_t *left_pts_zm  = malloc(sizeof(v3_t) * n);
    v3_t *right_pts_zm = malloc(sizeof(v3_t) * n);

    double error = 0.0;

    /* Compute the centroid of both point sets */
    right_centroid = v3_mean(n, right_pts);
    left_centroid  = v3_mean(n, left_pts);

    /* Compute the scale */
    sum_num = sum_den = 0.0;

    for (i = 0; i < n; i++) {
        v3_t r = v3_sub(right_centroid, right_pts[i]);
        v3_t l = v3_sub(left_centroid, left_pts[i]);

	sum_num += v3_magsq(r);
	sum_den += v3_magsq(l);
    }

    scale = sqrt(sum_num / sum_den);

    for (i = 0; i < n; i++) {
        v3_t r = v3_sub(right_centroid, right_pts[i]);
        v3_t l = v3_sub(left_centroid, left_pts[i]);

        right_pts_zm[i] = r;
        left_pts_zm[i]  = v3_scale(scale, l);
    }

    /* Compute the rotation */
    error = align_3D_rotation(n, right_pts_zm, left_pts_zm, R3x3);
    // printf("error[%d]: %0.3f\n", n, error);
    // matrix_print(3, 3, R3x3);

    /* Fill in the rotation matrix */
    R[0]  = R3x3[0]; R[1]  = R3x3[1]; R[2]  = R3x3[2]; R[3]  = 0.0;
    R[4]  = R3x3[3]; R[5]  = R3x3[4]; R[6]  = R3x3[5]; R[7]  = 0.0;
    R[8]  = R3x3[6]; R[9]  = R3x3[7]; R[10] = R3x3[8]; R[11] = 0.0;
    R[12] = 0.0;     R[13] = 0.0;     R[14] = 0.0;     R[15] = 1.0;
    
    /* Fill in the translation matrix */
    // matrix_ident(4, T);
    T[0] = 1.0;  T[1] = 0.0;  T[2] = 0.0;  T[3]  = Vx(right_centroid);
    T[4] = 0.0;  T[5] = 1.0;  T[6] = 0.0;  T[7]  = Vy(right_centroid);
    T[8] = 0.0;  T[9] = 0.0;  T[10] = 1.0; T[11] = Vz(right_centroid);
    T[12] = 0.0; T[13] = 0.0; T[14] = 0.0; T[15] = 1.0;

    if (scale_xform == 0)
	scale = 1.0;

    Tcenter[0] = scale;
    Tcenter[5] = scale;
    Tcenter[10] = scale;
    
    Tcenter[3] = -scale * Vx(left_centroid);
    Tcenter[7] = -scale * Vy(left_centroid);
    Tcenter[11] = -scale * Vz(left_centroid);

    matrix_product44(T, R, (double *) Ttmp);
    matrix_product44((double *)Ttmp, (double *)Tcenter, Tout);

    /* Now compute the RMS error between the points */
    RMS_sum = 0.0;

    for (i = 0; i < n; i++) {
	double left[4] = { Vx(left_pts[i]), 
			   Vy(left_pts[i]), 
			   Vz(left_pts[i]), 1.0 };
	double left_prime[3];
	double dx, dy, dz;

	matrix_product441(Tout, left, left_prime);

	dx = left_prime[0] - Vx(right_pts[i]);
	dy = left_prime[1] - Vy(right_pts[i]);
	dz = left_prime[2] - Vz(right_pts[i]);

	RMS_sum += dx * dx + dy * dy + dz * dz;
    }

    free(left_pts_zm);
    free(right_pts_zm);
    
    return sqrt(RMS_sum / n);
}
Ejemplo n.º 19
0
/* Align two sets of points with a 2D similarity transform */
int align_2D_ransac(int n, v3_t *r_pts, v3_t *l_pts, 
                    int num_ransac_rounds, double ransac_thresh,
                    double *Tret)
{
    int round;    
#define MIN_SUPPORT 2
    v3_t *l_inliers, *r_inliers;
    int num_inliers, max_inliers = 0;
    double Tbest[9], R[9], T[9], scale;
    int i;

    if (n < 3) {
	printf("[align_2D_ransac] Error: need at least 3 points!\n");
	return 0;
    }

    l_inliers = (v3_t *) malloc(sizeof(v3_t) * n);
    r_inliers = (v3_t *) malloc(sizeof(v3_t) * n);

    for (round = 0; round < num_ransac_rounds; round++) {
	int support[MIN_SUPPORT];
	int i, j;
    v3_t r_mean, l_mean, r0, l0;
	v3_t r_pts_small[MIN_SUPPORT], l_pts_small[MIN_SUPPORT];
	double Rtmp[9], T1tmp[9], T2tmp[9], tmp[9], Tout[9];
    double a, b;

    for (i = 0; i < MIN_SUPPORT; i++) {
        /* Select an index from 0 to n-1 */
        int idx, reselect;

        do {
            reselect = 0;
            idx = rand() % n;
            for (j = 0; j < i; j++) {
                if (support[j] == idx) {
                    reselect = 1;
                    break;
                }
            }
        } while (reselect);

        support[i] = idx;
        r_pts_small[i] = r_pts[idx];
        l_pts_small[i] = l_pts[idx];
    }

    r_mean = v3_scale(0.5, v3_add(r_pts_small[0], r_pts_small[1]));
    l_mean = v3_scale(0.5, v3_add(l_pts_small[0], l_pts_small[1]));

    r0 = v3_sub(r_pts_small[0], r_mean);
    // v3_t r1 = v3_sub(r_pts_small[1], mean);
    l0 = v3_sub(l_pts_small[0], l_mean);
    // v3_t l1 = v3_sub(l_pts_small[1], mean);

    a = (Vy(r0) + Vx(r0) * Vx(l0) / Vy(l0)) / 
        (Vy(l0) + Vx(l0) * Vx(l0) / Vy(l0));
    b = (Vx(r0) - a * Vx(l0)) / Vy(l0);

    Rtmp[0] = a;  Rtmp[1] = b;  Rtmp[2] = 0.0;
    Rtmp[3] = -b; Rtmp[4] = a;  Rtmp[5] = 0.0;
    Rtmp[6] = 0;  Rtmp[7] = 0;  Rtmp[8] = 1.0;

    matrix_ident(3, T1tmp);
    T1tmp[2] = -Vx(l_mean);
    T1tmp[5] = -Vy(l_mean);

    matrix_ident(3, T2tmp);
    T2tmp[2] = Vx(r_mean);
    T2tmp[5] = Vy(r_mean);        

    matrix_product(3, 3, 3, 3, Rtmp, T1tmp, tmp);
    matrix_product(3, 3, 3, 3, T2tmp, tmp, Tout);

	/* Count inliers */
	num_inliers = 0;
	for (i = 0; i < n; i++) {
	    double Tp[3];
	    double diff[3];
	    double dist;
	    matrix_product(3, 3, 3, 1, Tout, l_pts[i].p, Tp);
	    matrix_diff(3, 1, 3, 1, Tp, r_pts[i].p, diff);
	    dist = matrix_norm(3, 1, diff);
	    
	    if (dist < ransac_thresh) {
		num_inliers++;
	    }

	    if (num_inliers > max_inliers) {
		max_inliers = num_inliers;
		memcpy(Tbest, Tout, sizeof(double) * 9);
                // printf(" inliers_new: %d\n", num_inliers);
	    }
	}
    }

#if 0
    /* Reestimate using all inliers */
    num_inliers = 0;
    for (i = 0; i < n; i++) {
	double Tp[3];
	double diff[3];
	double dist;
	matrix_product(3, 3, 3, 1, Tbest, l_pts[i].p, Tp);
	matrix_diff(3, 1, 3, 1, Tp, r_pts[i].p, diff);
	dist = matrix_norm(3, 1, diff);
	    
	if (dist < ransac_thresh) {
	    r_inliers[num_inliers] = r_pts[i];
	    l_inliers[num_inliers] = l_pts[i];
	    num_inliers++;
	}
    }

    // align_horn(num_inliers, r_inliers, l_inliers, R, T, Tret, &scale, NULL);
    align_2D(num_inliers, r_inliers, l_inliers, R, T, Tret, &scale, NULL);
#else
    memcpy(Tret, Tbest, 9 * sizeof(double));
#endif

    free(r_inliers);
    free(l_inliers);

    return num_inliers;
#undef MIN_SUPPORT
}
Ejemplo n.º 20
0
Vector3 reflect_dir(Vector3 d, Vector3 n)
{
  return v3_add(d, v3_scale(-2 * v3_dot(n, d), n));
}
Ejemplo n.º 21
0
Archivo: cylin.c Proyecto: cheque/s3d
Vector3 cylin_gradient(Prim *p, Vector3 q)
{
  Vector3 w = v3_m4mult(q, p->ti);
  w.z = 0;
  return v3_m3mult(v3_scale(2., w), m4_transpose(p->ti));
}
Ejemplo n.º 22
0
Archivo: misc.c Proyecto: cheque/s3d
int point_coupling(Cone a, Cone b)
{
  Vector3 d = v3_unit(v3_sub(a.o, b.o));
  return dir_coupling(a, d) && dir_coupling(b, v3_scale(-1, d));
}