[gliffy]-spawn

dhamdham
{ "type": "updateSimState", "args": { "key": "main", "mimeType": "text/html", "value": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Gliffy - 3D Character Viewer</title>\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/GLTFLoader.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/DRACOLoader.js\"></script>\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/tween.js/18.6.4/tween.umd.min.js\"></script>\n <style>\n body {\n margin: 0;\n width: 512px;\n height: 512px;\n }\n </style>\n</head>\n<body>\n <div id=\"container\"></div>\n <div id=\"loading\">Loading Gliffy...</div>\n\n <script>\n const scene = new THREE.Scene();\n scene.background = new THREE.Color(0x222222);\n \n const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);\n camera.position.z = 5;\n \n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(512, 512);\n renderer.setPixelRatio(window.devicePixelRatio);\n renderer.outputEncoding = THREE.sRGBEncoding;\n document.getElementById('container').appendChild(renderer.domElement);\n \n const ambientLight = new THREE.AmbientLight(0xffffff, 1.5);\n scene.add(ambientLight);\n \n const directionalLight = new THREE.DirectionalLight(0xffffff, 2);\n directionalLight.position.set(1, 1, 1);\n scene.add(directionalLight);\n\n const backLight = new THREE.DirectionalLight(0x6441a5, 1);\n backLight.position.set(-1, 0.5, -1);\n scene.add(backLight);\n \n const controls = new THREE.OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n controls.minDistance = 3;\n controls.maxDistance = 10;\n \n const morphMeshes = [];\n \n let currentExpressionState = { 1: 0, 2: 0, 3: 0 };\n \n const expressionNames = {\n 'normal': 'Normal',\n 'squint': 'Squint',\n 'sad': 'Sad',\n 'custom': 'Custom'\n };\n \n const loader = new THREE.GLTFLoader();\n \n const dracoLoader = new THREE.DRACOLoader();\n dracoLoader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/');\n loader.setDRACOLoader(dracoLoader);\n \n loader.load(\n 'https://glifxyz--glif-eternum-web-server.modal.run/gliffy/glb',\n function (gltf) {\n document.getElementById('loading').style.display = 'none';\n \n const model = gltf.scene;\n scene.add(model);\n \n const box = new THREE.Box3().setFromObject(model);\n const center = box.getCenter(new THREE.Vector3());\n const size = box.getSize(new THREE.Vector3());\n \n model.position.x = -center.x;\n model.position.y = -center.y;\n model.position.z = -center.z;\n \n const maxDim = Math.max(size.x, size.y, size.z);\n camera.position.z = maxDim * 2;\n camera.far = maxDim * 10;\n camera.updateProjectionMatrix();\n \n model.traverse((node) => {\n if (node.isMesh && node.morphTargetInfluences && node.morphTargetInfluences.length > 0) {\n morphMeshes.push(node); \n for (let i = 0; i < node.morphTargetInfluences.length; i++) {\n node.morphTargetInfluences[i] = 0;\n }\n }\n });\n \n startExpressionPolling();\n \n addIdleAnimation(model);\n },\n function (xhr) {\n const loadingPercentage = Math.floor((xhr.loaded / xhr.total) * 100);\n document.getElementById('loading').textContent = 'Loading Gliffy... ' + loadingPercentage + '%';\n },\n function (error) {\n console.error('Error loading model:', error);\n document.getElementById('loading').textContent = 'Error loading model. Please try again.';\n }\n );\n \n function startExpressionPolling() {\n fetchExpressionState();\n \n setInterval(fetchExpressionState, 2000);\n }\n \n function fetchExpressionState() {\n fetch('https://glifxyz--glif-eternum-web-server.modal.run/gliffy/expression')\n .then(response => response.json())\n .then(data => {\n if (JSON.stringify(data) !== JSON.stringify(currentExpressionState)) {\n currentExpressionState = data;\n \n applyExpressionState(data);\n \n updateStatusDisplay(data);\n }\n })\n .catch(error => {\n console.error('Error fetching expression state:', error);\n });\n }\n \n function updateStatusDisplay(expressionState) {\n let expressionName = 'Custom';\n \n if (expressionState[1] === 0 && expressionState[2] === 0 && expressionState[3] === 0) {\n expressionName = 'Normal';\n } else if (expressionState[1] === 1 && expressionState[2] === 0 && expressionState[3] === 0) {\n expressionName = 'Squint';\n } else if (expressionState[1] === 0 && expressionState[2] === 1 && expressionState[3] === 0) {\n expressionName = 'Sad';\n }\n \n document.getElementById('status').textContent = 'Expression: ' + expressionName;\n }\n \n function applyExpressionState(expressionState) {\n const targetState = {};\n for (const [key, value] of Object.entries(expressionState)) {\n targetState[parseInt(key) - 1] = value;\n }\n \n morphMeshes.forEach(mesh => {\n const currentValues = {};\n for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {\n currentValues[i] = mesh.morphTargetInfluences[i];\n }\n \n new TWEEN.Tween(currentValues)\n .easing(TWEEN.Easing.Quadratic.InOut)\n .onUpdate(() => {\n for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {\n if (i in targetState) {\n mesh.morphTargetInfluences[i] = currentValues[i];\n }\n }\n })\n .start();\n });\n }\n \n function addIdleAnimation(model) {\n const initialY = model.position.y;\n \n new TWEEN.Tween({ y: initialY })\n .to({ y: initialY + 0.1 }, 2000)\n .easing(TWEEN.Easing.Sinusoidal.InOut)\n .repeat(Infinity)\n .yoyo(true)\n .onUpdate((obj) => {\n model.position.y = obj.y;\n })\n .start();\n \n const initialRotation = model.rotation.y;\n \n new TWEEN.Tween({ rotation: initialRotation })\n .to({ rotation: initialRotation + 0.1 }, 3000)\n .easing(TWEEN.Easing.Sinusoidal.InOut)\n .repeat(Infinity)\n .yoyo(true)\n .onUpdate((obj) => {\n model.rotation.y = obj.rotation;\n })\n .start();\n }\n \n window.addEventListener('resize', () => {\n camera.aspect = window.innerWidth / window.innerHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(window.innerWidth, window.innerHeight);\n });\n \n function animate(time) {\n requestAnimationFrame(animate);\n TWEEN.update(time);\n controls.update();\n renderer.render(scene, camera);\n }\n \n animate();\n </script>\n</body>\n</html>" } }
{ "type": "updateSimState", "args": { "key": "main", "mimeType": "text/plain", "value": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Gliffy - 3D Character Viewer</title>\n <!-- Three.js CDN scripts -->\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/GLTFLoader.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/DRACOLoader.js\"></script>\n <!-- Add TWEEN.js for smooth animations -->\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/tween.js/18.6.4/tween.umd.min.js\"></script>\n</head>\n<body>\n <div id=\"container\"></div>\n <div id=\"loading\">Loading Gliffy...</div>\n <div id=\"status\">Expression: Normal</div>\n\n <script>\n const scene = new THREE.Scene();\n scene.background = new THREE.Color(0x222222);\n \n const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);\n camera.position.z = 5;\n \n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(window.innerWidth, window.innerHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n renderer.outputEncoding = THREE.sRGBEncoding;\n document.getElementById('container').appendChild(renderer.domElement);\n \n const ambientLight = new THREE.AmbientLight(0xffffff, 1.5);\n scene.add(ambientLight);\n \n const directionalLight = new THREE.DirectionalLight(0xffffff, 2);\n directionalLight.position.set(1, 1, 1);\n scene.add(directionalLight);\n\n const backLight = new THREE.DirectionalLight(0x6441a5, 1);\n backLight.position.set(-1, 0.5, -1);\n scene.add(backLight);\n \n const controls = new THREE.OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n controls.minDistance = 3;\n controls.maxDistance = 10;\n \n const morphMeshes = [];\n \n let currentExpressionState = { 1: 0, 2: 0, 3: 0 };\n \n const expressionNames = {\n 'normal': 'Normal',\n 'squint': 'Squint',\n 'sad': 'Sad',\n 'custom': 'Custom'\n };\n \n const loader = new THREE.GLTFLoader();\n \n const dracoLoader = new THREE.DRACOLoader();\n dracoLoader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/');\n loader.setDRACOLoader(dracoLoader);\n \n loader.load(\n 'https://glifxyz--glif-eternum-web-server.modal.run/gliffy/glb',\n function (gltf) {\n document.getElementById('loading').style.display = 'none';\n \n const model = gltf.scene;\n scene.add(model);\n \n const box = new THREE.Box3().setFromObject(model);\n const center = box.getCenter(new THREE.Vector3());\n const size = box.getSize(new THREE.Vector3());\n \n model.position.x = -center.x;\n model.position.y = -center.y;\n model.position.z = -center.z;\n \n const maxDim = Math.max(size.x, size.y, size.z);\n camera.position.z = maxDim * 2;\n camera.far = maxDim * 10;\n camera.updateProjectionMatrix();\n \n model.traverse((node) => {\n if (node.isMesh && node.morphTargetInfluences && node.morphTargetInfluences.length > 0) {\n morphMeshes.push(node);\n console.log('Found mesh with ' + node.morphTargetInfluences.length + ' morph targets');\n console.log('Morph target names:', node.morphTargetDictionary);\n \n for (let i = 0; i < node.morphTargetInfluences.length; i++) {\n node.morphTargetInfluences[i] = 0;\n }\n }\n });\n \n startExpressionPolling();\n \n addIdleAnimation(model);\n },\n function (xhr) {\n const loadingPercentage = Math.floor((xhr.loaded / xhr.total) * 100);\n document.getElementById('loading').textContent = 'Loading Gliffy... ' + loadingPercentage + '%';\n },\n function (error) {\n console.error('Error loading model:', error);\n document.getElementById('loading').textContent = 'Error loading model. Please try again.';\n }\n );\n \n function startExpressionPolling() {\n fetchExpressionState();\n \n setInterval(fetchExpressionState, 2000);\n }\n \n function fetchExpressionState() {\n fetch('https://glifxyz--glif-eternum-web-server.modal.run/gliffy/expression')\n .then(response => response.json())\n .then(data => {\n if (JSON.stringify(data) !== JSON.stringify(currentExpressionState)) {\n currentExpressionState = data;\n \n applyExpressionState(data);\n \n updateStatusDisplay(data);\n }\n })\n .catch(error => {\n console.error('Error fetching expression state:', error);\n });\n }\n \n function updateStatusDisplay(expressionState) {\n let expressionName = 'Custom';\n \n if (expressionState[1] === 0 && expressionState[2] === 0 && expressionState[3] === 0) {\n expressionName = 'Normal';\n } else if (expressionState[1] === 1 && expressionState[2] === 0 && expressionState[3] === 0) {\n expressionName = 'Squint';\n } else if (expressionState[1] === 0 && expressionState[2] === 1 && expressionState[3] === 0) {\n expressionName = 'Sad';\n }\n \n document.getElementById('status').textContent = 'Expression: ' + expressionName;\n }\n \n function applyExpressionState(expressionState) {\n const targetState = {};\n for (const [key, value] of Object.entries(expressionState)) {\n targetState[parseInt(key) - 1] = value;\n }\n \n morphMeshes.forEach(mesh => {\n const currentValues = {};\n for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {\n currentValues[i] = mesh.morphTargetInfluences[i];\n }\n \n new TWEEN.Tween(currentValues)\n .easing(TWEEN.Easing.Quadratic.InOut)\n .onUpdate(() => {\n for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {\n if (i in targetState) {\n mesh.morphTargetInfluences[i] = currentValues[i];\n }\n }\n })\n .start();\n });\n }\n \n function addIdleAnimation(model) {\n const initialY = model.position.y;\n \n new TWEEN.Tween({ y: initialY })\n .to({ y: initialY + 0.1 }, 2000)\n .easing(TWEEN.Easing.Sinusoidal.InOut)\n .repeat(Infinity)\n .yoyo(true)\n .onUpdate((obj) => {\n model.position.y = obj.y;\n })\n .start();\n \n const initialRotation = model.rotation.y;\n \n new TWEEN.Tween({ rotation: initialRotation })\n .to({ rotation: initialRotation + 0.1 }, 3000)\n .easing(TWEEN.Easing.Sinusoidal.InOut)\n .repeat(Infinity)\n .yoyo(true)\n .onUpdate((obj) => {\n model.rotation.y = obj.rotation;\n })\n .start();\n }\n \n window.addEventListener('resize', () => {\n camera.aspect = window.innerWidth / window.innerHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(window.innerWidth, window.innerHeight);\n });\n \n function animate(time) {\n requestAnimationFrame(animate);\n TWEEN.update(time);\n controls.update();\n renderer.render(scene, camera);\n }\n \n animate();\n </script>\n</body>\n</html>" } }

2 Runs

3/28/2025, 3:32:19 PM

dhamdham4 mo. ago
{ "type": "updateSimState", "args": { "key": "main", "mimeType": "text/html", "value": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Gliffy - 3D Character Viewer</title>\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/GLTFLoader.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/DRACOLoader.js\"></script>\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/tween.js/18.6.4/tween.umd.min.js\"></script>\n <style>\n body {\n margin: 0;\n width: 512px;\n height: 512px;\n }\n </style>\n</head>\n<body>\n <div id=\"container\"></div>\n <div id=\"loading\">Loading Gliffy...</div>\n\n <script>\n const scene = new THREE.Scene();\n scene.background = new THREE.Color(0x222222);\n \n const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);\n camera.position.z = 5;\n \n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(512, 512);\n renderer.setPixelRatio(window.devicePixelRatio);\n renderer.outputEncoding = THREE.sRGBEncoding;\n document.getElementById('container').appendChild(renderer.domElement);\n \n const ambientLight = new THREE.AmbientLight(0xffffff, 1.5);\n scene.add(ambientLight);\n \n const directionalLight = new THREE.DirectionalLight(0xffffff, 2);\n directionalLight.position.set(1, 1, 1);\n scene.add(directionalLight);\n\n const backLight = new THREE.DirectionalLight(0x6441a5, 1);\n backLight.position.set(-1, 0.5, -1);\n scene.add(backLight);\n \n const controls = new THREE.OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n controls.minDistance = 3;\n controls.maxDistance = 10;\n \n const morphMeshes = [];\n \n let currentExpressionState = { 1: 0, 2: 0, 3: 0 };\n \n const expressionNames = {\n 'normal': 'Normal',\n 'squint': 'Squint',\n 'sad': 'Sad',\n 'custom': 'Custom'\n };\n \n const loader = new THREE.GLTFLoader();\n \n const dracoLoader = new THREE.DRACOLoader();\n dracoLoader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/');\n loader.setDRACOLoader(dracoLoader);\n \n loader.load(\n 'https://glifxyz--glif-eternum-web-server.modal.run/gliffy/glb',\n function (gltf) {\n document.getElementById('loading').style.display = 'none';\n \n const model = gltf.scene;\n scene.add(model);\n \n const box = new THREE.Box3().setFromObject(model);\n const center = box.getCenter(new THREE.Vector3());\n const size = box.getSize(new THREE.Vector3());\n \n model.position.x = -center.x;\n model.position.y = -center.y;\n model.position.z = -center.z;\n \n const maxDim = Math.max(size.x, size.y, size.z);\n camera.position.z = maxDim * 2;\n camera.far = maxDim * 10;\n camera.updateProjectionMatrix();\n \n model.traverse((node) => {\n if (node.isMesh && node.morphTargetInfluences && node.morphTargetInfluences.length > 0) {\n morphMeshes.push(node); \n for (let i = 0; i < node.morphTargetInfluences.length; i++) {\n node.morphTargetInfluences[i] = 0;\n }\n }\n });\n \n startExpressionPolling();\n \n addIdleAnimation(model);\n },\n function (xhr) {\n const loadingPercentage = Math.floor((xhr.loaded / xhr.total) * 100);\n document.getElementById('loading').textContent = 'Loading Gliffy... ' + loadingPercentage + '%';\n },\n function (error) {\n console.error('Error loading model:', error);\n document.getElementById('loading').textContent = 'Error loading model. Please try again.';\n }\n );\n \n function startExpressionPolling() {\n fetchExpressionState();\n \n setInterval(fetchExpressionState, 2000);\n }\n \n function fetchExpressionState() {\n fetch('https://glifxyz--glif-eternum-web-server.modal.run/gliffy/expression')\n .then(response => response.json())\n .then(data => {\n if (JSON.stringify(data) !== JSON.stringify(currentExpressionState)) {\n currentExpressionState = data;\n \n applyExpressionState(data);\n \n updateStatusDisplay(data);\n }\n })\n .catch(error => {\n console.error('Error fetching expression state:', error);\n });\n }\n \n function updateStatusDisplay(expressionState) {\n let expressionName = 'Custom';\n \n if (expressionState[1] === 0 && expressionState[2] === 0 && expressionState[3] === 0) {\n expressionName = 'Normal';\n } else if (expressionState[1] === 1 && expressionState[2] === 0 && expressionState[3] === 0) {\n expressionName = 'Squint';\n } else if (expressionState[1] === 0 && expressionState[2] === 1 && expressionState[3] === 0) {\n expressionName = 'Sad';\n }\n \n document.getElementById('status').textContent = 'Expression: ' + expressionName;\n }\n \n function applyExpressionState(expressionState) {\n const targetState = {};\n for (const [key, value] of Object.entries(expressionState)) {\n targetState[parseInt(key) - 1] = value;\n }\n \n morphMeshes.forEach(mesh => {\n const currentValues = {};\n for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {\n currentValues[i] = mesh.morphTargetInfluences[i];\n }\n \n new TWEEN.Tween(currentValues)\n .easing(TWEEN.Easing.Quadratic.InOut)\n .onUpdate(() => {\n for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {\n if (i in targetState) {\n mesh.morphTargetInfluences[i] = currentValues[i];\n }\n }\n })\n .start();\n });\n }\n \n function addIdleAnimation(model) {\n const initialY = model.position.y;\n \n new TWEEN.Tween({ y: initialY })\n .to({ y: initialY + 0.1 }, 2000)\n .easing(TWEEN.Easing.Sinusoidal.InOut)\n .repeat(Infinity)\n .yoyo(true)\n .onUpdate((obj) => {\n model.position.y = obj.y;\n })\n .start();\n \n const initialRotation = model.rotation.y;\n \n new TWEEN.Tween({ rotation: initialRotation })\n .to({ rotation: initialRotation + 0.1 }, 3000)\n .easing(TWEEN.Easing.Sinusoidal.InOut)\n .repeat(Infinity)\n .yoyo(true)\n .onUpdate((obj) => {\n model.rotation.y = obj.rotation;\n })\n .start();\n }\n \n window.addEventListener('resize', () => {\n camera.aspect = window.innerWidth / window.innerHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(window.innerWidth, window.innerHeight);\n });\n \n function animate(time) {\n requestAnimationFrame(animate);\n TWEEN.update(time);\n controls.update();\n renderer.render(scene, camera);\n }\n \n animate();\n </script>\n</body>\n</html>" } }
dhamdham4 mo. ago
{ "type": "updateSimState", "args": { "key": "main", "mimeType": "text/plain", "value": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Gliffy - 3D Character Viewer</title>\n <!-- Three.js CDN scripts -->\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/GLTFLoader.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/DRACOLoader.js\"></script>\n <!-- Add TWEEN.js for smooth animations -->\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/tween.js/18.6.4/tween.umd.min.js\"></script>\n</head>\n<body>\n <div id=\"container\"></div>\n <div id=\"loading\">Loading Gliffy...</div>\n <div id=\"status\">Expression: Normal</div>\n\n <script>\n const scene = new THREE.Scene();\n scene.background = new THREE.Color(0x222222);\n \n const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);\n camera.position.z = 5;\n \n const renderer = new THREE.WebGLRenderer({ antialias: true });\n renderer.setSize(window.innerWidth, window.innerHeight);\n renderer.setPixelRatio(window.devicePixelRatio);\n renderer.outputEncoding = THREE.sRGBEncoding;\n document.getElementById('container').appendChild(renderer.domElement);\n \n const ambientLight = new THREE.AmbientLight(0xffffff, 1.5);\n scene.add(ambientLight);\n \n const directionalLight = new THREE.DirectionalLight(0xffffff, 2);\n directionalLight.position.set(1, 1, 1);\n scene.add(directionalLight);\n\n const backLight = new THREE.DirectionalLight(0x6441a5, 1);\n backLight.position.set(-1, 0.5, -1);\n scene.add(backLight);\n \n const controls = new THREE.OrbitControls(camera, renderer.domElement);\n controls.enableDamping = true;\n controls.dampingFactor = 0.05;\n controls.minDistance = 3;\n controls.maxDistance = 10;\n \n const morphMeshes = [];\n \n let currentExpressionState = { 1: 0, 2: 0, 3: 0 };\n \n const expressionNames = {\n 'normal': 'Normal',\n 'squint': 'Squint',\n 'sad': 'Sad',\n 'custom': 'Custom'\n };\n \n const loader = new THREE.GLTFLoader();\n \n const dracoLoader = new THREE.DRACOLoader();\n dracoLoader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/');\n loader.setDRACOLoader(dracoLoader);\n \n loader.load(\n 'https://glifxyz--glif-eternum-web-server.modal.run/gliffy/glb',\n function (gltf) {\n document.getElementById('loading').style.display = 'none';\n \n const model = gltf.scene;\n scene.add(model);\n \n const box = new THREE.Box3().setFromObject(model);\n const center = box.getCenter(new THREE.Vector3());\n const size = box.getSize(new THREE.Vector3());\n \n model.position.x = -center.x;\n model.position.y = -center.y;\n model.position.z = -center.z;\n \n const maxDim = Math.max(size.x, size.y, size.z);\n camera.position.z = maxDim * 2;\n camera.far = maxDim * 10;\n camera.updateProjectionMatrix();\n \n model.traverse((node) => {\n if (node.isMesh && node.morphTargetInfluences && node.morphTargetInfluences.length > 0) {\n morphMeshes.push(node);\n console.log('Found mesh with ' + node.morphTargetInfluences.length + ' morph targets');\n console.log('Morph target names:', node.morphTargetDictionary);\n \n for (let i = 0; i < node.morphTargetInfluences.length; i++) {\n node.morphTargetInfluences[i] = 0;\n }\n }\n });\n \n startExpressionPolling();\n \n addIdleAnimation(model);\n },\n function (xhr) {\n const loadingPercentage = Math.floor((xhr.loaded / xhr.total) * 100);\n document.getElementById('loading').textContent = 'Loading Gliffy... ' + loadingPercentage + '%';\n },\n function (error) {\n console.error('Error loading model:', error);\n document.getElementById('loading').textContent = 'Error loading model. Please try again.';\n }\n );\n \n function startExpressionPolling() {\n fetchExpressionState();\n \n setInterval(fetchExpressionState, 2000);\n }\n \n function fetchExpressionState() {\n fetch('https://glifxyz--glif-eternum-web-server.modal.run/gliffy/expression')\n .then(response => response.json())\n .then(data => {\n if (JSON.stringify(data) !== JSON.stringify(currentExpressionState)) {\n currentExpressionState = data;\n \n applyExpressionState(data);\n \n updateStatusDisplay(data);\n }\n })\n .catch(error => {\n console.error('Error fetching expression state:', error);\n });\n }\n \n function updateStatusDisplay(expressionState) {\n let expressionName = 'Custom';\n \n if (expressionState[1] === 0 && expressionState[2] === 0 && expressionState[3] === 0) {\n expressionName = 'Normal';\n } else if (expressionState[1] === 1 && expressionState[2] === 0 && expressionState[3] === 0) {\n expressionName = 'Squint';\n } else if (expressionState[1] === 0 && expressionState[2] === 1 && expressionState[3] === 0) {\n expressionName = 'Sad';\n }\n \n document.getElementById('status').textContent = 'Expression: ' + expressionName;\n }\n \n function applyExpressionState(expressionState) {\n const targetState = {};\n for (const [key, value] of Object.entries(expressionState)) {\n targetState[parseInt(key) - 1] = value;\n }\n \n morphMeshes.forEach(mesh => {\n const currentValues = {};\n for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {\n currentValues[i] = mesh.morphTargetInfluences[i];\n }\n \n new TWEEN.Tween(currentValues)\n .easing(TWEEN.Easing.Quadratic.InOut)\n .onUpdate(() => {\n for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {\n if (i in targetState) {\n mesh.morphTargetInfluences[i] = currentValues[i];\n }\n }\n })\n .start();\n });\n }\n \n function addIdleAnimation(model) {\n const initialY = model.position.y;\n \n new TWEEN.Tween({ y: initialY })\n .to({ y: initialY + 0.1 }, 2000)\n .easing(TWEEN.Easing.Sinusoidal.InOut)\n .repeat(Infinity)\n .yoyo(true)\n .onUpdate((obj) => {\n model.position.y = obj.y;\n })\n .start();\n \n const initialRotation = model.rotation.y;\n \n new TWEEN.Tween({ rotation: initialRotation })\n .to({ rotation: initialRotation + 0.1 }, 3000)\n .easing(TWEEN.Easing.Sinusoidal.InOut)\n .repeat(Infinity)\n .yoyo(true)\n .onUpdate((obj) => {\n model.rotation.y = obj.rotation;\n })\n .start();\n }\n \n window.addEventListener('resize', () => {\n camera.aspect = window.innerWidth / window.innerHeight;\n camera.updateProjectionMatrix();\n renderer.setSize(window.innerWidth, window.innerHeight);\n });\n \n function animate(time) {\n requestAnimationFrame(animate);\n TWEEN.update(time);\n controls.update();\n renderer.render(scene, camera);\n }\n \n animate();\n </script>\n</body>\n</html>" } }
glif - [gliffy]-spawn by dham