Premier commit du cinquième front. Trois parties : - `unity/MyInfoMateVR/` : le projet Unity (6000.0.83f1, URP, Meta XR SDK 205), un APK unique pour tous les clients. Menu flottant à sélection au regard, appairage, chargement de scène GLB, POI, cache de contenu, télémétrie. - `unity-overlay/` : les mêmes scripts à recopier sur un projet Unity neuf, avec les pièges rencontrés consignés dans son README. - `viewer/` : viewer et éditeur de scène web autonome (Vite, TypeScript, three.js), partagé avec les autres fronts. - `docs/` : état des lieux, setup Unity, décisions d'architecture et plan d'exécution en 9 étapes. La scène est décrite par un `scene.json` poussé par `adb push` : l'app le préfère à celui embarqué dans l'APK. Les binaires (GLB, textures de l'échantillon Sponza, DLL Meta XR) passent par Git LFS dès ce premier commit — les y faire entrer après coup demanderait de réécrire l'historique. Les artefacts régénérés par l'éditeur et par CMake (`Library/`, `.utmp/`, Burst debug) sont ignorés. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
56 lines
2.3 KiB
C#
56 lines
2.3 KiB
C#
using UnityEngine;
|
|
|
|
namespace MyInfoMate.Vr.Scene
|
|
{
|
|
/// <summary>
|
|
/// Conversion glTF → Unity. <b>Le seul endroit du projet où elle existe.</b>
|
|
///
|
|
/// glTF est en main droite, Y-up, unités en mètres. Unity est en main
|
|
/// <b>gauche</b>. Passer de l'un à l'autre demande d'inverser un axe horizontal.
|
|
///
|
|
/// Le décor, lui, est converti par glTFast à l'import. Les coordonnées du
|
|
/// manifeste, elles, ne passent par aucun importeur. Si les deux conversions
|
|
/// ne sont pas la même, les objets placés sont en miroir par rapport au décor
|
|
/// — et c'est <b>invisible sur une scène symétrique</b>, donc découvert tard.
|
|
///
|
|
/// D'où <see cref="Axis"/> : la valeur par défaut est celle que documente
|
|
/// glTFast, mais elle se <b>vérifie</b> avec calibration.glb (voir
|
|
/// <see cref="CalibrationCheck"/>), elle ne se suppose pas. Si le test montre
|
|
/// un miroir, c'est cette seule ligne qui change.
|
|
/// </summary>
|
|
public static class GltfSpace
|
|
{
|
|
public enum Convention
|
|
{
|
|
NegateX,
|
|
NegateZ
|
|
}
|
|
|
|
public static Convention Axis = Convention.NegateX;
|
|
|
|
public static Vector3 ToUnity(Vector3 p) =>
|
|
Axis == Convention.NegateX
|
|
? new Vector3(-p.x, p.y, p.z)
|
|
: new Vector3(p.x, p.y, -p.z);
|
|
|
|
/// <summary>
|
|
/// Une réflexion inverse le sens des rotations : l'axe est réfléchi <i>et</i>
|
|
/// l'angle change de signe. Sur un quaternion, ça revient à inverser le signe
|
|
/// des deux composantes que la réflexion ne touche pas.
|
|
/// </summary>
|
|
public static Quaternion ToUnity(Quaternion q) =>
|
|
Axis == Convention.NegateX
|
|
? new Quaternion(q.x, -q.y, -q.z, q.w)
|
|
: new Quaternion(-q.x, -q.y, q.z, q.w);
|
|
|
|
/// <summary>Les coordonnées du manifeste arrivent en tableaux JSON.</summary>
|
|
public static Vector3 Position(float[] v) => ToUnity(new Vector3(v[0], v[1], v[2]));
|
|
|
|
public static Quaternion Rotation(float[] q) =>
|
|
ToUnity(new Quaternion(q[0], q[1], q[2], q[3]));
|
|
|
|
/// <summary>L'échelle est invariante par réflexion — pas de conversion.</summary>
|
|
public static Vector3 Scale(float[] s) => new Vector3(s[0], s[1], s[2]);
|
|
}
|
|
}
|