Search Unity

[RELEASED] Piglet: glTF Importer

Discussion in 'Assets and Asset Store' started by awesomesaucelabs, Jul 9, 2020.

  1. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @MidnightCoffeeInc

    Yes, doing the Piglet rescaling after adding box colliders should solve the problem. (That would be consistent with my explanation above.)

    The method that Piglet calls to rescale the model is
    HierarchyUtil.Resize
    , in
    Assets/Piglet/Scripts/Util/HiearchyUtil.cs
    . You could disable the
    GltfImportOptions.AutoScale
    option and then call that method yourself after adding the box collider.

    HierarchyUtil.Resize
    is a coroutine (
    IEnumerable
    ) method, so you would have to run it with a
    foreach
    loop, e.g.:

    Code (CSharp):
    1. foreach (var result in HierarchyUtil.Resize(gameObject, targetSize))
    2. {
    3.    // intentionally empty loop
    4. }
    (I haven't tested the above code, so please let me know if it doesn't work as expected, hangs, etc.)
     
  2. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @MidnightCoffeeInc

    Sorry, I think I was wrong... I think you will get the same result, even if you change the order of operations.

    I guess it's best if you try it yourself and see :)
     
  3. JudahMantell

    JudahMantell

    Joined:
    Feb 28, 2017
    Posts:
    476
    I ended up taking the code from HierarchyUtil and pasting it into a new function, passing in the bounds of the generated collider, and it worked perfectly!
    Once again, thank you so much for your continued help!

    If you're curious, here's the method:

    Code (CSharp):
    1.  public static void ScaleToFitWithinBounds(GameObject root, float targetSize, Bounds bounds)
    2.     {
    3.         Bounds? newBounds = bounds;
    4.         // avoid divide by zero
    5.         var size = newBounds.Value.extents.MaxComponent();
    6.         if (size < 0.000001f)
    7.             return;
    8.  
    9.         // scale hierarchy to target size
    10.         Vector3 scale = root.transform.localScale;
    11.         float scaleFactor = targetSize / size;
    12.         root.transform.localScale = scale * scaleFactor;
    13.     }
     
  4. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
  5. myspace_unity

    myspace_unity

    Joined:
    Jan 6, 2021
    Posts:
    1
    Hi @awesomesoucelabs,

    thank you so much for releasing a plugin like this. Piglet did become a lifesaver in our product. We are working on AR/XR products and projects to support people with disability.

    Because of the very good capabilities for more accessibility in the mobile world, iOS is a important target platform for us and the most important platform for people with limitations. Do you plan the support for the apple platform in the near future?

    I think there's a lot of demand in the mobile developer-community. Usually apps does support the "big 2" platforms.

    Keep up this great work! Outcome and the simplicity in using this plugin is amazing.

    Best,
    Marco
     
  6. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Hi Marco (@myspace_unity),

    Thanks for the encouraging words! It's always great to hear that my work has been valuable for other people.

    There is a good chance that Piglet already works fine on iOS. I haven't included iOS in the list of officially supported platforms yet because I haven't had a chance to test it thoroughly myself. And the reason I haven't tested it yet is that I don't currently own a Mac computer (Unity iOS builds require a Mac computer with Xcode installed). I did recently buy an iPhone 10 for testing purposes, though. I'll probably experiment with cloud build services and/or VMs to avoid the cost of buying another computer if I can.

    If you want to test Piglet on iOS yourself in the meantime, the quickest way is build the example scene under
    Assets/Piglet/Examples/RuntimeImport/Scenes
    for iOS and then run it on your iPhone. If you see a spinning 3D model of the Piglet mascot ("Sir Piggleston"), then it is working!

    I think you are the 3rd or 4th person to ask me about iOS support in the past week, so I'll take it as a strong hint. I've already promised to work on a couple of other features in January (KTX2 and Draco) though, so I may not get to it until February.
     
  7. ASGS_DumbFox

    ASGS_DumbFox

    Joined:
    Sep 23, 2017
    Posts:
    22

    Hey @awesomesaucelabs! My team is working with @DerrickBarra on integrating Piglet and there were two things I wanted to bring to your attention in case it's helpful:

    1. We have Piglet working in an iOS build and it appears to work well!
    2. In response to the quote I have here, we ran into an issue where textures weren't loading in properly for the model. Some material fields were empty, some base color textures were in the normal map field. Your response:
    Code (CSharp):
    1. var random = new Random(Guid.NewGuid().GetHashCode());
    did resolve this issue and textures appear to be loading properly now.

    One thing I'm noticing is that transparent materials such as the glass found in this vehicle:


    are still loading as opaque. Any insight into how the shader-type is selected based on the import?



     
  8. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Hi @ASGS_DumbFox!

    Thanks very much for letting me know! That is a valuable data point for me. I really need to work on official iOS support soon, because lots of people are asking for it.

    Glad that fixed it and sorry for the bug! In case you are not aware, the quoted random/guid fix was included in the latest Piglet release (1.1.1).

    The shader for a material is selected based on the glTF "alphaMode" property for the material (OPAQUE, MASK, or BLEND).

    Transparency looks correct when I view the car model with the Piglet web demo (https://awesomesaucelabs.github.io/piglet-webgl-demo/).

    Maybe you are using URP, though? (The web demo uses the built-in render pipeline.) Can you also let me know what version of Unity you are using?

    Your image links are broken for some reason. Maybe you are posting the wrong link type from imgur? (I've done that many times.)
     
  9. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @ASGS_DumbFox,

    The Piglet web demo is still on Piglet 1.1.0, whereas the latest version is Piglet 1.1.1.

    I'll update the web demo today to avoid unnecessary confusion.

    EDIT: The web demo is updated to Piglet 1.1.1 now.
     
    Last edited: Jan 15, 2021
  10. ASGS_DumbFox

    ASGS_DumbFox

    Joined:
    Sep 23, 2017
    Posts:
    22
    @awesomesaucelabs We are using Unity Editor 2020.1.4f1 - SRP. I tested an object that was mostly glass and all of the shaders came in as opaque. I'll continue to look into it and see why.

    And yeah I tried multiple times to fix the image links but it just wouldn't have it haha
     
  11. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @ASGS_DumbFox,

    Just checking: Normally "SRP" stands for Scriptable Render Pipeline, i.e. URP or HDRP. So you are saying that you are using URP, correct? (It matters because Piglet uses different shaders for URP vs. the built-in render pipeline.)

    Are you familiar with the "Order Independent Transparency" problem? (See here for a nice explanation.) If you are seeing funny behaviour with a model that is mostly made of transparent surfaces, it may be the key to understanding what is happening. The Piglet shaders address the Order Independent Transparency problem with a "Z-write prepass" (for both built-in render pipeline and URP) . It may be that there are better solutions that I still need to learn about and implement.

    If you are not able to publicly share the model with the transparency problems, maybe you can share it with me in a private e-mail? (awesomesaucelabs at gmail)
     
    Last edited: Jan 16, 2021
  12. ASGS_DumbFox

    ASGS_DumbFox

    Joined:
    Sep 23, 2017
    Posts:
    22
    @awesomesaucelabs Ah sorry I misspoke. I meant the Built-In Render Pipeline. We are not using any custom scripted pipeline, URP, or HDRP.

    The issue isn't really transparency behavior related but rather the lack there of. Objects that have transparency when we read them into our platform are being given the opaque shader.

    Unfortunately I haven't had the chance to sit down and dig into it but I'll let you know if I do. In the meantime I can send you an example via email of what our issue is since I can't seem to figure out how to link those images here.

    Thanks!
     
  13. khaled-P

    khaled-P

    Joined:
    Oct 30, 2020
    Posts:
    3
    Hi @awesomesaucelabs

    Thanks for the robust implementation and clean code!
    I'm working on building an application to visualize the Construction models and so far the plugin renders the models on both IOS and Android without problems.

    I was wondering though if there is a way to speed up the importing time, right now our bottleneck is that loading meshes takes a long time.

    I tried GltfUtility and it takes around 25% of the time needed to import the same gltf file but I had many problems using it on IOS and Android. So I was wondering what's the difference?
     
  14. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Hi @kplanradar,

    Thanks for the feedback! In particular, I am glad to hear that Piglet is working well for you on iOS. A few users have told me that Piglet is working well on iOS, but I still haven't gotten around to testing it myself. (It is pretty high on my TODO list, because lots of people have been asking me to add iOS to the list of officially supported platforms.)

    25% is a huge difference! No, unfortunately I don't know why Piglet is slower than GLTFUtility when loading your meshes. I plan to add Draco (mesh compression) support fairly soon, and while I am working on that I will also profile the mesh loading code and make sure I'm not doing anything stupid (lol). FYI, I will probably work on iOS support before Draco/mesh-loading, due to popular demand for iOS support.

    I am currently working on a release with KTX2/Basis support (supercompressed textures), which will greatly reduce texture loading times and overall loading times, assuming your models use textures. So hopefully that will improve your loading times while you are waiting for mesh-loading improvements. One significant downside/inconvenience of using KTX2 is that it requires preprocessing your glTF files to convert the textures from PNG/JPG to KTX2. (Personally, I use the "gltf-transform" for that task, which is a great command line tool.)
     
  15. khaled-P

    khaled-P

    Joined:
    Oct 30, 2020
    Posts:
    3
    @awesomesaucelabs

    Ah! sorry, actually I was totally mistaken, the loading time is even better than GLTFUtility. All I had to do is to load all the meshes once by moving
    Code (CSharp):
    1. yield return null
    to outside the for loop.

    Now the loading time is much better
     
  16. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @kplanradar

    Glad to hear!

    Yes, there is a trade-off between minimizing total import time and minimizing stalls to the main Unity thread (i.e. drops in frame rate), which is determined by how frequently Piglet yields.

    I've considered controlling the trade-off with a user-configurable parameter, e.g. "MillisecondsPerYield".
     
  17. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Piglet 1.2.0 released!

    Hi Piglet users :)

    I'm happy to announce the release of Piglet 1.2.0, which introduces support for supercompressed textures, via integration with @tteneder's awesome KtxUnity package. See Using Supercompressed Textures in the manual for background info and setup instructions.

    Using supercompressed textures gives a significant performance boost, resulting in faster model loading times and smaller glTF file sizes. The main trade-off is potential loss of visual quality, which can result in textures that look "blocky" or "low-res". However, the quality parameters are tweakable, and for many models/textures the difference in visual quality is barely noticeable.

    If you want to see some real-world examples, the Piglet Web Demo now provides normal and supercompressed ("etc1s") versions for some of the sample models ("Skull Salazar" and "Dragon"). Try loading the two versions of each model and observing the differences in visual quality, loading times, and file sizes.

    Changelog

    Shout-outs

    @tteneder Thanks for making KtxUnity and for your kind support!

    @DerrickBarra After many many months, I finally added it (!). Thanks for making the suggestion for KTX2 support in the first place. (I'm still planning to add Draco support as well.)

    @ASGS_DumbFox I included the shader fix for transparent/metallic objects in this release (switch from `alpha:auto` -> `alpha:fade`). This gives the carafe model a more reasonable appearance.
     
    Last edited: Feb 11, 2021
  18. DerrickBarra

    DerrickBarra

    Joined:
    Nov 19, 2013
    Posts:
    210
    @awesomesaucelabs : Great job! We're using Piglet for some client projects already, and once Draco is ready we'll be using it for all model loading at our studio. Can't wait!
     
  19. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
  20. ASGS_DumbFox

    ASGS_DumbFox

    Joined:
    Sep 23, 2017
    Posts:
    22
  21. Pode

    Pode

    Joined:
    Nov 13, 2013
    Posts:
    145
    @awesomesaucelabs thanks for the work on the compressed textures! It helps a lot to keep the app responsive.
     
  22. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @ASGS_DumbFox @Pode

    Thanks guys! I will let you know when Draco support is ready. May be a few weeks.
     
  23. JudahMantell

    JudahMantell

    Joined:
    Feb 28, 2017
    Posts:
    476
    Hey @awesomesaucelabs so far everything has been going great -- I freaking love Piglet :D -- but since I added a few more gltf models to load, the script(s) stop and I get this error from Piglet scripts. I'm not quite sure what it means/what to do about it. Do you have any ideas? If a model is incompatible, that's totally fine, but is there a way to have Piglet skip over this model, rather than stopping everything?
    Thanks so much, as always! :D

    EDIT: Here's the model that's causing the issue

    Code (CSharp):
    1. IndexOutOfRangeException: Index was outside the bounds of the array.
    2. GLTF.Schema.Accessor.AsTriangles (GLTF.Schema.NumericArray& contents, System.Byte[] bufferData) (at Assets/Piglet/Dependencies/UnityGLTF/GLTFSerialization/Schema/Accessor.cs:644)
    3. GLTF.GLTFHelpers.BuildMeshAttributes (System.Collections.Generic.Dictionary`2[System.String,GLTF.AttributeAccessor]& attributes) (at Assets/Piglet/Dependencies/UnityGLTF/GLTFSerialization/GLTFHelpers.cs:25)
    4. Piglet.GltfImporter.LoadMeshAttributes (GLTF.Schema.MeshPrimitive primitive) (at Assets/Piglet/Scripts/Importer/GltfImporter.cs:1357)
    5. Piglet.GltfImporter.LoadMeshPrimitive (GLTF.Schema.MeshPrimitive primitive, System.Int32 meshIndex, System.Int32 primitiveIndex, System.String meshName) (at Assets/Piglet/Scripts/Importer/GltfImporter.cs:1251)
    6. Piglet.GltfImporter.LoadMesh (GLTF.Schema.Mesh meshDef, System.Int32 meshId, System.String meshName) (at Assets/Piglet/Scripts/Importer/GltfImporter.cs:1231)
    7. Piglet.GltfImporter+<LoadMeshes>d__33.MoveNext () (at Assets/Piglet/Scripts/Importer/GltfImporter.cs:1202)
    8. Piglet.GltfImportTask.MoveNext () (at Assets/Piglet/Scripts/Importer/GltfImportTask.cs:267)
    9. ObjectDatabase+<LoadAllGltfModels>d__39.MoveNext () (at Assets/Scripts/ObjectDatabase.cs:278)
    10. UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <d29d557b212f474390dc0b17ef6ce0dd>:0)
    11.  
     
  24. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Hi @MidnightCoffeeInc,

    Thanks for the kind words! (I get a little boost whenever someone says that Piglet is working well for them!)

    I think I can see the problem with your shower model. Right now, Piglet can only handle triangle meshes (i.e. mesh type = TRIANGLE) whereas the glTF format actually allows lines (i.e. mesh type = LINES) and point clouds (i.e. mesh type = POINTS). I didn't think people would ever use those, but I was wrong :)

    I'm sure if/when I will add support for LINES/POINTS (it depends on how many people ask for it), but I will work on producing a better error message in the meantime. Also, in this case it would have been much better if Piglet had just skipped over the LINES mesh and continued to load the rest of the model.

    If you want your game/app to carry on after failing to load the model, you just have to put a try/catch block around your call to
    importTask.MoveNext
    . In addition, you will probably want to print a warning inside the `catch` block, to let you (and the user) know that one of the models failed to load.

    By the way, to check if a glTF file contains unsupported LINES/POINTS meshes, you can use the
    gltf-transform inspect
    command. (I provide some instructions about how to install the
    gltf-transform
    command line tool in the manual, in "Preprocessing glTF Files".)

    For example, here's the output of
    gltf-transform inspect
    on the shower model (sorry about the messy formatting):

     
    Last edited: Feb 18, 2021
  25. JudahMantell

    JudahMantell

    Joined:
    Feb 28, 2017
    Posts:
    476
    Thanks for the incredibly detailed response! Because the model was straight up downloaded from Sketchfab, I had no idea what it was made of, so I understand a lot better now. I will also look into try/catch blocks and see if I can implement them.
     
  26. daniel-md

    daniel-md

    Joined:
    Jan 26, 2015
    Posts:
    6
    Hi @awesomesaucelabs, first of all thank you very much for this truly awsome package! I just bought it and am very happy that it performs very well where other gltf-importers I tested do not! :)

    One question though: I was wondering why my imported models do not render shadows and then saw that you included the pragma noshadow keyword in your shaders -- is there a specific reason behind it or could it safely be removed?
     
  27. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Hi @daniel-md,

    Thanks for the compliment! I've been working on Piglet for about a year and a half now (full time), so it's very gratifying to hear that it is working well for people.

    Yes, I think you could safely enable shadows, lightmaps, etc. I haven't done any testing with shadows so I'd be interested to hear if you run into any issues.

    I turned off most of the optional features when I was writing the shaders because I was a shader noob at the time (maybe I still am), and I was pretty overwhelmed by all of the options. I figured it was safest to start with a vanilla shader setup and then make improvements from there.
     
    DerrickBarra likes this.
  28. ulralrafinger

    ulralrafinger

    Joined:
    Jun 14, 2018
    Posts:
    1
    Thank you~. This is a very good asset.
    Do you have any plans to develop an glb exporter?
     
  29. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Thanks, @ulralrafinger!

    Several people have also asked me to add glb export functionality, or asked how they could "create prefabs at runtime". I'm not sure exactly what types of games/apps those people were developing, but nonetheless I can see how export functionality could be useful, especially since neither Unity prefabs or asset bundles can be created/exported at runtime. For example, multiplayer games/apps could use glb export to share models with the other players at runtime, which aren't baked into the build.

    I will give some thought to adding exporter functionality, but it looks like I will be busy with other work for at least a couple of months, e.g. bug fixes, Draco compression, support/testing for more platforms (e.g. iOS). IMO, it is important for me a do a good job on the importer side first, before I expand my scope.

    In the meantime, I think your best option is to use a separate asset for glTF export, if any are available. I've noticed this one, although I haven't tried it: https://github.com/Plattar/gltf-exporter
     
  30. Pode

    Pode

    Joined:
    Nov 13, 2013
    Posts:
    145
    @awesomesaucelabs Just some quick information : Plattar is indeed a good exporter, and with the 'cleanest' output I think available on Unity right now. However it's working at edit time, not at runtime.
     
  31. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    I see. Thanks for the valuable info, @Pode!
     
  32. DannyWoo

    DannyWoo

    Joined:
    Oct 25, 2012
    Posts:
    24
    Unity Version 2020.3.0f1

    i made a .glb animation at http://monstermash.zone/#
    and it is working well in blender as attached PIC
    but it is broken in your piglet plugin always
    do u have any suggestions?

    and also it wasn't working on you webdemo

    but is is working well at https://gltf-viewer.donmccurdy.com/

    ===================================================
    i haven't time waitting for your ansawer so i'm using this one
    https://github.com/Siccity/GLTFUtility
    it is working for me with small modification

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class SkinedMeshAniamtion : MonoBehaviour
    {

    int aniFramCOunt;
    SkinnedMeshRenderer SMR;
    // Start is called before the first frame update
    void Start()
    {
    aniFramCOunt = GetComponent<SkinnedMeshRenderer>().sharedMesh.blendShapeCount;
    SMR = GetComponent<SkinnedMeshRenderer>();
    StartCoroutine(startAnimation());
    }


    IEnumerator startAnimation()
    {
    int idx = 0;
    while (true)
    {
    SMR.SetBlendShapeWeight(idx, 1);
    yield return new WaitForSeconds(0.05f);
    SMR.SetBlendShapeWeight(idx, 0);
    idx++;
    if (idx >= aniFramCOunt) idx = 0;
    }
    }

    }
    ==========================================
    anyway i'm waitting for your reply caz i payed 30$ to you aleady~
     

    Attached Files:

    Last edited: Mar 14, 2021
  33. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Hi @DannyWoo,

    Sorry to hear that Piglet isn't loading your model correctly!

    I would be happy to send you a refund. Just send me the e-mail address for your PayPal account and I will send the money back to you. (You can send me a private message on this forum or e-mail me at awesomesaucelabs@gmail.com.)

    Would you be able to share the glTF file for your tree model with me, so that I can debug it? I would love to use it as a test case to improve my importer, and hopefully I can fix it for you. (If you want, you can send the file to me privately at awesomesaucelabs@gmail.com.)

    I noticed in your original post that you mentioned the error "Exception: Piglet failed to load URP shader "Shader Graphs/URPMetallicRoughnessOpaque". Just in case you did not already solve it, you just need to double-click
    Assets/Piglet/Extras/URP-Shaders-2020.2.unitypackage
    file to unpack the URP shaders into
    Assets/Piglet/Resources/Shaders/URP
    . (I can't include the URP shaders in unpacked form because they cause compile errors in Unity projects that use the built-in render pipeline.)
     
    Last edited: Mar 14, 2021
    pranshu_unity likes this.
  34. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @DannyWoo,

    Thanks for sharing the code above, btw. It helps me narrow my debugging to blendshape weights/animation.

    I've tested blendshape animations before, but there must be something different about this particular model.
     
  35. Makio64

    Makio64

    Joined:
    Nov 9, 2014
    Posts:
    27
    @awesomesaucelabs
    Hi, it looks really promising!

    Do you have a deadline in mind for the implementation of Draco support ?

    Best
    D
     
  36. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    Hi @Makio64!

    No hard deadline, but I expect to make a release with Draco support in April. I've been working on Draco support for the past few weeks and its going well so far.

    I know lots of people have been waiting for Draco support!
     
  37. john_goren

    john_goren

    Joined:
    Mar 19, 2021
    Posts:
    15
    Thank you for the lovely plugin. After experiments with mysterious and under-documented solutions, this one did the trick. I was heartened to try the software by how friendly this thread was.
     
  38. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
  39. DerrickBarra

    DerrickBarra

    Joined:
    Nov 19, 2013
    Posts:
    210
    @awesomesaucelabs BTW found a bug in Unity 2021.1.1f1 in Piglet 1.2.0 within TextureUtil.cs ReadTextureEnum().

    Basically, UnityWebRequestTexture objects no longer have their .data field filled out on a successful texture retrieval. So you need to make a separate UnityWebRequest to check if the file is KTX/BASIS, and then if it's not, load it with a normal UnityWebRequestTexture object.

    Code (CSharp):
    1. /// <summary>
    2.         /// Coroutine to load a Texture2D from a URI.
    3.         /// </summary>
    4.         /// <returns>
    5.         /// A two-item tuple consisting of: (1) a Texture2D,
    6.         /// and (2) a bool that is true if the texture
    7.         /// was loaded upside-down. The bool is needed because
    8.         /// `UnityWebRequestTexture` loads PNG/JPG images into textures
    9.         /// upside-down, whereas KtxUnity loads KTX2/BasisU images
    10.         /// right-side-up.
    11.         /// </returns>
    12.         static public IEnumerable<(Texture2D, bool)> ReadTextureEnum(Uri uri)
    13.         {
    14.             // Note!: Using `UnityWebRequestTexture`
    15.             // is preferable to `Texture2D.LoadImage`
    16.             // because it does not block the main Unity thread.
    17.  
    18.             var request = UnityWebRequest.Get(uri);
    19.             request.SendWebRequest();
    20.  
    21.             while (!request.isDone)
    22.                 yield return (null, false);
    23.  
    24.             if (request.HasError())
    25.                 throw new Exception(string.Format(
    26.                     "failed to load image URI {0}: {1}",
    27.                     uri, request.error));
    28.  
    29.             var data = request.downloadHandler.data;
    30.  
    31.             if( IsKtx2Data( data ) )
    32.             {
    33. #if KTX_UNITY_0_9_1_OR_NEWER
    34.                 foreach( var result in LoadKtx2Data( data ) )
    35.                     yield return (result, false);
    36. #elif KTX_UNITY
    37.                 Debug.LogWarning("Failed to load texture in KTX2 format, "+
    38.                      "because KtxUnity package is older than 0.9.1.");
    39.                 yield return (null, false);
    40. #else
    41.                 Debug.LogWarning("Failed to load texture in KTX2 format "+
    42.                     "because KtxUnity package is not installed. Please install KtxUnity "+
    43.                     "by following the directions at https://github.com/atteneder/KtxUnity "+
    44.                     "(requires Unity 2019.3+).");
    45.                 yield return (null, false);
    46. #endif
    47.                 yield break;
    48.             }
    49.             else
    50.             {
    51.                 //Image is not a KTX2/Basis texture, load it as a .png/.jpg instead
    52.                 request = UnityWebRequestTexture.GetTexture( uri, true );
    53.                 request.SendWebRequest();
    54.  
    55.                 while( !request.isDone )
    56.                     yield return (null, false);
    57.  
    58.                 if( request.HasError() )
    59.                     throw new Exception( string.Format(
    60.                         "failed to load image URI {0}: {1}",
    61.                         uri, request.error ) );
    62.  
    63.                 Texture2D texture = DownloadHandlerTexture.GetContent( request );
    64.  
    65.                 yield return (texture, true);
    66.             }
    67.          
    68.         } //END ReadTextureEnum
     
  40. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @DerrickBarra,

    Sorry for the trouble, and thanks very much for reporting this. (And for sharing your fix as well!)

    I'll test this on my end and include your patch (or similar) in the next Piglet release.

    I didn't even know that Unity 2021 was out yet -- I guess I need to set up some email/RSS notifications.
     
  41. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @DerrickBarra,

    FYI, it looks like adding a null check is enough to fix the issue, i.e. change

    Code (CSharp):
    1. if (IsKtx2Data(data))
    to:

    Code (CSharp):
    1. if (data != null && IsKtx2Data(data))
    Really appreciate the heads up about this, since it completely breaks Piglet in Unity 2021.
     
  42. DerrickBarra

    DerrickBarra

    Joined:
    Nov 19, 2013
    Posts:
    210
    I might be mistaken, but you'll need to use the entire script change.

    In Unity 2021, UnityWebRequestTexture objects no longer get their .data object filled when the request completes. This might actually be a Unity bug since it's not mentioned in the docs anywhere. This means that you need to use both a UnityWebRequest to check the initial .data object for .ktx and a separate UnityWebRequestTexture to get the actual texture if it's a .jpg or .png.
     
  43. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @DerrickBarra,

    I agree that it is surprising, but the null-check fix seems to work. For whatever reason, the `.data` field is only null/unitialized when the data is in PNG/JPG format. I agree, it is probably a bug in Unity.

    So far I have only tested the null-check fix in the Editor, with both drag-and-drop glTF imports and runtime imports (using Piglet/Examples/RuntimeImport scene), and with both KTX2 and non-KTX2 glTF files. I'm in the process of doing similar tests for Windows standalone builds, Android builds, and WebGL builds.
     
  44. DerrickBarra

    DerrickBarra

    Joined:
    Nov 19, 2013
    Posts:
    210
    @awesomesaucelabs Well that's interesting, I wasn't aware that the .data field is still valid when loading a .ktx/.basis file.
     
  45. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    FYI @DerrickBarra (and anyone who is watching):

    All better now.

    I've just published Piglet 1.2.1 with the null check fix, and Piglet is working well in Unity 2021 now.

    Thanks again for your help!
     
  46. DerrickBarra

    DerrickBarra

    Joined:
    Nov 19, 2013
    Posts:
    210
    @awesomesaucelabs FYI I tried out the version of TextureUtil.cs with Piglet 1.2.1, and noticed the following issue loading up a GLTF .zip file with KTX2/Basis textures...

    upload_2021-4-9_8-50-21.png

    And here's the same model loaded using TextureUtil.cs ReadTextureEnum() from my script above.

    upload_2021-4-9_8-49-29.png

    And for reference, here's the horse loaded on the latest WebGL Piglet tester.

    upload_2021-4-9_8-53-51.png
     
    Last edited: Apr 9, 2021
  47. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @DerrickBarra

    I'm very surprised by that! (I *did* test it before I pushed the release...)

    I'm trying to reproduce your red and white render on my end now.

    Is your red and white pic from a WebGL build with Unity 2021.1.1f1? If so, any warnings in the web console?

    Piglet uses white textures when KtxUnity is not installed, but I'm not sure where the redness comes from!
     
  48. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @DerrickBarra

    BTW, the Piglet web tester is still using Piglet 1.2.0.
     
  49. DerrickBarra

    DerrickBarra

    Joined:
    Nov 19, 2013
    Posts:
    210
    @awesomesaucelabs : Those screenshots were from my Unity 2021.1.1f1 editor. I can create a nearly empty test project to show off the bug if you can't recreate it on your end.

    And yeah, the Piglet web tester being on 1.2.0 made it a good test, because it showed that the older version of Piglet could load the KTX texture.
     
  50. awesomesaucelabs

    awesomesaucelabs

    Joined:
    Aug 6, 2019
    Posts:
    191
    @DerrickBarra

    Unfortunately (or fortunately?), I'm still not able to reproduce the bug on my machine (Windows 10). Here's what I tried:

    (1) created a fresh project with Unity 2021.1.1f1
    (2) installed Piglet 1.2.1 from the Asset Store (Package Manager window)
    (3) installed KtxUnity 1.0.0 using the installer link from the GitHub README
    (4) drag-and-dropped the horse_KTX2.zip file into `Assets` folder

    Resulting prefab looks correct.

    I also did a WebGL build and the model loaded correctly there too.

    A minimal project to reproduce the bug would be very helpful! (Sorry to take up your time like this, btw! If you've got other stuff you need to be doing, I would certainly understand.)

    Aside: In the case of loading a KTX file from a .zip, TextureUtil.ReadTextureEnum doesn't even get called! The texture instead gets loaded by TextureUtil.LoadKtx2Data(data) at GltfImporter line 463. (The control flow for loading textures is more complicated than I would like, mostly in an effort to get the best possible performance.)
     
    Last edited: Apr 9, 2021