DECLARE SUB RenderPreview () DECLARE SUB RenderWireframe () DECLARE SUB ScanStartingEdge (x1%, y1%, x2%, y2%) DECLARE SUB ScanEndingEdge (x1%, y1%, x2%, y2%) DECLARE SUB DrawTriangle (x1%, y1%, x2%, y2%, x3%, y3%, c%) ' Working edge arrays DIM SHARED workingEdgeStart%(480), workingEdgeEnd%(480) TYPE TrackSegment angle AS INTEGER length AS INTEGER widthDelta AS INTEGER END TYPE DIM SHARED Track(20) AS TrackSegment DIM SHARED NumSegments AS INTEGER DIM SHARED workingSegment% READ TrackName$ READ NumSegments FOR i% = 0 TO NumSegments - 1 READ Track(i%).angle, Track(i%).length, Track(i%).widthDelta NEXT i% workingSegment% = NumSegments - 1 SCREEN 12 DO RenderWireframe k$ = "" WHILE k$ = "" k$ = UCASE$(INKEY$) WEND IF k$ = "Q" OR k$ = CHR$(27) THEN EXIT DO IF k$ = "A" THEN NumSegments = NumSegments + 1 Track(NumSegments).angle = 0 Track(NumSegments).length = 1 Track(NumSegments).widthDelta = 0 workingSegment% = workingSegment% + 1 END IF IF k$ = "D" THEN NumSegments = NumSegments - 1 workingSegment% = workingSegment% - 1 END IF IF k$ = "N" THEN workingSegment% = workingSegment% + 1 IF k$ = "P" THEN workingSegment% = workingSegment% - 1 IF workingSegment% < 0 THEN workingSegment% = NumSegments - 1 IF workingSegment% >= NumSegments THEN workingSegment% = 0 IF k$ = CHR$(0) + "H" THEN Track(workingSegment%).length = Track(workingSegment%).length + 1 IF k$ = CHR$(0) + "P" THEN Track(workingSegment%).length = Track(workingSegment%).length - 1 IF k$ = CHR$(0) + "K" THEN Track(workingSegment%).angle = Track(workingSegment%).angle + 5 IF k$ = CHR$(0) + "M" THEN Track(workingSegment%).angle = Track(workingSegment%).angle - 5 IF k$ = "W" THEN Track(workingSegment%).widthDelta = Track(workingSegment%).widthDelta + 5 IF k$ = "S" THEN Track(workingSegment%).widthDelta = Track(workingSegment%).widthDelta - 5 IF k$ = "R" THEN RenderPreview WHILE INKEY$ = "": WEND END IF IF k$ = "X" THEN OPEN "c:\basic\vfix\tracks.txt" FOR APPEND AS 1 PRINT #1, "DATA " + CHR$(34) + "Exported Track" + CHR$(34) PRINT #1, "DATA " + STR$(NumSegments) TrackData$ = "DATA " FOR i% = 0 TO NumSegments - 1 IF i% <> 0 THEN TrackData$ = TrackData$ + "," TrackData$ = TrackData$ + STR$(Track(i%).angle) TrackData$ = TrackData$ + "," + STR$(Track(i%).length) TrackData$ = TrackData$ + "," + STR$(Track(i%).widthDelta) NEXT i% PRINT #1, TrackData$ CLOSE #1 EXIT DO END IF LOOP DATA "My Track" DATA 9 DATA 0, 5, 0, -90, 18, 0, 0, 3, 0, -90, 18, 0, 0, 10, 0, -90, 18, 0, 0, 3, 0, -90, 18, 0, 0, 5, 0 SUB DrawTriangle (x1%, y1%, x2%, y2%, x3%, y3%, c%) ' Ensure vertices are in the correct order IF y2% < y1% THEN SWAP y2%, y1%: SWAP x2%, x1% IF y3% < y1% THEN SWAP y3%, y1%: SWAP x3%, x1% IF y3% < y2% THEN SWAP y3%, y2%: SWAP x3%, x2% ' Scan convert top triangle ScanStartingEdge x1%, y1%, x2%, y2% ScanEndingEdge x1%, y1%, x3%, y3% height% = y2% - y1% FOR i% = 0 TO height% y% = i% + y1% LINE (workingEdgeStart%(i%), y%)-(workingEdgeEnd%(i%), y%), c% NEXT i% IF y3% > y2% THEN ScanStartingEdge x2%, y2%, x3%, y3% height2% = y3% - y1% FOR i% = height% TO height2% y% = i% + y1% LINE (workingEdgeStart%(i% - height%), y%)-(workingEdgeEnd%(i%), y%), c% NEXT i% END IF END SUB SUB RenderPreview CLS DegToRad! = (3.141593 / 180) trackX! = 316 trackY! = 95 curAngle! = 90 curWidth! = 36 DIM x1%, y1%, x2%, y2% LINE (0, 0)-(640, 480), 2, BF cosine = COS(curAngle! * DegToRad!) sine = SIN(curAngle! * DegToRad!) ' Run through the track once to get the co-ordinates of the final segment FOR i% = 0 TO NumSegments - 1 FOR j% = 0 TO Track(i%).length - 1 cosine = COS(curAngle! * DegToRad!) sine = SIN(curAngle! * DegToRad!) x1% = trackX! + (curWidth! * cosine) y1% = trackY! - (curWidth! * sine) x2% = trackX! - (curWidth! * cosine) y2% = trackY! + (curWidth! * sine) trackX! = trackX! + (10 * sine) trackY! = trackY! + (10 * cosine) curAngle! = curAngle! + (Track(i%).angle / Track(i%).length) curWidth! = curWidth! + (Track(i%).widthDelta / Track(i%).length) NEXT j% NEXT i% trackX! = 316 trackY! = 95 curAngle! = 90 curWidth! = 35 FOR i% = 0 TO NumSegments - 1 kd1% = 0 kd2% = 0 FOR j% = 0 TO Track(i%).length - 1 cosine = COS(curAngle! * DegToRad!) sine = SIN(curAngle! * DegToRad!) prevX1% = x1%: prevX2% = x2% prevY1% = y1%: prevY2% = y2% prevKX1% = kX1%: prevKX2% = kX2% prevKY1% = kY1%: prevKY2% = kY2% x1% = trackX! + (curWidth! * cosine) y1% = trackY! - (curWidth! * sine) kX1% = trackX! + ((curWidth! + 4) * cosine) kY1% = trackY! - ((curWidth! + 4) * sine) x2% = trackX! - (curWidth! * cosine) y2% = trackY! + (curWidth! * sine) kX2% = trackX! - ((curWidth! + 4) * cosine) kY2% = trackY! + ((curWidth! + 4) * sine) DrawTriangle (prevX1%), (prevY1%), (x1%), (y1%), (prevX2%), (prevY2%), 0 DrawTriangle (prevX2%), (prevY2%), (x1%), (y1%), (x2%), (y2%), 0 IF Track(i%).angle <> 0 AND j% > 0 THEN SELECT CASE j% MOD 4 CASE 0: kc% = 15 CASE 1: kc% = 9 CASE 2: kc% = 15 CASE 3: kc% = 12 END SELECT DrawTriangle (prevX1%), (prevY1%), (prevKX1%), (prevKY1%), (kX1%), (kY1%), kc% DrawTriangle (prevX1%), (prevY1%), (kX1%), (kY1%), (x1%), (y1%), kc% DrawTriangle (prevX2%), (prevY2%), (prevKX2%), (prevKY2%), (kX2%), (kY2%), kc% DrawTriangle (prevX2%), (prevY2%), (kX2%), (kY2%), (x2%), (y2%), kc% END IF trackX! = trackX! + (10 * sine) trackY! = trackY! + (10 * cosine) curAngle! = curAngle! + (Track(i%).angle / Track(i%).length) curWidth! = curWidth! + (Track(i%).widthDelta / Track(i%).length) NEXT j% NEXT i% LINE (318, 60)-(318, 130), 15, , &HF0F0 LINE (319, 60)-(319, 130), 15, , &HF0F0 LINE (317, 60)-(317, 130), 15, , &HF0F0 LINE (320, 60)-(320, 130), 15, , &HF0F LINE (321, 60)-(321, 130), 15, , &HF0F LINE (322, 60)-(322, 130), 15, , &HF0F LINE (323, 60)-(323, 130), 15 LINE (316, 60)-(316, 130), 15 END SUB SUB RenderWireframe CLS DegToRad! = (3.141593 / 180) trackX! = 640 / 2 trackY! = 100 curAngle! = 90 curWidth! = 40 cp% = 0 FOR i% = 0 TO NumSegments - 1 FOR j% = 0 TO Track(i%).length - 1 cosine = COS(curAngle! * DegToRad!) sine = SIN(curAngle! * DegToRad!) col% = 12 IF i% = workingSegment% THEN col% = 14 LINE (trackX! + (curWidth! * cosine), trackY! - (curWidth! * sine))-(trackX! - (curWidth! * cosine), trackY! + (curWidth! * sine)), col% PSET (trackX!, trackY!), 15 IF cp% = 4 THEN LINE (trackX! - 1, trackY! - 1)-(trackX! + 1, trackY! + 1), 12, BF LINE (trackX! - curWidth!, trackY! - curWidth!)-(trackX! + curWidth!, trackY! + curWidth!), 10, B END IF cp% = (cp% + 1) MOD 6 trackX! = trackX! + (10 * sine) trackY! = trackY! + (10 * cosine) curAngle! = curAngle! + (Track(i%).angle / Track(i%).length) curWidth! = curWidth! + (Track(i%).widthDelta / Track(i%).length) NEXT j% NEXT i% END SUB SUB ScanEndingEdge (x1%, y1%, x2%, y2%) DIM x%, y%, i%, w% DIM deltaX%, height% DIM advanceAmt%, errorTerm%, errorTermAdv% DIM xMajorAdvAmt% x% = x1% deltaX% = x2% - x1% w% = ABS(deltaX%) IF deltaX% > 0 THEN advanceAmt% = 1 ELSE advanceAmt% = -1 height% = y2% - y1% IF height% <= 0 THEN workingEdgeEnd%(i%) = x% EXIT SUB END IF ' Case 1: vertical IF w% = 0 THEN FOR i% = 0 TO height% workingEdgeEnd%(i%) = x% NEXT i% ' Case 2: y-major ELSEIF height% > w% THEN IF deltaX% >= 0 THEN errorTerm% = 0 ELSE errorTerm% = 1 - height% FOR i% = 0 TO height% workingEdgeEnd%(i%) = x% errorTerm% = errorTerm% + w% IF errorTerm% > 0 THEN x% = x% + advanceAmt% errorTerm% = errorTerm% - height% END IF NEXT i% ' Case 3: x-major ELSE xMajorAdvAmt% = (w% \ height%) * advanceAmt% errorTermAdv% = w% MOD height% IF deltaX% >= 0 THEN errorTerm% = 0 ELSE errorTerm% = 1 - height% FOR i% = 0 TO height% workingEdgeEnd%(i%) = x% x% = x% + xMajorAdvAmt% errorTerm% = errorTerm% + errorTermAdv% IF errorTerm% > 0 THEN x% = x% + advanceAmt% errorTerm% = errorTerm% - height% END IF NEXT i% END IF END SUB SUB ScanStartingEdge (x1%, y1%, x2%, y2%) DIM x%, y%, i%, w% DIM deltaX%, height% DIM advanceAmt%, errorTerm%, errorTermAdv% DIM xMajorAdvAmt% x% = x1% deltaX% = x2% - x1% w% = ABS(deltaX%) IF deltaX% > 0 THEN advanceAmt% = 1 ELSE advanceAmt% = -1 height% = y2% - y1% IF height% <= 0 THEN workingEdgeStart%(i%) = x% EXIT SUB END IF ' Case 1: vertical IF w% = 0 THEN FOR i% = 0 TO height% workingEdgeStart%(i%) = x% NEXT i% ' Case 2: y-major ELSEIF height% > w% THEN IF deltaX% >= 0 THEN errorTerm% = 0 ELSE errorTerm% = 1 - height% FOR i% = 0 TO height% workingEdgeStart%(i%) = x% errorTerm% = errorTerm% + w% IF errorTerm% > 0 THEN x% = x% + advanceAmt% errorTerm% = errorTerm% - height% END IF NEXT i% ' Case 3: x-major ELSE xMajorAdvAmt% = (w% \ height%) * advanceAmt% errorTermAdv% = w% MOD height% IF deltaX% >= 0 THEN errorTerm% = 0 ELSE errorTerm% = 1 - height% FOR i% = 0 TO height% workingEdgeStart%(i%) = x% x% = x% + xMajorAdvAmt% errorTerm% = errorTerm% + errorTermAdv% IF errorTerm% > 0 THEN x% = x% + advanceAmt% errorTerm% = errorTerm% - height% END IF NEXT i% END IF END SUB