From cf91c1e234a9c6af0dda73c74a1a3a6b412580bf Mon Sep 17 00:00:00 2001 From: Lucas Farias Date: Tue, 13 May 2025 22:41:07 -0300 Subject: [PATCH 1/5] Draft RSM --- docs/file-formats/RSM.md | 496 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 494 insertions(+), 2 deletions(-) diff --git a/docs/file-formats/RSM.md b/docs/file-formats/RSM.md index 4555ac0c..e1813a8d 100644 --- a/docs/file-formats/RSM.md +++ b/docs/file-formats/RSM.md @@ -1,10 +1,502 @@ --- slug: /file-formats/rsm -title: RSM (Placeholder) +title: RSM --- +This document describes the RSM file format used in the Ragnarok Online client (and Arcturus). + +## Contents + +RSM files represent models that are scattered across the world, like buildings and trees. + +They contain: +* Animation length or animation frames per second +* Shade type +* Alpha +* Textures +* Meshes +* Animations + +From version 2.0 the extension of the files changed from `rsm` to `rsm2`. + +## Features + +### Animations + +Models can have their positon, scale, rotation and texture UVs animated. The duration +is defined on the model and can differ from the length defined on the animation track. + +The animation duration prior to version 2.2 was defined as 1000 frames per second, from 2.2 +onwards there is a new member that defines how many frames there are in a second. + +Version | Model-level position | Mesh-level position | Mesh-level rotation | Mesh-level scale | Mesh-level texture uv +--- | :---: | :---: | :---: | :---: | :---: +Version 1.1* | | | | | +Version 1.2* | | | | | +Version 1.3* | | | | | +Version 1.4 | ✅ | | ✅ | | +Version 1.5 | ✅ | | ✅ | | +Version 2.2 | | ✅ | ✅ | ✅ | +Version 2.3 | | ✅ | ✅ | ✅ | ✅ + +**\* No data** + +### Shading + +A model can use one of 3 shading types: +* Unlit +* Flat +* Smooth + +#### Unlit + +Meshes of an unlit model do not take any lighting. + +#### Flat + +With flat shading, the normal vectors are calculated per mesh. + +#### Smooth + +A smooth model take advantage of smoothing groups to calculate the normal vectors, where +each vertex can be influenced by multiple faces. + +### Transparency + +Initially models had an alpha member, but it is said to be unused, but models can still have +transparency by the use of TGA textures. + +## Layout + + +### Versions + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + :::info +No Data for this version +::: -This section is a placeholder. If you know anything about the topic, please help fill it with content! + + +:::info +No Data for this version +::: + + + + +:::info +No Data for this version ::: + + + + +```cpp title="RSM File Format (v1.4)" +struct RagnarokRSM { + char signature[4]; + uint8_t version_major; + uint8_t version_minor; + int32_t animation_length; + int32_t shade_type; + uint8_t alpha; + uint8_t padding[16]; + uint32_t texture_count; + // List of length `texture_count` of strings of length 40 + char** textures; + char root_mesh[40]; + uint32_t mesh_count; + Mesh meshes[mesh_count]; + uint32_t position_key_frame_count; + PositionKeyFrame position_key_frames[position_key_frame_count]; + uint32_t volume_box_count; + VolumeBox volume_boxes[volume_box_count]; +}; + +struct Mesh { + char name[40]; + char parent_name[40]; + uint32_t texture_count; + // Indexes into RagnarokRSM::textures + int32_t textures[texture_count]; + Mat3 transformation_matrix; + Vec3 offset; + Vec3 position; + float rotation_angle; + Vec3 rotation_axis; + Vec3 scale; + uint32_t vertex_count + Vec3 vertices[vertex_count]; + uint32_t uv_count; + TextureUV uvs[uv_count]; + uint32_t face_count; + Face faces[face_count]; + uint32_t rotation_key_frame_count; + RotationKeyFrame rotation_key_frames[rotation_key_frame_count]; +}; + +struct Face { + // Index into Mesh::vertices + uint16_t vertices[3]; + // Index into Mesh::uvs + uint16_t uvs[3]; + // Index into Mesh::textures + uint16_t texture_id; + uint8_t padding[2]; + bool two_sided; + uint8_t padding2[3]; + int32_t smoothing_group; +}; + +struct VolumeBox { + Vec3 size; + Vec3 position; + Vec3 rotation; + int32_t flags; +}; + +struct TextureUV { + Vec4 color; + Vec2 uv; +}; + +struct PositionKeyFrame { + int32_t frame; + Vec3 position; + float data; // Unknown purpose +} + +struct RotationKeyFrame { + int32_t frame; + Vec4 quaternion; +} +``` + + + + +```cpp title="RSM File Format (v1.5)" +struct RagnarokRSM { + char signature[4]; + uint8_t version_major; + uint8_t version_minor; + int32_t animation_length; + int32_t shade_type; + uint8_t alpha; + uint8_t padding[16]; + uint32_t texture_count; + // List of length `texture_count` of strings of length 40 + char** textures; + char root_mesh[40]; + uint32_t mesh_count; + Mesh meshes[mesh_count]; + uint32_t position_key_frame_count; + PositionKeyFrame position_key_frames[position_key_frame_count]; + uint32_t volume_box_count; + VolumeBox volume_boxes[volume_box_count]; + // diff-add + uint8_t padding2[4]; +}; + +struct Mesh { + char name[40]; + char parent_name[40]; + uint32_t texture_count; + // Indexes into RagnarokRSM::textures + int32_t textures[texture_count]; + Mat3 transformation_matrix; + Vec3 offset; + Vec3 position; + float rotation_angle; + Vec3 rotation_axis; + Vec3 scale; + uint32_t vertex_count + Vec3 vertices[vertex_count]; + uint32_t uv_count; + TextureUV uvs[uv_count]; + uint32_t face_count; + Face faces[face_count]; + uint32_t rotation_key_frame_count; + RotationKeyFrame rotation_key_frames[rotation_key_frame_count]; +}; + +struct Face { + // Index into Mesh::vertices + uint16_t vertices[3]; + // Index into Mesh::uvs + uint16_t uvs[3]; + // Index into Mesh::textures + uint16_t texture_id; + uint8_t padding[2]; + bool two_sided; + uint8_t padding2[3]; + int32_t smoothing_group; +}; + +struct VolumeBox { + Vec3 size; + Vec3 position; + Vec3 rotation; + int32_t flags; +}; + +struct TextureUV { + Vec4 color; + Vec2 uv; +}; + +struct PositionKeyFrame { + int32_t frame; + Vec3 position; + float data; // Unknown purpose +} + +struct RotationKeyFrame { + int32_t frame; + Vec4 quaternion; +} +``` + + + + +```cpp title="RSM File Format (v2.2)" +struct RagnarokRSM { + char signature[4]; + uint8_t version_major; + uint8_t version_minor; + int32_t animation_length; + int32_t shade_type; + uint8_t alpha; + // diff-add + float frames_per_second; + // diff-remove + uint8_t padding[16]; + uint32_t texture_count; + // diff-add-start + // List of length `texture_count` of length-prefixed strings + char** textures; + uint32_t root_mesh_count; + // List of length `root_mesh_count` of length-prefixed strings + char** root_mesh; + // diff-add-end + uint32_t mesh_count; + Mesh meshes[mesh_count]; + // diff-remove-start + uint32_t position_key_frame_count; + PositionKeyFrame position_key_frames[position_key_frame_count]; + // diff-remove-end + uint32_t volume_box_count; + VolumeBox volume_boxes[volume_box_count]; + // diff-remove + uint8_t padding2[4]; +}; + +struct Mesh { + // diff-add-start + // Length-prefixed string + char* name; + // Length-prefixed string + char* parent_name; + // diff-add-end + uint32_t texture_count; + // Indexes into RagnarokRSM::textures + int32_t textures[texture_count]; + Mat3 transformation_matrix; + // diff-remove + Vec3 offset; + Vec3 position; + // diff-remove-start + float rotation_angle; + Vec3 rotation_axis; + Vec3 scale; + // diff-remove-end + uint32_t vertex_count + Vec3 vertices[vertex_count]; + uint32_t uv_count; + TextureUV uvs[uv_count]; + uint32_t face_count; + Face faces[face_count]; + // diff-add-start + uint32_t scale_key_frame_count; + ScaleKeyFrame scale_key_frames[scale_key_frame_count]; + // diff-add-end + uint32_t rotation_key_frame_count; + RotationKeyFrame rotation_key_frames[rotation_key_frame_count]; + // diff-add-start + uint32_t position_key_frame_count; + PositionKeyFrame position_key_frames[position_key_frame_count]; + // diff-add-end +}; + +struct Face { + // Index into Mesh::vertices + uint16_t vertices[3]; + // Index into Mesh::vertices + uint16_t vertices[3]; + // Index into RagnarokRSM::textures + uint16_t texture_id; + uint8_t padding[2]; + bool two_sided; + uint8_t padding2[3]; + int32_t smoothing_group; +}; + +struct VolumeBox { + Vec3 size; + Vec3 position; + Vec3 rotation; + int32_t flags; +}; + +struct TextureUV { + Vec4 color; + Vec2 uv; +}; + +struct PositionKeyFrame { + int32_t frame; + Vec3 position; + float data; // Unknown purpose +} + +struct RotationKeyFrame { + int32_t frame; + Vec4 quaternion; +} + +// diff-add-start +struct ScaleKeyFrame { + int32_t frame; + Vec3 scale; + float data; // Unknown purpose +} +// diff-start-end +``` + + + + +```cpp title="RSM File Format (v2.2)" +struct RagnarokRSM { + char signature[4]; + uint8_t version_major; + uint8_t version_minor; + int32_t animation_length; + int32_t shade_type; + uint8_t alpha; + float frames_per_second; + // diff-remove-start + uint32_t texture_count; + // List of length `texture_count` of length-prefixed strings + char** textures; + // diff-remove-end + uint32_t root_mesh_count; + // List of length `root_mesh_count` of length-prefixed strings + char** root_mesh; + uint32_t mesh_count; + Mesh meshes[mesh_count]; + uint32_t volume_box_count; + VolumeBox volume_boxes[volume_box_count]; +}; + +struct Mesh { + // Length-prefixed string + char* name; + // Length-prefixed string + char* parent_name; + uint32_t texture_count; + // diff-add-start + // List of length `texture_count` of length-prefixed strings + char** textures; + // diff-add-end + Mat3 transformation_matrix; + Vec3 position; + uint32_t vertex_count + Vec3 vertices[vertex_count]; + uint32_t uv_count; + TextureUV uvs[uv_count]; + uint32_t face_count; + Face faces[face_count]; + uint32_t scale_key_frame_count; + ScaleKeyFrame scale_key_frames[scale_key_frame_count]; + uint32_t rotation_key_frame_count; + RotationKeyFrame rotation_key_frames[rotation_key_frame_count]; + uint32_t position_key_frame_count; + PositionKeyFrame position_key_frames[position_key_frame_count]; + // diff-add-start + uint32_t texture_animation_count; + TextureAnimation texture_animations[texture_animation_count]; + // diff-add-end +}; + +struct Face { + // Index into Mesh::vertices + uint16_t vertices[3]; + // Index into Mesh::uvs + uint16_t uvs[3]; + // Index into Mesh::textures + uint16_t texture_id; + uint8_t padding[2]; + bool two_sided; + uint8_t padding2[3]; + int32_t smoothing_group; +}; + +struct VolumeBox { + Vec3 size; + Vec3 position; + Vec3 rotation; + int32_t flags; +}; + +struct TextureUV { + Vec4 color; + Vec2 uv; +}; + +struct PositionKeyFrame { + int32_t frame; + Vec3 position; + float data; // Unknown purpose +} + +struct RotationKeyFrame { + int32_t frame; + Vec4 quaternion; +} + +struct ScaleKeyFrame { + int32_t frame; + Vec3 scale; + float data; // Unknown purpose +} + +// diff-add-start +struct TextureAnimation { + int32_t texture_id; + int32_t animation_count; + Animation animations[animation_count]; +} + +struct Animation { + int32_t animation_type; + int32_t animation_frame_count; + AnimationFrame animation_frames[animation_frame_count]; +} + +struct AnimationFrame { + int32_t frame; + float offset; +} +// diff-add-end +``` + + + From 1c13a367b24c206fd2aa798ae198c3c976f0833b Mon Sep 17 00:00:00 2001 From: RDW Date: Wed, 16 Jul 2025 23:22:27 +0200 Subject: [PATCH 2/5] Fix Docusaurus build error due to duplicate TabItem value --- docs/file-formats/RSM.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/file-formats/RSM.md b/docs/file-formats/RSM.md index e1813a8d..29e82906 100644 --- a/docs/file-formats/RSM.md +++ b/docs/file-formats/RSM.md @@ -381,9 +381,9 @@ struct ScaleKeyFrame { ``` - + -```cpp title="RSM File Format (v2.2)" +```cpp title="RSM File Format (v2.3)" struct RagnarokRSM { char signature[4]; uint8_t version_major; From c555345700de506f65e2b25bd9004906657eb3b7 Mon Sep 17 00:00:00 2001 From: RDW Date: Wed, 16 Jul 2025 23:23:22 +0200 Subject: [PATCH 3/5] npm run autoformat --- docs/file-formats/RSM.md | 45 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/docs/file-formats/RSM.md b/docs/file-formats/RSM.md index 29e82906..14d5c046 100644 --- a/docs/file-formats/RSM.md +++ b/docs/file-formats/RSM.md @@ -10,12 +10,13 @@ This document describes the RSM file format used in the Ragnarok Online client ( RSM files represent models that are scattered across the world, like buildings and trees. They contain: -* Animation length or animation frames per second -* Shade type -* Alpha -* Textures -* Meshes -* Animations + +- Animation length or animation frames per second +- Shade type +- Alpha +- Textures +- Meshes +- Animations From version 2.0 the extension of the files changed from `rsm` to `rsm2`. @@ -29,24 +30,25 @@ is defined on the model and can differ from the length defined on the animation The animation duration prior to version 2.2 was defined as 1000 frames per second, from 2.2 onwards there is a new member that defines how many frames there are in a second. -Version | Model-level position | Mesh-level position | Mesh-level rotation | Mesh-level scale | Mesh-level texture uv ---- | :---: | :---: | :---: | :---: | :---: -Version 1.1* | | | | | -Version 1.2* | | | | | -Version 1.3* | | | | | -Version 1.4 | ✅ | | ✅ | | -Version 1.5 | ✅ | | ✅ | | -Version 2.2 | | ✅ | ✅ | ✅ | -Version 2.3 | | ✅ | ✅ | ✅ | ✅ +| Version | Model-level position | Mesh-level position | Mesh-level rotation | Mesh-level scale | Mesh-level texture uv | +| ------------- | :------------------: | :-----------------: | :-----------------: | :--------------: | :-------------------: | +| Version 1.1\* | | | | | +| Version 1.2\* | | | | | +| Version 1.3\* | | | | | +| Version 1.4 | ✅ | | ✅ | | +| Version 1.5 | ✅ | | ✅ | | +| Version 2.2 | | ✅ | ✅ | ✅ | +| Version 2.3 | | ✅ | ✅ | ✅ | ✅ | **\* No data** ### Shading A model can use one of 3 shading types: -* Unlit -* Flat -* Smooth + +- Unlit +- Flat +- Smooth #### Unlit @@ -63,12 +65,11 @@ each vertex can be influenced by multiple faces. ### Transparency -Initially models had an alpha member, but it is said to be unused, but models can still have +Initially models had an alpha member, but it is said to be unused, but models can still have transparency by the use of TGA textures. ## Layout - ### Versions import Tabs from '@theme/Tabs'; @@ -108,7 +109,7 @@ struct RagnarokRSM { uint8_t alpha; uint8_t padding[16]; uint32_t texture_count; - // List of length `texture_count` of strings of length 40 + // List of length `texture_count` of strings of length 40 char** textures; char root_mesh[40]; uint32_t mesh_count; @@ -191,7 +192,7 @@ struct RagnarokRSM { uint8_t alpha; uint8_t padding[16]; uint32_t texture_count; - // List of length `texture_count` of strings of length 40 + // List of length `texture_count` of strings of length 40 char** textures; char root_mesh[40]; uint32_t mesh_count; From bb9baeffea9556da1d1eccc1225df399cb28a5e6 Mon Sep 17 00:00:00 2001 From: RDW Date: Wed, 16 Jul 2025 23:35:34 +0200 Subject: [PATCH 4/5] Remove placeholders for unknown RSM versions --- docs/file-formats/RSM.md | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/docs/file-formats/RSM.md b/docs/file-formats/RSM.md index 14d5c046..6ef15134 100644 --- a/docs/file-formats/RSM.md +++ b/docs/file-formats/RSM.md @@ -32,16 +32,11 @@ onwards there is a new member that defines how many frames there are in a second | Version | Model-level position | Mesh-level position | Mesh-level rotation | Mesh-level scale | Mesh-level texture uv | | ------------- | :------------------: | :-----------------: | :-----------------: | :--------------: | :-------------------: | -| Version 1.1\* | | | | | -| Version 1.2\* | | | | | -| Version 1.3\* | | | | | | Version 1.4 | ✅ | | ✅ | | | Version 1.5 | ✅ | | ✅ | | | Version 2.2 | | ✅ | ✅ | ✅ | | Version 2.3 | | ✅ | ✅ | ✅ | ✅ | -**\* No data** - ### Shading A model can use one of 3 shading types: @@ -76,27 +71,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - - -:::info -No Data for this version -::: - - - - -:::info -No Data for this version -::: - - - -:::info -No Data for this version -::: - - ```cpp title="RSM File Format (v1.4)" From 3c84a79c1a9e33e64d6816d2fb889e830ea1118c Mon Sep 17 00:00:00 2001 From: RDW Date: Wed, 16 Jul 2025 23:39:46 +0200 Subject: [PATCH 5/5] npm run autoformat --- docs/file-formats/RSM.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/file-formats/RSM.md b/docs/file-formats/RSM.md index 6ef15134..384a61e4 100644 --- a/docs/file-formats/RSM.md +++ b/docs/file-formats/RSM.md @@ -30,12 +30,12 @@ is defined on the model and can differ from the length defined on the animation The animation duration prior to version 2.2 was defined as 1000 frames per second, from 2.2 onwards there is a new member that defines how many frames there are in a second. -| Version | Model-level position | Mesh-level position | Mesh-level rotation | Mesh-level scale | Mesh-level texture uv | -| ------------- | :------------------: | :-----------------: | :-----------------: | :--------------: | :-------------------: | -| Version 1.4 | ✅ | | ✅ | | -| Version 1.5 | ✅ | | ✅ | | -| Version 2.2 | | ✅ | ✅ | ✅ | -| Version 2.3 | | ✅ | ✅ | ✅ | ✅ | +| Version | Model-level position | Mesh-level position | Mesh-level rotation | Mesh-level scale | Mesh-level texture uv | +| ----------- | :------------------: | :-----------------: | :-----------------: | :--------------: | :-------------------: | +| Version 1.4 | ✅ | | ✅ | | +| Version 1.5 | ✅ | | ✅ | | +| Version 2.2 | | ✅ | ✅ | ✅ | +| Version 2.3 | | ✅ | ✅ | ✅ | ✅ | ### Shading