Importing Custom Models
Custom Models for Custom Sprites
.brres subfile versions used in NSMBW
Subfile | Version | Type |
---|---|---|
MDL0 | 11 | Model |
CHR0 | 5 | Model Animation |
PAT0 | 4 | Texture Patterns |
SRT0 | 5 | Texture Animation |
VIS0 | 4 | Visibility Sequence |
CLR0 | 4 | Color Sequence |
SHP0 | ? | ? |
SCN0 | 5 | ? |
TEX0 | - | Texture |
Tools and requirements
- An extracted dump of the game.
- The model you want to import, its textures, animations, etc.
- A tool you can use for importing/exporting 3D models (3ds Max is recommended. Blender is more accessible, but only works with the latest versions of BrawlCrate. BrawlBox does not support Blender.
- A blank .arc file with the "g3d" folder. You can make one yourself simply by taking an existing .arc from the game's Object folder and deleting all .brres files, or by downloading this empty one here. Afterwards, you can import an existing .brres, or create a new one by right-clicking the folder and selecting New -> BRRES.
Process
todo:
- importing (converting with 3ds Max or fbx converter)
- fixing materials and shaders
Importing - Models
First you'll need a .dae file of the model that you want to import. You can either export using 3ds Max, or use FBX Converter to convert a model file into .dae.
Now, to get started on importing models, right-click on your brand new .brres and select Import -> Models. Then, select your .dae.
(todo: add something about settings and what they do; if you're reading this you can go ahead and enable Add Colors and Blender Bone Fix. They'll probably be useful.)
To add textures, right-click on your .brres and select Import -> Textures.
Importing - CHR0 Animations
You'll need a .anim file for your animations. (todo: add a guide)
Now we want to import our animations. Right-click on the .brres and select Import -> Model Animations, and import your .anim file. If you can't view the animations with BrawlCrate (which can happen), try to view it with BrawlBox instead.
Materials and Shaders
Materials
To create a material for the model, open the .mdl0 and go to the "Materials" folder. (If it doesn't exist, then right-click on the mdl0 and select New -> Material. It will generate a material and shader.) Right-click it, and select Add New Reference. Rename the material as necessary.
Once you've added your new reference, a new reference called "NewRef" will appear (this will also appear in the "Textures" folder of the mdl0). Rename it to the name of the texture that you want to reference. Afterwards, you can go to the "Textures" folder of the mdl0 and delete the "NewRef" texture reference, as it isn't needed anymore.
Shaders
Look for an existing object in the game's "Object" folder. Find the "lm_0XY" (where X is the identification number for the lightmap texture in its group, and Y is/are the identification letter(s) for the lightmap texture usage.). A chart of what these stand for can be seen below.
Identification Letter(s) | Translation | Meaning | Usage |
---|---|---|---|
m | map | Background | The background's lightmap |
mo | map object | (Fits in none of the other groups) | The lightmap of objects that don't fit in the other groups |
p | player | Player | The player's lightmap |
e | enemy | Enemy | The enemy's lightmap |
b | boss | Boss | The boss's lightmap |
i | item | Item | The item's lightmap |
Once you've found them, export them as .tex. Then import them into your model..
Go back to the file you exported the lightmaps from. Export the materials which use the lightmap. In the material you can see the shader that it uses. Export the shader as well (found in the "Shaders" folder in the mdl0).
Now go to your model, and replace the existing material and shader with the ones exported. For the material, be sure to rename the first ref to the actual texture of your model, since by now it's the name of the texture from the model we exported it from. Add any other references necessary. Be sure to rename the material itself if necessary.
Lastly, we open the "Objects" folder of the mdl0 and click on the object that uses the material that we just imported.
Set TextureMatrix[1 & 2]Enabled to true. This way the lightmap textures are properly used.
You can also refer to this side for another tutorial made for MKW, though be aware that there might be differences between MKW and NSMBW model importing processes!
Rigging
Often you have a model but it isn't rigged to bones. This means you can't animate it which basically makes it unusable in a game. Below are two tutorials, one for 3ds Max and one for Blender:
Transparent textures
Refer to this side to see how to setup the materials for transparency!
Code Examples
Setting up the lightmaps in the code
Texture Name | SetupTextures_[X] |
---|---|
lm_01b | Boss |
lm_01e | Enemy |
lm_01mo | MapObj |
lm_01i | Item |
lm_01m | Map |
lm_01p | Player |
In Newer we got functions called SetupTextures_X
. These have to be called in order to get your model to display correctly with applied lightmaps. Which one to call depends on the lightmap textures your model uses. E.g. if it has lm_01e
and lm_02e
for example, you will have to call SetupTextures_Enemy
.
Loading a model
//put this in your class definition so you can access it again after creating the model
mHeapAllocator_c allocator;
nw4r::g3d::ResFile resFile;
m3d::mdl_c bodyModel;
//usually in onCreate()
allocator.link(-1, GameHeaps[0], 0, 0x20);
resFile.data = getResource("pukupuku", "g3d/pukupuku.brres");
nw4r::g3d::ResMdl mdl = resFile.GetResMdl("pukupuku");
bodyModel.setup(mdl, &allocator, 0x227, 1, 0);
SetupTextures_Enemy(&bodyModel, 0);
//load animations here (see next paragraphs)
allocator.unlink();
Notice, that the bitmask passed to m3d::mdl_c::setup()
controls which parts of the model are copied. Most of the time you will see bodyModel.setup(mdl, &allocator, 0x224, 1, 0);
in Newer but for example for pat0 animations to only apply to one actor or sprite at a time and not all of them that are spawned somewhere, you have to bitwise or the bitfield with 0x3, so each time to object is spawned, a new copy of the animation is created that will only affect the newly spawned object and not the previous ones. Below a list of flags for different animation types:
Animation | Flag |
---|---|
pat0 | 0x3 |
srt0 | 0x204 |
clr0 | 0x108 |
vis0 | 0x40 |
shp0 | 0x7000 |
And that's why above you see bodyModel.setup(mdl, &allocator, 0x227, 1, 0);
instead as the code was written with the intention to use a pat0 animation. So: 0x224 | 0x3 = 0x227
.
CHR0 Animations
//add this to your class definition
m3d::anmChr_c chrAnimation;
nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("swim");
this->chrAnimation.setup(mdl, anmChr, &this->allocator, 0);
void daEnExample_c::bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate) {
nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr(name);
this->chrAnimation.bind(&this->bodyModel, anmChr, unk);
this->bodyModel.bindAnim(&this->chrAnimation, unk2);
this->chrAnimation.setUpdateRate(rate);
}
onCreate()
function next:bindAnimChr_and_setUpdateRate("swim", 1, 0.0, 1.0);
int daEnExample_c::onDraw() {
bodyModel.scheduleForDrawing();
return true;
}
void daEnExample_c::updateModelMatrices() {
matrix.translation(pos.x, pos.y - 8, pos.z);
matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z);
bodyModel.setDrawMatrix(matrix);
bodyModel.setScale(&scale);
bodyModel.calcWorld(false);
}
int daEnExample_c::onExecute() {
bodyModel._vf1C();
updateModelMatrices();
if (this->chrAnimation.isAnimationDone()) {
this->chrAnimation.setCurrentFrame(0.0);
}
return true;
}
PAT0 animations
nw4r::g3d::ResAnmTexPat anmPat;
m3d::anmTexPat_c patAnimation;
this->anmPat = this->resFile.GetResAnmTexPat("pukupuku");
this->patAnimation.setup(mdl, anmPat, &this->allocator, 0, 1);
this->patAnimation.bindEntry(&this->bodyModel, &anmPat, 0, 1);
this->patAnimation.setFrameForEntry(0, 0);
this->patAnimation.setUpdateRateForEntry(0.0f, 0);
this->bodyModel.bindAnim(&this->patAnimation);
void daEnExample_c::setColor(u32 color) {
this->patAnimation.setFrameForEntry(color, 0);
}
SRT0 animations
m3d::anmTexSrt_c body;
nw4r::g3d::ResAnmTexSrt anmRes = this->resFile.GetResAnmTexSrt("bubble");
this->body.setup(mdl, anmRes, &this->allocator, 0, 1);
this->body.bindEntry(&this->bodyModel, anmRes, 0, 0);
this->bodyModel.bindAnim(&this->body, 0.0);
void daEnExample_c::onExecute() {
//...
this->body.process();
}
onExecute()
.
VIS0 animations
to be added
CLR0 animations
to be added
SHP0 animations
to be added
Custom Models for Vanilla Sprites
Introduction
This tutorial will show you how to import custom models over vanilla models in NSMBW. Certain examples this guide will apply for are things like enemies, player models, etc. This does not cover replacing background models, for that see the Custom Backgrounds tutorial. DISCLAIMER: This guide will mainly be using Blender as it is the most accessible due to it being freely available. You should also have basic knowledge about Blender in general before diving into this tutorial. Let’s get started!
Tools and Requirements
- You own extracted dump of the game’s files
- The model you want to replace. See List of Object Files to find the models you want to replace.
- BrawlCrate (used over BrawlBox since it tends to be better with Blender exported models)
- Blender (version 3 will be used in this guide, but versions such as 2.9 will work as well)
- Autodesk FBX Converter for converting the models from FBX <-> DAE and some other formats.
- The model(s) you will be importing plus its textures. Can be either made from scratch, from this game or another, etc.
General model tips
The models you import I would personally recommend generally being around the same polygon count or less than the original models. You can go over the amount, but you shouldn’t be too crazy with the polygon count since this is a Wii game after all, and it could cause lag in-game with too many of said model on-screen.
Exporting models as a base
In BrawlCrate, open the .arc file that has the models you want to replace. For this example, I am going to be replacing the Climbing Chain Link Koopa model with the Dry Bones model from Mario Kart Wii. So for this I open nokonokoB.arc in the Object folder. Then open the brres file in the g3d folder, then navigate to the MDL0 that is the model you will be replacing, found in the 3DModels(NW4R) folder.
Right click the appropiate MDL0, select Export, and save the model as a .dae file wherever you can find it.
Next you want to export the materials and shaders to use later on.
Expand the "Materials" tab, and right click each material and export the same way you exported the shaders, and save it wherever you can find it. Then, expand the "Shaders" tab and export the shaders the same way you exported the materials in the previous step.
<NOTE: Add screenshots>
Importing into Blender
TO BE WRITTEN