feat: add GLTF transformation and compression support
Some checks are pending
CI/CD / test-and-build (push) Waiting to run
CI/CD / deploy (push) Blocked by required conditions

- 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:
Najjar\NajjarV02 2026-04-17 15:34:41 +04:00
parent 6dc705b332
commit 83d0d9ab00
13 changed files with 2198 additions and 11 deletions

2171
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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.

Binary file not shown.

Binary file not shown.

BIN
public/Suit_original.glb Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/Vest_original.glb Normal file

Binary file not shown.

View File

@ -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}` });

View File

@ -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)',

View File

@ -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
];