/*---------------------------------------------------------------------------*
  Project:	NITRO-System - build - demos - g3d - samples - UnbindTex
  File:     main.c

  Copyright 2004,2005 Nintendo.  All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Log: main.c,v $
  Revision 1.11  02/25/2005 03:12:03  takano_makoto
  Warning measures for signed<->unsigned casts

  Revision 1.10  11/12/2004 05:40:32  nishida
  Revised project name of file header.

  Revision 1.9  11/04/2004 10:43:25  nishida
  Fixed function header of SetCamera function.

  Revision 1.8  09/10/2004 10:39:28  nishida_kenji
  rename NNS_G3dGlbFlush to NNS_G3dGlbFlushP.

  Revision 1.7  09/01/2004 04:31:14  nishida_kenji
  rename imd files.

  Revision 1.6  08/05/2004 00:12:36  nishida_kenji
  time NNS_G3dDraw only.

  Revision 1.5  08/03/2004 07:22:12  nishida_kenji
  Add instruction.

  Revision 1.4  07/28/2004 07:50:43  nishida_kenji
  revised

  Revision 1.3  2004/07/26 06:47:30  nakajima_souichi
  (none)

  Revision 1.2  2004/07/22 06:41:26  morimun
  (none)

  Revision 1.1  2004/07/22 02:02:24  morimun
  (none)

  $NoKeywords: $
 *---------------------------------------------------------------------------*/

//---------------------------------------------------------------------------
//
// Sample of texture removal and switching
//
// Removes texture from model and switches texture with a different model.
//
// Sample Operation
// Texture is attached to cubes and rectangular solids.
// A button -> Switches textures.
// B button -> Removes textures.
//
// HOWTO:
// * Associate model and texture with NNS_G3dBindMdlTex and NNS_G3dBindMdlPltt.
// * You can cancel the association of model and texture with NNS_G3dReleaseMdlTex
//   and NNS_G3dReleaseMdlPltt.
// * Associate the texture name specified in the model using NNS_G3dBindMdlTexEx and
//   NNS_G3dBindMdlPlttEx.
// * You can cancel the association to the texture name specified in model with
//   NNS_G3dReleaseMdlTexEx and NNS_G3dReleaseMdlPlttEx.
//
//---------------------------------------------------------------------------


#include "g3d_demolib.h"

G3DDemoCamera gCamera;        // Camera structure.
G3DDemoGround gGround;        // Ground structure.

static void          InitG3DLib(void);
static NNSG3dResTex* LoadG3DTexture(NNSG3dResFileHeader* resFile);
static void          SetCamera(G3DDemoCamera* camera);


/* -------------------------------------------------------------------------
  Name:         NitroMain

  Description:  Sample main.
                Removes texture using B, and switches texture using A.

  Arguments:    None.

  Returns:      None.
   ------------------------------------------------------------------------- */
void
NitroMain(void)
{
    
    BOOL changeTexture = TRUE;
    
    //for two models
    NNSG3dResFileHeader* resFileCube = NULL;
    NNSG3dResFileHeader* resFileBox  = NULL;
    
    NNSG3dRenderObj cubeObject;
    NNSG3dResMdl*   cubeModel = NULL;
    NNSG3dResTex*   cubeTexture = NULL;
    
    NNSG3dRenderObj boxObject;
    NNSG3dResMdl*   boxModel = NULL;
    NNSG3dResTex*   boxTexture = NULL;
    
    G3DDemo_InitSystem();
    G3DDemo_InitMemory();
    G3DDemo_InitVRAM();

    InitG3DLib();
    G3DDemo_InitDisplay();

    // Makes the manager able to manage 4 slots of texture image slots,
    // and sets to the default manager.
    NNS_GfdInitFrmTexVramManager(4, TRUE);

    // Makes the manager able to manage 32 KB of palettes,
    // and sets to the default manager.
    NNS_GfdInitFrmPlttVramManager(0x8000, TRUE);

    {
        //
        // Load Box Model and initialize.
        // Get the NNSG3dResMdl* and NNSG3dResTex* to use later.
        //
        resFileBox = G3DDemo_LoadFile("data/TextureBox.nsbmd");
        (void)NNS_G3dResDefaultSetup(resFileBox);

        SDK_ASSERTMSG(resFileBox, "load failed");
        boxModel = NNS_G3dGetMdlByIdx(NNS_G3dGetMdlSet(resFileBox), 0);
        SDK_NULL_ASSERT(boxModel);

        boxTexture = NNS_G3dGetTex(resFileBox);
    }

    {
        //
        // Load Cube Model and initialize.
        // Get the NNSG3dResMdl* and NNSG3dResTex* to use later.
        //
        resFileCube = G3DDemo_LoadFile("data/TextureCube.nsbmd");
        (void)NNS_G3dResDefaultSetup(resFileCube);

        SDK_ASSERTMSG(resFileCube, "load failed");
        cubeModel = NNS_G3dGetMdlByIdx(NNS_G3dGetMdlSet(resFileCube), 0);
        SDK_NULL_ASSERT(cubeModel);

        cubeTexture = NNS_G3dGetTex(resFileCube);
    }

    // G3D: NNSG3dRenderObj initialization
    //
    // NNSG3dRenderObj is a structure that holds every type of information relating to one model and
    // animation applied to that model.
    // The area specified by the internal member pointer must be obtained and released by the user.
    // Here mdl can be NULL. (It must be set during NNS_G3dDraw.)
    //
    NNS_G3dRenderObjInit(&cubeObject, cubeModel);
    NNS_G3dRenderObjInit(&boxObject, boxModel);

    G3DDemo_InitCamera(&gCamera, 10*FX32_ONE, 16*FX32_ONE);
    G3DDemo_InitGround(&gGround, (fx32)(1.5*FX32_ONE));

    G3DDemo_InitConsole();
    G3DDemo_Print(0,0, G3DDEMO_COLOR_YELLOW, "UNBINDTEX SAMPLE");

    for(;;)
    {
        OSTick time;

        //Texture switching using A
        //bind becomes invalid when there isn't one after release
        if(G3DDEMO_IS_PAD_TRIGGER(PAD_BUTTON_A)) 
        {
            // Substitutes a texture having the name same_name.
            // The model texture used in this sample is a direct texture,
            // so there is no need to substitute the palette.
            NNS_G3D_DEFRESNAME(texName, "same_name");
            (void)NNS_G3dReleaseMdlTexEx(boxModel, &texName.resName);
            (void)NNS_G3dReleaseMdlTexEx(cubeModel, &texName.resName);

            if (changeTexture)
            {
                //
                // Bind the texture of the other model.
                //
                (void)NNS_G3dBindMdlTexEx(boxModel, cubeTexture, &texName.resName);
                (void)NNS_G3dBindMdlTexEx(cubeModel, boxTexture, &texName.resName);
            }
            else
            {
                //
                // Bind the texture of your own model.
                //
                (void)NNS_G3dBindMdlTexEx(boxModel, boxTexture, &texName.resName);
                (void)NNS_G3dBindMdlTexEx(cubeModel, cubeTexture, &texName.resName);
            }
            changeTexture = (changeTexture) ? FALSE : TRUE;
        }                            
        else if (G3DDEMO_IS_PAD_TRIGGER(PAD_BUTTON_B)) // remove the texture with the B button
        {
            NNS_G3dReleaseMdlTex(boxModel);
            NNS_G3dReleaseMdlPltt(boxModel); // does nothing when there is no palette
            
            NNS_G3dReleaseMdlTex(cubeModel);
            NNS_G3dReleaseMdlPltt(cubeModel); // does nothing when there is no palette
        }

        SVC_WaitVBlankIntr();
        G3DDemo_PrintApplyToHW();
        G3DDemo_ReadGamePad();

        G3DDemo_MoveCamera(&gCamera);
        G3DDemo_CalcCamera(&gCamera);



        G3X_Reset();
        G3X_ResetMtxStack();

        SetCamera(&gCamera);

        time = OS_GetTick();
        {
            //drawing boxModel
            VecFx32 trans = {FX32_ONE<<2, FX32_ONE<<2, 0};
            NNS_G3dGlbSetBaseTrans(&trans);
            NNS_G3dGlbFlushP();
            NNS_G3dDraw(&boxObject);
        }

        {
            //drawing cubeModel
            VecFx32 trans = {-FX32_ONE<<2, FX32_ONE<<2, 0};
            NNS_G3dGlbSetBaseTrans(&trans);
            NNS_G3dGlbFlushP();
            NNS_G3dDraw(&cubeObject);
        }
        time = OS_GetTick() - time;

        {
            // Set Translation before drawing ground.
            VecFx32 trans = {0,0,0};
            NNS_G3dGlbSetBaseTrans(&trans);
        }
        
        //
        // G3D: Before calling normal G3_XXX, NNS_G3dGeComFlushBuffer()
        //      must be called and synchronized
        //
        NNS_G3dGlbFlushP();
        NNS_G3dGeFlushBuffer();
        G3DDemo_DrawGround(&gGround);

        /* memory swap relating to geometry and rendering engine*/
        G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);

        G3DDemo_Printf(16,0, G3DDEMO_COLOR_YELLOW, "TIME:%06d usec", OS_TicksToMicroSeconds(time));
        
        //information display
        G3DDemo_Printf(0,2, G3DDEMO_COLOR_GREEN, "change Texture:A");
        G3DDemo_Printf(0,3, G3DDEMO_COLOR_GREEN, "release Texture:B");
    }
}

/* -------------------------------------------------------------------------
  Name:         InitG3DLib

  Description:  Initializes G3D library.

  Arguments:    None.

  Returns:      None.
   ------------------------------------------------------------------------- */
static void
InitG3DLib(void)
{
    //
    // G3D:
    // performs default initialization
    // ------------------------------------------------------------------------
    NNS_G3dInit();
}


/* -------------------------------------------------------------------------
  Name:         SetCamera

  Description:  Sets camera matrix and projection matrix in G3D global state.

  Arguments:    camera:		pointer to the G3DDemoCamera structure

  Returns:      None.
   ------------------------------------------------------------------------- */
static void
SetCamera(G3DDemoCamera* camera)
{
    G3DDemoLookAt* lookat = &camera->lookat;
    G3DDemoPersp*  persp  = &camera->persp;

    NNS_G3dGlbPerspective(persp->fovySin, persp->fovyCos, persp->aspect, persp->nearClip, persp->farClip);
    NNS_G3dGlbLookAt(&lookat->camPos, &lookat->camUp, &lookat->target);
}

