• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

WoWtoWC3conv

This bundle is marked as pending. It has not been reviewed by a staff member yet.

WoWtoWC3conv - new batch converter for WoW models​


Hey!
Porting many models from WoW to Warcraft3 can be complicated and it takes very long time. So, I have designed a tool for my own usage to batch convert those models. Later, I thought it might be useful for someone else, so I'm posting it here.

External materials used:​

Java is required to run it!

To convert your freshly exported model, just open the app and read the instructions.

Some, rare models require .anims files that don't exist. It is caused by a bug in jM2 converter. To omitte this, we simply need to create dummy animation files. That's why I have made 'dummyanims.exe'. Open Windows Command Processor, drag 'dummyanims.exe', click 'space', drag your model. Now you can click 'Enter' or drag additional models.
Remember! This app creates ~5000 new files in model's directory. You should delete them after conversion.


How the app works?​

  1. Deletes first 8 bytes of text (this makes model readable by jM2converter);
  2. Converts model to early Burning Crusade version (using jM2converter);
  3. Opens model in MdlVis and waits for respond (You have to manually canonize it now and save);
  4. Converts model to .mdl and deletes all Particle Emitters (using edited MDLX Converter);
  5. Changes mdl (texture, unshaded);
  6. Converts model back to .mdx (using edited MDLX Converter);
  7. Done!
C++:
#include<windows.h>
#include<vector>
#include<fstream>
#include<string>
#include<iostream>
#include<cstdio>
#include<cstdlib>

using std::system;
using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::ifstream;
using std::ofstream;
using std::string;
using std::ios;

bool unshaded = false;

void Help()
{
    cout<< "Welcome to WoWtoWC3conv v.1.2\n"
        << "This tool was made by Maldiran, but the core jM2converter was made by Koward. It also uses MdlVis and Mdlx converter.\n\n"
        << "To convert .m2 models to .mdx you should:\n"
        << "     1.Open Command Prompt (by clicking 'Enter' now or by clicking 'Windows'+'R' and typing 'cmd')\n"
        << "     2.Drag my program to the console window, type 'space';\n"
        << "     3.Drag your .m2 model to the console window, type 'space';\n"
        << "     4.Write your new texture name (for example texture1.blp, the model will have basic texture textures/texture1.blp);\n"
        << "     5.Click enter or, if you want to convert more models, type 'space' and repeat steps 3 and 4.\n"
        << "     Example command: path/WoWtoWC3converter.exe path/model1.m2 texture1.blp path/model2.m2 texture2.blp\n\n"
        << "If you aren't convering gear, than texture from point 4 will not apply (probably), but you still need to type its name;\n"
        << "If you want your new model/s to be unshaded (whole model), than at the end of line type 'true', example command:\n"
        << "     path/WoWtoWC3converter.exe path/model1.m2 texture1.blp path/model2.m2 texture2.blp true\n"
        << "In this case both model1 and model2 will be unshaded.\n\n\n"
        << "To exit help window and open Command Prompt hit 'Enter'\n";
    getchar();
}

void DeleteMD21(string inputfile)
{
    ifstream save(inputfile, ios::app | ios::binary);
    string line;
    getline(save, line);
    if (line.length() < 9)
    {
        string tem;
        getline(save, tem);
        line += tem;
    }
    if (line[3] == '1')
    {
        ofstream saves("temp.m2", ios::binary);
        if (line[8] == 'D')
            saves << 'M';
        if (line[8] == '2')
            saves << "MD";
        if (line[8] == '1')
            saves << "MD2";
        for (int i = 8; i < line.length(); i++)
            saves << line[i];
        while (getline(save, line))
        {
            saves <<endl<< line;
        }
        saves.close();
        save.close();
        remove(inputfile.c_str());
        rename("temp.m2", inputfile.c_str());
    }
    else { cout << "Not an MD21" << endl; save.close(); }
}

void Mdlchange(string inputfile, string image)
{
    ifstream save(inputfile, ios::app);
    ofstream saves("temp.mdl");
    string line;
    bool istextures = false;
    bool willtextures = true;
    bool ismaterials = true;
    bool willunshaded = unshaded;
    while (getline(save, line))
    {
        if (willtextures) { if (line.substr(0, 8) == "Textures") willtextures = false;  istextures = true; }
        else
        {
            if (istextures)
            {
                if (line == "    Bitmap {")
                {
                    getline(save, line);
                    if (line == "        Image \"\",")
                    {
                        while (getline(save, line))
                        {
                            if (line == "    }") { line.erase(); break; }
                            line.erase();
                        }
                    }
                    else saves << " Bitmap {" << endl;
                }
                if (line == "        Image \"Cape.blp\",") line = "        Image \"textures\\" + image + "\",";
                if (line[0] == '}') istextures = false;
            }
            else
            {
                if (willunshaded)
                {
                    if (line.substr(0, 9) == "Materials") ismaterials = true;
                    if (ismaterials)
                    {
                        if (line.substr(0, 13) == "            FilterMode")
                        {
                            saves << line << endl;
                            getline(save, line);
                            if (line != "            Unshaded,")
                                saves << "            Unshaded," << endl;
                        }
                        if (line[0] == '}') willunshaded = false;
                    }
                }
            }
        }
        saves << line << endl;
    }
    saves.close();
    save.close();
    remove(inputfile.c_str());
    rename("temp.mdl", inputfile.c_str());
}

int main(int argc, char* argv[])
{
    if (argc == 1)
    {
        Help();
        system("cmd");
        return 0;
    }
    int k = 0;
    string unsh = argv[argc - 1];
    if (argc == 2)
    {
        if (unsh == "help")
        {
            Help();
            return 0;
        }
    }
    if (unsh == "true")
    {
        unshaded = true;
        k++;
    }
    int j = 1;
    string path = argv[0];
    while (true)
    {
        if ((path.substr(path.size()-4, path.size())) == ".exe")
            break;
        path += ' ' + argv[j];
        j++;
    }
    while (true)
    {
        if ((path[path.size() - 1] == '\\') || (path[path.size() - 1] == '/'))
            break;
        path = path.substr(0, path.size() - 1);
    }
    for (int i = j; i < argc - k; i += 2)
    {
        string temp = argv[i];
        string text = argv[i + 1];
        cout << text << endl;
        cout << temp << endl << " {" << endl;
        DeleteMD21(temp);
        string command = "java -jar \"" + path + "subapps\\jM2converter.jar\" -in \"" + temp + "\" -out \"" + temp + "\" -bc";
        system(command.c_str());
        string isdone;
        command = "\"\"" + path + "mdlvis\\MdlVis.exe\" \"" + temp + "\"\"";
        cout << endl << "Now it is time to canonize model. In opened mdlvis click 'K' and 'Cltr+S' then close mdlvis and type 'done'." << endl;
        system(command.c_str());
        while (true)
        {
            cin >> isdone;
            if (isdone == "done") break;
        }
        temp = temp.substr(0, temp.size() - 2);
        command = "\"\"" + path + "subapps\\MdlxConverterEdited.exe\" \"" + temp + "mdx\"\"";
        system(command.c_str());
        remove((temp + "mdx").c_str());
        Mdlchange((temp + "mdl"), text);
        command = "\"\"" + path + "subapps\\MdlxConverterEdited.exe\" \"" + temp + "mdl\"\"";
        system(command.c_str());
        remove((temp + "mdl").c_str());
        cout << '}' << endl << endl;
    }
    cout << endl << "Done" << endl;
    return 0;
}
1.2 - option to make materials 'unshaded' added;
app will now run without dragging it to the console.
1.1 - 'replaceable ID 0 textures' don't longer appear;
bug that didn't allow to convert some models (due to present of 'end of line' between first 8 bytes) don't longer appear;
new exe file inside zip - 'dummyanims.exe' - some models are bugged and require additional .anim files, but they don't exist. This app will make them for you.
1.01 - minor bug with file paths has been fixed.
PS I hope it doesn't violate any rules by - in fact - reposting mdlvis. It is needed to convert models and it has to be included.
Contents

WoWtoWC3conv (Binary)

I knew, but .obj WoW models are not scaling properly. If you are going to use them with character models, it will be really painful. Additionally this converter is much faster and it automatically changes texture name. It also maintains geosets divided like in original WoW models.

And above this - animations. You can convert for example horse model via .obj, but you will lose all animations. Using this, you are converting the WoW model as it is, without changing anything (except particle emitters, but wc3 simply doesn't recognize them properly).
 
I knew, but .obj WoW models are not scaling properly. If you are going to use them with character models, it will be really painful.
Some models will be automatically rescaled by Retera's model studio.
it automatically changes texture name. It also maintains geosets divided like in original WoW models.
So does Retera's model studio.

And above this - animations. You can convert for example horse model via .obj, but you will lose all animations. Using this, you are converted the WoW model as it is, without changing anything (except particle emitters, but wc3 simply doesn't recognize them properly).
This is indeed interesting. Are you saying animations for all models will also be automatically applied when you convert models using your tool?
 
This is indeed interesting. Are you saying animations for all models will also be automatically applied when you convert models using your tool?
Animation names can be changed randomly, but animations should be intact. The only bugs might be present when vertex is attached to too many bones, but this is - again - Warcraft 3 problem.

This is made by using jM2converter. It is perfect and works really well. All credits to Koward for animation import.
 
Awesome, it works now!

The only thing I noticed though is that your tool seems to add a lot of empty replaceable ID 0 textures.

EDIT: Yeah there is something wrong with textures. Why are you renaming the textures texture1.blp and texture2.blp? How do you choose which one of them should be 1 and 2? It seems arbitrary going from the video.

I add texture1.blp at the end of the command line, but the textures aren't renamed since the textures aren't actually imported into the model, your tool just adds a lot of replaceable ID 0 textures. I have to manually import textures and apply them on the correct material layers as it is now.

EDIT 2: So it turns out some models will also not convert for some reason, you can see two videos below, showing what I did:

In this video the model failed to convert altogether:

In this video the textures failed to import so I had to manually apply them:
 
Last edited:
If the model is using more than one texture, than the texture is renamed to textures/xxxx.blp. If you are converting larger model, then you have to manually choose the correct texture, because app doesn't recognize where should it go. When you are converting models like items than this is not a problem.
With replaceable ID 0 I will deal tomorrow, I will simply delete all of them.

EDIT: 1. Ok, I know what happened in first video. I will fix it tomorrow. If you want this model now, than open freshly exported model with notepad and delete first 8 bytes. So, It should look like MD21xxxxMD20xxxx and make it MD20xx (normal notepad may not read all characters correctly, I prefer notepad++)

2. Simply too complicated model to assign all textures.


And by the way, you don't have to name your texture "texture1.blp", it can be whatever you want. I have used it as an example in tutorial.
 
Last edited:
If the model is using more than one texture, than the texture is renamed to textures/xxxx.blp. If you are converting larger model, then you have to manually choose the correct texture, because app doesn't recognize where should it go. When you are converting models like items than this is not a problem.
With replaceable ID 0 I will deal tomorrow, I will simply delete all of them.

EDIT: 1. Ok, I know what happened in first video. I will fix it tomorrow. If you want this model now, than open freshly exported model with notepad and delete first 8 bytes. So, It should look like MD21xxxxMD20xxxx and make it MD20xx (normal notepad may not read all characters correctly, I prefer notepad++)

2. Simply too complicated model to assign all textures.


And by the way, you don't have to name your texture "texture1.blp", it can be whatever you want. I have used it as an example in tutorial.
I see. I don't need the model now, I was just trying random models.

Anyway, rip successful and uploaded to the ported models section; Alliance Murloc WoW Rip
 
I see that you added this to the changelog;

"new exe file inside zip - 'dummyanims.exe' - some models are bugged and require additional .anim files, but they don't exist. This app will make them for you."

How exactly can I do this, and does it work with character models?

(sorry for the double post).
 
Level 5
Joined
Nov 22, 2005
Messages
80
download.png
I think I broke it.


Update with Error message?
download.png
 
Last edited:
I have added it to description:
Some, rare models require .anims files that don't exist. It is caused by a bug in jM2 converter. To omitte this, we simply need to create dummy animation files. That's why I have made 'dummyanims.exe'. Open Windows Command Processor, drag 'dummyanims.exe', click 'space', drag your model. Now you can click 'Enter' or drag additional models.
Remember! This app creates ~5000 new files in model's directory. You should delete them after conversion.
No, character models cannot be ripped as well as another bigger models. This is caused because of their vertices numbers. The max number in Warcraft models is around 21000 if I remember correctly. Character models and other big models (like K'thir one) are unportable without use of Blender.

@Drake Send your commands, errors in command prompt and so on. Tool is still new, there surely are bugs.
 
No, character models cannot be ripped as well as another bigger models. This is caused because of their vertices numbers. The max number for Warcraft models is around 21000 if I remember correctly. Character models and other big models (like K'thir one) are unportable without use of Blender.
Hmm Retera's model studio can convert even the biggest .wmo models without any use of Blender. Take this model for example, I am sure it has got well over 100k vertices;
Screenshot_1.png

The textures will also be automatically applied so you don't have to mess around with the materials etc.

Your tool is great for ripping things with animations, but for doodads Retera's model studio is still king imo.
 
I think I broke it.


Update with Error message?
Ok, there are two options.
1. You haven’t exported tigerloa0097-00.anim. Check it. If you don’t see this file then:
2. That’s the bug I have mentioned with dummyanims.exe! Do this
Some, rare models require .anims files that don't exist. It is caused by a bug in jM2 converter. To omitte this, we simply need to create dummy animation files. That's why I have made 'dummyanims.exe'. Open Windows Command Processor, drag 'dummyanims.exe', click 'space', drag your model. Now you can click 'Enter' or drag additional models.
Remember! This app creates ~5000 new files in model's directory. You should delete them after conversion.
Remember to replace the dummy files with orginal .anim files you have exported or you will have no animations.

  • Run dummyanims.exe
  • Delete .anims with identical names as original files.
  • Paste original files
  • Convert the model in normal way
  • Delete unnecessary.anim files



@FeelsGoodMan My converter doesn’t have option to convert .wmo, so Retera’s tool is faaaar better in this.
 
This looks promising , can you convert models containing .skel file ?

If not , is there any possibility to make it happen?
Since it relies on good old jM2converter, than no, it's not possible for now. But I can think about merging .skin with .m2 and then converting it. I don't know if it is possible at all, but I will check.
 
Converting script itself is intact since it is not open source, so there is no way to edit it. Using my program you can convert many models at once, change their texture names, delete unused 'replaceable ID 0', change all materials to unshaded if you will. It simply speeds up the process.
When using jM2converter you had to firstly delete MD21xxxx, than convert it, than canonize it, then change its textures and delete unused ones. It takes a lot of time and effort especially if you want to convert many models at once. Now you simply drag the model, type its texture name and all is done automatically.
 
murloc.gif


Ideologically, does anybody on friggin Planet Earth have the jm2converter source code? It's java so you could literally upgrade the source and include it in Retera Model's Studio as some kind of incorporated plugin or part of RMS.

Above is a GIF of a version of Retera Model Studio that I hacked together some day back in January or whenever. Someone sent me a build of WoW, like some alpha or something, that was so old that all the models were in the MDX format version 1300 (much closer to WC3 format than the release clients of WoW, I think?)

And so it was a single day's work with that particular MPQ that they sent me to make an RMS that could just link against WoW instead of WC3 as the game data source, and then you can click any model and the save code isn't changed so it just saves Warcraft III MDX files.

What is the reason that programmers do not pursue this kind of paradigm where you can just open WoW models and save to WC3 instead of going through like 3 different binary black box tools? In my one day of working, making the RMS that would load these WoW models was as simple as reading the online documentation of the WoW format


And, of course, as shown in this picture I did not bother getting a BLP2 parser, but surely that is well-documented as well.
 
Level 16
Joined
Jan 18, 2009
Messages
253
View attachment 378451

Ideologically, does anybody on friggin Planet Earth have the jm2converter source code? It's java so you could literally upgrade the source and include it in Retera Model's Studio as some kind of incorporated plugin or part of RMS.

Above is a GIF of a version of Retera Model Studio that I hacked together some day back in January or whenever. Someone sent me a build of WoW, like some alpha or something, that was so old that all the models were in the MDX format version 1300 (much closer to WC3 format than the release clients of WoW, I think?)

And so it was a single day's work with that particular MPQ that they sent me to make an RMS that could just link against WoW instead of WC3 as the game data source, and then you can click any model and the save code isn't changed so it just saves Warcraft III MDX files.

What is the reason that programmers do not pursue this kind of paradigm where you can just open WoW models and save to WC3 instead of going through like 3 different binary black box tools? In my one day of working, making the RMS that would load these WoW models was as simple as reading the online documentation of the WoW format


And, of course, as shown in this picture I did not bother getting a BLP2 parser, but surely that is well-documented as well.
Basically jm2converter retroports WoW files into old expansion file. For example people retroport it into Burning Crusade file format, by doing that allows MDLVIS to open BurningCrusade files. So the key might be MDLVIS old Burning Crusade M2 opening.

The converter was not made for warcraft 3 file format (mdx) but people took advantage of it.

Below i attached a version of jm2 converter, i think is the open source of it.
 

Attachments

  • jm2converter.rar
    849.6 KB · Views: 115
Level 3
Joined
May 23, 2022
Messages
18
@Maldiran
JM2converter is possible to add bone and attachment from .skel file to .m2 file before animation in .anim file add to bone?
JM2converter convert model with skel(only character base using that) it error becuase it have no bone
.skel contain attachment and bone split from .m2 file and they use same type of code

M2Array<M2Attachment> attachments
M2Array<M2CompBone> bones


Racaf can decompile and edit Class file in JM2converter
save Class file (Control + S to Save editing code)
normally can't read or save bytecode like this

Recaf GitHub - Col-E/Recaf: The modern Java bytecode editor
main-anim.gif
 
Last edited:
Level 3
Joined
May 23, 2022
Messages
18
jm2lib.blizzard.common.types.ArrayRef (This.AnimFiles error)
Array<Char> Character base is in .skel ,load <Char> from skel
Geoset is in .M2

jm2lib.blizzard.wow.legion.Model (edit)(bones and attachments)
this.bones.unmarshal(in); (edit)
this.attachments.unmarshal(in); (edit)
this.bones.marshal(out); (edit)
this.attachments.marshal(out); (edit)

jm2lib.blizzard.wow.M2Format (edit)(file import)
public static String getBoneName (new one)
public static String getAttachmentName (new one)

jm2lib.blizzard.wow.WoWFiles (edit)(file type)
I already add file type of .skel file but not finish

If someone can correct the code here the file
,I only surway line of code for you but this is out of my hand (Java isn't my thing)
 
Last edited:
Level 1
Joined
Jun 10, 2012
Messages
4
I got missing dll file-warnings, and after downloading them I'm getting "the application was unable to start correctly (0xc000007b)" when trying to use it..
Anyone have any pointers?
 
Level 3
Joined
Aug 14, 2019
Messages
28
this program doesn't work. it requires some dll. I installed the entire visual c++ package - I still get the error. why the author didn’t bother to install additional software to run it remains a mystery.
 
Top