diff --git a/Makefile b/Makefile index 9e983af..94c4fec 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ triangle_rotating.elf: $(DEFAULT) arm9/triangle_rotating.bin.o texture.elf: $(DEFAULT) arm9/texture.bin.o cube.elf: $(DEFAULT) arm9/cube.bin.o icosphere.elf: $(DEFAULT) arm9/icosphere.bin.o +majora.elf: $(DEFAULT) arm9/majora.bin.o TARGET = arm-none-eabi- AARCH = -march=armv4t -mlittle-endian diff --git a/arm9/Makefile b/arm9/Makefile index 1172c32..47c36b2 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -1,4 +1,4 @@ -OPT = -Os +OPT = -Og ALL = \ arm9.bin \ @@ -26,6 +26,22 @@ cube.elf: start.o examples/cube.o ../math/cos_table_fp12.o ../math/cos.o icosphere.elf: start.o examples/icosphere.o ../math/cos_table_fp12.o ../math/cos.o +MAJORA_RES = \ + ../res/060067E0.data.pal.o \ + ../res/060079E0.data.pal.o \ + ../res/06007DE0.data.pal.o \ + ../res/060077E0.data.pal.o \ + ../res/06007BE0.data.pal.o \ + ../res/06007FE0.data.pal.o \ + ../res/060067E0.data.o \ + ../res/060079E0.data.o \ + ../res/06007DE0.data.o \ + ../res/060077E0.data.o \ + ../res/06007BE0.data.o \ + ../res/06007FE0.data.o + +majora.elf: start.o examples/majora.o ../math/cos_table_fp12.o ../math/cos.o $(MAJORA_RES) + CFLAGS += -I../include -I../ include arm9.mk diff --git a/arm9/examples/majora.c b/arm9/examples/majora.c new file mode 100644 index 0000000..5451ab8 --- /dev/null +++ b/arm9/examples/majora.c @@ -0,0 +1,520 @@ +#include "io_registers.h" +#include "bits.h" + +#include "math/math.h" + +#include "res/060067E0.data.h" +#include "res/060067E0.data.pal.h" +#include "res/060077E0.data.h" +#include "res/060077E0.data.pal.h" +#include "res/060079E0.data.h" +#include "res/060079E0.data.pal.h" +#include "res/06007BE0.data.h" +#include "res/06007BE0.data.pal.h" +#include "res/06007DE0.data.h" +#include "res/06007DE0.data.pal.h" +#include "res/06007FE0.data.h" +#include "res/06007FE0.data.pal.h" +#include "models/majora.h" + +struct object * object[6] = { + &majora_1, + &majora_3, + &majora_4, + &majora_5, + &majora_6, + &majora_7, +}; + +int palette_offset[6]; +int pixel_dimension[6]; +uint32_t teximage_param[6]; + +int round_up_32(int n) +{ + return ((n + 63) / 64) * 64; +} + +uint16_t rgb565(const uint8_t * buf) +{ + uint8_t r = buf[0] >> 3; + uint8_t g = buf[1] >> 3; + uint8_t g_l = (buf[1] >> 2) & 1; + uint8_t b = buf[2] >> 3; + + return (g_l << 15) | (b << 10) | (g << 5) | (r << 0); +} + +void copy_palettes() +{ + int offset = 0; + volatile uint16_t * vram_f = (volatile uint16_t *)(0x06890000); + + int num_pixel_palettes = (sizeof (majora_pixel_palette)) / (sizeof (struct pixel_palette)); + for (int i = 0; i < num_pixel_palettes; i++) { + palette_offset[i] = offset; + + int colors = majora_pixel_palette[i].palette.size / 3; + + uint8_t * pal = majora_pixel_palette[i].palette.start; + + for (int c = 0; c < colors; c++) { + vram_f[c + (offset / 2)] = rgb565(&pal[c * 3]); + } + + offset = round_up_32(offset + colors * 2); + } +} + +int pixel_dimension_from_pixels(int pixels) +{ + switch (pixels) { + default: + case 64: return 8; + case 256: return 16; + case 1024: return 32; + case 4096: return 64; + case 16384: return 128; + case 65536: return 256; + case 262144: return 512; + case 1048576: return 1024; + } +} + +uint32_t teximage_size_from_dimension(int dimension) +{ + switch (dimension) { + default: + case 8: return TEXIMAGE_PARAM__t_size__8_texels + | TEXIMAGE_PARAM__s_size__8_texels; + case 16: return TEXIMAGE_PARAM__t_size__16_texels + | TEXIMAGE_PARAM__s_size__16_texels; + case 32: return TEXIMAGE_PARAM__t_size__32_texels + | TEXIMAGE_PARAM__s_size__32_texels; + case 64: return TEXIMAGE_PARAM__t_size__64_texels + | TEXIMAGE_PARAM__s_size__64_texels; + case 128: return TEXIMAGE_PARAM__t_size__128_texels + | TEXIMAGE_PARAM__s_size__128_texels; + case 256: return TEXIMAGE_PARAM__t_size__256_texels + | TEXIMAGE_PARAM__s_size__256_texels; + case 512: return TEXIMAGE_PARAM__t_size__512_texels + | TEXIMAGE_PARAM__s_size__512_texels; + case 1024: return TEXIMAGE_PARAM__t_size__1024_texels + | TEXIMAGE_PARAM__s_size__1024_texels; + } +} + +uint32_t make_teximage_param(int offset, int dimension) +{ + return 0 + | TEXIMAGE_PARAM__texture_coordinate_transformation_mode__vertex_source + | TEXIMAGE_PARAM__texture_format__256_color_palette + | teximage_size_from_dimension(dimension) + | TEXIMAGE_PARAM__repeat_t__repeat + | TEXIMAGE_PARAM__repeat_s__repeat + | TEXIMAGE_PARAM__texture_starting_address(offset >> 3); +} + +void copy_pixels() +{ + int offset = 0; + volatile uint16_t * vram_a = (volatile uint16_t *)(0x06800000); + + int num_pixel_palettes = (sizeof (majora_pixel_palette)) / (sizeof (struct pixel_palette)); + for (int i = 0; i < num_pixel_palettes; i++) { + int size = majora_pixel_palette[i].pixel.size; + pixel_dimension[i] = pixel_dimension_from_pixels(size); + teximage_param[i] = make_teximage_param(offset, pixel_dimension[i]); + uint8_t * pixel = majora_pixel_palette[i].pixel.start; + + for (int p = 0; p < size; p+=2) { + uint16_t texel = (pixel[p + 1] << 8) | (pixel[p + 0] << 0); + vram_a[(p + offset) / 2] = texel; + } + + offset += size; + } +} + +int u_to_s(int n, int dimension) +{ + return (n * dimension) >> 10; +} + +int v_to_t(int n, int dimension) +{ + return ((((1 << 15) - n) * dimension) >> 10); +} + +void copy_texture_data() +{ + // memory bank allocation + // use VRAM-A for texture pixel data + // use VRAM-E for texture palette data + + // temporarily map VRAM-A (128KB) to the arm9 address space: + // 0x06800000 - 0x0681FFFF + io_registers.a.VRAMCNT = 0 + | VRAMCNT__vram_a__enable + | VRAMCNT__vram_a__mst(0b00); // arm9 + + // temporarily map VRAM-F (16KB) to the arm9 address space: + // 0x06890000 - 0x06893FFF + io_registers.a.WVRAMCNT = 0 + | WVRAMCNT__vram_f__enable + | WVRAMCNT__vram_f__mst(0b000); // arm9 + + // at this point, VRAM-A/VRAM-E are not accessible by the 3d engine. + + copy_palettes(); + copy_pixels(); + + // map VRAM-A (128KB) to the 3d-engine "texture image slot 0": + // 0x00000 - 0x1ffff (3d engine texture image address space) + io_registers.a.VRAMCNT = 0 + | VRAMCNT__vram_a__enable + | VRAMCNT__vram_a__ofs(0) // slot 0 + | VRAMCNT__vram_a__mst(0b11); // texture image + + // map VRAM-F (16KB) to the 3d-engine "texture palette slot 0": + // 0x0000 - 0x3fff (3d engine texture palette address space) + io_registers.a.WVRAMCNT = 0 + | WVRAMCNT__vram_f__enable + | WVRAMCNT__vram_f__ofs(0) // slot 0 + | WVRAMCNT__vram_f__mst(0b011); // texture palette +} + +void main() +{ + // power control + io_registers.a.POWCNT = 0 + | POWCNT__lcd_output_destination__a_to_upper__b_to_lower + | POWCNT__geometry_engine__enable + | POWCNT__rendering_engine__enable + | POWCNT__lcd__enable; + + // enable bg0 and 3d graphics + io_registers.a.DISPCNT = 0 + | DISPCNT__display_mode__graphics_display + | DISPCNT__bg0__enable + | DISPCNT__display_selection_for_bg0__3d_graphics + ; + + // disable all 3d effects + io_registers.a.DISP3DCNT = 0 + | DISP3DCNT__clear_image__disable + | DISP3DCNT__fog_master__disable + | DISP3DCNT__edge_marking__disable + | DISP3DCNT__anti_aliasing__disable + | DISP3DCNT__alpha_blending__disable + | DISP3DCNT__alpha_test__disable + | DISP3DCNT__texture_mapping__enable; + + copy_texture_data(); + copy_texture_data(); + + // clear matrix stack status + io_registers.a.GXSTAT |= GXSTAT__matrix_stack_status__overflow_or_underflow; + + // load identity matrices + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__projection; + io_registers.a.MTX_IDENTITY = 0; + + /* + io_registers.a.MTX_SCALE = ((192 << 12) / (256)) / 2; + io_registers.a.MTX_SCALE = 0.5 * 4096; + io_registers.a.MTX_SCALE = 0.5 * 4096; + */ + + // load a symmetric perspective matrix, with aspect ratio correction + io_registers.a.MTX_LOAD_4X4 = (192 << 12) / 256; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 1 << 12; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = -(1 << 12); + + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = 0; + io_registers.a.MTX_LOAD_4X4 = -(1 << 12); + io_registers.a.MTX_LOAD_4X4 = 0; + + // translate the viewpoint + io_registers.a.MTX_TRANS = 0; + io_registers.a.MTX_TRANS = 0; + io_registers.a.MTX_TRANS = (int)(-2.0 * (float)(1 << 12)); + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position; + io_registers.a.MTX_IDENTITY = 0; + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position_and_vector; + io_registers.a.MTX_IDENTITY = 0; + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__texture; + io_registers.a.MTX_IDENTITY = 0; + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position_and_vector; + + // set the 3d clear color to a dark red + io_registers.a.CLEAR_COLOR = 0 + | CLEAR_COLOR__clear_polygon_id(31) + | CLEAR_COLOR__alpha_value(31) + | CLEAR_COLOR__blue(1) + | CLEAR_COLOR__green(1) + | CLEAR_COLOR__red(10); + + // set the depth buffer clear value to the maximum value + io_registers.a.CLEAR_DEPTH = CLEAR_DEPTH__value(0x7fff); + + // the 3d viewport is the entire display area + io_registers.a.VIEWPORT = 0 + | VIEWPORT__y2(191) + | VIEWPORT__x2(255) + | VIEWPORT__y1(0) + | VIEWPORT__x1(0); + + // normalized 45° vector + int c = 0.57735 * 512; + + // lighting + io_registers.a.LIGHT_VECTOR = 0 + | LIGHT_VECTOR__light_number(0) + | LIGHT_VECTOR__decimal_z(-c) + | LIGHT_VECTOR__decimal_y(-c) + | LIGHT_VECTOR__decimal_x(-c); + + io_registers.a.LIGHT_VECTOR = 0 + | LIGHT_VECTOR__light_number(1) + | LIGHT_VECTOR__decimal_z(-c) + | LIGHT_VECTOR__decimal_y(-c) + | LIGHT_VECTOR__decimal_x(c); + + io_registers.a.LIGHT_VECTOR = 0 + | LIGHT_VECTOR__light_number(2) + | LIGHT_VECTOR__decimal_z(-c) + | LIGHT_VECTOR__decimal_y(c) + | LIGHT_VECTOR__decimal_x(-c); + + io_registers.a.LIGHT_COLOR = 0 + | LIGHT_COLOR__light_number(0) + | LIGHT_COLOR__blue(31) + | LIGHT_COLOR__green(31) + | LIGHT_COLOR__red(31); + + io_registers.a.LIGHT_COLOR = 0 + | LIGHT_COLOR__light_number(1) + | LIGHT_COLOR__blue(31) + | LIGHT_COLOR__green(31) + | LIGHT_COLOR__red(31); + + io_registers.a.LIGHT_COLOR = 0 + | LIGHT_COLOR__light_number(2) + | LIGHT_COLOR__blue(31) + | LIGHT_COLOR__green(31) + | LIGHT_COLOR__red(31); + + // degrees + int theta = 0; + + while (1) { + // calculate sin/cos for 2d rotation; signed fp20.12 result + int cos = cos_fp12(theta); + int sin = sin_fp12(theta); + + int cos2 = cos_fp12(-theta >> 1); + int sin2 = sin_fp12(-theta >> 1); + + io_registers.a.MTX_MODE = MTX_MODE__matrix_mode__position_and_vector; + // reset position matrix + io_registers.a.MTX_IDENTITY = 0; + + io_registers.a.MTX_TRANS = 0; + io_registers.a.MTX_TRANS = (int)(-0.5 * (float)(1 << 12)); + io_registers.a.MTX_TRANS = 0; + + + // multiply by a y-axis rotation + /* + io_registers.a.MTX_MULT_3X3 = cos2; + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = sin2; + + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = 1 << 12; + io_registers.a.MTX_MULT_3X3 = 0; + + io_registers.a.MTX_MULT_3X3 = -sin2; + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = cos2; + */ + + /* + // multiply by a z-axis rotation + io_registers.a.MTX_MULT_3X3 = cos; + io_registers.a.MTX_MULT_3X3 = -sin; + io_registers.a.MTX_MULT_3X3 = 0; + + io_registers.a.MTX_MULT_3X3 = sin; + io_registers.a.MTX_MULT_3X3 = cos; + io_registers.a.MTX_MULT_3X3 = 0; + + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = 1 << 12; + */ + + // multiply by a x-axis rotation + io_registers.a.MTX_MULT_3X3 = 1 << 12; + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = 0; + + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = cos2; + io_registers.a.MTX_MULT_3X3 = -sin2; + + io_registers.a.MTX_MULT_3X3 = 0; + io_registers.a.MTX_MULT_3X3 = sin2; + io_registers.a.MTX_MULT_3X3 = cos2; + + // cube faces + + io_registers.a.DIF_AMB = 0 + | DIF_AMB__ambient_blue(3) + | DIF_AMB__ambient_green(3) + | DIF_AMB__ambient_red(3) + | DIF_AMB__diffuse_blue(10) + | DIF_AMB__diffuse_green(10) + | DIF_AMB__diffuse_red(10); + + io_registers.a.SPE_EMI = 0 + | SPE_EMI__specular_blue(25) + | SPE_EMI__specular_green(25) + | SPE_EMI__specular_red(25); + + /* + io_registers.a.COLOR = 0 + | COLOR__blue(31) + | COLOR__green(31) + | COLOR__red(31); + */ + + // the following polygons are fully opaque; backface culling is + // enabled + io_registers.a.POLYGON_ATTR = 0 + | POLYGON_ATTR__polygon_id(0) + | POLYGON_ATTR__alpha_value(31) + | POLYGON_ATTR__render_front_surface__enable + | POLYGON_ATTR__render_back_surface__enable + | POLYGON_ATTR__polygon_mode__modulation + | POLYGON_ATTR__light_2__enable + | POLYGON_ATTR__light_1__enable + | POLYGON_ATTR__light_0__enable; + + // the following vertices are a triangles + + io_registers.a.BEGIN_VTXS = BEGIN_VTXS__type__triangle; + + for (int oix = 0; oix < (sizeof (object)) / (sizeof (struct object *)); oix++) { + struct object * obj = object[oix]; + const int num_triangles = obj->triangle_count; + + int material = obj->material; + + io_registers.a.TEXPLTT_BASE = TEXPLTT_BASE__base_address(palette_offset[material] >> 4); + io_registers.a.TEXIMAGE_PARAM = teximage_param[material]; + + int dimension = pixel_dimension[material]; + + for (int i = 0; i < num_triangles; i++) { + // "When texture mapping, the Geometry Engine works faster if you + // issue commands in the following order: TexCoord→Normal→Vertex." + struct vertex_texture * at = &majora_texture[obj->triangle[i].a.texture]; + // convert from UV space to ST space + int au = at->u; + int av = at->v; + io_registers.a.TEXCOORD = 0 + | TEXCOORD__t_coordinate(v_to_t(av, dimension)) + | TEXCOORD__s_coordinate(u_to_s(au, dimension)); + + struct vertex_normal * an = &majora_normal[obj->triangle[i].a.normal]; + io_registers.a.NORMAL = 0 + | NORMAL__z_component(an->z) + | NORMAL__y_component(an->y) + | NORMAL__x_component(an->x); + + struct vertex_position * a = &majora_position[obj->triangle[i].a.position]; + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(a->z) + | VTX_10__y_coordinate(a->y) + | VTX_10__x_coordinate(a->x); + + struct vertex_texture * bt = &majora_texture[obj->triangle[i].b.texture]; + // convert from UV space to ST space + int bu = bt->u; + int bv = bt->v; + io_registers.a.TEXCOORD = 0 + | TEXCOORD__t_coordinate(v_to_t(bv, dimension)) + | TEXCOORD__s_coordinate(u_to_s(bu, dimension)); + + struct vertex_normal * bn = &majora_normal[obj->triangle[i].b.normal]; + io_registers.a.NORMAL = 0 + | NORMAL__z_component(bn->z) + | NORMAL__y_component(bn->y) + | NORMAL__x_component(bn->x); + + struct vertex_position * b = &majora_position[obj->triangle[i].b.position]; + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(b->z) + | VTX_10__y_coordinate(b->y) + | VTX_10__x_coordinate(b->x); + + struct vertex_texture * ct = &majora_texture[obj->triangle[i].c.texture]; + // convert from UV space to ST space + int cu = ct->u; + int cv = ct->v; + io_registers.a.TEXCOORD = 0 + | TEXCOORD__t_coordinate(v_to_t(cv, dimension)) + | TEXCOORD__s_coordinate(u_to_s(cu, dimension)); + + struct vertex_normal * cn = &majora_normal[obj->triangle[i].c.normal]; + io_registers.a.NORMAL = 0 + | NORMAL__z_component(cn->z) + | NORMAL__y_component(cn->y) + | NORMAL__x_component(cn->x); + + struct vertex_position * c = &majora_position[obj->triangle[i].c.position]; + io_registers.a.VTX_10 = 0 + | VTX_10__z_coordinate(c->z) + | VTX_10__y_coordinate(c->y) + | VTX_10__x_coordinate(c->x); + } + + } + + // end of the triangle + io_registers.a.END_VTXS = 0; + + // wait for the geometry engine + while (io_registers.a.GXSTAT & GXSTAT__geometry_engine_busy); + + // wait for the end of the current frame + while (io_registers.a.VCOUNT != 262); + while (io_registers.a.VCOUNT == 262); + + // swap buffers + io_registers.a.SWAP_BUFFERS = 0; + + // increment theta once per frame + theta += 1; + if (theta >= 360 * 16) { + theta = 0; + } + } +} diff --git a/common.mk b/common.mk index aaba43c..4ddb00e 100644 --- a/common.mk +++ b/common.mk @@ -12,6 +12,7 @@ CFLAGS += -Wno-error=maybe-uninitialized CFLAGS += -Wno-error=unused-but-set-variable CFLAGS += -Wno-error=unused-variable CFLAGS += -Wno-aggressive-loop-optimizations +CFLAGS += -fno-inline-small-functions CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics diff --git a/include/bits.h b/include/bits.h index c1de7eb..d783545 100644 --- a/include/bits.h +++ b/include/bits.h @@ -252,7 +252,7 @@ #define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__do_not_transform_texture_coordinates (0x0 << 30) #define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__texcoord_source (0x1 << 30) #define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__normal_source (0x2 << 30) -#define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__vextex_source (0x3 << 30) +#define TEXIMAGE_PARAM__texture_coordinate_transformation_mode__vertex_source (0x3 << 30) #define TEXIMAGE_PARAM__palette_color0_transparency__palette_setting (0x0 << 29) #define TEXIMAGE_PARAM__palette_color0_transparency__always_transparent (0x1 << 29) #define TEXIMAGE_PARAM__texture_format__no_texture (0x0 << 26) diff --git a/models/majora.h b/models/majora.h new file mode 100644 index 0000000..6ed1fa7 --- /dev/null +++ b/models/majora.h @@ -0,0 +1,933 @@ +#include "model.h" + +// .6 fixed-point +struct vertex_position majora_position[] = { + {28, 13, -2}, + {41, -9, -3}, + {17, 4, -2}, + {23, 8, 2}, + {-24, 8, 2}, + {-29, 13, -2}, + {-42, -9, -3}, + {-18, 4, -2}, + {0, 61, -3}, + {41, 20, -5}, + {0, -13, -7}, + {16, 68, -3}, + {35, 68, -3}, + {49, 52, -3}, + {-49, 52, -3}, + {-36, 68, -3}, + {-17, 68, -3}, + {-42, 20, -5}, + {-28, 95, 0}, + {-16, 63, -1}, + {-31, 62, -1}, + {-23, 60, 6}, + {22, 60, 6}, + {30, 62, -1}, + {27, 95, 0}, + {15, 63, -1}, + {64, 20, -1}, + {36, 25, -1}, + {43, 36, -1}, + {39, 30, 3}, + {-40, 30, 3}, + {-44, 36, -1}, + {-65, 20, -1}, + {-37, 25, -1}, + {-4, -4, -3}, + {-25, -20, -3}, + {-18, 3, -2}, + {-11, -1, 1}, + {24, -20, -3}, + {17, 3, -2}, + {10, -1, 1}, + {3, -4, -3}, + {-28, 14, -2}, + {-54, 3, -2}, + {-38, 23, -1}, + {-33, 18, 2}, + {53, 3, -2}, + {37, 23, -1}, + {32, 18, 2}, + {27, 14, -2}, + {0, 61, -3}, + {0, 42, 13}, + {6, 54, 11}, + {15, 29, 17}, + {0, 13, 6}, + {-16, 29, 17}, + {-19, 45, 18}, + {0, -13, -7}, + {-12, 14, 15}, + {-17, 68, -3}, + {-13, 61, 7}, + {-36, 68, -3}, + {-49, 52, -3}, + {-37, 48, 14}, + {-14, 53, 17}, + {-7, 54, 11}, + {30, 24, 13}, + {41, 20, -5}, + {49, 52, -3}, + {13, 53, 17}, + {18, 45, 18}, + {-31, 24, 13}, + {-42, 20, -5}, + {-24, 14, 7}, + {23, 14, 7}, + {-27, 60, 11}, + {12, 61, 7}, + {16, 68, -3}, + {26, 60, 11}, + {35, 68, -3}, + {36, 48, 14}, + {11, 14, 15}, +}; + +// .14 fixed-point +struct vertex_texture majora_texture[] = { + {11583, 9984}, + {13855, 16384}, + {16352, 31}, + {12704, 13184}, + {0, 31}, + {3647, 13184}, + {2496, 16384}, + {4768, 9984}, + {16223, 0}, + {16384, 16288}, + {3072, 3664}, + {256, 11056}, + {5439, 16415}, + {1679, 15952}, + {5456, 16384}, + {0, 384}, + {672, 16384}, + {4096, 1055}, + {2111, 0}, + {15679, 16384}, + {14240, 0}, + {16352, 384}, + {12256, 1055}, + {13631, 16384}, + {16384, 0}, + {12768, 4768}, + {13184, 10591}, + {0, 0}, + {3167, 10591}, + {2720, 16384}, + {3584, 4768}, + {2399, 16384}, + {6880, 11968}, + {0, 0}, + {4639, 14175}, + {11712, 14175}, + {16384, 0}, + {13951, 16384}, + {9472, 11968}, + {2399, 16384}, + {3968, 8735}, + {0, 0}, + {3167, 12575}, + {13184, 12575}, + {16384, 0}, + {13951, 16384}, + {12383, 8735}, + {10944, 13767}, + {12256, 16384}, + {12256, 11080}, + {12263, 5359}, + {8623, 8960}, + {8192, 12544}, + {8647, 5407}, + {12263, -17}, + {8840, 15552}, + {6792, 16415}, + {4415, 12712}, + {4112, 16440}, + {2976, 13160}, + {9232, 13943}, + {5744, 7960}, + {4112, 4903}, + {6431, 4712}, + {11480, -17}, + {6999, 15016}, +}; + +// .9 fixed-point +struct vertex_normal majora_normal[] = { + {-233, -430, -155}, + {425, 262, -113}, + {107, -155, 476}, + {48, -84, 502}, + {-108, -155, 476}, + {-49, -84, 502}, + {-426, 262, -113}, + {-426, 262, -113}, + {232, -430, -155}, + {232, -430, -155}, + {48, -84, 502}, + {107, -155, 476}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {0, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {-1, 25, -512}, + {-478, 46, -181}, + {-27, 245, 448}, + {444, 184, -176}, + {-12, 75, 506}, + {444, 184, -176}, + {26, 245, 448}, + {11, 75, 506}, + {477, 46, -181}, + {26, 245, 448}, + {477, 46, -181}, + {-445, 184, -176}, + {-445, 184, -176}, + {11, 75, 506}, + {-12, 75, 506}, + {-27, 245, 448}, + {-478, 46, -181}, + {291, 405, -113}, + {142, -104, 480}, + {-79, -479, -165}, + {62, -61, 504}, + {-79, -479, -165}, + {142, -104, 480}, + {-143, -104, 480}, + {-63, -61, 504}, + {-292, 405, -113}, + {-292, 405, -113}, + {78, -479, -165}, + {-143, -104, 480}, + {78, -479, -165}, + {142, -104, 480}, + {291, 405, -113}, + {-475, 155, -112}, + {312, -378, -149}, + {-80, -177, 473}, + {312, -378, -148}, + {-37, -96, 501}, + {-80, -177, 473}, + {36, -96, 501}, + {79, -177, 473}, + {474, 155, -112}, + {-313, -378, -149}, + {474, 155, -112}, + {79, -177, 473}, + {36, -96, 501}, + {-313, -378, -148}, + {-475, 155, -112}, + {-391, 311, -113}, + {187, -450, -159}, + {-121, -143, 476}, + {187, -450, -159}, + {-54, -78, 503}, + {-121, -143, 476}, + {53, -78, 503}, + {120, -143, 476}, + {390, 311, -113}, + {-188, -450, -159}, + {390, 311, -113}, + {120, -143, 476}, + {53, -78, 503}, + {-188, -450, -159}, + {120, -143, 476}, + {-121, -143, 476}, + {-54, -78, 503}, + {-391, 311, -113}, + {-276, 297, 311}, + {0, 398, 321}, + {0, 75, 506}, + {0, -109, 500}, + {-48, -49, 507}, + {0, 74, 506}, + {-26, 46, 509}, + {47, -49, 507}, + {13, -212, 466}, + {0, -355, 369}, + {-1, -109, 500}, + {157, 391, 290}, + {0, 398, 321}, + {85, 425, 271}, + {-243, 93, 441}, + {-211, 346, 312}, + {-417, 7, 297}, + {275, 297, 311}, + {117, 241, 435}, + {416, 7, 297}, + {283, -182, 385}, + {347, -277, 254}, + {-118, 241, 435}, + {25, 46, 509}, + {-252, -339, 290}, + {-284, -182, 385}, + {-348, -277, 254}, + {251, -339, 290}, + {347, -278, 254}, + {-64, 330, 385}, + {85, 425, 271}, + {-211, 346, 312}, + {-26, 46, 509}, + {-417, 7, 297}, + {-348, -277, 254}, + {-158, 391, 290}, + {-86, 425, 271}, + {-86, 425, 271}, + {63, 330, 385}, + {210, 346, 312}, + {210, 346, 312}, + {242, 93, 441}, + {416, 7, 297}, + {25, 46, 509}, + {-1, 74, 506}, + {283, -182, 385}, + {347, -277, 254}, + {0, -355, 369}, + {-348, -278, 254}, + {-14, -212, 466}, + {0, -109, 500}, + {157, 391, 290}, + {275, 297, 311}, + {117, 241, 435}, + {-64, 330, 385}, + {-26, 46, 509}, + {-243, 93, 441}, + {47, -49, 507}, + {-252, -339, 290}, + {-158, 391, 290}, + {-276, 297, 311}, + {25, 46, 509}, + {63, 330, 385}, + {-118, 241, 435}, + {-48, -49, 507}, + {242, 93, 441}, + {-48, -49, 507}, + {251, -339, 290}, + {117, 241, 435}, + {-64, 330, 385}, + {-118, 241, 435}, + {63, 330, 385}, + {-243, 93, 441}, + {210, 346, 312}, + {63, 330, 385}, + {-284, -182, 385}, + {416, 7, 297}, + {13, -212, 466}, + {-14, -212, 466}, +}; + +enum majora_material { + mtl_060067E0, + mtl_060077E0, + mtl_060079E0, + mtl_06007BE0, + mtl_06007DE0, + mtl_06007FE0, +}; + +struct pixel_palette majora_pixel_palette[] = { + [mtl_060067E0] = { + .pixel = { + .start = (uint8_t *)&_binary_060067E0_data_start, + .end = (uint8_t *)&_binary_060067E0_data_end, + .size = (int)&_binary_060067E0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_060067E0_data_pal_start, + .end = (uint8_t *)&_binary_060067E0_data_pal_end, + .size = (int)&_binary_060067E0_data_pal_size, + }, + }, + [mtl_060077E0] = { + .pixel = { + .start = (uint8_t *)&_binary_060077E0_data_start, + .end = (uint8_t *)&_binary_060077E0_data_end, + .size = (int)&_binary_060077E0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_060077E0_data_pal_start, + .end = (uint8_t *)&_binary_060077E0_data_pal_end, + .size = (int)&_binary_060077E0_data_pal_size, + }, + }, + [mtl_060079E0] = { + .pixel = { + .start = (uint8_t *)&_binary_060079E0_data_start, + .end = (uint8_t *)&_binary_060079E0_data_end, + .size = (int)&_binary_060079E0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_060079E0_data_pal_start, + .end = (uint8_t *)&_binary_060079E0_data_pal_end, + .size = (int)&_binary_060079E0_data_pal_size, + }, + }, + [mtl_06007BE0] = { + .pixel = { + .start = (uint8_t *)&_binary_06007BE0_data_start, + .end = (uint8_t *)&_binary_06007BE0_data_end, + .size = (int)&_binary_06007BE0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_06007BE0_data_pal_start, + .end = (uint8_t *)&_binary_06007BE0_data_pal_end, + .size = (int)&_binary_06007BE0_data_pal_size, + }, + }, + [mtl_06007DE0] = { + .pixel = { + .start = (uint8_t *)&_binary_06007DE0_data_start, + .end = (uint8_t *)&_binary_06007DE0_data_end, + .size = (int)&_binary_06007DE0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_06007DE0_data_pal_start, + .end = (uint8_t *)&_binary_06007DE0_data_pal_end, + .size = (int)&_binary_06007DE0_data_pal_size, + }, + }, + [mtl_06007FE0] = { + .pixel = { + .start = (uint8_t *)&_binary_06007FE0_data_start, + .end = (uint8_t *)&_binary_06007FE0_data_end, + .size = (int)&_binary_06007FE0_data_size, + }, + .palette = { + .start = (uint8_t *)&_binary_06007FE0_data_pal_start, + .end = (uint8_t *)&_binary_06007FE0_data_pal_end, + .size = (int)&_binary_06007FE0_data_pal_size, + }, + }, +}; + +struct triangle majora_1_triangle[] = { + { + {2, 0, 0}, + {0, 1, 1}, + {1, 2, 2}, + }, + { + {3, 3, 3}, + {2, 0, 0}, + {1, 2, 2}, + }, + { + {6, 4, 4}, + {4, 5, 5}, + {5, 6, 6}, + }, + { + {5, 6, 7}, + {7, 7, 8}, + {6, 4, 4}, + }, + { + {7, 7, 9}, + {4, 5, 5}, + {6, 4, 4}, + }, + { + {3, 3, 10}, + {1, 2, 11}, + {0, 1, 1}, + }, +}; + +struct object majora_1 = { + .triangle = &majora_1_triangle[0], + .quadrilateral = NULL, + .triangle_count = 6, + .quadrilateral_count = 0, + .material = mtl_06007BE0, +}; + +struct triangle majora_3_triangle[] = { + { + {10, 8, 12}, + {8, 9, 13}, + {9, 10, 14}, + }, + { + {13, 11, 15}, + {11, 12, 15}, + {12, 13, 16}, + }, + { + {16, 14, 17}, + {14, 11, 17}, + {15, 13, 18}, + }, + { + {14, 11, 19}, + {8, 9, 19}, + {17, 10, 19}, + }, + { + {8, 9, 20}, + {13, 11, 20}, + {9, 10, 20}, + }, + { + {11, 12, 21}, + {13, 11, 22}, + {8, 9, 23}, + }, + { + {14, 11, 24}, + {16, 14, 25}, + {8, 9, 23}, + }, + { + {8, 9, 26}, + {10, 8, 12}, + {17, 10, 27}, + }, +}; + +struct object majora_3 = { + .triangle = &majora_3_triangle[0], + .quadrilateral = NULL, + .triangle_count = 8, + .quadrilateral_count = 0, + .material = mtl_06007FE0, +}; + +struct triangle majora_4_triangle[] = { + { + {20, 15, 28}, + {18, 16, 29}, + {19, 17, 30}, + }, + { + {21, 18, 31}, + {19, 17, 32}, + {18, 16, 29}, + }, + { + {24, 19, 33}, + {22, 20, 34}, + {23, 21, 35}, + }, + { + {24, 19, 36}, + {23, 21, 37}, + {25, 22, 38}, + }, + { + {25, 22, 39}, + {22, 20, 40}, + {24, 19, 36}, + }, + { + {21, 18, 41}, + {18, 16, 42}, + {20, 15, 43}, + }, + { + {28, 23, 44}, + {26, 24, 45}, + {27, 25, 46}, + }, + { + {29, 26, 47}, + {27, 25, 48}, + {26, 24, 49}, + }, + { + {32, 27, 50}, + {30, 28, 51}, + {31, 29, 52}, + }, + { + {31, 29, 53}, + {33, 30, 54}, + {32, 27, 55}, + }, + { + {33, 30, 56}, + {30, 28, 51}, + {32, 27, 50}, + }, + { + {29, 26, 47}, + {26, 24, 57}, + {28, 23, 58}, + }, +}; + +struct object majora_4 = { + .triangle = &majora_4_triangle[0], + .quadrilateral = NULL, + .triangle_count = 12, + .quadrilateral_count = 0, + .material = mtl_060077E0, +}; + +struct triangle majora_5_triangle[] = { + { + {36, 31, 59}, + {34, 32, 60}, + {35, 33, 61}, + }, + { + {34, 32, 62}, + {37, 34, 63}, + {35, 33, 64}, + }, + { + {40, 35, 65}, + {38, 36, 66}, + {39, 37, 67}, + }, + { + {41, 38, 68}, + {39, 37, 69}, + {38, 36, 70}, + }, + { + {40, 35, 71}, + {41, 38, 72}, + {38, 36, 66}, + }, + { + {35, 33, 64}, + {37, 34, 63}, + {36, 31, 73}, + }, +}; + +struct object majora_5 = { + .triangle = &majora_5_triangle[0], + .quadrilateral = NULL, + .triangle_count = 6, + .quadrilateral_count = 0, + .material = mtl_06007DE0, +}; + +struct triangle majora_6_triangle[] = { + { + {44, 39, 74}, + {42, 40, 75}, + {43, 41, 76}, + }, + { + {42, 40, 77}, + {45, 42, 78}, + {43, 41, 79}, + }, + { + {48, 43, 80}, + {46, 44, 81}, + {47, 45, 82}, + }, + { + {49, 46, 83}, + {47, 45, 84}, + {46, 44, 85}, + }, + { + {48, 43, 86}, + {49, 46, 87}, + {46, 44, 88}, + }, + { + {43, 41, 89}, + {45, 42, 90}, + {44, 39, 91}, + }, +}; + +struct object majora_6 = { + .triangle = &majora_6_triangle[0], + .quadrilateral = NULL, + .triangle_count = 6, + .quadrilateral_count = 0, + .material = mtl_060079E0, +}; + +struct triangle majora_7_triangle[] = { + { + {52, 47, 92}, + {50, 48, 93}, + {51, 49, 94}, + }, + { + {54, 50, 95}, + {53, 51, 96}, + {51, 49, 97}, + }, + { + {56, 52, 98}, + {55, 51, 99}, + {51, 49, 97}, + }, + { + {58, 53, 100}, + {57, 54, 101}, + {54, 50, 102}, + }, + { + {60, 55, 103}, + {50, 48, 104}, + {59, 56, 105}, + }, + { + {63, 57, 106}, + {61, 58, 107}, + {62, 59, 108}, + }, + { + {65, 47, 109}, + {64, 60, 110}, + {51, 49, 97}, + }, + { + {68, 59, 111}, + {66, 61, 112}, + {67, 62, 113}, + }, + { + {69, 60, 114}, + {52, 47, 92}, + {51, 49, 97}, + }, + { + {70, 52, 115}, + {69, 60, 114}, + {51, 49, 97}, + }, + { + {73, 63, 116}, + {71, 61, 117}, + {72, 62, 118}, + }, + { + {74, 63, 119}, + {57, 64, 101}, + {67, 62, 120}, + }, + { + {50, 48, 93}, + {65, 47, 109}, + {51, 49, 97}, + }, + { + {75, 65, 121}, + {59, 56, 122}, + {61, 58, 123}, + }, + { + {64, 60, 110}, + {56, 52, 124}, + {51, 49, 97}, + }, + { + {71, 61, 117}, + {62, 59, 125}, + {72, 62, 126}, + }, + { + {55, 51, 99}, + {54, 50, 95}, + {51, 49, 97}, + }, + { + {50, 48, 104}, + {76, 55, 127}, + {77, 56, 128}, + }, + { + {77, 56, 129}, + {78, 65, 130}, + {79, 58, 131}, + }, + { + {79, 58, 132}, + {80, 57, 133}, + {68, 59, 134}, + }, + { + {53, 51, 96}, + {70, 52, 135}, + {51, 49, 136}, + }, + { + {66, 61, 137}, + {74, 63, 119}, + {67, 62, 138}, + }, + { + {57, 64, 139}, + {73, 63, 116}, + {72, 62, 140}, + }, + { + {57, 54, 101}, + {81, 53, 141}, + {54, 50, 142}, + }, + { + {50, 48, 104}, + {60, 55, 143}, + {65, 47, 144}, + }, + { + {60, 55, 143}, + {64, 60, 145}, + {65, 47, 144}, + }, + { + {75, 65, 146}, + {56, 52, 147}, + {64, 60, 110}, + }, + { + {63, 57, 148}, + {55, 51, 149}, + {56, 52, 124}, + }, + { + {71, 61, 117}, + {58, 53, 100}, + {55, 51, 149}, + }, + { + {73, 63, 150}, + {57, 54, 101}, + {58, 53, 100}, + }, + { + {76, 55, 151}, + {50, 48, 93}, + {52, 47, 152}, + }, + { + {69, 60, 114}, + {76, 55, 151}, + {52, 47, 152}, + }, + { + {70, 52, 153}, + {78, 65, 154}, + {69, 60, 155}, + }, + { + {53, 51, 156}, + {80, 57, 157}, + {70, 52, 115}, + }, + { + {81, 53, 141}, + {66, 61, 137}, + {53, 51, 158}, + }, + { + {57, 54, 101}, + {74, 63, 159}, + {81, 53, 141}, + }, + { + {64, 60, 160}, + {60, 55, 103}, + {75, 65, 161}, + }, + { + {76, 55, 127}, + {69, 60, 162}, + {78, 65, 130}, + }, + { + {59, 56, 105}, + {75, 65, 121}, + {60, 55, 103}, + }, + { + {78, 65, 163}, + {77, 56, 128}, + {76, 55, 127}, + }, + { + {56, 52, 147}, + {75, 65, 146}, + {63, 57, 164}, + }, + { + {61, 58, 123}, + {63, 57, 164}, + {75, 65, 121}, + }, + { + {78, 65, 154}, + {70, 52, 153}, + {80, 57, 133}, + }, + { + {80, 57, 133}, + {79, 58, 165}, + {78, 65, 166}, + }, + { + {55, 51, 149}, + {63, 57, 164}, + {71, 61, 167}, + }, + { + {80, 57, 133}, + {53, 51, 158}, + {66, 61, 137}, + }, + { + {62, 59, 125}, + {71, 61, 167}, + {63, 57, 164}, + }, + { + {66, 61, 112}, + {68, 59, 168}, + {80, 57, 133}, + }, + { + {54, 50, 95}, + {55, 51, 149}, + {58, 53, 169}, + }, + { + {53, 51, 158}, + {54, 50, 95}, + {81, 53, 170}, + }, + { + {58, 53, 100}, + {71, 61, 117}, + {73, 63, 150}, + }, + { + {66, 61, 137}, + {81, 53, 170}, + {74, 63, 159}, + }, +}; + +struct object majora_7 = { + .triangle = &majora_7_triangle[0], + .quadrilateral = NULL, + .triangle_count = 52, + .quadrilateral_count = 0, + .material = mtl_060067E0, +}; + diff --git a/models/majora.mtl b/models/majora.mtl new file mode 100644 index 0000000..3ed5529 --- /dev/null +++ b/models/majora.mtl @@ -0,0 +1,72 @@ +# Blender 4.1.1 MTL File: 'None' +# www.blender.org + +newmtl mtl_060067E0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 060067E0.png + +newmtl mtl_060077E0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 060077E0.png + +newmtl mtl_060079E0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 060079E0.png + +newmtl mtl_06007BE0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 06007BE0.png + +newmtl mtl_06007DE0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 06007DE0.png + +newmtl mtl_06007FE0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 06007FE0.png + +newmtl mtl_060087E0 +Ns 95.999992 +Ka 1.000000 1.000000 1.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.500000 +d 1.000000 +illum 2 +map_Kd 060087E0.png diff --git a/models/majora.obj b/models/majora.obj new file mode 100644 index 0000000..65eb6db --- /dev/null +++ b/models/majora.obj @@ -0,0 +1,430 @@ +# Blender 4.1.1 +# www.blender.org +mtllib majora.mtl +o 1 +v 0.451172 0.203125 -0.021484 +v 0.652344 -0.129883 -0.038086 +v 0.270508 0.073242 -0.027344 +v 0.361328 0.135742 0.034180 +v -0.361328 0.135742 0.034180 +v -0.451172 0.203125 -0.021484 +v -0.652344 -0.129883 -0.038086 +v -0.270508 0.073242 -0.027344 +vn -0.4545 -0.8383 -0.3012 +vn 0.8303 0.5125 -0.2191 +vn 0.2101 -0.3020 0.9299 +vn 0.0955 -0.1626 0.9821 +vn -0.2101 -0.3020 0.9299 +vn -0.0954 -0.1626 0.9821 +vn -0.8303 0.5125 -0.2191 +vn -0.8302 0.5125 -0.2191 +vn 0.4545 -0.8383 -0.3012 +vn 0.4544 -0.8383 -0.3012 +vn 0.0954 -0.1626 0.9821 +vn 0.2100 -0.3019 0.9299 +vt 0.707031 0.609375 +vt 0.845703 1.000000 +vt 0.998047 0.001953 +vt 0.775391 0.804688 +vt 0.000000 0.001953 +vt 0.222656 0.804688 +vt 0.152344 1.000000 +vt 0.291016 0.609375 +s 0 +usemtl mtl_06007BE0 +f 3/1/1 1/2/2 2/3/3 +f 4/4/4 3/1/1 2/3/3 +f 7/5/5 5/6/6 6/7/7 +f 6/7/8 8/8/9 7/5/5 +f 8/8/10 5/6/6 7/5/5 +f 4/4/11 2/3/12 1/2/2 +o 3 +v 0.000000 0.958008 -0.039062 +v 0.643555 0.322266 -0.070312 +v 0.000000 -0.203125 -0.096680 +v 0.254883 1.076172 -0.033203 +v 0.559570 1.070312 -0.033203 +v 0.765625 0.813476 -0.045898 +v -0.765625 0.813477 -0.045898 +v -0.559570 1.070313 -0.033203 +v -0.254883 1.076172 -0.033203 +v -0.643555 0.322266 -0.070313 +vn -0.0000 0.0496 -0.9988 +vn 0.0002 0.0494 -0.9988 +vn 0.0005 0.0496 -0.9988 +vn 0.0007 0.0497 -0.9988 +vn 0.0010 0.0501 -0.9987 +vn -0.0007 0.0497 -0.9988 +vn -0.0010 0.0501 -0.9987 +vn -0.0004 0.0495 -0.9988 +vn 0.0004 0.0495 -0.9988 +vn 0.0006 0.0494 -0.9988 +vn 0.0005 0.0493 -0.9988 +vn -0.0000 0.0493 -0.9988 +vn -0.0005 0.0494 -0.9988 +vn -0.0006 0.0494 -0.9988 +vn -0.0002 0.0494 -0.9988 +vn -0.0005 0.0496 -0.9988 +vt 0.990234 0.000000 +vt 1.000000 0.994141 +vt 0.187500 0.223633 +vt 0.015625 0.674805 +vt 0.332031 1.001953 +vt 0.102539 0.973633 +vt 0.333008 1.000000 +s 0 +usemtl mtl_06007FE0 +f 11/9/13 9/10/14 10/11/15 +f 14/12/16 12/13/16 13/14/17 +f 17/15/18 15/12/18 16/14/19 +f 15/12/20 9/10/20 18/11/20 +f 9/10/21 14/12/21 10/11/21 +f 12/13/22 14/12/23 9/10/24 +f 15/12/25 17/15/26 9/10/24 +f 9/10/27 11/9/13 18/11/28 +o 4 +v -0.436523 1.492188 0.012695 +v -0.238281 0.990234 -0.011719 +v -0.477539 0.968750 -0.013672 +v -0.353516 0.951172 0.095703 +v 0.353516 0.951172 0.095703 +v 0.477539 0.968750 -0.013672 +v 0.436524 1.492187 0.012695 +v 0.238281 0.990234 -0.011719 +v 1.013672 0.322265 -0.015625 +v 0.566406 0.394531 -0.011719 +v 0.673828 0.570312 -0.002930 +v 0.620117 0.479492 0.051758 +v -0.620117 0.479492 0.051758 +v -0.673828 0.570313 -0.002930 +v -1.013672 0.322266 -0.015625 +v -0.566406 0.394531 -0.011719 +vn -0.9317 0.0907 -0.3517 +vn -0.0513 0.4802 0.8757 +vn 0.8679 0.3594 -0.3428 +vn -0.0218 0.1484 0.9887 +vn 0.8680 0.3594 -0.3426 +vn 0.0512 0.4802 0.8757 +vn 0.0217 0.1483 0.9887 +vn 0.9317 0.0907 -0.3516 +vn 0.0513 0.4802 0.8757 +vn 0.9317 0.0906 -0.3517 +vn -0.8680 0.3594 -0.3428 +vn -0.8680 0.3595 -0.3426 +vn 0.0218 0.1483 0.9887 +vn -0.0217 0.1484 0.9887 +vn -0.0512 0.4802 0.8757 +vn -0.9317 0.0907 -0.3516 +vn 0.5699 0.7920 -0.2191 +vn 0.2787 -0.2021 0.9389 +vn -0.1539 -0.9345 -0.3211 +vn 0.1219 -0.1172 0.9856 +vn -0.1538 -0.9345 -0.3211 +vn 0.2788 -0.2022 0.9388 +vn -0.2788 -0.2022 0.9388 +vn -0.1219 -0.1172 0.9856 +vn -0.5699 0.7920 -0.2190 +vn -0.5699 0.7920 -0.2191 +vn 0.1538 -0.9345 -0.3211 +vn -0.2787 -0.2022 0.9388 +vn 0.1539 -0.9345 -0.3211 +vn 0.2787 -0.2022 0.9388 +vn 0.5698 0.7920 -0.2190 +vt 0.000000 0.023438 +vt 0.041016 1.000000 +vt 0.250000 0.064453 +vt 0.128906 0.000000 +vt 0.957031 1.000000 +vt 0.869141 0.000000 +vt 0.998047 0.023438 +vt 0.748047 0.064453 +vt 0.832031 1.000000 +vt 1.000000 0.000000 +vt 0.779297 0.291016 +vt 0.804688 0.646484 +vt 0.000000 0.000000 +vt 0.193359 0.646484 +vt 0.166016 1.000000 +vt 0.218750 0.291016 +s 0 +usemtl mtl_060077E0 +f 21/16/29 19/17/30 20/18/31 +f 22/19/32 20/18/33 19/17/30 +f 25/20/34 23/21/35 24/22/36 +f 25/20/37 24/22/38 26/23/39 +f 26/23/40 23/21/41 25/20/37 +f 22/19/42 19/17/43 21/16/44 +f 29/24/45 27/25/46 28/26/47 +f 30/27/48 28/26/49 27/25/50 +f 33/28/51 31/29/52 32/30/53 +f 32/30/54 34/31/55 33/28/56 +f 34/31/57 31/29/52 33/28/51 +f 30/27/48 27/25/58 29/24/59 +o 5 +v -0.060547 -0.047852 -0.033203 +v -0.383789 -0.310547 -0.046875 +v -0.270508 0.049805 -0.028320 +v -0.166016 -0.001953 0.027344 +v 0.383789 -0.310547 -0.046875 +v 0.270508 0.049805 -0.028320 +v 0.166016 -0.001953 0.027344 +v 0.060547 -0.047852 -0.033203 +vn -0.9276 0.3030 -0.2185 +vn 0.6111 -0.7368 -0.2891 +vn -0.1552 -0.3452 0.9256 +vn 0.6112 -0.7369 -0.2890 +vn -0.0709 -0.1856 0.9801 +vn -0.1553 -0.3452 0.9256 +vn 0.0709 -0.1856 0.9801 +vn 0.1553 -0.3452 0.9256 +vn 0.9277 0.3029 -0.2185 +vn -0.6111 -0.7369 -0.2891 +vn 0.9276 0.3029 -0.2185 +vn 0.1552 -0.3452 0.9256 +vn 0.0709 -0.1857 0.9800 +vn -0.6111 -0.7369 -0.2890 +vn -0.9277 0.3028 -0.2185 +vt 0.146484 1.000000 +vt 0.419922 0.730469 +vt 0.000000 0.000000 +vt 0.283203 0.865234 +vt 0.714844 0.865234 +vt 1.000000 0.000000 +vt 0.851562 1.000000 +vt 0.578125 0.730469 +s 0 +usemtl mtl_06007DE0 +f 37/32/60 35/33/61 36/34/62 +f 35/33/63 38/35/64 36/34/65 +f 41/36/66 39/37/67 40/38/68 +f 42/39/69 40/38/70 39/37/71 +f 41/36/72 42/39/73 39/37/67 +f 36/34/65 38/35/64 37/32/74 +o 6 +v -0.429688 0.225586 -0.019531 +v -0.836914 0.058594 -0.028320 +v -0.590820 0.372070 -0.012695 +v -0.510742 0.295899 0.042969 +v 0.836914 0.058594 -0.028320 +v 0.590820 0.372070 -0.012695 +v 0.510742 0.295898 0.042969 +v 0.429687 0.225586 -0.019531 +vn -0.7621 0.6093 -0.2193 +vn 0.3665 -0.8775 -0.3094 +vn -0.2348 -0.2774 0.9316 +vn 0.3666 -0.8775 -0.3093 +vn -0.1052 -0.1508 0.9830 +vn -0.2347 -0.2774 0.9316 +vn 0.1051 -0.1507 0.9830 +vn 0.2348 -0.2775 0.9316 +vn 0.7621 0.6092 -0.2192 +vn -0.3665 -0.8775 -0.3094 +vn 0.7621 0.6092 -0.2193 +vn 0.2348 -0.2774 0.9316 +vn 0.1051 -0.1508 0.9830 +vn -0.3665 -0.8775 -0.3093 +vn 0.2347 -0.2775 0.9316 +vn -0.2348 -0.2775 0.9316 +vn -0.1051 -0.1507 0.9830 +vn -0.7621 0.6092 -0.2192 +vt 0.146484 1.000000 +vt 0.242188 0.533203 +vt 0.000000 0.000000 +vt 0.193359 0.767578 +vt 0.804688 0.767578 +vt 1.000000 0.000000 +vt 0.851562 1.000000 +vt 0.755859 0.533203 +s 0 +usemtl mtl_060079E0 +f 45/40/75 43/41/76 44/42/77 +f 43/41/78 46/43/79 44/42/80 +f 49/44/81 47/45/82 48/46/83 +f 50/47/84 48/46/85 47/45/86 +f 49/44/87 50/47/88 47/45/89 +f 44/42/90 46/43/91 45/40/92 +o 7 +v 0.000000 0.958008 -0.039062 +v 0.000000 0.657227 0.215820 +v 0.097656 0.847656 0.176758 +v 0.246094 0.464844 0.268555 +v 0.000000 0.209961 0.107422 +v -0.246094 0.464844 0.268555 +v -0.291992 0.710938 0.281250 +v 0.000000 -0.203125 -0.096680 +v -0.184570 0.228516 0.241211 +v -0.254883 1.076172 -0.033203 +v -0.191406 0.959961 0.111328 +v -0.559570 1.070313 -0.033203 +v -0.765625 0.813477 -0.045898 +v -0.574219 0.756836 0.222656 +v -0.213867 0.839844 0.272461 +v -0.097656 0.847656 0.176758 +v 0.483398 0.388672 0.204102 +v 0.643555 0.322266 -0.070312 +v 0.765625 0.813476 -0.045898 +v 0.213867 0.839844 0.272461 +v 0.291992 0.710937 0.281250 +v -0.483398 0.388672 0.204102 +v -0.643555 0.322266 -0.070313 +v -0.374023 0.221680 0.122070 +v 0.374023 0.221680 0.122070 +v -0.419922 0.952148 0.172852 +v 0.191406 0.959961 0.111328 +v 0.254883 1.076172 -0.033203 +v 0.419922 0.952148 0.172852 +v 0.559570 1.070312 -0.033203 +v 0.574219 0.756836 0.222656 +v 0.184570 0.228516 0.241211 +vn -0.5389 0.5818 0.6091 +vn -0.0000 0.7781 0.6282 +vn -0.0000 0.1465 0.9892 +vn -0.0000 -0.2122 0.9772 +vn -0.0919 -0.0941 0.9913 +vn -0.0000 0.1464 0.9892 +vn -0.0492 0.0905 0.9947 +vn 0.0919 -0.0941 0.9913 +vn 0.0260 -0.4132 0.9103 +vn -0.0000 -0.6929 0.7210 +vn -0.0001 -0.2122 0.9772 +vn 0.3080 0.7641 0.5669 +vn -0.0000 0.7780 0.6282 +vn 0.1670 0.8317 0.5295 +vn -0.4742 0.1822 0.8614 +vn -0.4115 0.6761 0.6113 +vn -0.8131 0.0141 0.5819 +vn 0.5389 0.5818 0.6091 +vn 0.2295 0.4721 0.8511 +vn 0.8131 0.0140 0.5819 +vn 0.5535 -0.3543 0.7537 +vn 0.6778 -0.5410 0.4979 +vn -0.2295 0.4721 0.8511 +vn 0.0493 0.0905 0.9947 +vn -0.4916 -0.6608 0.5671 +vn -0.5535 -0.3544 0.7537 +vn -0.6778 -0.5410 0.4978 +vn 0.4916 -0.6608 0.5671 +vn 0.6778 -0.5411 0.4978 +vn -0.1243 0.6459 0.7532 +vn 0.1669 0.8318 0.5295 +vn -0.4114 0.6761 0.6113 +vn -0.0493 0.0905 0.9947 +vn -0.8131 0.0140 0.5819 +vn -0.6778 -0.5410 0.4979 +vn -0.3080 0.7641 0.5669 +vn -0.1670 0.8317 0.5295 +vn -0.1669 0.8318 0.5295 +vn 0.1243 0.6459 0.7532 +vn 0.4114 0.6761 0.6112 +vn 0.4115 0.6761 0.6112 +vn 0.4741 0.1822 0.8614 +vn 0.8131 0.0141 0.5819 +vn 0.0492 0.0905 0.9947 +vn -0.0001 0.1464 0.9892 +vn 0.5535 -0.3544 0.7537 +vn 0.6778 -0.5410 0.4978 +vn -0.0000 -0.6930 0.7210 +vn -0.6778 -0.5411 0.4978 +vn -0.0260 -0.4132 0.9103 +vn -0.0000 -0.2121 0.9772 +vn 0.3081 0.7640 0.5669 +vn 0.5389 0.5819 0.6091 +vn 0.2295 0.4722 0.8511 +vn -0.1243 0.6458 0.7533 +vn -0.0493 0.0906 0.9947 +vn -0.4741 0.1821 0.8614 +vn 0.0918 -0.0941 0.9913 +vn -0.4916 -0.6608 0.5672 +vn -0.3081 0.7640 0.5669 +vn -0.5389 0.5819 0.6091 +vn 0.0493 0.0906 0.9947 +vn 0.1243 0.6458 0.7533 +vn -0.2295 0.4721 0.8512 +vn -0.0918 -0.0940 0.9913 +vn 0.4741 0.1821 0.8614 +vn -0.0918 -0.0941 0.9913 +vn 0.4916 -0.6608 0.5672 +vn 0.2294 0.4722 0.8511 +vn -0.1243 0.6459 0.7533 +vn -0.2294 0.4722 0.8511 +vn 0.1242 0.6459 0.7533 +vn -0.4741 0.1822 0.8614 +vn 0.4114 0.6761 0.6113 +vn 0.1243 0.6459 0.7533 +vn -0.5535 -0.3543 0.7537 +vn 0.8131 0.0140 0.5820 +vn 0.0260 -0.4133 0.9102 +vn -0.0260 -0.4133 0.9102 +vt 0.667969 0.840332 +vt 0.748047 1.000000 +vt 0.748047 0.676270 +vt 0.748535 0.327148 +vt 0.526367 0.546875 +vt 0.500000 0.765625 +vt 0.527832 0.330078 +vt 0.748535 -0.000977 +vt 0.539551 0.949219 +vt 0.414551 1.001953 +vt 0.269531 0.775879 +vt 0.250977 1.003418 +vt 0.181641 0.803223 +vt 0.563477 0.851074 +vt 0.350586 0.485840 +vt 0.250977 0.299316 +vt 0.392578 0.287598 +vt 0.700684 -0.000977 +vt 0.427246 0.916504 +s 0 +usemtl mtl_060067E0 +f 53/48/93 51/49/94 52/50/95 +f 55/51/96 54/52/97 52/50/98 +f 57/53/99 56/52/100 52/50/98 +f 59/54/101 58/55/102 55/51/103 +f 61/56/104 51/49/105 60/57/106 +f 64/58/107 62/59/108 63/60/109 +f 66/48/110 65/61/111 52/50/98 +f 69/60/112 67/62/113 68/63/114 +f 70/61/115 53/48/93 52/50/98 +f 71/53/116 70/61/115 52/50/98 +f 74/64/117 72/62/118 73/63/119 +f 75/64/120 58/65/102 68/63/121 +f 51/49/94 66/48/110 52/50/98 +f 76/66/122 60/57/123 62/59/124 +f 65/61/111 57/53/125 52/50/98 +f 72/62/118 63/60/126 73/63/127 +f 56/52/100 55/51/96 52/50/98 +f 51/49/105 77/56/128 78/57/129 +f 78/57/130 79/66/131 80/59/132 +f 80/59/133 81/58/134 69/60/135 +f 54/52/97 71/53/136 52/50/137 +f 67/62/138 75/64/120 68/63/139 +f 58/65/140 74/64/117 73/63/141 +f 58/55/102 82/54/142 55/51/143 +f 51/49/105 61/56/144 66/48/145 +f 61/56/144 65/61/146 66/48/145 +f 76/66/147 57/53/148 65/61/111 +f 64/58/149 56/52/150 57/53/125 +f 72/62/118 59/54/101 56/52/150 +f 74/64/151 58/55/102 59/54/101 +f 77/56/152 51/49/94 53/48/153 +f 70/61/115 77/56/152 53/48/153 +f 71/53/154 79/66/155 70/61/156 +f 54/52/157 81/58/158 71/53/116 +f 82/54/142 67/62/138 54/52/159 +f 58/55/102 75/64/160 82/54/142 +f 65/61/161 61/56/104 76/66/162 +f 77/56/128 70/61/163 79/66/131 +f 60/57/106 76/66/122 61/56/104 +f 79/66/164 78/57/129 77/56/128 +f 57/53/148 76/66/147 64/58/165 +f 62/59/124 64/58/165 76/66/122 +f 79/66/155 71/53/154 81/58/134 +f 81/58/134 80/59/166 79/66/167 +f 56/52/150 64/58/165 72/62/168 +f 81/58/134 54/52/159 67/62/138 +f 63/60/126 72/62/168 64/58/165 +f 67/62/113 69/60/169 81/58/134 +f 55/51/96 56/52/150 59/54/170 +f 54/52/159 55/51/96 82/54/171 +f 59/54/101 72/62/118 74/64/151 +f 67/62/138 82/54/171 75/64/160 diff --git a/models/model.h b/models/model.h index 1bd1d2e..89545bc 100644 --- a/models/model.h +++ b/models/model.h @@ -22,18 +22,37 @@ struct quadrilateral { }; struct vertex_position { // signed 4.6 fixed point - uint16_t x; - uint16_t y; - uint16_t z; + int16_t x; + int16_t y; + int16_t z; }; struct vertex_normal { // s.9 fixed point - uint16_t x; - uint16_t y; - uint16_t z; + int16_t x; + int16_t y; + int16_t z; }; struct vertex_texture { // s.15 fixed point - uint16_t u; - uint16_t v; + int16_t u; + int16_t v; +}; + +struct object { + struct triangle * triangle; + struct quadrilateral * quadrilateral; + int triangle_count; + int quadrilateral_count; + int material; +}; + +struct start_size_end { + uint8_t * start; + uint8_t * end; + int size; +}; + +struct pixel_palette { + struct start_size_end pixel; + struct start_size_end palette; }; diff --git a/models/parse_material.py b/models/parse_material.py new file mode 100644 index 0000000..ced6923 --- /dev/null +++ b/models/parse_material.py @@ -0,0 +1,47 @@ +from dataclasses import dataclass + +@dataclass +class NewMtl: + name: str + +@dataclass +class MapKd: + name: str + +def parse_material_newmtl(args): + name, = args.split() + yield NewMtl(name) + +def parse_material_mapkd(args): + name, = args.split() + yield MapKd(name) + +def parse_mtl_line(line): + prefixes = [ + ('newmtl ', parse_material_newmtl), + ('map_Kd ', parse_material_mapkd), + ] + for prefix, parser in prefixes: + if line.startswith(prefix): + args = line.removeprefix(prefix) + yield from parser(args) + +def group_by_material(l): + current_material = None + for i in l: + if type(i) is NewMtl: + current_material = i + elif type(i) is MapKd: + assert current_material is not None + yield (current_material, i) + current_material = None + else: + assert False, type(i) + +def parse_mtl_file(buf): + return list(group_by_material(( + parsed + for line in buf.strip().split('\n') + for parsed in parse_mtl_line(line) + if not line.startswith('#') + ))) diff --git a/models/parse_obj_fixed_point.py b/models/parse_obj_fixed_point.py index 2ac7b18..f2f29ce 100644 --- a/models/parse_obj_fixed_point.py +++ b/models/parse_obj_fixed_point.py @@ -45,6 +45,19 @@ class Quadrilateral: c: IndexVTN d: IndexVTN +@dataclass +class Object: + name: str + +@dataclass +class Material: + lib: str + name: str + +@dataclass +class MtlLib: + name: str + def parse_fixed_point(s): negative = s.startswith('-') s = s.removeprefix('-') @@ -81,7 +94,7 @@ def int_minus_one(s): assert n >= 0 return n -def parse_vertex_indices(args): +def _parse_vertex_indices(args): indices = args.split('/') assert len(indices) == 3, indices return IndexVTN(*map(int_minus_one, indices)) @@ -89,18 +102,33 @@ def parse_vertex_indices(args): def parse_face(args): vertices = args.split() if len(vertices) == 3: - yield Triangle(*map(parse_vertex_indices, vertices)) + yield Triangle(*map(_parse_vertex_indices, vertices)) elif len(vertices) == 4: - yield Quadrilateral(*map(parse_vertex_indices, vertices)) + yield Quadrilateral(*map(_parse_vertex_indices, vertices)) else: assert False, (len(vertices), args) +def parse_object(args): + name, = args.split() + yield Object(name) + +def parse_material(args): + name, = args.split() + yield Material(None, name) + +def parse_mtllib(args): + name, = args.split() + yield MtlLib(name) + def parse_obj_line(line): prefixes = [ ('v ', parse_vertex_position), ('vn ', parse_vertex_normal), ('vt ', parse_vertex_texture), - ('f ', parse_face) + ('f ', parse_face), + ('o ', parse_object), + ('usemtl ', parse_material), + ('mtllib ', parse_mtllib), ] for prefix, parser in prefixes: if line.startswith(prefix): @@ -108,10 +136,31 @@ def parse_obj_line(line): yield from parser(args) def group_by_type(l): - grouped = defaultdict(list) + vertices = defaultdict(list) + current_object = None + faces = defaultdict(lambda: defaultdict(list)) + materials = dict() + current_mtllib = None for i in l: - grouped[type(i)].append(i) - return dict(grouped) + if type(i) in {VertexPosition, VertexTexture, VertexNormal}: + vertices[type(i)].append(i) + elif type(i) in {Triangle, Quadrilateral}: + assert current_object is not None + faces[current_object.name][type(i)].append(i) + elif type(i) is Material: + assert current_object is not None + assert current_mtllib is not None + i.lib = current_mtllib.name + assert current_object.name not in materials + materials[current_object.name] = i + elif type(i) is Object: + current_object = i + elif type(i) is MtlLib: + current_mtllib = i + else: + assert False, type(i) + + return dict(vertices), dict((k, dict(v)) for k, v in faces.items()), materials def parse_obj_file(buf): return group_by_type(( diff --git a/models/render_obj_fixed_point_c_source.py b/models/render_obj_fixed_point_c_source.py index 6e50c2d..818047c 100644 --- a/models/render_obj_fixed_point_c_source.py +++ b/models/render_obj_fixed_point_c_source.py @@ -9,9 +9,11 @@ from parse_obj_fixed_point import VertexTexture from parse_obj_fixed_point import Triangle from parse_obj_fixed_point import Quadrilateral +from parse_material import parse_mtl_file + vertex_position_fraction_bits = 6 # 4.6 vertex_normal_fraction_bits = 9 # s.9 -vertex_texture_fraction_bits = 15 # s.15 +vertex_texture_fraction_bits = 14 # s.15 def convert_fixed_point(fp, fraction_bits): point = 2 ** fraction_bits @@ -31,7 +33,7 @@ def render_face(face): yield "}," def render_faces(prefix, name, faces): - yield f"struct {name} {prefix}_{name}s[] = {{" + yield f"struct {name} {prefix}_{name}[] = {{" for face in faces: yield from render_face(face) yield "};" @@ -57,7 +59,7 @@ def render_vertex(vertex_tuple, fraction_bits): def render_vertices(prefix, name, vertices, fraction_bits): yield f"// .{fraction_bits} fixed-point" - yield f"struct vertex_{name} {prefix}_{name}s[] = {{" + yield f"struct vertex_{name} {prefix}_{name}[] = {{" for vertex in vertices: yield from render_vertex(vertex, fraction_bits) yield "};" @@ -80,6 +82,61 @@ def render_vertex_texture(prefix, vertex_textures): map(uv, vertex_textures), vertex_texture_fraction_bits) +def render_object(prefix, object_name, d, material): + yield f"struct object {prefix}_{object_name} = {{" + + triangle_count = len(d[Triangle]) if Triangle in d else 0 + quadrilateral_count = len(d[Quadrilateral]) if Quadrilateral in d else 0 + + if triangle_count > 0: + yield f".triangle = &{prefix}_{object_name}_triangle[0]," + else: + yield f".triangle = NULL," + + if quadrilateral_count > 0: + yield f".quadrilateral = &{prefix}_{object_name}_quadrilateral[0]," + else: + yield f".quadrilateral = NULL," + + yield f".triangle_count = {triangle_count}," + yield f".quadrilateral_count = {quadrilateral_count}," + + if material is None: + yield f".material = -1,", + else: + yield f".material = {material.name}," + + yield "};" + +def render_pixel_palette(prefix, newmtl, mapkd): + name, _ext = mapkd.name.rsplit('.', maxsplit=1) + pixel_name = f"{name}_data" + palette_name = f"{name}_data_pal" + + yield f"[{newmtl.name}] = {{" + yield ".pixel = {" + yield f".start = (uint8_t *)&_binary_{pixel_name}_start," + yield f".end = (uint8_t *)&_binary_{pixel_name}_end," + yield f".size = (int)&_binary_{pixel_name}_size," + yield "}," + yield ".palette = {" + yield f".start = (uint8_t *)&_binary_{palette_name}_start," + yield f".end = (uint8_t *)&_binary_{palette_name}_end," + yield f".size = (int)&_binary_{palette_name}_size," + yield "}," + yield "}," + +def render_materials(prefix, newmtl_mapkd): + yield f"enum {prefix}_material {{" + for newmtl, mapkd in newmtl_mapkd: + yield f"{newmtl.name},"; + yield "};" + + yield f"struct pixel_palette {prefix}_pixel_palette[] = {{" + for newmtl, mapkd in newmtl_mapkd: + yield from render_pixel_palette(prefix, newmtl, mapkd) + yield "};" + def render_header(): yield '#include "model.h"' yield "" @@ -88,14 +145,37 @@ with open(sys.argv[1]) as f: buf = f.read() prefix = sys.argv[2] -d = parse_obj_file(buf) +vertices, faces, materials = parse_obj_file(buf) render, out = renderer() render(render_header()) -render(render_vertex_positions(prefix, d[VertexPosition])) -render(render_vertex_texture(prefix, d[VertexTexture])) -render(render_vertex_normals(prefix, d[VertexNormal])) -if Triangle in d: - render(render_triangles(prefix, d[Triangle])) -if Quadrilateral in d: - render(render_quadrilateral(prefix, d[Quadrilateral])) +render(render_vertex_positions(prefix, vertices[VertexPosition])) +render(render_vertex_texture(prefix, vertices[VertexTexture])) +render(render_vertex_normals(prefix, vertices[VertexNormal])) + +materials_by_lib_name = set((m.lib, m.name) for m in materials.values()) +material_names = set() +for _, name in materials_by_lib_name: + assert name not in material_names + material_names.add(name) +material_libs = set(lib for lib, _ in materials_by_lib_name) +for material_lib in material_libs: + with open(material_lib) as f: + buf = f.read() + newmtl_mapkd = [ + (newmtl, mapkd) + for (newmtl, mapkd) in parse_mtl_file(buf) + if newmtl.name in material_names + ] + render(render_materials(prefix, newmtl_mapkd)) + +for object_name, d in faces.items(): + object_prefix = '_'.join((prefix, object_name)) + + if Triangle in d: + render(render_triangles(object_prefix, d[Triangle])) + if Quadrilateral in d: + render(render_quadrilateral(object_prefix, d[Quadrilateral])) + + render(render_object(prefix, object_name, d, materials.get(object_name))); + sys.stdout.write(out.getvalue()) diff --git a/models/verify_fixed_point.py b/models/verify_fixed_point.py new file mode 100644 index 0000000..869aaf7 --- /dev/null +++ b/models/verify_fixed_point.py @@ -0,0 +1,51 @@ +import sys + +from parse_obj_fixed_point import parse_obj_file +from parse_obj_fixed_point import VertexPosition +from parse_obj_fixed_point import VertexNormal +from parse_obj_fixed_point import VertexTexture +from parse_obj_fixed_point import Triangle + +def convert_fixed_point(fp, fraction_bits): + point = 2 ** fraction_bits + sign = -1 if fp.negative else 1 + n0 = sign * (fp.integer * fp.point + fp.fraction) + n1 = n0 * point // fp.point + return n1 + +from pprint import pprint + +with open(sys.argv[1]) as f: + buf = f.read() + +vertices, faces, materials = parse_obj_file(buf) + +position = vertices[VertexPosition] +texture = vertices[VertexTexture] +normal = vertices[VertexNormal] + +def flt(fp): + sign = -1 if fp.negative else 1 + return sign * (fp.integer + fp.fraction / fp.point) + +for object_name, d in faces.items(): + if object_name != '3': + continue + triangle = d[Triangle] + for t in triangle: + at = texture[t.a.vertex_texture] + bt = texture[t.b.vertex_texture] + ct = texture[t.c.vertex_texture] + print((flt(at.u), flt(at.v)), + (flt(bt.u), flt(bt.v)), + (flt(ct.u), flt(ct.v))) + + verts = [at, bt, ct] + + pprint([ + (convert_fixed_point(t.u, 15), convert_fixed_point(t.v, 15)) for t in verts + ]) + + pprint([ + [((convert_fixed_point(c, 15) * 31) >> 11) // (2 ** 4) for c in [t.u, t.v]] for t in verts + ]) diff --git a/registers/graphics_engine_bits.csv b/registers/graphics_engine_bits.csv index cd4a355..9c1513e 100644 --- a/registers/graphics_engine_bits.csv +++ b/registers/graphics_engine_bits.csv @@ -285,7 +285,7 @@ "TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","do_not_transform_texture_coordinates","0b00",, "TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","texcoord_source","0b01",, "TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","normal_source","0b10",, -"TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","vextex_source","0b11",, +"TEXIMAGE_PARAM","texture_coordinate_transformation_mode","31-30","vertex_source","0b11",, "TEXIMAGE_PARAM","palette_color0_transparency",29,"palette_setting",0,, "TEXIMAGE_PARAM","palette_color0_transparency",29,"always_transparent",1,, "TEXIMAGE_PARAM","texture_format","28-26","no_texture",0,, diff --git a/registers/graphics_engine_bits.ods b/registers/graphics_engine_bits.ods index 171c391..9b0f2bd 100644 Binary files a/registers/graphics_engine_bits.ods and b/registers/graphics_engine_bits.ods differ diff --git a/res/060067E0.data b/res/060067E0.data new file mode 100644 index 0000000..22fcf45 Binary files /dev/null and b/res/060067E0.data differ diff --git a/res/060067E0.data.h b/res/060067E0.data.h new file mode 100644 index 0000000..18644fb --- /dev/null +++ b/res/060067E0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060067E0_data_start __asm("_binary_060067E0_data_start"); +extern uint32_t _binary_060067E0_data_end __asm("_binary_060067E0_data_end"); +extern uint32_t _binary_060067E0_data_size __asm("_binary_060067E0_data_size"); diff --git a/res/060067E0.data.pal b/res/060067E0.data.pal new file mode 100644 index 0000000..687ba9f Binary files /dev/null and b/res/060067E0.data.pal differ diff --git a/res/060067E0.data.pal.h b/res/060067E0.data.pal.h new file mode 100644 index 0000000..4ef7b76 --- /dev/null +++ b/res/060067E0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060067E0_data_pal_start __asm("_binary_060067E0_data_pal_start"); +extern uint32_t _binary_060067E0_data_pal_end __asm("_binary_060067E0_data_pal_end"); +extern uint32_t _binary_060067E0_data_pal_size __asm("_binary_060067E0_data_pal_size"); diff --git a/res/060067E0.png b/res/060067E0.png new file mode 100644 index 0000000..d6e93a5 Binary files /dev/null and b/res/060067E0.png differ diff --git a/res/060077E0.data b/res/060077E0.data new file mode 100644 index 0000000..ddff5c7 Binary files /dev/null and b/res/060077E0.data differ diff --git a/res/060077E0.data.h b/res/060077E0.data.h new file mode 100644 index 0000000..b5ec90c --- /dev/null +++ b/res/060077E0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060077E0_data_start __asm("_binary_060077E0_data_start"); +extern uint32_t _binary_060077E0_data_end __asm("_binary_060077E0_data_end"); +extern uint32_t _binary_060077E0_data_size __asm("_binary_060077E0_data_size"); diff --git a/res/060077E0.data.pal b/res/060077E0.data.pal new file mode 100644 index 0000000..42ff69e --- /dev/null +++ b/res/060077E0.data.pal @@ -0,0 +1 @@ +hX(h \ No newline at end of file diff --git a/res/060077E0.data.pal.h b/res/060077E0.data.pal.h new file mode 100644 index 0000000..653b0b1 --- /dev/null +++ b/res/060077E0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060077E0_data_pal_start __asm("_binary_060077E0_data_pal_start"); +extern uint32_t _binary_060077E0_data_pal_end __asm("_binary_060077E0_data_pal_end"); +extern uint32_t _binary_060077E0_data_pal_size __asm("_binary_060077E0_data_pal_size"); diff --git a/res/060077E0.png b/res/060077E0.png new file mode 100644 index 0000000..38ee69a Binary files /dev/null and b/res/060077E0.png differ diff --git a/res/060079E0.data b/res/060079E0.data new file mode 100644 index 0000000..ddff5c7 Binary files /dev/null and b/res/060079E0.data differ diff --git a/res/060079E0.data.h b/res/060079E0.data.h new file mode 100644 index 0000000..56cb892 --- /dev/null +++ b/res/060079E0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060079E0_data_start __asm("_binary_060079E0_data_start"); +extern uint32_t _binary_060079E0_data_end __asm("_binary_060079E0_data_end"); +extern uint32_t _binary_060079E0_data_size __asm("_binary_060079E0_data_size"); diff --git a/res/060079E0.data.pal b/res/060079E0.data.pal new file mode 100644 index 0000000..395433c --- /dev/null +++ b/res/060079E0.data.pal @@ -0,0 +1 @@ +hh \ No newline at end of file diff --git a/res/060079E0.data.pal.h b/res/060079E0.data.pal.h new file mode 100644 index 0000000..17ecfc7 --- /dev/null +++ b/res/060079E0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060079E0_data_pal_start __asm("_binary_060079E0_data_pal_start"); +extern uint32_t _binary_060079E0_data_pal_end __asm("_binary_060079E0_data_pal_end"); +extern uint32_t _binary_060079E0_data_pal_size __asm("_binary_060079E0_data_pal_size"); diff --git a/res/060079E0.png b/res/060079E0.png new file mode 100644 index 0000000..50f84e4 Binary files /dev/null and b/res/060079E0.png differ diff --git a/res/06007BE0.data b/res/06007BE0.data new file mode 100644 index 0000000..dc01920 Binary files /dev/null and b/res/06007BE0.data differ diff --git a/res/06007BE0.data.h b/res/06007BE0.data.h new file mode 100644 index 0000000..7e829c4 --- /dev/null +++ b/res/06007BE0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007BE0_data_start __asm("_binary_06007BE0_data_start"); +extern uint32_t _binary_06007BE0_data_end __asm("_binary_06007BE0_data_end"); +extern uint32_t _binary_06007BE0_data_size __asm("_binary_06007BE0_data_size"); diff --git a/res/06007BE0.data.pal b/res/06007BE0.data.pal new file mode 100644 index 0000000..fe8bb58 --- /dev/null +++ b/res/06007BE0.data.pal @@ -0,0 +1 @@ + PHXhؐ \ No newline at end of file diff --git a/res/06007BE0.data.pal.h b/res/06007BE0.data.pal.h new file mode 100644 index 0000000..23c3573 --- /dev/null +++ b/res/06007BE0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007BE0_data_pal_start __asm("_binary_06007BE0_data_pal_start"); +extern uint32_t _binary_06007BE0_data_pal_end __asm("_binary_06007BE0_data_pal_end"); +extern uint32_t _binary_06007BE0_data_pal_size __asm("_binary_06007BE0_data_pal_size"); diff --git a/res/06007BE0.png b/res/06007BE0.png new file mode 100644 index 0000000..e3673ac Binary files /dev/null and b/res/06007BE0.png differ diff --git a/res/06007DE0.data b/res/06007DE0.data new file mode 100644 index 0000000..f63467b Binary files /dev/null and b/res/06007DE0.data differ diff --git a/res/06007DE0.data.h b/res/06007DE0.data.h new file mode 100644 index 0000000..5876ba2 --- /dev/null +++ b/res/06007DE0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007DE0_data_start __asm("_binary_06007DE0_data_start"); +extern uint32_t _binary_06007DE0_data_end __asm("_binary_06007DE0_data_end"); +extern uint32_t _binary_06007DE0_data_size __asm("_binary_06007DE0_data_size"); diff --git a/res/06007DE0.data.pal b/res/06007DE0.data.pal new file mode 100644 index 0000000..bafcd84 --- /dev/null +++ b/res/06007DE0.data.pal @@ -0,0 +1 @@ +@`PxX`pȘؘ \ No newline at end of file diff --git a/res/06007DE0.data.pal.h b/res/06007DE0.data.pal.h new file mode 100644 index 0000000..907eb60 --- /dev/null +++ b/res/06007DE0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007DE0_data_pal_start __asm("_binary_06007DE0_data_pal_start"); +extern uint32_t _binary_06007DE0_data_pal_end __asm("_binary_06007DE0_data_pal_end"); +extern uint32_t _binary_06007DE0_data_pal_size __asm("_binary_06007DE0_data_pal_size"); diff --git a/res/06007DE0.png b/res/06007DE0.png new file mode 100644 index 0000000..fa1a909 Binary files /dev/null and b/res/06007DE0.png differ diff --git a/res/06007FE0.data b/res/06007FE0.data new file mode 100644 index 0000000..1f0d0e0 Binary files /dev/null and b/res/06007FE0.data differ diff --git a/res/06007FE0.data.h b/res/06007FE0.data.h new file mode 100644 index 0000000..1700b55 --- /dev/null +++ b/res/06007FE0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007FE0_data_start __asm("_binary_06007FE0_data_start"); +extern uint32_t _binary_06007FE0_data_end __asm("_binary_06007FE0_data_end"); +extern uint32_t _binary_06007FE0_data_size __asm("_binary_06007FE0_data_size"); diff --git a/res/06007FE0.data.pal b/res/06007FE0.data.pal new file mode 100644 index 0000000..0338b00 Binary files /dev/null and b/res/06007FE0.data.pal differ diff --git a/res/06007FE0.data.pal.h b/res/06007FE0.data.pal.h new file mode 100644 index 0000000..c7b527f --- /dev/null +++ b/res/06007FE0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_06007FE0_data_pal_start __asm("_binary_06007FE0_data_pal_start"); +extern uint32_t _binary_06007FE0_data_pal_end __asm("_binary_06007FE0_data_pal_end"); +extern uint32_t _binary_06007FE0_data_pal_size __asm("_binary_06007FE0_data_pal_size"); diff --git a/res/06007FE0.png b/res/06007FE0.png new file mode 100644 index 0000000..b3e3972 Binary files /dev/null and b/res/06007FE0.png differ diff --git a/res/060087E0.data b/res/060087E0.data new file mode 100644 index 0000000..bc22d71 Binary files /dev/null and b/res/060087E0.data differ diff --git a/res/060087E0.data.h b/res/060087E0.data.h new file mode 100644 index 0000000..04704a1 --- /dev/null +++ b/res/060087E0.data.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060087E0_data_start __asm("_binary_060087E0_data_start"); +extern uint32_t _binary_060087E0_data_end __asm("_binary_060087E0_data_end"); +extern uint32_t _binary_060087E0_data_size __asm("_binary_060087E0_data_size"); diff --git a/res/060087E0.data.pal b/res/060087E0.data.pal new file mode 100644 index 0000000..53e65a2 Binary files /dev/null and b/res/060087E0.data.pal differ diff --git a/res/060087E0.data.pal.h b/res/060087E0.data.pal.h new file mode 100644 index 0000000..b033e5a --- /dev/null +++ b/res/060087E0.data.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_060087E0_data_pal_start __asm("_binary_060087E0_data_pal_start"); +extern uint32_t _binary_060087E0_data_pal_end __asm("_binary_060087E0_data_pal_end"); +extern uint32_t _binary_060087E0_data_pal_size __asm("_binary_060087E0_data_pal_size"); diff --git a/res/060087E0.png b/res/060087E0.png new file mode 100644 index 0000000..a1cadcf Binary files /dev/null and b/res/060087E0.png differ