Reality Virtually Hackathon FTW!

Recently I had the extreme pleasure and honor of working with a group of towering awesomeness, and we made something out of love with A-Frame that lets people give comfort and support to loved ones. In the process of working with Mo Kakwan, Ting-Kai Chang, Victoria Grant, and Lydia Jessup at the MIT Media Lab’s Reality Virtually Hackathon to make gARden Cards, not only did I feel like I gained a mind-blowing new family, but the experience opened my eyes to the true power of A-Frame… combine A-Frame with Vue’s component system and building, organizing, and object-orienting your code becomes trivial and easy. I arrived on Thursday having no idea what I was going to be doing and left Monday night with a new way to practice the craft that I love: WebVR. So for all of that, and the giant cardboard check now hanging proudly in the GoggleWorks VR Lab, thanks MIT!

3D finds the web

I’ve been doing 3D on the web since the days of Papervision3D in Flash, so when I say that I hadn’t really tried A-Frame until Reality Virtually, it wasn’t because I didn’t believe in the technology or found it too intimidating. Actually, after reading a bunch of “getting started” articles and docs and attending A-Frame demos at meetups and conferences about the same early demos, I was under the illusion that there wasn’t a good way to object orient A-Frame code, or even really get to the underlying three.js classes and geometry that I had been used to coding for years. As embarrassing as it is to admit now, I always thought of A-Frame as the HTML of the VR web: structural and quick to scaffold, but ultimately not sophisticated enough for the animation that an expressive web requires. So when we decided that we would use A-Frame as our VR Engine of choice, I was excited but a little skeptical of how far we’d be able to take the polish over the course of only a few days. As it turns out, it was the most organized and easily-extensible project I’ve worked on in years, thanks to Kai’s knowledge of Vue.

Coming into Vue

Vue.js is an HTML/JavaScript/CSS framework that I’d heard about for a few months in my small development circles here in Reading, PA, but had never really had the chance to experiment with yet. As Kai patiently explained Vue’s structure to Mo and I over the weekend, I realized that Vue works similarly to other frameworks I’d worked with in the past like Angular and Bootstrap, but it had the ability to also create components that could then be instantiated as simple template tags by other components, with each component’s markup, JavaScript, and CSS bundled into one ES6 file. And when those template tags are A-Frame tags, the result is a hierarchical DOM-structure in a reusable 3D component… pretty sweet!

<template>
  <!-- Planet that grows everything -->
  <Planet></Planet>
</template>

<script>
import Planet from '@/components/Planet'

export default {
  name: 'gARdenCards',
  components: {
    'Planet': Planet,
  }
}
</script>

A-Frame Templating

But now that we had our starting structure, how could we actually do the animation on materials and positions and rotations that aren’t immediately obvious with A-Frame? With backgrounds in Flash, Mo, Vee and I realized that the Vue structure was like MovieClips, where the View and Model/Controller were combined in one file, with imports, attribute getters/setters, and hooks for init events. Welp, Vue uses a “components” object for class imports, “data”, “params”, and “computed” objects and methods as getters/setters, and a “mounted” event handler that works just like init. And as for custom methods of the class, you guessed it, a “methods” object. This let us do things like replicate a bunch of FlowerHolder objects using Vue’s built-in iterator, while simultaneously giving all of the instances different properties a la a Factory design pattern like so:

<template>
 <a-sphere
  planet-gaze-rotator
  position="0 -2 -13"
  :radius="planetRadius"
  src="img/planet 1.png"
 >
   <flowerHolder
    v-for="(msg, idx) in popMsgs"
    :key="idx"
    :planet-radius="planetRadius"
    :type="msg.flower"
    :rot-x="msg.rotationX"
    :rot-y="msg.rotationY"
    :voiceurl="msg.voiceurl"
    :msg="`${msg.msg} \n by [${msg.name}]`"
    :stage="randomStage(idx)"
    ></flowerHolder>
 </a-sphere>
</template>

Where “msg” is a data property computed on “mounted”, and popMsgs is a computed attribute. And then each FlowerHolder has a Flower like so in its template:

 <template>
  <a-entity name='x-axis' :rotation="`${offsetX} 0 0`">
    <a-entity name='y-axis' :rotation="`0 0 ${offsetY}`">
      <a-entity name='planet-surface' :position="`0 ${hoverDistance} 0`">
        <flower ref="flower" :stage="stage" :modelids="modelids"
          :mtlids="mtlids" :ps="ps"
          :play="play"></flower>
      </a-entity>
    </a-entity>
  </a-entity>
 </template>

Putting it all together

And here’s a visual indication of how these classes all fit together:
gARdenFlowers-classdiagram

If there’s interest, we can do a more thorough breakdown of the JavaScript behind the gARden Cards, but in the meantime you can view the full open-source project at our public GitHub page, https://github.com/RealityVirtually2019/BizzyBee/

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>