Skip to content

Conversation

@Dantsz
Copy link

@Dantsz Dantsz commented Aug 10, 2025

Hi, I've wanted to have the Warcraft III models as glTFs, but couldn't find any satisfactory converter from .mdl/.mdx to any usual format so I ended up exporting them using this project, here's my code in case it would be a useful feature.

  • geometry is exported correctly (what I was specifically looking for)
  • materials work enough to display the textures
  • bone are exported, though not correctly
  • also added filtering geosets exported on whether or not they're present during a specific animation

@speige
Copy link

speige commented Nov 27, 2025

I'm too lazy to make a new PR to your fork, but I recommend refactoring the export() function of GLTFExport.java (to make it faster to resume)

    File outputFile = new File(baseDir + "/" + model.getName() + ".gltf");
    if (outputFile.exists()) {
        log.info("Skipping existing file: " + outputFile.getAbsolutePath());
        return;
    }

    var gltf = createGltfModel(model, animation);

Also, for doodads path you have the whole load & export in a try/catch, but for unitPaths only the export is in a try/catch, so if 1 unit model fails to load during export all, it'll stop progressing.

@speige
Copy link

speige commented Nov 27, 2025

Also, I was having out of memory issues, so I refactored getPngFromMaterial like this (I'm not sure if it'll help yet, but fingers crossed):

private static final ThreadLocal<ByteArrayOutputStream> BAOS_THREAD_LOCAL =
	    ThreadLocal.withInitial(() -> new ByteArrayOutputStream(2 * 1024 * 1024));
private static byte[] getPngFromMaterial(com.hiveworkshop.wc3.mdl.Material material, DataSource dataSource) {
	java.awt.image.BufferedImage img = null;
    try {
    	img = material.getBufferedImage(dataSource);
    	if (img == null) {
            return new byte[0];
        }
    	ByteArrayOutputStream baos = BAOS_THREAD_LOCAL.get();
        baos.reset();
        javax.imageio.ImageIO.write(img, "png", baos);
        return baos.toByteArray();
    } catch (IOException e) {
        log.severe("Failed to write image for material " + material.getName() + ": " + e.getMessage());
        return null;
    }
    finally {
        if (img != null) {
            img.flush();
        }
    }        
}

@Dantsz
Copy link
Author

Dantsz commented Dec 8, 2025

I'm too lazy to make a new PR to your fork, but I recommend refactoring the export() function of GLTFExport.java (to make it faster to resume)

    File outputFile = new File(baseDir + "/" + model.getName() + ".gltf");
    if (outputFile.exists()) {
        log.info("Skipping existing file: " + outputFile.getAbsolutePath());
        return;
    }

    var gltf = createGltfModel(model, animation);

Also, for doodads path you have the whole load & export in a try/catch, but for unitPaths only the export is in a try/catch, so if 1 unit model fails to load during export all, it'll stop progressing.

Thanks! Although I've not seen the change to getPngFromMaterial make a difference.

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.

2 participants