Robmaister / SharpNav

Advanced Pathfinding for C#
sharpnav.com
Other
537 stars 128 forks source link

.Obj exported from Unity3D causes System.IndexOutOfRangeException #68

Open Mirazes opened 7 years ago

Mirazes commented 7 years ago

@Robmaister When i start example from repo to load .obj and generate navmesh i get IndexOutOfRangeException on file ObjModel.cs line 88: if (!int.TryParse(line[1].Split('/')[2], out n0)) continue;

I'm using obj exporter from http://wiki.unity3d.com/index.php?title=TerrainObjExporter I can open .obj file generated by exporter inside blender and 3D builder so the format should not be a problem here.

StackTrace

   target SharpNav.Examples.ObjModel..ctor(String path) 
file SharpNav.Examples\ObjModel.cs:rivillä 88

   target SharpNav.Examples.ExampleWindow.LoadLevel() 
file SharpNav.Examples\ExampleWindow.Drawing.cs:rivillä 124

   target SharpNav.Examples.ExampleWindow.OnLoad(EventArgs e) file SharpNav.Examples\ExampleWindow.cs:rivillä 129

   target OpenTK.GameWindow.Run(Double updates_per_second, Double frames_per_second)
   target SharpNav.Examples.Program.Main(String[] args) file 
SharpNav.Examples\Program.cs:rivillä 16
Mirazes commented 7 years ago

I think i have figured out whats the problem here.. exported terrain from unity doesn't have a normal map and that causes ObjModel.cs to crash. I removed normal map from generation and example seems to work now. Also the main error which are pointed on my first message was nasty format error on my exporter.

Robmaister commented 7 years ago

Yeah, the ObjModel class is a bit fragile as it's meant to be part of the example and not a core part of the library.

Mirazes commented 7 years ago

Well i modified ObjModel a bit and i have working project now. You should check out some generic obj reader/writer and implement it to sharpnav as it would boost usage of this project alot.

Robmaister commented 7 years ago

I haven't looked recently, but yes, a model loading library to be used alongside SharpNav would make life a lot easier for people. The SharpNav interface just takes raw geometry, so anything that can put out triangles should work fine.

I would rather not bring on a ton of dependencies to the core of SharpNav for people who don't need model loading (already handled in-engine, or the geometry is generated), and the interfaces are easily separable.

If I had the time or energy, I would start a separate open-source project like this that exclusively did model loading, as that would be useful in a number of places.

Deepankar1993 commented 7 years ago

Are there any solution or workaround for this? I am also getting the same issue using TerrainObjExporter

for me it somewhat seems work by changing

                                if (!int.TryParse(line[1].Split('/')[2], out n0)) continue;
                                if (!int.TryParse(line[2].Split('/')[2], out n1)) continue;
                                if (!int.TryParse(line[3].Split('/')[2], out n2)) continue;

to

                                if (!int.TryParse(line[1].Split('/')[1], out n0)) continue;
                                if (!int.TryParse(line[2].Split('/')[1], out n1)) continue;
                                if (!int.TryParse(line[3].Split('/')[1], out n2)) continue;

and commenting out

                                norms.Add(tempNorms[n0]);
                                norms.Add(tempNorms[n1]);
                                norms.Add(tempNorms[n2]);

Are there any other way

Robmaister commented 7 years ago

Well with some effort I can generalize ObjLoader to accept models without normals, but do note that SharpNav.Examples is designed to help understand how SharpNav works, not as a tool that should be used in production.

If there were a library that loaded 3d model files into float[] or equivalent, I would just switch to using that instead. If I get a chance I'll generalize this since multiple people have run into the issue, though

Deepankar1993 commented 7 years ago

Can you give some info like how did you make your obj for the example ? and while comparing the difference on the obj files with the test obj file 1st difference I noticed is Orginal obj
f 4/1/4 2/2/2 1/3/1 3/4/3

Unity's generated f 66/66 67/67 2/2

what data the extra value in the originals obj file holds?

Deepankar1993 commented 7 years ago

I believe that extra value has something to do with normals but I got it working with no changes to the code Steps :

  1. TerrainObjExporter to get the Obj file of the Terrian from Unity (Name it anything you want ie : unityterrian.obj)
  2. Open Blender Go to File>Import > Select Wavefront(.obj)
  3. Now go to the folder where you saved "unityterrian.obj" and select it and Click "Export OBJ" Once your model open
  4. This time go to File>Export > Select Wavefront(.obj)
  5. Go to the folder you wanna save and Give it a name (ie :: "Nunityterrian.obj") Done Nunityterrian.obj will work fine with example

Note : As @Robmaister said Example is not intended for Production use

Robmaister commented 7 years ago

The obj file format supports a few ways of binding faces to vertices: https://en.wikipedia.org/wiki/Wavefront_.obj_file#Face_Elements

For simplicity (and since I need normals to draw the mesh with lighting properly) I only supported the last two formats, that is, I'm assuming there will always be two / characters per vertex in a face. Not all files are like this, some can have 0 or 1. (position only, or position + texcoord)

In the case of TerrainObjExport, it was not exporting normals at all - only positions and texcoords. By running it through Blender, you have Blender calculate and export normals with the obj file.