Code archives/File Utilities/Export stl
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| I needed an .stl exporter for a project I am working on. I found an importer in the archives, but it did not export, so I wrote one. To use, just call: SaveStl(Filename$,Entity,Children) Filename$ - The name to save the stl file. Entity - the entity you are saving Children - True, include children in the file; False, save only the referenced entity. Example: SaveStl("car.stl",CarEntity,True) Some notes: stl has no concept of child or parent entities. All children are saved as one huge mesh. stl format allows a file that can contain up to 4,294,967,295 triangles. Since Blitz3D does not have an unsigned int type, the maximum triangles is only 2,147,483,647 This function currently has no error checking. stl specifications only allow vertices without negative components. i.e. A vertex should not be -1,0,0. Most modern software will save/load negative coordinates in an stl file anyway, but is something to keep in mind should you be using software that sticks strictly to the specifications. Since the function here may save negative coordinates, you need to translate the entities before saving if you are planning on using those programs. Stl does not use color, nor textures. They will be stripped from the entity. Edit 05/22/16: Oops, forgot to flip the Z axis :) | |||||
;SaveStl() by TomToad
;
;Usage
; SaveStl(Filename$,Entity,Children)
;
; Filename$ - name of the file to be saved
; Entity - the entity to be saved
; Children - True, all children will be saved in the file; False - Only the referenced entity will be saved
;v1.1 05/22/16 z axis needed to be flipped
;v1.0 05/22/16 original version
Global SaveStlTrisCount = 0 ;This holds the total number of triangles saved
;Type to hold a 3d vector
Type Vector3D
Field X#
Field Y#
Field z#
End Type
;This function saves the actual triangles. Your program will not call this function. It is
; called by SaveStl() and recursively calls itself for each child entity
Function SaveStlTris(Stream,Entity,Children)
; if saving children, then check if the entity has any children. If no children exist, then
; recursively call this function with children set to false, otherwise call this function
; for each child entity
If Children = True Then
If CountChildren(Entity) > 0 Then
For i = 1 To CountChildren(Entity)
SaveStlTris(Stream,GetChild(Entity,i),True)
Next
End If
SaveStlTris(Stream,Entity,False)
Else
;Now to save the actual entity.
For SurfaceIndex = 1 To CountSurfaces(Entity) ;Go through each surface
Surface = GetSurface(Entity,SurfaceIndex)
SaveStlTrisCount = SaveStlTrisCount + CountTriangles(Surface) ;Keep track of number of triangles
For TriangleIndex = 0 To CountTriangles(Surface)-1 ;go through each triangle on the surface
v0 = TriangleVertex(Surface,TriangleIndex,0) ;get the vertices of the triangle
v1 = TriangleVertex(Surface,TriangleIndex,2) ; vertex 1 and 2 are swapped as stl uses a
v2 = TriangleVertex(Surface,TriangleIndex,1) ; counter-clockwise ordering
;stl doesn't use scale or rotation, so all the vertices must be transformed to
; world coordinates
t0.Vector3D = New Vector3d
TFormPoint(VertexX(surface,v0),VertexY(surface,v0),VertexZ(surface,V0),Entity,0)
t0\x = TFormedX()
t0\y = TFormedY()
t0\z = -TFormedZ()
t1.Vector3D = New Vector3d
TFormPoint(VertexX(surface,v1),VertexY(surface,v1),VertexZ(surface,V1),Entity,0)
t1\x = TFormedX()
t1\y = TFormedY()
t1\z = -TFormedZ()
t2.Vector3D = New Vector3d
TFormPoint(VertexX(surface,v2),VertexY(surface,v2),VertexZ(surface,V2),Entity,0)
t2\x = TFormedX()
t2\y = TFormedY()
t2\z = -TFormedZ()
;Now to create the surface normal so that the stl file knows which way is out
U.Vector3D = New Vector3D
V.Vector3D = New Vector3D
U\x = t1\x-t0\x
U\y = t1\y-t0\y
U\z = t1\z-t0\z
V\x = t2\x-t0\x
V\y = t2\y-t0\y
V\z = t2\z-t0\z
Normal.Vector3D = New Vector3D
Normal\x = U\y*V\z-U\z*V\y
Normal\y = U\z*V\x-U\x*V\z
Normal\z = U\x*V\y-U\y*V\x
;write the normal to the file
WriteFloat(Stream,Normal\x)
WriteFloat(Stream,Normal\y)
WriteFloat(Stream,Normal\z)
;write the triangle to the file
WriteFloat(Stream,t0\x)
WriteFloat(Stream,t0\y)
WriteFloat(Stream,t0\z)
WriteFloat(Stream,t1\x)
WriteFloat(Stream,t1\y)
WriteFloat(Stream,t1\z)
WriteFloat(Stream,t2\x)
WriteFloat(Stream,t2\y)
WriteFloat(Stream,t2\z)
;free the types
Delete Normal
Delete U
Delete V
Delete t0
Delete t1
Delete t2
;attribute count. set to 0
WriteShort(Stream,0)
Next
Next
End If
End Function
;Your program will call this function
;Filename: Name of the file to be saved
;Entity: Parent entity to be saved
;Children: True to aslo save child entities, false to only save parent
Function SaveStl(Filename$,Entity,Children)
SaveStlTrisCount = 0 ;reset the triangle count to 0
Stream = WriteFile(Filename)
For i = 1 To 21 ;80 byte header + triangle count
WriteInt(Stream,0)
Next
SaveStlTris(Stream,Entity,Children) ;save the triangles
current = FilePos(Stream) ;save the current stream position
SeekFile(Stream,80) ;move to the triangle count positon
WriteInt(Stream,SaveStlTrisCount) ;write the number of triangles saved
CloseFile Stream
End Function
;--------------------------------------------
;
; The code below is a sample of using the
; Function SaveStl()
;
;---------------------------------------------
Graphics3D 800,600
cube = CreateCube() ;create a cube
sphere = CreateSphere(8,Cube) ;create a sphere, make cube its parent
ScaleEntity sphere,2,2,2 ;scale and move the sphere
PositionEntity sphere,5,0,0
SaveStl("cube.stl",Cube,False) ;save the cube, but not its children
SaveStl("sphere.stl",sphere,False) ;save the sphere
SaveStl("all.stl",Cube,True) ;save the cube and all its children
camera = CreateCamera()
PositionEntity camera,0,0,-10
light = CreateLight()
RotateEntity light,45,45,45
While Not KeyHit(1)
Cls
UpdateWorld
RenderWorld
Flip
If KeyDown(17) ;w
MoveEntity camera,0,0,.2
End If
If KeyDown(31) ;s
MoveEntity camera,0,0,-.2
End If
If KeyDown(30) ;a
TurnEntity camera,0,-1,0
End If
If KeyDown(32) ;d
TurnEntity camera,0,1,0
End If
Wend |
Comments
| ||
| interesting code |
| ||
| Just got around to testing this Tom Toad, great work. |
Code Archives Forum