I started making one for one of my games ... this is about as far as I got. Not very versatile but was really just a test and as you can see all letters are low poly and made in-code. I've since settled for a simpler pixel perfect system but this may be of some use .....
Graphics3D 800,600,16,1 Global CAMERA = CreateCamera() : PositionEntity CAMERA, 0, 0, -100 CameraClsColor Camera,50,75,150 Global LIGHT = CreateLight() : RotateEntity LIGHT, 30,-45,0 Global LETTERS = MESHpivot() Dim Grid( 4, 6 ) Const C_Front = 1 Const C_Rear = 4 Const C_Left = 8 Const C_Right = 2 Const C_Top = 16 Const C_Bottom = 32 Global P1, P2, P3, P4 FONTcreate() TEST = FONTcreatepara("THE QUICK BROWN", "FOX JUMPS OVER", "THE LAZY DOG" ) YAW = 0 PITCH = 0 While Not KeyDown(1) YAW = YAW + KeyDown(205) - KeyDown(203 ) PITCH = PITCH + KeyDown( 200 ) - KeyDown(208 ) RotateEntity TEST, PITCH, YAW, 0 RenderWorld() Text 0,0,TrisRendered() Flip Wend ;=================================================== ;=================================================== ;=================================================== Function FONTcreatepara( t1$, t2$, t3$ , T4$="") Mesh = CreateMesh() Tmp = FONTcreateword( t1$, 1.0 ) AddMesh Tmp, Mesh : FreeEntity Tmp Tmp = FONTcreateword( t2$, .5 ) PositionMesh tmp, 0, -14 , 0 AddMesh Tmp, Mesh : FreeEntity Tmp Tmp = FONTcreateword( t3$, .75 ) PositionMesh tmp, 0, -28 , 0 AddMesh Tmp, Mesh : FreeEntity Tmp Tmp = FONTcreateword( t4$, .5 ) PositionMesh tmp, 0, -42 , 0 AddMesh Tmp, Mesh : FreeEntity Tmp MESHcenter( Mesh ) EntityFX Mesh, 2+4 Return Mesh End Function ;=================================================== ;=================================================== ;=================================================== Function FONTcreateword( t$ , Scale#=1.0 ) mesh = CreateMesh() For l = 1 To Len( t$ ) c$ = Mid$( t$ , l , 1 ) If c$<>" " copy = CopyMesh( FindChild( LETTERS , c$ ) ) ScaleMesh copy, Scale, Scale, Scale*5.0 RotateMesh copy, Rnd(-15,15 ), Rnd(-15,15) ,Rnd(-15,15) PositionMesh copy , l * 8.0 * Scale , 0, 0 AddMesh copy, mesh : FreeEntity copy EndIf Next MESHcenter( mesh ) EntityFX mesh, 2+4 Return mesh End Function ;=================================================== ;=================================================== ;=================================================== Function FONTcreate() ;V shape P1 = CreateMesh() s = CreateSurface( p1 ) v0 = AddVertex( s, -1,1,1 ) v1 = AddVertex( s, 1,1,1 ) v2 = AddVertex( s, -.9, 0, 1 ) v3 = AddVertex( s, 1,-1,1 ) v4 = AddVertex( s, -1,-1,1 ) v5 = AddVertex( s, -1,1,-1 ) v6 = AddVertex( s, 1,1,-1 ) v7 = AddVertex( s, -.9, 0, -1 ) v8 = AddVertex( s, 1,-1,-1 ) v9 = AddVertex( s, -1,-1,-1 ) AddTriangle s, v0, v4, v2 AddTriangle s, v0,v2,v1 AddTriangle s, v2,v4,v3 AddTriangle s, v5,v6,v7 AddTriangle s, v5,v7,v9 AddTriangle s, v9,v7,v8 AddTriangle s, v6,v1,v2 AddTriangle s, v2,v7,v6 AddTriangle s, v7,v2,v3 AddTriangle s, v3,v8,v7 AddTriangle s, v8,v3,v1 AddTriangle s, v1,v6,v8 p1 = MESHunweld( p1 ) MESHnormals( p1 ) HideEntity p1 ;Triangle shape P2 = CreateMesh() s = CreateSurface( P2 ) v0 = AddVertex( s , -1, 1, 1 ) v1 = AddVertex( s, 1, 1, 1 ) v2 = AddVertex( s, 1,-1,1 ) v3 = AddVertex( s, -1,-1,1 ) v4 = AddVertex( s , -1, 1, -1 ) v5 = AddVertex( s, 1, 1, -1 ) v6 = AddVertex( s, 1,-1,-1 ) v7 = AddVertex( s, -1, -1, -1 ) AddTriangle s, v1, v0, v3 AddTriangle s, v7, v4, v5 AddTriangle s, v1,v3,v7 AddTriangle s, v7,v5,v1 AddTriangle s, v0,v1,v5 AddTriangle s, v5,v4,v0 AddTriangle s, v3,v0,v4 AddTriangle s, v4,v7,v3 p2 = MESHunweld( p2 ) MESHnormals( p2 ) HideEntity p2 ;inside triangle P3 = CreateMesh() s = CreateSurface( P3 ) v0 = AddVertex( s , -1, 1, 1 ) v1 = AddVertex( s, 1, 1, 1 ) v2 = AddVertex( s, 1,-1,1 ) v3 = AddVertex( s, -1,-1,1 ) v4 = AddVertex( s , -1, 1, -1 ) v5 = AddVertex( s, 1, 1, -1 ) v6 = AddVertex( s, 1,-1,-1 ) v7 = AddVertex( s, -1, -1, -1 ) AddTriangle s, v2,v1,v5 AddTriangle s, v5,v6,v2 AddTriangle s, v3,v2,v6 AddTriangle s, v6,v7,v3 p3 = MESHunweld( p3 ) MESHnormals( p3 ) HideEntity p3 ;point P4 = CreateMesh() s = CreateSurface( P4 ) v0 = AddVertex( s, -1,1,1 ) v1 = AddVertex( s, 1,0 , 1 ) v2 = AddVertex( s, -1,-1,1 ) v3 = AddVertex( s, -1,1,-1 ) v4 = AddVertex( s, 1,0 , -1 ) v5 = AddVertex( s, -1,-1,-1 ) AddTriangle s, v0, v2, v1 AddTriangle s, v3, v4, v5 AddTriangle s, v0,v1,v4 AddTriangle s, v4, v3, v0 AddTriangle s, v1, v2, v5 AddTriangle s, v5, v4, v1 p4 = MESHunweld( p4 ) MESHnormals( p4 ) ; PositionEntity p4, 0, 0, -90 HideEntity p4 ;inside point P5 = CreateMesh() s = CreateSurface( P5 ) v0 = AddVertex( s, -1,1,1 ) v1 = AddVertex( s, 1,1 , 1 ) v2 = AddVertex( s, 1,-1,1 ) v3 = AddVertex( s, -1,-1,1 ) v4 = AddVertex( s, -1,1,-1 ) v5 = AddVertex( s, 1,1 , -1 ) v6 = AddVertex( s, 1,-1,-1 ) v7 = AddVertex( s, -1,-1,-1 ) AddTriangle s, v1,v0, v4 AddTriangle s, v4, v5, v1 AddTriangle s, v7, v3, v2 AddTriangle s, v2, v6, v7 p5 = MESHunweld( p5 ) MESHnormals( p5 ) HideEntity p5 Restore DATAletters Read No For l = 0 To No-1 For y= 1 To 5 For x =1 To 3 Read Grid( x, y ) Next Next Mesh = CreateMesh( LETTERS ) NameEntity Mesh , Chr$( 48 + l ) For y = 1 To 5 For x = 1 To 3 If Grid( x, y ) > 0 Flag = 0 Flag = Flag + C_Left * ( Grid( x-1, y ) > 0 ) Flag = Flag + C_Right * ( Grid( x+1, y ) > 0 ) Flag = Flag + C_Top * ( Grid( x, y-1 ) > 0 ) Flag = Flag + C_Bottom * ( Grid( x, y+1 ) > 0 ) Select Grid( x, y ) Case 1 Tmp = MESHcull( CreateCube() , Flag ) Case 2, 3, 4, 5 Tmp = CopyMesh( P1 ) Tmp = MESHcull( Tmp, C_Left ) RotateMesh Tmp, 0,0, ( Grid( x, y ) - 2 ) * 90 Case 6, 7, 8, 9 Tmp = CopyMesh( P2 ) RotateMesh Tmp, 0,0, ( Grid( x, y ) - 6 ) * 90 Tmp = MESHcull( Tmp , Flag ) Case 10,11,12,13 Tmp = CopyMesh( P1 ) RotateMesh Tmp, 0,0, ( Grid( x, y ) - 10 ) * 90 Case 14,15,16,17 Tmp = CopyMesh( P4 ) RotateMesh Tmp, 0,0, ( Grid( x, y ) - 14 ) * 90 Case 18,19,20,21 Tmp = CopyMesh( P2 ) RotateMesh Tmp, 0,0, ( Grid( x, y ) - 18 ) * 90 Tmp = MESHcull( Tmp, Flag ) Copy = MESHcull( CopyMesh( P3 ) , C_Top ) RotateMesh Copy, 0, 0, ( Grid( x, y ) - 18 ) * 90 AddMesh copy, tmp : FreeEntity copy Case 22,23,24,25 Tmp = CopyMesh( P2 ) RotateMesh Tmp, 0,0, ( Grid( x, y ) - 22 ) * 90 Tmp = MESHcull( Tmp, Flag ) Copy = MESHcull( CopyMesh( P3 ) , C_Left ) RotateMesh Copy, 0, 0, ( Grid( x, y ) - 22 ) * 90 AddMesh copy, tmp : FreeEntity copy Case 26,27,28,29 Tmp = CopyMesh( P4 ) RotateMesh Tmp, 0,0, ( Grid( x, y ) - 26 ) * 90 Copy = CopyMesh( P5 ) RotateMesh Copy, 0, 0, ( Grid( x, y ) - 26 ) * 90 AddMesh copy, tmp : FreeEntity copy End Select PositionMesh tmp, (x-2)*2 , -(y-3)*2 , 0 AddMesh tmp,Mesh FreeEntity tmp EndIf Next Next MESHnormals( Mesh ) s = GetSurface( Mesh , 1 ) For v= 0 To CountVertices(s) - 1 If VertexNZ( s, v ) < -.5 VertexColor s, v, 250,250,0 Else VertexColor s, v, 250,50,50 EndIf Next HideEntity Mesh Next FreeEntity P1 FreeEntity P2 FreeEntity P3 FreeEntity P4 End Function ;=================================================== ;=================================================== ;=================================================== Function MESHpivot() mesh = CreateMesh() s = CreateSurface( mesh ) NameEntity mesh, "ROOT" Return mesh End Function ;=================================================== ;=================================================== ;=================================================== Function MESHunweld( Mesh , clip0=False ) Copy = CreateMesh() ns = CreateSurface( Copy ) For su = 1 To CountSurfaces( Mesh ) s = GetSurface( Mesh , su ) For t = 0 To CountTriangles( s ) - 1 v0 = TriangleVertex( s, t, 0 ) v1 = TriangleVertex( s, t, 1 ) v2 = TriangleVertex( s, t, 2 ) If clip0 = False Or ( VertexY( s, v0 ) <>0 Or VertexY( s, v1) <> 0 Or VertexY( s, v2 ) <> 0 ) Nv0 = AddVertex( ns , VertexX( s , v0 ) , VertexY( s, v0 ) , VertexZ( s, v0 ) ) Nv1 = AddVertex( ns , VertexX( s , v1 ) , VertexY( s, v1 ) , VertexZ( s, v1 ) ) Nv2 = AddVertex( ns , VertexX( s , v2 ) , VertexY( s, v2 ) , VertexZ( s, v2 ) ) VertexColor ns, Nv0 , VertexRed( s, v0 ) , VertexGreen( s, v0 ) , VertexBlue( s, v0 ) VertexColor ns, Nv1 , VertexRed( s, v1 ) , VertexGreen( s, v1 ) , VertexBlue( s, v1 ) VertexColor ns, Nv2 , VertexRed( s, v2 ) , VertexGreen( s, v2 ) , VertexBlue( s, v2 ) AddTriangle ns , Nv0 , Nv1 , Nv2 EndIf Next Next FreeEntity mesh Return Copy End Function ;==================================================== ;==================================================== ;==================================================== Function MESHcenter( mesh ) sx# = MeshWidth( mesh ) sy# = MeshHeight( mesh ) sz# = MeshDepth( mesh ) FitMesh mesh , -sx*.5, -sy*.5 , -sz*.5 , sx, sy, sz Return mesh End Function ;=================================================== ;=================================================== ;=================================================== Function MESHnormals( mesh ) For l = 1 To CountSurfaces(mesh ) s = GetSurface( mesh , l ) ;calculate normals for flatshading For t = 0 To CountTriangles( s )-1 v0 = TriangleVertex( s, t, 0 ) v1 = TriangleVertex( s, t, 1 ) v2 = TriangleVertex( s, t, 2 ) ax# = VertexX( s, v1 ) - VertexX( s, v0 ) ay# = VertexY( s, v1 ) - VertexY( s, v0 ) az# = VertexZ( s, v1 ) - VertexZ( s, v0 ) bx# = VertexX( s, v2 ) - VertexX( s, v1 ) by# = VertexY( s, v2 ) - VertexY( s, v1 ) bz# = VertexZ( s, v2 ) - VertexZ( s, v1 ) Nx# = ( ay * bz ) - ( az * by ) Ny# = ( az * bx ) - ( ax * bz ) Nz# = ( ax * by ) - ( ay * bx ) Ns# = Sqr( Nx * Nx + Ny*Ny + Nz*Nz ) Nx = LIMIT( Nx / Ns, -1,1 ) Ny = LIMIT( Ny / Ns, -1, 1 ) Nz = LIMIT( Nz / Ns, -1, 1 ) For v = v0 To v2 VertexNormal s, v, Nx, Ny, Nz Next Next Next End Function ;=================================================== ;=================================================== ;=================================================== Function MESHcull( Mesh , Flags = 0 ) If Flags = 0 Return Mesh s = GetSurface( Mesh , 1 ) Copy = CreateMesh() Cs = CreateSurface( Copy ) For t = 0 To CountTriangles( s )-1 ;calculate triangle normal v0 = TriangleVertex( s, t, 0 ) v1 = TriangleVertex( s, t, 1 ) v2 = TriangleVertex( s, t, 2 ) ax# = VertexX( s, v1 ) - VertexX( s, v0 ) ay# = VertexY( s, v1 ) - VertexY( s, v0 ) az# = VertexZ( s, v1 ) - VertexZ( s, v0 ) bx# = VertexX( s, v2 ) - VertexX( s, v1 ) by# = VertexY( s, v2 ) - VertexY( s, v1 ) bz# = VertexZ( s, v2 ) - VertexZ( s, v1 ) Nx# = ( ay * bz ) - ( az * by ) Ny# = ( az * bx ) - ( ax * bz ) Nz# = ( ax * by ) - ( ay * bx ) Ns# = Sqr( Nx * Nx + Ny*Ny + Nz*Nz ) Nx = Nx / Ns Ny = Ny / Ns Nz = Nz / Ns OK = True For l = 0 To 5 Flag = 2^l If ( Flags And Flag) = Flag ;determine plane normal Select Flag Case C_Front px# = 0 : py# = 0 : pz# = 1 Case C_Rear px# = 0 : py# = 0 : pz# = -1 Case C_Left px# = -1 : py# = 0 : pz# = 0 Case C_Right px# = 1 : py# = 0 : pz# = 0 Case C_Top px# = 0 : py# = 1 : pz# = 0 Case C_Bottom px# = 0 : py# = -1 : pz# = 0 End Select If Nx = Px And Ny = Py And Nz = Pz OK = False EndIf Next If OK nv0 = AddVertex( Cs, VertexX( s , v0 ) , VertexY( s, v0 ) , VertexZ( s, v0 ) ) nv1 = AddVertex( Cs, VertexX( s , v1 ) , VertexY( s, v1 ) , VertexZ( s, v1 ) ) nv2 = AddVertex( Cs, VertexX( s , v2 ) , VertexY( s, v2 ) , VertexZ( s, v2 ) ) VertexNormal Cs , nv0 , Nx, Ny, Nz VertexNormal Cs , nv1 , Nx, Ny, Nz VertexNormal Cs , nv2 , Nx, Ny, Nz AddTriangle( Cs , nv0, nv1, nv2 ) EndIf Next FreeEntity mesh Return copy End Function ;=================================================== ;=================================================== ;=================================================== Function LIMIT#( q#, lo#, hi# ) If q < lo q = lo If q > hi q = hi Return q End Function .DATAletters Data 26+17 ;0 Data 1,1,1 Data 1,0,1 Data 1,0,1 Data 1,0,1 Data 1,1,1 ;1 Data 0,1,0 Data 0,1,0 Data 0,1,0 Data 0,1,0 Data 0,1,0 ;2 Data 1,1,1 Data 0,0,1 Data 1,1,1 Data 1,0,0 Data 1,1,1 ;3 Data 1,1,1 Data 0,0,1 Data 1,1,1 Data 0,0,1 Data 1,1,1 ;4 Data 1,0,0 Data 1,0,0 Data 1,1,1 Data 0,1,0 Data 0,1,0 ;5 Data 1,1,1 Data 1,0,0 Data 1,1,1 Data 0,0,1 Data 1,1,1 ;6 Data 1,1,1 Data 1,0,0 Data 1,1,1 Data 1,0,1 Data 1,1,1 ;7 Data 1,1,1 Data 0,0,1 Data 0,0,1 Data 0,0,1 Data 0,0,1 ;8 Data 1,1,1 Data 1,0,1 Data 1,1,1 Data 1,0,1 Data 1,1,1 ;9 Data 1,1,1 Data 1,0,1 Data 1,1,1 Data 0,0,1 Data 0,0,1 ;: Data 0,0,0 Data 0,1,0 Data 0,0,0 Data 0,1,0 Data 0,0,0 ;; Data 0,0,8 Data 0,8,1 Data 8,1,6 Data 1,6,0 Data 6,0,0 ;< Data 0,8,1 Data 8,1,6 Data 1,2,0 Data 9,1,7 Data 0,9,1 ;= Data 0,0,0 Data 0,0,0 Data 0,1,0 Data 0,0,0 Data 0,0,0 ;> Data 1,7,0 Data 9,1,7 Data 0,4,1 Data 8,1,6 Data 1,6,0 ;? Data 16,1,7 Data 0,4,1 Data 0,1,6 Data 0,0,0 Data 0,1,0 ;@ Data 0,15,0 Data 8,1,7 Data 1,1,1 Data 0,1,0 Data 0,1,0 ;A Data 8,1,7 Data 1,13,1 Data 1,1,1 Data 1,0,1 Data 17,0,17 ;B Data 1,1,7 Data 1,12,1 Data 1,1,2 Data 1,12,1 Data 1,1,6 ;C Data 8,1,14 Data 1,0,0 Data 1,0,0 Data 1,0,0 Data 9,1,14 ;D Data 1,1,7 Data 1,25,1 Data 1,0,1 Data 1,20,1 Data 1,1,6 ;E Data 8,1,14 Data 1,0,0 Data 1,1,14 Data 1,0,0 Data 9,1,14 ;F Data 8,1,14 Data 1,0,0 Data 1,1,14 Data 1,0,0 Data 17,0,0 ;G Data 8,1,14 Data 1,0,0 Data 1,0,15 Data 1,0,1 Data 9,1,6 ;H Data 15,0,15 Data 1,0,1 Data 1,1,1 Data 1,0,1 Data 17,0,17 ;I Data 16,1,14 Data 0,1,0 Data 0,1,0 Data 0,1,0 Data 16,1,14 ;J Data 0,0,15 Data 0,0,1 Data 0,0,1 Data 15,0,1 Data 9,1,6 ;K Data 15,0,8 Data 1,20,1 Data 1,1,2 Data 1,25,1 Data 17,0,9 ;L Data 15,0,0 Data 1,0,0 Data 1,0,0 Data 1,0,0 Data 9,1,14 ;M Data 8,3,7 Data 1,1,1 Data 1,29,1 Data 1,0,1 Data 17,0,17 ;N Data 8,1,7 Data 1,5,1 Data 1,0,1 Data 1,0,1 Data 17,0,17 ;O Data 8,1,7 Data 1,5,1 Data 1,0,1 Data 1,3,1 Data 9,1,6 ;P Data 1,1,7 Data 1,12,1 Data 1,1,6 Data 1,0,0 Data 17,0,0 ;Q Data 8,1,7 Data 1,5,1 Data 1,3,1 Data 9,1,6 Data 0,9,7 ;R Data 1,1,7 Data 1,12,1 Data 1,1,2 Data 1,5,1 Data 1,0,9 ;S Data 8,1,14 Data 1,2,0 Data 9,1,7 Data 0,4,1 Data 16,1,6 ;T Data 1,1,1 Data 0,1,0 Data 0,1,0 Data 0,1,0 Data 0,17,0 ;U Data 15,0,15 Data 1,0,1 Data 1,0,1 Data 1,3,1 Data 9,1,6 ;V Data 15,0,15 Data 1,0,1 Data 1,3,1 Data 9,1,6 Data 0,17,0 ;W Data 15,0,15 Data 1,0,1 Data 1,27,1 Data 1,1,1 Data 9,5,6 ;X Data 7,0,8 Data 1,3,1 Data 4,1,2 Data 1,5,1 Data 6,0,9 ;Y Data 7,0,8 Data 1,3,1 Data 9,1,6 Data 0,1,0 Data 0,17,0 ;Z Data 16,1,7 Data 0,4,1 Data 8,1,6 Data 1,2,0 Data 9,1,14