Skip to content

Commit 1445894

Browse files
committed
Add helper toggle and make directional controls spherical
1 parent d9d2f77 commit 1445894

File tree

3 files changed

+205
-31
lines changed

3 files changed

+205
-31
lines changed

src/controls.ts

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -287,14 +287,22 @@ export class URDFControls extends GUI {
287287
this._lightsFolder.addFolder('Directional Light');
288288
const ambientFolder = this._lightsFolder.addFolder('Ambient Light');
289289
const hemisphereFolder = this._lightsFolder.addFolder('Hemisphere Light');
290+
const helpersFolder = this._lightsFolder.addFolder('Light Helpers');
290291

291292
// Initialize settings for each light type
292293
const directionalSettings = {
293-
X: 3,
294-
Y: 10,
295-
Z: 3,
294+
// Spherical coordinates are more intuitive for light positioning
295+
Distance: 10.9, // Initial distance from origin
296+
Altitude: Math.PI / 4, // Initial altitude angle (radians)
297+
Azimuth: Math.PI / 4, // Initial azimuth angle (radians)
296298
Color: [255, 255, 255],
297-
Intensity: 1.0
299+
Intensity: 1.0,
300+
// Adding target controls
301+
Target: {
302+
X: 0,
303+
Y: 0,
304+
Z: 0
305+
}
298306
};
299307

300308
const ambientSettings = {
@@ -308,35 +316,73 @@ export class URDFControls extends GUI {
308316
Intensity: 1.0
309317
};
310318

319+
const helperSettings = {
320+
DirectionalHelper: true,
321+
HemisphereHelper: true
322+
};
323+
311324
// Position limits and steps
312325
const minPosition = -20;
313326
const maxPosition = 20;
314327
const positionStep = 0.1;
315328

329+
// Spherical coordinate limits and steps
330+
const minDistance = 0.1;
331+
const maxDistance = 30;
332+
const distanceStep = 0.1;
333+
const minAngle = -Math.PI;
334+
const maxAngle = Math.PI;
335+
const angleStep = 0.01;
336+
316337
// Intensity limits and steps
317338
const minIntensity = 0;
318339
const maxIntensity = 2;
319340
const intensityStep = 0.05;
320341

321-
// Directional light controls
342+
// Target controls for directional light
343+
const targetFolder = directionalFolder.addFolder('Target');
322344
this.controls.lights.directional = {
323345
position: {
324-
x: directionalFolder.add(
346+
// Using spherical coordinates instead of Cartesian
347+
distance: directionalFolder.add(
348+
directionalSettings,
349+
'Distance',
350+
minDistance,
351+
maxDistance,
352+
distanceStep
353+
),
354+
altitude: directionalFolder.add(
355+
directionalSettings,
356+
'Altitude',
357+
minAngle,
358+
maxAngle,
359+
angleStep
360+
),
361+
azimuth: directionalFolder.add(
325362
directionalSettings,
363+
'Azimuth',
364+
minAngle,
365+
maxAngle,
366+
angleStep
367+
)
368+
},
369+
target: {
370+
x: targetFolder.add(
371+
directionalSettings.Target,
326372
'X',
327373
minPosition,
328374
maxPosition,
329375
positionStep
330376
),
331-
y: directionalFolder.add(
332-
directionalSettings,
377+
y: targetFolder.add(
378+
directionalSettings.Target,
333379
'Y',
334380
minPosition,
335381
maxPosition,
336382
positionStep
337383
),
338-
z: directionalFolder.add(
339-
directionalSettings,
384+
z: targetFolder.add(
385+
directionalSettings.Target,
340386
'Z',
341387
minPosition,
342388
maxPosition,
@@ -381,6 +427,15 @@ export class URDFControls extends GUI {
381427
)
382428
};
383429

430+
// Light helpers controls
431+
this.controls.lights.helpers = {
432+
directionalHelper: helpersFolder.add(
433+
helperSettings,
434+
'DirectionalHelper'
435+
),
436+
hemisphereHelper: helpersFolder.add(helperSettings, 'HemisphereHelper')
437+
};
438+
384439
// Open main lights folder and directional subfolder
385440
this._lightsFolder.open();
386441
directionalFolder.open();

src/layout.ts

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -224,23 +224,54 @@ export class URDFLayout extends PanelLayout {
224224
// Directional light callbacks
225225
const directional = lightControl.directional;
226226

227-
// Position controls
228-
directional.position.x.onChange((newX: number) => {
229-
const y = directional.position.y.getValue();
230-
const z = directional.position.z.getValue();
231-
this._renderer.setDirectionalLightPosition(newX, y, z);
227+
// Position controls using spherical coordinates
228+
directional.position.distance.onChange((newDistance: number) => {
229+
const altitude = directional.position.altitude.getValue();
230+
const azimuth = directional.position.azimuth.getValue();
231+
this._renderer.setDirectionalLightPositionSpherical(
232+
newDistance,
233+
altitude,
234+
azimuth
235+
);
232236
});
233237

234-
directional.position.y.onChange((newY: number) => {
235-
const x = directional.position.x.getValue();
236-
const z = directional.position.z.getValue();
237-
this._renderer.setDirectionalLightPosition(x, newY, z);
238+
directional.position.altitude.onChange((newAltitude: number) => {
239+
const distance = directional.position.distance.getValue();
240+
const azimuth = directional.position.azimuth.getValue();
241+
this._renderer.setDirectionalLightPositionSpherical(
242+
distance,
243+
newAltitude,
244+
azimuth
245+
);
238246
});
239247

240-
directional.position.z.onChange((newZ: number) => {
241-
const x = directional.position.x.getValue();
242-
const y = directional.position.y.getValue();
243-
this._renderer.setDirectionalLightPosition(x, y, newZ);
248+
directional.position.azimuth.onChange((newAzimuth: number) => {
249+
const distance = directional.position.distance.getValue();
250+
const altitude = directional.position.altitude.getValue();
251+
this._renderer.setDirectionalLightPositionSpherical(
252+
distance,
253+
altitude,
254+
newAzimuth
255+
);
256+
});
257+
258+
// Target position controls for directional light
259+
directional.target.x.onChange((newX: number) => {
260+
const y = directional.target.y.getValue();
261+
const z = directional.target.z.getValue();
262+
this._renderer.setDirectionalLightTarget(newX, y, z);
263+
});
264+
265+
directional.target.y.onChange((newY: number) => {
266+
const x = directional.target.x.getValue();
267+
const z = directional.target.z.getValue();
268+
this._renderer.setDirectionalLightTarget(x, newY, z);
269+
});
270+
271+
directional.target.z.onChange((newZ: number) => {
272+
const x = directional.target.x.getValue();
273+
const y = directional.target.y.getValue();
274+
this._renderer.setDirectionalLightTarget(x, y, newZ);
244275
});
245276

246277
// Color and intensity controls
@@ -252,6 +283,15 @@ export class URDFLayout extends PanelLayout {
252283
this._renderer.setDirectionalLightIntensity(newIntensity);
253284
});
254285

286+
// Light helper visibility toggles
287+
lightControl.helpers.directionalHelper.onChange((visible: boolean) => {
288+
this._renderer.setDirectionalLightHelperVisibility(visible);
289+
});
290+
291+
lightControl.helpers.hemisphereHelper.onChange((visible: boolean) => {
292+
this._renderer.setHemisphereLightHelperVisibility(visible);
293+
});
294+
255295
// Ambient light callbacks
256296
const ambient = lightControl.ambient;
257297

src/renderer.ts

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export class URDFRenderer extends THREE.WebGLRenderer {
2525
private _colorGround = new THREE.Color();
2626
private _gridHeight = 0;
2727
private _robotIndex = -1;
28+
private _directionalLightHelper: THREE.DirectionalLightHelper | null = null;
29+
private _hemisphereLightHelper: THREE.HemisphereLightHelper | null = null;
2830

2931
/**
3032
* Creates a renderer to manage the scene elements
@@ -143,13 +145,13 @@ export class URDFRenderer extends THREE.WebGLRenderer {
143145
directionalLight.shadow.camera.far = 40;
144146
this._scene.add(directionalLight);
145147

146-
// Add a helper for the directional light with black color
147-
const directionalLightHelper = new THREE.DirectionalLightHelper(
148+
// Add a helper for the directional light
149+
this._directionalLightHelper = new THREE.DirectionalLightHelper(
148150
directionalLight,
149151
2,
150-
new THREE.Color(0x000000) // Black color for helper
152+
new THREE.Color(0x000000)
151153
);
152-
this._scene.add(directionalLightHelper);
154+
this._scene.add(this._directionalLightHelper);
153155

154156
const ambientLight = new THREE.AmbientLight('#fff');
155157
ambientLight.intensity = 0.5;
@@ -163,13 +165,13 @@ export class URDFRenderer extends THREE.WebGLRenderer {
163165
hemisphereLight.intensity = 1;
164166
this._scene.add(hemisphereLight);
165167

166-
// Add a helper for the hemisphere light with black color
167-
const hemisphereLightHelper = new THREE.HemisphereLightHelper(
168+
// Add a helper for the hemisphere light
169+
this._hemisphereLightHelper = new THREE.HemisphereLightHelper(
168170
hemisphereLight,
169171
2
170172
);
171-
hemisphereLightHelper.material.color.set(0x000000); // Black color for helper
172-
this._scene.add(hemisphereLightHelper);
173+
this._hemisphereLightHelper.material.color.set(0x000000); // Black color for helper
174+
this._scene.add(this._hemisphereLightHelper);
173175
}
174176

175177
/**
@@ -187,6 +189,80 @@ export class URDFRenderer extends THREE.WebGLRenderer {
187189
this._scene.children[hemisphereIndex] = hemisphereLight;
188190
}
189191

192+
/**
193+
* Toggle the visibility of the directional light helper
194+
*
195+
* @param visible - Whether the helper should be visible
196+
*/
197+
setDirectionalLightHelperVisibility(visible: boolean): void {
198+
if (this._directionalLightHelper) {
199+
this._directionalLightHelper.visible = visible;
200+
this.redraw();
201+
}
202+
}
203+
204+
/**
205+
* Toggle the visibility of the hemisphere light helper
206+
*
207+
* @param visible - Whether the helper should be visible
208+
*/
209+
setHemisphereLightHelperVisibility(visible: boolean): void {
210+
if (this._hemisphereLightHelper) {
211+
this._hemisphereLightHelper.visible = visible;
212+
this.redraw();
213+
}
214+
}
215+
216+
/**
217+
* Updates the target of the directional light
218+
*
219+
* @param x - The x coordinate of the target
220+
* @param y - The y coordinate of the target
221+
* @param z - The z coordinate of the target
222+
*/
223+
setDirectionalLightTarget(x: number, y: number, z: number): void {
224+
const directionalLight = this._scene.children.find(
225+
obj => obj.type === 'DirectionalLight'
226+
) as THREE.DirectionalLight;
227+
228+
if (directionalLight) {
229+
directionalLight.target.position.set(x, y, z);
230+
if (this._directionalLightHelper) {
231+
this._directionalLightHelper.update();
232+
}
233+
this.redraw();
234+
}
235+
}
236+
237+
/**
238+
* Updates the position of the directional light using spherical coordinates
239+
*
240+
* @param distance - Distance from target
241+
* @param altitude - Angle in radians from the horizontal plane (elevation)
242+
* @param azimuth - Angle in radians around the vertical axis
243+
*/
244+
setDirectionalLightPositionSpherical(
245+
distance: number,
246+
altitude: number,
247+
azimuth: number
248+
): void {
249+
const directionalLight = this._scene.children.find(
250+
obj => obj.type === 'DirectionalLight'
251+
) as THREE.DirectionalLight;
252+
253+
if (directionalLight) {
254+
const x = distance * Math.cos(altitude) * Math.cos(azimuth);
255+
const z = distance * Math.cos(altitude) * Math.sin(azimuth);
256+
const y = distance * Math.sin(altitude);
257+
258+
directionalLight.position.set(x, y, z);
259+
if (this._directionalLightHelper) {
260+
this._directionalLightHelper.update();
261+
}
262+
this.redraw();
263+
}
264+
}
265+
190266
/**
191267
* Change the background color of the scene
192268
*
@@ -265,6 +341,9 @@ export class URDFRenderer extends THREE.WebGLRenderer {
265341

266342
if (directionalLight) {
267343
directionalLight.position.set(x, y, z);
344+
if (this._directionalLightHelper) {
345+
this._directionalLightHelper.update();
346+
}
268347
this.redraw();
269348
}
270349
}

0 commit comments

Comments
 (0)