From 52dca7d90f96a0be5d572b21d9f518c5f9cfd24f Mon Sep 17 00:00:00 2001 From: Taggerung Date: Thu, 21 Sep 2023 19:01:10 -0400 Subject: [PATCH 1/8] Draft for a course model extractor Should be able to extract arbitrary vtx lists with a little adjustment Signed-off-by: Taggerung --- .gitignore | 1 + tools/utils.c | 20 ++++----- tools/utils.h | 2 +- tools/vtx_extract.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++ tools/vtx_extract.mk | 6 +++ 5 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 tools/vtx_extract.cpp create mode 100644 tools/vtx_extract.mk diff --git a/.gitignore b/.gitignore index 8095be485..01ede98f9 100755 --- a/.gitignore +++ b/.gitignore @@ -73,6 +73,7 @@ expected/* /music/**/*.m64 /sound/**/*.m64 /sound/**/*.aiff +/courses/**/*.vtx !/textures/**/*custom*.png !/textures/**/*custom*/**/*.png !/sound/**/*custom*.m64 diff --git a/tools/utils.c b/tools/utils.c index b4f0ccd6d..9c67a9644 100644 --- a/tools/utils.c +++ b/tools/utils.c @@ -237,16 +237,16 @@ void generate_filename(const char *in_name, char *out_name, char *extension) sprintf(out_name, "%s.%s", tmp_name, extension); } -char *basename(const char *name) -{ - const char *base = name; - while (*name) { - if (*name++ == '/') { - base = name; - } - } - return (char *)base; -} +// char *basename(const char *name) +// { +// const char *base = name; +// while (*name) { +// if (*name++ == '/') { +// base = name; +// } +// } +// return (char *)base; +// } void make_dir(const char *dir_name) { diff --git a/tools/utils.h b/tools/utils.h index a8d07eb19..d7d6f5fe4 100644 --- a/tools/utils.h +++ b/tools/utils.h @@ -137,7 +137,7 @@ void generate_filename(const char *in_name, char *out_name, char *extension); // extract base filename from file path // name: path to file // returns just the file name after the last '/' -char *basename(const char *name); +//char *basename(const char *name); // make a directory if it doesn't exist // dir_name: name of the directory diff --git a/tools/vtx_extract.cpp b/tools/vtx_extract.cpp new file mode 100644 index 000000000..856d92efe --- /dev/null +++ b/tools/vtx_extract.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include + +#include "libmio0.h" + +typedef struct { + uint32_t rom_offset; + std::string course_name; +} model_location; + +std::vector all_models = { + { 0x88fa10, "mario_raceway" }, + { 0x89b510, "choco_mountain" }, + { 0x8a7640, "bowsers_castle" }, + { 0x8b9630, "banshee_boardwalk" }, + { 0x8c2510, "yoshi_valley" }, + { 0x8cc900, "frappe_snowland" }, + { 0x8d8e50, "koopa_troopa_beach" }, + { 0x8ec390, "royal_raceway" }, + { 0x8fe640, "luigi_raceway" }, + { 0x90b3e0, "moo_moo_farm" }, + { 0x91b980, "toads_turnpike" }, + { 0x928c70, "kalimari_desert" }, + { 0x936fd0, "sherbet_land" }, + { 0x93cc60, "rainbow_road" }, + { 0x9438c0, "wario_stadium" }, + { 0x951780, "block_fort" }, + { 0x953890, "skyscraper" }, + { 0x955620, "double_deck" }, + { 0x956670, "dks_jungle_parkway" }, + { 0x963ef0, "big_donut" }, +}; + +typedef struct { + short ob[3]; /* x, y, z */ + short tc[2]; /* texture coord */ + unsigned char n[3]; /* color & alpha */ +} mk64_Vtx_n; + +std::ifstream & operator >> (std::ifstream &in, mk64_Vtx_n &vtx) { + // This is highly dependent on the `mk64_Vtx_n` type having no padding between its elements + // And that is the case, but its worth noting that its kind of brittle + in.read(reinterpret_cast(&vtx), sizeof(mk64_Vtx_n)); + return in; +} + +inline short bswap(short in) { + return ((in & 0xFF) << 8) | ((in >> 8) & 0xFF); +} + +// argv[1] -> path to baserom file +int main(int argc, char **argv) { + int err; + mk64_Vtx_n vtx; + std::ofstream vtx_obj; + std::ofstream model_inc; + std::ifstream model_bytes; + + std::string vtx_obj_path; + std::string model_inc_path; + // There HAS to be a better way to do this + std::string uncompressed_model = "./temp.model.bin"; + + for (auto model : all_models) { + vtx_obj_path = "./courses/" + model.course_name + "/course.vertices.obj"; + model_inc_path = "./courses/" + model.course_name + "/course.vtx"; + + err = mio0_decode_file(argv[1], model.rom_offset, uncompressed_model.c_str()); + + if (err != 0) { + std::cout << "Something wrong occurred when decoding " << model.course_name << "'s model" << std::endl; + goto loop_cleanup; + } + + // Should probably confirm that the file open actually worked + vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::trunc); + model_inc.open(model_inc_path, std::ios::out | std::ios::trunc); + model_bytes.open(uncompressed_model, std::ios::in | std::ios::binary); + + while(model_bytes >> vtx) { + // I hate all forms of string manipulation in C/++ + // If we could use gpp 13+ we could use the `fmt` feature to make this cleaner + // I also don't know if the bswap'ing is necessary everywhere or just on my machine + model_inc << "{" \ + << "{ " << std::to_string(bswap(vtx.ob[0])) << ", " << std::to_string(bswap(vtx.ob[1])) << ", " << std::to_string(bswap(vtx.ob[2])) << " }, " \ + << "{ " << std::to_string(bswap(vtx.tc[0])) << ", " << std::to_string(bswap(vtx.tc[1])) << " }, " \ + << "{ " << std::to_string(vtx.n[0]) << ", " << std::to_string(vtx.n[1]) << ", " << std::to_string(vtx.n[2]) << " }" \ + << "}," << std::endl; + vtx_obj << "v " << bswap(vtx.ob[0]) << " " << bswap(vtx.ob[1]) << " " << bswap(vtx.ob[2]) << std::endl; + } + +loop_cleanup: + model_bytes.close(); + model_inc.close(); + vtx_obj.close(); + } + return 0; +} diff --git a/tools/vtx_extract.mk b/tools/vtx_extract.mk new file mode 100644 index 000000000..7bc2c1bc3 --- /dev/null +++ b/tools/vtx_extract.mk @@ -0,0 +1,6 @@ +CPP := g++ + +CPPFLAGS := -fpermissive + +vtx_extract: vtx_extract.cpp libmio0.c libmio0.h utils.c utils.h + $(CPP) $(CPPFLAGS) -o $@ $^ From 5204dc8437bb385bb43e15332fd133f5d999f5b6 Mon Sep 17 00:00:00 2001 From: Taggerung Date: Sat, 23 Sep 2023 18:11:19 -0400 Subject: [PATCH 2/8] Update script to also extra face data from baserom course.vtx is the file to be #included in course_vertices.inc.c course.obj is, as named, an OBJ file with the vertex and face lists for the given course Signed-off-by: Taggerung --- tools/vtx_extract.cpp | 180 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 155 insertions(+), 25 deletions(-) diff --git a/tools/vtx_extract.cpp b/tools/vtx_extract.cpp index 856d92efe..0519b2513 100644 --- a/tools/vtx_extract.cpp +++ b/tools/vtx_extract.cpp @@ -6,31 +6,32 @@ #include "libmio0.h" typedef struct { - uint32_t rom_offset; + uint32_t model_rom_offset; + uint32_t packed_dl_rom_offset; std::string course_name; } model_location; std::vector all_models = { - { 0x88fa10, "mario_raceway" }, - { 0x89b510, "choco_mountain" }, - { 0x8a7640, "bowsers_castle" }, - { 0x8b9630, "banshee_boardwalk" }, - { 0x8c2510, "yoshi_valley" }, - { 0x8cc900, "frappe_snowland" }, - { 0x8d8e50, "koopa_troopa_beach" }, - { 0x8ec390, "royal_raceway" }, - { 0x8fe640, "luigi_raceway" }, - { 0x90b3e0, "moo_moo_farm" }, - { 0x91b980, "toads_turnpike" }, - { 0x928c70, "kalimari_desert" }, - { 0x936fd0, "sherbet_land" }, - { 0x93cc60, "rainbow_road" }, - { 0x9438c0, "wario_stadium" }, - { 0x951780, "block_fort" }, - { 0x953890, "skyscraper" }, - { 0x955620, "double_deck" }, - { 0x956670, "dks_jungle_parkway" }, - { 0x963ef0, "big_donut" }, + { 0x88fa10, 0x899104, "mario_raceway" }, + { 0x89b510, 0x8A55C4, "choco_mountain" }, + { 0x8a7640, 0x8B59A8, "bowsers_castle" }, + { 0x8b9630, 0x8BFF18, "banshee_boardwalk" }, + { 0x8c2510, 0x8CA2A0, "yoshi_valley" }, + { 0x8cc900, 0x8D6624, "frappe_snowland" }, + { 0x8d8e50, 0x8E8BC8, "koopa_troopa_beach" }, + { 0x8ec390, 0x8FAFF0, "royal_raceway" }, + { 0x8fe640, 0x907E40, "luigi_raceway" }, + { 0x90b3e0, 0x918ECC, "moo_moo_farm" }, + { 0x91b980, 0x925F50, "toads_turnpike" }, + { 0x928c70, 0x934004, "kalimari_desert" }, + { 0x936fd0, 0x93B9C8, "sherbet_land" }, + { 0x93cc60, 0x9426BC, "rainbow_road" }, + { 0x9438c0, 0x94E28C, "wario_stadium" }, + { 0x951780, 0x953058, "block_fort" }, + { 0x953890, 0x954F08, "skyscraper" }, + { 0x955620, 0x9562F4, "double_deck" }, + { 0x956670, 0x960ACC, "dks_jungle_parkway" }, + { 0x963ef0, 0x965A74, "big_donut" }, }; typedef struct { @@ -53,6 +54,11 @@ inline short bswap(short in) { // argv[1] -> path to baserom file int main(int argc, char **argv) { int err; + uint8_t opcode; + uint8_t data_byte; + uint16_t data_short; + short vtx_index; + short v1, v2, v3; mk64_Vtx_n vtx; std::ofstream vtx_obj; std::ofstream model_inc; @@ -64,10 +70,10 @@ int main(int argc, char **argv) { std::string uncompressed_model = "./temp.model.bin"; for (auto model : all_models) { - vtx_obj_path = "./courses/" + model.course_name + "/course.vertices.obj"; + vtx_obj_path = "./courses/" + model.course_name + "/course.obj"; model_inc_path = "./courses/" + model.course_name + "/course.vtx"; - err = mio0_decode_file(argv[1], model.rom_offset, uncompressed_model.c_str()); + err = mio0_decode_file(argv[1], model.model_rom_offset, uncompressed_model.c_str()); if (err != 0) { std::cout << "Something wrong occurred when decoding " << model.course_name << "'s model" << std::endl; @@ -86,9 +92,18 @@ int main(int argc, char **argv) { model_inc << "{" \ << "{ " << std::to_string(bswap(vtx.ob[0])) << ", " << std::to_string(bswap(vtx.ob[1])) << ", " << std::to_string(bswap(vtx.ob[2])) << " }, " \ << "{ " << std::to_string(bswap(vtx.tc[0])) << ", " << std::to_string(bswap(vtx.tc[1])) << " }, " \ - << "{ " << std::to_string(vtx.n[0]) << ", " << std::to_string(vtx.n[1]) << ", " << std::to_string(vtx.n[2]) << " }" \ + << "{ " << std::to_string(vtx.n[0]) << ", " << std::to_string(vtx.n[1]) << ", " << std::to_string(vtx.n[2]) << " }" \ << "}," << std::endl; - vtx_obj << "v " << bswap(vtx.ob[0]) << " " << bswap(vtx.ob[1]) << " " << bswap(vtx.ob[2]) << std::endl; + vtx_obj << "v " \ + << std::to_string(bswap(vtx.ob[0])) << " " << std::to_string(bswap(vtx.ob[1])) << " " << std::to_string(bswap(vtx.ob[2])) \ + << std::endl; + // Further processing will be required to get these numbers correct + // vt needs to be converted to a floating point value between 0 and 1 + // I'm not sure how to do that in this case + // vn currently has the "flag" variable shoved inside it, so we'd need to extract just the + // normals from it before writing it out to a file + //vtx_obj << "vt " << std::to_string(bswap(vtx.tc[0])) << " " << std::to_string(bswap(vtx.tc[1])) << std::endl; + //vtx_obj << "vn " << std::to_string(vtx.n[0]) << " " << std::to_string(vtx.n[1]) << " " << std::to_string(vtx.n[2]) << std::endl; } loop_cleanup: @@ -96,5 +111,120 @@ loop_cleanup: model_inc.close(); vtx_obj.close(); } + + for (auto model : all_models) { + vtx_obj_path = "./courses/" + model.course_name + "/course.obj"; + + // Should probably confirm that the file open actually worked + vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::app); + model_bytes.open(argv[1], std::ios::in | std::ios::binary); + model_bytes.seekg(model.packed_dl_rom_offset); + + while(model_bytes.read(&opcode, 1)) { + if (opcode == 0xFF) { + break; + } + + /** + * For unpack_vtx1/2, we are ignoring the fact that the v0 argument + * in gsSPVertex macro could be something other than 0. + * In our case it is always 0, but it is an assumption on our part. + * vtx_index will be incorrect if that assumption is ever broken. + **/ + if ((0x33 <= opcode) && (opcode <= 0x52)) { // unpack_vtx2, gsSPVertex + // 3 bytes including opcode + model_bytes.read(reinterpret_cast(&data_short), 2); + vtx_index = data_short + 1; + } else if (opcode == 0x28) { // unpack_vtx1, gsSPVertex + // 5 bytes including the opcode + model_bytes.read(reinterpret_cast(&data_short), 2); + vtx_index = data_short + 1; + // Only need the vertex "address", skip the other 2 bytes + model_bytes.seekg(2, std::ios_base::cur); + } else if (opcode == 0x29) { // unpack_triangle, gsSP1Triangle + // 3 bytes including opcode + // bottom 2 bytes looke like: + // Byte 3 Byte 2 + // X3333322 22211111 + model_bytes.read(reinterpret_cast(&data_short), 2); + v1 = data_short & 0x1F; + v2 = (data_short >> 5) & 7; + v2 |= ((data_short >> 8) & 3) << 3; + v3 = (data_short >> 10) & 0x1F; + v1 += vtx_index; + v2 += vtx_index; + v3 += vtx_index; + vtx_obj << "f " \ + << std::to_string(v1) << " " << std::to_string(v2) << " " << std::to_string(v3) \ + << std::endl; + } else if (opcode == 0x58) { // unpack_quadrangle, gsSP2Triangles + // 5 bytes including opcode + for (auto tri = 0; tri < 2; tri++) { + model_bytes.read(reinterpret_cast(&data_short), 2); + v1 = data_short & 0x1F; + v2 = (data_short >> 5) & 7; + v2 |= ((data_short >> 8) & 3) << 3; + v3 = (data_short >> 10) & 0x1F; + v1 += vtx_index; + v2 += vtx_index; + v3 += vtx_index; + vtx_obj << "f " \ + << std::to_string(v1) << " " << std::to_string(v2) << " " << std::to_string(v3) \ + << std::endl; + } + } else if ( + ((0x00 <= opcode) && (opcode <= 0x19)) || + (opcode == 0x26) || (opcode == 0x27) || + (opcode == 0x2A) || + ((0x2D <= opcode) && (opcode <= 0x2F)) || + ((0x53 <= opcode) && (opcode <= 0x57))) { + /** + * 0x00 - 0x14: unpack_lights, gsSPNumLights + * 0x15: unpack_combine_mode1, + * 0x16: unpack_combine_mode2, + * 0x17: unpack_combine_mode_shade, + * 0x18: unpack_render_mode_opaque, + * 0x19: unpack_render_mode_tex_edge, + * 0x26: unpack_texture_on, + * 0x27: unpack_texture_off, + * 0x2A: unpack_end_displaylist, + * 0x2D: unpack_cull_displaylist, + * 0x2E: unpack_combine_mode4, + * 0x2F: unpack_render_mode_translucent, + * 0x53: unpack_combine_mode5, + * 0x54: unpack_render_mode_opaque_decal, + * 0x55: unpack_render_mode_translucent_decal, + * 0x56: unpack_set_geometry_mode, + * 0x57: unpack_clear_geometry_mode, + **/ + // Only 1 byte, the opcode + ; + } else if ( + ((0x1A <= opcode) && (opcode <= 0x1F)) || + (opcode == 0x2B) || (opcode == 0x2C)) { + /** + * 0x1A - 0x1F, 0x2C: unpack_tile_sync, + * 0x2B: unpack_displaylist, + **/ + // 3 bytes including the opcode + model_bytes.seekg(2, std::ios_base::cur); + } else if ( + ((0x20 <= opcode) && (opcode <= 0x25)) || + (opcode == 0x30)) { + /** + * 0x20 - 0x25: unpack_tile_load_sync, + * 0x30: unpack_spline_3D, + **/ + // 4 bytes including the opcode + model_bytes.seekg(3, std::ios_base::cur); + } else { + std::cout << "WARNING UNEXPECTED opcode: " << std::to_string(opcode) << std::endl; + break; + } + } + + model_bytes.close(); + vtx_obj.close(); + } return 0; } From fcea67fdce0652670b00ec81d4b453ce8cb3016d Mon Sep 17 00:00:00 2001 From: Taggerung Date: Sun, 24 Sep 2023 22:17:16 -0400 Subject: [PATCH 3/8] More changes, works lightly better Signed-off-by: Taggerung --- tools/vtx_extract.cpp | 117 +++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 48 deletions(-) diff --git a/tools/vtx_extract.cpp b/tools/vtx_extract.cpp index 0519b2513..e5c4ab821 100644 --- a/tools/vtx_extract.cpp +++ b/tools/vtx_extract.cpp @@ -1,6 +1,7 @@ -#include -#include #include +#include +#include +#include #include #include "libmio0.h" @@ -37,7 +38,7 @@ std::vector all_models = { typedef struct { short ob[3]; /* x, y, z */ short tc[2]; /* texture coord */ - unsigned char n[3]; /* color & alpha */ + char n[3]; /* color & alpha */ } mk64_Vtx_n; std::ifstream & operator >> (std::ifstream &in, mk64_Vtx_n &vtx) { @@ -54,12 +55,11 @@ inline short bswap(short in) { // argv[1] -> path to baserom file int main(int argc, char **argv) { int err; - uint8_t opcode; - uint8_t data_byte; - uint16_t data_short; - short vtx_index; - short v1, v2, v3; mk64_Vtx_n vtx; + std::stringstream vtx_string; + std::stringstream vtx_tc_string; + std::stringstream vtx_norm_string; + std::stringstream model_string; std::ofstream vtx_obj; std::ofstream model_inc; std::ifstream model_bytes; @@ -77,50 +77,66 @@ int main(int argc, char **argv) { if (err != 0) { std::cout << "Something wrong occurred when decoding " << model.course_name << "'s model" << std::endl; - goto loop_cleanup; + continue; } // Should probably confirm that the file open actually worked - vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::trunc); - model_inc.open(model_inc_path, std::ios::out | std::ios::trunc); - model_bytes.open(uncompressed_model, std::ios::in | std::ios::binary); - + model_bytes.open(uncompressed_model, std::ios::in | std::ios::binary); while(model_bytes >> vtx) { // I hate all forms of string manipulation in C/++ // If we could use gpp 13+ we could use the `fmt` feature to make this cleaner // I also don't know if the bswap'ing is necessary everywhere or just on my machine - model_inc << "{" \ + model_string << "{" \ << "{ " << std::to_string(bswap(vtx.ob[0])) << ", " << std::to_string(bswap(vtx.ob[1])) << ", " << std::to_string(bswap(vtx.ob[2])) << " }, " \ << "{ " << std::to_string(bswap(vtx.tc[0])) << ", " << std::to_string(bswap(vtx.tc[1])) << " }, " \ << "{ " << std::to_string(vtx.n[0]) << ", " << std::to_string(vtx.n[1]) << ", " << std::to_string(vtx.n[2]) << " }" \ << "}," << std::endl; - vtx_obj << "v " \ + vtx_string << "v " \ << std::to_string(bswap(vtx.ob[0])) << " " << std::to_string(bswap(vtx.ob[1])) << " " << std::to_string(bswap(vtx.ob[2])) \ << std::endl; // Further processing will be required to get these numbers correct // vt needs to be converted to a floating point value between 0 and 1 // I'm not sure how to do that in this case - // vn currently has the "flag" variable shoved inside it, so we'd need to extract just the - // normals from it before writing it out to a file - //vtx_obj << "vt " << std::to_string(bswap(vtx.tc[0])) << " " << std::to_string(bswap(vtx.tc[1])) << std::endl; - //vtx_obj << "vn " << std::to_string(vtx.n[0]) << " " << std::to_string(vtx.n[1]) << " " << std::to_string(vtx.n[2]) << std::endl; + //vtx_tc_string << "vt " << std::to_string(bswap(vtx.tc[0])) << " " << std::to_string(bswap(vtx.tc[1])) << std::endl; + // Using signed chars to ensure the normals are signed before being divided + char n1 = vtx.n[0] & 0xFC; + char n2 = vtx.n[1] & 0xFC; + char n3 = vtx.n[2]; + vtx_norm_string << "vn " \ + << std::to_string(n1 / 128.0f) << " " \ + << std::to_string(n2 / 128.0f) << " " \ + << std::to_string(n3 / 128.0f) \ + << std::endl; } - -loop_cleanup: model_bytes.close(); - model_inc.close(); + + vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::trunc); + vtx_obj << vtx_string.rdbuf() /*<< vtx_tc_string.rdbuf()*/ << vtx_norm_string.rdbuf(); vtx_obj.close(); + + model_inc.open(model_inc_path, std::ios::out | std::ios::trunc); + model_inc << model_string.rdbuf(); + model_inc.close(); + } + int num_tris; + uint8_t opcode; + uint16_t data_short; + short vtx_index; + short v1, v2, v3; + std::stringstream face_string; + int object_num = 0; + int face_group_num = 0; + for (auto model : all_models) { vtx_obj_path = "./courses/" + model.course_name + "/course.obj"; // Should probably confirm that the file open actually worked - vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::app); model_bytes.open(argv[1], std::ios::in | std::ios::binary); model_bytes.seekg(model.packed_dl_rom_offset); - - while(model_bytes.read(&opcode, 1)) { + face_string << "o object" << std::to_string(object_num++) << std::endl; + while(model_bytes.read(reinterpret_cast(&opcode), 1)) { if (opcode == 0xFF) { break; } @@ -135,31 +151,29 @@ loop_cleanup: // 3 bytes including opcode model_bytes.read(reinterpret_cast(&data_short), 2); vtx_index = data_short + 1; + face_string << "g face_group" << std::to_string(face_group_num++) << std::endl; } else if (opcode == 0x28) { // unpack_vtx1, gsSPVertex // 5 bytes including the opcode model_bytes.read(reinterpret_cast(&data_short), 2); vtx_index = data_short + 1; // Only need the vertex "address", skip the other 2 bytes model_bytes.seekg(2, std::ios_base::cur); - } else if (opcode == 0x29) { // unpack_triangle, gsSP1Triangle - // 3 bytes including opcode - // bottom 2 bytes looke like: - // Byte 3 Byte 2 + } else if ((opcode == 0x29) || (opcode == 0x58)) { + /** + * 0x29: unpack_triangle, gsSP1Triangle + * 3 bytes including opcode + * 0x58: unpack_quadrangle, gsSP2Triangles + * 5 bytes including opcode + **/ + if (opcode == 0x29) { + num_tris = 1; + } else { + num_tris = 2; + } + // Each 2-byte holding the vertex indices looks like: + // Byte 2 Byte 1 // X3333322 22211111 - model_bytes.read(reinterpret_cast(&data_short), 2); - v1 = data_short & 0x1F; - v2 = (data_short >> 5) & 7; - v2 |= ((data_short >> 8) & 3) << 3; - v3 = (data_short >> 10) & 0x1F; - v1 += vtx_index; - v2 += vtx_index; - v3 += vtx_index; - vtx_obj << "f " \ - << std::to_string(v1) << " " << std::to_string(v2) << " " << std::to_string(v3) \ - << std::endl; - } else if (opcode == 0x58) { // unpack_quadrangle, gsSP2Triangles - // 5 bytes including opcode - for (auto tri = 0; tri < 2; tri++) { + for (auto tri = 0; tri < num_tris; tri++) { model_bytes.read(reinterpret_cast(&data_short), 2); v1 = data_short & 0x1F; v2 = (data_short >> 5) & 7; @@ -168,9 +182,12 @@ loop_cleanup: v1 += vtx_index; v2 += vtx_index; v3 += vtx_index; - vtx_obj << "f " \ - << std::to_string(v1) << " " << std::to_string(v2) << " " << std::to_string(v3) \ - << std::endl; + face_string << "f "; + // v index / vt index / vn index + face_string << std::to_string(v1) << "/" /*<< std::to_string(v1)*/ << "/" << std::to_string(v1) << " "; + face_string << std::to_string(v2) << "/" /*<< std::to_string(v2)*/ << "/" << std::to_string(v2) << " "; + face_string << std::to_string(v3) << "/" /*<< std::to_string(v3)*/ << "/" << std::to_string(v3) << " "; + face_string << std::endl; } } else if ( ((0x00 <= opcode) && (opcode <= 0x19)) || @@ -198,7 +215,9 @@ loop_cleanup: * 0x57: unpack_clear_geometry_mode, **/ // Only 1 byte, the opcode - ; + if (opcode == 0x2A) { + face_string << "o object" << std::to_string(object_num++) << std::endl; + } } else if ( ((0x1A <= opcode) && (opcode <= 0x1F)) || (opcode == 0x2B) || (opcode == 0x2C)) { @@ -222,8 +241,10 @@ loop_cleanup: break; } } - model_bytes.close(); + + vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::app); + vtx_obj << face_string.rdbuf(); vtx_obj.close(); } return 0; From 525d521ff21c2b17e98aa30cdf788c99cf840d0e Mon Sep 17 00:00:00 2001 From: Taggerung Date: Tue, 26 Sep 2023 22:20:45 -0400 Subject: [PATCH 4/8] Did some re-arranging to make getting the texutre coordinate possible This mostly works, although you have to generate the mtl file yourself and even then there's some stuff that's horribly messed up. Signed-off-by: Taggerung --- tools/vtx_extract.cpp | 287 +++++++++++++++++++++++++++--------------- 1 file changed, 189 insertions(+), 98 deletions(-) diff --git a/tools/vtx_extract.cpp b/tools/vtx_extract.cpp index e5c4ab821..06ca3aa6e 100644 --- a/tools/vtx_extract.cpp +++ b/tools/vtx_extract.cpp @@ -1,5 +1,8 @@ +#include #include #include +#include +#include #include #include #include @@ -7,47 +10,88 @@ #include "libmio0.h" typedef struct { + std::string course_name; uint32_t model_rom_offset; uint32_t packed_dl_rom_offset; - std::string course_name; + std::map textures; } model_location; std::vector all_models = { - { 0x88fa10, 0x899104, "mario_raceway" }, - { 0x89b510, 0x8A55C4, "choco_mountain" }, - { 0x8a7640, 0x8B59A8, "bowsers_castle" }, - { 0x8b9630, 0x8BFF18, "banshee_boardwalk" }, - { 0x8c2510, 0x8CA2A0, "yoshi_valley" }, - { 0x8cc900, 0x8D6624, "frappe_snowland" }, - { 0x8d8e50, 0x8E8BC8, "koopa_troopa_beach" }, - { 0x8ec390, 0x8FAFF0, "royal_raceway" }, - { 0x8fe640, 0x907E40, "luigi_raceway" }, - { 0x90b3e0, 0x918ECC, "moo_moo_farm" }, - { 0x91b980, 0x925F50, "toads_turnpike" }, - { 0x928c70, 0x934004, "kalimari_desert" }, - { 0x936fd0, 0x93B9C8, "sherbet_land" }, - { 0x93cc60, 0x9426BC, "rainbow_road" }, - { 0x9438c0, 0x94E28C, "wario_stadium" }, - { 0x951780, 0x953058, "block_fort" }, - { 0x953890, 0x954F08, "skyscraper" }, - { 0x955620, 0x9562F4, "double_deck" }, - { 0x956670, 0x960ACC, "dks_jungle_parkway" }, - { 0x963ef0, 0x965A74, "big_donut" }, + { "mario_raceway", 0x88fa10, 0x899104, + // This works, but is very painful to setup + // We'd probably have to create a master material file + // that all courses would reference, rather than one-per-course + { + { 0x00000, "checkerboard_yellow_pink" }, + { 0x00800, "texture_64619C" }, + { 0x01000, "grass_1" }, + { 0x01800, "texture_64BB60" }, + { 0x02000, "grass_7" }, + { 0x02800, "grass_5" }, + { 0x03000, "flag_red" }, + { 0x03800, "texture_663F90" }, + { 0x04000, "texture_6642A4" }, + { 0x04800, "texture_6640B4" }, + { 0x05000, "grass_10" }, + { 0x05800, "texture_6684F8" }, + { 0x06000, "sign_luigis_0" }, + { 0x07000, "sign_luigis_1" }, + { 0x08000, "sign_mario_star_0" }, + { 0x09000, "sign_mario_star_1" }, + { 0x0A000, "texture_66C8F4" }, + { 0x0A800, "sign_nintendo_red_0" }, + { 0x0B800, "sign_nintendo_red_1" }, + { 0x0C800, "texture_670AC8" }, + { 0x0D800, "texture_674354" }, + { 0x0E000, "road_0" }, + { 0x0F000, "road_finish_0" }, + { 0x10000, "texture_67B9B0" }, + { 0x10800, "sign_yoshi" }, + { 0x11800, "checkerboard_blue_gray" }, + { 0x12800, "sign_shell_shot_0" }, + { 0x13800, "sign_shell_shot_1" }, + { 0x14800, "sign_koopa_air_0" }, + { 0x15800, "sign_koopa_air_1" }, + } + }, + // { 0x89b510, 0x8A55C4, "choco_mountain" }, + // { 0x8a7640, 0x8B59A8, "bowsers_castle" }, + // { 0x8b9630, 0x8BFF18, "banshee_boardwalk" }, + // { 0x8c2510, 0x8CA2A0, "yoshi_valley" }, + // { 0x8cc900, 0x8D6624, "frappe_snowland" }, + // { 0x8d8e50, 0x8E8BC8, "koopa_troopa_beach" }, + // { 0x8ec390, 0x8FAFF0, "royal_raceway" }, + // { 0x8fe640, 0x907E40, "luigi_raceway" }, + // { 0x90b3e0, 0x918ECC, "moo_moo_farm" }, + // { 0x91b980, 0x925F50, "toads_turnpike" }, + // { 0x928c70, 0x934004, "kalimari_desert" }, + // { 0x936fd0, 0x93B9C8, "sherbet_land" }, + // { 0x93cc60, 0x9426BC, "rainbow_road" }, + // { 0x9438c0, 0x94E28C, "wario_stadium" }, + // { 0x951780, 0x953058, "block_fort" }, + // { 0x953890, 0x954F08, "skyscraper" }, + // { 0x955620, 0x9562F4, "double_deck" }, + // { 0x956670, 0x960ACC, "dks_jungle_parkway" }, + // { 0x963ef0, 0x965A74, "big_donut" }, }; typedef struct { short ob[3]; /* x, y, z */ short tc[2]; /* texture coord */ - char n[3]; /* color & alpha */ -} mk64_Vtx_n; + unsigned char ca[4]; /* color & alpha */ +} mk64_Vtx; -std::ifstream & operator >> (std::ifstream &in, mk64_Vtx_n &vtx) { - // This is highly dependent on the `mk64_Vtx_n` type having no padding between its elements +std::istream & operator >> (std::istream &in, mk64_Vtx &vtx) { + // This is highly dependent on the `mk64_Vtx` type having no padding between its elements // And that is the case, but its worth noting that its kind of brittle - in.read(reinterpret_cast(&vtx), sizeof(mk64_Vtx_n)); + in.read(reinterpret_cast(&vtx), sizeof(mk64_Vtx)); return in; } +typedef struct { + float u, v; +} uv; + inline short bswap(short in) { return ((in & 0xFF) << 8) | ((in >> 8) & 0xFF); } @@ -55,11 +99,17 @@ inline short bswap(short in) { // argv[1] -> path to baserom file int main(int argc, char **argv) { int err; - mk64_Vtx_n vtx; - std::stringstream vtx_string; - std::stringstream vtx_tc_string; - std::stringstream vtx_norm_string; - std::stringstream model_string; + int num_tris; + uint8_t opcode, data_byte; + uint16_t data_short; + uint32_t texture_addr; + float texture_height, texture_width, texture_extra_multi; + short vtx_index; + short v1, v2, v3; + int object_num = 0; + int face_group_num = 0; + std::vector vtx_list; + std::map uv_list; std::ofstream vtx_obj; std::ofstream model_inc; std::ifstream model_bytes; @@ -70,6 +120,12 @@ int main(int argc, char **argv) { std::string uncompressed_model = "./temp.model.bin"; for (auto model : all_models) { + // This might be inefficient, but declaring these outside the loop + // will(?) cause their internal buffers to balloon. + std::stringstream vtx_string; + std::stringstream vtx_tc_string; + std::stringstream model_string; + std::stringstream face_string; vtx_obj_path = "./courses/" + model.course_name + "/course.obj"; model_inc_path = "./courses/" + model.course_name + "/course.vtx"; @@ -82,55 +138,36 @@ int main(int argc, char **argv) { // Should probably confirm that the file open actually worked model_bytes.open(uncompressed_model, std::ios::in | std::ios::binary); - while(model_bytes >> vtx) { - // I hate all forms of string manipulation in C/++ - // If we could use gpp 13+ we could use the `fmt` feature to make this cleaner - // I also don't know if the bswap'ing is necessary everywhere or just on my machine - model_string << "{" \ - << "{ " << std::to_string(bswap(vtx.ob[0])) << ", " << std::to_string(bswap(vtx.ob[1])) << ", " << std::to_string(bswap(vtx.ob[2])) << " }, " \ - << "{ " << std::to_string(bswap(vtx.tc[0])) << ", " << std::to_string(bswap(vtx.tc[1])) << " }, " \ - << "{ " << std::to_string(vtx.n[0]) << ", " << std::to_string(vtx.n[1]) << ", " << std::to_string(vtx.n[2]) << " }" \ - << "}," << std::endl; - vtx_string << "v " \ - << std::to_string(bswap(vtx.ob[0])) << " " << std::to_string(bswap(vtx.ob[1])) << " " << std::to_string(bswap(vtx.ob[2])) \ - << std::endl; - // Further processing will be required to get these numbers correct - // vt needs to be converted to a floating point value between 0 and 1 - // I'm not sure how to do that in this case - //vtx_tc_string << "vt " << std::to_string(bswap(vtx.tc[0])) << " " << std::to_string(bswap(vtx.tc[1])) << std::endl; - // Using signed chars to ensure the normals are signed before being divided - char n1 = vtx.n[0] & 0xFC; - char n2 = vtx.n[1] & 0xFC; - char n3 = vtx.n[2]; - vtx_norm_string << "vn " \ - << std::to_string(n1 / 128.0f) << " " \ - << std::to_string(n2 / 128.0f) << " " \ - << std::to_string(n3 / 128.0f) \ - << std::endl; - } + std::copy( + std::istream_iterator(model_bytes), + std::istream_iterator(), + std::back_inserter(vtx_list) + ); model_bytes.close(); - vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::trunc); - vtx_obj << vtx_string.rdbuf() /*<< vtx_tc_string.rdbuf()*/ << vtx_norm_string.rdbuf(); - vtx_obj.close(); + for (auto vtx : vtx_list) { + /** + * I hate all forms of string manipulation in C/++ + * If we could use gpp 13+ we could use the `fmt` feature to make this cleaner + * I also don't know if the bswap'ing is necessary everywhere or just on my machine + **/ + model_string << "{"; + model_string << "{ "; + model_string << std::to_string(bswap(vtx.ob[0])) << ", " << std::to_string(bswap(vtx.ob[1])) << ", " << std::to_string(bswap(vtx.ob[2])); + model_string << " }, "; + model_string << "{ "; + model_string << std::to_string(bswap(vtx.tc[0])) << ", " << std::to_string(bswap(vtx.tc[1])); + model_string << " }, "; + model_string << "{ "; + model_string << std::to_string(vtx.ca[0]) << ", " << std::to_string(vtx.ca[1]) << ", " << std::to_string(vtx.ca[2]) << ", 0x00"; + model_string << " }"; + model_string << "},"; + model_string << std::endl; - model_inc.open(model_inc_path, std::ios::out | std::ios::trunc); - model_inc << model_string.rdbuf(); - model_inc.close(); - - } - - int num_tris; - uint8_t opcode; - uint16_t data_short; - short vtx_index; - short v1, v2, v3; - std::stringstream face_string; - int object_num = 0; - int face_group_num = 0; - - for (auto model : all_models) { - vtx_obj_path = "./courses/" + model.course_name + "/course.obj"; + vtx_string << "v "; + vtx_string << std::to_string(bswap(vtx.ob[0])) << " " << std::to_string(bswap(vtx.ob[1])) << " " << std::to_string(bswap(vtx.ob[2])); + vtx_string << std::endl; + } // Should probably confirm that the file open actually worked model_bytes.open(argv[1], std::ios::in | std::ios::binary); @@ -183,16 +220,40 @@ int main(int argc, char **argv) { v2 += vtx_index; v3 += vtx_index; face_string << "f "; - // v index / vt index / vn index - face_string << std::to_string(v1) << "/" /*<< std::to_string(v1)*/ << "/" << std::to_string(v1) << " "; - face_string << std::to_string(v2) << "/" /*<< std::to_string(v2)*/ << "/" << std::to_string(v2) << " "; - face_string << std::to_string(v3) << "/" /*<< std::to_string(v3)*/ << "/" << std::to_string(v3) << " "; + // v index / vt index / + face_string << std::to_string(v1) << "/" << std::to_string(v1) << "/" << " "; + face_string << std::to_string(v2) << "/" << std::to_string(v2) << "/" << " "; + face_string << std::to_string(v3) << "/" << std::to_string(v3) << "/" << " "; face_string << std::endl; + /** + * Supposedly, the tc values need to be scaled down into the range 0.0 to 1.0 + * However, doing the expected scaling will leave several u/v values well outside that range + * Blender doesn't care however. For some reason. + **/ + uv_list[v1 - 1].u = (bswap(vtx_list[v1 - 1].tc[0] * texture_extra_multi) / 32.0f) / texture_height; + uv_list[v2 - 1].u = (bswap(vtx_list[v2 - 1].tc[0] * texture_extra_multi) / 32.0f) / texture_height; + uv_list[v3 - 1].u = (bswap(vtx_list[v3 - 1].tc[0] * texture_extra_multi) / 32.0f) / texture_height; + uv_list[v1 - 1].v = 1.0 - ((bswap(vtx_list[v1 - 1].tc[1] * texture_extra_multi) / 32.0f) / texture_width); + uv_list[v2 - 1].v = 1.0 - ((bswap(vtx_list[v2 - 1].tc[1] * texture_extra_multi) / 32.0f) / texture_width); + uv_list[v3 - 1].v = 1.0 - ((bswap(vtx_list[v3 - 1].tc[1] * texture_extra_multi) / 32.0f) / texture_width); } + } else if (opcode == 0x2A) { // unpack_end_displaylist, + // Only 1 byte, the opcode + face_string << "o object" << std::to_string(object_num++) << std::endl; + } else if ((opcode == 0x26) || (opcode == 0x27)) { + /** + * 0x26: unpack_texture_on, + * 0x27: unpack_texture_off, + **/ + // Only 1 byte, the opcode + if (opcode == 0x26) { + texture_extra_multi = 0xFFFF / 65536.0f; + } else { + texture_extra_multi = 0x0001 / 65536.0f; + } + std::cout << std::to_string(texture_extra_multi) << std::endl; } else if ( ((0x00 <= opcode) && (opcode <= 0x19)) || - (opcode == 0x26) || (opcode == 0x27) || - (opcode == 0x2A) || ((0x2D <= opcode) && (opcode <= 0x2F)) || ((0x53 <= opcode) && (opcode <= 0x57))) { /** @@ -202,9 +263,6 @@ int main(int argc, char **argv) { * 0x17: unpack_combine_mode_shade, * 0x18: unpack_render_mode_opaque, * 0x19: unpack_render_mode_tex_edge, - * 0x26: unpack_texture_on, - * 0x27: unpack_texture_off, - * 0x2A: unpack_end_displaylist, * 0x2D: unpack_cull_displaylist, * 0x2E: unpack_combine_mode4, * 0x2F: unpack_render_mode_translucent, @@ -215,9 +273,7 @@ int main(int argc, char **argv) { * 0x57: unpack_clear_geometry_mode, **/ // Only 1 byte, the opcode - if (opcode == 0x2A) { - face_string << "o object" << std::to_string(object_num++) << std::endl; - } + ; } else if ( ((0x1A <= opcode) && (opcode <= 0x1F)) || (opcode == 0x2B) || (opcode == 0x2C)) { @@ -227,13 +283,40 @@ int main(int argc, char **argv) { **/ // 3 bytes including the opcode model_bytes.seekg(2, std::ios_base::cur); - } else if ( - ((0x20 <= opcode) && (opcode <= 0x25)) || - (opcode == 0x30)) { - /** - * 0x20 - 0x25: unpack_tile_load_sync, - * 0x30: unpack_spline_3D, - **/ + } else if ((0x20 <= opcode) && (opcode <= 0x25)) { // unpack_tile_load_sync, + // 4 bytes including the opcode + switch (opcode) { + case 0x20: + texture_height = 32.0f; + texture_width = 32.0f; + break; + case 0x21: + texture_height = 64.0f; + texture_width = 32.0f; + break; + case 0x22: + texture_height = 32.0f; + texture_width = 64.0f; + break; + case 0x23: + texture_height = 32.0f; + texture_width = 32.0f; + break; + case 0x24: + texture_height = 64.0f; + texture_width = 32.0f; + break; + case 0x25: + texture_height = 32.0f; + texture_width = 64.0f; + break; + } + model_bytes.read(reinterpret_cast(&data_byte), 1); + texture_addr = data_byte; + texture_addr <<= 11; + face_string << "usemtl " << model.textures[texture_addr] << std::endl; + model_bytes.seekg(2, std::ios_base::cur); + } else if (opcode == 0x30) { // unpack_spline_3D // 4 bytes including the opcode model_bytes.seekg(3, std::ios_base::cur); } else { @@ -243,9 +326,17 @@ int main(int argc, char **argv) { } model_bytes.close(); - vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::app); - vtx_obj << face_string.rdbuf(); + for (auto tc : uv_list) { + vtx_tc_string << "vt " << std::to_string(tc.second.u) << " " << std::to_string(tc.second.v) << std::endl; + } + + vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::trunc); + vtx_obj << vtx_string.rdbuf() << vtx_tc_string.rdbuf() << face_string.rdbuf(); vtx_obj.close(); + + model_inc.open(model_inc_path, std::ios::out | std::ios::trunc); + model_inc << model_string.rdbuf(); + model_inc.close(); } return 0; } From 8a77ec08715ccd3a1565d75b2ecace3bafa3f455 Mon Sep 17 00:00:00 2001 From: Taggerung Date: Sat, 30 Sep 2023 14:09:04 -0400 Subject: [PATCH 5/8] Over engineered a solution to a problem that doesn't exist Signed-off-by: Taggerung --- tools/vtx_extract.cpp | 201 +++++++++++++++++++++++++++--------------- 1 file changed, 131 insertions(+), 70 deletions(-) diff --git a/tools/vtx_extract.cpp b/tools/vtx_extract.cpp index 06ca3aa6e..fb306c64b 100644 --- a/tools/vtx_extract.cpp +++ b/tools/vtx_extract.cpp @@ -3,21 +3,35 @@ #include #include #include +#include #include #include #include #include "libmio0.h" -typedef struct { +struct mk64_Vtx{ + short ob[3]; /* x, y, z */ + short tc[2]; /* texture coord */ + unsigned char ca[4]; /* color & alpha */ +}; + +std::istream & operator >> (std::istream &in, mk64_Vtx &vtx) { + // This is highly dependent on the `mk64_Vtx` type having no padding between its elements + // And that is the case, but its worth noting that its kind of brittle + in.read(reinterpret_cast(&vtx), sizeof(mk64_Vtx)); + return in; +} + +struct model_location{ std::string course_name; uint32_t model_rom_offset; uint32_t packed_dl_rom_offset; std::map textures; -} model_location; +}; std::vector all_models = { - { "mario_raceway", 0x88fa10, 0x899104, + { "mario_raceway", 0x88fa10, 0x899104, // This works, but is very painful to setup // We'd probably have to create a master material file // that all courses would reference, rather than one-per-course @@ -54,43 +68,68 @@ std::vector all_models = { { 0x15800, "sign_koopa_air_1" }, } }, - // { 0x89b510, 0x8A55C4, "choco_mountain" }, - // { 0x8a7640, 0x8B59A8, "bowsers_castle" }, - // { 0x8b9630, 0x8BFF18, "banshee_boardwalk" }, - // { 0x8c2510, 0x8CA2A0, "yoshi_valley" }, - // { 0x8cc900, 0x8D6624, "frappe_snowland" }, - // { 0x8d8e50, 0x8E8BC8, "koopa_troopa_beach" }, - // { 0x8ec390, 0x8FAFF0, "royal_raceway" }, - // { 0x8fe640, 0x907E40, "luigi_raceway" }, - // { 0x90b3e0, 0x918ECC, "moo_moo_farm" }, - // { 0x91b980, 0x925F50, "toads_turnpike" }, - // { 0x928c70, 0x934004, "kalimari_desert" }, - // { 0x936fd0, 0x93B9C8, "sherbet_land" }, - // { 0x93cc60, 0x9426BC, "rainbow_road" }, - // { 0x9438c0, 0x94E28C, "wario_stadium" }, - // { 0x951780, 0x953058, "block_fort" }, - // { 0x953890, 0x954F08, "skyscraper" }, - // { 0x955620, 0x9562F4, "double_deck" }, + // { "choco_mountain", 0x89b510, 0x8A55C4, }, + // { "bowsers_castle", 0x8a7640, 0x8B59A8, }, + // { "banshee_boardwalk", 0x8b9630, 0x8BFF18, }, + // { "yoshi_valley", 0x8c2510, 0x8CA2A0, }, + // { "frappe_snowland", 0x8cc900, 0x8D6624, }, + // { "koopa_troopa_beach", 0x8d8e50, 0x8E8BC8, }, + // { "royal_raceway", 0x8ec390, 0x8FAFF0, }, + // { "luigi_raceway", 0x8fe640, 0x907E40, }, + // { "moo_moo_farm", 0x90b3e0, 0x918ECC, }, + // { "toads_turnpike", 0x91b980, 0x925F50, }, + // { "kalimari_desert", 0x928c70, 0x934004, }, + // { "sherbet_land", 0x936fd0, 0x93B9C8, }, + // { "rainbow_road", 0x93cc60, 0x9426BC, }, + // { "wario_stadium", 0x9438c0, 0x94E28C, }, + // { "block_fort", 0x951780, 0x953058, }, + // { "skyscraper", 0x953890, 0x954F08, }, + { "double_deck", 0x955620, 0x9562F4, + { + { 0x00000, "gray_cobblestone" }, + { 0x00800, "texture_642978" }, + } + }, // { 0x956670, 0x960ACC, "dks_jungle_parkway" }, // { 0x963ef0, 0x965A74, "big_donut" }, }; -typedef struct { - short ob[3]; /* x, y, z */ - short tc[2]; /* texture coord */ - unsigned char ca[4]; /* color & alpha */ -} mk64_Vtx; - -std::istream & operator >> (std::istream &in, mk64_Vtx &vtx) { - // This is highly dependent on the `mk64_Vtx` type having no padding between its elements - // And that is the case, but its worth noting that its kind of brittle - in.read(reinterpret_cast(&vtx), sizeof(mk64_Vtx)); - return in; -} - -typedef struct { +struct uv{ float u, v; -} uv; +} ; + +struct node{ + uint32_t address = 0; + std::shared_ptr parent = nullptr; + std::vector> children; + // There's no byte stream, so a stringstream will + // have to do instead + std::stringstream face_string; +}; + +// Emit leaf nodes in tree in DFS order +void parse_tree(std::shared_ptr root, std::stringstream &face_string) { + // Doing this silly check as a way to differentiate + // leaf nodes from traversal nodes. + if (!root->children.empty()) { + /* + Children "top to bottom" in dl file + */ + face_string << "o object" << std::to_string(root->address) << std::endl; + for (auto child : root->children) { + parse_tree(child, face_string); + } + /* + Children "bottom to top" in dl file + for (auto child = std::rbegin(root->children); child != std::rend(root->children); child++) { + parse_tree(*child, face_string); + } + */ + } else { + // face_string << "o object" << std::to_string(root->address) << std::endl; + face_string << root->face_string.str(); + } +} inline short bswap(short in) { return ((in & 0xFF) << 8) | ((in >> 8) & 0xFF); @@ -102,14 +141,12 @@ int main(int argc, char **argv) { int num_tris; uint8_t opcode, data_byte; uint16_t data_short; - uint32_t texture_addr; + uint32_t dl_count, texture_addr; float texture_height, texture_width, texture_extra_multi; short vtx_index; short v1, v2, v3; int object_num = 0; int face_group_num = 0; - std::vector vtx_list; - std::map uv_list; std::ofstream vtx_obj; std::ofstream model_inc; std::ifstream model_bytes; @@ -126,6 +163,10 @@ int main(int argc, char **argv) { std::stringstream vtx_tc_string; std::stringstream model_string; std::stringstream face_string; + std::map uv_list; + std::map> node_map; + std::vector vtx_list; + std::shared_ptr anode; vtx_obj_path = "./courses/" + model.course_name + "/course.obj"; model_inc_path = "./courses/" + model.course_name + "/course.vtx"; @@ -172,7 +213,9 @@ int main(int argc, char **argv) { // Should probably confirm that the file open actually worked model_bytes.open(argv[1], std::ios::in | std::ios::binary); model_bytes.seekg(model.packed_dl_rom_offset); - face_string << "o object" << std::to_string(object_num++) << std::endl; + + dl_count = 0; + anode = std::make_shared(); while(model_bytes.read(reinterpret_cast(&opcode), 1)) { if (opcode == 0xFF) { break; @@ -186,11 +229,13 @@ int main(int argc, char **argv) { **/ if ((0x33 <= opcode) && (opcode <= 0x52)) { // unpack_vtx2, gsSPVertex // 3 bytes including opcode + dl_count += 1; model_bytes.read(reinterpret_cast(&data_short), 2); vtx_index = data_short + 1; - face_string << "g face_group" << std::to_string(face_group_num++) << std::endl; + anode->face_string << "g face_group" << std::to_string(face_group_num++) << std::endl; } else if (opcode == 0x28) { // unpack_vtx1, gsSPVertex // 5 bytes including the opcode + dl_count += 1; model_bytes.read(reinterpret_cast(&data_short), 2); vtx_index = data_short + 1; // Only need the vertex "address", skip the other 2 bytes @@ -202,6 +247,7 @@ int main(int argc, char **argv) { * 0x58: unpack_quadrangle, gsSP2Triangles * 5 bytes including opcode **/ + dl_count += 1; if (opcode == 0x29) { num_tris = 1; } else { @@ -219,39 +265,38 @@ int main(int argc, char **argv) { v1 += vtx_index; v2 += vtx_index; v3 += vtx_index; - face_string << "f "; - // v index / vt index / - face_string << std::to_string(v1) << "/" << std::to_string(v1) << "/" << " "; - face_string << std::to_string(v2) << "/" << std::to_string(v2) << "/" << " "; - face_string << std::to_string(v3) << "/" << std::to_string(v3) << "/" << " "; - face_string << std::endl; + anode->face_string << "f "; + // v index / vt index / + anode->face_string << std::to_string(v1) << "/" << std::to_string(v1) << "/" << " "; + anode->face_string << std::to_string(v2) << "/" << std::to_string(v2) << "/" << " "; + anode->face_string << std::to_string(v3) << "/" << std::to_string(v3) << "/" << " "; + anode->face_string << std::endl; /** * Supposedly, the tc values need to be scaled down into the range 0.0 to 1.0 * However, doing the expected scaling will leave several u/v values well outside that range * Blender doesn't care however. For some reason. **/ - uv_list[v1 - 1].u = (bswap(vtx_list[v1 - 1].tc[0] * texture_extra_multi) / 32.0f) / texture_height; - uv_list[v2 - 1].u = (bswap(vtx_list[v2 - 1].tc[0] * texture_extra_multi) / 32.0f) / texture_height; - uv_list[v3 - 1].u = (bswap(vtx_list[v3 - 1].tc[0] * texture_extra_multi) / 32.0f) / texture_height; - uv_list[v1 - 1].v = 1.0 - ((bswap(vtx_list[v1 - 1].tc[1] * texture_extra_multi) / 32.0f) / texture_width); - uv_list[v2 - 1].v = 1.0 - ((bswap(vtx_list[v2 - 1].tc[1] * texture_extra_multi) / 32.0f) / texture_width); - uv_list[v3 - 1].v = 1.0 - ((bswap(vtx_list[v3 - 1].tc[1] * texture_extra_multi) / 32.0f) / texture_width); + uv_list[v1 - 1].u = ((bswap(vtx_list[v1 - 1].tc[0]) * texture_extra_multi) / 32.0f) / texture_height; + uv_list[v2 - 1].u = ((bswap(vtx_list[v2 - 1].tc[0]) * texture_extra_multi) / 32.0f) / texture_height; + uv_list[v3 - 1].u = ((bswap(vtx_list[v3 - 1].tc[0]) * texture_extra_multi) / 32.0f) / texture_height; + uv_list[v1 - 1].v = 1.0 - (((bswap(vtx_list[v1 - 1].tc[1]) * texture_extra_multi) / 32.0f) / texture_width); + uv_list[v2 - 1].v = 1.0 - (((bswap(vtx_list[v2 - 1].tc[1]) * texture_extra_multi) / 32.0f) / texture_width); + uv_list[v3 - 1].v = 1.0 - (((bswap(vtx_list[v3 - 1].tc[1]) * texture_extra_multi) / 32.0f) / texture_width); } } else if (opcode == 0x2A) { // unpack_end_displaylist, // Only 1 byte, the opcode - face_string << "o object" << std::to_string(object_num++) << std::endl; - } else if ((opcode == 0x26) || (opcode == 0x27)) { - /** - * 0x26: unpack_texture_on, - * 0x27: unpack_texture_off, - **/ + dl_count += 1; + node_map[anode->address] = std::move(anode); + anode = std::make_shared(); + anode->address = dl_count * 8; + } else if (opcode == 0x26) { // unpack_texture_on, // Only 1 byte, the opcode - if (opcode == 0x26) { - texture_extra_multi = 0xFFFF / 65536.0f; - } else { - texture_extra_multi = 0x0001 / 65536.0f; - } - std::cout << std::to_string(texture_extra_multi) << std::endl; + dl_count += 1; + texture_extra_multi = 1.0f; + } else if(opcode == 0x27) { // unpack_texture_off, + // Only 1 byte, the opcode + dl_count += 1; + texture_extra_multi = 0.0f; } else if ( ((0x00 <= opcode) && (opcode <= 0x19)) || ((0x2D <= opcode) && (opcode <= 0x2F)) || @@ -273,18 +318,27 @@ int main(int argc, char **argv) { * 0x57: unpack_clear_geometry_mode, **/ // Only 1 byte, the opcode - ; - } else if ( - ((0x1A <= opcode) && (opcode <= 0x1F)) || - (opcode == 0x2B) || (opcode == 0x2C)) { + if ((0x00 <= opcode) && (opcode <= 0x14)) { + dl_count += 3; + } else { + dl_count += 1; + } + } else if (opcode == 0x2B) { // unpack_displaylist, + // 3 bytes including the opcode + dl_count += 1; + model_bytes.read(reinterpret_cast(&data_short), 2); + node_map[data_short * 8]->parent = anode; + anode->children.push_back(node_map[data_short * 8]); + } else if (((0x1A <= opcode) && (opcode <= 0x1F)) || (opcode == 0x2C)) { /** * 0x1A - 0x1F, 0x2C: unpack_tile_sync, - * 0x2B: unpack_displaylist, **/ // 3 bytes including the opcode + dl_count += 3; model_bytes.seekg(2, std::ios_base::cur); } else if ((0x20 <= opcode) && (opcode <= 0x25)) { // unpack_tile_load_sync, // 4 bytes including the opcode + dl_count += 5; switch (opcode) { case 0x20: texture_height = 32.0f; @@ -314,10 +368,11 @@ int main(int argc, char **argv) { model_bytes.read(reinterpret_cast(&data_byte), 1); texture_addr = data_byte; texture_addr <<= 11; - face_string << "usemtl " << model.textures[texture_addr] << std::endl; + anode->face_string << "usemtl " << model.textures[texture_addr] << std::endl; model_bytes.seekg(2, std::ios_base::cur); } else if (opcode == 0x30) { // unpack_spline_3D // 4 bytes including the opcode + dl_count += 1; model_bytes.seekg(3, std::ios_base::cur); } else { std::cout << "WARNING UNEXPECTED opcode: " << std::to_string(opcode) << std::endl; @@ -326,6 +381,12 @@ int main(int argc, char **argv) { } model_bytes.close(); + for (auto bnode : node_map) { + if (bnode.second->parent == nullptr) { + parse_tree(bnode.second, face_string); + } + } + for (auto tc : uv_list) { vtx_tc_string << "vt " << std::to_string(tc.second.u) << " " << std::to_string(tc.second.v) << std::endl; } From a8c37b72439c5958d2c467755e95d29dc724b36c Mon Sep 17 00:00:00 2001 From: Taggerung Date: Sun, 1 Oct 2023 21:45:10 -0400 Subject: [PATCH 6/8] Complete the texture lists for every course Also made the master material file for all course. The paths in that file are relative so if it or the target png's move there will have to be a lot of other changes made Signed-off-by: Taggerung --- courses/master_course.mtl | 2759 +++++++++++++++++++++++++++++++++++++ tools/vtx_extract.cpp | 533 ++++++- 2 files changed, 3227 insertions(+), 65 deletions(-) create mode 100644 courses/master_course.mtl diff --git a/courses/master_course.mtl b/courses/master_course.mtl new file mode 100644 index 000000000..4087909b8 --- /dev/null +++ b/courses/master_course.mtl @@ -0,0 +1,2759 @@ +newmtl star_outline +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/star_outline.ia16.png + +newmtl texture_67A1B8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67A1B8.rgba16.png + +newmtl checkerboard_black_white +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/checkerboard_black_white.rgba16.png + +newmtl texture_662A34 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_662A34.rgba16.png + +newmtl rainbow +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/rainbow.rgba16.png + +newmtl texture_66ABA4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66ABA4.rgba16.png + +newmtl texture_67490C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67490C.rgba16.png + +newmtl texture_64BA50 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64BA50.rgba16.png + +newmtl texture_64286C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64286C.rgba16.png + +newmtl gray_checkerboard +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/gray_checkerboard.rgba16.png + +newmtl texture_64275C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64275C.rgba16.png + +newmtl texture_6747C4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6747C4.rgba16.png + +newmtl texture_6442D4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6442D4.rgba16.png + +newmtl gray_cobblestone +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/gray_cobblestone.rgba16.png + +newmtl texture_642978 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_642978.rgba16.png + +newmtl checkerboard_yellow_pink +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/checkerboard_yellow_pink.rgba16.png + +newmtl texture_64619C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64619C.rgba16.png + +newmtl grass_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_1.rgba16.png + +newmtl texture_64BB60 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64BB60.rgba16.png + +newmtl grass_7 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_7.rgba16.png + +newmtl grass_5 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_5.rgba16.png + +newmtl flag_red +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/flag_red.rgba16.png + +newmtl texture_663F90 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_663F90.rgba16.png + +newmtl texture_6642A4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6642A4.rgba16.png + +newmtl texture_6640B4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6640B4.rgba16.png + +newmtl grass_10 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_10.rgba16.png + +newmtl texture_6684F8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6684F8.rgba16.png + +newmtl sign_luigis_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_luigis_0.rgba16.png + +newmtl sign_luigis_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_luigis_1.rgba16.png + +newmtl sign_mario_star_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_mario_star_0.rgba16.png + +newmtl sign_mario_star_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_mario_star_1.rgba16.png + +newmtl texture_66C8F4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66C8F4.rgba16.png + +newmtl sign_nintendo_red_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_nintendo_red_0.rgba16.png + +newmtl sign_nintendo_red_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_nintendo_red_1.rgba16.png + +newmtl texture_670AC8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_670AC8.rgba16.png + +newmtl texture_674354 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_674354.rgba16.png + +newmtl road_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/road_0.rgba16.png + +newmtl road_finish_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/road_finish_0.rgba16.png + +newmtl texture_67B9B0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67B9B0.rgba16.png + +newmtl sign_yoshi +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_yoshi.rgba16.png + +newmtl checkerboard_blue_gray +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/checkerboard_blue_gray.rgba16.png + +newmtl sign_shell_shot_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_shell_shot_0.rgba16.png + +newmtl sign_shell_shot_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_shell_shot_1.rgba16.png + +newmtl sign_koopa_air_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_koopa_air_0.rgba16.png + +newmtl sign_koopa_air_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_koopa_air_1.rgba16.png + +newmtl texture_66CA98 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66CA98.rgba16.png + +newmtl texture_66EBF0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66EBF0.rgba16.png + +newmtl texture_675434 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_675434.rgba16.png + +newmtl texture_677F04 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_677F04.rgba16.png + +newmtl texture_678118 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_678118.rgba16.png + +newmtl texture_679258 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_679258.rgba16.png + +newmtl texture_67973C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67973C.rgba16.png + +newmtl texture_643B3C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_643B3C.rgba16.png + +newmtl texture_66A3DC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66A3DC.rgba16.png + +newmtl sign_wood_red_arrow +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_wood_red_arrow.rgba16.png + +newmtl texture_66DD38 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66DD38.rgba16.png + +newmtl texture_643430 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_643430.rgba16.png + +newmtl texture_660D8C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_660D8C.rgba16.png + +newmtl texture_6609D0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6609D0.rgba16.png + +newmtl grass_12 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_12.rgba16.png + +newmtl texture_67BEE8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67BEE8.rgba16.png + +newmtl sand_finish +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sand_finish.rgba16.png + +newmtl wheel_steam_engine +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/wheel_steam_engine.rgba16.png + +newmtl texture_669570 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_669570.rgba16.png + +newmtl waves_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/waves_1.rgba16.png + +newmtl waves_2 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/waves_2.rgba16.png + +newmtl texture_66D024 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66D024.rgba16.png + +newmtl texture_678CC8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_678CC8.rgba16.png + +newmtl texture_67842C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67842C.rgba16.png + +newmtl texture_67893C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67893C.rgba16.png + +newmtl texture_651984 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_651984.rgba16.png + +newmtl texture_651428 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_651428.rgba16.png + +newmtl texture_662924 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_662924.rgba16.png + +newmtl wood_bridge_slats +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/wood_bridge_slats.rgba16.png + +newmtl texture_65E2EC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65E2EC.rgba16.png + +newmtl texture_6846DC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6846DC.rgba16.png + +newmtl fence_rope +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/fence_rope.rgba16.png + +newmtl texture_685108 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_685108.rgba16.png + +newmtl texture_64CC20 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64CC20.rgba16.png + +newmtl texture_67F15C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67F15C.rgba16.png + +newmtl texture_67F450 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67F450.rgba16.png + +newmtl sign_wario_face +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_wario_face.rgba16.png + +newmtl texture_64C11C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64C11C.rgba16.png + +newmtl texture_64C7B4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64C7B4.rgba16.png + +newmtl texture_668228 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_668228.rgba16.png + +newmtl texture_668358 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_668358.rgba16.png + +newmtl texture_66AEB8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66AEB8.ia16.png + +newmtl texture_677A40 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_677A40.rgba16.png + +newmtl texture_67E428 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67E428.rgba16.png + +newmtl texture_643A34 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_643A34.rgba16.png + +newmtl texture_68272C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68272C.rgba16.png + +newmtl texture_682928 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_682928.rgba16.png + +newmtl texture_682B24 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_682B24.rgba16.png + +newmtl texture_682D20 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_682D20.rgba16.png + +newmtl texture_682F1C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_682F1C.rgba16.png + +newmtl texture_683118 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_683118.rgba16.png + +newmtl texture_64647C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64647C.rgba16.png + +newmtl texture_647F4C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_647F4C.rgba16.png + +newmtl texture_64FBF4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64FBF4.rgba16.png + +newmtl texture_653DB0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_653DB0.rgba16.png + +newmtl texture_652B54 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_652B54.rgba16.png + +newmtl texture_65315C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65315C.rgba16.png + +newmtl texture_6774D8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6774D8.rgba16.png + +newmtl sign_falling_rocks +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_falling_rocks.rgba16.png + +newmtl sign_backside +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_backside.rgba16.png + +newmtl texture_679C04 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_679C04.rgba16.png + +newmtl texture_67B864 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67B864.rgba16.png + +newmtl texture_67DC20 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67DC20.rgba16.png + +newmtl texture_64313C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64313C.rgba16.png + +newmtl texture_6528DC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6528DC.rgba16.png + +newmtl texture_66ED38 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66ED38.rgba16.png + +newmtl texture_676C6C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_676C6C.rgba16.png + +newmtl texture_676EA8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_676EA8.rgba16.png + +newmtl texture_679D34 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_679D34.rgba16.png + +newmtl grass_6 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_6.rgba16.png + +newmtl texture_6522E0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6522E0.rgba16.png + +newmtl texture_651F40 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_651F40.rgba16.png + +newmtl roof_tile +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/roof_tile.rgba16.png + +newmtl sign_bowser_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_bowser_0.rgba16.png + +newmtl sign_bowser_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_bowser_1.rgba16.png + +newmtl texture_6733CC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6733CC.rgba16.png + +newmtl texture_673118 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_673118.rgba16.png + +newmtl texture_673FF8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_673FF8.rgba16.png + +newmtl texture_674B28 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_674B28.rgba16.png + +newmtl sign_green_arrow +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_green_arrow.rgba16.png + +newmtl texture_68D834 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68D834.rgba16.png + +newmtl texture_676D7C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_676D7C.rgba16.png + +newmtl texture_67ADF0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67ADF0.rgba16.png + +newmtl texture_67EFEC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67EFEC.rgba16.png + +newmtl texture_673990 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_673990.rgba16.png + +newmtl texture_67A370 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67A370.rgba16.png + +newmtl texture_67A91C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67A91C.rgba16.png + +newmtl texture_648508 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_648508.rgba16.png + +newmtl texture_654460 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_654460.rgba16.png + +newmtl texture_654F74 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_654F74.rgba16.png + +newmtl texture_655998 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_655998.rgba16.png + +newmtl texture_655F38 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_655F38.rgba16.png + +newmtl texture_656AF4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_656AF4.rgba16.png + +newmtl texture_6575C8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6575C8.rgba16.png + +newmtl texture_658370 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_658370.rgba16.png + +newmtl texture_65912C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65912C.rgba16.png + +newmtl texture_659EE8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_659EE8.rgba16.png + +newmtl texture_65ADE0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65ADE0.rgba16.png + +newmtl texture_65BB3C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65BB3C.rgba16.png + +newmtl texture_65C8DC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65C8DC.rgba16.png + +newmtl texture_65D5D4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65D5D4.rgba16.png + +newmtl texture_65EAEC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65EAEC.rgba16.png + +newmtl texture_65E59C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65E59C.rgba16.png + +newmtl texture_65EE38 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65EE38.rgba16.png + +newmtl texture_65FB18 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65FB18.rgba16.png + +newmtl sign_pink_arrow +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_pink_arrow.rgba16.png + +newmtl waves_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/waves_0.ia16.png + +newmtl texture_683844 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_683844.rgba16.png + +newmtl texture_6457D8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6457D8.rgba16.png + +newmtl texture_6462C0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6462C0.rgba16.png + +newmtl texture_6864E8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6864E8.rgba16.png + +newmtl texture_686CF0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_686CF0.rgba16.png + +newmtl texture_6875A8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6875A8.rgba16.png + +newmtl texture_687EE8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_687EE8.rgba16.png + +newmtl texture_68876C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68876C.rgba16.png + +newmtl texture_689230 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_689230.rgba16.png + +newmtl texture_689C00 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_689C00.rgba16.png + +newmtl texture_68A484 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68A484.rgba16.png + +newmtl texture_68AC5C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68AC5C.rgba16.png + +newmtl texture_68B6A4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68B6A4.rgba16.png + +newmtl texture_68BE6C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68BE6C.rgba16.png + +newmtl texture_68C310 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68C310.rgba16.png + +newmtl texture_64B8D8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64B8D8.rgba16.png + +newmtl texture_645660 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_645660.rgba16.png + +newmtl number_yellow_blue_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/number_yellow_blue_1.rgba16.png + +newmtl number_yellow_blue_2 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/number_yellow_blue_2.rgba16.png + +newmtl number_yellow_blue_3 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/number_yellow_blue_3.rgba16.png + +newmtl number_yellow_blue_4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/number_yellow_blue_4.rgba16.png + +newmtl texture_668608 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_668608.rgba16.png + +newmtl texture_67B75C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67B75C.rgba16.png + +newmtl texture_6835F0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6835F0.rgba16.png + +newmtl texture_646CA8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_646CA8.rgba16.png + +newmtl texture_6473E4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6473E4.rgba16.png + +newmtl texture_647994 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_647994.rgba16.png + +newmtl texture_668920 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_668920.rgba16.png + +newmtl railroad_track +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/railroad_track.rgba16.png + +newmtl railroad_crossing_track +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/railroad_crossing_track.rgba16.png + +newmtl texture_67291C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67291C.rgba16.png + +newmtl fence_barbed_wire +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/fence_barbed_wire.rgba16.png + +newmtl texture_67D304 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67D304.rgba16.png + +newmtl texture_67E010 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67E010.rgba16.png + +newmtl texture_67EEAC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67EEAC.rgba16.png + +newmtl texture_645134 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_645134.rgba16.png + +newmtl texture_64FE68 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64FE68.rgba16.png + +newmtl texture_6607C0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6607C0.rgba16.png + +newmtl texture_6608C8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6608C8.rgba16.png + +newmtl grass_11 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_11.rgba16.png + +newmtl texture_671A88 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_671A88.rgba16.png + +newmtl road_2 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/road_2.rgba16.png + +newmtl road_3 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/road_3.rgba16.png + +newmtl road_4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/road_4.rgba16.png + +newmtl sign_toad_yellow +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_toad_yellow.rgba16.png + +newmtl sign_toad_green +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_toad_green.rgba16.png + +newmtl sign_merging_lanes +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_merging_lanes.rgba16.png + +newmtl texture_65127C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65127C.rgba16.png + +newmtl road_5 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/road_5.rgba16.png + +newmtl sign_toad_red +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_toad_red.rgba16.png + +newmtl texture_6447C4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6447C4.rgba16.png + +newmtl texture_676FB0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_676FB0.rgba16.png + +newmtl texture_64BB60 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64BB60.rgba16.png + +newmtl texture_64BCCC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64BCCC.rgba16.png + +newmtl texture_651B20 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_651B20.rgba16.png + +newmtl texture_66262C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66262C.rgba16.png + +newmtl texture_668728 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_668728.rgba16.png + +newmtl texture_66CD64 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66CD64.rgba16.png + +newmtl texture_66D698 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66D698.rgba16.png + +newmtl texture_66E608 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66E608.rgba16.png + +newmtl texture_67B388 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67B388.rgba16.png + +newmtl sign_welcome_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_welcome_0.rgba16.png + +newmtl sign_welcome_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_welcome_1.rgba16.png + +newmtl sign_wooden_back_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_wooden_back_0.rgba16.png + +newmtl sign_wooden_back_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_wooden_back_1.rgba16.png + +newmtl texture_68D940 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68D940.rgba16.png + +newmtl texture_685AC0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_685AC0.ia16.png + +newmtl wood_door_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/wood_door_0.rgba16.png + +newmtl grass_2 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_2.rgba16.png + +newmtl texture_64AF50 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64AF50.rgba16.png + +newmtl texture_64B090 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64B090.rgba16.png + +newmtl texture_64B54C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64B54C.rgba16.png + +newmtl texture_64B3F8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64B3F8.rgba16.png + +newmtl texture_674D58 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_674D58.rgba16.png + +newmtl texture_675064 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_675064.rgba16.png + +newmtl texture_675220 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_675220.rgba16.png + +newmtl texture_683314 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_683314.rgba16.png + +newmtl texture_68CDA0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_68CDA0.rgba16.png + +newmtl texture_6442D4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6442D4.rgba16.png + +newmtl texture_64440C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64440C.rgba16.png + +newmtl texture_6446AC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6446AC.rgba16.png + +newmtl gTextureMooMooFarmSignLeft +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../assets/courses/moo_moo_farm/gTextureMooMooFarmSignLeft.png + +newmtl gTextureMooMooFarmSignRight +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../assets/courses/moo_moo_farm/gTextureMooMooFarmSignRight.png + +newmtl texture_64ACAC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64ACAC.rgba16.png + +newmtl wheel_steam_engine_real +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/wheel_steam_engine_real.rgba16.png + +newmtl checkerbord_yellow_blue +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/checkerbord_yellow_blue.rgba16.png + +newmtl checkerboard_blue_green +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/checkerboard_blue_green.rgba16.png + +newmtl grass_3 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_3.rgba16.png + +newmtl texture_65100C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65100C.rgba16.png + +newmtl texture_65112C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_65112C.rgba16.png + +newmtl texture_653608 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_653608.rgba16.png + +newmtl sign_luigi_face_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_luigi_face_0.rgba16.png + +newmtl sign_luigi_face_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_luigi_face_1.rgba16.png + +newmtl texture_66C7A8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66C7A8.rgba16.png + +newmtl texture_6735DC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6735DC.rgba16.png + +newmtl texture_673C68 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_673C68.rgba16.png + +newmtl road_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/road_1.rgba16.png + +newmtl road_finish_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/road_finish_1.rgba16.png + +newmtl texture_67BBD8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67BBD8.rgba16.png + +newmtl sign_blue_64 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/sign_blue_64.rgba16.png + +newmtl wood_door_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/wood_door_1.rgba16.png + +newmtl texture_64F9E8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_64F9E8.rgba16.png + +newmtl crown_jewel_blue +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/crown_jewel_blue.rgba16.png + +newmtl crown +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/crown.rgba16.png + +newmtl crown_jewel_pink +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/crown_jewel_pink.rgba16.png + +newmtl checkerboard_pink +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/checkerboard_pink.rgba16.png + +newmtl castle_bricks +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/castle_bricks.rgba16.png + +newmtl castle_bridge +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/castle_bridge.rgba16.png + +newmtl grass_8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_8.rgba16.png + +newmtl grass_9 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/grass_9.rgba16.png + +newmtl texture_6646B8 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6646B8.rgba16.png + +newmtl texture_664408 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_664408.rgba16.png + +newmtl bricks_red +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/bricks_red.rgba16.png + +newmtl texture_665C0C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_665C0C.rgba16.png + +newmtl texture_6661AC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6661AC.rgba16.png + +newmtl texture_6663A4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6663A4.rgba16.png + +newmtl texture_667BAC +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_667BAC.rgba16.png + +newmtl flag_red_2 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/flag_red_2.rgba16.png + +newmtl texture_66DB60 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_66DB60.rgba16.png + +newmtl stainglass_peach_0 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/stainglass_peach_0.rgba16.png + +newmtl stainglass_peach_1 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/stainglass_peach_1.rgba16.png + +newmtl fence_post_wooden +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/fence_post_wooden.rgba16.png + +newmtl texture_6449D4 +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_6449D4.rgba16.png + +newmtl texture_67FE0C +Ka 1.000000 1.000000 1.000000 +Kd 1.000000 1.000000 1.000000 +Ks 0.000000 0.000000 0.000000 +Ns 1000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd ../textures/standalone/texture_67FE0C.rgba16.png diff --git a/tools/vtx_extract.cpp b/tools/vtx_extract.cpp index fb306c64b..58531e847 100644 --- a/tools/vtx_extract.cpp +++ b/tools/vtx_extract.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -31,67 +32,474 @@ struct model_location{ }; std::vector all_models = { - { "mario_raceway", 0x88fa10, 0x899104, - // This works, but is very painful to setup - // We'd probably have to create a master material file - // that all courses would reference, rather than one-per-course + { "mario_raceway", 0x88fa10, 0x899104, { { 0x00000, "checkerboard_yellow_pink" }, - { 0x00800, "texture_64619C" }, - { 0x01000, "grass_1" }, - { 0x01800, "texture_64BB60" }, - { 0x02000, "grass_7" }, - { 0x02800, "grass_5" }, - { 0x03000, "flag_red" }, - { 0x03800, "texture_663F90" }, - { 0x04000, "texture_6642A4" }, - { 0x04800, "texture_6640B4" }, - { 0x05000, "grass_10" }, - { 0x05800, "texture_6684F8" }, - { 0x06000, "sign_luigis_0" }, - { 0x07000, "sign_luigis_1" }, - { 0x08000, "sign_mario_star_0" }, - { 0x09000, "sign_mario_star_1" }, - { 0x0A000, "texture_66C8F4" }, - { 0x0A800, "sign_nintendo_red_0" }, - { 0x0B800, "sign_nintendo_red_1" }, - { 0x0C800, "texture_670AC8" }, - { 0x0D800, "texture_674354" }, - { 0x0E000, "road_0" }, - { 0x0F000, "road_finish_0" }, - { 0x10000, "texture_67B9B0" }, - { 0x10800, "sign_yoshi" }, - { 0x11800, "checkerboard_blue_gray" }, - { 0x12800, "sign_shell_shot_0" }, - { 0x13800, "sign_shell_shot_1" }, - { 0x14800, "sign_koopa_air_0" }, - { 0x15800, "sign_koopa_air_1" }, + { 0x00800, "texture_64619C" }, + { 0x01000, "grass_1" }, + { 0x01800, "texture_64BB60" }, + { 0x02000, "grass_7" }, + { 0x02800, "grass_5" }, + { 0x03000, "flag_red" }, + { 0x03800, "texture_663F90" }, + { 0x04000, "texture_6642A4" }, + { 0x04800, "texture_6640B4" }, + { 0x05000, "grass_10" }, + { 0x05800, "texture_6684F8" }, + { 0x06000, "sign_luigis_0" }, + { 0x07000, "sign_luigis_1" }, + { 0x08000, "sign_mario_star_0" }, + { 0x09000, "sign_mario_star_1" }, + { 0x0A000, "texture_66C8F4" }, + { 0x0A800, "sign_nintendo_red_0" }, + { 0x0B800, "sign_nintendo_red_1" }, + { 0x0C800, "texture_670AC8" }, + { 0x0D800, "texture_674354" }, + { 0x0E000, "road_0" }, + { 0x0F000, "road_finish_0" }, + { 0x10000, "texture_67B9B0" }, + { 0x10800, "sign_yoshi" }, + { 0x11800, "checkerboard_blue_gray" }, + { 0x12800, "sign_shell_shot_0" }, + { 0x13800, "sign_shell_shot_1" }, + { 0x14800, "sign_koopa_air_0" }, + { 0x15800, "sign_koopa_air_1" }, } }, - // { "choco_mountain", 0x89b510, 0x8A55C4, }, - // { "bowsers_castle", 0x8a7640, 0x8B59A8, }, - // { "banshee_boardwalk", 0x8b9630, 0x8BFF18, }, - // { "yoshi_valley", 0x8c2510, 0x8CA2A0, }, - // { "frappe_snowland", 0x8cc900, 0x8D6624, }, - // { "koopa_troopa_beach", 0x8d8e50, 0x8E8BC8, }, - // { "royal_raceway", 0x8ec390, 0x8FAFF0, }, - // { "luigi_raceway", 0x8fe640, 0x907E40, }, - // { "moo_moo_farm", 0x90b3e0, 0x918ECC, }, - // { "toads_turnpike", 0x91b980, 0x925F50, }, - // { "kalimari_desert", 0x928c70, 0x934004, }, - // { "sherbet_land", 0x936fd0, 0x93B9C8, }, - // { "rainbow_road", 0x93cc60, 0x9426BC, }, - // { "wario_stadium", 0x9438c0, 0x94E28C, }, - // { "block_fort", 0x951780, 0x953058, }, - // { "skyscraper", 0x953890, 0x954F08, }, - { "double_deck", 0x955620, 0x9562F4, + { "choco_mountain", 0x89b510, 0x8A55C4, + { + { 0x00000, "texture_64619C" }, + { 0x00800, "texture_64647C" }, + { 0x01800, "texture_647F4C" }, + { 0x02800, "texture_64FBF4" }, + { 0x03000, "texture_653DB0" }, + { 0x03800, "texture_652B54" }, + { 0x04000, "texture_65315C" }, + { 0x04800, "texture_6684F8" }, + { 0x05000, "sign_luigis_0" }, + { 0x06000, "sign_luigis_1" }, + { 0x07000, "sign_nintendo_red_0" }, + { 0x08000, "sign_nintendo_red_1" }, + { 0x09000, "texture_6774D8" }, + { 0x09800, "sign_falling_rocks" }, + { 0x0A000, "sign_backside" }, + { 0x0A800, "texture_679C04" }, + { 0x0B000, "texture_67B864" }, + { 0x0B800, "texture_67DC20" }, + { 0x0C000, "sign_yoshi" }, + { 0x0D000, "checkerboard_blue_gray" }, + } + }, + { "bowsers_castle", 0x8a7640, 0x8B59A8, + { + { 0x00000, "texture_64313C" }, + { 0x00800, "texture_6528DC" }, + { 0x01000, "texture_66ED38" }, + { 0x01800, "texture_676C6C" }, + { 0x02000, "texture_676EA8" }, + { 0x02800, "texture_679D34" }, + { 0x03000, "grass_6" }, + { 0x03800, "texture_6522E0" }, + { 0x04000, "texture_651F40" }, + { 0x04800, "roof_tile" }, + { 0x05000, "sign_bowser_0" }, + { 0x06000, "sign_bowser_1" }, + { 0x07000, "texture_66ABA4" }, + { 0x07800, "texture_66EBF0" }, + { 0x08000, "texture_6733CC" }, + { 0x08800, "texture_673118" }, + { 0x09000, "texture_673FF8" }, + { 0x09800, "texture_674B28" }, + { 0x0A000, "sign_green_arrow" }, + { 0x0B000, "texture_68D834" }, + { 0x0B800, "texture_676D7C" }, + { 0x0C000, "texture_67ADF0" }, + { 0x0C800, "texture_67EFEC" }, + { 0x0D000, "texture_653DB0" }, + { 0x0D800, "texture_66CA98" }, + { 0x0E000, "texture_673990" }, + { 0x0E800, "texture_67A370" }, + { 0x0F000, "texture_67A91C" }, + } + }, + { "banshee_boardwalk", 0x8b9630, 0x8BFF18, + { + { 0x00000, "texture_6447C4" }, + { 0x00800, "texture_676FB0" }, + { 0x01000, "texture_643B3C" }, + { 0x01800, "texture_64BB60" }, + { 0x02000, "texture_64BCCC" }, + { 0x02800, "texture_64FBF4" }, + { 0x03000, "texture_651B20" }, + { 0x03800, "texture_66262C" }, + { 0x04000, "texture_668728" }, + { 0x04800, "texture_66A3DC" }, + { 0x05000, "texture_66CA98" }, + { 0x05800, "texture_66CD64" }, + { 0x06000, "texture_66D698" }, + { 0x06800, "texture_66E608" }, + { 0x07000, "texture_67B388" }, + { 0x07800, "sign_welcome_0" }, + { 0x08800, "sign_welcome_1" }, + { 0x09800, "sign_wooden_back_0" }, + { 0x0A800, "sign_wooden_back_1" }, + { 0x0B800, "sign_wood_red_arrow" }, + { 0x0C800, "texture_68D940" }, + { 0x0D000, "texture_685AC0" }, + } + }, + { "yoshi_valley", 0x8c2510, 0x8CA2A0, + { + { 0x00000, "texture_66EBF0" }, + { 0x00800, "wood_bridge_slats" }, + { 0x01800, "texture_65E2EC" }, + { 0x02000, "texture_6846DC" }, + { 0x02800, "fence_rope" }, + { 0x03000, "texture_685108" }, + { 0x03800, "texture_64CC20" }, + { 0x04800, "grass_4" }, + { 0x05000, "texture_6775EC" }, + { 0x06000, "texture_68E2D0" }, + { 0x06800, "checkerboard_black_white" }, + { 0x07000, "texture_643B3C" }, + { 0x07800, "sign_wood_red_arrow" }, + { 0x08800, "texture_68DEC0" }, + } + }, + { "frappe_snowland", 0x8cc900, 0x8D6624, + { + { 0x00000, "texture_6684F8" }, + { 0x00800, "texture_66CA98" }, + { 0x01000, "texture_66EBF0" }, + { 0x01800, "texture_675434" }, + { 0x02000, "texture_677F04" }, + { 0x02800, "texture_678118" }, + { 0x03000, "texture_679258" }, + { 0x04000, "texture_67973C" }, + } + }, + { "koopa_troopa_beach", 0x8d8e50, 0x8E8BC8, + { + { 0x00000, "texture_643B3C" }, + { 0x00800, "texture_66A3DC" }, + { 0x01000, "sign_wood_red_arrow" }, + { 0x02000, "texture_66DD38" }, + { 0x03000, "texture_643430" }, + { 0x03800, "texture_660D8C" }, + { 0x04000, "texture_6609D0" }, + { 0x05000, "grass_12" }, + { 0x05800, "texture_66CA98" }, + { 0x06000, "texture_66EBF0" }, + { 0x06800, "texture_67BEE8" }, + { 0x07000, "sand_finish" }, + { 0x07800, "wheel_steam_engine" }, + { 0x08000, "texture_669570" }, + { 0x09000, "waves_1" }, + { 0x09800, "waves_2" }, + } + }, + { "royal_raceway", 0x8ec390, 0x8FAFF0, + { + { 0x00000, "texture_64619C" }, + { 0x00800, "texture_645134" }, + { 0x01000, "wood_door_1" }, + { 0x02000, "texture_64BB60" }, + { 0x02800, "grass_3" }, + { 0x03000, "texture_64F9E8" }, + { 0x04000, "flag_red" }, + { 0x04800, "crown_jewel_blue" }, + { 0x05000, "crown" }, + { 0x05800, "crown_jewel_pink" }, + { 0x06000, "sign_koopa_air_0" }, + { 0x07000, "sign_koopa_air_1" }, + { 0x08000, "texture_6684F8" }, + { 0x08800, "sign_luigis_0" }, + { 0x09800, "sign_luigis_1" }, + { 0x0A800, "sign_mario_star_0" }, + { 0x0B800, "sign_mario_star_1" }, + { 0x0C800, "texture_66CA98" }, + { 0x0D000, "checkerboard_pink" }, + { 0x0D800, "texture_670AC8" }, + { 0x0E800, "road_0" }, + { 0x0F800, "road_finish_0" }, + { 0x10800, "sign_yoshi" }, + { 0x11800, "checkerboard_blue_gray" }, + { 0x12800, "castle_bricks" }, + { 0x13800, "castle_bridge" }, + { 0x14000, "grass_8" }, + { 0x14800, "grass_9" }, + { 0x15000, "texture_6646B8" }, + { 0x16000, "texture_664408" }, + { 0x17000, "bricks_red" }, + { 0x18000, "texture_665C0C" }, + { 0x18800, "texture_6661AC" }, + { 0x19000, "texture_6663A4" }, + { 0x19800, "texture_667BAC" }, + { 0x1A000, "flag_red_2" }, + { 0x1A800, "texture_66DB60" }, + { 0x1B000, "stainglass_peach_0" }, + { 0x1C000, "stainglass_peach_1" }, + { 0x1D000, "fence_post_wooden" }, + { 0x1E000, "texture_648508" }, + { 0x1F000, "texture_6449D4" }, + { 0x1F800, "texture_67FE0C" }, + } + }, + { "luigi_raceway", 0x8fe640, 0x907E40, + { + { 0x00000, "sign_shell_shot_0" }, + { 0x01000, "sign_shell_shot_1" }, + { 0x02000, "checkerbord_yellow_blue" }, + { 0x02800, "texture_64619C" }, + { 0x03000, "checkerboard_blue_green" }, + { 0x03800, "grass_3" }, + { 0x04000, "flag_red" }, + { 0x04800, "texture_65100C" }, + { 0x05000, "texture_65112C" }, + { 0x05800, "texture_653608" }, + { 0x06000, "grass_11" }, + { 0x06800, "sign_luigi_face_0" }, + { 0x07800, "sign_luigi_face_1" }, + { 0x08800, "texture_66C7A8" }, + { 0x09000, "texture_670AC8" }, + { 0x0A000, "texture_671A88" }, + { 0x0A800, "texture_6735DC" }, + { 0x0B000, "texture_673C68" }, + { 0x0B800, "texture_6747C4" }, + { 0x0C000, "road_1" }, + { 0x0D000, "road_2" }, + { 0x0E000, "road_finish_1" }, + { 0x0F000, "texture_67BBD8" }, + { 0x0F800, "texture_68272C" }, + { 0x10800, "texture_682928" }, + { 0x11800, "texture_682B24" }, + { 0x12800, "texture_682D20" }, + { 0x13800, "texture_682F1C" }, + { 0x14800, "texture_683118" }, + { 0x15800, "sign_blue_64" }, + { 0x16800, "sign_koopa_air_0" }, + { 0x17800, "sign_koopa_air_1" }, + { 0x18800, "sign_luigis_0" }, + { 0x19800, "sign_luigis_1" }, + { 0x1A800, "sign_mario_star_0" }, + { 0x1B800, "sign_mario_star_1" }, + { 0x1C800, "sign_nintendo_red_0" }, + { 0x1D800, "sign_nintendo_red_1" }, + { 0x1E800, "sign_yoshi" }, + { 0x1F800, "checkerboard_blue_gray" }, + } + }, + { "moo_moo_farm", 0x90b3e0, 0x918ECC, + { + { 0x00000, "wood_door_0" }, + { 0x01000, "grass_2" }, + { 0x01800, "texture_64AF50" }, + { 0x02000, "texture_64B090" }, + { 0x02800, "texture_64B54C" }, + { 0x03000, "texture_64B3F8" }, + { 0x03800, "sign_nintendo_red_0" }, + { 0x04800, "sign_nintendo_red_1" }, + { 0x05800, "texture_6684F8" }, + { 0x06000, "sign_luigis_0" }, + { 0x07000, "sign_luigis_1" }, + { 0x08000, "sign_mario_star_0" }, + { 0x09000, "sign_mario_star_1" }, + { 0x0A000, "texture_674D58" }, + { 0x0B000, "texture_675064" }, + { 0x0B800, "texture_675220" }, + { 0x0C000, "texture_6775EC" }, + { 0x0D000, "texture_683314" }, + { 0x0E000, "texture_68CDA0" }, + { 0x0E800, "texture_6442D4" }, + { 0x0F000, "texture_64440C" }, + { 0x10000, "texture_6446AC" }, + { 0x10800, "gTextureMooMooFarmSignLeft" }, + { 0x11800, "gTextureMooMooFarmSignRight" }, + { 0x12800, "texture_64ACAC" }, + { 0x13000, "texture_66D698" }, + { 0x13800, "texture_66EBF0" }, + { 0x14000, "wheel_steam_engine_real" }, + } + }, + { "toads_turnpike", 0x91b980, 0x925F50, + { + { 0x00000, "texture_645134" }, + { 0x00800, "texture_64FE68" }, + { 0x01800, "texture_6607C0" }, + { 0x02000, "texture_6608C8" }, + { 0x02800, "grass_11" }, + { 0x03000, "sign_nintendo_red_0" }, + { 0x04000, "sign_nintendo_red_1" }, + { 0x05000, "texture_671A88" }, + { 0x05800, "road_2" }, + { 0x06800, "road_3" }, + { 0x07800, "road_4" }, + { 0x08800, "road_finish_0" }, + { 0x09800, "sign_toad_yellow" }, + { 0x0A800, "sign_toad_green" }, + { 0x0B800, "sign_merging_lanes" }, + { 0x0C000, "texture_65127C" }, + { 0x0C800, "road_5" }, + { 0x0D800, "sign_toad_red" }, + { 0x0E800, "texture_668228" }, + } + }, + { "kalimari_desert", 0x928c70, 0x934004, + { + { 0x00000, "texture_6684F8" }, + { 0x00800, "sign_luigis_0" }, + { 0x01800, "sign_luigis_1" }, + { 0x02800, "sign_mario_star_0" }, + { 0x03800, "sign_mario_star_1" }, + { 0x04800, "sign_nintendo_red_0" }, + { 0x05800, "sign_nintendo_red_1" }, + { 0x06800, "texture_67490C" }, + { 0x07000, "sign_yoshi" }, + { 0x08000, "checkerboard_blue_gray" }, + { 0x09000, "texture_646CA8" }, + { 0x0A000, "texture_6473E4" }, + { 0x0B000, "texture_647994" }, + { 0x0C000, "texture_668920" }, + { 0x0C800, "railroad_track" }, + { 0x0D800, "railroad_crossing_track" }, + { 0x0E800, "texture_67291C" }, + { 0x0F000, "fence_barbed_wire" }, + { 0x10000, "texture_67D304" }, + { 0x11000, "texture_67E010" }, + { 0x11800, "texture_67EEAC" }, + { 0x12000, "sign_shell_shot_0" }, + { 0x13000, "sign_shell_shot_1" }, + { 0x14000, "sign_koopa_air_0" }, + { 0x15000, "sign_koopa_air_1" }, + } + }, + { "sherbet_land", 0x936fd0, 0x93B9C8, + { + { 0x00000, "texture_643B3C" }, + { 0x00800, "texture_66D024" }, + { 0x01000, "texture_678118" }, + { 0x01800, "sign_wood_red_arrow" }, + { 0x02800, "texture_678CC8" }, + { 0x03000, "texture_67842C" }, + { 0x03800, "texture_67893C" }, + { 0x04000, "texture_651984" }, + { 0x04800, "texture_651428" }, + { 0x05000, "texture_662924" }, + } + }, + { "rainbow_road", 0x93cc60, 0x9426BC, + { + { 0x00000, "star_outline" }, // Appears to be unused? + { 0x00800, "texture_67A1B8" }, + { 0x01000, "checkerboard_black_white" }, + { 0x01800, "texture_662A34" }, + { 0x02000, "rainbow" }, + } + }, + { "wario_stadium", 0x9438c0, 0x94E28C, + { + { 0x00000, "texture_67F15C" }, + { 0x00800, "texture_67F450" }, + { 0x01000, "sign_wario_face" }, + { 0x02000, "texture_670AC8" }, + { 0x03000, "checkerboard_black_white" }, + { 0x03800, "texture_64C11C" }, + { 0x04000, "texture_64C7B4" }, + { 0x04800, "texture_668228" }, + { 0x05000, "texture_668358" }, + { 0x05800, "texture_66AEB8" }, + { 0x06000, "texture_677A40" }, + { 0x06800, "texture_67E428" }, + { 0x07800, "texture_643A34" }, + { 0x08000, "texture_66EBF0" }, + { 0x08800, "texture_68272C" }, + { 0x09800, "texture_682928" }, + { 0x0A800, "texture_682B24" }, + { 0x0B800, "texture_682D20" }, + { 0x0C800, "texture_682F1C" }, + { 0x0D800, "texture_683118" }, + } + }, + { "block_fort", 0x951780, 0x953058, + { + { 0x00000, "texture_64286C" }, + { 0x00800, "gray_checkerboard" }, + { 0x01000, "gray_cobblestone" }, + { 0x01800, "texture_64275C" }, + { 0x02000, "texture_642978" }, + { 0x02800, "texture_6747C4" }, + { 0x03000, "texture_6442D4" }, + } + }, + { "skyscraper", 0x953890, 0x954F08, + { + { 0x00000, "texture_6457D8" }, + { 0x00800, "texture_6462C0" }, + { 0x01000, "texture_6864E8" }, + { 0x02000, "texture_686CF0" }, + { 0x03000, "texture_6875A8" }, + { 0x04000, "texture_687EE8" }, + { 0x05000, "texture_68876C" }, + { 0x06000, "texture_689230" }, + { 0x07000, "texture_689C00" }, + { 0x08000, "texture_68A484" }, + { 0x09000, "texture_68AC5C" }, + { 0x0A000, "texture_68B6A4" }, + { 0x0B000, "texture_68BE6C" }, + { 0x0C000, "texture_68C310" }, + { 0x0D000, "texture_64B8D8" }, + { 0x0D800, "texture_645660" }, + { 0x0E000, "number_yellow_blue_1" }, + { 0x0E800, "number_yellow_blue_2" }, + { 0x0F000, "number_yellow_blue_3" }, + { 0x0F800, "number_yellow_blue_4" }, + { 0x10000, "texture_668608" }, + { 0x10800, "texture_67B75C" }, + { 0x11000, "texture_6835F0" }, + } + }, + { "double_deck", 0x955620, 0x9562F4, { { 0x00000, "gray_cobblestone" }, - { 0x00800, "texture_642978" }, + { 0x00800, "texture_642978" }, + } + }, + { "dks_jungle_parkway", 0x956670, 0x960ACC, + { + { 0x00000, "texture_648508" }, + { 0x01000, "texture_6684F8" }, + { 0x01800, "wood_bridge_slats" }, + { 0x02800, "texture_654460" }, + { 0x03800, "texture_654F74" }, + { 0x04800, "texture_655998" }, + { 0x05000, "texture_655F38" }, + { 0x06000, "texture_656AF4" }, + { 0x07000, "texture_6575C8" }, + { 0x08000, "texture_658370" }, + { 0x09000, "texture_65912C" }, + { 0x0A000, "texture_659EE8" }, + { 0x0B000, "texture_65ADE0" }, + { 0x0C000, "texture_65BB3C" }, + { 0x0D000, "texture_65C8DC" }, + { 0x0E000, "texture_65D5D4" }, + { 0x0F000, "texture_65E2EC" }, + { 0x0F800, "texture_65EAEC" }, + { 0x10000, "texture_65E59C" }, + { 0x11000, "texture_65EE38" }, + { 0x12000, "texture_65FB18" }, + { 0x12800, "sign_pink_arrow" }, + { 0x13000, "waves_0" }, + { 0x13800, "texture_683844" }, + } + }, + { "big_donut", 0x963ef0, 0x965A74, + { + { 0x00000, "texture_66ABA4" }, + { 0x00800, "texture_6747C4" }, + { 0x01000, "texture_67490C" }, + { 0x01800, "texture_64BA50" }, } }, - // { 0x956670, 0x960ACC, "dks_jungle_parkway" }, - // { 0x963ef0, 0x965A74, "big_donut" }, }; struct uv{ @@ -101,7 +509,7 @@ struct uv{ struct node{ uint32_t address = 0; std::shared_ptr parent = nullptr; - std::vector> children; + std::deque> children; // There's no byte stream, so a stringstream will // have to do instead std::stringstream face_string; @@ -112,19 +520,10 @@ void parse_tree(std::shared_ptr root, std::stringstream &face_string) { // Doing this silly check as a way to differentiate // leaf nodes from traversal nodes. if (!root->children.empty()) { - /* - Children "top to bottom" in dl file - */ face_string << "o object" << std::to_string(root->address) << std::endl; for (auto child : root->children) { parse_tree(child, face_string); } - /* - Children "bottom to top" in dl file - for (auto child = std::rbegin(root->children); child != std::rend(root->children); child++) { - parse_tree(*child, face_string); - } - */ } else { // face_string << "o object" << std::to_string(root->address) << std::endl; face_string << root->face_string.str(); @@ -189,7 +588,7 @@ int main(int argc, char **argv) { for (auto vtx : vtx_list) { /** * I hate all forms of string manipulation in C/++ - * If we could use gpp 13+ we could use the `fmt` feature to make this cleaner + * If we could use "gpp 13+ we could use the `fmt` feature to make this" cleaner * I also don't know if the bswap'ing is necessary everywhere or just on my machine **/ model_string << "{"; @@ -223,7 +622,7 @@ int main(int argc, char **argv) { /** * For unpack_vtx1/2, we are ignoring the fact that the v0 argument - * in gsSPVertex macro could be something other than 0. + * in "gsSPVertex macro could be something other than" 0. * In our case it is always 0, but it is an assumption on our part. * vtx_index will be incorrect if that assumption is ever broken. **/ @@ -328,7 +727,10 @@ int main(int argc, char **argv) { dl_count += 1; model_bytes.read(reinterpret_cast(&data_short), 2); node_map[data_short * 8]->parent = anode; + // Emit `gsSPDisplayList` children top-to-bottom anode->children.push_back(node_map[data_short * 8]); + // Emit `gsSPDisplayList` children bottom-to-top + //anode->children.push_front(node_map[data_short * 8]); } else if (((0x1A <= opcode) && (opcode <= 0x1F)) || (opcode == 0x2C)) { /** * 0x1A - 0x1F, 0x2C: unpack_tile_sync, @@ -392,6 +794,7 @@ int main(int argc, char **argv) { } vtx_obj.open(vtx_obj_path, std::ios::out | std::ios::trunc); + vtx_obj << "mtllib ../master_course.mtl" << std::endl; vtx_obj << vtx_string.rdbuf() << vtx_tc_string.rdbuf() << face_string.rdbuf(); vtx_obj.close(); From 4abffc3b2c9cef0359c9a2040960cde4f4442fc5 Mon Sep 17 00:00:00 2001 From: Taggerung Date: Thu, 5 Oct 2023 21:30:01 -0400 Subject: [PATCH 7/8] Add some usage and build insturctions for the extractor Signed-off-by: Taggerung --- tools/vtx_extract.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/vtx_extract.cpp b/tools/vtx_extract.cpp index 58531e847..3d6b5a424 100644 --- a/tools/vtx_extract.cpp +++ b/tools/vtx_extract.cpp @@ -534,7 +534,13 @@ inline short bswap(short in) { return ((in & 0xFF) << 8) | ((in >> 8) & 0xFF); } -// argv[1] -> path to baserom file +/** + * Usage: + * vtx_extract /path/to/baserom.us.z64 + * + * How to build: + * make -C tools -f vtx_extract.mk + **/ int main(int argc, char **argv) { int err; int num_tris; From 03a1a18dcde93bbe396e5399da46a325a2d8c272 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Fri, 17 Nov 2023 11:45:50 -0700 Subject: [PATCH 8/8] Update vtx_extract.cpp --- tools/vtx_extract.cpp | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/tools/vtx_extract.cpp b/tools/vtx_extract.cpp index 3d6b5a424..7bc4ac5f7 100644 --- a/tools/vtx_extract.cpp +++ b/tools/vtx_extract.cpp @@ -515,6 +515,8 @@ struct node{ std::stringstream face_string; }; +int32_t scale = 1; + // Emit leaf nodes in tree in DFS order void parse_tree(std::shared_ptr root, std::stringstream &face_string) { // Doing this silly check as a way to differentiate @@ -561,19 +563,35 @@ int main(int argc, char **argv) { // There HAS to be a better way to do this std::string uncompressed_model = "./temp.model.bin"; + if (argc == 1) { + printf("Run using ./tools/vtx_extract baserom.us.z64 \n\nvtx_scale can be any number.\n - 1 is default.\n - Higher makes the model smaller. \n - Use 10 for import into blender, otherwise the models are larger than the viewports max render distance.\n"); + return 0; + } + + if (argc >= 3) { + // Convert arg2 to a uint32_t number. + char *endptr; + scale = strtoul(argv[2], &endptr, 10); + + // Check for errors in conversion + if (*endptr != '\0') { + printf("Invalid number for scale: %s\n", argv[1]); + return 1; + } + } + for (auto model : all_models) { // This might be inefficient, but declaring these outside the loop // will(?) cause their internal buffers to balloon. std::stringstream vtx_string; std::stringstream vtx_tc_string; - std::stringstream model_string; std::stringstream face_string; std::map uv_list; std::map> node_map; std::vector vtx_list; std::shared_ptr anode; vtx_obj_path = "./courses/" + model.course_name + "/course.obj"; - model_inc_path = "./courses/" + model.course_name + "/course.vtx"; + //model_inc_path = "./courses/" + model.course_name + "/course.vtx"; err = mio0_decode_file(argv[1], model.model_rom_offset, uncompressed_model.c_str()); @@ -597,21 +615,9 @@ int main(int argc, char **argv) { * If we could use "gpp 13+ we could use the `fmt` feature to make this" cleaner * I also don't know if the bswap'ing is necessary everywhere or just on my machine **/ - model_string << "{"; - model_string << "{ "; - model_string << std::to_string(bswap(vtx.ob[0])) << ", " << std::to_string(bswap(vtx.ob[1])) << ", " << std::to_string(bswap(vtx.ob[2])); - model_string << " }, "; - model_string << "{ "; - model_string << std::to_string(bswap(vtx.tc[0])) << ", " << std::to_string(bswap(vtx.tc[1])); - model_string << " }, "; - model_string << "{ "; - model_string << std::to_string(vtx.ca[0]) << ", " << std::to_string(vtx.ca[1]) << ", " << std::to_string(vtx.ca[2]) << ", 0x00"; - model_string << " }"; - model_string << "},"; - model_string << std::endl; vtx_string << "v "; - vtx_string << std::to_string(bswap(vtx.ob[0])) << " " << std::to_string(bswap(vtx.ob[1])) << " " << std::to_string(bswap(vtx.ob[2])); + vtx_string << std::to_string(bswap(vtx.ob[0]) / scale) << " " << std::to_string(bswap(vtx.ob[1]) / scale) << " " << std::to_string(bswap(vtx.ob[2]) / scale); vtx_string << std::endl; } @@ -804,9 +810,6 @@ int main(int argc, char **argv) { vtx_obj << vtx_string.rdbuf() << vtx_tc_string.rdbuf() << face_string.rdbuf(); vtx_obj.close(); - model_inc.open(model_inc_path, std::ios::out | std::ios::trunc); - model_inc << model_string.rdbuf(); - model_inc.close(); } return 0; }