Kiyote Wolf's amazing cheap Texturemapping. It's cheap cause it's SLOOOOOOOOOOOOOOOOOOW... This routine works with a few givens, it uses a standard array, used for PUT/GET sprite graphics, the index of the sprite, and a chain style entry of data for the 4 corners and the amount of repeating of the texture. You will notice, it takes the first 8 entries and applies it to where the corners of the polygon are. It uses the same standard polygon definition, where it goes from the upperleft corner, clockwise, to the bottom left corner. Then, it see's if there was a command "SCALE" in the chain and takes the next two entries as the values to repeat the texture within the area plotting, in both X and Y directions. How does it work? Well, one day awhile ago.. last year?? I had one of those genius, Einstein moments, and it had something to do with a problem i was upset about with Google Sketchup, not "Google's Ketchup..", but anyway, I decided to make a SVGA texture mapping routine. Well, that was fun for awhile, but what do I do most? Work with sprites. So I worked at it for a week and condensed the entire program down into a single SUB, which lets me take my ordinary sprites, and make them extrodinary textures. The code self checks itself, and modifies it's way of rendering to adjust for redundancy, speed, scale, and size, and makes minor adjustments based on a radius method of checking your proposed work. I'm sure that making each of these modes of drawing would make for another copy of this routine, letting me manually choose the scale and quality based on individual results, but I am obviously quite lazy and am going to let the computer choose the quality as per it's measuring. What happens in this code is a giant binary tree search, which does a sliver of the mapped polygon in one direction, as a binary tree, grabbing pixels from the source to the destination by measuring each point in the tree as it goes along. Why is this important? Because, when we go into details of how the polygon stretches, by going at it in a binary fashion, where the pixels are originally and where they ultimately should go, the computer is able to faithfully recreate the texture in a real stretched reproduction because it measures half of half of half of this distance between the actual and the model. I have even tested this routine to do a floor mapping technique, which it lacks the checking ability to control the pixels to make them large enough for floor mapping, but that can be changed of course eventually, which means,.. You can plot your texture mapped polygon on the screen, or have every point off the screen without having to worry about clipping. The math is still going to work even with negative numbers and far off positive numbers that do not appear on the screen, and your texture is going to appear on the screen as it should, only what is visible appearing, because the code will do so faithfully. It is slow as 8088 GWBasic, or worse, but for those of us who wanna grasp the idea of 3D math without having as much headache, and those of us who cheat and pre-render.. (hee hee.. me..), this is a golden opportunity to test out something random in the name of 3D math, and get away with it. I am very very proud of the insane but actually doable nature of this code, because that has always been my way of doing anything anyway. Kudos 3D programmers, and 3D n00bs like myself. '******* WORKING EXAMPLE OF CODE,.. FINISHED AND READY TO USE.. ASSUMING THE GRID MULTI ' CODE IS PRESENT AS WELL AS PER MY PREVIOUS COLUMN ENTRY. ' YOU WILL ONLY NEED THE VERT AND THE GRID MULTI ROUTINES TO USE THIS EXAMPLE. ' I USED THE CHAIN DATA ENTRY METHOD CAUSE I HATE USING TWENTY MILLION VARIABLES JUST FOR X/Y DATA SUB TextureSpr (Sprite(), image, DataStrg2$) DataStrg$ = DataStrg2$ REDIM CornerX(20), CornerY(20) ImageWidth = Sprite(0) / 8 'get the image width ImageHeight = Sprite(1) 'and height WWidth = ImageWidth WHeight = ImageHeight ElmPerImg = (4 + INT((ImageWidth * 8 + 7) / 8) * ImageHeight + 1) \ 2 'without going into a LONGINTEGER format, we can check an overflow 'by subtracting the ADDEND from the .....you get the point... wbuf = 0 FOR w = 1 TO image wbuf = wbuf + ElmPerImg IF (32768 - wbuf) < ElmPerImg THEN EXIT SUB NEXT w StartElm = ElmPerImg * image 'element # in the IF UBOUND(Sprite) < StartElm THEN EXIT SUB SourceSeg = VARSEG(Sprite(StartElm)) 'source image SourceOfs& = VARPTR(Sprite(StartElm)) + 4 'skip size info CornerX(4) = GridMulti(DataStrg$, 0) CornerY(4) = GridMulti(DataStrg$, 1) CornerX(5) = GridMulti(DataStrg$, 2) CornerY(5) = GridMulti(DataStrg$, 3) CornerX(6) = GridMulti(DataStrg$, 4) CornerY(6) = GridMulti(DataStrg$, 5) CornerX(7) = GridMulti(DataStrg$, 6) CornerY(7) = GridMulti(DataStrg$, 7) ' Scale2 = 7 ScaleX = 1 ScaleY = 1 ScalePtr = GridIF(DataStrg$, "SCALE") IF ScalePtr > 0 THEN ScaleX = GridMulti(DataStrg$, ScalePtr + 1) ScaleY = GridMulti(DataStrg$, ScalePtr + 2) END IF CornerX(0) = 0 CornerY(0) = 0 CornerX(1) = ImageWidth * ScaleX CornerY(1) = 0 CornerX(2) = ImageWidth * ScaleX CornerY(2) = ImageHeight * ScaleY CornerX(3) = 0 CornerY(3) = ImageHeight * ScaleY FOR w = 4 TO 7 IF w = 4 THEN CornerAvgX = CornerX(w) CornerAvgY = CornerY(w) ELSE CornerAvgX = (CornerAvgX + CornerX(w)) \ 2 CornerAvgY = (CornerAvgY + CornerY(w)) \ 2 END IF NEXT w CornerDist! = 0 CornerMax! = 0 FOR w = 4 TO 7 CornerDist! = SQR((CornerAvgX - CornerX(w)) ^ 2 + (CornerAvgY - CornerY(w)) ^ 2) IF CornerDist! > CornerMax! THEN CornerMax! = CornerDist! NEXT w Scale = 0 '<> Does the max size go beyond 15 pels? If so,.. work large,.. if not.. small IF CornerDist! < 15 THEN Scale = -1 Scale3 = 0 IF CornerDist! > 30 THEN Scale3 = -1 Scale4 = 0 IF CornerDist! > 50 THEN Scale4 = -1 'IF Scale2 > 1 THEN Scale = -1 ' 0 1 ' ' 3 2 ' We render our simple texture mapped polygon similar to standard ' methods FOR w = 0 TO 7 CornerX(w + 8) = CornerX(w) CornerY(w + 8) = CornerY(w) NEXT w REDIM pgn(10, 10, 10) '4095 = 12 bits FOR BigCnt = 0 TO (63 + 48 * Scale * (-1 * (Scale2 = 1))) FOR BigCnt2 = 0 TO (63 + 48 * Scale * (-1 * (Scale2 = 1))) FOR w = 0 TO 7 CornerX(w) = CornerX(w + 8) CornerY(w) = CornerY(w + 8) NEXT w FOR t = 0 TO (7 + 4 * Scale * (-1 * (Scale2 = 1))) Flag = SGN(BigCnt AND 2 ^ t) Flag2 = SGN(BigCnt2 AND 2 ^ t) pgn(1, 1, 1) = CornerX(0) pgn(2, 1, 1) = (CornerX(0) + CornerX(1)) \ 2 pgn(3, 1, 1) = CornerX(1) pgn(1, 2, 1) = (CornerX(0) + CornerX(3)) \ 2 pgn(2, 2, 1) = (CornerX(0) + CornerX(1) + CornerX(2) + CornerX(3)) \ 4 pgn(3, 2, 1) = (CornerX(1) + CornerX(2)) \ 2 pgn(1, 3, 1) = CornerX(3) pgn(2, 3, 1) = (CornerX(3) + CornerX(2)) \ 2 pgn(3, 3, 1) = CornerX(2) pgn(1, 1, 2) = CornerY(0) pgn(2, 1, 2) = (CornerY(0) + CornerY(1)) \ 2 pgn(3, 1, 2) = CornerY(1) pgn(1, 2, 2) = (CornerY(0) + CornerY(3)) \ 2 pgn(2, 2, 2) = (CornerY(0) + CornerY(1) + CornerY(2) + CornerY(3)) \ 4 pgn(3, 2, 2) = (CornerY(1) + CornerY(2)) \ 2 pgn(1, 3, 2) = CornerY(3) pgn(2, 3, 2) = (CornerY(3) + CornerY(2)) \ 2 pgn(3, 3, 2) = CornerY(2) pgn(1, 1, 3) = CornerX(0 + 4) pgn(2, 1, 3) = (CornerX(0 + 4) + CornerX(1 + 4)) \ 2 pgn(3, 1, 3) = CornerX(1 + 4) pgn(1, 2, 3) = (CornerX(0 + 4) + CornerX(3 + 4)) \ 2 pgn(2, 2, 3) = (CornerX(0 + 4) + CornerX(1 + 4) + CornerX(2 + 4) + CornerX(3 + 4)) \ 4 pgn(3, 2, 3) = (CornerX(1 + 4) + CornerX(2 + 4)) \ 2 pgn(1, 3, 3) = CornerX(3 + 4) pgn(2, 3, 3) = (CornerX(3 + 4) + CornerX(2 + 4)) \ 2 pgn(3, 3, 3) = CornerX(2 + 4) pgn(1, 1, 4) = CornerY(0 + 4) pgn(2, 1, 4) = (CornerY(0 + 4) + CornerY(1 + 4)) \ 2 pgn(3, 1, 4) = CornerY(1 + 4) pgn(1, 2, 4) = (CornerY(0 + 4) + CornerY(3 + 4)) \ 2 pgn(2, 2, 4) = (CornerY(0 + 4) + CornerY(1 + 4) + CornerY(2 + 4) + CornerY(3 + 4)) \ 4 pgn(3, 2, 4) = (CornerY(1 + 4) + CornerY(2 + 4)) \ 2 pgn(1, 3, 4) = CornerY(3 + 4) pgn(2, 3, 4) = (CornerY(3 + 4) + CornerY(2 + 4)) \ 2 pgn(3, 3, 4) = CornerY(2 + 4) CornerX(0) = pgn(1 + Flag, 1 + Flag2, 1) CornerY(0) = pgn(1 + Flag, 1 + Flag2, 2) CornerX(1) = pgn(2 + Flag, 1 + Flag2, 1) CornerY(1) = pgn(2 + Flag, 1 + Flag2, 2) CornerX(2) = pgn(2 + Flag, 2 + Flag2, 1) CornerY(2) = pgn(2 + Flag, 2 + Flag2, 2) CornerX(3) = pgn(1 + Flag, 2 + Flag2, 1) CornerY(3) = pgn(1 + Flag, 2 + Flag2, 2) CornerX(4) = pgn(1 + Flag, 1 + Flag2, 3) CornerY(4) = pgn(1 + Flag, 1 + Flag2, 4) CornerX(5) = pgn(2 + Flag, 1 + Flag2, 3) CornerY(5) = pgn(2 + Flag, 1 + Flag2, 4) CornerX(6) = pgn(2 + Flag, 2 + Flag2, 3) CornerY(6) = pgn(2 + Flag, 2 + Flag2, 4) CornerX(7) = pgn(1 + Flag, 2 + Flag2, 3) CornerY(7) = pgn(1 + Flag, 2 + Flag2, 4) NEXT t FOR m = 1 TO 3 FOR n = 1 TO 3 IF Scale = 0 THEN FOR o = -1 TO 1 FOR p = -1 TO 1 px = ABS(pgn(m, n, 1) - (o * (Scale2 > 1)) * (-1 * (Scale <> 0))) MOD ImageWidth '+ o py = ABS(pgn(m, n, 2) - (p * (Scale2 > 1)) * (-1 * (Scale <> 0))) MOD ImageHeight'+ p IF Scale3 THEN px = (pgn(m, n, 1) MOD ImageWidth) '+ o py = (pgn(m, n, 2) MOD ImageHeight)' + p ELSE px = (pgn(m, n, 1) MOD ImageWidth) + o py = (pgn(m, n, 2) MOD ImageHeight) + p END IF BLoc = py IF BLoc > ImageHeight THEN BLoc = ImageHeight IF BLoc < 0 THEN BLoc = 0 CLoc = px IF CLoc > ImageWidth THEN CLoc = ImageWidth IF CLoc < 0 THEN CLoc = 0 ALoc = (BLoc) * ImageWidth + CLoc DEF SEG = SourceSeg sc = PEEK(SourceOfs& + CLNG(ALoc)) 'check source IF Scale3 THEN IF ((ABS(SGN(o)) = 1) AND (ABS(SGN(p)) = 1) AND (Scale4 = 0)) THEN REM ELSE IF VGAFlag THEN PSET (pgn(m, n, 3) + o, pgn(m, n, 4) + p), sc ELSEIF SVGAFlag THEN PutPRGB sc Pset24 pgn(m, n, 3) + o, pgn(m, n, 4) + p END IF END IF ELSE IF (o >= 0) AND (p >= 0) THEN IF VGAFlag THEN PSET (pgn(m, n, 3) + o, pgn(m, n, 4) + p), sc ELSEIF SVGAFlag THEN PutPRGB sc Pset24 pgn(m, n, 3) + o, pgn(m, n, 4) + p END IF END IF END IF NEXT p NEXT o ELSE px = pgn(m, n, 1) MOD ImageWidth py = pgn(m, n, 2) MOD ImageHeight BLoc = py IF BLoc > ImageHeight THEN BLoc = ImageHeight IF BLoc < 0 THEN BLoc = 0 CLoc = px IF CLoc > ImageWidth THEN CLoc = ImageWidth IF CLoc < 0 THEN CLoc = 0 ALoc = (BLoc) * ImageHeight + CLoc DEF SEG = SourceSeg sc = PEEK(SourceOfs& + CLNG(ALoc)) 'check source IF VGAFlag THEN PSET (pgn(m, n, 3), pgn(m, n, 4)), sc ELSEIF SVGAFlag THEN PutPRGB sc Pset24 pgn(m, n, 3), pgn(m, n, 4) END IF END IF NEXT n NEXT m NEXT BigCnt2 NEXT BigCnt END SUB '**************** END OF CODE EXAMPLE