feat: Add UV reprojection and texture baking via WebGL
Build and Deploy / build-and-push (push) Successful in 1m27s

This commit is contained in:
AI Bot
2026-09-17 09:34:14 +05:30
parent c7ebd76e1c
commit e2ae339abf
3 changed files with 278 additions and 2 deletions
+42 -1
View File
@@ -7,6 +7,8 @@ import { useTexturePipeline } from "../hooks/useTexturePipeline";
interface ModelViewerProps {
object: THREE.Object3D | null;
sceneObjects: any[];
bakeRequest?: { id: string, type: 'planar' | 'cylinder' | 'sphere' | 'box', timestamp: number } | null;
onBakeComplete?: (dataUrl: string) => void;
}
interface MeshMaterialManagerProps {
@@ -211,7 +213,9 @@ const FillMesh = ({ fillProps, originalMesh }: { fillProps: any, originalMesh: T
return createPortal(fillNode, originalMesh);
};
export const ModelViewer = forwardRef<THREE.Group, ModelViewerProps>(({ object, sceneObjects }, ref) => {
import { reprojectUVs, bakeTextureToNewUVs } from '../lib/bakingUtils';
export const ModelViewer = forwardRef<THREE.Group, ModelViewerProps>(({ object, sceneObjects, bakeRequest, onBakeComplete }, ref) => {
const internalRef = useRef<THREE.Group>(null);
const groupRef = (ref as any) || internalRef;
const textureCache = useRef<Map<string, THREE.Texture>>(new Map());
@@ -241,6 +245,43 @@ export const ModelViewer = forwardRef<THREE.Group, ModelViewerProps>(({ object,
};
}, []);
const { gl } = useThree();
// Handle Baking Request
useEffect(() => {
if (bakeRequest && onBakeComplete && meshCache.size > 0) {
const sceneObj = sceneObjects.find(obj => obj.id === bakeRequest.id);
if (!sceneObj) return;
// Find the primary mesh for this object (we assume the first mesh for now)
let targetMesh: THREE.Mesh | null = null;
for (const mesh of meshCache.values()) {
targetMesh = mesh;
break;
}
if (targetMesh && sceneObj.materialProps?.map) {
const tex = textureCache.current.get(sceneObj.materialProps.map);
if (tex) {
// Keep old UVs
const oldUVArray = targetMesh.geometry.attributes.uv.array.slice() as Float32Array;
// Apply new UV mapping (mutates geometry.attributes.uv)
reprojectUVs(targetMesh.geometry, bakeRequest.type);
// Bake
try {
const dataUrl = bakeTextureToNewUVs(targetMesh, oldUVArray, tex, gl, 1024);
onBakeComplete(dataUrl);
} catch (e) {
console.error("Baking failed", e);
onBakeComplete(sceneObj.materialProps.map); // Fallback to original
}
}
}
}
}, [bakeRequest, meshCache, sceneObjects, gl, onBakeComplete]);
// Main transform update for the core model
useEffect(() => {
if (object && sceneObjects) {