Skip to content

Instantly share code, notes, and snippets.

@simonw

simonw/glb.md Secret

Created December 13, 2024 18:49
Show Gist options
  • Save simonw/64a33cd6af819674defddb92f5f2e713 to your computer and use it in GitHub Desktop.
Save simonw/64a33cd6af819674defddb92f5f2e713 to your computer and use it in GitHub Desktop.

Displaying GLB 3D Models on Web Pages

human (Dec 12, 2024, 09:01 AM)

options for displaying a glb file on a web page

assistant (Dec 12, 2024, 09:01 AM)

I'll help you explore different options for displaying a GLB (GL Binary) 3D model file on a web page. Here are the main approaches:

  1. Using Three.js:
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();

const loader = new GLTFLoader();
loader.load(
    'path/to/model.glb',
    (gltf) => {
        scene.add(gltf.scene);
    },
    undefined,
    (error) => console.error(error)
);
  1. Using Model-viewer (Google's web component):
<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>

<model-viewer
    src="path/to/model.glb"
    alt="3D model"
    auto-rotate
    camera-controls
    shadow-intensity="1"
></model-viewer>
  1. Using Babylon.js:
import * as BABYLON from 'babylonjs';
import 'babylonjs-loaders';

const canvas = document.getElementById('renderCanvas');
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);

BABYLON.SceneLoader.ImportMesh(
    '',
    'path/to/',
    'model.glb',
    scene,
    (meshes) => {
        // Model loaded successfully
    }
);

Key considerations for choosing an approach:

  • Model-viewer is the simplest to implement but offers less customization
  • Three.js provides the most control and customization but requires more setup
  • Babylon.js offers a good balance of features and ease of use
  • All options support modern browsers with WebGL capability

If you'd like to see a complete implementation of any of these approaches or have specific requirements for your 3D model display, let me know and I can provide more detailed code.

human (Dec 12, 2024, 09:01 AM)

build an artifact I can open a glb file in

assistant (Dec 12, 2024, 09:01 AM)

I'll create a React component that uses model-viewer to display GLB files, as it's the most straightforward approach and has good browser support.

create 3D Model Viewer Component

import React, { useEffect, useState } from 'react';

const ModelViewer = () => {
  const [modelData, setModelData] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    // Load the model-viewer script
    const script = document.createElement('script');
    script.type = 'module';
    script.src = 'https://cdnjs.cloudflare.com/ajax/libs/model-viewer/3.3.0/model-viewer.min.js';
    document.body.appendChild(script);

    return () => {
      document.body.removeChild(script);
    };
  }, []);

  const handleFileUpload = async (event) => {
    const file = event.target.files[0];
    if (!file) return;

    if (!file.name.toLowerCase().endsWith('.glb')) {
      setError('Please upload a GLB file');
      return;
    }

    try {
      // Create a blob URL for the file
      const blobUrl = URL.createObjectURL(file);
      setModelData(blobUrl);
      setError(null);
    } catch (err) {
      setError('Error loading the file');
      console.error('Error:', err);
    }
  };

  return (
    <div className="w-full max-w-4xl mx-auto p-4">
      <div className="mb-4">
        <label className="block text-sm font-medium mb-2">
          Upload GLB File:
          <input
            type="file"
            accept=".glb"
            onChange={handleFileUpload}
            className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
        </label>
      </div>

      {error && (
        <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
          {error}
        </div>
      )}

      {modelData && (
        <div className="w-full h-96 border border-gray-300 rounded-lg overflow-hidden">
          <model-viewer
            src={modelData}
            alt="3D model viewer"
            camera-controls
            auto-rotate
            shadow-intensity="1"
            style={{ width: '100%', height: '100%' }}
          ></model-viewer>
        </div>
      )}
    </div>
  );
};

export default ModelViewer;

I've created a React component that allows you to:

  1. Upload a GLB file through a file input
  2. View the 3D model using Google's model-viewer web component
  3. Interact with the model using camera controls and auto-rotation

The component includes:

  • File validation to ensure only GLB files are uploaded
  • Error handling for invalid files
  • A responsive container that works well on different screen sizes
  • Basic styling using Tailwind CSS classes

To use this component:

  1. Simply upload a GLB file using the file input
  2. The 3D model will be displayed in the viewer below
  3. You can:
    • Rotate the model by dragging
    • Zoom with the scroll wheel
    • Pan by right-clicking and dragging

Would you like me to add any additional features or make any adjustments to the viewer?

human (Dec 12, 2024, 09:02 AM)

don't use react

assistant (Dec 12, 2024, 09:02 AM)

I'll create a simple HTML file that can display GLB files using model-viewer without React.

create 3D Model Viewer

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D Model Viewer</title>
    <script type="module" src="https://cdnjs.cloudflare.com/ajax/libs/model-viewer/3.3.0/model-viewer.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 20px;
            font-family: system-ui, -apple-system, sans-serif;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
        }
        .upload-container {
            margin-bottom: 20px;
        }
        .file-input {
            display: block;
            width: 100%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            margin-top: 8px;
        }
        .viewer-container {
            width: 100%;
            height: 500px;
            border: 1px solid #ccc;
            border-radius: 4px;
            overflow: hidden;
            display: none;
        }
        model-viewer {
            width: 100%;
            height: 100%;
        }
        .error {
            background-color: #fee2e2;
            border: 1px solid #ef4444;
            color: #b91c1c;
            padding: 12px;
            border-radius: 4px;
            margin-bottom: 20px;
            display: none;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="upload-container">
            <label>
                Upload GLB File:
                <input type="file" accept=".glb" class="file-input" id="fileInput">
            </label>
        </div>
        
        <div class="error" id="error"></div>
        
        <div class="viewer-container" id="viewerContainer">
            <model-viewer
                camera-controls
                auto-rotate
                shadow-intensity="1"
                id="modelViewer">
            </model-viewer>
        </div>
    </div>

    <script>
        const fileInput = document.getElementById('fileInput');
        const modelViewer = document.getElementById('modelViewer');
        const viewerContainer = document.getElementById('viewerContainer');
        const errorElement = document.getElementById('error');

        fileInput.addEventListener('change', (event) => {
            const file = event.target.files[0];
            if (!file) return;

            if (!file.name.toLowerCase().endsWith('.glb')) {
                errorElement.textContent = 'Please upload a GLB file';
                errorElement.style.display = 'block';
                viewerContainer.style.display = 'none';
                return;
            }

            try {
                const blobUrl = URL.createObjectURL(file);
                modelViewer.src = blobUrl;
                viewerContainer.style.display = 'block';
                errorElement.style.display = 'none';

                // Clean up the blob URL when the model is loaded
                modelViewer.addEventListener('load', () => {
                    URL.revokeObjectURL(blobUrl);
                }, { once: true });
            } catch (err) {
                errorElement.textContent = 'Error loading the file';
                errorElement.style.display = 'block';
                viewerContainer.style.display = 'none';
                console.error('Error:', err);
            }
        });
    </script>
</body>
</html>

I've created a simple HTML page that allows you to:

  1. Upload a GLB file through a file input
  2. View the 3D model using Google's model-viewer web component
  3. Interact with the model using camera controls and auto-rotation

Features include:

  • File validation to ensure only GLB files are uploaded
  • Error handling for invalid files
  • Automatic cleanup of blob URLs after model loading
  • Responsive design that works on different screen sizes
  • Clean, minimal styling

To use it:

  1. Upload a GLB file using the file input
  2. The 3D model will appear in the viewer below
  3. You can:
    • Rotate the model by dragging
    • Zoom with the scroll wheel
    • Pan by right-clicking and dragging

Would you like me to add any additional features or make any adjustments to the viewer?

human (Dec 12, 2024, 09:03 AM)

rewrite that so that instead of a file input it is hard coded to a URL - use a dummy URL for the moment

assistant (Dec 12, 2024, 09:03 AM)

rewrite 3D Model Viewer with Fixed URL

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D Model Viewer</title>
    <script type="module" src="https://cdnjs.cloudflare.com/ajax/libs/model-viewer/3.3.0/model-viewer.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 20px;
            font-family: system-ui, -apple-system, sans-serif;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
        }
        .viewer-container {
            width: 100%;
            height: 500px;
            border: 1px solid #ccc;
            border-radius: 4px;
            overflow: hidden;
        }
        model-viewer {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="viewer-container">
            <model-viewer
                src="https://example.com/path/to/model.glb"
                camera-controls
                auto-rotate
                shadow-intensity="1">
            </model-viewer>
        </div>
    </div>
</body>
</html>

I've simplified the viewer to use a hardcoded URL instead of file input. Just replace https://example.com/path/to/model.glb with your actual GLB file URL. I've also removed all the file handling logic and error states since they're no longer needed.

The viewer retains all the interaction features:

  • Rotate by dragging
  • Zoom with scroll wheel
  • Pan with right-click drag

Would you like me to make any adjustments to this simpler version?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment