1

Issue and solution needed

Hi, I created a VR scene using A-frame (https://aframe.io) and I currently have a custom component in my scene that mirrors the code on a canvas onto a plane in my scene. I'm wondering how I can edit the component to instead of mirroring a canvas onto the plane, the component will mirror a div onto a plane in my scene. The problem I have is that I want to embed HTML in my scene and I currently cannot accomplish this using the canvas so how can I edit my component so that instead of mirroring a canvas onto my plane, the code is mirroring a div. I should be able to insert any of my code inside that div and it should appear on the plane. The canvas also currently updates in real-time and the new component should also have that feature. This means that if I have an animation playing inside my div, the animation should also be playing on my plane. How can I change my component to achieve this? Here is a fiddle containing my current code: https://jsfiddle.net/AidanYoung/vbz7efhu/1/ Here is my current code:

   <!DOCTYPE html>
<html>

<head>
    <title>Loading...</title>
  <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
  <script src="https://unpkg.com/aframe-simple-sun-sky@^1.2.2/simple-sun-sky.js"></script>
    
</head>

<body>

<script>

AFRAME.registerComponent('draw-canvas', {

    init: function()
    {
        this.canvas = document.querySelector("#mycanvas");

        this.context = this.canvas.getContext('2d');
        
        this.x = 200;
        this.y = 100;
        this.dx = 5;
        this.dy = 3;
    },
    
    tick: function(t)
    {
        this.x += this.dx;
        this.y += this.dy;
        
        if (this.x > 512-50 || this.x < 0)
            this.dx *= -1;
        if (this.y > 512-50 || this.y < 0)
            this.dy *= -1;
    
        // clear canvas
        this.context.fillStyle = "#8888FF";
        this.context.fillRect(0,0, 512,512);
        
        // draw rectangle
        this.context.fillStyle = "#FF0000";
        this.context.fillRect( this.x, this.y, 50, 50 );

        // thanks to https://github.com/aframevr/aframe/issues/3936 for the update fix
        let material = this.el.getObject3D('mesh').material;
        if (!material.map)
            return;
        else
            material.map.needsUpdate = true;
    }
    
});

</script>

<a-scene  vr-mode-ui="enabled: false">
    

    <script>
        AFRAME.registerComponent('limit-my-distance', {
          init: function() {
            this.zero = new THREE.Vector3(0, 0, 0);
          },
          tick: function() {
            if (this.el.object3D.position.distanceTo(this.zero) > 10) {
              this.el.object3D.position.set(0, 1.6, 0);
            }
            //this.el.object3D.position.x += 0.1;
          }
        });
      </script>
        <a-camera limit-my-distance></a-camera>
    
    <a-assets timeout="10000">
        <img id="grid" src="images/border.png" />
        <img id="sky" src="images/stars.jpg" />
        <!-- texture sizes should be powers of 2 -->
        <canvas id="mycanvas" width=512 height=512 ></canvas>
    </a-assets>
    

    <a-simple-sun-sky sun-position="0.7 0.4 -1"></a-simple-sun-sky>
    <a-entity light="type: ambient; color: #BBB"></a-entity>
    <a-entity light="type: directional; color: #FFF; intensity: 1.5" position="0.7 0.4 -1"></a-entity>  <a-plane
        width="100" height="100"
        position=" 0.00 0.00 0.00" 
        rotation="-90 0 0" 
        color="royalblue" 
    >
    </a-plane>
    
    
    <a-plane
        id = "canvas-display"
        width = "4" height = "4"
        position = "0 3.5 -6"
        material = "shader: flat; src: #mycanvas;"
        draw-canvas>        
    </a-plane>
   
    <a-gltf-model src="https://cdn.glitch.com/9f39024a-cefe-48b1-ab98-4056bba0cf4d%2FCircles.glb?v=1622685767402" position="-0.1 0.5 -1" scale="1.8 1.8 1.8"></a-gltf-model>

</a-scene>

</body>
</html>
Sam Joshua
  • 310
  • 6
  • 17
Aidan Young
  • 554
  • 4
  • 15

1 Answers1

1

Since A-Frame is built on top of Three.js, the following should be possible:

  • CSS3DRenderer to render a div, the periodictable is a good example. UPDATE: Even CSS2DRenderer should be sufficient for this task.
  • to combine it with the rest of the scene which is rendered by a WebGLRenderer this post should be helpful. UPDATE: Perhaps not necessary.

Update

In more detail, since you already can display a canvas inside of A-Frame, you should just attach the three.js CSSrenderer to it. This is not a working example, just a sketch that should guide you.

Here the init():

this.canvas = document.querySelector("#mycanvas");
this.renderer = new THREE.CSS3DRenderer();
this.renderer.setSize(this.canvas.innerWidth, this.canvas.innerHeight);
this.canvas.appendChild(this.renderer.domElement);

//may not work for you, just place the camera as you wish
this.camera = new THREE.PerspectiveCamera(
    40, this.canvas.innerWidth / this.canvas.innerHeight, 0.1, 200 );
this.camera.position.z = 30;

this.scene = new THREE.Scene();

//create a div with id="mydiv" and put all you want to display in there
const element = document.getElementById('mydiv');
this.scene.add(new CSS3DObject(element));

And tick():

this.renderer.render(this.scene, this.camera);
Isolin
  • 845
  • 7
  • 20
  • The link looks like it could work however I'm unsure of how I can get the mirroring into my A-frame scene from three.js – Aidan Young Jun 16 '21 at 00:36
  • I have no experience with A-Frame, but quite some with Three.js. I will update the answer to provide more details. – Isolin Jun 16 '21 at 09:36
  • The code looks like it would work but I still dont have an idea of I can get this into my A-frame scene. I've tried inserting the three.js directly into the scene without any results. – Aidan Young Jun 17 '21 at 03:54
  • As I said, I have no experience with A-Frame, so I can't help you directly. I know it is built on top of Three.js, so the compatibility must be there. If you try searching, you will for sure find pointers how to achieve it. I tried to search right now and the first result I found already gives good hints on accessing the underlying Three.js components from A-Frame: https://stackoverflow.com/questions/38106567/combining-a-frame-with-three-js – Isolin Jun 28 '21 at 15:12