/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  This program is free software; you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by    */
/*  the Free Software Foundation; either version 1, or (at your option)     */
/*  any later version.                                                      */
/*                                                                          */
/*  This program is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
/*  GNU General Public License for more details.                            */
/*                                                                          */
/*  You should have received a copy of the GNU General Public License       */
/*  along with this program; if not, write to the Free Software             */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/



#include <stdio.h>
#include <fcntl.h>
#include "C_volvis.h"
#include <gl/gl.h>
#include <gl/device.h>


#define WINDOW_MODE		0
#define FULL_SCREEN_MODE	1

#define	MAX_IMAGES	200
#define STOPPED         1
#define LOOPING         2
#define MOUSEPOS        3
#define FORBACK         4
#define SWINGING        5

#define FORWARD         0
#define BACK            1

#define	TIME_INCREMENT	0.05

int		current_frame;
unsigned long 	*images[MAX_IMAGES];
int		width, height;
int		depth;
int		num_images;
int		mode;
int		direction;
int		startx, starty;
int		endx, endy;

double		delay_time;

float		fgetmousex();

main(argc, argv)
int argc;
char *argv[];
{
	int		fd;
	int		loop;
	char		final[256];
	unsigned char	*red_image;
	unsigned char	*green_image;
	unsigned char	*blue_image;
	unsigned char	*rptr;
	unsigned char	*gptr;
	unsigned char	*bptr;
	unsigned char	temp_char;
	unsigned long	*iptr;
	int		zoom_factor;
	int		image_start;
	int		image_limit;
	int		screen_mode;
	int		menu;
	int		status;
	short		val;
	C_Image		image;

	char		*msg[200];

	extern void	C_wait();

	if(argc != 5)
	{
       	     C_message("Usage: animate base_name zoom image_start image_limit");
	     exit(0);
	}

	zoom_factor = atoi( argv[2] );

	image_start = atoi( argv[3] );

	image_limit = atoi( argv[4] );

	screen_mode = WINDOW_MODE;

	/* Open The First Image To Get Width & Height Info */
	sprintf(final, "%s.%d.img", argv[1], image_start );	

	status = C_read_image_from_file( &image, final );
	if( status == C_ERROR )
	{
		sprintf( msg, "Problem Opening %s", final );
		C_error_message( msg );
		exit( -1 );
	}

	width = image.width;
	height = image.height;

	/* Free Up First Image Memory */
	free( image.red );
	free( image.green );
	free( image.blue );

	switch( screen_mode )
	{
		case FULL_SCREEN_MODE:
			startx = 1;	/* Change Later!! */
			starty = 1;

			if( startx < 0  || starty < 0 )
			{
				C_error_message("Try a smaller zoom factor!");
				exit(0);
			}
			break;

		case WINDOW_MODE:
			startx = 1;
			starty = 1;
			break;
	}

	endx = startx + width - 1;
	endy = starty + height - 1;

	prefposition( 0, width*zoom_factor, 0, height*zoom_factor );

	winopen( "Animate" );
	RGBmode();
	doublebuffer();
	gconfig();

	RGBcolor( 0, 0, 0 );

	clear();
	swapbuffers();
	clear();

	num_images = 0;

	while ( ((fd = open(final, O_RDONLY ) ) >= 0) && 
		(num_images < MAX_IMAGES) &&
		(num_images < image_limit))
	{
		close(fd);
		
		status = C_read_image_from_file( &image, final );
		if( status == C_ERROR )
		{
			sprintf( msg, "Problem Opening %s", final );
			C_error_message( msg );
			exit( -1 );
		}

		rptr = image.red;
		gptr = image.green;
		bptr = image.blue;

		images[num_images] = (unsigned long *)
			malloc( width * height * sizeof(long) );
		if( images[num_images] == NULL )
		{
			sprintf(msg, "Could NOT Allocate Memory For Image: %d", 
				num_images );
			C_error_message( msg );
			exit( -2 );
		}

		iptr = images[num_images];

		for ( loop = 0; loop < (width*height); loop++)
		{
		   *(iptr++) =   (*(rptr++)) +
				((*(gptr++))<<8) +
				((*(bptr++))<<16);
		}

		free( image.red );
		free( image.green );
		free( image.blue );

		num_images++;

		sprintf(final, "%s.%d.img", argv[1], (num_images+image_start));

	}

	rectzoom( (float) zoom_factor, (float) zoom_factor );

    	qdevice(LEFTMOUSE);
    	qdevice(MIDDLEMOUSE);
    	qdevice(MENUBUTTON);
    	qdevice(INPUTCHANGE);
    	qdevice(LEFTARROWKEY);
    	qdevice(RIGHTARROWKEY);

	menu = defpup("animate %t|stop|loop|swing|mousepos|for/back|slower|faster|exit");

	delay_time = 0.0;

	current_frame = 0;

	mode = LOOPING;

	direction = FORWARD;

	pixmode( PM_TTOB, TRUE );

	while( 1 )
	{
            if(mode == LOOPING) 
	    {
                while(!qtest())
                    step();
            }
            if(mode == SWINGING) 
	    {
                while(!qtest())
                    swing();
            }
	    switch(qread(&val))
	    {
		case LEFTARROWKEY:
			if(val)
			{
				direction = BACK;
				step();
			}
			break;
		case RIGHTARROWKEY:
			if(val)
			{
				direction = FORWARD;
				step();
			}
			break;
		case MIDDLEMOUSE:
			if(val)
			{
				direction = FORWARD;
				while(getbutton(MIDDLEMOUSE))
					step();
			}
			break;
		case LEFTMOUSE:
			if(val)
			{
				if(mode == MOUSEPOS)
				{
				    while(getbutton(LEFTMOUSE))
				      gotoframe((int)(num_images*fgetmousex()));
                    		} 
				else 
				{
				    direction = BACK;
				    while(getbutton(LEFTMOUSE))
					step();
				}
			}
			break;

		case MENUBUTTON:
			if(val)
			{
				switch(dopup(menu))
				{
                        		case 1:
                         	   		mode = STOPPED;
                            			break;
                        		case 2:
                            			mode = LOOPING;
                            			break;
                        		case 3:
                            			mode = SWINGING;
                            			break;
                        		case 4:
                            			mode = MOUSEPOS;
                            			break;
                        		case 5:
                            			mode = FORBACK;
                            			break;
					case 6:		/* Slower */
						delay_time += TIME_INCREMENT;
						break;
					case 7:		/* Faster */
						delay_time -= TIME_INCREMENT;
						if( delay_time < 0.0 )
							delay_time = 0.0;
						break;
					case 8:
						free_memory();
						exit();
                    		}
                	}

			break;

		}
					
	}

}

display_frame( frame_number )
{
	/* Delay Image Display */
	if( delay_time != 0.0 )
		C_wait( delay_time );

	lrectwrite(startx, starty, endx, endy, images[frame_number]);
}

free_memory()
{
	int	loop;

	for( loop=0; loop<num_images; loop++ )
	{
		free( images[loop] );
	}
}

back()
{
    current_frame--;
    if(current_frame<0)
        current_frame = num_images-1;
    display_frame(current_frame);
    swapbuffers();
}

forward()
{
    current_frame++;
    if(current_frame >= num_images)
        current_frame = 0;
    display_frame(current_frame);
    swapbuffers();
}

step()
{
    if(direction == FORWARD)
        forward();
    else
        back();
}

swing()
{

    if(current_frame == 0)
        direction = FORWARD;
    if(current_frame == num_images-1)
        direction = BACK;
    step();
}

gotoframe(n)
int n;
{
    if(n >= num_images)
        n = num_images-1;
    if(n<0)
        n = 0;
    if(n!=current_frame) {
        current_frame = n;
        display_frame(current_frame);
        swapbuffers();
    }
}


float fgetmousex()
{
    long xorg, yorg;
    long xsize, ysize;

    getsize(&xsize,&ysize);
    getorigin(&xorg,&yorg);
    return ((float)getvaluator(MOUSEX)-xorg)/(float)xsize;
}

C_message( string )
char	*string;
{
	printf("%s\n", string );
}

C_error_message( string )
char	*string;
{
	printf("ERROR: %s\n", string );
}
