diff --git a/docs/asset_reference.md b/docs/asset_reference.md
index 06af0ef6..13aa6e89 100644
--- a/docs/asset_reference.md
+++ b/docs/asset_reference.md
@@ -1,6 +1,6 @@
# Asset Reference
-This file was generated from asset_schema.wtf and is for version 29 of the asset format.
+This file was generated from asset_schema.wtf and is for version 30 of the asset format.
## Index
@@ -1111,14 +1111,13 @@ No children.
| - | - | - | - | - |
| name | The name of the material being referenced. | String | Yes | RAC/GC/UYA/DL |
| wrap_mode | The UV wrapping mode, stored as an array of two strings. Possible values are ["repeat" "repeat"] (the default), ["repeat" "clamp"], ["clamp" "repeat"] and ["clamp" "clamp"]. | Array | No | RAC/GC/UYA/DL |
-| glass | Only for mobies. Make the material shiny, like glass? | Boolean | *Not yet documented.* | *Not yet documented.* |
-| chrome | Only for mobies. Make the material shiny, like chrome? | Boolean | *Not yet documented.* | *Not yet documented.* |
+| effect_mode | List of effect modifiers, only relevant for mobies. Possible values are [], ["none"], ["chrome"] and ["glass"]. | Array | No | RAC/GC/UYA/DL |
*Children*
| Name | Description | Allowed Types | Required | Games |
| - | - | - | - | - |
-| diffuse | The diffuse map (main texture). | Texture | Yes | RAC/GC/UYA/DL |
+| diffuse | The diffuse map (main texture). | Texture | No | RAC/GC/UYA/DL |
### Collision
diff --git a/docs/asset_system.md b/docs/asset_system.md
index 3ac251ac..df4e1e7f 100644
--- a/docs/asset_system.md
+++ b/docs/asset_system.md
@@ -144,6 +144,7 @@ Each asset type is defined in `asset_schema.wtf` and a code generator, `asset_co
| Format Version | Wrench Version | Description |
| - | - | - |
+| 30 | | Added effect_mode attribute to Material assets, removed chrome and glass attributes, and made diffuse children optional. |
| 29 | | Added hero_groups attributes to Collision assets. |
| 28 | | Use glTF (.glb) for the moby models instead of COLLADA. |
| 27 | v0.5 | Use glTF (.glb) for the shrub and sky models instead of COLLADA. The mesh attribute of the SkyShell asset is now of type Mesh instead of Collection. The starting_rotation and angular_velocity attributes now only will only apply for UYA and DL (which is more correct). |
diff --git a/docs/instance_reference.md b/docs/instance_reference.md
index 0f31658a..2867ff59 100644
--- a/docs/instance_reference.md
+++ b/docs/instance_reference.md
@@ -1,6 +1,6 @@
# Instance Reference
-This file was generated from instance_schema.wtf and is for version 29 of the instance format.
+This file was generated from instance_schema.wtf and is for version 30 of the instance format.
## Instances
diff --git a/src/assetmgr/asset_schema.wtf b/src/assetmgr/asset_schema.wtf
index dfcc4576..c7520569 100644
--- a/src/assetmgr/asset_schema.wtf
+++ b/src/assetmgr/asset_schema.wtf
@@ -16,7 +16,7 @@
along with this program. If not, see .
*/
-format_version: 29
+format_version: 30
// *****************************************************************************
@@ -1714,19 +1714,18 @@ AssetType Material {
games: [1 2 3 4]
StringAttribute element {}
}
-
- BooleanAttribute glass {
- desc: "Only for mobies. Make the material shiny, like glass?"
- }
-
- BooleanAttribute chrome {
- desc: "Only for mobies. Make the material shiny, like chrome?"
+
+ ArrayAttribute effect_mode {
+ desc: "List of effect modifiers, only relevant for mobies. Possible values are [], [\"none\"], [\"chrome\"] and [\"glass\"]."
+ required: false
+ games: [1 2 3 4]
+ StringAttribute element {}
}
Child diffuse {
desc: "The diffuse map (main texture)."
allowed_types: ["Texture"]
- required: true
+ required: false
games: [1 2 3 4]
}
}
diff --git a/src/assetmgr/material_asset.cpp b/src/assetmgr/material_asset.cpp
index 31fe0d64..90b15e9f 100644
--- a/src/assetmgr/material_asset.cpp
+++ b/src/assetmgr/material_asset.cpp
@@ -27,17 +27,21 @@ MaterialSet read_material_assets(const CollectionAsset& src)
src.for_each_logical_child_of_type([&](const MaterialAsset& asset) {
Material& material = materials.emplace_back();
material.name = asset.name();
- const TextureAsset& diffuse = asset.get_diffuse();
- std::string diffuse_path = asset.get_diffuse().src().path.string();
- auto key = std::make_pair(&diffuse.file(), diffuse_path);
- auto iter = texture_indices.find(key);
- if (iter == texture_indices.end()) {
- texture_indices[key] = next_texture_index;
- material.surface = MaterialSurface(next_texture_index);
- next_texture_index++;
- textures.emplace_back(diffuse.file(), asset.get_diffuse().src().path);
+ if (asset.has_diffuse()) {
+ const TextureAsset& diffuse = asset.get_diffuse();
+ std::string diffuse_path = asset.get_diffuse().src().path.string();
+ auto key = std::make_pair(&diffuse.file(), diffuse_path);
+ auto iter = texture_indices.find(key);
+ if (iter == texture_indices.end()) {
+ texture_indices[key] = next_texture_index;
+ material.surface = MaterialSurface(next_texture_index);
+ next_texture_index++;
+ textures.emplace_back(diffuse.file(), asset.get_diffuse().src().path);
+ } else {
+ material.surface = MaterialSurface(iter->second);
+ }
} else {
- material.surface = MaterialSurface(iter->second);
+ material.surface = MaterialSurface(glm::vec4(1.f, 0.f, 1.f, 1.f));
}
if (asset.has_wrap_mode()) {
std::vector wrap_mode = asset.wrap_mode();
@@ -50,6 +54,19 @@ MaterialSet read_material_assets(const CollectionAsset& src)
}
}
}
+ if (asset.has_effect_mode()) {
+ for(std::string effect : asset.effect_mode()) {
+ if (effect == "none") {
+ material.effect_mode = MaterialEffectMode::NONE;
+ }
+ if (effect == "chrome") {
+ material.effect_mode = MaterialEffectMode::CHROME;
+ }
+ if (effect == "glass") {
+ material.effect_mode = MaterialEffectMode::GLASS;
+ }
+ }
+ }
});
return {materials, textures};
}
diff --git a/src/core/gltf.cpp b/src/core/gltf.cpp
index 785524a0..111dd72f 100644
--- a/src/core/gltf.cpp
+++ b/src/core/gltf.cpp
@@ -116,6 +116,7 @@ struct GLTFBuffer
// GLTF, Scenes & Nodes
static ModelFile read_gltf(const Json& src, Buffer bin_chunk);
static Json write_gltf(const ModelFile& src, OutBuffer bin_chunk);
+static void validate_gltf(const ModelFile& gltf);
static Asset read_asset(const Json& src);
static Json write_asset(const Asset& src);
static Scene read_scene(const Json& src);
@@ -256,6 +257,7 @@ ModelFile read_glb(Buffer src)
try {
auto json = Json::parse(src.lo + json_offset, src.lo + json_offset + json_size);
gltf = read_gltf(json, src.subbuf(bin_offset, bin_size));
+ validate_gltf(gltf);
} catch (Json::exception& e) {
verify_not_reached("%s", e.what());
}
@@ -265,6 +267,8 @@ ModelFile read_glb(Buffer src)
std::vector write_glb(const ModelFile& gltf)
{
+ validate_gltf(gltf);
+
std::vector result;
OutBuffer dest(result);
@@ -590,6 +594,71 @@ static Json write_gltf(const ModelFile& src, OutBuffer bin_chunk)
return dest;
}
+static void validate_gltf(const ModelFile& gltf)
+{
+ for (const Scene& scene : gltf.scenes) {
+ const char* name = scene.name.has_value() ? scene.name->c_str() : "unnamed";
+
+ for (NodeIndex node : scene.nodes) {
+ verify(node >= 0 && node < gltf.nodes.size(),
+ "Out of bounds node index %d for scene '%s'.", node, name);
+ }
+ }
+
+ for (const Node& node : gltf.nodes) {
+ const char* name = node.name.has_value() ? node.name->c_str() : "unnamed";
+
+ for (NodeIndex child : node.children) {
+ verify(child >= 0 && child < gltf.nodes.size(),
+ "Out of bounds child index %d for node '%s'.", child, name);
+ }
+
+ if (node.mesh.has_value()) {
+ verify(*node.mesh >= 0 && *node.mesh < gltf.meshes.size(),
+ "Out of bounds mesh index %d for node '%s'.", *node.mesh, name);
+ }
+ }
+
+ for (const Animation& animation : gltf.animations) {
+ const char* name = animation.name.has_value() ? animation.name->c_str() : "unnamed";
+
+ for (SamplerIndex sampler : animation.sampler_input) {
+ verify(sampler >= 0 && sampler < gltf.samplers.size(),
+ "Out of bounds sampler index %d for animation '%s'.", sampler, name);
+ }
+ }
+
+ for (const Mesh& mesh : gltf.meshes) {
+ const char* name = mesh.name.has_value() ? mesh.name->c_str() : "unnamed";
+
+ for (const MeshPrimitive& primitive : mesh.primitives) {
+ if (primitive.material.has_value()) {
+ verify(*primitive.material >= 0 && *primitive.material < gltf.materials.size(),
+ "Out of bounds material index %d for mesh '%s'.", *primitive.material, name);
+ }
+ }
+ }
+
+ for (const Material& material : gltf.materials) {
+ const char* name = material.name.has_value() ? material.name->c_str() : "unnamed";
+
+ if (material.pbr_metallic_roughness.has_value() && material.pbr_metallic_roughness->base_color_texture.has_value()) {
+ const TextureInfo& info = *material.pbr_metallic_roughness->base_color_texture;
+ verify(info.index >= 0 && info.index < gltf.textures.size(),
+ "Out of bounds texture index %d for material '%s'.", info.index, name);
+ }
+ }
+
+ for (const Texture& texture : gltf.textures) {
+ const char* name = texture.name.has_value() ? texture.name->c_str() : "unnamed";
+
+ if (texture.sampler.has_value()) {
+ verify(*texture.sampler >= 0 && *texture.sampler < gltf.samplers.size(),
+ "Out of bounds sampler index %d for texture '%s'.", *texture.sampler, name);
+ }
+ }
+}
+
static Asset read_asset(const Json& src)
{
Asset dest;
diff --git a/src/core/gltf.h b/src/core/gltf.h
index 62199213..c6f67844 100644
--- a/src/core/gltf.h
+++ b/src/core/gltf.h
@@ -25,6 +25,16 @@
namespace GLTF {
+using SceneIndex = s32;
+using NodeIndex = s32;
+using AnimationIndex = s32;
+using MeshIndex = s32;
+using MaterialIndex = s32;
+using TextureIndex = s32;
+using ImageIndex = s32;
+using SamplerIndex = s32;
+using SkinIndex = s32;
+
struct Asset
{
Opt copyright;
@@ -35,17 +45,17 @@ struct Asset
struct Scene
{
- std::vector nodes;
+ std::vector nodes;
Opt name;
};
struct Node
{
// unimplemented: camera
- std::vector children;
- Opt skin;
+ std::vector children;
+ Opt skin;
Opt matrix;
- Opt mesh;
+ Opt mesh;
Opt rotation;
Opt scale;
Opt translation;
@@ -70,12 +80,12 @@ struct Animation
{
Opt name;
std::vector channel_groups;
- std::vector sampler_input;
+ std::vector sampler_input;
};
struct TextureInfo
{
- s32 index;
+ TextureIndex index;
Opt tex_coord;
};
@@ -133,7 +143,7 @@ struct MeshPrimitive
{
u32 attributes_bitfield = 0;
std::vector indices;
- Opt material;
+ Opt material;
Opt mode;
// unimplemented: targets
};
@@ -148,7 +158,7 @@ struct Mesh
struct Texture
{
- Opt sampler;
+ Opt sampler;
Opt source;
Opt name;
};
diff --git a/src/core/material.cpp b/src/core/material.cpp
index 820c29c5..a43083e4 100644
--- a/src/core/material.cpp
+++ b/src/core/material.cpp
@@ -36,8 +36,8 @@ EffectiveMaterialsOutput effective_materials(const std::vector& materi
equal &= materials[i].wrap_mode_s == materials[j].wrap_mode_s;
equal &= materials[i].wrap_mode_t == materials[j].wrap_mode_t;
}
- if (attributes & MATERIAL_ATTRIB_METAL_MODE) {
- equal &= materials[i].metal_mode == materials[j].metal_mode;
+ if (attributes & MATERIAL_ATTRIB_EFFECT_MODE) {
+ equal &= materials[i].effect_mode == materials[j].effect_mode;
}
if (equal) {
effective.materials.emplace_back((s32) j);
diff --git a/src/core/material.h b/src/core/material.h
index 747b9a30..15b0ea5c 100644
--- a/src/core/material.h
+++ b/src/core/material.h
@@ -55,9 +55,9 @@ enum class WrapMode
REPEAT, CLAMP
};
-enum class MetalEffectMode
+enum class MaterialEffectMode
{
- OFF, CHROME, GLASS
+ OFF, NONE, CHROME, GLASS
};
struct Material
@@ -66,14 +66,14 @@ struct Material
MaterialSurface surface;
WrapMode wrap_mode_s = WrapMode::REPEAT;
WrapMode wrap_mode_t = WrapMode::REPEAT;
- MetalEffectMode metal_mode = MetalEffectMode::OFF;
+ MaterialEffectMode effect_mode = MaterialEffectMode::OFF;
};
enum MaterialAttribute
{
MATERIAL_ATTRIB_SURFACE = 1 << 1,
MATERIAL_ATTRIB_WRAP_MODE = 1 << 2,
- MATERIAL_ATTRIB_METAL_MODE = 1 << 3
+ MATERIAL_ATTRIB_EFFECT_MODE = 1 << 3
};
// An effective material is a set of materials that for some subset of
diff --git a/src/instancemgr/instance_schema.wtf b/src/instancemgr/instance_schema.wtf
index 76c395cd..f4dfd062 100644
--- a/src/instancemgr/instance_schema.wtf
+++ b/src/instancemgr/instance_schema.wtf
@@ -16,7 +16,7 @@
along with this program. If not, see .
*/
-format_version: 29
+format_version: 30
InstanceType Moby {
desc: "Moving, interactive, or otherwise dynamic objects with an associated update function."
@@ -24,7 +24,7 @@ InstanceType Moby {
transform_mode: "POSITION_ROTATION_SCALE"
variable: "moby_instances"
link_type: "mobylink"
-
+
s8 mission {}
s32 uid {}
s32 bolts {}
diff --git a/src/wrenchbuild/classes/moby_class.cpp b/src/wrenchbuild/classes/moby_class.cpp
index 798fa767..31655526 100644
--- a/src/wrenchbuild/classes/moby_class.cpp
+++ b/src/wrenchbuild/classes/moby_class.cpp
@@ -39,8 +39,9 @@ static void unpack_moby_mesh(
bool animated,
const std::string name);
static void pack_mesh_only_class(OutputStream& dest, const MobyClassAsset& src, BuildConfig config);
-static s32 count_materials(const CollectionAsset& materials);
static void unpack_materials(CollectionAsset& materials, GLTF::ModelFile& gltf);
+static void handle_special_materials(CollectionAsset& materials, GLTF::ModelFile& gltf);
+static void handle_invalid_materials(CollectionAsset& materials, GLTF::ModelFile& gltf);
static bool test_moby_class_core(
std::vector& src, AssetType type, BuildConfig config, const char* hint, AssetTestMode mode);
@@ -118,11 +119,6 @@ static void unpack_phat_class(MobyClassAsset& dest, InputStream& src, BuildConfi
{
unpack_asset_impl(dest.core(), src, nullptr, config);
- s32 texture_count = 0;
- if (!g_asset_unpacker.dump_binaries && dest.has_materials()) {
- texture_count = count_materials(dest.get_materials());
- }
-
std::vector buffer = src.read_multiple(0, src.size());
MOBY::MobyClassData data = MOBY::read_class(buffer, config.game());
@@ -138,9 +134,7 @@ static void unpack_phat_class(MobyClassAsset& dest, InputStream& src, BuildConfi
unpack_moby_mesh(gltf, *scene, data.bangles[i].low_lod, data.scale, animated, stringf("bangle_%zu_low_lod", i));
}
- if (!g_asset_unpacker.dump_binaries && dest.has_materials()) {
- unpack_materials(dest.get_materials(), gltf);
- }
+ unpack_materials(dest.materials(), gltf);
std::vector glb = GLTF::write_glb(gltf);
auto [stream, ref] = dest.file().open_binary_file_for_writing("mesh.glb");
@@ -164,25 +158,11 @@ static void unpack_mesh_only_class(
unpack_moby_mesh(gltf, *scene, meshes.high_lod, scale, animated, "moby");
unpack_moby_mesh(gltf, *scene, meshes.low_lod, scale, animated, "moby_low_lod");
- if (!g_asset_unpacker.dump_binaries && dest.has_materials()) {
- unpack_materials(dest.get_materials(), gltf);
- }
+ unpack_materials(dest.materials(), gltf);
std::vector glb = GLTF::write_glb(gltf);
auto [stream, ref] = dest.file().open_binary_file_for_writing("mesh.glb");
stream->write_v(glb);
-
- //MobyClassCoreAsset& core = dest.core();
- //
- //MeshAsset& moby_mesh = core.mesh();
- //moby_mesh.set_name("moby");
- //moby_mesh.set_src(ref);
- //
- //MeshAsset& moby_low_lod_mesh = core.low_lod_mesh();
- //moby_low_lod_mesh.set_name("moby_low_lod");
- //moby_low_lod_mesh.set_src(ref);
- //
- //core.set_scale(scale);
}
static void unpack_moby_mesh(
@@ -232,19 +212,6 @@ static void pack_mesh_only_class(OutputStream& dest, const MobyClassAsset& src,
dest.write_v(buffer);
}
-static s32 count_materials(const CollectionAsset& materials)
-{
- s32 texture_count = 0;
- for (s32 i = 0; i < 16; i++) {
- if (materials.has_child(i)) {
- texture_count++;
- } else {
- break;
- }
- }
- return texture_count;
-}
-
static void unpack_materials(CollectionAsset& materials, GLTF::ModelFile& gltf)
{
for (s32 i = 0; i < 16; i++) {
@@ -270,6 +237,63 @@ static void unpack_materials(CollectionAsset& materials, GLTF::ModelFile& gltf)
material_asset.set_name(*material.name);
}
+
+ handle_special_materials(materials, gltf);
+ handle_invalid_materials(materials, gltf);
+}
+
+static void handle_special_materials(CollectionAsset& materials, GLTF::ModelFile& gltf)
+{
+ std::optional special_material_indices[3];
+ static const char* special_material_names[3] = { "none", "chrome", "glass" };
+ static const glm::vec4 special_material_colours[3] =
+ { glm::vec4(1.f, 0.f, 1.f, 1.f), glm::vec4(0.5f, 0.5f, 0.5f, 1.f), glm::vec4(1.f, 1.f, 1.f, 1.f) };
+
+ for (GLTF::Mesh& mesh : gltf.meshes) {
+ for (GLTF::MeshPrimitive& primitive : mesh.primitives) {
+ if (primitive.material.has_value() && *primitive.material >= -3 && *primitive.material <= -1) {
+ s32 index = -*primitive.material - 1;
+
+ std::optional& material_index = special_material_indices[index];
+ if (!material_index.has_value()) {
+ MaterialAsset& material_asset = materials.child(special_material_names[index]);
+ material_asset.set_name(special_material_names[index]);
+
+ material_index = gltf.materials.size();
+ GLTF::Material& material = gltf.materials.emplace_back();
+ material.name = special_material_names[index];
+ GLTF::MaterialPbrMetallicRoughness& pbr = material.pbr_metallic_roughness.emplace();
+ pbr.base_color_factor = special_material_colours[index];
+ }
+
+ primitive.material = material_index;
+ }
+ }
+ }
+}
+
+static void handle_invalid_materials(CollectionAsset& materials, GLTF::ModelFile& gltf)
+{
+ static const char* error_material_name = "error";
+
+ Opt placeholder_material_index;
+ for (GLTF::Mesh& mesh : gltf.meshes) {
+ for (GLTF::MeshPrimitive& primitive : mesh.primitives) {
+ if (primitive.material.has_value() && (*primitive.material < 0 || *primitive.material >= gltf.materials.size())) {
+ if (!placeholder_material_index.has_value()) {
+ MaterialAsset& material_asset = materials.child(error_material_name);
+ material_asset.set_name(error_material_name);
+
+ placeholder_material_index = (GLTF::MaterialIndex) gltf.materials.size();
+ GLTF::Material& placeholder_material = gltf.materials.emplace_back();
+ placeholder_material.name = error_material_name;
+ GLTF::MaterialPbrMetallicRoughness& pbr = placeholder_material.pbr_metallic_roughness.emplace();
+ pbr.base_color_factor = glm::vec4(1.f, 0.f, 1.f, 1.f);
+ }
+ primitive.material = placeholder_material_index;
+ }
+ }
+ }
}
static bool test_moby_class_core(
diff --git a/src/wrenchbuild/level/collision_asset.cpp b/src/wrenchbuild/level/collision_asset.cpp
index 61e24106..4db76cbc 100644
--- a/src/wrenchbuild/level/collision_asset.cpp
+++ b/src/wrenchbuild/level/collision_asset.cpp
@@ -64,10 +64,6 @@ static void unpack_collision_asset(CollisionAsset& dest, InputStream& src, Build
static void pack_collision_asset(OutputStream& dest, const CollisionAsset& src, BuildConfig config)
{
- if (g_asset_packer_dry_run) {
- return;
- }
-
pack_level_collision(dest, src, nullptr, nullptr, -1);
}
@@ -84,6 +80,10 @@ void pack_level_collision(
const Gameplay* gameplay,
s32 chunk)
{
+ if (g_asset_packer_dry_run) {
+ return;
+ }
+
ColladaScene scene;
for (s32 i = 0; i < 256; i++) {
diff --git a/src/wrenchbuild/level/level_classes.h b/src/wrenchbuild/level/level_classes.h
index a8331b33..c1b6e044 100644
--- a/src/wrenchbuild/level/level_classes.h
+++ b/src/wrenchbuild/level/level_classes.h
@@ -37,6 +37,7 @@ void unpack_moby_classes(
BuildConfig config,
s32 moby_stash_addr,
const std::set& moby_stash);
+void unpack_rac1_armor_classes();
void pack_moby_classes(
OutputStream& index,
OutputStream& core,
diff --git a/src/wrenchbuild/level/level_core.cpp b/src/wrenchbuild/level/level_core.cpp
index f9fcca07..d555e234 100644
--- a/src/wrenchbuild/level/level_core.cpp
+++ b/src/wrenchbuild/level/level_core.cpp
@@ -165,14 +165,36 @@ void unpack_level_core(
}
}
}
-
+
+ // TODO: Unpack to main moby_classes directory, and refactor this into a
+ // separate function?
if (config.game() == Game::RAC) {
+ auto moby_class_entries = index.read_multiple(header.moby_classes);
+ auto moby_class_textures = index.read_multiple(header.moby_textures);
+
CollectionAsset& gadgets = dest.gadgets(SWITCH_FILES);
auto gadget_entries = index.read_multiple(header.gadget_offset_rac1, header.gadget_count_rac1);
+
for (RacGadgetHeader& entry : gadget_entries) {
ByteRange range{entry.offset_in_asset_wad, (s32) data.size() - entry.offset_in_asset_wad};
MobyClassAsset& moby = gadgets.foreign_child(entry.class_number);
moby.set_id(entry.class_number);
+
+ const MobyClassEntry* class_entry = nullptr;
+ for (const MobyClassEntry& test_class_entry : moby_class_entries) {
+ if (test_class_entry.o_class == entry.class_number) {
+ class_entry = &test_class_entry;
+ }
+ }
+ verify(class_entry, "No moby class entry for gadget %d.", entry.class_number);
+
+ bool stashed = moby_stash.contains(entry.class_number);
+ if (stashed) {
+ moby.set_stash_textures(true);
+ }
+
+ unpack_level_materials(moby.materials(), class_entry->textures, moby_class_textures, texture_data, gs_ram, config.game(), stashed ? moby_stash_addr : -1);
+
unpack_compressed_asset(moby, data, range, config, FMT_MOBY_CLASS_PHAT);
}
}
@@ -251,6 +273,7 @@ void pack_level_core(
std::vector gs_table;
std::vector part_defs;
if (!g_asset_packer_dry_run) {
+ // TODO: Pack R&C1 gadget textures.
shared = read_level_textures(first_chunk_asset.get_tfrags().get_materials(), mobies, ties, shrubs);
for (LevelTexture& record : shared.textures) {
diff --git a/src/wrenchbuild/level/sky_asset.cpp b/src/wrenchbuild/level/sky_asset.cpp
index aa26597b..cb40d2b4 100644
--- a/src/wrenchbuild/level/sky_asset.cpp
+++ b/src/wrenchbuild/level/sky_asset.cpp
@@ -26,8 +26,6 @@
#include
#include
-#define SEPERATE_SKY_CLUSTERS
-
static void unpack_sky_asset(SkyAsset& dest, InputStream& src, BuildConfig config);
static void pack_sky_asset(OutputStream& dest, const SkyAsset& src, BuildConfig config);
static void unpack_sky_textures(