Experience: learned about how to debug a logical error in coding with a scientific methodology, which could be a quite valuable lesson for future debugging.

1. Bug come up

The logic bug (in this example) appears when the frontend of Unity tried to parse a stl file from backend compiler, transform to mesh and show in the room scene.

The parser is originally implemented based on an existing package pb_stl with a few modification to the function "importBinary" and "importAscii", because the original functions are used to parse local stl files and in our case the stl files are acquired directly from backend compiler using web links. Therefore, the input of the two functions will be Memory Stream, instead of file name.

But after making the modification and testing on the two types of the stl files, the bug comes up:

from ASCII stl

from Binary stl

From the two images, we notice that the object mesh parsed from Binary stl looks fine while the object mesh from ASCII stl looks wrong, as if all the wooden packs become hollow and lose front faces, showing the internal zigzag structures which is supposed to be hidden as seen in from the right image.

2. Locate bug position

This process of parsing and showing object in frontend Unity scene from backend compiler is an end-to-end test, therefore, in order to locate the bug position, the end-to-end process should be broken down to smaller steps:

  • 1) The backend compiler generates a stl file (either binary or ascii) according to a given set of parameters
  • 2) The compiler passes the stl file to a weblink
  • 3) The unity script receives the stl file from the weblink
  • 4) The script parses the stl file and generates meshes
  • 5) The frontend of unity presents the meshes from scripts in the virtual scene

In simpler words, the process is: backend compiler \(\rightarrow\) unity script \(\rightarrow\) frontend renderer. So the logic bug can be in these three locations: backend compiler, unity script, frontend renderer. And some possible error reasons could be:

  • For backend compiler, the generated ascii stl file and binary stl file are different.
  • For script, the function that is used to parse ascii stl file has logical errors.
  • For frontend renderer, it is possible that the render frequency is not high enough or for some other reason to fail to show the complete object mesh.

To check whether the bug is in backend compiler, we need to check whether the generated binary stl file and ascii stl file are the same at first place. We can use the existing two stl files and convert them to the other format using online converter, so now there are four stl files for testing:

  • original ascii stl
  • original binary stl
  • ascii-from-binary stl
  • binary-from-ascii stl

When directly looking into the file metadata, the only readable files are original ascii stl and ascii-from-binary stl. A detailed introduction of stl file format and difference between ascii and binary file can be found at wiki. Basically, Ascii stil file is in the format of:

solid _name_
    facet normal $n_i, n_j, n_k$
        outer loop
            vertex $v_{1x}, v_{1y}, v_{1z}$
            vertex $v_{2x}, v_{2y}, v_{2z}$
            vertex $v_{3x}, v_{3y}, v_{3z}$
        endloop
    endface
    ... (more facets)
endsolid

The main difference from original ascii stl and ascii-from-binary stl file is that, the facets with normal (0, 0, 0) in the original ascii stl are (NaN, NaN, NaN) in ascii-from-binary stl file.

After inputing all four stl files into Unity frontend renderer, both ascii stl files (original ascii and ascii-from-binary) have the same results as upper left image, and both binary stl files (original binary and binary-from-ascii) have the same results as upper right image, suggesting that the difference in the compiler-generated file is trivial, what causes the bug is most likely how the script parses the ascii stl file.

So the bug is located to the script function "importAscii".

3. Debug script

The original imported script from pb_stl module is quite organized, with functions using switch sentence to identify each line of the Ascii stl file and save the vertex position information.

One thing that is really easily to go wrong when coding in Unity is that, the world coordinate system in Unity is different from the default 3D coordinate system.

(Image cited from aclockworkberry)

In Unity, the upwards direction is y-axis while in vertex position in ascii stl is z-axis. The original parser function already include a "UnityCoordTrafo" function for this purpose, but I'm afraid that is not the only place where the coordinate system influences the parser.

After some time of looking into scripts and ascii stl file format, with some partial tests (the idea is the same, breaking down the function and locating to more detailed bug position), the bug is finally fixed by changing the orientation of each facet. Instead of parsing three vertices in order, it should save in a counter clock-wise orientation, meaning that the order of three vertices in the facet list is (1, 3, 2). In this way, the object mesh parsed from ascii stl file would look exactly the same as binary stl file.

Conclusion

It is important to break down an end-to-end test to smaller steps to contrain the bug location to smaller and smaller range and finally debug successfully.

(Updated: 08/20)

Next Post Previous Post