Home Unreal Engine

UE4 FBX Importer

13
EDIT: This was originally split off from the Handplane3D thread requesting a UE4 preset for Handplane. It's now discussing some apparent faults in the way UE4 calculates tangents on imported FBX files.



I think that's probably because UE3 is (still?) unknown in terms of tangent basis so Handplane was close but not quite. UE4 has a clearly defined tangent basis.

Personally I'd prefer to use Handplane over xNormal's obj-to-tangent converter tool as Handplane's much faster and easier.

Replies

  • Son Kim
    Offline / Send Message
    Son Kim triangle
    UE4 is a totally different beast, its vastly more popular than UDK :) - I look forward to handplane support for UE4 it seem UE4 isn't even sync with Mikk-TSpace?!

    It's Quack's file with baked with Xnormal 3.19.8
    If you want to bake your own: https://copy.com/TO16UFcRkhU1KTXk
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Blender Game Engine works correctly as well, kappa.3clInrz.png

    Interestingly enough, if you export the .fbx from Blender (which uses mikktspace natively) and include tangents and bitangents, and then import those tangents and bitangents into UE4, it just happens that the normal map we baked against the .fbx with no exported tangents works perfectly!

    EiiIVbw.png

    (mesh from Blender on the right, mesh from Quack on the left)

    Which seems to indicate that there's a problem with the mikktspace calculator within UE4's importer, since the tangents seem to work OK when they come from Blender's native MikkTSpace.

    gtBqL2d.png

    Oh bother, look at those gratuitously split tangent vectors. This does seem to be a bug after all! In the meantime, you can just export everything from Blender with tangents and import those tangents and bitangents into UE4, then when they come out with the fix for this you can go back to your regularly scheduled pipeline.
  • Farfarer
    Yeah, I spotted those tons of splits on a test mesh I was using.

    I thought it was an issue with Modo's FBX exporter... looks like it might be UE4's FBX importer.
  • Son Kim
    Offline / Send Message
    Son Kim triangle
    @JedTheKrampus - Thanks for testing! Could you post your findings here also: https://answers.unrealengine.com/questions/14375/normal-map-workflow-with-xnormal-is-not-working.html

    Same to Farfarer, we need to get fresh eyes on this and bump that thread.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    OK, I've posted my findings there. I'm also stepping through their FBX import code to see if I can help to isolate the problem further.
  • Farfarer
    I've posted up my results, too. I've had a look through the code, but didn't get very far going through it on Github... I'll need to download it and look at it locally I think.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    I've found that the tangent splitting has nothing to do with UV seams.

    iV03DJi.png
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    In my debugging adventures, I've found that it's possible to create static mesh sockets in Blender by creating an empty and naming it with the prefix "SOCKET". However, the imported socket only shows up at the origin with a .fbx from Blender. I'm making a note to myself to figure out later whether it's a bug with Blender .fbx, a bug with Unreal .fbx, or an intended behavior.

    xKQQnRh.png
  • Farfarer
    Should probably move this to a new thread in the Unreal subforum.
  • Son Kim
    Offline / Send Message
    Son Kim triangle
    Farfarer wrote: »
    Should probably move this to a new thread in the Unreal subforum.

    +1 Agreed, can a mod move our post to the Unreal subforum? Or how should we do this? And thank you guys for posting on AnswerHub!
  • Geezus
    Offline / Send Message
    Geezus mod
    I've merged the last posts to a separate thread named UE4 FBX Importer, here in the Unreal subforum. Let me know if you want any further changes.
  • Farfarer
    Cheers dude :)

    Jed: I've not seen issues directly related to sharp angles. Quote of my reply on the UE4 Answers;

    I'm not sure. I've tried some tests based on that and I can't seem to get 90 degree angles to do anything strange. I get tons of tangent splits where I have UV splits, though. Give this mesh a look over, should show what I mean.

    Bottom row is just a bunch of planes that meet at different angles. Next row up is those joined up to triangles at the side. Next row up is the same, but unwrapped with UV splits and BAM tons of tangent splits. Top one is them as closed surfaces and there's tangent splits with those too because of the UV splits.

    Angle Test Mesh
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    I think that line 570 of UE4/Source/Editor/UnrealEd/Private/FBX/FBXStaticMeshImport.cpp may be an area of interest, based on my debugging efforts. I think part of the problem is that UE4 (as far as I can tell) calculates tangent vectors many times for each vertex, I think once for each triangle the vertex is touching, and it doesn't merge the tangents into one vector, hence the egregious tangent splitting. I'm wondering if it might ameliorate our issues if we went through each unique vertex and looked up all the tangents for each of them, then normalized that sum and set that as the tangent.

    I've been doing additional testing of my own, comparing Mikktspace tangents exported from Blender to tangent space vectors calculated by Unreal. You can see that there's quite a bit of splitting going on all over the place in the mesh that UE4 is calculating tangents for, and not necessarily on the UV borders.

    UE4 calculated:
    O7SfZZw.png

    Imported MikkTSpace from Blender:
    eEzQKkV.png

    I don't think there's actually a single tangent vector in the UE4-calculated version of this monkey that's properly merged. Will investigate further when I get home and see if I can figure out what the real solution to all this is.
  • Farfarer
    Good hunting, I'll check out that area of the code tomorrow.

    But yeah, the tangent should be summed (and orthonormalised) for each vertex that shares the same properties (position, normal, UV). Looks like it's not.
  • Farfarer
    So the actual code that generates the tangents is found in a method called ComputeTangents in MeshUtilities.cpp at (or around) line 1586.

    I'll have a peruse through that and see if anything strange is happening.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    zNZAeXg.png

    Usually if there are that many braces in a row, there's a good chance that someone has made a mistake somewhere.
  • MeshMagnet
    Offline / Send Message
    MeshMagnet polycounter lvl 9
    Can someone give me a TLDR of what's going on here?

    Is the FBX importer on the 4.5 release bugged? Or is this more specific to Blender and Handplane?
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    The FBX importer on the 4.5 release is bugged. It leaves tangent vectors split in some places where it shouldn't, which leads to shading errors in some cases, but as far as I can tell the Mikktspace calculation itself is correct other than that. I think it might have to do with UE4 not being able to infer smoothing continuity properly when it doesn't detect that your .fbx has smoothing groups.

    While we're working on a fix, if you notice shading errors in your mesh and you've baked the normal maps in Xnormal, just use the old-school synced workflow of exporting tangents from your DCC app, baking in Xnormal with those exported tangents (which Xnormal does automatically if you've exported tangents), and importing your mesh into UE4 with the "Import Normals and Tangents" option.
  • Farfarer
    Yeah, it's not finding the polygons that each vertex should get it's tangent vectors from. So it's instead creating tangents at each vertex for each polygon, target than a normalised sum of all the polygons of the vertex.

    Unfortunately, I can't use the "fix" because MODO doesn't export tangents and binormals :/
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Blender is free and can export the tangent space. Why not just use it as a stopgap? (Unless you're making foliage and you need custom normals, of course.) Plus, when we figure out the real fix, you won't have to rebake everything because it was already in Mikktspace.
  • repete
    Offline / Send Message
    repete polycounter lvl 6
    Honestly I can't take this shit any more guys, what the fuck is the point in doing game art ?

    I know everyone is doing their best here but if a standard cannot be reached then we seem to be pissing into the wind.



    qRswh6K.gif
  • Farfarer
    It's just a bug, dude. Not the end of the world.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Shh, shh. It's going to be OK. No one's X.509 certs and private keys are going to get stolen because UE4's tangent space calculation is slightly wrong. :)
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Perhaps this may be of interest to you--I was able to import Quack's model as well as the standard monkey, with UE4 importing normals and calculating tangents and no tangent space splits.

    See:

    GWz3ygF.png

    All you have to do is import it as a skeletal mesh and everything works fine. Well, except for stationary and static lights and distance fields. This leads me to believe that the issue probably isn't within the ComputeTangents method itself, but perhaps somewhere a little further up the call stack. I'm going to compare the way that static and skeletal meshes are built and see if I can learn anything.
  • Son Kim
    Offline / Send Message
    Son Kim triangle
    Perhaps one of you should start a new thread about this on AnswerHUB as its not really related to Xnormal, beside that thread hasn't receive any bump from Epic.

    Is there a way to save smoothing group(or Maya style edge/soft edge) along with tangents in blender?
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Yes, you can do Maya-style hard/soft edges in Blender pretty easily (more easily than vanilla Modo at least), and they export to UE4. Unfortunately, you can't just import your .fbx and export it; you have to set up the smoothing in Blender instead.

    dkGYV7c.png

    Let's say I've modeled a beveled box in Modo and I want to take it through to Unreal Engine 4, with hard edges where I have UV splits. If I import it into Blender from the File menu, I get a fully smoothed box with UVs. If I right-click the cube to make it my active object, then press Tab to enter edit mode, I'll be able to set specific edges as 'sharp.'

    The fastest way to get this done after you've gone into Edit Mode with Tab is to select everything (A key), press Space to bring up the text search, type part of "Seams from Islands", and click the Seams from Islands button that comes up.

    Ex4kJfR.png

    Then, deselect everything with A, press Ctrl+Tab to bring up subobject modes and click Edge (or press E).

    xdnuwWq.png

    Right-click to select an edge that was marked as a UV split (they're red), then press Shift+G to bring up a Select Similar menu. Pick Seam from that menu to select all your edges that have UV splits.

    zQ1oFAz.png

    Then hit space and type "Mark Sharp" (or find the buttons for it on the toolbar to the left as I've indicated.) You'll see all your UV splits become bright green, which means that they'll be exported as hard edges.

    pm84Fhq.png

    If you're wondering why the sharp edges don't show up in the viewport, you have to go to a particular tab and check the Auto Smooth box for them to show up. But they'll be exported, and that's what matters most. Here's the box you have to check. Also make sure that smoothing angle is set to 180 degrees, so you have full control over sharp edges.

    FTrCFCS.png

    At this point you can select any edges that the previous process made sharp that you actually want to be smooth, and click the Smooth button under Edges. You can speed up the selection process by using loop select (Alt+Right Click), select shortest path (Ctrl+Right Click), box select (B, then LMB-drag to select more things, MMB-drag to select fewer things, or RMB to cancel), and circle select (C, then LMB-drag, MMB-drag, and RMB do the same things, as well as the scroll wheel which increases and decreases the size of the brush.) If you want to be able to select through your model, press Z, which toggles between wireframe and shaded modes and also has the side-effect of toggling raycast selection.

    Once you've got everything smoothed the way you want it, toss a Triangulate modifier at the end of the stack and exit Edit mode if you want. This ensures that the tangent space is correctly exported and that all the bakes are correct.

    GQlkrFJ.png

    Finally, export a .fbx from the file menu. Make sure that selected objects is checked, apply modifiers is checked, and tangent space is checked. Everything else should be OK out of the box (although you may want to increase the scale to 100 as well, depending on how the mesh imported from Modo. You can change the import scale in UE4 as well and it works well.)

    INMXVuN.png

    When you take the model to UE4, make sure that you've set the importer to import normals and tangents. Otherwise, you'll get split tangents as usual.
  • Farfarer
    Perhaps this may be of interest to you--I was able to import Quack's model as well as the standard monkey, with UE4 importing normals and calculating tangents and no tangent space splits.

    See:

    GWz3ygF.png

    All you have to do is import it as a skeletal mesh and everything works fine. Well, except for stationary and static lights and distance fields. This leads me to believe that the issue probably isn't within the ComputeTangents method itself, but perhaps somewhere a little further up the call stack. I'm going to compare the way that static and skeletal meshes are built and see if I can learn anything.
    Interesting, I'll see what differences there are between them.
  • Son Kim
    Offline / Send Message
    Son Kim triangle
    @JedTheKramus

    thanks for the run down! I'm a modo user so I don't know my way around blender.

    I just got a reply

    "Sorry for the delay in response, I was away on vacation. I have Eric looking into this now. He will be able to help you resolve the problem.

    Let me know if you need any help again.

    -Alexander"

    I forwarded this thread to Alexander to give to Eric, since there isn't a answerHUB thread for it other than Quack's thread.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Farfarer, have you figured out yet exactly what a "wedge" is?
  • Farfarer
    Far as I can tell, it's just a vertex.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    I figured out why the monkey mesh from Blender had so many tangent space splits. It's because exporting the mesh with smoothing 'off' to export the tangent space led to all the smoothing group flags being set to zero, which means that the following condition in ComputeTangents can never be met:

    if ((NextFaceIndex != OtherFaceIdx)
    && (RawMesh.FaceSmoothingMasks[NextFace.FaceIndex] & RawMesh.FaceSmoothingMasks[OtherFace.FaceIndex]))

    So, that's that. If I export the monkey mesh with smoothing set to Edge I can still spot some tangent space splits, but everything that's off a UV split is A-OK. The exported tangent basis works OK, though, and it's a good reference for what mikktspace tangents look like. As far as I'm concerned this is probably something that I'll want to discuss with mont29, since he knows a lot more about Blender's FBX export than I do.

    I've created a more minimal 2-manifold mesh that reproduces the problem. Quack's is kind of a pain to step all the way through. This one is six triangles, which is still a bear but is a bit more doable. Here's the mesh with the tangent space imported from Blender (no smoothing group data included.) This is the tangent space that a correct MikkTSpace implementation would calculate.

    jF6Kuwv.png

    This is what UE4 calculates. ("Smoothing groups" in this file, and no tangent space.)

    6XhC6lo.png

    You can see that there are splits in the one where there aren't splits in the other. I'm pretty sure at this point that you were right about the split tangents having to do with UV splits not being handled correctly, so all we have to do now is step through the code with this more minimal mesh and see if we can figure out where it goes wrong.

    You can download the test meshes here:

    Face smoothed (import normals and no tangents to reproduce problem)
    https://mega.co.nz/#!xE12iCAR!sw3tsl6HWjdLMe5-wwulCHV_DT5fzJDHuXAn3vDXzZs

    Smoothing off and tangent space exported (import normals and tangents to have a reference of the correct tangent space)
    https://mega.co.nz/#!FJcAnRbJ!e_A4nH1QhwcVq_wCEZxD5eQIXwTcC2s2rzLlu0UODtg

    Cheers,

    Jed
  • Farfarer
    I'm exporting from MODO and it's saving the smoothing group info just fine, and it's still broken.

    I think the issue probably lies in that code somewhere, though. I had a look at optimising the mesh further up the chain, but that'd only work if all of the UV maps shared the same boundaries, so I can see why it needs doing this way.

    Still need to get a chance to go through the code thoroughly. Kind of annoying that a lot of the array contents aren't viewable in debug.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    I think that UE4 only checks UV boundaries in the first UV set. Don't remember where I saw it, but it was somewhere in there. I'd have to do some serious testing to see whether this is actually a problem, and I have a pretty strong hunch that it's not.

    There are definitely still problems if you save the smoothing data, I never denied that. Should probably clarify: It's just that there are some vertices that are altogether far from a seam, and have their tangents correctly merged if the mesh has smoothing group data saved. With smoothing set to 'off' in Blender, RawMesh.FaceSmoothingMasks is set to zero throughout the mesh, which means that none of the faces get marked for tangent smoothing at all, so every vertex has split tangents. Setting smoothing to 'edge' or 'face' means that RawMesh.FaceSmoothingMasks is generally set to 1, which means that UE4 can at least think about merging the tangents (and it does, in a lot of cases, but not everywhere that it matters.)

    As far as seeing array contents, I haven't really had any problems. You can see the contents of the array that has the tangents, but the problem is that the section of the code that isn't doing its job right doesn't actually touch the arrays. We need more faces that are marked with bBlendTangents = true than we have right now, and that happens in that section of code that has the ridiculous number of terminating braces that I was making fun of before.
  • Farfarer
    Yeah, you might be right.

    So this is the simplest mesh I can think of that clearly shows the issue.

    Going to start debugging the import process of this and see if I can figure out what's up... (once the damn thing's finished building).
  • Farfarer
    So I've managed to get it blending the tangents that should be blended, and not blending those that shouldn't \o/

    Although I'm not certain about their correctness - I'm getting slightly hard seams around the UV edges and I'm not sure why yet. Even if I make those edges hard and re-bake.

    Bit of a hack, I'll need to go through it a bit more carefully to see if it's actually correct.
  • MeshMagnet
    Offline / Send Message
    MeshMagnet polycounter lvl 9
    It looks like Epic just released 4.5.1.

    Does anybody know if they address this issue with the update?
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
  • Farfarer
    So two responses from UE4 staff and both of them claim this is "as designed". So doesn't look like we're going to get any help from them.
  • Son Kim
    Offline / Send Message
    Son Kim triangle
    Farfarer wrote: »
    So two responses from UE4 staff and both of them claim this is "as designed". So doesn't look like we're going to get any help from them.

    Yup, it's disappointing. Thanks for fixing it and submitting a pull request! hopefully the PR will work on most mesh cases.
  • WarrenM
    Hey, the programmers here say they don't see a pull request for this. If you haven't put it in, please do! They want to take a look.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Yeah, put up your pull request! I really want to see a fix for this soon.

    After a couple of days working on this, I'm coming to the conclusion that it could be beneficial to integrate Mr. Mikkelsen's code that calculates MikkTSpace tangents. The methods used in ComputeTangents seem mostly OK to me, but if we do fix this particular bug with the tangent space computation on static meshes, who knows what other subtle problems will be there that are insidious and difficult to detect? It's better to use the reference implementation, in my opinion, and be sure that, if there are any defects in the tangent space computation, that at least they will be consistent with the defects that are in all the other implementations.

    It's free for commercial and non-commercial use, an extremely permissive license. The only real stipulation is that if you redistribute an altered version, you mustn't solely attribute the code to Mr. Mikkelsen.

    See: https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/mikktspace.c
    https://svn.blender.org/svnroot/bf-blender/trunk/blender/intern/mikktspace/mikktspace.h

    For instructions on the integration process itself, this post is helpful as a starting point:
    http://coremega.tumblr.com/post/5707679685/mikktspace-for-normal-mapping

    I've been working on my own integration of this for the past day or so in my free time, but I'm running into a rough patch with UnrealBuildTool and precompiled headers. Pretty sure I'm on the verge of figuring it out, though. It's really a better solution, in the long term, to integrate this rather than whatever band-aid patches Farfarer or I might come up with, for both static and skeletal meshes, although I can appreciate that you guys are constantly on a tight release schedule and don't necessarily have the time to do everything right.
  • Farfarer
    I haven't put a pull request in yet. I'm still working in rewriting the function St that it works with meshes that have imported or calculated normals.

    Mostly trying to wrap it around the general framework that's there as I'm not really au fait with the full mesh import pipeline.

    No point submitting a fix that doesn't fix everything.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Aight, I think I've got my patch working as well, it calculates tangents correctly with the reference MikkTSpace implementation with my pyramid as well as Quack's test mesh.

    See:

    UhDk1bU.png

    I want to test this further, including with some more complex and non-manifold meshes to make sure that everything works correctly with .fbx files from programs that aren't Blender and I haven't broken any other part of the pipeline. One other nice thing about my implementation is that it doesn't fail if the smoothing groups are all set to zero :> But for that testing to happen, I have to work on my desktop, and for that to happen this World Series game has to end.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    My initial tests are encouraging. I find that importing a pretty typical 44-triangle custom normals cube made in Maya with its tangent basis gets a vertex count of 46 with its tangents imported from Maya. With the old UE4 tangent space calculation method, it gets a vertex count of 62 from tangent splits. With the new MikkTSpace reference tangent space calculation, it gets a vertex count of 38. I also haven't changed how the tangent and normal recomputation options work from vanilla 4.5, which is good. So all I need to do is change the GUID for MeshUtilities and I can put up my pull request.
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    OK, my pull request is up!

    https://github.com/EpicGames/UnrealEngine/pull/561

    I look forward to getting this fixed as soon as possible.
  • Farfarer
    Nice one, I think you've done one better than me.

    I was just trying to make sure the tangents blended, bit implementing MikkTSpace itself is probably the way to go :P
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    I would certainly appreciate it if you would give the patch the old test-around-a-roo. I can't find any problems with it myself, but that doesn't mean that it's problem-free.
  • haiddasalami
    Offline / Send Message
    haiddasalami polycounter lvl 14
    // if you've worked at valve you'd better not read this method

    Haha. Awesome job!
  • Farfarer
    Just tested it with an xNormal bake on a single-smooth-group cube out of Modo. Perfect results. Well played, dude :)

    However, the Y/green channel used to have to be flipped and now it doesn't.

    That's technically good because now it matches the +X+Y+Z output from xNormal (as it should) but skinned meshes are not using this proper MikkTSpace implementation.

    So I skinned the cube I tested on to a bone and imported it as a skeletal mesh. But now it's normal map is incorrect and needs it's green channel flipping (I'm using the same material and normal map from the original cube I tested).

    Might need to have either skeletal meshes use this same thing, or have the static mesh implementation work with X+Y-Z+ maps as default.

    I'm not sure which is preferable for Epic. Really, they should fix all their normal maps and adopt this new version - have it done correctly - but that might piss off a lot of people :P
  • JedTheKrampus
    Offline / Send Message
    JedTheKrampus polycounter lvl 8
    Yeah, that would be a lot of re-baked normal maps. I can't believe I missed that! I'm so used to checking and unchecking the "flip green channel" button in the texture editor when things look wrong that I forgot to check it this time. Shouldn't be too hard to fix, though.
13
Sign In or Register to comment.