ScratchAPixel : Quelqu'un a-t-il déjà implémenté leur projection perspective ?

Le problème exposé dans ce sujet a été résolu.

Hello à tous !

Quelqu’un a déjà essayé d’implémenter ça ?

  1. https://www.scratchapixel.com/lessons/3d-basic-rendering/computing-pixel-coordinates-of-3d-point

  2. https://www.scratchapixel.com/lessons/3d-basic-rendering/computing-pixel-coordinates-of-3d-point/mathematics-computing-2d-coordinates-of-3d-points

  3. https://www.scratchapixel.com/code.php?id=23&origin=/lessons/3d-basic-rendering/computing-pixel-coordinates-of-3d-point

Car perso j’obtiens ça pour leur arbre (sans avoir dessiné les segments, juste les points) :

Image utilisateur

Au lieu de ça :

Image utilisateur

Et aussi, j’ai essayé de dessiner ce cube :

1
2
3
4
5
6
7
8
  Seq(0, 15, 0),
  Seq(0, 15, 20),
  Seq(0, 0, 0),
  Seq(0, 0, 20),
  Seq(15, 15, 0),
  Seq(15, 15, 20),
  Seq(15, 0, 0),
  Seq(15, 0, 20)

Ce qui me donne cela (j’ai rajouté les segments à la main) :

Image utilisateur

Alors que j’aurais voulu avoir un cube comme ça :

Image utilisateur

J’ai essayé de diminuer la profondeur des 4 points du devant du cube, ça semble marcher :

1
2
3
4
5
6
7
8
  Seq(0, 15, 0),
  Seq(0, 15, 5),
  Seq(0, 0, 0),
  Seq(0, 0, 5),
  Seq(15, 15, 0),
  Seq(15, 15, 5),
  Seq(15, 0, 0),
  Seq(15, 0, 5)
Image utilisateur

J’ai par ailleurs aussi essayé de translater vers la droite deux points, ce qui a également marché :

1
2
3
4
5
6
7
8
  Seq(0, 15, 0),
  Seq(0, 15, 5),
  Seq(0, 0, 0),
  Seq(0, 0, 5),
  Seq(15, 15, 0),
  Seq(20, 15, 5),
  Seq(15, 0, 0),
  Seq(20, 0, 5)

Résultat :

Image utilisateur

Donc voilà, je sais bien que vous montrer ça sans code ou quoi ça ne sert pas à grand-chose. Le truc c’est que ScratchAPixel n’utilise pas de matrice de projection perspective, le cours veut vraiment entrer dans les détails et considère à juste titre que cette matrice n’est qu’un outil qui cache les véritables mécanismes (qui eux sont vraiment expliqués, et c’est ça que j’ai appliqué/implémenté).

En plus de ça je suis sûr et certain que ma perspective marche (déjà rien que les tests ci-dessus tendent à le montrer).

C’est juste que leur matrice camera-to-world (que j’ai inversée pour avoir la matrice world-to-camera) est peut-être incorrecte, dans le sens où elle ne me permettra jamais d’obtenir un cube vu de face. SAUF QUE si vous n’avez jamais lu le cours de ScratchAPixel OU que vous n’avez pas trop de connaissances en infographie, parler de "matrice camera-to-world" ou de "matrice world-to-camera" ça ne vous avancera pas à grand-chose pour m’aider. Sachez juste que c’est pas une matrice de projection perspective.

Du coup voilà, si jamais quelqu’un a déjà lu ça en entier ou encore mieux : qu’il a déjà essayé d’implémenter ça, on peut en parler ici si c’est possible ? ^^’

Merci d’avance et bonne soirée à tous :) !

PS : au cas où, leur matrice camera-to-world est :

1
2
3
4
5
6
Seq(
          Seq(0.871214, 0, -0.490904, 0),
          Seq(-0.192902, 0.919559, -0.342346, 0),
          Seq(0.451415, 0.392953, 0.801132, 0),
          Seq(14.777467, 29.361945, 27.993464, 1)
        )

Inversée, on obtient la matrice world-to-camera qu’il faut utiliser d’après leur cours, qui est la suivante :

1
2
3
4
ArrayBuffer(0.8712134471343778, -0.19290207078160884, 0.45141489009083896, 0.0)
ArrayBuffer(-1.545258968022739E-7, 0.9195582297541908, 0.3929527292207119, 0.0)
ArrayBuffer(-0.4909038179934774, -0.3423459264824255, 0.801132140002119, 0.0)
ArrayBuffer(0.8677749286593306, -14.565965812600595, -40.63508878499671, 1.0)
+0 -0

@A-312 Non, il ne veut pas relier les points, il cherche à corriger sa perspective (bon, pour le sapin, il est difficile de voir le problème juste avec les points ^^).

@The-Aloha-Protocol Je n’ai pas trop le temps de jeter un coup d’œil aujourd’hui (peut-être à la pause midi ou si j’arrive à atteindre mon objectif de la semaine, on verra), mais tu peux m’envoyer ton code en MP (ou je réimplémenterais ça demain si j’ai fini mon travail aujourd’hui ^^).

Supposons que la matrice world-to-camera est valide, que fais tu une fois que tu as multiplié ta position par cette matrice ?

@A-312 Non, il ne veut pas relier les points, il cherche à corriger sa perspective (bon, pour le sapin, il est difficile de voir le problème juste avec les points ^^).

JuDePom

C’est la même chose à vue de nez. J’ai même vérifié :

Superposition des deux images de sapin

Alors, c’est juste que le cube/caméra est mal placé :P

La matrice world_to_cam en dur pour le sapin n’est pas adaptée au positionnement du cube. Il faudrait essayer de la créer à partir des formules, afin de pouvoir positionner la caméra, le look_at et autres paramètres tranquillement.

Ah mais oui non mais je suis trop débile laissez tomber… J’ai pris certaines lettres et sommets de lettres (les légendes) pour des carrés/pixels… Bref…

Alors justement on en vient à ce que je pensais. A savoir que la matrice world to camera est fausse pour le cube mais bonne pour le sapin.

Scratch À Pixel n’explique pas comment la remplir avec les bons coefficients. Ils ont trouvé celle-ci grâce à Autodesk Maya.

Existe-t-il des formules ?

Je rappelle au cas où que ce n’est pas la matrice de projection perspective.

Maya n’affiche que la matrice correspondante au positionnement de la caméra(position, rotation, échelle). Donc tu as juste à partir d’une matrice identité 4*4 et lui ajouter les transformations.

Dans la première partie de l’article World view projection, tu as tout ce qu’il te faut pour les transformations (translation, rotation, etc.).

Je suis un peu rouillé sur le sujet (j’ai fait une thèse sur un sujet connexe il y a 10 ans), mais as-tu au moins les formules pour définir ta matrice world-to-camera ?

A priori celle-ci se définit par les positions relatives entre :

  • le centre de la caméra dans le repère-monde,
  • le plan de l’image dans le repère-monde

Pour ce qui est du cube il semble évident que le plan de la caméra doit être parallèle à une face du cube, et le centre de la caméra aligné avec les centres de deux faces du cube (avant et arrière).

+0 -0

@JuDePom : les transformations que je vais faire sur la matrice identité, je les choisis en fonction de ce que @nohar a dit du coup (i.e. : "Pour ce qui est du cube il semble évident que le plan de la caméra doit être parallèle à une face du cube, et le centre de la caméra aligné avec les centres de deux faces du cube (avant et arrière).").

Du coup si on considère ce cube (exprimé relativement au monde) :

1
2
3
4
5
6
7
8
          Seq(0, 200, 0),
          Seq(0, 200, 100),
          Seq(0, 0, 0),
          Seq(0, 0, 100),
          Seq(200, 200, 0),
          Seq(200, 200, 100),
          Seq(200, 0, 0),
          Seq(200, 0, 100)

, la matrice de transformation world-to-camera serait :

1
2
3
4
          Seq(1, 0, 0, 0),
          Seq(0, 1, 0, 0),
          Seq(0, 0, 1, 0),
          Seq(100, 100, 10, 1)

Sauf que ça me donne ça :

Image utilisateur

Pourtant, cette matrice est censée placer la caméra au milieu X et Y du cube, et l’éloigner suffisamment de ce dernier pour bien le voir.

Et merci pour l’article, il est notamment plus complet que ScratchAPixel au niveau des matrices de transformation. Bon par contre j’ai relevé une ou deux petites différences avec le site sus-cité mais peu importe ce n’est pas l’objet du topic :p

+0 -0

Alors, je ne sais pas vraiment si c’est des colonnes ou des lignes pour ta matrice; mais, supposons que ce soit le bon ordre, donc des colonnes ^^).

Pour l’éloignement, en fait, tu rentres dans ton cube en mettant une translation en Z positive.

Ta caméra se retrouve en (100, 100, 10), qui est à l’intérieur du cube.

En lignes ! :)

Et oui, je m’en suis aperçu plus 2 min après avoir posté sauf que

1) mettre la caméra bien avant le cube avec un z bien plus grand ne change pas grand chose au problème, je ne vois toujours pas le cube de face mais un peu de côté. Je ferai un screenshot en rentrant

2) on voit quand même les 4 points alors que la caméra est actuellement dans le cube c’est bizarre

Désolé pour le peu de temps que je suis disponible…

En lignes ! :)

Ça ne pouvait donc pas aller ^^

2) on voit quand même les 4 points alors que la caméra est actuellement dans le cube c’est bizarre

En faite, non, ce n’est pas étrange si tu n’as pas implémenté de "clipping planes" :P

Du coup je viens de voir ton édit, ce qui rend incorrect mon précédent message :p

Je ne comprends pas pourquoi ma matrice n’est pas correcte, puisque j’ai juste à translater ma caméra non ? A moins qu’il faille que je la rotationne en plus.

Merci pour l’aide au fait!

Edit : je sèche vraiment sur les coefficients à choisir, j’comprends même pas pourquoi ceux que j’ai pris ne marchent pas…

+0 -0

Tu devrais regarder du côté de la profondeur (pespective) plutôt que d’essayer de modifier la Translation en coordonnées homogènes, si tu souhaites obtenir : https://i.stack.imgur.com/ofKx8.jpg

Si ça peut t’aider à visualiser : http://wordsandbuttons.online/interactive_guide_to_homogeneous_coordinates.html


@JuDePom: Comme ça :

1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
100, 100, 10, 1

1
2
3
4
1, 0, 0, 0  <--- Rajoute deux espaces à la fin.
0, 1, 0, 0  
0, 0, 1, 0  
100, 100, 10, 1

Hello @A-312, le ray-tracing n’est qu’une méthode parmi d’autres pour faire le rendu d’objets 3D. Ce n’est pas parce qu’elle fait l’objet d’un cours sur ZdS qu’il faut la recommander à tout-va :p , perso devoir envoyer le rayon partout pour espérer qu’un point entre en collision avec, j’aime pas trop l’idée.

De toute façon il me faut juste choisir les bons coefs pour ma matrice de transfo, et le tour sera joué, je verrais bien mon cube.


Nouvelle matrice de transfo

Bon du coup j’ai re-réfléchi et j’ai modifié ma matrice de transfo. J’ai effectué une rotation de la caméra.

Nouvelle matrice de transormation :

1
2
3
4
          Seq(300, 150, 0, 0),
          Seq(150, 300, 0, 0),
          Seq(125, 125, -150, 0),
          Seq(150, 150, 0, 1)

Avec ce cube :

1
2
3
4
5
6
7
8
          Seq(0, 300, 0),
          Seq(0, 300, -300),
          Seq(0, 0, 0),
          Seq(0, 0, -300),
          Seq(300, 300, 0),
          Seq(300, 300, -300),
          Seq(300, 0, 0),
          Seq(300, 0, -300)

Explications.

L’origine de la caméra doit être au centre des faces avant et arrière. La caméra doit être orientée de cette façon : son axe X doit être parallèle aux bords supérieur et arrière de la face avant (ou arrière), idem pour son axe Y mais avec des bords gauche et droit, son axe Z doit être perpendiculaire au centre des faces avant et arrière et aller de la caméra au cube.

L’origine du nouveau système de coordonnées (caméra) est donc Seq(100, 100, 300, 1) dans le monde. Et est ainsi situé en amont du cube (i.e. de la face du cube la plus proche).

L’extrémité de son axe X est situé en Seq(150, 0, 300, 0), i.e. : 150 unités vers la droite, 0 vers le haut, et 300 en profondeur. Un truc similaire est réalisé pour son axe Y : Seq(0, 150, 300, 0).

Concernant l’axe Z (profondeur) : Seq(0, 0, 150, 0) traduit une extrémité Z de cet axe située en profondeur 150.

Résultat

Image utilisateur

:(

+0 -0

@A-312 Oui, le formatage était horrible ^^ (sur téléphone c’est assez embêtant d’écrire, surtout quand le correcteur modifie tout… )

@The-Aloha-Protocol Tu peux écrire ta matrice sous forme de matrice ? Car tes ’seq’, c’est pas compréhensible sur ce que tu représentes.

Et si ta matrice se lit exactement comme elle est écrite : un seq = une ligne, alors ta matrice est toujours erronée. (Pour cela que je préfère une vrai écriture de matrice, pour lever toute ambiguïté.)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte