richardhcli
make new folder, subfolder of git, since images is too annoying to deal with
b012e8c
Raw
History Blame Contribute Delete
6.76 kB
/**
* SphereManager.js
* Manages the creation, deletion, and customization of spheres in the Three.js scene
*/
class SphereManager {
constructor(scene) {
this.scene = scene;
this.spheres = new Map();
this.sphereMeshes = new Map();
this.geometries = new Map();
this.materials = new Map();
}
/**
* Create and add a new sphere to the scene
* @param {string} name - Unique identifier for the sphere
* @param {object} config - Configuration object
* @param {number} config.radius - Sphere radius (default: 1)
* @param {string} config.color - Hex color (default: '#ff0000')
* @param {THREE.Vector3} config.position - Position vector (default: 0,0,0)
* @param {number} config.opacity - Opacity 0-1 (default: 1)
* @returns {THREE.Mesh} The created sphere mesh
*/
addSphere(name, config = {}) {
// Prevent duplicate names
if (this.spheres.has(name)) {
console.warn(`Sphere with name "${name}" already exists. Skipping.`);
return null;
}
// Set defaults
const radius = config.radius || 1;
const color = config.color || '#ff0000';
const position = config.position || new THREE.Vector3(0, 0, 0);
const opacity = config.opacity !== undefined ? config.opacity : 1;
// Create geometry and material
const geometry = new THREE.SphereGeometry(radius, 32, 32);
const material = new THREE.MeshStandardMaterial({
color: new THREE.Color(color),
opacity: opacity,
transparent: opacity < 1,
emissive: new THREE.Color(color),
emissiveIntensity: 0.3,
metalness: 0.3,
roughness: 0.4
});
// Create mesh
const mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(position);
mesh.name = name;
mesh.userData = {
sphereName: name,
radius: radius,
originalColor: color,
connections: []
};
// Store references
this.scene.add(mesh);
this.spheres.set(name, mesh.userData);
this.sphereMeshes.set(name, mesh);
this.geometries.set(name, geometry);
this.materials.set(name, material);
console.log(`✓ Sphere added: ${name}`, config);
return mesh;
}
/**
* Remove a sphere from the scene
* @param {string} name - Name of the sphere to remove
*/
removeSphere(name) {
const mesh = this.sphereMeshes.get(name);
if (!mesh) {
console.warn(`Sphere "${name}" not found.`);
return;
}
// Remove from scene
this.scene.remove(mesh);
// Clean up geometry and material
const geometry = this.geometries.get(name);
const material = this.materials.get(name);
if (geometry) geometry.dispose();
if (material) material.dispose();
// Remove from maps
this.spheres.delete(name);
this.sphereMeshes.delete(name);
this.geometries.delete(name);
this.materials.delete(name);
console.log(`✓ Sphere removed: ${name}`);
}
/**
* Update sphere properties
* @param {string} name - Name of the sphere
* @param {object} config - Properties to update
*/
updateSphere(name, config = {}) {
const mesh = this.sphereMeshes.get(name);
if (!mesh) {
console.warn(`Sphere "${name}" not found.`);
return;
}
// Update position
if (config.position) {
mesh.position.copy(config.position);
}
// Update color
if (config.color) {
const colorObj = new THREE.Color(config.color);
mesh.material.color.copy(colorObj);
mesh.material.emissive.copy(colorObj);
mesh.userData.originalColor = config.color;
}
// Update opacity
if (config.opacity !== undefined) {
mesh.material.opacity = config.opacity;
mesh.material.transparent = config.opacity < 1;
}
// Update scale (for size changes without recreating geometry)
if (config.scale !== undefined) {
mesh.scale.set(config.scale, config.scale, config.scale);
}
console.log(`✓ Sphere updated: ${name}`);
}
/**
* Get sphere mesh by name
* @param {string} name - Name of the sphere
* @returns {THREE.Mesh} The sphere mesh
*/
getSphere(name) {
return this.sphereMeshes.get(name);
}
/**
* Get all spheres
* @returns {Array} Array of sphere data
*/
getAllSpheres() {
return Array.from(this.spheres.entries()).map(([name, data]) => ({
name,
...data,
mesh: this.sphereMeshes.get(name)
}));
}
/**
* Change sphere color with animation
* @param {string} name - Name of the sphere
* @param {string} newColor - New hex color
* @param {number} duration - Animation duration in ms
*/
changeColorSmooth(name, newColor, duration = 500) {
const mesh = this.sphereMeshes.get(name);
if (!mesh) return;
const startColor = mesh.material.color.getHex();
const endColor = new THREE.Color(newColor).getHex();
const startTime = Date.now();
const animate = () => {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
const currentColor = new THREE.Color().lerpHexColors(startColor, endColor, progress);
mesh.material.color.copy(currentColor);
mesh.material.emissive.copy(currentColor);
if (progress < 1) {
requestAnimationFrame(animate);
} else {
mesh.userData.originalColor = newColor;
}
};
animate();
}
/**
* Add a glow effect to a sphere
* @param {string} name - Name of the sphere
* @param {boolean} enable - Whether to enable glow
*/
setGlow(name, enable = true) {
const mesh = this.sphereMeshes.get(name);
if (!mesh) return;
if (enable) {
mesh.material.emissiveIntensity = 0.8;
} else {
mesh.material.emissiveIntensity = 0.3;
}
}
/**
* Clear all spheres
*/
clearAll() {
const names = Array.from(this.spheres.keys());
names.forEach(name => this.removeSphere(name));
console.log('✓ All spheres cleared');
}
/**
* Get sphere count
* @returns {number}
*/
getCount() {
return this.spheres.size;
}
}