PDA

Voir la version complète : Moteur physique d'un flipper , et rien d'autre :)


Comtois
23/04/2005, 12h23
Bon , le sujet m'intéresse ,mais je n'ai pas la moindre idée de ce qu'il faut faire .
Je fais un nouveau post , parce que le sujet est ouvert à tous , et n'a rien à voir avec le projet de flipper en commun.
Ici il n'est pas question de parler de langage , mais d'un moteur , et s'il est nécessaire d'aligner des lignes de code, essayez de le faire de préférence en pseudo code, et si vous ne pouvez pas faire autrement , alors dans le langage de votre choix en détaillant.

j'ai commencé par chercher des cours de physique sur les mobiles sur un plan incliné , je vous livre ici le début des recherches , je commence tout juste .

Plan incliné (http://www.phy6.org/stargaze/Fvector.htm)

Soit s l'angle de la pente.
à retenir

Masse du mobile : m
Poids du mobile : p = m * g
direction = p * sin(s)
Accélération = g sin(s)

si j'écris des bêtises ,merci de me corriger :)

avec google , on passe du site cité ci dessus , à ce genre de site

hor sujet ? (http://www.educauto.org/Documents/Infotech/pneu1.pdf)
je ne l'ai pas encore lu , mais c'est difficile de trouver les bons sites ,c'est soit niveau collège et on apprend rien , soit des thèses , et on ne comprend rien :)

bon , je cherche encore .

ensuite , il y a besoin de quoi ? gérer des collisions glissantes ? comment fait la balle pour suivre le pourtour d'une table ? exemple dans une rampe de lancement , si elle est incurvée , la balle suit le profil sans rebondir .

Lightness1024!
23/04/2005, 12h43
tu n'a pas besoin de faire les calculs (formels) explicite du mouvement sur un plan incliné.
au contraire ton moteur doit faire réagir la balle naturellement correctement.
tu n'as qu'une loi a appliquer, c'est l'acceleration de la pesanteur, le reste de tous les effets que pourra subir la balle sera conséquence du moteur de collisions.
donc en résumé, le gros du probleme se trouve dans les collisions et rien d'autre.
pour simplifier tu peux oublier les moments et les mouvements de rotations de la bille sur elle même qui n'aurons aucun effets si les frottements ne sont pas gérés (peu important). cela peut etre important si tu tiens compte des moments d'inertie de la bille dans les mouvements avec frottements.
sans tout ceci, seuls les forces importent, et les forces de réaction.
tu peux te simplifier le probleme en travaillant en 2D, et en disant que l'acceleration verticale de la bille est celle de la terre fois le sinus de l'angle du flipper ave le sol. (ou le cosinus si tu prends un angle par rapport au mur).
enfin pour ca fait un dessin ce n'est qu'un petit calcul à ne faire qu'une seule fois.

et à partir de ca seuls les réactions des paroies vont compter maintenant.
donc trouve une méthode géométrique qui te permet de trouver le point de contact entre la périphérie d'un cercle et un segment lorsque tu déplaces ton cercle selon un vecteur vitesse V.
une fois que tu as ca, applique les relations de la quantité de mouvement (p=mv) pour faire rebondir ta balle, si elle rebondi sur un champignon, alors de l'énergie cinétique est ajoutée au mouvement, tu peux en tenir compte de maniere empirique en multipliant le vecteur V par un coefficient supérieur à 1.

voila bonne chance

Comtois
23/04/2005, 12h48
donc trouve une méthode géométrique qui te permet de trouver le point de contact entre la périphérie d'un cercle et un segment lorsque tu déplaces ton cercle selon un vecteur vitesse V.

J'avais aussi commencé à m'intéresser à ça , alors je vais ressortir ce que j'avais mis de côté et plancher dessus :)

tu parles de collisions et de rebonds, mais pour faire glisser la balle sur le pourtour de la table de flipper ? tu as une idée de ce qu'il faut faire ?

bon , j'ai un début de piste, je vais bosser ça déjà .

Lightness1024!
23/04/2005, 13h28
oui j'ai implémenté une technique de detection des collisions 3D basé sur un modèle spéhrique dans mon FPS (www.serhum.fr.st) donc je suis effectivement en mesure de le faire.
mais je ne vais pas trop t'aider non plus sinon tu n'auras pas la même satisfaction intellectuelle.

j'ai parlé de rebond oui, mais il y a rebond et glissement en même temps, il faut partager l'énergie :D

Comtois
23/04/2005, 13h30
mais je ne vais pas trop t'aider non plus sinon tu n'auras pas la même satisfaction intellectuelle.

Ne t'inquiète pas pour ça , j'ai d'autres ressources pour ma satisfaction intellectuelle :D

LaurentUSA
23/04/2005, 16h40
Le modele suggere par L1024 est tres insuffisant. Il faudra gerer spin et friction dynamique.

Comtois
23/04/2005, 16h43
Le modele suggere par L1024 est tres insuffisant. Il faudra gerer spin et friction dynamique.

ah zut , j'étais tout content d'avoir trouvé ça

Collision glissante (http://www.gamedev.net/reference/articles/article1026.asp)

ça ne va pas suffire alors ? mais est-ce que c'est une bonne piste ?
De toute façon , je ne perdrai pas mon temps à tenter de comprendre et de faire quelque chose sur cette base .

Lightness1024!
24/04/2005, 00h38
Je commence à me demander si il dit pas ca juste pour le plaisir de toujours me contredir parce qu'il m'aime pas. :00000005:

le tutoriel de Paul Nettle est de très très bonne facture et d'ailleur je m'en suis largement inspiré pour batir mon detecteur de collisions.
Et je peux affirmer qu'a base de collisions de ce genre la tous les effets que l'on est en droit d'attendre d'un flipper de qualité niveau "MS pinball 3D" pouront être réalisés.

LXS
24/04/2005, 15h15
J'avoue que pour un petit jeu... c'est sortir l'artillerie lourde.

Comtois
24/04/2005, 17h11
Yahou ! Je suis content , voici un début de résultat .
Pour l'instant , je détecte la collision d'une sphère avec deux segments .
c'est peut-être un détail pour vous , mais pour moi c'est déjà beaucoup :00000023:

Vous pouvez voir ce que ça donne , téléchargez TestCollision (http://perso.wanadoo.fr/comtois/sources/testcollision.exe) (28 ko)

Les segments et la sphère peuvent être déplacés à la souris , pour cela il suffit de faire glisser les extrémités des segments ou le centre de la sphère.

Je ne mets pas encore le source, j'ai du boulot pour améliorer la chose , et d'autres tests à faire , comme les collisions glissantes.

LXS
24/04/2005, 17h21
Bon ben j'attendrai les sources, les exé se lancent pas chez moi :mad:

Comtois
24/04/2005, 17h30
ça fonctionne chez quelqu'un ou ça plante chez tout le monde ?

Je viens de télécharger le fichier pour le tester ,et chez moi ça tourne (XP sp2).

Loulou
24/04/2005, 17h48
Chez moi ça fonctionne au poil (Windows XP SP1).

ZeBlueCow
24/04/2005, 17h50
ici ça marche nickel :)

(portable avec xp sp 2 + ati)

Joker-eph
28/04/2005, 12h56
Chez moi ça tourne pas ( Kernel 2.6.9-gentoo-r9 ) :00000002:

Comtois
28/04/2005, 18h29
si j'ai du courage ce week-end , je te ferai une version linux :)

normalement , j'ai juste à compiler sous linux sans toucher à mon code, ah que c'est cool PureBasic :)

et si j'ai encore un peu de courage ce week-end , je bosse sur les collisions glissantes . Mais avant je vais me faire un banc d'essai en 3D , comme ça je pourrai tester les fonctions sur de la 2D et de la 3D .

Joker-eph
28/04/2005, 20h00
C'etait juste un troll :00000023:

Ne t'embète pas pour moi, j'attendrai que ton code soit "présentable"

Comtois
30/04/2005, 19h07
oui j'ai implémenté une technique de detection des collisions 3D basé sur un modèle spéhrique dans mon FPS (www.serhum.fr.st) donc je suis effectivement en mesure de le faire.
mais je ne vais pas trop t'aider non plus sinon tu n'auras pas la même satisfaction intellectuelle.

Et si on disait qu'en ce qui concerne ma satisfaction intellectuelle je suis comblé ? et que tu daignes m'en dire un peu plus hein dis ? :)

Bon j'ai un peu avancé, maintenant ça glisse , enfin c'est vraiment pas terrible .
TestCollision (http://perso.wanadoo.fr/comtois/sources/testcollision.exe)
(il n'y a pas grand chose de plus à voir par rapport à la dernière fois , alors téléchargez seulement si vous n'avez rien de mieux à faire :)

j'ai encore quelques essais à faire .
Ensuite , peut-être que dans une semaine ou deux, je serai en mesure de faire un résumé de mes déboires, et une présentation de ce que j'ai déjà fait , ainsi qu'un bilan des points sur lesquels j'aimerais quelques informations , en espérant que quelqu'un saura y répondre pour me débloquer .

A suivre ... :)

Comtois
01/05/2005, 01h00
Que diriez vous de traduire ce tut Collision glissante (http://www.gamedev.net/reference/articles/article1026.asp) en français , et surtout en détaillant un peu plus , parce que tel quel c'est galère !!

par exemple

double intersect(Point pOrigin, Vector pNormal, Point rOrigin, Vector rVector)
{
double d = -(planeNormal * planeOrigin);
double numer = planeNormal * rayOrigin + d;
double denom = planeNormal * rayVector;
return -(numer / denom);
}

il faudra expliquer que planeNormal * planeOrigin, c'est en fait un produit scalaire , et pour les forts en math , essayer d'apporter le maximum d'infos , ou d'autres façons d'arriver au même résultat. Faire un rappel sur le calcul des normales, etc.Bref développer complètement l'exemple pour qu'il soit fonctionnel.

Je ne suis malheureusement pas en mesure de le faire seul .

demain , je vais commencer , en espérant ne pas écrire trop de bêtises :)

ça pourrait être l'occasion d'aborder pas mal de problèmes que l'on rencontre souvent dans la programmation des jeux.
Calcul des normales, calcul des collisions , gestions des collisions, etc.

C'est un projet qu'on pourrait avoir en commun non ??

Comtois
01/05/2005, 10h10
Bon je commence par le début ,et aussi par le plus simple

Dans la doc on peut lire ça :

// Inputs: plane origin, plane normal, ray origin ray Vector.
// NOTE: both vectors are assumed To be normalized

double Intersect(Point pOrigin, Vector pNormal, Point rOrigin, Vector rVector)
{
double d = -(planeNormal * planeOrigin);
double numer = planeNormal * rayOrigin + d;
double denom = planeNormal * rayVector;
Return -(numer / denom);
}

Voici ce que j'en ai compris :

pOrigin c'est un point du plan , peu importe lequel
pNormal , c'est la normale du plan , le vecteur est normé.
rOrigin , c'est la position d'Origine de la sphère
rVector , c'est la direction dans laquelle on veut calculer la distance du point au plan, le vecteur est normé.

double Intersect(Point pOrigin, Vector pNormal, Point rOrigin, Vector rVector)
{
double d = -(pNormal.x * pOrigin.x + pNormal.y * pOrigin.y + pNormal.z * pOrigin.z);
//Numérateur
double numer = (pNormal.x * rOrigin.x + pNormal.y * rOrigin.y + pNormal.z * rOrigin.z) + d;
//dénominateur
double denom = (pNormal.x * rVector.x + pNormal.y * rVector.y + pNormal.z * rVector.z);
Return -(numer / denom);
}

Quelques rappels

Norme d'un vecteur

Soit le Vecteur V(x,y,z)

Sa Norme est égale à :

|V| = Sqr( x² + y² + z²)

On parle d'un vecteur normé quand sa norme est égale à 1.

La norme représente la longueur du vecteur.

Normale d'un plan

Il s'agit d'un vecteur orthoganal à ce plan .
Pour le déterminer , on peut effectuer un produit vectoriel entre deux vecteurs du plan .

Soit deux vecteurs V1(x1,y1,z1) et V2(x2,y2,z2) et la Normale N(xn,yn,zn)

xn = y1z2 - y2z1
yn = z1x2 - z2x1
zn = x1y2 - x2y1

Et je termine par le produit scalaire , il y en a beaucoup dans ce tut , ça serait dommage de ne pas en parler :)

Produit scalaire

Soit deux vecteurs V1(x1,y1,z1) et V2(x2,y2,z2)

le produit scalaire V1*V2 = x1x2 + y1y2 + z1z2


Pour la traduction du texte anglais , je préfère ne pas me lancer là dedans , j'ai fait très peu d'anglais.mais ça serait bien si quelqu'un voulait s'en charger .

Bon je vais continuer à détailler les fonctions de mon côté .

Lightness1024!
03/05/2005, 23h59
bon alors ok, je veux bien en dire un maximum, je me demande ou j'ai foutu mes papiers avec tous les calculs..
hum, je crois que je les ait oubliés à Bordeaux :/ (je suis à Lyon pour les vacances)

je n'ai pas du tout regardé un pet de son implémentation, car je ne suis pas certain mais je crois que ya des erreurs et puis de toute façons je préfère trouver toutes ces fonctions par moi meme.

bon, je peux choper directement le code source dans mon projet et poster, mais c pas super propre je le dis tout de suite.
et puis de tête je peux en ressortir bcp kan meme. (des maths, pas du code hein)


//-------------------------------------------------------------------------------------------------------
// Fonction: détermine le coefficient de collision entre un vecteur (vO + V) et un plan (N, d)
// retourne: le coefficient en question (NaN si parrallele #INF)
//-------------------------------------------------------------------------------------------------------
float GetVectorRatioToPlane2(const D3DXVECTOR3& N, const D3DXVECTOR3& PtOnPlane, const D3DXVECTOR3& vOrigin, const D3DXVECTOR3& vector)
{
D3DXVECTOR3 d1;
d1 = PtOnPlane - vOrigin;
return D3DXVec3Dot(&d1, &N) / D3DXVec3Dot(&vector, &N);
}


l'explication de cette fonction provient si je me souvient bien (putain chui con de pas avoir mes papiers) du résultat de l'idée suivante:

en entrée on a:
-un vecteur, et un point de départ pour ce vecteur (donc un segment de droite positionné dans l'espace).
-un plan (ce plan, on a une normale et un point lui appartenant)

ca fait donc 4 vecteurs.

l'idée c'est de projeter le vecteur formé du segment reliant le point sur le plan, et l'origine du rayon à tracer, sur la normale du plan.
cela a pour effet de retourner un nombre (scalaire) indiquant la dimension du vecteur (d1) vue de la normale du plan.
(l'ombre, la projection orthogonale, la dimension/la coordonnée selon N...)
autrement dit, la distance qui sépare le point origine du plan.

non je me trompe de piste, ca peut pas s'expliquer directement, en fait c'est le résultat analytique à partir de l'équation qui dit que le produit scalaire entre le vecteur reliant le point intersection I (que l'on souhaite trouver) et la normale est nul.
apres on exprime nos vecteurs par combinaison de trucs suivant le plan et la normale.
bon, je sens que je vais prendre un papier et recommencer (ca fait longtemps que je l'ai faite celle la :) )
(...) (temps qui passe)
ok je l'ai:
N . (Orig + t * Ray - P)) = 0
il faut extraire t.

car on sait que: N.PI = 0
N = normale du plan
PI = Intersection - point du plan
or, I peut s'exprimer comme un coefficient t fois notre Rayon.
donc I = OrigineRayon + t * Rayon
donc on remplace et ca donne l'equation en haut.
ensuite on travaille dessus:
N(PO+tV) = 0
N(OP) = N.tV
t = N.OP / N.V
et voila !

voici une petite partie des trucs que je fais pour m'aider dans ces problemes:
seulement celui la c'est pas vraimentle début :)
http://lightness1024.free.fr/SlidingPlane.png

cette image représente le moyen de calculer le vecteur glissement apres une detection de collision.
donc ca vient en dernier, mais le shema peut permettre de se mettre bcp de choses en tête.

le point de contact sphere plan c'est une des plus grosses étapes, quand il tombe pile au milieu d'un triangle, ca va encore, mais quand il tombe au dela, il faut utiliser la technique Paul Nettle, i.e.: backtracer un rayon dans le sens opposé à la direction et cherche les intersections avec la sphere.

ce qui se fait a l'aide d'une fonction comme ceci:


//-------------------------------------------------------------------------------------------------
// Fonction: détermine le coefficient de collision du premier point d'intersection entre une sphere et un rayon
// note : si le vecteur directeur du rayon n'est pas normalisé le résultat est imprévisible
// : retourne vrai si t prend cette valeur, faux si l'intersection n'existe pas
//-------------------------------------------------------------------------------------------------
bool SphereWithRayIntersect(const D3DXVECTOR3& SCenter, const float& SRadius, const D3DXVECTOR3& Point0, const D3DXVECTOR3& RayD, float* t)
{
// la technique de cette fonction est purement analytique, et non géométrique
// le rayon est paramétré par P = Point0 + t * RayD
// la sphère est décrite par: norme(P - SCenter)² = SRadius²
// la résolution de ce système donne un polynôme du deuxième degré en t
// on trouve a = RayD.RayD, b = RayD.dist * 2, c = dist.dist - SRadius²
// on trouve d = b² - 4ac
// après simplifications (notamment pdtScalaire(RayD, RayD) = 1)
// on trouve t1 = RayD.dist - sqrt((RayD.dist)² - dist.dist + SRadius²) et t2 pareil mais avec +

D3DXVECTOR3 dist;
float t1;
float d; // discriminant réduit
float b;
float sqd;

dist = SCenter - Point0; // inversé par rapport au calcul pour éviter un * -1 plus tard
b = D3DXVec3Dot(&RayD, &dist); // le vrai b est -2 * celui-ci
d = b * b - D3DXVec3Dot(&dist, &dist) + SRadius * SRadius;
if (d < 0.0f)
{
// pas de solutions => pas d'intersection !
return false;
}
sqd = sqrt(d);
// t1 est la plus petite racine (entre t1 = b - sqd et t2 = b + sqd)
// c'est le premier point de collision: donc c'est lui qui nous interresse
t1 = b - sqd; // pas -b car b est déjà inversé
*t = t1;
return true;
}

je pourrais aussi l'expliquer, ca m'a pris pas mal de temps pour la trouver donc je vais peut etre pas recommencer maintenant, j'attendrais Bordeaux si ca ne vous gène pas :D

Lightness1024!
04/05/2005, 00h53
arf on a pas le droit a bcp d'images en meme temps :'(
voila la suite:


pour savoir si le point d'intersection rayon/plan tombe dans le triangle testé ou à coté, cette fonction sera utile:


//-------------------------------------------------------------------------------------------------------
// Fonction: vérifie si un point se situe dans un triangle de la structure POLY_N_PLANE
// note : encore la même que celle d'au dessus mais spéciale optimisée collisions
//-------------------------------------------------------------------------------------------------------
bool IsInPNPPrism(const D3DXVECTOR3& point, const POLY_N_PLANE* pnp)
{
int vertx;
D3DXVECTOR3 v;

for (vertx = 0; vertx < 3; ++vertx)
{
v = pnp->vertex[vertx] - point;
if (D3DXVec3Dot(&v, &pnp->EdgeNormal[vertx]) < 0.0f)
{ // point en dehors du triangle
return false;
}
}
return true;
}


sachant que:


struct POLY_N_PLANE
{
D3DXVECTOR3 vertex[3];
D3DXVECTOR3 normal;
D3DXVECTOR3 EdgeNormal[3];
D3DXVECTOR3 EdgeDirect[3];
float d;
};


petite image que j'avais faite ya longtemps:

http://lightness1024.free.fr/expl2.PNG

le truc c'est de dire, si le point est à gauche de toutes les arêtes alors il est dans le triangle.
(pour ca on calcule les normales aux aretes, et on fais des produits scalaires avec les vecteurs gris, si ils sont tous négatifs (ou positifs selon l'orientation) c'est que le point est à l'intérieur de l'arête).

Lightness1024!
04/05/2005, 01h02
http://forumv3.games-creators.org/viewtopic_5825.htm

Comtois
04/05/2005, 07h20
Merci , c'est pas sûr que j'ai le niveau en math pour capter quelque chose ,mais je vais regarder ça attentivement , et essayer de le mettre en pratique avec purebasic :)

Mokona
04/05/2005, 07h20
Ce que je ne comprends pas, c'est pourquoi il faudrait calculer le glissement.

Une bille de flipper, ca rebondit. Et non seulement sa rebondit, mais c'est en rotation, ce qui fait que le rebond n'est pas tres simple. Pour la même raison, sa trajectoire n'est pas rectiligne (ceci dit, on doit pouvoir revenir à un cas rectiligne si on considère un temps très court).

Les collisions glissantes, c'est plutôt ce qui permet à un personnage de FPS de ne pas rester scotché à un mur à la moindre collision, non ?

Bahamut
04/05/2005, 07h53
Il faut faire de la physique approximative dans le câdre des jeux.

Calculer le glissement n'est pas totalement faux.
On peut toujours calculer le frottement de glissement de la balle (selon la force de poussée exercée sur elle) sur les différents éléments du flipper selon leur coefficient d'adhérence/frottement...puis vient deux types de frottements : le frottement sec et le frottement humide/lubrifié.
--> Les frottements mécaniques = Loi de Coulomb (si ma mémoire est bonne).
Sachant que le coefficient de frottement n'est pas le même selon qu'on a un contact acier/acier ou bien acier/bois, ou bois/bois ou bois/glace, etc....
==> mais est ce vraiment interressant ?

Suivre exactement un modèle mécanique ou physique est impossible. Le processeur va passer plus de temps à calculer le modèle mathématique qu'exécuter le reste. Cherchez plutôt un modèle simplifié proche du modèle réel. Ce modèle doit être simple mais assez réaliste...c'est là toute la difficulté. :00000013:

Parcontre, je n'ai pas vu le mot Gravité ds vos posts ?
(bon, j'avoue que j'ai lu une ligne sur 2)
La gravité doit etre integrée

Lightness1024!
04/05/2005, 08h47
mokona:
oui tu as 100% raison en réalité, c'est ce que je mentionnait dans la premiere page.
ici j'ai posté le code et les dessins que j'ai produits lors de l'implémentation de mon FPS, donc tu as raison.

dans le cas du flipper, il faut faire un rebond avec une petite perte d'energie, (comme je l'ai déja expliqué). le coup de la rotation et des frottements j'en ai déja parlé aussi, je pense que pour avoir un modele "sans suriprises" genre pinball 3d, il est possible d'ignorer les moments d'inertie, et tout forottements sans que ca paraisse horrible.

Comtois
04/05/2005, 12h30
Parcontre, je n'ai pas vu le mot Gravité ds vos posts ?
(bon, j'avoue que j'ai lu une ligne sur 2)
La gravité doit etre integrée

si si j'en ai parlé dès le début , il faut tenir compte du plan incliné de la table de flipper .

Plan incliné

Soit s l'angle de la pente.
à retenir

Masse du mobile : m
Poids du mobile : p = m * g
direction = p * sin(s)
Accélération = g sin(s)

Sinon , faute de savoir comment mieux gérer la simulation d'une balle de flipper , on peut dans un premier temps simplifier à l'extrème , du moment que le plaisir du jeu est présent , c'est ce qui compte .
Ensuite , dans un deuxième temps , il est toujours possible de chercher à améliorer la physique , si quelqu'un est capable de le faire ou d'apporter des idées , c'est sûr que ça serait intéressant de pousser un peu plus loin , mais commençons modestement , faisons un truc qui fonctionne , et après on pourra passer à la version 2.0 :)

J'avais commencé des recherches sur la gestion d'une balle de billard , il y a beaucoup de calcul qui tient compte justement de l'effet de glissement et de rotation de la balle . ça pourrait servir de base , mais chaque chose en son temps.