playcanvas / editor

Issue tracker for the PlayCanvas Editor
https://playcanvas.com/
150 stars 28 forks source link

UV auto-unwrap is not supported for GLB model assets #194

Open devcem opened 3 years ago

devcem commented 3 years ago

Auto-unwrap pipeline doesn't work for GLB file format, only JSON (after PlayCanvas generation) files can be auto-unwrapped. There is no error, I tested same model with JSON and GLB file format, auto-unwrap function doesn't do anything for GLB files.

I can provide sample files, but I believe it's valid for all GLB formats.

willeastcott commented 3 years ago

Exactly right, @devcem. Thanks for logging this. I mentioned this to the team at the end of last week, so it's a known issue. For now, I guess consider sticking to JSON for models that require UV unwrap or maybe just generate your unwrapped UV1 in Max/Maya/Blender. At this point, I can't really give an ETA for a fix because we'd need to assess potential solutions first.

valentincognito commented 3 years ago

I was so happy to see GLB integration but this problem really prevent us from using the new format. If anyone knows a temporary fix on the 3d softwares side it would be awesome to share it here :-)

valentincognito commented 3 years ago

For anyone out there needing a temporary solution I may have one. Not sure if it's the best solution but it works for me. I created a quick python script for blender that imports all fbx from a folder, add a new uv map called uv1 (could be named differently) and re-export the fbx with their original names. If you import again in playcanvas the "missing uv1" error will still be here but the lightmapping works !

import bpy
import os

context = bpy.context
scene = context.scene

models_dir="C:/my_fbx_folder_path/"

for root, dirs, files in os.walk(models_dir):
    for filename in files:
       bpy.ops.import_scene.fbx(filepath=models_dir+filename)

        bpy.ops.object.select_all(action='DESELECT')

        for o in bpy.context.scene.objects:
            if o.type == 'MESH':
                o.select_set(True)
                #we need at least one active mesh to be able to use the join function
                context.view_layer.objects.active = o
            else:
                o.select_set(False)

        #joining all the meshes from the current object
        bpy.ops.object.join()

        #add a new UV layer and smart unwrap with options that seem to work with playcanvas
        bpy.ops.mesh.uv_texture_add()
        bpy.ops.object.editmode_toggle()
        bpy.ops.mesh.select_all(action='SELECT')
        bpy.ops.uv.smart_project(island_margin=0.2, user_area_weight=0, use_aspect=False, stretch_to_bounds=False)

        #export and overwrite the FBX
        bpy.ops.export_scene.fbx(filepath=models_dir + filename, use_selection=True)

        #delete everything from the scene
        bpy.ops.object.editmode_toggle()
        bpy.ops.object.select_all(action='SELECT')
        bpy.ops.object.delete()

Note that you can achieve the same result without scripting, just select your mesh in blender, go to object data properties -> UV Maps and add a new map to the list !

slimbuck commented 3 years ago

Thanks for this @valentincognito that's just great!

@willeastcott I was thinking we can add a GLB import option to generate these at conversion time. Would that work?

willeastcott commented 3 years ago

@slimbuck For sure, UV1 generation on import makes sense to me.

valentincognito commented 3 years ago

I may have spoken too fast.. Adding a new UV map in blender actually fix the light mapping and we can see the object actually receives light and shadow but some shadows seem wrong / broken.. It would help to understand what the auto unwrap button exactly does in the editor to be able to reproduce it in a 3d software

slimbuck commented 3 years ago

Hi @valentincognito,

Unwrap UV generates a new set of UVs that map all polygons of a mesh to unique parts of a texture (i.e. no overlapping or repeats in UV space). This makes sense if we want to store lighting in a texture and have it be unique across all surfaces.

You may want to check that blender did the same when you generated the UV map, because if not then you might find lighting sometimes looks correct and sometimes not.

Thanks

slimbuck commented 3 years ago

I haven't read the whole article, but you can see https://conceptartempire.com/uv-mapping-unwrapping/ for a better explanation :)

slimbuck commented 3 years ago

Would just add that the 'Unwrap UV' option in the editor is just a convenience (as you've found out) since you can always generate the UVs in your modelling package.

valentincognito commented 3 years ago

@slimbuck I know what UV unwrapping is :-) What I was saying is that it would be helpful to know which "options" are used by the auto unwrap feature from the editor. Because in 3d software there are many different ways to do an auto unwrap and all of them have different results when imported in playcanvas.

That being said I think I have found a working setting for me in Blender. This is how i setup the UV smart unwrap to have it work in the playcanvas editor:

bpy.ops.uv.smart_project(island_margin=0.2, user_area_weight=0, use_aspect=False, stretch_to_bounds=False)

I also found out that merging all the meshes together helps !

Sometimes the shadows might still be broken, I then recommend tweaking the lightmap size multiplier. I found out that 512 is usually a good starting value. (with the above blender UV smart unwrap settings)

I also updated the script I wrote above!

slimbuck commented 3 years ago

Oh I see, apologies @valentincognito :) The editor unwrap should work similarly to the ones available in blender et al. If you can provide an example where lighting doesn't work we could perhaps take a look. You may be seeing issues due to the grouping that lightmapper uses, but I'm not familiar with the details. Perhaps @mvaligursky knows more?

mvaligursky commented 3 years ago

I believe out ightmapper ignores meshes that do not have uv1 channel. So this is set up somewhere before lightmapping, I'm not familiar with that part yet. Otherwise I don't think a type of unwrapping makes a difference. The only thing is that when mesh is unwrapped, the individual triangles / patches do not overlap in the texture, as it all needs to be mapped uniquely in order to have correct lightmaps. There also needs to be a 2-3 pixel gap between individual unwrapped patches, to avoid dilate shader from leaking to other patches.

Crefossus commented 3 years ago

I just ran into this and was confused for a bit. Maybe giving error feedback after you click auto-unwrap on a glb is a good idea until it gets fixed. IE "GLB not yet supported for auto-unwrap. See https://github.com/playcanvas/editor/issues/194 or use json by unchecking convert to glb in menu, settings, asset tasks, then delete and reupload the model." Feel free to use that or whatever

yaustar commented 3 years ago

This issue has been re-raised with another client.

thisredone commented 3 years ago

Is this being addressed?

yaustar commented 3 years ago

AFAIK, unfortunately not in the short term. The UV1 coordinates will needed to be added in a modelling package as the current workaround

hodgegw commented 2 years ago

I'm am not an expert in any of this, but I had/have a .glb object, and when I took into blender it appeared as if its correct, but when I exported the object under a different format, such as .dae, .fbx, or even .obj, and brought the object back into blender using one of those, that the mapping of the texture was all off. I think this is what you all are talking about, but if I'm wrong please excuse this post.

I worked around this issue by first converting the .glb asset/object to .obj format via the "anyconv.com" web site, brought it then into blender, and exported it as a .dae, and all was good for the mapping. Hope this helps, and again sorry if I'm off-topic.