Adding a new model to the website - PatPL/Generic-Engines-Web GitHub Wiki
To understand this guide you'll need to know at least the basics of Blender and Javascript
Setup
To add a new model to the website, you need Typescript compiler (And therefore Node.js), the model (.mu and .dds texture files), Blender, and Blender's mu addon. I suggest using VSCode for file editing.
In this example I'll add an 'LV-NX4 "Fat Mun" Atomic Rocket Motor' from SXT.
Start Blender and import the model. Move the model to the (0,0,0) point of the scene. Then, add a cyllinder mesh. Set Vertices to 500, Radius to 0.5, and Depth to 1.0. This will be your reference cyllinder of size 1m x 1m. We'll use it later to find various sizes and positions. Move it to (0,0,0).
Use CMD to navigate to the directory with 'tsconfig.json' file, and run 'tsc -w' command. This will compile Typescript into Javascript on the fly. Keep the terminal open. (Or open the project's folder in VSCode, and type 'tsc -w' in the terminal (Ctrl + `)).
Adding the new model's template
First, add a new entry to the bottom of the 'Model' enum in Enums/Model.ts. I chose name 'NERVAwide'. This is the unique ID used to recognize the model.
Then, navigate to the Data/ModelInfo.ts file. Add a new object to the bottom of the 'models' array. VSCode should let you know of any missing properties. I'll describe every property later. You can also look for a template on the bottom of the file. I'll use the template in this guide.
Filling out the properties
I will fill out the fields in an order, that makes the most sense.
The comment
Currently, the 'models' array is not indexed. This might change in the future. For now it's important to keep Model enum and the array synchronized. That's why you should type the name of the model in the comment.
//Model.NERVAwide
ModelName
This is the name shown on the website.
ModelName: "NERVA wide",
ImageLabel
This is the name of the engine in the model selector. Should be the same as the ModelName, but can be overridden
get ImageLabel(): string { return this.ModelName }
ModelType
Used to group engines back when the engines were selected from a dropdown list. Not used for now, but might have some use in the future. Try to use 'Fake' for made up models, and 'IRL' for models based on real engines. You can see all options in the EngineGroupType enum, in Enums/EngineGroupType.ts.
ModelType: EngineGroupType.Fake,
HiddenMuObjects
GE's engines use neither fairings, nor any additional adaptors. That's why they have to be hidden in game. This array has names of objects, that have to be hidden. Our model has a fairing, so I have to hide it. I find the fairing in the Blender's Outliner, and copy the fairing's name. I paste this name in the array. Then I delete the fairing from the scene. You should also remove any colliders from the scene, as they just obscure the view. Don't type collider's names in the array though.
HiddenMuObjects: [
"fairing"
],
ThrustTransformName
This is the origin of the thrust. Find appropiate empty node in Blender, and copy the name. Most likely It'll be called 'thrustTransform', and will be located near the engine bell.
ThrustTransformName: "thrustTransform",
GimbalTransformName
This is the object, that will be gimballed. Make sure the origin of the object is in the right place, and that thrustTransform's node is a child of the object. Try to rotate the object around in blender and see whether it looks right. This model has no nozzle object, so I'll paste in the thrustTransform's name.
GimbalTransformName: "thrustTransform",
OriginalBellWidth
This is the width of the bell. To measure it, move the 1m cyllinder near the bell, press 's', and move the mouse, so that the cyllinder just barely covers the entire bell. The scale of the cyllinder is the value you should enter.
OriginalBellWidth: 2.074,
OriginalBaseWidth
Same thing as above, but with the base of the engine.
OriginalBaseWidth: 2.895,
PlumeSizeMultiplier
This one's tough, because it has no representation in Blender. I've noticed that aiming for 85-90% of the OriginalBellWidth seems to fit most of the times. Is plume's size doesn't fit the bell, you'll have to tweak this value.
PlumeSizeMultiplier: 1.8,
PlumePositionOffset
This is the offset of plume's origin relative to thrustTransform. If the plume should appear above the thrustTransform, the offset should be negative, and if the plume should appear below the thrustTransform, the offset should be positive. You can find this offset by selecting the thrustTransform in blender, pressing 'gz', and moving the thrustTransform roughly to the middle of the bell. The offset will be in the lower left corner
PlumePositionOffset: -2,
NodeStackTop
Make the cyllinder small, and move it to where the top stack node should be. Then copy the cyllinder's Z position.
NodeStackTop: 0.05,
NodeStackBottom
Same as above, but on the bottom of the engine
NodeStackBottom: -5.74,
OriginalHeight
Usually should be equal to NodeStackTop - NodeStackBottom, but can be overridden. Then that would be equal to the Z scale of the cyllinder on the model.
get OriginalHeight (): number { return this.NodeStackTop - this.NodeStackBottom; },
TextureDefinitions
Some models use textures from the base game. Check the .cfg file of the part from the original mod, and look for stuff that looks like this:
texture = model000 , Squad/Parts/Engine/liquidEngineLV-N/model000
texture = model001_NRM , Squad/Parts/Engine/liquidEngineLV-N/model001
texture = model002 , Squad/Parts/Engine/liquidEngineLV-N/model002
texture = fairing , Squad/Parts/Engine/liquidEngineLV-N/model003
Copy all of these.
TextureDefinitions: `
texture = model000 , Squad/Parts/Engine/liquidEngineLV-N/model000
texture = model001_NRM , Squad/Parts/Engine/liquidEngineLV-N/model001
texture = model002 , Squad/Parts/Engine/liquidEngineLV-N/model002
texture = fairing , Squad/Parts/Engine/liquidEngineLV-N/model003
`,
ModelFiles
First, place the model (.mu) in the files/[Mod name]/[Optionally separate folder]/ directory. Add the path to the file to the array.
Then, visit this site and upload the .mu file. The site will list every texture file used in the model. Copy every required file to the same directory as above, and add paths to these files to the array.
ModelFiles: [
"files/models/SXT/NERVA/portlyman.mu",
"files/models/SXT/NERVA/fairing.dds",
"files/models/SXT/NERVA/model000.dds",
"files/models/SXT/NERVA/model001_NRM.dds",
"files/models/SXT/NERVA/model002.dds"
],
ModelPath
This is the path to the model (*.mu), but with 'files' replaced with GenericEngines, and without extension.
ModelPath: "GenericEngines/models/SXT/NERVA/portlyman",
CanAttachOnModel
Should you be able to attach other parts to this part? Good for SRBs. The collider should resemble the model as much as possible
CanAttachOnModel: false,
OriginalTankVolume
The volume of the tanks on the model with the original (in blender) size. Unit: L. Kinda tricky to calculate. 1 unit in Blender is 1m. Use that. Try adding toruses, cyllinders or spheres, and make then tank sized. Then calculate their volume.
OriginalTankVolume: 0,
An example:
RadialAttachment
If false, the engine will attach without a node like most RO engines. (For bottom mounted engines)
If true, the engine will attach like SRBs in vanilla KSP. (For side mounted engines)
RadialAttachment: false,
RadialAttachmentPoint
How far off center should be the engine's radial attachment node? Keep 0 if RadialAttachment is false.
Should be ~1/2 of the OriginalBaseWidth
RadialAttachmentPoint: 0,
ImageSource
The URL to the model preview in the model selector. Try to keep the same name as in the comment to avoid conflicts.
ImageSource: "img/modelPreviews/NERVAwide.png",
Result
This is the final object. The model should be ready.
, { //Model.NERVAwide
get OriginalHeight (): number { return this.NodeStackTop - this.NodeStackBottom; },
OriginalBellWidth: 2.074,
OriginalBaseWidth: 2.895,
PlumeSizeMultiplier: 1.8,
PlumePositionOffset: -2,
NodeStackTop: 0.05,
NodeStackBottom: -5.74,
ModelPath: "GenericEngines/models/SXT/NERVA/portlyman",
ModelFiles: [
"files/models/SXT/NERVA/portlyman.mu",
"files/models/SXT/NERVA/fairing.dds",
"files/models/SXT/NERVA/model000.dds",
"files/models/SXT/NERVA/model001_NRM.dds",
"files/models/SXT/NERVA/model002.dds"
],
TextureDefinitions: `
texture = model000 , Squad/Parts/Engine/liquidEngineLV-N/model000
texture = model001_NRM , Squad/Parts/Engine/liquidEngineLV-N/model001
texture = model002 , Squad/Parts/Engine/liquidEngineLV-N/model002
texture = fairing , Squad/Parts/Engine/liquidEngineLV-N/model003
`,
ThrustTransformName: "thrustTransform",
GimbalTransformName: "thrustTransform",
ModelName: "NERVA wide",
ModelType: EngineGroupType.Fake,
HiddenMuObjects: [
"fairing"
],
CanAttachOnModel: false,
OriginalTankVolume: 0,
RadialAttachment: false,
RadialAttachmentPoint: 0,
ImageSource: "img/modelPreviews/NERVAwide.png",
get ImageLabel(): string { return this.ModelName }
}
Test everything
Now the model should appear in the model selector on the website. Create an engine list with few engines with varying sizes, and export them. Launch KSP and check whether the engine is in the game, the textures are correct, and whether the plume is set up correctly. That's all.
Example test engine list:
AA0BBAAwMDAxAAAAAAAA8D8AAAAAAECPQAAAAAAAQG9AAAAAAADAckABAAIAAAAAAAAA8D8AAAAAAADwPwAAAAAAAABAAAAAAAAAJEDoAwAAAAAAAACAVkABAAAAAAEAAAAAAAAAAAAAAAIAAAAAABAnAAAAAAAAAQAAAAAAAAAAAAAAAAAAAQAAAAANAQQAMDAwMgAAAAAAAPA/AAAAAABAj0AAAAAAAEBvQAAAAAAAwHJAAQACAAAAAAAAAPA/AAAAAAAA8D8AAAAAAAAAQAAAAAAAACRA6AMAAAAAAAAAgFZAAQAAAAABAAAAAAAAAAAAAAACAAgAAAAQJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAADQEEADAwMDMAAAAAAADwPwAAAAAAQI9AAAAAAABAb0AAAAAAAMByQAEAAgAAAAAAAADwPwAAAAAAAAhAAAAAAAAACEAAAAAAAAAkQOgDAAAAAAAAAIBWQAEAAAAAAQAAAAAAAAAAAAAAAgAOAAAAECcAAAAAAAABAAAAAAAAAAAAAAAAAAABAAAAAA0BBAAwMDA0AAAAAAAA8D8AAAAAAECPQAAAAAAAQG9AAAAAAADAckABAAIAAAAAAAAA8D8AAAAAAAAIQAAAAAAAACJAAAAAAAAAJEDoAwAAAAAAAACAVkABAAAAAAEAAAAAAAAAAAAAAAIAAgAAABAnAAAAAAAAAQAAAAAAAAAAAAAAAAAAAQAAAA==