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:
parent
6dc705b332
commit
83d0d9ab00
2171
package-lock.json
generated
2171
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,6 +11,9 @@
|
||||
"test:watch": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gltf-transform/core": "^4.3.0",
|
||||
"@gltf-transform/extensions": "^4.3.0",
|
||||
"@gltf-transform/functions": "^4.3.0",
|
||||
"@libsql/client": "^0.17.2",
|
||||
"@prisma/adapter-libsql": "^7.7.0",
|
||||
"@prisma/client": "^7.7.0",
|
||||
@ -22,6 +25,7 @@
|
||||
"@stripe/stripe-js": "^9.1.0",
|
||||
"@types/three": "^0.183.1",
|
||||
"bcryptjs": "^3.0.3",
|
||||
"draco3dgltf": "^1.5.7",
|
||||
"framer-motion": "^12.38.0",
|
||||
"gsap": "^3.14.2",
|
||||
"i18next": "^26.0.3",
|
||||
@ -37,6 +41,7 @@
|
||||
"zustand": "^5.0.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gltf-transform/cli": "^4.3.0",
|
||||
"@tailwindcss/postcss": "^4.2.2",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
|
||||
Binary file not shown.
BIN
public/Kandoura_original.glb
Normal file
BIN
public/Kandoura_original.glb
Normal file
Binary file not shown.
BIN
public/Suit.glb
BIN
public/Suit.glb
Binary file not shown.
BIN
public/Suit_original.glb
Normal file
BIN
public/Suit_original.glb
Normal file
Binary file not shown.
Binary file not shown.
BIN
public/Unitree_G1_original.glb
Normal file
BIN
public/Unitree_G1_original.glb
Normal file
Binary file not shown.
BIN
public/Vest.glb
BIN
public/Vest.glb
Binary file not shown.
BIN
public/Vest_original.glb
Normal file
BIN
public/Vest_original.glb
Normal file
Binary file not shown.
@ -1,8 +1,22 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { jwtVerify } from 'jose';
|
||||
import { writeFile, mkdir } from 'fs/promises';
|
||||
import { writeFile, mkdir, readFile } from 'fs/promises';
|
||||
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) {
|
||||
// Verify admin JWT
|
||||
@ -51,6 +65,13 @@ export async function POST(request: Request) {
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
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
|
||||
const version = Date.now();
|
||||
return NextResponse.json({ modelPath: `/models/${safeId}.glb?v=${version}` });
|
||||
|
||||
@ -74,9 +74,9 @@ function OverlaySection({
|
||||
const panelStyle: React.CSSProperties = isCenter
|
||||
? { textAlign: 'center' }
|
||||
: {
|
||||
background: 'rgba(255, 255, 255, 0.45)',
|
||||
backdropFilter: 'blur(16px)',
|
||||
WebkitBackdropFilter: 'blur(16px)',
|
||||
background: 'rgba(255, 255, 255, 0.92)',
|
||||
backdropFilter: 'blur(20px)',
|
||||
WebkitBackdropFilter: 'blur(20px)',
|
||||
padding: '2.5rem',
|
||||
borderRadius: '1.5rem',
|
||||
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.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.80, [0.3, 0.3, 2.2]], // Circle to front-low
|
||||
[0.92, [0, -0.3, 2.5]], // LOW ANGLE: heroic looking up
|
||||
[0.80, [-1.8, 0.3, 3.0]], // Circle to front-left, pulled back to avoid text overlap
|
||||
[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
|
||||
];
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user