Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grid Emitter: Thickness option #100

Open
afrokick opened this issue Dec 13, 2024 · 2 comments
Open

Grid Emitter: Thickness option #100

afrokick opened this issue Dec 13, 2024 · 2 comments

Comments

@afrokick
Copy link

Hey! Would be nice to have thickness for Grid Emitter!

Value 0 means emitting on edges.
Value 1 - emitting from full square/volume.

Value between 0 and 1 means the thickness of borders.

For instance, thickness = 0.4:

Screenshot 2024-12-13 at 11 10 46
  • Green Area: emitting area
@ManHunter
Copy link

I will support you.
I think in this case it would be cool to add a new type of emitter: Rectangle: {width: number, height: number, thickness: number}

@ManHunter
Copy link

Here is an example of a custom EmitterShape:

import {
    ConstantValue,
    EmissionState,
    EmitterMode,
    EmitterShape,
    FunctionValueGenerator,
    GeneratorMemory,
    IParticleSystem,
    Particle,
    ShapeJSON,
    ValueGenerator,
    ValueGeneratorFromJSON
} from "three.quarks";

/**
 * Interface representing the parameters for a rectangle emitter.
 */
export interface RectangleEmitterParameters {
    /**
     * The width of the rectangle.
     */
    width?: number;
    /**
     * The height of the rectangle.
     */
    height?: number;
    /**
     * The thickness of the ring.
     * 1 is a full rectangle, 0 is a ring with 0 radius.
     */
    thickness?: number;
    /**
     * The mode of the emitter.
     * {@link EmitterMode}
     */
    mode?: EmitterMode;
    /**
     * The length of segment of which emitter point converges at the start and end, when mode is EmitterMode.Loop or EmitterMode.PingPong.
     * {@link EmitterMode}
     */
    spread?: number;
    /**
     * The speed of the emitter start point travels when mode is EmitterMode.Loop or EmitterMode.PingPong.
     * {@link EmitterMode}
     */
    speed?: ValueGenerator | FunctionValueGenerator;
}

/**
 * a particle emitter that emits particles from a rectangle.
 */
export class RectangleEmitter implements EmitterShape {
    type = 'rectangle';
    width: number;
    height: number;
    thickness: number; // [0, 1]
    mode: EmitterMode;
    spread: number;
    speed: ValueGenerator | FunctionValueGenerator;
    memory: GeneratorMemory;

    private currentValue = 0;

    constructor(parameters: RectangleEmitterParameters = {}) {
        this.width = parameters.width ?? 10;
        this.height = parameters.height ?? 10;
        this.thickness = parameters.thickness ?? 1;
        this.mode = parameters.mode ?? EmitterMode.Random;
        this.spread = parameters.spread ?? 0;
        this.speed = parameters.speed ?? new ConstantValue(1);
        this.memory = [];
    }

    update(system: IParticleSystem, delta: number): void {
        this.currentValue += this.speed.genValue(this.memory, system.emissionState.time / system.duration) * delta;
    }

    initialize(p: Particle, emissionState: EmissionState) {
        const innerWidth = this.width * (1 - this.thickness);
        const innerHeight = this.height * (1 - this.thickness);
        const halfInnerWidth = innerWidth / 2;
        const halfInnerHeight = innerHeight / 2;

        let x, y;

        do {
            const randomX = Math.random();
            const randomY = Math.random();

            x = (randomX - 0.5) * this.width;
            y = (randomY - 0.5) * this.height;
        } while (Math.abs(x) < halfInnerWidth && Math.abs(y) < halfInnerHeight);

        p.position.x = x;
        p.position.y = y;
        p.position.z = 0;

        p.velocity.set(Math.random() - 0.5, Math.random() - 0.5, 0).multiplyScalar(p.startSpeed);
    }

    toJSON(): ShapeJSON {
        return {
            type: 'rectangle',
            width: this.width,
            height: this.height,
            thickness: this.thickness,
            mode: this.mode,
            spread: this.spread,
            speed: this.speed.toJSON(),
        };
    }

    static fromJSON(json: any): RectangleEmitter {
        return new RectangleEmitter({
            width: json.width,
            height: json.height,
            thickness: json.thickness,
            mode: json.mode,
            speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,
            spread: json.spread,
        });
    }

    clone(): EmitterShape {
        return new RectangleEmitter({
            width: this.width,
            height: this.height,
            thickness: this.thickness,
            mode: this.mode,
            speed: this.speed.clone(),
            spread: this.spread,
        });
    }
}

2024-12-13.13-19-07-453.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants