From: ellman AT xs4all DOT nl () Newsgroups: comp.os.msdos.djgpp Subject: Allegro Spheres (was: Re: Z-bufering) Date: 3 Apr 1997 21:36:53 GMT Organization: XS4ALL Message-ID: <5i17tl$h97$1@news0.xs4all.nl> References: <33414D32 DOT 147D AT geocities DOT com> <5htheu$cf0$1 AT news0 DOT xs4all DOT nl> <33433811 DOT 455 AT cam DOT org> NNTP-Posting-Host: xs2.xs4all.nl Lines: 63 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp In article <33433811 DOT 455 AT cam DOT org>, Tudor wrote: >ellman AT xs4all DOT nl wrote: >> PS. I've just written some code to draw a sphere lit from a single >> lightsource, but it's too slow, >1) How did you produce the sphere? I was thinking how the **** you can >automatically make one, like give it the center ,radius, number of >"stripes" and then it builds itself. But no luck so far... The spheres I'm using don't have "stripes". They're real spheres. The function is given the x, y, z co-ordinates of the sphere in screen-space, the radius, the light-source vector, the mimimum intensity colour, and the maximum intensity colour (this corresponds to the GCOL type polygon in Allegro). I could expand it to have multiple lightsources of different colours, but that will slow it down too much, as a dot product is done once for every pixel for every lightsource. What I've done is pinched the filled circle drawing code from Allegro's implementation and modified the bit that draws the horizontal lines of pixels. For each pixel in the sphere, the negative Z value is calculated using the equasion z^2=r^2-x^2-y^2 (I could also use Hardenburgh's circle algorithm, but that only gives integer Z values, which are less accurate than fixed or floating Zs which come in handy for Z buffering). I have used Allegro's lookup-table sqare-root function and pre-calculated r^2-y^2. Using that Z and the X and Y, I get the vector from the middle of the sphere to the point I've just calculated. This is divided by the radius (or multiplied by 1/radius which can be calculated outside the loop) to get the unit vector (the Y component is normalised outside the loop for drawing a line of pixels). I then take the dot product of this vector and the reversed unit light direction, and this gives us the intensity of light for each point. This intensity is normalised to [0..1] by doing (result_of_dot_product>>1) + (1<<15) The colour of the sphere pixel (using the mode that corresponds to POLYTYPE_GCOL) is calculated by dark_colour + (light_colour-dark_colour)*intensity. It's up to the programmer to set up the palette correctly with a smooth colour gradiend (and perhaps a gamma corrected). When I get round to doing the POLYTYPE_RGB version, gamma-correction could mean serious CPU usage. The implementation of the algorithm I described is turns out to be slow, and on a 100MhZ pentium, it takes a few frames just to draw a sphere of radius 100. I have speeded up the algorithm by mirroring the calculated Z value in the X and Y axes, but that just speeds up Z value calculation, and I still have to do a dot product for each point. >2) About textures..that seems a tough one. Thinking you'll have dozens >or hundreds of polys in a sphere you'll gonna have to find a smart algo >to texturing it... Something like Quake's skins? (like you have a single >bitmap for the guy and the engine will know how to wrap it up around >him..) It's even tougher for 'real-spheres' :-( AE. -- Andrei Ellman - URL: http://www.xs4all.nl/~ellman/ae-a - ae1 AT york DOT ac DOT uk "All I wanna do is have some fun :-) || ae-a AT minster DOT york DOT ac DOT uk I've got the feeling I'm not the only one" || mailto:ellman AT xs4all DOT nl -- Sheryl Crow :-) || It's what you make of it.