Search Unity

ObjReader - load .obj files at runtime

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

  1. Deleted User

    Deleted User

    Guest

    Good afternoon Eric,

    I am having problems when using your examples (WWWExample) on an Android device.
    It can import .obj files from external sources (http://...), but not from the device it self.
    I have tried to import this asset from the project directory in Android ("jar:file:// + Application.persistentDataPath + /name.obj), but neither it does work (I have already access a sqlite database this way).

    What could the problem be?

    Thank you,
    Inigo
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I believe you need to manage permissions for Android apps; this topic might help.

    --Eric
     
  3. adityasankar

    adityasankar

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

    Quick question for you:
    I'm trying to load the following OBJ file: http://keech.cs.washington.edu:8000/03001627/db549976c0b7b960d42ec7e303174a87/model.obj

    Unfortunately, when it loads, I'm seeing a strange artifact (attached), as if the per-vertex diffuse colors are being set incorrectly -- at least that's my guess.

    The OBJ seems fine, as it loads properly in MeshLab, other 3rd party OBJ Loaders for Unity. In fact, when I load it as an asset into a unity project, it seems fine too! However, it may be possible the OBJ format is not compatible with your plugin.

    Any suggestions on what may be causing this? I intend to look into the source code, but figured I'd ask you first.

    Thanks in advance for your support -- and for creating this awesome plugin! Cheers.
     

    Attached Files:

  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Actually the normals in the file seem to be messed up, as seen in Blender:

    Screen Shot 2016-06-30 at 11.21.06 PM.png

    If they're recalculated and the file re-exported, the object looks fine.

    --Eric
     
  5. UDN_acb614e6-1e88-4c62-a5cc-19a29763e234

    UDN_acb614e6-1e88-4c62-a5cc-19a29763e234

    Joined:
    Aug 3, 2016
    Posts:
    1
    Hi Eric,

    i just bought your ObjReader,
    Now i have a problem with my models, some have more then 4 points under a face like:

    f 11/94/11 64/87/64 63/67/63 19/56/19 23/58/23 20/57/20 12/95/12

    your code just drop these and some parts of my model are missing.
    Is there a way to implement something, so these parts are also in my model?
    Or do i have to recalculate them?
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Models should be made from triangles or quads; n-gons aren't supported, and ObjReader prints a warning about what's happening. You can use an app like Blender to triangulate faces, then re-export.

    --Eric
     
  7. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    Little problem with transparency:

    Objects in 3dsmax having alpha = 0.75
    Objects from Obj reader in unity having alpha = 0.25 (= 1 - alpha)
    The reason can be read here.

    So my Objects *.mtl has:

    newmtl Knot
    Ns 10.0000
    Ni 1.5000
    d 0.2500
    Tr 0.7500
    Tf 0.2500 0.2500 0.2500
    illum 2
    Ka 0.0000 0.0000 0.0000
    Kd 0.5882 0.5882 0.5882
    Ks 0.0000 0.0000 0.0000
    Ke 0.0000 0.0000 0.0000
    map_Ka textures\ground010.jpg
    map_Kd textures\ground010.jpg

    As it looks, your reader takes "Tr" instead of "d".

    Could you offer a switch for selecting "d" vs "Tr"?
     
    Last edited: Oct 22, 2016
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    In the ParseMTL function, after dVal is assigned, add this:

    Code (csharp):
    1. if (lineStart == "tr") {
    2.     dVal = 1.0f - dVal;
    3. }
    --Eric
     
  9. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    I deleted the dll, imported theObjReader.cs and added those lines.
    It works in Editor, but how to get it running on Android/iOS?
     
    Last edited: Oct 23, 2016
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It works as-is on iOS and Android; there's no platform-specific code. The dll and source code are identical.

    --Eric
     
  11. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    Right, it seems I have a differnt issue.
    The project that worked yesterday, doesn´t work today an Android anymore.
    Maybe I have problems using persistant datapath....

    The obj comes from inside a zipfile that gets downloaded and unzipped to persistant datapath right now.
    Maybe I have to clean Cache and stuff before?
     
    Last edited: Oct 23, 2016
  12. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    On Android you might have to mess with the manifest file.

    --Eric
     
  13. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    Ok, could you give me a hint how to do that?

    (The interesting part is, that my project with ObjReader worked on Friday on Android, iOS and WebGL.
    Since yesterday I don´t get it running on Android and WebGL (iOS not tested yet), using exactly the same project...)
     
    Last edited: Oct 24, 2016
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Probably something else then, since that wouldn't have anything to do with WebGL. I'd recommend reverting the project to a working state and proceeding from there.

    --Eric
     
  15. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    Besides this:
    I opened a new empty project in Unity, imported your package.
    Importing file (pig, car ) in Editor works, but also not on Android.
    Also tried another phone. Its so strange!
     
  16. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I've been told by other ObjReader users that editing the Android manifest works, but I haven't done that myself, so unfortunately I can't offer more specific advice.

    --Eric
     
  17. wxxhrt

    wxxhrt

    Joined:
    Mar 18, 2014
    Posts:
    163
    Hi Eric,

    This looks perfect for a project I'm planning, can you tell me if it's possible to scan the contents of a directory and import any obj's that gets added to it?

    Thanks
    Will
     
  18. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's definitely possible, although you'd need to do the scanning directory part yourself using the System.IO classes. Then you would use the appropriate path(s) that you get with ObjReader.

    --Eric
     
  19. damro

    damro

    Joined:
    Nov 20, 2016
    Posts:
    4
    @Eric5h5 What is the conversion between Ks, Ka, Kd, Ns and the respective Unity parameters you use for the .mtl file? My imported materials look overly dull after import...
     
  20. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Ka values are set to the material shader's _Emission property, Kd sets _Color, Ks sets _SpecColor, and Ns sets _Shininess. If the appropriate shader properties aren't present, then the values don't get set. It does occur to me that the standard shader uses different property names, so I should add code to check for those too. In the meantime, you'd need to stick with legacy shaders such as Legacy/Specular.

    --Eric
     
  21. damro

    damro

    Joined:
    Nov 20, 2016
    Posts:
    4
    @Eric5h5 But do you convert them 1:1? I mean Ka, Ks, Kd do have a range from 0 to 1 and Ns has a range from 0 to 1000. Whereas I think _Color, _SpecColor and _Emission range from 0 to 255, and _Shininess ranges from 0 to 1. That means do you multiply it just by 255 or divide it by 1000 respectively? I thought the reason that the materials look not shiny enough was because of a conversion error. So I just wanted to understand how those properties are converted? I mean shouldn't it be a non-linear conversion?
     
  22. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    No, _Color etc. are float4s and the range is 0 to 1. There's no conversion; the values are applied as-is. (Aside from Ns, where the range is 0 to 1000, so it's divided by 1000 since _Shininess is 0 to 1.)

    --Eric
     
  23. damro

    damro

    Joined:
    Nov 20, 2016
    Posts:
    4
    Ok thanks... I wonder what the conversion to Unity's standard shaders is then to make it look more shiny and vibrant. The 1:1 conversion really washs out all the colors of the materials...
     
    Last edited: Nov 21, 2016
  24. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It might just be your lighting; in my tests the results were as expected.

    --Eric
     
  25. damro

    damro

    Joined:
    Nov 20, 2016
    Posts:
    4
    Or my .mtl files. I got them from a different vendor and it seems like they exported it differently and now I have to readjust all specular Colors and the shininess because all materials look washed out.
     
  26. roboman5000

    roboman5000

    Joined:
    Sep 27, 2016
    Posts:
    19
    Hi Eric -

    First of all, wanted to thank you for some of the great tools you've created. Appreciate your work + the support you give your users.

    Anyway, I'm running into some CPU spikes - normally these wouldn't be issues but in VR it causes it to kick into "non-vomit-inducing mode" and fades in and out of a different scene.

    My question is: is there a way I might be able to throttle CPU usage for remote obj loads - or at last spread out the workload to stay under a certain timing threshold. I'm already running the code in a co-routine and using ConvertFileAsync. The obj files are 250k - 1MB. See attached for profiler stats.

    Thoughts appreciated! Thanks.
     

    Attached Files:

  27. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Hi, the async part of ConvertFileAsync refers to downloading a file; the conversion itself always takes place in one frame. At this time there isn't a way to run that over multiple frames, sorry.

    --Eric
     
  28. yjahir

    yjahir

    Joined:
    Jun 3, 2015
    Posts:
    3
    Hello Eric,
    I bought the dll and was successful to load and display the obj from my android phone location. But I am having this problem to rotate the model. I tried to use the objRotation feature in the update function but seems like it only rotates once and does not do anything. Can you show me how to constantly have the rotation in the update function. I need this for the obj to rotate according to the head movement in VR. I am very new to unity development as well. Thanks in advance.
     

    Attached Files:

  29. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    As the docs say, "ObjRotation will rotate the resulting object meshes around the specified x, y, and z axes. Like ScaleFactor, this 'bakes' the rotation into the mesh, rather than rotating the GameObjects." It can't be used to continuously rotate an object.

    The ConvertFile function returns an array of GameObjects (if there's only one object, the array will have one entry). So you can simply refer to the transform component of the GameObject(s) in the array. The Example2-WWW script shows an example of this. If you're new to Unity, I would very strongly recommend spending time doing some tutorials first to become familiar with the engine and API.

    --Eric
     
  30. yjahir

    yjahir

    Joined:
    Jun 3, 2015
    Posts:
    3
    Thanks,
    Can you tell me how to get the GameObjects from the ConvertFile. I tried it just like the convertFileAsync

    ObjReader.ObjData objData;

    objData = ObjReader.use.ConvertFileAsync (objFileName, true, standardMaterial);


    and it shows error "cannot implicitly convert unityEngine.Gameobject[] to ObjReader.ObjData

    when I try this

    objData = ObjReader.use.ConvertFile (objFileName, true, standardMaterial, transparentMaterial);

    Thanks a lot again for helping
     
  31. rahharya

    rahharya

    Joined:
    Jun 6, 2016
    Posts:
    8
    ´maybe because you forgot to place the mtl file in the same directory as your obj file. i have the same Problem, works in Editor and not in Android. now it worked. :)


    Btw. Thanks Eric for the Super Assets.
    It is my first Projekt with Unity.
    I hope that it can load more than 65000 Recticle in the future
     

    Attached Files:

    • OBJ.png
      OBJ.png
      File size:
      323.8 KB
      Views:
      795
    Last edited: Dec 14, 2016
  32. yjahir

    yjahir

    Joined:
    Jun 3, 2015
    Posts:
    3
    I got it. I declared a gameobject like

    GameObject[] go;


    Then in start did

    go = ObjReader.use.ConvertFile(objFileName, true, standardMaterial,transparentMaterial);


    and in update function I did the following to rotate

    go[0].transform.Rotate(Vector3.right * Time.deltaTime);


    Thanks. My goal is to use the head movement in VR and rotate the obj according to that. Will work on that now.
     
  33. ulvang

    ulvang

    Joined:
    Sep 10, 2015
    Posts:
    6
    Hi. I am facing the same issue with a large model (> 100 000) vertices, and I am trying to use groups in the obj file to split up the meshes, but I still get the error " the number of vertices exceeds the maximum limit of 65534 ..."
    My question is if it is possible to "restart" the indexing of vertices within the file for each group, or are every new vertex always given a the next index number? I.e. so that in the following example the face indices for group-2 refer to the last "set" of vertices and not the first?

    g group-1
    v 0 0 0
    v 0 10 0
    v 0 10 10
    f 1 2 3

    g group-2
    v 20 0 0
    v 20 10 0
    v 20 10 10
    f 1 2 3

    Or do I have to split my big obj file into separate files?
     
    Last edited: Dec 21, 2016
  34. ulvang

    ulvang

    Joined:
    Sep 10, 2015
    Posts:
    6
    I realized that it was the "Combine Multiple Groups" flag on the ObjReader that generated the error, as all my groups were merged into one mesh resulting in too many vertices. Setting this flag to false resolved my problem :)

    So it is not a problem that the vertex index is higher than 65,534 as long as the resulting mesh does not contain more that 65,534 vertices, and I guess "restarting" the vertex index in the obj file is not possible and not needed!
     
  35. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The vertex index is in fact restarted for each group as long as mesh combining is not used. Hence there's no limit on the number of vertices in a file, as long as each group < 65K vertices.

    --Eric
     
  36. wxxhrt

    wxxhrt

    Joined:
    Mar 18, 2014
    Posts:
    163
    HI is there a built in function to centre the pivot point to the centre of the mesh's bounds? Thanks
     
  37. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, there's an "auto center on origin" option.

    --Eric
     
  38. aashwini005

    aashwini005

    Joined:
    Jan 19, 2017
    Posts:
    14
    Hi Eric,

    I am using Unity to load an obj file and view it through Oculus in virtual reality.
    My problem is that I have around 50000 such obj files which need to be loaded one at a time in the scene.
    So basically I want to replace a previous obj file loaded in the scene with a new file during runtime.
    The files are named in an order; ex: file_000.obj, file_001.obj, file_002.obj,...etc.

    Will the OBJReader solve my problem? If so, how and what functions can I write in my C# code to load these files from my local disk?
     
  39. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Sure, that's not a problem. The ConvertFile function in ObjReader reads files from disk.

    --Eric
     
  40. grimmy

    grimmy

    Joined:
    Feb 2, 2009
    Posts:
    409
    Hi Eric, I'm trying to use the ObjReadaer for the first time but I'm getting a null reference exception on the line:

    objData = ObjReader.use.ConvertFileAsync (objFileName, true, standardMaterial);

    I am sure that objFileName and standardMaterial are NOT null so that just leaves me with the ObjReader. But isn't that all wrapped up in a dll? My original decalration of the objReader looks like this (C#):

    public ObjReader.ObjData objData;

    Does that all sound okay? Demo all works fine so it must be something in my code.
     
  41. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You can try using the source to see if there's anything going on in the ObjReader code. What you posted seems OK from what I can tell.

    --Eric
     
  42. m-i-e-c-z

    m-i-e-c-z

    Joined:
    Nov 10, 2010
    Posts:
    27
    Hi!

    I have a small feature request. Could you add an option to automatically split a mesh into multiple objects if it exceeds the 65k vertex limit? There is an option to combine OBJ groups into one object, but it would be great if there would be an option to split a mesh too. I know that 65k vertices is a lot, but there are cases, when you have to deal with such a mesh.

    Thanks a lot,
    Maciej
     
  43. CritCauchy

    CritCauchy

    Joined:
    Jan 31, 2017
    Posts:
    1
    Hi,
    I'm looking for an obj-loader that supports objects with more than 65000 vertices, too. Unfortunately, I can't simplify the object or reduce the number of vertices.
    regards
    CC
     
  44. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    ObjReader supports objects with >65K vertices if the object is organized into groups where each group <65K vertices.

    --Eric
     
  45. m-i-e-c-z

    m-i-e-c-z

    Joined:
    Nov 10, 2010
    Posts:
    27
    Yes, I am aware of that. I was thinking of an object with a single group that exceeds the 65k limit and some kind of auto-splitting mechanism (such as splitting the triangles of a mesh into multiple game objects).
     
  46. aashwini005

    aashwini005

    Joined:
    Jan 19, 2017
    Posts:
    14
    Hi Eric,

    I imported the ObjReader from Asset Store after which I had no errors but when I clicked extras-> ObjReaderSource.UnityPackage it imported some .cs file and after which I am seeing these two errors:
    1> Assets/ObjReader/Demo Scripts/Example1_TextAsset.cs(20,25): error CS0433: The imported type `ObjReader' is defined multiple times
    2> Assets/ObjReader/Demo Scripts/Example2-WWW.js(7,23): BCE0018: The name 'ObjReader.ObjData' does not denote a valid type ('not found'). Did you mean 'System.Reflection.Emit.OpCodeType'?

    Could you please help me how to remove these errors?

    Regards,
    Akanksha
     
  47. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You can't have both the source and the DLL imported at the same time.

    --Eric
     
  48. aashwini005

    aashwini005

    Joined:
    Jan 19, 2017
    Posts:
    14
    What shall I do now to remove one of it and make things working?
     
  49. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Delete the ObjReader.cs script.

    --Eric
     
  50. wxxhrt

    wxxhrt

    Joined:
    Mar 18, 2014
    Posts:
    163
    Hi Eric,

    Thanks for the great asset. Everything worked fine until I tried to save my app as WebGL, I'm going through the process of changing

    ObjReader.use.ConvertFile

    to

    ObjReader.use.ConvertFileAsync

    and am running into a problem, which I think is more to do with my understanding of C# yield statements.

    The following is my import code, it never gets to adding components, am I doing something obviously wrong?

    Thanks

    Code (CSharp):
    1. IEnumerator ImportNow(string path){
    2.         Material randomMaterial = materialArray[Random.Range(0,materialArray.Length)];
    3.        // GameObject[] importedModels = ObjReader.use.ConvertFile (path, false, randomMaterial); // this works with the non asyncronous
    4.  
    5.         objData = ObjReader.use.ConvertFileAsync (path, false, randomMaterial);
    6.         while (!objData.isDone) {
    7.             Debug.Log("loading");
    8.             yield return null;
    9.          
    10.         }
    11.         GameObject[] importedModels = objData.gameObjects;
    12.  
    13.         Debug.Log(path);
    14.  
    15.         GameObject importedModel = importedModels[0];
    16.  
    17.         GameObject walls = GameObject.Find("Walls");
    18.         importedModel.transform.parent = walls.transform;
    19.      
    20.         importedModel.AddComponent<BoxCollider>();
    21.         importedModel.AddComponent<classInitialConditions2>();
    22.         importedModel.AddComponent<classScale2>();
    23.         importedModel.AddComponent<classTranslate2>();
    24.         importedModel.AddComponent<classRotate2>();
    25.         importedModel.AddComponent<classSafeSpace>();
    26.         importedModel.AddComponent<AudioSource>();
    27.  
    28.  
    29.  
    30.  
    31.         do{
    32.             rndPos = RandomPositionWithin(limits.transform);
    33.             importedModel.transform.localPosition = rndPos;
    34.         } while (!IsInsideLimits(importedModel.transform, limits.transform));
    35.  
    36.      
    37.      }

    EDIT: A little more background- ImportNow gets called a number of times from a for loop. For some reason the first model thats imported is getting made the child of "Walls" then getting lots of copies of the components added to it, rather than copies added to each imported model ( all models get imported ). Any ideas?
     
    Last edited: Mar 2, 2017