## Inspiration
**Augmented Perception**
Remembering the past; augmented perception is a project by Janus developer bai in which he crawled and visualized the web of JanusXR virtual worlds people created and linked together

**Silk Road**
Thinking about what history can teach us about how to connect disparate virtual worlds together.


However,
**Night Sky**
In retrospect I think I was too heads down thinking about how to solve the metavese alignment problem.
When I added this night sky shader to The Street world in Webaverse I was awestruck by the beauty on my screen. Even if the skysphere was fictional, it dawned on me how looking out into the cyberspace cosmos made me feel like I was part of something bigger.
> what if the stars were distant virtual worlds? and when you look up you see constellations that visualize the links / portals connecting between some of them? [tweet](https://twitter.com/dankvr/status/1600026115409444864)

>
> Ancient civilizations found inspiration in the stars and constellations in the night sky. They saw them as more than just celestial bodies; they saw stories, myths, and divine beings in the heavens. The stars guided navigation, marked the passage of time, and influenced agricultural activities. They became a part of cultural identity, passed down through generations, and played a role in shaping religious beliefs and rituals.
---
## Gathering Data
### Hyperfy
- https://github.com/madjin/hyperfy-archive
This script formats the raw JSON into just what we need by display the URLs for all `hyperfy_portals`. Keep in mind though that traversal can happen from all sorts of other objects, such as images / zones / models. I think for now, `hyperfy_portals` has an intentional and easy to understand context better for literacy when explaining the project to others.
```python!
import json
import sys
if len(sys.argv) != 2:
print("Usage: python parse_json.py <filename>")
sys.exit(1)
filename = sys.argv[1]
with open(filename, "r") as file:
data = json.load(file)
output = []
for item in data:
item_data = {
"id": item["id"],
"title": item["title"],
"description": item["description"],
"image": item["image"],
"slug": item["slug"]
}
entities = json.loads(item["entities"])
portals = []
for entity in entities:
if entity["id"] == "hyperfy-portal":
if "state" in entity and "$fields" in entity["state"] and "url" in entity["state"]["$fields"]:
url = entity["state"]["$fields"]["url"]
portals.append({
"url": url
})
if portals:
item_data["hyperfy_portals"] = portals
output.append(item_data)
# Print the output as a JSON string
print(json.dumps(output, indent=2))
```


## Voxels
## Decentraland
---
## Libraries
- https://github.com/vasturiano/3d-force-graph
- https://github.com/vasturiano/3d-force-graph-vr

```bash!
#!/bin/bash
mkdir -p circle
for file in *.png; do
convert "${file}" \( +clone -threshold -1 -negate -fill white -draw "circle $(identify -format %w "${file}" | awk '{print $1/2}'), $(identify -format %h "${file}" | awk '{print $1/2}') $(identify -format %w "${file}" | awk '{print $1/2}'), 0" \) \
-alpha Off -compose copy_opacity -composite "circle/${file}"
done
```
**img-nodes example**
```html!
<!DOCTYPE html>
<html>
<head>
<style>
body, html {
height: 100%;
width: 100%;
margin: 0;
overflow: hidden;
}
#3d-graph {
height: 100%;
width: 100%;
}
</style>
<script src="//unpkg.com/three"></script>
<script src="//unpkg.com/3d-force-graph"></script>
</head>
<body>
<div id="3d-graph"></div>
<script type="importmap">{ "imports": { "three": "https://unpkg.com/three/build/three.module.js" }}</script>
<script type="module">
const ORIGIN = 'https://hyperfy.io';
function urlToAbsolute(url) {
if (!url) return url;
if (url.startsWith('http')) {
// Already an absolute URL
return url;
}
if (url.startsWith('/')) {
// Relative URL starting with "/"
return ORIGIN + url;
}
// Assuming the URL is a slug or path
return ORIGIN + '/' + url;
}
// Load JSON data from file
fetch('data3.json')
.then(response => response.json())
.then(data => {
const nodes = data.map(item => {
const imageName = item.image ? item.image.split('/').pop() : '';
const img = `imgs/circle/${imageName || 'placeholder.png'}`;
return {
id: item.id,
img: img,
title: item.title,
slug: item.slug,
hyperfy_portals: item.hyperfy_portals || []
};
});
const links = [];
nodes.forEach(node => {
node.hyperfy_portals.forEach(portal => {
if (typeof portal.url === 'string') {
const targetUrl = urlToAbsolute(portal.url);
const targetNode = nodes.find(n => n.hyperfy_portals.some(p => urlToAbsolute(p.url) === targetUrl));
if (targetNode) {
links.push({
source: node.id,
target: targetNode.id
});
}
}
});
});
const gData = {
nodes,
links
};
const Graph = ForceGraph3D({ controlType: 'fly' })
(document.getElementById('3d-graph'))
.nodeThreeObject(({ img }) => {
const imgTexture = new THREE.TextureLoader().load(img);
imgTexture.colorSpace = THREE.SRGBColorSpace;
const material = new THREE.SpriteMaterial({ map: imgTexture });
const sprite = new THREE.Sprite(material);
sprite.scale.set(12, 12);
return sprite;
})
.nodeLabel(({ title, slug }) => `Name: ${title || 'N/A'} Slug: ${slug}`)
.onNodeHover(node => {
if (!node) {
document.body.style.cursor = 'default';
} else {
document.body.style.cursor = 'pointer';
}
})
.linkWidth(1) // Adjust the line thickness here
.graphData(gData);
const bloomPass = new UnrealBloomPass();
bloomPass.strength = 1.2;
bloomPass.radius = 1;
bloomPass.threshold = 0.1;
Graph.postProcessingComposer().addPass(bloomPass);
})
.catch(error => {
console.error('Error loading data:', error);
});
</script>
</body>
</html>
```
---