/****************************************************************************
 * RAGE128 Chapter 6 Sample Code                                            *
 *                                                                          *
 * tritxstp.c - This program demonstrates how to draw a texture mapped      *
 * 3D triangle strip using CCE command packets.                             *
 *                                                                          *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.           *
 ****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <i86.h>
#include <conio.h>
#include "..\..\util\regdef.h"
#include "..\..\util\defines.h"
#include "..\..\util\main.h"
#include "..\..\util\cce.h"
#include "..\util\cntx3d.h"
#include "..\util\prim.h"
#include "..\util\texture.h"

#define NUM_TRIS 40
#define PI_X_2 6.28319f
#define TEX_FILE "..\\image\\wood.bmp"

char gErrMsg [64] = {0};

extern DWORD BPPOverride; // Override default 8bpp mode in Chap 3 lib.


/****************************************************************************
 * main                                                                     *
 *  Function: Main loop.                                                    *
 *    Inputs: none                                                          *
 *   Outputs: none                                                          *
 ****************************************************************************/

void main (int argc, char *argv[])
{
	int i, exitcode = 0;
    PRIMDATA tristrip;
    float centerx, centery, innerradius, outerradius, angle, deltaangle, 
		  sinval, cosval; 
    TEXINFO texinfo;

    printf ("Rage 128 Sample Code, Chapter 6.\n"
        "TRITXSTP.EXE\n\n"
        "This program demonstrates how to draw a texture mapped triangle strip using\n"
        "Rage 128 CCE command packets.\n\n"
        "Mode resolution (eg 640 480) and colour depth (15, 16, 32)\n"
        "should be passed as command line arguments.\n"
        "Default resolution and colour depth is 640x480, 32bpp.\n\n"
        "Press any key to continue.\n\n");

    getch ();

    // Inspect arguments for invalid color depth.

    for (i = 1; i < argc; i++)
    {
        if ((strcmp (argv[i], "8") == 0) || (strcmp (argv[i], "24") == 0))
		{
			printf ("\nThis program does not operate at 8 or 24 bpp.");
			printf ("\nProgram terminated.");
			exit (1);
		}
	}

    // Override default 8bpp mode in Chap 3 lib.

    BPPOverride = 32;

    // First, run StartUp function to set up the application.

    R128_StartUp (argc, argv);

    // Clear the screen.

    R128_ClearScreen (DARKBLUE);

    // Initialize the CCE microengine.

    if (R128_CCEInit (CCE_MODE_192BM) != CCE_SUCCESS)
    {
        R128_ShutDown ();
        printf ("R128_CCEInit failed!!\n");
        exit (1);
    } // if

	// Set the default 3D context.

    R128_Init3DContext ();

    // Create a triangle strip.

    tristrip.verts = (LPTLVERTEX2) malloc ((NUM_TRIS + 2) *
        sizeof (TLVERTEX2));
    if (tristrip.verts == NULL)
    {
        sprintf (gErrMsg, "tristrip malloc failed!!");
        exitcode = 1;
		goto exit_app;
    }
    tristrip.numverts = NUM_TRIS + 2;

    // Compute triangle position and size paramters.

	centerx = R128_AdapterInfo.xres/2.0f;
	centery = R128_AdapterInfo.yres/2.0f; 
	outerradius = (centery * 0.9f); 
	innerradius = (centery * 0.45f); 
	angle = 0.0f;
	deltaangle = PI_X_2/((float) NUM_TRIS/2.0f);

    // Set the perimiter vertices.

    for (i=0; i <= (NUM_TRIS/2); i++)
    {
		sinval = (float)sin ((double)angle);
		cosval = (float)cos ((double)angle);

        tristrip.verts[i*2].x = centerx + (sinval * innerradius);
        tristrip.verts[i*2].y = centery - (cosval * innerradius);
        tristrip.verts[i*2].z = 0.5f;
        tristrip.verts[i*2].rhw = 1.0f;
        tristrip.verts[i*2].diffuse = 0x00ffffff;
        tristrip.verts[i*2].specular = 0x00000000;
        tristrip.verts[i*2].s2 = tristrip.verts[i*2].s1 = 1.0f +
            (sinval * 0.5f);
        tristrip.verts[i*2].t2 = tristrip.verts[i*2].t1 = 1.0f +
            (cosval * 0.5f);

        tristrip.verts[(i*2)+1].x = centerx + (sinval * outerradius);
        tristrip.verts[(i*2)+1].y = centery - (cosval * outerradius);
        tristrip.verts[(i*2)+1].z = 0.5f;
        tristrip.verts[(i*2)+1].rhw = 1.0f;
        tristrip.verts[(i*2)+1].diffuse = 0x00808080;
        tristrip.verts[(i*2)+1].specular = 0x00000000;
        tristrip.verts[(i*2)+1].s2 = tristrip.verts[(i*2)+1].s1 = 1.0f +
            (sinval * 1.0f);
        tristrip.verts[(i*2)+1].t2 = tristrip.verts[(i*2)+1].t1 = 1.0f +
            (cosval * 1.0f);

		angle += deltaangle;
    }

	// Load the texture map.

	memset (&texinfo, 0, sizeof (texinfo));
    ATTEMPT (R128_LoadTextureBMP_ARGB8888 (TEX_FILE, &texinfo),
        "LoadTextureBMP failed!!")

	// Set the texture.

    ATTEMPT (R128_SetTexture (0, &texinfo), "SetTexture failed!!")

	// Enable texture mapping.

    ATTEMPT (R128_SetTextureState (0, TEXSTATE_ENABLE, TRUE),
        "enable texture failed!!")

	// Set the minification filtering mode.

    ATTEMPT (R128_SetTextureState (0, TEXSTATE_MINBLEND, 
		MINBLEND_BILINEAR), "set min blend failed!!")

	// Set the magnification filtering mode.

    ATTEMPT (R128_SetTextureState (0, TEXSTATE_MAGBLEND, 
		MAGBLEND_BILINEAR), "set mag blend failed!!")

    ATTEMPT (R128_SetTextureState (0, TEXSTATE_COMB_FNC, 
        TEXCOMBFNC_MODULATE), "set comb fnc failed!!")

    // Draw the triangle strip.

    ATTEMPT (R128_DrawTriangleStrip (&tristrip), 
        "DrawTriStrip failed!!")

	// Wait for key press to exit.

    getch ();

exit_app:

    // Free the vertex buffer.

	if (tristrip.verts)
		free (tristrip.verts);

    // Free the texture.

	if (texinfo.Offset[0])
		R128_FreeTexture (&texinfo);

	// Close 3D context, shut down micro-engine and restore original mode.

	R128_Close3DContext ();
    R128_CCEEnd (CCE_END_WAIT);
    R128_ShutDown ();

	// print error message if any.

	if (exitcode == 1)
		printf ("%s\n", gErrMsg);

	exit (exitcode);
} // main

