Code archives/3D Graphics - Misc/DigitText
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
Want to display some graphics fonts in your 3d view, but don't want to use overlayed 2d? These routines create and update a digit mesh which is essentially a flat mesh using seperate surfaces to display your text for a given text string, using a loaded 2d font image for the characters. The example code shows how to set up your camera in order to get the screen positioning correct, as the routines place the digit text mesh in relative 2d space. So you give the create routine 2d x and y coordinates and a parent camera, and it places the entity at the correct position in 3d space so that the digit mesh's text is the correct pixel size and position relative to your 2d screen. The routine that determines which font image frame index to use expects your font image characters to be ordered in a certain order. Here is the order: Index Character ----- --------- 0 , 1 - 2 . 3 / 4 : 5 = 6 ? 7 0 8 1 9-16 2-9 17 A 18-43 B-Z You can of course just change the UpdateDigitText() function to use a different frame index list for your font, which you will need to do anyway to use characters not covered by my font. You can download a font image example here: ![]() If you have any problems of questions on this code, feel free to email them to me. Mark Rosten markbasic@... | |||||
;digit sprites for HUD ;by Mark Rosten ;markbasic@planetflibble.com Graphics3D 640,480 ;for example only. not needed ;=================================== declares ;-- hud digit text declares Global digitbrush, digitbrushblank Global digitlasttxt$ ;-- load texture font frames Global fonttexwidth = 16 Global fonttexheight = 16 Global fonttexture = LoadAnimTexture( "digifont.png", 4+16+32, fonttexwidth, fonttexheight, 0, 43 ) If fonttexture = 0 Then RuntimeError( "File 'digifont.png' not found!" ) ;=================================== functions ;------------- create digit entity (for hud display text) Function CreateDigitEntity( parent, numdigits, x, y, CamZoom#=1.0 ) ;-- create work brushes? If Not digitbrush ; create work brushes digitbrush = CreateBrush() digitbrushblank = CreateBrush() ; clear blank digit brush texture ; (reset all pixels in texture to alpha 0, colour 0,0,0 ) tex = CreateTexture(1,1,4) SetBuffer TextureBuffer(tex) For ty=0 To TextureHeight(tex)-1 For tx=0 To TextureWidth(tex)-1 WritePixel tx,ty,0 Next Next SetBuffer BackBuffer() ; assign blank alpha'ed texture to blank work brush BrushTexture digitbrushblank, tex ; release texture FreeTexture tex EndIf ;-- create digit mesh ent = CreateDigitMesh( numdigits, parent ) ;-- adjust start position y by font height y = y + fonttexheight ;-- set entity properties EntityFX ent, 1+4+8 ;full bright, flatshaded, disable fog EntityOrder ent, -1 ;bring to front ;-- position entity relative to camera ; (if you have multiple cameras then you will need to hide the digit entity before ; rendering the cameras that you don't want the digit entity visible in) PositionEntity ent,x-(GraphicsWidth()/2),(GraphicsHeight()/2)-y,(GraphicsWidth()/2) * CamZoom# ;un-comment this to ignore the positioning in 2d space and view as normal mesh ;PositionEntity ent, -50, 0, 100 ;-- return newly created entity Return ent End Function ;------------- create digit mesh (quads joined together. one surf per quad) Function CreateDigitMesh( numdigits=1, parent ) ;-- create mesh mesh = CreateMesh( parent ) ;-- determine x and y sizes for single digit segment xsiz = fonttexwidth-1 ysiz = fonttexheight-1 ;-- create seperate quad per digit segment For digit = 1 To numdigits ; create a surface for this quad surf = CreateSurface( mesh ) ; create corner vertices for quad v0 = AddVertex( surf, x, ysiz, 0, 0, 0 ) ;top left v1 = AddVertex( surf, x+xsiz, ysiz, 0, 1, 0 ) ;top right v2 = AddVertex( surf, x+xsiz, 0, 0, 1, 1 ) ;bottom right v3 = AddVertex( surf, x, 0, 0, 0, 1 ) ;bottom left ; create 2 triangles to create quad AddTriangle surf, v0, v1, v2 AddTriangle surf, v0, v2, v3 ; increment x start position for next quad x = x + xsiz Next ;-- update normals (not sure if needed) UpdateNormals mesh ;-- return newly created mesh Return mesh End Function ;------------- update surface textures for digit mesh to show text Function UpdateDigitText( ent, txt$, newx=-999, newy=-999, camzoom#=1.0 ) ;-- change in position? If newx <> -999 If newx <> digitlastx Or newy <> digitlasty PositionEntity ent,newx-(GraphicsWidth()/2),(GraphicsHeight()/2)-newy,(GraphicsWidth()/2) * CamZoom# EndIf EndIf ;-- if no change in text since last call, then don't need to do anything If txt$ = digitlasttxt$ Then Return ;-- store this text digitlasttxt$ = txt$ ;-- convert to uppercase txt$ = Upper$(txt$) ;-- texture digits 1 to length of passed text For i = 1 To Len(txt$) ; only texture available surfaces If i <= CountSurfaces( ent ) ; get this digit's surface handle surf = GetSurface( ent, i ) ; determine texture frame ; (this is based on layout of font image loaded) f = 0 Select Mid$(txt$,i,1) Case "," f = 0 Case "-" f = 1 Case "." f = 2 Case "/" f = 3 Case ":" f = 4 Case "=" f = 5 Case "?" f = 6 Case "0","1","2","3","4","5","6","7","8","9" f = Int(Mid$(txt$,i,1))+7 Default If Mid$(txt$,i,1) >= "A" And Mid$(txt$,i,1) <= "Z" f = (Asc(Mid$(txt$,i,1)) - 64) + 16 EndIf End Select ; set brush texture and paint surface with it? If f > 0 BrushTexture digitbrush, fonttexture, f PaintSurface surf, digitbrush Else ; no available font character for this digit. so use blank digit PaintSurface surf, digitbrushblank EndIf Else ; text exceeds number of surfaces in digit mesh, so exit loop Exit EndIf Next ;-- clear remaining digits? If Len(txt$) < CountSurfaces( ent ) ; go through remaining digit surfaces.. For i = Len(txt$)+1 To CountSurfaces( ent ) ; get this digit's surface handle surf = GetSurface( ent, i ) ; use blank digit for this surface PaintSurface surf, digitbrushblank Next EndIf End Function ;=================================== example usage ; (remove this section when copying in to your program) ;create light light = CreateLight() ;for test only. not needed ;initialise camera camera = CreateCamera() camzoom# = 1.0 CameraZoom camera,camzoom# CameraRange camera,1,((GraphicsWidth()/2) * camzoom#)+1000 ;setup digit mesh (8 digits in this example) numdigits = 14 mydigit_entity = CreateDigitEntity( camera, numdigits, 64, 64, camzoom# ) ;create cube to rotate in front of camera cube = CreateCube() EntityColor cube, 128,0,0 PositionEntity cube, 0, 0, 5 ;render loop While Not KeyHit(1) test$ = Str$(cnt) : cnt = cnt + 1 If Len(test$) < numdigits Then test$ = String$("0",8-Len(test$)) + test$ test$ = "Test "+test$ ;if mouse button then pass new x/y 2d coordinates to fuction ;otherwise just update digit text If MouseDown(1) And detach=False UpdateDigitText( mydigit_entity, test$, MouseX(), MouseY(), camzoom# ) Else UpdateDigitText( mydigit_entity, test$ ) EndIf ;turn dummy cube TurnEntity cube, .5, 1, .5 ;toggle wireframe on W key If KeyHit(17) showwire = Not showwire WireFrame showwire EndIf ;toggle digit text detach from camera If KeyHit(57) detach = Not detach If detach EntityParent mydigit_entity, cube PositionEntity mydigit_entity, 0, 0, 10 Else EntityParent mydigit_entity, camera RotateEntity mydigit_entity, 0, 0, 0 UpdateDigitText( mydigit_entity, test$, 64, 64, camzoom# ) EndIf EndIf ;update and render world UpdateWorld RenderWorld ;instructions text Text 0,0,"Hold mouse button to move digit text in 2d space" Text 0,12,"Press W to toggle wireframe mode" Text 0,24,"Press SPACE to toggle digit text attachment to camera or cube" Flip Wend End |
Comments
None.
Code Archives Forum