How To > Read and Write Geometry Data > Output Geometry Data To Text File - Part One |
This is a very basic example of exporting mesh geometry data to an external text file. The file could be then parsed back by MAXScript or any other 3D application supporting scripting and reading of ASCII files. In Part One, we will export only the vertex and face list to a fixed path name. In Part Two, we will enhance the code to let the user select a destination file, and will support several other mesh features (edge visibility, smoothing groups, texture coordinates etc.)
In a separate tutorial, we will develop a script to import back the geometry data and recreate the mesh in the scene.
Editable_Mesh : GeometryClass and TriMesh : Value
We create a TriMesh snapshot of the first object found in the scene selection. This method evaluates the state on top of the modifier stack including any Space Warp bindings. The result is a TriMesh value which is stored in memory (does not exist in the scene). We will be able to access all its vertices and faces as if it was a scene object though.
Note that we still don’t check whether the user has selected an object in the scene and whether the first selected object is of geometry class. This is just a rough sketch of the final code and isn’t completely idiot-proof. The user has to make sure a valid object is selected. We will add such tests in Part Two of the tutorial.
Next we define a variable containing the destination path for exporting. We use the GetDir function with the keyword #export to get the 3ds Max system path set up for export operations. We add to it the file name testmesh.dat. This name can be any valid name you might want to use. In Part Two, we will let the user select a path and name using an open file dialog.
Using the defined output path, we create a new file and store the resulting fileStream value in a user variable called out_file. Using this variable as the destination, we will be able to output to the file.
The TriMesh value we created has the properties .numverts and .numfaces just like every mesh object in the scene. We get both values and store in user variables because we are going to need them multiple times.
Editable_Mesh : GeometryClass and TriMesh : Value
Now we can output to the file for the first time – we define a formatting pattern specifying that there will be two user elements written out, divided by a comma. The line will end with a new line control character specified by backslash-n. After the formatting string, we have to provide as many output expressions as % symbols in the formatting string – each of the variables we supply will be evaluated and the result will replace the % character.
If the numbers of vertices and faces are 8 and 12 respectively (a typical Box), the result of the output will be
At the end of the format function we provide a to: destination. If we don’t do this, the output will go by default to the MAXScript Listener.
The next step would be to output all vertices of the mesh. We will step through all vertices by using a for loop starting with 1 and ending with the number of vertices in the TriMesh. The variable v will change its value from 1 to num_verts each time the loop is repeated. It will end when the num_verts value is exceeded.
Using the value currently stored in the loop’s v variable, we get the respective indexed vertex by calling the getVert method on the tmesh value. The result will be stored in a user variable and will be a Point3 value (3D Position value) representing the world position of the vertex.
Editable_Mesh : GeometryClass and TriMesh : Value
The vertex position has to be written out to the file. We specify a formatting string telling the format function to output the value of the vert variable followed by a comma. We don’t want a new line – all vertex positions will appear in a single line, divided by commas.
At this place, the v loop ends and returns to the for v... statement unless the v variable has reached the num_verts value. This means that the block enclosed in the brackets will be repeated num_verts times.
To separate the vertex list from the face list, we output a single New Line character to the file. The formatting string expects no user expressions as we don’t include any % placeholders.
The output of the face list is very similar to the vertex list code We just use the other variable...
...and get the face definition instead of the vertex position. A face definition is also a Point3 value, but it contains indices to the 3 vertices defining the face instead of a position. The numbers stored in the Point3 value will be thus integers between 1 and num_verts. We store the result in a user variable called face...
...and output it to the file just like we did with the vertex.
At this place, the f loop ends and returns to the for f... statement unless the f variable has reached the num_faces value. This means that the block enclosed in the brackets will be repeated num_faces times.
Finally, we close the file so we can open it for reading. If we don’t do this, the file will be marked as open by the Windows OS and MAXScript will be unable to read from it. If a script causes an error before a file is closed explicitly, you can call gc() to perform garbage collection - as a side effect, any locked files will be released.
Delete the TriMesh value to release the used memory for garbage collection. Otherwise, running the script multiple times can cause memory leaks.
To make sure the output looks like expected, we open the file name defined in the beginning of the script in a MAXScript editor.
For a simple cube at the world origin, the output should look like
To test the script, create a geometry object, select it in the scene, then select Tools > Evaluate from the MAXScript Editor’s menu or alternatively, press Ctrl+E. The resulting output file should open in a new MAXScript editor.
As already mentioned, this is the basic code for geometry output. Still it can be made even more compact. Below is a shorter version of the same code without the opening in Editor for preview. Please compare the two scripts and see why both of them do the same thing although expressed slightly differently.
Now that we have some output, we can go on and write a corresponding input script to read back the data and create a new scene object.
How To ... Read Geometry Data From Text File - Part One
Also, in Part Two of the Geometry Output tutorial, we will make the code more robust and add some more features.
How To ... Read Geometry Data From Text File - Part One