← Documentación

Ampliar UFO@home con módulos

No hay cuenta: un módulo es un archivo en una dirección suya. El editor lo carga, las grabaciones que lo necesitan lo citan.

Lo que aporta un módulo#

Fuentes de datos (imágenes aéreas, relieve del suelo, meteorología, tráfico aéreo…) y modelos 3D, cada uno con el crédito que pide su licencia. Se suman a los de UFO@home: en los selectores del editor, después de ellos, y en la escena allí donde una grabación cita uno de sus modelos.

El manifiesto#

Un archivo JSON, ufoathome-module.json por convención, legible desde otros sitios (CORS). Sus direcciones relativas se leen desde la suya.

El manifiesto de abajo es de solo lectura y conoce su formato: pon el cursor dentro de un objeto y pulsa Ctrl+Espacio (⌥+I en Mac) para listar todas las claves que podrían ir ahí, con lo que significa cada una.

{
  "format": 1,
  "id": "acme",
  "name": "ACME surveys",
  "credit": "© ACME",
  "creditUrl": "https://acme.example",
  "contributes": {
    "imagery": [
      {
        "id": "acme-ortho",
        "name": "ACME ortho",
        "credit": "© ACME",
        "creditUrl": "https://acme.example/licence",
        "tiles": "https://tiles.acme.example/ortho/{z}/{x}/{y}.jpg"
      }
    ],
    "elevation": [
      {
        "id": "acme-relief",
        "name": "ACME relief",
        "credit": "© ACME",
        "creditUrl": "https://acme.example/licence",
        "tiles": "relief/{z}/{x}/{y}.png"
      }
    ],
    "models": [
      {
        "id": "acme-weather-balloon",
        "kind": "entity",
        "name": "Weather balloon",
        "file": "models/balloon.glb",
        "sizeM": {
          "widthM": 2,
          "lengthM": 2,
          "heightM": 2
        },
        "credit": {
          "title": "Weather balloon",
          "author": "ACME",
          "license": "CC BY 4.0",
          "sourceUrl": "https://acme.example/models"
        }
      }
    ]
  },
  "script": "module.js"
}
  • imagery: teselas de imágenes corrientes, con {z}, {x} e {y} en la dirección en el orden que el servicio les da.
  • elevation: teselas de relieve codificadas en PNG Terrarium (altura = R × 256 + G + B / 256 − 32768 m).
  • models: archivos glTF o GLB, cada uno con su tipo (vehicle, aircraft, building, entity…), su tamaño y su crédito, como en el catálogo de UFO@home.
  • Un id que otro módulo o UFO@home ya da en el mismo lugar se rechaza, para todo el módulo: dé a los suyos un prefijo propio.

Cuando hace falta código#

Un servicio cuyas respuestas tienen una forma propia necesita código: script cita un módulo ES cuya exportación por defecto devuelve implementaciones de las interfaces de src/modules.

// module.js: its default export returns more implementations, at any point.
export default ({ manifestUrl }) => ({
  weather: [{
    id: "acme-weather", name: "ACME weather", credit: "© ACME", creditUrl: "https://acme.example",
    create: () => ({ /* the methods of WeatherProvider */ })
  }]
})

Los lugares donde un módulo puede añadir: weather, place, timeZone, narrative, assessment, lightPollution, aircraft, upperAir, elevation, imagery, surroundings, decorModels, skyEvents, interpretations, perception.

Un script se ejecuta con todos los derechos de la página. Solo se ejecuta para un módulo que la persona añadió, nunca para uno que cita una grabación.

Simular un tipo de evento del cielo#

Un tipo de evento del cielo (un rayo, un cohete, una bengala…) es lo que una grabación declara en skyEvents.<clave>, dibujado en la escena y editado en una parte propia del grupo Cielo. Su simulation da a la escena un objeto three.js y lo coloca en cada imagen, según el instante y el marco en que está la escena (dónde está el ojo, el aire, el suelo, el viento); nunca dibuja por sí misma. El marco dice también dónde está realmente el testigo, el instante real, la magnitud más débil visible, lo que dejan pasar las nubes y el aire, y le permite iluminar el suelo (lightFrom) y deslumbrar al ojo (glareFrom). Constrúyala con el three que recibe el script, nunca con una copia propia. Los lanzamientos, los haces y los bólidos de UFO@home están escritos así, en src/modules/sky-events.

// A kind of event of the sky: stated in recordings under skyEvents.ballLightning.
export default ({ three }) => ({
  skyEvents: [{
    id: "ballLightning", name: "Ball lightning", credit: "© ACME", creditUrl: "https://acme.example",
    create: () => ({
      key: "ballLightning",
      title: { en: "Ball lightning", fr: "Foudre en boule" },
      simulation: async () => () => {
        const object = new three.Group()
        return {
          object,
          drawnCount: 0,
          // Places and lights the events at t (ms), from frame.eye; draws nothing itself.
          update(events, t, frame) { /* … */ },
          dispose() { object.removeFromParent() }
        }
      },
      // Optional: the part of the Sky group that edits them.
      editor: async () => (container, host, language) => ({ sync() {}, refresh() {}, setTime(t) {}, async setLanguage(l) {} })
    })
  }]
})

Un tipo de interpretación#

Una lectura de un relato que declaran unos pocos parámetros, calculada en cuerpos cuando se muestra (farolillos soltados desde un jardín, bengalas señuelo que lanzó un avión): declarada en interpretation.<clave>, dada a interpretations con una key, un title, bodiesOf(item) que devuelve los cuerpos que es, y un editor opcional. No es un hecho del cielo: es lo que alguien afirma que el relato vio.

Añadir uno en el editor#

En el grupo Archivos, el elemento Módulos: escriba la dirección del manifiesto y pulse Añadir. Sus módulos se guardan en este navegador, pueden desactivarse o quitarse, y guardarse en un archivo (Guardar mis módulos) que los carga en otro lugar (Cargar módulos).

Una grabación que lo necesita#

Una grabación que dibuja un modelo de un módulo lo cita, para que quien la abra vea lo mismo: el editor escribe su dirección en el archivo en cuanto se usa uno de sus modelos, relativa a la grabación cuando ambos están en el mismo sitio, y Citado por esta grabación la desmarca. Un lector que no añadió el módulo recibe lo que su manifiesto declara, sin su script.

{
  "modules": ["https://acme.example/ufo/ufoathome-module.json"]
}

En el propio UFO@home#

Una implementación también puede unirse a UFO@home: cada tipo tiene su carpeta en src/modules, cuyo README dice qué escribir y dónde registrarlo. Una pull request es bienvenida.