Engineers Durik256 Posted November 9, 2023 Engineers Posted November 9, 2023 (edited) 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, 2024 by Durik256 description 1 1
Rinorsi Posted July 27, 2024 Posted July 27, 2024 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
Engineers Durik256 Posted July 27, 2024 Author Engineers Posted July 27, 2024 (edited) 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, 2024 by Durik256 1
Rinorsi Posted July 27, 2024 Posted July 27, 2024 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
Engineers Solution Durik256 Posted July 27, 2024 Author Engineers Solution Posted July 27, 2024 (edited) 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, 2025 by Durik256 1
Rinorsi Posted July 28, 2024 Posted July 28, 2024 (edited) 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, 2024 by Rinorsi
Engineers Durik256 Posted July 28, 2024 Author Engineers Posted July 28, 2024 (edited) 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, 2024 by Durik256 1
Rinorsi Posted July 28, 2024 Posted July 28, 2024 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! 1
Members monowire Posted January 19 Members Posted January 19 Could you add support to Where Winds Meet?
Kizurin Posted January 29 Posted January 29 (edited) 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 29 by Kizurin
Members monowire Posted February 19 Members Posted February 19 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. 1
Supporter wq223 Posted February 21 Supporter Posted February 21 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 1
Engineers shak-otay Posted February 21 Engineers Posted February 21 (edited) 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 21 by shak-otay
Supporter wq223 Posted February 21 Supporter Posted February 21 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. 1
Engineers shak-otay Posted February 21 Engineers Posted February 21 Thanks! Could you give the start address of the first vertex block in your sample? (don't have the time to trick around)
Supporter wq223 Posted February 21 Supporter Posted February 21 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
Engineers shak-otay Posted February 21 Engineers Posted February 21 (edited) 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 21 by shak-otay
Supporter wq223 Posted March 29 Supporter Posted March 29 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 2
Supporter wq223 Posted March 30 Supporter Posted March 30 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.
Jenny1367 Posted April 16 Posted April 16 (edited) 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 16 by Jenny1367
Supporter wq223 Posted April 16 Supporter Posted April 16 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.
Jenny1367 Posted April 16 Posted April 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
Supporter wq223 Posted April 16 Supporter Posted April 16 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
Jenny1367 Posted April 16 Posted April 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? ><
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now