Advanced Shape Descriptor Controls #1127
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Split from #1072
Discussion thread
Related Trello card
Components of this PR depend on #1126 to function correctly. A lot of the refactoring included in the ShapeHierarchy PR removes the assumptions about wagon shapes that don't play nice with modifications to the shape file.
This PR adds an assortment of features to the MSTS shape descriptor (.sd) file that allow for manipulation of shape file data without editing the shape file itself. Effectively all of these features could be achieved by uncompressing and editing a shape file in a text editor, but that process is messy, involved, counterintuitive, prone to mistakes, and sometimes simply not possible due to copyright concerns. By manipulating the shape data but leaving the shape file untouched, modifications can be made easily, safely, and legally all from a text editor.
WagonShape ( dash9.s CustomFile.sd )
would load the "CustomFile.sd" shape descriptor rather than the "dash9.sd" shape descriptor. Additionally, if you have another engine/wagon using the same shape, but with a different .sd (likeWagonShape ( dash9.s MyReskin.sd )
, it will be treated as a separate shape entirely, allowing one "actual" shape file on the disk to be used as if it were multiple different shapes, saving file space. Note that relative file pathing works here, so the .eng/.wag, .s, and .sd can all be in entirely different folders-organize files however you like.ESD_ORTSTextureReplacement ( OriginalTexture.ace ReplacementTexture.ace )
to replace the texture definition for "OriginalTexture" inside the shape file with "ReplacementTexture.ace". While .ace is given in the example, .dds works too. Relative file pathing works here as well, so textures can be in different folders from the shape. Multiple textures can be replaced at once by adding additional statements, or adding multiple pairs of textures to one statement likeESD_ORTSTextureReplacement ( OldTex1.ace NewTex1.dds OldTex2.ace NewTex2.dds )
. If one of the 'old' textures can't be found in the shape file, a warning is recorded and no changes will be made to the shape. This feature is for the reskinners out there as, when combined with the previous feature, it allows for implementing reskins without requiring any shape file copying/pasting/renaming/uncompressing/editing. For example, the .eng of a reskin could useWagonShape ( "..\\DASH9\\dash9.s" "dash9reskin.sd" )
to reference the original shape file in its original location, but then overwrite the textures using thedash9reskin.sd
file inside the current folder, so long as that .sd file specifies something to specify the new textures likeESD_ORTSTextureReplacement ( us2dash9.ace dash9reskinA.dds us2dash92.ace dash9reskinB.dds )
.ESD_ORTSMatrixTranslation ( MATRIX x y z )
to the .sd file, whereMATRIX
is the name of the shape matrix that should be modified (matrix names can be found in utilities like shape viewer). If the shape doesn't have a matrix named MATRIX, a warning is added to the log and the change isn't applied.x y z
are the offsets from the original position of the sub object in +right/-left, +up/-down, and +forward/-backward direction, respectively. The offset uses units of length, default is meters. Note that this, and the other similar MATRIX changes can only be applied once per matrix, but can be applied multiple times as long as its to a different matrix each time. Also, applying any transform to one matrix will cause all sub-objects below it in the hierarchy to be transformed as well (the hierarchy can also be seen in utilities like shape viewer).ESD_ORTSMatrixScale ( MATRIX x y z )
but this timex y z
are the widthwise, heightwise, and lengthwise scale factors, respectively. Scale factors greater than 1 increase size, between 0 and 1 reduce size (these are units), and negative scale can be used to mirror a sub object. This can be especially useful for shapes which were built for the wrong track gauge.ESD_ORTSMatrixRotation ( MATRIX y p r )
where this timey p r
are the yaw (+left), pitch (+up), and roll (+counter-clockwise) angle to rotate the MATRIX by. Units are radians by default, but thedeg
suffix can be used to give angles measured in degrees. Note that rotation is applied last out of the 3 matrix transformations, which should reduce risk of model warping. Be careful when changing shape transforms as this can have far-reaching effects as many simulator systems rely on the 3D model data to function correctly.ESD_ORTSMatrixReanme ( OLDNAME NEWNAME )
to rename the matrix called OLDNAME to a name of NEWNAME. If the shape doesn't contain a matrix with OLDNAME then a warning will be added to the log and nothing will change. The name of the matrix is important for a few systems, especially animations, but sometimes matrices could be named incorrectly, so this allows that to be fixed without needing to uncompress and edit the shape file.ESD_ORTSLODOverride ( LODindex LODdistance )
to change the LOD with an index of LODindex to have a viewing distance of LODdistance (measured in distance units, default meters). Note that the LODindex starts at 0! 0 is the closest LOD, 1 is the second closes LOD, etc...ESD_ORTSMatrixParent ( MATRIXNAME PARENTNAME )
changes the hierarchy parent of the matrix called MATRIXNAME to be the matrix called PARENTNAME. Changing the hierarchy could cause things like infinite loops, but error checking is done on the resulting hierarchy to prevent setting a broken hierarchy, with a warning added to the log if the settings are invalid (or if either named matrix can't be found). Note that changing a matrix's hierarchy parent may require changing the position/rotation of the matrix for it to appear in the expected location, as the position/rotation are measured relative to the hierarchy parent, not relative to the 3D model as a whole.ESD_ORTSShaderReplacement ( id ShaderName )
where id is the index of the shader in theshader_names
list of the shape file (as an index, the firstnamed_shader
listed is actually shader 0, not shader 1) and ShaderName is the name of the shader, case-sensitive (valid shader names areTex
,TexDiff
,BlendATex
,BlendATexDiff
,AddATex
, andAddATexDiff
, experienced creators will be familiar with all those shaders). The intended use for this is to enable/disable transparency on shapes without the need to decompress the shape. If the id or ShaderName is invalid for any reason, warnings will show up in the log.ESD_ORTSObjectVisibility ( MATRIXNAME 0/1 )
. Like other parameters, MATRIXNAME refers to a named matrix in the shape hierarchy, but this time the second input will tell the GPU to render that matrix if the input is nonzero (this is the default behavior), and if the second input is 0 the GPU will not render anything directly attached to that matrix. The parent and children of that matrix will still be rendered, only the single specific matrix mentioned won't appear on the screen. The matrix will still be simulated though, so this can save some GPU power if shape objects don't need to be rendered, but it won't save any CPU.I am not sure if any of the methods used here will be applicable for glTF, I suspect the methodology may be similar, but the exact implementation will be different.