Ask me anything
Ithy Logo
Sign in to save

Comprehensive Debugging Guide for Your 3D Knowledge Map Project

Resolve Common Issues and Optimize Your Three.js Application for a Smooth Experience

threejs 3d graph

Key Takeaways

  • Ensure Proper Initialization: Verify all imports and initialization steps to prevent runtime errors.
  • Optimize Performance: Implement performance enhancements like instancing and frustum culling.
  • Robust Event Handling: Manage event listeners effectively to avoid memory leaks and ensure responsive interactions.

1. Import and Initialization Issues

a. Correct Import Statements

Ensure that all Three.js modules and other dependencies are correctly imported. Incorrect paths or missing modules can lead to runtime errors.

// Correct Three.js and OrbitControls imports
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { dbManager } from './db';

b. Database Initialization

Properly handle asynchronous database initialization to ensure that your application doesn't proceed before the database is ready.

dbManager.init()
    .then(() => {
        console.log('Database initialized');
    })
    .catch(error => {
        console.error('Database initialization error:', error);
        // Implement fallback or retry logic here
    });

2. Performance Optimization

a. Optimize Particle Systems

Handling a large number of particles can be performance-intensive. Consider reducing the particle count or using GPU-accelerated systems.

createParticles() {
    const particleCount = 5000;
    const geometry = new THREE.InstancedBufferGeometry();
    const baseGeometry = new THREE.SphereGeometry(0.5, 8, 8);
    
    geometry.instanceCount = particleCount;
    geometry.setAttribute('position', baseGeometry.getAttribute('position'));
    geometry.setAttribute('normal', baseGeometry.getAttribute('normal'));
    
    // Initialize instance positions, colors, sizes, and phases here
    
    const material = new THREE.ShaderMaterial({
        vertexShader: /* Your vertex shader code */,
        fragmentShader: /* Your fragment shader code */,
        uniforms: {
            time: { value: 0 }
        }
    });
    
    this.particleSystem = new THREE.InstancedMesh(geometry, material, particleCount);
    this.scene.add(this.particleSystem);
}

b. Implement Frustum Culling

Use frustum culling to avoid rendering objects that are outside the camera's view, enhancing rendering performance.

this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000);
this.camera.frustumCulled = true;

3. Event Handling and Memory Management

a. Properly Manage Event Listeners

Ensure that all event listeners are correctly added and removed to prevent memory leaks and unintended behavior.

setupEventListeners() {
    window.addEventListener('resize', this.onWindowResize.bind(this));
    // Add other event listeners here
    
    // Clean up in dispose method
}

dispose() {
    window.removeEventListener('resize', this.onWindowResize.bind(this));
    // Remove other event listeners and dispose of Three.js resources
}

b. Handle Drag and Drop Boundaries

Implement boundary checks to prevent nodes from being dragged outside the visible scene.

onMouseMove(event) {
    if (this.isDragging && this.selectedNode) {
        // Calculate new position
        this.raycaster.setFromCamera(this.mouse, this.camera);
        if (this.raycaster.ray.intersectPlane(this.dragPlane, this.dragPoint)) {
            // Boundary checks
            const max = 1000, min = -1000;
            this.selectedNode.position.x = Math.min(Math.max(this.dragPoint.x, min), max);
            this.selectedNode.position.y = Math.min(Math.max(this.dragPoint.y, min), max);
            this.selectedNode.position.z = Math.min(Math.max(this.dragPoint.z, min), max);
        }
    }
}

4. Shader and Material Management

a. Update Glow Materials Appropriately

When updating node textures, ensure that associated glow effects are also updated to reflect the new material properties.

setNodeTexture(nodeId, textureName) {
    const node = this.nodes.get(parseInt(nodeId));
    if (!node) return;
    
    node.userData.customization.texture = textureName;
    
    switch (textureName) {
        case 'metal':
            node.material = new THREE.MeshStandardMaterial({
                color: node.material.color,
                metalness: 0.9,
                roughness: 0.1,
                emissive: node.material.color,
                emissiveIntensity: 0.3
            });
            break;
        // Handle other texture cases
        default:
            node.material = new THREE.MeshStandardMaterial({
                color: node.material.color,
                metalness: 0.8,
                roughness: 0.2,
                emissive: node.material.color,
                emissiveIntensity: 0.2
            });
            break;
    }
    
    if (node.userData.glowMesh) {
        node.userData.glowMesh.material.uniforms.color.value.setHex(node.material.color.getHex());
    }
}

5. User Interface and Interaction

a. Customize Node Interaction

Ensure that node interactions such as clicking, dragging, and right-clicking are handled smoothly without interfering with camera controls.

onMouseDown(event) {
    event.preventDefault();
    
    // Calculate mouse position
    const rect = this.renderer.domElement.getBoundingClientRect();
    this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
    
    this.raycaster.setFromCamera(this.mouse, this.camera);
    const intersects = this.raycaster.intersectObjects(Array.from(this.nodes.values()));
    
    if (intersects.length > 0) {
        const intersectedNode = intersects[0].object;
        
        if (event.button === 2) { // Right click
            this.showNodeCustomizationMenu(intersectedNode);
            return;
        }
        
        if (event.button === 0) { // Left click
            this.controls.enabled = false;
            this.selectedNode = intersectedNode;
            this.isDragging = true;
            
            // Show metadata
            this.showNodeMetadata(intersectedNode);
            
            // Set up drag plane
            const normal = new THREE.Vector3(0, 0, 1).applyQuaternion(this.camera.quaternion);
            this.dragPlane.setFromNormalAndCoplanarPoint(normal, this.selectedNode.position);
            return;
        }
        
        if (event.button === 1) { // Middle click
            // Handle depth dragging
        }
    } else {
        this.controls.enabled = true;
    }
}

b. Manage Modal Positioning

Keep UI modals within the viewport even when nodes move out of view.

showNodeMetadata(node) {
    if (!node || !node.userData || !node.userData.id) return;
    
    const modal = document.getElementById('nodeMetadataModal');
    if (!modal) return;
    
    // Update modal content
    const labelElement = document.getElementById('nodeLabel');
    const contentElement = document.getElementById('nodeContent');
    labelElement.textContent = node.userData.label || 'Node Label';
    contentElement.textContent = node.userData.content || 'Click to add content...';
    
    // Position modal over node
    const nodeWorldPos = new THREE.Vector3();
    node.getWorldPosition(nodeWorldPos);
    const nodeScreenPos = nodeWorldPos.clone().project(this.camera);
    
    const rect = this.renderer.domElement.getBoundingClientRect();
    const x = ((nodeScreenPos.x + 1) / 2) * rect.width + rect.left;
    const y = ((-nodeScreenPos.y + 1) / 2) * rect.height + rect.top;
    
    modal.style.transform = 'translate(-50%, -100%)';
    modal.style.left = `${x}px`;
    modal.style.top = `${y}px`;
    
    // Ensure modal stays within viewport
    // Additional logic can be implemented here
    
    modal.style.display = 'block';
    modal.classList.add('visible');
}

6. Saving and Loading State

a. Persisting Data Correctly

Handle saving and loading of the map state to ensure data integrity and proper restoration of nodes.

saveMap() {
    const data = {
        nodes: Array.from(this.nodes.values()).map(node => ({
            id: node.userData.id,
            label: node.userData.label,
            position: {
                x: node.position.x,
                y: node.position.y,
                z: node.position.z
            }
        }))
    };
    
    chrome.storage.local.set({ mindMap: data }, () => {
        console.log('Mind map saved successfully.');
    });
}

loadMap() {
    chrome.storage.local.get(['mindMap'], (result) => {
        if (result.mindMap) {
            // Clear existing nodes
            this.nodes.forEach(node => this.scene.remove(node));
            this.nodes.clear();
            
            // Recreate nodes from saved data
            result.mindMap.nodes.forEach(nodeData => {
                const node = this.addNode();
                node.userData.id = nodeData.id;
                node.userData.label = nodeData.label;
                node.position.set(nodeData.position.x, nodeData.position.y, nodeData.position.z);
                this.nodes.set(node.userData.id, node);
            });
        } else {
            console.warn('No saved mind map found.');
        }
    });
}

7. Additional Recommendations

a. Use TypeScript for Type Safety

Consider migrating to TypeScript to leverage type checking and reduce runtime errors.

b. Implement Undo/Redo Functionality

Enhance user experience by allowing undo and redo actions for node modifications.

c. Add Visual Feedback

Provide visual cues such as highlighting selected nodes to improve interactivity.


Conclusion

By addressing the initialization, performance, event handling, and UI interaction issues outlined above, you can enhance the stability and responsiveness of your 3D knowledge map project. Implement the recommended optimizations and best practices to ensure a smooth and engaging user experience.

References


Last updated January 18, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI