3dreamengine / 3DreamEngine

3DreamEngine is an *awesome* 3d engine for LÖVE.
MIT License
388 stars 17 forks source link

New drawParticle system vs. new one (with batches) #35

Closed thisnickwasfree closed 4 years ago

thisnickwasfree commented 4 years ago

Could you you return old drawParticle system as an alternative method? It was much simpler and had better functionality in some cases.

And as for the new one…

  1. I see no way to add time interval between frames (in old wan it was possible to change frames manually with custom rate, not the best variant, but it works).
  2. New PS has no controls for looping (and not looping) of the image sequence.
  3. There is no method for catching of the last frame and removing PS after playing.

So, the upgrading of the new system can help too.

Luke100000 commented 4 years ago

Could you you return old drawParticle system as an alternative method? It was much simpler and had better functionality in some cases.

The old system was CPU bound and needed replacement, but I will readd an simplier interface for non batched particles. Similar interface as love.graphics.draw provides.

Sadly I do not fully understand your question. You can switch the texture (PS.texture) and more importantly, you can use quads for animations etc. The looping part is not part if the PS itself. The Interface is designed to be similar to LÖVEs spritebatches.

Theoretically you have access to PS.instances, which contains the queued particles.

thisnickwasfree commented 4 years ago

Sadly I do not fully understand your question

Ok, look…

  1. Time interval. Usually we do not need to switch the frame any update, but once per 100 ms, 200 ms, 1 second, etc. Look at anim8 library for love2d, for example. In other words: I have a sequence from 9 quads, and I want to play the animation from this quads (particle system in 3Dreamengine's terms) during 3 seconds, for example. Or 5 seconds. Or any other time. So, I need to add a time interval between two frames as a param for newParticleBatch or drawParticleBatch.

  2. Loop. Sequence (particle system) consists of 9 quads (or 12, or 32 — does not matter). So, I can play it once (1 — 9 frames) or replay it every time after ending the animation (after playing last frame). And that's hard enough to calculate time of replay manually while it can be just a callback to the end of animation.

  3. After playing the animation (9 quads, for example), I want to clear screen from the particle system. The last frame/quad is not empty. So, callback for this needed: last frame played — calling clear function. Like a param for drawParticleBatch, for example.

thisnickwasfree commented 4 years ago

The old system was CPU bound and needed replacement Well, the main thing is not the old mechanism itself, but it's possibilities. If the new mechanism can do the same without problems of old one — that's good.

thisnickwasfree commented 4 years ago
  1. Has simple solution: dream:drawParticleBatch(self.ParticleSystem); self.ParticleSystem = nil;
Luke100000 commented 4 years ago

Sadly I do not fully understand your question

Ok, look…

1. Time interval. Usually we do not need to switch the frame any update, but once per 100 ms, 200 ms, 1 second, etc. Look at anim8 library for love2d, for example.
   In other words: I have a sequence from 9 quads, and I want to play the animation from this quads (particle system in 3Dreamengine's terms) during 3 seconds, for example. Or 5 seconds. Or any other time. So, I need to add a time interval between two frames as a param for newParticleBatch or drawParticleBatch.

2. Loop. Sequence (particle system) consists of 9 quads (or 12, or 32 — does not matter). So, I can play it once (1 — 9 frames) or replay it every time after ending the animation (after playing last frame). And that's hard enough to calculate time of replay manually while it can be just a callback to the end of animation.

3. After playing the animation (9 quads, for example), I want to clear screen from the particle system. The last frame/quad is not empty. So, callback for this needed: last frame played — calling clear function. Like a param for drawParticleBatch, for example.

Does this work?

PS:add(x, y, z, size, emission, quads[math.floor(time * FPS + optionalParticleID) % framesTotal + 1])

At this point note that we are talking about two different things. 3Dreams particles renders them, provides the shaders, mesh handling and optimizations stuff. What you want is an animator (e.g. anim8). You can for example use anim8 to animate your sprite, then draw it with 3Dream. animation:getFrameInfo() seems the right function, I never used anim8.

Since quite a lot of people use anim8 I might consider a small wrapper.

thisnickwasfree commented 4 years ago

Does this work?

I use something like this with old mechanism, but in new one I use for-cycle to add quads: old one variant with adding one quad per draw shows no animation.

Old variant:

self.progress = self.progress + 12.5 * dt;

local _quad = global.spell_effects[math.ceil(self.progress)]; dream:drawParticle(media.images[self.Effect], _quad, self.coordinates.x, self.coordinates.z, -1 * self.coordinates.y, self.Size, nil, 0.25);

New variant:

    if self.ParticleSystem then
        self.ParticleSystem:clear ();
        for i = 1, self.limit do
            self.ParticleSystem:add(self.coordinates.x,  self.coordinates.z + 0.5,  -1 * self.coordinates.y, 100* self.Size, 1, global.spell_effects[i]);
        end;
        dream:drawParticleBatch(self.ParticleSystem);
        self.ParticleSystem = nil;
    end;

New one looks almost ok, but speed of animation is too high.

What you want is an animator

May be. I was looking for a possibility to play 2d sprites in 3d space, and the particle system of 2DreamEngine looks like the proper functionality for this.

You can for example use anim8 to animate your sprite, then draw it with 3Dream.

Anim8 is a good library, but it's 2d. So, using it for 3d can cause additional troubles and calculations, I guess. I use it in current projects, bur osd-animations only.

But anyway, doesn't particle system need time-interval param itself? Of course there are other ways to get this result (duplicating of every quad while adding, for example), but they do not look good enough.

Luke100000 commented 4 years ago

Ah I think I get the confusion: 3Dream particles is NOT a particle system. It's a spritebatch. It only provides rendering.

But anyway, doesn't particle system need time-interval param itself

If it was a system, yes.

Anim8 is a good library, but it's 2d.

No, Anim8 does only animate. The actual drawing is done by love2d in a single line. So you can just swap this single line to 3Dream and its works too. The additional calculations are done by 3Dream anyways. I will put that in the docu soon.

thisnickwasfree commented 4 years ago

Ah I think I get the confusion: 3Dream particles is NOT a particle system. It's a spritebatch. It only provides rendering.

Yes, like here:

https://www.youtube.com/watch?v=ccMe82tpPx4&feature=youtu.be&t=3487

Or here:

https://youtu.be/d8kDM33Au4A?t=12

The second link — temp effects which are made with old «particle system». I can do the same with the new one, but I need to control the framerate of the batch. With this control I can ise, for eaxample, 9x9 or 1x12 image strips for 1 — 2 seconds of effects. As it was in old version.

Luke100000 commented 4 years ago

I am still unsure why the new system wont work since it covers the exact same behavior, just batched, but in any case you want and need a single function for this. It's on the way.

thisnickwasfree commented 4 years ago

I am still unsure why the new system wont work

It works. But… If it is batched, that'll be better to make something like this:

if self.ParticleSystem then
    self.ParticleSystem:clear ();
    for i = 1, 9 do
        self.ParticleSystem:add(x, y, z, scale, emission,quad);
    end;
            self.ParticleSystem:SetFrameInterval (100); -- 100 ms or any other units between frames
    dream:drawParticleBatch(self.ParticleSystem);
    self.ParticleSystem = nil;
end;

And not to count this interval manually as before. In old system I've done this manually, counting the index of the quad in a table at every update of draw function. Not the best way. So, if there are batches now, that'll be good to set their frame rate. How do switch the frames? One per update? But this is rare situation, I guess. Usually graphical resources has only a few frames and their frames should be switched once per custom time interval, not an update (which depends on CPU speed).

It's on the way.

That's really good.

thisnickwasfree commented 4 years ago

Hey, Luke100000, are you ok? Sorry for the question, but there are no news from you during last two months. And this situation is suspenseful due to the situation in the world at these days.

Luke100000 commented 4 years ago

Hey, Luke100000, are you ok? Sorry for the question, but there are no news from you during last two months. And this situation is suspenseful due to the situation in the world at these days.

Your concerns are very kind, don't worry, I'm fine :) I had a project to finish in the last days, am working on another game and started a major extension to 3Dream (Collada support and bone animations, GPU based, nearly done). However they turned out to be more difficult than I thought and destroyed my plans in terms of time schedule.

thisnickwasfree commented 4 years ago

Sounds good. Well, as for this topic. I`ve found the variant of using new particle system which makes what I need. And I've found out one strange thing: adding quad which was not created (for example, quad[10] for 1 — 9 quad sequence) will cause drawing of the whole quad-sheet (all frames that used graphical file has inside). That's not a real problem — it's easy to make limits inside user's code, just strange behavior.

Luke100000 commented 4 years ago

Sounds good. Well, as for this topic. I`ve found the variant of using new particle system which makes what I need. And I've found out one strange thing: adding quad which was not created (for example, quad[10] for 1 — 9 quad sequence) will cause drawing of the whole quad-sheet (all frames that used graphical file has inside). That's not a real problem — it's easy to make limits inside user's code, just strange behavior.

Since 3Dream is pure lua I can not tell if you supply nil or nothing, therefore it will behave as if there is no quad (since they are optional). Which will assume the entire atlas is the image. Therefore I can't fix this easily.

Luke100000 commented 4 years ago

Particle batches changed a bit and single particles have been added, they should cover your needs.