From a3a824fe9ceba703c07280fb6fe8cc5059a3b78f Mon Sep 17 00:00:00 2001 From: SleepKiller Date: Wed, 20 Nov 2019 17:37:53 +1300 Subject: [PATCH] add exporter docs --- README.md | 55 +------------ docs/images/failed_export_example.png | Bin 0 -> 36768 bytes docs/reference_manual.md | 113 ++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 53 deletions(-) create mode 100644 docs/images/failed_export_example.png diff --git a/README.md b/README.md index 04f953b..f254e17 100644 --- a/README.md +++ b/README.md @@ -3,60 +3,9 @@ WIP .msh (SWBF toolchain version) exporter for Blender 2.8 Currently capable of exporting the active scene without collision primitives or skinning information. -### Behaviour to be aware of +### Installing -#### A UI panel named "SWBF .msh Properties" is added under the Material context. -Unsurprisingly Blender's modern and sophisticated materials don't map down well/easilly to what .msh files support. Thus seperate properties are provided for all .msh material properties. - -#### For UV layers and vertex colors layers it is the active layer that is exported. -Unlikely to come up since if you're working on a model for SWBF you're unlikely to have multiple layers to start -with but incase you do, there you go. - -#### If a scene has multiple "roots" they will be reparented to a new "root" added during export. -This is to make sure the .msh file only has one root in it. Any object that doesn't have a parent is considered a root. -There is no need to explicitly make sure your scene only has one root as a result of this, it is fine to let the exporter -add one and perform the reparenting. - -#### Object scales are applied during export. -Despite `.msh` files have a field in their transform section for scale it seams to get ignored by modelmunge. -As a result there is no point in even trying to export the scale. Instead it is applied to a the vertex coordinates during export. -The way it is applied is very basic but it should give the expected result for most use cases. Currently only the scale component of -the transform hierarchy is applied but it'd probably be better to transform the coordinates in world space and then transform them -back into local space using only translation and rotation. - -#### Object types with no possible representation in .msh files are not exported unless they have children. -Currently the exporter considers the following object types fall in this category. As I am unfamilar with Blender it is -possible that more object types should be added. - -- Lattices -- Cameras -- Lights -- Light Probes -- Speakers - -If an object with one of the above types has children it is always exported as an empty. - -#### Objects whose name starts with "sv_", "p_" or "collision" will be marked as hidden in the .msh file. -This should be consistent with other .msh exporters. As far as I know the only special thing about collision meshes or -"sv_" meshes is their name and the fact they're hidden. As such you should be able to just make a mesh and give it the right -name to get a shadow volume or or collision mesh. (Collision primitives are still preferred from the game's standpoint, -but those aren't supported yet.) - -The check for if a name begins with "sv_", "p_" or "collision" is case-insensitive. So you should be able to do -"Collision-sv-mesh" if you prefer it to "collision-sv-mesh". - -#### For completeness poloygons (`NDXL` chunks), triangles (`NDXT`) and triangle strips (`STRP`) are all saved. -This should hopefully give the .msh files the greatest chance of being opened by the various tools out there. - -Saving polygons also will make any hypothetical importer work better, since quads and ngons could be restored on import. - -The triangle strips are generated using a brute-force method that seams to give decent results. - -#### If a scene has no materials a default one will be added to the resulting .msh file. -Can't imagine this coming up much (Maybe if you're model is just for collisions or shadows?) but that's how it works. - -#### Meshes without any materials will be assigned the first material in the .msh file. -This shouldn't be relevant as any mesh that you haven't assigned a material to is likely to just be collision geometry or shadow geometry. +> TODO: Install instructions. ### Work to be done - [x] Raise an error when a .msh segment has more than 32767 vertices. diff --git a/docs/images/failed_export_example.png b/docs/images/failed_export_example.png new file mode 100644 index 0000000000000000000000000000000000000000..8b6e7ea7c8a4d45461daa98d1e0446a153a29958 GIT binary patch literal 36768 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 Nfi|w^+0V4z|1T0Q5>WsE literal 0 HcmV?d00001 diff --git a/docs/reference_manual.md b/docs/reference_manual.md index 72bad3b..8f27911 100644 --- a/docs/reference_manual.md +++ b/docs/reference_manual.md @@ -1,3 +1,116 @@ +## Exporter +The currently exporter has pretty straight forward behaviour. It'll grab the current active scene and export it as a .msh file that can be consumed by Zero Editor and modelmunge. + +> NOTE: A key limitation to know of is that there is currently no support for skinned meshes. (Meshes with vertex weights.) Support is planned in the future. + +### Export Properties + +#### Generate Triangle Strips +Enables or disables Triangle Strips generation. + +Triangle strip generation can be slow for meshes with thousands of faces and is off by default to enable a fast mesh iteration workflow if desired. + +In order to improve runtime performance and reduce munged model size you are **strongly** advised to turn **Enable** triangle strip generation for your "final" export. + +For very complex scenes with meshes that have tens of thousands (or more) faces Blender may freeze up for a couple minutes while triangle strips are generated. Either minimize it and do something else on your PC while you wait and it'll eventually finish. + +### Export Failures +There should be few things that can cause an export to fail. Should you encounter one you can consult the list below for how to remedy the situation. If you're error isn't on the list then feel free to [Open an issue](https://github.com/SleepKiller/SWBF-msh-Blender-Export/issues/new), remember to attach a .blend file that reproduces the issue. + +As of Blender 2.8 after an export has failed you can look in the "Scripting" workspace and in the bottom left corner you should be able to look for and find the description of the "RuntimeError" that caused the failure. + +![Example of failed .msh export.](images/failed_export_example.png) + +The "RuntimeError" at the top of the callstack should contain the error message. The [System Console](https://docs.blender.org/manual/en/latest/advanced/command_line/launch/windows.html?highlight=toggle%20system%20console#details) should also contain the error and can be easier to read. + +#### "RuntimeError: Error: Object does not have geometry data" +This is currently known to only happen for [Grease Pencil](https://docs.blender.org/manual/en/latest/grease_pencil/index.html) objects. There is currently no support in Blender for easilly converting a Grease Pencil object into a temporary mesh in Python the same way you do for other objects, hence no direct support for exporting them. + +To solve this error you can manually convert the Grease Pencil object to a mesh before exporting. + +#### "RuntimeError: Object '\{object name\}' has resulted in a .msh geometry segment that has more than 32767 vertices! Split the object's mesh up and try again!" +This error indicates that after turning a Blender mesh into geometry segments for a .msh file that one of the geometry segments +had more vertices than is supported in a .msh file. + +.msh geometry segments are created by iterating through a mesh's faces and assigning them to a segment based on their material. A mesh produces as many geometry segments as materials it uses. So a mesh that uses 3 materials will produce 3 geometry segments. + +To solve this error you must cut the offending Object's mesh up so that no single geometry segment made from it has more than 32767 vertices. + +#### "RuntimeError: Object '\{object name\}' is being used as a sphere collision primitive but it's dimensions are not uniform!" +This error indicates that an object marked as a sphere Collision Primitive X length, Y length and Z length are not equal. + +Rather than export a collision primitive that doesn't match what you see in Blender the exporter instead raises the error to let you know and provide you the chance to fix it. + +Fixing it should be as simple as making sure the sure representing your Collision Primitive is indeed a sphere and not an ellipsoid. Make sure it's [Scale Transform](https://docs.blender.org/manual/en/latest/scene_layout/object/editing/transform/basics.html#scale) is uniform and that you have not made any changes to the vertices or faces that would cause the mesh to cease being a sphere. (Or an approximation of one.) + +If all else fails, simply add a new UV sphere or Ico Sphere with the intended radius and location of the problematic Collision Primitive. Then delete the old one and try exporting again. + +#### "RuntimeError: Object '\{object name\}' is being used as a cylinder collision primitive but it's X and Y dimensions are not uniform!" +This error indicates that an object marked as a cylinder Collision Primitive X length and Y length are not equal. Cylinder Collision Primitives in .msh files require a uniform radius. + +Rather than export a collision primitive that doesn't match what you see in Blender the exporter instead raises the error to let you know and provide you the chance to fix it. + +In order to fix this first ensure the problematic object's [Scale Transform](https://docs.blender.org/manual/en/latest/scene_layout/object/editing/transform/basics.html#scale)'s X and Y axes have the same value. Then make sure there are no faces/vertices that are outside the intended radius of the cylinder and try again. + +If all else fails, simply add a new Cylinder with the intended radius, length, location and rotation of the problematic Collision Primitive. Then delete the old one and try exporting again. + +#### "RuntimeError: Object '\{object name\}' has no primitive type specified in it's name!" +This error indicates that an object in your scene has "p_" in it's name, indicating it is a Collision Primitive but does not also contain a Collision Primitive type in it's name. + +To solve this error consult the [Collision Primitives](#collision-primitives) section and rename the problematic Collision Primitive accordingly. Usually by adding "sphere, "cylinder" or "box" to the name. + +### Potential Edge Case Behaviour + +#### Materials for .msh files must be managed through the added UI panel named "SWBF .msh Properties" is added under the Material context. +Unsurprisingly Blender's modern and sophisticated materials don't map down well/easilly to what .msh files support. Thus seperate properties are provided for all .msh material properties. + +See the Materials section in this document for more info. + +#### Meshes and Transforms are converted from Blender's coordinate space to .msh file coordinate space during export. +This involves swapping the Y and Z axes and mirroring the X axis. In most cases this should just create the result you expect as the resulting .msh file should be aligned the same way in Blender, ingame (after going through modelmunge) and in Zero Editor. + +#### For UV layers and vertex colors layers it is the active layer that is exported. +Unlikely to come up since if you're working on a model for SWBF you're unlikely to have multiple layers to start with but incase you do, there you go. + +#### If a scene has multiple "roots" they will be reparented to a new "root" added during export. +This is to make sure the .msh file only has one root in it. Any object that doesn't have a parent is considered a root. + +There is no need to explicitly make sure your scene only has one root as a result of this, it is fine to let the exporter add one and perform the reparenting. + +#### Object scales are applied during export in world space. +Despite `.msh` files have a field in their transform section for scale it seams to get ignored by modelmunge. + +As a result there is no point in even trying to export the scale. Instead it is applied to a the vertex coordinates during export. + +The world space scale is fetched for an object and applied to all the vertex coordinates. + +#### Object types with no possible representation in .msh files are not exported unless they have children. +Currently the exporter considers the following object types fall in this category. As I am unfamilar with Blender it is possible that more object types should be added. + +- Lattices +- Cameras +- Lights +- Light Probes +- Speakers + +If an object with one of the above types has children it is always exported as an empty. + +#### Objects whose name starts with "sv_", "p_" or "collision" will be marked as hidden in the .msh file. +This should be consistent with other .msh exporters. + +#### For completeness poloygons (`NDXL` chunks), triangles (`NDXT`) and triangle strips (`STRP`) are all saved. +This should hopefully give the .msh files the greatest chance of being opened by the various tools out there. + +Saving polygons also will make any hypothetical importer work better, since quads and ngons could be restored on import. + +The triangle strips are generated using a brute-force method that seams to give decent results. + +#### If a scene has no materials a default one will be added to the resulting .msh file. +Can't imagine this coming up much (Maybe if you're model is just for collisions or shadows?) but that's how it works. + +#### Meshes without any materials will be assigned the first material in the .msh file. +This shouldn't be relevant as any mesh that you haven't assigned a material to is likely to just be collision geometry or shadow geometry. + ## Shadow Volumes SWBF's rendering engine uses Shadow Volumes for it's shadows. What this means is that the mesh for the shadow is seperate and different from the main mesh. And in order for your model to have shadows you must make the shadow mesh.