Reversed stats pass + real-model import pipeline (CASSEROLA DX, MORRY)

Stats quietly inverted: shitboxier IRL = better in game. Excel X3 is now the
fastest car; TURDRUNNER is the slowest. tools/import_shitbox.py converts
downloaded models (glb/gltf/fbx/obj/blend) to game GLBs -- normalizes scale,
yaw, ride-height origin. First two imports: Corolla mk7 and Morris Mini.
shitboxes/ stash gitignored + .gdignore'd (its .blend files broke Godot's
headless import scan).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-27 22:24:36 +10:00
parent 9a3b0c6c6a
commit 4c5323ba60
41 changed files with 692 additions and 30 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
screenshot.png
shot_*.png
screenshot.png.import
shitboxes/

View File

@ -40,8 +40,18 @@ Model convention (any GLB works, hand-modelled or generated):
Piss-take names on purpose: real model names and badges are trademarks.
To improve a silhouette: supply a side-on photo + front three-quarter photo, tweak the
profile points in the spec, rebuild, screenshot. Kerb weight and power figures go in
stats.tres if you want realism; otherwise vibes.
profile points in the spec, rebuild, screenshot.
**Stats are low-key reversed**: the shitboxier the car was in real life, the better it
performs here. The Excel X3 is the fastest car in the game; the muscle cars are all bark.
Downloaded models (from `shitboxes/`, gitignored + .gdignore'd) convert via:
```
/Applications/Blender.app/Contents/MacOS/Blender -b -P tools/import_shitbox.py -- "<file>" <car_id> <length_m> [yaw_deg]
```
Imported cars don't shed det_* panels until someone cuts their doors out in Blender.
## Add a level

BIN
cars/casserola_dx/car.glb Normal file

Binary file not shown.

View File

@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://dd3aov85sbn27"
path="res://.godot/imported/car.glb-6d8f2b8e5e0b6a46e40628e041439d43.scn"
[deps]
source_file="res://cars/casserola_dx/car.glb"
dest_files=["res://.godot/imported/car.glb-6d8f2b8e5e0b6a46e40628e041439d43.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cu6nllj3pxu8a"
path="res://.godot/imported/car_Image_0.png-f1e34ca46982f898b4d6c90b3f6c6148.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "348a9791dc41b89796ec3808b5b5262f"
}
[deps]
source_file="res://cars/casserola_dx/car_Image_0.png"
dest_files=["res://.godot/imported/car_Image_0.png-f1e34ca46982f898b4d6c90b3f6c6148.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://rleiwuy8oepq"
path="res://.godot/imported/car_Image_1.png-7be6a4a226014f015afe6ba35f1b7930.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "d8398af19e8e5a388342942b69550581"
}
[deps]
source_file="res://cars/casserola_dx/car_Image_1.png"
dest_files=["res://.godot/imported/car_Image_1.png-7be6a4a226014f015afe6ba35f1b7930.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bpj1jtpedqarf"
path="res://.godot/imported/car_Image_2.png-80fd138f6ac8f7ecbe057d68af58c928.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "64c1da604221bbc3457fd79772c2b578"
}
[deps]
source_file="res://cars/casserola_dx/car_Image_2.png"
dest_files=["res://.godot/imported/car_Image_2.png-80fd138f6ac8f7ecbe057d68af58c928.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bycgy0k5lu2rl"
path="res://.godot/imported/car_Image_3.png-eb4dcce541ecf0773ccc0fe8e2f1c81a.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "a2a9d313578563b9027384ffab32dc67"
}
[deps]
source_file="res://cars/casserola_dx/car_Image_3.png"
dest_files=["res://.godot/imported/car_Image_3.png-eb4dcce541ecf0773ccc0fe8e2f1c81a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://waymjnr0x1nk"
path="res://.godot/imported/car_Image_4.png-6c71e70c624b2dcf5383b469a764211d.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "b62d822f463da9bc8f0826af96238280"
}
[deps]
source_file="res://cars/casserola_dx/car_Image_4.png"
dest_files=["res://.godot/imported/car_Image_4.png-6c71e70c624b2dcf5383b469a764211d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,13 @@
[gd_resource type="Resource" script_class="CarStats" load_steps=2 format=3]
[ext_resource type="Script" path="res://src/car_stats.gd" id="1"]
[resource]
script = ExtResource("1")
display_name = "CASSEROLA DX"
model_path = "res://cars/casserola_dx/car.glb"
engine_power = 18.0
mass = 1000.0
grip = 7.0
length = 4.27
width = 1.80

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "CHAEBOL HLYR X1"
model_path = "res://cars/chaebol_x1/car.glb"
engine_power = 10.0
engine_power = 15.0
mass = 900.0
grip = 6.2
grip = 6.5
length = 4.28
width = 1.60

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "CHAEBOL HLYR X2"
model_path = "res://cars/chaebol_x2/car.glb"
engine_power = 11.5
engine_power = 17.0
mass = 950.0
grip = 6.5
grip = 6.8
length = 4.15
width = 1.61

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "DADSON 420YO"
model_path = "res://cars/datto_120y/car.glb"
engine_power = 11.0
engine_power = 20.0
mass = 850.0
grip = 6.5
grip = 7.0
length = 3.92
width = 1.50

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "CHAEBOL HLYR X3"
model_path = "res://cars/excel_x3/car.glb"
engine_power = 12.0
engine_power = 22.0
mass = 980.0
grip = 6.8
grip = 7.5
length = 4.10
width = 1.62

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "FLOORED XD LOLTOP"
model_path = "res://cars/floored_xd/car.glb"
engine_power = 22.0
engine_power = 10.0
mass = 1450.0
grip = 5.2
grip = 4.5
length = 4.85
width = 1.91

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "Gemmy TX"
model_path = "res://cars/gemmy_tx/car.glb"
engine_power = 13.0
engine_power = 16.0
mass = 950.0
grip = 7.0
grip = 7.2
length = 4.13
width = 1.57

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "HARDON CMERE"
model_path = "res://cars/hardon_cmere/car.glb"
engine_power = 12.0
engine_power = 19.0
mass = 1060.0
grip = 5.8
grip = 6.0
length = 4.48
width = 1.66

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "HARDON SHAGGEN"
model_path = "res://cars/hardon_shaggen/car.glb"
engine_power = 14.0
engine_power = 13.0
mass = 1250.0
grip = 5.5
grip = 5.0
length = 4.55
width = 1.72

View File

@ -6,7 +6,7 @@
script = ExtResource("1")
display_name = "Kingswood HQ"
model_path = "res://cars/kingswood_hq/car.glb"
engine_power = 15.0
engine_power = 14.0
mass = 1400.0
grip = 5.5
length = 4.81

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "MAXI MERK"
model_path = "res://cars/maxi_merk/car.glb"
engine_power = 12.0
engine_power = 13.0
mass = 800.0
grip = 6.5
grip = 6.0
length = 4.35
width = 1.45

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "MINI MERK"
model_path = "res://cars/mini_merk/car.glb"
engine_power = 9.0
engine_power = 17.0
mass = 600.0
grip = 7.5
grip = 8.0
length = 3.05
width = 1.42

BIN
cars/morry/car.glb Normal file

Binary file not shown.

42
cars/morry/car.glb.import Normal file
View File

@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://c6dpiro6fcq0g"
path="res://.godot/imported/car.glb-0f2fdbe283a5aac151743baf08dd07fa.scn"
[deps]
source_file="res://cars/morry/car.glb"
dest_files=["res://.godot/imported/car.glb-0f2fdbe283a5aac151743baf08dd07fa.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1

BIN
cars/morry/car_texture.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 MiB

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bi6prwdh3ns62"
path="res://.godot/imported/car_texture.jpg-d907562fb0b101f8744fabee19c3eb54.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "1bce60184df05cd7b8719c8a4950dd96"
}
[deps]
source_file="res://cars/morry/car_texture.jpg"
dest_files=["res://.godot/imported/car_texture.jpg-d907562fb0b101f8744fabee19c3eb54.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

13
cars/morry/stats.tres Normal file
View File

@ -0,0 +1,13 @@
[gd_resource type="Resource" script_class="CarStats" load_steps=2 format=3]
[ext_resource type="Script" path="res://src/car_stats.gd" id="1"]
[resource]
script = ExtResource("1")
display_name = "MORRY"
model_path = "res://cars/morry/car.glb"
engine_power = 16.0
mass = 620.0
grip = 8.0
length = 3.05
width = 1.45

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "TURDRUNNER SLUR 500"
model_path = "res://cars/turdrunner_slur/car.glb"
engine_power = 21.0
engine_power = 9.0
mass = 1200.0
grip = 6.0
grip = 4.3
length = 4.51
width = 1.71

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "VL Terbo"
model_path = "res://cars/vl_terbo/car.glb"
engine_power = 19.0
engine_power = 11.0
mass = 1250.0
grip = 5.0
grip = 4.8
length = 4.72
width = 1.72

View File

@ -6,8 +6,8 @@
script = ExtResource("1")
display_name = "XF Fungoon"
model_path = "res://cars/xf_falcon/car.glb"
engine_power = 15.0
engine_power = 12.0
mass = 1350.0
grip = 5.5
grip = 5.2
length = 4.91
width = 1.86

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bvj8acey6cfwt"
path="res://.godot/imported/shot_casserola_dx.png-143068759f8248f4e67facd7ba986a47.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shot_casserola_dx.png"
dest_files=["res://.godot/imported/shot_casserola_dx.png-143068759f8248f4e67facd7ba986a47.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bm80bpeqm41q4"
path="res://.godot/imported/shot_chaebol_x1.png-ab23f1251ae9c80a4dbe158ad9a4e40d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shot_chaebol_x1.png"
dest_files=["res://.godot/imported/shot_chaebol_x1.png-ab23f1251ae9c80a4dbe158ad9a4e40d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://khjyhwdfp4of"
path="res://.godot/imported/shot_chaebol_x2.png-85e80bf3292aa38ec2e2af06d6395f40.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shot_chaebol_x2.png"
dest_files=["res://.godot/imported/shot_chaebol_x2.png-85e80bf3292aa38ec2e2af06d6395f40.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ogsrhjmu4sa5"
path="res://.godot/imported/shot_hardon_cmere.png-791bf7aa28c70148da5c8cc8507cb785.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shot_hardon_cmere.png"
dest_files=["res://.godot/imported/shot_hardon_cmere.png-791bf7aa28c70148da5c8cc8507cb785.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

40
shot_morry.png.import Normal file
View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bn4ofl8uhfeaq"
path="res://.godot/imported/shot_morry.png-654f7e7886c576aa15987960425204b9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://shot_morry.png"
dest_files=["res://.godot/imported/shot_morry.png-654f7e7886c576aa15987960425204b9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -17,7 +17,8 @@ func _run() -> void:
assert(s != null and s.engine_power > 0.0, "bad stats: %s" % p)
if s.model_path != "":
assert(load(s.model_path) is PackedScene, "bad model: %s" % s.model_path)
Game.car_path = cars.values()[0]
# datto is procedural (has det_* parts); imported models legitimately have none
Game.car_path = cars.get("datto_120y", cars.values()[0])
Game.level_path = levels.values()[0]
# cruise: throttle 3s, car must move

82
tools/import_shitbox.py Normal file
View File

@ -0,0 +1,82 @@
"""Convert a downloaded model (glb/gltf/fbx/obj/blend) into a game-ready car GLB.
Run: /Applications/Blender.app/Contents/MacOS/Blender -b -P tools/import_shitbox.py -- \
"<input path>" <car_id> <target_length_m> [yaw_deg]
Normalizes: uniform scale so the longest horizontal extent = target length,
optional yaw (degrees) so the nose faces +Y (Godot -Z), centered, ground at
-0.75 (the controller's ride height). Exports cars/<car_id>/car.glb.
ponytail: imported models have no det_* panels, so they don't shed parts --
cutting doors out of downloaded meshes is per-model surgery for later.
"""
import math
import os
import sys
import bpy
from mathutils import Vector
argv = sys.argv[sys.argv.index("--") + 1:]
src, car_id, target_len = argv[0], argv[1], float(argv[2])
yaw = math.radians(float(argv[3])) if len(argv) > 3 else 0.0
ext = os.path.splitext(src)[1].lower()
if ext == ".blend":
bpy.ops.wm.open_mainfile(filepath=src)
else:
bpy.ops.wm.read_factory_settings(use_empty=True)
if ext in (".glb", ".gltf"):
bpy.ops.import_scene.gltf(filepath=src)
elif ext == ".fbx":
bpy.ops.import_scene.fbx(filepath=src)
elif ext == ".obj":
bpy.ops.wm.obj_import(filepath=src)
else:
raise SystemExit("unsupported: " + ext)
for obj in list(bpy.data.objects):
if obj.type not in ("MESH", "EMPTY"):
bpy.data.objects.remove(obj, do_unlink=True)
meshes = [o for o in bpy.data.objects if o.type == "MESH"]
assert meshes, "no meshes found"
root = bpy.data.objects.new("body", None)
bpy.context.collection.objects.link(root)
for obj in bpy.data.objects:
if obj is not root and obj.parent is None:
mw = obj.matrix_world.copy()
obj.parent = root
obj.matrix_world = mw
def bbox():
lo = Vector((1e9, 1e9, 1e9))
hi = Vector((-1e9, -1e9, -1e9))
dg = bpy.context.evaluated_depsgraph_get()
for o in meshes:
for c in o.evaluated_get(dg).bound_box:
w = o.matrix_world @ Vector(c)
lo = Vector(map(min, lo, w))
hi = Vector(map(max, hi, w))
return lo, hi
root.rotation_euler = (0, 0, yaw)
bpy.context.view_layer.update()
lo, hi = bbox()
size = hi - lo
scale = target_len / max(size.x, size.y)
root.scale = (scale,) * 3
bpy.context.view_layer.update()
lo, hi = bbox()
center = (lo + hi) / 2
root.location = Vector((-center.x, -center.y, -lo.z - 0.75))
bpy.context.view_layer.update()
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "cars", car_id)
os.makedirs(out, exist_ok=True)
for obj in bpy.data.objects:
obj.select_set(True)
path = os.path.join(out, "car.glb")
bpy.ops.export_scene.gltf(filepath=path, export_format="GLB", use_selection=True)
lo, hi = bbox()
print("imported %s -> %s | size %.2f x %.2f x %.2f" % (src, path, hi.x - lo.x, hi.y - lo.y, hi.z - lo.z))