jpaver / opengametools

A set of open c++ game development tools that are lightweight, easy-to-integrate and free to use. Currently hosting a magicavoxel .vox full scene loader.
MIT License
373 stars 35 forks source link

ogt_vox: setting k_read_scene_flags_groups false looses hidden and layer information #43

Open dougbinks opened 1 year ago

dougbinks commented 1 year ago

If k_read_scene_flags_groups is set to false loading the scene will loose information about hidden groups or group layers & thus groups which are in hidden layers.

This is because in addition to flattening the transform hierarchy the instance group_index is set to 0.

I am not sure of the best way to resolve this. Preserving the group_index might work but would potentially break some code, flattening the hidden information might work but a group can be in a layer different to it's children so that also needs to be taken into account. A new flag might be needed (perhaps k_flatten_hidden which flattens both layer and group hidden).

For my own code I am now going to flatten the transform hierarchy myself to work around this.

jpaver commented 1 year ago

Hey @dougbinks sorry for the late response, this somehow went under my radar. Good catch!

I think it's likely to be most useful to have the scene reader ultimately display the same thing that magicavoxel does when you're looking at the scene. For example: put all instances on layer 0, group them and put this group on layer1. Toggling visibility of layer1 turns off all instances that are children of the group that is now hidden.

So my proposal would be: set the instance.hidden field to true for all output instances if any of their parent groups is in a hidden layer. In essence, we don't just flatten the transform part of the groups anymore, but also the hidden state. What do you think?

dougbinks commented 1 year ago

I think that should work.

My current code in Avoyd uses the non flatten hierarchy and then flattens the hidden and transform as follows:

const ogt_vox_instance* instance = &scene->instances[instance_index];

bool hidden = instance->hidden || scene->layers[ instance->layer_index ].hidden;
ogt_vox_transform flattened_transform = instance->transform;
uint32_t group_index = instance->group_index;
while( scene->groups && group_index != k_invalid_group_index && !hidden ) {
    const ogt_vox_group& group = scene->groups[ group_index ];
    hidden = hidden || group.hidden;
    if( group.layer_index != k_invalid_group_index ) {
        hidden = hidden || scene->layers[ group.layer_index ].hidden;
    }
    flattened_transform = _vox_transform_multiply(flattened_transform, group.transform);
    group_index = group.parent_group_index;
}

If you like I can look into creating a PR for this, but it will be a while as I have a lot on at the moment.