/*****************************************************************************
Name            :   ant.cpp
Title           :   Create and animate ant 
C Author        :   Stel Michael
Created         :   28 June 1993


Copyright       :   1992 by VideoLogic Limited. All rights reserved.
		    No part of this software, either material or conceptual
		    may be copied or distributed, transmitted, transcribed,
		    stored in a retrieval system or translated into any
		    human or computer language in any form by any means,
		    electronic, mechanical, manual or other-wise, or
		    disclosed to third parties without the express written
		    permission of VideoLogic Limited, HomePark Estate,
		    King's Langley, Hertfordshire, WD4 8LZ, U.K.

Description     :   Functions and data for the creation and animation
					of the giant ants
						   .
Program Type    :   Microsoft Visual C++ V2	  
*****************************************************************************/

#define Cplusplus 
#define PI	3.14159265359f

#include <stdlib.h>
#include <windows.h>
#include "sgl.h"
#include "sclist.h" 
#include "actor.h"  
#include "obtypes.h"
#include <time.h>    
#include <math.h>
#include "ant.h"
#include "effects.h"

extern int camera7;

extern void	sgl_simple_plane2(sgl_vector a,sgl_vector b,sgl_vector c,sgl_bool visible);

extern void	sgl_texture_plane( int texName, float a[3], float b[3], float c[3], int visible, 
					float xScale, float yScale, sgl_bool FirstPlane);

extern void	sgl_texture_plane_glow( int texName, float a[3], float b[3], float c[3], int visible, 
					float xScale, float yScale, sgl_bool FirstPlane);

extern int cpan1Tex,cpan2Tex,cpan3Tex,pan1Tex,pan3Tex,thrustTex;

extern void get3pts(int noplanes, sgl_vector* reppt, sgl_vector* normal, sgl_vector* pt, sgl_bool inter_check);

extern int cpan3Tex,fireTex;

static sgl_colour white	= {1.0f,1.0f,1.0f};
static sgl_colour black	= {0.0f,0.0f,0.0f};
	
extern Effect Explosion;
extern Effect Explosion2;

/* Ant body parts */
static float	ant_body[3] = {0.2f,0.1f,0.0f};
static float	ant_body_shin[3] = {1.0f,1.0f,1.0f};
static float	ant_eye_l[3] = {5.0f,0.1f,0.0f};

/* Ant body part offsets */
static float	tail_off[3] = {0.0f,0.0f,-50.0f};
static float	chest_off[3] = {0.0f,0.0f,100.0f};
static float	neck_off[3] = {0.0f,0.0f,50.0f};
static float	head_off[3] = {0.0f,0.0f,60.0f};
static float	jaw_off[3] = {5.0f,-8.0f,130.0f};
static float	eye_off[3] = {45.0f,5.0f,82.0f};
static float	hip_off[3][3] =	{ 	
									30.0f,0.0f,-50.0f, 
									30.0f,0.0f,50.0f, 
									30.0f,0.0f,50.0f
								};
static float	knee_off[3] = {160.0f,0.0f,0.0f };

/* Starting y angles of all six legs */

static float	start_y[6]= {
								-HIP_Y_LIMIT/4,
								HIP_Y_LIMIT/4,
								-HIP_Y_LIMIT/2,
								HIP_Y_LIMIT/2,
								-HIP_Y_LIMIT,
								HIP_Y_LIMIT,
							};


/******************************************************************
* Function Names	: void Add_ant_base()
*					: void Add_ant_thigh()
*					: void Add_ant_foot()
*					: void Add_ant_tail()
*					: void Add_ant_neck()
*					: void	Add_ant_head()
*					: void Add_ant_jaw()
* Inputs			: none
* Outputs			: none
* Returns			: void
* Description		: Add different parts of ant to the display list 
******************************************************************/

void Add_ant_base()
{
	int		i;
	
	float	r_points[14][3]	=	{
									0.0f,0.0f,60.0f,
									0.0f,0.0f,-60.0f,

									0.0f,10.0f,60.0f,
									0.0f,-10.0f,60.0f,
									0.0f,10.0f,-60.0f,
									0.0f,-10.0f,-60.0f,

									40.0f,0.0f,60.0f,
									40.0f,0.0f,60.0f,
									-40.0f,0.0f,60.0f,
									-40.0f,0.0f,60.0f,
									40.0f,0.0f,-60.0f,
									40.0f,0.0f,-60.0f,
									-40.0f,0.0f,-60.0f,
									-40.0f,0.0f,-60.0f

								};

	float	normals[14][3] = 	{
									0.0f,0.0f,1.0f,
									0.0f,0.0f,-1.0f,

									0.0f,3.0f,1.0f,
									0.0f,-3.0f,1.0f,
									0.0f,3.0f,-1.0f,
									0.0f,-3.0f,-1.0f,
									1.0f,1.0f,0.5f,
									1.0f,-1.0f,0.5f,
									-1.0f,1.0f,0.5f,
									-1.0f,-1.0f,0.5f,
									1.0f,1.0f,-0.5f,
									1.0f,-1.0f,-0.5f,
									-1.0f,1.0f,-0.5f,
									-1.0f,-1.0f,-0.5f
								};

	sgl_vector pt[14*3];
	
	sgl_create_transform(FALSE);
	sgl_rotate(sgl_z_axis,PI/2.0f);

	sgl_create_material(FALSE,TRUE);	
    sgl_set_omap (sgl_omap_inter_normal, 0.0f);
    sgl_set_smap ( sgl_smap_sphere, 0.1f,0.1f,0.0f,0.0f,400.0f);
    sgl_set_diffuse(white);
	sgl_set_texture_effect(TRUE,TRUE,TRUE,FALSE);
	sgl_set_specular(white,1);
	sgl_set_texture_map(fireTex,FALSE,FALSE);

	sgl_rotate(sgl_z_axis,-PI/2.0f);
	  
	get3pts(14, r_points, normals, pt, TRUE);
		
	sgl_add_plane (r_points[0], pt[1], pt[2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);

	for (i=1;i<14;i++)
   	    sgl_add_plane (r_points[i], pt[i*3+1], pt[i*3+2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);
}


void Add_ant_thigh()
{			  
	int		i;
	
	float	r_points[6][3]	= 	{
								  	-5.0f,0.0f,0.0f,
									160.0f,0.0f,0.0f,
									0.0f,5.0f,0.0f,
									0.0f,-5.0f,0.0f,
									0.0f,0.0f,5.0f,
									0.0f,0.0f,-5.0f	
								};

	float	normals[6][3] = 	{
									-1.0f,0.0f,0.0f,
								 	1.0f,0.0f,0.0f,
								 	0.0f,1.0f,0.0f,
									0.0f,-1.0f,0.0f,
									0.0f,0.0f,1.0f,
									0.0f,0.0f,-1.0f
							 	};

	sgl_vector pt[6*3];

	sgl_create_transform(FALSE);
	sgl_rotate(sgl_z_axis,PI/2.0f);

	sgl_create_material(FALSE,TRUE);	
    sgl_set_omap (sgl_omap_inter_normal, 0.0f);
	sgl_set_smap ( sgl_smap_sphere, 0.4f,0.3f,0.0f,0.0f,200.0f);
	sgl_set_diffuse(white);
	sgl_set_texture_effect(TRUE,TRUE,TRUE,FALSE);
	sgl_set_specular(white,1);
	sgl_set_texture_map(fireTex,FALSE,FALSE);

	sgl_rotate(sgl_z_axis,-PI/2.0f);

	get3pts(6, r_points, normals, pt, TRUE);

	sgl_create_convex (FALSE);
    sgl_add_plane (pt[2],r_points[0],pt[1] ,  FALSE, NULL,NULL,NULL, NULL,NULL,NULL);

	for (i=1;i<6;i++)
  	    sgl_add_plane (r_points[i], pt[i*3+1], pt[i*3+2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);
}


void Add_ant_foot()
{	
	int		i;
	
	float	r_points[5][3]	= 	{
									0.0f,0.0f,0.0f,
									0.0f,15.0f,0.0f,
									0.0f,-15.0f,0.0f,
									0.0f,0.0f,15.0f,
									0.0f,0.0f,-15.0f
								};

	float	normals[5][3] = 	{
									1.0f,0.0f,0.0f,
								 	-0.5f,1.0f,0.0f,
								 	-0.5f,-1.0f,0.0f,
									-0.5f,0.0f,1.0f,
									-0.5f,0.0f,-1.0f,
							 	};
		
	sgl_vector pt[5*3];

	sgl_create_material(FALSE,TRUE);	
	sgl_set_omap (sgl_omap_obj_normal, 0.0f);
	sgl_set_smap ( sgl_smap_sphere, 0.25f,0.25f,0.0f,0.0f,30.0f);
	sgl_set_diffuse(white);
   	sgl_set_texture_effect(TRUE,TRUE,TRUE,FALSE);
	sgl_set_specular(white,1);
	sgl_set_texture_map(fireTex,FALSE,FALSE);

	get3pts(5, r_points, normals, pt, TRUE);

	sgl_create_convex (FALSE);

    sgl_add_plane (r_points[0], pt[1], pt[2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);

	for (i=1;i<5;i++)
  	    sgl_add_plane (r_points[i], pt[i*3+1], pt[i*3+2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);
}  
 

void Add_ant_tail()
{	
	int		i;	

	float	r_points[13][3]	=	{
									0.0f,0.0f,1.0f,
									0.0f,20.0f,10.0f,
									0.0f,-20.0f,10.0f,
									0.0f,30.0f,-130.0f,
									0.0f,-30.0f,-130.0f,
									40.0f,0.0f,50.0f,
									40.0f,0.0f,50.0f,
									-40.0f,0.0f,50.0f,
									-40.0f,0.0f,50.0f,
									40.0f,0.0f,-150.0f,
									40.0f,0.0f,-150.0f,
									-40.0f,0.0f,-150.0f,
									-40.0f,0.0f,-150.0f
								};

	float	normals[13][3] = 	{
									0.0f,0.0f,1.0f,
									0.0f,3.0f,1.0f,
  									0.0f,-3.0f,1.0f,
									0.0f,3.0f,-1.0f,
									0.0f,-3.0f,-1.0f,
									1.0f,1.0f,0.5f,
									1.0f,-1.0f,0.5f,
									-1.0f,1.0f,0.5f,
									-1.0f,-1.0f,0.5f,
									1.0f,1.0f,-0.5f,
									1.0f,-1.0f,-0.5f,
									-1.0f,1.0f,-0.5f,
									-1.0f,-1.0f,-0.5f
								};

	sgl_vector pt[13*3];
	
	sgl_create_transform(FALSE);
   	sgl_rotate(sgl_z_axis,PI/2.0f);
		
	sgl_create_material(FALSE,TRUE);	
	sgl_set_omap (sgl_omap_obj_normal, 0.0f);
    sgl_set_smap ( sgl_smap_sphere, 0.025f,0.025f,0.0f,0.0f,400.0f);

	sgl_rotate(sgl_z_axis,-PI/2.0f);

	sgl_set_diffuse(white);
	sgl_set_texture_effect(TRUE,TRUE,TRUE,FALSE);
	sgl_set_specular(white,1);
	sgl_set_texture_map(fireTex,FALSE,FALSE);
	
	get3pts(13, r_points, normals, pt, TRUE);

	sgl_create_convex (FALSE);

    sgl_add_plane (r_points[0], pt[1], pt[2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);

	for (i=1;i<13;i++)
		sgl_add_plane (r_points[i], pt[i*3+1], pt[i*3+2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);
}


void Add_ant_neck()
{	
	int		i;

	float	r_points[8][3]	= 	{
									0.0f,10.0f,0.0f,
									0.0f,-10.0f,0.0f,
									0.0f,0.0f,-10.0f,
									0.0f,0.0f,60.0f,
									30.0f,0.0f,0.0f,
									30.0f,0.0f,0.0f,
									-30.0f,0.0f,0.0f,
									-30.0f,0.0f,0.0f
								};

	float	normals[8][3] = 	{
									0.0f,1.0f,0.0f,
									0.0f,-1.0f,0.0f,
									0.0f,0.0f,-1.0f,
									0.0f,0.0f,1.0f,
									1.0f,1.0f,0.0f,
									1.0f,-1.0f,0.0f,
									-1.0f,1.0f,0.0f,
									-1.0f,-1.0f,0.0f
							 	};
	
	sgl_vector pt[8*3];
		
	get3pts(8, r_points, normals, pt, FALSE);
 
 	sgl_create_transform(FALSE);
	sgl_rotate(sgl_z_axis,PI/2.0f);
			
	sgl_create_material(FALSE,TRUE);	
 	sgl_set_omap (sgl_omap_obj_normal, 0.0f);
   	sgl_set_smap ( sgl_smap_sphere, 0.025f,0.025f,0.0f,0.0f,400.0f);

	sgl_rotate(sgl_z_axis,-PI/2.0f);

 	sgl_set_diffuse(white);
	sgl_set_texture_effect(TRUE,TRUE,TRUE,FALSE);
	sgl_set_specular(white,1);
	sgl_set_texture_map(fireTex,FALSE,FALSE);


	sgl_create_convex (FALSE);

    sgl_add_plane (r_points[0], pt[1], pt[2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);

	for (i=1;i<8;i++)
 	    sgl_add_plane (r_points[i], pt[i*3+1], pt[i*3+2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);
}


void Add_ant_head()
{		
	int		i;

	float	r_points[15][3]	= 	{
									0.0f,10.0f,0.0f,
									0.0f,-10.0f,0.0f,
									0.0f,0.0f,-10.0f,
									0.0f,0.0f,140.0f,
									30.0f,0.0f,-10.0f,
									30.0f,0.0f,-10.0f,
									-30.0f,0.0f,-10.0f,
									-30.0f,0.0f,-10.0f,
									0.0f,15.0f,0.0f,
									0.0f,-15.0f,0.0f,
									0.0f,0.0f,140.0f,
									30.0f,0.0f,140.0f,
									-30.0f,0.0f,140.0f,
									20.0f,0.0f,140.0f,	 // eye_face x+	
									-20.0f,0.0f,140.0f	 // eye_face x-
								};

	float	normals[15][3] = 	{
									0.0f,6.0f,-1.0f,
									0.0f,-6.0f,-1.0f,
									0.0f,0.0f,-1.0f,
									0.0f,1.0f,1.0f,
									1.0f,1.0f,-0.5f,
									1.0f,-1.0f,-0.5f,
									-1.0f,1.0f,-0.5f,
									-1.0f,-1.0f,-0.5f,
									0.0f,1.0f,0.0f,
									0.0f,-1.0f,0.0f,
									0.0f,5.0f,1.0f,
									2.0f,0.0f,1.0f,
									-2.0f,0.0f,1.0f,
									3.0f,6.0f,2.0f,
									-3.0f,6.0f,2.0f
							 	};

	sgl_vector pt[15*3];
	
	sgl_create_transform(FALSE);
	sgl_rotate(sgl_z_axis,PI/2.0f);

	sgl_create_material(FALSE,TRUE);	
	sgl_set_omap (sgl_omap_obj_normal, 0.0f);
	sgl_set_smap ( sgl_smap_sphere, 0.025f,0.025f,0.0f,0.0f,1000.0f);
	sgl_set_diffuse(white);
  	sgl_set_texture_effect(TRUE,TRUE,TRUE,FALSE);
   	sgl_set_specular(white,1);
	sgl_set_texture_map(fireTex,FALSE,FALSE);

	sgl_rotate(sgl_z_axis,-PI/2.0f);

	get3pts(15, r_points, normals, pt, TRUE);

    sgl_add_plane (r_points[0], pt[1], pt[2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);

	for (i=1;i<15;i++)
 	    sgl_add_plane (r_points[i], pt[i*3+1], pt[i*3+2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);
}


void Add_ant_jaw()
{			 
	int		i;

	float	r_points[5][3]	=	{
									0.0f,4.0f,0.0f,
									0.0f,-4.0f,0.0f,
									0.0f,0.0f,0.0f,
									0.0f,0.0f,0.0f,
									0.0f,0.0f,70.0f,
								};

	float	normals[5][3] = 	{
									0.0f,1.0f,0.0f,
									0.0f,-1.0f,0.0f,
									-1.0f,0.0f,0.0f,
									2.0f,0.0f,-1.0f,
									1.5f,0.0f,1.0f,
							 	};


	sgl_vector pt[5*3];
		
	get3pts(5, r_points, normals, pt, TRUE);

    sgl_add_plane (r_points[0], pt[1], pt[2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);
		 
	for (i=1;i<5;i++)
  	    sgl_add_plane (r_points[i], pt[i*3+1], pt[i*3+2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);  
}


void Add_ant_eye()
{			
	int		i;

	float	r_points[10][3]	= 	{
									0.0f,0.0f,0.0f,
									0.0f,10.0f,0.0f,

									0.0f,20.0f,0.0f,
									0.0f,20.0f,0.0f,
									0.0f,20.0f,0.0f,
									0.0f,20.0f,0.0f,

									0.0f,20.0f,0.0f,
									0.0f,20.0f,0.0f,
									0.0f,20.0f,0.0f,
									0.0f,20.0f,0.0f
								};

	float	normals[10][3] = 	{
									0.0f,-1.0f,0.0f,
									0.0f,1.0f,0.0f,

									1.0f,0.5f,0.0f,
									-1.0f,0.5f,0.0f,
									0.0f,1.0f,1.0f,
									0.0f,1.0f,-1.0f,

									1.0f,2.5f,1.0f,
									1.0f,2.5f,-1.0f,
									-1.0f,2.5f,1.0f,
									-1.0f,2.5f,-1.0f
								};


	sgl_vector pt[10*3];
		
	get3pts(10, r_points, normals, pt, TRUE);

	sgl_create_convex (FALSE); 
	sgl_add_plane (r_points[0], pt[1], pt[2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);

	for (i=1;i<10;i++)

 	    sgl_add_plane (r_points[i], pt[i*3+1], pt[i*3+2], FALSE, NULL,NULL,NULL, NULL,NULL,NULL);
}


/*****************************************************************
* Function Name		: Create_Ant    
* Inputs			: pos - starting position of ant in 3d space
*				  	  orient - stating orientation of ant in 3d 
*					  space
*					: ativate - distance from dome before becoming active
* Output			: none
* Returns			: Ant specification
* Description		: Creates an instance of the ant data structure
*					  and adds all the ant's body parts to the
*					  display list
******************************************************************/

gi_ant*	Create_Ant( float pos[3], float	orient[3],float	activate)
{
	int i,l;
	gi_ant *a_ptr;

	if ( (a_ptr=(gi_ant far *) malloc(sizeof(gi_ant)) )!=NULL)
	{
		/* base is at the top of the group hierarchy */
		a_ptr->id = sgl_create_list(TRUE,TRUE,FALSE);
		a_ptr->status=WALKING;
		a_ptr->body_transform[BASE]=sgl_create_transform(TRUE);
		a_ptr->mandible_ang=0.0f;
		a_ptr->velocity=0.8f;
        a_ptr->activate_dis=activate;
              
		for (i=0;i<3;i++)
		{
			a_ptr->pos[i]=pos[i];
			a_ptr->orient[i]=orient[i];
		}
     
		Add_ant_base(); 
		 																			
		sgl_create_list(FALSE,TRUE,FALSE);
			sgl_translate(tail_off[0],tail_off[1],tail_off[2]);
			a_ptr->body_transform[TAIL]=sgl_create_transform(TRUE);
			Add_ant_tail();
		sgl_to_parent();

		for (l=0;l<2;l++)
 		{
			/* Add back two left legs to display list */

			sgl_create_list(FALSE,TRUE,FALSE);
				sgl_translate(hip_off[l][0],hip_off[l][1],hip_off[l][2]);
				a_ptr->left_legs[l].status=ONGROUND;
				a_ptr->left_legs[l].thigh_y=start_y[l];
				a_ptr->left_legs[l].hip_transform=sgl_create_transform(TRUE);
				Add_ant_thigh();

				sgl_create_list(FALSE,TRUE,FALSE);
					sgl_translate(knee_off[0],knee_off[1],knee_off[2]);
					sgl_rotate(sgl_z_axis, -PI/2);
					a_ptr->left_legs[l].knee_transform=sgl_create_transform(TRUE);
					Add_ant_thigh();
					sgl_translate(knee_off[0],knee_off[1],knee_off[2]);
					Add_ant_foot();
				sgl_to_parent();

		  	sgl_to_parent();

			/* Add back two right legs to display list */

		  	sgl_create_list(FALSE,TRUE,FALSE);
				sgl_translate(-hip_off[l][0],hip_off[l][1],hip_off[l][2]);
				sgl_scale(-1.0f,1.0f,1.0f);
				a_ptr->right_legs[l].status=ONGROUND;
				a_ptr->right_legs[l].thigh_y=start_y[l+3];   
				a_ptr->right_legs[l].hip_transform=sgl_create_transform(TRUE);
				Add_ant_thigh();

				sgl_create_list(FALSE,TRUE,FALSE);
					sgl_translate(knee_off[0],knee_off[1],knee_off[2]);
					sgl_rotate(sgl_z_axis,-PI/2);
					a_ptr->right_legs[l].knee_transform=sgl_create_transform(TRUE);
					Add_ant_thigh();
					sgl_translate(knee_off[0],knee_off[1],knee_off[2]);
					Add_ant_foot();
				sgl_to_parent();

		   sgl_to_parent();
		}

		/* chest is root group for upper body including two front legs */

		sgl_create_list(FALSE,TRUE,FALSE);
			sgl_translate(chest_off[0],chest_off[1],chest_off[2]);
			a_ptr->body_transform[CHEST]=sgl_create_transform(TRUE);
			Add_ant_base();

			/* Add front left leg to display list */

			sgl_create_list(FALSE,TRUE,FALSE);
				sgl_translate(hip_off[2][0],hip_off[2][1],hip_off[2][2]);
				a_ptr->left_legs[2].status=ONGROUND;
				a_ptr->left_legs[2].thigh_y=start_y[2]; 
				a_ptr->left_legs[2].hip_transform=sgl_create_transform(TRUE);
				Add_ant_thigh();

				sgl_create_list(FALSE,TRUE,FALSE);
					sgl_translate(knee_off[0],knee_off[1],knee_off[2]);
					sgl_rotate(sgl_z_axis, -PI/2);
					a_ptr->left_legs[2].knee_transform=sgl_create_transform(TRUE);
					Add_ant_thigh();
					sgl_translate(knee_off[0],knee_off[1],knee_off[2]);
					Add_ant_foot();
				sgl_to_parent();

			sgl_to_parent();
	
			/* Add front right leg to display list */

		   	sgl_create_list(FALSE,TRUE,FALSE);
				sgl_translate(-hip_off[2][0],hip_off[2][1],hip_off[2][2]);
				sgl_scale(-1.0f,1.0f,1.0f);
				a_ptr->right_legs[2].status=ONGROUND;
				a_ptr->right_legs[2].thigh_y=start_y[5];
				a_ptr->right_legs[2].hip_transform=sgl_create_transform(TRUE);
				Add_ant_thigh();

					sgl_create_list(FALSE,TRUE,FALSE);
					sgl_translate(knee_off[0],knee_off[1],knee_off[2]);
					sgl_rotate(sgl_z_axis, -PI/2);
					a_ptr->right_legs[2].knee_transform=sgl_create_transform(TRUE);
					Add_ant_thigh();
					sgl_translate(knee_off[0],knee_off[1],knee_off[2]);
					Add_ant_foot();
				sgl_to_parent();

			sgl_to_parent();

			/* Add neck and head to display group */

	  		sgl_create_list(FALSE,TRUE,FALSE);
				sgl_translate(neck_off[0],neck_off[1],neck_off[2]);
				a_ptr->body_transform[NECK]=sgl_create_transform(TRUE);
				Add_ant_neck();

				sgl_create_list(FALSE,TRUE,FALSE);
					sgl_translate(head_off[0],head_off[1],head_off[2]);
					a_ptr->body_transform[HEAD]=sgl_create_transform(TRUE);
					Add_ant_head();
			    
					sgl_create_list(FALSE,TRUE,FALSE);
						sgl_translate(eye_off[0],eye_off[1],eye_off[2]);
						sgl_set_diffuse(ant_eye_l);
						sgl_set_glow(ant_eye_l);
						sgl_scale(1.5f,1.0f,3.0f);
						sgl_rotate(sgl_y_axis, -PI/3);
						sgl_rotate(sgl_z_axis, -PI/6);
						Add_ant_eye();
				   	sgl_to_parent();
                
					sgl_create_list(FALSE,TRUE,FALSE);
						sgl_translate(-eye_off[0],eye_off[1],eye_off[2]);
						sgl_set_diffuse(ant_eye_l);
						sgl_set_glow(ant_eye_l);
						sgl_scale(1.5f,1.0f,3.0f);
						sgl_rotate(sgl_y_axis, PI/3);
						sgl_rotate(sgl_z_axis, PI/6);
						Add_ant_eye();
					sgl_to_parent();
               
					sgl_create_list(FALSE,TRUE,FALSE);
						sgl_translate(jaw_off[0],jaw_off[1],jaw_off[2]);
						a_ptr->body_transform[JAWA]=sgl_create_transform(TRUE);
						Add_ant_jaw();
					sgl_to_parent();
		  

	  				sgl_create_list(FALSE,TRUE,FALSE);				
						sgl_translate(-jaw_off[0],jaw_off[1],jaw_off[2]);
						sgl_scale(-1.0f,1.0f,1.0f);
						a_ptr->body_transform[JAWB]=sgl_create_transform(TRUE);
						Add_ant_jaw();
					sgl_to_parent();
			 
					sgl_create_transform(FALSE);
					sgl_translate(0.0f,80.0f,-720.0f);

					camera7 = sgl_create_camera(2.0f,10.0f,0.0f);

				sgl_to_parent();

			sgl_to_parent();

		sgl_to_parent(); // end of chest group
    
	sgl_to_parent(); // end of entire ant group
	}
	return (a_ptr);
}


/*****************************************************************
* Function Name		: Adjust_Direction    
* Inputs			: a_ptr - pointer to instance of gi_ant 
*					  structure
*				  	  pos - position of craft in 3d space
*				  	  ant - unused
* Outputs			: none
* Returns			: void
* Description		: Modifies direction of ant 
******************************************************************/

void Adjust_Direction(gi_ant *a_ptr,float pos[3], int ant)
{
	int		i;

    float 	magxz;

	float	craft_dis,craft_dir[3];
                 
	float	Dx,Dz;                
                    
	float	ang_diff,dp;
                     
    float	z1,x1,z2,x2,a,b,d;
                     
	/* find direction of craft relative to ant */
	
	for  (i=0;i<3;i++)
		craft_dir[i] = pos[i]-(a_ptr->pos[i]);
                                                                   
	craft_dis = (float) sqrt(craft_dir[0]*craft_dir[0]+craft_dir[1]*craft_dir[1]+craft_dir[2]*craft_dir[2]);

	/* calculate angle in xz plane between ant's direction and 
	   craft's position	*/
                                                
    z1 = (float) cos(a_ptr->orient[1])+a_ptr->pos[2];
    x1 = (float) sin(a_ptr->orient[1])+a_ptr->pos[0];
    
    z2 = a_ptr->pos[2];
    x2 = a_ptr->pos[0];
    
    a = pos[2];
    b = pos[0];
    
    d = ((x2-x1)*a) - ((z2-z1)*b)+z2*x1-z1*x2;                         

    magxz =(float)  sqrt(craft_dir[0]*craft_dir[0]+craft_dir[2]*craft_dir[2]);
    
    if (magxz<=0.01f) 
    	ang_diff=0.0f;
    else
    {
      	Dx = craft_dir[0]/magxz;
    	Dz = craft_dir[2]/magxz;
        
        dp= Dx* (float) sin(a_ptr->orient[1])+Dz* (float) cos(a_ptr->orient[1]);
        
		ang_diff = (float) acos(dp);
	}

	if (d>0.0f)     
		{
			a_ptr->orient[1]+=( (float) fabs(ang_diff)/80.0f)*a_ptr->velocity;      
			if (a_ptr->orient[1]>=TWOPI)
    			a_ptr->orient[1]-=TWOPI;
		}
		else                                
		{
			a_ptr->orient[1]-=( (float) fabs(ang_diff)/80.0f)*a_ptr->velocity;       
			if (a_ptr->orient[1]<TWOPI)
  			  	a_ptr->orient[1]+=TWOPI; 
		}                                                                   
}


/*****************************************************************
* Function Name		: Animate_Ant   
* Inputs			: a_ptr - pointer to instance of gi_ant 
*					  structure
*				  	  craft - pointer to craft object
*				  	  ant - number of ants
* Outputs			: none
* Returns			: void
* Description		: Modifies direction of ant 
******************************************************************/

void Animate_Ant(gi_ant *a_ptr,ControlledObject *craft, int ant)
{   
	static float go_pnt[2][3];
                    
  	int finished;
                    
	int	tran,i,legsdown,randNum;
            
    float craft_dis,dome_dis,go_x,go_z;
    float c_pos[3];
                                  
    sgl_vector	craft_dir;
                                  
	tran=a_ptr->body_transform[NECK];
	sgl_modify_transform(tran, TRUE);
	sgl_rotate(sgl_x_axis, -PI/8);

	tran=a_ptr->body_transform[HEAD];
	sgl_modify_transform(tran, TRUE);
	sgl_rotate(sgl_x_axis, PI/6);
  
	c_pos[0] = craft->GetPos()[0];
	c_pos[1] = craft->GetPos()[1];
	c_pos[2] = craft->GetPos()[2];

	for  (i=0;i<3;i++)
		craft_dir[i] = (c_pos[i])-(a_ptr->pos[i]);
                                                                   
	craft_dis = (float) sqrt(craft_dir[0]*craft_dir[0]+craft_dir[1]*craft_dir[1]+craft_dir[2]*craft_dir[2]);
	dome_dis = (float) sqrt(c_pos[0]*c_pos[0]+c_pos[1]*c_pos[1]+c_pos[2]*c_pos[2]);
	                                                                         
   	if (ant==0)
		a_ptr->velocity=1.6f;
	else
		a_ptr->velocity=2.6f;

	switch(a_ptr->status)
	{
		case WALKING: 
			Snap_mandibles(a_ptr);
			Wiggle_tail(a_ptr);
			Adjust_Direction(a_ptr,c_pos,ant);
			legsdown = Walk_ant(a_ptr,ant);
			if (((craft_dis>a_ptr->activate_dis) || (dome_dis>a_ptr->activate_dis)) && legsdown)
				a_ptr->status=STILL;
			break;
		case STILL:            
			Snap_mandibles(a_ptr);
			Wiggle_tail(a_ptr);
			if ((craft_dis<=a_ptr->activate_dis) || (dome_dis<=a_ptr->activate_dis))
				a_ptr->status=WALKING;                
			
			randNum=rand()%10;
			
			if (randNum==5) 
			{                
				go_x= (float) ((rand()%400)-200);
				go_z= (float) ((rand()%400)-200);
				go_pnt[ant][0]=go_x;
				go_pnt[ant][1]=0.0f;
				go_pnt[ant][2]=go_z; 
			
				a_ptr->status=WALKABOUT;		
			}		
			break;             
			
		case WALKABOUT:            
			Snap_mandibles(a_ptr);
			Wiggle_tail(a_ptr); 
			Adjust_Direction(a_ptr,go_pnt[ant],ant); 
			legsdown = Walk_ant(a_ptr,ant);   
			
			if ((craft_dis<=a_ptr->activate_dis) || (dome_dis<=a_ptr->activate_dis) && legsdown)
				a_ptr->status=WALKING;
			
			randNum=rand()%10;
				
			if ((randNum==5) && legsdown)    
				a_ptr->status=STILL;
		
			break;
			          	                
		case HIT:
				Explode_Ant(a_ptr,TRUE);
	
				if (Explosion.GetStatus()!=ALIVE)
				{
					Explosion.SetStatus(ALIVE);
					Explosion.Init(a_ptr->pos);
				}
				else
				{
					Explosion2.SetStatus(ALIVE);
					Explosion2.Init(a_ptr->pos);
				}
			          	                
			    a_ptr->status=EXPLODING;
			break;
			        	                
		case EXPLODING: 		  
 		        finished=Explode_Ant(a_ptr,FALSE);
		        if (finished)
		        	a_ptr->status=DEAD;
			break;
		case DEAD:
				
			break;

		default:
			break;
	}
}


/*****************************************************************
* Function Name		: Snap_mandibles 
* Inputs			: a_ptr - pointer to ant whose mandibles are 
*					: to snap
* Outputs			: none
* Returns 			: void
* Description		: Animates the mandibles of a particular ant
******************************************************************/

void Snap_mandibles(gi_ant *a_ptr)
{
	int	tran;
	float jaw_ang;
                                                   
	a_ptr->mandible_ang+=0.1f;

	if ((a_ptr->mandible_ang)>MAND_Y_LIMIT)
		a_ptr->mandible_ang=-MAND_Y_LIMIT;
	
	jaw_ang = (float) (MAX_THIGH_Z * cos(PI*((a_ptr->mandible_ang)/(2*MAND_Y_LIMIT))));

	tran=a_ptr->body_transform[JAWA];
	sgl_modify_transform(tran, TRUE);
	sgl_rotate(sgl_y_axis, jaw_ang);

	tran=a_ptr->body_transform[JAWB];
	sgl_modify_transform(tran, TRUE);
	sgl_rotate(sgl_y_axis, jaw_ang);
}


/*****************************************************************
* Function Name		: Wiggle_tail 
* Inputs			: a_ptr - pointer to ant tail is to wiggle
* Outputs			: none
* Returns			: void
* Description		: Animates the abdomen of an ant
******************************************************************/

void Wiggle_tail(gi_ant *a_ptr)
{
	int	tran;
	float a_ang;
	float move_dis;

	move_dis=a_ptr->velocity;

	a_ptr->tail_ang+=( (float) asin(move_dis/32.0f));		

	if ((a_ptr->tail_ang)>TAIL_X_LIMIT)
		a_ptr->tail_ang=-TAIL_X_LIMIT;

	a_ang = (float) (MAX_TAIL_X * cos(PI*((a_ptr->tail_ang)/(2*TAIL_X_LIMIT))));

	tran=a_ptr->body_transform[TAIL];
	sgl_modify_transform(tran, TRUE );
	sgl_rotate(sgl_x_axis, TAIL_X_REST-a_ang);
}


/*****************************************************************
* Function Name		: Walk_ant 
* Inputs			: a_ptr - pointer to ant 
* Outputs			: none
* Returns			: flag
* Description		: Makes an ant walk in its current direction at 
*					  its current speed
******************************************************************/

int	Walk_ant(gi_ant	*a_ptr,int ant)
{
	int	tran;
	int	i,downcount;
	float thigh_y_change;
	float y_off,z_off;

	float move_dis,dome_dis;

	/* adjust body position using the body's direction and
	   distance travelled in time frame */

	dome_dis = (float) sqrt(a_ptr->pos[0]*a_ptr->pos[0]+a_ptr->pos[3]*a_ptr->pos[3]);

	move_dis=a_ptr->velocity;

	a_ptr->pos[2]+= (float) ( move_dis*cos(a_ptr->orient[1])*10.0f );
	a_ptr->pos[0]+= (float) ( move_dis*sin(a_ptr->orient[1])*10.0f );
	a_ptr->pos[1] = 20.0f; 

 	tran=a_ptr->body_transform[BASE];
	sgl_modify_transform(tran, TRUE);

	sgl_translate(a_ptr->pos[0],a_ptr->pos[1],a_ptr->pos[2]);

	sgl_rotate(sgl_x_axis, a_ptr->orient[0]);
	sgl_rotate(sgl_y_axis, a_ptr->orient[1]);
	sgl_rotate(sgl_z_axis, a_ptr->orient[2]);

	thigh_y_change = (float) asin(move_dis/16.0f);		                              
                                
	downcount=0;                           
                                
	for (i=0;i<3;i++)
 	{
		/* adjust positions of left legs */
                
	 	tran=a_ptr->left_legs[i].hip_transform;
		sgl_modify_transform(tran, TRUE);

		switch(a_ptr->left_legs[i].status)
		{
			case ONGROUND:
				downcount+=1;
				(a_ptr->left_legs[i].thigh_y)+=thigh_y_change;
				if ((a_ptr->left_legs[i].thigh_y)>HIP_Y_LIMIT)
				{
					a_ptr->left_legs[i].thigh_y=HIP_Y_LIMIT;
					a_ptr->left_legs[i].status=LIFTING;
				}
				break;
			case LIFTING:
				(a_ptr->left_legs[i].thigh_y)-=(thigh_y_change*2);
				if ((a_ptr->left_legs[i].thigh_y)<-HIP_Y_LIMIT)
				{ 
					a_ptr->left_legs[i].thigh_y=-HIP_Y_LIMIT;
					a_ptr->left_legs[i].status=ONGROUND;
				}
				break;
			default:
				break;
		}
        
		y_off=a_ptr->left_legs[i].thigh_y;

		if (i==0)
			 y_off+=BACKLEG_Y_OFF;
	 
		if (i==2)
			 y_off+=FRONTLEG_Y_OFF;
		
		sgl_rotate(sgl_y_axis, y_off);

		if (a_ptr->left_legs[i].status==LIFTING)
			z_off = (float) ( MAX_THIGH_Z * cos (PI*((a_ptr->left_legs[i].thigh_y)/(2*HIP_Y_LIMIT))) );
		else
			z_off=0.0f;

		sgl_rotate(sgl_z_axis, HIP_Z_REST+z_off);    
		
		a_ptr->left_legs[i].thigh_z=HIP_Z_REST+z_off;
		
		tran=a_ptr->left_legs[i].knee_transform;
		sgl_modify_transform(tran, TRUE);
  		sgl_rotate(sgl_z_axis, KNEE_Z_REST-z_off);

		/* adjust positions of right legs */
		tran=a_ptr->right_legs[i].hip_transform;
		sgl_modify_transform(tran, TRUE);

		switch(a_ptr->right_legs[i].status)
		{            
			case ONGROUND: 
				downcount+=1;
				(a_ptr->right_legs[i].thigh_y)+=thigh_y_change;         
				if ((a_ptr->right_legs[i].thigh_y)>HIP_Y_LIMIT)
				{
					a_ptr->right_legs[i].thigh_y=HIP_Y_LIMIT;
					a_ptr->right_legs[i].status=LIFTING;
				}
				break;

			case LIFTING:
				(a_ptr->right_legs[i].thigh_y)-=(thigh_y_change*2);
				if ((a_ptr->right_legs[i].thigh_y)<-HIP_Y_LIMIT)
				{
 					a_ptr->right_legs[i].thigh_y=-HIP_Y_LIMIT;
					a_ptr->right_legs[i].status=ONGROUND;
				}
				break;

			default:

				break;
		}

		y_off=a_ptr->right_legs[i].thigh_y;

		if (i==0)
			 y_off+=BACKLEG_Y_OFF;
		if (i==2)
			 y_off+=FRONTLEG_Y_OFF;

		sgl_rotate(sgl_y_axis, y_off);

		if (a_ptr->right_legs[i].status==LIFTING)
			z_off = (float) ( MAX_THIGH_Z * cos (PI*((a_ptr->right_legs[i].thigh_y)/(2*HIP_Y_LIMIT))) );
		else
			z_off=0.0f;

		sgl_rotate(sgl_z_axis, HIP_Z_REST+z_off);   
		
		a_ptr->right_legs[i].thigh_z=HIP_Z_REST+z_off;
		
		tran=a_ptr->right_legs[i].knee_transform;

		sgl_modify_transform(tran, TRUE);
  		sgl_rotate(sgl_z_axis, KNEE_Z_REST-z_off);
	} 
	
	if (downcount==6)
		return(1);
	else
		return(0);
}
 

/*****************************************************************
* Function Name		: Explode_Ant 
* Inputs			: a_ptr - pointer to ant 
*					  justhit - flag indicating whether the ant 
*					  has just been hit.  This is usually set when 	
*					  Explode_Ant is first called
* Outputs			: none
* Returns			: flag indicating status of stillparts
* Description		: Makes an ant explode
******************************************************************/
 
int	Explode_Ant(gi_ant *a_ptr,int justhit)
{                           
	int	tran,i;       
	float theta,alpha;                      
	float proj_x,proj_y,proj_z,u;
    static int frames;        
    int stillparts;        
    float rx,rz,ry;
    float rotx,rotz,roty;
                  
    if (justhit)
    {   
        a_ptr->frames=0;
		 
    	for(i=0;i<3;i++)  
    	{   
    		a_ptr->left_legs[i].status=FLYING;
    		a_ptr->right_legs[i].status=FLYING;   
    		a_ptr->cheststate=FLYING;
    		a_ptr->tailstate=FLYING;  
    		a_ptr->basestate=FLYING;	
    	
    		a_ptr->left_legs[i].spinx=0.0f;
    		a_ptr->left_legs[i].spiny=0.0f;
    		a_ptr->left_legs[i].spiny=0.0f;

    		a_ptr->right_legs[i].spinx=0.0f;
    		a_ptr->right_legs[i].spiny=0.0f;
    		a_ptr->right_legs[i].spinz=0.0f;                                
    		                                
  		  	a_ptr->left_legs[i].velocity=8.0f+(float) i;   
  		  	a_ptr->right_legs[i].velocity=8.0f+(float) i;  		  	
    	} 
    }
    
    stillparts=0;
                
    for (i=0;i<3;i++)
	{   	
	    if (a_ptr->left_legs[i].status==FLYING)   
	    {
			tran=a_ptr->left_legs[i].hip_transform;	
			sgl_modify_transform(tran, TRUE);	 
		      
			theta=a_ptr->orient[1]-a_ptr->left_legs[i].thigh_y-(PI/4.0f);
			alpha=a_ptr->left_legs[i].thigh_z;
		              
			u=a_ptr->left_legs[i].velocity*4.0f;
		                         
			proj_x=u* (float) cos(alpha)* (float) sin(theta)*a_ptr->frames;
			proj_z=u* (float) cos(alpha)* (float) cos(theta)*a_ptr->frames;                         
		                                      
			proj_y=u* (float) sin(alpha)*a_ptr->frames-(0.15f*a_ptr->frames*a_ptr->frames);                                      
		                                      
			sgl_translate(proj_x,proj_y,proj_z);    
		
			rx=(float) (rand()%4);
			rz=(float) (rand()%4);  
			ry=(float) (rand()%4);
		   
			a_ptr->left_legs[i].spinx+=(0.0250f+0.0250f *rx);    
			a_ptr->left_legs[i].spinz+=(0.0250f+0.0250f *rz);  
			a_ptr->left_legs[i].spiny+=(0.0250f+0.0250f *ry);              
		
			rotx=a_ptr->right_legs[i].spinx;
			rotz=a_ptr->right_legs[i].spinz;
			roty=a_ptr->right_legs[i].spiny;                                 
		                                 
			sgl_rotate(sgl_x_axis, rotx);
			sgl_rotate(sgl_z_axis, rotz);  
			sgl_rotate(sgl_y_axis, roty);	
		                
			if (proj_y<-4.0f) 
				a_ptr->left_legs[i].status=INSEA;    
		}
		else
			stillparts+=1;				
    }
    
    for (i=0;i<3;i++)
	{   
		if (a_ptr->right_legs[i].status==FLYING)   
	    {	
			tran=a_ptr->right_legs[i].hip_transform;	
			sgl_modify_transform(tran,TRUE);	 
			      
			theta=a_ptr->orient[1]+a_ptr->right_legs[i].thigh_y+(PI/4.0f);
			alpha=a_ptr->right_legs[i].thigh_z;
		              
			u=a_ptr->right_legs[i].velocity*4.0f;
			                         
			proj_x=u* (float) cos(alpha)* (float) sin(theta)*a_ptr->frames;
			proj_z=u* (float) cos(alpha)* (float) cos(theta)*frames;                         
		                                      
			proj_y=u* (float) sin(alpha)*a_ptr->frames-(0.2f*a_ptr->frames*a_ptr->frames);                                      
		                                      
			sgl_translate(proj_x,proj_y,proj_z);    
        
      	 	rx=(float) (rand()%4);
			rz=(float) (rand()%4);  
			ry=(float) (rand()%4);
		   
			a_ptr->right_legs[i].spinx+=(0.0250f+0.0250f *rx);    
			a_ptr->right_legs[i].spinz+=(0.0250f+0.0250f *rz);  
			a_ptr->right_legs[i].spiny+=(0.0250f+0.0250f *ry);              
		                                 
			rotx=a_ptr->right_legs[i].spinx;
			rotz=a_ptr->right_legs[i].spinz;
			roty=a_ptr->right_legs[i].spiny;                                 
		                                 
			sgl_rotate(sgl_x_axis, rotx);
			sgl_rotate(sgl_z_axis, rotz);  
			sgl_rotate(sgl_y_axis, roty);
			
			if (proj_y<-4.0f)    
				a_ptr->right_legs[i].status=INSEA; 
		}
		else
			stillparts+=1;		
    }
    
    if (a_ptr->cheststate==FLYING)   
    {
	    tran=a_ptr->body_transform[CHEST];
   		sgl_modify_transform(tran,TRUE);
    
	    theta=a_ptr->orient[1]+PI/2;
	    alpha=0.4f; 
	    u=2.0f;
    					  
	    proj_x=u* (float) cos(alpha)* (float) sin(theta)*a_ptr->frames;
		proj_z=u* (float) cos(alpha)* (float) cos(theta)*frames;	                                      
		proj_y=u* (float) sin(alpha)*a_ptr->frames-(0.1f*a_ptr->frames*a_ptr->frames);  
                
	    sgl_translate(proj_x,proj_y,proj_z);      
	    
	    if (proj_y<-2.0f)
	    	a_ptr->cheststate=INSEA;
    }
    else
    	stillparts+=1;                    
    
    if (a_ptr->tailstate==FLYING)   
    {
	    tran=a_ptr->body_transform[TAIL];
   		sgl_modify_transform(tran,TRUE);
    
	    theta=(PI/2-a_ptr->orient[1]);
	    alpha=0.5f; 
	    u=2.5f;
    
	    proj_x=u* (float) cos(alpha)* (float) sin(theta)*a_ptr->frames;
		proj_z=u* (float) cos(alpha)* (float) cos(theta)*frames;	                                      
		proj_y=u* (float) sin(alpha)*a_ptr->frames-(0.1f*a_ptr->frames*a_ptr->frames);  
                
	    sgl_translate(proj_x,proj_y,proj_z);      
	    
	    if (proj_y<-2.0f)
	    	a_ptr->tailstate=INSEA;
    }
    else
    	stillparts+=1;            
    
    
    if (a_ptr->basestate==FLYING)   
    {
	    tran=a_ptr->body_transform[BASE];
   		sgl_modify_transform(tran,TRUE);
    
	    theta=0.0f;
	    alpha=PI/4; 
	    u=0.5f;
    
	    proj_x=u* (float) cos(alpha)* (float) sin(theta)*a_ptr->frames;
		proj_z=u* (float) cos(alpha)* (float) cos(theta)*frames;	                                      
		proj_y=u* (float) sin(alpha)*a_ptr->frames-(0.1f*a_ptr->frames*a_ptr->frames);  
                
	    sgl_translate(a_ptr->pos[0]+proj_x,a_ptr->pos[1]+proj_y,a_ptr->pos[2]+proj_z);      
	    
	    sgl_rotate(sgl_x_axis, a_ptr->orient[0]);
		sgl_rotate(sgl_y_axis, a_ptr->orient[1]);
		sgl_rotate(sgl_z_axis, a_ptr->orient[2]);
	    
	    if (proj_y<-5.0f)
	    	a_ptr->basestate=INSEA;
    }
    else
    	stillparts+=1;            
    
    a_ptr->frames+=1;
    
	if (stillparts==9)
		return 1;
	else
		return 0;
}    
