Иногда необходимо сохранить созданный mesh в Blitz3D в формат 3ds, который понимается многими редакторами. Такая потребность может возникнуть если вы делаете редактор к своей игре или просто редактор.

Код разработал markcw в 2006 году в сообществе blitzmax. И так, сам исходный код:

;Save Mesh 3DS, on 26/9/06

Graphics3D 640,480,0,2
AppTitle "Save Mesh 3DS"
SetBuffer BackBuffer()

camera=CreateCamera() ;init world
light=CreateLight()
RotateEntity light,45,45,0

tex=MakeTestTexture(128,128) ;new texture

shape=0 ;type of shape to save
Select shape
 Case 0
  mesh1=CreateCube() : child1=CreateCube(mesh1)
  PositionEntity child1,1,-1,1 : RotateEntity child1,30,-30,30
 Case 1
  mesh1=CreateSphere(8) : child1=CreateSphere(8,mesh1)
  PositionEntity child1,1,1,-1
 Case 2
  mesh1=CreateCylinder(8,True) : child1=CreateCylinder(8,True,mesh1)
  PositionEntity child1,1,1,1 : RotateEntity child1,30,30,-30
 Case 3
  mesh1=CreateCone(8,True) : child1=CreateCone(8,True,mesh1)
  PositionEntity child1,1,-1,-1
 Case 4
  mesh1=LoadMesh("yourname.x")
 Case 5
  mesh1=LoadAnimMesh("yourname.x")
End Select
EntityTexture mesh1,tex ;texture
If child1 Then EntityTexture child1,tex

filename$="test.3ds" ;save to 3ds file
;texfile$="test.bmp" ;optional texture filename
ok=SaveMesh3DS(mesh1,filename$,texfile$)

mesh2=LoadMesh(filename$) ;load new 3ds
If Len(texfile$)=0 Then EntityTexture mesh2,tex ;texture

PositionEntity mesh1,-2,0,5 ;position to left
PositionEntity mesh2,2,0,5 ;position to right

While Not KeyHit(1)
 RenderWorld()

 TurnEntity mesh1,0.3,0.2,0.1
 TurnEntity mesh2,0.3,0.2,0.1

 If KeyHit(17) Then wf=Not wf : WireFrame wf ;W key

 Text 0,0,"ok="+ok+" filename$="+filename$

 Flip
Wend

Function SaveMesh3DS(mesh,filename$,texfile$="",diffuse=$CCCCCC)
 ;Saves a given mesh, or mesh hierarchy, as a 3DS file
 ;From "3dsinfo.txt" by Jochen Wilhelmy
 ;mesh=mesh/mesh hierarchy handle, filename$="name.3ds"
 ;texfile$=optional texture file, diffuse=optional diffuse color

 Local file,piv,matname$,mnlen,tflen,ent,surf,si,mi,objname$,onlen
 Local tssize,tmsize,tfsize,tosize,tcsize,tvsize,otsize
 Local eobjsize,ematsize,editsize,i

 file=WriteFile(filename$)
 If Not file Return False ;fail code
 piv=CreatePivot() ;pivot to tform vertices

 ;calculate chunk sizes and file size
 matname$="Material"
 mnlen=Len(matname$)+1
 tflen=Len(texfile$)+1
 ent=mesh
 While ent
  For si=1 To CountSurfaces(ent)
   surf=GetSurface(ent,si)
   mi=mi+1 : If mi<10 Then objname$="mesh0"+mi Else objname$="mesh"+mi
   onlen=Len(objname$)+1
   tssize=6+(CountTriangles(surf)*4) ;sizeof(Tri_Smooth)
   tmsize=8+mnlen+(CountTriangles(surf)*2) ;sizeof(Tri_Material)
   tfsize=8+(CountTriangles(surf)*4*2)+tmsize+tssize ;sizeof(Tri_FaceList)
   tosize=8+(CountVertices(surf)*2) ;sizeof(Tri_VertexOptions)
   tcsize=8+(CountVertices(surf)*2*4) ;sizeof(Tri_MappingCoords)
   tvsize=8+(CountVertices(surf)*3*4) ;sizeof(Tri_VertexList)
   otsize=6+tvsize+tcsize+tosize+54+tfsize ;sizeof(Object_TriMesh)
   eobjsize=eobjsize+(6+onlen+otsize) ;sizeof(All_Edit_Objects)
  Next
  ent=NextChild(ent)
 Wend
 ematsize=6+(6+mnlen)+(15*3)+(14*6)+10 ;sizeof(Edit_Material)
 If tflen>1 Then ematsize=ematsize+(6+(6+tflen)) ;Mat_TextureMap1
 editsize=6+10+ematsize+10+eobjsize ;sizeof(Edit3DS)

 ;Main3DS Chunk
 WriteShort file,$4D4D ;wChunkID, Main3DS
 WriteInt file,6+10+editsize ;dwChunkSize, filesize
 ;Version3DS Chunk
 WriteShort file,$0002 ;wChunkID, Version3DS
 WriteInt file,10 ;dwChunkSize, sizeof(Version3DS)
 WriteInt file,3 ;ChunkData, dwVersion3DS

 ;Edit3DS Chunk, Main3DS Subchunk
 WriteShort file,$3D3D ;wChunkID, Edit3DS
 WriteInt file,editsize ;dwChunkSize, editsize=6+ematsize+eobjsize
 ;Edit_MeshVersion, Edit3DS Subchunk
 WriteShort file,$3D3E ;wChunkID, Edit_MeshVersion
 WriteInt file,10 ;dwChunkSize, sizeof(Edit_MeshVersion)
 WriteInt file,3 ;ChunkData, dwMeshVersion

 ;Edit_Material Chunk, Edit3DS Subchunk
 WriteShort file,$AFFF ;wChunkID, Edit_Material
 WriteInt file,ematsize ;dwChunkSize, ematsize=6+(6+mnlen)+(15*3)
 ;Mat_Name01 Chunk, Edit_Material Subchunk
 WriteShort file,$A000 ;wChunkID, Mat_Name01
 WriteInt file,6+mnlen ;dwChunkSize, sizeof(Mat_Name01)
 WriteStringAscii(file,matname$) ;ChunkData, material name
 WriteByte file,0 ;ChunkData, Ascii-z null byte
 ;Mat_Ambient Chunk, Edit_Material Subchunk
 WriteShort file,$A010 ;wChunkID, Mat_Ambient
 WriteInt file,15 ;dwChunkSize, sizeof(Mat_Ambient)
 WriteShort file,$0011 ;wChunkID, bRGB
 WriteInt file,9 ;dwChunkSize, sizeof(bRGB)
 WriteRGBColor(file,$666666) ;ChunkData, ambient color
 ;Mat_Diffuse Chunk, Edit_Material Subchunk
 WriteShort file,$A020 ;wChunkID, Mat_Diffuse
 WriteInt file,15 ;dwChunkSize, sizeof(Mat_Diffuse)
 WriteShort file,$0011 ;wChunkID, bRGB
 WriteInt file,9 ;dwChunkSize, sizeof(bRGB)
 WriteRGBColor(file,diffuse) ;ChunkData, diffuse color
 ;Mat_Specular Chunk, Edit_Material Subchunk
 WriteShort file,$A030 ;wChunkID, Mat_Specular
 WriteInt file,15 ;dwChunkSize, sizeof(Mat_Specular)
 WriteShort file,$0011 ;wChunkID, bRGB
 WriteInt file,9 ;dwChunkSize, sizeof(bRGB)
 WriteRGBColor(file,$FFFFFF) ;ChunkData, specular color
 ;Mat_Shininess Chunk, Edit_Material Subchunk
 WriteShort file,$A040 ;wChunkID, Mat_Shininess
 WriteInt file,14 ;dwChunkSize, sizeof(Mat_Shininess)
 WriteShort file,$0030 ;wChunkID, wPercent
 WriteInt file,8 ;dwChunkSize, sizeof(wPercent)
 WriteShort file,75 ;ChunkData, Shininess
 ;Mat_ShininessStrength Chunk, Edit_Material Subchunk
 WriteShort file,$A041 ;wChunkID, Mat_ShininessStrength
 WriteInt file,14 ;dwChunkSize, sizeof(Mat_ShininessStrength)
 WriteShort file,$0030 ;wChunkID, wPercent
 WriteInt file,8 ;dwChunkSize, sizeof(wPercent)
 WriteShort file,20 ;ChunkData, ShininessStrength
 ;Mat_Transparency Chunk, Edit_Material Subchunk
 WriteShort file,$A050 ;wChunkID, Mat_Transparency
 WriteInt file,14 ;dwChunkSize, sizeof(Mat_Transparency)
 WriteShort file,$0030 ;wChunkID, wPercent
 WriteInt file,8 ;dwChunkSize, sizeof(wPercent)
 WriteShort file,0 ;ChunkData, Transparency
 ;Mat_TransparencyFalloff Chunk, Edit_Material Subchunk
 WriteShort file,$A052 ;wChunkID, Mat_TransparencyFalloff
 WriteInt file,14 ;dwChunkSize, sizeof(Mat_TransparencyFalloff)
 WriteShort file,$0030 ;wChunkID, wPercent
 WriteInt file,8 ;dwChunkSize, sizeof(wPercent)
 WriteShort file,0 ;ChunkData, TransparencyFalloff
 ;Mat_ReflectionBlur Chunk, Edit_Material Subchunk
 WriteShort file,$A053 ;wChunkID, Mat_ReflectionBlur
 WriteInt file,14 ;dwChunkSize, sizeof(Mat_ReflectionBlur)
 WriteShort file,$0030 ;wChunkID, wPercent
 WriteInt file,8 ;dwChunkSize, sizeof(wPercent)
 WriteShort file,0 ;ChunkData, ReflectionBlur
 ;Mat_SelfIllumination Chunk, Edit_Material Subchunk
 WriteShort file,$A084 ;wChunkID, Mat_SelfIllumination
 WriteInt file,14 ;dwChunkSize, sizeof(Mat_SelfIllumination)
 WriteShort file,$0030 ;wChunkID, wPercent
 WriteInt file,8 ;dwChunkSize, sizeof(wPercent)
 WriteShort file,0 ;ChunkData, SelfIllumination
 ;Edit_WireThickness Chunk, Edit_Material Subchunk
 WriteShort file,$A087 ;wChunkID, Edit_WireThickness
 WriteInt file,10 ;dwChunkSize, sizeof(Edit_WireThickness)
 WriteFloat file,1 ;fWireThickness
 ;Mat_TextureMap1 Chunk, Edit_Material Subchunk
 If tflen>1
  WriteShort file,$A200 ;wChunkID, Mat_TextureMap1
  WriteInt file,6+(6+tflen) ;dwChunkSize, sizeof(Mat_TextureMap1)
  ;Mat_TextureFilename, Mat_TextureMap1 Subchunk
  WriteShort file,$A300 ;wChunkID, Mat_TextureFilename
  WriteInt file,6+tflen ;dwChunkSize, sizeof(Mat_TextureFilename)
  WriteStringAscii(file,texfile$) ;ChunkData, texture filename
  WriteByte file,0 ;ChunkData, Ascii-z null byte
 EndIf

 ;Edit_OneUnit Chunk, Edit3DS Subchunk
 WriteShort file,$0100 ;wChunkID, Edit_OneUnit
 WriteInt file,10 ;dwChunkSize, sizeof(Edit_OneUnit)
 WriteFloat file,1 ;fOneUnit

 ;calculate each mesh object chunk sizes
 ent=mesh : mi=0
 While ent
  For si=1 To CountSurfaces(ent)
   surf=GetSurface(ent,si)
   mi=mi+1 : If mi<10 Then objname$="mesh0"+mi Else objname$="mesh"+mi
   onlen=Len(objname$)+1
   tssize=6+(CountTriangles(surf)*4) ;sizeof(Tri_Smooth)
   tmsize=8+mnlen+(CountTriangles(surf)*2) ;sizeof(Tri_Material)
   tfsize=8+(CountTriangles(surf)*4*2)+tmsize+tssize ;sizeof(Tri_FaceList)
   tosize=8+(CountVertices(surf)*2) ;sizeof(Tri_VertexOptions)
   tcsize=8+(CountVertices(surf)*2*4) ;sizeof(Tri_MappingCoords)
   tvsize=8+(CountVertices(surf)*3*4) ;sizeof(Tri_VertexList)
   otsize=6+tvsize+tcsize+tosize+54+tfsize ;sizeof(Object_TriMesh)
   eobjsize=6+onlen+otsize ;sizeof(Edit_Object)
   ;position/rotate pivot to tform surface vertices
   PositionEntity piv,EntityX(ent,1),EntityY(ent,1),EntityZ(ent,1),1
   RotateEntity piv,EntityPitch(ent,1),EntityYaw(ent,1),EntityRoll(ent,1),1

   ;Edit_Object Chunk, Edit3DS Subchunk
   WriteShort file,$4000 ;wChunkID, Edit_Object
   WriteInt file,eobjsize ;dwChunkSize, eobjsize=6+onlen+otsize
   WriteStringAscii(file,objname$) ;ChunkData, object name
   WriteByte file,0 ;ChunkData, Ascii-z null byte

   ;Object_TriMesh Chunk, Edit_Object Subchunk
   WriteShort file,$4100 ;wChunkID, Object_TriMesh
   WriteInt file,otsize ;dwChunkSize, otsize=6+tvsize+tcsize+54+tfsize
   ;Tri_VertexList Chunk, Object_TriMesh Subchunk
   WriteShort file,$4110 ;wChunkID, Tri_VertexList
   WriteInt file,tvsize ;dwChunkSize, tvsize=8+(nVerts*3*4)
   WriteShort file,CountVertices(surf) ;ChunkData, wVerticesTotal
   For i=0 To CountVertices(surf)-1 ;switch y and z axis
    TFormPoint VertexX(surf,i),VertexY(surf,i),VertexZ(surf,i),piv,0
    WriteFloat file,TFormedX() ;fVertexX
    WriteFloat file,TFormedZ() ;fVertexY
    WriteFloat file,TFormedY() ;fVertexZ
   Next
   ;Tri_MappingCoords Chunk, Object_TriMesh Subchunk
   WriteShort file,$4140 ;wChunkID, Tri_MappingCoords
   WriteInt file,tcsize ;dwChunkSize, tcsize=8+(nVerts*2*4)
   WriteShort file,CountVertices(surf) ;ChunkData, wVerticesTotal
   For i=0 To CountVertices(surf)-1 ;invert v coord
    WriteFloat file,VertexU(surf,i) ;fVertexU
    WriteFloat file,-VertexV(surf,i) ;fVertexV
   Next
   ;Tri_VertexOptions Chunk, Object_TriMesh Subchunk
   WriteShort file,$4111 ;wChunkID, Tri_VertexOptions
   WriteInt file,tosize ;dwChunkSize, tosize=8+(nVerts*2)
   WriteShort file,CountVertices(surf) ;ChunkData, wVerticesTotal
   For i=0 To CountVertices(surf)-1 ;invert v coord
    WriteShort file,$0700 ;AllVertexOptions
   Next
   ;Tri_Local Chunk, Object_TriMesh Subchunk
   WriteShort file,$4160 ;wChunkID, Tri_Local
   WriteInt file,54 ;dwChunkSize, sizeof(Tri_Local)
   For i=0 To 3 ;X,Y,Z,Origin
    If i=0 Then WriteFloat file,1 Else WriteFloat file,0 ;fLocal1
    If i=1 Then WriteFloat file,1 Else WriteFloat file,0 ;fLocal2
    If i=2 Then WriteFloat file,1 Else WriteFloat file,0 ;fLocal3
   Next
   ;Tri_FaceList Chunk, Object_TriMesh Subchunk
   WriteShort file,$4120 ;wChunkID, Tri_FaceList
   WriteInt file,tfsize ;dwChunkSize, tfsize=8+(nTris*4*2)+tmsize+tssize
   WriteShort file,CountTriangles(surf) ;ChunkData, wTrianglesTotal
   For i=0 To CountTriangles(surf)-1 ;invert face order
    WriteShort file,TriangleVertex(surf,i,2) ;wTriangleVertexA
    WriteShort file,TriangleVertex(surf,i,1) ;wTriangleVertexB
    WriteShort file,TriangleVertex(surf,i,0) ;wTriangleVertexC
    WriteShort file,$0407 ;wFaceFlags
   Next
   ;Tri_Material Chunk, Tri_FaceList Subchunk
   WriteShort file,$4130 ;wChunkID, Tri_Material
   WriteInt file,tmsize ;dwChunkSize, tmsize=8+mnlen+(nTris*2)
   WriteStringAscii(file,matname$) ;ChunkData, material name
   WriteByte file,0 ;ChunkData, Ascii-z null byte
   WriteShort file,CountTriangles(surf) ;ChunkData, wTrianglesAssigned
   For i=0 To CountTriangles(surf)-1
    WriteShort file,i ;wTriangleIndex
   Next
   ;Tri_Smooth Chunk, Tri_FaceList Subchunk
   WriteShort file,$4150 ;wChunkID, Tri_Smooth
   WriteInt file,tssize ;dwChunkSize, tssize=6+(nTris*4)
   For i=0 To CountTriangles(surf)-1
    WriteInt file,1 ;dwTriangleSmoothGroup
   Next

  Next
  ent=NextChild(ent)
 Wend

 FreeEntity piv
 CloseFile file
 Return True ;success code

End Function

Function WriteStringAscii(file,ascii$)
 ;file=file handle, ascii$=ascii string

 Local i,char$
 For i=1 To Len(ascii$)
  char$=Mid(ascii$,i,1)
  WriteByte(file,Asc(char$))
 Next

End Function

Function WriteRGBColor(file,rgb)
 ;file=file handle, rgb=3-byte value

 WriteByte(file,(rgb And $FF0000) Shr 16) ;r
 WriteByte(file,(rgb And $00FF00) Shr 8) ;g
 WriteByte(file,(rgb And $0000FF)) ;b

End Function

Function NextChild(ent)
 ;Returns next child of entity as if it was on the same hierarchy level
 ;"NextChild(entity)", by Beaker

 If CountChildren(ent)>0
  Return GetChild(ent,1)
 EndIf
 Local foundunused=False
 Local foundent=0,parent,sibling
 While foundunused=False And ent<>0
  parent=GetParent(ent)
  If parent<>0
   If CountChildren(parent)>1
    If GetChild(parent,CountChildren(parent))<>ent
     For siblingcnt=1 To CountChildren(parent)
      sibling=GetChild(parent,siblingcnt)
      If sibling=ent
       foundunused=True
       foundent=GetChild(parent,siblingcnt+1)
      EndIf
     Next
    EndIf
   EndIf
  EndIf
  ent=parent
 Wend
 Return foundent

End Function

Function MakeTestTexture(width,height)

 Local texture,x,y,rgb
 texture=CreateTexture(width,height)
 LockBuffer(TextureBuffer(texture))
 For y=0 To TextureHeight(texture)-1
  For x=0 To TextureWidth(texture)-1
   rgb=y+(y*256)+(x*256^2) ;gradient color
   WritePixelFast x,y,rgb,TextureBuffer(texture)
  Next
 Next
 UnlockBuffer(TextureBuffer(texture))
 SetBuffer TextureBuffer(texture)
 Color 255,255,255 : Oval 40,40,30,30
 Color 0,0,0 : Text 50,50,"3DS" : Color 255,255,255
 SetBuffer BackBuffer()
 Return texture

End Function
(Visited 164 times, 1 visits today)