'''Texturing and tesselation of 3d models for QBCM '''Cube by SCM '''All others by Relsoft '''SetvideoSeg by Plasma357 '''Tritexture modified from CGI Joe's code. '''Tesselation also of 2nd degree shapes by Biskbart '''Rel.betterwebber.com DECLARE SUB FFIX (Mode%) DECLARE SUB SortPolys (Model() AS ANY, Poly() AS ANY) DECLARE SUB ShellSort (Poly() AS ANY, Min%, Max%) DECLARE SUB LoadCube (Model() AS ANY, Poly() AS ANY, radius%) DECLARE SUB AF.Print (Xpos%, Ypos%, Text$, Col%) DECLARE SUB DrawModel (Model() AS ANY, Poly() AS ANY, Cull%) DECLARE SUB LoadPlane (Model() AS ANY, Poly() AS ANY, radius%) DECLARE SUB SetVideoSeg (Segment%) DECLARE SUB Tritexture (xx1%, yy1%, xx2%, yy2%, xx3%, yy3%, uu1%, vv1%, uu2%, vv2%, uu3%, vv3%, TSEG%, TOFF%) DECLARE SUB HTLine (xx1%, xx2%, yy%, uu1&, uu2&, vv1&, vv2&, Twidth%, TOFF%) DECLARE SUB RotateAndProject (Model() AS ANY, AngleX%, AngleY%, AngleZ%) DECLARE SUB LoadCylinder (Model() AS ANY, Poly() AS ANY, radius%, Slices%, Bands%, zdist%) DECLARE SUB LoadSphere (Model() AS ANY, Poly() AS ANY, radius%, Slices%, Bands%) DEFINT A-Z REM $DYNAMIC TYPE Point3d x AS SINGLE 'our 3d point y AS SINGLE z AS SINGLE xr AS SINGLE 'Rotated 3d point yr AS SINGLE 'not needed really Zr AS SINGLE scrx AS INTEGER 'projected x/y coords scry AS INTEGER 'for display on screen END TYPE TYPE PolyType p1 AS INTEGER 'vertex 1 of our triangle p2 AS INTEGER 'huh? p3 AS INTEGER Clr AS INTEGER 'color for flat shading u1 AS INTEGER 'Texture U and V v1 AS INTEGER u2 AS INTEGER v2 AS INTEGER u3 AS INTEGER v3 AS INTEGER zcenter AS INTEGER 'everage z coord of a poly idx AS INTEGER 'index used for sorting END TYPE CONST FALSE = 0, TRUE = NOT FALSE CONST LENS = 256 'our multiplier CONST XCENTER = 160 'mid x and y of screen 13 CONST YCENTER = 100 CONST TSIZE% = 32 'our texture size CONST TSIZEM1% = TSIZE% - 1 'speed issues used for tiling(AND) CONST PI = 3.14151693# REDIM SHARED Vpage(32009) AS INTEGER 'out buffer REDIM SHARED Texture%(((4 + (TSIZE% * TSIZE%)) \ 2)) 'dimiension or 'texture array DIM SHARED Lcos(359) AS SINGLE 'LUTS for fast rotation DIM SHARED Lsin(359) AS SINGLE REDIM SHARED Model(1) AS Point3d 'our 3d object REDIM SHARED Tri(1) AS PolyType 'its polygons DIM SHARED Thetax, Thetay, Thetaz 'angle of rotation DIM SHARED TextSeg%, Textoff%, ImgSize% 'easy reference DIM SHARED camz%, camy%, camx% 'our cartesian camera FFIX 0 RANDOMIZE TIMER FOR i = 0 TO 359 'prefcalc our Lookup tables a! = i * PI / 180 Lcos(i) = COS(a!) Lsin(i) = SIN(a!) NEXT i CLS SCREEN 0 WIDTH 80 LOCATE 1, 1 'get input PRINT "Choose Model:" PRINT "1. Plane" PRINT "2. Cube [Default]" PRINT "3. Cylinder" PRINT "4. Sphere" DO K$ = INKEY$ LOOP UNTIL K$ <> "" Cull = TRUE 'if backface culing enabled SELECT CASE ASC(K$) CASE 49 LoadPlane Model(), Tri(), 80 Cull = FALSE 'Plane has only one face CASE 50 LoadCube Model(), Tri(), 45 CASE 51 LoadCylinder Model(), Tri(), 50, 8, 8, 20 CASE 52 LoadSphere Model(), Tri(), 70, 10, 10 CASE ELSE LoadCube Model(), Tri(), 45 END SELECT CLS SCREEN 13 'generate our palette j! = 255 / 360 * 3 'Maxcolor/2PI*Frequency K! = 255 / 360 * 1 l! = 255 / 360 * 2 FOR i% = 0 TO 255 OUT &H3C8, i% m% = INT(a!) n% = INT(b!) o% = INT(c!) r% = 63 * ABS(SIN(m% * PI / 180)) 'The sine-wwave g% = 63 * ABS(SIN(n% * PI / 180)) b% = 63 * ABS(SIN(o% * PI / 180)) a! = a! + j! b! = b! + K! c! = c! + l! OUT &H3C9, r% OUT &H3C9, g% OUT &H3C9, b% NEXT 'Generate texture FOR y% = -TSIZE% \ 2 TO TSIZE% \ 2 - 1 yy% = ABS(y%) FOR x% = -TSIZE% \ 2 TO TSIZE% \ 2 - 1 xx% = ABS(x%) c% = SIN(xx% / 12) * 32 + SIN(yy% / 12) * 256 + SIN((yy% + xx%) / 8) * 64 PSET (x% + TSIZE% \ 2, y% + TSIZE% \ 2), c% NEXT x% NEXT y% 'get texture ImgSize% = (4 + TSIZE% * TSIZE%) \ 2 GET (0, 0)-STEP(TSIZE% - 1, TSIZE% - 1), Texture%(0) TextSeg% = VARSEG(Texture%(0)) 'easy reference Textoff% = VARPTR(Texture%(0)) Thetax = INT(RND * 360) 'random starting angles Thetay = INT(RND * 360) Thetaz = INT(RND * 360) REDIM Vpage(32009) AS INTEGER 'Clear offscreen buffer Vpage(6) = 2560 'Width 320*8 Vpage(7) = 200 'Height LAYER = VARSEG(Vpage(0)) + 1 'Buffer Seg(Ask Plasma) SetVideoSeg LAYER 'Set Draw to Buffer T# = TIMER frame& = 0 'frame counter for FPS DO K$ = INKEY$ 'user control of camera SELECT CASE UCASE$(K$) CASE "A" camz% = camz% + 1 CASE "Z" camz% = camz% - 1 CASE "S" camy% = camy% + 1 CASE "X" camy% = camy% - 1 CASE "D" camx% = camx% + 1 CASE "C" camx% = camx% - 1 CASE ELSE END SELECT frame& = frame& + 1 SetVideoSeg LAYER 'Set Draw to Buffer LINE (0, 0)-(319, 199), 0, BF 'cls Thetax = (Thetax + 1) MOD 360 'increase angles of rotation Thetay = (Thetay + 1) MOD 360 Thetaz = (Thetaz + 1) MOD 360 '''rotate object RotateAndProject Model(), Thetax, Thetay, Thetaz ''sort em by distance SortPolys Model(), Tri() ''show our original texture PUT (0, 0), Texture%, PSET ''draw our textured model DrawModel Model(), Tri(), Cull SetVideoSeg &HA000 'set draw to screen WAIT &H3DA, 8 'vsynch PUT (0, 0), Vpage(6), PSET 'BitBlit LOOP UNTIL K$ = CHR$(27) 'escape"? DEF SEG 'restore current seg CLS SCREEN 0 WIDTH 80 PRINT frame& / (TIMER - T#) 'print FPS c$ = INPUT$(1) 'wait for keypress... FFIX -1 END '''Cube polygon connecting points in Quad form CUBECONNECT: DATA 0, 1, 2, 3 DATA 1, 5, 6, 2 DATA 5, 4, 7, 6 DATA 4, 0, 3, 7 DATA 4, 5, 1, 0 DATA 3, 2, 6, 7 REM $STATIC SUB AF.Print (Xpos%, Ypos%, Text$, Col%) 'Prints the standard 8*8 CGA font 'Paramenters: 'Segment=the Layer to print to 'Xpos,Ypos=the coordinates of the text 'Text$=the string to print 'col= is the color to print(gradient) x% = Xpos% y% = Ypos% Spacing% = 8 FOR i% = 0 TO LEN(Text$) - 1 x% = x% + Spacing% offset% = 8 * ASC(MID$(Text$, i% + 1, 1)) + 14 FOR j% = 0 TO 7 DEF SEG = &HFFA6 Bit% = PEEK(offset% + j%) IF Bit% AND 1 THEN PSET (x%, y% + j%), Col% + j% IF Bit% AND 2 THEN PSET (x% - 1, y% + j%), Col% + j% IF Bit% AND 4 THEN PSET (x% - 2, y% + j%), Col% + j% IF Bit% AND 8 THEN PSET (x% - 3, y% + j%), Col% + j% IF Bit% AND 16 THEN PSET (x% - 4, y% + j%), Col% + j% IF Bit% AND 32 THEN PSET (x% - 5, y% + j%), Col% + j% IF Bit% AND 64 THEN PSET (x% - 6, y% + j%), Col% + j% IF Bit% AND 128 THEN PSET (x% - 7, y% + j%), Col% + j% NEXT j% NEXT i% END SUB SUB DrawModel (Model() AS Point3d, Poly() AS PolyType, Cull) STATIC 'if its a plane, 'we don't need to backface cull thre polys as the planes 'are supposed to be displayed. ;*) FOR i = 0 TO UBOUND(Poly) j = Poly(i).idx x1 = Model(Poly(j).p1).scrx 'Get triangles from "projected" x2 = Model(Poly(j).p2).scrx 'X and Y coords since Znormal x3 = Model(Poly(j).p3).scrx 'Does not require a Z coord y1 = Model(Poly(j).p1).scry 'V1= Point1 connected to V2 then y2 = Model(Poly(j).p2).scry 'V2 to V3 and so on... y3 = Model(Poly(j).p3).scry IF Cull THEN Znormal = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3) IF (Znormal < 0) THEN u1 = Poly(j).u1 v1 = Poly(j).v1 u2 = Poly(j).u2 v2 = Poly(j).v2 u3 = Poly(j).u3 v3 = Poly(j).v3 TOFF% = VARPTR(Texture%(0)) Tritexture x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3, TextSeg%, TOFF% END IF ELSE u1 = Poly(j).u1 v1 = Poly(j).v1 u2 = Poly(j).u2 v2 = Poly(j).v2 u3 = Poly(j).u3 v3 = Poly(j).v3 TOFF% = VARPTR(Texture%(0)) Tritexture x1, y1, x2, y2, x3, y3, u1, v1, u2, v2, u3, v3, TextSeg%, TOFF% END IF NEXT i END SUB SUB FFIX (Mode%) STATIC IF Mode% = 0 THEN DIM isr(0 TO 5) AS LONG 'FFix by Dav,Plasma and v1ctor isr(0) = &H53EC8B55: isr(1) = &H83025E8B isr(2) = &H8E0602EB: isr(3) = &HC7260446 isr(4) = &H79B9007: isr(5) = &HCF9B5D5B DEF SEG = 0 OldISR1 = PEEK(&HF4) OldISR2 = PEEK(&HF5) OldISR3 = PEEK(&HF6) OldISR4 = PEEK(&HF7) POKE &HF4, VARPTR(isr(0)) AND 255 POKE &HF5, (CLNG(VARPTR(isr(0))) AND &HFF00&) \ 256 POKE &HF6, VARSEG(isr(0)) AND 255 POKE &HF7, (CLNG(VARSEG(isr(0))) AND &HFF00&) \ 256 ELSE DEF SEG = 0 POKE &HF4, OldISR1 POKE &HF5, OldISR2 POKE &HF6, OldISR3 POKE &HF7, OldISR4 END IF END SUB SUB HTLine (xx1%, xx2%, yy%, uu1&, uu2&, vv1&, vv2&, Twidth%, TOFF%) x1% = xx1% x2% = xx2% y% = yy% u1& = uu1& v1& = vv1& u2& = uu2& v2& = vv2& IF x1% > x2% THEN SWAP x1%, x2%: SWAP u1&, u2&: SWAP v1&, v2& xdiff% = 1 + x2% - x1% du& = (u2& - u1&) \ xdiff% dv& = (v2& - v1&) \ xdiff% u& = u1& v& = v1& Twidthm1% = Twidth% - 1 FOR l% = x1% TO x2% u% = (u& \ 65536) AND Twidthm1% v% = (v& \ 65536) AND Twidthm1% Col% = PEEK(TOFF% + (u% + v% * Twidth%)) PSET (l%, y%), Col% u& = u& + du& v& = v& + dv& NEXT l% END SUB SUB LoadCube (Model() AS Point3d, Poly() AS PolyType, radius) 'Generation code by: 'by Steve McCarthy(SCM) 'Tesselation by me. :*) REDIM Model(7) AS Point3d Theta! = PI / 4 dTheta! = PI / 2 FOR P = 0 TO 7 Model(P).x = radius * SGN(COS(Theta!)) ' x Model(P).y = radius * SGN(SIN(Theta!)) ' y Model(P).z = radius - (radius * 2) * (P \ 4) ' z Theta! = Theta! + dTheta! NEXT P 'Tesselate REDIM Poly(11) AS PolyType RESTORE CUBECONNECT j = 0 FOR i = 0 TO 5 READ p1, p2, p3, p4 Poly(j).p1 = p4 Poly(j).p2 = p2 Poly(j).p3 = p1 j = j + 1 Poly(j).p1 = p4 Poly(j).p2 = p3 Poly(j).p3 = p2 j = j + 1 NEXT i 'calculate vertex coords centering it FOR j = 0 TO UBOUND(Poly) u1 = 0 v1 = 0 u2 = TSIZEM1% v2 = TSIZEM1% u3 = TSIZEM1% v3 = 0 Poly(j).u1 = u1 Poly(j).v1 = v1 Poly(j).u2 = u2 Poly(j).v2 = v2 Poly(j).u3 = u3 Poly(j).v3 = v3 Poly(j).idx = j j = j + 1 u1 = 0 v1 = 0 u2 = 0 v2 = TSIZEM1% u3 = TSIZEM1% v3 = TSIZEM1% Poly(j).u1 = u1 Poly(j).v1 = v1 Poly(j).u2 = u2 Poly(j).v2 = v2 Poly(j).u3 = u3 Poly(j).v3 = v3 Poly(j).idx = j NEXT j END SUB SUB LoadCylinder (Model() AS Point3d, Poly() AS PolyType, radius, Slices, Bands, zdist) 'Generation code by: 'by Relsoft=me .;*) 'I. Cylindrical to cartesian '/// x = COS(theta) '/// y = SIN(theta) '/// z = z REDIM Model((Slices * Bands) - 1) AS Point3d i = 0 z! = -zdist * Slices / 2 FOR Slice = 0 TO Slices - 1 FOR Band = 0 TO Bands - 1 Theta! = (2 * PI / Bands) * Band Model(i).x = radius * COS(Theta!) Model(i).y = radius * SIN(Theta!) Model(i).z = z! i = i + 1 NEXT Band z! = z! + zdist NEXT Slice i = 0 MaxPoly = 0 FOR Slice = 0 TO Slices - 1 FOR Band = 0 TO Bands - 1 i = i + 2 MaxPoly = MaxPoly + 2 NEXT Band NEXT Slice REDIM Poly(MaxPoly) AS PolyType MaxVertex = (Slices * Bands) i = 0 FOR Slice = 0 TO Slices - 1 FOR Band = 0 TO Bands - 1 Poly(i).p1 = (Slice * Slices + Band + Slices) MOD MaxVertex Poly(i).p2 = Slice * Slices + (Band + 1) MOD Slices Poly(i).p3 = Slice * Slices + Band i = i + 1 Poly(i).p1 = (Slice * Slices + Band + Slices) MOD MaxVertex Poly(i).p2 = (Slice * Slices + (Band + 1) MOD Slices + Slices) MOD MaxVertex Poly(i).p3 = Slice * Slices + (Band + 1) MOD Slices i = i + 1 NEXT Band NEXT Slice 'calculate vertex coords centering it FOR j = 0 TO UBOUND(Poly) - 1 u1 = 0 v1 = 0 u2 = TSIZEM1% v2 = TSIZEM1% u3 = TSIZEM1% v3 = 0 Poly(j).u1 = u1 Poly(j).v1 = v1 Poly(j).u2 = u2 Poly(j).v2 = v2 Poly(j).u3 = u3 Poly(j).v3 = v3 Poly(j).idx = j j = j + 1 u1 = 0 v1 = 0 u2 = 0 v2 = TSIZEM1% u3 = TSIZEM1% v3 = TSIZEM1% Poly(j).u1 = u1 Poly(j).v1 = v1 Poly(j).u2 = u2 Poly(j).v2 = v2 Poly(j).u3 = u3 Poly(j).v3 = v3 Poly(j).idx = j NEXT j END SUB SUB LoadPlane (Model() AS Point3d, Poly() AS PolyType, radius) 'Generation code by: 'by Relsoft = me ;*) REDIM Model(3) AS Point3d REDIM Poly(1) AS PolyType Theta! = 90 * PI / 180 FOR i = 0 TO 3 Model(i).x = radius * (COS(Theta!)) Model(i).y = radius * (SIN(Theta!)) Model(i).z = 0 Theta! = Theta! + PI / 2 NEXT i 'set poly num(Tesselate) Poly(0).p1 = 3 Poly(0).p2 = 1 Poly(0).p3 = 0 Poly(1).p1 = 3 Poly(1).p2 = 2 Poly(1).p3 = 1 'calculate vertex coords centering it FOR j = 0 TO UBOUND(Poly) u1 = 0 v1 = 0 u2 = TSIZEM1% v2 = TSIZEM1% u3 = TSIZEM1% v3 = 0 Poly(j).u1 = u1 Poly(j).v1 = v1 Poly(j).u2 = u2 Poly(j).v2 = v2 Poly(j).u3 = u3 Poly(j).v3 = v3 Poly(j).idx = j j = j + 1 u1 = 0 v1 = 0 u2 = 0 v2 = TSIZEM1% u3 = TSIZEM1% v3 = TSIZEM1% Poly(j).u1 = u1 Poly(j).v1 = v1 Poly(j).u2 = u2 Poly(j).v2 = v2 Poly(j).u3 = u3 Poly(j).v3 = v3 Poly(j).idx = j NEXT j END SUB SUB LoadSphere (Model() AS Point3d, Poly() AS PolyType, radius, Slices, Bands) 'Generation code by: 'by Relsoft=me .;*) '/// x = p SIN(Phi) COS(theta) '/// y = p SIN(Phi) SIN(theta) '/// z = p COS(Phi) MaxVertex = (1 + Slices) * (Bands + 1) - Bands REDIM Model(MaxVertex) AS Point3d i = 0 FOR SliceLoop = 0 TO Slices Phi! = PI / Slices * SliceLoop FOR BandLoop = 0 TO Bands - 1 Theta! = 2 * PI / Bands * BandLoop Model(i).x = -INT(radius * SIN(Phi!) * COS(Theta!)) Model(i).y = -INT(radius * SIN(Phi!) * SIN(Theta!)) Model(i).z = -INT(radius * COS(Phi!)) i = i + 1 NEXT BandLoop NEXT SliceLoop i = 0 MaxPoly = 0 FOR Slice = 0 TO Slices FOR Band = 0 TO Bands - 1 i = i + 2 MaxPoly = MaxPoly + 2 NEXT Band NEXT Slice REDIM Poly(MaxPoly) AS PolyType i = 0 FOR Slice = 0 TO Slices FOR Band = 0 TO Bands - 1 Poly(i).p1 = (Slice * Slices + Band + Slices) MOD MaxVertex Poly(i).p2 = Slice * Slices + (Band + 1) MOD Slices Poly(i).p3 = Slice * Slices + Band i = i + 1 Poly(i).p1 = (Slice * Slices + Band + Slices) MOD MaxVertex Poly(i).p2 = (Slice * Slices + (Band + 1) MOD Slices + Slices) MOD MaxVertex Poly(i).p3 = Slice * Slices + (Band + 1) MOD Slices i = i + 1 NEXT Band NEXT Slice 'calculate vertex coords centering it FOR j = 0 TO UBOUND(Poly) - 1 u1 = 0 v1 = 0 u2 = TSIZEM1% v2 = TSIZEM1% u3 = TSIZEM1% v3 = 0 Poly(j).u1 = u1 Poly(j).v1 = v1 Poly(j).u2 = u2 Poly(j).v2 = v2 Poly(j).u3 = u3 Poly(j).v3 = v3 Poly(j).idx = j j = j + 1 u1 = 0 v1 = 0 u2 = 0 v2 = TSIZEM1% u3 = TSIZEM1% v3 = TSIZEM1% Poly(j).u1 = u1 Poly(j).v1 = v1 Poly(j).u2 = u2 Poly(j).v2 = v2 Poly(j).u3 = u3 Poly(j).v3 = v3 Poly(j).idx = j NEXT j END SUB SUB RotateAndProject (Model() AS Point3d, AngleX, AngleY, AngleZ) STATIC ''Right handed system ''when camera components increase: ''x=goes left ''y=goes down ''z goes into the screen '''rotation: counter-clockwise of each axis ''ei. make yourself perpenicular to the axis ''wave your hand from the center of your body to the left. ''That's how it rotates. ;*) 'Precalculate the SIN and COS of each angle cx! = Lcos(AngleX) sx! = Lsin(AngleX) cy! = Lcos(AngleY) sy! = Lsin(AngleY) cz! = Lcos(AngleZ) sz! = Lsin(AngleZ) '''After2 hours of work, I was able to weed out the constants from '''Rotate and project N to reduce my muls to 9 instead of 12. woot!!!! xx! = cy! * cz! xy! = sx! * sy! * cz! - cx! * sz! xz! = cx! * sy! * cz! + sx! * sz! yx! = cy! * sz! yy! = cx! * cz! + sx! * sy! * sz! yz! = -sx! * cz! + cx! * sy! * sz! zx! = -sy! zy! = sx! * cy! zz! = cx! * cy! FOR i = 0 TO UBOUND(Model) x! = Model(i).x y! = Model(i).y z! = Model(i).z RotX! = (x! * xx! + y! * xy! + z! * xz!) - camx% RotY! = (x! * yx! + y! * yy! + z! * yz!) - camy% RotZ! = (x! * zx! + y! * zy! + z! * zz!) - camz% Model(i).xr = RotX! Model(i).yr = RotY! Model(i).Zr = RotZ! 'Project Distance% = (LENS - RotZ!) IF Distance% THEN Model(i).scrx = (LENS * RotX! / Distance%) + XCENTER Model(i).scry = -(LENS * RotY! / Distance%) + YCENTER ELSE END IF NEXT i END SUB SUB SetVideoSeg (Segment) STATIC DEF SEG IF VideoAddrOff& = 0 THEN ' First time the sub is called ' We need to find the location of b$AddrC, which holds the graphics ' offset (b$OffC) and segment (b$SegC). Since b$AddrC is in the default ' segment, we can find it by setting it to a certain value, and then ' searching for that value. SCREEN 13 ' Set b$SegC to A000 (00A0 in memory) PSET (160, 100), 0 ' Set b$OffC to 7DA0 (not needed in the IDE) FOR offset& = 0 TO 32764 ' Search for b$AddrC, which is IF PEEK(offset&) = &HA0 THEN ' in the default segment and IF PEEK(offset& + 1) = &H7D THEN ' should have a value of IF PEEK(offset& + 2) = &H0 THEN ' A0 7D 00 A0. IF PEEK(offset& + 3) = &HA0 THEN VideoAddrOff& = offset& + 2 ' If we found it, record the EXIT FOR ' offset of b$SegC and quit END IF ' looking. (Oddly, changing END IF ' the b$OffC doesn't seem to END IF ' do anything, so this is why END IF ' this sub only changes b$SegC) NEXT END IF ' Change b$SegC to the specified Segment POKE VideoAddrOff&, Segment AND &HFF POKE VideoAddrOff& + 1, (Segment AND &HFF00&) \ &H100 END SUB SUB ShellSort (Poly() AS PolyType, Min, Max) 'Shell sort Algorithm ' Set comparison offset to half the number of records. offset = Max \ 2 ' Loop until offset gets to zero. DO WHILE offset > 0 Limit = Max - offset DO ' Assume no switches at this offset. Switch = FALSE ' Compare elements for the specified field and switch ' any that are out of order. FOR i = Min TO Limit - 1 Ti = Poly(i).zcenter Tj = Poly(i + offset).zcenter IF Ti > Tj THEN SWAP Poly(i).idx, Poly(i + offset).idx SWAP Poly(i).zcenter, Poly(i + offset).zcenter Switch = i END IF NEXT i ' Sort on next pass only to location where last switch was made. Limit = Switch LOOP WHILE Switch ' No switches at last offset. Try an offset half as big. offset = offset \ 2 LOOP END SUB SUB SortPolys (Model() AS Point3d, Poly() AS PolyType) FOR i% = 0 TO UBOUND(Poly) Poly(i%).zcenter = Model(Poly(i%).p1).Zr + Model(Poly(i%).p2).Zr + Model(Poly(i%).p3).Zr Poly(i%).idx = i% NEXT i% ShellSort Poly(), 0, UBOUND(Poly) END SUB SUB Tritexture (xx1%, yy1%, xx2%, yy2%, xx3%, yy3%, uu1%, vv1%, uu2%, vv2%, uu3%, vv3%, TSEG%, TOFF%) x1% = xx1% y1% = yy1% u1% = uu1% v1% = vv1% x2% = xx2% y2% = yy2% u2% = uu2% v2% = vv2% x3% = xx3% y3% = yy3% u3% = uu3% v3% = vv3% DEF SEG = TSEG% TSIZ% = (PEEK(TOFF%) + PEEK(TOFF% + 1) * 256) \ 8 IF y1% > y2% THEN SWAP y1%, y2%: SWAP x1%, x2%: SWAP u1%, u2%: SWAP v1%, v2% IF y1% > y3% THEN SWAP y1%, y3%: SWAP x1%, x3%: SWAP u1%, u3%: SWAP v1%, v3% IF y2% > y3% THEN SWAP y2%, y3%: SWAP x2%, x3%: SWAP u2%, u3%: SWAP v2%, v3% d1& = 0: dg1 = 0 ydiffa% = y2% - y1% IF ydiffa% THEN d1& = ((x2% - x1%) * 65536) \ ydiffa% ud1& = ((u2% - u1%) * 65536) \ ydiffa% vd1& = ((v2% - v1%) * 65536) \ ydiffa% END IF ydiffb% = y3% - y2% IF ydiffb% THEN d2& = ((x3% - x2%) * 65536) \ ydiffb% ud2& = ((u3% - u2%) * 65536) \ ydiffb% vd2& = ((v3% - v2%) * 65536) \ ydiffb% END IF ydiffc% = y3% - y1% IF ydiffc% THEN d3& = ((x3% - x1%) * 65536) \ ydiffc% ud3& = ((u3% - u1%) * 65536) \ ydiffc% vd3& = ((v3% - v1%) * 65536) \ ydiffc% END IF lx& = x1% * 65536 rx& = x1% * 65536 lu& = u1% * 65536: ru& = lu& lv& = v1% * 65536: rv& = lv& FOR y% = y1% TO y2% - 1 HTLine (lx& \ 65536), (rx& \ 65536), y%, (lu&), (ru&), (lv&), (rv&), TSIZ%, TOFF% + 4 lx& = lx& + d1& rx& = rx& + d3& lu& = lu& + ud1& ru& = ru& + ud3& lv& = lv& + vd1& rv& = rv& + vd3& NEXT lx& = (x2% * 65536) lu& = u2% * 65536 lv& = v2% * 65536 ' HERE d1 has been added (y2%-y1%)+1 times to lx = x2 ' d3 has been added (y2%-y1%)+1 times to rx FOR y% = y2% TO y3% HTLine (lx& \ 65536), (rx& \ 65536), y%, (lu&), (ru&), (lv&), (rv&), TSIZ%, TOFF% + 4 lx& = lx& + d2& rx& = rx& + d3& lu& = lu& + ud2& ru& = ru& + ud3& lv& = lv& + vd2& rv& = rv& + vd3& NEXT y% END SUB