diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/graph.js | 33 | ||||
| -rw-r--r-- | src/views/App.js | 46 | ||||
| -rw-r--r-- | src/views/Detail.js | 1 |
3 files changed, 69 insertions, 11 deletions
diff --git a/src/graph.js b/src/graph.js index 0b2917c..a210f23 100644 --- a/src/graph.js +++ b/src/graph.js @@ -5,7 +5,7 @@ import { union } from "./utils/set_utils.js"; const IMG_SCALE = 20; -export default function buildGraph(db, handlers) { +export default function buildGraph({ db, objects, handlers }) { const linkable = {}; const groups = {}; const data = { nodes: [], links: [] }; @@ -56,7 +56,6 @@ export default function buildGraph(db, handlers) { /** * find common links */ - data.links.forEach((link) => { const a = data.nodes[link.source]; const b = data.nodes[link.target]; @@ -79,14 +78,30 @@ export default function buildGraph(db, handlers) { .showNavInfo(false) .nodeLabel((node) => node.title) .nodeThreeObject((node) => { - let sprite; - if (node.data.thumbnail?.uri) { - const imgTexture = new THREE.TextureLoader().load( - node.data.thumbnail.uri - ); + let sprite, material, texture, video; + if (node.data.object) { + const object = node.data.object; + var box = new THREE.Box3().setFromObject(object); + var center = new THREE.Vector3(); + box.getCenter(center); + object.position.sub(center); + object.scale.set(100, 100, 100); + return object; + } else if (node.data.thumbnail?.uri) { + if (node.data.thumbnail.type === "video") { + video = document.createElement("video"); + video.src = node.data.thumbnail.uri; + video.muted = true; + video.loop = true; + video.autoplay = true; + video.play(); + texture = new THREE.VideoTexture(video); + } else { + texture = new THREE.TextureLoader().load(node.data.thumbnail.uri); + } // console.log(imgTexture); const aspect = node.data.thumbnail.width / node.data.thumbnail.height; - const material = new THREE.SpriteMaterial({ map: imgTexture }); + material = new THREE.SpriteMaterial({ map: texture }); sprite = new THREE.Sprite(material); sprite.scale.set(IMG_SCALE, IMG_SCALE / aspect); return sprite; @@ -113,7 +128,7 @@ export default function buildGraph(db, handlers) { { x: 0, y: 0, z: 0 }, 0 ); - setTimeout(() => zoomOut(1000)); + setTimeout(() => zoomOut(1000), 1000); }; const zoomOut = (duration = 1000) => { diff --git a/src/views/App.js b/src/views/App.js index b435047..6734c21 100644 --- a/src/views/App.js +++ b/src/views/App.js @@ -3,6 +3,8 @@ */ import React, { useState, useEffect, useCallback } from "react"; +import * as THREE from "three"; +import { MTLLoader, OBJLoader } from "@hbis/three-obj-mtl-loader"; import Detail from "./Detail.js"; import Legend from "./Legend.js"; @@ -18,10 +20,14 @@ export default function App() { /** Load the database */ useEffect(async () => { const newDb = await loadDB(); + await loadObjects(newDb); setDb(newDb); setGraph( - buildGraph(newDb, { - click: handleClick, + buildGraph({ + db: newDb, + handlers: { + click: handleClick, + }, }) ); }, []); @@ -64,3 +70,39 @@ async function loadDB() { const request = await fetch("/assets/db.json"); return await request.json(); } + +async function loadObjects(db) { + await Promise.all( + db.page.reduce((promises, item) => { + if (item.threeObject) { + promises.push(loadObject(item)); + } + return promises; + }, []) + ); +} + +function loadObject(item) { + return new Promise((resolve) => { + let { path, file } = item.threeObject; + path = "assets/" + path; + const manager = new THREE.LoadingManager(); + manager.setURLModifier((url) => { + if (!url.match("/")) { + url = path + url; + } + return url; + }); + const mtlLoader = new MTLLoader(manager); + const objLoader = new OBJLoader(manager); + mtlLoader.setMaterialOptions({ side: THREE.DoubleSide }); + mtlLoader.load(file.replace(".obj", ".mtl"), (materials) => { + materials.preload(); + objLoader.setMaterials(materials); + objLoader.load(file, (object) => { + item.object = object; + resolve(); + }); + }); + }); +} diff --git a/src/views/Detail.js b/src/views/Detail.js index 9ac3e57..ff6a6a5 100644 --- a/src/views/Detail.js +++ b/src/views/Detail.js @@ -45,6 +45,7 @@ export default function Detail({ node, visible, onClose }) { <Vimeo video={data.images[0].uri.replace("player.", "")} autoplay + loop /> </div> ) |
