(mentioned exhaust connect in the wiki) |
|||
(One intermediate revision by the same user not shown) | |||
Line 168: | Line 168: | ||
=== Additional Considerations === | === Additional Considerations === | ||
==== Exhausts require a special socket ==== | |||
When making an exhaust fixture, a socket should be added to the mesh with the name <code>ExhaustConnect</code> in the location where the exhaust fixture would connect to the rest of the exhaust piping. the socket should have the Y-axis follow the direction the piping would take. This generally means the Y-axis of the socket should go into the exhaust fixture: | |||
[[File:ExhaustConnectSocket.jpg|frameless]] | |||
==== Unwrapping reflector lights ==== | ==== Unwrapping reflector lights ==== | ||
Line 283: | Line 288: | ||
===Creating the Thumbnail=== | ===Creating the Thumbnail=== | ||
You should already be here by default when you load up the Automation project. Check the top tab in Unreal and make sure it says 'ThumbnailGeneratorLevel_Fixture'. If you are not in the thumbnail generator level, open it from <code> | You should already be here by default when you load up the Automation project. Check the top tab in Unreal and make sure it says 'ThumbnailGeneratorLevel_Fixture'. If you are not in the thumbnail generator level, open it from <code>ModTools/ThumbnailGeneratorLevel_Fixture</code>.<gallery mode="nolines" widths="360" heights="240"> | ||
File:UE4ModCreation 27.gif | File:UE4ModCreation 27.gif | ||
File:UE4ModCreation 28.gif | File:UE4ModCreation 28.gif |
Latest revision as of 20:14, 15 November 2023
Overview
A fixture is a collection of files, for which a cpp
file serves as the parent file. All the settings for a fixture are inside this cpp
file.
Fixtures are comprised of up to 4 optional sub-meshes (a UV mesh, conforming mesh, skinned mesh, and additional mesh) depending on the type of fixture:
- A UV mesh is the silhouette of the cutout hole that a fixture makes in a car body.
- A conforming mesh (e.g. grilles, outer light glass, or body moulding) will deform to the shape of the body.
- A skinned mesh (e.g. light internals) will maintain its relative internal shapes, but will conform roughly to the shape of the body.
- An addditional mesh (e.g. mirrors) will retain its shape no matter where it is placed on the body.
Fixtures need material slots set up correctly to look as intended, and preview thumbnails to appear in-game.
Performance considerations
The performance of fixtures (and bodies) in UE4 is a constant discussion of balance.
There is a performance impact to poly count with fixtures in that a ray is cast to the body for every vertex; the more vertices there are in a mesh, the longer it'll take to conform to the body. This is why you'll see more detailed fixtures sit there for a few seconds before conforming to the car.
This is doubly so for fixtures that cut into the body—a UV mesh's vertices are raycast to the car on every frame while you're dragging the fixture around. UV meshes impact performance significantly with a higher poly count; try to keep UV meshes as low-poly as possible.
For optimal performance:
- Keep UV meshes lower than 100 triangles. With between 100 and 150 triangles, the fixture may lag when being dragged around; any higher and it will lag too much to use properly.
- Try to keep conforming meshes lower than 5,000 triangles. Higher-resolution meshes take longer than usual to conform to the car once they are placed.
Fixture blueprints
A Fixture is composed of a Blueprint that contains the fixture settings and sub-meshes.
Fixture Settings
Meshes (more on these below):
- Conforming Mesh - Defines the Static Mesh sub-mesh used by this fixture.
- UV Mesh - Defines the UV Mesh sub-mesh used by this fixture.
- Skinned Mesh - Defines the Skinned Mesh sub-mesh used by this fixture.
- Additional Mesh - Defines the Additional Mesh sub-mesh used by this fixture.
Text:
- Text Data - Only used for typeable text.
Fixture Preview:
- GUID - Unique identifier for this fixture.
- Family GUID - Identifier for this fixture family. This should be unique to every other family GUID, and identical to every other variant of this fixture.
Fixture:
- Fixture Type - What category this fixture should be in (e.g. headlight, aerial, grille, etc).
- Centre Snap Distance - Defines at what distance, in cm, the fixture will snap to the centre line of the car (10 by default).
- Lock Normal to Cardinal - Determines whether the fixture will conform to one of the five cardinal directions in 3D space (forwards, backwards, left, right, or upwards) by default. A non-cardinal-locked fixture will simply face in the direction of the surface on which it is placed. Cardinal locking is useful for fixtures such as lights and mirrors, since it ensures that they don't face in (or conform to) odd directions.
- Export Breakability Override - Certain categories of fixtures can break off when damaged in BeamNG.drive. This setting lets you force a fixture to be breakable or unbreakable.
- Fixture Shape - Used to filter fixtures by rectangular, round, or complex shapes. Mostly used for lights.
- Year - Used to filter fixtures by year. Useful for era-specific fixtures, such as sealed beam headlights.
- Use This Fixture as Family Preview - if you have many variants of a fixture, enabling this setting for one variant will make it the one that shows up in the main fixture menu (overriding the first fixture as per alphabetical order).
Path:
- Fixture Class - Set this to
A_Fixture
to ensure that the fixture works as intended in-game.
Fixture Sub-Meshes
UV Mesh
The UV Mesh (imported as a Static Mesh in UE4) is a flat silhouette that tells the fixture to cut a hole into the car body. You will only need vertices along the outside edges of the UV mesh, and a UV mesh is only required if your fixture intends to cut into the car. Unlike other meshes, UV meshes do not require any UV maps.
Conforming Mesh
The Conforming Mesh (imported as a Static Mesh in UE4) is a mesh where each vertex is deformed to match the surface of the car body. It is also a required mesh if the fixture has a UV mesh, as the conforming mesh is used to cover the jagged edge of the hole created by the UV mesh. A conforming mesh that could logically be placed on top of other fixtures should also have its outside edges extend beneath the body; the default distance for this extrusion is slightly farther than 10 cm.
Skinned Mesh
The Skinned Mesh (imported as a Skeletal Mesh in UE4) is used when you have parts of a fixture that should conform to the rough shape of the car, but also retain the dimensions and ratios of any individual components. A skinned mesh will have a bone for each element that is parented to a root bone.
Some vertices of a skinned mesh will conform to the car as with a conforming mesh if they are a) within 1.5 mm of the car body surface, whether weighted to any bones or not, b) weighted to the root bone, or c) not weighted to any bones. Because of the former, there may be a small gap of at least 1 mm between the edge of the skinned mesh and the car body. To cover up this gap, a conforming mesh is often used to connect the edge of the skinned mesh with the car body.
Additional Mesh
The Additional Mesh (imported as a Static Mesh in UE4) does not deform in any way and will remain in place relative to the location of the fixture. An additional mesh has no skin or bones, and no part of it will deform to the shape of the car. Examples of additional meshes are exhaust tips, wing mirrors, and most fixtures intended for 3D placement.
Modelling a fixture
Note: This how-to assumes a general understanding of polygonal 3D modelling software. Any 3D modelling package will do, as no custom scripts are required to author fixture meshes.
Hard Rooster has created a full video series for fixture modding in Blender. The full series can be found here.
Fixture Orientation
Fixtures are oriented in the following manner in a 3D modelling program. Note how the negative Y axis faces forwards.
Fixture Y-Axis Thresholds
There are 2 important values to take in to note for fixture sub-meshes.
- A skinned mesh will have some of its vertices conform to the car as if it were a conforming mesh, but only if those vertices are within 1.5 mm from Y=0. A vertex with a Y axis value of 1.5 mm will conform to the car as if it were part of a conforming mesh, and a vertex with a Y axis value of 2.0 mm will not.
- The outer edges of most vanilla conforming meshes (and inner edges of things with holes in them, like open grilles) usually sit 10 cm below the surface (or 10 cm inwards along the Y axis). This stops fixtures from appearing to 'float' when put on top of other fixtures that cut into cars and leave holes, such as grilles and moulding. This is by no means a hard-and-fast rule; specific applications may call for fixtures to extend anywhere from 1 to 100 cm into the body.
It's a bit confusing at first, but following these rules will ensure your fixture works correctly.
Deciding What Sub-Meshes You'll Need
Fixtures have a fairly convoluted list of things that are or are not needed, depending on what's in the fixture.
- If you have a UV mesh, you need a conforming mesh to cover the hole.
- If you have a conforming mesh, it isn't required to have anything else unless said Conforming Mesh has parts that go below the car body mesh (in which case you'll need a UV Mesh to cut a hole out for it).
- If you have a skinned mesh, you'll need a conforming mesh and a UV mesh, as a skinned mesh can only be inside the car. Therefore, a UV mesh is needed to cut out that hole, and a conforming mesh is needed to cover the edge of that hole.
- If you have an additional mesh positioned above the car body, nothing else is needed. If the additional mesh is obscured by the car body mesh, you'll need a UV mesh to cut out the hole for that (and by extension, a conforming mesh to line that hole).
For this example, we'll make the components for the headlight fixture below (a Conforming Mesh, UV Mesh, and a Skinned mesh with 4 bones).
Creating the Sub-Meshes
Creating a UV Mesh
The UV mesh defines the texels (texture pixles) of the car body that will be cut out by the fixture. Each vertex is used as a point of reference, and lines are drawn between them along the edges of the UV mesh to define the final cutout shape. If there are too few vertices, the cutout shape may become distorted, since the vertices are projected onto the car texture before being cut out (with the actual edges of the UV mesh not being used). This, combined with the round "pelt unwrap" nature of car bodies' UV maps, can result in waviness between vertices in the cutout shape. This is more pronounced on larger fixtures, or fixtures that are stretched to several times their original size.
A UV mesh should have vertices at regular intervals around the outside to determine the cutout shape of the fixture. Any vertices that aren't on an edge are irrelevant and will only make the fixture slower to render. Note that UV meshes can be made in annulus shapes with holes in the middle, like a doughnut.
The UV mesh should be roughly halfway between the outside edge of the skinned mesh (which should share its edge with the inside edge of the conforming mesh) and the outside edge of the conforming mesh.
See below for the example UV mesh in comparison to its respective conforming mesh.
Note that the centre vertices may need to be offset slightly from their respective axes; see Additional Notes for more information.
If you're having trouble with wavy cutouts on cars, segment your UV mesh into quads instead of a starburst pattern, as shown here.
Creating a Conforming Mesh
A conforming mesh is a single basic polygonal mesh that conforms to the shape of the car body.
The conforming mesh should have enough polygons at regular intervals so that it doesn't appear blocky or clip through the car body. The more polygons you add to the conforming mesh, the longer it will take to calculate its final morph position, but this does not impact performance when it is dragged around.
For this example fixture, we'll be using a conforming mesh for two purposes:
- Connecting the skinned mesh to the car body.
- Covering the cutout hole created by the UV mesh.
However, a conforming mesh can be used without a skinned mesh, such as:
- for trim pieces, moulding, or badges.
- for vents and grilles, when used with a UV mesh.
We'll start by using the UV mesh as our reference point. Our conforming mesh needs to cover the hole created here, so we'll make a ring of faces to surround the UV mesh with enough width to not allow any visible gaps between the cutout and the conforming mesh. We'll extend this edge out along the -Y axis (forward from the car body) by a millimetre or two to prevent faces from clipping through the car body, and we'll extrude a ring of faces around the outside of it to connect the mesh to the car body like so:
Because this fixture is going to have a skinned mesh, we'll need to take that into consideration too. A skinned mesh will have any vertices that are farther than 1.5 mm in the -Y axis conform to the car in the same way as a conforming mesh, so we'll need to match this mesh structure such that the two meshes connect seamlessly. Here is the conforming mesh, with the skinned mesh and UV mesh:
This headlight fixture will also have a glass cover over it, so we'll add that in now. For this example, I've added a small step to the inside of the conforming mesh to add a little bit of detail. The glass cover will then be placed on top. You'll also notice that the outside edge of this headlight has been extruded deep behind the surface; this is so it can be placed on top of other headlights or grilles and not appear to float.
Unwrapping the Mesh
The next step is to unwrap the mesh. We'll be using 3ds Max's default UVW Map modifier, setting it to 'box' projection (cube projection in Blender), and setting the length, width, and height dimensions all to 2. This value is important if your fixture mod intends to use our default materials, because said materials assume that the UVs of the fixture conform to this setting.
Basically, what this is doing is UV mapping the mesh so that the 0-1 areas of the UV map are 2cm².
We'll go over the import process and material setup after we've created all of the meshes.
Creating a Skinned Mesh
A skinned mesh is the most complicated mesh in a fixture. It follows the same rules as the conforming Mesh in terms of overall mesh structure and UV mapping, but the manner in which it conforms to the car is more nuanced.
The vertices of a skinned Mesh will conform to the car in the same manner as the conforming mesh if those vertices are within 1.5 mm of the Y axis. This is useful for having these parts of the mesh connect to a conforming mesh, as they will conform the same in that area.
The rest of the mesh will conform relative to their skinned bones and weights. For this example, I've created a Skinned Mesh with 4 bones, and weighted them like so:
The bones are free-floating and are parented only to the root bone. In 3ds Max, usually use Dummy Actors for my bones, but you can use a box mesh or whatever works.
Take note that the vertices that conform to the mesh do so in the same manner as the conforming mesh, but are still weighted to their respective bones. This is because Automation's fixture system uses the distance that these vertices were morphed to determine how far back to conform each bone. If these vertices were weighted to the root bone instead, the fixture would not know how far to morph the skinned sections of the mesh.
Unreal Engine 4 also requires a bone hierarchy, so I've made a root bone and parented all of the other bones to it. The root bone should not be weighted to any vertices here, though with other fixtures, weighting vertices to the root bone makes them conform even if they're outside of the 1.5 mm threshold. Whatever you do, though, do not weight a vertex to the root bone and another bone at the same time, as the vertex in question will snap to the fixture's origin point
Take a look at the image below of the skinned mesh on the car (there's also a conforming mesh there around the edge, but we'll ignore that for now). The outer ring of vertices is conforming to the car as if it was part of a conforming mesh, and the rest of the mesh is conforming as per their bone weights:
Unwrapping the Mesh
Assign the same box map (with a scale of 2, 2, 2) as you did with the conforming mesh.
Creating an Additional Mesh
An Additional Mesh is a simple mesh with no skin or morphs that does not deform in any way. The Additional Mesh does rotate around the fixture position, and will maintain its relative position from its pivot point.
Take this exhaust fixture as an example. Note that the entirety of the exhaust is offset from the pivot point—this is so that it can hang under the car, since the fixture itself must have its pivot point on the car.
Additional Considerations
Exhausts require a special socket
When making an exhaust fixture, a socket should be added to the mesh with the name ExhaustConnect
in the location where the exhaust fixture would connect to the rest of the exhaust piping. the socket should have the Y-axis follow the direction the piping would take. This generally means the Y-axis of the socket should go into the exhaust fixture:
Unwrapping reflector lights
If your fixture is a light that contains a reflector surface (such as an incandescent bulb), there are some special considerations.
Let's take a look at this fixture as an example:
Several things are of note with regards to light components.
The reflector shader material looks at the UVs of the mesh to determine how to render it.
- The bulbs themselves should be unwrapped as a single point with zero scale exactly at UV coordinate
0.5,0.5
(the UV is scaled to a single point in the very center).- The reflector shader is a single material, so to render the bulb slightly transparent and with a colour to it, the shader renders all faces unwrapped at
0.5,0.5
as a bulb. Because the shader has such a tight tolerance for the UV coordinates, this doesn't affect other overlapping surfaces within the UV map.
- The reflector shader is a single material, so to render the bulb slightly transparent and with a colour to it, the shader renders all faces unwrapped at
- The main reflector surface should be unwrapped such that each quad face fills the entirety of the
0-1
UV coordinate space (Reset UV projection
in Blender).- The reflector shader has a reflector dome texture which it uses, so any surface you wish to have this dome texture on it should be unwrapped as such.
- Any other part of the reflector that you want to have vertical or horizontal lines on should be unwrapped as a single point with zero scale exactly at UV coordinate
0,1
(the UV is scaled to a single point in the bottom left corner).- The shader will dynamically render a corrugated effect on any UV at the bottom left corner.
- Parts of the reflector that should be perfectly flat should be unwrapped as a single point with zero scale exactly at UV coordinate
0,0
(the UV is scaled to a single point in the top left corner).
Applying materials to a light component
The bulb and reflector for each light should be assigned to the same material slot to save on draw calls. Each separate light, however, should be a different material slot for freedom of choice in terms of light configurations.
Unwrapping radial glass
For light glass with a radial pattern, unwrap the glass so that the radial pattern fills the whole UV space as a single texture.
Fixture setup within Unreal Engine 4
This step assumes that the correct version of Unreal Engine is installed and configured correctly. See Modding for more information on the correct version of Unreal Engine to use and how to view mod content folders. Also see the official Unreal Engine documentation on importing FBX files for more information.
Creating your Fixture Mod Plugin
Using the correct version of Unreal Engine, with our modding tool project opened and plugins loaded, select 'Create Mod' from the top menu bar.
Importing Files
There are several ways to import your sub-meshes to this mod folder. The easiest is to simply navigate to the folder you want to import your files in the Content Browser, then click the 'Import' button to import files to that folder, select the meshes you want to import, and click 'Open'. none|thumb|360x360px
UV meshes, conforming meshes, and additional meshes should be imported as static meshes ('Skeletal Mesh' is un-ticked in the import dialogue), while skinned meshes should be imported as skeletal meshes ('Skeletal Mesh' is ticked in the import dialogue).
Note that 'Skeletal Meshes' will import with additional 'Skeleton' and 'Physics Asset' files. These are important. You don't need to do anything with them, but don't delete them.
Note that 'Import Materials' is also unticked, as we do not want to import any materials from the modelling software. The final set of imported files in Unreal Engine should look like this:
Once your files are imported, it's important to set 'CPU Access' to true for all static meshes. You can do this by selecting every static mesh, right-clicking on it and selecting 'Set Meshes to Allow CPU Access'.
Default Materials and Material Slots
Note: This step assumes a basic understanding of UE4's Static Mesh editor and Skeletal Mesh editor. Alternatively, material slots can be named appropriately within a 3D modelling program of choice.
The fixture material system in Automation relies on the name of the material slots within the meshes to define what materials can be applied to the fixture. Therefore, assigning the correct materials to the meshes is only important for the initial selection and loading of that fixture. In this manner, it is possible to have custom materials applied to your fixture with it still being compatible with Automation's fixture material menu.
The fixture material menu in Automation relies on the names of the material slots on the sub-meshes to decide what category of materials the player can select from, with said names in the format category_#
(case-sensitive, with '#' being a single- or multiple-digit number of choice).
The available categories for fixture materials are as follows:
If you only have a single slot for a fixture material category, you still need a number for it. This number scales infinitely, meaning a fixture can have many separate slots of a single category assigned to it. A fixture's sub-meshes cannot share the same name on its material slots. If a fixture contains meshes with duplicate slot names, they will appear as a single material slot in-game (this can be used to merge slots on, for example, a conforming and additional mesh).
With light fixtures, the names of the slots for the corresponding pair of glass and reflector material slot names should share the same number. For example, a fixture with two lights would have glass_01
(or just glass_1
) and bulb_01
, and glass_02
and bulb_02
.
Below is a headlight's conforming mesh with its default materials set and the names of its material slots set to their respective types. The workflow for additional meshes should be identical.
- Headlight Conforming Mesh Materials Setup 01.jpg
The Skeletal Mesh editor looks a little different, but the slot naming conventions are the same:
Assigning Default Materials
While the slot names define what materials the player can choose from in-game, it doesn't define what material first gets loaded when the fixture is spawned in.
When the fixture is first placed on the car, it loads the material that is set in that fixture's sub-mesh default materials. For the sub-mesh examples above, you can see that not only have the slots been named appropriately, they also have materials assigned to them. Therefore, for all your fixture sub-meshes, default materials should be applied. (They're not strictly necessary, but your fixtures deserve better than the default grey checkered material.)
To find where all the materials available in-game are, open up the CarMaterialUtils
blueprint (located in Content
-> Utility
), and open the 'Get Materials from Slot' function. There, you can view the list of each material that gets assigned to each slot, find them in the content folder, and assign them to your mesh as the default material. Note, though, that these steps are only to find where the default materials are. We do not use the Utils blueprint itself to assign materials to fixtures.
To do this, open CarMaterialUtils
...
...then open 'Get Fixture Materials from Slot', located in CarMaterialUtils
-> Car Painting
-> GetFixtureMaterialsFromSlot
.
From there, select the corresponding materials array for the material category you want to apply to your sub-mesh from the Local Variables tab, and in the details panel you'll see an array of the materials used for that slot type. By expanding that, you can see the materials, and by selecting the small magnifying glass icon, view that material in the Content Browser, and from there apply it to your sub-mesh.
Creating and Setting Up the CPP File
Right-click in the content browser, and from the 'Camso' sub-menu, select the 'Fixture Preview Data' option. You should now have a fixture CPP file in your content browser.
Open the CPP file. You should get something like this:
Fill out the 'Meshes' section with the meshes you've made, leave the 'Text' data empty, generate a GUID and Family GUID (or copy the family GUID if you're making a variant), and set the 'Fixture' settings to the relevant info as laid out near the top of this page. Finally, in the 'Path' section, make sure there is one item in the array, and fill it with A_Fixture
. This is important; your fixture will not work if this is not filled correctly.
When you're done, you should have something that looks like this:
Be sure to save your files.
Creating the Thumbnail
You should already be here by default when you load up the Automation project. Check the top tab in Unreal and make sure it says 'ThumbnailGeneratorLevel_Fixture'. If you are not in the thumbnail generator level, open it from ModTools/ThumbnailGeneratorLevel_Fixture
.
From the top menu, open the drop-down next to the 'Play' button and select 'Simulate'. You should now be 'simulating' the level.
Generate Fixture Thumbnails
Select the Fixture Thumbnail Generator from the World Outliner, and add your fixture blueprint to the 'Fixture Previews to Generate' array (by first clicking the 'plus' icon, then putting the fixtures you have created into the list). Repeat this process for every fixture you have created. It does not matter if these fixtures are of the same family or not. Then, select 'Export Preview' to generate the Thumbnail file.
Because these files are created by the modding tools, they need to be manually saved (even if no asterisks are present).
Your fixture mod is now ready to be shared!
Cooking and sharing your mod
To use the mod you have just created, you need to 'share' it. See the main Modding page on how to share your mod.
Additional notes
- Fixtures should not have any vertices along the centre axes to avoid any miscalculation by the fixture gizmo. If the game casts a ray through the centre line of the car, it may miss the two halves of the car and return a false positive of the fixture being out of bounds. Offsetting your vertices slightly will avoid this. Additional meshes are the sole exception to this rule, as they do not conform in any way.
- If you're testing out a fixture and the meshes it uses haven't been finalized, you can use UE4's 'Reimport' function to replace the existing mesh with a newer version of it. All the materials already assigned to the mesh will be preserved, as will its reference in the blueprint, saving you the trouble of manually reimporting a mesh and having to reassign materials and put it into the blueprint again. This works for car body meshes as well.
- Is CPU access still turned on for all static meshes? If your mod causes a crash or isn't visible in-game, this might be unticked. It does that sometimes; re-enable it and try again.
- If the first fixture in a thumbnail generation array ends up with an unusually sparkly thumbnail, this can be fixed by giving it an additional duplicate array entry (which forces UE4 to render the thumbnail again normally).