/*****************************************************************************
* Abstraction of the data been interpolated in rendering process.	     *
******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                *
******************************************************************************
* Written by:  Bassarab Dmitri & Plavnik Michael       Ver 0.2, Apr. 1995    *
*****************************************************************************/

#include "program.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Performs COPY operation on object of Interpol type, which contains data  M
*   to be interpolated during polygons scan converting. Interpol objects has M
*   some sort of linked structure, so copy is tricky.                        M
*                                                                            *
* PARAMETERS:                                                                M
*   Dst:      OUT, pointer to destination object.                            M
*   Src:      IN, pointer to source object.                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   InterpolStruct *:  pointer to destination object.                        M
*                                                                            *
* KEYWORDS:                                                                  M
*   InterpolCopy, Interpol structure, interpolation                          M
*****************************************************************************/
InterpolStruct *InterpolCopy(InterpolStruct *Dst, InterpolStruct *Src)
{
    IntensivityStruct
	*Keep = Dst -> i;

    *Dst = *Src;
    if (Dst -> i && Src -> i)
        memcpy(Dst -> i = Keep, Src -> i,
	       sizeof(IntensivityStruct) * Context.Lights.n);
    else
        Dst -> i = NULL;
    return Dst;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Initialize object of Interpol type to be an increment in interpolation   M
*   between first and second Interpol objects in scan conversion process.    M
*                                                                            *
* PARAMETERS:                                                                M
*   Dst:     OUT, pointer to delta(increment) object to be initialized.      M
*   v1:      IN, pointer to the first Interpol object.                       M
*   v2:      IN, pointer to the second Interpol object.                      M
*   d:       IN, scaling factor determined by dimension of the polygon on    M
*            the current scan line.                                          *
*                                                                            *
* RETURN VALUE:                                                              M
*   InterpolStruct *: pointer to dst object.                                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   InterpolDelta, Interpol, interpolation                                   M
*****************************************************************************/
InterpolStruct *InterpolDelta(InterpolStruct *Dst,
			      InterpolStruct *v1,
			      InterpolStruct *v2,
			      RealType d)
{
    int j;

    if (fabs(d) < IRIT_EPS)
        d = IRIT_EPS;

    Dst -> z = (v1 -> z - v2 -> z) / d;
    Dst -> w = (v1 -> w - v2 -> w) / d;
    Dst -> u = (v1 -> u - v2 -> u) / d;
    Dst -> v = (v1 -> v - v2 -> v) / d;
    PT_SUB(Dst -> n, v1 -> n, v2 -> n);
    PT_SCALE(Dst -> n, 1 / d);
    if (Dst -> i && v1 -> i && v2 -> i)
        for (j = 0; j < Context.Lights.n; ++j) {
            Dst -> i[j].diff = (v1 -> i[j].diff - v2 -> i[j].diff) / d;
            Dst -> i[j].spec = (v1 -> i[j].spec - v2 -> i[j].spec) / d;
    }
    else
        Dst -> i = NULL;
    return Dst;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Increments destination Interpol object by delta Interpol object computed M
*   by "InterpolDelta" call. By that way we progress interpolation process.  M
*                                                                            *
* PARAMETERS:                                                                M
*   Dst:     IN OUT, pointer to object to be incremented.                    M
*   d:       IN, pointer to delta object.                                    M
*                                                                            *
* RETURN VALUE:                                                              M
*   InterpolInterpol *: pointer to destination object.                       M
*                                                                            *
* KEYWORDS:                                                                  M
*   InterpolIncr, Interpol, interpolation                                    M
*****************************************************************************/
InterpolStruct *InterpolIncr(InterpolStruct *Dst, InterpolStruct *d)
{
    int j;

    Dst -> z += d -> z;
    Dst -> w += d -> w;
    Dst -> u += d -> u;
    Dst -> v += d -> v;
    PT_ADD(Dst -> n, Dst -> n, d -> n);
    if (Dst -> i && d -> i)
        for (j = 0; j < Context.Lights.n; ++j) {
            Dst -> i[j].diff += d -> i[j].diff;
            Dst -> i[j].spec += d -> i[j].spec;
        }
    return Dst;
}
