coy@ssc-vax.UUCP (Stephen B Coy) (03/29/89)
[...] Hi there, Last night I saw the article in Byte about the Renderman standard. In the sample source code the displacement function, dent(), calls a function called noise(). Noise() takes a point as its parameter and returns a float in the range 0..1. The article says this is a semi-random value that changes slowly over the surface of the object. My question: Does anyone out there know what this noise function really is? Are you willing to share this info/source with the rest of us? Please? Thanks in advance for any responses. Stephen Coy uw-beaver!ssc-vax!coy ps Anyone have any decent marble texture functions you'd like to share?
aaa@pixar.UUCP (Tony Apodaca) (03/30/89)
In article <2553@ssc-vax.UUCP> coy@ssc-vax.UUCP (Stephen B Coy) writes: > Last night I saw the article in Byte about the Renderman >standard. In the sample source code the displacement function, dent(), >calls a function called noise()... > ...My question: Does anyone out there know what this >noise function really is? Three-dimensional simulated natural textures using pseudorandom functions were simultaneously and independently developed by Darwyn Peachey and Ken Perlin in 1984-5. Both have papers in the 1985 Siggraph Proceedings describing their systems. Perlin, in particular, describes in detail how noise() is implemented and can be used creatively to describe large classes of natural phenomena. Conceptually, noise() is a "stochastic three-dimensional function which is statistically invariant under rotation and translation and has a narrow bandpass limit in frequency" (paraphrased from [Perlin1985]). This means that you put three-space points in, and you get values back which are basically random. But if you put other nearby points in, you get values that are very similar. The differences are still random, but the maximum rate of change is controlled so that you can avoid aliasing. If you put a set of points in from a different region of space, you will get values out which have "the same amount" of randomness. If you have ever been interested in realistic computer graphics, do whatever it takes to get a look at Perlin's paper. In 1985, his pictures were absolutely astounding. In 1989, they are STILL astounding. >ps Anyone have any decent marble texture functions you'd like to > share? Perlin's paper has a simple marble texture function: /* assume marble_color() is a color lookup table function */ float turbulence(point p) { float t=0, scale=1; while(scale > pixelsize) { t += abs(noise(p / scale)*scale); scale /= 2; } return t; } color marble(point p) { float x = xcomp(p) + turbulence(p); return marble_color(sin(x)); } -- UUCP: {sun,ucbvax}!pixar!aaa Tony Apodaca ARPA,BITNET: aaa%pixar.uucp@sun.com Pixar, San Rafael, CA, USA
bullerj@handel.colostate.edu (Jon Buller) (03/31/89)
In article <3599@pixar.UUCP> aaa@pixar.UUCP (Tony Apodaca) writes: >In article <2553@ssc-vax.UUCP> coy@ssc-vax.UUCP (Stephen B Coy) writes: >> ...My question: Does anyone out there know what this >>noise function really is? > > Three-dimensional simulated natural textures using pseudorandom >functions were simultaneously and independently developed by Darwyn >Peachey and Ken Perlin in 1984-5. Both have papers in the 1985 >Siggraph Proceedings describing their systems. Perlin, in particular, >describes in detail how noise() is implemented and can be used creatively [A description of the properties of the noise function goes here...] > If you have ever been interested in realistic computer graphics, do >whatever it takes to get a look at Perlin's paper. In 1985, his pictures >were absolutely astounding. In 1989, they are STILL astounding. No kidding, some of those pictures are INCREDIBLE. Here is my code for a look-alike to the Pixar Noise function, and while I can't say anything about exactly what Pixar's looks like, I think this is probably close. After reading the 1985 SIGGRAPH papers on 3d texturing, (and seeing my prof's code to do a similar thing) I wrote this. It uses a quadratic B-Spline instead of the cubic Hermite interpolant implied in the paper. Also note that DNoise is just the x, y, and z derivatives of Noise (which are also B-Splines). The hashing functions are from Knuth's Art of Computer Programming (I don't remember which volume though). I know the code is Pascal, and all of you will hate it, but I belive I write better Pascal than C... One final note, this was Lightspeed Pascal 2.0 for the Macintosh, but things have been reformatted slighly to get it on the net. I hope this is what you all wanted. Enjoy, Jon bullerj@handel.cs.colostate.edu ...!ncar!ccncsu!handel!bullerj (These are my ideas (and code), nobody else SHOULD want these bugs) I'm just trying to graduate. Apple, Pixar, HP, etc. take note, I would like your job offers, I have tired of the university life. (* ---------- cut here ---------- cut here ---------- cut here ---------- *) const MaxPts = 512; { Must be 2^n} MPM1 = MaxPts - 1; type PtsTyp = array[0..MaxPts] of Extended; var Points: PtsTyp; function Noise (Loc: Vect; Pts: PtsTyp): Extended; const P1 = 173; P2 = 263; {Reasonable numbers to (attempt to) avoid diagonal repetition} P3 = 337; phi = 0.618033988749894842; {phi = (Sqrt(5)-1)/2} var xi, yi, zi: Integer; xa, xb, xc, ya, yb, yc, za, zb, zc: Integer; xf, yf, zf: Extended; x2, x1, x0, y2, y1, y0, z2, z1, z0: Extended; p000, p100, p200, p010, p110, p210, p020, p120, p220: Extended; p001, p101, p201, p011, p111, p211, p021, p121, p221: Extended; p002, p102, p202, p012, p112, p212, p022, p122, p222: Extended; begin xi := Trunc(Loc[1]); xa := Trunc(P1 * (xi * phi - Trunc(xi * phi))); xb := Trunc(P1 * ((xi + 1) * phi - Trunc((xi + 1) * phi))); xc := Trunc(P1 * ((xi + 2) * phi - Trunc((xi + 2) * phi))); yi := Trunc(Loc[2]); ya := Trunc(P2 * (yi * phi - Trunc(yi * phi))); yb := Trunc(P2 * ((yi + 1) * phi - Trunc((yi + 1) * phi))); yc := Trunc(P2 * ((yi + 2) * phi - Trunc((yi + 2) * phi))); zi := Trunc(Loc[3]); za := Trunc(P3 * (zi * phi - Trunc(zi * phi))); zb := Trunc(P3 * ((zi + 1) * phi - Trunc((zi + 1) * phi))); zc := Trunc(P3 * ((zi + 2) * phi - Trunc((zi + 2) * phi))); p000 := Pts[BitAnd(xa + ya + za, MPM1)];{p000 := Pts[(xa+ya+za) mod MaxPts]} p100 := Pts[BitAnd(xb + ya + za, MPM1)]; p200 := Pts[BitAnd(xc + ya + za, MPM1)]; p010 := Pts[BitAnd(xa + yb + za, MPM1)]; p110 := Pts[BitAnd(xb + yb + za, MPM1)]; p210 := Pts[BitAnd(xc + yb + za, MPM1)]; p020 := Pts[BitAnd(xa + yc + za, MPM1)]; p120 := Pts[BitAnd(xb + yc + za, MPM1)]; p220 := Pts[BitAnd(xc + yc + za, MPM1)]; p001 := Pts[BitAnd(xa + ya + zb, MPM1)]; p101 := Pts[BitAnd(xb + ya + zb, MPM1)]; p201 := Pts[BitAnd(xc + ya + zb, MPM1)]; p011 := Pts[BitAnd(xa + yb + zb, MPM1)]; p111 := Pts[BitAnd(xb + yb + zb, MPM1)]; p211 := Pts[BitAnd(xc + yb + zb, MPM1)]; p021 := Pts[BitAnd(xa + yc + zb, MPM1)]; p121 := Pts[BitAnd(xb + yc + zb, MPM1)]; p221 := Pts[BitAnd(xc + yc + zb, MPM1)]; p002 := Pts[BitAnd(xa + ya + zc, MPM1)]; p102 := Pts[BitAnd(xb + ya + zc, MPM1)]; p202 := Pts[BitAnd(xc + ya + zc, MPM1)]; p012 := Pts[BitAnd(xa + yb + zc, MPM1)]; p112 := Pts[BitAnd(xb + yb + zc, MPM1)]; p212 := Pts[BitAnd(xc + yb + zc, MPM1)]; p022 := Pts[BitAnd(xa + yc + zc, MPM1)]; p122 := Pts[BitAnd(xb + yc + zc, MPM1)]; p222 := Pts[BitAnd(xc + yc + zc, MPM1)]; xf := Loc[1] - xi; x1 := xf * xf; x2 := 0.5 * x1; x1 := 0.5 + xf - x1; x0 := 0.5 - xf + x2; yf := Loc[2] - yi; y1 := yf * yf; y2 := 0.5 * y1; y1 := 0.5 + yf - y1; y0 := 0.5 - yf + y2; zf := Loc[3] - zi; z1 := zf * zf; z2 := 0.5 * z1; z1 := 0.5 + zf - z1; z0 := 0.5 - zf + z2; Noise := z0 * (y0 * (x0 * p000 + x1 * p100 + x2 * p200) + y1 * (x0 * p010 + x1 * p110 + x2 * p210) + y2 * (x0 * p020 + x1 * p120 + x2 * p220)) + z1 * (y0 * (x0 * p001 + x1 * p101 + x2 * p201) + y1 * (x0 * p011 + x1 * p111 + x2 * p211) + y2 * (x0 * p021 + x1 * p121 + x2 * p221)) + z2 * (y0 * (x0 * p002 + x1 * p102 + x2 * p202) + y1 * (x0 * p012 + x1 * p112 + x2 * p212) + y2 * (x0 * p022 + x1 * p122 + x2 * p222)); end; function Turb (Size: Integer; ScaleFactor: Extended; Loc: Vect; Pts: PtsTyp): Extended; var Scale, Result: Extended; Cur: Integer; begin Result := Noise(Loc, Pts); Scale := 1.0; Cur := 1; while Cur < Size do begin Cur := BSL(Cur, 1); {Cur := Cur * 2} Scale := Scale * ScaleFactor; Loc := Scale_Vect(2.0, Loc); Result := Result + Noise(Loc, Pts) * Scale; end; Turb := Result; end; function DNoise (Loc: Vect; Pts: PtsTyp): Vect; const P1 = 173; P2 = 263; P3 = 337; phi = 0.618033988749894842; var xi, yi, zi: Integer; xa, xb, xc, ya, yb, yc, za, zb, zc: Integer; xf, yf, zf: Extended; x2, x1, x0, y2, y1, y0, z2, z1, z0: Extended; xd2, xd1, xd0, yd2, yd1, yd0, zd2, zd1, zd0: Extended; p000, p100, p200, p010, p110, p210, p020, p120, p220: Extended; p001, p101, p201, p011, p111, p211, p021, p121, p221: Extended; p002, p102, p202, p012, p112, p212, p022, p122, p222: Extended; begin xi := Trunc(Loc[1]); xa := Trunc(P1 * (xi * phi - Trunc(xi * phi))); xb := Trunc(P1 * ((xi + 1) * phi - Trunc((xi + 1) * phi))); xc := Trunc(P1 * ((xi + 2) * phi - Trunc((xi + 2) * phi))); yi := Trunc(Loc[2]); ya := Trunc(P2 * (yi * phi - Trunc(yi * phi))); yb := Trunc(P2 * ((yi + 1) * phi - Trunc((yi + 1) * phi))); yc := Trunc(P2 * ((yi + 2) * phi - Trunc((yi + 2) * phi))); zi := Trunc(Loc[3]); za := Trunc(P3 * (zi * phi - Trunc(zi * phi))); zb := Trunc(P3 * ((zi + 1) * phi - Trunc((zi + 1) * phi))); zc := Trunc(P3 * ((zi + 2) * phi - Trunc((zi + 2) * phi))); p000 := Pts[BitAnd(xa + ya + za, MPM1)]; p100 := Pts[BitAnd(xb + ya + za, MPM1)]; p200 := Pts[BitAnd(xc + ya + za, MPM1)]; p010 := Pts[BitAnd(xa + yb + za, MPM1)]; p110 := Pts[BitAnd(xb + yb + za, MPM1)]; p210 := Pts[BitAnd(xc + yb + za, MPM1)]; p020 := Pts[BitAnd(xa + yc + za, MPM1)]; p120 := Pts[BitAnd(xb + yc + za, MPM1)]; p220 := Pts[BitAnd(xc + yc + za, MPM1)]; p001 := Pts[BitAnd(xa + ya + zb, MPM1)]; p101 := Pts[BitAnd(xb + ya + zb, MPM1)]; p201 := Pts[BitAnd(xc + ya + zb, MPM1)]; p011 := Pts[BitAnd(xa + yb + zb, MPM1)]; p111 := Pts[BitAnd(xb + yb + zb, MPM1)]; p211 := Pts[BitAnd(xc + yb + zb, MPM1)]; p021 := Pts[BitAnd(xa + yc + zb, MPM1)]; p121 := Pts[BitAnd(xb + yc + zb, MPM1)]; p221 := Pts[BitAnd(xc + yc + zb, MPM1)]; p002 := Pts[BitAnd(xa + ya + zc, MPM1)]; p102 := Pts[BitAnd(xb + ya + zc, MPM1)]; p202 := Pts[BitAnd(xc + ya + zc, MPM1)]; p012 := Pts[BitAnd(xa + yb + zc, MPM1)]; p112 := Pts[BitAnd(xb + yb + zc, MPM1)]; p212 := Pts[BitAnd(xc + yb + zc, MPM1)]; p022 := Pts[BitAnd(xa + yc + zc, MPM1)]; p122 := Pts[BitAnd(xb + yc + zc, MPM1)]; p222 := Pts[BitAnd(xc + yc + zc, MPM1)]; xf := Loc[1] - xi; x1 := xf * xf; x2 := 0.5 * x1; x1 := 0.5 + xf - x1; x0 := 0.5 - xf + x2; xd2 := xf; xd1 := 1.0 - xf - xf; xd0 := xf - 1.0; yf := Loc[2] - yi; y1 := yf * yf; y2 := 0.5 * y1; y1 := 0.5 + yf - y1; y0 := 0.5 - yf + y2; yd2 := yf; yd1 := 1.0 - yf - yf; yd0 := yf - 1.0; zf := Loc[3] - zi; z1 := zf * zf; z2 := 0.5 * z1; z1 := 0.5 + zf - z1; z0 := 0.5 - zf + z2; zd2 := zf; zd1 := 1.0 - zf - zf; zd0 := zf - 1.0; DNoise[1] := z0 * (y0 * (xd0 * p000 + xd1 * p100 + xd2 * p200) + y1 * (xd0 * p010 + xd1 * p110 + xd2 * p210) + y2 * (xd0 * p020 + xd1 * p120 + xd2 * p220)) + z1 * (y0 * (xd0 * p001 + xd1 * p101 + xd2 * p201) + y1 * (xd0 * p011 + xd1 * p111 + xd2 * p211) + y2 * (xd0 * p021 + xd1 * p121 + xd2 * p221)) + z2 * (y0 * (xd0 * p002 + xd1 * p102 + xd2 * p202) + y1 * (xd0 * p012 + xd1 * p112 + xd2 * p212) + y2 * (xd0 * p022 + xd1 * p122 + xd2 * p222)); DNoise[2] := z0 * (yd0 * (x0 * p000 + x1 * p100 + x2 * p200) + yd1 * (x0 * p010 + x1 * p110 + x2 * p210) + yd2 * (x0 * p020 + x1 * p120 + x2 * p220)) + z1 * (yd0 * (x0 * p001 + x1 * p101 + x2 * p201) + yd1 * (x0 * p011 + x1 * p111 + x2 * p211) + yd2 * (x0 * p021 + x1 * p121 + x2 * p221)) + z2 * (yd0 * (x0 * p002 + x1 * p102 + x2 * p202) + yd1 * (x0 * p012 + x1 * p112 + x2 * p212) + yd2 * (x0 * p022 + x1 * p122 + x2 * p222)); DNoise[3] := zd0 * (y0 * (x0 * p000 + x1 * p100 + x2 * p200) + y1 * (x0 * p010 + x1 * p110 + x2 * p210) + y2 * (x0 * p020 + x1 * p120 + x2 * p220)) + zd1 * (y0 * (x0 * p001 + x1 * p101 + x2 * p201) + y1 * (x0 * p011 + x1 * p111 + x2 * p211) + y2 * (x0 * p021 + x1 * p121 + x2 * p221)) + zd2 * (y0 * (x0 * p002 + x1 * p102 + x2 * p202) + y1 * (x0 * p012 + x1 * p112 + x2 * p212) + y2 * (x0 * p022 + x1 * p122 + x2 * p222)); DNoise[4] := 0.0; end; function DTurb (Size: Integer; ScaleFactor: Extended; Loc: Vect; Pts: PtsTyp): Vect; var Result: Vect; Scale: Extended; Cur: Integer; begin Result := DNoise(Loc, Pts); Scale := 1.0; Cur := 1; while Cur < Size do begin Cur := BSL(Cur, 1); Scale := Scale * ScaleFactor; Loc := Scale_Vect(2.0, Loc); Result := Add_Vect(Result, Scale_Vect(Scale, DNoise(Loc, Pts))); end; DTurb := Result; end; ------------------------------------------------------------------------------- Jon Buller FROM fortune IMPORT quote; ..!ccncsu!handel!bullerj FROM lawyers IMPORT disclaimer;
jamesa@arabian.Sun.COM (James D. Allen) (04/06/89)
In article <3599@pixar.UUCP>, aaa@pixar.UUCP (Tony Apodaca) writes: > In article <2553@ssc-vax.UUCP> coy@ssc-vax.UUCP (Stephen B Coy) writes: > > Last night I saw the article in Byte about the Renderman > >standard. In the sample source code the displacement function, dent(), > >calls a function called noise()... > > ...My question: Does anyone out there know what this > >noise function really is? > > ... Conceptually, noise() > is a "stochastic three-dimensional function which is statistically > invariant under rotation and translation and has a narrow bandpass > limit in frequency" (paraphrased from [Perlin1985]). This means that > you put three-space points in, and you get values back which are basically > random. But if you put other nearby points in, you get values that are > very similar. The differences are still random, but the maximum rate of > change is controlled so that you can avoid aliasing. If you put a set > of points in from a different region of space, you will get values out > which have "the same amount" of randomness. Anyone willing to post a detailed description of such an algorithm? (Jon Buller posted one, but I couldn't figure it out: what is `Pts'?) > -- > UUCP: {sun,ucbvax}!pixar!aaa Tony Apodaca > ARPA,BITNET: aaa%pixar.uucp@sun.com Pixar, San Rafael, CA, USA -James Allen
bullerj@handel.colostate.edu (Jon Buller) (04/07/89)
In article <97699@sun.Eng.Sun.COM> jamesa@arabian.Sun.COM (James D. Allen) writes: >In article <3599@pixar.UUCP>, aaa@pixar.UUCP (Tony Apodaca) writes: >> In article <2553@ssc-vax.UUCP> coy@ssc-vax.UUCP (Stephen B Coy) writes: >> > ...My question: Does anyone out there know what this >> >noise function really is? >> >> ... Conceptually, noise() >> is a "stochastic three-dimensional function which is statistically >> invariant under rotation and translation and has a narrow bandpass >> limit in frequency" (paraphrased from [Perlin1985]). This means that >> you put three-space points in, and you get values back which are basically >> random. But if you put other nearby points in, you get values that are >> very similar. The differences are still random, but the maximum rate of >> change is controlled so that you can avoid aliasing. If you put a set >> of points in from a different region of space, you will get values out >> which have "the same amount" of randomness. > > Anyone willing to post a detailed description of such an > algorithm? (Jon Buller posted one, but I couldn't figure it out: > what is `Pts'?) Sorry about not really describing my program to anyone, I know what it does, and I never expected anyone else to see it (isn't it obvious) :-) What it does is: pass a location in space, and an array of random numbers (this is 'Pts'). I fill the array with 0.0 .. 1.0 but any values or range will work. (I have other textures which color based on distance to the nearest point of a random set, hence the name, It has 4 values per entry at times.) Step 1: change the location to a group of points to interpolate. This is where xa,xb,xc,...zc come in, any location with the same coords (when trunc'ed) will produce the same xa...zc values, making the same values for the interpolation at the end. These xa..zc are then hashed in to the 'Pts' array to produce p000...P222, these 27 random numbers are then interpolated with a Quadratic 3d B-Spline (the long ugly formula at the end). The variables based on xf,yf, and zf (I belive they are x0..z2) are the B-Spline basis functions (notice to get DNoise, just take the (partial) deriveatives(sp?) of the basis functions and re-evaluate the spline). Step 2: now you have a value that is always smaller than the largest random number in 'Pts' (equal to in the odd case that major bunches of the numbers are also the maximum in the range). By the same argument, all numbers returned are larger than the smallest number in the array. (this can be handy if you don't want to have to clip your values to some limit.) I hope this explains the use of the routine better. Sorry I didn't realize that earlier. If you have any other questions about it, mail them to me, and I'll do my best to explain it. Jon ------------------------------------------------------------------------------- Jon Buller FROM fortune IMPORT quote; ..!ccncsu!handel!bullerj FROM lawyers IMPORT disclaimer;
dirks@alligator.cis.ohio-state.edu (william r dirks) (04/14/89)
I implemented Jon Buller's noise functions the other night. (Thanks Jon, I've been looking for a decent noise function for a long time.) Anyway, I rendered a polygon situated in the x-y plane with DNoise() added to the normal vectors to make a bumpy-looking surface. But I noticed there were discontinuities in the "bumps." Studying the image, I noticed that where x and y were both positive the bumps were continuous, where x was negative and y was positive there were lines of discontinuity parallel to the y-axis, where x was positive and y was negative the lines were parallel to the x-axis, and where both x and y were negative the two sets of lines intersected to form squares. On a hunch I changed all the trunc()'s in the source to floor()'s. And presto!! Continuous bumps everywhere! Now I can make bumpy surfaces that look just like Perlin's! I traced a bumpy glass last night. I don't know why a glass would be bumpy, but it looks cool as hell! (The difference between trunc() and floor(), of course, is that trunc() rounds toward 0, but floor() always rounds down. So these functions are the same for positive numbers, but different for negative ones.) __________________________________________________________________________ | Name: Bill Dirks | | Address: dirks@baloo.eng.ohio-state.edu | | Bumper Sticker: "STOP ME AND ASK ME ABOUT MY RAY-TRACER" | | Quote: "Survival and preservation must cancel out programming." | | -- Star Trek, "What Are Little Girls Made Of?" | | Disclaimer: #include <stddisclaimer.h> | `=========================================================================='
bullerj@handel.colostate.edu (Jon Buller) (04/14/89)
In article <43327@tut.cis.ohio-state.edu> william r dirks <dirks@cis.ohio-state.edu> writes: >Anyway, I rendered a polygon situated in the x-y plane with DNoise() >added to the normal vectors to make a bumpy-looking surface. But I >noticed there were discontinuities in the "bumps." > >Studying the image, I noticed that where x and y were both positive >the bumps were continuous, where x was negative and y was positive >there were lines of discontinuity parallel to the y-axis, where x was >positive and y was negative the lines were parallel to the x-axis, and >where both x and y were negative the two sets of lines intersected to >form squares. > >On a hunch I changed all the trunc()'s in the source to floor()'s. > >And presto!! Continuous bumps everywhere! I wish I could do that, my compiler doesn't have a built in Floor, and I haven't had the time to hack one up from the Mac toolbox and SANE (IEEE math pkg) calls, oh well, I'll have to settle for only using X, Y, and Z >= 0.0 One other thing you might notice, Noise is C1 continuous, DNoise is only C0. This means that DNoise will have creases in it (along the planes of the random grid. To see this, crank out a square: 0<X<5, 0<Y<5, Z=0. You will see smooth regions within each unit square, and creases btween squares. To aviod this, use a cubic B-Spline, or cubic Hermite (as hinted to in the SIGGRAPH procedings) the problem there, is that you either need more data points (64 instead of 27) for the B-Spline, or deravative info at each point of the grid (a normal plane, 4 floats instead of 1). This would take too muh time for me to code up to be worth it, and would probably run too much slower (10min for a 200x200 pixel picture now, ug.) If somebody wants to give me a cray-3 to play with, I'll write more accurate (and slower) code, until then... 8-) ------------------------------------------------------------------------------- Jon Buller FROM fortune IMPORT quote; ..!ccncsu!handel!bullerj FROM lawyers IMPORT disclaimer;
malloy@nprdc.arpa (Sean Malloy) (04/16/89)
In article <1648@ccncsu.ColoState.EDU> bullerj@handel.colostate.edu.UUCP (Jon Buller) writes: |In article <43327@tut.cis.ohio-state.edu> william r dirks <dirks@cis.ohio-state.edu> writes: |>On a hunch I changed all the trunc()'s in the source to floor()'s. |> |>And presto!! Continuous bumps everywhere! | | I wish I could do that, my compiler doesn't have a built in Floor, |and I haven't had the time to hack one up from the Mac toolbox and SANE |(IEEE math pkg) calls, oh well, I'll have to settle for only using |X, Y, and Z >= 0.0 If I understand the problem correctly, writing a floor() function is extremely simple: int floor(x) double x; { if (x >= 0.0) return(trunc(x)); else return(trunc(x)+1); } Sean Malloy | "The proton absorbs a photon Navy Personnel Research & Development Center | and emits two morons, a San Diego, CA 92152-6800 | lepton, a boson, and a malloy@nprdc.navy.mil | boson's mate. Why did I ever | take high-energy physics?"
bullerj@handel.colostate.edu (Jon Buller) (04/17/89)
In article <1771@skinner.nprdc.arpa> malloy@nprdc.arpa (Sean Malloy) writes: >If I understand the problem correctly, writing a floor() function is >extremely simple: >int floor(x) >double x; >{ > if (x >= 0.0) return(trunc(x)); > else return(trunc(x)+1); >} > Sean Malloy | "The proton absorbs a photon > Navy Personnel Research & Development Center | and emits two morons, a > San Diego, CA 92152-6800 | lepton, a boson, and a > malloy@nprdc.navy.mil | boson's mate. Why did I ever > | take high-energy physics?" I like this ^^^^^^ 8-) Well, that almost works, if x = -1.0, floor = -1.0, your_func = 0.0 (you meant return(trunc(x)-1); didn't you?) in this case, your_func = -2.0, this ----> ^^^^^^^^ will work if x is NOT an integer, will break if it is, and it is admittedly a simple thing to fix, but as I said before, I've been LAZY. I can't use the thing in a render quite yet, so I haven't bothered. ------------------------------------------------------------------------------- Jon Buller FROM fortune IMPORT quote; ..!ccncsu!handel!bullerj FROM lawyers IMPORT disclaimer;
peter@celia.UUCP (Peter Farson) (04/22/89)
In article <1669@ccncsu.ColoState.EDU> bullerj@handel.colostate.edu.UUCP (Jon Buller) writes: >In article <1771@skinner.nprdc.arpa> malloy@nprdc.arpa (Sean Malloy) writes: >>If I understand the problem correctly, writing a floor() function is >>extremely simple: > >>int floor(x) >>double x; >>{ >> if (x >= 0.0) return(trunc(x)); >> else return(trunc(x)+1); >>} > > >Well, that almost works, if x = -1.0, floor = -1.0, your_func = 0.0 >(you meant return(trunc(x)-1); didn't you?) in this case, your_func = -2.0, >this ----> ^^^^^^^^ will work if x is NOT an integer, will break if it is, >and it is admittedly a simple thing to fix, but as I said before, I've been >LAZY. I can't use the thing in a render quite yet, so I haven't bothered. > How about: int floor(x) double x; { if (x >= 0.0) return(trunc(x)); else return(trunc(x-.999999)); } The only problem with this is with the accuracy of the .999999 constant. Ideally you would want a floating point binary constant with all bits set to 1 in the mantissa, to the precision of the binary floating point format of the machine. Any error in this value should not be too big a deal though in most cases - it just causes values that are very close to an integer to be treated as though they are an integer (-1.00000001 being mistaken for -1.0000000000, for example). But there is one pitfall: if there are too many decimal digits in this constant for the machine's precision, it might get rounded up to 1.00, which would make the function return incorrect results for negative integers. -- Can a bee be said to be Peter Farson An entire bee if celia!peter@tis.llnl.gov Half the bee is not a bee ...{ihnp4,ames}!lll-tis!celia!peter Due to some ancient injury?
malloy@nprdc.arpa (Sean Malloy) (04/24/89)
In article <465@celia.UUCP> celia!peter@tis.llnl.gov (Peter Farson) writes: > How about: > >int floor(x) >double x; >{ >if (x >= 0.0) return(trunc(x)); > else return(trunc(x-.999999)); > } > Looking back at my original (and slightly broken) solution, the corrected function would be: int floor(x) double x; { if ((x >= 0.0)||(x == trunc(x)) return(trunc(x)); else return(trunc(x)+1); } Sean Malloy | "The proton absorbs a photon Navy Personnel Research & Development Center | and emits two morons, a San Diego, CA 92152-6800 | lepton, a boson, and a malloy@nprdc.navy.mil | boson's mate. Why did I ever | take high-energy physics?"
platt@cs.swarthmore.edu (Steve Platt) (04/24/89)
Off the top of my head,
int floor(x)
double x;
{ if (x>=0) return(trunc(x));
else return(-trunc(-x));
}
seems to do the trick.