Page 1 sur 1

Métrique en 3D?

Publié : lun. 16/janv./2006 20:44
par Dräc
Il y a un truc que je n’ai pas bien pigé sur les dimensions en 3D.

Imaginez que l’on ne crée pas de « World ».
Nous n’avons pas de référentiel particulier qu’aurait procuré un terrain.

Prenons par exemple la démo PB nommée « Entity.pb » (celle avec les robots)

Si j’écris EntityLocate(2, 200, 0, 0), je positionne l’entité 2 à la « coordonnée » (200, 0, 0)

Que représente cette valeur 200? Des cacahouètes ou des choux ?
200 quoi ?
Où est la métrique dans tout cela ?

En effet, mon souci est de vouloir faire coller des coordonnées 3D avec celles de ma 2D iso, mais je sens que c’est pas gagné.
Si on ajoute que la projection orthogonale n’est pas fonctionnelle, c’est mission impossible…

Publié : mar. 17/janv./2006 1:25
par cederavic
Je te conseil d'attendre la V4 pour te metre a la 3D, car pour le moment c'est plus bidouille est co ;)

Publié : mer. 18/janv./2006 15:38
par Dräc

Publié : mer. 18/janv./2006 19:12
par cederavic
Fred a écrit :i will take a closer look to that.
:P

(toute façon c'est la mode de se dir "ça ira mieu avec la V4" alors...)

Publié : mer. 18/janv./2006 22:21
par Dräc
En fait, Fred va regarder le disfonctionnement de la projection ortogonale sans perspective, mais ne prévoit rien pour la métrique...

En attendant, l'ordinateur décide bien de quelque chose car on peut lui dire de placer une entité 3D a une certaine coordonnée.

A la rigueur, il me suffirait de savoir quel est ce choix.
Une fois cela connue, je peux m'adapter à l'échelle (par une règle de trois), car les coordonnées sont divisibles car de types réels...

Donc ma question: quel choix d'échelle est-il pris par l'application dans le moteur 3D ?

Publié : mer. 18/janv./2006 22:41
par comtois
ce que j'ai compris de cette fonction cameraprojection() c'est qu'elle ne permettrait pas de calculer des projections mais de faire un affichage en 2D ?

Ce qui serait intéressant c'est une fonction qui donne la position sur l'écran d'un point 3D.

Pour ce qui est de l'échelle 3D ,il s'agit d'unité , à toi de fixer une échelle.
Par exemple faire correspondre 100 unités pour 1 mètre.
ou 500 unités pour un centimètre.
Et il n'y a pas de correspondance avec l'écran , tu n'as pas d'autre solution que de faire une projection. En connaissant les angles , la focale et la position de la caméra et la résolution de l'écran.

Du coup c'est à toi de construire ta règle de trois.
Trouve la bonne position pour ta camera en déplaçant tes particules sur ta map 2D , relève les positions 3D et 2D,tu vas bien finir par trouver une position de caméra avec le bon angle ? Ta map 2D est fixe ? ou elle peut scroller ?

Publié : mer. 18/janv./2006 23:36
par Guimauve
Moi ce que j'aurais besoin comme fonctions 3D :

1. Une commande qui puisse me dire les dimensions hors tout d'une entité. C'est pour vérifier la grandeur des entités. Afin de ne pas avoir un objet qui doit faire 15 mètres et qui en fait 1500 mètres. Et un autre objet qui doit faire 1700 mètres et qui ne fait que 1.7 mètres.
On Loadmesh(), GetOverallSize() si les dimensions sont OK on passe à la mesh suivante, si non ScaleEntity(ID,x,y,z) et on passe à la mesh suivante.

2. Une commande qui permet de retrouver l'index du vertice cliqué à l'écran. C'est pour faire un éditeur d'entité, en utilisant les vertices pour calculer des points de localisation d'entités qui doivent bouger ensemble ils seront corrigés automatiquement même après un ScaleEntity().

3. Une commande qui perment d'obtenir la position absolue d'un vertice dans le monde 3D. C'est pour localiser une entité comme la mesh d'un tirs laser au bon endroit dans le monde 3D.

A+
Guimauve

Publié : ven. 20/janv./2006 18:38
par comtois
Guimauve a écrit :Moi ce que j'aurais besoin comme fonctions 3D :

1. Une commande qui puisse me dire les dimensions hors tout d'une entité. C'est pour vérifier la grandeur des entités. Afin de ne pas avoir un objet qui doit faire 15 mètres et qui en fait 1500 mètres. Et un autre objet qui doit faire 1700 mètres et qui ne fait que 1.7 mètres.
On Loadmesh(), GetOverallSize() si les dimensions sont OK on passe à la mesh suivante, si non ScaleEntity(ID,x,y,z) et on passe à la mesh suivante.
Oui ça pourrait être pratique . +1

Pour l'instant je fais un fichier xml du mesh avec OgreXmlmachintruc ensuite j'analyse avec une petite routine (je ne sais plus ce que j'en ai fait d'ailleurs !) le xml pour récupérer les dimensions du mesh .

J'avais dû faire ça pour recentrer un mesh , en gros je calculais son centre et les offsets en x,y et z pour recalculer les positions des vertices .
ça fonctionne bien, sauf s'il y a un skeleton , là faudrait aussi adapter les valeurs , mais je n'avais pas réussi :?

Publié : ven. 20/janv./2006 21:41
par Guimauve
C'est très facile à faire lorsque l'on peut accèder au tableau des vertices.
Il faut chercher les extremums de l'entité. La plus petite et la plus grande
coordonnée en x, en y et en z.

Avec les données contenues dans un fichier xml ou directX on obtient
facilement les données. Mais avec un loadMesh() c'est impossible pour le
moment.

Si pour faire ça on doit passer par un script xml ou autre, les commandes
présente dans la dll xmltoogremesh doivent être Wrappé et incluse avec
le moteur 3D.

Une autre commande que j'aimerais bien avoir c'est SaveMesh(Nomfichier$).

À mon avis ça ne deverait pas être très difficile à faire. Il faut écrire les
données dans le même ordre qu'elle sont lues par la commande
LoadMesh(). Ça deverait marcher en théorie.

Ce que je trouve dommage avec le moteur OGRE c'est qu'il n'y a aucun
programme pour éditer le fichier Mesh directement. Bien sûr un
programme capable de charger n'importe quel type de fichier standard
(.3ds, .x, .lwo, etc), de faire l'édition complète du fichier mesh avec les
LOD progressif, de diviser en sous mesh une mesh, éditer les matières,
bref tout pour que ça marche bien.

Et avant qu'on me dise, il y a plein d'exportateur pour plein de
programme de modélisation et même certain sont gratuit.

C'est long, il faut prendre le model 3D, l'exporter sur un script xml,
ensuite il faut prendre ce script et le transformer en format mesh pour
enfin l'utiliser.

Dans mon cas, je fais la modélisation avec Rhinoceros 3D, j'exporte le
model 3D au format .3ds. Je complète l'édition du fichier .3ds avec
Ultimate Unwarp3D. Et là je suis bloqué, à moins d'exporté au format .x.

Ensuite reconvertir le fichier .x en .xml pour ensuite le transformé en
.mesh pour finalement être en mesure de l'utiliser. Bref c'est l'enfer.

Faire un éditeur pour automatiser tout ça, ça risque d'ajouter 10 à 15
mois de travail au projet. Programmation à temps perdu il va sans dire.
J'ai pas le temps de programmer à temps plein, j'ai trop de chose à faire
en ce moment. Et ça risque d'être comme ça pour encore 2 à 3 années
encore.

Pour ce qui est de :

MilkShape3D : J'ai fais des tests, résultat il à détecter un problème avec
un de mes models et la correction qu'il a fait à générer un espacement
très apparent entre les polygones. Model 3D devenu inutilisable.

Blender : Vraiment pas UserFriendly

Ultimate Unwarp3D : C'est bien, mais aucun export vers les fichiers Ogres
pour le moment. Faudrait apprendre le Langage C++ à fond et avec
Visual C++ programmer un plugin pour exporter les données dans le
format de fichier désiré. J'ai pas Visual C++, de plus je n'aime pas la
Syntaxe du C/C++. Sans compter le temps nécessaire pour apprendre le
C++ pour être en mesure de bien programmer le plugin.

3D StudioMax : 3500.00 $ à acheter ??? Pour un jeu qui rsique d'être
gratuit si je le complète c'est vraiment trop cher.

XSI/SoftImage : Similaire à 3D StudioMax, Trop cher à acheter.

Des suggestions :?:

A+
Guimauve

Publié : ven. 20/janv./2006 23:28
par comtois
des suggestions pour la modélisation ? non aucune , j'ai horreur de ça :)
C'est pourquoi je suis condamné à faire joujou avec des cubes et des sphères. Bon j'ai quelques modèles au format 3DS ou .X , mais je ne peux pas récupérer les animations ,c'est ennuyeux.

Pour ce que je fais c'est pas trop gênant .

Publié : sam. 21/janv./2006 21:21
par Dräc
Passer des coordonnées 3D à celles de l’écran, ce n’est pas très compliqué.
Il s’agit d’une simple projection.

Ainsi, si (x,y,z) sont les coordonnées de l’objet 3D (son centre par exemple) par rapport à la camera (puisque le projection est sur l’écran) alors la projection sera :

Code : Tout sélectionner

x0= ScreenWidth*(0.5-x/z)
y0= ScreenHeight*(0.5+y/z)
ScreenWidth et ScreenHeight sont les dimensions de l’écran
Le 0,5 c’est pour s’ajuster à l’origine de l’écran : la caméra est centrée mais l’origine de l’écran est dans le coin supérieur gauche. De plus l’axe y est vers le bas…

Mais cela ne suffit pas, l’écran est plus large que haut et il faut donc corriger.
D’où la correction suivante :

Code : Tout sélectionner

x0= ScreenWidth*(0.5-x/z * Ratio)
y0= ScreenHeight*(0.5+y/z)
avec Ratio = 0.75

Ratio représente pour moi, le rapport entre la hauteur et la largeur de la caméra qui peut etre différent de celui de l’écran, mais pour un meilleur rendu se doit d’etre comparable.
Or, il est impossible de le connaître en PB, mais 0.75 me semble la valeur par défaut, c’est celui des écrans 4/3 (=1.333 soit 1/0.75).

Enfin, il faut aussi prendre en compte « l’angle de vision » de la caméra, qui n’est rien d’autre qu’un zoom.
Si d est la distance de l’élément à la camera (l’élément faisant face à la caméra), son rayon apparent est donné par

Code : Tout sélectionner

r = d * tan (angle)

r
_____
\    |
 \   |  d
  \  |
   \ |
    \|
L’angle de vision de la camera est 2 fois cet angle.
On ne parle donc plus de rayon apparent mais de diamètre apparent.

Notons :
FOV0 l’angle de vision initial de la camera
FOV l’angle de vision courant

alors la dilatation du diamètre apparent est donnée par

Code : Tout sélectionner

1/Fac = tan (FOV/2)/tan(FOV0/2)
Ainsi, notre projection devient :

Code : Tout sélectionner

x0= ScreenWidth*(0.5-x/z * Ratio * Fac)
y0= ScreenHeight*(0.5+y/z * Fac)
Là encore, il n’est pas possible de connaître FOV0 en PB.
Si mon raisonnement est correct, il est de 53,0195° !!

Pour confirmer mes dires, voici un petit code.
Ce code affiche un sprite carré au centre de chaque Billboard grace à la projection exposée ci-dessus.
On peut vérifier ainsi que l’on connaît la position d’un élément 3D sur l’écran !

Les gfx sont ceux contenus dans le répertoire Data des examples PB (changez Path$ et Include).

- Les flèches pour déplacer les éléments 3D
- Page suivant / Page précédente pour changer la profondeur
- F1/F2 pour changer l’angle de vision de la caméra.

PS : j’utilise des billboard pour simuler une projection orthogonale


; Projection 3D vers 2D
; Permet de passer de coordonnées 3D aux coordonnées 2D de l'écran
;
; Dräc 01/06

#CameraSpeed = 10
DefType.f KeyX, KeyY, Fac, Ratio, FOV
Global ScreenWidth, ScreenHeight, x0, y0, Fac, Ratio

Ratio.f = 0.75
FOV.f = 53.0195

Path$ = "C:\Program Files\PureBasic\Examples\Sources\"
IncludeFile "C:\Program Files\PureBasic\Examples\Sources\Screen3DRequester.pb"

Procedure Projection(x.f, y.f, z.f)
 x0= ScreenWidth*(0.5-x/z * Ratio *Fac)
 y0= ScreenHeight*(0.5+y/z* Fac)
EndProcedure

  
If InitEngine3D ()

   Add3DArchive (Path$+ "Data\" , #PB_3DArchive_FileSystem )
  
   InitSprite ()
   InitKeyboard ()
   InitMouse ()
  
   If Screen3DRequester()
    
     CreateMaterial (0, LoadTexture (0, Path$+ "Data/clouds.jpg" ))
     RotateMaterial (0, 0.05, 1)
    
     CreateBillboardGroup (0, MaterialID (0), 10, 10)
     BillboardGroupLocate (0, 0, 0, -40)
    
     AddBillboard (0, 0, 0, 0, 0)
     AddBillboard (1, 0, -20, 0, 0)
     AddBillboard (2, 0, 20, 0, 0)
      
     CreateCamera (0, 0, 0, 100, 100)

     CreateSprite (0, 10, 10)
     StartDrawing ( SpriteOutput (0))
     Box (0,0, 10,10, RGB (255,0,255))
     StopDrawing ()

     Repeat
      Screen3DEvents()
      
       ClearScreen (0, 0, 0)
            
       If ExamineKeyboard ()
        
         If KeyboardPushed ( #PB_Key_Left )
          KeyX = - #CameraSpeed
         ElseIf KeyboardPushed ( #PB_Key_Right )
          KeyX = #CameraSpeed
         Else
          KeyX = 0
         EndIf
                  
         If KeyboardPushed ( #PB_Key_Up )
          KeyY = - #CameraSpeed
         ElseIf KeyboardPushed ( #PB_Key_Down )
          KeyY = #CameraSpeed
         Else
          KeyY = 0
         EndIf
        
         If KeyboardPushed ( #PB_Key_PageUp )
          KeyZ = - #CameraSpeed
         ElseIf KeyboardPushed ( #PB_Key_PageDown )
          KeyZ = #CameraSpeed
         Else
          KeyZ = 0
         EndIf

         If KeyboardPushed ( #PB_Key_F1 )
          FOV - 0.5
         ElseIf KeyboardPushed ( #PB_Key_F2 )
          FOV + 0.5
         EndIf
                
       EndIf
       CameraFOV (0, FOV)
      Fac = Tan (0.5*53.0195*3.1415/180.)/ Tan (0.5*FOV*3.1415/180.)
      
       ;MoveCamera(0, KeyX, KeyY, KeyZ)
       MoveBillboardGroup (0, KeyX, KeyY, KeyZ)
      
       RenderWorld ()

      Projection(( BillboardGroupX (0)+ BillboardX (0,0))- CameraX (0), BillboardGroupY (0)- CameraY (0), BillboardGroupZ (0)- CameraZ (0))
       DisplaySprite (0, x0-5, y0-5)

      Projection(( BillboardGroupX (0)+ BillboardX (1,0))- CameraX (0), BillboardGroupY (0)- CameraY (0), BillboardGroupZ (0)- CameraZ (0))
       DisplaySprite (0, x0-5, y0-5)

      Projection(( BillboardGroupX (0)+ BillboardX (2,0))- CameraX (0), BillboardGroupY (0)- CameraY (0), BillboardGroupZ (0)- CameraZ (0))
       DisplaySprite (0, x0-5, y0-5)

      Screen3DStats()
       FlipBuffers ()
     Until KeyboardPushed ( #PB_Key_Escape ) Or Quit = 1
   EndIf
    
Else
   MessageRequester ( "Error" , "The 3D Engine can't be initialized" ,0)
EndIf
  
End

Publié : sam. 21/janv./2006 21:21
par Dräc
Voici donc pourquoi je suis demandeur à connaître certains paramètres de l’environnement 3D…
Il y a en effet certains manques comme connaître et modifier « Ratio » et « FOV0 ».
En effet, selon la définition de l’écran, un cercle peut devenir une ellipse à moins de changer le ratio de la caméra…

Publié : sam. 21/janv./2006 22:02
par comtois
Il vaut mieux demander au moteur de faire le calcul de la projection.
Je me contenterais bien d'une fonction qui me retourne la projection sans avoir à faire le calcul moi même :)

S'il faut le faire soi même ,alors c'est clair qu'il manque des infos :?

Publié : dim. 22/janv./2006 0:02
par Dräc
Mais elle existe déjà puisque le rendu 3D consiste en premier lieu à projeter la scène sur l’écran !

L'inverse est moins vrai: positionner une entité 3D à partir de coordonnées 2D.
Heureusement, il suffit d'inverser les formules ci-dessus.

Mais il est important de connaître certains paramètres principaux du moteur 3D pas uniquement pour la projection !

Comme je le disais, il y a la maîtrise des proportions à l’affichage.
Il est étonnant aussi qu’avec PB on puisse modifier l’angle de vision, mais qu’il manque le moyen de le lire !