Search Unity

ObjReader - load .obj files at runtime

Discussion in 'Assets and Asset Store' started by Eric5h5, May 7, 2013.

  1. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Still not really understanding I guess...you're talking about not directly using Unity, but also about entering and exiting play mode, which requires directly using Unity. So if you're using Unity, then just import models directly in the editor; there's no need for ObjReader in this case. if you're not using the editor, then you can use ObjReader for importing models at runtime and a different asset for exporting .obj files (and then loading them again as needed with ObjReader).

    --Eric
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You're going to have to import every time regardless. You could re-save the imported .obj files using a custom binary format which would be faster to re-import, but it's not possible to save imported files "into" a Unity app if that's what you're talking about.

    --Eric
     
  3. Sylvie_Spaces

    Sylvie_Spaces

    Joined:
    Jun 1, 2017
    Posts:
    3
    Hi,

    I am getting an error when I try and import my obj from disk at runtime:
    Unity Editor can import and display the mesh without issue. Any ideas? Mesh has been generated by Meshlab and has normals.

    e: I notice that the examples all use .obj in the form of txt files, but mine is just a .obj, could this be the problem?
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    There can only be 3 elements per vertex (x/y/z). For some reason there are 6 in your file. Normals are separate so I don't know what the repeated ".752941" is supposed to be, but it's not part of the .obj spec and should be removed. (Obj files are always text files, regardless of extension, which doesn't matter.)

    --Eric
     
  5. Sylvie_Spaces

    Sylvie_Spaces

    Joined:
    Jun 1, 2017
    Posts:
    3
    Yea, I figured this out. I was encoding extra information when I exported from MeshLab, and I stripped some of it out and now I have 3 vertices per row. Thanks!
     
  6. BlakeSchreurs

    BlakeSchreurs

    Joined:
    Aug 10, 2016
    Posts:
    51
    I've just converted my project to 2017.01, and it seems to break ObjReader. Am I alone?
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    No, there was a change in Unity where checking for www.error == null doesn't work like it used to. You can fix it in the ObjReader.cs source by changing all three instances of "if (www.error != null)" to "if (!string.IsNullOrEmpty(www.error))" instead.

    --Eric
     
  8. mrvv

    mrvv

    Joined:
    May 2, 2016
    Posts:
    5
    hi!
    im trying to load an obj with MTL and texture folder like so:

    var pathOnDevice = Application.persistentDataPath;
    var objFileName = pathOnDevice + "/asdgadsg.obj";
    var nuobj = ObjReader.use.ConvertFile (objFileName, true, standardMaterial, transparentMaterial);

    i attached the files here.
    when i load it with useMtl set to false it works fine.(so the paths are working. i have the texture folder obj and mtl next to each other in the dir)
    but when i set useMtl true it never shows anything.
    why is that? i also don't get any errors in the console.

    is my mtl not compatible?

    when i import it to assets via unity editor it works fine with textures and everything : /
    i must be missing something small... but what ?
     

    Attached Files:

  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Actually it prints an error message about a texture not being found. This is due to the MTL file using "\" instead of "/" as a path character. I had a check for that for the obj file path, but neglected to do it for image file paths. I made a fix for the next version, but in the meantime replacing the path characters in the MTL file makes it work.

    --Eric
     
    mrvv likes this.
  10. mrvv

    mrvv

    Joined:
    May 2, 2016
    Posts:
    5
    woa thanks for the fast reply. sorry i just spammed you with an email as well.
    i will try this right now!

    thanks! this workaround works :)
     
    Last edited: Aug 16, 2017
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    ObjReader 2.6 is out, and submitted to the asset store:

    Fixes:
    • Loading from WWW works with Unity 2017.
    • Fixed image paths that contain "\" as a path character instead of "/".

    --Eric
     
  12. Titos

    Titos

    Joined:
    Jul 26, 2012
    Posts:
    12
    Eric, are you intending to put yields in so that object do not freeze the system while loading?
     
  13. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    No; it's not the sort of thing that can be effectively made into a coroutine. Multi-threading is a possibility, but currently lack of support on certain platforms (namely WebGL) makes that not appealing.

    --Eric
     
  14. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Hi Eric,

    I heavily use OBJReader in my mobile app to load (and unload) 3D-Objects at runtime.
    But after destroying these GameObjects and using Ressources.UnloadunusedAssets() the memory is not really cleaned.

    How can I clean my memory from objects that have been imported at runtime?
     
  15. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    ObjReader does nothing special; just standard Unity GameObjects and meshes. Anything memory-related that works for Unity automatically works for ObjReader. Maybe your code still has references to the objects or something?

    --Eric
     
  16. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Hi Eric,

    I am pretty sure that I don´t have any references left.
    Unfortunately I´m no expert on this, but is it possible that your variables

    var objData = new ObjData();
    string objFile = "";
    ...

    produce permanent heap allocation especially when calling objreader.cs multiple times?

    Wouldn´t it make sense to declare them in public variables and use them cached as decribed here?
    Please have a close look at "Strings/StringBuilderClass" - thank you!
     
    Last edited: Sep 1, 2017
  17. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It wouldn't make any sense for them to be public variables, no. There's no chance at all that strings have anything to do with it, since those are garbage collected by the Mono GC when appropriate and are completely separate from Unity's objects (GameObject etc.).

    --Eric
     
  18. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I should say that I don't see any memory issues here. Say I have an empty scene, load an object with a texture, then destroy it. Before:

    obm1.png

    When object is loaded and on-screen:

    obm2.png

    After destroying object:

    obm3.png

    --Eric
     
  19. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Hi Eric,

    thank you very much for looking into it.
    The thing is, that my profiler shows the same results as yours (output before loading and after deleting obj-data is the same), but XCode reports completely different results: Hughe amount of data left after obj is deleted. Unfortunately XCode rules here.
    What other variables are there that might better be cached as public ones?
     
  20. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    There aren't any variables that should be public, and that has no effect on memory usage in any case. I can't really help with XCode; I have to go by what Unity says, since that's the only thing I have any control over at all. I can fix memory problems that show up in the profiler, but if there are differences in behavior between Unity apps on different platforms, that's something that Unity needs to address.

    --Eric
     
  21. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Ok, after some days of research I found out that strings generated at runtime are my problem:
    I wrote a very basic code that simply reads text from file into a string.
    Setting this string to null or "" and reading from file again successively kills memory.
    This is not covered by the Unity profiler, you only see it in XCode.

    Optimizing-garbage-collection-unity-games

    Unity-webgl-memory-the-unity-heap

    Since objreader heavily generates strings, my question is:

    Whats your way to prevent memory to fill up from repetitively unloading/loading obj data with objreader?
     
    Last edited: Sep 5, 2017
  22. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It doesn't happen in Unity in general, so you'd have to send a bug report to Unity about how GC is apparently not working on iOS.

    --Eric
     
  23. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Meanwhile I was able to find the reason for my memory issue and to change the objreader so the problem is completely gone.

    In the beginning ObjReader.cs reads the obj-file into memory as one large string.
    Then this string ("objFile) is passed through the script to process materials, meshes and textures.
    This string can get too large to be removed from memory by GarbageCollector and stays in memory.
    (For anyone who is interested in further informatiion about this, please read the link from Dustin-Horne here.)

    I changed the script so I do not read the file as one big part but line by line (when a line is needed) with streamreader.
    I don´t pass the obj-string from method to method but only the path to the file.

    @Eric5h5
    I would appreciate that you do this very easy change to your script so that everyone can benefit from it, especially user that deploy for mobile. Thank you!
     
    Last edited: Sep 9, 2017
  24. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The problem is I need to use WWW.text for downloading, and can't use StreamReader for that, so it's not usable for a general case.

    --Eric
     
  25. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    I see, what about downloading the obj-file to PersistantData-Folder or StreamingAssets-Folder with www before and then use Streamreader?
    So do I and it works across all platforms.
     
  26. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    In that case you'd have the large string in memory anyway when you download it, so it seems you're back to the original problem.

    --Eric
     
  27. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    I assume that File.WriteAllBytes (targetpath, www.bytes) puts it onto disk not into memory.
    At least memory keeps clean.
     
    Last edited: Sep 12, 2017
  28. j835111

    j835111

    Joined:
    Sep 18, 2017
    Posts:
    3
    Hello,this is a great asset.But I have a problem.When I used spot in the sample files.The model has not texture.How did I set the texture in the MTL files?
     

    Attached Files:

  29. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Your images didn't work, but if I run the Example2-WWW demo, Spot loads fine including textures.

    Screen Shot 2017-09-17 at 10.22.51 PM.png

    --Eric
     
  30. j835111

    j835111

    Joined:
    Sep 18, 2017
    Posts:
    3
    What do you mean images didn't work ? And how to fix it?I run the Example2-WWW demo,it also work.Did Example2-WWW load MTL files?
    How can I generate a model from local with right texture?
     
  31. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    When you posted, the images weren't showing up, but they're fixed now. I assume you're using Example 1, which uses Unity TextAsset project files. Those are entirely text-based, so there's no possibility of using textures in that case. I expect you meant to use Example 3, which loads local files, including textures.

    --Eric
     
  32. j835111

    j835111

    Joined:
    Sep 18, 2017
    Posts:
    3
    It's work! Thanks a lot!
     
  33. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Hi Eric,

    with Unity 2017.1.1 we can now catch if our apps recieve memory warnings:
    https://docs.unity3d.com/ScriptReference/Application-lowMemory.html

    Your Objreader.cs has a method called ObjData.Cancel() which seems the right way for cancelling the import process when a memory warning was recieved.
    At least it works for the async method GetTexturesAsync().

    But when my obj-file consists of thousands/millions of vertices with no textures at all, I assume I have to cancel while generating the meshes (class CreateObjects)? Is this possible?
     
    Last edited: Sep 21, 2017
  34. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It's not possible, unless you want to edit the source code. However I doubt it's really feasible anyway, but is something you'd do after the mesh is generated.

    --Eric
     
  35. odinrossi

    odinrossi

    Joined:
    Oct 5, 2015
    Posts:
    6
    This is not working on webgl.
    I'm not using dll version. Using a source ObjReader.cs.


    Code (CSharp):
    1.     if (www.error != null) {
    2.             Debug.LogError ("Error loading " + objFilePath + ": " + www.error);
    3.             objData.SetDone();
    4.             yield break;
    5.         }
    line 851 in ObjReader.cs.


    Thanks.
     
  36. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Please update to the latest version of ObjReader.

    --Eric
     
  37. odinrossi

    odinrossi

    Joined:
    Oct 5, 2015
    Posts:
    6
    It's already latest version of ObjReader.

    So i'm using ObjReader.use, same method like from dll.

    Is that ok?
     
  38. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Sorry, looks like the source on the asset store version is version 2.5, not 2.6. I'll take care of that, but in the meantime, you can fix the issue by doing this.

    --Eric
     
  39. odinrossi

    odinrossi

    Joined:
    Oct 5, 2015
    Posts:
    6
    I have changed as you told, and before you suggestion and still go this error :


    https://ibb.co/jDjkqb

    What to do?

    Thanx.
     
  40. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    What version of Unity are you using? I tried a ObjReader 2.6 WebGL build with Unity 2017.1 and it works without any errors.

    --Eric
     
  41. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Also the correct source is now on the store. (Yes, already...Friday afternoon "whatever just approve everything YOLO LOL let's go home!" frenzy perhaps? Not that I'm complaining. ;) )

    --Eric
     
  42. Daft_Hunk

    Daft_Hunk

    Joined:
    Nov 15, 2016
    Posts:
    15
    Hello ! I just bought your plugin in order to change from OBJ Import I was using.
    But I'm facing the same problem, do you have any clue on this ?

    Left is imported with your plugin and right in the editor :

    (I'm using the WWW async function as my models are on the disk and my call in a coroutine)

    And also why there is more meshes with plugin ?
     
  43. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Hi, looks like either the surface normal for that polygon is flipped, or possibly you're using ngons, which aren't supported (check the warnings). That can be fixed in the model. ObjReader creates a mesh for each group, unless you use CombineMultipleGroups.

    --Eric
     
  44. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Hello Eric,

    I have a problem with a simple cube modelled in 3dsmax and imported with objreader.
    In this picture you can see the same cube

    - imported with unity (TOP)
    - imported with objreader (Middle) ("use supplied normals" disabled)
    - imported with objreader (Bottom) ("use supplied normals" enabled)



    I tried with all kind of combinations of your parameters ("use supplied normals", "compute tangents") and 3dsmax parameters, but the mesh never renders as clean as the native imported one.

    Do you have an idea?
     
  45. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Doesn't look like a problem with normals; is it UV mapped? You could also post the .obj file here.

    --Eric
     
  46. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Here´s the cube (yes I also tried with cubic uvw map)
     
  47. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Any news on that?
     
  48. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Weird, I posted a reply but there's no sign of it. Anyway, the cube only has 8 verts, which makes correct normals impossible. A cube should have 24 verts; ObjReader doesn't do any auto-splitting.

    --Eric
     
  49. Kubic75

    Kubic75

    Joined:
    Jan 2, 2017
    Posts:
    83
    Hmm I see, I really would like to see auto-splitting as a part of objreader since the content creators of the obj data mostly don´t know about vertexsplitting when building the model or downloading from any source, right?
     
  50. mannan_suzukake

    mannan_suzukake

    Joined:
    Oct 27, 2017
    Posts:
    1
    Hi.

    I want to make the downloaded object from url child of the existing object automatically.

    I'm trying to make it come true by using "Instantiate" but Unity tells me
    "Cannot implicitly convert type `UnityEngine.GameObject' to `ObjReader.ObjData".

    How can I make it come true? Do you have any idea?