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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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 -
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
Please sign in to leave a comment.
Have a comment?