kctess5 / voxelizer

A simple mesh voxelizer, GPU accelerated with CUDA
MIT License
86 stars 12 forks source link

obj output doesn't seem to work #1

Closed mwlow closed 8 years ago

mwlow commented 8 years ago

The voxelizer seems to work on the provided meshes, but on all the other meshes I've tried, obj export results in "#end" written to file and nothing else. Binvox export may or may not work--the output files are of reasonable size, but I haven't tried to parse and verify their contents.

Here's one of the models for which this problem occurs: model_000003.obj.zip

kctess5 commented 8 years ago

Thanks for the note - I opened your model in meshlab and there's something wrong with it. I suspect that this is causing the problems. If you try out one of the meshes in the /data folder it should work.

airplane00

This algorithm relies on even/odd numbers of collisions between the mesh and rays cast from each discretized point in space. If the mesh has a problem such that every ray returns an even number of intersections, then it will result in the behavior you mention. If you're unable to use another mesh for some reason, you might be able to repair the one you have with meshlab or another mesh editing program.

The binvox file does work, but the output is basically garbage. I recommend trying out viewvox for viewing binvox files.

I can triage this a bit more if you can't get it working.

mwlow commented 8 years ago

Ah, that is very helpful, thanks. I needed a voxelizer for a project so, after I couldn't get yours to work, I wrote my own as a quick hack--did it in the same way, but without CUDA. I noticed that the number of intersections between any ray and the mesh was always even. With the meshes that I'm processing (ShapeNet), it seems to be a pretty common issue.

It would be nice to have an algorithm that could work on any mesh, but perhaps that's out of scope. What I ended up doing was shooting a bunch of rays and checking whether any of them had 0 intersections. Super inefficient, there's probably a better approach.

kctess5 commented 8 years ago

If the mesh is always returning an even number of intersections because the mesh is double thick, then you should use (num_intersections/2)%2 in place of num_intersections%2 to determine occupancy. This should be more efficient and correct. I did it real quick and implemented a command line flag to specify a double thick mesh (-d). I pushed the changes. Seems to work ok, given enough samples - that mesh isn't entirely double thick. I've attached the .binvox file that I was able to generate with the following command (~100 seconds on the GTX970):

./bin/voxelizer -v ./model_000003.obj ./airplane -s 15 -r 128 -d

airplane.binvox.zip

There's a bit of messiness because it's not entirely double thick, but it could be cleaned up by hand or processed with a 3d median filter if necessary.

I think it makes semantic sense that the double thick mesh would be processed incorrectly without the -d flag, because in some sense the only part that is "inside" the mesh is the very small (or non-existent) region between the meshes. The internal cavity is in enclosed by the mesh, but not necessarily inside it.

I'm not sure if this would help, but there's another algorithm based off of the winding numbers. Martin Bisson seems to have done some excellent work on the subject: https://vimeo.com/72468198

mwlow commented 8 years ago

Hmm. The thing that concerns me about (num_intersections/2)%2 is that it seems to work on only a very limit subset of meshes--you have to know whether the mesh is double thick beforehand, which is not possible in my case as I'm running it on 40k+ meshes. However, I do agree with your sentiment about semantics. It's not immediately clear whether you want the shell or the volume contained within the shell, so output behavior is undefined. In my case I was looking for a set of points completely enclosed by any shell.

Thanks for taking the time to look into this!