November 9, 20232 yr Supporter MESSIAH game support : +(Diablo Immortal, Ace Racing, Fantasy Westward Journey, 1 unk) \\\\\\\\\\\MeshToOBJ.exe Link on github: MeshToOBJ.exe \\\\\\\\\\\Noesis for Noesis for *.mesh/*.model link on github: fmt_mesh_diablo.py Edited February 17, 20242 yr by Durik256 description
July 27, 20241 yr On 11/10/2023 at 12:28 AM, Durik256 said: MESSIAH game support : +(Diablo Immortal, Ace Racing, Fantasy Westward Journey, 1 unk) \\\\\\\\\\\MeshToOBJ.exe Link on github: MeshToOBJ.exe \\\\\\\\\\\Noesis for Noesis for *.mesh/*.model link on github: fmt_mesh_diablo.py How did you obtain these models? I tried parsing the visible strings, MESSIAH, Compressed_P_C_N_UV1_TB, W4B_I4B, but I couldn't get any clue. The parsed vertex data, xyz, all contain abnormal values. Could you please share how you successfully read and converted the .mesh file to .obj? Thank you very much! I know mesh to obj can read the models, but I want to know the method so that I can integrate it into my Python script for execution. I'm researching ACE Racing. mesh.rar
July 27, 20241 yr Author Supporter 2 hours ago, Rinorsi said: How did you obtain these models? I tried parsing the visible strings, MESSIAH, Compressed_P_C_N_UV1_TB, W4B_I4B ... Compressed: P - (12bytes) as 3float C - (4bytes) N - (4bytes) UV1/2 - (4bytes) as 2HalfFloat TB - (8bytes) Other: template: [target][count][type] sample: W4B = target:Weight, count:4, type:Byte On my githab there is a plugin(python) for diablo, it also uses MESSIAH. (you can see the implementation there) Edited July 27, 20241 yr by Durik256
July 27, 20241 yr Thank you, I spent the whole day trying to understand, but even after modifying the Noesis plugin (fmt_mesh_diablo.py) according to the data you provided, it still doesn't seem to work and causes Noesis to crash. Or perhaps, how can I batch convert .mesh files to .obj using Python? Besides models, AceRacing also includes many FX or particles that are compressed with LZMA. I want to use a Python script to batch convert models to precisely extract the parts that belong to models from all the decompressed files. If you can assist me, I would be very grateful. AceRacing-Mesh.rar
July 27, 20241 yr Author Supporter Solution On 7/27/2024 at 4:15 PM, Rinorsi said: Noesis plugin (fmt_mesh_diablo.py) why did you remove (author's name) from the script? MeshToOBJ supports batch processing. i made plugin for Noesis for AceRacing fmt_mesh_AceRacer.py *(Later I’ll make a universal for everyone messiah) Edited April 7, 20251 yr by Durik256
July 28, 20241 yr 13 hours ago, Durik256 said: why did you remove (author's name) from the script? MeshToOBJ supports batch processing. i made plugin for Noesis for AceRacing fmt_mesh_AceRacing.py *(Later I’ll make a universal for everyone messiah) thx!!! I apologize, I use chatgpt so i dont know why it remove author's name from the script. …… I have encountered some issues that seem to be unable to execute properly, so I have modified the plugin to ensure that it can now execute properly. I fixed some bugs in fmt_mesh_AceRacing.py, and now it can correctly read .messiah model information (perhaps the data differs between the Chinese version and the global version; I have only tested models obtained from the Chinese version with .MESSIAH, which can be read correctly). Noesis-Plugins/fmt_mesh_AceRacing.py at master · Durik256/Noesis-Plugins (github.com) Fixes include: Changed the file header check in the noepyCheckType function to match the first 8 bytes (.MESSIAH) instead of bytes 1 to 8. Replaced bs.read with bs.readBytes in the noepyLoadModel function to correctly handle the reading of binary data. This ensures the read operations correctly interpret the data formats. Corrected the method name for binding UV buffers from rapi.rpgBindUVXBufferOfs to rapi.rpgBindUV1BufferOfs, which is the correct method available in the Noesis API for binding UV buffers. Edited July 28, 20241 yr by Rinorsi
July 28, 20241 yr Author Supporter 3 hours ago, Rinorsi said: Fixes include: I'll duplicate the answer from Github: 1)magic check is correct. (it doesn’t matter how many bytes you check, it’s just to check the validity of the file). I just skip the first dot (I don’t remember why I did this, maybe in other MESSIAH games there was another symbol instead of a dot) 2)reading bytes through bs.read() is the same as through bs.readBytes(), this can be seen in the Noesis code ``` def read(self, fmtStr): if isinstance(fmtStr, str): self.toUnpacker(); r = noeSuper(self).read(fmtStr); self.fromUnpacker(); return r else: return self.readBytes(fmtStr) #assume byte count ``` 3)rpgBindUVXBufferOfs is used to set the UVS to the desired channel. It is not necessary to use an explicit method for the desired channel. especially when there are several channels or more than 2 from Noesis documentation: ``` {"rpgBindUVXBuffer", RPGBindUVXBuffer, METH_VARARGS, "binds uvx buffer. (Oiiii)"}, //args=bytes for uv2's, dataType, stride, uv index, uv elem count By replacing rpgBindUVXBufferOfs with rpgBindUV1BufferOfs, you broke the code, since some models have several UVs channels. you always set UVs to the zero channel. that is, if there are multiple UVs you will only get the last one. ``` so I think all your changes are unnecessary the only thing that can be used is the magic check. *(send me the file that gave the error) The plugin is absolutely functional and does not need any corrections Edited July 28, 20241 yr by Durik256
July 28, 20241 yr 5 minutes ago, Durik256 said: I'll duplicate the answer from Github: magic check is correct. (it doesn’t matter how many bytes you check, it’s just to check the validity of the file). I just skip the first dot (I don’t remember why I did this, maybe in other MESSIAH games there was another symbol instead of a dot) 2) reading bytes through bs.read() is the same as through bs.readBytes(), this can be seen in the Noesis code def read(self, fmtStr): if isinstance(fmtStr, str): self.toUnpacker(); r = noeSuper(self).read(fmtStr); self.fromUnpacker(); return r else: return self.readBytes(fmtStr) #assume byte count rpgBindUVXBufferOfs is used to set the UVS to the desired channel. It is not necessary to use an explicit method for the desired channel. especially when there are several channels or more than 2 from Noesis documentation: {"rpgBindUVXBuffer", RPGBindUVXBuffer, METH_VARARGS, "binds uvx buffer. (Oiiii)"}, //args=bytes for uv2's, dataType, stride, uv index, uv elem count By replacing rpgBindUVXBufferOfs with rpgBindUV1BufferOfs, you broke the code, since some models have several UVs channels. you always set UVs to the zero channel. that is, if there are multiple UVs you will only get the last one. so I think all your changes are unnecessary the only thing that can be used is the magic check. *(send me the file that gave the error) 该插件绝对功能强大,不需要任何更正 Okay, I'm not quite sure what the problem might be, maybe it's a version issue? Anyway, I sincerely thank you for your help!
January 29Jan 29 On 1/19/2026 at 4:47 PM, monowire said: Could you add support to Where Winds Meet? After testing, meshtoobj.exe supports WWM models Edited January 29Jan 29 by Kizurin
February 19Feb 19 Localization On 1/28/2026 at 10:10 PM, Kizurin said: After testing, meshtoobj.exe supports WWM models From what i know, not entirely. Because WMM's .mesh has its differences from other games .mesh. The program will convert a lot of mesh to obj, but also a lot will fail, because the mesh support is not specific to this game. So that is what i was talking about, a full support to WWM's messiah .mesh or a Noesis plugin to visualize WWM .mesh.
February 21Feb 21 Supporter On 2/19/2026 at 6:03 PM, monowire said: From what i know, not entirely. Because WMM's .mesh has its differences from other games .mesh. The program will convert a lot of mesh to obj, but also a lot will fail, because the mesh support is not specific to this game. So that is what i was talking about, a full support to WWM's messiah .mesh or a Noesis plugin to visualize WWM .mesh. I've looked at a few meshes that won't load and I can't explain what the problem is, but it seems like the indexes and vertex data aren't working properly First we should understand the basic structure of the grid of this game The file header includes 8-byte magic number (.MESSIAH) 4 bytes padding 4 bytes data length 2 byte identifier - normal is 0, this game is 2 2-byte subgrid number 4-byte vertex number 4-byte index number 4 identifiers Each identifier has a length of 2 bytes Bounding box - 40 bytes Subgrid data - 16 bytes The data area includes Index data - each index takes two bytes After the index is the vertex data. The vertex determines how many bytes a vertex data uses according to the structure given by the descriptor. There is 52 bytes of bounding box data at the end of the file Take this file example I provided Total file length: 8407 Number of subgrids: 1 Vertex: 378 Index: 378 File metadata occupies 122 bytes, followed by index data. If parsed by two bytes per index, the index length occupies 756 bytes. Four descriptors, two of which have valid vertex data First descriptor: P3F_N4B_T2F Contains 12 bytes for position, 4 bytes for normal, and 8 bytes for UV 378*24=9072 bytes Second descriptor: T4H_B4H Contains 8 bytes for tangents and 8 bytes for side tangents 378*16=6048 bytes End of file: 52 bytes 122+756+9072+6048+52=16050 Almost half of the data is missing 653232324553ccbd.zip
February 21Feb 21 Supporter 2 hours ago, wq223 said: The file header includes 8-byte magic number (.MESSIAH) 4 bytes padding 4 bytes data length 2 byte identifier - normal is 0, this game is 2 2-byte subgrid number 4-byte vertex number 4-byte index number 4 identifiers Each identifier has a length of 2 bytes Bounding box - 40 bytes Subgrid data - 16 bytes Thanks. But without showing the header it's hard to follow. "Each identifier has a length of 2 bytes" is not fully correct, it's string lengths, not identifiers, the strings ("descriptors") follow, as you mentioned then. So 0B00 P3F_N4B_T2F 0700 T4H_B4H 0400 None 0400 None The bounding box is -0.156100 -0.068000 -0.150600 0.156100 0.068000 0.150600 (24 bytes and 4 floats subgrid) ... btw, what is the "subgrid" exactly and is the attached file compressed? (Giving the start addresses of blocks of your file sample could help a lot.) Edited February 21Feb 21 by shak-otay
February 21Feb 21 Supporter 1 hour ago, shak-otay said: Thanks. But without showing the header it's hard to follow. "Each identifier has a length of 2 bytes" is not fully correct, it's string lengths, not identifiers, the strings ("descriptors") follow, as you mentioned then. So 0B00 P3F_N4B_T2F 0700 T4H_B4H 0400 None 0400 None The bounding box is -0.156100 -0.068000 -0.150600 0.156100 0.068000 0.150600 (24 bytes and 4 floats subgrid) ... btw, what is the "subgrid" exactly and is the attached file compressed? (Giving the start addresses of blocks of your file sample could help a lot.) It should be a problem caused by translation Here the number of subgrids is determined by the 2 bytes after the flag. After the bounding box data is the information of each subgrid. Normally, each subgrid information is 16 bytes. Multiple subgrids mean that there are multiple repeated 16 bytes. These 16 bytes are 4-byte starting index 4-byte index number 4-byte starting vertex 4-byte vertex number The subgrids will eventually be merged into one grid, and this file only has one grid 0200-logo/0100-1 grid It seems that many meshes in this game have this anomaly. The index and vertex data are completely larger than the entire file. It does look like it is compressed, but it doesn't feel like it.
February 21Feb 21 Supporter Thanks! Could you give the start address of the first vertex block in your sample? (don't have the time to trick around)
February 21Feb 21 Supporter 1 hour ago, shak-otay said: Thanks! Could you give the start address of the first vertex block in your sample? (don't have the time to trick around) I'm also not sure if the vertex position is normal. If the file is normal, the vertex should start around 878 bytes. But I think the index and vertex data are compressed
February 21Feb 21 Supporter 878 bytes, so vertex start at 0x36E? That looks random. Anyways the descriptor tell that floats (F) and halffloats (H) are used. But I couldn't seem to find any of them. btw, the data starting from 0x1100 appears to be shifted by one byte each 16 bytes block: edit: although shorts are not mentioned I used them and got this (not a mesh) : v 65.636719 0.246094 -49.625000 v -43.585938 -123.339844 28.015625 v -43.585938 -123.339844 28.015625 v -43.585938 -123.339844 28.015625 v -43.585938 -123.339844 28.015625 v 72.289062 0.750000 30.734375 v 72.289062 0.750000 30.734375 v 72.289062 0.750000 30.734375 v 72.289062 0.750000 30.734375 v -43.585938 -123.339844 28.015625 v -43.585938 -123.339844 28.015625 v 72.289062 0.750000 30.734375 v 72.289062 0.750000 30.734375 v 72.289062 70.750000 26.613281 v 72.300781 70.750000 26.613281 v 72.300781 70.750000 26.613281 v 72.300781 0.750000 30.734375 v 72.289062 70.750000 26.613281 v 72.289062 70.750000 26.613281 v 72.289062 0.750000 30.734375 v 85.109375 -15.171875 77.968750 v 85.109375 -15.171875 77.968750 v 72.296875 70.750000 26.613281 v 72.300781 70.750000 26.613281 v 85.121094 -15.171875 77.968750 v 74.933594 0.957031 78.734375 v 85.121094 -15.171875 77.968750 v 74.921875 0.957031 78.734375 v 74.921875 0.957031 78.734375 v 74.921875 0.957031 78.734375 v 85.121094 -15.171875 77.968750 Edited February 21Feb 21 by shak-otay
March 29Mar 29 Supporter I added skeleton support to Where Winds Meet, I'm currently reverse engineering the animation files, it may take a long time as I'm still struggling with the compressed meshes for version 2, I won't be releasing the script for a while until it's finished
March 30Mar 30 Supporter 7 hours ago, Durik256 said: I did this a long time ago Well done, I will work hard to make it. The good news so far is that I have found the animation file processing function, which may be able to make up for some details I don’t know.
April 16Apr 16 On 3/30/2026 at 6:31 AM, Durik256 said: I did this a long time ago Sorry for bothering again, but the other messiah game (for all times) updated their model to include skeleton anim (and possibly shapekeys or bone controls on eyes and mouth) too. is it possible to add support to them too? decrypted samples attached ><sample.zip Edited April 16Apr 16 by Jenny1367
April 16Apr 16 Supporter 1 hour ago, Jenny1367 said: Sorry for bothering again, but the other messiah game (for all times) updated their model to include skeleton anim (and possibly shapekeys or bone controls on eyes and mouth) too. is it possible to add support to them too? decrypted samples attached ><sample.zip There are some errors in the renaming. Send me your resource library file and renaming script.
April 16Apr 16 Just now, wq223 said: There are some errors in the renaming. Send me your resource library file and renaming script. res.zip some files (anim and base.skeleton) were already named in the resource dir btw
April 16Apr 16 Supporter 11 minutes ago, Jenny1367 said: res.zip some files (anim and base.skeleton) were already named in the resource dir btw The order of model and skin is reversed, add lz4 decompression resource.py
April 16Apr 16 5 minutes ago, wq223 said: The order of model and skin is reversed, add lz4 decompression resource.py 9.32 kB · 0 downloads Thanks for the update! Wondering if you know any tools to properly read them tho? ><
Create an account or sign in to comment