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
