IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

3D Java Discussion :

[JAVA3D] Positionner la camera vers le centre de mon objet


Sujet :

3D Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Novembre 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 15
    Par défaut [JAVA3D] Positionner la camera vers le centre de mon objet
    Bonjour,

    Je suis en train de me mettre a l'API de Java3D et le système de gestion des ViewingPlatform me résiste. Je n'arrive pas à me représenter ce que je modifie.

    Voila ce que j'aimerai faire :

    J'ai un pavé [0,0,0] , [100,200,100]
    J'aimerai positionner ma camera en [0,300,0] et qu'elle regarde le point [50,150,50]



    Je me suis donc construit une classe BattleCamera mais je n'arrive pas a comprendre l'enchainement des transformations sur mon PlatformView :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
     
    package com.didigame.acariaempire.battle;
     
    import javax.media.j3d.BoundingSphere;
    import javax.media.j3d.BranchGroup;
    import javax.media.j3d.Transform3D;
    import javax.media.j3d.TransformGroup;
    import javax.media.j3d.View;
    import javax.media.j3d.ViewPlatform;
    import javax.vecmath.Point3d;
    import javax.vecmath.Vector3d;
     
    import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
    import com.sun.j3d.utils.behaviors.mouse.MouseBehavior;
    import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
    import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
    import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
    import com.sun.j3d.utils.universe.SimpleUniverse;
    import com.sun.j3d.utils.universe.ViewingPlatform;
     
    public class BattleCamera {
     
    	private BattleView battleView;
    	private Point3d centerPosition;
    	private Point3d currentPosition;
     
    	public BattleCamera( BattleView battleView )
    	{
    		this.battleView = battleView;
     
    		//Set camera max distance
    		double cameraDepth = 2 * battleView.getSceneDepth();
    		View view = battleView.getUniverse().getViewer().getView();
    		view.setBackClipDistance( cameraDepth );
     
    		centerPosition = new Point3d( battleView.getSceneWidth() / 2.0, 150, battleView.getSceneDepth() / 2.0 );
    		currentPosition = new Point3d( 0, 0, 0 );
     
    		initKeyCatcher();
    		initMouseCatcher();
    		initialPosition();
     
    	}
     
     
    	private void initKeyCatcher() {...}
     
    	public void initMouseCatcher() {...}
     
    	private void initialPosition()
    	{
    		ViewPlatform viewPf = battleView.getUniverse().getViewingPlatform().getViewPlatform();
    		viewPf.setViewAttachPolicy( View.NOMINAL_SCREEN );
    		walkAroundCenter( 0.0,300.0, 0.0 );
    	}
     
    	private void setCameraPosition( double x, double y, double z )
    	{
    		ViewingPlatform viewingPf = battleView.getUniverse().getViewingPlatform();
     
        	TransformGroup vpGroup = viewingPf.getMultiTransformGroup().getTransformGroup(0);
        	Transform3D vpTranslation = new Transform3D(); 
        	vpTranslation.setTranslation( new Vector3d( x, y, z ) );
        	vpGroup.setTransform(vpTranslation);
     
        	currentPosition = new Point3d( x, y, z );
    	}
     
     
    	private void rotateCamera( )
    	{
    		ViewingPlatform viewingPf = battleView.getUniverse().getViewingPlatform();
     
        	TransformGroup vpGroup = viewingPf.getMultiTransformGroup().getTransformGroup(1);
        	Transform3D rotation = new Transform3D(); 
        	rotation.lookAt( centerPosition, currentPosition, new Vector3d(0,1,0));
        	vpGroup.setTransform( rotation );
    	}
     
     
    	public void walkAroundCenter( double x, double y, double z )
    	{
    		//Translation
    		setCameraPosition( x, y, z );
     
    		rotateCamera();
    	}
    }
    Ce que je n'arrive pas a comprendre, c'est pourquoi lorsque je fait mon lookAt suivi de la translation, je trouve un résultat diffèrent que lorsque je fais translation puis lookAt....

    Si quelqu'un peut éclairer ma lanterne...

    Merci d'avance

  2. #2
    Expert confirmé

    Profil pro
    Fabricant et casseur d'avions
    Inscrit en
    Avril 2004
    Messages
    3 817
    Détails du profil
    Informations personnelles :
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Fabricant et casseur d'avions
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2004
    Messages : 3 817
    Par défaut
    Salut,

    Citation Envoyé par Aschiehle Voir le message
    Ce que je n'arrive pas a comprendre, c'est pourquoi lorsque je fait mon lookAt suivi de la translation, je trouve un résultat diffèrent que lorsque je fais translation puis lookAt....

    Si quelqu'un peut éclairer ma lanterne...
    Ca, c'est parce que les transformations 3D ne sont pas commutatives.
    Translation*Rotation!=Rotation*Translation

    Pour bien s'en rendre compte, il faut se pencher sur les calculs matriciels correspondant à ces transformations.

    De manière plus imagée, pour ton cas, prend l'exemple de toi regardant ton écran.

    Je te dis: regarde ton écran, et bouge de 2 mètres vers la droite.
    Le résultat sera différent de si je te dis: bouge de deux mètres vers la droite, et regarde ton écran.
    Sauf si dans le premier cas je te dis "continue à regarder ton écran en bougeant vers la droite", mais ça rajoute une rotation supplémentaire, que tu n'as pas dans ton code... d'où la différence.
    "Errare humanum est, sed perseverare diabolicum"

    Ma page sur DVP.com

  3. #3
    Membre averti
    Inscrit en
    Novembre 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 15
    Par défaut
    Salut,
    Merci pour la réponse.

    Je ne doit pas avoir du tout compris ce que faisait le lookAt en fait...

    Pour moi :

    - setCameraPosition : Déplacement de la camera dans le repère initiale
    - lookAt : Aucun changement de position. Simplement une orientation de la camera vers un point précis.

    Vu que le déplacement n'était pas relatif (dans ce que j'avais compris) au repère de l'objet mais au repère de la scène, je pensais pouvoir inter-changer les deux.
    Pour reprendre ton exemple, je pensais :
    Regarde vers le nord / va te mettre au point B


    Dans ton explication, deux choses m'intéresse grandement :

    "continue à regarder ton écran en bougeant vers la droite"
    Il y a moyen de faire cela par code, sans avoir a recalculer la rotation soit même a chaque fois ?
    C'est ce que j'aimerai que fasse ma méthode walkAroundCenter(...) en fait

    Ca, c'est parce que les transformations 3D ne sont pas commutatives.
    Translation*Rotation!=Rotation*Translation
    Donc lookAt = Rotation ...
    Voici ce que décrit l'API :
    public void lookAt(Point3d eye,
    Point3d center,
    Vector3d up)

    Helping function that specifies the position and orientation of a view matrix. The inverse of this transform can be used to control the ViewPlatform object within the scene graph.

    Parameters:
    eye - the location of the eye
    center - a point in the virtual world where the eye is looking
    up - an up vector specifying the frustum's up direction
    Ce que je fais donc :
    eye = le point ou j'ai pose ma camera via la fonction setCamera()
    center = le point que je veux regarder
    up = (0,1,0) pour ne pas avoir la vue totalement retournée.

    C'est manifestement pas cela qu'il faut faire ... mais je ne vois pas ce qui cloche....

    Si quelqu'un voit ce qui cloche....

  4. #4
    Expert confirmé

    Profil pro
    Fabricant et casseur d'avions
    Inscrit en
    Avril 2004
    Messages
    3 817
    Détails du profil
    Informations personnelles :
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Fabricant et casseur d'avions
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2004
    Messages : 3 817
    Par défaut
    Citation Envoyé par Aschiehle Voir le message
    C'est manifestement pas cela qu'il faut faire ... mais je ne vois pas ce qui cloche....
    Si si, c'est ce qu'il faut faire... mais je ne vois pas du tout quel est ton problème. Faire les deux transformations dans des ordres différents ne donne pas le même résultat, ok... donc il suffit de prendre l'ordre qui donne le bon et puis voilà. Non?

    D'ailleurs je ne vois pas pourquoi tu parles de translation. Tu positionnes ta caméra là où tu veux, et tu vises le point que tu veux, tout ça avec le lookAt. A quoi sert la translation?
    "Errare humanum est, sed perseverare diabolicum"

    Ma page sur DVP.com

  5. #5
    Membre averti
    Inscrit en
    Novembre 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 15
    Par défaut
    Le lookAt est censé faire les deux?

    Ok, je vais tester en supprimant ma translation :p

    Le lookAt fait bien lui même la translation.

    Nouvel essai:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    public class BattleCamera {
     
    	private BattleView battleView;
    	private Point3d centerPosition;
    	private Point3d currentPosition;
     
    	public BattleCamera( BattleView battleView )
    	{
    		this.battleView = battleView;
     
    		//Set camera max distance
    		double cameraDepth = 10 * battleView.getSceneDepth();
    		View view = battleView.getUniverse().getViewer().getView();
    		view.setBackClipDistance( cameraDepth );
     
    		initialPosition();
    		initKeyCatcher();
    		initMouseCatcher();
    	}
     
     
    	private void initKeyCatcher() {...}
     
    	public void initMouseCatcher()  {...}
     
    	private void initialPosition()
    	{
    		centerPosition = new Point3d( 0, 0, 0 );
    		updateCamera( 10, 50, 10 );
    	}
     
    	public void updateCamera( double x, double y, double z )
    	{
    		currentPosition = new Point3d( x, y, z );
     
    		ViewingPlatform viewingPf = battleView.getUniverse().getViewingPlatform();
     
        	TransformGroup vpGroup = viewingPf.getMultiTransformGroup().getTransformGroup(0);
        	Transform3D rotation = new Transform3D(); 
        	rotation.lookAt( currentPosition, centerPosition, new Vector3d(0,1,0));
        	vpGroup.setTransform( rotation );
    	}
    }
    Résultat :
    Le lookAt positionne bien la camera. Plus besoin que je fasse une translation puis une rotation!
    Je n'arrive pas a comprendre comment il positionne la camera.


    Test numéro 1 :
    J'ai tenté de faire un test simple pour voir ce qui allait pas :
    scène : [0,0,100,100]
    centerPosition = (0,0,0)
    currentPosition = (10,50,10)

    Logiquement, je devrais visualiser le coin [0,0,10,10] avec cette exemple.
    Et ben non! Je vois.. le vide!
    Et quand je recule la camera, je finis par voir ma scene. En haut à droite de l'écran. Comme si j'étais en [-10,-50,-10]

    Test numéro 2 :
    centerPosition = (0,0,0)
    currentPosition = (-10,-50,10)

    Je me retrouve à peu près a l'endroit que j'avais espéré dans le test 1.


    Il y a donc encore quelque chose que je n'ai manifestement pas compris. Si ca saute aux yeux a quelqu'un...

    Sinon, si quelqu'un sait comment logger la position du ViewingPletform, je suis aussi preneur

    Merci d'avance

    Edit 2 :
    Eureka !
    lookAt est la matrice inversée!

    Il fallait simplement que je fasse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        	Transform3D look = new Transform3D(); 
        	look.lookAt( currentPosition, centerPosition, new Vector3d(0,1,0));
     
           	Transform3D rotation = new Transform3D(); 
           	rotation.invert( look );
    Problème résolu!

  6. #6
    Expert confirmé

    Profil pro
    Fabricant et casseur d'avions
    Inscrit en
    Avril 2004
    Messages
    3 817
    Détails du profil
    Informations personnelles :
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Fabricant et casseur d'avions
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2004
    Messages : 3 817
    Par défaut
    Citation Envoyé par Aschiehle Voir le message
    Le lookAt est censé faire les deux?
    Les trois premiers paramètres du lookAt sont la position de la caméra...
    Les trois suivant ceux du point visé...
    Les trois derniers ceux du vecteur pour orienter le haut.

    A partir de tout ça, tu positionnes ta caméra, et tu l'orientes. Si tu rajoutes une translation pour la positionner, en fait tu la déplaces depuis le point que tu lui avais passé en paramètre, et suivant le vecteur translation que tu rajoutes avec ton autre déplacement.

    Citation Envoyé par Aschiehle Voir le message
    Test numéro 1 :
    J'ai tenté de faire un test simple pour voir ce qui allait pas :
    scène : [0,0,100,100]
    centerPosition = (0,0,0)
    currentPosition = (10,50,10)

    Logiquement, je devrais visualiser le coin [0,0,10,10] avec cette exemple.
    Et ben non! Je vois.. le vide!
    Non. Tu devrais visualiser le point (0,0,0), c'est celui que tu vises.
    Si tu ne vois rien, c'est sans doute que tu es trop près (regarde du côté des plans de clipping). Avec ce currentPosition, ta caméra est à l'intérieur du cube, et regarde l'origine. Enfin, du cube... tu fais une scène 2D ou 3D en fait?


    Citation Envoyé par Aschiehle Voir le message
    Et quand je recule la camera, je finis par voir ma scene. En haut à droite de l'écran. Comme si j'étais en [-10,-50,-10]
    clipping...
    Par contre il faudrait voir exactement ce que tu fais quand tu "recules la caméra".

    Citation Envoyé par Aschiehle Voir le message
    Il y a donc encore quelque chose que je n'ai manifestement pas compris. Si ca saute aux yeux a quelqu'un...
    Euh... non, en fait ce n'est pas super clair ce que tu ne comprends pas!
    lookAt est sensé positionner et orienter ta caméra. Il n'y a pas de tutu à enfiler ni de pirouette à faire, c'est direct et super simple: positionnement, axe de visée, vecteur haut. Avec ça, tout est défini.

    Citation Envoyé par Aschiehle Voir le message
    Problème résolu!
    Fais attention avec les matrices... là, si ça se trouve, tu appliques une transformation inverse à ton monde de celle que tu aurais appliqué directement à ta caméra... ce qui en gros revient à faire la même chose, mais pas sur le même objet!
    Mais bon, normalement, ça fonctionne...
    "Errare humanum est, sed perseverare diabolicum"

    Ma page sur DVP.com

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Positionner le scroll vers le bas
    Par pesti dans le forum GWT et Vaadin
    Réponses: 3
    Dernier message: 12/08/2009, 01h34
  2. Réponses: 2
    Dernier message: 12/10/2008, 12h21
  3. Réponses: 10
    Dernier message: 22/05/2008, 12h32
  4. Réponses: 10
    Dernier message: 23/10/2007, 09h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo