Three.js: SkinnedMesh bug lorsque loin de la racine de la scène (0,0,0)

Créé le 9 févr. 2018  ·  113Commentaires  ·  Source: mrdoob/three.js

Je pense avoir trouvé un bug sur votre SkinnedMesh (testé sur iPhone 6 & 8).

Si cela est déjà signalé, je suis désolé, je ne l'ai pas trouvé dans la liste des problèmes :(

Il semble que le skinning gpu ne fonctionne pas correctement et devient fou sur mobile.
Lorsqu'un SkinnedMesh se déplace ou se déplace à des positions de valeur élevée (ex: x: 0, y: 0, z: 1000), le skinning n'est plus précis et commence la danse de l'araignée.

L'échelle du maillage affecte le bogue.

Il semble que les valeurs des os du squelette ne soient pas calculées correctement à chaque image et que la matrice bonesTexture / bonesMatrix du shader de skinning pousse les sommets au mauvais endroit.
C'est juste mon sentiment bien sûr.

J'ai effectué de nombreux tests avant de publier ceci ... à la recherche d'un indice dans mes exportations animées, mais j'ai trouvé que le bogue se produisait avec tout type de formats (GLTF, FBX, Collada, JSON, ...) et les modèles du repo ThreeJS.

C'est très ennuyeux car cela signifie que nous ne pouvons pas développer un jeu de coureur simple avec un avatar en cours d'exécution (avatar.position.z augmentant alors) sans avoir ce problème: ((
Je ne sais toujours pas comment je vais le gérer car morphTargets n'est pas une option :(

J'espère que vous pouvez aider ici.

J'ai fait des exemples clairs avec une source propre pour exposer le problème. Il est assez facile de le vérifier sur un téléphone intelligent:

Apparaissant uniquement sur mobile (z = 10000):
http://cornflex.org/webgl/skinning-bug.html

Avec floatVertexTextures défini sur false (z = 10000):
http://cornflex.org/webgl/skinning-bug2.html

S'aggrave avec la distance (z augmente):
http://cornflex.org/webgl/skinning-bug3.html

Très très loin du centre (z = 70000000)> bug apparaissant également sur le bureau mais certainement dû à un problème de précision du flotteur:
http://cornflex.org/webgl/skinning-bug4.html

Aperçu vidéo dans mon environnement de jeu:
Il s'agit d'un monde à l'échelle réaliste (1,0 m = 1,0 unité de trois js).
Le bogue n'apparaît qu'après 50-60m de la racine de la scène et s'aggrave avec la distance:
http://cornflex.org/webgl/skin-bug.mp4

TRÈS IMPORTANT
Le maillage utilisé à partir du repo ThreeJS est beaucoup trop grand. Il mesure 20 m de haut.
C'est pourquoi la valeur z doit être plus grande pour voir le bogue.
Si ce maillage est réduit à une taille réaliste, le bogue commence à apparaître même à 100 m.

Version Three.js
  • [x] Dev
  • [x] r89
  • [X] ...
Navigateur
  • [ ] Tous
  • [] Chrome
  • [] Firefox
  • [ ] Internet Explorer
  • [x] Safari
OS
  • [ ] Tous
  • [ ] Les fenêtres
  • [] macOS
  • [] Linux
  • [ ] Android
  • [x] iOS
Configuration matérielle requise (carte graphique, périphérique VR, ...)

iPhone 6, 8

Bug

Commentaire le plus utile

Je voudrais souligner cette section de l'utilisateur zeoverlord :

La gigue n'est naturelle que pour les flottants, les variables perdront en précision plus le nombre est élevé, donc la précision est meilleure plus elle est proche de 1,0. Maintenant, ce n'est pas vraiment un problème, mais cela signifie que si vous faites beaucoup de calculs matriciels avec des nombres énormes, vous allez avoir beaucoup de dégradation de la précision (aka gigue). Vous devez donc faire tous vos calculs autour de l'origine avec des nombres raisonnables, puis le traduire

Tous les 113 commentaires

Euh, votre démo a l'air bien sur mon Pixel.

Problèmes confirmés sur mon iPhone SE -

img_6324

Problèmes de précision WebGL dans iOS peut-être

Mais les appareils iOS utilisent en fait le chemin de code basé sur la texture flottante de l'implémentation de skinning, non? Pouvez-vous vérifier cela avec le test de conformité suivant?

https://www.khronos.org/registry/webgl/conformance-suites/1.0.3/conformance/extensions/oes-texture-float.html

iPhone SE a cinq échecs sur cette page. 😕

J'ai fait un petit screencast pour vous montrer dans mon projet:
http://cornflex.org/webgl/skin-bug.mp4

Si l'avatar va trop loin de 0,0,0, le skin commence à devenir vraiment bogué comme vous pouvez le voir.
J'ai fait un profilage profond du squelette et des os. Tout semble bien sauf que la géométrie est "retirée" d'une certaine manière ... J'ai pensé à une mauvaise racine d'animation mais encore une fois, tout semble bien dans Threejs avec ça ...

Le problème est clairement lié au squelette et à la texture des os du shader Skinning.
J'ai également pensé à la précision, mais comme l'a dit Mugen, l'appareil iOS devrait le supporter facilement.

... pourquoi seulement sur iphone alors: /

Je suis assez coincé ... Je réoriente vers les séquences png comme plan de sauvegarde ... :(

Cela est probablement dû au fait que l'iPhone 6 ne supporte pas suffisamment d'os.

J'ai eu exactement le même problème.

Vérifiez votre limite osseuse ici: https://virtulo.us/2/vr/test

Je ne pense pas.
Si le skinnedmesh reste à 0,0,0, il n'y a aucun problème: /
Je pense même à déplacer tous les actifs au lieu de l'avatar ... (c'est ma solution de contournement n ° 2) mais je préférerais sûrement que le squelette fonctionne aussi bien que le bureau bien sûr.

Un ami vient de signaler le même bug sur l'iPhone 8

Après avoir regardé les sources de ThreeJS pendant 2 jours ... Je pense qu'il y a un problème lorsque le bonesTexture est mis à jour.
Il semble que cette texture ne se met pas à jour correctement, puis repousse les sommets à leurs positions d'origine ... mais je peux me tromper bien sûr.

img_1411

Hmmm ... ici, j'ai quelques échecs, regardez:

img_1412

Peut-être que le problème est lié à ces échecs. Mon Pixel, par exemple, réussit tous les tests.

Essayons quelque chose: allez à WebGLCapabilities et définissez la valeur de floatVertexTextures sur false (cela empêchera l'utilisation de la texture float). Créez une version et utilisez cette version three.js dans votre application. Je suis curieux de savoir ce qui se passe 😊.

https://github.com/mrdoob/three.js/blob/099e4364541502fdf22fc7b1c0f54239d2ba1708/src/renderers/webgl/WebGLCapabilities.js#L105

Déjà essayé floatVertexTextures = false sur le moteur de rendu.
La peau cesse de devenir folle mais il n'y a plus d'animation: /
Je vais pousser un échantillon.

Vous voilà:
http://cornflex.org/webgl/skinning-bug2.html

renderer.capabilities.floatVertexTextures = false;

=> Aucune animation en cours d'exécution

img_1413

Ouais, même chose sur mon Pixel (Desktop fonctionne). Je suppose que nous atteignons une limite uniforme.

J'ai fait un dernier échantillon, avec un bug apparaissant progressivement:
http://cornflex.org/webgl/skinning-bug3.html

Commence à 0,0,0 et avance ... attendez quelques secondes ... la peau commence à devenir folle.

C'est assez bizarre tout va bien à 0,0,0. n'est-ce pas?

z: 1255> toujours OK
z: 18870> peau folle

img_1415

img_1414

Comme je l'ai dit, j'ai profilé en profondeur toutes les positions du squelette et des os côté CPU. Toutes les valeurs semblent tout à fait correctes. Le seul indice que j'ai est que les bonesTextures et les bonesMatrix ne fonctionnent pas correctement sur iOS lorsque le maillage s'éloigne de 0,0,0.

J'ai vérifié les positions des os parce que c'est un comportement typique des os stables du nœud racine ou des choses comme ça ... mais non ...

J'ai vérifié la précision du flotteur côté GPU dans vos shaders de peau, mais encore une fois ... rien ne semble avoir d'impact.

Personne très étrange n'a déplacé un SkinnedMesh dans une scène et n'a jamais rapporté cela: /

Encore une question: rencontrez-vous le même problème avec Chrome?

Même problème ouais.

img_1416

Cela ressemble à un problème de précision. Avez-vous essayé de réduire la scène? (11195 est 11 kilomètres).

Une autre option serait de déplacer la scène au lieu du personnage. A tendance à être une solution courante pour les grandes scènes.

De plus, je suppose que le code de skinning est dans l'espace mondial. Nous pourrions enquêter là-dessus.

Je vois que votre nombre d'os est de 67.

Mon (wifes) iphone 6 a une limite Max Hardware Bones de 27.

Les déformations que je vois sont identiques à celles que j'ai vues sur son téléphone dans mon jeu (et le même problème que j'avais avant que mon animateur répare les mailles armitures). Je serais surpris si cela ne faisait pas au moins partie de votre problème.

Pourquoi ça empire avec le temps? Aucune idée. Quelqu'un d'autre a mentionné quelque chose de similaire, je ne sais pas si c'est lié: https://discourse.threejs.org/t/updated-with-fiddle-as-animations-go-faster-there-is-increasing-error-in-accuracy/ 1707/6

Une autre chose ennuyeuse que j'ai trouvée sur les iphones (iphone 6 au moins): je DOIS utiliser la précision du shader highp, mediump et lowp ne déforment pas le maillage de la même manière effrayante (comme mon problème d'os sur le téléphone), mais les textures semblent bizarre et déformé / pixelisé lors de l'animation.

Quelle est votre limite osseuse matérielle sur l'appareil que vous testez?

@mrdoob j'ai déjà essayé de réduire mais le skinning devient fou beaucoup plus vite en fait: /
Si vous réduisez à 0,1, le bogue apparaît 10 fois plus vite.

La démo que j'ai utilisée ici pour expliquer vient des trois exemples.
Dans mon jeu, l'échelle n'est pas si grande mais le bug est le même, n'apparaissant que plus rapidement.

En effet, le skinning semble être fait dans l'espace du monde, ou l'espace local, mais devient extensible lorsqu'il est éloigné du centre. C'est pourquoi ça marche plutôt bien à 0,0,0

Déplacer tout le monde au lieu de l'avatar est mon travail n ° 2.
Vous devez admettre que c'est un mauvais choix lorsque vous avez développé toute la routine d'un jeu de coureur dans worldspace déjà avec la physique et tout. Et z = 11000 n'est pas si loin pour un jeu de coureurs: / ... et c'est juste un homme qui court, pas un navire.

J'ai fait beaucoup de jeux avec ThreeJS mais c'est la première fois que j'utilise un skinnedmesh. Ce bogue iOS est vraiment ennuyeux.

Workaroung # 1: Je vais faire 6 séquences png comme animations de sprites. Ensuite, je peux garder une logique de l'espace mondial. La date limite n'est pas loin :(

@titansoftime Le problème apparaît également sur l'iPhone 8 de ma femme. Cela ne concerne pas uniquement l'iPhone 6.
De plus, si vous avez un problème de max bones, il sera bogué depuis le début. Ici, vous pouvez voir que ce n'est pas un buggy à 0,0,0. Alors la limite des os n'est pas le problème. Calcul de l'espace mondial des os et des osMatrix dans les shaders de skinning est, IMO.

Quel est le Max Hardware Bones de l'iPhone 8?

Je ne sais pas. Et je ne suis pas sûr que cela dépend de l'appareil.

Mais encore une fois ... IMO, ce n'est pas du tout lié à la valeur maxbones.

L'échantillon fonctionne correctement sur iphone 6,8, X ... même 5 ... uniquement lorsque le SkinnedMesh reste à 0,0,0
https://threejs.org/examples/webgl_loader_fbx.html

Si maxbones était un problème, nous n'aurions pas non plus un bon skinning à 0,0,0.

Je voudrais souligner cette section de l'utilisateur zeoverlord :

La gigue n'est naturelle que pour les flottants, les variables perdront en précision plus le nombre est élevé, donc la précision est meilleure plus elle est proche de 1,0. Maintenant, ce n'est pas vraiment un problème, mais cela signifie que si vous faites beaucoup de calculs matriciels avec des nombres énormes, vous allez avoir beaucoup de dégradation de la précision (aka gigue). Vous devez donc faire tous vos calculs autour de l'origine avec des nombres raisonnables, puis le traduire

Mmmh, très intéressant @ Mugen87! Il semble que vous ayez repéré la fuite.

z: 1255> toujours OK
z: 18870> peau folle

L'erreur pourrait être de votre côté.
Une erreur courante: le modificateur de peau n'a pas été correctement appliqué.
Erreur 1: sommets contrôlés par trop d'os
Erreur 2: sommets sans poids (ou avec un poids très faible).

Lorsque le SkinnedMesh est proche de l'origine (0,0,0), vous ne remarquerez pas ces erreurs.
Mais quand il est éloigné ... vous blâmerez la précision de l'appareil mobile.
Donc, la première chose à faire est de redessiner (correctement cette fois) le modificateur de peau.

@RemusMar Avez-vous regardé la source de la page?
L'exemple que j'ai exposé vient directement des sources ThreeJS.

Assez bien mentionné dans ma description;)

J'ai effectué de nombreux tests avant de publier ceci ... à la recherche d'un indice dans mes exportations animées mais j'ai trouvé que le bogue se produisait avec tout type de format (GLTF, FBX, Collada, JSON, ...)

J'ai fait un exemple clair avec une source propre pour exposer le problème. Il est assez facile de le vérifier sur un téléphone intelligent:

http://cornflex.org/webgl/skinning-bug.html

L'exemple que j'ai exposé vient directement des sources ThreeJS.

Et alors?

Comment l'erreur peut être de mon côté lorsque cela se produit avec tous les exemples de skinnedmesh de ThreeJS :)

Tu as dit:

L'erreur pourrait être de votre côté.
Une erreur courante: le modificateur de peau n'a pas été correctement appliqué.
Erreur 1: sommets contrôlés par trop d'os
Erreur 2: sommets sans poids (ou avec un poids très faible).

FBX est de ThreeJS ... et vous pouvez essayer avec GLTF ou tout autre format. Le problème est le même.

var loader = new THREE.FBXLoader ();
loader.load ('https://threejs.org/examples/models/fbx/xsi_man_skinning.fbx', OnFBXLoaded);

@ Mugen87 a trouvé un indice. Espérons que le gars qui a créé le maillage à peau gpu pourra le réparer.

Comment l'erreur peut être de mon côté lorsque cela se produit avec tous les exemples de skinnedmesh de ThreeJS

J'ai dit "L'erreur pourrait être de votre côté.".
La ligne du bas:
Utilisez un SkinnedMesh simple avec un modificateur de peau correctement appliqué:

  • max 4 os par sommet
  • tous les poids = 1,0000

Voyez si vous pouvez reproduire le bogue.

T'es en colère? :)
Ce bug ne peut pas être de mon côté ... les modèles (fbx, gltf, dae, peu importe) et le code source proviennent de ThreeJS.

Veuillez lire les messages de @ Mugen87 .

Utilisez un SkinnedMesh simple avec un modificateur de peau correctement appliqué:

  • max 4 os par sommet
  • tous les poids = 1,0000

Voyez si vous pouvez reproduire le bogue.

Je dois partir maintenant.
à votre santé

Hmmm. Vous savez quels gars? Cela se produit également sur le bureau :(

Comme l'exemple de maillage ThreeJS est énorme (100m de haut), je l'ai placé très très loin: z = 10000000
Et regardez, même problème:
http://cornflex.org/webgl/skinning-bug4.html

C'est définitivement quelque chose lié aux positions et aux calculs des os dans l'espace mondial, comme exposé par @ Mugen87 :

https://www.opengl.org/discussion_boards/archive/index.php/t-159613.html
https://www.opengl.org/discussion_boards/archive/index.php/t-159364.html

Comme expliqué précédemment à @mrdoob , j'ai déjà essayé de réduire l'échelle du maillage mais le problème est encore pire ... même sur le bureau et vous rencontrez le bogue pas si loin de 0,0,0 alors.

Dans mon propre jeu (avec des échelles réalistes 1: 1), le bogue apparaît déjà à z: 100.

Vous continuez à utiliser des maillages à peau mal conçus ...
Bref, pour clore ce sujet, voici l'étude de cas de 1 à 1000000 (un million !!!):
http://necromanthus.com/Test/html5/Lara_1000000.html
Cliquez sur la scène pour basculer entre Y = 0 et Y = 1000000
Un changement d'éclairage global mineur est disponible par interrupteur.
Donc, si le maillage skinné est correctement conçu, le résultat est (presque) parfait.
à votre santé

Nous l'examinerons après la sortie de ce mois-ci.

@mrdoob Merci.

@RemusMar Vous continuez à ignorer ce qui a été dit ici. Veuillez relire le fil de discussion en entier :)

Je viens de vous donner un exemple de travail mais vous ne comprenez toujours pas.
http://necromanthus.com/Test/html5/Lara_1000000.html

Et vous continuez à parler de mauvaises pratiques .
Veuillez garder à l'esprit les points suivants:
Le nombre de chiffres à virgule flottante simple précision est de 7.
Cela couvre 1234567 et 123456,7
La plupart des cartes de poids sont livrées avec 4 décimales, mais même une seule donne des résultats décents.
Pour cette raison, tous les moteurs 3D recommandent une valeur maximale de 10 000 pour la taille mondiale.
De 0000.001 à 9999.999
Nous voulons tous des mondes 3D «infinis» ou immenses, mais ce n'est pas possible.
Que faites-vous est complètement faux à bien des égards:
conception de jeux, performances, animations et collisions.
J'espère que vous avez maintenant la photo principale.

@RemusMar
J'ai bien compris ce que vous avez dit mais malheureusement votre modèle a le même problème ... à un moindre degré mais toujours là:
http://cornflex.org/webgl/skin-bug2.mp4

La source:
http://cornflex.org/webgl/skinning-bug5.html

Et si je donne une position supérieure à z = 60000, ça empire ... et jusqu'à 100000 c'est complètement invisible.

Nous voulons tous des mondes 3D «infinis» ou immenses, mais ce n'est pas possible.

LOL, je ne veux pas d'un monde immense et infini ... Je veux juste faire un jeu de coureur, comme je l'ai fait plusieurs fois auparavant avec ThreeJS ... mais cette fois j'ai besoin d'un skinnedmesh comme avatar.

Ma scène: http://cornflex.org/webgl/skin-bug.mp4

Si nous n'arrivons pas à animer un avatar sur plusieurs mètres ... alors à quoi ça sert ?? (à l'échelle réaliste 1m = 1 unité threejs, le bug apparaît déjà à partir de 100).

BTW, votre modèle mesure 150 m de haut ... ce n'est pas une échelle réaliste.
ÉDITER:
Voici la même scène avec échelle (0,01, 0,01, 0,01) sur votre modèle, pour obtenir une taille réaliste (environ 1,5 m alors). Comme vous pouvez le voir, il est déjà buggé à z = 300 sur mobile:
http://cornflex.org/webgl/skin-bug3.mp4

Que faites-vous est complètement faux à bien des égards:
conception de jeux, performances, animations et collisions.

LOL LOL ... Je suggère de visiter mes sites Web et mon blog sur la création de jeux (http://quentinlengele.com, http://cornflex.org, http://www.ddrsa.com, http://br9732.com )

EDIT: votre scène n'est pas visible sur iOS, écran vide (http://necromanthus.com/Test/html5/Lara_1000000.html).
img_1418

Le skinning semble être fait dans l'espace du monde, ou l'espace local, mais s'étire lorsqu'il est éloigné du centre. C'est pourquoi ça marche plutôt bien à 0,0,0

Voyons voir:

vec3 transformed = vec3( position );
...
#ifdef USE_SKINNING
    vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );
    vec4 skinned = vec4( 0.0 );
    skinned += boneMatX * skinVertex * skinWeight.x;
    skinned += boneMatY * skinVertex * skinWeight.y;
    skinned += boneMatZ * skinVertex * skinWeight.z;
    skinned += boneMatW * skinVertex * skinWeight.w;
    transformed = ( bindMatrixInverse * skinned ).xyz;
#endif

ne me ressemble pas à un espace mondial? dans un maillage régulier, transformed est défini sur l'attribut position - c'est-à-dire les coordonnées locales.

donc tout ce qui se passe se passe du côté js, où les matrices de liaison et d'os sont calculées. peut-être que la matrice de liaison fait beaucoup d'étirement, et les matrices osseuses pourraient être manipulées pour fonctionner dans d'autres coordonnées qui ne nécessitent pas autant d'étirement dans la matrice de liaison ... ou quelque chose comme ça

(modifier: nvm, je pense que je me trompe)

me

@makc Malheureusement, je ne vois pas assez de données revalorisantes dans votre copier / coller du shader de skinning pour dire si le calcul est fait dans les coordonnées spatiales locales ou mondiales.

Comme je l'ai dit, il y a sûrement quelque chose qui ne va pas avec le calcul des matrices osseuses ou peut-être que l'ordre de calcul de ces matrices n'est pas correct. Comme vous pouvez le voir sur le forum OpenGL et comme @ Mugen87 l'a mentionné, c'est l'indice le plus revalorisant, du moins pour moi:

La gigue n'est naturelle que pour les flottants, les variables perdront en précision plus le nombre est élevé, donc la précision est meilleure plus elle est proche de 1,0. Maintenant, ce n'est pas vraiment un problème, mais cela signifie que si vous faites beaucoup de calculs matriciels avec des nombres énormes, vous allez avoir beaucoup de dégradation de la précision (aka gigue). Vous devez donc faire tous vos calculs autour de l'origine avec des nombres raisonnables, puis le traduire

Encore une fois, comme expliqué, l'échelle de l'objet affecte le bogue.
L'exemple avec les sources ThreeJS présente ce bogue uniquement à z = 100000 mais c'est parce que la taille du maillage (provenant également de la source ThreeJS) est énorme. Le garçon qui court mesure 150 m.

Lorsque vous faites un jeu, vous n'utilisez pas ce genre d'échelle bien sûr. Vous essayez toujours de garder votre monde avec 1 m = 1 unité. Ceci est même obligatoire pour obtenir une bonne physique et un bon comportement.

Le problème ici est lorsque vous utilisez un SkinnedMesh avec une taille réaliste: le bogue apparaît déjà à z = 300.

Dans n'importe quel moteur, vous pouvez déposer un SkinnedMesh en le mettant à x: 30000, y: 60000, z: 140000000 et il n'y a pas de problème avec les os et le skinning. Pas de tremblements.

Je comprends très bien que nous travaillons ici sur un noyau Javascript ... mais quand même.

Les trolls prétendant ici "nous voulons tous des mondes infinis mais c'est impossible" doivent retourner à l'école et apprendre les transformations matricielles. Ou mieux regarder les jeux du monde ouvert et leur demander comment leur avatar peut être "skinnedmeshed" si loin de la racine de la scène 0,0,0 ......

Je dois dire que ce bug est amusant. Ici, j'ai pu le reproduire sur le bureau, mais 60K n'étaient pas suffisants pour manquer de précision:
needs more zeroes

ok, donc à z = 1e8, voici ce que nous avons avec le shader actuel:

screen shot 2018-02-14 at 1 15 56

et voici ce que nous avons si nous changeons le shader en ceci (légère variation de mon test hors de la tête ci-dessus que j'ai édité):

#ifdef USE_SKINNING
    vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );
    vec4 skinned = vec4( 0.0 );
    skinned += ( bindMatrixInverse * boneMatX ) * skinVertex * skinWeight.x;
    skinned += ( bindMatrixInverse * boneMatY ) * skinVertex * skinWeight.y;
    skinned += ( bindMatrixInverse * boneMatZ ) * skinVertex * skinWeight.z;
    skinned += ( bindMatrixInverse * boneMatW ) * skinVertex * skinWeight.w;
    transformed = skinned.xyz;
#endif

screen shot 2018-02-14 at 1 16 54

encore fragile, mais semble bien mieux :) maintenant, qu'est-ce que cela signifie dans le contexte de ce problème?

Tout d'abord, vous ne pouvez pas simplement copier-coller ce hack dans le shader. Je veux dire, vous pouvez, mais cela remplace 1 multiplication de matrice par 4. ce que je propose à la place est soit a) fusionner la matrice osseuse avec l'inverse de la matrice de liaison du côté js et passer comme un uniforme unique, ou b) créer un autre uniforme juste pour cela morceau de shader. Cela résoudrait alors ce problème (un peu) et diminuerait le nombre de multiplications de matrice dans le shader (de 1).

Oh et

Trolls ici prétendant "nous voulons tous des mondes infinis mais c'est impossible"

Je pense que ce qu'ils essayaient de dire, c'est que vous pouviez contourner le problème sans réparer la bibliothèque de votre côté. Pas nécessaire devrait, mais pourrait.

@makc Merci beaucoup pour votre temps là-dessus.
Malheureusement, il est trop tard. Je dois livrer vendredi. J'ai utilisé des séquences PNG comme solution de contournement.

Si vous voulez déboguer cela assez profondément. Pourriez-vous essayer d'utiliser une taille de maillage réaliste?
Encore une fois, ce modèle Lara mesure aussi 60 m de haut si je me souviens bien.

Je suis assez curieux de voir si votre patch fonctionne également à une échelle réaliste :)

Oh et ... fais-tu ton test sous iOS?
Comme expliqué dans ce fil, cela se produit principalement sur les appareils iOS (6, 8).
Sur Desktop, seules des valeurs très très importantes posent le problème.

Merci encore

@OrtOfOn vous pouvez essayer le patch @makc en ajoutant ceci en haut de votre code:

THREE.ShaderChunk.skinning_vertex = `
#ifdef USE_SKINNING
    vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );
    vec4 skinned = vec4( 0.0 );
    skinned += ( bindMatrixInverse * boneMatX ) * skinVertex * skinWeight.x;
    skinned += ( bindMatrixInverse * boneMatY ) * skinVertex * skinWeight.y;
    skinned += ( bindMatrixInverse * boneMatZ ) * skinVertex * skinWeight.z;
    skinned += ( bindMatrixInverse * boneMatW ) * skinVertex * skinWeight.w;
    transformed = skinned.xyz;
#endif
`;

THREE.WebGLShader: Shader n'a pas pu compiler. : /

patch

oh mec. vous vous êtes retrouvé avec de fausses citations et une mise en forme sur une ligne. comment copier-coller comme ça?

aussi, je l'ai fait pour voir ces images farfelues, ce qui satisfait ma curiosité. J'espère que quelqu'un d'autre le prendra d'ici :)

@makc CTRL + C / CTRL + V ... juste à partir d'ici ...: /

Malheureusement, le bug est moins fort qu'avant mais toujours là :(

Testé sur iOS (patch appliqué):

Maillage à l'échelle 1.0 (avatar d'environ 20 m de haut exactement), position z = 10000
http://cornflex.org/webgl/skin-patch1.mp4

Maille à l'échelle 0,1 (avatar d'environ 2 m de haut), position z = 3000
http://cornflex.org/webgl/skin-patch2.mp4

@mrdoob Je vais essayer de reproduire :) Il est apparu sur une seule ligne. J'écrivais sur la page quand j'ai vu votre réponse apparaître et qu'elle ne ressemblait pas à ça normalement, je vous le promets: p ... j'obtiendrai ces points bonus, vous verrez :)

EDIT: BTW vous avez édité votre message? :)

Je pense que l'effet résiduel peut être sans rapport avec le skinning et affecter en fait tout mais vous ne le remarquez pas car il n'y a pas d'animation.

@OrtOfOn à votre place, j'essaierais d'envelopper toute votre scène (avec une caméra) dans Object3D supplémentaire et de définir les coordonnées de cet objet à -1 * coords d'avatar à chaque image. Cela le garderait pour toujours dans 0,0,0 coordonnées mondiales.

@markc Je n'aime vraiment pas tricher comme ça. Le gameplay et la scène ne sont pas conçus pour être torturés comme ça et en tant que premier jeu mobile, les performances doivent être optimales bien sûr.

Aussi ... pas mon cas, mais imaginez cela avec plusieurs ennemis dans SkinnedMesh, venant de partout ...

Je n'avais pas le choix car la date limite et j'ai remplacé le SkinnedMesh par des animations de spritesheet (le client est OK). Sinon, je n'ai pas sauf pour rencontrer quelque chose comme ça. J'utilise ThreeJS dans presque tous les projets Web et j'en suis très très satisfait.

Nous ne voulons pas de "mondes infinis", mais nous voulons pouvoir utiliser ces jolies fonctionnalités de SkinnedMesh et d'animations dans les coordonnées spatiales du monde, comme nous le faisons dans les moteurs célèbres :)

Je suis un peu déçu d'une certaine manière ... parce que j'ai fait un script Animator très cool basé sur des fonctionnalités de crossfade et inspiré de mecanim ... Pour le prochain projet sûrement: /

@markc Je n'aime vraiment pas tricher comme ça.

Je ne pense pas du tout que ce soit de la triche. C'est ainsi que fonctionnent toutes les simulations spatiales. En fait, le rendu 3D en temps réel décale fondamentalement toute la scène de sorte que le centre se trouve là où se trouve la caméra.

@mrdoob ouais je sais qu'une caméra n'existe même pas. Puissance des matrices :) (je fais moi-même des développements natifs WebGL / OpenGL)

Quoi qu'il en soit, mettre toute la scène dans un objet de jeu me semble un peu barbare ... surtout pour faire fonctionner une animation skinned.

@OrtOfOn vous pouvez en fait utiliser la scène elle-même. par exemple dans l'exemple de lara, faites ceci:

scene.add(camera);
scene.position.z = -60000;

et c'est ok (modifier: cependant, il y a quelque chose qui ne va pas avec la lumière quand vous faites ça ... @mrdoob ?)

@makc Merci encore de proposer des correctifs.

Je ne veux pas du tout être pessimiste mais quelque chose me dit que l'éclairage ne sera pas le seul problème en faisant ce genre de manipulations. C'est pourquoi j'appelle ces trucs et astuces en raison de l'incertitude du résultat et des conséquences sur d'autres parties du pipeline.

Malheureusement, les gens qui créent des jeux ont de la physique, des raycasters, des particules, ... beaucoup de choses qui sont conçues et doivent être conçues pour être dans l'espace du monde avec des échelles réalistes.

De plus, je suis assez curieux de voir ces patchs en action avec plus d'un SkinnedMesh, comme des ennemis se cachant ou se reproduisant à certains endroits de la scène. Car quel est l'intérêt d'être limité à un seul avatar skinnedmesh à 0,0,0 alors?

Je vais creuser profondément dans la source dès que je peux mais je dois livrer quelque chose dans 2 jours ... donc mes animations de spritesheet sont assez bien pour le moment, espérons-le.

Car quel est l'intérêt d'être limité à un seul avatar skinnedmesh à 0,0,0 alors?

Le fait est qu'il est hautement improbable que vous rendiez simultanément le skin à 0,0,0 et un autre skin à z = 60000. Seuls quelques skins autour du 0,0,0 arriveront à l'écran, et ils ne seront pas assez loin pour déclencher le bogue.

@makc Encore
http://cornflex.org/webgl/skin-bug.mp4

Utilisez-vous toujours un avatar de 20 m de haut dans vos jeux? :)
Parce que le nombre sur lequel vous vous êtes concentré (60000) n'est utilisé que pour exposer le bogue sur le bureau (avec ce très énorme lara ou cet énorme échantillon de fbx threejs) ... pas sur mobile. Et mon avatar ne va pas aussi loin bien sûr ...

Je confirmerais qu'il s'agit d'un problème iOS. Depuis au moins la génération 6S / 6S +, iOS a eu un problème avec floatVertexTextures. Le correctif que nous avons utilisé consiste à désactiver cette fonctionnalité sur iOS. Cela limite les os que nous pouvons utiliser, mais nous devons les limiter de toute façon pour prendre en charge les téléphones plus merdiques.

Comme les appareils iOS échouent au test de conformité publié par @ Mugen87 , ce serait probablement une bonne idée de désactiver floatVertexTextures, ou probablement même floatFragmentTextures, sur iOS par défaut, car il n'implémente clairement pas correctement une fonctionnalité qu'il annonce prendre en charge.

@ daniel-nth je suppose que c'est logique. Cependant ... @OrtOfOn disait que z = 60K reproduit le problème sur le bureau ... Je n'ai aucun problème à 60K sur le bureau, seul 1e8 me suffisait pour "reproduire". Donc, peut-être que ce problème est en réalité au moins 3 problèmes distincts:

  • textures flottantes sur ios,
  • quelque chose à 60K sur le bureau de @OrtOfOn ,
  • manque de précision à 1e8 en raison d'un mauvais ordre de multiplication de la matrice dans le bit de shader des os (celui que j'ai dérangé ci-dessus),
  • peut-être quelque chose d'autre dans le vertex shader, car la fille était encore un peu tremblante après le patch.

Salut les gars,
Tout d'abord, merci de revenir sur ce bogue. Je n'ai toujours pas trouvé le temps de creuser dedans :(

@ daniel-nth L'échelle de l'objet affecte le bogue:

Sur iOS, avec cet objet "Lara" très énorme (hauteur = 120, échelle = 1), le bug apparaît en effet à z = 60000. Mais, si vous prenez un maillage de taille réaliste (hauteur = 1,8, échelle = 1), il n'apparaît déjà qu'à z = 100.

plus le skinnedmesh, plus la traduction doit être pour voir le bogue.

Comme déjà testé et rapporté dans ce fil de discussion, la désactivation de floatTextures sur iOS résulte sans skinning du tout.

Je soupçonne également une mauvaise multiplication de la matrice ou un ordre de multiplication des barres de la matrice osseuse.

Sur iOS, avec ce très gros objet "Lara" (hauteur = 120, échelle = 1), le bug apparaît à z = 60000

@OrtOfOn attendez, alors sur iOS? mais vous avez aussi dit:

le nombre sur lequel vous vous êtes concentré (60000) n'est utilisé que pour exposer le bogue sur le bureau (avec ce très énorme lara ou cet énorme échantillon de fbx threejs) ... pas sur mobile.

Sur iOS, avec cet objet "Lara" très énorme (hauteur = 120, échelle = 1), le bug apparaît en effet à z = 60000.

Ce n'est pas du tout énorme.
Et vous ne comprenez toujours pas la relation entre la taille du modèle et l'échelle mondiale.
Pour la dernière fois:
http://necromanthus.com/Test/html5/Lara_1000000.html
Hauteur Modeil environ = 75 et échelle mondiale = 9 999 999.
De Z = 0 à Z = 1 000 000 (un million !!!)
Étant donné que le nombre de chiffres à virgule flottante simple précision est de 7, il ne reste plus du tout de décimales !!!
Il fonctionne parfaitement sur tous les ordinateurs portables et ordinateurs de bureau que j'ai.
Encore plus:
il fonctionne parfaitement sur Android 6 et 7 et divers téléphones mobiles Samsung.

lara_1000000

@RemusMar dans votre exemple, entrez ceci dans la console:

camera.position.z += 1e8;
scene.children[2].position.z += 1e8;

vous verrez quelque chose comme ceci:
screen shot 2018-03-03 at 15 48 53

screen shot 2018-03-03 at 15 51 41
c'est trippant

Je vais vous dire que z = 1e6 n'a pas l'air mal non plus. autour de 1e7 c'est déjà perceptible, et 1e8 est juste fou

@OrtOfOn La définition de capabilities.floatVertexTextures sur false fonctionne pour nous sur iOS. Je soupçonne que votre modèle utilise de nombreux os pour rentrer dans les uniformes.

Je vais vous dire que z = 1e6 n'a pas l'air mal non plus. autour de 1e7 c'est déjà perceptible, et 1e8 est juste fou

Je sais, mais pour ces valeurs, vous manquez de précision.
Pour la précision du poids du sommet du maillage skinné, la taille maximale du monde est de 9,999,999
Cela se traduit par des distances maximales de quelques millions, pas plus.
à votre santé

@makc En effet, je me suis trompé de chiffres pour le bureau. Il doit être très énorme, vous avez raison et j'ai mentionné dans le fil plus tôt en fait: / https://github.com/mrdoob/three.js/issues/13288#issuecomment -364650679

@ daniel-nth Bon à savoir mais en êtes-vous sûr? Voici le test que j'ai fait ici dans ce fil, avec un modèle 3D provenant de sources threejs. Vous pouvez toujours consulter le code. @ Mugen87 a également fait le même retour, aucune animation avec ce modèle. https://github.com/mrdoob/three.js/issues/13288#issuecomment -364572653

Oh, je vois que le modèle n'est plus présent. 404 sur https://threejs.org/examples/models/fbx/xsi_man_skinning.fbx

@ daniel-nth Si vous utilisez un nouveau modèle avec moins d'os, alors je vous crois;)

@RemusMar Tout à fait d'accord avec vous sur les distances évoquées dans les derniers articles. Les nombres (1e6, 1e8, 1e9, ...) résulteront certainement avec une mauvaise précision. Aucun doute à ce sujet. Mais arrêtez de me troller. Arrêtez de prétendre que je ne comprends rien et demandez-vous si un maillage d'avatar d'une hauteur de 120 n'est pas énorme. Pour moi, c'est très énorme et peu utilisable dans un gamedev avec d'autres objets à l'échelle réalistes réalisés par des artistes, des raycasts, de la physique, de l'éclairage ... et à livrer en 3 semaines.

J'insiste: garder les actifs à une échelle réaliste avec des unités métriques est quelque chose d'obligatoire pour construire correctement un jeu basé sur la physique :)

Dommage que, sur iOS, je ne puisse pas faire tourner mon avatar sur 100m dans ces conditions d'échelle réalistes: /

MISE À JOUR: Quoi qu'il en soit, @ daniel-nth semble nous dire qu'il fonctionne maintenant avec floatTextures désactivé et un nombre très limité d'os.

Mais s'il te plaît, arrête de me troller
J'insiste: garder les actifs à une échelle réaliste avec des unités métriques est quelque chose d'obligatoire pour construire correctement un jeu basé sur la physique :)

Je ne te trolle pas.
Mais 1,5 unité ne signifie pas 1,5 mètre
à votre santé

@OrtOfOn

J'insiste: garder les actifs à une échelle réaliste avec des unités métriques est quelque chose d'obligatoire pour construire correctement un jeu basé sur la physique :)

mais cette échelle est une valeur arbitraire auto-imposée. vous pouvez tout aussi bien décider d'utiliser des centimètres, et alors "un maillage d'avatar d'une hauteur de 120" est en fait plus petit que la moyenne.

@makc Bien sûr, mais le moteur physique / les bibliothèques s'attendent à ce que vous

Bien sûr, cela dépend du niveau de précision que vous devez atteindre et des valeurs comme 1e6, 1e7, ... sont beaucoup trop grandes et présenteront des problèmes de précision. Et vous n'aurez jamais besoin de déplacer un maillage skinned aussi loin. Nous avons convenu de cela. Mais, sur iOS, nous devrions pouvoir déplacer un skinnedmesh gpu (1,5 unité de haut) dans une plage de plusieurs centaines d'unités au moins.

mais le moteur physique / les bibliothèques s'attendent à ce que vous utilisiez des valeurs métriques.

Ce n'est pas vrai.
Les mètres, centimètres, pouces, etc. ne sont pas pertinents.
Comme je l'ai dit (plusieurs fois) auparavant, tout ce qui compte, c'est la taille du monde (échelle) et la précision.
Gardez à l'esprit les points suivants:
si vous avez un maillage skinné avec une hauteur = 1,5 unité, vous êtes obligé par la carte des poids des sommets d'utiliser au moins 2-3 décimales.
Pour le moteur physique (le cas échéant), vous devrez peut-être 3-4 décimales pour des résultats acceptables.
Si la précision globale nécessite 4 décimales, la taille maximale de votre monde est de 999 (car le nombre de chiffres à virgule flottante simple précision est 7).
En d'autres termes, vous pouvez utiliser des distances de quelques centaines si vous voulez des animations décentes et une physique décente.
J'espère que vous avez une vue d'ensemble cette fois.
à votre santé

@RemusMar Je vais m'arrêter ici. Il semble que vous ne vouliez pas ou ne vouliez pas tester votre coque sur un appareil iOS. Vous ne pouvez pas utiliser la "distance de quelques centaines" sur ces appareils avec des skinnedmeshes gpu. Le maillage devient fou très vite. C'est le but de ce fil et je voulais juste le signaler au début. Alors c'est tout.

J'espère que vous avez compris que toutes vos propositions et échantillons ne fonctionnent pas sur les appareils iOS, comme le rapportent d'autres personnes ici et mes captures d'écran: /

Vous ne pouvez pas utiliser la "distance de quelques centaines" sur ces appareils avec des skinnedmeshes gpu.

Vous vous trompez encore.
Voir la capture d'écran ci-dessus (Android 7 - téléphone mobile Samsung).
Hauteur du modèle = 75 (rayon de la sphère englobante environ 38) et distance 1000000 (un million !!!)
Ou hauteur du modèle = 1,5 et distance 20 000.

ps
N'est-ce pas mon problème qu'iOS a toujours été une collection de bogues.

@RemusMar Je n'ai pas tort,

Pas mon problème si vous détestez tellement Apple. Quand un de mes clients veut un jeu 3D basé sur le Web avec ThreeJS, je ne lui dis pas "va te faire foutre avec tes iphones" ... Si tu le fais, je suis désolé pour toi.

Fin de la transmission ici ... Je ne peux plus suivre ça.

@OrtOfOn Oui, le modèle que j'ai utilisé a 19 os, le 404 fbx en a 67.

https://github.com/mrdoob/three.js/issues/13288#issuecomment -364550036 avait un lien vers une page qui montre la limite osseuse uniforme. La formule utilisée par cette page est Math.floor((data.webgl.params.MAX_VERTEX_UNIFORM_VECTORS - 20) / 4); Je ne sais pas si c'est exact à 100% pour three.js, mais elle en rapporte 27 même sur l'iPhone X, qui est malheureusement moins de la moitié d'un Galaxy S3, mais encore beaucoup un jeu WebGL mobile. J'ai rapidement parcouru mon dossier de travail et dans les 26 projets WebGL, un seul a un modèle avec plus d'ossements, et ce modèle reste à 0,0,0.

@OrtOfOn : J'ai des problèmes similaires avec une scène fixe et le déplacement d'un personnage écorché dans la scène. le personnage tremble terriblement sur ios. le nombre d'os est de 22. dimensions de la scène sont raisonnables. Je crois que le problème est que l'utilisation de textures de sommets vous limite aux flottants 32 bits, couplée à l'affirmation ci-dessus que Threejs calcule le skinning dans l'espace mondial!

J'examine l'affirmation de l'espace mondial maintenant, et j'espère mettre en œuvre la bonne façon de calculer les positions vert dans l'espace local et ensuite traduire l'objet - comme il se doit. Je n'ai jamais entendu parler de personne utilisant le skinning pour placer l'objet dans l'espace mondial, donc je ne sais pas pourquoi l'implémenteur aurait fait une telle chose.

je posterai quand j'aurai une solution.

juste pour info, les textures flottantes sur ios ne sont pas seulement rompues avec les vertex shaders. J'ai récemment changé les textures flottantes en textures entières pour corriger les bandes de couleurs sur iOS, donc c'est un problème universel d'ios. vous pourriez probablement utiliser des textures entières pour réparer les os sur iOS, si vous le vouliez vraiment - voici un extrait pertinent du shader de quelqu'un d'autre:

vec2 encodeFloatRG( float v )
{
    vec2 kEncodeMul = vec2(1.0, 255.0);
    float kEncodeBit = 1.0/255.0;
    vec2 enc = kEncodeMul * v;
    enc = fract (enc);
    enc.x -= enc.y * kEncodeBit;
    return enc;
}

float decodeRGFloat( vec2 enc )
{
    vec2 kDecodeDot = vec2(1.0, 1.0/255.0);
    return dot( enc, kDecodeDot );
}

... en fait, vous pourriez probablement (je suppose ici, je n'ai pas vraiment essayé quelque chose comme ça) faire fonctionner les textures d'os flottants aussi, si vous acceptez la précision ios comme limite de précision globale et stockez deux flottants dans la texture au lieu d'un

J'ai entièrement résolu le problème en demandant à threej de faire le calcul de skinning dans l'espace local - là où il appartient - et de traduire le modèle en coordonnées du monde réel de la manière standard via la matrice spatiale mondiale.

Les problèmes ci-dessus sont complètement résolus pour le skinning sur iOS. Je dois également souligner que cette solution est universelle - fonctionne parfaitement sur tous les navigateurs de bureau ainsi que sur les appareils Android que j'ai testés. Le skinning de l'espace local IMHO est la bonne façon de procéder dans presque tous les cas, et cette méthode devrait être la méthode par défaut pour ThreeJS. @mrdoob : quelle est votre

mesh = new THREE.SkinnedMesh(geo.geometry, mat);
mesh.bindMode = 'detached';
var skel = new THREE.Skeleton(bones, boneInvs);
var bsm = new THREE.Matrix4().fromArray(geoPrims.bsm);
mesh.bind(skel, bsm);

// make bsmInv identity for models that have multiple skins
mesh.bindMatrixInverse = new THREE.Matrix4();

// patch SkinnedMesh's updateMtxWorld:
// we're using local skinning, so don't keep resetting binMatrixInverse (leave identity)
// the reason we're using .bind here is for models that have more than one skin
mesh.updateMatrixWorld = PatchSkinnedMeshUpdateMW.bind(mesh);

// re-normalize since input data has been compressed
mesh.normalizeSkinWeights();

// remove bone roots and add to bone root list
for (var bi = 0, bl = bones.length ; bi < bl ; bi++) {
    if (bones[bi].parent && !bones[bi].parent.isBone) {
        bones[bi].parent.remove(bones[bi]);
        boneRoots.push(bones[bi]);
    }
}

Où 'boneRoots' doit être ajouté à l'objet de scène racine (afin qu'ils obtiennent des mises à jour de matrice mais n'héritent pas de toutes les matrices de la hiérarchie menant au skinnedmesh réel). Ajoutez ces boneRoots à la racine de votre scène (code non affiché).

Et voici le patch pour remplacer l'implémentation SkinnedMesh de threeJS (notez que cela n'est nécessaire que puisque updatematrixworld de threejs écrase le bindMatrixInverse que nous voulons conserver comme identité). Vous pouvez également vous lier directement à THREE.Mesh..prototype.UpdateMatrixWorld au lieu d'utiliser une fonction de patch.

function PatchSkinnedMeshUpdateMW( force ) {
    THREE.Mesh.prototype.updateMatrixWorld.call( this, force );
}

@ denbo-ft Je pense que cela me semble bien. Souhaitez-vous créer un PR pour cela?

@ denbo-ft Merci beaucoup pour vos efforts. Désolé pour la réponse tardive, je ne suivais plus ce fil.

nous avons également ce problème dans notre produit - n'importe quel navigateur (si vous vous éloignez suffisamment de 0,0,0) mais plus visible sur iOS car il se produit dès que vous êtes à environ 2-3 unités. Critique pour nous mais au moins on rigole bien quand on voit ça
image

Ok, il semble qu'il y ait plus de gens qui en ont besoin. Je n'ai jamais contribué à un projet open source github mais je suis familier avec git et j'essaierai de créer un PR. :)

Pareil ici. Mon SkinnedMesh ressemble à un épisode du Dr Katz, thérapeute professionnel sur iPhone.

Pour info, mon message du 21 mai a toute la solution. Pas beaucoup de correctifs pour les sources ThreeJS - la plupart des correctifs appartiennent à votre chargeur et / ou au code de configuration de la scène pour vos projets individuels.

La solution de base consiste à utiliser le mode «détaché» (qui n'est pas documenté, btw) et à placer la hiérarchie osseuse dans votre scène au niveau de la scène racine - pas en place avec la hiérarchie de caractères pouvant être rendue réelle. Ensuite, corrigez une chose simple à partir du moteur (SkinnedMesh.update), et vous devriez être prêt à partir.

Éditer:
Nous avons un format de fichier et un chargeur complètement personnalisés pour TJS, donc malheureusement, pour créer un PR complet avec un exemple de solution, je devrais réparer l'un des chargeurs prédéfinis fournis (tels que Collada). Je vais chercher à faire ça maintenant

merci, j'allais consacrer un peu de temps pour essayer de comprendre et aussi appliquer votre solution de manière plus générique (la vôtre semblait un peu spécifique à votre projet). Pourriez-vous partager un peu plus de contexte pour votre code?

Dr Katz, thérapeute professionnel

Je ne suis pas accro ou quoi que ce soit, mais putain .

ÉDITER:

J'ai créé avec succès une pull request - faites-moi savoir si je peux faire quelque chose de plus.

Message d'origine:

J'ai une succursale locale avec les changements, mais je n'arrive pas à pousser à l'origine. Même en fournissant mes creds github, j'obtiens cette erreur:

En poussant vers https://github.com/mrdoob/three.js.git
remote: autorisation de mrdoob / three.js.git refusée à denbo-ft.
fatal: impossible d'accéder à ' https://github.com/mrdoob/three.js.git/ ': l'URL demandée a renvoyé l'erreur: 403

J'adorerais quelques conseils car c'est ma première contribution à github. Merci!

Pour info si le PR fonctionne pour mrdoob et est intégré, il existe un nouveau mode de liaison "local" qui prend en charge ce changement. Je ne voulais pas patcher ou modifier le mode de liaison "détaché" non documenté car il n'y a aucune indication qui l'utilise ou ce qui l'utilise et je ne voulais pas casser quelque chose dont je n'étais pas au courant. Mais il me semble que c'était peut-être prévu à cet effet.

Tout binMode = "local" ne change pas le bindMatrixInverse pendant la mise à jour, contrairement à "détaché", qui le réinitialise à l'inverse de bindMatrix, au lieu de le laisser à l'identité.

Voir l'exemple webgl_loader_collada_skinning.html dans ce PR pour voir les quelques changements nécessaires au niveau de la scène afin d'obtenir une peau locale appropriée sur les personnages qui se déplacent dans la scène.

La démo du chargeur Stormtrooper DAE a été utilisée pour tester ce correctif. Le personnage a été déplacé à 2000 unités de l'origine pour ces tests. Captures d'écran ci-dessous.

Les photos ci-dessous proviennent de l'iPhone X / Safari 11

Avant ce changement (à 2000, 2000, 2000):
img_0658

Après ce changement:
img_0659

Pensez-vous qu'il existe un moyen d'y parvenir sans avoir les os au niveau de la scène racine et (0,0,0)? J'utilise les os pour attacher des trucs à l'avatar, le faire regarder des points, etc. Et je suppose que je ne suis pas le seul

Vous avez deux options:

1) Gardez les os dans l'espace mondial à la racine pour bénéficier du skinning local tel que mis en œuvre dans threejs. Ensuite, effectuez des transformations supplémentaires si vous devez absolument attacher une arme à un os, par exemple, pour l'introduire dans l'espace avatar.

2) Laissez Bones dans l'espace avatar tel quel et déformez-vous sur iOS.

Je ferais certainement le n ° 1. Vous pouvez toujours faire le calcul pour déterminer où l'objet attachable doit être à une image donnée lorsque vous avez déjà la position de l'os et la position du personnage. Mais, il n'y a pas de solution de contournement pour le n ° 2 car la déformation est causée par un emballage au niveau HAL des appareils iOS et vous ne pouvez rien y faire. Bien sûr, vous pouvez ajouter des hacks supplémentaires en essayant d'utiliser les différents emballages HalfWord, etc. ci-dessus, mais ils réduisent tous le problème, ne le font pas disparaître. Le problème de skinning sur iOS disparaîtra complètement si vous effectuez le skinning dans l'espace local (plus précisément, gardez les os centrés sur l'origine mondiale pour garder les nombres aussi petits que possible). Puis xform dans l'espace de caractères pour les pièces jointes.

Plus d'informations:

Le problème avec la façon dont il est implémenté dans TJS n'est pas spécifiquement TJS, mais pour résoudre le problème de la limite osseuse due au nombre limité d'uniformes par programme de shader, BoneTextures est utilisé. C'est une solution assez standard. Cependant, sur iOS, les flottants dans les textures sont quantifiés - emballés / compressés - en quelque chose de plus petit que 32 bits. Cela provoque la "mante religieuse" ou d'autres effets farfelus des personnages lorsque la taille / magnitude du nombre est "grande", c'est-à-dire supérieure à quelques centaines.

Ok super, on fait quoi maintenant? Eh bien, chaque grande fonctionnalité de votre jeu (moteur de jeu en fait) nécessite généralement des normes de pratique. Exemple: dites aux artistes de centrer le personnage sur l'origine. Placez le nœud racine du personnage sur les pieds / sol, créez les os et la peau d'une manière particulière. Ensuite, écrivez un exportateur (ou un importateur dans le cas de TJS) et un importateur qui connaissent vos règles de processus. Ensuite, prenez en charge la fonctionnalité finale dans le moteur lors du chargement des actifs qui ont cette configuration. C'est ainsi que nous faisons les choses dans l'industrie du jeu.

Il est ingérable et indéterministe (deux choses terribles pour le développement de jeux) de s'attendre à ce que TOUTE méthode de création, TOUT format de fichier et TOUT chargeur générique gère parfaitement toutes les fonctionnalités de votre jeu. Il doit y avoir des normes et des processus en cours de route.

Si votre personnage utilise le skinning et a également besoin d'une géo attachée pour des armes ou autre, pensez à ce qui est nécessaire pour que le moteur puisse skinning, puis travaillez avec cela. J'ai proposé une telle solution à titre d'exemple. Malheureusement, le PR n'a pas été accepté car, pour une raison quelconque, ils ne veulent pas changer les chargeurs. de toute façon, j'espère avoir expliqué le problème et la solution dans le fil ci-dessus, ainsi que le PR que j'ai soumis.

Je ne peux pas vraiment y contribuer beaucoup plus que ce que j'ai déjà fait. J'espère avoir aidé certaines personnes ...

Bonne chance!

Le problème de skinning sur iOS disparaîtra complètement si vous effectuez le skinning dans l'espace local

Comme je l'ai dit depuis le début, c'est une solution de contournement pour une limitation iOS (bogue) et vous devez gaspiller de la puissance de traitement pour cela.
Ce n'est pas une solution!
La vraie solution consiste à augmenter la précision en virgule flottante sur iOS (à la valeur normale de 7 chiffres).
http://davenewson.com/posts/2013/unity-coordinates-and-scales.html

@ denbo-ft J'ai effectivement implémenté votre PR (nous avons notre propre chargeur) alors merci pour votre contribution, cela a été apprécié. J'espérais une autre approche car nous avons plusieurs avatars dans nos scènes, ils se déplacent, attrapent des objets, interagissent les uns avec les autres, etc. et avoir le squelette en 0,0,0 nous obligerait à changer beaucoup de choses dans notre code, risquer d'avoir de nouveaux problèmes, etc.

J'ai passé du temps à réfléchir au problème, mais je n'ai pas trouvé de meilleure solution. (En train d'essayer)

@RemusMar

La vraie solution est d'augmenter la précision en virgule flottante sur iOS

peut-être que quelqu'un devrait d'abord demander à @grorg and co quel est le problème avec les textures flottantes, et comment se fait-il que ce soit comme ça? parce que j'ai le sentiment que ce n'est pas seulement un bug mais la "solution" d'Apple à un autre problème

J'ai le sentiment que ce n'est pas seulement un bug mais la "solution" d'Apple à un autre problème

Probablement vrai.
Similaire au problème sur Firefox Android: bogue signalé, vérifié par les développeurs, mais non corrigé au cours des 5 derniers mois (2 versions)!?!

Voici comment fonctionne le développement logiciel de nos jours:
au lieu de correctifs au bon endroit, il existe des solutions de contournement chez les tiers.
Résultat final: des collections de bugs, de ressources gaspillées et de bloatware !!!

@jfcampos
Je recommanderais de garder la hiérarchie des os à la racine et d'ajouter simplement une fonction pour saisir la position WS finale de n'importe quel os en la multipliant par le martixWorld de la matrice de localisation réelle de l'avatar. C'est super simple et vous rendra ce que vous aviez avant le correctif.

Alternativement, si vous avez les côtelettes, vous pouvez revenir à la méthode d'origine (avec le bogue), inclure les matrices locales dans la texture osseuse, en doublant son utilisation de la texture, puis modifier les fragments de shader pour faire le calcul supplémentaire sur le gpu pendant le skinning . Gardez à l'esprit que cette solution, bien que «plus propre» du point de vue du code, double (peut-être quadruplant) la quantité de texture qui est téléchargée sur le GPU à chaque image, et donc beaucoup moins efficace que la suggestion ci-dessus. Mais pour toutes les raisons que vous pourriez avoir et dont je ne suis pas conscient, il peut être plus avantageux pour vous de le faire de cette dernière façon.

De ce qui n'était pas une solution auparavant, il existe maintenant plusieurs options pour être compatibles avec TOUS les appareils, ce qui est une exigence évidente pour la plupart des projets.

On dirait que je vais devoir utiliser des os à 0,0,0 et faire quelques calculs de matrice supplémentaires pour les autres choses. Merci!

@ denbo-ft est correct. C'est un problème three.js causé par l'écorchage dans l'espace mondial.

Pour référence, c'est ici que le changement de skin-espace-monde a été effectué: https://github.com/mrdoob/three.js/pull/4812.

Cette page vous a été utile?
0 / 5 - 0 notes