I want to create a the ability to 'draw' particles. Is there a way to make particles follow a path?

  • Hi Dplatz,

    Yes, this is possible :)

    First we can use the TouchComponent to figure out where the user is tapping.

    var event = script.createEvent("TouchStartEvent");
    event.bind(function(eventData)
    {
        var touchedPos = eventData.getTouchPosition();
        print("touch started at " + touchedPos.x + " " + touchedPos.y);
    });

    Take a look at https://lensstudio.snapchat.com/api/classes/TouchStartEvent/ for more information.

    Then, we can use a script to generate particles in world space. Take a look at this guide to see an example of spawning particles based on an object's position: https://lensstudio.zendesk.com/hc/en-us/community/posts/360012401863/comments/360000612463

    Can't wait to see what you come up with!

    Cheers,

    Jon

    Comment actions Permalink
  • Thanks Jon!

    This is really cool! That world particle guide is great. I've got the default fountain to move and generate particles around in the scene but it doesn't work in the camera preview.

    Where should I be putting the TouchComponent to make this work when I tap and hold in the preview?

    Do I need to link the TouchComponent to the WorldParticleController some how?

    Thanks again for your help :)

    Dom

     

    Comment actions Permalink
  • Glad to hear Dom!

    What the WorldParticleController does is copy the particle system and leaves it at the last position it was at every frame. 

    So, if you wanted to be able to move the particles in the Preview panel, you can add a manipulate component and a touch component to your particle system.

    Then the WorldParticleController script will take care of leaving a particle trail for you!

    By default the manipulate component is designed for an object on a surface. Take a look at this guide if you want to manipulate the object in screen space. https://lensstudio.zendesk.com/hc/en-us/community/posts/115020451423/comments/115005538003

    Don't forget to share what you come up with!

    Jon

    Comment actions Permalink
  • Hey Jon,

    Thanks for all your help!

    I've looked at that guide but I seem to only be able to move the particles in space if the camera is 90 degrees on the X axis. In this case, the particles are flying into the camera. Is there a way to make it like your above demonstration?

    Also, the particles on mine are emitting constantly and i have to 'grab' the particle emitter to drag. Is it possible for the particles to only start emitting when I tap and hold anywhere on the screen? So the screen is blank to begin and it starts from any tap position?

    Thank you again!

    Dom

    Comment actions Permalink
  • Hi Dom,

    Glad to hear! In this case we can use the touch position to make our own manipulate system (so we don't have to "grab" an object). 

    Since we want the user to be able to touch anywhere, we can enable touchBlocking with no Touch Component so that every screen tap is registered. 

    global.touchSystem.touchBlocking = true;

     

    Then, we can create a touch event that detects anytime the user moves their finger on the screen. We can take the position of the user's finger in screen space and calculate a world position that is equivalent to set an object to. 

    // Call this function every time the user touches the screen and moves their finger
    var event = script.createEvent("TouchMoveEvent");
    event.bind(function(eventData)
    {
    // Get the screen space position where a user touched.
    var touchedPos = eventData.getTouchPosition();

    // Convert screen space position to world space
    var objPos = script.camera.screenSpaceToWorldSpace(touchedPos, 40.0)

    // Apply the calculated position to an object
    script.obj.getTransform().setWorldPosition(objPos)
    });

    The second argument to screenSpaceToWorldSpace refers to the z position you want the world space to be in. Because by default the camera's position is -40, I set this to 40 so that the world space position is at 0. However you may want to try different numbers based on your scene set up. 

    Finally, I take the calculated position and apply it to my object. In this case, the particle object. 

     

    Let me know how it goes!

    Jonathan

     

    Final code looks something like:

    // The camera used to render the scene
    // @input Component.Camera camera

    // The object we want to move around
    // @input SceneObject obj

    // intercept every screen touch
    global.touchSystem.touchBlocking = true;

    // Call this function every time the user touches the screen and moves their finger
    var event = script.createEvent("TouchMoveEvent");
    event.bind(function(eventData)
    {
    // Get the screen space position where a user touched.
    var touchedPos = eventData.getTouchPosition();

    // Convert screen space position to world space
    var objPos = script.camera.screenSpaceToWorldSpace(touchedPos, 40.0)

    // Apply the calculated position to an object
    script.obj.getTransform().setWorldPosition(objPos)
    });

     

     

     

     

    Comment actions Permalink
  • Thanks Jon, this is perfect!

    Exactly what I was wanting to achieve.

    I'm just wondering if there is a way for the particles to fade away after you've drawn the path?

    I would like it so when I take my finger off the screen, the particles stop. 

     

     

    Comment actions Permalink
  • Hi Dom,

    Take a look at this previous guide which demonstrates fading in and out the particle by reducing particle count over time. 

    https://lensstudio.zendesk.com/hc/en-us/community/posts/360014138263/comments/360000668086

    Cheers!

    Jon

    Comment actions Permalink
  • Hey Jon,

    That works perfectly but unfortunately I can't seem to get all 3 scripts to work together.

    I can't seem to get the fade in script and the above 'draw particle' script that you wrote to work together.

    Do you mind having a look at my set up and see if there's something I'm missing?

    Thanks again!

    Dom

     

     

    Comment actions Permalink
  • Hi Dplatz!

    Were you able to figure it out? Ya you might have to do some wrangling since the scripts were not designed to perfectly work together. If you still need some help, do you mind uploading your project so I can take a look at what the issue is?

    Thanks in advance!

    Jon

    Comment actions Permalink
  • Hey Jon!

     

    No sorry, I couldn't figure it out. You're right though, I think it just needs some wrangling and it will work a charm!

    https://drive.google.com/drive/folders/13MuzZGDnXl2_JJna9pSg3snGXMLfqHrJ?usp=sharing 

    Appreciate all your help Jon!

    Thanks,

    Dom

     

    Comment actions Permalink
  • Hi Dplatz,

    One way to do this is to use spawnMaxParticles (as in the last linked guide) as a way to fade away the particles and disable them when the particle is faded. Similarly instead of adding the particles based on time, we can add particles based on whether user is touching the screen or not. 

    For example: in the updateWorldParticles function in WorldParticleController.js we can reduce the number of spawnMaxParticles every frame and then disable them once it reaches 0 to create a fading effect. 

    // Update all particle system's time
    for (var i = 0; i < script.maxParticleSystems; ++i) {
    var timeOffset = startTimes[i];
    var obj = instances[i];
    var pass = matPasses[i];

    pass.spawnMaxParticles -= 8;

    if (pass.spawnMaxParticles < 0) {
    obj.enabled = false;
    }

    }

    Now, when we spawn the particle we just need to set their spawnMaxParticles back to our original particle count:

    // Restart particle system's position at current pos as needed
    if (global.touching) {
    var currentPos = script.particle.getTransform().getWorldPosition();
    var index = nextSpawnIdx % script.maxParticleSystems;
    var instance = instances[index];

    startTimes[index] = currentTime;
    matPasses[index].spawnMaxParticles = 100;

    instance.enabled = true;
    instance.getTransform().setWorldPosition(new vec3(currentPos.x,currentPos.y,currentPos.z));

    nextSpawnIdx++;
    }

    You'll notice here I am checking for global.touching

    What we want to do is tell this script that user is touching the screen and when they've stopped. In ParticleMover.js, you can use TouchStartEvent and TouchEndEvent to manage this status:

    var event = script.createEvent("TouchStartEvent");
    event.bind(function(eventData)
    {
    global.touching = true;
    });

    var event = script.createEvent("TouchEndEvent");
    event.bind(function(eventData)
    {
    global.touching = false;
    });

    Finally, one thing you might want to do, is get where the user touch and move the object to that position (as you did in the TouchMoveEvent) also in the TouchStartEvent, since you want the particle to instantly appear where the user touches, rather than when they start moving their finger. 

     

    Let me know how it goes, can't wait to see the result :)

     


     

    Comment actions Permalink
  • Hey Jon,

    Thanks so much for helping out!

    I can't seem to move the particles now. Sorry, are you able to provide the full scripts?

    I think somewhere along the way of chopping and changing, I'm editing out something important!

    Thanks so much!

    Comment actions Permalink
  • I appreciate this solution, but Snap just needs to add a world space / local space option on the emitter so it emits either parented or not. Every particle system in real game engines have this feature and it's easy to implement at a lower level.

    Comment actions Permalink
Have a comment?

Please sign in to leave a comment.

We're here to help! We just need a little bit of information...

What system are you using?

Have you downloaded the latest version of Lens Studio?

Please download the latest version of Lens Studio. If you still run into this issue, please come back and report it!

Is this issue causing Lens Studio to crash?

What system do you run Lens Studio on?

Version

Graphics

Follow the next steps to help us solve your issue:

  • Copy and paste this text into your TerminalCommand Window
    open ~/Library/Preferences/Snap/Lens\ Studio/ %LOCALAPPDATA%\Snap\Lens Studio Copy Text
  • Press ReturnEnter to run the command. The Lens Studio folder will automatically open
  • Prepare to upload your files: zip the "Log" Folder by right-clicking and choosing "compress."
    Locate the Log.txt file right above it.

    Attach a screenshot of the issue:

Name:

Email:

What is this most relevant to?

Please enter a brief description of your issue:

Thanks for submitting this issue.

Unfortunately, it's likely due to the operating system or hardware you're using – since they don't meet the system requirements for Lens Studio.

Still, we hear you loud and clear, and are logging the issue in case there's ever a workaround we can provide!

Minimum Requirements

Operating System: Windows 10 (64 bit); MacOS 10.11+

Hardware: Minimum of Intel Core i3 2.5Ghz or AMD Phenom II 2.6Ghz with 4 GB RAM; Intel HD Graphics 4000 / Nvidia GeForce 710 / AMD Radeon HD 6450 or better; screen resolution of 1280x768 or higher

We'll try to resolve this issue as soon as possible. Thanks for letting us know about it!

Keep an eye out for a followup email from us. We may have a couple more questions for you, or we might already have a solution to offer.

Happy creating!