Zatarita

Working With GBXModel [3ds max]

Welcome!

        Recently I've been keeping pretty busy. I started going back to school, and the holidays have kept me going; however, I found some free time and I wanted to do something modding related.

I read a lot of questions about custom models on some of the discords I frequent. I felt this would be an awesome opportunity to expand our knowledge base on OC. C20 has a lot of extremely useful information, but my hope is to teach you a deeper understanding of how the engine handles creating and managing a model presented in a scene.

         A GBXModel is the pc variant for the tag used to define a model used as an asset for Halo. A GBXModel isn't just "a model" but instead it is a collection of models. These models define the objects state for a given instance or condition. These models can be broken down into Regions and assigned Permutations for some variation, defined Levels of Detail for proper optimization, bound to Nodes for animation, and assigned Markers for special effects. In order to create a GBXModel we need to use tool's Model command to compile the raw model (jms) into a GBXModel. Tool will take all of our different models and compile them all into the collection of models discussed above. Of course this is an oversimplification for the introduction to the concepts, there's a bit more that goes into it. I will discuss each of these ideas later in the post.

 

Table Of Contents

1. Nodes

1-1: Summary

1-2: Example Hierarchy of Nodes

1-3: Creating a Node

  • Newer Versions Of Max
  • Older Versions Of Max

1-4: Other Node Information

1-5: Common Node Issues

  • Tool
  • Ghost JMS Exporter

2. Regions

2-1: Summary

2-2: Example Region Variations (Permutations)

2-3: Creating a Region

  • Blitzkreig & Ghost JMS Exporter
  • FBX-to-jms

2-4: Creating a Permutation

3. Markers

3-1: Summary

3-2: Example Markers

3-3: Creating a Marker

4. LODs

4-1: Summary

4-2: Example LODs

4-3: Creating LODs

5. Creating GBXModels

5-1: Exporting

  • FBX-to-jms
  • Ghost JMS Exporter

5-2: Compiling a Model

 

 

Additional Information

 

PLEASE If I missed anything, or could make anything more clear lemme know c:

I would like for this to be as accurate and complete as possible. It took me 8 hours to write this up, I want to make sure it wasn't for waste! Happy modding

 

Updates:

12/22/21

Markers : TY Galap/Mata for the suggestion to clarify markers aren't required to be spheres, and reemphasize that orientation matters.

Regions : Updated network sync details

12/25/21

Markers : included example

LODs : Wrote introduction

01/06/22

LODs: Wrote "Creating LODs"

Formatting: Adjusted nodes to its own post setup TOC.

01/11/22

Formatting: Finished

 

To Do Once I have time to update:
        Discuss GBXModel Importer by ghost

Takka and swamp like this

Specifications:

S3dpak - format - Imeta/ipak - format - Fmeta - format

Programs:

H2a-inflate - SuP

Share this post


Link to post
Share on other sites

Tiddy-bits:

Nodes

        Nodes are anchor points for our 3d models. They are called nodes because they determine the object hierarchy like a graph. Every model requires at minimum a root node. This node must be prefixed with "frame" or "bip01". Beyond that nodes act like "bones". You anchor a portion of the mesh to a node, and when we animate; it's the nodes that we are animating. Each part of a mesh that moves during animation needs to be assigned to a node. It's worth noting that each vertex can only be influenced by up to two nodes in the case of a rigged model. There are other uses for nodes as well; however, I will cover those later in the collision_model.

        Nodes don't have any mesh data themselves, they represent a point in a hierarchy with a 3d coordinate and orientation. We typically represent them as a scene object such as a sphere; however, this is only used to interact with the node in the scene. Once we export the models to jms the 3d position, orientation, and position in the hierarchy are the only bits of information passed through to the GBXModel. It's also important to remember nodes need to remain consistent between permutations. (discussed later)

 

Example Hierarchy of Nodes:

Spoiler

unknown.png
unknown.png
 

Notice how all of the children (frame chain, frame gun, and the gun its self) move when I move the parent node "frame gun mount base"

None of the "frame" objects are actually spheres that appear in the final GBXModel, instead they link children objects to their parents and determine their location and rotation in 3d space.


Creating a Node:

Spoiler

        First we want to create a primitive that will be used as a handle for the node, I chose a sphere. Then I rename the sphere so the name starts with "frame ". After doing that we can either use the "Select and Link" tool for older versions of max, or on newer versions you can just drag the child object over the parent in the scene explorer panel on the left and it will adjust the hierarchy for you. When rigging a biped the skinning process will handle binding vertexes to bones. The "bones" of a biped rigging get interpreted as nodes and mapped accordingly by the engine.

        Once the nodes are mapped correctly, if you move or rotate your frame the object should reflect the changes are well. Nodes may contain more child nodes; however, there is a limit to how many nodes you can have. This depends on version. Check out C20 for more information on that.

 

Newer Versions:

Spoiler

unknown.png

unknown.png

 

On Newer versions of max you can just click and drag the name over the "frame" object in the hierarchy panel


Older Versions:

Spoiler

unknown.png

unknown.png

 

On older versions of max click the "Select and Link" tool in the top left corner. Then click and drag from your object onto the sphere named "frame"


Other Node Information:

Spoiler

Your root node position influences the position of the bounding sphere for a model. The bounding sphere is responsible for optimizing out the mesh when you can't see it anymore. This will cause inappropriate culling (or not drawing the object to save resources) as the engine doesn't think you can see the item any more. This may also impact physics calculations. Keeping the position of your root node as close to "center" as possible will be the most optimal.

unknown.png

 

An easy way to do this in 3DS Max is to use the align tool. Before you link the object to the frame, select the frame and use the align tool to align to the objects center. This will put the frame in the most optimal position for the bounding sphere.
unknown.png

unknown.png

unknown.png

 

Common Node Issues

Spoiler

Tool:

Spoiler

"No actors to export. Actor root node must start with prefix 'frame' or 'bip01'."

Seen when "tool fbx-to-jms" doesn't find a root node prefixed with "frame"

 

"### ERROR this model has too many nodes."

Seen when you exceed the node limit. Check this out for more technical information.

 

 

Ghost JMS Exporter:

Spoiler

"There are no actors to export!"

Seen when jms exporter doesnt find a root node prefixed with "frame".

 

 


Specifications:

S3dpak - format - Imeta/ipak - format - Fmeta - format

Programs:

H2a-inflate - SuP

Share this post


Link to post
Share on other sites

Regions

        Regions are named sections of a model. This allows you to create different versions for that section of model that can be selected randomly or assigned with scripting. These variations are called Permutations. There are other uses for regions; however, they are covered more in the collision_geometry section of the tutorial. Because these permutations can be selected randomly the region needs to be mapped to the same bones as the base mesh. Which means they require the same amount of nodes even if the vertices that those nodes bind to doesn't exist in this permutation. 

 

There are special case regions used by the engine when specific conditions are met:

~damaged : Gets chosen when the object's health reaches a certain threashold.

~shield_off : Gets chosen when the object's shields run out ( If it has shields )

~primary_blur : Chosen when a weapon reaches a firing speed threshold with primary trigger pressed.

~secondary_blur : Chosen when a weapon reaches a firing speed threshold with secondary trigger pressed.

~blur : Chosen when vehicle reaches a speed threshold specified in a vehicle tag.

 

        These special permutations are completely optional; however, they add a lot of life to a object. They will make a bit more sense when we get to collision models, I will hold off on explaining them until I get around to making that tutorial. Something to notice is that these names all start with a "~" which is a special character used to tell the engine that this region isn't one that we want to get randomly chosen. We can use this naming convention for our own purposes if we like; however, the only way we can utilize a permutation like that is through scripting. For people making campaign/coop missions this may be desirable.

 

        Also any permutation selected randomly will not synchronize over a network. This means in order to use permutations as variations for objects online, and have each player see the same one, you MUST select it with a script at start up. If not each player can have a different random permutation set. For some scenery objects this is not that big a deal. For example halo 3 uses this concept to change the position of stickers on a barrel. For other objects though you need to be careful as it may cause inconsistencies between clients. My general rule of thumb for this is "if the collision stays the same it's ok". A random pile of papers on a table, or different labels on a barrel won't impact game play; though, a soda machine being there for some people and not others can be game breaking. Having permutations can add some variety to your maps, but try to keep it to smaller details for multiplayer, or force the permutation with a script for all clients.

 

(optionally you can also create LODs once you're done creating regions and permutations)

 

Example Region Variations (Permutations):

Spoiler

unknown.png

Left: Marine Base ----- Right: Marine [Sgt Johnson Head] [Long Sleves]

 

Example Permutation:

unknown.png

Example of how nodes must exist even when the remaining mesh isn't present for a specified region

 

Creating A Region:

Spoiler

Defining regions depends on what tools you are using...

 

For Ghost JMS Exporter and Blitzkreig you define a region by selecting the faces you want in a region and giving it a name in "Name Selection Set": 

Spoiler

unknown.png

 

For tool fbx-to-jms you assign a region using the material name

Spoiler

unknown.png

 

The first half of the name is the material its self, the last half is the region.
Then between the material name, and the region name there is "_atr_lpr_"

 

This allows you to define regions with the same texture and different names, as well as regions with different textures in the same name.

face_atr_lpr_head
hair_atr_lpr_head

Defines two materials, face and hair, they are both in the "head" region

 

shirt_atr_lpr_torso

shirt_atr_lpr_arms

defines one material shirt, but it is split up between the region torso, and the region arms

 

 

Creating a Permutation:

Spoiler

        Creating a permutation is pretty simple. Once we've defined regions in our main model; we can isolate the regions that we wish to make a variation of, make the variation and then save it with a new name. When tool goes to compile the model it will find the other variants and create a permutation for each region we included. In our example I create a cork board which will have pieces of paper on it. The papers will pick a random permutation when it loads the level.

        I create a region named "base" with a material "cork" which contains the cork board it's self. This region is our default region. It will be chosen no matter what. This version has no paper on it. I bind this to a frame and export it with the name "base.fbx". Next I create a couple sheets of paper that will go "on" the cork board.  These get their own regions called "papers" and their own texture called paper. I us the original model as a reference to place the papers, and then bind just the paper to the frame and export with the name "papers_1.fbx". I make a variation of the position of the papers and export it as "papers_2.fbx". Then I convert all the models to JMS using the fbx-to-jms command through tool. When tool compiles these models with the model command they will get combined into one model. The base model will always show, but the "papers" region will pick a random variation at load. I create an example scenery object to show you the end result. You could if you like add a "papers" region to the base mesh as well. Tool will find the matching regions and create a new permutation for paper called "base". The base permutation also has a chance of being randomly selected. (remember if you want you can add ~ to the front to avoid it being randomly selected)

 

Create Board:

unknown.png

 

Create "Cork" Material and "Base" Region:

unknown.png

 

Use Board as a Reference To Place Papers:
unknown.png

 

Create "Paper" material in "Papers" region:

unknown.png

 

Delete Cork Board From This Permutation After Done as Reference and Bind to Frame:

unknown.png

 

Export The File as Papers_1:

unknown.png

 

Create Variation and bind to frame:

unknown.png

 

Export as Papers_2:

unknown.png

 

Create JMS File: (This is discussed further towards the end of the tutorial)

unknown.png

 

Create Model:

unknown.png

unknown.png

 

Final Product:

unknown.png


Specifications:

S3dpak - format - Imeta/ipak - format - Fmeta - format

Programs:

H2a-inflate - SuP

Share this post


Link to post
Share on other sites

Markers

        Markers are points relative to the mesh that can be used to define a position (and rotation) used for things like spawning special effects or attaching an object to another. For example we could have a marker at the end of a gun that emits smoke, or a marker used to attach the pipe to the Keyes' hand. Markers are created similar to nodes; however their names must start with a #. They are represented with a scene object, such as a sphere or other primitive. The object is just a handle used to adjust position and orientation of the marker relative to a node. None of it's mesh data will be included once we export. When creating tags that utilize the gbxmodel we can define the effects that spawn at the markers, or in scripts we can reference the marker names directly. Any markers that happen to have the same name will have the effect applied to both positions at once. For example if you have two marker called "#steam_emitter" and you attach a steam emitting effect to that marker name, both markers will emit steam. It's also worth noting that markers are owned by the permutation. This means that unlike nodes there don't have to be the same amount markers for all permutations. You can have a permutation that has two steam emitters, a perm that has one steam emitter, and a perm that has none if you like. 

 

There are a few special case markers as well. Halo uses these for certain functionality like head position so AI knows where to look, or hand locations. For more information on this check out the c20 page on markers; They do a great job explaining this, and I don't want to reinvent the wheel.

 

Example Markers:

Spoiler

unknown.png

The pelican uses markers for many purposes. Each seat, seat's camera position, vehicle entry position, lights, thrusters, cargo position, etc. are all their own markers littered throughout the model. How these markers get utilized is determined by the tag that implements the object (the vehicle tag) and scripts that might be executed referencing against pelican as an object. 

 

 

Creating a Marker:

Spoiler

        Creating a marker is similar to creating a node. I'm going to use a sphere to denote it's location in space and to give us a handle to modify it's position and rotation. (It is not required we use a sphere. Some people prefer using shapes that better presents it's orientation; such as a pyramid or asymmetrical cube) Next we're going to apply the special name to it, #steam. I'm going to make a few permutations of this model. A variation with 0, 1, and 2 steam emitters like mentioned above. Then compile and build an example scenery object to test the markers. Assigning effects to markers aren't going to be a part of this tutorial, as that's done outside of the gbxmodel its self.

 

Create Markers and Name it #Steam:

unknown.png

 

Link it to a Frame, Export, and Build (See Creating GBXModels at the end):

unknown.png

 

Create a Test Scenery Object:
unknown.png

 

Notice how the bottom one has no steam emitters, the middle one has one steam emitter, and the top one has two. The number of markers does not need to remain consistent between permutations.


Specifications:

S3dpak - format - Imeta/ipak - format - Fmeta - format

Programs:

H2a-inflate - SuP

Share this post


Link to post
Share on other sites

Levels Of Detail (LODs)

        LODs are (optional, but highly recommended) optimized versions of permutations that are chosen based off distance the object is from the camera. Your first instinct might be "My computer was built almost 20 years after this game has been made. It can handle high poly counts, let's crank up the detail."; however, I would like to temper your expectations.

There are two main reasons for this:

1) High poly counts does not necessarily mean better detail (It may just be poorly optimized). It's better to say more with less. Not everyone has a high end system. We can't forget this is a game and people may wish to play competitively against each other. a versatile asset uses only the amount of detail necessary to say what it needs to say.

2) Something I call "Detail Dissonance"; When your mesh has more detail than surrounding meshes it contrasts more with the scene. Artistically this draws someone's eye more to that object. This this could be a good or bad thing depending on your desired outcome. It is in my opinion that high poly model surrounded by low poly models can break the cohesion, and unbalance a scene if not done properly. Using LODs will help prevent this for far away objects.

 

Halo allows you to define 5 optional stages of LODs:

super-high

high

medium

low

super-low

Tool will remind you when compiling GBXModels to set the LOD cutoffs. These are set inside guerilla and determine the threshold where one switches to the other. (see below "Creating LODs")

 

Something to note about LODs and markers and nodes. You still require all of the nodes to be in each LOD version; however, markers are only read from the Super-high LOD. This means if your mesh doesn't utilize a Super-high LOD your markers aren't going to be included. If you don't use any LODs the default option will be super-high, so this may not be an issue. Though, do keep it in mind.

 

Example LODs:

Spoiler

unknown.png

Super-high, Medium, and Super-low LODs.

Notice the variations in detail between the versions.

 

unknown.png

LODs are chosen using the diameter of the object's bounding sphere in pixels. To see an object's bounding sphere in sapien press ~ to open your console and type these two commands:

debug_objects true

debug_objects_bounding_spheres true

 

Creating LODs:

Spoiler

        Creating LODs is pretty simple. For each permutation you make, take some time to create lower poly versions of the model (sometimes you can get away with using the optimize modifier). Then when you're happy with the mesh. Export the file (see below "Creating GBXModels") into your models folder like you would when creating a permutation; however, After we type the name of the permutation we're also going to type a space and the name of the LOD this model represents. We're going to do this for each permutation.

unknown.png

 

        After we create the GBXModel with tool it will remind us we need to set the LOD cutoffs. To do this after the model is created, we're going to open guerilla. Goto file>open and navigate to our new model (Remember tool reflects the naming convention you used in the data folder. So if the models are located data\scenery\object\models the GBXModel will be output in tags\scenery\object\object.gbxmodel.) Once open, right at the very top we see the 5 text boxes that hold the cutoff values measured in "pixels". The "pixels" is how many pixels the bounding sphere takes up on screen (see example LODs above). The further away the object is the fewer pixels it'll take up on screen. Every model is a little different so these values need to be played with until you get something you like.

        Something to note as it is slightly unintuitive. The bounding radius of the model is set in the tag that implements the GBXModel. So you need to be careful if you have separate tags that use the same GBXModel. (like the pelican for example has a vehicle tag and a scenery tag) you want to make sure you use consistent bounding radii between the two or the LODs will behave differently between the two (which may or may not be desirable). If this doesn't make any sense right now don't worry. We'll touch on this more in future tutorials.

unknown.png

unknown.png


Specifications:

S3dpak - format - Imeta/ipak - format - Fmeta - format

Programs:

H2a-inflate - SuP

Share this post


Link to post
Share on other sites

Creating GBXModels
         creating a GBXModel requires us to export our data from 3ds max in a format tool can utilize. This format is called .jms and to get a model in that format we have a few options: Ghost JMS Exporter, Blitzkrieg, and FBX using H1A-EK's tool. For this tutorial I will touch on Ghosts JMS Exporter, and tool's fbx-to-jms converter which are the more popular of the options.

 

        All jms files are expected to be inside of a folder named "models" and this folder is expected to be found inside your "data" directory. Beyond this it is up to you how you wish to organize your folders. Tool will mirror the naming convention you used with the "data" folder in your "tags" folder for compiled files. If you save your models in "data\scenery\new_thing\models" tool will compile your GBXModel to "tags\scenery\new_thing\new_thing.gbxmodel" and create the necessary folders to facilitate that.

 

Exporting

Spoiler

Tool FBX-to-jms

Spoiler

        Once you've read this tutorial and have your super awesome model you wish to export. we're going to go to "File>Export". This will open a file explorer dialog box. We want to select "Autodesk (.FBX)" as the type. We will navigate to our data directory and create a new folder with the name of our object. Inside we will create the "models" folder that our FBX file will sit inside. We'll name our model, and click save. After we have done that we will open a command prompt in our root chelan_1 directory and run the command:

        tool fbx-to-jms "data\new_model\models\new_model.fbx" "data\new_model\models\new_model.jms"

This will convert our fbx model into a jms and let us move on to the next step of compiling our GBXModel (explained below)

 

File>Export:
unknown.png

Navigate to My Data Directory:

unknown.png

 

 

(Notice the path data\gbxmodel\nodes\models and notice the save as type FBX)

 

Convert the FBX to jms:

unknown.png

 

 

Ghosts JMS Exporter:

Spoiler

 Instalation:

Spoiler

      To use the Ghost JMS Exporter we first need to download it from their website. After downloading I'm going to open my Downloads folder, and copy the script. Next we're going to open 3Ds Max and under "Scripting>Run Script.." I'm going to paste the downloaded script. It may ask you for administrator permission, this is because the scripts folder is part of the "program files" for some reason. Just go ahead and accept and you have the exporter installed!

Copy the Script:

unknown.png

 

Open the Run Script Dialog:

unknown.png

 

Paste the Script Into the Scripts Folder:

unknown.png

 

Using The Exporter:

Spoiler

        Once you have your model you wish to export. we're going to go to "Scripting>Run Script.." and select the JMS Exporter we just installed. This will open up a minimalistic window. We're going to leave all the settings default and click export JMS Data. This will open a file explorer dialog box. We will navigate to our data directory and create a new folder with the name of our object. Inside we will create the "models" folder that our JMS file will sit inside. We'll name our model, and click save.

 

Run Script:

unknown.png

 

JMS Exporter:

unknown.png

 

Exporter Window:

unknown.png

 

Save the JMS:

unknown.png

(Notice the path data\testing\gbxmodel\nodes\models)

 

 

Compiling a Model:

Spoiler

        Once we have the models organized in the "data/.../models" folder we will ask tool to compile the model. The way we do this is by opening a command shell in the modding directory and running "tool model data\root\new_thing\". Notice that this doesn't include the "models" folder. Tool expects there to be a models folder, and it will yell at you over it too. When we do this for the first time tool will ask you what type of shaders we wish to make for the model. It will ask you for each material assigned to the models (shaders aren't covered in this tutorial). After it does this it will say it failed, but you just need to run the command again now that the shaders were defined. After that, we've compiled our first gbxmodel!

 

Open CMD In Chelan_1 Directory:

unknown.png

unknown.png

 

Run Command and Assign Shaders:

unknown.png

 

Run Command Again:

unknown.png

 

 


Specifications:

S3dpak - format - Imeta/ipak - format - Fmeta - format

Programs:

H2a-inflate - SuP

Share this post


Link to post
Share on other sites
  • Recently Browsing   0 members

    No registered users viewing this page.