DIRECTORY G3dBasic, G3dNormalCoding, G3dVector, Random, Real, RealFns; G3dNormalCodingImpl: CEDAR PROGRAM IMPORTS G3dVector, Random, Real, RealFns EXPORTS G3dNormalCoding ~ BEGIN Triple: TYPE ~ G3dBasic.Triple; RandomStream: TYPE ~ Random.RandomStream; NtoGTable: TYPE ~ ARRAY [0 .. 17] OF ARRAY [0 ..17] OF INT; GtoNTable: TYPE ~ ARRAY [0 .. 255] OF Triple; ntogTable: NtoGTable ¬ InitNtoGTable[]; gtonTable: GtoNTable ¬ InitGtoNTable[]; rs: RandomStream ¬ Random.Create[range: 500, seed: 1989]; EncodeNormal: PUBLIC PROC [dx, dy: REAL, dither: BOOLEAN ¬ TRUE, userRS: RandomStream ¬ NIL] RETURNS [pval: INT] ~ { scale: REAL ¬ 8.5; -- 17/2.0 dz: REAL ¬ 1.0 - ((dx * dx) + (dy * dy)); xentry, yentry: INT; lrs: RandomStream ¬ IF userRS = NIL THEN rs ELSE userRS; IF dz < 0.0 THEN RETURN[0] ELSE { IF dither THEN { slip: REAL ¬ 3.0/17.0; -- use 3.0/17.0 for good results, 1.0/17.0 for debugging scale: REAL ¬ (2.0 * slip) / 499.0; xfuzz: REAL ¬ (scale * Random.NextInt[lrs]) - slip; yfuzz: REAL ¬ (scale * Random.NextInt[lrs]) - slip; dx ¬ dx + xfuzz; dy ¬ dy + yfuzz; dz ¬ (dx * dx) + (dy * dy); IF dz > 1.0 THEN { dz ¬ RealFns.SqRt[dz]; dx ¬ dx / dz; dy ¬ dy / dz; }; }; xentry ¬ MIN[16, Real.Floor[(1.0 + dx) * scale]]; yentry ¬ MIN[16, Real.Floor[(1.0 + dy) * scale]]; RETURN[ntogTable[yentry][xentry]]; }; }; DecodeNormal: PUBLIC PROC [pval: INT] RETURNS [n: Triple] ~ { RETURN[gtonTable[pval]]; }; IsValidNormalIndex: PUBLIC PROC [index: INT] RETURNS [BOOLEAN] ~ { RETURN[index >= 6 AND index < 255]; }; BuildNormalTables: PUBLIC PROC [] ~ { ntogTable ¬ InitNtoGTable[]; gtonTable ¬ InitGtoNTable[]; rs ¬ Random.Create[range: 500, seed: 1989]; }; InitNtoGTable: PROC [] RETURNS [ng: NtoGTable] ~ { GridCheck: PROC [centerx, centery, size: REAL] RETURNS [BOOLEAN] ~ { d: REAL ¬ 1.0 - ((centerx * centerx) + (centery * centery)); IF d > 0.0 THEN RETURN [TRUE] ELSE { lx: REAL ¬ centerx - size; hx: REAL ¬ centerx + size; ly: REAL ¬ centery - size; hy: REAL ¬ centery + size; IF (lx*lx) + (ly*ly) < 1.0 THEN RETURN [TRUE]; IF (lx*lx) + (hy*hy) < 1.0 THEN RETURN [TRUE]; IF (hx*hx) + (hy*hy) < 1.0 THEN RETURN [TRUE]; IF (hx*hx) + (ly*ly) < 1.0 THEN RETURN [TRUE]; RETURN [FALSE]; }; }; width: INT ¬ 17; current: INT ¬ 6; iwidth: REAL ¬ 1.0/width; offset: REAL ¬ iwidth - 1.0; inc: REAL ¬ 2.0 * iwidth; FOR y: INT IN [0 .. width) DO ny: REAL ¬ offset + (y * inc); FOR x: INT IN [0 .. width) DO nx: REAL ¬ offset + (x * inc); IF GridCheck[nx, ny, iwidth] THEN { ng[y][x] ¬ current; current ¬ current+1; } ELSE { ng[y][x] ¬ -1; }; ENDLOOP; ENDLOOP; }; InitGtoNTable: PROC [] RETURNS [gn: GtoNTable] ~ { hits: INT; offset: REAL ¬ -16.0/17.0; inc: REAL ¬ 2.0/17.0; FOR a: INT IN [0 .. 255] DO gn[a] ¬ [-1.0, -1.0, -1.0]; ENDLOOP; FOR y: INT IN [0 .. 16] DO FOR x: INT IN [0 .. 16] DO entry: INT ¬ ntogTable[y][x]; IF entry > 0 THEN { ulx: REAL ¬ (x * inc) - 1.0; uly: REAL ¬ (y * inc) - 1.0; wid: REAL ¬ inc / 5.0; norm: Triple ¬ [0.0, 0.0, 0.0]; hits ¬ 0; FOR i: INT IN [0 .. 5] DO fy: REAL ¬ uly + wid*i; FOR j: INT IN [0 .. 5] DO fx: REAL ¬ ulx + wid*j; fz: REAL ¬ (fx*fx)+(fy*fy); IF fz <= 1.0 THEN { fz ¬ RealFns.SqRt[1.0 - fz]; norm ¬ G3dVector.Add[norm, [fx, fy, -fz]]; hits ¬ hits + 1; }; ENDLOOP; ENDLOOP; gn[entry] ¬ G3dVector.Unit[norm]; }; ENDLOOP; ENDLOOP; }; END. ΐ G3dNormalCodingImpl.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Glassner, April 14, 1989 1:35:37 pm PDT Bloomenthal, July 15, 1992 10:43 pm PDT Types Custom Types Globals -- NOTE that the order of these calls is important Encode a G3dRender Context3d EncodeAllNormals: PUBLIC PROC [context3d: Context3d] ~ { Action: PROC ~ { width: NAT _ Real.Fix[context3d.viewPort.w]; height: NAT _ Real.Fix[context3d.viewPort.h]; scanSeg: PixelBuffer _ ImagerPixel.NewPixels[context3d.pixels.samplesPerPixel, width]; refV: REF NAT _ NARROW[Atom.GetPropFromList[context3d.displayProps, $NormalBuffer]]; v: NAT; IF refV # NIL THEN { v _ refV^; } ELSE G3dRender.Error[$Fatal, "Normals not available"]; FOR y: NAT IN [0..height) DO ImagerPixel.GetPixels[ -- get scanline of pixels self: context3d.pixels, pixels: scanSeg, initIndex: [f: 0, s: y], count: width ]; FOR x: NAT IN [0..width) DO IF scanSeg[v+2][x] > 0 THEN scanSeg[0][x] _ EncodeNormal[ LOOPHOLE[scanSeg[v ][x], INTEGER]/32768.0, -LOOPHOLE[scanSeg[v+1][x], INTEGER]/32768.0 ] ELSE scanSeg[0][x] _ 0; ENDLOOP; ImagerPixel.PutPixels[ -- return modified pixels self: context3d.pixels, pixels: scanSeg, initIndex: [f: 0, s: y], count: width ]; ENDLOOP; IF context3d.viewer # NIL THEN context3d.class.drawInViewer[ context3d, NEW[G3dRender.ImagerProcRec _ [G3dColorDisplaySupport.StuffBuf, NIL]] ]; }; CedarProcess.DoWithPriority[background, Action]; -- be nice to other processess }; Normal Encoding/Decoding Procedures Normal Table Creation The Normal Table: We reserve 9 entries for special use: 0: Foreground color (usually black) 255: Background color (usually white) 1: Light Source Swatch 2: Material Swatch 3-5: Reserved Thus there are 249 entries left, in the range [6 .. 254], all of which are used. -- NOTE that the order of these calls is important the following calls are in no special order -- NOTE! You must call InitNtoGTable before calling InitGtoNTable Κ8•NewlineDelimiter –"cedarcode" style™šœ™Jšœ Οeœ6™BJšœ'™'J™'J˜—šΟk œ=˜FJ˜—šΡblnœžœž˜"Jšžœ!˜(Jšžœ˜J˜—Jšœž˜headšΟl™Jšœ žœ˜#Jšœžœ˜+—š  ™ Jš œžœžœ žœžœ žœžœ˜>Jšœžœžœ žœ˜0—š ™JšΟc2™2J˜'J˜'J˜9—š ™šΟnœžœžœ™8š’œžœ™Jšœžœ"™,Jšœžœ"™-JšœV™VJšœžœžœžœ>™TJšœžœ™šžœžœ™Jšžœ™Jšžœ2™6—šžœžœžœ ž™šœ ‘™9JšœQ™Q—šžœžœžœ ž™šžœ™šžœ™#Jšžœžœ ™,Jšœžœžœ ™,Jšœ™—Jšžœ™—Jšžœ™—šœ!‘™:JšœN™NJ™—Jšžœ™—šžœžœžœ™=Jšœ ™ Jšžœ=žœ™FJšœ™—J™—Jšœ4‘™RJ™——š #™#š’ œžœžœ žœ žœžœžœžœžœ˜tJšœžœ ‘ ˜Jšœžœ!˜)Jšœžœ˜Jš œžœ žœžœžœ˜8šžœ ˜ Jšžœžœ˜šžœ˜šžœžœ˜Jšœžœ‘8˜PJšœžœ˜#Jšœžœ(˜3Jšœžœ(˜3J˜J˜J˜Jšžœ žœ;˜KJ˜—Jšœ žœ%˜1Jšœ žœ%˜1Jšžœ˜"—J˜—J˜J˜—š ’ œžœžœžœžœ˜=Jšžœ˜J˜J˜—š ’œžœžœ žœžœžœ˜BJšžœ žœ˜#J˜——š ™™™%J™#J™%J™J™J™ —J™PJ™—J˜š’œžœžœ˜%Jš‘2™2J˜J˜Jšœ+™+J˜+J˜J˜J˜—š’ œžœžœ˜2J˜š ’ œžœžœžœžœ˜DJšœžœ5˜<šžœ žœžœžœ˜šžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜J˜Jšžœžœžœžœ˜/Jšžœžœžœžœ˜.Jšžœžœžœžœ˜.Jšžœžœžœžœ˜.Jšžœžœ˜J˜——J˜J˜—Jšœžœ˜Jšœ žœ˜Jšœžœ ˜Jšœžœ˜Jšœžœ˜šžœžœžœž˜Jšœžœ˜šžœžœžœž˜Jšœžœ˜šžœ˜Jšžœ-˜1Jšžœ˜—Jšžœ˜—Jšžœ˜—J˜J˜—Jš‘Πbc‘:™Bš’ œžœžœ˜2Jšœžœ˜ Jšœžœ˜Jšœžœ ˜Jš žœžœžœ žœžœ˜@šžœžœžœ ž˜šžœžœžœ ž˜Jšœžœ˜šžœ žœ˜Jšœžœ˜Jšœžœ˜Jšœžœ ˜J˜J˜ šžœžœžœ ž˜Jšœžœ˜šžœžœžœ ž˜Jšœžœ˜Jšœžœ˜šžœ žœ˜J˜J˜*J˜J˜—Jšžœ˜—Jšžœ˜—J˜!J˜—Jšžœ˜—Jšžœ˜J˜—Jšœ˜J˜——Jšžœ˜J™J˜—…— ξζ