views:

353

answers:

3

I'm wondering about how you would implement an effect similar to this one implemented in flash. It would just be a black screen which, when the user touches and drags over it, produces an effect similar to the one seen in the flash movie.

What is this effect called? Do you have a better example?
One of my biggest problems is articulating exactly what it is I'm talking about. I need both a name for this type of effect as well as a video that can display what it is I'm talking about. This would help others understand the problem better.

The closest term I could think of which describes something similar is a pointer trail. The only difference being that instead of showing the cursor, it would show a solid trail that gently fades away. The website that made the flash example, calls it Particle Ghosting. Another example of it is in this YouTube video for HP, which shows the effect between 0:30 to 0:36. It starts out more like paint, but eventually turns into the fading trail effect.

If you have a better name for this effect or a better example, please mention it and I will update the post.

Which iPhone technology would be required?
OpenGL or Quartz 2D? I'm guessing core graphics is out of the question due to speed. Any other technology I'm missing? It needs to be fast enough without any lag. Assuming a trail that lasts about a second at any given point, there may be a considerable amount of animated pixels at the same time when the user moves their finger fast. Possibly even filling up most of the screen with pixels that need to be faded out. The effect should look very elegant, nothing like the choppiness of the pointer trail in XP.

How would it be implemented?
Ideally, I don't want the fadeout effect to be as rigid as it is in the flash example (where it's a perfect circle), and more like in the HP video where the fade out is more organic (where there are different fadeouts at every point in the trail).

Would I manipulate individual pixels directly? I.e. would I need to keep track of every pixel that the finger has moved over and call a function repeatedly such as PaintPixel(x, y, brightness) which modifies the RGB value of the pixel? This seems like an excessive amount of pixel modification and sounds like it would slow the whole system down. However, I have never done this kind of thing before, so I wouldn't know if this is how it's usually done. For example, let's assume that a single touch takes up 32x32 pixels. We have 32 x 32 = 1024 pixels for each touch. As the finger moves, an additional 1024 pixels will need to be animated, most of which are already overlapping with the previous touch. Assuming the finger passed over the height of the iPhone within a second, we're talking about 480 x 32 pixels = 15,360 pixels being updated many times a second.

Would I use a small video clip that fades from white to black and just generate a lot of instances of the video clip as the finger moves? I don't have a version of Flash that can open up the flash example, so I can't examine the source code of it, but I'm guessing that it's just creating new instances of video clips as the dot moves around. This gets a bit tricky for an organic fade out which would probably involve making several fade out video clips and randomly choosing one for each point.

Would I use a set of images (e.g. 100 or so circles each representing a touch which fades from solid white to black) and then create and replace instances of them as time progresses? For example, as the finger moves I would display touch100.jpg at that point, which represents pure white, and in the next iteration the same point would display touch99.jpg, then touch98.jpg, continuing until it reaches touch0.jpg, which represents pure black.

Any other ideas I'm missing?

I'm sorry if these ideas sound outlandish. As you can probably tell, I have never done anything similar to this before so I don't know what the usual way of implementing this kind of effect is and I'm just throwing out any idea I can think of.

Which resources would you recommend to learn how to implement this?
Is there any learning material you would recommend for someone trying to learn how to implement this kind of thing?

I don't want to spend a bunch of time learning one technology (e.g. Quartz) when I would need to know an entirely different technology to implement it (e.g. OpenGL).

Is there any other information I forgot to provide?
Are there any additional questions you would recommend I ask?

+1  A: 

I would do the following:

  • Create a bitmap onto which you will draw, call it your canvas
  • Create a image representing the trail, in your example a solid circle
  • Every frame draw this circle where the user currently has their finger
  • Also on every frame, apply a transform to the canvas which multiplies the alpha of each pixel by a value smaller than 1, ie 0.99

This will make everything that is on screen slowly fade, with the circles drawn most recently being most visible.

I've done similar things in Flash (dust behind a car) and it works pretty well

As for a technology, you could probably do this with Quartz, only if the performance was too bad would I switch to OpenGL

pheelicks
A: 

If you'd like to use OpenGL you can:

  1. Draw the trail out as an image, you'll need to experiment with sizes, but the trail image should have an alpha channel.
  2. Next add code to calculate a movement vector for your pointer.
  3. Now calculate a line perpendicular to the movement vector for your pointer.
  4. Create points that fall along the line that you calculated, these points should be offset from the position of your pointer (the distance depends on the size of your pointer).
  5. Store a buffer of the two points calculated above over time.
  6. Now, you'll use OpenGL to create a quad strip using the points in your buffer as vertices.
  7. Finally apply the trail image that you drew as a texture to the quad strip that you created.
jessecurry
+1  A: 

pheelicks has a good design, simple to implement, and it may work well. It has the disadvantage of having to re-calculate the entire screen every frame, which may be less efficient than would be optimal. I would propose the following design that may have better performance (or it may have worse performance; most performance things have to be tested to see).

For every circle, generate a non-opaque CALayer and attach it to your view. Assign its contents to be a pre-rendered circle CGImageRef. Attach a fade animation to it. Attach it to the view. Using an animation delegate, remove the layer when it completes its animation. I would probably then re-use the layer rather than destroying it and creating a new one. It already has your circle in it after-all, so reusing it should be extremely cheap. (EDIT: I was rethinking this; you don't even have to remove and re-add the layer, just move it to its new location, or hide it if you don't need it. You could make all these circles sub-layers of a "trail" layer if you wanted an easy way to remove the whole trail when it's not needed.)

The advantage of my scheme is that it only calculates pixels that matter, and relies on the iPhone's optimized drawing system to do the calculations. It can generate a large number of layers, but the system is designed to handle that (and the number of layers is fixed by your trail-length and frame-rate). The code should also be very simple.

Rob Napier