Menu | JAQForum Ver 19.10.27 |
Forum Index : Microcontroller and PC projects : Elite ships converted to full 3D by CLAUDE
The following is I think extraordinary - I'll leave it to you to judge https://elite.bbcelite.com/deep_dives/ship_blueprints.html Has blueprints for all the ships used in the game ELITE as used in the 6502 source. Unfortunately, the way these are defined is incompatible with the MMBasic 3D engine so I thought that would be a good test for CLAUDE. I fed it the MMBasic manual for the Pico together with the 3D pdf manual from the download. I then screen scraped one of the ships (VIPER) and saved it as a txt file on the PICO - see below. I then asked CLAUDE to write a MMbasic program to convert this into a basic program that would read in the Elite model file and convert it to Basic statements to create the 3D model in MMBasic and then display it. It took a small number of iterations some Basic syntax, others the maths e.g. Me Claude Here is the converter that Claude produced - note that I told it to use OPTION EXPLICIT and below that is the fully running file displaying the Viper ship in 3D rotating on the screen ' Elite Ship Blueprint to MMBasic DRAW3D Converter ' Reads Elite ship data files and generates MMBasic code OPTION EXPLICIT OPTION BASE 0 ' Declare all variables DIM filename$ LENGTH 50 DIM outfile$ LENGTH 50 DIM txt$ LENGTH 200 DIM rest$ LENGTH 200 DIM s$ LENGTH 200 DIM INTEGER nv, ne, nf, i, j, k, p1, p2, f1, f2, dotpos DIM INTEGER totalidx, curr, nextv, found, startv DIM FLOAT vx(100), vy(100), vz(100) DIM INTEGER e1(100), e2(100), ef1(100), ef2(100) DIM INTEGER facevert(100, 20) DIM INTEGER facecount(100) DIM INTEGER edgeused(100) DIM INTEGER faceedges(50), nfaceedges ' Get filename from user INPUT "Enter ship blueprint filename: ", filename$ IF filename$ = "" THEN END ' Create output filename (change .txt to .bas) dotpos = INSTR(filename$, ".") IF dotpos > 0 THEN outfile$ = LEFT$(filename$, dotpos-1) + ".bas" ELSE outfile$ = filename$ + ".bas" ENDIF ' Open and read the file OPEN filename$ FOR INPUT AS #1 ' Skip to vertices section DO WHILE NOT EOF(#1) LINE INPUT #1, txt$ IF INSTR(txt$, "_VERTICES") > 0 THEN EXIT LOOP ' Count vertices and read vertex data nv = 0 DO WHILE NOT EOF(#1) LINE INPUT #1, txt$ txt$ = Trim$(txt$, " " + CHR$(9)) ' Stop at edges section IF INSTR(txt$, "_EDGES") > 0 THEN EXIT ' Parse VERTEX lines IF LEFT$(txt$, 6) = "VERTEX" THEN ' Extract x, y, z coordinates p1 = INSTR(txt$, " ") rest$ = Trim$(MID$(txt$, p1), " " + CHR$(9)) ' Get x coordinate p2 = INSTR(rest$, ",") vx(nv) = VAL(LEFT$(rest$, p2-1)) rest$ = Trim$(MID$(rest$, p2+1), " " + CHR$(9)) ' Get y coordinate p2 = INSTR(rest$, ",") vy(nv) = VAL(LEFT$(rest$, p2-1)) rest$ = Trim$(MID$(rest$, p2+1), " " + CHR$(9)) ' Get z coordinate p2 = INSTR(rest$, ",") vz(nv) = VAL(LEFT$(rest$, p2-1)) nv = nv + 1 ENDIF LOOP ' Count edges and read edge data ne = 0 DO WHILE NOT EOF(#1) LINE INPUT #1, txt$ txt$ = Trim$(txt$, " " + CHR$(9)) ' Stop at faces section IF INSTR(txt$, "_FACES") > 0 THEN EXIT ' Parse EDGE lines IF LEFT$(txt$, 4) = "EDGE" THEN ' Extract vertex1, vertex2, face1, face2 p1 = INSTR(txt$, " ") rest$ = Trim$(MID$(txt$, p1), " " + CHR$(9)) ' Get vertex1 p2 = INSTR(rest$, ",") e1(ne) = VAL(LEFT$(rest$, p2-1)) rest$ = Trim$(MID$(rest$, p2+1), " " + CHR$(9)) ' Get vertex2 p2 = INSTR(rest$, ",") e2(ne) = VAL(LEFT$(rest$, p2-1)) rest$ = Trim$(MID$(rest$, p2+1), " " + CHR$(9)) ' Get face1 p2 = INSTR(rest$, ",") ef1(ne) = VAL(LEFT$(rest$, p2-1)) rest$ = Trim$(MID$(rest$, p2+1), " " + CHR$(9)) ' Get face2 p2 = INSTR(rest$, ",") ef2(ne) = VAL(LEFT$(rest$, p2-1)) ne = ne + 1 ENDIF LOOP ' Count faces nf = 0 DO WHILE NOT EOF(#1) LINE INPUT #1, txt$ txt$ = Trim$(txt$, " " + CHR$(9)) IF LEFT$(txt$, 4) = "FACE" THEN nf = nf + 1 LOOP CLOSE #1 PRINT "Found"; nv; "vertices,"; ne; "edges,"; nf; "faces" PRINT "Writing output to: "; outfile$ ' Open output file OPEN outfile$ FOR OUTPUT AS #2 ' Initialize face data FOR i = 0 TO nf-1 facecount(i) = 0 NEXT i ' Build faces by following edges in order FOR f1 = 0 TO nf-1 ' Clear edge used flags for this face FOR i = 0 TO ne-1 edgeused(i) = 0 NEXT i ' Collect all edges that belong to this face nfaceedges = 0 FOR i = 0 TO ne-1 IF ef1(i) = f1 OR ef2(i) = f1 THEN faceedges(nfaceedges) = i nfaceedges = nfaceedges + 1 ENDIF NEXT i IF nfaceedges = 0 THEN CONTINUE FOR ' Start with first edge facevert(f1, 0) = e1(faceedges(0)) facevert(f1, 1) = e2(faceedges(0)) facecount(f1) = 2 edgeused(faceedges(0)) = 1 startv = e1(faceedges(0)) curr = e2(faceedges(0)) ' Follow edges to build complete face DO WHILE curr <> startv AND facecount(f1) < 20 found = 0 FOR j = 0 TO nfaceedges-1 i = faceedges(j) IF edgeused(i) = 0 THEN IF e1(i) = curr THEN nextv = e2(i) found = 1 ELSEIF e2(i) = curr THEN nextv = e1(i) found = 1 ENDIF IF found = 1 THEN IF nextv <> startv THEN facevert(f1, facecount(f1)) = nextv facecount(f1) = facecount(f1) + 1 ENDIF edgeused(i) = 1 curr = nextv EXIT FOR ENDIF ENDIF NEXT j IF found = 0 THEN EXIT DO LOOP NEXT f1 ' Calculate total face indices needed totalidx = 0 FOR i = 0 TO nf-1 totalidx = totalidx + facecount(i) NEXT i ' Generate MMBasic code to file PRINT #2, "' Generated from Elite ship blueprint: "; filename$ PRINT #2, "OPTION BASE 0" PRINT #2, "" PRINT #2, "DIM n = 1" PRINT #2, "DIM nv ="; nv PRINT #2, "DIM nf ="; nf PRINT #2, "DIM camera = 1" PRINT #2, "" PRINT #2, "' Vertex data" PRINT #2, "DIM FLOAT vertices(2,"; nv-1; ")" PRINT #2, "FOR i = 0 TO"; nv-1 PRINT #2, " READ vertices(0,i), vertices(1,i), vertices(2,i)" PRINT #2, "NEXT i" PRINT #2, "" ' Output vertex data FOR i = 0 TO nv-1 PRINT #2, "DATA"; vx(i); ","; vy(i); ","; vz(i) NEXT i PRINT #2, "" PRINT #2, "MATH SCALE vertices(), 2.0, vertices()" PRINT #2, "" PRINT #2, "' Face counts" PRINT #2, "DIM INTEGER facecount("; nf-1; ")" PRINT #2, "FOR i = 0 TO"; nf-1 PRINT #2, " READ facecount(i)" PRINT #2, "NEXT i" PRINT #2, "" ' Output face counts FOR i = 0 TO nf-1 STEP 10 s$ = "DATA " FOR j = i TO MIN(i+9, nf-1) s$ = s$ + STR$(facecount(j)) IF j < MIN(i+9, nf-1) THEN s$ = s$ + "," NEXT j PRINT #2, s$ NEXT i PRINT #2, "" PRINT #2, "' Face vertex indices ("; totalidx; "total)" PRINT #2, "DIM INTEGER faces("; totalidx-1; ")" PRINT #2, "FOR i = 0 TO"; totalidx-1 PRINT #2, " READ faces(i)" PRINT #2, "NEXT i" PRINT #2, "" ' Output face vertex data FOR i = 0 TO nf-1 s$ = "DATA " FOR j = 0 TO facecount(i)-1 s$ = s$ + STR$(facevert(i,j)) IF j < facecount(i)-1 THEN s$ = s$ + "," NEXT j PRINT #2, s$ NEXT i PRINT #2, "" PRINT #2, "' Colors" PRINT #2, "DIM INTEGER colours(4)" PRINT #2, "colours(0) = RGB(180,180,200)" PRINT #2, "colours(1) = RGB(100,100,120)" PRINT #2, "colours(2) = RGB(200,50,50)" PRINT #2, "colours(3) = RGB(60,60,80)" PRINT #2, "colours(4) = RGB(150,150,170)" PRINT #2, "" PRINT #2, "DIM INTEGER edge("; nf-1; ")" PRINT #2, "FOR i = 0 TO"; nf-1 PRINT #2, " edge(i) = 3" PRINT #2, "NEXT i" PRINT #2, "" PRINT #2, "DIM INTEGER fill("; nf-1; ")" PRINT #2, "FOR i = 0 TO"; nf-1 PRINT #2, " fill(i) = i MOD 5" PRINT #2, "NEXT i" PRINT #2, "" PRINT #2, "DRAW3D CREATE n, nv, nf, camera, vertices(), facecount(), faces(), colours(), edge(), fill()" PRINT #2, "" PRINT #2, "' Setup camera" PRINT #2, "DIM INTEGER viewplane = 600" PRINT #2, "DRAW3D CAMERA camera, viewplane, 0, 0" PRINT #2, "" PRINT #2, "' Animation variables" PRINT #2, "DIM FLOAT yaw = 0, pitch = 0, roll = 0" PRINT #2, "DIM FLOAT q1(4)" PRINT #2, "" PRINT #2, "CLS" PRINT #2, "" PRINT #2, "' Main display loop" PRINT #2, "DO" PRINT #2, " MATH Q_EULER yaw, pitch, roll, q1()" PRINT #2, " INC yaw, RAD(1)" PRINT #2, " INC pitch, RAD(2)" PRINT #2, " INC roll, RAD(0.5)" PRINT #2, " DRAW3D ROTATE q1(), 1" PRINT #2, " DRAW3D SHOW 1, 0, 0, 1000, 1" PRINT #2, " PAUSE 100" PRINT #2, "LOOP" CLOSE #2 PRINT "Conversion complete!" PRINT "Output written to: "; outfile$ END ' Custom Trim function (like manual example) FUNCTION Trim$(s$, c$) AS STRING LOCAL result$ LENGTH 200 result$ = s$ ' Trim from left DO WHILE INSTR(c$, LEFT$(result$, 1)) > 0 AND LEN(result$) > 0 result$ = MID$(result$, 2) LOOP ' Trim from right DO WHILE INSTR(c$, RIGHT$(result$, 1)) > 0 AND LEN(result$) > 0 result$ = LEFT$(result$, LEN(result$) - 1) LOOP Trim$ = result$ END FUNCTION ' Generated from Elite ship blueprint: viper.txt Option BASE 0 Dim n = 1 Dim nv = 15 Dim nf = 7 Dim camera = 1 ' Vertex data Dim FLOAT vertices(2, 14) For i = 0 To 14 Read vertices(0,i), vertices(1,i), vertices(2,i) Next i Data 0, 0, 72 Data 0, 16, 24 Data 0,-16, 24 Data 48, 0,-24 Data -48, 0,-24 Data 24,-16,-24 Data -24,-16,-24 Data 24, 16,-24 Data -24, 16,-24 Data -32, 0,-24 Data 32, 0,-24 Data 8, 8,-24 Data -8, 8,-24 Data -8,-8,-24 Data 8,-8,-24 Math SCALE vertices(), 2.0, vertices() ' Face counts Dim INTEGER facecount( 6) For i = 0 To 6 Read facecount(i) Next i Data 3,4,4,4,4,3,6 ' Face vertex indices ( 28total) Dim INTEGER faces( 27) For i = 0 To 27 Read faces(i) Next i Data 1,7,8 Data 0,1,8,4 Data 0,3,7,1 Data 0,2,6,4 Data 0,3,5,2 Data 2,5,6 Data 7,8,4,6,5,3 ' Colors Dim INTEGER colours(4) colours(0) = RGB(180,180,200) colours(1) = RGB(100,100,120) colours(2) = RGB(200,50,50) colours(3) = RGB(60,60,80) colours(4) = RGB(150,150,170) Dim INTEGER edge( 6) For i = 0 To 6 edge(i) = 3 Next i Dim INTEGER fill( 6) For i = 0 To 6 fill(i) = i Mod 5 Next i Draw3D CREATE n, nv, nf, camera, vertices(), facecount(), faces(), colours(), edge(), fill() ' Setup camera Dim INTEGER viewplane = 600 Draw3D CAMERA camera, viewplane, 0, 0 ' Animation variables Dim FLOAT yaw = 0, pitch = 0, roll = 0 Dim FLOAT q1(4) CLS ' Main display loop Do Math Q_EULER yaw, pitch, roll, q1() Inc yaw, Rad(1) Inc pitch, Rad(2) Inc roll, Rad(0.5) Draw3D ROTATE q1(), 1 Draw3D SHOW 1, 0, 0, 1000, 1 Pause 100 Loop .SHIP_VIPER EQUB 0 \ Max. canisters on demise = 0 EQUW 75 * 75 \ Targetable area = 75 * 75 EQUB LO(SHIP_VIPER_EDGES - SHIP_VIPER) \ Edges data offset (low) EQUB LO(SHIP_VIPER_FACES - SHIP_VIPER) \ Faces data offset (low) EQUB 77 \ Max. edge count = (77 - 1) / 4 = 19 EQUB 0 \ Gun vertex = 0 EQUB 42 \ Explosion count = 9, as (4 * n) + 6 = 42 EQUB 90 \ Number of vertices = 90 / 6 = 15 EQUB 20 \ Number of edges = 20 EQUW 0 \ Bounty = 0 EQUB 28 \ Number of faces = 28 / 4 = 7 EQUB 23 \ Visibility distance = 23 EQUB 120 \ Max. energy = 120 EQUB 32 \ Max. speed = 32 EQUB HI(SHIP_VIPER_EDGES - SHIP_VIPER) \ Edges data offset (high) EQUB HI(SHIP_VIPER_FACES - SHIP_VIPER) \ Faces data offset (high) EQUB 1 \ Normals are scaled by = 2^1 = 2 EQUB %00010001 \ Laser power = 2 \ Missiles = 1 .SHIP_VIPER_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 0, 0, 72, 1, 2, 3, 4, 31 \ Vertex 0 VERTEX 0, 16, 24, 0, 1, 2, 2, 30 \ Vertex 1 VERTEX 0, -16, 24, 3, 4, 5, 5, 30 \ Vertex 2 VERTEX 48, 0, -24, 2, 4, 6, 6, 31 \ Vertex 3 VERTEX -48, 0, -24, 1, 3, 6, 6, 31 \ Vertex 4 VERTEX 24, -16, -24, 4, 5, 6, 6, 30 \ Vertex 5 VERTEX -24, -16, -24, 5, 3, 6, 6, 30 \ Vertex 6 VERTEX 24, 16, -24, 0, 2, 6, 6, 31 \ Vertex 7 VERTEX -24, 16, -24, 0, 1, 6, 6, 31 \ Vertex 8 VERTEX -32, 0, -24, 6, 6, 6, 6, 19 \ Vertex 9 VERTEX 32, 0, -24, 6, 6, 6, 6, 19 \ Vertex 10 VERTEX 8, 8, -24, 6, 6, 6, 6, 19 \ Vertex 11 VERTEX -8, 8, -24, 6, 6, 6, 6, 19 \ Vertex 12 VERTEX -8, -8, -24, 6, 6, 6, 6, 18 \ Vertex 13 VERTEX 8, -8, -24, 6, 6, 6, 6, 18 \ Vertex 14 .SHIP_VIPER_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 3, 2, 4, 31 \ Edge 0 EDGE 0, 1, 1, 2, 30 \ Edge 1 EDGE 0, 2, 3, 4, 30 \ Edge 2 EDGE 0, 4, 1, 3, 31 \ Edge 3 EDGE 1, 7, 0, 2, 30 \ Edge 4 EDGE 1, 8, 0, 1, 30 \ Edge 5 EDGE 2, 5, 4, 5, 30 \ Edge 6 EDGE 2, 6, 3, 5, 30 \ Edge 7 EDGE 7, 8, 0, 6, 31 \ Edge 8 EDGE 5, 6, 5, 6, 30 \ Edge 9 EDGE 4, 8, 1, 6, 31 \ Edge 10 EDGE 4, 6, 3, 6, 30 \ Edge 11 EDGE 3, 7, 2, 6, 31 \ Edge 12 EDGE 3, 5, 6, 4, 30 \ Edge 13 EDGE 9, 12, 6, 6, 19 \ Edge 14 EDGE 9, 13, 6, 6, 18 \ Edge 15 EDGE 10, 11, 6, 6, 19 \ Edge 16 EDGE 10, 14, 6, 6, 18 \ Edge 17 EDGE 11, 14, 6, 6, 16 \ Edge 18 EDGE 12, 13, 6, 6, 16 \ Edge 19 .SHIP_VIPER_FACES \ normal_x, normal_y, normal_z, visibility FACE 0, 32, 0, 31 \ Face 0 FACE -22, 33, 11, 31 \ Face 1 FACE 22, 33, 11, 31 \ Face 2 FACE -22, -33, 11, 31 \ Face 3 FACE 22, -33, 11, 31 \ Face 4 FACE 0, -32, 0, 31 \ Face 5 FACE 0, 0, -48, 31 \ Face 6 Edited 2025-09-30 18:46 by matherp |
||||||
Wauw, About a year ago I tried to manually convert (using the 6502 data) a Cobra to PicoMite, controlling it with a nunchuck (3 axis sensors). I never got it right, there was always some surface transparent, or a rib sticking out. So I never published it. Now we have a way to convert all elite spacecraft to MMbasic format. Great... Thanks, Volhout P.S. I added use of framebuffer F to avoid glitches. Edited 2025-09-30 19:19 by Volhout |
||||||
Many thanks for this! Very nice entry point to look in to. And fantastic MMBasic as the processing speed is overwhelming. The example above doesn't look that attractive, this shows the beauty better: Option BASE 0 MODE 2 FRAMEBUFFER create FRAMEBUFFER write f Dim n = 1 Dim nv = 15 Dim nf = 7 Dim camera = 1 ' Vertex data Dim FLOAT vertices(2, 14) For i = 0 To 14 Read vertices(0,i), vertices(1,i), vertices(2,i) Next i Data 0, 0, 72 Data 0, 16, 24 Data 0,-16, 24 Data 48, 0,-24 Data -48, 0,-24 Data 24,-16,-24 Data -24,-16,-24 Data 24, 16,-24 Data -24, 16,-24 Data -32, 0,-24 Data 32, 0,-24 Data 8, 8,-24 Data -8, 8,-24 Data -8,-8,-24 Data 8,-8,-24 Math SCALE vertices(), 2.0, vertices() ' Face counts Dim INTEGER facecount( 6) For i = 0 To 6 Read facecount(i) Next i Data 3,4,4,4,4,3,6 ' Face vertex indices ( 28total) Dim INTEGER faces( 27) For i = 0 To 27 Read faces(i) Next i Data 1,7,8 Data 0,1,8,4 Data 0,3,7,1 Data 0,2,6,4 Data 0,3,5,2 Data 2,5,6 Data 7,8,4,6,5,3 ' Colors Dim INTEGER colours(5) colours(0) = RGB(red) colours(1) = RGB(blue) colours(2) = RGB(green) colours(3) = RGB(pink) colours(4) = RGB(brown) colours(5) = RGB(white) Dim INTEGER edge( 6) For i = 0 To 6 edge(i) = 3 Next i Dim INTEGER fill( 6) For i = 0 To 6 fill(i) = i Mod 5 Next i Draw3D CREATE n, nv, nf, camera, vertices(), facecount(), faces(), colours(), edge(), fill() ' Setup camera Dim INTEGER viewplane = 600 Draw3D CAMERA camera, viewplane, 0, 0 ' Animation variables Dim FLOAT yaw = 0, pitch = 0, roll = 0 Dim FLOAT q1(4) CLS Colour RGB(white),RGB(white) ' Main display loop Do Math Q_EULER yaw, pitch, roll, q1() Inc yaw, Rad(1) Inc pitch, Rad(2) Inc roll, Rad(0.5) Draw3D ROTATE q1(), 1 Draw3D SHOW 1, 0, 0, 1000, 1 Pause 20 FRAMEBUFFER copy f,n Loop .SHIP_VIPER EQUB 0 \ Max. canisters on demise = 0 EQUW 75 * 75 \ Targetable area = 75 * 75 EQUB LO(SHIP_VIPER_EDGES - SHIP_VIPER) \ Edges data offset(low) EQUB LO(SHIP_VIPER_FACES - SHIP_VIPER) \ Faces data offset(low) EQUB 77 \ Max. edge count = (77 - 1) / 4 = 19 EQUB 0 \ Gun vertex = 0 EQUB 42 \ Explosion count = 9, As (4 * n) + 6 = 42 EQUB 90 \ Number of vertices = 90 / 6 = 15 EQUB 20 \ Number of edges = 20 EQUW 0 \ Bounty = 0 EQUB 28 \ Number of faces = 28 / 4 = 7 EQUB 23 \ Visibility distance = 23 EQUB 120 \ Max. energy = 120 EQUB 32 \ Max. speed = 32 EQUB HI(SHIP_VIPER_EDGES - SHIP_VIPER) \ Edges data offset(high) EQUB HI(SHIP_VIPER_FACES - SHIP_VIPER) \ Faces data offset(high) EQUB 1 \ Normals are scaled by = 2^1 = 2 EQUB %00010001 \ Laser power = 2 \ Missiles = 1 .SHIP_VIPER_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 0, 0, 72, 1, 2, 3, 4, 31 \ Vertex 0 VERTEX 0, 16, 24, 0, 1, 2, 2, 30 \ Vertex 1 VERTEX 0, -16, 24, 3, 4, 5, 5, 30 \ Vertex 2 VERTEX 48, 0, -24, 2, 4, 6, 6, 31 \ Vertex 3 VERTEX -48, 0, -24, 1, 3, 6, 6, 31 \ Vertex 4 VERTEX 24, -16, -24, 4, 5, 6, 6, 30 \ Vertex 5 VERTEX -24, -16, -24, 5, 3, 6, 6, 30 \ Vertex 6 VERTEX 24, 16, -24, 0, 2, 6, 6, 31 \ Vertex 7 VERTEX -24, 16, -24, 0, 1, 6, 6, 31 \ Vertex 8 VERTEX -32, 0, -24, 6, 6, 6, 6, 19 \ Vertex 9 VERTEX 32, 0, -24, 6, 6, 6, 6, 19 \ Vertex 10 VERTEX 8, 8, -24, 6, 6, 6, 6, 19 \ Vertex 11 VERTEX -8, 8, -24, 6, 6, 6, 6, 19 \ Vertex 12 VERTEX -8, -8, -24, 6, 6, 6, 6, 18 \ Vertex 13 VERTEX 8, -8, -24, 6, 6, 6, 6, 18 \ Vertex 14 .SHIP_VIPER_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 3, 2, 4, 31 \ Edge 0 EDGE 0, 1, 1, 2, 30 \ Edge 1 EDGE 0, 2, 3, 4, 30 \ Edge 2 EDGE 0, 4, 1, 3, 31 \ Edge 3 EDGE 1, 7, 0, 2, 30 \ Edge 4 EDGE 1, 8, 0, 1, 30 \ Edge 5 EDGE 2, 5, 4, 5, 30 \ Edge 6 EDGE 2, 6, 3, 5, 30 \ Edge 7 EDGE 7, 8, 0, 6, 31 \ Edge 8 EDGE 5, 6, 5, 6, 30 \ Edge 9 EDGE 4, 8, 1, 6, 31 \ Edge 10 EDGE 4, 6, 3, 6, 30 \ Edge 11 EDGE 3, 7, 2, 6, 31 \ Edge 12 EDGE 3, 5, 6, 4, 30 \ Edge 13 EDGE 9, 12, 6, 6, 19 \ Edge 14 EDGE 9, 13, 6, 6, 18 \ Edge 15 EDGE 10, 11, 6, 6, 19 \ Edge 16 EDGE 10, 14, 6, 6, 18 \ Edge 17 EDGE 11, 14, 6, 6, 16 \ Edge 18 EDGE 12, 13, 6, 6, 16 \ Edge 19 .SHIP_VIPER_FACES \ normal_x, normal_y, normal_z, visibility FACE 0, 32, 0, 31 \ Face 0 FACE -22, 33, 11, 31 \ Face 1 FACE 22, 33, 11, 31 \ Face 2 FACE -22, -33, 11, 31 \ Face 3 FACE 22, -33, 11, 31 \ Face 4 FACE 0, -32, 0, 31 \ Face 5 FACE 0, 0, -48, 31 \ Face 6 |
||||||
I tried to set the background colour of the 3d drawing from black to white without looking into the manual and failed. Is there a way? p.s in MODE 3 with PSRAM it looks breathtaking nice!! Edited 2025-09-30 20:44 by dddns |
||||||
Sorry, don't want to spoil your thread, I made a mistake. This is all you need: Option BASE 0 MODE 2 FRAMEBUFFER create FRAMEBUFFER write f Dim n = 1 Dim nv = 15 Dim nf = 7 Dim camera = 1 ' Vertex data Dim FLOAT vertices(2, 14) For i = 0 To 14 Read vertices(0,i), vertices(1,i), vertices(2,i) Next i Data 0, 0, 72 Data 0, 16, 24 Data 0,-16, 24 Data 48, 0,-24 Data -48, 0,-24 Data 24,-16,-24 Data -24,-16,-24 Data 24, 16,-24 Data -24, 16,-24 Data -32, 0,-24 Data 32, 0,-24 Data 8, 8,-24 Data -8, 8,-24 Data -8,-8,-24 Data 8,-8,-24 Math SCALE vertices(), 2.0, vertices() ' Face counts Dim INTEGER facecount( 6) For i = 0 To 6 Read facecount(i) Next i Data 3,4,4,4,4,3,6 ' Face vertex indices ( 28total) Dim INTEGER faces( 27) For i = 0 To 27 Read faces(i) Next i Data 1,7,8 Data 0,1,8,4 Data 0,3,7,1 Data 0,2,6,4 Data 0,3,5,2 Data 2,5,6 Data 7,8,4,6,5,3 ' Colors Dim INTEGER colours(4) colours(0) = RGB(red) colours(1) = RGB(blue) colours(2) = RGB(green) colours(3) = RGB(pink) colours(4) = RGB(brown) Dim INTEGER edge( 6) For i = 0 To 6 edge(i) = 3 Next i Dim INTEGER fill( 6) For i = 0 To 6 fill(i) = i Mod 5 Next i Draw3D CREATE n, nv, nf, camera, vertices(), facecount(), faces(), colours(), edge(), fill() ' Setup camera Dim INTEGER viewplane = 600 Draw3D CAMERA camera, viewplane, 0, 0 ' Animation variables Dim FLOAT yaw = 0, pitch = 0, roll = 0 Dim FLOAT q1(4) CLS Colour RGB(white),RGB(white) ' Main display loop Do Math Q_EULER yaw, pitch, roll, q1() Inc yaw, Rad(1) Inc pitch, Rad(2) Inc roll, Rad(0.5) Draw3D ROTATE q1(), 1 Draw3D SHOW 1, 0, 0, 1000, 1 Pause 20 FRAMEBUFFER copy f,n Loop |
||||||
I'm still working with Claude on this. There is a bug/feature in the ELITE definitions that causes some models not to convert properly. This is work-in-progress to fix but I've run out of credit on Claude for the moment. The issue is that some of the models have coincident vertices so there are an unbalanced number of vertices and edges which is impossible. Cobra Mk3 is an example of this so the 3d rendering isn't correct. |
||||||
Thank you for the development, having a "nice looking future"! |
||||||
Still not getting there |
||||||
That has been a genuinely interesting day. There is precisely NO WAY I could have solved this by myself - pretty humbling. To make it work a modification to the MMBasic firmware has been needed to add an new feature. Rendering of the 3D object works by Painters algorithm. This works by sorting the faces and drawing those further away first. In addition the MMBasic firmware supports "back face culling". This doesn't draw faces that are pointing away from the camera. In order to sort the faces the current MMbasic code uses the Z axis position of the face centroid. This works in many situations but in some 3D models it is better to use the furthest vertex and sort on that. I've added that as an option to DRAW3D SHOW and DRAW3D WRITE DRAW3D SHOW n, x, y, z [,nocull][,usefurthest] DRAW3D WRITE n, x, y, z [,nocull][,usefurthest] set 1 to use the furthest vertex and zero (default) to use the centroid. The model conversion code is now as below. I've also attached the demo of the Cobra ship. You will need an update to the firmware to run this - attached for the RP2350 PicoMite. I'll add this to all the versions in the next beta. Have a play with the conversion program and try other models as in the elite source - let me know how you get on. Demo video here PicoMite.zip This code was written by the convert program below ' Elite Ship - Converter v2.9.7 (Origin-based normals) Option BASE 0 Dim n=1,nv= 28,nf= 17,camera=1 Dim FLOAT vertices(2, 27) For i=0 To 27 Read vertices(0,i),vertices(1,i),vertices(2,i) Next i Data 32, 0, 76 Data -32, 0, 76 Data 0, 26, 24 Data -120,-3,-8 Data 120,-3,-8 Data -88, 16,-40 Data 88, 16,-40 Data 128,-8,-40 Data -128,-8,-40 Data 0, 26,-40 Data -32,-24,-40 Data 32,-24,-40 Data -36, 8,-40 Data -8, 12,-40 Data 8, 12,-40 Data 36, 8,-40 Data 36,-12,-40 Data 8,-16,-40 Data -8,-16,-40 Data -36,-12,-40 Data 0, 0, 76 Data 0, 0, 90 Data -80,-6,-40 Data -80, 6,-40 Data -88, 0,-40 Data 80, 6,-40 Data 88, 0,-40 Data 80,-6,-40 Math SCALE vertices(),2.0,vertices() Dim INTEGER facecount( 16) For i=0 To 16 Read facecount(i) Next i Data 3,3,3,3,3,3,3,3,3,7 Data 4,4,3,3,4,4,4 Dim INTEGER faces( 59) For i=0 To 59 Read faces(i) Next i Data 2,1,0 Data 2,5,1 Data 0,6,2 Data 5,3,1 Data 0,4,6 Data 2,9,5 Data 6,9,2 Data 5,8,3 Data 4,7,6 Data 6,7,11,10,8,5,9 Data 12,13,18,19 Data 14,15,16,17 Data 22,24,23 Data 25,26,27 Data 1,3,8,10 Data 0,1,10,11 Data 11,7,4,0 Dim INTEGER colours(4),edge( 16),fill( 16) colours(0)=RGB(180,180,200):colours(1)=RGB(100,100,120) colours(2)=RGB(200,50,50):colours(3)=RGB(60,60,80):colours(4)=RGB(150,150,170) For i=0 To 16 edge(i)=3:fill(i)=i Mod 5 Next i Draw3D CREATE n,nv,nf,camera,vertices(),facecount(),faces(),colours(),edge(),fill() Dim INTEGER viewplane=600 Draw3D CAMERA camera,viewplane,0,0 Dim FLOAT yaw=0,pitch=0,roll=0,q1(4) CLS Do Math Q_EULER yaw,pitch,roll,q1() Inc yaw,Rad(1):Inc pitch,Rad(2):Inc roll,Rad(0.5) Draw3D ROTATE q1(),1 Draw3D SHOW 1,0,0,1000,0,1 Pause 100 Loop This is the COBRA model from https://elite.bbcelite.com/deep_dives/ship_blueprints.html .SHIP_COBRA_MK_3 EQUB 3 \ Max. canisters on demise = 3 EQUW 95 * 95 \ Targetable area = 95 * 95 EQUB LO(SHIP_COBRA_MK_3_EDGES - SHIP_COBRA_MK_3) \ Edges data offset (low) EQUB LO(SHIP_COBRA_MK_3_FACES - SHIP_COBRA_MK_3) \ Faces data offset (low) EQUB 153 \ Max. edge count = (153 - 1) / 4 = 38 EQUB 84 \ Gun vertex = 84 / 4 = 21 EQUB 42 \ Explosion count = 9, as (4 * n) + 6 = 42 EQUB 168 \ Number of vertices = 168 / 6 = 28 EQUB 38 \ Number of edges = 38 EQUW 0 \ Bounty = 0 EQUB 52 \ Number of faces = 52 / 4 = 13 EQUB 50 \ Visibility distance = 50 EQUB 150 \ Max. energy = 150 EQUB 28 \ Max. speed = 28 EQUB HI(SHIP_COBRA_MK_3_EDGES - SHIP_COBRA_MK_3) \ Edges data offset (low) EQUB HI(SHIP_COBRA_MK_3_FACES - SHIP_COBRA_MK_3) \ Faces data offset (low) EQUB 1 \ Normals are scaled by = 2^1 = 2 EQUB %00010011 \ Laser power = 2 \ Missiles = 3 .SHIP_COBRA_MK_3_VERTICES \ x, y, z, face1, face2, face3, face4, visibility VERTEX 32, 0, 76, 15, 15, 15, 15, 31 \ Vertex 0 VERTEX -32, 0, 76, 15, 15, 15, 15, 31 \ Vertex 1 VERTEX 0, 26, 24, 15, 15, 15, 15, 31 \ Vertex 2 VERTEX -120, -3, -8, 3, 7, 10, 10, 31 \ Vertex 3 VERTEX 120, -3, -8, 4, 8, 12, 12, 31 \ Vertex 4 VERTEX -88, 16, -40, 15, 15, 15, 15, 31 \ Vertex 5 VERTEX 88, 16, -40, 15, 15, 15, 15, 31 \ Vertex 6 VERTEX 128, -8, -40, 8, 9, 12, 12, 31 \ Vertex 7 VERTEX -128, -8, -40, 7, 9, 10, 10, 31 \ Vertex 8 VERTEX 0, 26, -40, 5, 6, 9, 9, 31 \ Vertex 9 VERTEX -32, -24, -40, 9, 10, 11, 11, 31 \ Vertex 10 VERTEX 32, -24, -40, 9, 11, 12, 12, 31 \ Vertex 11 VERTEX -36, 8, -40, 9, 9, 9, 9, 20 \ Vertex 12 VERTEX -8, 12, -40, 9, 9, 9, 9, 20 \ Vertex 13 VERTEX 8, 12, -40, 9, 9, 9, 9, 20 \ Vertex 14 VERTEX 36, 8, -40, 9, 9, 9, 9, 20 \ Vertex 15 VERTEX 36, -12, -40, 9, 9, 9, 9, 20 \ Vertex 16 VERTEX 8, -16, -40, 9, 9, 9, 9, 20 \ Vertex 17 VERTEX -8, -16, -40, 9, 9, 9, 9, 20 \ Vertex 18 VERTEX -36, -12, -40, 9, 9, 9, 9, 20 \ Vertex 19 VERTEX 0, 0, 76, 0, 11, 11, 11, 6 \ Vertex 20 VERTEX 0, 0, 90, 0, 11, 11, 11, 31 \ Vertex 21 VERTEX -80, -6, -40, 9, 9, 9, 9, 8 \ Vertex 22 VERTEX -80, 6, -40, 9, 9, 9, 9, 8 \ Vertex 23 VERTEX -88, 0, -40, 9, 9, 9, 9, 6 \ Vertex 24 VERTEX 80, 6, -40, 9, 9, 9, 9, 8 \ Vertex 25 VERTEX 88, 0, -40, 9, 9, 9, 9, 6 \ Vertex 26 VERTEX 80, -6, -40, 9, 9, 9, 9, 8 \ Vertex 27 .SHIP_COBRA_MK_3_EDGES \ vertex1, vertex2, face1, face2, visibility EDGE 0, 1, 0, 11, 31 \ Edge 0 EDGE 0, 4, 4, 12, 31 \ Edge 1 EDGE 1, 3, 3, 10, 31 \ Edge 2 EDGE 3, 8, 7, 10, 31 \ Edge 3 EDGE 4, 7, 8, 12, 31 \ Edge 4 EDGE 6, 7, 8, 9, 31 \ Edge 5 EDGE 6, 9, 6, 9, 31 \ Edge 6 EDGE 5, 9, 5, 9, 31 \ Edge 7 EDGE 5, 8, 7, 9, 31 \ Edge 8 EDGE 2, 5, 1, 5, 31 \ Edge 9 EDGE 2, 6, 2, 6, 31 \ Edge 10 EDGE 3, 5, 3, 7, 31 \ Edge 11 EDGE 4, 6, 4, 8, 31 \ Edge 12 EDGE 1, 2, 0, 1, 31 \ Edge 13 EDGE 0, 2, 0, 2, 31 \ Edge 14 EDGE 8, 10, 9, 10, 31 \ Edge 15 EDGE 10, 11, 9, 11, 31 \ Edge 16 EDGE 7, 11, 9, 12, 31 \ Edge 17 EDGE 1, 10, 10, 11, 31 \ Edge 18 EDGE 0, 11, 11, 12, 31 \ Edge 19 EDGE 1, 5, 1, 3, 29 \ Edge 20 EDGE 0, 6, 2, 4, 29 \ Edge 21 EDGE 20, 21, 0, 11, 6 \ Edge 22 EDGE 12, 13, 9, 9, 20 \ Edge 23 EDGE 18, 19, 9, 9, 20 \ Edge 24 EDGE 14, 15, 9, 9, 20 \ Edge 25 EDGE 16, 17, 9, 9, 20 \ Edge 26 EDGE 15, 16, 9, 9, 19 \ Edge 27 EDGE 14, 17, 9, 9, 17 \ Edge 28 EDGE 13, 18, 9, 9, 19 \ Edge 29 EDGE 12, 19, 9, 9, 19 \ Edge 30 EDGE 2, 9, 5, 6, 30 \ Edge 31 EDGE 22, 24, 9, 9, 6 \ Edge 32 EDGE 23, 24, 9, 9, 6 \ Edge 33 EDGE 22, 23, 9, 9, 8 \ Edge 34 EDGE 25, 26, 9, 9, 6 \ Edge 35 EDGE 26, 27, 9, 9, 6 \ Edge 36 EDGE 25, 27, 9, 9, 8 \ Edge 37 .SHIP_COBRA_MK_3_FACES \ normal_x, normal_y, normal_z, visibility FACE 0, 62, 31, 31 \ Face 0 FACE -18, 55, 16, 31 \ Face 1 FACE 18, 55, 16, 31 \ Face 2 FACE -16, 52, 14, 31 \ Face 3 FACE 16, 52, 14, 31 \ Face 4 FACE -14, 47, 0, 31 \ Face 5 FACE 14, 47, 0, 31 \ Face 6 FACE -61, 102, 0, 31 \ Face 7 FACE 61, 102, 0, 31 \ Face 8 FACE 0, 0, -80, 31 \ Face 9 FACE -7, -42, 9, 31 \ Face 10 FACE 0, -30, 6, 31 \ Face 11 FACE 7, -42, 9, 31 \ Face 12 And this is the conversion program written by CLAUDE. There are all sort of sophisticated elements in this to handle coplanar faces, to correct the face normal vector to be pointing away from the origin and just to read the source above. It really is very impressive ' Elite Ship Blueprint to MMBasic DRAW3D Converter ' Version 2.9.7 - FIXED: Normals face outward from origin Option EXPLICIT Option BASE 0 ' === ALL VARIABLE DECLARATIONS === Dim filename$ LENGTH 50, outfile$ LENGTH 50 Dim txt$ LENGTH 200, rest$ LENGTH 200, s$ LENGTH 200 Dim INTEGER nv, ne, nf, i, j, k, p1, p2, f1, f2, dotpos Dim INTEGER totalidx, curr, nextv, found, startv, temp, mergeCount Dim INTEGER nTotalSubfaces, totalSubfaceVerts, maxIter Dim FLOAT vx(100), vy(100), vz(100) Dim INTEGER vf1(100), vf2(100), vf3(100), vf4(100) Dim FLOAT fnx(100), fny(100), fnz(100) Dim INTEGER e1(100), e2(100), ef1(100), ef2(100) Dim INTEGER facevert(100, 20), facecount(100) Dim INTEGER edgeused(100), faceedges(50), nfaceedges Dim INTEGER allSubfaceVerts(500), allSubfaceCount(200) Dim INTEGER nOutline, nInternal, useGeometric, hasInternal Dim FLOAT faceZ, zTolerance Dim INTEGER hasZ, zCount, filteredCount, includeEdge Dim INTEGER loopVerts(20), nLoopVerts, loopsFound Dim INTEGER reversedCount, vIdx Dim INTEGER v0wind, v1wind, v2wind Dim FLOAT v0x,v0y,v0z,v1x,v1y,v1z,v2x,v2y,v2z Dim FLOAT e1x,e1y,e1z,e2x,e2y,e2z,nx,ny,nz,dot Dim FLOAT fcx, fcy, fcz Dim INTEGER v0chk, face9Start, face9Count Input "Enter ship blueprint filename: ", filename$ If filename$ = "" Then End dotpos = Instr(filename$, ".") If dotpos > 0 Then outfile$ = Left$(filename$, dotpos-1) + ".bas" Else outfile$ = filename$ + ".bas" EndIf Open filename$ For INPUT As #1 Do While Not Eof(#1) Line Input #1, txt$ If Instr(txt$, "_VERTICES") > 0 Then Exit Loop nv = 0 Do While Not Eof(#1) Line Input #1, txt$ txt$ = Trim$(txt$, " " + Chr$(9)) If Instr(txt$, "_EDGES") > 0 Then Exit If Left$(txt$, 6) = "VERTEX" Then p1 = Instr(txt$, " ") rest$ = Trim$(Mid$(txt$, p1), " " + Chr$(9)) p2 = Instr(rest$, ",") vx(nv) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") vy(nv) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") vz(nv) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") vf1(nv) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") vf2(nv) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") vf3(nv) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") vf4(nv) = Val(Left$(rest$, p2-1)) nv = nv + 1 EndIf Loop ne = 0 Do While Not Eof(#1) Line Input #1, txt$ txt$ = Trim$(txt$, " " + Chr$(9)) If Instr(txt$, "_FACES") > 0 Then Exit If Left$(txt$, 4) = "EDGE" Then p1 = Instr(txt$, " ") rest$ = Trim$(Mid$(txt$, p1), " " + Chr$(9)) p2 = Instr(rest$, ",") e1(ne) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") e2(ne) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") ef1(ne) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") ef2(ne) = Val(Left$(rest$, p2-1)) ne = ne + 1 EndIf Loop nf = 0 Do While Not Eof(#1) Line Input #1, txt$ txt$ = Trim$(txt$, " " + Chr$(9)) If Left$(txt$, 4) = "FACE" Then p1 = Instr(txt$, " ") rest$ = Trim$(Mid$(txt$, p1), " " + Chr$(9)) p2 = Instr(rest$, ",") fnx(nf) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") fny(nf) = Val(Left$(rest$, p2-1)) rest$ = Trim$(Mid$(rest$, p2+1), " " + Chr$(9)) p2 = Instr(rest$, ",") fnz(nf) = Val(Left$(rest$, p2-1)) nf = nf + 1 EndIf Loop Close #1 Print "Elite Ship Converter v2.9.7" Print "Found"; nv; "vertices,"; ne; "edges,"; nf; "faces" For i = 0 To nf-1 facecount(i) = 0 Next i nTotalSubfaces = 0 totalSubfaceVerts = 0 Print "Building faces (hybrid: on-plane outline + internal edges)..." For f1 = 0 To nf-1 For i = 0 To ne-1 edgeused(i) = 0 Next i useGeometric = 0 hasZ = 0 zTolerance = 2.0 hasInternal = 0 For i = 0 To ne-1 If ef1(i) = f1 And ef2(i) = f1 Then hasInternal = 1 Exit For EndIf Next i If hasInternal = 1 Then zCount = 0 faceZ = 0 For i = 0 To ne-1 If (ef1(i) = f1 Or ef2(i) = f1) Then If hasZ = 0 Then faceZ = vz(e1(i)) hasZ = 1 EndIf If Abs(vz(e1(i)) - faceZ) < zTolerance Then zCount = zCount + 1 If Abs(vz(e2(i)) - faceZ) < zTolerance Then zCount = zCount + 1 EndIf Next i If zCount > 10 Then useGeometric = 1 EndIf nfaceedges = 0 nOutline = 0 nInternal = 0 For i = 0 To ne-1 includeEdge = 0 If (ef1(i) = f1 Or ef2(i) = f1) Then If hasInternal = 1 Then If ef1(i) = f1 And ef2(i) = f1 Then includeEdge = 1 nInternal = nInternal + 1 ElseIf Abs(vz(e1(i)) - faceZ) < zTolerance And Abs(vz(e2(i)) - faceZ) < zTolerance Then includeEdge = 1 nOutline = nOutline + 1 Else nOutline = nOutline + 1 EndIf Else includeEdge = 1 If ef1(i) <> ef2(i) Then nOutline = nOutline + 1 Else nInternal = nInternal + 1 EndIf EndIf EndIf If includeEdge = 1 Then faceedges(nfaceedges) = i nfaceedges = nfaceedges + 1 EndIf Next i Print " Face"; f1; ":"; nOutline; "outline,"; nInternal; "internal edges"; If hasInternal = 1 Then Print " (hybrid)"; EndIf If nfaceedges = 0 Then Print " -> EMPTY" Continue For EndIf loopsFound = 0 Do While loopsFound < 10 startv = -1 For i = 0 To nfaceedges-1 If edgeused(faceedges(i)) = 0 Then startv = e1(faceedges(i)) curr = e2(faceedges(i)) edgeused(faceedges(i)) = 1 Exit For EndIf Next i If startv = -1 Then Exit Do loopVerts(0) = startv loopVerts(1) = curr nLoopVerts = 2 maxIter = 0 Do While curr <> startv And nLoopVerts < 20 maxIter = maxIter + 1 If maxIter > nfaceedges + 5 Then Exit Do found = 0 For j = 0 To nfaceedges-1 i = faceedges(j) If edgeused(i) = 0 Then If e1(i) = curr Then nextv = e2(i) found = 1 ElseIf e2(i) = curr Then nextv = e1(i) found = 1 EndIf If found = 1 Then If nextv <> startv Then loopVerts(nLoopVerts) = nextv nLoopVerts = nLoopVerts + 1 EndIf edgeused(i) = 1 curr = nextv Exit For EndIf EndIf Next j If found = 0 Then Exit Do Loop If curr = startv And nLoopVerts >= 3 Then allSubfaceCount(nTotalSubfaces) = nLoopVerts For i = 0 To nLoopVerts-1 allSubfaceVerts(totalSubfaceVerts) = loopVerts(i) totalSubfaceVerts = totalSubfaceVerts + 1 Next i nTotalSubfaces = nTotalSubfaces + 1 loopsFound = loopsFound + 1 EndIf Loop If loopsFound > 1 Then Print " ->"; loopsFound; "subfaces" ElseIf loopsFound = 1 Then Print " -> OK" Else Print " -> FAILED" EndIf Next f1 Print "Total subfaces built:"; nTotalSubfaces Print "Total vertices:"; totalSubfaceVerts Print "Checking winding direction (outward from origin)..." reversedCount = 0 vIdx = 0 For i = 0 To nTotalSubfaces-1 If allSubfaceCount(i) >= 3 Then v0wind = allSubfaceVerts(vIdx) v1wind = allSubfaceVerts(vIdx+1) v2wind = allSubfaceVerts(vIdx+2) ' Get first 3 vertices v0x=vx(v0wind):v0y=vy(v0wind):v0z=vz(v0wind) v1x=vx(v1wind):v1y=vy(v1wind):v1z=vz(v1wind) v2x=vx(v2wind):v2y=vy(v2wind):v2z=vz(v2wind) ' Calculate face center (average of all verts in this subface) fcx = 0: fcy = 0: fcz = 0 For j = 0 To allSubfaceCount(i)-1 fcx = fcx + vx(allSubfaceVerts(vIdx+j)) fcy = fcy + vy(allSubfaceVerts(vIdx+j)) fcz = fcz + vz(allSubfaceVerts(vIdx+j)) Next j fcx = fcx / allSubfaceCount(i) fcy = fcy / allSubfaceCount(i) fcz = fcz / allSubfaceCount(i) ' Compute winding normal e1x=v1x-v0x:e1y=v1y-v0y:e1z=v1z-v0z e2x=v2x-v0x:e2y=v2y-v0y:e2z=v2z-v0z nx=e1y*e2z-e1z*e2y:ny=e1z*e2x-e1x*e2z:nz=e1x*e2y-e1y*e2x ' Check if normal points away from origin (dot with face center) dot=nx*fcx+ny*fcy+nz*fcz If dot < 0 Then ' Normal points inward, reverse winding reversedCount = reversedCount + 1 For j=0 To allSubfaceCount(i)\2-1 k=allSubfaceCount(i)-1-j temp=allSubfaceVerts(vIdx+j) allSubfaceVerts(vIdx+j)=allSubfaceVerts(vIdx+k) allSubfaceVerts(vIdx+k)=temp Next j EndIf vIdx = vIdx + allSubfaceCount(i) Else vIdx = vIdx + allSubfaceCount(i) EndIf Next i Print "Reversed"; reversedCount; "subfaces to face outward" Print "Writing to: "; outfile$ Open outfile$ For OUTPUT As #2 Print #2, "' Elite Ship - Converter v2.9.7 (Origin-based normals)" Print #2, "OPTION BASE 0" Print #2, "DIM n=1,nv=";nv;",nf=";nTotalSubfaces;",camera=1" Print #2, "DIM FLOAT vertices(2,";nv-1;")" Print #2, "FOR i=0 TO";nv-1 Print #2, " READ vertices(0,i),vertices(1,i),vertices(2,i)" Print #2, "NEXT i" Print #2, "" For i = 0 To nv-1 Print #2, "DATA";vx(i);",";vy(i);",";vz(i) Next i Print #2, "" Print #2, "MATH SCALE vertices(),2.0,vertices()" Print #2, "DIM INTEGER facecount(";nTotalSubfaces-1;")" Print #2, "FOR i=0 TO";nTotalSubfaces-1 Print #2, " READ facecount(i)" Print #2, "NEXT i" Print #2, "" For i = 0 To nTotalSubfaces-1 Step 10 s$ = "DATA " For j = i To Min(i+9, nTotalSubfaces-1) s$ = s$ + Str$(allSubfaceCount(j)) If j < Min(i+9, nTotalSubfaces-1) Then s$ = s$ + "," Next j Print #2, s$ Next i Print #2, "" Print #2, "DIM INTEGER faces(";totalSubfaceVerts-1;")" Print #2, "FOR i=0 TO";totalSubfaceVerts-1 Print #2, " READ faces(i)" Print #2, "NEXT i" Print #2, "" vIdx = 0 For i = 0 To nTotalSubfaces-1 If allSubfaceCount(i) > 0 Then s$ = "DATA " For j = 0 To allSubfaceCount(i)-1 s$ = s$ + Str$(allSubfaceVerts(vIdx)) vIdx = vIdx + 1 If j < allSubfaceCount(i)-1 Then s$ = s$ + "," Next j Print #2, s$ EndIf Next i Print #2, "" Print #2, "DIM INTEGER colours(4),edge(";nTotalSubfaces-1;"),fill(";nTotalSubfaces-1;")" Print #2, "colours(0)=RGB(180,180,200):colours(1)=RGB(100,100,120)" Print #2, "colours(2)=RGB(200,50,50):colours(3)=RGB(60,60,80):colours(4)=RGB(150,150,170)" Print #2, "FOR i=0 TO";nTotalSubfaces-1 Print #2, " edge(i)=3:fill(i)=i MOD 5" Print #2, "NEXT i" Print #2, "DRAW3D CREATE n,nv,nf,camera,vertices(),facecount(),faces(),colours(),edge(),fill()" Print #2, "DIM INTEGER viewplane=600" Print #2, "DRAW3D CAMERA camera,viewplane,0,0" Print #2, "DIM FLOAT yaw=0,pitch=0,roll=0,q1(4)" Print #2, "CLS" Print #2, "DO" Print #2, " MATH Q_EULER yaw,pitch,roll,q1()" Print #2, " INC yaw,RAD(1):INC pitch,RAD(2):INC roll,RAD(0.5)" Print #2, " DRAW3D ROTATE q1(),1" Print #2, " DRAW3D SHOW 1,0,0,1000,0,1" Print #2, " PAUSE 100" Print #2, "LOOP" Close #2 Print "Conversion complete!" End Function Trim$(s$,c$) As STRING Local result$ LENGTH 200 result$=s$ Do While Instr(c$,Left$(result$,1))>0 And Len(result$)>0 result$=Mid$(result$,2) Loop Do While Instr(c$,Right$(result$,1))>0 And Len(result$)>0 result$=Left$(result$,Len(result$)-1) Loop Trim$=result$ End Function |
||||||
matherp, will this change be added to the MMB4W? |
||||||
And CCM2, please? |
||||||
![]() |
The Back Shed's forum code is written, and hosted, in Australia. |