From 6e182cf4acae62b39f159bcf1adcafd98c7980b1 Mon Sep 17 00:00:00 2001 From: AI Bot Date: Thu, 17 Sep 2026 09:44:35 +0530 Subject: [PATCH] feat: Add Flip X and Flip Y options for UV baking --- src/components/ModelViewer.tsx | 4 ++-- src/lib/bakingUtils.ts | 17 +++++++++---- src/pages/Editor.tsx | 44 +++++++++++++++++++++++----------- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/components/ModelViewer.tsx b/src/components/ModelViewer.tsx index ebcda10..351f43c 100644 --- a/src/components/ModelViewer.tsx +++ b/src/components/ModelViewer.tsx @@ -7,7 +7,7 @@ import { useTexturePipeline } from "../hooks/useTexturePipeline"; interface ModelViewerProps { object: THREE.Object3D | null; sceneObjects: any[]; - bakeRequest?: { id: string, type: 'planar' | 'cylinder' | 'sphere' | 'box', timestamp: number } | null; + bakeRequest?: { id: string, type: 'planar' | 'cylinder' | 'sphere' | 'box', flipX?: boolean, flipY?: boolean, timestamp: number } | null; onBakeComplete?: (dataUrl: string) => void; } @@ -271,7 +271,7 @@ export const ModelViewer = forwardRef(({ object, // Bake try { - const dataUrl = bakeTextureToNewUVs(targetMesh, oldUVArray, tex, gl, 1024); + const dataUrl = bakeTextureToNewUVs(targetMesh, oldUVArray, tex, gl, 1024, bakeRequest.flipX, bakeRequest.flipY); onBakeComplete(dataUrl); } catch (e) { console.error("Baking failed", e); diff --git a/src/lib/bakingUtils.ts b/src/lib/bakingUtils.ts index bc6c5ec..d45b9ff 100644 --- a/src/lib/bakingUtils.ts +++ b/src/lib/bakingUtils.ts @@ -100,7 +100,9 @@ export function bakeTextureToNewUVs( oldUVArray: Float32Array, oldTexture: THREE.Texture, renderer: THREE.WebGLRenderer, - resolution = 1024 + resolution = 1024, + flipX = false, + flipY = false ): string { // Store original geometry attributes const geometry = mesh.geometry.clone(); @@ -113,15 +115,22 @@ export function bakeTextureToNewUVs( // Color is sampled from the old texture using the old UVs (uv2) const bakeMaterial = new THREE.ShaderMaterial({ uniforms: { - tDiffuse: { value: oldTexture } + tDiffuse: { value: oldTexture }, + uFlipX: { value: flipX ? 1.0 : 0.0 }, + uFlipY: { value: flipY ? 1.0 : 0.0 } }, vertexShader: ` attribute vec2 uv2; varying vec2 vOldUV; + uniform float uFlipX; + uniform float uFlipY; void main() { vOldUV = uv2; - // Flip X and Y to fix upside down and reversed texture - gl_Position = vec4(1.0 - uv.x * 2.0, 1.0 - uv.y * 2.0, 0.0, 1.0); + + float finalX = mix(uv.x * 2.0 - 1.0, 1.0 - uv.x * 2.0, uFlipX); + float finalY = mix(uv.y * 2.0 - 1.0, 1.0 - uv.y * 2.0, uFlipY); + + gl_Position = vec4(finalX, finalY, 0.0, 1.0); } `, fragmentShader: ` diff --git a/src/pages/Editor.tsx b/src/pages/Editor.tsx index 2a24835..686d897 100644 --- a/src/pages/Editor.tsx +++ b/src/pages/Editor.tsx @@ -642,7 +642,8 @@ export default function Editor() { const [renderProgress, setRenderProgress] = useState<{ step: string; progress: number } | null>(null); const [isRenderComplete, setIsRenderComplete] = useState(false); const [bakedDataUrl, setBakedDataUrl] = useState(null); - const [bakeRequest, setBakeRequest] = useState<{ id: string, type: 'planar' | 'cylinder' | 'sphere' | 'box', timestamp: number } | null>(null); + const [bakeOptions, setBakeOptions] = useState({ flipX: false, flipY: false }); + const [bakeRequest, setBakeRequest] = useState<{ id: string, type: 'planar' | 'cylinder' | 'sphere' | 'box', flipX: boolean, flipY: boolean, timestamp: number } | null>(null); const [importStatus, setImportStatus] = useState(null); const [importError, setImportError] = useState(null); const [modelData, setModelData] = useState<{ name: string, data: string, extension: string } | null>(null); @@ -4687,19 +4688,34 @@ export default function Editor() { {selectedObject.materialProps?.mappingType && selectedObject.materialProps.mappingType !== 'uv' && selectedObject.materialProps.mappingType !== 'triplanar' && ( - +
+ Baking Options +
+ + +
+ +
)}