10
$\begingroup$

Suppose we have a MeshRegion that we want to export to an obj file with, say double precision. Is that possible with Export? And how would we do that? The documentation on "OBJ" does not list any options. I am asking explicitly about Export. Of course, I could write my own OBJ exporter, but this would be somewhat awkward. (I've actually done it already.)

The default seems to export only about 6 decimal digits as the following example is supposed to show:

R = MeshRegion[
   {{0., 0., 0.}, {Sqrt[2.], 0., 0.}, {0., Sqrt[2.], 0.}},
   Triangle[{{1, 2, 3}}]
   ];
file = FileNameJoin[{$TemporaryDirectory, "a.obj"}];
Export[file, R];
MeshCoordinates[Import[file]] - MeshCoordinates[R]

{{0., 0., 0.}, {-3.60048*10^-6, 0., 0.}, {0., -3.60048*10^-6, 0.}}

$\endgroup$
0

1 Answer 1

8
$\begingroup$

Don't have the time to fully answer this yet, but here's a debug tool I developed previously. First off we can figure out how OBJ is exported

getFormatExportData["OBJ"]

{"FormatName" -> "OBJ", "DefaultElement" -> "Graphics3D", 
 "DocumentedElements" -> None, "Function" -> System`Convert`OBJDump`ExportOBJ, 
 "FunctionChannels" -> {"Streams"}, "HiddenElements" -> None, 
 "Options" -> {"InvertNormals", "VerticalAxis", "Comments"}, 
 "Sources" -> \
{"/Applications/Mathematica.app/Contents/SystemFiles/Kernel/SystemResources/\
MacOSX-x86-64/Convert/Common3D.mx", 
   "/Applications/Mathematica.app/Contents/SystemFiles/Kernel/SystemResources/\
MacOSX-x86-64/Convert/OBJ.mx"}, "BinaryFormat" -> True, 
 "File" -> "/Applications/Mathematica.app/Contents/SystemFiles/Formats/OBJ/\
Export.m"}

Then we get the defs for that func (you may need to load the .mx first)

System`Convert`OBJDump`ExportOBJ // GeneralUtilities`PrintDefinitionsLocal

ExportOBJ[strm_, expr_, opts___] := Block[
    {res, nopts, method, a, expr1, obj},
    nopts = Flatten @ {opts};
    method = ("ImportExportMethod" /. nopts) /. {"ImportExportMethod" -> $ImportExportMethod};
nopts = DeleteCases[nopts, "ImportExportMethod" -> _];
a = Flatten[expr /. {RuleDelayed -> List}];
nopts = Union @ Flatten @ Join[nopts, Most @ a];
nopts = Select[nopts, Function[Equal[Head @ #, Rule]]];
obj = Last @ a;
expr1 = "Graphics3D" -> obj;
res = dispatchExportOBJ[method, strm, expr1, nopts];
res /; UnsameQ[res, $Failed]
];

Which means it's handled by dispatchExportOBJ and so looking at those defs we get back to either System`Convert`OBJDump`LegacyExportOBJ or System`Convert`OBJDump`ImprovedLgacyExportOBJ, the latter of which seems to delegate to GeometryTools`WGTAssimpExport and the former of which is just a bunch of WriteString calls which could be modified to have higher precision.

Can't get you to a full solution at this point in time though.

$\endgroup$
1
  • $\begingroup$ Thank you so much! I did mean you to dig that deeply into the internals, but I learned a lot from this. Apparently, there is no easy way to specify precision other than overwriting the library function pointed onto by GeometryTools`GeometryToolsDump`iWGTAssimpExport. But then it is easier for me use my customized library functions anyways. Anyways, thank you for looking into this. have my accept! $\endgroup$ Mar 20, 2021 at 11:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.