PDA

Voir la version complète : Calculer la norme d'un vecteur


thoduv
08/10/2006, 13h33
Salut !

Thoduv et ses questions chiantes sont de retour ! :devil:

Pour mon système de déplacement, j'ai besoin de calculer la norme d'un vecteur, or je ne connais que la formule compliquée avec la terrifiante racine carrée. Très mauvais pour la GBA tout ca.

http://www.sc.ucl.ac.be/ete-mathphys/vecteurs/images/vec04.gif(avec seulement deux dimensions pour moi).

Est-ce que quelqu'un connait quelque chose de plus simple (sans racine) ?

Merci d'avance ! :)

RefiX
08/10/2006, 13h35
ca sert peut être à rien dans ton cas mais racine carré d'un nombre c'est aussi ce nombre à la puissance 1/2

Darkmath
08/10/2006, 13h37
ça pose pb à la gba ça? moi sur DS pour des calculs du même type en 3D j'ai pas de problème.... :S

thoduv
08/10/2006, 13h38
Ben la GBA est 4 fois moins rapide que la DS. Je pourrais aussi utiliser une "LUT" mais ca me fait chier de sortir tout cet attirail pour un pauvre petit calcul 2d de vecteur.

DJP
08/10/2006, 13h50
Bah, si tu as besoin de calculer la norme c'est que tu la compare a quelquechose d'autre... passe ce quelquechose d'autre au carré :p

Pitt
08/10/2006, 13h51
Ben là, je crois pas qu'il y est d'autres formules ; je vais regarder dans mes bouquins, mais je pense que:
. _______
\/ x² + y²

est la seule solution ...

Par contre, tu peux comparer des normes de vecteurs au carré ...

EDIT: grillé :hum: ^^

thoduv
08/10/2006, 13h59
Non, c'est pas pour une comparaison, en fait pour un déplacement y faut une vitesse (v), un temps (t) et une distance (vecteur d). Mon idée c'est de tout relier comme ca:

___________
V dx² + dy²
t = -----------------
v

pour pouvoir calculer le nombre de pixels à déplacer par frame f.

fx = dx / t
fy = dy / t

YoBoY
08/10/2006, 15h08
Bon si je comprends bien, tu pars d'une vitesse v (donnée sans direction) et tu veuxconnaitre ton déplacement sur les axes x et y en fonction d'un vecteur de direction D et ce entre deux frames (donc le temps t est fixe).

Si c'est ça alors il faut bien comprendre que le vecteur de direction est normalisé à 1 (c'est ça taille c'est imuable) et que ces composantes x et y sont les cos et sin de l'angle que forme cette direction avec l'axe x.
Bref tu résouds facilement ton probleme avec un table de cos et de sin (plus ou moins fine) et tu as tes déplacements en multipiant c'est composantes x et y par ta vitesse et ta base de temps.

Après si j'ai rien compris au probleme réexplique.

Brunni
08/10/2006, 15h11
ça pose pb à la gba ça? moi sur DS pour des calculs du même type en 3D j'ai pas de problème.... :S
Ben la GBA est 4 fois moins rapide que la DS. Je pourrais aussi utiliser une "LUT" mais ca me fait chier de sortir tout cet attirail pour un pauvre petit calcul 2d de vecteur.
C'est surtout que la racine carrée est gérée en hard sur DS, pas sur GBA ;)

thoduv
08/10/2006, 15h55
Bon si je comprends bien, tu pars d'une vitesse v (donnée sans direction) et tu veuxconnaitre ton déplacement sur les axes x et y en fonction d'un vecteur de direction D et ce entre deux frames (donc le temps t est fixe).

Si c'est ça alors il faut bien comprendre que le vecteur de direction est normalisé à 1 (c'est ça taille c'est imuable) et que ces composantes x et y sont les cos et sin de l'angle que forme cette direction avec l'axe x.
Bref tu résouds facilement ton probleme avec un table de cos et de sin (plus ou moins fine) et tu as tes déplacements en multipiant c'est composantes x et y par ta vitesse et ta base de temps.

Après si j'ai rien compris au probleme réexplique.
Je ne m'occupe pas de l'angle, puisque je ne le connais pas.
En gros voilà le code avec la racine:
typedef struct
{
f32 qX, qY;
u16 qN;
} dMove_t;

/* info: f32 est un nombre à virgule fixe sur 32 bits */
/* _div_f32f32(a,b) divise deux f32 */
/* srf32(a) transforme un f32 en int */
/* fis32(a) transforme un int en f32 */
void dMoveInit(dMove_t *m, u16 dX, u16 dY, f32 v)
{
m->qN = srf32(_div_f32f32(fis32(iSqrt32(dX * dX + dY * dY)), v)); /* qN = t en fait */
m->qX = _div_f32f32(dX, fis32(m->qN));
m->qY = _div_f32f32(dY, fis32(m->qN));
}


J'ai pas encore testé, je vais le faire.

YoBoY
08/10/2006, 16h42
je sais pas comment tu gères tes déplacements, mais au final, vu que le moyen de controle est souvent une croix directionnelle tu as 4 directions principales, 8 avec les diagonales, ce qui te fait 8 vecteurs de directions pour la plupars des jeux.
Après tu as des controles qui peuvent différer, et les actions gauche droites donnent une rotation vers la gauche ou vers la droite d'un certain angle, et les actions haut bas controle le mouvement avant arrière sur cette direction, ce qui nous donne un nombre de direction la plupart du temps aussi assez fixe.

Bref quand tu veux "bouger" faut pas perdre de vue le reste.

Essaye de préciser le contexte, le but, et l'idée de base de ta modélisation parceque un code source avec des noms de variables sur 2 lettres c'est un peu dur à lire (pour moi)

thoduv
08/10/2006, 16h49
je sais pas comment tu gères tes déplacements, mais au final, vu que le moyen de controle est souvent une croix directionnelle tu as 4 directions principales, 8 avec les diagonales, ce qui te fait 8 vecteurs de directions pour la plupars des jeux.
Après tu as des controles qui peuvent différer, et les actions gauche droites donnent une rotation vers la gauche ou vers la droite d'un certain angle, et les actions haut bas controle le mouvement avant arrière sur cette direction, ce qui nous donne un nombre de direction la plupart du temps aussi assez fixe.

Bref quand tu veux "bouger" faut pas perdre de vue le reste.

Essaye de préciser le contexte, le but, et l'idée de base de ta modélisation parceque un code source avec des noms de variables sur 2 lettres c'est un peu dur à lire (pour moi)
Ok, c'est vrai que mon code est incompréhensible.
En fait il s'agit de faire un moteur de déplacement, par exemple dans mon script, je dis: "déplace tel évenement de (10,60) à une vitesse de 4 depl/frame.

On prends donc la longueur de la distance à parcourir (la norme du vecteur donc), on divise par la vitesse 4, ce qui nous donne le nombre de frames. On divise ensuite les distance X et Y par ce nombre de frames, et on a le nombre (à virgule) par lequel on doit augmenter la position à chaque frame.

Mais de toutes facon, c'est pas grave, je vais me débrouiller avec la racine carrée.

Darkmath
08/10/2006, 16h56
C'est surtout que la racine carrée est gérée en hard sur DS, pas sur GBA ;)

Désolé pour le hors sujet mais pourrais tu me dire ou trouver un ensemble des fonctions justement gérées direct en hard par la DS? Ca m'interesse.

Brunni
08/10/2006, 17h15
Il y a DSTek (http://neimod.com/dstek/), excellent document qui couvre ces deux points, mais pour le reste je suis complètement nouveau donc je ne saurais pas trop te conseiller :S
Sinon j'ai quand même pas complètement compris ce que tu veux faire, mais en effet pour calculer la distance totale tu ne couperas pas à la racine, et arctan pour l'angle (sauf erreur). Par contre si c'est un déplacement simple il te suffit de gérer différemment les deux composantes X et Y. Exemple x0,y0; départ, x1,y1: arrivée:
Distance X: x1 - x0
Déplacement par frame X: (x1 - x0) / nbFrames
Pareil pour Y. Mais après je ne sais pas si ça te conviendra ou si c'est moi qui ai mal compris ce que tu veux faire ;)

thoduv
08/10/2006, 17h27
Nan, le Martin Korth c'est Gbatek, et c'est par là : http://nocash.emubase.de/gbatek.htm : toute la DS et la GBA de A à Z.
Dstek, c'est un début de doc sur la DS, mais c'est très très incomplet.

Brunni> effectivement, c'est ce que je faisais d'habitude, mais ca ne convient plus quand on veut gérer la vitesse des deux directions.

Sinon, mon truc marche, après avoir galéré avec les divisions de fixed-point. :)
Pour la racine carrée, j'ai piqué la fonction de Nrx, et si ca rame trop je ferais une "LUT": http://playeradvance.org/forum/showpost.php?p=81603&postcount=52

YoBoY
08/10/2006, 19h31
Bon ta vitesse est assez ambigue.

Esseyons d'y voir plus clair, ta vitesse est le nombre de pixels sur le vecteur qui doivent bouger par frame donc.

Tu as un objet position (X0, Y0) et tu veux le déplacer à la position (X1, Y1).
Ta distance D vérifie > (X1-X0)² + (Y1-Y0)² = D²
ton nombre de frames F vérifie > F² = D² / V²
Ton nombre de frame est un entier (ça on peux pas avoir autre chose) donc soit tu calcules la racine carré pour ce F, soit tu as un tableau, soit tu utilises un algothime (ça existe)

Après je rejoins Brunni et tes Xd = (X1-X0)/F et Yd = (Y1-Y0)/F pour tes delta de déplacement

Avantage, un seul calcul de racine carré
Avantage2, tu travailles avec des entiers (a bas les nombre réels).

Bonne chance

thoduv
08/10/2006, 20h48
J'ai deux solutions:
- N'utiliser que des entiers, dans ce cas il me faut deux variables: un délai, et un incrément X, Y. A chaque fois que "délai" frames sont passés, j'augmente avec l'incrément (ca correspond à une fraction Incrément/Délai): j'aime pas ce système, je trouve ca pas propre, et obtenir une fraction à partir d'une division c'est pas évident.
- Utiliser des réels, dans ce cas je n'ai plus qu'une variable d'incrémentation X, Y, et j'augmente à chaque frame ma position (les décimales ne sont pas affichées, évidement, mais elles servent dans l'incrémentation, deux frames à 0.5 => déplacement de 1)

Ca revient au même, puisque 0.5 = 1 / 2.

Mais je préfere la deuxieme méthode parce que je trouve plus propre, et qu'en plus je compte utiliser des zooms, et le fait d'avoir des positions réeles ca me permettra d'avoir des déplacement plus "lisses" quand c'est zoomé.

Nrx
09/10/2006, 00h50
Oui, calculer une racine carrée n'est pas chose annodine (coût CPU), et si tu peux l'éviter il est sage de le faire... mais ce n'est pas non plus un drame ; tu peux te permettre de calculer quelques racines carrées par frame sans soucis (cf. Mister Jelly, GOD, ...) ;).

YnotnA
09/10/2006, 23h10
_______
|a| = Vax²+ay²

Cour élementaire mes cher amis... d'apres ce calcul il suffit simplement d'utiliser le fameux théorème de pythagore pour calculer l'hypoténus d'un triangle rectangle, rien de plus simple

essayer avec le triangle 3,4,5
_____
5 = V3²+4²
3 pour X
4 pour Y
norme = 5

Pour ce qui est de supprimer la racine ce n'est pas chose facile... Je voudrais pas dire de connerie mais je me demande si c'est pas faisable en complexe... je regarde ca demain si j'ai le temps