/****************************************************************************
 *                  mechsim.h
 *
 *  Author: Christoph Hormann <chris_hormann@gmx.de>
 *
 *  Mechanics simulation
 *
 *  Copyright 2002-2005 Christoph Hormann
 *
 * from Persistence of Vision(tm) Ray Tracer version 3.6.
 * Copyright 1991-2003 Persistence of Vision Team
 * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd.
 *---------------------------------------------------------------------------
 * NOTICE: This source code file is provided so that users may experiment
 * with enhancements to POV-Ray and to port the software to platforms other
 * than those supported by the POV-Ray developers. There are strict rules
 * regarding how you are permitted to use this file. These rules are contained
 * in the distribution and derivative versions licenses which should have been
 * provided with this file.
 *
 * These licences may be found online, linked from the end-user license
 * agreement that is located at http://www.povray.org/povlegal.html
 *---------------------------------------------------------------------------
 * This program is based on the popular DKB raytracer version 2.12.
 * DKBTrace was originally written by David K. Buck.
 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
 *---------------------------------------------------------------------------
 *
 *===========================================================================
 * This file is part of MegaPOV, a modified and unofficial version of POV-Ray
 * For more information on MegaPOV visit our website:
 * http://megapov.inetart.net/
 *===========================================================================
 *
 * $RCSfile: mechsim.h,v $
 * $Revision: 1.13 $
 * $Author: chris $
 *
 *****************************************************************************/ 

#ifndef MECHSIM_H
#define MECHSIM_H
BEGIN_POV_NAMESPACE

/*****************************************************************************
* Global preprocessor defines
******************************************************************************/

#ifndef MECHSIM_DEBUG
#define MECHSIM_DEBUG 0
#endif

#define MECHSIM_METHOD_EULER 1
#define MECHSIM_METHOD_HEUN 2
#define MECHSIM_METHOD_RUNGE_KUTTA4 3
#define MECHSIM_METHOD_GRADIENT 4

#define MECHSIM_FLAG_FIXED 1

#define MECHSIM_COLLISION_NONE 0
#define MECHSIM_COLLISION_ALL 1
#define MECHSIM_COLLISION_GROUP 2

#define MECHSIM_ENV_METHOD_FORCE 1
#define MECHSIM_ENV_METHOD_IMPACT 2

#define MECHSIM_FACE_BOUNDING_AUTO 0
#define MECHSIM_FACE_BOUNDING_NO 1
#define MECHSIM_FACE_BOUNDING_BBOX 2
#define MECHSIM_FACE_BOUNDING_HASH 3

/*****************************************************************************
* Global typedefs
******************************************************************************/

typedef int INT_VECT[3];

/* ------------------------------------------------------ */
typedef struct mechsim_state_struct MECHSIM_STATE;

struct mechsim_state_struct {
  VECTOR Position;
  VECTOR Velocity;
};

/* ------------------------------------------------------ */
typedef struct mechsim_mass_struct MECHSIM_MASS;

struct mechsim_mass_struct {

  int Index;

  VECTOR Position;
  VECTOR Velocity;
	// Yes, we don't need them during the simulation but after it
	// (for being able to access them from SDL)
  VECTOR Acceleration;
  DBL Mass;
  DBL Radius;
  int Flag;
  int Attach;
  int Force;

  int Group;
};

/* ------------------------------------------------------ */
typedef struct mechsim_connect_struct MECHSIM_CONNECT;

struct mechsim_connect_struct {

  int Index;

  int Idx1;
  int Idx2;

  DBL Length;
  DBL Stiffness;
  DBL Damping;

  int Group;
};

/* ------------------------------------------------------ */
typedef struct mechsim_face_struct MECHSIM_FACE;

struct mechsim_face_struct {

  int Index;

  int Idx1;
  int Idx2;
  int Idx3;

  int Group;
};

/* ------------------------------------------------------ */
typedef struct mechsim_group_struct MECHSIM_GROUP;

struct mechsim_group_struct {

  int max_masses;
  int max_connects;
  int max_faces;

  int mass_count;
  int connect_count;
  int faces_count;

  MECHSIM_MASS **Masses;
  MECHSIM_CONNECT **Connects;
  MECHSIM_FACE **Faces;
};

/* ------------------------------------------------------ */

typedef struct mechsim_ve_element_struct MECHSIM_VE_ELEMENT;

struct mechsim_ve_element_struct {

  DBL Y;
  DBL Stiffness;
  DBL Damping;
};

typedef struct mechsim_viscoelastic_struct MECHSIM_VISCOELASTIC;

struct mechsim_viscoelastic_struct {

  int Index;

  int Idx1;
  int Idx2;

  DBL Length;
  DBL Stiffness0;
	int element_count;
	int Accuracy;
  MECHSIM_VE_ELEMENT *Element;
};


/* ------------------------------------------------------ */
typedef struct bounding_hashtable_item BOUNDING_HASHTABLE_ITEM;

struct bounding_hashtable_item {
  int time_stamp; // time stamp of this item
  int size; // size of the index list
  int used; // used size of the index list
  int *index; // index list
};

/* ------------------------------------------------------ */
typedef struct mechsim_bounding_data MECHSIM_BOUNDING_DATA;

struct mechsim_bounding_data {
  int time_stamp; // current time stamp for faster updating of the hashing list
  SNGL_VECT Unit; // unit size of the grid
  int intersect_list_size; // size of the intersection list for hashing
  int intersect_list_index; // current index of the intersection list for hasing
  int* intersect_list; // the intersection list for hashing
  int bitfield_size; // size of the bit field
  unsigned int* bitfield; // bit field
  int bounding_hashtable_size; // size of the hashing list
  BOUNDING_HASHTABLE_ITEM* bounding_hashtable; // hashing list
  BBOX* Faces_BBox_Array; // array of bounding boxes used for faces
  BBOX* Face_Groups_BBox_Array; // array of bounding boxes used for groups, bounded objects are faces
  BBOX* Mass_Groups_BBox_Array; // array of bounding boxes used for groups, bounded objects are masses
  BBOX* Connect_Groups_BBox_Array; // array of bounding boxes used for groups, bounded objects are connections
  BBOX* Connects_BBox_Array; // array of bounding boxes used for connections
};

/* ------------------------------------------------------ */
typedef struct mechsim_data_struct MECHSIM_DATA;

struct mechsim_data_struct {

  int max_masses;
  int max_connects;
  int max_faces;
  int max_groups;

  int max_viscoelastics;

  int mass_count;
  int connect_count;
  int faces_count;
  int group_count;

  int ve_count;

  MECHSIM_MASS *Masses;
  MECHSIM_CONNECT *Connects;
  MECHSIM_FACE *Faces;
  MECHSIM_GROUP *Groups;

	MECHSIM_VISCOELASTIC *Viscoelastics;

  OBJECT *Faces_Object;
};

/* ------------------------------------------------------ */
typedef struct mechsim_environment_struct MECHSIM_ENVIRONMENT;

struct mechsim_environment_struct {

  FUNCTION_PTR Function;
  OBJECT *Object;
  DBL Stiffness;
  DBL Damping;
  DBL Friction;
  DBL Friction_Excess;
  unsigned int Method;

  MECHSIM_ENVIRONMENT *Next;
};

/* ------------------------------------------------------ */
typedef struct mechsim_fields_struct MECHSIM_FIELDS;

struct mechsim_fields_struct {

  FUNCTION_PTR *Function;
  int count;
  int max_count;
};

/* ------------------------------------------------------ */
typedef struct mechsim_forces_struct MECHSIM_FORCES;

struct mechsim_forces_struct {

  FUNCTION_PTR *Function;
  int count;
  int max_count;
};

/* ------------------------------------------------------ */
typedef struct mechsim_interactions_struct MECHSIM_INTERACTIONS;

struct mechsim_interactions_struct {

  FUNCTION_PTR *Function;
  int count;
  int max_count;
};

/* ------------------------------------------------------ */
typedef struct mechsim_attachments_struct MECHSIM_ATTACHMENTS;

struct mechsim_attachments_struct {

  FUNCTION_PTR *Function;
	INT_VECT *Fixed;
  int count;
  int max_count;
};

/* ------------------------------------------------------ */
typedef struct mechsim_options_struct MECHSIM_OPTIONS;

struct mechsim_options_struct {

  unsigned int Method;
  int Step_Count;
  DBL Time_Step;
  DBL Start_Time;
  DBL End_Time;
	bool Timing_Given;
	bool Timing_Loaded;

	// for adaptive time stepping
  DBL Accuracy;
  DBL Time_Step_Min;

  // For message output
  int Steps;
  DBL Time;
	DBL TS_Min;
	DBL TS_Max;

  VECTOR gravity;
  DBL Damping;

  MECHSIM_ENVIRONMENT *Environment;
	int Env_max_count;
	int Env_count;

  DBL Collision_Stiffness;
  DBL Collision_Damping;
  DBL Collision_Friction;
  DBL Collision_Friction_Excess;
  int Calc_Collision;
  int Calc_Collision_Faces;
  int Calc_Collision_Connections;

  char* Load_File_Name;
  char* Save_File_Name;

  bool Save_File;
  int Save_File_Type;

  bool Enabled;

  MECHSIM_DATA Data;

  MECHSIM_INTERACTIONS Interactions;
  MECHSIM_ATTACHMENTS Attachments;
  MECHSIM_FIELDS Fields;
  MECHSIM_FORCES Forces;
  
  unsigned int Bounding;
	INT_VECT Fixed;
};

/*****************************************************************************
* Global variables
******************************************************************************/

extern MECHSIM_OPTIONS MechsimOptions;

/*****************************************************************************
* Global functions
******************************************************************************/

DBL Mechsim_Connect_Evaluate(int Idx);
DBL Mechsim_Viscoelastic_Evaluate(int Idx);

bool Mechsim_read_file (IStream * fd, int Group);

void Initialize_MechSim(void);
void Deinitialize_MechSim(void);

void Mechsim_Simulate(void);


END_POV_NAMESPACE

#endif
