#include <math.h>
#include "mx3.h"
#include "poly.h"
#define MINDEL 1e-7

/*
 * pmap_param: find 3x4 affine parameterization that maps texture space
 * to object space.  The texture and object space coordinates of each
 * vertex are passed in the fields (u,v) and (x,y,z) of g->vert[i], resp.
 */

void pmap_param(poly *g,
                double TO[3][4])        /* texture to object transform */
{
    int i;
    double del, pu, pv, qu, qv, p, q, am, bm, cm;
    poly_vert *a, *b, *c;

    /* find three consecutive vertices with noncollinear texture coords */
    a = &g->vert[g->n-2];
    b = &g->vert[g->n-1];
    c = &g->vert[0];
    pu = b->u-a->u; pv = b->v-a->v;
    for (i=0; i<g->n; i++, a++, b++, c++, pu=qu, pv=qv) {
        qu = c->u-b->u; qv = c->v-b->v;
        del = pu*qv-pv*qu;
        if (fabs(del)>MINDEL) break;
    }
    if (i>=g->n)
        ERROR("degenerate polygon");

    /*
     * compute texture to object transform from those three vertices.
     * (note that the correspondences at other vertices are ignored;
     * they are assumed to obey the same affine mapping)
     */
    am = DET2(b->u, c->u, b->v, c->v);
    bm = DET2(c->u, a->u, c->v, a->v);
    cm = DET2(a->u, b->u, a->v, b->v);
    p = b->x-a->x;
    q = c->x-b->x;
    TO[0][0] = DET2(p , q , pv, qv);
    TO[1][0] = DET2(pu, qu, p , q );
    TO[2][0] = a->x*am+b->x*bm+c->x*cm;
    p = b->y-a->y;
    q = c->y-b->y;
    TO[0][1] = DET2(p , q , pv, qv);
    TO[1][1] = DET2(pu, qu, p , q );
    TO[2][1] = a->y*am+b->y*bm+c->y*cm;
    p = b->z-a->z;
    q = c->z-b->z;
    TO[0][2] = DET2(p , q , pv, qv);
    TO[1][2] = DET2(pu, qu, p , q );
    TO[2][2] = a->z*am+b->z*bm+c->z*cm;
    TO[0][3] = 0.;
    TO[1][3] = 0.;
    TO[2][3] = del;
}
