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
    It's correct, the position is always (0, 0, 0), unless you move the object after it's generated. The mesh vertices can be anywhere and are unrelated to the transform.position, but that's why I implemented the AutoCenterOnOrigin option.

    --Eric
     
  2. critic

    critic

    Joined:
    Jun 14, 2013
    Posts:
    8
    But then there is no way to know where the objects are in Unity, there must be some position being given by the obj export as the objects are offset as they are in the actual model, it's just that this position is not being set by the import.

    I have nodes in the import, need the position of these nodes as they are used for the positioning of other items. Also I'm not sure how Unity does not know a difference of world positions of two items that are clearly not in the same place.
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    There isn't; the only positions that exist in an .obj file are of the vertex positions. There is no "transform.position" of an .obj I'm afraid.

    --Eric
     
  4. critic

    critic

    Joined:
    Jun 14, 2013
    Posts:
    8
    Your AutoCenterOnOrigin feature knows the offset of the objects in the model, would it be too difficult for you to set the transform position to this offset instead of (0,0,0)?

    edit
    I made a small change to the source, object positions are now reported correctly, thanks for the plugin.
     
    Last edited: Jan 2, 2015
  5. Fargrey

    Fargrey

    Joined:
    Mar 30, 2013
    Posts:
    3
    Hello i have some questions i would like to ask before bying this, i'm currently developing an app for android which download 3D models from a server and load them in the app on runtime so the user can watch it.
    1) I already saw that it should work on android but would it work if i download the file externally without using unity ressources and packages then load it to the scene with your plugin?
    2) Does it support textures?
    3) the files are pretty big does the plugin work well with large files?
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    1) ObjReader can load any file you have access to.
    2) Yes.
    3) As long as each group in the .obj file is <65K vertices.

    --Eric
     
  7. Fargrey

    Fargrey

    Joined:
    Mar 30, 2013
    Posts:
    3
    Just one last question, most os the obj builder i've found online struggle with files exported from sketchup to obj, does yours work?
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, but keep in mind that meshes still need to be constructed correctly (surface normals pointing in the correct direction, etc.).

    --Eric
     
  9. kaka1412

    kaka1412

    Joined:
    Aug 20, 2012
    Posts:
    5
    Hi,
    I have a question about run the demo scene on iOS platform with Build setting is arm64. There is a crash when run with arm64 , it work fine with armv7. It mean ObjReader don't support iOS 64-bit, right? If yes, please help me solve this problem, we need update my project to 64-bit.
    many thanks,
     
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's up to Unity to support building to ARM64; you can submit a bug report. They've stated that the goal for IL2CPP is to support anything that works with standard iOS AOT publishing (which ObjReader does support), so if it doesn't work that's a Unity bug.

    --Eric
     
  11. kaka1412

    kaka1412

    Joined:
    Aug 20, 2012
    Posts:
    5
    I just run a demo scene (Example1-TextAsset/Example2-WWW) after import ObjReader package. I don't change any script in the package. I just want to know do you have a same problem? and Do you submit the report to Unity if that is Unity bug? And is there any support from Unity to solve with ObjReader?
     
  12. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I haven't tested ARM64. You should submit a bug report.

    --Eric
     
  13. raj231

    raj231

    Joined:
    Nov 18, 2014
    Posts:
    46
    I'm doing Augmented Reality image recognition project (vuforia) and loading the .obj model from server when the image is recognized. The problem is, when my target found the loading text will start to display the percentage of load and if it comes at 99% and the camera is freezing to load the model. I'm not sure why the camera is freezing. How can we load model without freeze the camera?

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

    while (!objData.isDone) {
    Debug.Log (" objData is not there");


    loadingText.text = "Loading... " + (objData.progress*100).ToString("f0") + "%";
    yield return loadingText.text;
    }
    //myHealth.Progress (100); // done
    loadingText.enabled = false;
    string modelName = objData.gameObjects [0].name;

    model = GameObject.Find (modelName); // find the model reference

    model.name = targetIDModel; // change the model name to targetID !!!
    }

    GameObject modelClone = Instantiate( model ) as GameObject; //clone the model

    modelClone.transform.localPosition = Vector3.zero; // bring the clone to origin

    modelClone.transform.parent = itbModel.gameObject.transform; // pair the clone to the instantiated image target

    modelClone.transform.localScale = Vector3.one;
     
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    If it's a large model, it will take a little time to process. There's not much you can do about that.

    --Eric
     
  15. raj231

    raj231

    Joined:
    Nov 18, 2014
    Posts:
    46
    The model size is 3, 4, 5MB . All the size models are taking time to load and the camera is freezing at 99%
     
  16. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, it probably takes about half a second to compute, depending on CPU speed.

    --Eric
     
  17. raj231

    raj231

    Joined:
    Nov 18, 2014
    Posts:
    46
    I'm not sure your plugin because when i load the model from local in unity, it's loading fast and the camera is not freezing..But when i load the model from server, it freezing.
     
  18. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It's clearly going to take longer to download from a server than loading it locally. Unity does hang for a couple of seconds when importing models (depending on file size), if that's what you mean by "camera freezing".

    --Eric
     
  19. CarpetHead

    CarpetHead

    Joined:
    Nov 22, 2013
    Posts:
    20
    Hey,
    I'm using the following function to download an obj and import it into my scene:

    objData = ObjReader.use.ConvertFileAsync (url, true, new Material (Shader.Find ("Diffuse")));

    This is done inside a coroutine which checks for objData.isDone.

    It works perfectly; however sometimes before this process is completed, I need to be able to cancel this process without the obj being imported when the download completes.

    Is there some function that does this? can you help me out?

    Thanks!
     
  20. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    There isn't a function that does this currently, but I can add one. How about an ObjReader.CancelDownload() function, where the ObjData.gameObjects variable remains null, or do you need an ObjData.cancelled variable?

    --Eric
     
  21. CarpetHead

    CarpetHead

    Joined:
    Nov 22, 2013
    Posts:
    20
    Thanks for the quick reply, if possible it would be great if I could cancel on an individual basis rather than a global basis, but exactly how it works isn't too important! A function works fine.
     
    Last edited: Jan 30, 2015
  22. raj231

    raj231

    Joined:
    Nov 18, 2014
    Posts:
    46
    How can we load animation at runtime from server? Is there anyway to use?
     
  23. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The .obj format does not have animation.

    --Eric
     
  24. raj231

    raj231

    Joined:
    Nov 18, 2014
    Posts:
    46
    One more thing for camera freeze, when i load the model using AssetBundle the camera is not freezing but if i use your plugin to load the same model then the camera is freezing. So, where is the problem? I'm not sure to understand this issue..
     
  25. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Those are two entirely different things which can't be compared. AssetBundles already had the models imported and converted in Unity, so there is no more processing required. Importing an .obj file requires reading text files, parsing them, and constructing the mesh at runtime. This is many orders of magnitude slower than just loading some already processed data.

    --Eric
     
  26. raj231

    raj231

    Joined:
    Nov 18, 2014
    Posts:
    46
    Yes, you are correct and do you know how can load animation from server? I've searched and found the Assetbundle, but is it possible to load the animation without using AssetBundle?
     
  27. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You should start a new topic; this topic is only for ObjReader support.

    --Eric
     
  28. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Dear all,
    I have bought this graet asset...however I have somethig to solve that I can't think how to do it.
    Basically I am importing quite a lot of objects under one obj file, now I want to rotate over time one of them.
    Everything works ok however the function to rotate starts before the objects are imported so it throws a null object reference error which is right because the object does not exist yet. After a while the object arrives and the error disapper.
    How can I make it so that the function update starts after the objects are imported?
    at the moment I have this but is still not doing it :

    void Update () {
    if (objData != null && objData.gameObjects != null) {
    test.GetComponent<Transform>().Rotate(0, Time.deltaTime*20, 0);
    }
    }

    Many thanks
    Nic
     
  29. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You should use a coroutine instead of Update; see the WWW examples for how to yield on object downloads.

    --Eric
     
  30. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    I was already doing:
    test=GameObject.Find("object");
    test.GetComponent<Transform>().Rotate(0, Time.deltaTime*20, 0);
    inside a couroutine but I moved the:
    test.GetComponent<Transform>().Rotate(0, Time.deltaTime*20, 0);
    with a global variable test in void Update() because Time.deltaTime was not working in it.
     
  31. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Time.deltaTime works fine in coroutines. Also you shouldn't use Find, since the ConvertFile functions already return the GameObjects.

    --Eric
     
  32. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    I have tried this inside my couroutine and it does not work only inside Update:
    GameObject.Find("name").GetComponent<Transform>().Rotate(0, Time.deltaTime*20, 0);

    Also you shouldn't use Find, since the ConvertFile functions already return the GameObjects.
    How do I access the objects by name and also its material? I am importing one obj file with many objects inside. Using Example2


    Sorry I have also another problem, basically I think ObjeReader is doing this:
    If the material is not supplied or is null, then a default material generated by ObjReader (using the built-in VertexLit shader) will be used instead.
    Because my objects have an Transparent VertexLit Material instead of a Diffuse and so they are transparents, but my .obj file has a .mtl files. In the slot of standard material I have supplied a standard material.

    This is what is inside my mtl

    newmtl townMat
    Ns 10.000000
    Ni 1.500000
    d 1.000000
    Tr 0.000000
    Tf 1.000000 1.000000 1.000000
    illum 2
    Ka 0.588000 0.588000 0.588000
    Kd 0.588000 0.588000 0.588000
    Ks 0.000000 0.000000 0.000000
    Ke 0.000000 0.000000 0.000000

    Many thanks Nic
     
    Last edited: Feb 6, 2015
  33. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Please don't use GameObject.Find; it's bad for performance and not necessary. See the ObjReader docs for ConvertFilesAsync, which describes the ObjData class, which contains the GameObject array. The Example2-WWW script shows how the array is accessed. Time.deltaTime works perfectly fine in coroutines; if you're unsure how to use them, consult the Unity docs.

    I'm unclear what your second problem is about. If you don't want the default materials, you should supply a non-transparent material, and a transparent material. If the MTL file indicates transparency, then the transparent material will be used, otherwise the standard material will be used.

    --Eric
     
  34. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Hi Eric
    Thanks a lot I will have a look on how to access members of an array by name in the docs.

    For the second problem I am exporting the .obj from 3dsMax, I want all the originals materials and textures to be applied but for some reason Unity applies a Transparent/ VertexLit shader and no texture when importing.
    Thanks
    Nic
     
  35. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You don't access the array entries by name, it's by index. It's not possible to import materials from other modeling apps; all materials must be applied in Unity.

    --Eric
     
  36. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Hi Eric
    Regarding arrays: how do I know which one is which if it is by index? I have quite a lot of objects.

    Regarding Materials why does my Object reader assign a Transparent/VertexLit shader? is it how is supposed to be?
    I saw the example2 and it looks pretty straight forward to me: a .obj with spot material and a texture, all coming from the server, when they get imported a diffuse material get assigned
    I have copied the code from this example
     
  37. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    It's by object order in the file, so the first group will be 0, the next one is 1, etc. It's using a transparent shader because the MTL file indicates 100% transparency. (Actually it's contradictory...it says "d 1.0" but "Tr 0.0", which are opposite, but ObjReader is using the last one since it reads files line by line.)

    --Eric
     
  38. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Hi Eric
    I have done this in my courotine and nothing is happening
    objData.gameObjects[1].GetComponent<Transform>().Rotate(0, Time.deltaTime*20, 0);
    The object stand still :(

    Solved the problem of the transparency(in 3dsMax needed to set opacity to 0), but I still have the VertexLit applied instead of Diffuse.
    Do you know why?
    Many thanks.
    Nic
     
    Last edited: Feb 7, 2015
  39. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I'd have to see more code, since that by itself seems OK. (You don't need GetComponent though, just objData.gameObjects[1].transform.Rotate is fine.)

    VertexLit is used for the default material, so if you supply your own material using Diffuse, that will work. See the Example2-WWW scene.

    --Eric
     
  40. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Dear Eric Many thanks for your help!
    I understand how it works now, I think I can start to have some fun.
    So to remember to all the others if using 3dsMax:
    - put Opacity to 0 on the used materials, otherwise they will be transparent in Unity
    On exporting:
    - Flip YZ_axis ON
    - Texture Coordinate ON
    - Normals ON
    - Export Material ON
    - Create Mat_Library ON
    All the rest can stay off
    Open the .obj file with a text editor and edit the # object nameofobject line with o nameoftheobject (for some reason my exporter puts a comment on the line), SAVE!
    Open the .mtl material file and put the right path to the texture if is not already set, SAVE!

    I hope it helps...

    Regarding this:
    objData.gameObjects[0].transform.Rotate(0, Time.deltaTime*20, 0);

    My code is a bit of a mess however I have tried to put it in the Example2 script and still doesn't do anything unless I use the void Update() function. No problem I don't need it for the moment.
    Many thanks for this great asset! Later...
    Nic
     
    Last edited: Feb 8, 2015
  41. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    I guess is already time for opening another topic...
    How can I swap material at runtime? I have tried this but nothing is happening(ClayMat is the name assigned in 3ds max to one of the objects and appears also in Unity when runnig the script)
    objData.gameObjects [0].renderer.material.name = "ClayMat";

    Also I would like to swap textures used in the .mtl file, is this the right way to do it:
    objData.gameObjects[0].renderer.material.mainTexture = ...?
    Many thanks
    Nic
     
  42. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You change materials by setting the material, not the name. See the Unity docs.

    --Eric
     
  43. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    I have tried this in order to assign the material of the second object in the array to the first but it dosen't work.

    objData.gameObjects[0].renderer.material = objData.gameObjects[1].renderer.material;

    Nic
     
  44. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I tried it, works fine. Using pig.obj, here you can see that using your code makes the eyes (gameObjects[0]) have the same material as the tongue (gameObjects[1]):

    Screen Shot 2015-02-09 at 12.46.52 PM.png

    --Eric
     
  45. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Sorry actually worked!!!
    Many thanks
    Nic

    Regarding textures is a bit more complicate because I don't know how to get the name of the texture from the .mtl file
    So for example if I have the first material with a texture and I want to apply that texture to the second material is it this?
    objData.gameObjects[0].renderer.material.mainTexture = objData.gameObjects[1].renderer.material.mainTexture;
     
  46. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's correct.

    --Eric
     
  47. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Ok so my idea is this: lets say I create an .obj file with 10 dummy cubes in 3dsMax.
    5 cubes with 5 different materials and no textures an the other 5 cubes are the same but with textures.
    I will use this template in order to change materials and textures to my other objects in the scene.
    The reason for doing this is because on my final project the .obj file will come from another person which is in charge of doing the modelling and the initial texturing, while I am in charge of doing the interaction with Unity.
    The final user has to have the possibility to change the materials and/or the textures.
    In this way I can say to the modeler to include the cubes in the exported .obj and .mtl files so that I can use them as templates.
    Do you think is a good solution?
    Do you think that I can actually have the cubes as separate .obj and .mtl files? If so how can I load and 2 obj files with ObjectReader and interact between them?

    Thanks Nic
     
    Last edited: Feb 9, 2015
  48. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I don't really understand what you're doing with your project, so I can't advise what the best way is. Anyway, you can read multiple .obj files just by calling ConvertFile for each file.

    --Eric
     
  49. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    aah ok I will try that, will send some screenshots once I got somethig.
    Many thanks for now
    Nic
     
  50. imagoculturae

    imagoculturae

    Joined:
    Apr 8, 2014
    Posts:
    81
    Hi Eric, me again sorry...
    I have added this into my load function:

    if (objData2 != null && objData2.gameObjects != null) {
    for (var b = 0; b < objData2.gameObjects.Length; b++) {
    Destroy (objData2.gameObjects);
    }
    }
    objData2 = ObjReader.use.ConvertFileAsync (objFileName2, true, standardMaterial);

    However the objects of objData2 do not get destroied, do you know why?I have also changed the var in b,just in case...

    Many thanks Nic