/*-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc., and/or its licensors.  All 
// rights reserved.
// 
// The coded instructions, statements, computer programs, and/or related 
// material (collectively the "Data") in these files contain unpublished 
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
// licensors,  which is protected by U.S. and Canadian federal copyright law 
// and by international treaties.
// 
// The Data may not be disclosed or distributed to third parties or be 
// copied or duplicated, in whole or in part, without the prior written 
// consent of Autodesk.
// 
// The copyright notices in the Software and this entire statement, 
// including the above license grant, this restriction and the following 
// disclaimer, must be included in all copies of the Software, in whole 
// or in part, and all derivative works of the Software, unless such copies 
// or derivative works are solely in the form of machine-executable object 
// code generated by a source language processor.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, 
// OR ARISING FROM A COURSE OF DEALING, USAGE, OR TRADE PRACTICE. IN NO 
// EVENT WILL AUTODESK AND/OR ITS LICENSORS BE LIABLE FOR ANY LOST 
// REVENUES, DATA, OR PROFITS, OR SPECIAL, DIRECT, INDIRECT, OR 
// CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK AND/OR ITS LICENSORS HAS 
// BEEN ADVISED OF THE POSSIBILITY OR PROBABILITY OF SUCH DAMAGES. 
// ==========================================================================
*/

/*
 * mocapserver.h - Definitions for writing motion capture servers for
 *	         Maya
 *
 */

#if !defined(__CAPSERVER_H__)
#define __CAPSERVER_H__ 1

#if defined(__cplusplus)
extern "C" {
#endif

#ifdef _WIN32
#define PROTOTYPES
#endif

/*
 * Use the high level "am i in the devkit" flag to control the rotation
 * order flag
 */
#define CAP_ROTATION_ORDER_MAYA 1
#define CAP_ROTATION_ORDER_KIN  0
#ifndef CAP_ROTATION_ORDER
#	ifdef MAYA_MOCAP_DEVKIT
#		define CAP_ROTATION_ORDER CAP_ROTATION_ORDER_MAYA
#	else
#		define CAP_ROTATION_ORDER CAP_ROTATION_ORDER_KIN
#	endif
#endif

/*
 * Define basic motion capture types
 */

typedef struct _CapChannel *CapChannel;	/* Opaque pointer to a channel */

typedef float CapPosition[3];	/* A 3D position */

typedef float CapQuaternion[4];	/* A quaternion */

typedef float CapMatrix[4][4];	/* A 4x4 matrix */

typedef float CapMatrix3[3][3];	/* A 3x3 matrix */

/*
 * Enumerated types
 */

typedef enum CapSeverity
{
  CAP_SEV_DEBUG,
  CAP_SEV_INFO,
  CAP_SEV_WARNING,
  CAP_SEV_ERROR,
  CAP_SEV_FATAL,
  _CAP_SEV_LAST
} CapSeverity;

/*
 * Note: don't change the order of these.  They match the
 * TrackUsage enum in track.h. (At least UNKNOWN through LENS do.)
 */
typedef enum CapChannelUsage
{
  CAP_USAGE_NONE = -1,
  CAP_USAGE_UNKNOWN,
  CAP_USAGE_POSITION,
  CAP_USAGE_ORIENTATION,
  CAP_USAGE_XPOS,
  CAP_USAGE_YPOS,
  CAP_USAGE_ZPOS,
  CAP_USAGE_XROT,
  CAP_USAGE_YROT,
  CAP_USAGE_ZROT,
  CAP_USAGE_XSCALE,
  CAP_USAGE_YSCALE,
  CAP_USAGE_ZSCALE,
  CAP_USAGE_SCALE,
  CAP_USAGE_ATTACH,
  CAP_USAGE_COUPLING,
  CAP_USAGE_FILEINTERP,
  CAP_USAGE_SHAPE,
  CAP_USAGE_WEIGHT,
  CAP_USAGE_HITHER,
  CAP_USAGE_YON,
  CAP_USAGE_LENS,
  CAP_USAGE_POS_ORIENT,
  _CAP_USAGE_LAST
} CapChannelUsage;

/*
 * Rotation order for converting Euler angles to quaternions
 */
typedef enum CapRotationOrder
{
  /*
   * these rotation orders are kept for backward compatibility
   * and define rotations compatible with Kinemation/TAV naming
   */
  CAP_ROT_XYZ_KIN,
  CAP_ROT_XZY_KIN,
  CAP_ROT_YXZ_KIN,
  CAP_ROT_YZX_KIN,
  CAP_ROT_ZXY_KIN,
  CAP_ROT_ZYX_KIN,

  /*
   * the following rotation order names are reversed from the
   * Kinemation/TAV set but are compatible with PA/Maya names
   */ 

  CAP_ROT_XYZ_MAYA = CAP_ROT_ZYX_KIN,
  CAP_ROT_XZY_MAYA = CAP_ROT_YZX_KIN,
  CAP_ROT_YXZ_MAYA = CAP_ROT_ZXY_KIN,
  CAP_ROT_YZX_MAYA = CAP_ROT_XZY_KIN,
  CAP_ROT_ZXY_MAYA = CAP_ROT_YXZ_KIN,
  CAP_ROT_ZYX_MAYA = CAP_ROT_XYZ_KIN

} CapRotationOrder;

/*
 * This allows us to neither break old code, nor have to rewrite the
 * the entire interface for a consistant "guard_string" implementation
 */
#if CAP_ROTATION_ORDER == CAP_ROTATION_ORDER_MAYA
#	define CAP_ROT_XYZ CAP_ROT_XYZ_MAYA
#	define CAP_ROT_XZY CAP_ROT_XZY_MAYA
#	define CAP_ROT_YXZ CAP_ROT_YXZ_MAYA
#	define CAP_ROT_YZX CAP_ROT_YZX_MAYA
#	define CAP_ROT_ZXY CAP_ROT_ZXY_MAYA
#	define CAP_ROT_ZYX CAP_ROT_ZYX_MAYA
#elif CAP_ROTATION_ORDER == CAP_ROTATION_ORDER_KIN
#	define CAP_ROT_XYZ CAP_ROT_XYZ_KIN
#	define CAP_ROT_XZY CAP_ROT_XZY_KIN
#	define CAP_ROT_YXZ CAP_ROT_YXZ_KIN
#	define CAP_ROT_YZX CAP_ROT_YZX_KIN
#	define CAP_ROT_ZXY CAP_ROT_ZXY_KIN
#	define CAP_ROT_ZYX CAP_ROT_ZYX_KIN
#else
	This compiler error indicates that you have not set a valid
	value for the symbol CAP_ROTATION_ORDER.
#endif

typedef enum CapCommand
{
  CAP_CMD_ERROR,
  CAP_CMD_AUTHORIZE,
  CAP_CMD_INIT,
  CAP_CMD_VERSION,
  CAP_CMD_INFO,
  CAP_CMD_DATA,
  CAP_CMD_START_RECORD,
  CAP_CMD_STOP_RECORD,
  CAP_CMD_CLOSE,
  CAP_CMD_QUIT,
  _CAP_CMD_LAST
} CapCommand;

/*
 * Figure out if we should use prototypes or not
 */

#if !defined(_PROTO)
#if defined(PROTOTYPES) || defined(FUNCPROTO) || defined(__STDC__) || defined(__EXTENSIONS__) || defined(__cplusplus)
#define _PROTO(x)	x
#else
#define _PROTO(x)	()
#endif
#endif // !defined(_PROTO)

/*
 * Capture library function declarations/prototypes
 */

int	CapWaitTimeout _PROTO((int fd, int msec));

/*  ========== CapDaemonize ==========
 *
 *  SYNOPSIS
 *      Turn this process into a daemon
 *
 *  PARAMETERS
 *      None
 *
 *  DESCRIPTION
 *	This routine turns the current process into a daemon process.
 *	A daemon process runs in the background in its own process
 *	group with no controlling terminal.  Important signals are
 *	also handled correctly.
 *
 *  RETURN VALUE
 *      0 if no error occurred or -1 if there was a problem.
 *	if -1 is returned, errno is set appropriately.
 * 
 *  NOTES
 *	On Unix, this routine causes the process to make a lot of changes:
 *      o ALL files are closed (including stdin, stdout, and stderr).
 *      o The pid changes (done with fork()).
 *      o The parent pid changes to 1.
 *      o The trapped signals may change (SIGHUP is ignored)
 *      o The current directory changes to /.
 *      o The umask is cleared.
 */
int	CapDaemonize _PROTO((void));

/* ========== CapError ==========
 *
 *  SYNOPSIS
 *	Generate an error message at an appropriate place
 *
 *  PARAMETERS
 *	int	client_fd	File desc of socket to client
 *	CapSeverity severity	The severity of the error
 *	char	*pgm		The name of the program
 *	char	*fmt		A printf style format string
 *	...			Args for the format string as necessary
 *
 *  DESCRIPTION
 *	This routine generates an appropriately placed error message.
 *	If the client file descriptor is valid, the message is passed
 *	to the client.  Otherwise, if we are running as a daemon, the
 *	message is sent to syslog, else it is sent to stderr.
 *
 *  RETURN VALUE
 *      0 if no error occurred or -1 if there was a problem.
 *	if -1 is returned, errno is set appropriately.
 */
int	CapError _PROTO((int client_fd, CapSeverity sev, char *pgm,
			 char *fmt,...));
             
/*  ========== CapServe ==========
 *
 *  SYNOPSIS
 *	Create a socket, wait for a connection and return the file
 *	descriptor.  (This routine is unneeded if the server is
 *	being started by inetd.)
 *
 *  PARAMETERS
 *	char	*server		The server name
 *
 *  DESCRIPTION
 *	This routine takes a server name, creates the socket, and
 *	waits for a connection.  It then removes the original sockets
 *	and returns the connection to the client.
 *
 *	A server name takes one of two formats: either <host>:<port>
 *	or <path>.  The <host>:<port> format creates an Internet
 *	family socket on the LOCAL host (the <host> part is IGNORED)
 *	for the specified port.  The port can be an integer port number
 *	or a service name that can be found by getservbyname().
 *	The <path> format specifies a pathname to use as the address
 *	of a Unix family socket for local connections only.  If 
 *	<path> starts with a '/', it is taken to be an absolute path
 *	otherwise, the path is assumed to be relative to "/tmp/".
 *
 *  RETURN VALUE
 *      The file descriptor on which the client is connected or
 *	-1 if there was some error (errno will be set appropriately).
 */
int	CapServe _PROTO((char *server));

/*  ========== CapCreateInetSocket ==========
 *
 *  SYNOPSIS
 *	Create an internet socket and return its file descriptor
 *
 *  PARAMETERS
 *	char	*service	The service name in /etc/services
 *	short	def_port	The default port number if service does
 *				not work
 *
 *  DESCRIPTION
 *	This routine creates an internet socket and returns its file
 *	descriptor.  If service is not NULL, it is looked up in
 *	/etc/services to get the port number to use.  If it is NULL
 *	or the lookup fails, def_port is used instead.
 *
 *  RETURN VALUE
 *      0 if no error occurred or -1 if there was a problem.
 *	if -1 is returned, errno is set appropriately.
 */
int	CapCreateInetSocket _PROTO((char *service, short def_port));

/*  ========== CapCreateUnixSocket ==========
 *
 *  SYNOPSIS
 *	Create a unix socket and return its file descriptor
 *
 *  PARAMETERS
 *	char	*name		The file name to create.  If the
 *				name does not contain a '/' then
 *				"/tmp/" is prepended.
 *
 *  DESCRIPTION
 *	This routine creates a unix socket and returns its file
 *	descriptor.  If name contains a '/' then use that name
 *	directly.  If it does not contain a '/' then "/tmp/" is
 *	prepended to the name.
 *
 *  RETURN VALUE
 *      0 if no error occurred or -1 if there was a problem.
 *	if -1 is returned, errno is set appropriately.
 */
int	CapCreateUnixSocket _PROTO((char *name));

/*  ========== CapUnlinkUnixSocket ==========
 *
 *  SYNOPSIS
 *	Unlinks a unix socket and return its file descriptor
 *
 *  PARAMETERS
 *	char	*name		The file name to create.
 *
 *  DESCRIPTION
 *	This routine unlinks a unix socket.
 *	If name contains a '/' then use that name
 *	directly.  If it does not contain a '/' then "/tmp/" is
 *	prepended to the name.
 */
void CapUnlinkUnixSocket(char *name);

/*  ========== CapGetCommand ==========
 *
 *  SYNOPSIS
 *	Wait for and return the next command from the client
 *
 *  PARAMETERS
 *	int	client_fd	The socket connection to the client
 *
 *  DESCRIPTION
 *	This routine will read and return the next command from
 *	the client.  Any additional data that is passed with the
 *	command will be saved in a static area for later querying.
 *
 *  RETURN VALUE
 *	A CapCommand value
 */
CapCommand CapGetCommand _PROTO((int client_fd));

/*  ========== CapGetAuthInfo ==========
 *
 *  SYNOPSIS
 *	Return the authorization info that is in the client_query_buf
 *
 *  PARAMETERS
 *	int	client_fd	The client connection
 *	char	*user		The remote user
 *	char	*host		The remote host
 *	char	*realhost	The remote host as looked up from
 *				the address of the client connection
 *
 *  DESCRIPTION
 *	This routine returns the authorization info that is available
 *	if the current command is CAP_CMD_AUTHORIZE.
 *
 *  RETURN VALUE
 *	0 if there is no error or -1 if the last command was not
 *	CAP_CMD_AUTHORIZE.
 */
int	CapGetAuthInfo _PROTO((int client_fd, char *ruser, char *rhost,
			       char *realrhost));

/*  ========== CapInitialize ==========
 *
 *  SYNOPSIS
 *	Initialize the communications link
 *
 *  PARAMETERS
 *	int	client_fd	The client file descriptor
 *
 *  DESCRIPTION
 *	Do the initial handshake with the client and determine
 *	if the two processes can speak the same protocol.
 *
 *  RETURN VALUE
 *	0 if there is no error or -1 if there was some error.
 */
int	CapInitialize _PROTO((int client_fd, char *name));

/*  ========== CapAuthorize ==========
 *
 *  SYNOPSIS
 *	Send authorization back to the client
 *
 *  PARAMETERS
 *	int	client_fd	The client file descriptor
 *	int	authorized	The authorization flag
 *
 *  DESCRIPTION
 *	Tell the client whether he is authorized to use this server
 *	or not.
 *
 *  RETURN VALUE
 *	-1 if there was an error.  0 if everything is Ok.
 */
int	CapAuthorize _PROTO((int client_fd, int authorized));

/*  ========== CapVersion ==========
 *
 *  SYNOPSIS
 *	Send server version info to the client
 *
 *  PARAMETERS
 *	int	client_fd	The client file descriptor
 *	char	*server_name	The name of the server
 *	char	*version	The version number of the server
 *	char	*description	A 1-line description of the server
 *
 *  DESCRIPTION
 *	Send the version information to the client.
 *
 *  RETURN VALUE
 *	0 if no error occurred or -1 if there was an error.
 */
int	CapVersion _PROTO((int client_fd, char *server_name,
			   char *server_version, char *description));

/*  ========== CapInfo ==========
 *
 *  SYNOPSIS
 *	Send channel info from the server to the client.
 *
 *  PARAMETERS
 *	int	client_fd	The client file descriptor
 *
 *  DESCRIPTION
 *	Send a description of the available data from to the client
 *
 *  RETURN VALUE
 *	0 if there was no error or -1 if there was.
 */
int	CapInfo _PROTO((int client_fd, float min_rate, float max_rate,
			float def_rate, unsigned int buf_size, int dynamic));

/*  ========== CapGetRequestedFrame ==========
 *
 *  SYNOPSIS
 *	Return the requested frame that is in the client_query_buf
 *
 *  PARAMETERS
 *	int	client_fd	The client connection
 *
 *  DESCRIPTION
 *	This routine returns the frame number that was passed from the
 *	client with the CAP_CMD_DATA command.
 *
 *  RETURN VALUE
 *	The frame number passed in the CAP_CMD_DATA command or -1 if
 *	there is some error.
 */
int	CapGetRequestedFrame _PROTO((int client_fd));

/*  ========== CapGetRequestedTime ==========
 *
 *  SYNOPSIS
 *	Return the requested time that is in the client_query_buf
 *
 *  PARAMETERS
 *	int	client_fd	The client connection
 *
 *  DESCRIPTION
 *	This routine returns the frame number that was passed from the
 *	client with the CAP_CMD_DATA command.
 *
 *  RETURN VALUE
 *	The frame number passed in the CAP_CMD_DATA command or -1.0 if
 *	there is some error.
 */
float	CapGetRequestedTime _PROTO((int client_fd));

/*  ========== CapData ==========
 *
 *  SYNOPSIS
 *	Send the data to a client
 *
 *  PARAMETERS
 *	int	   client_fd	The client file descriptor
 *
 *  DESCRIPTION
 *	This routine sends all the saved data to the client.
 *
 *  RETURN VALUE
 *	Returns -1 for an error or 0 for no error.  If there is an
 *	error, errno is set to an appropriate value.
 */
int	CapData _PROTO((int client_fd));

/*  ========== CapSetData ==========
 *
 *  SYNOPSIS
 *	Set the data for a channel
 *
 *  PARAMETERS
 *	CapChannel channel	The channel
 *	void	   *data	A pointer to the data
 *
  *  DESCRIPTION
 *	This routine saves the data for later sending to the client.
 *	The data passed in is assumed to match the data type of the
 *	channel.
 *
 *  RETURN VALUE
 *	Returns -1 for an error or 0 for no error.  If there is an
 *	error, errno is set to an appropriate value.
 */
int	CapSetData _PROTO((CapChannel channel, void *data));

/*  ========== CapStartRecord ==========
 *
 *  SYNOPSIS
 *	Start recording
 *
 *  PARAMETERS
 *	int	   client_fd	The client file descriptor
 *	int	   sample_rate	The samples per second
 *
 *  DESCRIPTION
 *	This routine allocates space for recorded data and
 *	tells the client what the sample rate will be
 *
 *  RETURN VALUE
 *	Returns -1 for an error or 0 for no error.  If there is an
 *	error, errno is set to an appropriate value.
 */
int	CapStartRecord _PROTO((int client_fd, float sample_rate,
			       unsigned int buf_size));
                   
int	CapRecord _PROTO((int client_fd, float time));

/*  ========== CapStopRecord ==========
 *
 *  SYNOPSIS
 *	Stop recording and send the recorded data to the client
 *
 *  PARAMETERS
 *	int	   client_fd	The client file descriptor
 *
 *  DESCRIPTION
 *	This routine transmits the recorded data to the client
 *
 *  RETURN VALUE
 *	Returns -1 for an error or 0 for no error.  If there is an
 *	error, errno is set to an appropriate value.
 */
int	CapStopRecord _PROTO((int client_fd));

/*  ========== CapCreateChannel ==========
 *
 *  SYNOPSIS
 *	Create a new channel and add it to the channel hierarchy
 *
 *  PARAMETERS
 *	char       *name	The new channel's name
 *	CapChannelUsage usage	How the channel's data is to be used
 *	int	    data_type	The type of the channel (1, 3, 4, 6, or 7)
 *
 *  DESCRIPTION
 *	This routine creates a new channel in the channel hierarchy
 *	and returns a handle to the new channel.
 *
 *  RETURN VALUE
 *	The handle for the newly created handle or NULL if there was
 *	some error.
 */
CapChannel CapCreateChannel _PROTO((char *name, CapChannelUsage usage,
				    int data_type));
                    
/*  ========== CapGetRequestedRecordRate ==========
 *
 *  SYNOPSIS
 *	Return the record sample rate provided by the client
 *
 *  PARAMETERS
 *	int	client_fd	The client connection
 *
 *  DESCRIPTION
 *	This routine returns the sample rate that was passed from the
 *	client with the CAP_CMD_START_RECORD command.
 *
 *  RETURN VALUE
 *	The sample rate passed in the CAP_CMD_START_RECORD command or -1.0 if
 *	there is some error.
 */
float	CapGetRequestedRecordRate _PROTO((int client_fd));

/*  ========== CapGetRequestedRecordSize ==========
 *
 *  SYNOPSIS
 *	Return the record buffer size provided by the client
 *
 *  PARAMETERS
 *	int	client_fd	The client connection
 *
 *  DESCRIPTION
 *	This routine returns the buffer size that was passed from the
 *	client with the CAP_CMD_START_RECORD command.
 *
 *  RETURN VALUE
 *	The buffer size passed in the CAP_CMD_START_RECORD command or 1 if
 *	there is some error.
 */
int	CapGetRequestedRecordSize _PROTO((int client_fd));

#define EXPAND_ERROR_BUF 256

/*
 *  ========== CapExpandFilename ==========
 *
 *  SYNOPSIS
 *	Expand any environment variables or ~[user] in a filepath
 *
 *  PARAMETERS
 *	char *in_name		the incoming path
 *	char *out_name		the outgoing path  - the caller
 *				must ensure that out_name points to
 *				enough space to hold the expanded result
 *				(MAXPATHLEN, defined in sys/param.h).
 *
 *  DESCRIPTION
 *	CapExpandFilename does the following:
 *	1.  On Unix, look for a ~[username] at the start of in_name,
 *	    which is expanded to the login directory for that user.
 *	2.  Expand any environment variables.  They can be
 *	    anywhere in the in_name, are started with a $, and
 *	    ended with a / or end-of-string.
 *
 *  RETURN VALUE
 *	a pointer to out_name on success
 *	
 *	If the routine fails, the routine returns NULL and
 *	the global string CapExpandErrorMsg contains
 *	the reason for failure. 
 */
extern char   CapExpandErrorMsg[EXPAND_ERROR_BUF];
char   *CapExpandFilename _PROTO((const char *in_name, char *out_name));

/* ***********************************/
/*          Math functions           */
/* ***********************************/

/*  ========== CapQuat2Euler ==========
 *
 *  SYNOPSIS
 *	Convert a quaternion to Euler angles.
 *
 *  PARAMETERS
 *	CapRotationOrder	 order	The order of rotations
 *	CapQuaternion		 q      The quaternion
 *	float               *x	The x-rotation
 *	float               *y	The y-rotation
 *	float               *z	The z-rotation
 *
 *  DESCRIPTION
 *	This routine converts a quaternion to Euler angles.
 *
 *	The quaternion is assumed to be a unit quaternion stored
 *	in w, x, y, z order.
 */
void	CapQuat2Euler _PROTO((CapRotationOrder order, CapQuaternion q,
			      float *x, float *y, float *z));
                  
/*  ========== CapEuler2Quat ==========
 *
 *  SYNOPSIS
 *	Convert Euler angles to a quaternion
 *
 *  PARAMETERS
 *	CapRotationOrder    order	The rotation order
 *	float               x	The x-rotation in radians
 *	float               y	The y-rotation in radians
 *	float               z	The z-rotation in radians
 *	CapQuaternion       q	The quaternion
 *
 *  DESCRIPTION
 *	This routine converts the Euler angles (in the given order)
 *	to a quaternion.
 */
void	CapEuler2Quat _PROTO((CapRotationOrder order, float x, float y,
			      float z, CapQuaternion q));

/*  ========== CapQuat2Matrix ==========
 *
 *  SYNOPSIS
 *	Convert a quaternion to a 4x4 matrix
 *
 *  PARAMETERS
 *	CapQuaternion       q	The quaternion
 *	CapMatrix           m	The matrix
 *
 *  DESCRIPTION
 *	This routine converts a quaternion to a matrix.
 */
void	CapQuat2Matrix _PROTO((CapQuaternion q, CapMatrix m));

/*  ========== CapMatrix2Quat ==========
 *
 *  SYNOPSIS
 *	Convert (the orientation part of) a 4x4 matrix to a quaternion
 *
 *  PARAMETERS
 *	CapMatrix           m	The matrix
 *	CapQuaternion       q	The quaternion
 *
 *  DESCRIPTION
 *	This routine takes the upper-left 3x3 submatrix from a 4x4 and
 *	converts it to a quaternion.
 */
 void	CapMatrix2Quat _PROTO((CapMatrix m, CapQuaternion q));

/*  ========== CapQuat2Matrix3 ==========
 *
 *  SYNOPSIS
 *	Convert a quaternion to a 3x3 matrix
 *
 *  PARAMETERS
 *	CapQuaternion       q	The quaternion
 *	CapMatrix3          m	The matrix
 *
 *  DESCRIPTION
 *	This routine converts a quaternion to a 3x3 matrix.
 */
void	CapQuat2Matrix3 _PROTO((CapQuaternion q, CapMatrix3 m));

/*  ========== CapMatrix32Quat ==========
 *
 *  SYNOPSIS
 *	Convert a 3x3 matrix to a quaternion
 *
 *  PARAMETERS
 *	CapMatrix3          m	The 3x3 matrix
 *	CapQuaternion       q	The quaternion
 *
 *  DESCRIPTION
 *	This routine converts a 3x3 rotation matrix to a quaternion.
 */
void	CapMatrix32Quat _PROTO((CapMatrix3 m, CapQuaternion q));

/*  ========== CapQuatMult ==========
 *
 *  SYNOPSIS
 *	Multiply 2 quaternions
 *
 *  PARAMETERS
 *	CapQuaternion		 q1	A quaternion
 *	CapQuaternion		 q2	A quaternion
 *	CapQuaternion		 q0	The result
 *
 *  DESCRIPTION
 *	This routine creates a composite quaternion that is equivalent
 *	to rotating by q2, then q1.
 */
void	CapQuatMult _PROTO((CapQuaternion q1, CapQuaternion q2,
			    CapQuaternion q0));

/*  ========== CapQuatRotate ==========
 *
 *  SYNOPSIS
 *	Rotate a vector by a quaternion
 *
 *  PARAMETERS
 *	CapQuaternion	  q		The quaternion
 *	CapPosition	  p		The point
 *	CapPosition	  r		The result
 *
 *  DESCRIPTION
 *	This routine rotates the point p by the quaternion q and stores
 *	the result in r.
 *
 *  NOTES
 *	This assumes that the quaternion q is normalized
 */
void	CapQuatRotate _PROTO((CapQuaternion q, CapPosition p,
			      CapPosition r));

/*  ========== CapQuatMagnitude ==========
 *
 *  SYNOPSIS
 *	Return the magnitude of a quaternion
 *
 *  PARAMETERS
 *	CapQuaternion		 q	The quaternion
 *
 *  RETURN VALUE
 *	The magnitude of the quaternion.
 *
 *  DESCRIPTION
 *	This routine returns the magnitude of a quaternion.
 */
float	CapQuatMagnitude _PROTO((CapQuaternion q));

/*  ========== CapQuatNormalize ==========
 *
 *  SYNOPSIS
 *	Normalize the quaternion
 *
 *  PARAMETERS
 *	CapQuaternion     q		The quaternion
 *
 *  DESCRIPTION
 *	This routine normalizes a quaternion in place.
 */
void	CapQuatNormalize _PROTO((CapQuaternion q, CapQuaternion qn));

/*  ========== CapQuatInvert ==========
 *
 *  SYNOPSIS
 *	Invert a quaternion
 *
 *  PARAMETERS
 *	CapQuaternion     q		The quaternion
 *	CapQuaternion     qi		The inverse quaternion
 *
 *  DESCRIPTION
 *	This routine returns the invers of a quaternion.  The quaternion
 *	does not have to be normalized.
 */
void	CapQuatInvert _PROTO((CapQuaternion q, CapQuaternion qi));

/*  ========== CapEuler2Matrix ==========
 *
 *  SYNOPSIS
 *	Convert Euler angles to a matrix
 *
 *  PARAMETERS
 *	CapRotationOrder  order		The rotation order
 *	float		  x		The x-rotation
 *	float		  y		The y-rotation
 *	float		  z		The z-rotation
 *	CapMatrix	  m		The matrix
 *
 *  DESCRIPTION
 *	This routine converts the Euler angles (in the given order)
 *	to a matrix.
 */
void	CapEuler2Matrix _PROTO((CapRotationOrder order, float x, float y,
				float z, CapMatrix m));
                
/*  ========== CapEuler2Matrix3 ==========
 *
 *  SYNOPSIS
 *	Convert Euler angles to a 3x3 matrix
 *
 *  PARAMETERS
 *	CapRotationOrder  order		The rotation order
 *	float		  x		The x-rotation
 *	float		  y		The y-rotation
 *	float		  z		The z-rotation
 *	CapMatrix3	  m		The 3x3 matrix
 *
 *  DESCRIPTION
 *	This routine converts the Euler angles (in the given order)
 *	to a 3x3 matrix.
 */
void	CapEuler2Matrix3 _PROTO((CapRotationOrder order, float x, float y,
				 float z, CapMatrix3 m));

/*  ========== CapMatrix2Euler ==========
 *
 *  SYNOPSIS
 *	Convert a matrix to Euler angles.
 *
 *  PARAMETERS
 *	CapRotationOrder	 ord	The order of rotations
 *	CapMatrix		 m	The matrix
 *	float			*x	The x-rotation
 *	float			*y	The y-rotation
 *	float			*z	The z-rotation
 *
 *  DESCRIPTION
 *	This routine converts a matrix to Euler angles.
 */
void	CapMatrix2Euler _PROTO((CapRotationOrder ord, CapMatrix m,
				float *x, float *y, float *z));

/*  ========== CapMatrix32Euler ==========
 *
 *  SYNOPSIS
 *	Convert a 3x3 matrix to Euler angles.
 *
 *  PARAMETERS
 *	CapRotationOrder	 ord	The order of rotations
 *	CapMatrix3		 m	The 3x3 matrix
 *	float			*x	The x-rotation
 *	float			*y	The y-rotation
 *	float			*z	The z-rotation
 *
 *  DESCRIPTION
 *	This routine converts a matrix to Euler angles.
 */
void	CapMatrix32Euler _PROTO((CapRotationOrder ord, CapMatrix3 m,
				 float *x, float *y, float *z));

#if defined(__cplusplus)
}
#endif

#endif /* __CAPSERVER_H__ */
