/* NAME = utilb.c */
/************************************************************/
/*    utilb.c: Module d'interfacage d'anyflo avec le C      */
/*       Sun 29-02-2015 (16.3) (Michel BRET)                */
/************************************************************/

/************************************************************************/
/*                                                                      */
/*        DEVELOPPEMENT D'UNE APPLICATION                               */
/*                                                                      */
/*    Toute commande multiple contenant un mot défini par               */
/* l'utilisateur (par exemple com0 défini dans komc.h                   */
/* correspondant à son numéro interne compris entre 400 599             */
/* defini dans defc.h) est passé à la fonction                          */
/* EVALUER_2(pd0, suite, fin, pd_eg) définie dans ce fichier            */
/* (voir  "application" dans AIDE_ANYFLO.htm qui lance le fichier       */
/* manuel.applic.htm)                                                   */
/*                                                                      */
/*            PRINCIPE D'UTILISATION                                    */
/*                                                                      */
/*    1) Pour modifier des algorithmes d'anyflo, il faut:               */
/*        a) Modifier la fonction correspondante dans ce fichier        */
/*            pers_utilisateur pour la perspective                      */
/*            texture3d_utilisateur pour une texture 3d                 */
/*            lum_utilisateur pour une lumiere                          */
/*            mappe_utilisateur pour une mappe                          */
/*            type_utilisateur pour executer un type                    */
/*            ajust_vol_image_utilisateur pour ajust vol image          */
/*            collision_utilisateur pour les collisions                 */
/*       	fonc_genetique_utilisateur et fonc_particule_utilisateur    */
/*                pour les algorithmes genetiques                       */
/*            DEVICE_UTIL() pour la gestion d'un peripherique (capteur) */ 
/*        b) Linker:                                                    */
/*                Lanver VisualC++ sous Windows                         */
/*                Ou faire make dans /usr/anyflo sous UNIX              */
/*                                                                      */
/*    2) Pour ajouter des commandes dans anyflo il faut:                */
/*        a) Ajouter leurs noms dans /usr/anyflo/komc.h                 */
/*        b) Ajouter leurs #define dans defc.h                          */
/*        c) Ecrire les fonctions les executant dans EVALUER_2          */
/*        d) Linker                                                     */
/*                                                                      */
/************************************************************************/

/***************************************************************/
/*            PILE DE PASSAGE DES PARAMETRES                   */
/*        entre l'interpreteur et l'application                */
/*                                                             */
/*    com1(p1) com2(p2) .... comn(pn):                         */
/*        execute et retourne une valeur                       */
/*    com1(p1) com2(p2) .... comn(pn) = pd_eg:                 */
/*        execute selon les valeurs de pd_eg                   */
/*                                                             */
/*    pd0 -> (dim,MULT,n,0)(COM1)(COM2)...                     */
/*        dim = taille (en 32 bits) du buffer                  */
/*        n = nombre de commandes                              */
/*        COMi = (dim,env,num)(datas)                          */
/*            env = numero de l'environnement                  */
/*                0: Interpreteur (commandes de koma.h)        */
/*                1: Anyflo (commandes de komb.h)              */
/*                2: Utilisateur (commandes de komc.h)         */
/*            num = numero de la commande                      */
/*            si dim > 3:                                      */
/*                datas = (dim,type,np,dimp)(valeurs)          */
/*                    dim = taille du buffer                   */
/*                    type = type des valeurs                  */
/*                        A_LONG: Entiers                      */
/*                        A_FLOAT: Flottants                   */
/*                        A_CHAR: Caracteres                   */
/*                        HYBRIDE:                             */
/*                            Il y a np bloc de valeurs        */
/*                            de format datas                  */
/*                                                             */
/*    Si pd_eg != 0: pd_eg -> expression evaluee selon un      */
/*    format datas = (dim,type,np,dimp)(valeurs)               */
/*                                                             */
/*    Une evaluation peut etre retournee dans pd0 selon un     */
/*    format datas = (dim,type,np,dimp)(valeurs)               */
/*                                                             */
/***************************************************************/

#include "defa.h"
#include "defb.h"
#include "defc.h"
#include "exta.h"
#include "extb.h"

/* ESSAI socket */
#define WIN32_LEAN_AND_MEAN 
#include <winsock.h>
#include <iostream.h>

long EXEC_BRUSH_C(struct Objet *, long);
long EXEC_VOL_C(struct Objet *, long);
long EXEC_VIEW_C(struct Objet *, long);

#include <stdio.h> 
long INIT_SOCK(long *);
long READ_SOCK();
SOCKET Sock;

long EVALUER_2_0(long *, long *, long *, long *);
long EDIT_2(long *, long *, long *, long *);
EVALUER_2_1(long *, long *, long *, long *);

long EVALUER_2_1(long *, long *, long *, long *);

struct Objet *get_pile_d(long, long);

/* =============================== */
/* DEVELOPPEMENT D'UNE APPLICATION */
/* =============================== */

/************************************************************
Exécute la commande multiple:
com0(p0) com_1(p1) ... qui retourne une valeur, ou
com0(p0) com_1(p1) ... = pd_eg qui affecte une valeur
Retourne 0 si OK, < 0 si erreur et > 2 si autre environnement
*************************************************************/

long EVALUER_2(long *pd0, long *suite, long *fin, long *pd_eg)

{
	long n, *pd;

	n = pd0[2];    /* n = nombre de commandes */
	pd = pd0 + DIM_TETE;    /* pd -> 1ère commande (dim,env1,com1)(datas1) */

	while (n --)
	{
		if (pd[1] > 2) return(pd[1]);	/* Autre environnement */
		switch (pd[2])
		{
		case COM0: return(EVALUER_2_0(pd0, pd_eg, suite, fin));	/* ... com0(p0) ... [= pd_eg] */
		case COM1: return(EVALUER_2_1(pd0, pd_eg, suite, fin));	/* ... com0(p0) ... [= pd_eg] */
		/* etc... */
		}
		pd += *pd;
	}

return (0);
}

/************************************************************
Exécute la commande multiple:
com0(p0) com_1(p1) ... qui retourne une valeur, ou
com0(p0) com_1(p1) ... = pd_eg qui affecte une valeur
Retourne 0 si OK, < 0 si erreur et > 2 si autre environnement
*************************************************************/

long EVALUER_2_0(long *pd0, long *pd_eg, long *suite, long *fin)
{
long n, *pd;

	n = pd0[2];    /* multiplicite de la commande */
	pd = pd0 + DIM_TETE;    /* pd -> 1ère commande (dim,env1,com1)(datas1) */

	while (n --)
	{
		if (pd[1] > 2) return(pd[1]);	/* Autre environnement */
		switch (pd[2])
		{
		case EDIT: return(EDIT_2(pd0, pd_eg, suite, fin));	/* editer ... com0(p0) */
		case COM1: return(EVALUER_2_1(pd0, pd_eg, suite, fin));	/* ... com1(p1) ... [= pd_eg] */
		/* etc... */
		}
		pd += *pd;
	}

	return(0);
}

/**************
editer commande
***************/

long EDIT_2(long *pd0, long *pd_eg, long *suite, long *fin)
{
	long n, *pd;
	float *pf;

	n = pd0[2];    /* n = nombre de commandes */
	pd = pd0 + DIM_TETE;    /* pd -> 1ère commande (dim,env1,com1)(datas1) */

	while (n --)
	{
		if (pd[1] > 2) return(pd[1]);	/* Autre environnement */
		switch (pd[2])
		{
		case COM0: return(EVALUER_2_1(pd0, pd_eg, suite, fin));
		/* etc... */
		}
		pd += *pd;
	}
	VOIR_CHAR("%s\n", "EDIT_c()");
	return(0);
}

/************************************************************
Exécute la commande multiple:
com1(p1) com_2(p2) ... qui retourne une valeur, ou
com1(p1) com_2(p2) ... = pd_eg qui affecte une valeur
Retourne 0 si OK, < 0 si erreur et > 2 si autre environnement
*************************************************************/

long EVALUER_2_1(long *pd0, long *pd_eg, long *suite, long *fin)
{
	char *buf;
	long dimc, dim;

	buf = (char *) malloc(100000);

	strcpy(buf, "/* NAME = enva.h */");
	strcat(buf, "/*********************************************************/");
	strcat(buf, "/*    enva.h: Environnement interpreteur                 */");
	strcat(buf, "/*        Version Mon 30-06-2014) (Michel BRET 16.2)     */");
	strcat(buf, "/*********************************************************/");

	dimc = strlen(buf); dim = DIM_TETE + dimc / sizeof(long) + 1;
	*pd0 = DIM_TETE + dim; pd0[1] = A_CHAR; pd0[2] = dimc; pd0[3] = 1;
	strcpy((char *) (pd0 + DIM_TETE), buf);
	free(buf);
	return(0);
}

/******************************
Retourne la pile (env>=2, type)
******************************/

struct Objet *get_pile_c(long env, long type)
{
	switch (env)
	{
	case 2:	/* Environnement actuel */
		switch (type)
		{
		case COM0:	/* A FAIRE */
			break;
		}
	}

	return(0);
}

/***************************************************
Retourne (env,type) de la pile dont p_obj est membre
****************************************************/

struct Objet *get_pile_env_type_c(struct Objet *p_obj, long *env, long *type)
{
	while (1)
	{
		if (p_obj->pere == 0) break;
		p_obj = p_obj->pere;
	}
/* A FAIRE */
}

/***************************
Retourne la pile (env, type)
****************************/

struct Objet *get_pile_d(long env, long type)
{
	return(0);
}

    /***************/
    /* PERSPECTIVE */
    /***************/

/********************************************
num = numero < 0 de la fonction (pers(num)
type1, type2 = ABS, SCREEN, EYE, PERS
pf1 -> point origine, pf2 -> point transforme
*********************************************/

void pers_utilisateur(long num, long type1, long type2, float *pf1, float *pf2)

{
	switch (num)
	{
	case -1:    /* 1ere fonction */
		switch (type1)
		{
		case ABS:
			switch (type2)
			{
			/* Repere absolu -> Repere de l'oeil */
			/* --------------------------------- */
				case EYE:
					break;
			}
			break;
		case SCREEN:
			switch (type2)
			{
			/* Repere de l'ecran -> Repere absolu (pour les mappes) */
			/* ---------------------------------------------------- */
				case ABS:
					break;
			/* Repere de l'ecran -> Repere de l'oeil (pour les mappes) */
			/* ------------------------------------------------------- */
				case EYE:
					break;
			}
			break;
		case EYE:
			switch (type2)
			{
			/* Repere de l'oeil -> Repere de la pers */
			/* ------------------------------------- */
			case PERS:
				break;
			}
			break;
		case PERS:
			switch (type2)
			{
			/* Repere de la pers -> Repere absolu (pour les mappes) */
			/* ---------------------------------------------------- */
			case ABS:
				break;
			/* Repere de la pers -> Repere de l'ecran */
			/* -------------------------------------- */
			case SCREEN:
				break;
			}
			break;
		}
		break;

	case -2:    /* 2eme fonction */
	/* etc ... */
		break;
	}
}

/***********/
/* TEXTURE */
/***********/

/**************************************************
texture3d_utilisateur(pd, cont, p_cou)
code = -1, -2, ...: Code utilisateur
pd -> (dim,type,np,dimp)(datas)
cont -> strcut Contour du point
p_cou -> couleur calculee (normalisee entre 0 et 1
Les datas sont les parametres de:
    texture vol num=code,data
    ou de: texture fac(n1) vol(n2)=code,datas
**************************************************/

void texture3d_utilisateur(long *pd, struct Contour *cont, float *p_cou)

{
	long code, nd;
	float *pf;
	float x, y, z, cr, cv, cb, r, v, b, pr, pv, pb;
	double c, s;

	nd = pd[2] - 1;    /* Nombre de datas */
	pf = (float *) (pd + DIM_TETE);    /* pf -> datas float */
	code = *pf++;
	switch (code)
	{
	case -1:    /* Exemple 1: Sinusoidal */
		x = cont->xa; y = cont->ya; z = cont->za;
		cr = (nd > 0) ? *pf++ : 0.0;
		cv = (nd > 1) ? *pf++ : 0.0;
		cb = (nd > 2) ? *pf : 0.0;
		pr = cr * sin(x + y + z);
		pv = cv * sin(x * y - z);
		pb = cb * sin(0.0 - x + y * z);
		*p_cou++ = 0.25 * ((2 + cos(cr * (x + y + z) + pr)) +
            	1 + sin(cr * (x - y + 2 * z)));
		*p_cou++ = 0.25 * ((2 + cos(cv * (x * y + z) + pv)) +
			1 + sin(cv * (x + y * z)));
		*p_cou = 0.25 * ((2 + cos(cb * (2 * x - 1.5 * y + 0.178 * z) + pb)) +
			1 + sin(cb * (x + 3.5 * y - 0.78 * z)));
		break;
	case -2:    /* Exemple 2: Bump mapping */
		x = cont->xa; y = cont->ya; z = cont->za;
		cr = (nd > 0) ? *pf++ : 0.1;
		cv = (nd > 1) ? *pf++ : 0.1;
		cb = (nd > 2) ? *pf++ : 0.1;
		c = (nd > 3) ? *pf : 0.1;
		cr = cr * cos(c * x); cv = cv * sin(c * y); cb = cb * cos(c * z);
		cont->nx += cr; cont->ny += cv; cont->nz += cb;
		unitaire(&(cont->nx), &(cont->nx));
		*p_cou++ = cont->r / Max_cou;
		*p_cou++ = cont->v / Max_cou;
		*p_cou = cont->b / Max_cou;
		break;
	}
}

/**********/
/* LIGHTS */
/**********/

/******************************************************************
ferm = fermer lum numero
(xa,ya,za) = coordonnees absolues du point eclaire
(nx,ny,nz) = normale unitaire a la surface en ce point
(r1,v1,b1) = couleur de la surface en ce point
col (entre 0 et Max_cou = valeur maximum d'une composante)
(col,spe,bri) = coefficients d'eclairement
    col = 0: Fil de fer
          1: FLAT
          2: Lissage de GOURAUD
          3: Lissage de PHONG
          si col < 0: La normale n'est pas orientee
    spe = specullaire
    bri = brillance
(xs,ys,zs) = position absolue de la lumiere
(rs,vs,bs) = couleur de la lumiere
(r2,v2,b2) = pointeurs vers la couleur calculee (entre 0 et Max_cou)
********************************************************************/

void lum_utilisateur(long ferm, float xa, float ya, float za, float nx, float ny, float nz,
float r1, float v1, float b1, long col, float spe, float bri,
float xs, float ys, float zs, float rs, float vs, float bs, float *r2, float *v2, float *b2)

{
	float k, buf[3];

	switch (ferm)
	{
	case 1:    /* Exemple 1 */
	/* Determiner le vecteur unitaire point -> lumiere */
		*buf = (xs - xa); buf[1] = (ys - ya); buf[2] = (zs - za);
		unitaire(buf, buf);

    /* Composante diffuse = cos(i) */
		k = *buf * nx + buf[1] * ny + buf[2] * nz;

	/* Determiner la lumiere renvoyee par le point */
		r1 = (r1 * rs) / Max_cou; v1 = (v1 * vs) / Max_cou; b1 = (b1 * bs) / Max_cou;
		*r2 = k * r1; *v2 = k * v1; *b2 = k * b1;
		break;

	default:
		*b2 = *v2 = *r2 = 0.0;    /* Securite */
	}
}

/************/
/* TEXTURES */
/************/

/*************************************************************************
pa -> (xa,ya,za) = coordonnees absolues du point
mappe vol nv = num,type,p1,p2,p3,p4,p5,
Si l'image numero num existe buf_mappe -> informations
    buf_mappe->type = type
    buf_mappe->r = p1
    buf_mappe->v = p2
    buf_mappe->b = p3
    buf_mappe->rf,vf,bf = rf,vf,bf
    buf_mappe->mobx = p5
    buf_mappe->moby = p6
    buf_cou -)couleur ajoutee
   (entre 0 et Max_cou = valeur maximum d'une composante)
/*************************************************************************/

void mappe_utilisateur(float *pa, struct Mappe *buf_mappe, float *buf_cou)

{
	switch (buf_mappe->type)
	{
	case -1:    /* Exemple */
		*buf_cou++ += alea(Max_cou);
		*buf_cou++ += alea(Max_cou);
		*buf_cou += alea(Max_cou);
		break;
	}
}

/*********/
/* TYPES */
/*********/

/********************************************
p_vol -> volume courant
n = numero de la fonction a executer
pd0 -> (dim,type,n,1,t1,t2,...,tn)(dim,datas)
Retourne0 et < 0 si erreur
********************************************/

long type_utilisateur(struct Objet *p_vol, long n, long *pd0)

{
	char *pc;
	long type, nb;
	float *pf;

	type = pd0[1];
	pd0 += *pd0;    /* pd0 -> (dim,datas) */
	nb = *pd0++ - 1;
	pf = (float *) pd0;
	pc = (char *) pd0;
	switch (n)
	{
	case 1:
		printf("FUNC UN\n"); break;
	case 2:
		printf("FUNC DEUX\n"); break;
	}

	switch (type)
	{
	case A_FLOAT:
		while (nb-- > 0) printf("%f ", *pf++);
		break;
	case A_CHAR:
		printf("%s", pc);
		break;
	}

	putchar('\n');
	return(0);
}

/********************/
/* ADJUST VOL IMAGE */
/********************/

/*************************************************************
p_exec -> (code,datas) de ajust(code,datas)vol image
(r1,v1,b1) = moyenne de la couleur (ou du tsv) autour du point
pf -> Coordonnees absolues du point
sem_tsv = COL ou HSV
Retourne < 0 si erreur
*************************************************************/

long ajust_vol_image_utilisateur(long *p_exec, double r1, double v1, double b1,
float *pf, long sem_tsv)

{
	long n, code;
	float cr, cv, cb, amplitude, frequence, seuil;
	float *p_datas;

	if ((n = p_exec[2]) > 0)
	{
		p_datas = (float *) (p_exec + DIM_TETE); code = *p_datas++;
		switch (code)
		{
		case 1:    /* Le cas d'anyflo ... */
			cr = (n > 1) ? *p_datas++ : 0.0;
			cv = (n > 2) ? *p_datas++ : 0.0;
			cb = (n > 3) ? *p_datas : 0.0;
			pf[2] -= (cr * r1 + cv * v1 + cb * b1) / 3.0;
			break;

		case 2:    /* Exemple avec un sinus */
			amplitude = (n > 1) ? *p_datas++ : 0.0;
			frequence = (n > 2) ? *p_datas++ : 0.0;
			switch (sem_tsv)
			{
			case COL:
				pf[2] -= amplitude * sin(frequence * 2 * PI * (r1 + v1 + b1) / 3.0);
				break;
			case HSV:
				pf[2] -= amplitude * sin(frequence * 2 * PI * r1 / 360.0);
				break;
		}
		break;

		case 3:    /* Seuillage */
			amplitude = (n > 1) ? *p_datas++ : 100.0;
			seuil = (n > 2) ? *p_datas++ : 0.5;
			pf[2] = ((r1 + v1 + b1) / 3.0 < seuil) ? 0.0 : amplitude;
			break;
		case 4:    /* Bruit */
			amplitude = (n > 1) ? *p_datas++ : 100.0;
			pf[2] = amplitude * (r1 + v1 + b1) * randf(1.0) / 3.0;
			break;
		}
	}

	return(0);
}

/*************/
/* COLLISION */
/*************/

/***********************************
algo = numero de l'algorithme
p_vola -> volume mobile
p_poia -> points de vola
p_volb -> obstacle
p_coe -> coe collision vola
p_coe_som -> coe som collision vola
p_fac_col -> fac collision vola
p_err -> erreur collision vola
Retourne < 0 si erreur
***********************************/

long collision_utilisateur(long algo, struct Objet *p_vola, struct Objet *p_volb,
long *p_poia, long *p_coe, long *p_coe_som, long *p_fac_col, long *p_err)

{
	switch (algo)
	{
	case 1:    /* Algorithme 1 */
		break;
	case 2:    /* Algorithme 2 */
		break;
	/* etc ... */
	}

	return(0);
}

/***********/
/* GENETIC */
/***********/

/*******************************************************
p -> (dim,type,np,dimp)(np particules de dimension dimp)
Evalue dans pfe, retourne < 0 si erreur
*******************************************************/

long fonc_genetique_utilisateur(long num_fonc, long *p, long num, float *pfe)

{
	long dimp;
	float x, y, *pf;

	switch (num_fonc)
	{
	/* Exemple 1: p est un vecteur de dimp floats (0.0 ou 1.0)
	   la valeur retournee est le nombre code en binaire */
	case 1:
		dimp = p[3];    /* Dimension du vecteur */
		pf = (float *) (p + DIM_TETE) + dimp * (num - 1);
		x = 0.0; y = 1.0;
		while (dimp-- > 0)
		{
			x += y * *pf++; y *= 2.0;
		}
		*pfe = x;
		break;
	}

	return(0);
}

/*****************************************************
num = numero de la fonction executee (entre 1 et 1000)
Evalue dans pfe
Retourne < 0 si erreur
*****************************************************/

long fonc_particule_utilisateur(long num, float *pfe)

{
	switch (num)
	{
	case 1:
		break;
	case 2:
		break;
	}

	printf("num = %d\n", num);
	*pfe = 1.0;

	return(0);
}

/* Version du 17-07-2002 Michel Bret d'apres Workingsocket */
/*      Visual C++ Project | Settings | Link | Object/Library modules | ws2_32.lib */

/*****************************************************************
serveur: Lance le serveur qui attend une connection avec un client
client0 lepetitlabo: Lance le client sur la machine lepetitlabo
	client envoie -> serveur recoit
exit serveur -> exit cliend
******************************************************************/

/*
#define WIN32_LEAN_AND_MEAN 
#include <winsock2.h> 
#include <iostream.h>

#include <stdio.h>
*/

long INIT_SOCK(long *pd0)
{

char                    buffer[128], buf[128]; 
int                     retval, stat; 
unsigned int            addr=0;
long cpt; 
struct sockaddr_in      sin; 
struct hostent          *host; 
WSADATA                 wsaData; 

printf("LANCEMENT CLIENT\n");;

WSAStartup(0x202,&wsaData);   // Startup 
  
host = gethostbyname("secousse");

// Try DNS lookup
if (!host)   
// DNS failed try as IP
	addr = inet_addr("secousse");  
printf("host = %d addr = %d\n", host, addr);
  
if ((!host)  && (addr == INADDR_NONE) )
	{   
    // DNS and IP failed 
    printf("Unable to resolve \n"); 
    return -1; 
	} 
  
if (host != NULL)
	{   
    // Copy server info 
    memcpy(&(sin.sin_addr),host->h_addr,host->h_length); 
    sin.sin_family = host->h_addrtype; 
	}
else
	{
    sin.sin_addr.s_addr = addr; 
    sin.sin_family = AF_INET; 
	}

// Create socket 
sin.sin_port = htons(8889);
if ((Sock = socket(AF_INET, SOCK_STREAM,0)) == INVALID_SOCKET)
	{  
    printf("socket() failed\n"); 
    return -1; 
	}            
printf("create socket %d\n", Sock);
 
// Connect to server port
if (connect(Sock,(struct sockaddr*)&sin,sizeof(sin)) == INVALID_SOCKET)
	{ 
    printf("connect() failed\n"); 
    return -1; 
	} 
printf("CONNECTION OK\n");

return(0);
}

long READ_SOCK()
{
char buf[128];
long stat, retval, nb, att, i;

	sprintf(buf, "ENVOI\n"); 
	if ((stat = send(Sock,buf,strlen(buf),0)) == SOCKET_ERROR )
		goto erreur;
	if ((stat = send(Sock,"\0",1,0)) == SOCKET_ERROR )
		goto erreur;
printf("send %s\n", buf);

nb = 0; att = 12;
for (i = 0; i < att; i++)
	if (nb = recv(Sock, buf, sizeof(buf), 0) >= 0)
		break;

buf[nb] = 0;





//	retval=recv(Sock,buf,sizeof(buf),0);                       
printf("recv %s\n", buf);

/*
closesocket(s);             // Close connection   
cout << "Closed connection.\n"; flush(cout);
*/
return 0;

erreur:
printf("ERROR send %d\n", stat);
closesocket(Sock);             // Close connection   
//cout << "Closed connection.\n"; flush(cout);
return(0);
}

/***************/
/* INTERACTION */
/***************/

/*****************************************************************************************
La gestion de l'interaction par interaction fonc(i,"fi") est doublée
d'appels aux fonctions _F_i() (ecrites dans utilb.c),
ces fonctions retournent 0 et -1 en cas d'erreur (provoque la sortie du mode interaction).

interaction fonc(0,"f0");
interaction fonc(1,"f1");
interaction fonc(2,"f2");
interaction fonc(3,"f3");
interaction fonc(4,"f4");
interaction fonc(5,"f5");
         Les fonctions _F_i() et fi() sont exécutées dans l'ordre suivant:
_F_0();f0();
_F_1();f1(); 
trajectoires(); 
_F_2();f2(); 
dynamique(); 
_F_3();f3(); 
collisions();automatismes(); 
_F_4();f4(); 
ecran ;affichages(); 
_F_5();f5(); 
*****************************************************************************************/

/* Fonction executee une seule fois */
/* -------------------------------- */

long _F_0()
{
	return(0);
}

/* Fonction executee a chaque image avant les trajectoires */
/* ------------------------------------------------------- */

long _F_1()
{
	return(0);
}

/* Fonction executee a chaque image avant la dynamique */
/* --------------------------------------------------- */

long _F_2()
{
	return(0);
}

/* Fonction executee a chaque image avant les collisions */
/* ----------------------------------------------------- */

long _F_3()
{
	return(0);
}

/* Fonction executee a chaque image avant ll'affichage */
/* --------------------------------------------------- */

long _F_4()
{
	return(0);
}

/* Fonction executee a chaque image apres l'affichage */
/* -------------------------------------------------- */

long _F_5()
{

/* Exemple: variation de la couleur du fond
	static float c = 0.0;
	*Pf_fond = Pf_fond[1] = Pf_fond[2] = c;
	c += 0.01; if(c > 1.0) c = 0.0;
*/
	return(0);
}

/******************************************/
/* GESTION DES DEVICEERIQUES UTILISATEURS */
/******************************************/

/******
A FAIRE
*******/

long DEVICE_UTIL(long *pd0, long *suite, long *fin, long *pd_eg)
{
	return(0);
}

/***************************************/
/* EXECUTION DES FUNCTIONS LOCALE en C */
/***************************************/

long EXEC_C(struct Objet *p_obj, long num)
{
	switch (p_obj->type_1)
	{
	case BRUSH: return(EXEC_BRUSH_C(p_obj, num));
	case VOL: return(EXEC_VOL_C(p_obj, num));
	case VIEW: return(EXEC_VIEW_C(p_obj, num));
	}
	return(0);
}

long EXEC_VOL_C(struct Objet *p_obj, long num)
{
	switch (num)
	{
	case 0:	/* 1er algorithme */
		break;
	}
	return(0);
}

long EXEC_VIEW_C(struct Objet *p_obj, long num)
{
	switch (num)
	{
	case 0:	/* 1er algorithme */
		break;
	}
	return(0);
}

long EXEC_BRUSH_C(struct Objet *p_obj, long num)
{
	switch (num)
	{
	case 0:	/* 1er algorithme */
		break;
	}
	return(0);
}

/******************************
p_obj -> field
num = numero > 0 de la fonction
poi -> point, force -> force
*******************************/

long field_utilisateur(struct Objet *p_obj, long num, float *poi, float *force)

{
	long *p;
	float c;
	float poi0[3], normal[3];
	float *pf_poi;

	if (p = GET_DATAS_1(p_obj->bloc, POI))
	{
		pf_poi = (float *) (p + DIM_TETE);
		*poi0 = *poi - *pf_poi; poi0[1] = poi[1] - pf_poi[1]; poi0[2] = poi[2] - pf_poi[2];	/* CP */
	}
	else
	{
		*poi0 = *poi; poi0[1] = poi[1]; poi0[2] = poi[2];	/* CP */
	}

	switch (num)
	{
	case 1:    /* vortex */
		*normal = 0.0 - poi[1]; normal[1] = *poi; normal[2] = 0.0;	/* normal to CP */
		*force  = 0.0001 * *normal - 0.005 * *poi0;
		force[1]  = 0.0001 * normal[1] - 0.005 * poi0[1];
		force[2]  = 0.0001 * normal[2] - 0.005 * poi0[2];
		break;
	case-2:    /* 2eme fonction */
	/* etc ... */
		break;
	}

	return(0);
}

long TRAJ_FUNC_C(struct Objet *p_obj_traj, long num)
{
	return(0);
}

void IS_NOT_A_GRID()
{
	message(1, 15);
}

/* END */
