Skip to content

Conversation

@Almamu
Copy link

@Almamu Almamu commented Feb 20, 2025

This PR adds the following featurers

  • Exporting individual Scenery entries
  • Exporting individual Animation frame entries
  • Exporting all geometry available in one NSF file
  • Exporting all the frames of an animation into separate files

Once the OBJ is exported it can be imported in any 3D software. Due to the OBJ format being a bit lacking, there's some minor adjustements that need to happen once imported into your 3D tool of choice. I'd recommend using blender and this script to get the best results possible:

import bpy

# apply the node tree changes to the material
def update_material (materialRef):
    image = materialRef.node_tree.nodes['Image Texture']
    bsdf = materialRef.node_tree.nodes['Principled BSDF']
    # remove the output links for the image
    for link in image.outputs['Color'].links:
        materialRef.node_tree.links.remove (link)
    # connect the image's alpha to the principled's alpha
    materialRef.node_tree.links.new (image.outputs['Alpha'], bsdf.inputs['Alpha'])
    # add the color attribute
    color = materialRef.node_tree.nodes.new ('ShaderNodeVertexColor')
    # set the layer name, use hardcoded value for now
    color.layer_name = 'Color'
    # add the color mix
    mix = materialRef.node_tree.nodes.new ('ShaderNodeMix')
    # setup settings
    mix.data_type = 'RGBA'
    materialRef.blend_method = 'BLEND'
    materialRef.show_transparent_back = False
    # now link inputs, depending on the blending mode these have to be performed differently
    if image.image.name.endswith("b0.bmp"):
        mix.inputs[0].default_value = 1
        mix.blend_type = 'MULTIPLY'
        materialRef.node_tree.links.new (image.outputs['Color'], mix.inputs[6])
        materialRef.node_tree.links.new (color.outputs['Color'], mix.inputs[7])
    elif image.image.name.endswith("b1.bmp"):
        mix.inputs[0].default_value = 1
        mix.blend_type = 'ADD'
        materialRef.node_tree.links.new (image.outputs['Color'], mix.inputs[6])
        materialRef.node_tree.links.new (color.outputs['Color'], mix.inputs[7])
        materialRef.node_tree.links.new (color.outputs['Color'], bsdf.inputs['Alpha'])
    elif image.image.name.endswith("b2.bmp"):
        mix.inputs[0].default_value = 1
        mix.blend_type = 'SUBTRACT'
        materialRef.node_tree.links.new (image.outputs['Color'], mix.inputs[6])
        materialRef.node_tree.links.new (color.outputs['Color'], mix.inputs[7])
    else:
        mix.inputs[0].default_value = 1
        mix.blend_type = 'MULTIPLY'
        materialRef.node_tree.links.new (image.outputs['Color'], mix.inputs[6])
        materialRef.node_tree.links.new (color.outputs['Color'], mix.inputs[7])
        
    materialRef.node_tree.links.new (mix.outputs[2], bsdf.inputs[0])
    image.interpolation = 'Closest'
    return

def can_update_material (materialRef):
    if not materialRef:
        return False
    if not materialRef.node_tree:
        return False
    if not materialRef.node_tree.nodes:
        return False
    if not len(materialRef.node_tree.nodes) == 3:
        return False
    if not 'Image Texture' in materialRef.node_tree.nodes:
        return False
    if not 'Material Output' in materialRef.node_tree.nodes:
        return False
    if not 'Principled BSDF' in materialRef.node_tree.nodes:
        return False

for material in bpy.data.materials:
    if can_update_material (material) is False:
        continue
    
    update_material (material)

The script will update all the materials in use and create the proper Color Attribute and color mixing required for everything to display properly.

Things left to consider this PR completed:

  • Generate texture atlas instead of multiple small files
  • Fix some issues with exported models not using the right texture
  • Make use of object groups for exporting multiple frames/animations

Almamu added 15 commits February 9, 2025 17:54
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Added OBJ export to normal scenery entries

Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
This enabled 3D software with scripting capabilities (like blender) to display textures properly

Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
Frame export should keep filename length the same regardless of the amount of frames
Added eid to texture export to prevent textures being overriden when they were indeed different

Signed-off-by: Alexis Maiquez Murcia <almamu@almamu.com>
@AraHaan
Copy link
Contributor

AraHaan commented Feb 21, 2025

Why not also have option to export directly to a .blend or .fbx for import in Blender 3.6 LTS or above? For those who want to skip the .obj step and jump straight into the blender step.

@Almamu
Copy link
Author

Almamu commented Mar 17, 2025

Why not also have option to export directly to a .blend or .fbx for import in Blender 3.6 LTS or above? For those who want to skip the .obj step and jump straight into the blender step.

.obj is easier to work with and easier to understand (for example, making a plugin to take the CrashEdit export, import into Unity and use the animations right as they are from the export is trivial, without the need of complex operations or adjustments). Not to mention that regardless of where you export the model to, you'll need to do some manual processing on the model for it to look right.

@jbreckmckye
Copy link

Firstly @Almamu this is really cool - I like that you've managed to fix up the camera controls in the preview too

I couldn't find any working builds of this fork - there is a dropbox link but it seems to be restricted.

If anyone else comes across this, this was how I built it locally (as someone with zero .NET knowledge). Assuming you already have the .NET SDK installed (v8+)

  • clone the fork
  • check out the deprecate branch
  • initialise submodules (git submodule update --init --recursive)
  • then run the build with dotnet build CrashEdit.sln

The debug build is a bit interesting, seems to have a couple of UI bugs, but that's probably something wrong with my setup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants