feat: add GLTF transformation and compression support
- Updated package.json to include @gltf-transform/core, @gltf-transform/extensions, @gltf-transform/functions, and draco3dgltf for GLB file processing. - Implemented GLB compression using Draco in the upload model API route. - Adjusted camera keyframes in ScrollScene for improved animation. - Enhanced overlay styles in ScrollOverlays for better visual clarity. - Added original GLB files for Kandoura, Suit, Unitree_G1, and Vest. - Updated existing GLB files for Kandoura, Suit, Unitree_G1, and Vest.
This commit is contained in:
Generated
+2166
-5
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,9 @@
|
|||||||
"test:watch": "vitest"
|
"test:watch": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@gltf-transform/core": "^4.3.0",
|
||||||
|
"@gltf-transform/extensions": "^4.3.0",
|
||||||
|
"@gltf-transform/functions": "^4.3.0",
|
||||||
"@libsql/client": "^0.17.2",
|
"@libsql/client": "^0.17.2",
|
||||||
"@prisma/adapter-libsql": "^7.7.0",
|
"@prisma/adapter-libsql": "^7.7.0",
|
||||||
"@prisma/client": "^7.7.0",
|
"@prisma/client": "^7.7.0",
|
||||||
@@ -22,6 +25,7 @@
|
|||||||
"@stripe/stripe-js": "^9.1.0",
|
"@stripe/stripe-js": "^9.1.0",
|
||||||
"@types/three": "^0.183.1",
|
"@types/three": "^0.183.1",
|
||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
|
"draco3dgltf": "^1.5.7",
|
||||||
"framer-motion": "^12.38.0",
|
"framer-motion": "^12.38.0",
|
||||||
"gsap": "^3.14.2",
|
"gsap": "^3.14.2",
|
||||||
"i18next": "^26.0.3",
|
"i18next": "^26.0.3",
|
||||||
@@ -37,6 +41,7 @@
|
|||||||
"zustand": "^5.0.12"
|
"zustand": "^5.0.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@gltf-transform/cli": "^4.3.0",
|
||||||
"@tailwindcss/postcss": "^4.2.2",
|
"@tailwindcss/postcss": "^4.2.2",
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.2",
|
"@testing-library/react": "^16.3.2",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,8 +1,22 @@
|
|||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { cookies } from 'next/headers';
|
import { cookies } from 'next/headers';
|
||||||
import { jwtVerify } from 'jose';
|
import { jwtVerify } from 'jose';
|
||||||
import { writeFile, mkdir } from 'fs/promises';
|
import { writeFile, mkdir, readFile } from 'fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { Document, NodeIO } from '@gltf-transform/core';
|
||||||
|
import { ALL_EXTENSIONS } from '@gltf-transform/extensions';
|
||||||
|
import { draco, dedup, prune, weld, simplify } from '@gltf-transform/functions';
|
||||||
|
import draco3d from 'draco3dgltf';
|
||||||
|
|
||||||
|
async function compressGLB(inputPath: string): Promise<void> {
|
||||||
|
const io = new NodeIO()
|
||||||
|
.registerExtensions(ALL_EXTENSIONS)
|
||||||
|
.registerDependencies({ 'draco3d.decoder': await draco3d.createDecoderModule(), 'draco3d.encoder': await draco3d.createEncoderModule() });
|
||||||
|
|
||||||
|
const document = await io.read(inputPath);
|
||||||
|
await document.transform(dedup(), prune(), weld(), draco());
|
||||||
|
await io.write(inputPath, document);
|
||||||
|
}
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
// Verify admin JWT
|
// Verify admin JWT
|
||||||
@@ -51,6 +65,13 @@ export async function POST(request: Request) {
|
|||||||
const buffer = Buffer.from(await file.arrayBuffer());
|
const buffer = Buffer.from(await file.arrayBuffer());
|
||||||
await writeFile(destPath, buffer);
|
await writeFile(destPath, buffer);
|
||||||
|
|
||||||
|
// Compress the uploaded GLB with Draco to reduce file size
|
||||||
|
try {
|
||||||
|
await compressGLB(destPath);
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('GLB compression failed, serving uncompressed:', err);
|
||||||
|
}
|
||||||
|
|
||||||
// Append a version timestamp so useGLTF cache is busted on replacement uploads
|
// Append a version timestamp so useGLTF cache is busted on replacement uploads
|
||||||
const version = Date.now();
|
const version = Date.now();
|
||||||
return NextResponse.json({ modelPath: `/models/${safeId}.glb?v=${version}` });
|
return NextResponse.json({ modelPath: `/models/${safeId}.glb?v=${version}` });
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ function OverlaySection({
|
|||||||
const panelStyle: React.CSSProperties = isCenter
|
const panelStyle: React.CSSProperties = isCenter
|
||||||
? { textAlign: 'center' }
|
? { textAlign: 'center' }
|
||||||
: {
|
: {
|
||||||
background: 'rgba(255, 255, 255, 0.45)',
|
background: 'rgba(255, 255, 255, 0.92)',
|
||||||
backdropFilter: 'blur(16px)',
|
backdropFilter: 'blur(20px)',
|
||||||
WebkitBackdropFilter: 'blur(16px)',
|
WebkitBackdropFilter: 'blur(20px)',
|
||||||
padding: '2.5rem',
|
padding: '2.5rem',
|
||||||
borderRadius: '1.5rem',
|
borderRadius: '1.5rem',
|
||||||
boxShadow: '0 8px 32px rgba(0, 0, 0, 0.08)',
|
boxShadow: '0 8px 32px rgba(0, 0, 0, 0.08)',
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ const CAMERA_KEYFRAMES: [number, [number, number, number]][] = [
|
|||||||
[0.40, [0.3, 1.5, 2.0]], // HEAD+CHEST: tight, high angle looking down
|
[0.40, [0.3, 1.5, 2.0]], // HEAD+CHEST: tight, high angle looking down
|
||||||
[0.55, [1.2, 2.2, 2.2]], // ABOVE: bird's eye with slight right offset
|
[0.55, [1.2, 2.2, 2.2]], // ABOVE: bird's eye with slight right offset
|
||||||
[0.68, [1.6, 0.7, 2.5]], // Dramatic right side sweep
|
[0.68, [1.6, 0.7, 2.5]], // Dramatic right side sweep
|
||||||
[0.80, [0.3, 0.3, 2.2]], // Circle to front-low
|
[0.80, [-1.8, 0.3, 3.0]], // Circle to front-left, pulled back to avoid text overlap
|
||||||
[0.92, [0, -0.3, 2.5]], // LOW ANGLE: heroic looking up
|
[0.92, [-1.5, -0.1, 3.2]], // LOW ANGLE: heroic, offset left for right-side text
|
||||||
[1.0, [0, 1.2, 5.5]], // Final: pull back for configurator
|
[1.0, [0, 1.2, 5.5]], // Final: pull back for configurator
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user