# pouët.net

## oldschool effects

category: code [glöplog]

Hi all sceners

Just watching old cool demos by TBL, Orange, Aardbei. How to do these effects:

1. How to move particle in funky way like in deesbab/orange https://postimg.org/image/mhw8ij9t7/ I know how to do simple particle system and move particles, but how to move them way like in Orange demos?

2. How to create 3D shape like in please the cookie thing/aardbei https://postimg.org/image/cd029y9e3/ or astral blur/tbl https://postimg.org/image/gwu9idb57/

Any hints, equations, links will be much appreciated!
There's lots of code examples in http://glslsandbox.com/
In both cases the answer is as simple as: Sinus!

1.) Move your particles in a circle, pseudocode:
Code:``` for(i=Particles.arraySize;i>0;i--) { Particles[i].pos.x = sin(time + i/Particles.arraySize*PI*2); Particles[i].pos.y = cos(time + i/Particles.arraySize*PI*2); } ```

Now the funky way, pseudocode:
Code:``` for(i=Particles.arraySize;i>0;i--) { Particles[i].pos.x = sin(time + i/Particles.arraySize*PI*2) + 0.2f*sin(time * 0.7f+i*.5) + 0.1f*cos(time * 0.6f+i*.4) + 0.1f*cos(time * 0.5f+i*.6); Particles[i].pos.y = cos(time + i/Particles.arraySize*PI*2) +0.2f*sin(time * 0.2f+i*.7) + 0.1f*sin(time * 0.3f+i*.8) + 0.1f*sin(time * 0.4f+i*.9); } ```

Add 3rd Dimension Z and done.

2.) Same thing, except you iterate over your vertices instead of particles and alter the position of each...for morphing objects, do this every frame, for static deformed objects just do it at generation of object, given you generate the vertex-data yourself for a simple sphere, like this: sphere-code
Quote:
In both cases the answer is as simple as: Sinus!

isnt that the answer to like... any "oldschool" effect? :o)
i was also wondering about that astralblur image, if it shows isosurface or if its just sines as well :P but yes. one can add and multiply sines together to get any kind of wobbling effect, but remember to tweak phase, amplitude and angle for each component and axis.
i just watched the astral demo now, and from what i can see its most likely rendering the triangles with the marching cubes algorithm, because we see the metaballs right after that scene. so the surface in that screenshot is not squareroots to get isoblobs, but sines or something else to get it too look like that slimy blob-thingy.
Quote:
I know how to do simple particle system and move particles, but how to move them way like in Orange demos?

Not an exact science, I think, you need to fiddle around a bit. But the gist of it is to use index, time and screen positions creatively at once per particle. This way you can add some local acceleration, scaling or color shifts to make things look less stale. Maybe start by adding a simple "+sin(t+i*10)" to your movement sinus and go from there.
Geiss has some fine pointers on that. Another nice one is inverting your blob surface (and potentially scrolling/interpolating through slices) to get that metaballs-from-inside-tunnel.
Also, particles like in later Orange demos were based on actual emitters (first and last) and IFS (middle), but very nicely executed (blur, motion, colors, amount) et cetera. But no rocket science. In fact that whole demo is a showcase of nicely executing effects, look at the 2D bitmap FX.
Wouldn't the one in deesbab be a trefoil knot or something like that that's being twisted and rendered as particles?

You can create something similar to the morphing shape by creating a sphere and wobbling it. A simple way is to use spherical coordinates something like this:

Code:``` for (float u = 0.f; u < PI; u += PI / 128) { for (float v = 0.v; v < 2 * PI; v += PI / 128) { vector3 vertex = vector3(sinf(u) * sinf(u), sinf(u) * cosf(u), cosfu)); //unit sphere float radius = 1.0 + 0.3f * sin(u * some_nice_value1 + time * speed1) + 0.2 * cos(v * some_nice_value2 + time * speed2) + 0.1 * sin(u * some_nice_value3 + v * some_nice_value4 + time*speed3); vector3 point = vertex * radius; draw(point); } } ```

This is a very classic effect in demos. You'd also need to connect all the points created like this into a triangle mesh, but I'll leave that as an exercise ;)
As a sidenote, here are some specific math things that you can google that will help you with figuring out how some classic effects work:

1) TNB-Frame (or Frenet-Serret-frame). This is for orienting things in 3d space. It's a set of three vectors that will basically point forward, up, and sideways. For the deesbab thing for example, you'd define a path (using sines or splines or whatever), and from the path you can calculate the three directions. Then you could project a ring of points alongside the "up" and "sideways" vectors. You can also make growing tubes this way if you connect the points you calculated with polygons. And, if you put your camera inside this, you have a tunnel!

2) Splines, particularly Catmull-Rom and Bezier. With these, you can define a set of points in 3d space and calculate a curve that goes through all of them. There are different splines for different purposes with different parameters and qualities, but Catmull-Rom is particularly "friendly" and easy-to-use.

3) Marching Cubes. It's used for polygonizing a scalar field, ie. you have a some function that tells you the density of something in space. Then, when you run it through the marching cubes algorithm, you get a polygon mesh out of it. There are many uses for this, but the classic metaballs effect stands out.

4) Raytracing. Nowadays you can do all kinds of cool things with casting rays and figuring out where they go, because you have lots of processing power.

And of course, linear algebra (vectors and matrices) is essential for all computer graphics.
1) Vortex effect.
2) What it is.
3) My love.
Code:``` static GLfloat vdata = { {-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z}, {0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X}, {Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0} }; static GLuint tindices = { {0, 4, 1}, {0, 9, 4}, {9, 5, 4}, {4, 5, 8}, {4, 8, 1}, {8, 10, 1}, {8, 3, 10}, {5, 3, 8}, {5, 2, 3}, {2, 7, 3}, {7, 10, 3}, {7, 6, 10}, {7, 11, 6}, {11, 0, 6}, {0, 1, 6}, {6, 1, 10}, {9, 0, 11}, {9, 11, 2}, {9, 2, 5}, {7, 2, 11} }; void normalize(GLfloat *a) { GLfloat d=sqrt(a*a+a*a+a*a); a/=d; a/=d; a/=d; } void drawTri(GLfloat *a, GLfloat *b, GLfloat *c, int div, float r) { if (div<=0) { glNormal3fv(a); glVertex3f(a*r, a*r, a*r); glNormal3fv(b); glVertex3f(b*r, b*r, b*r); glNormal3fv(c); glVertex3f(c*r, c*r, c*r); } else { GLfloat ab, ac, bc; for (int i=0;i<3;i++) { ab[i]=(a[i]+b[i])/2; ac[i]=(a[i]+c[i])/2; bc[i]=(b[i]+c[i])/2; } normalize(ab); normalize(ac); normalize(bc); drawTri(a, ab, ac, div-1, r); drawTri(b, bc, ab, div-1, r); drawTri(c, ac, bc, div-1, r); drawTri(ab, bc, ac, div-1, r); //<--Comment this line and sphere looks really cool! } } void drawSphere(int ndiv, float radius=1.0) { glColor3f(0.0f, 0.0f, 0.0f); glBegin(GL_TRIANGLES); for (int i=0;i<20;i++) drawTri(vdata[tindices[i]], vdata[tindices[i]], vdata[tindices[i]], ndiv, radius); glEnd(); } ```