Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ module.exports = {
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'@typescript-eslint/no-explicit-any': 'off',
},
};
59 changes: 59 additions & 0 deletions fixtures/glxf/TableScene.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"asset": {
"version": "2.0",
"experience": true
},
"assets": [
{
"uri": "RedTable.glb"
},
{
"uri": "IridescentDishWithOlives.glb"
},
{
"uri": "StainedGlassLamp.glb"
}
],
"nodes": [
{
"name": "root",
"children": [1, 2, 3, 4]
},
{
"name": "Table",
"asset": 0,
"translation": [0, 0, 0]
},
{
"name": "IridescentDishWithOlives",
"asset": 1,
"translation": [0, 0, -0.2]
},
{
"name": "Lamp",
"asset": 2,
"translation": [0.2, 0, 0.4]
},
{
"camera": 0,
"rotation": [-0.12909476333357384, -0.5350785203344225, -0.08315080323337401, 0.8307294764712628],
"translation": [-1.1538678407669067, 0.3662871718406677, 0.4870622456073761]
}
],
"scene": 0,
"scenes": [
{
"nodes": [0]
}
],
"cameras": [
{
"perspective": {
"yfov": 1,
"zfar": 763,
"znear": 0.07
},
"type": "perspective"
}
]
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"prepare": "npm run build",
"preview": "vite preview"
"preview": "vite preview",
"generate-src": "node scripts/generate-src.js"
},
"devDependencies": {
"@types/node": "^20.10.4",
Expand Down
78 changes: 78 additions & 0 deletions scripts/generate-src.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { readFileSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

/**
* Convert a glTF-style JSON scene to an array of SrcObj objects
* @param {Object} json - The glTF JSON scene
* @param {string} baseUrl - Base URL for assets
* @returns {Array} Array of SrcObj objects
*/
function glxfToSrc(json, baseUrl = '') {
const srcObjects = [];

// Get the root scene
const rootScene = json.scenes[json.scene];
if (!rootScene) return srcObjects;

// Function to process nodes recursively
function processNode(nodeIndex) {
const node = json.nodes[nodeIndex];
if (!node) return;

// If this node has an asset, create a SrcObj
if (node.asset !== undefined && json.assets[node.asset]) {
const asset = json.assets[node.asset];
const srcObj = {
url: baseUrl + asset.uri,
label: node.name,
};

// Add position if translation exists
if (node.translation) {
srcObj.position = [node.translation[0], node.translation[1], node.translation[2]];
}

// Add rotation if it exists (convert from quaternion to Euler if needed)
if (node.rotation) {
// Note: The JSON has quaternion rotation [x, y, z, w]
// You might need to convert this to Euler angles depending on your needs
// For now, we'll store it as-is and let Three.js handle it
srcObj.rotation = [node.rotation[0], node.rotation[1], node.rotation[2]];
}

// Add scale if it exists
if (node.scale) {
srcObj.scale = [node.scale[0], node.scale[1], node.scale[2]];
}

srcObjects.push(srcObj);
}

// Process children recursively
if (node.children) {
node.children.forEach((childIndex) => processNode(childIndex));
}
}

// Process all root nodes
rootScene.nodes.forEach((nodeIndex) => processNode(nodeIndex));

return srcObjects;
}

// Read the TableScene.json file
const sceneJsonPath = resolve(__dirname, '../fixtures/glxf/TableScene.json');
const sceneJson = JSON.parse(readFileSync(sceneJsonPath, 'utf8'));

// Base URL for the assets (adjust as needed)
const baseUrl = 'https://glxf-demo-assets.vercel.app/';

// Convert the scene to SrcObj array
const srcArray = glxfToSrc(sceneJson, baseUrl);

// Output the result
console.log(JSON.stringify(srcArray, null, 2));
35 changes: 23 additions & 12 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useControls } from 'leva';
import { normalizeSrc, ViewerRef, SrcObj, Viewer, ControlPanel } from '../index';
import { Toaster } from '@/components/ui/sonner';
import { toast } from 'sonner';
// @ts-ignore
// @ts-expect-error import DOMPurify from 'dompurify';
import DOMPurify from 'dompurify';
import useStore from './Store';
import { PresetsType } from '@react-three/drei/helpers/environment-assets';
Expand All @@ -13,12 +13,7 @@ function App() {
const viewerRef = useRef<ViewerRef>(null);
const loadedUrlsRef = useRef<string[]>([]);

const {
cameraMode,
environmentMap,
setAmbientLightIntensity,
setEnvironmentMap
} = useStore();
const { cameraMode, environmentMap, setAmbientLightIntensity, setEnvironmentMap } = useStore();

// Configurable app data, includes list of models and scene/UI presets
const config = {
Expand Down Expand Up @@ -75,20 +70,36 @@ function App() {
scale: [1, 1, 1],
},
] as SrcObj[],
'Stanford Bunny':
'https://raw.githubusercontent.com/JulieWinchester/aleph-assets/main/bunny.glb',
// 'Frog (Draco) URL': 'https://aleph-gltf-models.netlify.app/Frog.glb',
'glxf demo': [
{
url: 'https://glxf-demo-assets.vercel.app/RedTable.glb',
label: 'Table',
position: [0, 0, 0],
},
{
url: 'https://glxf-demo-assets.vercel.app/IridescentDishWithOlives.glb',
label: 'IridescentDishWithOlives',
position: [0, 0, -0.2],
},
{
url: 'https://glxf-demo-assets.vercel.app/StainedGlassLamp.glb',
label: 'Lamp',
position: [0.2, 0, 0.4],
},
] as SrcObj[],
'Stanford Bunny': 'https://raw.githubusercontent.com/JulieWinchester/aleph-assets/main/bunny.glb',
// 'Frog (Draco) URL': 'https://aleph-gltf-models.netlify.app/Frog.glb',
},
scene: {
ambientLightIntensity: 0,
environmentMap: 'apartment',
rotation: [0, 0, 0], // Default rotation in radians
}
},
};

// https://github.com/KhronosGroup/glTF-Sample-Assets/blob/main/Models/Models-showcase.md
// https://github.com/google/model-viewer/tree/master/packages/modelviewer.dev/assets
const [{ src }, _setLevaControls] = useControls(() => ({
const [{ src }] = useControls(() => ({
src: {
options: config.srcs,
},
Expand Down
Loading