pouët.net

How to do dot balls?

category: code [glöplog]
I know it's not 1993 anymore, but dot balls are still on my (very ling) list of "things I once wanted to do in real-time". Back then I pre-calced them and blitted them. But on the one hand I know that all those "x hundreds of pixel balls" where probably done diffrently and on the other hand but my current target platform hardly has any RAM left for that.

Any examples for me to learn from?
added on the 2011-06-29 10:15:56 by JAC! JAC!
long time ago, i did "realtime" dotballs in Qbasic through drawing a spiral, but in the form of a sphere.... The other approach, and the slightly faster one was to draw dot circles with different diameters.
added on the 2011-06-29 13:22:13 by Exin Exin
we need a dot balls tutorial.
added on the 2011-06-29 15:52:46 by zerkman zerkman
Are you talking about vectorballs/bobs, or spheres made up of dots?
added on the 2011-06-29 16:11:31 by phoenix phoenix
pixel, sprite.. who cares :) "draw x on position y". adok, some wise words bitte!
added on the 2011-06-29 16:20:03 by superplek superplek
I should have written dot sphere, right. A sphere mde of dots in 3d, maybe with projection and z<0 detection and rotation around 2 or 3 axis. Dots may be spread regular or like this BB Image
added on the 2011-06-29 17:17:27 by JAC! JAC!
Assuming you have some kind of x/y/z 3D rotation routine already, here's how you'd set up a bunch of random points on a sphere (rnd being the good ol' basic function to generate a random number from 0 to 1 :):

Code: for p = 1 to points angle = rnd * 2 * pi ' put dot somewhere on a 2D circle x(p) = cos(angle) * radius y(p) = sin(angle) * radius ' rotate dot along a circle facing the x-axis of radius y(p) zangle = rnd * 2 * pi z(p) = cos(zangle) * y(p) y(p) = sin(zangle) * y(p) next p


and here's something to distribute the points evenly:

Code: for p = 1 to longpts * latpts angle = (pi / longpts) * ((pi - 1) mod longpts) x(p) = cos(angle) * radius y(p) = sin(angle) * radius zangle = ((2 * pi) / latpts) * ((p - 1) \ longpts) z(p) = cos(zangle) * y(p) y(p) = sin(zangle) * y(p) next p


err.. roughly at least.
added on the 2011-06-29 18:02:05 by phoenix phoenix
2nd box edit: (p - 1), not (pi - 1)
added on the 2011-06-29 18:04:02 by phoenix phoenix
Or, if we're talking about an oldskool platform where this sort of thing matters: you can save a few multiplications by treating each point on the sphere as a rotation of (1,0,0) - i.e. just add a random (or regular) offset per point to your angles when doing the rotation, rather than plotting them in 3D space in advance.
added on the 2011-06-29 18:33:01 by gasman gasman
Many dotballs on the Atari ST (and some were nice) were made with rotation around the vertical axis only. This saves a lot of time (no muls at all if i'm correct, only table lookup).
added on the 2011-06-29 18:36:25 by baah baah
Breaking it made it a lot more interesting:

http://studio.sketchpad.cc/sp/pad/view/yldXhh44XZ/latest
added on the 2011-06-29 18:36:48 by visy visy
Lol, at first I thought this was a spin off of Adok's article :)

I was also wondering about this effect and how to do it on the CPC (even if it has been done once in unique iirc, though not a complete sphere with many many of them :)

I was searching along the lines of a different approach, not just do regular 3d rotations of points in a sphere, because I thought the insistence of this kind of dot objects was there for a reason, for example one approach I was thinking, having precalced x,y coordinates in an order that goes along in a theta,phi spherical like coords grid, so that you can "scroll" the pattern of random dots (or also text forming dots like in Unique or any bitmap you like on your balls XD) in their new directions and get the x,y coords very fast without real rotation.

Yet I was too lazy to try back then :P
added on the 2011-06-29 18:44:49 by Optimus Optimus
JAC!: on what platform?
added on the 2011-06-29 19:50:09 by rudi rudi
The table lookup is my current plan (1 axis only, hard enough for the platform). But thinking about the symmetrie, I thought there is some well know optimization so I can stay with some add/sub and a reasonable table size.

@rudi: Very oldschool but If I tell, I'll spoil the compo ;-)
added on the 2011-06-29 20:08:34 by JAC! JAC!
JAC!: ok, maybe you've looked into harmonic oscillators.
added on the 2011-06-29 20:46:48 by rudi rudi
If you do a dot-sphere with evenly distributed dots, and then skip the 3d-projection (balls tend to look OK even without it) you can get away with some serious optimizations using mirroring.
added on the 2011-06-29 21:18:15 by Sdw Sdw
Still on the ST, quite cool effect showing objects with only one axis of rotation but morphing between objects can be seen here:
http://pouet.net/prod.php?which=15439
added on the 2011-06-29 21:51:53 by baah baah
I think you can have (x;y) and (-x;y) plotted in different colors (back/front) without any visual hint of it. Thus you only need half a sinus table before looping, which gains space too.
added on the 2011-06-29 21:54:43 by baah baah
Assuming phoenix notation.

for p = 1 to points
tmpX = rnd - .5 // tmpX in ]-.5, .5[
tmpY = rnd - .5 // tmpY in ]-.5, .5[
tmpZ = rnd - .5 // tmpZ in ]-.5, .5[
d = radius / sqrt(tmpX*tmpX + tmpY*tmpY + tmpZ*tmpZ) // d is radius / norm(vect(tmpX, tmpY, tmpZ)
x(p) = tmpX * d;
y(p) = tmpY * d;
z(p) = tmpZ * d;
// p coord is : vect(tmpX, tmpY, tmpZ) * radius / norm(vect(tmpX, tmpY, tmpZ))
// so norm(p) = radius
next p


With this method :
- the point repartition is homogeneous unlike phoenix method. (more point on poles)
- you only have one "/" and one "sqrt" instead of 4 trigonometric calls.


Maybe I say shits
added on the 2011-06-30 09:56:52 by Orace Orace
FFFUUUU

Code: for p = 1 to points tmpX = rnd - .5 // tmpX in ]-.5, .5[ tmpY = rnd - .5 // tmpY in ]-.5, .5[ tmpZ = rnd - .5 // tmpZ in ]-.5, .5[ // d = radius / norm(vect(tmpX, tmpY, tmpZ)) d = radius / sqrt(tmpX*tmpX + tmpY*tmpY + tmpZ*tmpZ) // p = vect(tmpX, tmpY, tmpZ) * radius / norm(vect(tmpX, tmpY, tmpZ)) // so norm(p) = radius x(p) = tmpX * d; y(p) = tmpY * d; z(p) = tmpZ * d; next p


You also can use simple coordinate rotation :

Code: for p = 1 to points by 48 tmpX = rnd - .5 // tmpX in ]-.5, .5[ tmpY = rnd - .5 // tmpY in ]-.5, .5[ tmpZ = rnd - .5 // tmpZ in ]-.5, .5[ // d = radius / norm(vect(tmpX, tmpY, tmpZ)) d = radius / sqrt(tmpX*tmpX + tmpY*tmpY + tmpZ*tmpZ) // p = vect(tmpX, tmpY, tmpZ) * radius / norm(vect(tmpX, tmpY, tmpZ)) // so norm(p) = radius tmpX = tmpX * d; tmpY = tmpY * d; tmpZ = tmpZ * d; p[1 to 8] = (+/-) tmpX, (+/-) tmpY, (+/-) tmpZ p[9 to 16] = (+/-) tmpX, (+/-) tmpZ, (+/-) tmpY p[16 to 24] = (+/-) tmpY, (+/-) tmpX, (+/-) tmpZ p[24 to 32] = (+/-) tmpY, (+/-) tmpZ, (+/-) tmpX p[32 to 40] = (+/-) tmpZ, (+/-) tmpX, (+/-) tmpY p[40 to 48] = (+/-) tmpZ, (+/-) tmpY, (+/-) tmpX next 48 p


But the result can be to mush regular
added on the 2011-06-30 10:04:19 by Orace Orace
1 pass.
1 points and is 47 symmetry.
OK
BB Image


Different POV.
To much regular.
BB Image


3 pass. 3x48 points.
To mush regular.
BB Image


48 pass without any symmetry.
Nice
BB Image

3x48 pass without any symmetry.
Very Nice
BB Image
added on the 2011-06-30 10:45:33 by Orace Orace
NIAN NIAN

Code: private FloatBuffer buildData(double radius, int passNumber) { double[] signs = new double[] {-1, 1}; FloatBuffer dataBuffer = FloatBuffer.allocate(passNumber * 48 * 4); dataBuffer.rewind(); for (int i = 0 ; i < passNumber ; i++) { double x = Math.random() - .5; double y = Math.random() - .5; double z = Math.random() - .5; double d = radius / Math.sqrt(x * x + y * y + z * z); x *= d; y *= d; z *= d; for (double xSign: signs) { for (double ySign: signs) { for (double zSign: signs) { for (int perm = 0 ; perm < 6 ; perm++) { float[] value = getPerm(perm, (float) (xSign * x), (float) (ySign * y), (float) (zSign * z)); dataBuffer.put(value); // put X,Y,Z dataBuffer.put(1); // put W = 1 } } } } } dataBuffer.rewind(); return dataBuffer; } private float[] getPerm(int perm, float x, float y, float z) { switch (perm) { case 0: return new float[] {x, y, z}; case 1: return new float[] {x, z, y}; case 2: return new float[] {y, x, z}; case 3: return new float[] {y, z, x}; case 4: return new float[] {z, x, y}; case 5: return new float[] {z, y, x}; default: return new float[] {x, y, z}; } }
added on the 2011-06-30 10:50:23 by Orace Orace
http://mathworld.wolfram.com/SpherePointPicking.html

Another easy way to pick a random point on a sphere is to generate three ***Gaussian** random variables x, y, and z. Then the distribution of the vectors [x; y; z] / sqrt(x^2+y^2+z^2) is uniform over the surface S^2 (Muller 1959, Marsaglia 1972).


BB Image
added on the 2011-06-30 11:09:04 by Orace Orace
Thanks for all the responses. Actually the creation of the pixel distribution was not my intend question, but how to do the rotation itself with minimum of computing/RAM, based on the symmetrie. Today I'll leave for my vacation and so I'm look forward to some coding when I'm back ;-)
added on the 2011-07-01 16:07:57 by JAC! JAC!
Hey Jac, here is how to do it:

- you only have to calculate the rotation of one half circle
- you can mirror this through the center to get a full circle (swap x,y)
- you can use this full circle to build the ball
- calculate the rotation of a vector perpendicular to the center of the main circle
- scale this vector
- scale the circle to smaller versions with tables
- use the vector to offset the smaller circle versions
added on the 2011-07-01 18:15:36 by Oswald Oswald

login