Jak komunikować się z hologramem w HoloLens? Jest kilka sposobów, wśród których można wymienić spojrzenie. I o nim dziś będzie mowa.
W Holographic Academy znajdziemy o tym dwa tutoriale: Holograms 101E: Introduction with Emulator i Holograms 210: Gaze. Pierwszy zawiera prosty przykład w rozdziale 2. Drugi tutorial we wszystkich swoich 6 częściach pokazuje bardziej zaawansowane przykłady. Jednak do jego rodziału trzeciego włącznie można jakoś obejść się bez fizycznego urządzenia i jest to bardziej zaawansowana realizacja tego, co już widzieliśmy w pierwszym tutorialu. Chodzi tutaj o wirtualny kursor, który po skierowaniu naszego wzroku na jakiś przedmiot zmieni wygląd i przyklei się do oglądanej płaszczyzny, a także o reakcję samego przedmiotu. I tym zajmiemy się dzisiaj.
Do bardziej zaawansowanych rzeczy z ostatnich trzech części drugiego tutoriala (przecinanie kierunkowe, ustawianie hologramu zawsze przodem do nas, czy podążanie za nami) może kiedyś wrócimy. Nie ma emulacji kierunku patrzenia, fizyczne urządzenie byłoby tutaj wskazane. Póki co, nie próbowałem odpalać na emulatorze.
Przykłady z akademii sobie odpaliłem, ogólnie super, działają (no może z wyjątkiem tego z pierwszego tutoriala, ale po zmianie kodu też poszedł). Aha, natrafiłem jeszcze na szkolenie Pluralsight zatytułowane HoloLens Development Fundamentals, które też mogę polecić. Tam są podstawy, ale zrealizowane w całości własnoręcznie, nawet kursor.
Czy jednak tworzenie - w sumie dość podstawowej rzeczy - jaką jest kursor i reakcja na spojrzenie - nie może być bardziej szybkie i proste? Może. Przy pomocy HoloToolkit, a właściwie HoloToolkit-Unity, z którego dziś skorzystamy. Gwoli ścisłości, tutoriale z akademii i wspomniana kiedyś przeze mnie książka też używają pewnych elementów tego toolkitu, ale z początkowej, starej wersji. My dziś skorzystamy z najnowszej wersji, która różni się od tej początkowej dość istotnie. Upraszcza implementację i wprowadza infrastrukturę w postaci interfejsów. Dobrze opisuje to post Unity 5.5 and the HoloToolkit – Changes in Input when Developing HoloLens Apps. Generalnie jednak jakoś ta wiedza nie jest szeroko promowana…
Jak rozpocząć korzystanie z toolkitu w Unity? Rzuciłem okiem na stronkę GetStarted, pobrałem gotową wersję i na kopii swojego projektu z sześcianem zaimportowałem pakiet HoloToolkit-Unity-v1.5.5.0.unitypackage do Unity (Assets -> Import Package -> Custom Package…). Jakich elementów użyć, by kursor nam działał i coś się działo na obiekcie? Wobec braku dobrych tutoriali, znalazłem gdzieś na forum, że najlepiej sobie obejrzeć testowe sceny (po zaimportowaniu toolkitu w Assets > HoloToolkit > Input > Tests > Scenes), co też uczyniłem.
A teraz już do dzieła!
Czego potrzebujemy, by mieć kursor, który odpowiednio zachowa się na przedmiocie 3D? Przeciągamy InputManager.prefab z Assets > HoloToolkit > Input > Prefabs do panelu Hierarchy. Kursor wybieramy sobie z Assets > HoloToolkit > Input > Prefabs > Cursor. W naszym przypadku chcemy zmieniać jego postać po skrzyżowaniu naszego wzroku z przedmiotem i dobry będzie to tego Cursor.prefab. Przeciągamy go podobnie jak poprzednio do Hierarchy.
Projekt Unity eksportujemy tak jak w poprzednich postach do projektu Visual Studio i uruchamiamy na emulatorze (chyba że ma ktoś urządzenie). Gdy nie patrzymy na sześcian to kursor jawi się jako światełko:
Jak spojrzymy na sześcian, to kursor przybierze wygląd pierścienia przyległego do ściany:
Jak kierować spojrzeniem w emulatorze? Klikam i przeciągam myszą albo naciskam sobie klawisze strzałek na klawiaturze. Chodzenie to z kolei mogą być klawisze W, A, S i D. Wiecej o używaniu emulatora na stronie Using the HoloLens emulator.
A dlaczego nie zrobiłem póki co spoglądania na zielony, animowany szkielet, jaki mam w HoloVision2? Przymierzałem się, ale natrafiłem na kilka przeszkód. W inspektorze sześcianu na scenie jest coś takiego jak collider (tutaj box collider, są też inne rodzaje), automatycznie dodany. Bez elementu collider na modelu nie będą wykrywane kolizje i kursor będzie się zachowywać tak, jakby niczego tam nie było. W przypadku bardziej złożonych modeli możemy dodać do nich w inspektorze mesh collider otaczający wybrany mesh z modelu dokładnie takim jak on kształtem. Nie jest to jednak wydajne rozwiązanie, jeśli model animujemy. Collider typu mesh jest kosztowny w obliczeniach. Możemy wtedy dla poszczególnych części modelu poustawiać elementy collider (mesh czy bardziej wydajne jeśli nie stracimy dużo na kształcie - box, sphere czy capsule). Astronauta z akademii HoloLens jest tak właśnie zrobiony. O obiektach collider można poczytać w tutorialach z importu modeli do Unity czy książkach o tym środowisku. Okazuje się, że można nawet automatycznie próbować wygenerować collider-y za pomocą opcji Generate Colliders w inspektorze modelu z Assets. Na moim szkielecie nic się jednak samo nie wygenerowało. Mesh w tym modelu jest tylko jeden i dotyczy całej postaci w pozycji leżącej, jak ręcznie dodam do niego mesh collider to dotyczy on także pozycji leżącej, nawet jeśli szkielet stoi i jak trafię w collider to kursor może się zmienić, ale trzeba liczyć na łut szczęścia. Astronauta Microsoftu ma wiele elementów mesh w sobie, co ułatwia zdaje się tworzenie collider-ów dla poszczególnych części. Na razie temat zostawiam, może do niego wrócę za jakiś czas, zobaczymy.
Teraz reakcja obiektu na spojrzenie. Można stworzyć w Assets Unity własny skrypt w C# (prawy przycisk –> Create –> C# script), edytować go w Visual Studio poprzez podwójne kliknięcie i potem podpiąć do obiektu na scenie poprzez przeciągnięcie na jego zakładkę Inspector (albo od razu przez Add Component w inspektorze). Ja poszedłem jeszcze bardziej na skróty i podpiąłem skrypt FocusedObjectColorChanger z testów toolkita (Assets > HoloToolkit > Input > Tests > Scripts).
Jak nazwa wskazuje ustawia kolor obiektu na wskazany, jeśli spojrzymy na niego. Oto kod:
[RequireComponent(typeof(Renderer))]
public class FocusedObjectColorChanger : MonoBehaviour, IFocusable
{
[Tooltip("Object color changes to this when focused.")]
public Color FocusedColor = Color.red;
private Color originalColor;
private Material cachedMaterial;
private void Awake()
{
cachedMaterial = GetComponent<Renderer>().material;
originalColor = cachedMaterial.GetColor("_Color");
}
public void OnFocusEnter()
{
cachedMaterial.SetColor("_Color", FocusedColor);
}
public void OnFocusExit()
{
cachedMaterial.SetColor("_Color", originalColor);
}
private void OnDestroy()
{
DestroyImmediate(cachedMaterial);
}
}
Widzimy dość prostą klasę C#, która standardowo w przypadku skryptów dziedziczy po MonoBehaviour, a w przypadku obsługi focusa ze spojrzenia i w nowym HoloToolkicie dodatkowo implementuje interfejs IFocusable. Efekt działania prezentuję poniżej:
W przykładach toolkitu widziałem jeszcze skrypt GazeResponder, który podświetla materiał (trochę podobnie jak w przypadku astronauty w akademii HoloLens).
Dzisiejszy przykład udostępniłem na github jako HoloVision3.
Zabawa z HoloLens trwa nadal. Do zobaczenia w następnym odcinku.