/*---------------------------------------------------------------------------*
  Project:  NITRO-System - build - demos - g3d - samples - 1mat1shp
  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.7  02/25/2005 03:08:35  takano_makoto
  Warning measures for signed<->unsigned casts

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

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

  Revision 1.4  10/15/2004 09:52:15  nishida_kenji
  small fix.

  Revision 1.3  09/02/2004 06:56:49  nishida_kenji
  Draw many cubes.

  Revision 1.2  08/31/2004 05:11:40  nishida_kenji
  small fix

  Revision 1.1  08/17/2004 10:50:49  nishida_kenji
  Initial check in.

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

//---------------------------------------------------------------------------
//
// Displaying a very simple model at high speed
//
// The specified material ID and shape ID pair are rendered at high speed by using NNS_G3dDraw1Mat2Shp.
//  
//
// Sample Operation
// Pressing the A button switches between rendering using NNS_G3dDraw1MatShp and rendering using NNS_G3dDraw.
//  
//
// HOWTO:
// 1: Load model resource file  (.nsbmd file)  in main memory.
// 2: Perform default setup operation for resource loaded
//    with NNS_G3dResDefaultSetup function.
// 3: Use NNS_G3dGetMdISet and NNS_G3dGetMdIByldx to obtain the model to use from the model resource.
//     
// 4: Use the NNS_G3dGlbXXXX function to set such things as light direction and color,
//    projection matrix, camera matrix, and model base SRT.
// 5: Use NNS_G3dGlbFlush to send the values set in Step 5 to the geometry engine.
// 6: Use NNS_G3dDraw1Mat1Shp to draw a simple model at high speed.
//
//---------------------------------------------------------------------------

#include "g3d_demolib.h"

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

static void           InitG3DLib(void);
static NNSG3dResMdl*  LoadG3DModel(const char* path);
static void           SetCamera(G3DDemoCamera* camera);


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

  Description:  Sample main.

  Arguments:    None.

  Returns:      None.
 ------------------------------------------------------------------------- */
void
NitroMain(void)
{
    NNSG3dRenderObj object;
    NNSG3dResMdl*   pModel;
    void*           pResFile;
    BOOL            is1Mat1Shp = TRUE;

    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 model resource
        //
        pResFile = G3DDemo_LoadFile("data/cube_n_t.nsbmd");
        SDK_ASSERTMSG(pResFile, "load failed");

        //
        // calls the default initialization function and sets up
        //
        if (!NNS_G3dResDefaultSetup(pResFile))
        {
            NNS_G3D_ASSERTMSG(0, "NNS_G3dResDefaultSetup failed");
        }

        //
        // get index #0 model from model set in model resource
        //
        pModel = NNS_G3dGetMdlByIdx(NNS_G3dGetMdlSet(pResFile), 0);
        SDK_ASSERTMSG(pModel, "model not found");
    }

    //
    // G3D: NNSG3dRenderObj initialization
    //
    // It is not necessary for NNS_G3dDraw1Mat1Shp but this is used for comparing with normal drawing method.
    //
    NNS_G3dRenderObjInit(&object, pModel);

    G3DDemo_InitCamera(&gCamera, 0*FX32_ONE, 120*FX32_ONE);
    G3DDemo_InitGround(&gGround, (fx32)(1.5*FX32_ONE));

    G3DDemo_InitConsole();
    G3DDemo_Print(0,0, G3DDEMO_COLOR_YELLOW, "1MAT1SHP");

    for(;;)
    {
        OSTick time;

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

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

        G3X_Reset();
        G3X_ResetMtxStack();

        SetCamera(&gCamera);

        if (G3DDEMO_IS_PAD_TRIGGER(PAD_BUTTON_A))
        {
            is1Mat1Shp = is1Mat1Shp ? FALSE : TRUE;
        }
        if (is1Mat1Shp)
        {
            G3DDemo_Printf(0,1, G3DDEMO_COLOR_GREEN, "NNS_G3dDraw1Mat1Shp");
        }
        else
        {
            G3DDemo_Printf(0,1, G3DDEMO_COLOR_GREEN, "NNS_G3dDraw        ");
        }

        {
            //
            // G3D:
            // Collects and transfers the state set with G3dGlbXXXX.
            // Camera and projection matrix, and the like, are set.
            //
            NNS_G3dGlbFlush();

            time = OS_GetTick();
            {
                //
                // G3D: NNS_G3dDraw1Mat1Shp
                //
                // Drawing performed as material ID and shape ID specified by user.
                // Animations are not supported.
                // If the last argument is FALSE, the material transmission is omitted.
                // (However, by manipulating material of model resource,
                //  the material animation effect can be achieved.
                //  See model.h and ModifyNsbmd in the sample.)
                //
                int i, j;
                BOOL sendMaterial = TRUE;
                VecFx32 trans = {0, 0, 0};

                //
                // Arrange 200 boxes with texture.
                //
                for (i = 0; i < 20; ++i)
                {
                    trans.z = (i - 10) * FX32_ONE * 7;
                    for (j = 0; j < 10; ++j)
                    {
                        trans.x = (j - 5) * FX32_ONE * 7;

                        // Since this is a simple object, it is OK to set only the current matrix,
                        // without using NNS_G3dGlbFlush.
                        NNS_G3dGeLoadMtx43(&NNS_G3dGlb.cameraMtx);
                        NNS_G3dGeTranslateVec(&trans);

                        if (is1Mat1Shp)
                        {
                            // Material data after the 2nd frame is not sent to the geometry engine.
                            NNS_G3dDraw1Mat1Shp(pModel, 0, 0, sendMaterial);
                            sendMaterial = FALSE;
                        }
                        else
                        {
                            NNS_G3dDraw(&object);
                        }
                    }
                }
            }
            time = OS_GetTick() - time;
        }

        {
            VecFx32 trans = {0, 0, 0};
            NNS_G3dGlbSetBaseTrans(&trans);
            //
            // G3D: Before calling normal G3_XXX, NNS_G3dGeComFlushBuffer()
            //      must be called and synchronized
            //
            NNS_G3dGlbFlush();
            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));
    }
}


/* -------------------------------------------------------------------------
  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);
}

