Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -189,20 +189,11 @@ class LightingControl3D(gr.HTML):
|
|
| 189 |
wrapper.insertBefore(renderer.domElement, promptOverlay);
|
| 190 |
|
| 191 |
// Lighting
|
| 192 |
-
scene.add(new THREE.AmbientLight(0xffffff, 0.
|
| 193 |
|
| 194 |
// Grid
|
| 195 |
scene.add(new THREE.GridHelper(8, 16, 0x333333, 0x222222));
|
| 196 |
|
| 197 |
-
// Floor for shadows
|
| 198 |
-
const floorGeo = new THREE.PlaneGeometry(10, 10);
|
| 199 |
-
const floorMat = new THREE.ShadowMaterial({ opacity: 0.3 });
|
| 200 |
-
const floor = new THREE.Mesh(floorGeo, floorMat);
|
| 201 |
-
floor.rotation.x = -Math.PI / 2;
|
| 202 |
-
floor.position.y = 0;
|
| 203 |
-
floor.receiveShadow = true;
|
| 204 |
-
scene.add(floor);
|
| 205 |
-
|
| 206 |
// Constants
|
| 207 |
const CENTER = new THREE.Vector3(0, 0.75, 0);
|
| 208 |
const BASE_DISTANCE = 2.5;
|
|
@@ -257,7 +248,6 @@ class LightingControl3D(gr.HTML):
|
|
| 257 |
const planeMaterial = new THREE.MeshStandardMaterial({ map: currentTexture, side: THREE.DoubleSide, roughness: 0.5, metalness: 0 });
|
| 258 |
let targetPlane = new THREE.Mesh(new THREE.PlaneGeometry(1.2, 1.2), planeMaterial);
|
| 259 |
targetPlane.position.copy(CENTER);
|
| 260 |
-
targetPlane.castShadow = true;
|
| 261 |
targetPlane.receiveShadow = true;
|
| 262 |
scene.add(targetPlane);
|
| 263 |
|
|
@@ -271,7 +261,6 @@ class LightingControl3D(gr.HTML):
|
|
| 271 |
scene.remove(targetPlane);
|
| 272 |
targetPlane = new THREE.Mesh(new THREE.PlaneGeometry(1.2, 1.2), planeMaterial);
|
| 273 |
targetPlane.position.copy(CENTER);
|
| 274 |
-
targetPlane.castShadow = true;
|
| 275 |
targetPlane.receiveShadow = true;
|
| 276 |
scene.add(targetPlane);
|
| 277 |
return;
|
|
@@ -304,7 +293,6 @@ class LightingControl3D(gr.HTML):
|
|
| 304 |
planeMaterial
|
| 305 |
);
|
| 306 |
targetPlane.position.copy(CENTER);
|
| 307 |
-
targetPlane.castShadow = true;
|
| 308 |
targetPlane.receiveShadow = true;
|
| 309 |
scene.add(targetPlane);
|
| 310 |
}
|
|
@@ -323,19 +311,19 @@ class LightingControl3D(gr.HTML):
|
|
| 323 |
const bulbMat = new THREE.MeshStandardMaterial({ color: 0xffff00, emissive: 0xffff00, emissiveIntensity: 1 });
|
| 324 |
const bulb = new THREE.Mesh(new THREE.SphereGeometry(0.15, 16, 16), bulbMat);
|
| 325 |
lightGroup.add(bulb);
|
| 326 |
-
const pointLight = new THREE.PointLight(0xffffff,
|
| 327 |
pointLight.castShadow = true;
|
| 328 |
-
pointLight.shadow.mapSize.width =
|
| 329 |
-
pointLight.shadow.mapSize.height =
|
| 330 |
-
pointLight.shadow.camera.near = 0.
|
| 331 |
-
pointLight.shadow.camera.far =
|
| 332 |
lightGroup.add(pointLight);
|
| 333 |
scene.add(lightGroup);
|
| 334 |
|
| 335 |
-
//
|
| 336 |
const azimuthRing = new THREE.Mesh(
|
| 337 |
new THREE.TorusGeometry(AZIMUTH_RADIUS, 0.04, 16, 64),
|
| 338 |
-
new THREE.MeshStandardMaterial({ color:
|
| 339 |
);
|
| 340 |
azimuthRing.rotation.x = Math.PI / 2;
|
| 341 |
azimuthRing.position.y = 0.05;
|
|
@@ -343,12 +331,12 @@ class LightingControl3D(gr.HTML):
|
|
| 343 |
|
| 344 |
const azimuthHandle = new THREE.Mesh(
|
| 345 |
new THREE.SphereGeometry(0.18, 16, 16),
|
| 346 |
-
new THREE.MeshStandardMaterial({ color:
|
| 347 |
);
|
| 348 |
azimuthHandle.userData.type = 'azimuth';
|
| 349 |
scene.add(azimuthHandle);
|
| 350 |
|
| 351 |
-
//
|
| 352 |
const arcPoints = [];
|
| 353 |
for (let i = 0; i <= 32; i++) {
|
| 354 |
const angle = THREE.MathUtils.degToRad(-90 + (180 * i / 32));
|
|
@@ -357,17 +345,38 @@ class LightingControl3D(gr.HTML):
|
|
| 357 |
const arcCurve = new THREE.CatmullRomCurve3(arcPoints);
|
| 358 |
const elevationArc = new THREE.Mesh(
|
| 359 |
new THREE.TubeGeometry(arcCurve, 32, 0.04, 8, false),
|
| 360 |
-
new THREE.MeshStandardMaterial({ color:
|
| 361 |
);
|
| 362 |
scene.add(elevationArc);
|
| 363 |
|
| 364 |
const elevationHandle = new THREE.Mesh(
|
| 365 |
new THREE.SphereGeometry(0.18, 16, 16),
|
| 366 |
-
new THREE.MeshStandardMaterial({ color:
|
| 367 |
);
|
| 368 |
elevationHandle.userData.type = 'elevation';
|
| 369 |
scene.add(elevationHandle);
|
| 370 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
function updatePositions() {
|
| 372 |
const distance = BASE_DISTANCE;
|
| 373 |
const azRad = THREE.MathUtils.degToRad(azimuthAngle);
|
|
@@ -649,7 +658,7 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 649 |
image = gr.Image(label="Input Image", type="pil", height=300)
|
| 650 |
|
| 651 |
gr.Markdown("### 🎮 3D Lighting Control")
|
| 652 |
-
gr.Markdown("*Drag the colored handles:
|
| 653 |
|
| 654 |
lighting_3d = LightingControl3D(
|
| 655 |
value={"azimuth": 0, "elevation": 0},
|
|
|
|
| 189 |
wrapper.insertBefore(renderer.domElement, promptOverlay);
|
| 190 |
|
| 191 |
// Lighting
|
| 192 |
+
scene.add(new THREE.AmbientLight(0xffffff, 0.1));
|
| 193 |
|
| 194 |
// Grid
|
| 195 |
scene.add(new THREE.GridHelper(8, 16, 0x333333, 0x222222));
|
| 196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
// Constants
|
| 198 |
const CENTER = new THREE.Vector3(0, 0.75, 0);
|
| 199 |
const BASE_DISTANCE = 2.5;
|
|
|
|
| 248 |
const planeMaterial = new THREE.MeshStandardMaterial({ map: currentTexture, side: THREE.DoubleSide, roughness: 0.5, metalness: 0 });
|
| 249 |
let targetPlane = new THREE.Mesh(new THREE.PlaneGeometry(1.2, 1.2), planeMaterial);
|
| 250 |
targetPlane.position.copy(CENTER);
|
|
|
|
| 251 |
targetPlane.receiveShadow = true;
|
| 252 |
scene.add(targetPlane);
|
| 253 |
|
|
|
|
| 261 |
scene.remove(targetPlane);
|
| 262 |
targetPlane = new THREE.Mesh(new THREE.PlaneGeometry(1.2, 1.2), planeMaterial);
|
| 263 |
targetPlane.position.copy(CENTER);
|
|
|
|
| 264 |
targetPlane.receiveShadow = true;
|
| 265 |
scene.add(targetPlane);
|
| 266 |
return;
|
|
|
|
| 293 |
planeMaterial
|
| 294 |
);
|
| 295 |
targetPlane.position.copy(CENTER);
|
|
|
|
| 296 |
targetPlane.receiveShadow = true;
|
| 297 |
scene.add(targetPlane);
|
| 298 |
}
|
|
|
|
| 311 |
const bulbMat = new THREE.MeshStandardMaterial({ color: 0xffff00, emissive: 0xffff00, emissiveIntensity: 1 });
|
| 312 |
const bulb = new THREE.Mesh(new THREE.SphereGeometry(0.15, 16, 16), bulbMat);
|
| 313 |
lightGroup.add(bulb);
|
| 314 |
+
const pointLight = new THREE.PointLight(0xffffff, 5, 0, 2);
|
| 315 |
pointLight.castShadow = true;
|
| 316 |
+
pointLight.shadow.mapSize.width = 512;
|
| 317 |
+
pointLight.shadow.mapSize.height = 512;
|
| 318 |
+
pointLight.shadow.camera.near = 0.5;
|
| 319 |
+
pointLight.shadow.camera.far = 500;
|
| 320 |
lightGroup.add(pointLight);
|
| 321 |
scene.add(lightGroup);
|
| 322 |
|
| 323 |
+
// BLUE: Azimuth ring
|
| 324 |
const azimuthRing = new THREE.Mesh(
|
| 325 |
new THREE.TorusGeometry(AZIMUTH_RADIUS, 0.04, 16, 64),
|
| 326 |
+
new THREE.MeshStandardMaterial({ color: 0x007bff, emissive: 0x007bff, emissiveIntensity: 0.3 })
|
| 327 |
);
|
| 328 |
azimuthRing.rotation.x = Math.PI / 2;
|
| 329 |
azimuthRing.position.y = 0.05;
|
|
|
|
| 331 |
|
| 332 |
const azimuthHandle = new THREE.Mesh(
|
| 333 |
new THREE.SphereGeometry(0.18, 16, 16),
|
| 334 |
+
new THREE.MeshStandardMaterial({ color: 0x007bff, emissive: 0x007bff, emissiveIntensity: 0.5 })
|
| 335 |
);
|
| 336 |
azimuthHandle.userData.type = 'azimuth';
|
| 337 |
scene.add(azimuthHandle);
|
| 338 |
|
| 339 |
+
// RED: Elevation arc
|
| 340 |
const arcPoints = [];
|
| 341 |
for (let i = 0; i <= 32; i++) {
|
| 342 |
const angle = THREE.MathUtils.degToRad(-90 + (180 * i / 32));
|
|
|
|
| 345 |
const arcCurve = new THREE.CatmullRomCurve3(arcPoints);
|
| 346 |
const elevationArc = new THREE.Mesh(
|
| 347 |
new THREE.TubeGeometry(arcCurve, 32, 0.04, 8, false),
|
| 348 |
+
new THREE.MeshStandardMaterial({ color: 0xdc3545, emissive: 0xdc3545, emissiveIntensity: 0.3 })
|
| 349 |
);
|
| 350 |
scene.add(elevationArc);
|
| 351 |
|
| 352 |
const elevationHandle = new THREE.Mesh(
|
| 353 |
new THREE.SphereGeometry(0.18, 16, 16),
|
| 354 |
+
new THREE.MeshStandardMaterial({ color: 0xdc3545, emissive: 0xdc3545, emissiveIntensity: 0.5 })
|
| 355 |
);
|
| 356 |
elevationHandle.userData.type = 'elevation';
|
| 357 |
scene.add(elevationHandle);
|
| 358 |
|
| 359 |
+
// Refresh button
|
| 360 |
+
const refreshBtn = document.createElement('div');
|
| 361 |
+
refreshBtn.innerHTML = '🔄';
|
| 362 |
+
refreshBtn.style.position = 'absolute';
|
| 363 |
+
refreshBtn.style.top = '10px';
|
| 364 |
+
refreshBtn.style.right = '10px';
|
| 365 |
+
refreshBtn.style.background = 'rgba(255,255,255,0.5)';
|
| 366 |
+
refreshBtn.style.padding = '5px';
|
| 367 |
+
refreshBtn.style.borderRadius = '50%';
|
| 368 |
+
refreshBtn.style.cursor = 'pointer';
|
| 369 |
+
refreshBtn.style.zIndex = '10';
|
| 370 |
+
refreshBtn.style.fontSize = '20px';
|
| 371 |
+
wrapper.appendChild(refreshBtn);
|
| 372 |
+
|
| 373 |
+
refreshBtn.addEventListener('click', () => {
|
| 374 |
+
azimuthAngle = 0;
|
| 375 |
+
elevationAngle = 0;
|
| 376 |
+
updatePositions();
|
| 377 |
+
updatePropsAndTrigger();
|
| 378 |
+
});
|
| 379 |
+
|
| 380 |
function updatePositions() {
|
| 381 |
const distance = BASE_DISTANCE;
|
| 382 |
const azRad = THREE.MathUtils.degToRad(azimuthAngle);
|
|
|
|
| 658 |
image = gr.Image(label="Input Image", type="pil", height=300)
|
| 659 |
|
| 660 |
gr.Markdown("### 🎮 3D Lighting Control")
|
| 661 |
+
gr.Markdown("*Drag the colored handles: 🔵 Azimuth (Direction), 🔴 Elevation (Height)*")
|
| 662 |
|
| 663 |
lighting_3d = LightingControl3D(
|
| 664 |
value={"azimuth": 0, "elevation": 0},
|