
/* $XConsortium: xfutils.c,v 5.3 94/04/17 20:46:43 hersh Exp $ */

/*****************************************************************

Copyright (c) 1989,1990, 1991  X Consortium

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of the X Consortium shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the X Consortium.

Copyright (c) 1989,1990, 1991 by Sun Microsystems, Inc.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Sun Microsystems,
and the X Consortium, not be used in advertising or publicity 
pertaining to distribution of the software without specific, written 
prior permission.  

SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT 
SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/



/* 
 * This file contains transformation utilties 
 */

#include "phigs/phigs.h"
#include "math.h"
#include "imath.h"
#include "logmsg.h"
#include "xfutils.h"

/*
 * global variables
 */

/*
 * forward declaration
 */
/*
 * export routines 
 */
void i_translate();
void i_translate3();
void i_scale3();
void i_scale();
void i_rotate();
void i_rotatex();
void i_rotatey();
void i_rotatez();
void i_buildtran3();
void i_buildtran();
void i_composetran3();
void i_composetran();
void i_composematrix();
void i_composematrix3();
void i_evalvieworientationmtx3();
void i_evalvieworientationmtx();
void i_evalviewmappingmtx3();
void i_evalviewmappingmtx();
void i_tranpt();
void i_tranpt3();
void i_identity();
void i_identity3();
/*
 * local routines 
 */
static void i_vectprod();
static void i_vectnorm();
static void i_vectnorm3();
static Pfloat i_vectlen();
static Pfloat i_vectlen3();
static void i_multmat();
static void i_multmat3();


/*
 * i_translate(vec,mtx)
 */
void
i_translate(vec,mtx)
	Pvec vec;		/* vector */
	Pmatrix mtx;		/* OUT matrix */
{
	i_identity(mtx);
	mtx[0][2] = vec.delta_x;
	mtx[1][2] = vec.delta_y;
}

/*
 * i_translate3(vec,mtx)
 */
void 
i_translate3(vec,mtx) 
        Pvec3 vec;            /* vector */ 
        Pmatrix3 mtx;           /* OUT matrix */
{ 
	i_identity3(mtx);
	mtx[0][3] = vec.delta_x;
	mtx[1][3] = vec.delta_y;
	mtx[2][3] = vec.delta_z;
} 

/*
 * i_scale(vec,mtx)
 */
void
i_scale(vec,mtx)
	Pvec vec;		/* vector */
	Pmatrix mtx;		/* OUT matrix */
{
	i_identity(mtx);
	mtx[0][0] = vec.delta_x;
	mtx[1][1] = vec.delta_y;
}

/*
 * i_scale3(vec,mtx)
 */
void 
i_scale3(vec,mtx) 
        Pvec3 vec;            /* vector */ 
        Pmatrix3 mtx;           /* OUT matrix */
{ 
	i_identity3(mtx);
        mtx[0][0] = vec.delta_x;
        mtx[1][1] = vec.delta_y;
        mtx[2][2] = vec.delta_z;
} 

/*
 * i_rotate(angle,mtx)
 */
void
i_rotate(angle,mtx)
	Pfloat angle;		/* angle */
	Pmatrix mtx;		/* OUT matrix */
{
	i_identity(mtx);
	mtx[0][0] = mtx[1][1] = cos(angle);
	mtx[0][1] = - (mtx[1][0] = sin(angle));
}

/*
 * i_rotatex(angle,mtx)
 */
void
i_rotatex(angle,mtx)
	Pfloat angle;		/* angle */
	Pmatrix3 mtx;		/* OUT matrix */
{
	i_identity3(mtx);
	mtx[1][1] = mtx[2][2] = cos(angle);
	mtx[1][2] = - (mtx[2][1] = sin(angle));
}

/*
 * i_rotatey(angle,mtx)
 */
void
i_rotatey(angle,mtx)
	Pfloat angle;		/* angle */
	Pmatrix3 mtx;		/* OUT matrix */
{
	i_identity3(mtx);
	mtx[0][0] = mtx[2][2] = cos(angle);
	mtx[2][0] = - (mtx[0][2] = sin(angle));
}

/*
 * i_rotatez(angle,mtx)
 */
void
i_rotatez(angle,mtx)
	Pfloat angle;		/* angle */
	Pmatrix3 mtx;		/* OUT matrix */
{
	i_identity3(mtx);
	mtx[0][0] = mtx[1][1] = cos(angle);
	mtx[0][1] = - (mtx[1][0] = sin(angle));
}


/*
 * i_buildtran3(ref,xlate,xrot,yrot,zrot,scale,mtx) build a 3d matrix
 */
void
i_buildtran3(ref,xlate,xrot,yrot,zrot,scale,mtx)
	Ppoint3 ref;		/* reference pt */
	Pvec3 xlate;		/* xlate factor */
	Pfloat xrot;		/* x-axis rotation */
	Pfloat yrot;		/* y-axis rotation */
	Pfloat zrot;		/* z-axis rotation */
	Pvec3 scale;		/* scaling factor */
	Pmatrix3 mtx;		/* OUT matrix */
{
        Pmatrix3 tempmat1, tempmat2, tempmat3;

        i_identity3(tempmat1);
        tempmat1[0][3] = ref.x + xlate.delta_x;
        tempmat1[1][3] = ref.y + xlate.delta_y;
        tempmat1[2][3] = ref.z + xlate.delta_z;

        i_identity3(tempmat2);
        tempmat2[0][0] = tempmat2[1][1] = cos(zrot);
        tempmat2[0][1] = -sin(zrot);
        tempmat2[1][0] = sin(zrot);

        i_multmat3(tempmat1,tempmat2,tempmat3);

        i_identity3(tempmat2);
        tempmat2[0][0] = tempmat2[2][2] = cos(yrot);
        tempmat2[0][2] = sin(yrot);
        tempmat2[2][0] = -sin(yrot);

        i_multmat3(tempmat3,tempmat2,tempmat1);

        i_identity3(tempmat2);
        tempmat2[1][1] = tempmat2[2][2] = cos(xrot);
        tempmat2[1][2] = -sin(xrot);
        tempmat2[2][1] = sin(xrot);
 
        i_multmat3(tempmat1,tempmat2,tempmat3);
 
        i_identity3(tempmat2);
        tempmat2[0][0] = scale.delta_x;
        tempmat2[1][1] = scale.delta_y;
        tempmat2[2][2] = scale.delta_z;

        i_multmat3(tempmat3,tempmat2,tempmat1);

        i_identity3(tempmat2);
        tempmat2[0][3] = -ref.x;
        tempmat2[1][3] = -ref.y;
        tempmat2[2][3] = -ref.z;

        i_multmat3(tempmat1,tempmat2,mtx);


}

/*
 * i_buildtran(ref,xlate,rot,scale,mtx) build a 2d matrix
 */
void
i_buildtran(ref,xlate,rot,scale,mtx)
        Ppoint ref;		/* reference pt */ 
        Pvec xlate;		/* xlate factor */
        Pfloat rot;		/* rotation */
        Pvec scale;		/* scaling factor */ 
        Pmatrix mtx;		/* OUT matrix */
{
        Pmatrix tempmat1, tempmat2, tempmat3;

        i_identity(tempmat1);
        tempmat1[0][2] = ref.x + xlate.delta_x;
        tempmat1[1][2] = ref.y + xlate.delta_y;

        i_identity(tempmat2);
        tempmat2[0][0] = tempmat2[1][1] = cos(rot);
        tempmat2[0][1] = -sin(rot);
        tempmat2[1][0] = sin(rot);

        i_multmat(tempmat1,tempmat2,tempmat3);

        i_identity(tempmat2);
        tempmat2[0][0] = scale.delta_x;
        tempmat2[1][1] = scale.delta_y;

        i_multmat(tempmat3,tempmat2,tempmat1);

        i_identity(tempmat2);
        tempmat2[0][2] = -ref.x;
        tempmat2[1][2] = -ref.y;

        i_multmat(tempmat1,tempmat2,mtx);

} 
 
/*
 * i_composetran(mtx1,ref,xlate,angle,scale,mtx2)
 */
void
i_composetran(mtx1,ref,xlate,angle,scale,mtx2) 
	Pmatrix mtx1;		/* matrix */
        Ppoint ref;		/* reference pt */ 
        Pvec xlate;		/* xlate factor */
        Pfloat angle;		/* rotation */
        Pvec scale;		/* scaling factor */ 
	Pmatrix mtx2;		/* OUT matrix */
{
	Pmatrix mtx3;

	i_buildtran(ref,xlate,angle,scale,mtx3);
	i_multmat(mtx3,mtx1,mtx2);
}

/*
 * i_composetran3(mtx1,ref,xlate,xangle,yangle,zangle,scale,mtx2) 
 */
void
i_composetran3(mtx1,ref,xlate,xangle,yangle,zangle,scale,mtx2) 
	Pmatrix3 mtx1;		/* matrix */
        Ppoint3 ref;		/* reference pt */ 
        Pvec3 xlate;		/* xlate factor */
        Pfloat xangle;		/* x rotation */
        Pfloat yangle;		/* y rotation */
        Pfloat zangle;		/* z rotation */
        Pvec3 scale;		/* scaling factor */ 
	Pmatrix3 mtx2;		/* OUT matrix */
{
	Pmatrix3 mtx3;

	i_buildtran3(ref,xlate,xangle,yangle,zangle,scale,mtx3);
	i_multmat3(mtx3,mtx1,mtx2);
}

/*
 * i_composematrix(mtx1,mtx2,mtx3) compose two 2D matrix
 */
void
i_composematrix(mtx1,mtx2,mtx3)
	Pmatrix mtx1;		/* matrix */
	Pmatrix mtx2;		/* matrix */
	Pmatrix mtx3;		/* OUT matrix */
{
	i_multmat(mtx1,mtx2,mtx3);
}

/*
 * i_composematrix3(mtx1,mtx2,mtx3) compose two 3D matrix
 */
void
i_composematrix3(mtx1,mtx2,mtx3)
	Pmatrix3 mtx1;		/* matrix */
	Pmatrix3 mtx2;		/* matrix */
	Pmatrix3 mtx3;		/* OUT matrix */
{
	i_multmat3(mtx1,mtx2,mtx3);
}

/*
 * i_evalvieworientationmtx3(mapping,mtx) evaluate the 3D view mapping matrix
 */
void
i_evalvieworientationmtx3(vrp,vpn,vup,mtx)
	Ppoint3 vrp;		/* view reference point */
	Pvec3 vpn;		/* view plane normal */
	Pvec3 vup;		/* view up vector */
	Pmatrix3 mtx;		/* OUT matrix */
{
        Pvec3 v1, v2, v3;
        Pmatrix3 tempmat1, tempmat2;

        i_vectprod(&vup,&vpn,&v1);

        i_identity3(tempmat1);
        i_vectnorm3(&v1);
        tempmat1[0][0] = v1.delta_x;
        tempmat1[0][1] = v1.delta_y;
        tempmat1[0][2] = v1.delta_z;

        v3 = vpn;
        i_vectnorm3(&v3);
        tempmat1[2][0] = v3.delta_x;
        tempmat1[2][1] = v3.delta_y;
        tempmat1[2][2] = v3.delta_z;
 
        i_vectprod(&v3,&v1,&v2);
        tempmat1[1][0] = v2.delta_x;
        tempmat1[1][1] = v2.delta_y;
        tempmat1[1][2] = v2.delta_z;
 
        i_identity3(tempmat2);
        tempmat2[0][3] = -vrp.x;
        tempmat2[1][3] = -vrp.y;
        tempmat2[2][3] = -vrp.z;
 
        i_multmat3(tempmat1,tempmat2,mtx);
}

/*
 * i_evalvieworientationmtx(mapping,mtx) evaluate the 2D view mapping matrix
 */
void
i_evalvieworientationmtx(vrp,vup,mtx)
	Ppoint vrp;		/* view reference point */
	Pvec vup;		/* view up vector */
	Pmatrix mtx;		/* OUT matrix */
{
        Pvec v;
        Pmatrix tempmat1, tempmat2;
 
        v = vup;
        i_identity(tempmat1);
        i_vectnorm(&v);
 
        tempmat1[0][0] = v.delta_y;
        tempmat1[0][1] = -v.delta_x;
 
        tempmat1[1][0] = v.delta_x;
        tempmat1[1][1] = v.delta_y;
 
        i_identity(tempmat2);
        tempmat2[0][2] = -vrp.x;
        tempmat2[1][2] = -vrp.y;

        i_multmat(tempmat1,tempmat2,mtx);

}

/*
 * i_evalviewmappingmtx3(viewmap,mtx) evaluate the 3D view mapping matrix
 */
void
i_evalviewmappingmtx3(viewmap,mtx)
	Pview_map3 viewmap;	/* view mapping */
	Pmatrix3 mtx;		/* OUT matrix */
{
        Pmatrix3 tempmat1, tempmat2, tempmat3;
        Pfloat perp, perp1, scalex, scaley, shearx, sheary;

        if (viewmap.proj_type == PTYPE_PARAL) {
            i_identity3(tempmat1);
            tempmat1[0][3] = viewmap.proj_vp.x_min;
            tempmat1[1][3] = viewmap.proj_vp.y_min;
            tempmat1[2][3] = viewmap.proj_vp.z_max;

            i_identity3(tempmat2);
            tempmat2[0][0] = (viewmap.proj_vp.x_max - viewmap.proj_vp.x_min) / 
		(viewmap.win.x_max - viewmap.win.x_min);
            tempmat2[1][1] = (viewmap.proj_vp.y_max - viewmap.proj_vp.y_min) / 
		(viewmap.win.y_max - viewmap.win.y_min);
            if (feq(viewmap.front_plane,viewmap.back_plane))
                tempmat2[2][2] = 0.0;
            else
                tempmat2[2][2] = (viewmap.proj_vp.z_max-viewmap.proj_vp.z_min)/
		 (viewmap.front_plane - viewmap.back_plane);

            i_multmat3(tempmat1,tempmat2,tempmat3);

            i_identity3(tempmat1);
            tempmat1[0][3] = -viewmap.win.x_min;
            tempmat1[1][3] = -viewmap.win.y_min;
            tempmat1[2][3] = -viewmap.front_plane;
            i_multmat3(tempmat3,tempmat1,tempmat2);

            i_identity3(tempmat1);
            tempmat1[0][2] = (0.5 * (viewmap.win.x_min + viewmap.win.x_max)
		- viewmap.proj_ref_point.x) / (viewmap.proj_ref_point.z - viewmap.view_plane);
            tempmat1[1][2] = (0.5 * (viewmap.win.y_min + viewmap.win.y_max)
		- viewmap.proj_ref_point.y) / (viewmap.proj_ref_point.z - viewmap.view_plane);
	    tempmat1[0][3] = tempmat1[0][2] * -viewmap.view_plane;
            tempmat1[1][3] = tempmat1[1][2] * -viewmap.view_plane;
            i_multmat3(tempmat2,tempmat1,mtx);
        }
        else {
            /* Perspective projection */
            perp = -1.0 / (viewmap.back_plane - viewmap.proj_ref_point.z);
            shearx = (0.5 * (viewmap.win.x_max + viewmap.win.x_min) - 
		viewmap.proj_ref_point.x) / (viewmap.proj_ref_point.z - viewmap.view_plane);
            sheary = (0.5 * (viewmap.win.y_max + viewmap.win.y_min) - 
		viewmap.proj_ref_point.y) / (viewmap.proj_ref_point.z - viewmap.view_plane);
            scalex = 2.0 * perp * (viewmap.proj_ref_point.z - viewmap.view_plane) /
                     (viewmap.win.x_max - viewmap.win.x_min);
            scaley = 2.0 * perp * (viewmap.proj_ref_point.z - viewmap.view_plane) /
                     (viewmap.win.y_max - viewmap.win.y_min);

            i_identity3(mtx);
            mtx[0][0] = 0.5 * scalex * (viewmap.proj_vp.x_max - 
		viewmap.proj_vp.x_min);
            mtx[0][2] = 0.5 * (viewmap.proj_vp.x_max-viewmap.proj_vp.x_min) 
		* (scalex * shearx - perp) - perp * viewmap.proj_vp.x_min;
            mtx[0][3] = 0.5 * (viewmap.proj_vp.x_max - viewmap.proj_vp.x_min)
		* (perp * viewmap.proj_ref_point.z - scalex *
                (viewmap.proj_ref_point.x + shearx * viewmap.proj_ref_point.z)) +
                perp * viewmap.proj_ref_point.z * viewmap.proj_vp.x_min;
            mtx[1][1] = 0.5 * scaley * (viewmap.proj_vp.y_max - 
		viewmap.proj_vp.y_min);
            mtx[1][2] = 0.5 * (viewmap.proj_vp.y_max - viewmap.proj_vp.y_min)
		 * (scaley * sheary - perp) - perp * viewmap.proj_vp.y_min;
            mtx[1][3] = 0.5 * (viewmap.proj_vp.y_max - viewmap.proj_vp.y_min)		 * (perp * viewmap.proj_ref_point.z - scaley *
                 (viewmap.proj_ref_point.y + sheary * viewmap.proj_ref_point.z)) +
                 perp * viewmap.proj_ref_point.z * viewmap.proj_vp.y_min;
 
            perp1 = (viewmap.front_plane - viewmap.proj_ref_point.z) /
                    (viewmap.back_plane - viewmap.proj_ref_point.z);
            if (feq(perp1,1.0)) {
                mtx[2][2] = 0.0;
                mtx[2][3] = perp * viewmap.proj_ref_point.z * viewmap.proj_vp.z_max;
            }
            else {
                mtx[2][2]=perp*((viewmap.proj_vp.z_max-viewmap.proj_vp.z_min) /
			 (1.0 - perp1) - viewmap.proj_vp.z_max);
                mtx[2][3] = (-(viewmap.proj_vp.z_max - viewmap.proj_vp.z_min) /
                               (1.0 - perp1)) * (perp * viewmap.proj_ref_point.z - perp1)+
                               perp * viewmap.proj_ref_point.z * viewmap.proj_vp.z_max;
            }

            mtx[3][2] = -perp;
            mtx[3][3] = perp * viewmap.proj_ref_point.z;
        }
}

/*
 * i_evalviewmappingmtx(mapping,mtx) evaluate the 2D view mapping matrix
 */
void
i_evalviewmappingmtx(viewmap,mtx)
	Pview_map viewmap;	/* view mapping */
	Pmatrix mtx;		/* OUT matrix */
{
        Pmatrix tempmat1, tempmat2, tempmat3;

        i_identity(tempmat1);
        tempmat1[0][2] = viewmap.proj_vp.x_min;
        tempmat1[1][2] = viewmap.proj_vp.y_min;

        i_identity(tempmat2);
        tempmat2[0][0] = (viewmap.proj_vp.x_max - viewmap.proj_vp.x_min) /
                       (viewmap.win.x_max - viewmap.win.x_min);
        tempmat2[1][1] = (viewmap.proj_vp.y_max - viewmap.proj_vp.y_min) /
                       (viewmap.win.y_max - viewmap.win.y_min);
        i_multmat(tempmat1,tempmat2,tempmat3);
 
        i_identity(tempmat1);
        tempmat1[0][2] = -viewmap.win.x_min;
        tempmat1[1][2] = -viewmap.win.y_min;
        i_multmat(tempmat3,tempmat1,mtx);

}

/*
 * i_tranpt(point,matrix,oupt)
 */
void
i_tranpt(point,matrix,outpt)
	Ppoint point,*outpt;
	Pmatrix matrix;
{
        int i;
        float sum, mult;

        for (i = 0; i < 3; i++) {
                sum = 0.0;
                sum += matrix[i][0] * point.x;
                sum += matrix[i][1] * point.y;
                sum += matrix[i][2];
                switch (i) {
                        case 0:
                                outpt->x = sum;
                                break;
                        case 1:
                                outpt->y = sum;
                                break;
                        case 2:
                                mult = sum;
                                break;
                }
        }
        outpt->x = outpt->x / mult;
        outpt->y = outpt->y / mult;
}

/*
 * i_tranpt3(point,matrix,oupt)
 */
void
i_tranpt3(point,matrix,outpt)
	Ppoint3 point,*outpt;
	Pmatrix3 matrix;
{
        int i;
        float sum, mult;

        for (i = 0; i < 4; i++) {
                sum = 0.0;
                sum += matrix[i][0] * point.x;
                sum += matrix[i][1] * point.y;
                sum += matrix[i][2] * point.z;
                sum += matrix[i][3];
                switch (i) {
                        case 0:
                                outpt->x = sum;
                                break;
                        case 1:
                                outpt->y = sum;
                                break;
                        case 2:
                                outpt->z = sum;
                                break;
                        case 3:
                                mult = sum;
                                break;
                }
        }
        outpt->x = outpt->x / mult;
        outpt->y = outpt->y / mult;
        outpt->z = outpt->z / mult;
}


void
i_identity3(mat)
Pmatrix3 mat;
{
	int i,j;

	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
			mat[i][j] = 0.0;
	for (i = 0; i < 4; i++)
		mat[i][i] = 1.0;
}

void
i_identity(mat)
Pmatrix mat;
{
	int i,j;

	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++)
			mat[i][j] = 0.0;
	for (i = 0; i < 3; i++)
		mat[i][i] = 1.0;
}

static void
i_multmat3(mat1,mat2,mat3)
Pmatrix3 mat1, mat2, mat3;
{
	int i,j,k;
	Pfloat sum;

	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++) {
			sum = 0.0;
			for (k = 0; k < 4; k++) {
				sum += mat1[i][k] * mat2[k][j];
			}
			mat3[i][j] = sum;
		}
}

static void
i_multmat(mat1,mat2,mat3)
Pmatrix mat1, mat2, mat3;
{
	int i,j,k;
	Pfloat sum;

	for (i = 0; i < 3; i++)
		for (j = 0; j < 3; j++) {
			sum = 0.0;
			for (k = 0; k < 3; k++) {
				sum += mat1[i][k] * mat2[k][j];
			}
			mat3[i][j] = sum;
		}
}


static Pfloat
i_vectlen3(v)
Pvec3 v;
{
	return((Pfloat) sqrt(v.delta_x * v.delta_x + v.delta_y * 
		v.delta_y + v.delta_z * v.delta_z));
}

static Pfloat
i_vectlen(v)
Pvec v;
{
	return((Pfloat) sqrt(v.delta_x * v.delta_x + v.delta_y * v.delta_y));
}

static void
i_vectprod(v1,v2,v3)
Pvec3 *v1,*v2,*v3;
{
	v3->delta_x = v1->delta_y * v2->delta_z - v1->delta_z * v2->delta_y;
	v3->delta_y = v1->delta_z * v2->delta_x - v1->delta_x * v2->delta_z;
	v3->delta_z = v1->delta_x * v2->delta_y - v1->delta_y * v2->delta_x;
}

static void
i_vectnorm3(v)
Pvec3 *v;
{
	Pfloat len;

	len = i_vectlen3(*v);
	v->delta_x = v->delta_x / len;
	v->delta_y = v->delta_y / len;
	v->delta_z = v->delta_z / len;
}

static void
i_vectnorm(v)
Pvec *v;
{
	Pfloat len;

	len = i_vectlen(*v);
	v->delta_x = v->delta_x / len;
	v->delta_y = v->delta_y / len;
}


