BasicConstraintsPlugin
A comprehensive plugin providing essential particle constraints and forces
BasicConstraintsPlugin
The BasicConstraintsPlugin is a comprehensive plugin that provides essential particle constraints and forces, including lifetime management, velocity updates, mouse interaction, and basic physics. This plugin serves as a foundation for most particle systems and demonstrates best practices for plugin development.
Features
- Lifetime Management: Automatic particle lifetime countdown and disposal
 - Color Fading: Smooth alpha fading based on remaining lifetime
 - Velocity Updates: Force-based velocity integration
 - Mouse Interaction: Interactive mouse repulsion forces
 - Position Updates: Velocity-based position integration
 - Origin Restoration: Spring-like forces that pull particles back to origin
 - Complete Physics Loop: Full force → acceleration → velocity → position pipeline
 
Installation
import { ParticleSystem, BasicConstraintsPlugin } from 'particlize';
const particleSystem = new ParticleSystem({ canvas });
const plugin = new BasicConstraintsPlugin();
// Apply plugin to system
plugin.onInit(particleSystem);Properties
| Property | Type | Description | 
|---|---|---|
name | string | Plugin identifier: "BasicConstraintsPlugin" | 
description | string | Plugin description and feature summary | 
Provided Properties
The plugin automatically sets up these properties:
| Property | Components | Default Value | Description | 
|---|---|---|---|
origin | 3 | N/A | Original particle positions for restoration | 
position | 3 | N/A | Current particle positions | 
velocity | 3 | [0, 0, 0] | Current particle velocities | 
force | 3 | [0, 0, 0] | Accumulated forces on particles | 
size | 1 | [1] | Particle sizes | 
mass | 1 | [1] | Particle masses | 
lifetime | 1 | [-1] | Particle lifetimes (-1 = infinite) | 
color | 4 | [1, 0, 1, 1] | Particle colors (RGBA) | 
Provided Constraints
Lifetime Management
if (lifetime > 0.0) {
  lifetime -= u_delta;
}Color Fading
if(lifetime > 0.0 && lifetime < 1.0) {
  float fadeAlpha = smoothstep(0.0, 1.0, lifetime);
  color.a *= fadeAlpha;
}Velocity Updates
vec3 acceleration = force / mass;
velocity += acceleration * u_delta;
// Mouse repulsion
vec2 toParticle = position.xy - u_mouse.xy;
float dist = length(toParticle);
if(dist < 0.2 && dist > 0.0) {
  vec2 dir = normalize(toParticle);
  float strength = (1.0 - (dist / 0.2)) * 100.0;
  velocity.xy += dir * strength * u_delta;
}Position Updates
position += velocity * u_delta;Mouse Interaction
The plugin provides automatic mouse interaction setup:
// Mouse tracking
window.addEventListener("mousemove", (event) => {
  system.mouse.x = (event.clientX / system.canvas.width) * 2 - 1;
  system.mouse.y = -(event.clientY / system.canvas.height) * 2 + 1;
});
// Raycasting for 3D mouse position
system.raycaster.setFromCamera(system.mouse, system.camera);
system.raycaster.ray.intersectPlane(system.raycastPlane, system.intersectionPoint);Complete Example
import { ParticleSystem, BasicConstraintsPlugin, MeshSurfaceSampler, SamplerFrame } from 'particlize';
import * as THREE from 'three';
// Create particle system
const particleSystem = new ParticleSystem({ canvas });
// Apply basic constraints plugin
const plugin = new BasicConstraintsPlugin();
plugin.onInit(particleSystem);
// Create particles
const geometry = new THREE.SphereGeometry(1, 32, 32);
const sampler = new MeshSurfaceSampler(geometry);
const frame = new SamplerFrame({ sampler, count: 10000 });
particleSystem.addParticles(frame);
// Render loop
function animate() {
  // Update plugin
  plugin.onUpdate(particleSystem);
  
  // Update particle system
  particleSystem.update();
  particleSystem.render();
  
  requestAnimationFrame(animate);
}
animate();Customization
Modifying Plugin Parameters
After initialization, you can modify the plugin's constraints:
// Apply plugin
plugin.onInit(particleSystem);
// Modify origin restoring force strength
particleSystem.manager.setUniforms('force', {
  'u_originRestoringForce_strength': 5.0  // Stronger restoration
});
// Modify mouse repulsion area
particleSystem.manager.setUniforms('velocity', {
  'u_mouse': new THREE.Vector3(0, 0, 0)  // Custom mouse position
});Extending the Plugin
You can extend the BasicConstraintsPlugin for custom behavior:
class CustomBasicPlugin extends BasicConstraintsPlugin {
  onInit(system: ParticleSystem) {
    // Call parent initialization
    super.onInit(system);
    
    // Add custom constraints
    const customForce = new Constraint('customGravity', /*glsl*/`
      force += vec3(0.0, -0.5, 0.0) * mass; // Custom gravity
    `);
    
    system.manager.constrain('force', customForce);
  }
  
  onUpdate(system: ParticleSystem) {
    // Call parent update
    super.onUpdate(system);
    
    // Custom update logic
    const time = performance.now() * 0.001;
    system.manager.setUniforms('force', {
      'u_customGravity_time': time
    });
  }
}Property Groups
The plugin creates efficient property groups:
.group(['position', 'size'])        // Rendering properties
.group(['velocity', 'lifetime'])     // Dynamic properties  
.group(['force', 'mass'])           // Physics propertiesGlobal Uniforms
The plugin sets up essential global uniforms:
.setUniformsAll({
  u_time: 0,                        // Current time
  u_delta: 0,                       // Delta time
  u_resolution: new THREE.Vector2(width, height),
  u_texture_resolution: new THREE.Vector2(width, height),
  u_mouse: system.intersectionPoint  // Mouse position
})Integration with Particle Material
The plugin automatically links FBO textures to the particle material:
// Position texture
system.particleMaterial.uniforms[positionFBO.textureName] = {
  value: positionFBO.read.texture,
};
// Velocity/lifetime texture
system.particleMaterial.uniforms[lifetimeFBO.textureName] = {
  value: lifetimeFBO.read.texture,
};
// Color texture
system.particleMaterial.uniforms[colorFBO.textureName] = {
  value: colorFBO.read.texture,
};Best Practices
- Plugin Order: Apply plugins before adding particles
 - Update Cycle: Call 
onUpdate()in your render loop - Property Setup: Let the plugin handle property setup for consistency
 - Customization: Modify uniforms after initialization rather than during
 - Performance: The plugin is optimized for common use cases
 
Advanced Usage
Selective Feature Usage
If you only need certain features, create a custom plugin:
class MinimalPhysicsPlugin implements ParticlePlugin {
  name = "MinimalPhysics";
  
  onInit(system: ParticleSystem) {
    // Only setup position and velocity
    system.manager
      .add('position', 3)
      .add('velocity', 3, new Float32Array([0, 0, 0]))
      .group(['position', 'velocity']);
    
    // Only position updates
    const positionUpdate = new Constraint('positionUpdate', /*glsl*/`
      position += velocity * u_delta;
    `);
    
    system.manager.constrain('position', positionUpdate);
  }
  
  onUpdate(system: ParticleSystem) {
    // Minimal update logic
  }
}Multi-System Usage
The plugin can be applied to multiple particle systems:
const systems = [
  new ParticleSystem({ canvas: canvas1 }),
  new ParticleSystem({ canvas: canvas2 }),
  new ParticleSystem({ canvas: canvas3 })
];
systems.forEach(system => {
  const plugin = new BasicConstraintsPlugin();
  plugin.onInit(system);
});Performance Considerations
- GPU-Optimized: All constraints run on the GPU
 - Efficient Grouping: Properties are grouped for optimal memory layout
 - Minimal Overhead: Plugin adds minimal computational overhead
 - Scalable: Performs well with large particle counts
 - Memory Efficient: Reuses textures and materials where possible
 
Troubleshooting
Plugin Not Working
- Ensure 
onInit()is called before adding particles - Call 
onUpdate()in your render loop - Verify the particle system is properly initialized
 
Poor Performance
- Check particle count - reduce if necessary
 - Monitor FBO texture sizes
 - Consider disabling unused features
 
Mouse Interaction Issues
- Verify canvas mouse coordinates are correct
 - Check camera setup for raycasting
 - Ensure the raycast plane is properly positioned
 
Particles Not Moving
- Check that forces are being applied
 - Verify velocity constraints are active
 - Ensure time uniforms are being updated