Skip to content

Extracting map meshes

Prerequisites

Additional notes before getting started

This tutorial was tested on Blender 3.1.

Python knowledge is preferred for this tutorial, but you can get by without it.

Python does not need to be installed for this to work.

The resulting .bin files can be imported into any language that can read binary numbers from a file. The id files are a chain of 32-bit integers in little-endian format, and the vertices are stored at 3 32-bit floats in a row (x, y, z), also stored in little-endian format. Each ID in ids corresponds to the index of the vertex if you parsed the vertices in the order that they appear in the file. (By default.)

Overview

  1. Opening U-Model the right way
  2. How to identify a map
  3. Extracting a map
  4. Identifying collision files
  5. Importing to Blender
  6. Converting object to binary data

Opening U-Model the right way

Create a bat file called umodel.bat, and save this to it:

umodel.exe -game=rocketleague -path="C:\Program Files (x86)\Steam\steamapps\common\rocketleague\TAGame\CookedPCConsole"

Depending on where you saved U-Model, you may have to use cd before that to get to it:

cd C:\Program Files (x86)\umodel_win32
umodel.exe -game=rocketleague -path="C:\Program Files (x86)\Steam\steamapps\common\rocketleague\TAGame\CookedPCConsole"

Use this bat file that you create to launch U-Model whenever you need to use it.

If you have Rocket League install through Epic Games, use this path instead: C:\Program Files\Epic Games\rocketleague\TAGame\CookedPCConsole

WARNING: Be sure to use the 32-bit version of U-Model! You're safe as long as you don't change umodel.exe to umodel_64.exe. Some assets will refuse to load, if you do.

How to identify a map

In the top-left-ish corner, there's space for you to filter all the files. If you type in _P.upk, you will get a list of all of the maps.

If you're looking for a map, filter by MapImage. You can double-click on a file to view a preview of the map with a similar name. Press the key O (or go top left -> File -> Open package) to get back to the menu with all of the files.

Extracting a map

In this example, I will be using Stadium_P.upk - otherwise known as DFH Stadium.

Right-click on the map you want to export, click Export, and all of the map data will be extracted for you.

All files are extracted to the UmodelExport folder in whatever folder you saved U-Model to. For me, this is C:\Program Files (x86)\umodel_win32\UmodelExport.

Identifying collision files

Inside the folder of the map you extracted, there should be 5 more folders - the one that you want is called StaticMesh3. In this folder, simply look for any .pskx files that have the word collision in them. For DFH Stadium, there are 4 files:

  • Goal_STD_Collision.pskx
  • Field_STD_Collision_Corner.pskx
  • Field_STD_Collision_SideTop.pskx
  • Field_STD_Collision_SideBot.pskx

These files contain all of the available field collision information.

Importing to Blender

Open Blender, and select "General." This will load a default 3D scene, with a cube, light source, and camera.

image

Next, in the top right, delete all three of these things. (Right-click -> Delete)

image

Now, we import ONE of our objects. This is important - we can only convert one at a time unless changes are made to the script in the next section. When you want to convert another object, delete the only one in the scene first. The process is the same as deleting the cube, as we did previously.

To import an object, go to the top right -> Files -> Import -> Skeleton Mesh (.psk). Use this to import one of the .pskx collision files that we got earlier.

image

For this, I have imported DFH Stadium's Field_STD_Collision_Corner.pskx.

image

Converting the object to binary data

At the top of Blender, select the Scripting tab.

image In the top middle, select New.

image

Copy & paste the below Python script:

import bpy

# Blender Python API Documentation
# https://docs.blender.org/api/current/index.html

print()

if len(bpy.context.scene.objects) != 1:
    print("MORE THAN ONE OBJECT EXISTS!")
    exit()

obj_name = "soccar_corner"

data = bpy.context.scene.objects[0].data

ids = []
verts = []

for tri in data.polygons:
    for id in tri.vertices:
        ids.append(id)

for vert in data.vertices:
    for coord in vert.co:
        verts.append(coord)

print(f"Number of ids: {len(ids)}")
print(f"Number of triangles: {len(ids) / 3}")
print(f"Number of coordinates: {len(verts)}")
print(f"Number of vertices: {len(verts) / 3}")

import os
from pathlib import Path

os.chdir(Path.home() / "Documents")

#import json

#with open(obj_name + "_ids.json", "w") as f:
#    json.dump(ids, f)

#print("Wrote json ids")

#with open(obj_name + "_vertices.json", "w") as f:
#    json.dump(verts, f)
#    
#print("Wrote json vertices")

import struct

with open(obj_name + "_ids.bin", "wb") as f:
    f.write(struct.pack("<" + "i" * len(ids), *ids))

print("Wrote binary ids")

with open(obj_name + "_vertices.bin", "wb") as f:
    f.write(struct.pack("<" + "f" * len(verts), *verts))

print("Wrote binary vertices")

You can edit the line obj_name = "soccar_corner" near the top to adjust the name of the outputted file, and os.chdir(Path.home() / "Documents") to edit the output folder.

Click on the Play/Run button in the top middle to run the script.

image

This creates the two bin files containing the ids and vertices from the object.

image

If you want an example of using collision data and compiling them into a mesh to run collision queries on, check out the rl_ball_sym Rust project: