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
    Code (csharp):
    1. foo[0].AddComponent(MeshCollider).sharedMesh = foo[0].GetComponent(MeshFilter).mesh;
    Best not to use strings in Get/AddComponent, BTW.

    --Eric
     
  2. BigKnockDown

    BigKnockDown

    Joined:
    Mar 23, 2013
    Posts:
    16
    Hi,
    I have a query regarding Objreader.
    Is there any way that we can download the obj files in parts but in a contentious process.
    For example We have a 6mb obj file to download, depending on the connection speed it may take some time and it will keep user waiting .So can we first download the 'mesh' only then apply material one after another. I think by doing this initial time of loading the model will reduce.
    Is it possible ? If yes How can we achieve this ?
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's what it does already, actually...it downloads the mesh first, then any textures afterwards. The process is non-blocking, so you can do other things while the mesh + textures are downloading.

    --Eric
     
  4. jackforest2012

    jackforest2012

    Joined:
    Aug 17, 2014
    Posts:
    2
    Hi, recently I want to load huge .obj files to Unity3d on the fly. The .obj file has millions of triangles in it with totally over ten million ( more than 10,000,000) lines. It is very slow to load and render in Unity3d.
    Can this plugin solve this problem? Or is there any advice?
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    While it's technically possible to load .obj files that large with ObjReader, it requires that each group in the file be no more than 65K vertices.

    --Eric
     
  6. jackforest2012

    jackforest2012

    Joined:
    Aug 17, 2014
    Posts:
    2
    I've tried the plugin with my model. It reports an error of "Out of memory":

    Code (JavaScript):
    1. OutOfMemoryException: Out of memory
    2. System.Text.StringBuilder.InternalEnsureCapacity (Int32 size) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Text/StringBuilder.cs:725)
    3. System.Text.StringBuilder.Append (System.Char[] value, Int32 startIndex, Int32 charCount) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Text/StringBuilder.cs:480)
    4. System.IO.StreamReader.ReadToEnd () (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.IO/StreamReader.cs:520)
    5. System.IO.File.ReadAllText (System.String path, System.Text.Encoding encoding) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.IO/File.cs:588)
    6. System.IO.File.ReadAllText (System.String path) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.IO/File.cs:582)
    7. ObjReader.ConvertFile (System.String objFilePath, Boolean useMtl, UnityEngine.Material standardMaterial, UnityEngine.Material transparentMaterial, .ObjData objData)
    8. ObjReader.ConvertFile (System.String objFilePath, Boolean useMtl, UnityEngine.Material standardMaterial, UnityEngine.Material transparentMaterial)
    9. Example3-ExternalFile+$Start$11+$.MoveNext () (at Assets/ObjReader/Demo Scripts/Example3-ExternalFile.js:16)
    My obj file contains more than 47,000 groups with a total of nearly 4 million triangles. Every group contains 10K vertices at most.
    It is true that my obj file is extremely huge, but I hope there is some solution.
    Thank you.
     
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Try making a 64-bit build.

    --Eric
     
  8. andrea_maticad

    andrea_maticad

    Joined:
    Aug 26, 2014
    Posts:
    4
    Hi to all,

    we purchased the plugin and we have a problem when running it under iOS: instruction 9 in

    Code (CSharp):
    1.     void Awake() {
    2.         // Only one instance of ObjReader should exist
    3.         if (FindObjectsOfType (typeof(ObjReader)).Length > 1) {
    4.             Destroy (this);
    5.             return;
    6.         }
    7.         DontDestroyOnLoad (this);
    8.         // Force "." to always be treated as a decimal, so values in .obj files are parsed correctly
    9.         System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
    10.         transform.position = Vector3.zero;
    11.         transform.rotation = Quaternion.identity;
    12.         transform.localScale = Vector3.one;
    13.     }
    gives exception

    Code (CSharp):
    1. Attempting to JIT compile method 'CultureInfo__TypeMetadata:.ctor ()' while running with --aot-only.
    I think this is because reflection is not supported under iOS.

    Any suggestion?

    Thanks,
    Andrea
     
  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Hi, it builds and runs fine on iOS here. There's no reflection involved that I know of.

    --Eric
     
  10. andrea_maticad

    andrea_maticad

    Joined:
    Aug 26, 2014
    Posts:
    4
    Hi,
    instruction

    Code (CSharp):
    1. System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
    uses reflection and always gives exception under iOS (it is catched, look at xcode output window). Next instructions

    Code (CSharp):
    1. transform.position = Vector3.zero;
    2. transform.rotation = Quaternion.identity;
    3. transform.localScale = Vector3.one;
    are never executed.

    The library should work on systems where "." is decimal separator, but may not work on systems where it is not. I think current culture shouldn't be changed, instead decimal separator should be passed in all float.Parse instructions.

    Regards,
    Andrea
     
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I see; I was running with "fast but no exceptions". I've changed that for the next version...if you want to do it now, remove that line, import the System.Globalization namespace, and change all instances of "float.Parse (*)" to "float.Parse (*, CultureInfo.InvariantCulture)".

    --Eric
     
  12. andrea_maticad

    andrea_maticad

    Joined:
    Aug 26, 2014
    Posts:
    4
    Hi Eric,
    ok, I will change all the instances of float.Parse.

    Thanks for your answer,
    Andrea
     
  13. Leo-Bounce

    Leo-Bounce

    Joined:
    Mar 2, 2011
    Posts:
    12
    Hi Eric,
    We are currently using ObjReader and experiencing some problems while importing Obj models from SketchUp.
    ObjReader can't recognise some materials and load them as Standard but other programs like 3ds max load it without problems. Can you please take a look at my example model? https://dl.dropboxusercontent.com/u/4346524/Flower_Test.zip Exported from SketchUp with triangulation.
    Also I have a question about grouping - is it possible to automatically split by 65k vertexes while grouping? This is very important for us because for the most models we can't use this feature at all. Its collapse all geometry from Obj into one mesh (no other options like group by vertex count or by Mat name etc is available).
    Thank you!!!
     
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I found the issue and released ObjReader 2.3.4. (Will upload to the asset store next.) It's not possible to automatically split groups, sorry. If you don't combine groups into submeshes, then each group will be a separate GameObject, which means that as long as each group < 65K vertices, then you can have .obj files of unlimited size. There's no real difference between using submeshes and separate objects as far as performance goes; it's mostly a matter of convenience. So if you group separate objects under an empty GameObject as a parent, then it's pretty much the same thing as using submeshes.

    --Eric
     
  15. Leo-Bounce

    Leo-Bounce

    Joined:
    Mar 2, 2011
    Posts:
    12
    Thank you very much for the fast fix - it works perfect!
    About groups - what I need is not splittings groups. Let's consider that all groups is less than 65k. We need to Combine Multiple Groups with additional options Split by 65k. So in cycle we count vertices in Current mesh + vertices in group to be added. If the sum is < 65k then Combine this Group to Current Mesh. Else add new mesh to GameObject hierarchy and Combine this group to new mesh. Count vertices in next Group and try co combine with new mesh and so on.
    So result model will be collapsed groups where each mesh is less than 65k.
     
  16. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'm not sure I understand the benefit of doing that...if you're going to end up with multiple GameObjects anyway, surely 1 GameObject per group is fine?

    --Eric
     
  17. Leo-Bounce

    Leo-Bounce

    Joined:
    Mar 2, 2011
    Posts:
    12
    Hi Eric,

    Let me show you an example:

    In this picture I imported an Obj file without combining groups. Each group here is a separate game object with a few polygons - this is very bad for memory because each Game Object in unity consume additional memory for internal purposes such as position, components etc. You will not see any difference in performance on small scene since Unity combine everything anyway with power of Static Batching but still all the memory for this objects will be wasted (batching will require additional memory for storing the combined mesh). So in huge scene we can end up with "out of memory" assert. Correct me if i'm wrong.

    Thank you!
     
  18. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Static batching can't work on dynamic objects; it can only work on objects built into Unity scenes. So there won't be any memory used by batching.

    --Eric
     
  19. servinova

    servinova

    Joined:
    Jan 7, 2013
    Posts:
    11
    Can not get the load objects from WebPlayer work in any way.

    I downloaded your ObjReaderDemo.unity3d and ObjReader.htm file from your website and I've put them on my server and yours if it works. Can you tell me where is the difference?

    I'm using to compile the version 4.5.4f1
     
  20. megisto

    megisto

    Joined:
    Dec 25, 2009
    Posts:
    127
    Hello Eric5h5,
    will your importer work with webGL?
     
  21. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I would guess it's the crossdomain.xml file. http://docs.unity3d.com/Manual/SecuritySandbox.html

    WebGL publishing isn't coming until Unity 5. There's no particular reason to think it wouldn't work, though.

    --Eric
     
  22. megisto

    megisto

    Joined:
    Dec 25, 2009
    Posts:
    127
    Thank you :)
     
  23. servinova

    servinova

    Joined:
    Jan 7, 2013
    Posts:
    11
    If the problem was not the crossdomain yours should work.

    I have created some code to download a picture from the same server and it works perfectly with www.

    If there were any problems with the crossdomain could not download an image either.

    Correct me if I'm wrong.

    I have also changed the version 4.3.4f1 and untiy to either.

    I've tried Chrome and Firefox and nothing.

    Has anyone managed to solve the problem?
     
  24. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I don't think I understand what the problem actually is...if you build the Example2-WWW file (with no modifications) as a webplayer, does it work? It's fine here.

    --Eric
     
  25. servinova

    servinova

    Joined:
    Jan 7, 2013
    Posts:
    11
    At no time have I made any changes. I built two-WebPlayer and WWW as not working.

    Com version of Unity that you have compiled your own?
    Thank you
     
  26. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It works with any version of Unity. This is a build probably from 4.3.

    --Eric
     
  27. servinova

    servinova

    Joined:
    Jan 7, 2013
    Posts:
    11
    Now it works perfectly, the problem was to include the DLL in the WebPlayer compiler. :-(

    Thanks Eric
     
  28. PranayKamat

    PranayKamat

    Joined:
    May 29, 2013
    Posts:
    6
    Hello,

    i get this message while loading a obj file

    The number of vertices in this object exceeds the maximum allowable limit of 30000
    UnityEngine.Debug:LogError(Object)
    ObjReader:CreateObjects(String&, Boolean, Dictionary`2, Material, ObjData)
    ObjReader:Convert(String&, String&, Material, Material, String, Boolean)
    ObjReader:ConvertFile(String, Boolean, Material, Material, ObjData)
    ObjReader:ConvertFile(String, Boolean, Material, Material)
    $:MoveNext() (at Assets/ObjReader/Demo Scripts/Example3-ExternalFile.js:17)

    i thought unity's limit was 65K, why would i get this message?

    thanks
     
  29. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You have the maxPoints variable set to 30000 (the default).

    --Eric
     
  30. harzo

    harzo

    Joined:
    Oct 9, 2014
    Posts:
    2
    Hello Eric,
    Seems that there is a problem with your ObjReader or maybe i need to learn sth.

    I have same issue, servinova had:
    ObjReader works in Unity but after build (webPlayer) it doesn't import an *.obj from your website. Even "Loading..." text is not appearing.

    Servinova said that he/she "included the DLL in the WebPlayer compiler" and it works but i don't know how to do that.

    I tried to build project on two computers and it is the same.

    Can you help me?
     
  31. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Actually I'm not sure what that meant; as noted in the docs, when making webplayer builds, you should use the source and not the DLL.

    --Eric
     
  32. harzo

    harzo

    Joined:
    Oct 9, 2014
    Posts:
    2
    Ok. That was my fault of course because i tried to use .dll file :)

    Thank you for your support
    and sorry for your trouble, Eric
     
  33. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It's not any trouble; that's what this topic is for. :)

    --Eric
     
  34. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Version 2.3.5 is out, to address Unity 5 compatibility.

    --Eric
     
  35. VioletteA

    VioletteA

    Joined:
    Sep 19, 2014
    Posts:
    2
    Hi Eric,

    First of all, thank you VERY MUCH for your work, it works perfectly & does exactly what i need :)
    Secondly, i was wondering if you are considering to make a DAE importer, or if you have any idea about how to build one? Can't find one working for Android...

    Thank you again,

    Violette.

    (PS: I appologize for my English)
     
  36. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Thank you! I'm sorry to say I haven't really considered making a DAE importer, since there hasn't been much demand and it looks like it would be complex to properly support.

    --Eric
     
  37. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Hi Eric
    I have just bought Object Reader.
    On the importer I have attached also a box collider and a script which rotates the object with a mouse.
    Unfortunately they do not work(they do work on normal object placed in the scene)
    Also I have noticed that the objects only displays if Override diffuse is checked.
    Can you give me some Help?
    Many thanks
    Nic
     
  38. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You would need to attach the collider and script to the object actually generated by ObjReader. (The ConvertFile functions return a GameObject[] array.) None of the demo objects require OverrideDiffuse to be checked, so I'm not really sure why that would ever be the case. All it does is override the diffuse color in the mtl file with the diffuse color of the material you supply.

    --Eric
     
  39. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    How do I do that?
    At the moment I am attaching the the collider and the script in the inspector, I am not really a programmer but with some guide I can script a bit(Javascript).
    Also my final output will be the webplayer with object retrieved from the resources folder which will reside in some server I think. Which of the 3 example should I use?
     
  40. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Example2_WWW. This also includes an example of how to reference objects returned by ConvertFileAsync, in this case the variable objData, which has a gameObject array. Specifically the FocusOnObjects function has some code that loops through all the objects that were generated by ObjReader and uses the renderer.bounds:

    Code (csharp):
    1.     for (var i = 0; i < objData.gameObjects.Length; i++) {
    2.         bounds.Encapsulate (objData.gameObjects[i].GetComponent(Renderer).bounds);
    3.     }
    So objData.gameObjects[0] refers to the first object, objData.gameObjects[1] is the second, etc.

    --Eric
     
  41. flaminghairball

    flaminghairball

    Joined:
    Jun 12, 2008
    Posts:
    868
    Clean code, nice API, does what it says on the tin.

    I ran into an issue with it (user error) and support was fast (<12 hours) and friendly. I can't recommend this highly enough if you need cross-platform runtime model importing.
     
  42. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Sorry still not sure how to attach the mouse script and the box collider to the Object generated by ObjReader, how do I get that, can I do it from the inspector? This is my scenario:

    objreader.jpg
     
  43. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You don't do it in the inspector, you do it in code, using AddComponent. The objects generated by ObjReader don't exist until after the ConvertFile function runs.

    --Eric
     
  44. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Code (JavaScript):
    1. for (var i = 0; i < objData.gameObjects.Length; i++) {
    2.         bounds.Encapsulate (objData.gameObjects[i].GetComponent(Renderer).bounds);
    3.         objData.gameObjects.AddComponent("BoxCollider");
    This tells me that AddComponent is not a UnityEngine.GameObjects[]
     
  45. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You would need to add it to each object in the array, as shown on the previous line; you can't add a component to an array. Also don't use quotes with AddComponent.

    --Eric
     
  46. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Code (JavaScript):
    1. for (var i = 0; i < objData.gameObjects.Length; i++) {
    2.         bounds.Encapsulate (objData.gameObjects[i].GetComponent(Renderer).bounds);
    3.         objData.gameObjects[0].AddComponent(BoxCollider);
    Nice! This is working!!! Thanks a lot Eric!

    Sorry but could I just ask you how can I scale the collider to the size to of the imported object?
    or why can't I do this which is using the box collider from the inspector?
    Code (JavaScript):
    1. for (var i = 0; i < objData.gameObjects.Length; i++) {
    2.         bounds.Encapsulate (objData.gameObjects[i].GetComponent(Renderer).bounds);
    3.         var bc = gameObject.GetComponent(BoxCollider);
    4.         objData.gameObjects[0].AddComponent(bc);
     
    Last edited: Nov 6, 2014
  47. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Unity automatically scales the box collider to the bounds of the mesh when it's first added, so you don't actually have to do anything.

    --Eric
     
  48. karthees

    karthees

    Joined:
    Oct 15, 2013
    Posts:
    13
    Hi,

    I'm getting .mtl not found error and the loading stoping in 50%.
     
  49. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Ok thanks I understand, but sorry for being so pedantic, why can I not pass a variable for my BoxCollider? woud be nice to have extra control with components added in the inspector, if one wanted to.
    or simplier like this maybe?
    Code (JavaScript):
    1. objData.gameObjects[0].AddComponent(gameObject.GetComponent(BoxCollider));
     
    Last edited: Nov 6, 2014
  50. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    AddComponent already returns the component; you don't need GetComponent.

    @karthees: I would guess the .obj file specifies a .mtl file, which you don't have. You can remove the line referencing the .mtl file, or else put the .mtl file in the proper location.

    --Eric