Family Constellation (2022)
Made Using: Oculus Quest 2 · Virtual Reality · AFrame · ThreeJS · React · Maya · Projector
Role: 3D modeler, animator, technical artist, and coder

To preview the final pieces with interactivity: VR Version | Flat/non-VR Version

Family Constellation was made as part of my MFA thesis show for the School of the Art Institute of Chicago. It was intended to be viewed via an Oculus Quest 2 headset along with a wall projection in a gallery setting.

Family Constellation aims to deconstruct my own traditional patriarchal family tree into a constellation that lives in an immersive VR world. Intense connectivity and the desire for being recorded, this work plays with themes of navigation, ancient histories, the natural world, and astronomy. Meanwhile, celebrating and recognizing pioneering women’s and men’s contributions to the Arab world and culture today - regardless of gender norms or social expectations.

View from the VR version View from the non-VR version

The code in .html file

<head>
  <style>
    body {
      margin: 0;
    }
  </style>
  <script src="//unpkg.com/3d-force-graph-vr"></script>
  <script src="//unpkg.com/three-spritetext"></script>
</head>

<body>
  <div id="3d-graph">
    <a-scene>
      <a-entity id="rig"
      movement-controls="fly: true;
      speed: 3;
      movementEasing: 15;
      movementAcceleration: 80;"
      position="25 0 100">
        <a-entity 
            camera
            position="0 1.6 0"
            look-controls></a-entity>
            </a-entity>
      <a-assets>
        <img id="star" src="circle.png">

        <video 
        id="SphereVideo" 
        autoplay="true" 
        loop= "true"  
        crossorigin="anonymous"
        playsinline=""
        src="FC_April29_Bitrate8720p.mp4">
      </a-assets>
      <a-videosphere src ="#SphereVideo" radius="10000"></a-videosphere>
      <a-entity forcegraph="
      json-url: alani_2.json;
      linkDirectionalParticles: value;
      linkDirectionalParticleWidth: 1;
      linkDirectionalParticleColor:() => '4267FF';
      linkDirectionalParticleResolution: 10;
      linkDirectionalParticleSpeed: (d) => d.value * 0.002;
      linkColor: () => 'white';
      linkWidth: 0.5;
      nodeAutoColorBy: 'group';
      node-three-object: node => newTexture(node);
      "></a-entity>
    </a-scene>
  </div>

  <script>

document.addEventListener('click', videoPlay);
var vid = document.querySelector('#SphereVideo');
vid.load();

function videoPlay() {
    if ( vid.readyState === 4 ) {   
  
      document.removeEventListener('click', vid.play()) }


}

    // star sprite load
    const map = new THREE.TextureLoader().load("circle.png");

    function newTexture(node){

        //star sprite
        const material = new THREE.SpriteMaterial({ map: map });
        const spriteicon = new THREE.Sprite(material);
        spriteicon.layers.enable(2);
        spriteicon.scale.set(3, 3, 1);

        //text sprite
        const sprite = new SpriteText(node.id);
        sprite.layers.enable(2);
        sprite.color = "white";
        sprite.textHeight = 1.5;
        sprite.strokeWidth = 2;
        sprite.strokeColor = "black";
        sprite.backgroundColor = false;
        sprite.layers.enable(1);

        const group = new THREE.Group();
        group.add(spriteicon);
        group.add(sprite);

        return group;
    }

  </script>


</body>

Snippets of the 360 renders for the VR version

Snippets of the flat renders used for the projection component