Hi JFK, i dont know if it can be adapted for your needs, its set up for a group of terrain blocks as one mesh, but that could be adapted to recursively store any mesh (in theory).
There is a surface recording system and if a texture has been used once already it cross references its ID. Or at least should do :P
in the record brushes bit, you would still need to find a way of reading the getsurfacebrushes FX (at the moment im setting it manually from TEDs internal knowlage of what i want, but if you store it there in \bfx it should still be able to cross reference the same texs
Mabe the system i use for recording brushes may help you, or not...
Type brushdata
Field brushname$, surfnumber,mesh, texindex ,bfx, lmindex,brush
End Type
Type texdata
Field texname$,texindex,lmindex,lmname,islightmap,mesh,surfnumber
End Type
Global b3d_numtexs,b3d_numbrushes,b3d_currentlm
Function writeb3d_terrainAsonemesh(e_filename$)
;reset texture list
Delete Each brushdata
Delete Each texdata
;open output file
;If trn_quadnumbery>1 Or trn_quadnumberx>1 numb$="("+a+","+b+")"
filenameout$=e_filename$+".b3d"
b3d_numtexs=0
b3d_numbrushes=0
For b=1 To trn_quadnumbery
For a=1 To trn_quadnumberx
quad=quad+1
lmname$=e_filename$+"("+a+","+b+")"+"_LM.bmp"
b3d_recordtextures_terrainAsonemesh(meshout(a,b),"",lmname,quad)
;lm
td.texdata=New texdata
td\texindex=b3d_numtexs
td\texname$=lmname$
td\islightmap=True
b3d_numtexs=b3d_numtexs+1
b3d_recordbrushes_terrainAsonemesh(meshout(a,b),0,quad)
Next
Next
file=WriteFile( filenameout )
b3dSetFile( file )
b3dBeginChunk( "BB3D" )
b3dWriteInt( 1 ) ;version
writetextures()
writebrushes()
b3dBeginChunk( "NODE" )
b3dWriteString( "TERRAIN" )
b3dWriteFloat( 0 ) ;x_pos
b3dWriteFloat( 0 ) ;y_pos
b3dWriteFloat( 0 ) ;z_pos
b3dWriteFloat( 1 ) ;x_scale
b3dWriteFloat( 1 ) ;y_scale
b3dWriteFloat( 1 ) ;z_scale
b3dWriteFloat( 1 ) ;rot_w
b3dWriteFloat( 0 ) ;rot_x
b3dWriteFloat( 0 ) ;rot_y
b3dWriteFloat( 0 ) ;rot_z
For b=1 To trn_quadnumbery
For a=1 To trn_quadnumberx
writemesh(meshout(a,b))
Next
Next
b3dendchunk()
b3dendchunk()
CloseFile (file)
End Function
Function b3d_recordtextures_terrainAsonemesh(mesh,e_directory$,lmname$,quad)
If EntityClass (mesh)="Mesh"
For sc=1 To CountSurfaces (mesh)
;analyse mesh
surf=GetSurface (mesh,sc)
brush=GetSurfaceBrush (surf)
tex1=GetBrushTexture (brush,0)
name$=TextureName (tex1)
nonew=0
;get rid of tex path & copy textures
from$=name$
XE_XFilen$=strip_path(from)
CopyFile from,e_directory+XE_XFilen$
DebugLog "Copying tex to "+e_directory+XE_XFilen$
;if not in data create a new texture
If nonew=0
td.texdata=New texdata
td\texindex=b3d_numtexs
b3d_numtexs=b3d_numtexs+1
td\texname$=name$
td\islightmap=0
td\mesh=mesh
td\surfnumber=sc
EndIf
;cleanup
If brush FreeBrush brush :brush=0
If tex2 FreeTexture tex2 :tex2=0
If tex1 FreeTexture tex1 :tex1=0
Next
EndIf
;recurse all
For cc=1 To CountChildren(mesh)
chi=GetChild(mesh,cc)
b3d_recordtextures_terrainasonemesh(chi,e_directory$,lmname,quad)
Next
End Function
Function b3d_recordbrushes_terrainAsonemesh(mesh,fx,quad)
If EntityClass (mesh)="Mesh"
For sc=1 To CountSurfaces (mesh)
;analyse mesh
surf=GetSurface (mesh,sc)
brush=GetSurfaceBrush (surf)
tex1=GetBrushTexture (brush,0)
name$=TextureName (tex1)
;Create new brush
br.brushdata=New brushdata
br\mesh=mesh
br\surfnumber=sc
br\bfx=fx
br\brush=b3d_numbrushes
b3d_numbrushes=b3d_numbrushes+1
;specials for forcing vertex alpha in terrains
If Instr(EntityName(mesh),"TRN_BASE") Then br\bfx=2+FX
If Instr(EntityName(mesh),"TRN_ALPHA") Then br\bfx=2+32+FX
;look up index for texture used
For t.texdata=Each texdata
If t\texname$=name$ And t\mesh=mesh And t\surfnumber=sc Then
br\texindex=t\texindex
br\lmindex=b3d_numtexs-1
DebugLog "Brush lightmapinex="+mesh+" "+sc+","+br\texindex+","+(b3d_numtexs-1)
EndIf
Next
br\brushname$="brush_"+Int(b3d_numbrushes-1)+"_"+name$
;cleanup
If brush FreeBrush brush :brush=0
If tex2 FreeTexture tex2 :tex2=0
If tex1 FreeTexture tex1 :tex1=0
Next
EndIf
;recurse all
For cc=1 To CountChildren(mesh)
chi=GetChild(mesh,cc)
b3d_recordbrushes_terrainAsonemesh(chi,fx,quad)
Next
End Function
Function writetextures()
b3dBeginChunk( "TEXS" ) ; list all textures used by the mesh
For td.texdata=Each texdata
If td\islightmap=False
b3dWriteString(strip_path(td\texname)) ;texture file
b3dWriteInt( 1+8 ) ;flags
b3dWriteInt( 2 ) ;blend
b3dWriteFloat( 0 ) ;x in tex 0 (hu?)
b3dWriteFloat( 0 ) ;y in tex 0
b3dWriteFloat(1.000);tu );tex_uvscale(7-i) ) ;x scale 1
b3dWriteFloat(1.000);tex_uvscale(7-i) ) ;y scale 1
b3dWriteFloat(0 ) ;rotation 0
typ$="tex"
Else
b3dWriteString(strip_path(td\texname)) ;texture file
b3dWriteInt( 1+ 8 + 16 + 32 + 65536) ;flags
b3dWriteInt( 2 ) ;blend
b3dWriteFloat( 0 ) ;x in tex 0 (hu?)
b3dWriteFloat( 0 ) ;y in tex 0
b3dWriteFloat(1.000);tu );tex_uvscale(7-i) ) ;x scale 1
b3dWriteFloat(1.000);tex_uvscale(7-i) ) ;y scale 1
b3dWriteFloat(0 ) ;rotation 0
typ$="lm"
EndIf
DebugLog strip_path(td\texname)+" "+typ+" "+indx
indx=indx+1
Next
b3dEndChunk()
End Function
Function Writebrushes()
b3dBeginChunk( "BRUS" ) ; describe all brushes used by the mesh
b3dWriteInt(2) ;number of textures per brush ; (eg 2 with lightmap)
For br.brushdata=Each brushdata
b3dWriteString( br\brushname$ ) ;brushname
b3dWriteFloat( 1 ) ;red
b3dWriteFloat( 1 ) ;green
b3dWriteFloat( 1 ) ;blue
b3dWriteFloat( 1 ) ;alpha
b3dWriteFloat( 0 ) ;shininess
b3dWriteInt( 1 ) ;blendmode
b3dWriteInt( br\bfx) ;brushfx
b3dWriteInt( br\texindex ) ;used texture index
b3dWriteInt( br\lmindex ) ;additional texture index (eg lightmap), but here we only use 1 (see above)
DebugLog br\texindex +" "+br\lmindex
Next
b3dEndChunk() ;end of BRUS chunk
End Function
Function WriteMESH( mesh )
b3dBeginChunk( "NODE" )
name$=EntityName(mesh):If name="" name="noname"
b3dWriteString( name$ )
b3dWriteFloat( EntityX(MESH) ) ;x_pos
b3dWriteFloat( EntityY(MESH) ) ;y_pos
b3dWriteFloat( EntityZ(MESH) ) ;z_pos
b3dWriteFloat( 1 ) ;x_scale
b3dWriteFloat( 1 ) ;y_scale
b3dWriteFloat( 1 ) ;z_scale
b3dWriteFloat( 1 ) ;rot_w
b3dWriteFloat( 0 ) ;rot_x
b3dWriteFloat( 0 ) ;rot_y
b3dWriteFloat( 0 ) ;rot_z
If EntityClass(mesh)="Mesh"
b3dBeginChunk( "MESH" )
b3dWriteInt( -1 ) ;no 'entity' brush -1
b3dBeginChunk( "VRTS" )
b3dWriteInt( 3 ) ;flags - 0=no normal/color
b3dWriteInt( 2) ;number of tex_coord sets (eg: 2 with lightmap)
b3dWriteInt( 2 ) ;coords per set (u,v,w?) 2 with uv, 3 with uvw
n_surfs=CountSurfaces( mesh )
For k=n_surfs To 1 Step -1
surf=GetSurface( mesh,k )
n_verts=CountVertices( surf )-1
For j=0 To n_verts
b3dWriteFloat( VertexX( surf,j ) )
b3dWriteFloat( VertexY( surf,j ) )
b3dWriteFloat( VertexZ( surf,j ) )
b3dWriteFloat( VertexNX( surf,j ) )
b3dWriteFloat( VertexNY( surf,j ) )
b3dWriteFloat( VertexNZ( surf,j ) )
b3dWritefloat( VertexRed( surf,j )/255 )
b3dWritefloat( VertexGreen( surf,j )/255 )
b3dWritefloat( VertexBlue( surf,j )/255 )
b3dWriteFloat( VertexAlpha( surf,j ) )
b3dWriteFloat( VertexU#( surf,j,0 ) )
b3dWriteFloat( VertexV#( surf,j,0 ) )
; b3dWriteFloat( VertexW#( surf,j,0 ) )
; If lightmap_onoff
uaj#=VertexU#( surf,j,1 );VertexX( surf,j )/trn_size;
vaj#=VertexV#( surf,j,1 );VertexY( surf,j )/trn_size;
b3dWriteFloat( uaj) ; lightmap uv
b3dWriteFloat( vaj) ; lightmap uv
; b3dWriteFloat( VertexW#( surf,j,1 ) )
; EndIf
Next
Next
b3dEndChunk() ;end of VRTS chunk
first_vert=0
For k=n_surfs To 1 Step -1
surf=GetSurface( mesh,k )
n_tris=CountTriangles( surf )-1
b3dBeginChunk( "TRIS" )
b3dWriteInt( lookuptexidfromsurf(mesh,k,0) ) ;brush for these triangles (surf -1 !!!)
For j=0 To n_tris
b3dWriteInt( first_vert+TriangleVertex( surf,j,0 ) )
b3dWriteInt( first_vert+TriangleVertex( surf,j,1 ) )
b3dWriteInt( first_vert+TriangleVertex( surf,j,2 ) )
Next
b3dEndChunk() ;end of TRIS chunk
first_vert=first_vert+CountVertices( surf )
Next
b3dEndChunk() ;end of MESH chunk
EndIf
For cc=CountChildren(mesh)To 1 Step -1
chi=GetChild(mesh,cc)
WriteMESH( chi )
Next
b3dEndChunk() ;end of node chunk
End Function
Function lookuptexidfromsurf(mesh,surfnumber,fromlayer)
DebugLog "From Mesh:"+mesh+" surf:"+Surfnumber
For td.brushdata=Each brushdata
If td\mesh=mesh And td\surfnumber=surfnumber
DebugLog"yes to :"+td\mesh+" Surf:"+surfnumber +" Tex:"+td\texindex+" lm:"+td\lmindex +" brush:"+td\brush
Return td\brush
EndIf
Next
End Function