Skip to content

Adding a new model to the website

PatPL edited this page Jun 23, 2019 · 15 revisions

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==