//////////////////////////////////////////////////////////////////////////////
//
//  CAMERA.C , includes LIGHTING
//  =======
//

#include "glover.h"
//#include "puzzles.h"
//#include "cameo.h"

//GsF_LIGHT light;

CAMERAVARS	CamVars;

RGBCD ambientLight={75,28,41,0};

VECTOR	cameraLockPos;
#define	SCALE	16384

//#define	NORMALCAM
//#define		AHEADCAM
#define		LAGCAM
/******************************************************************/

/************************************************************************************************/
void lightInitFlat(void)
{ 
 	GsSetAmbient(ambientLight.r*16,ambientLight.g*16,ambientLight.b*16);
 	GsSetLightMode(2);	   //fogging?
}
/*************************************************************************************/
COLLDATA	cameraColl;
COLLDATA	cameraProbeColl[2];

UBYTE		cameraHit;
UBYTE		cameraProbeHit[2];
VECTOR		CameraProbePos[2];
VECTOR		CameraProbeVel[2];
//VECTOR		CameraPos
VECTOR		probe1,probe2;
//VECTOR		CameraVel;

LONG		distanceChange;
LONG		heightChange;
LONG		posSteps;

BEHAVIOUR_PHYSICS	CameraBehaviour=
{
	10*4096,			// mass;
	GRAVITY,			// gravity;
	1*4096,				// bounce
	(4096),				// drag
	4096*10,			// maxspeed
	20*4096,			// radius
	4096,				// accel
};

BEHAVIOUR_PHYSICS	CameraProbeBehaviour=
{
	10*4096,			// mass;
	GRAVITY,			// gravity;
	1*4096,				// bounce
	(4096),				// drag
	4096*10,			// maxspeed
	20*4096,			// radius
	4096,				// accel
};

void Init_Camera(){

//ULONG	loop;
	{
		// This is Fred being paranoid about resetting things for the controlkey demos
		FMEMZERO(&cameraColl,sizeof(cameraColl));
		FMEMZERO(&cameraProbeColl[0],2*sizeof(COLLDATA));
		cameraHit = 0;
		cameraProbeHit[0] = 0;
		cameraProbeHit[1] = 0;
		FMEMZERO(&CameraProbePos[0],2*sizeof(VECTOR));
		FMEMZERO(&CameraProbeVel[0],2*sizeof(VECTOR));
		FMEMZERO(&probe1,2*sizeof(VECTOR));
		FMEMZERO(&probe2,2*sizeof(VECTOR));
		heightChange = 0;
		distanceChange = 0;
		posSteps = 0;
	}

	GsSetProjection(projection);	//default distance of projection; alters perspective
	SetGeomOffset(0,0); //camera focused on middle of screen
	CamVars.camera.vpx = 0; CamVars.camera.vpy = 0x1000; CamVars.camera.vpz = 0x1200;
	CamVars.camera.vrx = 0; CamVars.camera.vry = 0; CamVars.camera.vrz = 0;
	CamVars.camera.rz  = 0;
	CamVars.camera.super = WORLD;

	CamVars.targetmodel=pGlovePSA;
	
	CamVars.angle=0;
	CamVars.requiredHeight=FARHEIGHT;
	ZEROVECTOR(&CamVars.cameraVel);
	CamVars.oldModelPos.vx=pGlovePSA->position.vx;
	CamVars.oldModelPos.vy=pGlovePSA->position.vy;
	CamVars.oldModelPos.vz=pGlovePSA->position.vz;

	CamVars.camera.vrx=pGlovePSA->position.vx;
	CamVars.camera.vry=pGlovePSA->position.vy;
	CamVars.camera.vrz=pGlovePSA->position.vz;

	CamVars.camera.vpx=pGlovePSA->position.vx;
	CamVars.camera.vpy=pGlovePSA->position.vy-FARHEIGHT;
	CamVars.camera.vpz=pGlovePSA->position.vz+(FARDISTANCE);

	CamVars.oldVR.vx=CamVars.camera.vpx;
	CamVars.oldVR.vy=CamVars.camera.vpy;
	CamVars.oldVR.vz=CamVars.camera.vpz;

	CamVars.mode=FAR;

	CamVars.rotationSpeed=1024;
	CamVars.requiredHeight=CamVars.currentHeight=FARHEIGHT;
	CamVars.distance=FARDISTANCE;

	CamVars.zoomMode=FALSE;

	CamVars.fixedPosChangeFlag=FALSE;
	CamVars.fixedLookChangeFlag=FALSE;
	CamVars.targetChangeFlag=FALSE;
	CamVars.lastHeightChange=0;
	// NORMAL
	CamVars.flags=NULL;
	CamVars.fixedHeight=0;
	CamVars.fixedHeightFlag=FALSE;

	cameraColl.physics=&CameraBehaviour;
	cameraColl.pPos=&cameraPos;
	cameraColl.pVel=&cameraVel;

	cameraProbeColl[0].physics=&CameraProbeBehaviour;
	cameraProbeColl[0].pPos=&CameraProbePos[0];
	cameraProbeColl[0].pVel=&CameraProbeVel[0];

	cameraProbeColl[1].physics=&CameraProbeBehaviour;
	cameraProbeColl[1].pPos=&CameraProbePos[1];
	cameraProbeColl[1].pVel=&CameraProbeVel[1];

	CamVars.showGlove=TRUE;
	CamVars.showBall=TRUE;
	CamVars.lastY=999999999;

	CamVars.circleFinished=0;
	CamVars.doing=NORMALCAM;
	CamVars.camChanged=FALSE;
	GsSetRefView2(&CamVars.camera);
}

/************************************************************************************************/
//long	lastHeightChange=0;

void  UpdateCamera(long test)
{
	if(CamVars.flags&(FIXEDLOOKAT|LOOKATPLAT) )
	{
		GloveCtrl.disableTimer=3;
		GloveCtrl.cameoDisableDamage=5;
//		DB("disabling damage\n");
	}

//	if ( (CamVars.flags&CIRCLE) ) CamVars.circleFinished=INCIRCLE;
//	else if ( !(CamVars.flags&CIRCLE) && CamVars.circleFinished==INCIRCLE)
//		CamVars.circleFinished=CIRCLESTOP;


	if (test && !(CamVars.flags&FIXEDDISTANCE) )
	{
		if ( CamVars.mode==ZOOM && (debounce[0]&PAD_SQUARE || debounce[0]&PAD_CIRCLE || debounce[0]&PAD_CROSS) && CamVars.zoomMode==ZOOMEDIN)
		{
			//CamVars.currentHeight=CamVars.requiredHeight=CLOSEHEIGHT;
			//CamVars.distance=CLOSEDISTANCE;
			CamVars.currentHeight=CamVars.requiredHeight=FARHEIGHT;
			CamVars.distance=FARDISTANCE;
			CamVars.zoomMode=GOFROMZOOM;
			CamVars.zoomChangeTime=0;
		}
		if (debounce[0]&PAD_TRIANGLE && !cameo_running)
		{
			if (CamVars.mode==ZOOM && CamVars.zoomMode==ZOOMEDIN)
			{
				CamVars.currentHeight=CamVars.requiredHeight=FARHEIGHT;
				CamVars.distance=FARDISTANCE;
				CamVars.zoomMode=GOFROMZOOM;
				CamVars.zoomChangeTime=0;
			}
			else if (CamVars.mode==ZOOM && CamVars.zoomMode!=ZOOMEDIN);
			else CamVars.mode++;


			if(cheatActivated & LOOKMODE_CHEAT)
			{
				if (CamVars.mode>ZOOM) CamVars.mode=FAR;
			}
			else
			{
				//if (CamVars.mode>CLOSE) CamVars.mode=FAR;
				if (CamVars.mode>ZOOM) CamVars.mode=FAR;
			}


			if ( (GloveCtrl.action!=HAND_WALK && GloveCtrl.action!=HAND_CRAWL && GloveCtrl.action!=HAND_JOINED 
			&& GloveCtrl.action!=HAND_BALLWALK && GloveCtrl.action!=HAND_IDLE) && CamVars.mode==ZOOM ) CamVars.mode=FAR;
			
			//if (CamVars.mode==ZOOM && GloveCtrl.insideSnowBall) CamVars.mode=FAR;
			
			switch (CamVars.mode)
			{
				case FAR:
				{
					CamVars.currentHeight=CamVars.requiredHeight=FARHEIGHT;
					CamVars.distance=FARDISTANCE;
					CamVars.zoomMode=FALSE;
					break;
				}
				case MIDDLE:
				{
					CamVars.currentHeight=CamVars.requiredHeight=MIDDLEHEIGHT;
					CamVars.distance=MIDDLEDISTANCE;
					CamVars.zoomMode=FALSE;
					break;
				}
				case CLOSE:
				{
					CamVars.currentHeight=CamVars.requiredHeight=CLOSEHEIGHT;
					CamVars.distance=CLOSEDISTANCE;
					CamVars.zoomMode=FALSE;
					break;
				}
				case ZOOM:
				{
					//CamVars.currentHeight=CamVars.requiredHeight=ZOOMHEIGHT;
					//CamVars.distance=ZOOMDISTANCE;
					if (CamVars.zoomMode) break;

					CamVars.zoomMode=GOTOZOOM;
					CamVars.zoomChangeTime=0;
					break;
				}
			}
		}
		if (CamVars.flags&FIXEDHEIGHT)
		{
			//CamVars.currentHeight=CamVars.requiredHeight=CamVars.fixedHeight;
			CamVars.fixedHeightFlag=TRUE;	// FIXEDHEIGHT ONLY SET ONCE
		}
	}
	// Will this be where the camera cases go?
	if (GloveCtrl.levelFinished)
	{
		CamVars.currentHeight=CamVars.requiredHeight=FARHEIGHT;
		CamVars.distance=FARDISTANCE;
		CamVars.zoomMode=FALSE;
	}
 	moveCamera(&CamVars);
	if (!test)
	{
		CamVars.flags2=NULL;
		PuzzleVars.user_variables[2]=0;
	}

}



/*****************************************************************************************/
//	moveCamera
//
//	This Routine handles which type of camera is required
/*****************************************************************************************/
void	moveCamera(CAMERAVARS *CamVars)
{
LONG	angle,temp1;
VECTOR	temp;
LONG	temp3[9];



	// fool camera into running all the time
	CamVars->camera.vrx=CamVars->CamVr.vx;
	CamVars->camera.vry=CamVars->CamVr.vy;
	CamVars->camera.vrz=CamVars->CamVr.vz;
	CamVars->camera.vpx=CamVars->CamVp.vx;
	CamVars->camera.vpy=CamVars->CamVp.vy;
	CamVars->camera.vpz=CamVars->CamVp.vz;
	CamVars->cameraVel.vx=CamVars->CamVel.vx;
	CamVars->cameraVel.vy=CamVars->CamVel.vy;
	CamVars->cameraVel.vz=CamVars->CamVel.vz;
	normalCamera(CamVars);

	
	CamVars->camera.vpx+=(CamVars->cameraVel.vx/4096);
	CamVars->camera.vpy+=(CamVars->cameraVel.vy/4096);
	CamVars->camera.vpz+=(CamVars->cameraVel.vz/4096);


	// This is where the mad cam height bug lives
	// looks like a cross over from +ve to -ve is the cause of the fuck up

	//if ( ((CamVars->lastY+20) < CamVars->camera.vpy) && (CamVars->lastY<CamVars->camera.vpy) && CamVars->lastY>0)

	if ( ((CamVars->lastY+20) < CamVars->camera.vpy) && (CamVars->lastY<CamVars->camera.vpy) )
	{
		CamVars->camera.vpy=CamVars->lastY+20;
	}

	temp.vx=CamVars->camera.vpx*4096;
	temp.vy=CamVars->camera.vpy*4096;
	temp.vz=CamVars->camera.vpz*4096;

	temp3[0]=getHeightAtCam( temp.vx-(19*4096), temp.vy, temp.vz+(19*4096) );
	temp3[1]=getHeightAtCam( temp.vx-(18*4096), temp.vy, temp.vz );
	temp3[2]=getHeightAtCam( temp.vx-(20*4096), temp.vy, temp.vz-(18*4096) );

	temp3[3]=getHeightAtCam( temp.vx, temp.vy, temp.vz+(18*4096) );
	temp3[4]=getHeightAtCam( temp.vx, temp.vy, temp.vz );
	temp3[5]=getHeightAtCam( temp.vx, temp.vy, temp.vz-(21*4096) );

	temp3[6]=getHeightAtCam( temp.vx+(20*4096), temp.vy, temp.vz+(20*4096) );
	temp3[7]=getHeightAtCam( temp.vx+(18*4096), temp.vy, temp.vz );
	temp3[8]=getHeightAtCam( temp.vx+(19*4096), temp.vy, temp.vz-(18*4096) );

	CamVars->groundHeight=temp3[0];
	for (temp1=1;temp1<9;temp1++)
	{
		if (CamVars->groundHeight>temp3[temp1]) CamVars->groundHeight=temp3[temp1];
	}
	//printf ("ground Height %d \n",CamVars->groundHeight);

	// Hopefully the cam height bug is fixed  

	if (CamVars->groundHeight!=-1 && CamVars->groundHeight!=0)
	{
		if ((CamVars->groundHeight/4096) < MINGROUNDHEIGHT)
		{
			temp1=(MINGROUNDHEIGHT-(CamVars->groundHeight/4096));
			CamVars->lastHeightChange=( (CamVars->lastHeightChange*10) + temp1)/11;
			CamVars->camera.vpy-=CamVars->lastHeightChange;

			temp1-=CamVars->lastHeightChange;

			if (temp1 > CamVars->lastHeightChange) CamVars->lastHeightChange++;
			else if (temp1 < CamVars->lastHeightChange) CamVars->lastHeightChange--;
			//printf ("a\n");			
			//CamVars->camera.vpy-=(MINGROUNDHEIGHT-(CamVars->groundHeight/4096) );
			//CamVars->lastHeightChange=(MINGROUNDHEIGHT-(CamVars->groundHeight/4096) );
		}
		else
		{
			//printf ("b\n");
			CamVars->lastHeightChange=(CamVars->lastHeightChange*10)/11;
			CamVars->camera.vpy-=CamVars->lastHeightChange;
		}
	}

//	temp1=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
//	temp1=temp1&4095;

	TIMER_START(TIMER_COLLISION);
	CameraCollision(CamVars);
	TIMER_STOP(TIMER_COLLISION);

	if (CamVars->mode==ZOOM)
	{
		cameraProbeHit[0]=FALSE;
		cameraProbeHit[1]=FALSE;
		cameraHit=FALSE;
	}

	if (cameraProbeHit[0])
	{
		CamVars->cameraVel.vx=CameraProbeVel[0].vx;
		CamVars->cameraVel.vy=CameraProbeVel[0].vy;
		CamVars->cameraVel.vz=CameraProbeVel[0].vz;

		CamVars->camera.vpx=(CameraProbePos[0].vx-probe1.vx)/4096;
		CamVars->camera.vpy=(CameraProbePos[0].vy-probe1.vy)/4096;
		CamVars->camera.vpz=(CameraProbePos[0].vz-probe1.vz)/4096;
	}

	if (cameraProbeHit[1])
	{
		CamVars->cameraVel.vx=CameraProbeVel[1].vx;
		CamVars->cameraVel.vy=CameraProbeVel[1].vy;
		CamVars->cameraVel.vz=CameraProbeVel[1].vz;

		CamVars->camera.vpx=(CameraProbePos[1].vx-probe2.vx)/4096;
		CamVars->camera.vpy=(CameraProbePos[1].vy-probe2.vy)/4096;
		CamVars->camera.vpz=(CameraProbePos[1].vz-probe2.vz)/4096;
	}

	if (cameraHit)
	{
		CamVars->cameraVel.vx=cameraVel.vx;
		CamVars->cameraVel.vy=cameraVel.vy;
		CamVars->cameraVel.vz=cameraVel.vz;

		CamVars->camera.vpx=cameraPos.vx/4096;
		CamVars->camera.vpy=cameraPos.vy/4096;
		CamVars->camera.vpz=cameraPos.vz/4096;
	}
	CamVars->lastY=CamVars->camera.vpy;

	CamVars->CamVr.vx=CamVars->camera.vrx;
	CamVars->CamVr.vy=CamVars->camera.vry;
	CamVars->CamVr.vz=CamVars->camera.vrz;
	CamVars->CamVp.vx=CamVars->camera.vpx;
	CamVars->CamVp.vy=CamVars->camera.vpy;
	CamVars->CamVp.vz=CamVars->camera.vpz;
	CamVars->CamVel.vx=CamVars->cameraVel.vx;
	CamVars->CamVel.vy=CamVars->cameraVel.vy;
	CamVars->CamVel.vz=CamVars->cameraVel.vz;




	if ( !(CamVars->flags&CIRCLE) && CamVars->circleFinished )
	{	// Because of the way cam circle works its not possable to do a return to position instead it set the camera 
		// to the circle position

		CamVars->doing=NORMALCAM;
  		CamVars->fixedPosChangeTime=0;
  		CamVars->fixedPosChangeFlag=FALSE;

		temp.vx=(CamVars->targetmodel->position.vx-CamVars->circlePos.vx);
		temp.vz=(CamVars->targetmodel->position.vz-CamVars->circlePos.vz);
		temp.vy=0;
		MakeUnit(&temp);
		
		SCALEVECTOR(&temp,(CamVars->distance+distanceChange));
		temp.vy=(CamVars->targetmodel->position.vy);
		CamVars->camera.vpx=temp.vx+CamVars->targetmodel->position.vx;
		CamVars->camera.vpz=temp.vz+CamVars->targetmodel->position.vz;
		CamVars->camera.vpy=temp.vy-CamVars->currentHeight;

		CamVars->camera.vrx=CamVars->targetmodel->position.vx;
		CamVars->camera.vry=CamVars->targetmodel->position.vy-(gloveColl.radius/4096);
		CamVars->camera.vrz=CamVars->targetmodel->position.vz;

		angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
		CamVars->angle=angle&4095;
		CamVars->CamVr.vx=CamVars->camera.vrx;
		CamVars->CamVr.vy=CamVars->camera.vry;
		CamVars->CamVr.vz=CamVars->camera.vrz;
		CamVars->CamVp.vx=CamVars->camera.vpx;
		CamVars->CamVp.vy=CamVars->camera.vpy;
		CamVars->CamVp.vz=CamVars->camera.vpz;

		CamVars->cameraVel.vx=CamVars->CamVel.vx=0;
		CamVars->cameraVel.vy=CamVars->CamVel.vy=0;
		CamVars->cameraVel.vz=CamVars->CamVel.vz=0;
		CamVars->circleFinished=NULL;
	}

	cameraOveride(CamVars);

	if ( CamVars->zoomMode ) cameraZoom(CamVars);

	if ( (CamVars->flags&PARALLEL) )
	{
		angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
		angle=angle&4095;
		if ( abs(CamVars->parallelAngle-angle) > 64 )
			CamVars->parallelAngle=angle;
	}

	if (!CamVars->zoomMode) setCamera(CamVars);
}

/*****************************************************************************************/
//	normalCamera
//
//	This Routine will move the camera dependant on the position (not angle) of the target
/*****************************************************************************************/
#define CAM_STORES 5
VECTOR		posStore[CAM_STORES];

SHORT		cycle=0;
SHORT		cycleLen=CAM_STORES;

void	normalCamera(CAMERAVARS *CamVars)
{
	VECTOR	temp;
	LONG	mag;
	LONG	angle,tAngle,tAngle1,cAngle,temp1,temp2;
	LONG	leftRight,upDown;
	LONG	rotSpeed=1024;

	leftRight=(nrightx[0]);
	upDown=-(nrighty[0]);


	if (GloveCtrl.action==HAND_ROTOR) CamVars->requiredHeight+=50;
	if (GloveCtrl.action==HAND_HOPPING) CamVars->requiredHeight+=100;

	//if (PuzzleVars.user_variables[2]) CamVars->requiredHeight+=100;

	if ( CamVars->flags&ADDITIONALHEIGHT && CamVars->additionalHeight>0 )
	{
		if ( CamVars->currentHeight > FIXEDNEGHEIGHT )
		{
			CamVars->currentHeight-=( CamVars->currentHeight-FIXEDNEGHEIGHT )/4;
		}
		else if ( CamVars->currentHeight < FIXEDNEGHEIGHT )
		{
			CamVars->currentHeight-=( CamVars->currentHeight-FIXEDNEGHEIGHT )/4;
		}
	}
	else
	{
		if ( CamVars->currentHeight > (CamVars->requiredHeight+heightChange) )
		{
			CamVars->currentHeight-=(CamVars->currentHeight - CamVars->requiredHeight+heightChange)/4;
		}
		else if ( CamVars->currentHeight < (CamVars->requiredHeight+heightChange) )
			CamVars->currentHeight-=(CamVars->currentHeight - CamVars->requiredHeight+heightChange)/4;
	}

	if (GloveCtrl.action==HAND_ROTOR) CamVars->requiredHeight-=50;
	if (GloveCtrl.action==HAND_HOPPING) CamVars->requiredHeight-=100;

	//if (PuzzleVars.user_variables[2]) CamVars->requiredHeight-=100;

	// Find move amount
	if (CamVars->targetChangeFlag)
	{
		if (CamVars->targetChangeTime==0)
		{
			CamVars->spare.vx=CamVars->oldTargetmodel->position.vx;
			CamVars->spare.vy=CamVars->oldTargetmodel->position.vy;
			CamVars->spare.vz=CamVars->oldTargetmodel->position.vz;
		}

		if (CamVars->oldTargetmodel==CamVars->targetmodel)
		{
			CamVars->targetChangeFlag=FALSE;
			CamVars->camera.vrx=CamVars->targetmodel->position.vx;
			CamVars->camera.vry=CamVars->targetmodel->position.vy-(gloveColl.radius/4096);
			CamVars->camera.vrz=CamVars->targetmodel->position.vz;
		}
		else
		{
			mag=CamVars->targetChangeTime;

			temp.vx=(( CamVars->targetmodel->position.vx*mag ) + ( CamVars->spare.vx* (TARGETSTEPS-mag) ) )/TARGETSTEPS;
			temp.vy=(( CamVars->targetmodel->position.vy*mag ) + ( CamVars->spare.vy* (TARGETSTEPS-mag) ) )/TARGETSTEPS;
			temp.vz=(( CamVars->targetmodel->position.vz*mag ) + ( CamVars->spare.vz* (TARGETSTEPS-mag) ) )/TARGETSTEPS;

			CamVars->camera.vrx=temp.vx;
			CamVars->camera.vry=temp.vy-(gloveColl.radius/4096);
			CamVars->camera.vrz=temp.vz;
			CamVars->targetChangeTime++;
			if (CamVars->targetChangeTime==TARGETSTEPS)
			{
				CamVars->targetChangeFlag=FALSE;
			}
		}
	}
	else
	{

#ifdef	LAGCAM
		posStore[cycle].vx=CamVars->targetmodel->position.vx;
		posStore[cycle].vy=CamVars->targetmodel->position.vy;
		posStore[cycle].vz=CamVars->targetmodel->position.vz;

		for (temp1=0;temp1<cycleLen;temp1++)
		{
			if (temp1!=cycle)
			{
				if ( (posStore[cycle].vx-posStore[temp1].vx)> 10 )
					posStore[temp1].vx=posStore[cycle].vx-10;
				if ( (posStore[cycle].vx-posStore[temp1].vx)<-10 )
					posStore[temp1].vx=posStore[cycle].vx+10;

				if ( (posStore[cycle].vy-posStore[temp1].vy)> 10 )
					posStore[temp1].vy=posStore[cycle].vy-10;
				if ( (posStore[cycle].vy-posStore[temp1].vy)<-10 )
					posStore[temp1].vy=posStore[cycle].vy+10;

				if ( (posStore[cycle].vz-posStore[temp1].vz)> 10 )
					posStore[temp1].vz=posStore[cycle].vz-10;
				if ( (posStore[cycle].vz-posStore[temp1].vz)<-10 )
					posStore[temp1].vz=posStore[cycle].vz+10;

/*
				if ( abs(posStore[cycle].vx-posStore[temp1].vx)>5 )
				{
					posStore[temp1].vx=CamVars->targetmodel->position.vx;
					posStore[temp1].vy=CamVars->targetmodel->position.vy;
					posStore[temp1].vz=CamVars->targetmodel->position.vz;
				}
				else if ( abs(posStore[cycle].vy-posStore[temp1].vy)>5 )
				{
					posStore[temp1].vx=CamVars->targetmodel->position.vx;
					posStore[temp1].vy=CamVars->targetmodel->position.vy;
					posStore[temp1].vz=CamVars->targetmodel->position.vz;
				}
				else if ( abs(posStore[cycle].vz-posStore[temp1].vz)>5 )
				{
					posStore[temp1].vx=CamVars->targetmodel->position.vx;
					posStore[temp1].vy=CamVars->targetmodel->position.vy;
					posStore[temp1].vz=CamVars->targetmodel->position.vz;
				}
*/
			}
		}


		cycle++;
		if (cycle>=cycleLen) cycle=0;

		CamVars->camera.vrx=posStore[0].vx;
		CamVars->camera.vry=posStore[0].vy;
		CamVars->camera.vrz=posStore[0].vz;

		for (temp1=1;temp1<cycleLen;temp1++)
		{
			CamVars->camera.vrx+=posStore[temp1].vx;
			CamVars->camera.vry+=posStore[temp1].vy;
			CamVars->camera.vrz+=posStore[temp1].vz;
		}
		CamVars->camera.vrx = CamVars->camera.vrx / cycleLen;
		CamVars->camera.vry = CamVars->camera.vry / cycleLen;
		CamVars->camera.vrz = CamVars->camera.vrz / cycleLen;

		CamVars->camera.vry-=(gloveColl.radius/4096);
#endif
#ifdef	NORMALCAM
		CamVars->camera.vrx=CamVars->targetmodel->position.vx;
		CamVars->camera.vry=CamVars->targetmodel->position.vy-(gloveColl.radius/4096);
		CamVars->camera.vrz=CamVars->targetmodel->position.vz;
#endif

#ifdef	AHEADCAM

		if (CamVars->targetmodel==pBallPSA)
		{
			angle=calc_angle( (ballPos.vx-ballOldPos.vx),(ballPos.vz-ballOldPos.vz) );
			//CamVars->angle=angle&4095;
			temp.vx=ballPos.vx-ballOldPos.vx;
			temp.vz=ballPos.vz-ballOldPos.vz;
			temp.vy=0;
			mag=Magnitude(&temp);
			//printf ("mag %d\n",mag);
			temp.vx=0;
			temp.vy=0;
			//temp.vz=(4096*10);
			temp.vz=mag;
			RotateVector2D(&temp, &temp, angle);
			CamVars->camera.vrx=(ballPos.vx+temp.vx)/4096;
			CamVars->camera.vry=((ballPos.vy+temp.vy)/4096)-(gloveColl.radius/4096);
			CamVars->camera.vrz=(ballPos.vz+temp.vz)/4096;
		}
		else
		{
			temp.vx=0;
			temp.vy=0;
			temp.vz=-(GloveCtrl.speed*640);
			RotateVector2D(&temp, &temp, GloveCtrl.direction);
			CamVars->camera.vrx=(glovePos.vx+temp.vx)/4096;
			CamVars->camera.vry=((glovePos.vy+temp.vy)/4096)-(gloveColl.radius/4096);
			CamVars->camera.vrz=(glovePos.vz+temp.vz)/4096;
		}

		posStore[cycle].vx=CamVars->camera.vrx;
		posStore[cycle].vy=CamVars->camera.vry;
		posStore[cycle].vz=CamVars->camera.vrz;

		cycle++;
		if (cycle>=cycleLen) cycle=0;

		CamVars->camera.vrx=posStore[0].vx;
		CamVars->camera.vry=posStore[0].vy;
		CamVars->camera.vrz=posStore[0].vz;

		for (temp1=1;temp1<cycleLen;temp1++)
		{
			CamVars->camera.vrx+=posStore[temp1].vx;
			CamVars->camera.vry+=posStore[temp1].vy;
			CamVars->camera.vrz+=posStore[temp1].vz;
		}
		CamVars->camera.vrx=CamVars->camera.vrx/cycleLen;
		CamVars->camera.vry=CamVars->camera.vry/cycleLen;
		CamVars->camera.vrz=CamVars->camera.vrz/cycleLen;



#endif
	}

	if (CamVars->fixedLookChangeFlag==TRUE)
	{
		mag=CamVars->fixedLookChangeTime;
		temp.vx=(( CamVars->targetmodel->position.vx*mag ) + ( CamVars->lookAtPos.vx* (LOOKSTEPS-mag) ) )/LOOKSTEPS;
		temp.vy=(( CamVars->targetmodel->position.vy*mag ) + ( CamVars->lookAtPos.vy* (LOOKSTEPS-mag) ) )/LOOKSTEPS;
		temp.vz=(( CamVars->targetmodel->position.vz*mag ) + ( CamVars->lookAtPos.vz* (LOOKSTEPS-mag) ) )/LOOKSTEPS;

		CamVars->camera.vrx=temp.vx;
		CamVars->camera.vry=temp.vy-(gloveColl.radius/4096);
		CamVars->camera.vrz=temp.vz;
		CamVars->fixedLookChangeTime++;
		if (CamVars->fixedLookChangeTime==LOOKSTEPS)
		{
			CamVars->fixedLookChangeFlag=FALSE;
		}
	}

	{
		temp.vx=CamVars->camera.vpx-CamVars->camera.vrx;
		temp.vy=0;
		temp.vz=CamVars->camera.vpz-CamVars->camera.vrz;
		mag=Magnitude(&temp);
		if (mag==0) mag=1;
	}

	//if (!distanceChange) mag=CamVars->distance;

	CamVars->oldVR.vx=CamVars->camera.vrx;
	CamVars->oldVR.vy=CamVars->camera.vry;
	CamVars->oldVR.vz=CamVars->camera.vrz;

	// Now work out view point

// Puzzle modification by Fred II (Atlantis GeneralWu area, for example)
// (definitely wrong, this one... oops!)
	//if (CamVars->flags&ADDITIONALDISTANCE)  temp1=(CamVars->distance+CamVars->additionalDistance -mag)*16;

	/*if (CamVars->flags&ADDITIONALDISTANCE)*/  
	temp1=(CamVars->distance+distanceChange -mag)*16;
	//else temp1=(CamVars->distance -mag)*16;
	
	if (temp1)
	{
		temp.vx=(temp.vx*temp1);
		temp.vy=(temp.vy*temp1);
		temp.vz=(temp.vz*temp1);
	}
	else 
	{
		temp.vx=0;
		temp.vy=0;
		temp.vz=0;
	}

	// This bit move the cam behind actor

	// Work out angle
	angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
	CamVars->angle=angle&4095;

	CamVars->cameraVel.vx+=temp.vx;
	CamVars->cameraVel.vy+=temp.vy;
	CamVars->cameraVel.vz+=temp.vz;

	// need to add a bit of swing also need a camera vel only if glove moving

	tAngle1=(pGlovePSA->world.rotate.vy)&4095;
	if (GloveCtrl.action==HAND_BALLWALK) tAngle1=(tAngle1+2048)&4095;

	if ((CamVars->flags&FIXEDANGLE))
	{
		tAngle=(CamVars->fixedAngle+2048)&4095;
		//printf ("target rot %d  angle %d\n",tAngle,CamVars->fixedAngle);
	}
	else tAngle=(tAngle1+2048)&4095;	

	if ((CamVars->flags&PARALLEL))
	{
		tAngle=(CamVars->parallelAngle+2048)&4095;
		//printf ("target rot %d  angle %d\n",tAngle,CamVars->fixedAngle);
	}


	cAngle=(CamVars->angle)&4095;
	temp1 = findShortestAngle(cAngle,tAngle);
	temp2 = findShortestAngle(cAngle,tAngle1);

	ZEROVECTOR(&temp);
	temp.vz = 4096*8;


/*	if (CamVars->mode==ZOOM)
	{
		if (leftRight==0 && upDown==0) // try the second analog
		{
			leftRight=(nleftx[0]);
			upDown=(nlefty[0]);
		}
	}
*/

	if ( abs(leftRight) > 256 ) mag=TRUE;	// do we use buttons or anolg for cam?
	else mag=FALSE;

	// move camera from pad
	if ( !((CamVars->flags&FIXEDANGLE) || (CamVars->flags&PARALLEL)) )
	{
		if (mag==TRUE)
		{
			if (CamVars->mode==ZOOM)
			{
				leftRight=0;
				upDown=0;
			}
			else leftRight/=4;
			if ( leftRight )
			{
				RotateVector2D(&temp, &temp, cAngle-leftRight);
				CamVars->cameraVel.vx+=temp.vx;
				CamVars->cameraVel.vy+=temp.vy;
				CamVars->cameraVel.vz+=temp.vz;
  			}
		}
		else
		{
			mag=1024;
			//if (CamVars->mode==ZOOM)
			if ( (pad[0] & PAD_L1) && CamVars->mode!=ZOOM)
			{
				RotateVector2D(&temp, &temp, cAngle+mag);
				CamVars->cameraVel.vx+=temp.vx;
				CamVars->cameraVel.vy+=temp.vy;
				CamVars->cameraVel.vz+=temp.vz;
			}
			else if ( (pad[0] & PAD_R1) && CamVars->mode!=ZOOM )
			{
				RotateVector2D(&temp, &temp, cAngle-mag);
				CamVars->cameraVel.vx+=temp.vx;
				CamVars->cameraVel.vy+=temp.vy;
				CamVars->cameraVel.vz+=temp.vz;
			}
		}
	}

	// move camera up and down from pad
	if ( !(CamVars->flags&FIXEDHEIGHT) && !(CamVars->fixedHeightFlag) )
	{
		if ( abs(upDown) > 256 ) mag=TRUE;	// do we use buttons or anolg for cam?
		else mag=FALSE;
		if (mag==TRUE)
		{
			if (CamVars->mode==ZOOM) upDown/=1636;
			else upDown/=409;


			if ( (upDown>0) && (CamVars->requiredHeight<=200 ) ) CamVars->requiredHeight+=upDown;
			else if ( upDown<0 && (CamVars->requiredHeight>=30 ) && CamVars->mode!=ZOOM) CamVars->requiredHeight+=upDown;
			else if ( upDown<0 && (CamVars->requiredHeight>=0 ) && CamVars->mode==ZOOM) CamVars->requiredHeight+=upDown;
		}
	}
	else CamVars->requiredHeight=CamVars->fixedHeight;
	// move camera behind glove	or move to fixed angle

	
	if (CamVars->flags&FIXEDANGLE)
	{
		rotSpeed=1024;
	}
	else
	{
		if (GloveCtrl.ballWithHand)
		{
			temp.vx=ballVel.vx;
			temp.vz=ballVel.vz;
			temp.vy=0;

//			rotSpeed=Magnitude(&temp)/16;			// old
//			if (rotSpeed>1024) rotSpeed=1024;		// old

			rotSpeed=Magnitude(&temp)/32;			// new

			if (BallCtrl.type==BALL_MODE_BOWLING) rotSpeed=(Magnitude(&temp)/24)-256;			// new
			else rotSpeed=(Magnitude(&temp)/32)-512;			// new
			if (rotSpeed<0) rotSpeed=0;
			if (rotSpeed>1024) rotSpeed=1024;			// new
		}
		else
			rotSpeed=(1024*GloveCtrl.speed)/RUNSPEED;
	}


	//if ( (GloveCtrl.speed!=0 && !((CamVars->flags&FIXEDANGLE) || (CamVars->flags&PARALLEL)) ) /*&& abs(temp2)>100*/)
	if ( (rotSpeed && !((CamVars->flags&FIXEDANGLE) || (CamVars->flags&PARALLEL)) ) /*&& abs(temp2)>100*/)
	{
		//rotSpeed=(1024*GloveCtrl.speed)/RUNSPEED;
		if (temp1>455)
		{
			ZEROVECTOR(&temp);
			temp.vz = 4096*8;
			if (temp1 > 1794)
				temp.vz=(temp.vz/ ((temp1-1792)/2) );
				
			RotateVector2D(&temp, &temp, cAngle+rotSpeed);
			CamVars->cameraVel.vx+=temp.vx;
			CamVars->cameraVel.vy+=temp.vy;
			CamVars->cameraVel.vz+=temp.vz;
		}
		else if (temp1<-455)
		{
			ZEROVECTOR(&temp);
			temp.vz = 4096*8;
			if (temp1 < -1794)
				temp.vz=(temp.vz/ ((-temp1-1792)/2) );

			RotateVector2D(&temp, &temp, cAngle-rotSpeed);
			CamVars->cameraVel.vx+=temp.vx;
			CamVars->cameraVel.vy+=temp.vy;
			CamVars->cameraVel.vz+=temp.vz;
		}
	}

	else if ( ((CamVars->flags&FIXEDANGLE) || (CamVars->flags&PARALLEL)) )
	{
		if (temp1>0)
			temp1=(temp1-2048);
		else if (temp1<0)
			temp1=(2048+temp1);


		temp2=abs(temp1);

		ZEROVECTOR(&temp);
		if (temp2<500 && temp2>0)
		{
			temp.vz=-(((8*4096)*temp2)/500);
		}
		else if (temp2>=500) temp.vz=-(8*4096);
		else temp.vz=0;

		if (temp1>=0)
		{
			RotateVector2D(&temp, &temp, cAngle+rotSpeed);
			CamVars->cameraVel.vx+=temp.vx;
			CamVars->cameraVel.vy+=temp.vy;
			CamVars->cameraVel.vz+=temp.vz;
		}
		else if (temp1<0)
		{
			RotateVector2D(&temp, &temp, cAngle-rotSpeed);
			CamVars->cameraVel.vx+=temp.vx;
			CamVars->cameraVel.vy+=temp.vy;
			CamVars->cameraVel.vz+=temp.vz;
		}
	}

	CamVars->cameraVel.vx/=2;
	CamVars->cameraVel.vy/=2;
	CamVars->cameraVel.vz/=2;

	if (CamVars->mode==ZOOM)
	{
		if (Magnitude(&CamVars->cameraVel)>4096*10)
		{
			CamVars->cameraVel.vx/=2;
			CamVars->cameraVel.vy/=2;
			CamVars->cameraVel.vz/=2;
		}
	}

	CamVars->camera.vpy=(CamVars->targetmodel->position.vy-(CamVars->currentHeight));

	if ( (CamVars->flags&PARALLEL) )
	{
		if (leftRight < 256 )
		{
			if ( pad[0] & PAD_L1 ) leftRight=4096;
			else if ( pad[0] & PAD_R1 ) leftRight=-4096;
		}
		if ( abs(leftRight) > 256 ) mag=TRUE;	// do we use buttons or anolg for cam?
		else mag=FALSE;
		if (mag)
		{
			leftRight/=256;
			CamVars->parallelAngle-=leftRight;
		}
		CamVars->parallelAngle=(CamVars->parallelAngle&4095);
		CamVars->angle=CamVars->parallelAngle;
	}


#if PRINTMESS==YES
	sprctrl.scalex=4096;
	sprctrl.scaley=4096;
	textPrintf("Camera PosP x %d y %d z %d\n",CamVars->camera.vpx,CamVars->camera.vpy,CamVars->camera.vpz);
	textPrintf("Camera PosR x %d y %d z %d\n",CamVars->camera.vrx,CamVars->camera.vry,CamVars->camera.vrz);
#endif
}

/*****************************************************************************************/
//	cameraOverides
//
//	This Routine handles camera casese
/*****************************************************************************************/

void	cameraOveride(CAMERAVARS *CamVars)
{
LONG	mag,angle;
VECTOR	temp;

	//if (frame<200 && level!=CAVE) posSteps=POSSTEPSSLOW;
	//else posSteps=POSSTEPSFAST;
	posSteps=POSSTEPSFAST;

	if ( (CamVars->flags&FIXEDPOSITION) || (CamVars->flags&SETFIXEDPOSITION) )
	{
		if ( (CamVars->lastPos.vx!=CamVars->fixedPos.vx) || (CamVars->lastPos.vy!=CamVars->fixedPos.vy) || (CamVars->lastPos.vz!=CamVars->fixedPos.vz) )
		{
			CamVars->camChanged=TRUE;
			CamVars->lastPos.vx=CamVars->fixedPos.vx;
			CamVars->lastPos.vy=CamVars->fixedPos.vy;
			CamVars->lastPos.vz=CamVars->fixedPos.vz;
			printf ("cam changed angle %d\n",CamVars->angle);
			CamVars->lastAngle=CamVars->realAngle;
			setCamera(CamVars);
			//GloveCtrl.leftRight=padX;
			//GloveCtrl.upDown=padX;
		}
	}

	//	CAM_DISTANCE
	if (!(CamVars->flags&ADDITIONALDISTANCE) ) CamVars->additionalDistance=0;
	if (!(CamVars->flags&ADDITIONALHEIGHT) )
	{
		CamVars->additionalHeight=0;
	}

	if (CamVars->flags&ADDITIONALDISTANCE)
	{
		if (distanceChange<CamVars->additionalDistance)
		{
			if (distanceChange < (CamVars->additionalDistance-5))
				distanceChange+=5;
			else distanceChange=CamVars->additionalDistance;
		}
		else if (distanceChange>CamVars->additionalDistance)
		{
			if (distanceChange > (CamVars->additionalDistance+5))
				distanceChange-=5;
			else distanceChange=CamVars->additionalDistance;
		}
	}
	else if (distanceChange>0)
	{
		if (distanceChange > 5)
			distanceChange-=5;
		else distanceChange=0;
	}

	// CAM_HEIGHT
	if (CamVars->flags&ADDITIONALHEIGHT)
	{
		if (heightChange<CamVars->additionalHeight)
		{
			if (heightChange < (CamVars->additionalHeight-5))
				heightChange+=5;
			else heightChange=CamVars->additionalHeight;
		}
		else if (heightChange>CamVars->additionalHeight)
		{
			if (heightChange > (CamVars->additionalHeight+5))
				heightChange-=5;
			else heightChange=CamVars->additionalHeight;
		}
	}
	else if (heightChange<0)
	{
		if (heightChange < -5)
			heightChange+=5;
		else heightChange=0;
	}
	else if (heightChange>0)
	{
		if (heightChange > 5)
			heightChange-=5;
		else heightChange=0;
	}

	// returning from cam change
	if (CamVars->fixedPosChangeFlag==MOVETOGLOVE)
	{
		CamVars->fixedPos.vx=CamVars->CamVp.vx;
		CamVars->fixedPos.vy=CamVars->CamVp.vy;
		CamVars->fixedPos.vz=CamVars->CamVp.vz;

		mag=CamVars->fixedPosChangeTime++;
		temp.vx=(( CamVars->fixedPos.vx*mag ) + ( CamVars->posChange.vx* (posSteps-mag) ) )/posSteps;
		temp.vy=(( CamVars->fixedPos.vy*mag ) + ( CamVars->posChange.vy* (posSteps-mag) ) )/posSteps;
		temp.vz=(( CamVars->fixedPos.vz*mag ) + ( CamVars->posChange.vz* (posSteps-mag) ) )/posSteps;
		CamVars->camera.vpx=temp.vx;
		CamVars->camera.vpy=temp.vy;
		CamVars->camera.vpz=temp.vz;
		if (CamVars->fixedPosChangeTime==(posSteps))
		{
			CamVars->fixedPosChangeFlag=NULL;
			CamVars->fixedPosChangeTime=0;
		}
	}


	// CAM_FIXEDPOS
	if (CamVars->flags&FIXEDPOSITION)
	{
		if (CamVars->fixedPosChangeFlag==FALSE)
		{
			// start of fixed pos
			CamVars->posChange.vx=CamVars->camera.vpx;
			CamVars->posChange.vy=CamVars->camera.vpy;
			CamVars->posChange.vz=CamVars->camera.vpz;
			//CamVars->fixedPosChangeFlag=TRUE;
			CamVars->fixedPosChangeTime=0;
			CamVars->cameraVel.vx=0;
			CamVars->cameraVel.vy=0;
			CamVars->cameraVel.vz=0;
			CamVars->fixedPosChangeFlag=MOVETOFIXED;

//			cameraLockPos.vx=CamVars->camera.vrx;
//			cameraLockPos.vy=CamVars->camera.vry;
//			cameraLockPos.vz=CamVars->camera.vrz;
		}
		if (CamVars->fixedPosChangeFlag==MOVETOFIXED)
		{
			// moving to fixed pos
			mag=CamVars->fixedPosChangeTime++;
			temp.vx=(( CamVars->fixedPos.vx*mag ) + ( CamVars->posChange.vx* (posSteps-mag) ) )/posSteps;
			temp.vy=(( CamVars->fixedPos.vy*mag ) + ( CamVars->posChange.vy* (posSteps-mag) ) )/posSteps;
			temp.vz=(( CamVars->fixedPos.vz*mag ) + ( CamVars->posChange.vz* (posSteps-mag) ) )/posSteps;
			CamVars->camera.vpx=temp.vx;
			CamVars->camera.vpy=temp.vy;
			CamVars->camera.vpz=temp.vz;
			if (CamVars->fixedPosChangeTime==posSteps) CamVars->fixedPosChangeFlag=FIXED;
			CamVars->doing=MOVINGTOPOSITION;
		}
		else if (CamVars->fixedPosChangeFlag!=MOVETOGLOVE)
		{
			// holding in fixed pos
			CamVars->camera.vpx=CamVars->fixedPos.vx;
			CamVars->camera.vpy=CamVars->fixedPos.vy;
			CamVars->camera.vpz=CamVars->fixedPos.vz;
			CamVars->doing=INPOSITION;
		}
	}

	if ( CamVars->fixedPosChangeFlag && CamVars->fixedPosChangeFlag!=CIRCLEFIXED && !(CamVars->flags & FIXEDPOSITION) && !(CamVars->flags & CIRCLE))
	{
		// move cam case just ended (returning to normal position?)
		CamVars->posChange.vx=CamVars->CamVp.vx;
		CamVars->posChange.vy=CamVars->CamVp.vy;
		CamVars->posChange.vz=CamVars->CamVp.vz;

		mag=CamVars->fixedPosChangeTime;

		temp.vx=(( CamVars->fixedPos.vx*mag ) + ( CamVars->posChange.vx* (posSteps-mag) ) )/posSteps;
		temp.vy=(( CamVars->fixedPos.vy*mag ) + ( CamVars->posChange.vy* (posSteps-mag) ) )/posSteps;
		temp.vz=(( CamVars->fixedPos.vz*mag ) + ( CamVars->posChange.vz* (posSteps-mag) ) )/posSteps;

		CamVars->camera.vpx=temp.vx;
		CamVars->camera.vpy=temp.vy;
		CamVars->camera.vpz=temp.vz;

		CamVars->fixedPosChangeTime--;
		CamVars->doing=MOVEINGFROMPOSITION;

		if ( CamVars->fixedPosChangeTime<=0)
		{
			CamVars->fixedPosChangeFlag=FALSE;
			CamVars->doing=NORMALCAM;
		}
	}

	//printf ("SETFIXEDPOSITION %d flags %d\n",SETFIXEDPOSITION,CamVars->flags);

	if(CamVars->flags & SETFIXEDPOSITION)
	{
		// set cam at fixed position
		CamVars->camera.vpx=CamVars->fixedPos.vx;
		CamVars->camera.vpy=CamVars->fixedPos.vy;
		CamVars->camera.vpz=CamVars->fixedPos.vz;

		if (!CamVars->setFixedPosFlag)
		{
			printf ("setting fixed\n");
			cameraLockPos.vx=CamVars->camera.vrx;
			cameraLockPos.vy=CamVars->camera.vry;
			cameraLockPos.vz=CamVars->camera.vrz;
		}

		CamVars->setFixedPosFlag=TRUE;
		CamVars->fixedPosChangeFlag=FIXED;
		//printf ("set fixed\n");
	}

	if ( !(CamVars->flags & SETFIXEDPOSITION) && CamVars->setFixedPosFlag)
	{
		// put it back
		CamVars->fixedLookChangeFlag=FALSE;
		CamVars->fixedPosChangeFlag=FALSE;
		CamVars->setFixedPosFlag=FALSE;
		//printf ("set fixed off\n");
	}

	if(CamVars->flags & FIXEDLOOKAT )
	{
		// set to look position
		CamVars->fixedLookChangeFlag=ENABLE;
		CamVars->camera.vrx=CamVars->lookAtPos.vx;
		CamVars->camera.vry=CamVars->lookAtPos.vy;
		CamVars->camera.vrz=CamVars->lookAtPos.vz;
		angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
		CamVars->angle=angle&4095;
	}

// note - cameos need to override the hoop position & any box-related camera conditions, so they're here at the end
	if(CamVars->flags2 & CAMFLAG_CAMEO_POS)
	{
//		DB("Cameo Camera\n");

		CamVars->camera.vpx=cameo_cam_pos.vx>>12;
		CamVars->camera.vpy=cameo_cam_pos.vy>>12;
		CamVars->camera.vpz=cameo_cam_pos.vz>>12;
		angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
		CamVars->angle=angle&4095;
//		CamVars->fixedPosChangeFlag=FALSE;
		CamVars->fixedPosChangeFlag=MOVETOFIXED;
		CamVars->targetChangeFlag=FALSE;
	}
	if(CamVars->flags2 & CAMFLAG_CAMEO_TARG)
	{
		CamVars->camera.vrx=cameo_cam_targ.vx>>12;
		CamVars->camera.vry=cameo_cam_targ.vy>>12;
		CamVars->camera.vrz=cameo_cam_targ.vz>>12;
		angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
		CamVars->angle=angle&4095;
//		CamVars->fixedLookChangeFlag=FALSE;
		CamVars->fixedLookChangeFlag=ENABLE;

		CamVars->targetChangeFlag=FALSE;
	}

	if ( !(CamVars->flags & FIXEDLOOKAT) && (CamVars->flags&(FIXEDPOSITION|SETFIXEDPOSITION)) )
	{
		// if locked but not target then set target
		CamVars->camera.vrx=CamVars->targetmodel->position.vx;
		CamVars->camera.vry=CamVars->targetmodel->position.vy;
		CamVars->camera.vrz=CamVars->targetmodel->position.vz;
		angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
		CamVars->angle=angle&4095;
	}


	if( CamVars->flags&CIRCLE && CamVars->fixedPosChangeFlag==FALSE)
	{	// cam circle just started
		//DB ("starting circle\n");
		CamVars->fixedPosChangeFlag=MOVETOFIXED;
		CamVars->fixedPosChangeTime=0;
		CamVars->posChange.vx=CamVars->CamVp.vx;
		CamVars->posChange.vy=CamVars->CamVp.vy;
		CamVars->posChange.vz=CamVars->CamVp.vz;
		CamVars->circleFinished=MOVETOCIRCLE;
	}

	if(CamVars->flags & CIRCLE)
	{
		//work out circle position
		//DB ("processing circle\n");
		temp.vx=(CamVars->targetmodel->position.vx-CamVars->circlePos.vx);
		temp.vz=(CamVars->targetmodel->position.vz-CamVars->circlePos.vz);
		temp.vy=0;
		MakeUnit(&temp);
		
		SCALEVECTOR(&temp,(CamVars->distance+distanceChange));
		temp.vy=(CamVars->targetmodel->position.vy);

		CamVars->camera.vpx=temp.vx+CamVars->targetmodel->position.vx;
		CamVars->camera.vpz=temp.vz+CamVars->targetmodel->position.vz;
		CamVars->camera.vpy=temp.vy-CamVars->currentHeight;//-(gloveColl.radius/4096);

		CamVars->camera.vrx=CamVars->targetmodel->position.vx;
		CamVars->camera.vry=CamVars->targetmodel->position.vy-(gloveColl.radius/4096);
		CamVars->camera.vrz=CamVars->targetmodel->position.vz;

		angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
		CamVars->angle=angle&4095;
	}

	if( CamVars->flags&CIRCLE && CamVars->fixedPosChangeFlag==MOVETOFIXED)
	{
		//sub div to circle position
		//DB ("moving to position\n");
		CamVars->doing=MOVINGTOPOSITION;		
		mag=CamVars->fixedPosChangeTime++;
		CamVars->camera.vpx= ((CamVars->posChange.vx*(posSteps-mag)) + ((temp.vx+CamVars->targetmodel->position.vx)*mag))/posSteps ;
		CamVars->camera.vpz= ((CamVars->posChange.vz*(posSteps-mag)) + ((temp.vz+CamVars->targetmodel->position.vz)*mag))/posSteps ;
		CamVars->camera.vpy= temp.vy-CamVars->currentHeight;//-(gloveColl.radius/4096);
		CamVars->circleFinished=MOVETOCIRCLE;
		if (mag==posSteps)
		{
			//DB ("In possition\n");
			// in position set to locked
			CamVars->fixedPosChangeFlag=CIRCLEFIXED;
			CamVars->circleFinished=INCIRCLE;
			CamVars->fixedPosChangeTime=0;
			CamVars->posChange.vx=CamVars->camera.vpx;
			CamVars->posChange.vz=CamVars->camera.vpz;
			CamVars->doing=INPOSITION;
		}
	}

	if(CamVars->flags & LOOKATPLAT)
	{
		// set cam target to platfrom 
		CamVars->camera.vrx=CamVars->pLookAt->vx/4096;
		CamVars->camera.vry=CamVars->pLookAt->vy/4096;
		CamVars->camera.vrz=CamVars->pLookAt->vz/4096;

		//DB("Looking at plat ... (%d,%d,%d)\n", CamVars->camera.vrx, CamVars->camera.vry, CamVars->camera.vrz);

		if(CamVars->flags&FIXEDPOSITION)
		{
			// set cam position
			CamVars->camera.vpx=CamVars->fixedPos.vx;
			CamVars->camera.vpy=CamVars->fixedPos.vy;
			CamVars->camera.vpz=CamVars->fixedPos.vz;

			//DB("... from (%d,%d,%d)\n", CamVars->camera.vpx, CamVars->camera.vpy, CamVars->camera.vpz);
		}

		angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
		CamVars->angle=angle&4095;
	}
/*
	if ( (CamVars->flags&FIXEDPOSITION) || (CamVars->flags&SETFIXEDPOSITION) )
	{
		if ( (CamVars->lastPos.vx!=CamVars->fixedPos.vx) || (CamVars->lastPos.vy!=CamVars->fixedPos.vy) || (CamVars->lastPos.vz!=CamVars->fixedPos.vz) )
		{
			CamVars->camChanged=TRUE;
			CamVars->lastPos.vx=CamVars->fixedPos.vx;
			CamVars->lastPos.vy=CamVars->fixedPos.vy;
			CamVars->lastPos.vz=CamVars->fixedPos.vz;
			printf ("cam changed\n");
			CamVars->lastAngle=CamVars->angle;
			setCamera(CamVars);
		}
	}
*/

}

// The be-all and end all.
// Totally hit the camera's position. TOTALLY.

// Aim:- to prevent all movement screwups such as happen on teleports & respawns

void HitCameraPosition(VECTOR *pos, VECTOR *targ)
{
	int i;
	int angle;


	CamVars.targetChangeFlag=FALSE;
	CamVars.targetChangeTime=0;
	CamVars.targetmodel=pGlovePSA;

	CamVars.camera.vpx = pos->vx >> 12;
	CamVars.camera.vpy = pos->vy >> 12;
	CamVars.camera.vpz = pos->vz >> 12;

	CamVars.camera.vrx = targ->vx >> 12;
	CamVars.camera.vry = targ->vy >> 12;
	CamVars.camera.vrz = targ->vz >> 12;

	CamVars.lookAtPos.vx=CamVars.camera.vrx;
	CamVars.lookAtPos.vy=CamVars.camera.vry;
	CamVars.lookAtPos.vz=CamVars.camera.vrz;

	CamVars.fixedPos.vx=CamVars.camera.vpx;
	CamVars.fixedPos.vy=CamVars.camera.vpy;
	CamVars.fixedPos.vz=CamVars.camera.vpz;

	CamVars.targetChangeFlag = FALSE;

	CamVars.CamVp = CamVars.fixedPos;
	CamVars.CamVr = CamVars.oldVR = CamVars.oldModelPos = CamVars.lookAtPos;

	for(i = 0; i < CAM_STORES; i++)
	{
//posStore[cycle].vx=CamVars->camera.vrx
		posStore[i] = CamVars.CamVr;
	}
	CamVars.oldModelPos=CamVars.CamVr;

	CamVars.posChange.vx=0;
	CamVars.posChange.vy=0;
	CamVars.posChange.vz=0;

	CamVars.cameraVel.vx = 0;
	CamVars.cameraVel.vy = 0;
	CamVars.cameraVel.vz = 0;
	CamVars.CamVel.vx = 0;
	CamVars.CamVel.vy = 0;
	CamVars.CamVel.vz = 0;

	cameraColl.oldPos = CamVars.fixedPos;
	cameraProbeColl[0].oldPos = CamVars.fixedPos;
	cameraProbeColl[1].oldPos = CamVars.fixedPos;

	CameraProbePos[0] = CamVars.fixedPos;
	CameraProbePos[1] = CamVars.fixedPos;

	CamVars.flags |= FIXEDPOSITION | FIXEDLOOKAT;

	angle=calc_angle( (CamVars.camera.vpx-CamVars.camera.vrx),(CamVars.camera.vpz-CamVars.camera.vrz) );
	CamVars.angle=angle&4095;

}

// Used by the hoops as soon as you've popped out of the hoop
// (note "enebled" check on the glove, to deal with those levels where you play as the ball, when they happen)
void Camera_BeginLookAtPlayer()
{
	if(GloveCtrl.enabled)
	{
		CamVars.oldTargetmodel=CamVars.targetmodel;
		CamVars.targetChangeTime=0;
		CamVars.targetChangeFlag=TRUE;
		CamVars.targetmodel=pGlovePSA;
	}
	else
	{
		CamVars.oldTargetmodel=CamVars.targetmodel;
		CamVars.targetChangeTime=0;
		CamVars.targetChangeFlag=TRUE;
		CamVars.targetmodel=pBallPSA;
	}
}


/*****************************************************************************************/
//	CameraCollision
//
//	This Routine will check the camera against objects
/*****************************************************************************************/


UBYTE	switchcam=FALSE;
//UBYTE	switchcam=TRUE;

void	CameraCollision(CAMERAVARS *CamVars)
{
	LONG	temp1[5],camSphere;
	VECTOR	scale;

	camSphere=(80)*4096;

	cameraColl.pPos->vx=CamVars->camera.vpx*4096;
	temp1[0]=cameraColl.pPos->vy=CamVars->camera.vpy*4096;
	cameraColl.pPos->vz=CamVars->camera.vpz*4096;

	cameraColl.pVel->vx=CamVars->cameraVel.vx;
	cameraColl.pVel->vy=CamVars->cameraVel.vy;
	cameraColl.pVel->vz=CamVars->cameraVel.vz;

	cameraColl.radius=camSphere;

	scale.vz=-(60*4096);
	scale.vx=0;
	scale.vy=0;

	RotateVector2D(&probe1, &scale, CamVars->angle+512);
	RotateVector2D(&probe2, &scale, CamVars->angle-512);

	cameraProbeColl[0].pPos->vx=cameraColl.pPos->vx+probe1.vx;
	cameraProbeColl[0].pPos->vy=cameraColl.pPos->vy+probe1.vy;
	cameraProbeColl[0].pPos->vz=cameraColl.pPos->vz+probe1.vz;
	
	cameraProbeColl[1].pPos->vx=cameraColl.pPos->vx+probe2.vx;
	cameraProbeColl[1].pPos->vy=cameraColl.pPos->vy+probe2.vy;
	cameraProbeColl[1].pPos->vz=cameraColl.pPos->vz+probe2.vz;

	cameraProbeColl[0].pVel->vx=cameraColl.pVel->vx;
	cameraProbeColl[0].pVel->vy=cameraColl.pVel->vy;
	cameraProbeColl[0].pVel->vz=cameraColl.pVel->vz;

	cameraProbeColl[1].pVel->vx=cameraColl.pVel->vx;
	cameraProbeColl[1].pVel->vy=cameraColl.pVel->vy;
	cameraProbeColl[1].pVel->vz=cameraColl.pVel->vz;

	cameraHit = collboxCheckSphere(&cameraColl);

/*
	pBallPSA->position.vx=cameraColl.pPos->vx>>12;
	pBallPSA->position.vy=cameraColl.pPos->vy>>12;
	pBallPSA->position.vz=cameraColl.pPos->vz>>12;
	
	objectSetAnimation(pBallPSA, 0);
	objectDraw(pBallPSA);


	pBallPSA->position.vx=cameraProbeColl[0].pPos->vx>>12;
	pBallPSA->position.vy=cameraProbeColl[0].pPos->vy>>12;
	pBallPSA->position.vz=cameraProbeColl[0].pPos->vz>>12;
	
	objectSetAnimation(pBallPSA, 0);
	objectDraw(pBallPSA);

	pBallPSA->position.vx=cameraProbeColl[1].pPos->vx>>12;
	pBallPSA->position.vy=cameraProbeColl[1].pPos->vy>>12;
	pBallPSA->position.vz=cameraProbeColl[1].pPos->vz>>12;
	
	objectSetAnimation(pBallPSA, 0);
	objectDraw(pBallPSA);
*/


	cameraProbeHit[0] = collboxCheckSphere(&cameraProbeColl[0]);
	cameraProbeHit[1] = collboxCheckSphere(&cameraProbeColl[1]);
}

long	carnivalHeightFrig=0;

//********************************************************************************************************************/
void	setCamera(CAMERAVARS *CamVars)
{
	VECTOR	scale,oldP,oldR;
	LONG	angle;

	oldR.vx=CamVars->camera.vrx;
	oldR.vy=CamVars->camera.vry;
	oldR.vz=CamVars->camera.vrz;

	oldP.vx=CamVars->camera.vpx;
	oldP.vy=CamVars->camera.vpy;
	oldP.vz=CamVars->camera.vpz;

	if (PuzzleVars.user_variables[2])
	{
		//printf ("mag height on\n");
		CamVars->camera.vry-=carnivalHeightFrig;
		if (carnivalHeightFrig<45) carnivalHeightFrig++;
	}
	else if (carnivalHeightFrig)
	{
		//printf ("mag height off\n");
		CamVars->camera.vry-=carnivalHeightFrig;
		carnivalHeightFrig--;
	}
	
	//PuzzleVars.user_variables[2]=0;

	CamVars->camera.vrx=(CamVars->camera.vrx*SCALE)/4096;
	CamVars->camera.vry=(CamVars->camera.vry*SCALE)/4096;
	CamVars->camera.vrz=(CamVars->camera.vrz*SCALE)/4096;

	CamVars->camera.vpx=(CamVars->camera.vpx*SCALE)/4096;
	CamVars->camera.vpy=(CamVars->camera.vpy*SCALE)/4096;
 	CamVars->camera.vpz=(CamVars->camera.vpz*SCALE)/4096;

#if RELEASE==NO
	if (debounce[1]&PAD_SELECT)
	{
		if (switchcam==TRUE) switchcam=FALSE;
		else switchcam=TRUE;
	}
	if (switchcam==TRUE)
	{
		CamVars->camera.vrx=CamVars->targetmodel->position.vx*4;
		CamVars->camera.vry=CamVars->targetmodel->position.vy*4;
		CamVars->camera.vrz=CamVars->targetmodel->position.vz*4;

		CamVars->camera.vpx=CamVars->camera.vrx;
		CamVars->camera.vpy=CamVars->camera.vry-3000;
		CamVars->camera.vpz=CamVars->camera.vrz;
	}
#endif

	if (CamVars->setFixedPosFlag && CamVars->mode!=ZOOM/* || (CamVars->flags&FIXEDPOSITION) */)
	{
		CamVars->camera.vrx=cameraLockPos.vx;
		CamVars->camera.vry=cameraLockPos.vy;
		CamVars->camera.vrz=cameraLockPos.vz;
	}


	weatherDoEarthquake(); // this fiddles about with the camera, you see.

// Workaround for a crashbug in Space2, immediately after the came, GsSetRefView2L bombed, given these numbers:-
//  camera.c [1557] sc1 - vp = 76,-1416,61696, vr= -292,-84,14368, rz=851968 (0)

	{
		scale.vx = CamVars->camera.vrx - CamVars->camera.vpx;
		scale.vy = CamVars->camera.vry - CamVars->camera.vpy;
		scale.vz = CamVars->camera.vrz - CamVars->camera.vpz;
		if(Magnitude(&scale) > 26754)
		{
			DB("Camera Extreme Range problem, worked around\n");
			while(Magnitude(&scale) > 26754)
			{
				scale.vx = scale.vx /2;
				scale.vy = scale.vy /2;
				scale.vz = scale.vz /2;
				CamVars->camera.vrx = CamVars->camera.vpx + scale.vx;
				CamVars->camera.vry = CamVars->camera.vpy + scale.vy;
				CamVars->camera.vrz = CamVars->camera.vpz + scale.vz;
			}
		}
	}

	angle=calc_angle( (CamVars->camera.vpx-CamVars->camera.vrx),(CamVars->camera.vpz-CamVars->camera.vrz) );
	CamVars->realAngle=angle&4095;


	GsSetRefView2L(&CamVars->camera);

	sprctrl.scalex=2048;
	sprctrl.scaley=2048;

	CamVars->camera.vrx=oldR.vx;
	CamVars->camera.vry=oldR.vy;
	CamVars->camera.vrz=oldR.vz;

	CamVars->camera.vpx=oldP.vx;
	CamVars->camera.vpy=oldP.vy;
	CamVars->camera.vpz=oldP.vz;

	scale.vx=SCALE;
	scale.vy=SCALE;
	scale.vz=SCALE;

	ScaleMatrixL(&GsWSMATRIX,&scale);

	CamVars->oldModelPos.vx=CamVars->targetmodel->position.vx;
	CamVars->oldModelPos.vy=CamVars->targetmodel->position.vy;
	CamVars->oldModelPos.vz=CamVars->targetmodel->position.vz;


}

//********************************************************************************************************************/


//LONG	testc1=25;
//LONG	testc2=20;

void	carnivalBonusCamera(void)
{
VECTOR	temp;


#if RELEASE == NO
	if (!(pad[1]&PAD_UP) )
#endif
	{
		temp.vx=0;
		temp.vz=150;

		RotateVector2D(&temp,&temp,CannonCtrl.camDirection);


		//CamVars.camera.vrx=CamVars.targetmodel->position.vx;
		//CamVars.camera.vrz=CamVars.targetmodel->position.vz;

		CamVars.camera.vrx=0;
		CamVars.camera.vrz=0;


		CamVars.camera.vry=CamVars.targetmodel->position.vy-(gloveColl.radius/4096);

		CamVars.camera.vpx = temp.vx;
		CamVars.camera.vry-=(50-(CannonCtrl.elevation/50));
		CamVars.camera.vpy = CamVars.camera.vry-(CannonCtrl.elevation/25)-16;

		CamVars.camera.vpz = temp.vz;
	}
#if RELEASE == NO
	else
	{
		temp.vx=0;
		temp.vz=150;
		//temp.vz=900;
		RotateVector2D(&temp,&temp,CannonCtrl.camDirection);

		CamVars.camera.vrx=CamVars.targetmodel->position.vx;
		CamVars.camera.vrz=CamVars.targetmodel->position.vz;

		CamVars.camera.vpx = temp.vx;
		CamVars.camera.vry-=(50-(CannonCtrl.elevation/50));
		CamVars.camera.vpy = CamVars.camera.vry-(CannonCtrl.elevation/25)-16;

		CamVars.camera.vpy = CamVars.camera.vry-1600;
		CamVars.camera.vpz = temp.vz;
	}
#endif

	setCamera(&CamVars);

}

void	CarnivalBossCamera(void)
{
//	if(level == CARNIVALBOSS && !cameo_running)
	{
		int tangle, cangle;
		VECTOR temp;

// actually, there's supposed to be a bit of lag on this

		tangle=calc_angle( glovePos.vx, glovePos.vz) & 4095;
		tangle = (tangle + 0x800) & 4095;

//		tangle += caboss_spin * 16;


		cangle = (CamVars.angle)&4095;
		cangle = findShortestAngle(cangle,tangle);
		
		if(cangle > 2048)
			cangle -= 4096;

//		if (cangle > 512 || cangle < -512)
//			CamVars.angle = tangle;
//		else
//			CamVars.angle -= cangle / 12;

		CamVars.angle -= cangle / 6;


		temp.vx = rsin(CamVars.angle+0x800);
		temp.vz = rcos(CamVars.angle+0x800);
/*
		CamVars.camera.vpx = 0-(temp.vx * 320) / 4096;
		CamVars.camera.vpy = -250;
		CamVars.camera.vpz = 0-(temp.vz * 320) / 4096;

		CamVars.camera.vrx = 0;
		CamVars.camera.vry = -140;
		CamVars.camera.vrz = 0;
*/

		if(CamVars.camera.vpy != CamVars.requiredHeight)
		{
			CamVars.camera.vpy += (CamVars.requiredHeight-CamVars.camera.vpy)/12;
		}

		CamVars.camera.vpx = 0-(temp.vx * 290) / 4096;
//		CamVars.camera.vpy = -150;
		CamVars.camera.vpz = 0-(temp.vz * 290) / 4096;

		CamVars.camera.vrx = 0;
		CamVars.camera.vry = CamVars.camera.vpy /2;	//-80;
		CamVars.camera.vrz = 0;


		setCamera(&CamVars);

	}
}
/******************************************************************************************************/
void	FearBossCamera(void)
{
	int tangle, cangle;
	VECTOR temp;

	if(CamVars.flags)
	{
		UpdateCamera(TRUE);
		UpdateCamera(FALSE);
		FearSnapFlag = 1;
		return;
	}


	if((glovePos.vy >> 12) > -300)
		CamVars.requiredHeight = (glovePos.vy>>12)-350;
	else
		CamVars.requiredHeight = -300-350;

// actually, there's supposed to be a bit of lag on this

	tangle=calc_angle( glovePos.vx, glovePos.vz) & 4095;
	tangle = (tangle + 0x800) & 4095;

	if(FearSnapFlag)
	{
		CamVars.angle = tangle;
	}

	cangle = (CamVars.angle)&4095;
	cangle = findShortestAngle(cangle,tangle);
	
	if(cangle > 2048)
		cangle -= 4096;
	if (cangle > 200) cangle = 200;
	if (cangle < -200) cangle = -200;

	CamVars.angle -= cangle / 12;

	temp.vx = rsin(CamVars.angle+0x800);
	temp.vz = rcos(CamVars.angle+0x800);

	if(CamVars.camera.vpy != CamVars.requiredHeight)
	{
		CamVars.camera.vpy += (CamVars.requiredHeight-CamVars.camera.vpy)/12;
	}

	if(FearSnapFlag)
	{
		CamVars.camera.vpy = CamVars.requiredHeight;
	}


	CamVars.camera.vpx = 0-(temp.vx * 220) / 4096;
	CamVars.camera.vpz = 0-(temp.vz * 220) / 4096;


	CamVars.camera.vrx = (glovePos.vx>>12);	
	CamVars.camera.vry = (glovePos.vy>>12) + 200;
	CamVars.camera.vrz = (glovePos.vz>>12);	


	if(FearCrossPlatTimer)
	{
		int temp2;
		int amount;

		FearCrossPlatTimer--;

		temp2 = FearCrossPlatTimer;

		if(temp2 > FearCrossPlatDurn * 3/4)
		{
			temp2 = FearCrossPlatDurn - temp2;
			amount = FearCrossPlatDurn * 1/4;
		}
		else
		{
			amount = FearCrossPlatDurn * 3/4;
		}



//		temp2 = rcos(temp2 * 2048 / amount) + 4096;

		temp2 = rcos(temp2 * 2048 / amount);
		temp2 = 4096 - temp2;
		amount = 8192;



//		CamVars.camera.vpy -= 20 * temp2/amount;
		CamVars.camera.vpy -= 5 * temp2/amount;

		CamVars.camera.vrx  -= CamVars.camera.vrx * (temp2 * 300/256) / amount;
		CamVars.camera.vrz  -= CamVars.camera.vrz * (temp2 * 300/256) / amount;


		CamVars.camera.vpx  += CamVars.camera.vpx * (temp2 * 150/256) / amount;
		CamVars.camera.vpz  += CamVars.camera.vpz * (temp2 * 150/256) / amount;

	}
/*
	DB("vp = %d %d %d, vr = %d %d %d\n",
		CamVars.camera.vpx,CamVars.camera.vpy,CamVars.camera.vpz,
		CamVars.camera.vrx,CamVars.camera.vry,CamVars.camera.vrz
		);
*/
	setCamera(&CamVars);
	FearSnapFlag = 0;
}


void	SpaceBossCamera(void)
{
	VECTOR temp;
//	if (level==SPACEBOSS2 && !cameo_running)	// special case for space boss 2
	{
		temp.vx = 0;
		temp.vy = (150 * rsin(SpBossCtrl.xa_cam))>>12;
		temp.vz = (150 * rcos(SpBossCtrl.xa_cam))>>12;
		RotateVector2D(&temp,&temp,SpBossCtrl.ya_cam);

		CamVars.camera.vpx = glovePos.vx>>12;
		CamVars.camera.vpy = glovePos.vy>>12;
		CamVars.camera.vpz = glovePos.vz>>12;

		CamVars.camera.vrx = (glovePos.vx>>12) - temp.vx;
		CamVars.camera.vry = (glovePos.vy>>12) - temp.vy;
		CamVars.camera.vrz = (glovePos.vz>>12) - temp.vz;
		setCamera(&CamVars);
	}
}


void	WayroomCamera(void)
{
//	if(level == CARNIVALBOSS && !cameo_running)
	{
		int tangle, cangle;
		VECTOR temp;

		CamVars.requiredHeight = -300;
// actually, there's supposed to be a bit of lag on this

		tangle=calc_angle( glovePos.vx, glovePos.vz) & 4095;
		tangle = (tangle + 0x800) & 4095;

		if(frame < 2)
		{
			CamVars.angle = tangle;
		}
		else
		{
			cangle = (CamVars.angle)&4095;
			cangle = findShortestAngle(cangle,tangle);
		
			if(cangle > 2048)
				cangle -= 4096;

			CamVars.angle -= cangle / 12;
		}

		temp.vx = rsin(CamVars.angle+0x800);
		temp.vz = rcos(CamVars.angle+0x800);

		if(CamVars.camera.vpy != CamVars.requiredHeight)
		{
			CamVars.camera.vpy += (CamVars.requiredHeight-CamVars.camera.vpy)/12;
		}

		CamVars.camera.vpx = 0-(temp.vx * 290) / 4096;
//		CamVars.camera.vpy = -150;
		CamVars.camera.vpz = 0-(temp.vz * 290) / 4096;

		CamVars.camera.vrx = 0;
		CamVars.camera.vry = CamVars.camera.vpy /2;	//-80;
		CamVars.camera.vrz = 0;

		setCamera(&CamVars);

	}
}


////////////////////////////////////////////////////////////////////////////////////////
#define	ZOOMCHANGETIME	20


void	cameraZoom(CAMERAVARS *CamVars)
{
VECTOR	posChange;
VECTOR	camDirection,tempVec;
LONG	mag;
LONG	leftRight,upDown;

	leftRight=(nrightx[0]);
	upDown=-(nrighty[0]);

	if (!leftRight && !upDown)
	{
		leftRight=(nleftx[0]);
		upDown=-(nlefty[0]);
	}
	if ( (GloveCtrl.deathType || GloveCtrl.insideSnowBall) && CamVars->zoomMode!=GOFROMZOOM)
	{
		//CamVars->currentHeight=CamVars->requiredHeight=CLOSEHEIGHT;
		//CamVars->distance=CLOSEDISTANCE;

		CamVars->currentHeight=CamVars->requiredHeight=FARHEIGHT;
		CamVars->distance=FARDISTANCE;

		CamVars->zoomMode=GOFROMZOOM;
		CamVars->zoomChangeTime=0;
		CamVars->showGlove=TRUE;
		CamVars->showBall=TRUE;
	}

	CamVars->zoomCamVr.vx=CamVars->camera.vrx;
	CamVars->zoomCamVr.vy=CamVars->camera.vry;	
	CamVars->zoomCamVr.vz=CamVars->camera.vrz;

	CamVars->zoomCamVp.vx=CamVars->camera.vpx;
	CamVars->zoomCamVp.vy=CamVars->camera.vpy;
	CamVars->zoomCamVp.vz=CamVars->camera.vpz;

	//if (CamVars->zoomChangeTime<ZOOMCHANGETIME)
	if (CamVars->zoomMode==GOTOZOOM)
	{
		camDirection.vx=CamVars->camera.vrx-CamVars->camera.vpx;
		camDirection.vy=CamVars->camera.vry-CamVars->camera.vpy;	
		camDirection.vz=CamVars->camera.vrz-CamVars->camera.vpz;

		tempVec.vx=0;
		tempVec.vy=0;
		tempVec.vz=-4096;
		
		RotateVector2D(&tempVec,&tempVec,GloveCtrl.direction);		

		MakeUnit(&camDirection);
		mag=CamVars->zoomChangeTime;

		camDirection.vx=( (tempVec.vx*mag)+(camDirection.vx*(ZOOMCHANGETIME-mag)) )/ZOOMCHANGETIME;
		camDirection.vy=( (tempVec.vy*mag)+(camDirection.vy*(ZOOMCHANGETIME-mag)) )/ZOOMCHANGETIME;
		camDirection.vz=( (tempVec.vz*mag)+(camDirection.vz*(ZOOMCHANGETIME-mag)) )/ZOOMCHANGETIME;

		if (mag==ZOOMCHANGETIME/2)
		{
			CamVars->showGlove=FALSE;
			if (GloveCtrl.action==HAND_JOINED) CamVars->showBall=FALSE;
		}

		posChange.vx=(( CamVars->targetmodel->position.vx*mag ) + ( CamVars->camera.vpx* (ZOOMCHANGETIME-mag) ) )/ZOOMCHANGETIME;
		posChange.vy=(( (CamVars->targetmodel->position.vy-(gloveColl.radius/2048) )*mag ) + ( CamVars->camera.vpy* (ZOOMCHANGETIME-mag) ) )/ZOOMCHANGETIME;
		posChange.vz=(( CamVars->targetmodel->position.vz*mag ) + ( CamVars->camera.vpz* (ZOOMCHANGETIME-mag) ) )/ZOOMCHANGETIME;

		CamVars->camera.vpx=posChange.vx;
		CamVars->camera.vpy=posChange.vy;
		CamVars->camera.vpz=posChange.vz;
		
		CamVars->zoomCamLookAt.vx=(camDirection.vx);
		CamVars->zoomCamLookAt.vy=(camDirection.vy);
		CamVars->zoomCamLookAt.vz=(camDirection.vz);

		CamVars->camera.vrx=posChange.vx+(camDirection.vx/40);
		CamVars->camera.vry=posChange.vy+(camDirection.vy/40);
		CamVars->camera.vrz=posChange.vz+(camDirection.vz/40);
		CamVars->zoomChangeTime++;
		if (CamVars->zoomChangeTime==ZOOMCHANGETIME) CamVars->zoomMode=ZOOMEDIN;
	}
	
	if (CamVars->zoomMode==ZOOMEDIN)
	{
		CamVars->camera.vpx=CamVars->targetmodel->position.vx;
		CamVars->camera.vpy=CamVars->targetmodel->position.vy-(gloveColl.radius/2048);
		CamVars->camera.vpz=CamVars->targetmodel->position.vz;

		CamVars->camera.vrx=CamVars->camera.vpx+(CamVars->zoomCamLookAt.vx/40);
		CamVars->camera.vry=CamVars->camera.vpy+(CamVars->zoomCamLookAt.vy/40);
		CamVars->camera.vrz=CamVars->camera.vpz+(CamVars->zoomCamLookAt.vz/40);

		MakeUnit(&CamVars->zoomCamLookAt);
		RotateVector2D(&CamVars->zoomCamLookAt,&CamVars->zoomCamLookAt,leftRight/128);
		if (upDown) CamVars->zoomCamLookAt.vy+=upDown/64;
	}
	
	if (CamVars->zoomMode==GOFROMZOOM)
	{
		camDirection.vx=CamVars->camera.vrx-CamVars->camera.vpx;
		camDirection.vy=CamVars->camera.vry-CamVars->camera.vpy;	
		camDirection.vz=CamVars->camera.vrz-CamVars->camera.vpz;

		MakeUnit(&camDirection);
		mag=CamVars->zoomChangeTime;

		tempVec.vx=0;
		tempVec.vy=0;
		tempVec.vz=-4096;
		
		RotateVector2D(&tempVec,&tempVec,GloveCtrl.direction);		

		camDirection.vx=( (tempVec.vx*(ZOOMCHANGETIME-mag))+(camDirection.vx*mag) )/ZOOMCHANGETIME;
		camDirection.vy=( (tempVec.vy*(ZOOMCHANGETIME-mag))+(camDirection.vy*mag) )/ZOOMCHANGETIME;
		camDirection.vz=( (tempVec.vz*(ZOOMCHANGETIME-mag))+(camDirection.vz*mag) )/ZOOMCHANGETIME;

		if (mag==ZOOMCHANGETIME/2)
		{
			CamVars->showGlove=TRUE;
			CamVars->showBall=TRUE;
		}

		posChange.vx=(( CamVars->targetmodel->position.vx*(ZOOMCHANGETIME-mag) ) + ( CamVars->camera.vpx* mag ) )/ZOOMCHANGETIME;
		posChange.vy=(( (CamVars->targetmodel->position.vy-(gloveColl.radius/2048) )*(ZOOMCHANGETIME-mag) ) + ( CamVars->camera.vpy* mag ) )/ZOOMCHANGETIME;
		posChange.vz=(( CamVars->targetmodel->position.vz*(ZOOMCHANGETIME-mag) ) + ( CamVars->camera.vpz* mag ) )/ZOOMCHANGETIME;

		CamVars->camera.vpx=posChange.vx;
		CamVars->camera.vpy=posChange.vy;
		CamVars->camera.vpz=posChange.vz;
		
		CamVars->zoomCamLookAt.vx=(camDirection.vx);
		CamVars->zoomCamLookAt.vy=(camDirection.vy);
		CamVars->zoomCamLookAt.vz=(camDirection.vz);

		CamVars->camera.vrx=posChange.vx+(camDirection.vx/40);
		CamVars->camera.vry=posChange.vy+(camDirection.vy/40);
		CamVars->camera.vrz=posChange.vz+(camDirection.vz/40);
		CamVars->zoomChangeTime++;
		if (CamVars->zoomChangeTime==ZOOMCHANGETIME)
		{
			CamVars->zoomMode=FALSE;
			CamVars->mode=FAR;
			CamVars->zoomChangeTime=0;
		}
	}
	setCamera(CamVars);

	CamVars->camera.vrx=CamVars->zoomCamVr.vx;
	CamVars->camera.vry=CamVars->zoomCamVr.vy;	
	CamVars->camera.vrz=CamVars->zoomCamVr.vz;

	CamVars->camera.vpx=CamVars->zoomCamVp.vx;
	CamVars->camera.vpy=CamVars->zoomCamVp.vy;
	CamVars->camera.vpz=CamVars->zoomCamVp.vz;

}






