Create program to translate wavefront .obj files into a form that our parser handles well
bradley-mcfadden opened this issue · 1 comments
Introduction
Currently, our WavefrontParser runs into a lot of problems. It cannot handle multiple objects in a file, or mutiple usemtl statements with the same material. Rather than fix the parser, it seems to make more sense to write a separate program that can produce new files that our parser understands better.
Requirements
Output files need the following characteristics:
- Only one object definition line per file.
- All vertex definitions appear consecutively.
- All vertex normal definitions appear consecutively.
- All vertex texture definitions appear consecutively.
- usemtl statements should only appear once per each unique material.
- Only one mtllib statement (and file!) per object file.
How to implement
- After each object definitions comes vertices, normals, then texture coordinates. Next comes a long list of face indices. For the first object, nothing needs to change here. For each new object, the vertices, normals, and texture coordinates should be appended to these respective lists for the first object. Keep track of the number of vertices/normals/textures in the previous object while doing this. Then, the faces for the new object need to be append to the list of faces for the new object. But the indices for each face needs to be adjusted by the offset.
- Pretty easy. Do a pass through the file, and track all vertices in some list. Print the whole list in one section afterward.
- Same as 2
- Same as 3
- Do a pass through the faces section for each object. When coming across a usemtl statement, create a list pointed to by the name of the material. Append faces to this list. Afterward, for the faces section, output the key of each list, then its faces.
- Inspect the format of .mtl files, and merge the two files into a single file containing all the map_Kd lines that point to the appropriate files for each material.
Format of the files
Rough format of a wavefront file is like this:
o Engineer mtllib engineer.mtl v 0.1 3.2 0.5 ... vn 0.1 0.2 0.3 ... vt 0.1 1.0 0.0 usemtl Material__10 f 1/2/1 2/3/1 1/2/3 ... usemtl Material__11 f 1/2/1 2/3/1 3/3/1 ... usemtl Material__10 f 1/2/3 1/4/1 5/1/5 ... usemtl Material__11 f 1/1/2 5/2/1 6/51 ... o Engineer_Wrench mtllib wrench.mtl ...
There are other line headers in these files like g, s, and l, but I only listed the ones that we consider. For this issue, you only need to worry about changing lines starting with f, usemtl, o.
That's probably oversimplifying things. The biggest pain would be multiple objects, so I recommend avoiding that if possible, since you need to modify the indices for a bunch of faces. If you'd only like to implement 5, that's fine, you just need a HashMap and a list of strings holding the line of text for each face of that material, and 1) can be done fairly quickly with some manual effort in Blender.
Helpful information on Wavefront files:
https://en.wikipedia.org/wiki/Wavefront_.obj_file
Update on this - I made a python script that addresses 5). It will be pushed later. It may not be worth the effort to do the rest of the points, as that can be done with a small amount of manual effort in Blender.