How To ... Output Geometry Data To Text File - Part One

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.

Related Topics:

Editable_Mesh : GeometryClass and TriMesh : Value

FileStream Values

NATURAL LANGUAGE

Get a snapshot of the first selected object.

Define an output file name.

Create a new file using the file name.

Get the number of vertices and faces in the mesh.

Output the vertex and face count to the file.

Step through all vertices .

Read the position into a variable.

Write out the vertex position to the file.

Step through all faces.

Read the face definition into a variable.

Write out the face definition to the file.

Close the file.

Open the file to take a look at the result.

MAXSCRIPT

tmesh = snapshotAsMesh selection[1]
out_name = ((GetDir #export)+"/testmesh.dat")
out_file = createfile out_name
num_verts = tmesh.numverts
num_faces = tmesh.numfaces
format "%,%\n" num_verts num_faces to:out_file
for v = 1 to num_verts do
(
 vert = getVert tmesh v
 format "%," vert to:out_file
)
format "\n" to:out_file
for f = 1 to num_faces do
(
 face = getFace tmesh f
 format "%," face to:out_file
)
close out_file
delete tmesh
edit out_name

Step-By-Step

tmesh = snapshotAsMesh selection[1]

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.

snapshotAsMesh

out_name = ((GetDir #export)+"/testmesh.dat")

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.

3ds MaxSystem Directories

out_file = createfile out_name

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.

FileStream Values

num_verts = tmesh.numverts num_faces = tmesh.numfaces

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

format "%,%\n" num_verts num_faces to:out_file

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

8,12

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.

FileStream Values

for v = 1 to num_verts do (

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.

For Loop

vert = getVert tmesh v

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

format "%," vert to:out_file

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.

format "\n" to:out_file

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.

for f = 1 to num_faces do (

The output of the face list is very similar to the vertex list code We just use the other variable...

face = getFace tmesh f

...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...

format "%," face to:out_file

...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.

close out_file

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 tmesh

Delete the TriMesh value to release the used memory for garbage collection. Otherwise, running the script multiple times can cause memory leaks.

edit out_name

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

SAMPLE OUTPUT OF A CUBE

8,12
[-50,-50,0],[50,-50,0],[-50,50,0],[50,50,0],[-50,-50,100],[50,-50,100],[-50,50,100],[50,50,100],
[1,3,4],[4,2,1],[5,6,8],[8,7,5],[1,2,6],[6,5,1],[2,4,8],[8,6,2],[4,3,7],[7,8,4],[3,1,5],[5,7,3],

Using the Script

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.

Optimizing the code

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.

MAXSCRIPT

tmesh = snapshotAsMesh selection[1]
out_file = createfile ((GetDir #export)+"/testmesh.dat")
format "%,%\n" tmesh.numverts tmesh.numfaces to:out_file
for v = 1 to tmesh.numverts do
format "%," (getVert tmesh v)to:out_file
format "\n" to:out_file
for f = 1 to tmesh.numfaces do
format "%," (getFace tmesh f) to:out_file
close out_file

Where to go from here

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.

Back to

"How To" Tutorials Index Page

Next

How To ... Read Geometry Data From Text File - Part One

How To ... Output Geometry Data To Text File - Part Two

How To ... Read Geometry Data From Text File - Part Two