Assembling models and environments made of non aligning objects - SWTOR-Slicers/WikiPedia GitHub Wiki

By Cren

This guide is of general application, but it happens to be especially useful when dealing with Decorations and Strongholds, as they are the most typical use case.

When dealing with SWTOR's "static" models (relatively simple objects, furniture, arquitectural elements, specific environments, etc.), we usually find ourselves with two types:

  1. Models made of a single object. For example, a rock, a table, a computer console, a mountain, etc.

  2. Models made of multiple objects. Say, a player ship, a complex machine, a stronghold, etc. Those models are assembled out of a series of objects, for several reasons (re-using objects from a "Lego set" of elements, ease of modeling and texturing, game engine limitations, etc.).

So far that's not that different to what happens with "dynamic" models such as Player Characters and re-gearable NPCs (multiple body part objects) and creature-type ones like most NPCs, animals, etc. (single objects, mostly).

But in the multiple object, static models category, we find ourselves dealing with two variants:

  1. Those that share their origin point and fit each other perfectly. For example, the Sith Warrior's ship. The Fury Interceptor's base model is composed of a series de objects, each one most often being a room with floor, ceiling, walls, and a few fixed elements of furniture. They are easy to find inside specific folders, using simple filenaming conventions. When one imports those objects, they appear in the 3D viewport correctly placed already, no need to reposition them at all.

  2. And those that don't share their origin points and don't fit each other naturally. They often don't even share an uniform size or orientation. The reason behind that is that it wouldn't be that useful for the game developer: they are objects meant to be freely repositioned as per the particular necessities of a location or scene, especially if we are talking "construction set" stuff such as generic walls, stairs, roads, complex machines, series of tunnels and caves…

This is the case of Strongholds and many Decorations. If one imports, say, all of Dromund Kaas' Strongold's objects, maybe a few of them will fit each other, but there are several major pieces such as the stairs leading to the top floor that don't: they appear in the center, intersecting each other. The same happens with relatively complex models that were part of a location and BioWare repurposes them as Decorations: many of those models were created by rearranging (moving, scaling and rotating) a few single objects to produce the appearance of something new.

Adjusting them by hand to obtain the correct appearance is a major chore. But we don't have to: we have the tool to find the required coordinates and transformations, and ways to apply them.

Finding the model

We have several ways to find SWTOR models "by hand", based on searching for their entries in TORCommunity.com and Jedipedia.net's databases. Some are more immediate than others:

  • Directly finding the .gr2 files' pathnames in TORC's Detailed Data tab.
  • Indirectly, by using ModelIDs and searching for them and their associated data inside our extracted assets folder.

Tipically those only work for single object models, and that data isn't always available in those websites.

  • And more indirectly yet, by using FQNs (Fully Qualified Names) and their associated data. They give us the most precise and detailed information about the models, but we'll have to use the Slicers GUI app's Node Viewer tool. It's not difficult at all: just a little more laborious.

FQNs always work, but they require to run the Slicers GUI app, use its Node Browser tool, and have something to copypaste information into. For what we want to do and the kind of data we need, they are our only option.

Extracting a single object model

First of all, we need to identify the model, starting with its in-game name. Let's use this Stronghold Decoration as an example:

This is the Medicinal Fungus. With that, we launch a search in TORCommunity's database:

torcommunity.com/database/decoration/822056F/medicinal+fungus/

Now, if we go to “DETAILED DATA” we wouldn’t find any .GR2 direction. But we know that every model needs at least 1 .GR2 file, so let's find it. On the line 22 we find this: "DecorationFqn":"plc.stronghold.harvesting.bioanalysis.mushroom_green"

We’ll use that direction to find the .GR2 file, using the Slicer’s GUI Node Viewer.

Open your Slicer’s GUI Node Viewer, you will have something like this

Now we use the direction of the DecorationFqn: plc->stronghold->harvesting->bioanalysis->mushroom_green here, we will find the node direction where the model is: “plcModel 4611686019112067712 String dyn.stronghold.harvesting.bioanalysis.mushroom_green”

So we go to that direction: dyn->stronghold->harvesting->bioanalysis->mushroom_green

And we finally got it! dynVisualFqn: /art/static/harvesting/har_mushroom_green.gr2

The mushroom is a separate model, but we can also notice that we have the pot direction: /art/static/area/vos_voss/item/vos_item_temple_planter.gr2

Congratulations! Now u know how to extract the decoration/world models! How to extract a model made by other models: As we know, there are models that are made by other models, this is the example we’ll use, the Egg incubator:

Let’s follow what we know and look the “dyn” information on TORCommunity: https://torcommunity.com/database/decoration/tPvyuPP/egg+incubator/?#tab-details We’ll see this direction: "DecorationFqn": "dyn.stronghold.technological.machines.neutral.egg_incubator", And here is when we realize that we have a big problem. The model is made by 47 different .GR2 files. Ok, let’s port it into blender:

This isn’t like the photo! That’s because all the models have their own position, scale, and rotation values. So, now I really recommend to export the node as json and open it on a text editor like Visual Studio Code, Notepad++, or what you prefer, because the node has 5322 lines!!!.

We know that each GR2 file have his own position, scale and rotation value, we can find them here:

                    "dynPosition": {
                        "Id": "4611686038108070005",
                        "type": "Vector3",
                        "value": {
                            "x": -0.024000000208616257,
                            "y": 0.08250000327825546,
                            "z": -0.23240000009536743
                        }
                    },
                    "dynRotation": {
                        "Id": "4611686038108070006",
                        "type": "Vector3",
                        "value": {
                            "x": 39.970088958740234,
                            "y": 0,
                            "z": 0
                        }
                    },
                    "dynScale": {
                        "Id": "4611686038108070007",
                        "type": "Vector3",
                        "value": {
                            "x": 0.5378999710083008,
                            "y": 0.5378999710083008,
                            "z": 0.5378999710083008
                        }
                    },
                    "dynVisualFqn": {
                        "Id": "4611686038125770001",
                        "type": "String",
                        "value": "/art/fx/geometry/fxmonitors/ai_holo_screen_text_sm.gr2"

( i let the format of my visual cause is a beta guide) We could try to port each gr2 file and put it on blender with their Position/Rotation/Scale data, but, it will be something like this:

It doesn’t look like the model! That’s because SWTOR didn’t work the XYZ axis like blender. Here is a photo to help you to understand:
So, knowing this, we must follow this rules: Position: X -> X Y -> -(Z) Z -> Y Rotation: X -> X+90 Y -> Z Z -> -(Y)
Scale: X -> X Y -> Y Z -> Z

Yeah, not very easy, let go step by step: First, the position: "dynPosition": { "Id": "4611686038108070005", "type": "Vector3", "value": { "x": -0.024000000208616257, "y": 0.08250000327825546, "z": -0.23240000009536743 } },

So, on blender Blender X = Dyn X (no changes) Blender Y = Dyn -(Z) (We have to invert it) Blender Z= Dyn Y
The rotation: Blender automatically puts the X rotation to 90, we will have to add the X rotation provided on DynRotation. (We just can put +(Value) and blender will be the rest). Blender X = 90 (the base by blender) + (DynRotation) Blender Y =Dyn Z Blender Z =Dyn (-Y)

And the Scale is the same as the Node: Blender X = Dyn X Blender Y= Dyn Y Blender Z = Dyn Z

Knowing this, we can build the model and (after a long time) finally got it:

This is the end of the guide, hope this can help! (don’t know if add about textures)

CAUTION!!! This rules aren’t perfect, some times, the rotations change, like X -> X Y-> Z Z -> Y or X -> X Y-> -(Z) Z -> Y With the example (Egg incubator) i had rotation problems with things that are “dobles”, because, for example,
this “bases” have the same rotation data, but I need to flip the right one manually.

Also, some pipes give me the same problem (forgot exactly which one). Me and Crunch are trying to know in which cases this happens, I'll look for it!

Special thanks to Crunch (Crunch#0298), he helped me a lot with the rules.