7 minute read

Nos adentramos en la sexta semana del blog. Los retos indicados son:

Utilizar Blender.

Investigar sobre entidades padre-hijo con el fin de solucionar el problema de sincronización de las físicas.

Investigar sobre que ocurre cuando los usuarios introducen diferentes valores para las físicas.

Introducción de parámetros a través de un formulario.

Blender

Sincronización físicas

La semana pasada tuve una reunión con David Moreno, el cual me indico que el problema de sincronización dado al usar físicas es debido a que no son deterministas, por tanto, dependen del procesador. Como solución propuso que no se enviaran las físicas, sino los cambios de posición, lo cual puede lograrse con entidades padre, que se encargan de la posición, y entidades hijo, que se encargan del resto.

  • html

Podemos observar que movement es la entidad padre, mientras que sphere es la entidad hijo.

<a-entity id="movement" 
  networked="template:#movement-template;networkId:movement;persistent:true;owner:scene">

    <a-entity id="sphere" 
    networked="template:#sphere-template;networkId:sphere;persistent:true;owner:scene">
    </a-entity>

</a-entity>
  • ¿Cómo coordinar la posición entre navegadores?

He llegado a dos opciones posibles.

  1. setInterval - Julio/6J/examples/302.html -

Mediante el uso de setInterval podemos obtener los cambios de posición de nuestra esfera, pero no observo continuidad, sino un movimiento a parches.

Nota:

  • Parece que si pongo en myCallBack la sincronización de la esfera mejora la situación, muy ligeramente.
  1. tick - Julio/6J/examples/303.html -

Tick: Llamado en cada bucle de renderizado o marca de la escena. Se utiliza para cambios o controles continuos.

Mediante el uso de tick podemos observar cambios de posición en nuestra esfera. En función del instante existe mayor o menor continuidad. No soluciona el problema, ya que el usuario visualizaria el contenido a trompicones e incluso en ocasiones se queda congelado.

La función tick no permite usar el prefijo this., por ello, he introducido en su interior una función denominada exchange, que si lo permite y noto cierta mejora, aunque no es perfecto.

Notas:

  • En Aframe básico funciona sin problemas
  • Cuando grabo la pantalla se realentiza mucho el movimiento en el navegador que solo recibe los cambios de movimiento

Conclusión

Los resultados obtenidos me han llevado a comprobar si realmente no es igual el movimiento entre los navegadores cuando las físicas son compartidas, ya que la semana anterior observabamos un pequeño delay entre los navegadores, el cual se ha incrementado al compartir la posición. Antes de comprobar mis conclusiones en Networked Aframe lo he hecho en Aframe, ya que me permite observar con sencillez como en cada refresco del navegador los movimientos en las entidades que componen la escena son diferentes, ¿es esto que las físicas no son deterministas? Las pruebas en Networked Aframe permiten observar como estos cambios en los movimientos de las entidades en cada refresco coinciden con lo sucedido en Aframe, pero la posición siempre se comparte. Hemos de tener en cuenta que position es un componente que se comparte por si solo en Networked Aframe. Por tanto, como conclusión puedo confirmar que los movimientos dados en los navegadores se comparten al compartir las físicas y no es necesario compartir únicamente la posición, ya que esto da lugar a problemas como delay y congelados.

¿Qué ocurre cuando ambos navegadores llevan parte de las físicas?

En el siguiente video podemos observar cierta lentitud de sincronización cuando un navegador lleva el mando sobre una entidad y otro sobre otra, por tanto, como conclusión tenemos que es recomendable que todas las físicas se encuentre en uno de los navegadores.

Julio/6J/A022.html

  • Ejemplos Networked Aframe

Julio/6J/304J.html

Julio/6J/305J.html

  • Ejemplo: Aframe

Julio/30J/phy_ex2.html

¿Qué ocurre cuando las físicas estan iniciadas desde el primer momento?

Hasta ahora he observado lo que ocurre cuando las físicas son iniciadas por uno de los navegadores, pero ¿qué ocurre cuando estan al introducirnos en la escena?

  1. Julio/30J/A041.html

En este caso tenemos posicionadas las físicas en templates y al iniciar los diferentes navegadores no se sincronizan.

    <template id="sphere-template">
      <a-entity 
      push
      class="raycastable" 
      geometry="primitive: sphere" 
      material="color: red" 
      position="2 20 -20" 

      ammo-body="type: dynamic; 
      emitCollisionEvents: true;
      gravity: 0 -9.8 0;
      linearDamping: 0.1" 
      ammo-shape="type: sphere"

      ></a-entity>
    </template>
  1. Julio/30J/A042.html

En este caso tenemos posicionadas las físicas al iniciar la escena, initScene. En ciertas ocasiones se da sincronización, pero no es lo común, ya que tiende a bugearse. Normalmente las entidades no adquieren el movimiento natural con la presencia de físicas, es decir, no caen desde las alturas o traspasan entidades solidas. En este caso pondría como solución la compartición de la posición, pero ya he comentado anteriormente que tampoco es muy eficaz.

Actuación de Networked Aframe ante datos por teclado

A continuación, vamos a observar que ocurre cuando introducimos en los navegadores valores diferentes. ¿Se mantiene el último valor introducido? ¿Actúan de forma diferente?

Antes de empezar hemos de tener en cuenta que es muy importante compartir los valores introducidos por teclado entre los navegadores, ya que si no es así cada uno actuará de una forma, y no es lo que estamos buscando.

Nota:

  • En ejemplos anteriores he observado como si el valor introducido por teclado no es compartido cada navegador actuará de una forma, es decir, si inicializo el movimiento en aquel en el que he modificado la variable actua con la variable indicada, pero en caso contrario no.

Compartición, entre navegadores, de los valores introducidos por teclado

El modo para compartir los valores entre navegadores que he pensado es a través de templates cuya entidad interior es texto, ya que de este modo podemos compartir su valor.

  • html

Template

  <a-assets>
    <template id="text-template">
      <a-entity 
      class="raycastable" 
      text="value: No value; color: red; width: 10; height: 10"
      position="0 3 -5"
      ></a-entity>
    </template>

Renderizado

  <a-entity id="text" 
    networked="template:#text-template;networkId:text;persistent:true;owner:scene">
  </a-entity>
  • script

Sincronización

  if (!NAF.schemas.hasTemplate("#text-template")) {
        NAF.schemas.add({
          template: '#text-template',
          components: [
            "position",
            "rotation",
            {
              component: 'text',
              property: 'value'
            }
          ]
        });
  }

Compartición del valor

  if (name=="i"){
    console.log("Ingresa número");
    var text = document.querySelector('#text');
    var read = prompt("Ingrese un valor: ");
    //Añadir físicas esfera
    this.text.setAttribute('text', {
        value: read
    });
    NAF.utils.takeOwnership(this.text);
  }

Este método nos permite que ambos navegadores tengan el mismo valor en la variable deseada, por ello, a no ser que lo programemos de algún modo siempre almacenará el último valor introducido.

Julio/30J/A021.html

Conclusión

  1. Para que ambos navegadores visualicen la escena con el parámetro introducido por uno de ellos, independientemente de quien la inicie, se ha de compartir el valor introducido mediante la entidad text. Si este valor no es compartido entre navegadores el movimiento dependerá de quien lo inicie.

  2. La entidad text mantendrá el último valor introducido, independientemente del navegador que lo introduzca. Aunque hemos de tener en cuenta que esto podría evitarse a partir de cambios en nuestro código.

  3. ¿Quién gobierna? En mis ejemplos ambos navegadores pueden introducir valores al pulsar la tecla ‘i’ o iniciar el movimiento al pulsar la tecla ‘o’. Observamos que la introducción del valor no hace que uno de los navegadores mande, pero al iniciar el movimiento esto cambia, ya que aquel que pulsa la tecla ‘o’ gobierna en la escena. ¿Cómo sabemos que gobierna en la escena? Cuando sacamos al otro navegador de la escena no ocurre nada, pero en caso contrario la escena se paraliza en aquel que no la ha iniciado y continua abierto. Esto me lleva a determinar que no es necesario eliminar las físicas de uno de los navegadores, ya que por defecto parece ser que el otro únicamente replica las acciones que hace el navegador que lleva el mando.

Nota:

Entre los componentes de una escena encontramos elementos sin físicas, elementos pasivos con físicas y elementos autonomos con físicas. Hasta ahora los ejemplos realizados tienen en cuenta elementos sin físicas y pasivos con físicas. Por tanto, hemos de lograr que los autonomos con físicas los lleve uno de los navegadores, ya que en caso contario se darian incoherencias.

Formulario

El objetivo final del TFG es que dos usuarios introduzcan una serie de parámetros, que serán determinantes en el funcionamiento de los objetos autonomos. Por tanto, creo importante la existencia de un formulario inicial en el que se indiquen estos parámetros.

A-frame

  • Formulario

El siguiente formulario permite el envio de parámetros al otro HTML.

  <!DOCTYPE html>
  <html>
  <head>
  <title>FORM</title>
  </head>
  <body>
  <form id="form" method="GET" action="display_ex1.html">
  COLOR: <input type="text" name="color" id="color">
  RADIUS: <input type="text" name="radius" id="radius">
  <input type="button" value="Submit" onclick="submitForm()">
  </form>
  <script>
  function submitForm(){
      if(typeof(localStorage) != "undefined"){
          localStorage.color = document.getElementById("color").value;
          localStorage.radius = document.getElementById("radius").value;

      }
      document.getElementById("form").submit();
  }
  </script>
  </body>
  </html>
  • Display

El siguiente código permite la recepción de los parámetros del formulario.

  <!DOCTYPE html>
  <html>
    <head>
      <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
      <script>
          function setData(){
              if(typeof(localStorage) != "undefined"){
                  var x;
                  var y;
                  x = localStorage.color;
                  y = localStorage.radius;
                  console.log(x + y)

              }
          }
      </script>
    </head>
    <body onload="setData()">
      <a-scene>
        <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
        <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
        <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
        <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
        <a-sky color="#ECECEC"></a-sky>
      </a-scene>
    </body>
  </html>

Networked Aframe