/*
 *
 * VRML to RW converter plug-in
 */

/****************************************************************************
 * 
 * VRML 2.0 to RW3.0 Converter
 * Copyright (C) 1998 Criterion Technologies
 *
 * Author  : Damian Scallan 
 *
 * Module  : TextureTransform.c
 *                                                                         
 * Purpose : Who knows?
 *                                                                         
 ****************************************************************************/

/****************************************************************************
 Includes
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "rpplugin.h"
#include <rpdbgerr.h>
#include "rpvrmlanim.h"
#include "rpvrml.h"
#include "texturetransform.h"

static const char __RWUNUSED__ rcsid[] =
    "@@(#)$Id: texturetransform.c,v 1.25 2001/01/26 12:11:01 johns Exp $";

/****************************************************************************
 Local (static) Globals
 */

RwMatrix            GtextureTransform;

/****************************************************************************
 Local (Static) Prototypes
 */

static RwBool       TextureTransform_SetTranslation(sfvec2f * texCoord);
static RwBool       TextureTransform_SetRotation(sffloat angle);
static RwBool       TextureTransform_SetScale(sfvec2f * scale);

RwBool
TextureTransform_Convert(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("TextureTransform_Convert"));
    RWASSERT(an);

    if (an)
    {
        AbstractField      *af;
        char               *nodeName;

        nodeName = AbstractNode_GetBaseName(an);
        if (rwstrcmp(nodeName, RWSTRING("TextureTransform")) != 0)
        {
            RWASSERT(FALSE);
            RWRETURN(FALSE);
        }

        /* everything must be done is this order */

        if ((af =
             AbstractNode_GetAbstractField(an,
                                           RWSTRING("translation"))))
        {
            Field              *field;
            sfvec2f            *translation;

            field = AbstractField_GetField(af);
            translation = FieldSfvec2f_GetValue(field);
            if (!translation)
            {
                RWRETURN(FALSE);
            }
            TextureTransform_SetTranslation(translation);
        }

        if ((af =
             AbstractNode_GetAbstractField(an, RWSTRING("center"))))
        {
            Field              *field;
            sfvec2f            *center;

            field = AbstractField_GetField(af);
            center = FieldSfvec2f_GetValue(field);
            if (!center)
            {
                RWRETURN(FALSE);
            }
            TextureTransform_SetTranslation(center);
        }

        if ((af =
             AbstractNode_GetAbstractField(an, RWSTRING("rotation"))))
        {
            Field              *field;
            sffloat            *rotation;

            field = AbstractField_GetField(af);
            rotation = FieldSffloat_GetValue(field);
            if (!rotation)
            {
                RWRETURN(FALSE);
            }
            TextureTransform_SetRotation(*rotation);
        }

        if ((af = AbstractNode_GetAbstractField(an, RWSTRING("scale"))))
        {
            Field              *field;
            sfvec2f            *scale;

            field = AbstractField_GetField(af);
            scale = FieldSfvec2f_GetValue(field);
            if (!scale)
            {
                RWRETURN(FALSE);
            }
            TextureTransform_SetScale(scale);
        }

        if ((af =
             AbstractNode_GetAbstractField(an, RWSTRING("center"))))
        {
            Field              *field;
            sfvec2f            *center;

            field = AbstractField_GetField(af);
            center = FieldSfvec2f_GetValue(field);
            if (!center)
            {
                RWRETURN(FALSE);
            }
            center->x = -center->x;
            center->y = -center->y;
            TextureTransform_SetTranslation(center);
        }

        RWRETURN(TRUE);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(FALSE);
}

void
TextureTransform_Reset(void)
{
    RWFUNCTION(RWSTRING("TextureTransform_Reset"));

    RwMatrixSetIdentity(&GtextureTransform);

    RWRETURNVOID();
}

RwBool
TextureTransform_Apply(sfvec2f * outTexCoord, sfvec2f * inTexCoord)
{
    RWFUNCTION(RWSTRING("TextureTransform_Apply"));
    RWASSERT(outTexCoord);
    RWASSERT(inTexCoord);

    if (outTexCoord && inTexCoord)
    {
        RwV3d               texCoord3;

        texCoord3.x = inTexCoord->x;
        texCoord3.y = inTexCoord->y;
        texCoord3.z = (RwReal) (0);

        RwV3dTransformPoints(&texCoord3, &texCoord3, 1,
                             &GtextureTransform);

        outTexCoord->x = texCoord3.x;
        outTexCoord->y = texCoord3.y;

        RWRETURN(TRUE);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(FALSE);
}

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

   private Matrix methods

   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */

static              RwBool
TextureTransform_SetTranslation(sfvec2f * texCoord)
{
    RWFUNCTION(RWSTRING("TextureTransform_SetTranslation"));
    RWASSERT(texCoord);

    if (texCoord)
    {
        RwV3d               translation;

        translation.x = texCoord->x;
        translation.y = texCoord->y;
        translation.z = (RwReal) (0);

        RwMatrixTranslate(&GtextureTransform, &translation,
                          rwCOMBINEPRECONCAT);

        RWRETURN(TRUE);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(FALSE);
}

static              RwBool
TextureTransform_SetRotation(sffloat angle)
{
    RwV3d               axis =
        { (RwReal) (0), (RwReal) (0), (RwReal) (1) };
    RwReal              angleDeg =
        ((angle) * ((RwReal) (180.0 / rwPI)));

    RWFUNCTION(RWSTRING("TextureTransform_SetRotation"));

    RwMatrixRotate(&GtextureTransform, &axis, angleDeg,
                   rwCOMBINEPRECONCAT);

    RWRETURN(TRUE);
}

static              RwBool
TextureTransform_SetScale(sfvec2f * scale)
{
    RWFUNCTION(RWSTRING("TextureTransform_SetScale"));
    RWASSERT(scale);

    if (scale)
    {
        RwV3d               scale3;

        scale3.x = scale->x;
        scale3.y = scale->y;
        scale3.z = (RwReal) (1);

        RwMatrixScale(&GtextureTransform, &scale3, rwCOMBINEPRECONCAT);

        RWRETURN(TRUE);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(FALSE);
}
