ScanMountGoat / xenoblade_blender

Blender addon for importing Xenoblade models, maps, and animations
MIT License
6 stars 1 forks source link

Option to merge the meshes of map props #28

Closed BlockBuilder57 closed 2 weeks ago

BlockBuilder57 commented 2 weeks ago

Map props, when imported, are separated by material. This is just a thing Monolith does, so I'm not exactly surprised by this. However I know for a fact that one "prop" (referred to here as ModelGroupIndex) just consists of a number of meshes. An option to combine these meshes based on the that index would help streamline a lot of extra work.

Alternatively, grouping by identical positions also seems to work well. Here is an incredibly slow Python script that demonstrates what I mean:

import bpy
from mathutils import *;
from math import *;

collection = bpy.context.collection

objdict = dict(location = (0.0, 0.0, 0.0), object = None)

for obj in collection.objects:
    if obj.type != 'MESH':
        continue
    if obj.location.length <= 0:
        continue

    vec = obj.location[:]
    if vec in objdict:
        parent = objdict[vec]

        bpy.context.view_layer.objects.active = parent
        parent.select_set(True)
        obj.select_set(True)

        bpy.ops.object.join()

        parent.select_set(False)
    else:
        objdict[vec] = obj

A combination of the two is likely the best option. It sounds like it would break everything nice about using the same mesh in multiple nodes, but amazingly this method preserves all of that. I'm not really quite sure how.

ScanMountGoat commented 2 weeks ago

Map props, when imported, are separated by material.

Switching materials requires changing GPU state and needs another draw call. Each mesh in Blender corresponds to the data structure for a draw call in the binary file without any additional splitting.

An option to combine these meshes based on the that index would help streamline a lot of extra work.

I'll try and look into using collection instances instead of linked duplicates (alt+d) for meshes. The map format technically instances groups of meshes instead of individual meshes like you mentioned. This should also cover your use case in #29 if the base collection is at the origin and hidden. Characters don't use instancing, so this shouldn't interfere with anyone doing model edits. https://docs.blender.org/manual/en/latest/scene_layout/object/properties/instancing/collection.html

BlockBuilder57 commented 2 weeks ago

Collection instances would be perfect, actually! It should still be able to make use of GPU instancing but also be easy to throw into an asset library, best of both worlds.

There is one concern though: I'm unsure what Blender's behavior for exporting collection instances is. If it treats everything all the same as if its nodes were separate instances, there may not be an issue. But if it exports them as empties, that might not be ideal for the people that export the whole map in one go. I wouldn't envy having to fix thousands of props by hand...

ScanMountGoat commented 2 weeks ago

There is one concern though: I'm unsure what Blender's behavior for exporting collection instances is.

What export format and program are you planning on using? I can't guarantee a seamless experience outside of Blender, but it would be helpful for my testing to see how people are actually using the models.

BlockBuilder57 commented 2 weeks ago

For exporting out to Unity or other game engines, I'd personally just use fbx.

BlockBuilder57 commented 2 weeks ago

Just tested with https://github.com/BlockBuilder57/xenoblade_blender/commit/e8330f4998e95406c185000f25fc516b43be356d and a normal fbx output does in fact retain the meshes properly. No concern needed!

I've closed #29, but I'll leave this open in case there's more that you're planning.