JeuWeb - Crée ton jeu par navigateur
Faire de la 3D avec canvas 2D - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Faire de la 3D avec canvas 2D (/showthread.php?tid=7011)

Pages : 1 2 3


Faire de la 3D avec canvas 2D - Aleskweb - 01-07-2013

Bonjour,

Avec un ami nous aimerions pouvoir simuler des rotations et mouvements 3D de plans a l'aide de la fonction setTransform de canvas.

Le but serait de réaliser une fonction avec trois arguments (rotationX,rotationY,rotationZ) qui transformerais le plan afin de simuler une rotation 3D.

Pour le moment nous arrivons a faire des rotations mais sans perspective, comme si on était en caméra orthogonale. Et nous cherchons des pistes pour ajouter la perspective et donc avoir un effet de profondeur.
Aussi, vu qu'il n'y aura que ces plans en 3D, le reste sera des sprites 2D, nous aimerions éviter d'utiliser un environnement 3D.

Cette fonction est assez compliquée a comprendre, si quelqu’un a bien saisi, des explications en plus sont les bienvenues. De plus nous aimerions avoir des avis si ce que nous envisageons est possible/impossible.




Merci d'avance Smile

Ps: Le but serait de pouvoir arriver a un résultat de ce genre : http://tulrich.com/geekstuff/canvas/perspective.html sans utiliser canvas3D


RE: Faire de la 3D avec canvas 2D - Maks - 01-07-2013

Tu peux utiliser le raycasting, mais même avec des web workers bon courage pour les 60fps


RE: Faire de la 3D avec canvas 2D - Aleskweb - 01-07-2013

Un 30 fps suffirait largement et il y aurait max une animation de plan a la fois (jeu de carte). C'est pour ca, qu'il faudrait rester dans un canvas, pour l'interface
Je vais me documenter la dessus
Merci


RE: Faire de la 3D avec canvas 2D - sclabet - 06-07-2013

Bonjour,
je pense que c'est possible, si ton problème est toujours d'actualité, je m'y penche dès que je trouve un peu de temps (ce qui n'est pas gagné en ce moment, mais je trouverai bien dans la semaine).


RE: Faire de la 3D avec canvas 2D - Xenos - 06-07-2013

Ce sont des maths (mais j'ai pas envie d'y creuser). http://en.wikipedia.org/wiki/3D_projection Il te faut déterminer la matrice de projection (3D vers 2D), et l'appliquer à ton canvas.
Mais de ce que je vois, setTransform ( http://www.w3schools.com/tags/canvas_transform.asp ) n'utilise que 6 coordonnées matricielle (la dernière ligne de la matrice étant forcée à 0 0 1). J'ai donc un sérieux doute sur la faisabilité de la perpective elle-même.
En termes simples, une perspective va changer un rectangle (mur de maisons d'une rue par exemple) en un trapèze, car il existe un "point de fuite"
[Image: persp2.jpg]
Or, la transformation offerte par SetTransform ne permettra pas cet effet, à cause de la contrainte sur la dernière ligne...

Je doute donc sérieusement de la faisabilité du projet, via setTransform seul.


RE: Faire de la 3D avec canvas 2D - sclabet - 07-07-2013

il y a vraiment plus simple, je n'ai pas le temps maintenant mais je m'y penche dès que possible


RE: Faire de la 3D avec canvas 2D - sclabet - 08-07-2013

en fait Xenos tu as raison, il faut bien utiliser les matrices, par contre le dessin que tu proposes est un dessin en perspective vraie grandeur (celle que perçois notre œil et qui noues est donc beaucoup plus agréable(géométrie projective)) ce que je vais proposer est une perspective cavalière (géométrie euclidienne).

la fonction setTransform fait la projection sur l'écran de la transformation euclidienne (matrice 3x3) suivant un axe perpendiculaire à celui-ci :

setTransform(a, b, c, d, e, f)
a c e
b d f
0 0 1

or la composée de trois rotations autour des axes X, Y et Z donne la matrice :

cosy*cosz //// sinx*siny*cosz-cosx*sinz //// cosx*siny*cosz+sinx*sinz
cosy*sinz //// sinx*siny*sinz+cosx*cosz //// cosx*siny*sinz-sinx*cosz
-siny ////////////// sinx*cosy /////////////// cosx*cosy


finalement en ne retenant que ce qui m'intéresse :

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

const X = 45;
const Y = 60;
const Z = 30;

var cosx = Math.cos(X*Math.PI/180);
var sinx = Math.sin(X*Math.PI/180);
var cosy = Math.cos(Y*Math.PI/180);
var siny = Math.sin(Y*Math.PI/180);
var cosz = Math.cos(Z*Math.PI/180);
var sinz = Math.sin(Z*Math.PI/180);

ctx.setTransform(cosy*cosz,cosy*sinz,sinx*siny*cosz-cosx*sinz,sinx*siny*sinz+cosx*cosz,cosx*siny*cosz+sinx*sinz,cosx*siny*sinz-sinx*cosz);
ctx.fillStyle='lightblue';
ctx.fillRect(50,50,250,100);
ctx.fillStyle='red';
ctx.font='30px Arial';
ctx.fillText('JeuWeb.org', 100,100);

voilà, j'espère que ça sera utile Wink


RE: Faire de la 3D avec canvas 2D - Xenos - 09-07-2013

Citation :il faut bien utiliser les matrices
Quelque soit la transformation à faire, si elle peut être faite d'une base (3D orthogonale classique) dans une autre (2D orthogonale qu'est l'écran), alors elle peut se faire par matrice (dite matrice de passage, si les dimensions sont réduites, on parle de matrice de projection, mais l'idée est identique, c'est juste qu'on fait "sauter" une dimension). Cavalière ou en perspective, toute projection peut donc se faire par matrice Wink

Citation :par contre le dessin que tu proposes est un dessin en perspective vraie grandeur (celle que perçois notre œil et qui noues est donc beaucoup plus agréable(géométrie projective))

Tout comme l'exemple qui était donné: on a un effet de perspective du journal. Mais c'est un effet réalisé par "éléments finis": on triangule l'objet et on fait une projection cavalière sur chaque triangle. Chaque triangle a sa propre matrice de projection, et on "s'arrange" pour que ces matrices donnent, au final, un faux effet de perspective. C'est pour cette raison que le texte est déformé: la perspective est discontinue car chaque triangle est en projection cavalière.

Citation :ce que je vais proposer est une perspective cavalière.
Tu ne pourras pas faire mieux de toute façon avec setTransform Wink Mathématiquement, la matrice setTransform conserve le parallélisme. Donc, impossible de changer un rectangle (cotés parallèles) en un trapèze (rectangle "en perspective"), dont deux cotés ne sont pas parallèles. Inutile de tourner le problème dans tous les sens, il n'a pas de solution de cette façon, via setTranform.

Citation :la composée de trois rotations autour des axes X, Y et Z
Précise pour les rotations: X puis Y puis Z, axes fixes du plan, ou X Y Z axes liées à l'objet lui-même? Les résultats sont très différents...


RE: Faire de la 3D avec canvas 2D - sclabet - 09-07-2013

tu as une solide formation en mathématiques, pour les lecteurs non initiés: la fonction setTransform est une application affine (famille qui contient les rotations, les projections, etc...)

Citation :Tout comme l'exemple qui était donné: on a un effet de perspective du journal. Mais c'est un effet réalisé par "éléments finis": on triangule l'objet et on fait une projection cavalière sur chaque triangle. Chaque triangle a sa propre matrice de projection, et on "s'arrange" pour que ces matrices donnent, au final, un faux effet de perspective. C'est pour cette raison que le texte est déformé: la perspective est discontinue car chaque triangle est en projection cavalière.
effectivement je n'avais pas remarqué (gg à toi , en fait je me demandais le pourquoi des petits triangles... Wink
l'image globale semble en perspective vrai grandeur (plus c'est proche plus c'est vu gros...et à l'inverse, plus c'est loin plus c'est vu petit) alors que localement sur chaque triangle tu dis que c'est une projection cavalière (les parallèles réelles sont vues parallèles sur le dessin)
chapeau bas au programmeur, l'idée est excellente le rendu est très bon

Citation :Tu ne pourras pas faire mieux de toute façon avec setTransform Mathématiquement, la matrice setTransform conserve le parallélisme. Donc, impossible de changer un rectangle (cotés parallèles) en un trapèze (rectangle "en perspective"), dont deux cotés ne sont pas parallèles. Inutile de tourner le problème dans tous les sens, il n'a pas de solution de cette façon, via setTranform.
oui tu as parfaitement raison : la perspective cavalière n'est pas agréable à l'oeil et il n'y a aucun moyen via setTransform de faire mieux, à part peut être de rajouter des ombrages mais je ne suis pas persuadé que le résultat soit meilleur...

Citation :Précise pour les rotations: X puis Y puis Z, axes fixes du plan, ou X Y Z axes liées à l'objet lui-même? Les résultats sont très différents...
oui mes notations sont mal choisies : X, Y et Z sont en réalité les angles en degrés des rotations autour des axes x, y et z (axes affines du plan car je ne fais aucun changement de base, il n'y a pas de matrice de passage)


RE: Faire de la 3D avec canvas 2D - Xenos - 09-07-2013

Citation :tu as une solide formation en mathématiques
Ingénieur centralien :p La prépa, ça laisse quelques traces -_-
La triangularisation est utilisée depuis belle lurette ^^ Mais oui, le concepteur (ou le concepteur de jsGL) a du se plonger dans les maths et les éléments finis pour atteindre ce genre de résultat. (éléments finis: découper un "truc" continue en "trucs" élémentaires, par exemple, approximer une courbe par une ligne brisée, ou une surface sphérique par des triangles, comme le font la plupart des jeux vidéos)

Je ne crois pas qu'il existe de fonction, dans canvas 2D, qui ne soit pas justement "affine", c'est à dire qu'il n'existe pas de fonction permettant de faire de la profondeur (par exemple, par de fonction qui permettrait d'afficher une image de hauteur 100px sur le coté gauche, et 10px sur le coté droit, donnant un "effet" de perspective, effet très partiel).

Et les seules solutions envisageables me semblent être:
- Zapper canvas 2D, et prendre WebGL (plus simple)
- Chercher une bibliothèque javascript, comme jsGL, pour faire une approximation de la perspective 3D (plus compatible car canvas 2D)
- Coder tout soi-même en faisant sa propre triangulation et ses propres effets (bonne chance!)