begin process at 2012 05 27 16:24:22
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Graphique

 > FONCTIONS DE ROTATION DANS L'ESPACE

FONCTIONS DE ROTATION DANS L'ESPACE


 Information sur la source

Note :
Aucune note
Catégorie :Graphique Niveau :Débutant Date de création :30/10/2004 Date de mise à jour :27/03/2005 19:24:28 Vu :6 965

Auteur : dletozeun

Ecrire un message privé
Commentaire sur cette source (48)
Ajouter un commentaire et/ou une note

 Description

Cet header contient des fonctions permettant de faire tourner un point dans l'espace selon les axes X,Y et Z
L'algorithme est inspiré de la geométrie avec les complexes.

Source

  • #ifndef Rotate
  • #define Rotate
  • #define precision 0.1 // c'est cette valeur qu'il faut changer pour modifier la precision
  • // de cos et sin (multiple de 10 sinon ca créé des tableaux de taille
  • // non entiere
  • #define Pi 3.14159265358 // A Y
  • // |
  • #include <math.h> // |
  • // | X
  • /*Fonctions de rotation dans l'espace par Dletozeun // 0-------->
  • // /
  • Utilisation: // Z /
  • V
  • _les 2 premiers arguments correspondent aux coordonnées dans le plan de rotation du point à faire
  • tourner.
  • _Les arguments Ax et Ay correspondent aux coordonnées du point représentant l'axe de rotation
  • dans le plan de rotation
  • _L'argument alpha représente l'angle de rotation en degrés
  • /!\ NE PAS OUBLIER AVANT D'UTILSER CES FONCTIONS DE LANCER LA FONCTION : init_sin_cos() POUR
  • INITIALISER LES TABLEAUX SIN,COS SINON PLANTAGE GARANTI !!!
  • ET LA FOCNTION : FreeRotate() POUR LIBERER LES TABLEAUX; */
  • float* tabSin;
  • float* tabCos;
  • /*_________________________INITIALISATION DES TABLES COSINUS ET SINUS:__________________________*/
  • void init_sin_cos()
  • {
  • tabSin=(float*)malloc((360/precision)*sizeof(float));
  • tabCos=(float*)malloc((360/precision)*sizeof(float));
  • for(float a=0;a<360;a+=precision)
  • {
  • int pas=(1/precision)*a;
  • float Angle_rad=(a*Pi)/180;
  • tabSin[pas]=sin(Angle_rad);
  • tabCos[pas]=cos(Angle_rad);
  • }
  • }
  • /*FIN DE L'INITIALISATION*/
  • float Tsin(float angle) //renvoie le sinus de angle
  • {
  • int rang=((int)((1/precision)*angle));
  • return tabSin[rang];
  • }
  • float Tcos(float angle) //renvoie le cosinus de angle
  • {
  • int rang=((int)((1/precision)*angle));
  • return tabCos[rang];
  • }
  • /*______________________________FONCTIONS DE ROTATION:________________________________________*/
  • void ExpRotateZ(float* x, float* y, float Ax, float Ay, float alpha)/*Rotation autour de
  • l'axe Z*/
  • {
  • float xt;
  • float sinc=Tsin(alpha);
  • float cosc=Tcos(alpha);
  • xt=*x;
  • *x=((*x)-Ax)*cosc+(Ay-(*y))*sinc+Ax; //Ces deux lignes sont surement incomprehensibles
  • *y=((*y)-Ay)*cosc+(xt-Ax)*sinc+Ay; //présentées comme ca mais on les retrouve très
  • //vite en se souvenant de la géométrie avec les
  • //complexes*/
  • }
  • void ExpRotateY(float* x, float* z, float Ax, float Ay, float alpha)/*Rotation autour de
  • l'axe Y*/
  • {
  • float xt;
  • float sinc=Tsin(alpha);
  • float cosc=Tcos(alpha);
  • xt=*x;
  • *x=((*x)-Ax)*cosc+(Ay-(*z))*sinc+Ax;
  • *z=((*z)-Ay)*cosc+(xt-Ax)*sinc+Ay;
  • }
  • void ExpRotateX(float* y, float* z, float Ax, float Ay, float alpha)/*Rotation autour de
  • l'axe X*/
  • {
  • float yt;
  • float sinc=Tsin(alpha);
  • float cosc=Tcos(alpha);
  • yt=*y;
  • *y=((*y)-Ax)*cosc+(Ay-(*z))*sinc+Ax;
  • *z=((*z)-Ay)*cosc+(yt-Ax)*sinc+Ay;
  • }
  • void FreeRotate()
  • {
  • free(tabSin);
  • free(tabCos);
  • }
  • #endif
#ifndef Rotate
#define Rotate

#define precision 0.1    // c'est cette valeur qu'il faut changer pour modifier la precision 
                         // de cos et sin (multiple de 10 sinon ca créé des tableaux de taille 
                         //  non entiere
#define Pi 3.14159265358                                  //        A Y
                                                          //        |
#include <math.h>                                         //        |
                                                          //        |          X
/*Fonctions de rotation dans l'espace par Dletozeun       //        0-------->
                                                          //       /
  Utilisation:                                            //    Z /
                                                                 V
  _les 2 premiers arguments correspondent aux coordonnées dans le plan de rotation du point à faire
   tourner.
  _Les arguments Ax et Ay correspondent aux coordonnées du point représentant l'axe de rotation
   dans le plan de rotation
  _L'argument alpha représente l'angle de rotation en degrés
  
  /!\ NE PAS OUBLIER AVANT D'UTILSER CES FONCTIONS DE LANCER LA FONCTION : init_sin_cos() POUR 
      INITIALISER LES TABLEAUX SIN,COS SINON PLANTAGE GARANTI !!!
      
      ET LA FOCNTION : FreeRotate() POUR LIBERER LES TABLEAUX;         */
  

float* tabSin;
float* tabCos;
/*_________________________INITIALISATION DES TABLES COSINUS ET SINUS:__________________________*/
void init_sin_cos()
{
    tabSin=(float*)malloc((360/precision)*sizeof(float));
    tabCos=(float*)malloc((360/precision)*sizeof(float));

    
    for(float a=0;a<360;a+=precision)
    {
        int pas=(1/precision)*a;
        float Angle_rad=(a*Pi)/180;
        tabSin[pas]=sin(Angle_rad);
        tabCos[pas]=cos(Angle_rad);
    }
}
/*FIN DE L'INITIALISATION*/

float Tsin(float angle) //renvoie le sinus de angle
{
    int rang=((int)((1/precision)*angle));

    return tabSin[rang];
}

float Tcos(float angle) //renvoie le cosinus de angle
{
    int rang=((int)((1/precision)*angle));
    return tabCos[rang];
}

/*______________________________FONCTIONS DE ROTATION:________________________________________*/

void ExpRotateZ(float* x, float* y, float Ax, float Ay, float alpha)/*Rotation autour de
                                                                                l'axe Z*/
{
    float xt;
    float sinc=Tsin(alpha);
    float cosc=Tcos(alpha);
            xt=*x;
            *x=((*x)-Ax)*cosc+(Ay-(*y))*sinc+Ax; //Ces deux lignes sont surement incomprehensibles 
            *y=((*y)-Ay)*cosc+(xt-Ax)*sinc+Ay;   //présentées comme ca mais on les retrouve très 
                                                 //vite en se souvenant de la géométrie avec les 
                                                 //complexes*/
            
}

void ExpRotateY(float* x, float* z, float Ax, float Ay, float alpha)/*Rotation autour de
                                                                                l'axe Y*/
{    
    float xt;
    float sinc=Tsin(alpha);
    float cosc=Tcos(alpha);
            xt=*x;
            *x=((*x)-Ax)*cosc+(Ay-(*z))*sinc+Ax;
            *z=((*z)-Ay)*cosc+(xt-Ax)*sinc+Ay; 
} 

void ExpRotateX(float* y, float* z, float Ax, float Ay, float alpha)/*Rotation autour de
                                                                                l'axe X*/
{
    float yt;
    float sinc=Tsin(alpha);
    float cosc=Tcos(alpha);
            yt=*y;
            *y=((*y)-Ax)*cosc+(Ay-(*z))*sinc+Ax;
            *z=((*z)-Ay)*cosc+(yt-Ax)*sinc+Ay;
} 

void FreeRotate()
{
    free(tabSin);
    free(tabCos);
}    

#endif

 Conclusion

Voila ! J'attends les critiques permettant d'optimiser mon code.


 Historique

01 novembre 2004 19:55:40 :
Avec les conseils de Kirua et funto j'ai supprimé les fonctions sinus et cosinus de mes fonctions de rotation en créant des tables sin et cos
01 novembre 2004 20:08:51 :
remplacement du commentaire "L'argument alpha représente l'angle de rotation en radians" par :" L'argument alpha représente l'angle de rotation en degrés" C'est important quand meme!
27 mars 2005 19:24:28 :
ajout de la fonction FreeRotate() pour liberer la memoire des tableaux

 Sources du même auteur

ALGORITHME DE LIGNES

 Sources de la même categorie

Source avec Zip Source avec une capture PLANNING D'EQUIPE par grephit
Source avec Zip APPLICATION DE DESSIN DE QUELQUES FIGURES par laguchori
Source avec Zip Source avec une capture HDR EXPOSURE FUSION par mecrosoft
Source avec Zip Source avec une capture IRC CLIENT MULTISERVEUR EN MFC (TXIRC) par TeniX
Source avec Zip ENTETE DU FICHIER BMP (BIPMAP) par k.Lutchi

Commentaires et avis

Commentaire de Funto66 le 30/10/2004 20:05:24

Ben si tu veux optimiser ton code, il faut éviter d'utiliser les fonctions trigonométriques directement dans la fonction, ça bouffe du temps !
En général pour ça on crée des gros tableaux qui contiennent des valeurs pour les fonctions trigo. Genre tab_sin[28] renverrait la valeur de sin(28), mais t'es pas obligé de rester en degrés ou en radians, tu peux prendre une unité plus petite pour une meilleure précision ;)

Sinon pour faire tourner des points en général on utilise des matrices ou des quaternions (m'en demande pas plus sur ce sujet par contre lol) ^^

Commentaire de dletozeun le 30/10/2004 20:15:38

oui mais faut vraiment de gros tableaux pour ne pas deformer les objets...
En tout cas merci, je retiens cette remarque.
ET les matrices et quaternions , ce n'est pas encore de mon niveau mais je vais me renseigner la dessus...

Commentaire de Pamaury le 30/10/2004 21:47:48

moinje conseille les matrices car c'est vraiment pratique:
-> tu fais tes transformation sur la matrice et tu applique ensuite cette matrices à tous les point qui subissent la transformation ainsi, pas besoin d'appeler 50 fois la fonction cos si t'as 50 points . Un bon site qui introduit ce sujet:
http://prografix.games-creators.org/document/70
Sinon regarde sur le net il doit y avoir plein de trucs .
Sinon pour les quaternions je m'en suis jamais servit masi il me semble que c'est pour gérer le déplacement d'un objet par rapport à un autre lui-même en mouvement de façon assez facilement ^^

Commentaire de AlexMAN le 30/10/2004 21:53:24

si tu veux vraiment optimiser ton code o max, enleve les fonctions trigonometrik de math.h, utilise la FPU (donc de l'asm) et fais ce ke ta conseillé Funto66...
Voila ;)

++

Commentaire de dletozeun le 30/10/2004 23:18:43

ok ok ^^ merci pour tous ces conseils je vais revoir ca

Commentaire de Funto66 le 31/10/2004 01:37:21

Ouais enfin je pense que la meilleure optimisation possible serait l'usage des capacités de la carte graphique pour gérer les matrices -> OpenGL ou DirectX ^^
Enfin, tout dépend de ce que tu veux faire tourner aussi, et surtout de ce que tu veux en faire ;)

Commentaire de luhtor le 31/10/2004 10:51:53

L'utilisation des matrices ne changent rien ici, puisque ca reviendra au final a faire exactement les memes calculs que ce que tu obtiens en complèxes. A un moment ou un autre, faudra bien le faire ce calcul matricielle :)

Commentaire de Kirua le 31/10/2004 13:06:39

pour le tableau de correspondance ce n'est pas si gros que ça. imaginons que tu désires une précision d'un dixième de degré, ça te fait 3600 * 4 = 14Ko, c'est raisonnable je crois :) bon, bien sûr, après tu exploites les propriétés trigonométriques si tu veux économiser de la place:

cos(x) = sin(90-x)
tan(x) = sin(x) / cos(x)

euh, bien entendu tu dois tjs t'arranger pr convertir l'indice d'accès au tableau afin de rester ds l'intervalle [0, 360] (càd 0, 3600 en fait).

je te conseille de faire une classe "wrapper", que tu nommerais CTrigo, et qui au démarrage crée un tableau statique (tu pourrais vouloir plusieurs occurrences de la classe, mais c'est pas vrmnt la peine de se tapper un singleton) avec les valeurs sinusoïdes, selon la précision voulue (à préciser en statique aussi). ensuite tu crées des fonctions Sin(), Cos(), Tan(), Cotan() qui convertiront elles-mêmes les angles histoire de pas se casser la tête.

exemple:

l'angle 54,8 sera à l'infice int(54.8 * 10) = 548 (pr précision 10)

l'angle -37 sera à l'indice (360 + (-37))*10 = 3230

et l'angle 589 sera à l'indice (589%360)*10

enfin, ça doit pas être trop dur ni lourd pt de vue machine de faire ces calculs. oublie pas que si tu veux calculer Tan à partir de cos et de sin, tu peux parfaitement calculer l'angle exacte une seule fois dans la fonction Tan, puis ne pas appeler les fonctions Cos et Sin qui referaient l'adaptation de l'angle, mais directemet depuis Tan renvoyer la valeur tableau.

tu peux aussi imaginer une méthode de conversion de l'angle, tout simplement ^^


vala

Commentaire de djl le 31/10/2004 15:29:58

j'avais fais un exemple en c (pour cos et sin seulement)

http://www.cppfrance.com/code.aspx?ID=24821

mais je sais pas si ca marche bien

Commentaire de dletozeun le 31/10/2004 20:44:49

merci Kirua je vais essayer de faire ca ...

Commentaire de Arnaud16022 le 31/10/2004 22:31:45

dletozeun, je sais pas du tout a quoi ca va te servir tout ca.
pour faire tourner un point autour d'une droite (pour commencer on va dire qu'elle passe par l'origine) autre qu'un axe, tu peux pas faire d'abord une rotation autour d'un axe puis une autrre rotation autour d'un axe perpendiculaire. Le point serait déplacé, certes, mais il ne serait pas du tout a la position voulue.
Les matrices c'est tout con, en gros t'as qu'à savoir les multiplier, mais la encore ce n'est QUE autour des axes.

La meilleure solution, universelle, pratique, RAPIDE et tout et tout, c'est effectivement les quaternions.
Maisc'est pas la peine d'essayer de reprogrammer ca toi meme, pasque toute la doc ou presque est en anglais, et que c'set qd meme assez dur (ne serait-ce que le concept: un quaternions, en fait, ca s'appelle aussi un hyperscalaire a 4 dimensions, qui sert entre autres a des rotations spheriques 4D ... voila qui laisse songeur.)
Bref...t'es pas sorti de l'auberge... et tes fonctions sont lentes (dsl...) et inutiles (re-dsl...) sauf cas précis

oh encore untruc: tout au début tu fais
#ifndef Rotate
sans rien derriere... je vois pas comment ca peut marcher. ce qu'il faut c'est :
#ifndef Rotate_h
#define Rotate_h
... ton code ...
#endif

Commentaire de dletozeun le 01/11/2004 18:55:11

Arnaud16022> Je ne comprends pas le probleme avec "le point qui ne serait pas du tout a la place voulue"

Pour quoi il ne serait pas possible de faire tourner mon point autour d'un axe quelquonque (X par exple) puis autour d'un axe perpendiculaire (Y par exemple)

Et puis je ne vois l'inutilité de ces fonctions !? Ca ne sert pas pour toi la rotation pour animer un objet en 3D?
Et je n'ai pas dit que mes fonctions etaient rapides...d'ailleurs si t'as lu les autres commentaires je suis en train de les optimiser un peu

Commentaire de Arnaud16022 le 01/11/2004 19:46:10

ben vi j'ai lu.
en fait tes fonctions peuvent trres bien servir pour créer un effet JOLI dans un programme qui aura le mérite (oh oui! c'est pas si courant) d'etre personnel.

"Pour quoi il ne serait pas possible de faire tourner mon point autour d'un axe quelquonque (X par exple) puis autour d'un axe perpendiculaire (Y par exemple)"
essaye et tu verras que ca marche pas (le plus souvent du moins). je veux dire par la que le point va tourner correctement autour des 2 axes, comme tu le lui a demandé, mais a la fini sera pas tout a fait a la place escomptée; Ca marche si tu trouve le moyen de calculer les angles de rotations voulus mais pour ca bon courage.

Commentaire de dletozeun le 01/11/2004 20:05:55

Désolé Arnaud16022 (ca doit venir de moi) mais je ne te suis pas trop...
En fait j'ai tester ces fonctions dans mon debut de moteur 3D ou je fais tourner un cube dans tous les sens que je veux grace a ces fonctions...et ca fonctionne tres bien pour ce que je veux faire.

Ce point ne sera pas a la place escompté parce que les fonctions sin et cos n'ont pas une precision infinie ...c'est ca que tu veux dire?

le but de ces fonctions est faire tourner un point a l'ecran...pas besoin d'une precision enorme C'est pas un logiciel de calcul que je veux faire!

Sinon j'ai mis a jour mon code en y ajoutant des tableaux contenant les valeurs de sin et cos au 10eme de de gré pres... enfin vous pouvez facilement modifier cette valeur avec le : #define precision

Commentaire de Arnaud16022 le 01/11/2004 21:28:44

nan c'est pas ca tu tout.
je sé pas comment te l'expliquer, dsl.
je vais chercher un lien qui expliquera ca mieux que moi.
mais tes fonctions sont utiles.
Je te cite juste une page ou c'est dit et pas explique (c'est pas spécifiquement le but de cette page):

"Des transformations correctes ne peuvent pas être obtenue en cumulant des angles de rotations. Pour ce faire, il faudrait user de quaternions, mais là n'est pas le propos de notre sujet :) "

source :http://membres.lycos.fr/javamus/articles/trfmat.html
c'est sur les matrices et les transfos, ca peut t'intéresser

Commentaire de dletozeun le 01/11/2004 22:03:26

Ok merci je lirai ca kan j'aurais le tps

Commentaire de basted le 01/11/2004 22:28:40

je crois qu'il faut un petit eclairsissement sur les quaterinon ! il faut distingué une definition de plan par les angle d'euler et par les quaternion.
Par le angle d'euler, on fait calsiquement une rotation sur l'axe des x puis y , puis z, mais cela pose un pb appele de perte de degre de liberté appelé: "Gimbal Lock"
cf.: http://membres.lycos.fr/javamus/articles/mqfaq.html question q34

pour palié a ce probleme: les quaternions

Mais sinon je trouve ta demarche interessente, il faut savoir que les calcul des coordonnée de points peuvent etre plus rapide a effectuer en CPU qu'en GPU, par exemple en OpenGL, glRotated s'execute chez moi en 775 ns alors que le meme calcul fait avec une class de matrise se fait en 635 ns (et je n'est pas optimisé la class: en claire sin et cos)

Du coup j'imagine qu'en fait cela n'est pas materiel, ou si c'est la cas ce n'est pas "rentable". Sauf effectivement dans le cas ou la transformation s'applique a beaucoup de vertex, et encors c'est largement a discuter car bon nombre d'objet sont static par rapport a une matrise donnée (a mediter)

Pour l'histoire des option de sin et cos (en fait la seul chose a vraiment optimiser), j'ai crus comprendre que cela etait pris en compt par des instruction ASM special apparu avec SSL, SSL2, SSL3, 3DNow!, MMX une petit class qui gerais ca serai le bien venu
cf.: http://lfmat.sourceforge.net/
l'onglet benchmarq ecris en claire "ca dechire grave ++"

Commentaire de Funto66 le 02/11/2004 01:46:39

Huh? L'utilisation de sin et cos, plus rapide qu'un glRotated()?? J'en doute quand même...

Mais si jamais c'est le cas, on pourrait en tirer un super avantage : qd on fait tourner un objet, on pourrait le faire tourner en "software" (sur la CPU et non le GPU) et fournir les données transformées au GPU; on aurait ainsi aussi les coordonnées transformées directement accessibles dans notre prog, ce qui pourrait être intéressant pr les collisions :) (bien qu'un système par bounding boxes doit être bien plus optimisé quand même ^^).

Commentaire de basted le 02/11/2004 10:04:29

J'ai fait un bench GL utilisant le query performance counter dans pour tester tout ca. Evidament ca demend de ta carte 3D, pour ma parte j'ai tester avec une machine bureautique (carte 3D tres tres bof) et un machine de gamer (ATI6800), dans les 2 cas le CPU est plus rapide.

Je vous fournirais l'URL de mon testGLperf quand je l'aurais totalement finis. Mais de toute facon le pre-calcul de vertex est plus que courrent, ne reste qu'a savoir dans quel cas c'est interessent.

Commentaire de Funto66 le 02/11/2004 13:12:59

Cool :) Tu pourrais le poster sur CppFrance tant qu'à faire ton test ;)

Commentaire de dletozeun le 02/11/2004 15:31:14

J'ai créé des tableaux cos et sin pour remplacer le calcule de sin et cos a chaque rotation mais je ne vois pas de différence de rapidité...a vrai dire je ne sais pas comment m'y prendre pour tester mes fonctions efficacement
Une question : glRotated() utilise le GPU ?

Commentaire de Funto66 le 02/11/2004 17:39:56

Oui ça utilise le GPU.
Et pour tester les perfs, faudrait que tu mesures les FPS; avec l'API Win32 t'as les fonctions QueryPerformanceCounter(), GetTicks(), avec SDL t'as SDL_GetTicks(), avec GLUT à la limite glutTimerFunc() et avec la lib standard t'as clock().

Commentaire de Pamaury le 02/11/2004 19:57:53

clock laisse tombé c'est pas assez précis mais QueryPerformanceCounter() est excellent car vraiment très précis .

Commentaire de dletozeun le 02/11/2004 22:47:40

merci je v tester ca

Commentaire de Arnaud16022 le 03/11/2004 00:28:14

en fait sur windows ya pas mieux

Commentaire de Pamaury le 03/11/2004 07:58:08

"en fait sur windows ya pas mieux" -> en fait sur les PC il y a pas mieux car en réalité
QueryPerformanceCounter n'est qu'une intreface pour utiliser un compteur HARDWARE dispo sur tout les PC assez recent . Ce compteur est extremmement précis, il attend la nano seconde en précision sur mon ordi .

Commentaire de Kirua le 03/11/2004 17:49:35

s'il attend la nanoseconde et si je ne suis pas tt à fait idiot (prions), ça veut dire qu'il mesure quasiement au cycle processeur près! sauf erreur, nano c'est 10^-9, et comme on fonctionne souvent avec des processeurs de fréquence en Ghz, on y est quoi :/ c'est vrai que clock peut ps rivaliser :)

Commentaire de Pamaury le 03/11/2004 18:31:52

peut être que justement QueryPerformanceCounter c'est l'horloge du CPU ??? après tout c'est possible je regarde et je te dis ce qu'il en est .

Commentaire de Arnaud16022 le 03/11/2004 19:50:04

hé vi kirua, nano c'est 10^-9!
par contre, vu le niveau global du site, je ne pense pas qu'il y ait vraiment besoin d'une telle précision...dans hoverbike j'avais clock et ca marchait bien...
en ce moment c'et plutot sdl_getticks

Commentaire de Pamaury le 03/11/2004 20:59:14

If a high-resolution performance counter exists on the system, you can use the QueryPerformanceFrequency function to express the frequency, in counts per second. The value of the count is processor dependent. On some processors, for example, the count might be the cycle rate of the processor clock.

Donc sur certain processeur çà peut être les cycles d'horloges mais c'est pas obligatoire .

Commentaire de Kirua le 03/11/2004 21:21:28

merci pr la précision. quand je fais un QueryPerformanceFrequency sur mon PC qui est cadencé à 2.26Ghz (P4), j'obtiens environ 6 millions et demi.

Commentaire de Arnaud16022 le 03/11/2004 21:41:39

mais ca sert a quoi alors si c'est pas universel?

Commentaire de Kirua le 03/11/2004 21:45:03

ben c'est universel sur ton PC à toi ^^ regarde, comme tu peux récupérer les écarts en ticks, et que le nombre de ticks par seconde est une constante pour un ordinateur donné (en tout cas entre un boot et un shut down), tu n'as aucun problème pr déterminer avec bcp de précision (autant que les float quoi, mdr) le temps "réel" (en ms) écoulé depuis la dernière frame (par exemple). ensuite, ds le cas d'un moteur physique, ben tu n'as qu'à faire pour une bille par exemple:

Bille.Position += Bille.Vitesse * delta_temps;

avec delta_temps un flottant en secondes, et Vitesse et Position des grandeures vectorielles. de cette manière, à 1 ou à 1 000 000 de FPS, tu avances pareil sur les deux ordis... mais l'image sera pas forcément fluide :)

Commentaire de Pamaury le 03/11/2004 22:07:34

ouais c'est le compteur le plus précis qu'on peut trouver et de très loin . Pour info, sur mon ordi(2.4Ghz) clock a une précision de 15 ms !!!!! donc c'est pas génial parce contre timeGetTime et GetTickCount sont précis à la ms environ .
Il y a aussi ftime et GetSystemTime qui sont assez précis(à la ms environ) . Et avec la SDL il y a SDL_GetElapsedTime je crois .

Commentaire de basted le 03/11/2004 22:18:54

l'API QueryPerformanceFrequency indique justement la frequence, pour l'utiliser:

class Timer
{
public:
__int64 beginTime;
double tick;

public:
Timer()
{
__int64 frecTimer;
QueryPerformanceFrequency((LARGE_INTEGER *)&frecTimer);
tick = 1.0/frecTimer;
}

void Start()
{
QueryPerformanceCounter((LARGE_INTEGER *)&beginTime);
}

double Stop()
{
__int64 currentTime;
QueryPerformanceCounter((LARGE_INTEGER *)&currentTime);
return (currentTime - beginTime)*tick;

}
};

Chez moi la presision est 270ns c'est donc loin de la frequence de mon proceseur, et trop lent aussi  pour messurer les operation assembleur de base (ajout, multiplication etc ...)

Commentaire de Kirua le 03/11/2004 22:32:57

mets 'tick' en static, et initialise à 0. ds le constructeur tu rajoutes if(!tick) Query...

ton code est VC only, à cause des __int64. est-e qu'un long long int n'est pas ok? sur une machine 32 bits, ça vaudra aussi un 64 bits, et sur les machines ultérieures, ça vaudra probablement plus, mais tt de même assez. non ?

Commentaire de Arnaud16022 le 03/11/2004 23:10:07

hum, kirua, je sais quand meme ce qu'est le fps...
D'ailleurs ce que tu dis est faux.
Bille.Position += Bille.Vitesse * delta_temps;
Vitesse est calculée a partir de l'accélération, qui ellemme est calculée a partir dee la vitesse.
Ca fait une equation différentielle, et sur un ordi pour résoudre ca on peut pas le faire analytiquement, du coup ya plus 36 solution, il faut le faire numériquement.
Pour ca il faut prendre le plus petit intervalle de temps possible, et à 1FPS c'est pas top. ducoup la solution n'est pas (exactement) la meme à 1 et a 100000 de fps.
mais, oui, je sais, je pinaille.

Pamaury: pour GetTickCount, je trouve ca normal qu'il soit a la ms pres, puisque c'est la définition du tick (nbre de millisecondes deepuis le boot, non?)

Basted: pourquoi ne pas mesurer le temps d'execution de
for (int a=0;a!=1000000;a++){}
puis ded
for (int a=0;a!=1000000;a++){b*10;}
et faire la différence des deux, et diviser par 1000000? ca sreait juste comme calcul? A priori oui, mais bon o sait jamais...

Bon, il est 11 heures.. plus que 8 heures de vacances...BOUH!


++

Commentaire de basted le 04/11/2004 00:14:34

arnaud: j'avais utilisé la meme idée (for (int a=0;a!=1000000;a++){}) mais le pb c'est qu'i faudrai alors que le temp mesuré entre 2 QueryPerformanceCounter soit constant ... mais ce n'est pas le cas! En effet si on fait:
_int64 times[1000];
for (long i=0;i<1000;i++)
{
QueryPerformanceCounter((LARGE_INTEGER *)&time[i]);
}
si on regard le tableau: suprise ne chiffre ne sont pas exactement constant, (en moyenne=5 cycle) ce pourais ne pas etre grave si ce que l'on mesure est grand face l'impressision. Pense que le tick est de 270ns donc si il y a un cycle de trop ca peut faire une enorme difference meme avec une boucle enorme. En fait c'est un probleme quentique (qui l'aurai cru)

En ce qui concerne le __int64, ca n'est pas reservée au machine 64bit bien sur, c'est un mots clef specifique windows et donc effectivement ce n'est pas portable. La definition d'un LONGLONG est:
typedef __int64 LONGLONG
donc ... il faut que chaque implementation sache geré un type equivalent

Commentaire de Kirua le 04/11/2004 07:52:00

"D'ailleurs ce que tu dis est faux."

non, mon exemple est correct. la position est bien majorée d'une fraction du vecteur vitesse "à ce moment-là". (même si en effet pr un mouvement circulaire par exemple, ou tt autre mouvement pr lequel une force est appliquée ponctuellement, évidemment la précision dépend du nb de FPS, mais ici je n'ai pas prétendu faire intervenir des forces (ds l'exemple quoi)).

Commentaire de Pamaury le 04/11/2004 18:34:07

"En ce qui concerne le __int64, ca n'est pas reservée au machine 64bit bien sur, c'est un mots clef specifique windows et donc effectivement ce n'est pas portable. La definition d'un LONGLONG est:
typedef __int64 LONGLONG
donc ... il faut que chaque implementation sache geré un type equivalent"
-> si vous travaillez sous Windows il y a ULARGE_INTEGER et  LARGE_INTEGER qui sont des structures 64-bit (en fait c'est un union) etq ui marche très bien sur tous les compilo .

Commentaire de basted le 05/11/2004 08:27:23

Une petite remarque pour les optimisation trigo clasique (cos, sin tan asin etc ...): il existe des algo tres optimisé et/ou qui trouve des valeurs approché. Vous pourez regardez sur le site:
http://www.simgear.org/ dans le projet il y a un truc appelet "fastmath.h/.cpp", pour example voici une fonc qui definis les sinus:

// valable de [0;PI/2]
float fast_sin(const float val)
{
  float fASqr = val*val;
  float fResult = -2.39e-08f;
  fResult *= fASqr;
  fResult += 2.7526e-06f;
  fResult *= fASqr;
  fResult -= 1.98409e-04f;
  fResult *= fASqr;
  fResult += 8.3333315e-03f;
  fResult *= fASqr;
  fResult -= 1.666666664e-01f;
  fResult *= fASqr;
  fResult += 1.0f;
  fResult *= val;
  return fResult;
}

etonant non ?!

J'ai tester avec Excel pour savoir si les valeurs etait correct; et la, surprise toute les valeurs sont correct.

Commentaire de Funto66 le 05/11/2004 20:54:27

Wow;
où est-ce qu'ils ont pu trouver ça? En tous cas si ça marche bien ben ça doit être super rapide :)
Je prends note :) Tu pourrais pas nous filer un lien direct vers les autres fonctions trigo tant qu'à faire ? ;)

Commentaire de Arnaud16022 le 05/11/2004 21:32:50

en tout cas pour cos c'est pas dur, tu rajoute PI/2...

1.666666664, c'est la valeur approchée de 5/3? si ouica serait pas plus précis encore de tout mettre en double ou long et dee mettre la fraction a la place?

Commentaire de luhtor le 06/11/2004 11:49:54

Bon je vais me répéter puisque j'avais deja posté sur ce sujet. Mais pour tout les processeurs de pentium, la fonction RDTSC (Read time stamp counter) marche tres bien. Elle retourne le nombre de cycle d'horloge depuis le dernier redémarrage. Pour les AMD, la fonction retourne un résultat étrange, mais lorsque l'on fait l'écart entre deux instants, c'est correct:

extern __inline__ unsigned long long int rdtsc()
{
unsigned long long int x;
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
return x;
}

Pour une approximation du cosinus, j'utiliserais plutot un tableau de float, et une interpolation linéaire entre chaque valeur. Ca retourne quelque chose de très correct.

L'approximation position += accélération * (delta_t)^2 est tres correct, mais faut rester au dessus de 50fps, en dessous faut faire de calcul de position par frame pour garder une certaine précision. Et puis, qui a besoin d'une telle précision ?
Le truc le plus banal comme la chute libre (dans un jeu par exemple), n'aurait besoin que de 10 rafraichissement par seconde.

Commentaire de dletozeun le 12/11/2004 23:54:44

d'apres mes tests: les fonctions ainsi optimisées permettent de calculer la nouvelle position par une rotation en environ 2 ms avec Tsin et Tcos a la place de environ 4 ms avec les fonctions trigo normales :sin cos...
tout sur un amd 2100+ 1.7 GHz

Commentaire de Arnaud16022 le 13/11/2004 22:18:50

chapeau
et pour la précision des valeurs?

Commentaire de Zazour le 15/04/2005 00:13:08

interessant le fil de discussion :)
mais j'aimerai consulter la doc sur gamecreator "http://prografix.games-creators.org/document/70" et il n'y a pas d'image

Commentaire de Arnaud16022 le 15/04/2005 18:39:55

C quoi le rapport avec les sinus/cosinus? ta page est sur les matrices...

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,640 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales