Semana 11. A-frame
Nos adentramos en la decimoprimera semana del blog. Los retos indicados son:
Introducción a Websim
Malla de colisión compleja
Introducción a Websim
Creación de una escena
Marta Quintana me ha indicado donde se encuentran las escenas A-frame y que no se usa HTML, sino JSON para su creación. Por tanto, durante estos primeros días voy a practicar en la construcción de escenas mediante JSON. Por otro lado, hasta ahora han usado el motor de físicas CANNON y yo estoy usando AMMO.
Escena 1
Se trata de una escena muy básica con un suelo, un cielo, una geometría básica y un modelo 3D.
Escena 2
La modificación de la siguiente escena con respecto a la anterior es el uso de el modelo creado en Blender por mí.
Introducción Networked Aframe
Una vez instalado NAF, ¿cómo puedo añadirlo a la escena? Marta me ha indicado que he de crear una carpeta en JavaScript editor e introducir todo lo que sea necesario para luego añadir en ‘index.html’ los enlaces necesarios.
Introducción del motor de físicas AMMO
Por otro lado, no localizo la ubicación del motor de físicas que ha sido utilizado hasta ahora. Sin saber sobre el tema anteriormente comentado he intentado añadir el motor de físicas AMMO y únicamente al indicar que el driver es AMMO deja de funcionar por completo la escena.
Nota
Usando el modo teleoperador (icono palanca) podemos movernos con el coche por la escena.
- u - avanzar
- i - retroceder
- h - derecha
- j - izquierda
Usando el modo cámara (icono grabadora) podemos visualizar aquello que visualiza el coche.
Malla de colisión compleja.
La semana anterior comenté que una posible solución a la hora de crear mallas con formas más complejas es usar Collision Filtering. ¿Cómo funciona este método?
La entidad ha de contener los siguientes componentes:
- collisionFilterGroup
- collisionFilterMask
Se ha de tener en cuenta que el valor de collisionFilterMask se obtiene a partir de la operación OR entre los valores collisionFilterGroup de las entidades que colisionan. Para determinar si hay interación se ha de realizar la operación AND entre collisionFilterGroup y collisionFilterMask y en caso de que el valor sea igual a 0 no chocarán las entidades implicadas.
Entidad constituida por diversas mallas.
<a-scene physics="driver: ammo;
debug: true;
debugDrawMode: 1;"
background="color: pink">
<!--
-->
<a-entity camera position="0 3 5" look-controls wasd-controls></a-entity>
<!-- Suelo -->
<a-plane
ammo-body="type: static;
collisionFilterGroup: 2; collisionFilterMask: 3"
ammo-shape="type: box"
position="0 -3 -10" rotation="-90 0 0" width="30" height="12"
color="yellow"></a-plane>
<!-- Bola -->
<a-sphere
material="color: blue" position="0 0 -10" radius="1.5"
ammo-body="type: dynamic;
emitCollisionEvents: true;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="fit: all">
<a-sphere
material="color: red" position="-1.5 -0.5 0"
ammo-body="type: dynamic;
emitCollisionEvents: true;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="fit: all"
></a-sphere>
<a-sphere
material="color: green" position="-2.5 -0.5 0"
ammo-body="type: dynamic;
emitCollisionEvents: true;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="fit: all"
></a-sphere>
<a-sphere
material="color: red" position="-3.5 -0.5 0"
ammo-body="type: dynamic;
emitCollisionEvents: true;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="fit: all"
></a-sphere>
<a-sphere
material="color: green" position="-4.5 -0.5 0"
ammo-body="type: dynamic;
emitCollisionEvents: true;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="fit: all"
></a-sphere>
<a-sphere
material="color: red" position="-5.5 -0.5 0"
ammo-body="type: dynamic;
emitCollisionEvents: true;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="fit: all"
></a-sphere>
<a-sphere
material="color: green" position="-6.5 -0.5 0"
ammo-body="type: dynamic;
emitCollisionEvents: true;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="fit: all"
></a-sphere>
<a-sphere
material="color: black" position="1 0.5 -0.5" radius="0.5"
></a-sphere>
<a-sphere
material="color: black" position="1 0.5 0.5" radius="0.5"
></a-sphere>
</a-sphere>
</a-scene>
-
Entidades que conforman un gusano
collisionFilterGroup: 1; collisionFilterMask: 2
Los valores dados son 1 y 2, por tanto, la operación OR es igual a 3. ¿Habrá interación entre las entidades que contengan estos valores? La respuesta es NO, ya que la operación AND entre 1 y 3 es igual a 0.
-
Suelo
collisionFilterGroup: 2; collisionFilterMask: 3
Los valores dados son 2 y 3, por tanto, la operación OR dada con los valores del gusano es igual a 3. ¿Habrá interación entre las entidades que contengan estos valores? La respuesta es SI, ya que la operación AND entre 2 y 3 es distinta a 0.
Nota: El valor de collisionFilterMask es elegido teniendo en cuenta que resultado entre las operaciones OR y AND
¿Qué ocurriría si otra entidad colisionará con nuestra entidad formada por diversas mallas?
Por ahora se ha logrado que una geometría compleja creada en A-frame se encuentre envuelta por diversas mallas de colisión sin que interactuen entre sí, pero qué pasaría si otra entidad externa chocara con este modelo 3D.
Como podemos ver en el video anterior al tratarse de entidades dinámicas todas se ven afectadas por las físicas y la forma de nuestro modelo no se mantiene. Por tanto, una posible solución es que únicamente la entidad padre sea dynamic y el resto, las hijas, static. ¿Funciona? Si, como podemos ver en el siguiente video ahora el modelo actua como un conjunto.
Otorgar una malla de colisión compleja a un modelo 3D creado en Blender.
Por tanto, teniendo en cuenta los resultados obtenidos anteriormente para otorgar una malla de colisión compleja a un modelo 3D creado en Blender se han de usar entidades padre-hija, siendo la entidad padre la que otorga las físicas. La complejidad de adaptar la malla es mayor que en el caso anterior, donde el modelo 3D habia sido creado con A-frame, pero el resultado del modelo es mucho mejor si usamos Blender. Por todo lo anterior, he de decir que la dificultad a la hora de poner la malla de colisión es menor que la de crear un modelo 3D en A-frame.
<a-scene physics="driver: ammo;
debug: true;
debugDrawMode: 1;"
background="color: pink">
<a-assets>
<a-asset-item id="car" src="assets/car.gltf"></a-asset-item>
</a-assets>
<!-- Coche -->
<a-entity
gltf-model="#car"
position="0 0 -10"
rotation="0 90 0"
ammo-body="type: dynamic;
emitCollisionEvents: true;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="type: box;fit: manual; halfExtents: 1.5 1 3.7; offset: 0 0 -0.3"
>
<a-entity
geometry="primitive: box"
material="opacity: 0"
scale="2 2 3"
position="0 1 -1"
ammo-body="type: static;
collisionFilterGroup: 1; collisionFilterMask: 2"
ammo-shape="fit: all"
>
</a-entity>
</a-entity>
<!-- Camara -->
<a-entity camera position="0 1 5" look-controls wasd-controls></a-entity>
<!-- Suelo -->
<a-plane
ammo-body="type: static; collisionFilterGroup: 2; collisionFilterMask: 3"
ammo-shape="type: box"
position="0 -3 -10" rotation="-90 0 0" width="30" height="12"
color="yellow">
</a-plane>
</a-scene>
Es importante no olvidar que para mantener unidas las diferentes mallas de colisión las entidades hija han de ser estáticas, por ello, si otras entidades chocan no la traspasarán, pero no habrá reacciones por parte de las hijas. Una posible solución sería añadirlas una función para que en caso de colisión haya una reacción. ¿El problema? En las colisiones no podemos determinar desde donde proviene el golpe, por tanto, no podemos determinar cual sería el movimiento natural del objeto. Opciones:
- La colisión no provoque movimiento.
- La colisión provoque un movimiento aleatorio que puede asemejarse o no al que se daría de forma natural.