2020SOFTWARE.
2121'''
2222
23- from .IOTools import unpackStream , readNullTerminatedString , calculatePadding
23+ from io import BytesIO
24+
25+ from .IOTools import unpackStream , packStream , readNullTerminatedString , calculatePadding
2426from . import A3DObjects
2527
2628'''
@@ -65,13 +67,33 @@ def read(self, stream):
6567 self .readRootBlock2 (stream )
6668 elif self .version == 3 :
6769 self .readRootBlock3 (stream )
70+ else :
71+ raise RuntimeError (f"Unknown A3D version: { self .version } " )
72+
73+ def write (self , stream , version = 2 ):
74+ # Write header data
75+ stream .write (A3D_SIGNATURE )
76+ packStream ("<2H" , stream , version , 0 )
77+
78+ # Write root block
79+ if version == 1 :
80+ self .writeRootBlock1 (stream )
81+ elif version == 2 :
82+ self .writeRootBlock2 (stream )
83+ elif version == 3 :
84+ self .writeRootBlock3 (stream )
85+ else :
86+ raise RuntimeError (f"Unknown A3D version: { version } whilst writing A3D" )
6887
6988 '''
7089 Root data blocks
7190 '''
7291 def readRootBlock1 (self , stream ):
7392 raise RuntimeError ("Version 1 files are not supported yet" )
7493
94+ def writeRootBlock1 (self , stream ):
95+ raise RuntimeError ("Version 1 files are not supported yet" )
96+
7597 def readRootBlock2 (self , stream ):
7698 # Verify signature
7799 signature , _ = unpackStream ("<2I" , stream )
@@ -85,6 +107,21 @@ def readRootBlock2(self, stream):
85107 self .readTransformBlock2 (stream )
86108 self .readObjectBlock2 (stream )
87109
110+ def writeRootBlock2 (self , stream ):
111+ buffer = BytesIO ()
112+
113+ # Write data to the buffer
114+ print ("Writing root block" )
115+ self .writeMaterialBlock2 (buffer )
116+ self .writeMeshBlock2 (buffer )
117+ self .writeTransformBlock2 (buffer )
118+ self .writeObjectBlock2 (buffer )
119+
120+ # Write buffer to stream
121+ packStream ("<2I" , stream , A3D_ROOTBLOCK_SIGNATURE , buffer .tell ())
122+ buffer .seek (0 , 0 )
123+ stream .write (buffer .read ())
124+
88125 def readRootBlock3 (self , stream ):
89126 # Verify signature
90127 signature , length = unpackStream ("<2I" , stream )
@@ -101,6 +138,21 @@ def readRootBlock3(self, stream):
101138 padding = calculatePadding (length )
102139 stream .read (padding )
103140
141+ def writeRootBlock3 (self , stream ):
142+ buffer = BytesIO ()
143+
144+ # Write data to the buffer
145+ print ("Writing root block" )
146+ self .writeMaterialBlock3 (buffer )
147+ self .writeMeshBlock3 (buffer )
148+ self .writeTransformBlock3 (buffer )
149+ self .writeObjectBlock3 (buffer )
150+
151+ # Write buffer to stream
152+ packStream ("<2I" , stream , A3D_ROOTBLOCK_SIGNATURE , buffer .tell ())
153+ buffer .seek (0 , 0 )
154+ stream .write (buffer .read ())
155+
104156 '''
105157 Material data blocks
106158 '''
@@ -117,6 +169,20 @@ def readMaterialBlock2(self, stream):
117169 material .read2 (stream )
118170 self .materials .append (material )
119171
172+ def writeMaterialBlock2 (self , stream ):
173+ buffer = BytesIO ()
174+
175+ # Write data to the buffer
176+ print ("Writing material block" )
177+ packStream ("<I" , buffer , len (self .materials ))
178+ for material in self .materials :
179+ material .write2 (buffer )
180+
181+ # Write buffer to stream
182+ packStream ("<2I" , stream , A3D_MATERIALBLOCK_SIGNATURE , buffer .tell ())
183+ buffer .seek (0 , 0 )
184+ stream .write (buffer .read ())
185+
120186 def readMaterialBlock3 (self , stream ):
121187 # Verify signature
122188 signature , length , materialCount = unpackStream ("<3I" , stream )
@@ -134,6 +200,24 @@ def readMaterialBlock3(self, stream):
134200 padding = calculatePadding (length )
135201 stream .read (padding )
136202
203+ def writeMaterialBlock3 (self , stream ):
204+ buffer = BytesIO ()
205+
206+ # Write data to the buffer
207+ print ("Writing material block" )
208+ packStream ("<I" , buffer , len (self .materials ))
209+ for material in self .materials :
210+ material .write3 (buffer )
211+
212+ # Write buffer to stream
213+ packStream ("<2I" , stream , A3D_MATERIALBLOCK_SIGNATURE , buffer .tell ())
214+ buffer .seek (0 , 0 )
215+ stream .write (buffer .read ())
216+
217+ # Padding
218+ paddingSize = calculatePadding (buffer .tell ())
219+ stream .write (b"\x00 " * paddingSize )
220+
137221 '''
138222 Mesh data blocks
139223 '''
@@ -150,6 +234,20 @@ def readMeshBlock2(self, stream):
150234 mesh .read2 (stream )
151235 self .meshes .append (mesh )
152236
237+ def writeMeshBlock2 (self , stream ):
238+ buffer = BytesIO ()
239+
240+ # Write data to the buffer
241+ print ("Writing mesh block" )
242+ packStream ("<I" , buffer , len (self .meshes ))
243+ for mesh in self .meshes :
244+ mesh .write2 (buffer )
245+
246+ # Write buffer to stream
247+ packStream ("<2I" , stream , A3D_MESHBLOCK_SIGNATURE , buffer .tell ())
248+ buffer .seek (0 , 0 )
249+ stream .write (buffer .read ())
250+
153251 def readMeshBlock3 (self , stream ):
154252 # Verify signature
155253 signature , length , meshCount = unpackStream ("<3I" , stream )
@@ -167,6 +265,24 @@ def readMeshBlock3(self, stream):
167265 padding = calculatePadding (length )
168266 stream .read (padding )
169267
268+ def writeMeshBlock3 (self , stream ):
269+ buffer = BytesIO ()
270+
271+ # Write data to the buffer
272+ print ("Writing mesh block" )
273+ packStream ("<I" , buffer , len (self .meshes ))
274+ for mesh in self .meshes :
275+ mesh .write3 (buffer )
276+
277+ # Write buffer to stream
278+ packStream ("<2I" , stream , A3D_MESHBLOCK_SIGNATURE , buffer .tell ())
279+ buffer .seek (0 , 0 )
280+ stream .write (buffer .read ())
281+
282+ # Padding
283+ paddingSize = calculatePadding (buffer .tell ())
284+ stream .write (b"\x00 " * paddingSize )
285+
170286 '''
171287 Transform data blocks
172288 '''
@@ -187,6 +303,22 @@ def readTransformBlock2(self, stream):
187303 parentID , = unpackStream ("<i" , stream )
188304 self .transformParentIDs .append (parentID )
189305
306+ def writeTransformBlock2 (self , stream ):
307+ buffer = BytesIO ()
308+
309+ # Write data to the buffer
310+ print ("Writing transform block" )
311+ packStream ("<I" , buffer , len (self .transforms ))
312+ for transform in self .transforms :
313+ transform .write2 (buffer )
314+ for parentID in self .transformParentIDs :
315+ packStream ("<i" , buffer , parentID )
316+
317+ # Write buffer to stream
318+ packStream ("<2I" , stream , A3D_TRANSFORMBLOCK_SIGNATURE , buffer .tell ())
319+ buffer .seek (0 , 0 )
320+ stream .write (buffer .read ())
321+
190322 def readTransformBlock3 (self , stream ):
191323 # Verify signature
192324 signature , length , transformCount = unpackStream ("<3I" , stream )
@@ -195,7 +327,6 @@ def readTransformBlock3(self, stream):
195327
196328 # Read data
197329 print (f"Reading transform block with { transformCount } transforms and length { length } " )
198- transforms = []
199330 for _ in range (transformCount ):
200331 transform = A3DObjects .A3DTransform ()
201332 transform .read3 (stream )
@@ -209,6 +340,26 @@ def readTransformBlock3(self, stream):
209340 padding = calculatePadding (length )
210341 stream .read (padding )
211342
343+ def writeTransformBlock3 (self , stream ):
344+ buffer = BytesIO ()
345+
346+ # Write data to the buffer
347+ print ("Writing transform block" )
348+ packStream ("<I" , buffer , len (self .transforms ))
349+ for transform in self .transforms :
350+ transform .write3 (buffer )
351+ for parentID in self .transformParentIDs :
352+ packStream ("<i" , buffer , parentID )
353+
354+ # Write buffer to stream
355+ packStream ("<2I" , stream , A3D_TRANSFORMBLOCK_SIGNATURE , buffer .tell ())
356+ buffer .seek (0 , 0 )
357+ stream .write (buffer .read ())
358+
359+ # Padding
360+ paddingSize = calculatePadding (buffer .tell ())
361+ stream .write (b"\x00 " * paddingSize )
362+
212363 '''
213364 Object data blocks
214365 '''
@@ -225,6 +376,20 @@ def readObjectBlock2(self, stream):
225376 objec .read2 (stream )
226377 self .objects .append (objec )
227378
379+ def writeObjectBlock2 (self , stream ):
380+ buffer = BytesIO ()
381+
382+ # Write data to the buffer
383+ print ("Writing object block" )
384+ packStream ("<I" , buffer , len (self .objects ))
385+ for objec in self .objects :
386+ objec .write2 (buffer )
387+
388+ # Write buffer to stream
389+ packStream ("<2I" , stream , A3D_OBJECTBLOCK_SIGNATURE , buffer .tell ())
390+ buffer .seek (0 , 0 )
391+ stream .write (buffer .read ())
392+
228393 def readObjectBlock3 (self , stream ):
229394 # Verify signature
230395 signature , length , objectCount = unpackStream ("<3I" , stream )
@@ -240,4 +405,22 @@ def readObjectBlock3(self, stream):
240405
241406 # Padding
242407 padding = calculatePadding (length )
243- stream .read (padding )
408+ stream .read (padding )
409+
410+ def writeObjectBlock3 (self , stream ):
411+ buffer = BytesIO ()
412+
413+ # Write data to the buffer
414+ print ("Writing object block" )
415+ packStream ("<I" , buffer , len (self .objects ))
416+ for objec in self .objects :
417+ objec .write3 (buffer )
418+
419+ # Write buffer to stream
420+ packStream ("<2I" , stream , A3D_OBJECTBLOCK_SIGNATURE , buffer .tell ())
421+ buffer .seek (0 , 0 )
422+ stream .write (buffer .read ())
423+
424+ # Padding
425+ paddingSize = calculatePadding (buffer .tell ())
426+ stream .write (b"\x00 " * paddingSize )
0 commit comments