diff --git a/minecraft/configuration.idx b/minecraft/configuration.idx index ef1ac34..58df8cc 100644 Binary files a/minecraft/configuration.idx and b/minecraft/configuration.idx differ diff --git a/minecraft/gen/blocks.py b/minecraft/gen/blocks.py index e877391..f50d99d 100644 --- a/minecraft/gen/blocks.py +++ b/minecraft/gen/blocks.py @@ -1,98 +1,7 @@ import struct -def id_to_px(i): - x = i % 16 - y = i // 16 - return x * 16, y * 16 - -def px_to_id(px, py): - x = px // 16 - y = py // 16 - i = y * 16 + x - return i - unk = 185 -mapping = [ - (1, 1, "stone"), - (2, 0, "grass"), - (31, 0, "grass"), # fixme actually tallgrass - (3, 2, "dirt"), - (4, 16, "stonebrick"), - (5, 4, "wood"), - (6, 15, "sapling"), - (7, 17, "bedrock"), - (8, 205, "water"), # flowing - (9, 205, "water"), # still - (10, 237, "lava"), # flowing - (11, 237, "lava"), # still - (12, 18, "sand"), - (13, 19, "gravel"), - (14, 32, "oreGold"), - (15, 33, "oreIron"), - (16, 34, "oreCoal"), - (17, 20, "log"), - (18, 52, "leaves"), - (19, 48, "sponge"), - (20, 49, "glass"), - (35, 64, "cloth"), - (37, 13, "flower"), - (38, 12, "rose"), - (39, 29, "mushroom"), - (40, 28, "mushroom"), - (41, 39, "blockGold"), - (42, 38, "blockIron"), - (43, 5, "stoneSlab"), # double - (44, 5, "stoneSlab"), # single - (45, 7, "brick"), - (46, 8, "tnt"), - (47, 35, "bookshelf"), - (48, 36, "stoneMoss"), - (49, 37, "obsidian"), - (50, 80, "torch"), - (51, 31, "fire"), - (52, 65, "mobSpawner"), - (53, 4, "stairsWood"), - (54, 27, "chest"), - (55, 84, "redstoneDust"), - (56, 50, "oreDiamond"), - (57, 40, "blockDiamond"), - (58, 43, "workbench"), - (59, 88, "crops"), - (60, 87, "farmland"), - (61, 44, "furnace"), # off - (62, 61, "furnace"), # burning - (63, unk, "sign"), - (64, 81, "doorWood"), - (65, 83, "ladder"), - (66, 128, "rail"), - (67, 16, "stairsStone"), - (68, unk, "sign"), - (69, 96, "lever"), - (70, 6, "pressurePlate"), - (71, 82, "doorIron"), - (72, 6, "pressurePlate"), - (73, 51, "oreRedstone"), - (74, 51, "oreRedstone"), - (75, 115, "notGate"), - (76, 99, "notGate"), - (77, unk, "button"), - (78, 66, "snow"), - (79, 67, "ice"), - (80, 66, "snow"), - (81, 70, "cactus"), - (82, 72, "clay"), - (83, 73, "reeds"), - (84, 74, "jukebox"), - (85, 4, "fence"), - (86, 102, "pumpkin"), - (87, 103, "hellrock"), - (88, 104, "hellsand"), - (89, 105, "lightgem"), - (90, 14, "portal"), - (91, 102, "pumpkin"), -] - lookup = { k: v for k, v, _ in mapping } diff --git a/minecraft/gen/cube.obj b/minecraft/gen/cube.obj new file mode 100644 index 0000000..6b1c27f --- /dev/null +++ b/minecraft/gen/cube.obj @@ -0,0 +1,36 @@ +# Blender 5.0.0 +# www.blender.org +o Cube +v 1.000000 1.000000 -1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +v -1.000000 -1.000000 -1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -1.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 1.000000 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +vt -0.000000 0.000000 +vt 1.000000 -0.000000 +s 0 +f 5/1/1 3/2/1 1/3/1 +f 3/4/2 8/5/2 4/6/2 +f 7/4/3 6/5/3 8/6/3 +f 2/1/4 8/2/4 6/3/4 +f 1/4/5 4/5/5 2/6/5 +f 5/4/6 2/5/6 6/6/6 +f 5/1/1 7/4/1 3/2/1 +f 3/4/2 7/2/2 8/5/2 +f 7/4/3 5/2/3 6/5/3 +f 2/1/4 4/4/4 8/2/4 +f 1/4/5 3/2/5 4/5/5 +f 5/4/6 1/2/6 2/5/6 diff --git a/minecraft/gen/cube.py b/minecraft/gen/cube.py deleted file mode 100644 index c771311..0000000 --- a/minecraft/gen/cube.py +++ /dev/null @@ -1,134 +0,0 @@ -positions = [ - (1.0, 1.0, -1.0), - (1.0, -1.0, -1.0), - (1.0, 1.0, 1.0), - (1.0, -1.0, 1.0), - (-1.0, 1.0, -1.0), - (-1.0, -1.0, -1.0), - (-1.0, 1.0, 1.0), - (-1.0, -1.0, 1.0) -] - -normals = [ - (0.0, 1.0, 0.0), - (0.0, 0.0, 1.0), - (-1.0, 0.0, 0.0), - (0.0, -1.0, 0.0), - (1.0, 0.0, 0.0), - (0.0, 0.0, -1.0), -] - -textures = [ - (1.0, 0.0), - (0.0, 1.0), - (0.0, 0.0), - (1.0, 1.0), - (0.0, 0.0), - (1.0, 0.0), -] - -indices = [ - [ - [4, 0, 0], - [2, 1, 0], - [0, 2, 0], - ], - [ - [2, 3, 1], - [7, 4, 1], - [3, 5, 1], - ], - [ - [6, 3, 2], - [5, 4, 2], - [7, 5, 2], - ], - [ - [1, 0, 3], - [7, 1, 3], - [5, 2, 3], - ], - [ - [0, 3, 4], - [3, 4, 4], - [1, 5, 4], - ], - [ - [4, 3, 5], - [1, 4, 5], - [5, 5, 5], - ], - [ - [4, 0, 0], - [6, 3, 0], - [2, 1, 0], - ], - [ - [2, 3, 1], - [6, 1, 1], - [7, 4, 1], - ], - [ - [6, 3, 2], - [4, 1, 2], - [5, 4, 2], - ], - [ - [1, 0, 3], - [3, 3, 3], - [7, 1, 3], - ], - [ - [0, 3, 4], - [2, 1, 4], - [3, 4, 4], - ], - [ - [4, 3, 5], - [0, 1, 5], - [1, 4, 5], - ], -] - -vertex_buffer = [] -index_buffer = [] -index_lookup = {} - -for triangle in indices: - for p_ix, t_ix, n_ix in triangle: - key = (p_ix, n_ix, t_ix) - if key not in index_lookup: - position = positions[p_ix] - normal = normals[n_ix] - texture = textures[t_ix] - index = len(vertex_buffer) - index_lookup[key] = index - vertex_buffer.append((tuple(position), - tuple(normal), - tuple(texture))) - - index_buffer.append(index_lookup[key]) - -def gen(): - for position, normal, texture in vertex_buffer: - p = ", ".join(map(str, map(float, position))) - n = ", ".join(map(str, map(float, normal))) - t = ", ".join(map(str, map(float, texture))) - print(f"vertex_t(vec3({p}), vec3({n}), vec2({t})),") - - for i in range(len(index_buffer) // 3): - tri = ", ".join(str(index_buffer[i * 3 + n]) for n in range(3)) - print(f"{tri},") - -from collections import defaultdict -by_normal = defaultdict(list) -for i in range(len(index_buffer) // 3): - tri = [index_buffer[i * 3 + n] for n in range(3)] - s = set(vertex_buffer[j][1] for j in tri) - assert len(s) == 1 - normal, = iter(s) - by_normal[normal].append(tri) - -from pprint import pprint -pprint(dict(by_normal)) -pprint(vertex_buffer) diff --git a/minecraft/gen/data.py b/minecraft/gen/data.py new file mode 100644 index 0000000..da4a05e --- /dev/null +++ b/minecraft/gen/data.py @@ -0,0 +1,353 @@ +from dataclasses import dataclass + +class BlockID: + AIR = 0 + STONE = 1 + GRASS = 2 + DIRT = 3 + STONEBRICK = 4 + WOOD = 5 + SAPLING = 6 + BEDROCK = 7 + WATER = 8 + WATER_CALM = 9 + LAVA = 10 + LAVA_CALM = 11 + SAND = 12 + GRAVEL = 13 + ORE_GOLD = 14 + ORE_IRON = 15 + ORE_COAL = 16 + TREE_TRUNK = 17 + LEAVES = 18 + SPONGE = 19 + GLASS = 20 + ORE_LAPIS = 21 + BLOCK_LAPIS = 22 + DISPENSER = 23 + SANDSTONE = 24 + NOTE_BLOCK = 25 + BED = 26 + RAIL_POWERED = 27 + RAIL_ACTIVATOR = 28 + PISTON_STICKY = 29 + COBWEB = 30 + TALL_GRASS = 31 + DEAD_BUSH = 32 + PISTON = 33 + PISTON_HEAD = 34 + CLOTH = 35 + PISTON_MOVING = 36 + FLOWER = 37 + ROSE = 38 + MUSHROOM_1 = 39 + MUSHROOM_2 = 40 + BLOCK_GOLD = 41 + BLOCK_IRON = 42 + STONESLAB_FULL = 43 + STONESLAB_HALF = 44 + BRICKS = 45 + TNT = 46 + BOOKSHELF = 47 + MOSS_STONE = 48 + OBSIDIAN = 49 + TORCH = 50 + FIRE = 51 + SPAWNER = 52 + STAIRS_WOOD = 53 + CHEST = 54 + WIRE = 55 + ORE_EMERALD = 56 + BLOCK_EMERALD = 57 + WORKBENCH = 58 + WHEAT = 59 + FARMLAND = 60 + FURNACE = 61 + FURNACE_LIT = 62 + SIGN = 63 + DOOR_WOOD = 64 + LADDER = 65 + RAIL = 66 + STAIRS_STONE = 67 + SIGN_WALL = 68 + LEVER = 69 + PLATE_STONE = 70 + DOOR_IRON = 71 + PLATE_WOOD = 72 + ORE_REDSTONE = 73 + ORE_REDSTONE_LIT = 74 + NOT_GATE_OFF = 75 + NOT_GATE_ON = 76 + BUTTON_STONE = 77 + TOPSNOW = 78 + ICE = 79 + SNOW = 80 + CACTUS = 81 + CLAY = 82 + REEDS = 83 + JUKEBOX = 84 + FENCE = 85 + PUMPKIN = 86 + NETHERRACK = 87 + SOUL_SAND = 88 + GLOWSTONE = 89 + PORTAL = 90 + PUMPKIN_LIT = 91 + CAKE = 92 + REPEATER_OFF = 93 + REPEATER_ON = 94 + INVISIBLE = 95 + TRAPDOOR = 96 + STONE_MONSTER_EGG = 97 + STONE_BRICKS = 98 + MUSHROOM1_BLOCK = 99 + MUSHROOM2_BLOCK = 100 + CLOTH_00 = 101 + CLOTH_10 = 102 + CLOTH_20 = 103 + CLOTH_30 = 104 + CLOTH_40 = 105 + CLOTH_50 = 106 + CLOTH_60 = 107 + CLOTH_70 = 108 + CLOTH_01 = 109 + CLOTH_11 = 110 + CLOTH_21 = 111 + CLOTH_31 = 112 + CLOTH_41 = 113 + CLOTH_51 = 114 + CLOTH_61 = 115 + + INFO_UPDATEGAME1 = 248 + INFO_UPDATEGAME2 = 249 + LEAVES_CARRIED = 254 + +class Texture: + GRASS_TOP = 0 + STONE = 1 + DIRT = 2 + GRASS_SIDE = 3 + PLANKS = 4 + STONE_SLAB_SIDE = 5 + STONE_SLAB_TOP = 6 + BRICKS = 7 + TNT_SIDE = 8 + TNT_TOP = 9 + TNT_BOTTOM = 10 + COBWEB = 11 + ROSE = 12 + FLOWER = 13 + WATER_STATIC = 14 + SAPLING = 15 + STONEBRICK = 16 + BEDROCK = 17 + SAND = 18 + GRAVEL = 19 + LOG_SIDE = 20 + LOG_TOP = 21 + IRON = 22 + GOLD = 23 + EMERALD = 24 + CHEST_ONE_TOP = 25 + CHEST_ONE_SIDE = 26 + CHEST_ONE_FRONT = 27 + MUSHROOM_RED = 28 + MUSHROOM_BROWN = 29 + OBSIDIAN_CRYING = 30 + FIRE1 = 31 + ORE_GOLD = 32 + ORE_IRON = 33 + ORE_COAL = 34 + BOOKSHELF = 35 + MOSSY_STONE = 36 + OBSIDIAN = 37 + GRASS_SIDE_OVERLAY = 38 + TALL_GRASS = 39 + NONE40 = 40 + CHEST_TWO_FRONT_LEFT = 41 + CHEST_TWO_FRONT_RIGHT = 42 + WORKBENCH_TOP = 43 + FURNACE_FRONT = 44 + FURNACE_SIDE = 45 + DISPENSER_SIDE = 46 + FIRE2 = 47 + SPONGE = 48 + GLASS = 49 + ORE_EMERALD = 50 + ORE_RED_STONE = 51 + LEAVES_TRANSPARENT = 52 + LEAVES_OPAQUE = 53 + NONE54 = 54 + DEAD_BUSH = 55 + NONE56 = 56 + CHEST_TWO_BACK_LEFT = 57 + CHEST_TWO_BACK_RIGHT = 58 + WORKBENCH_SIDE_1 = 59 + WORKBENCH_SIDE_2 = 60 + FURNACE_LIT = 61 + FURNACE_TOP = 62 + NONE63 = 63 + CLOTH_64 = 64 + SPAWNER = 65 + SNOW = 66 + ICE = 67 + GRASS_SIDE_SNOW = 68 + CACTUS_TOP = 69 + CACTUS_SIDE = 70 + CACTUS_BOTTOM = 71 + CLAY = 72 + REEDS = 73 + JUKEBOX_SIDE = 74 + JUKEBOX_TOP = 75 + NONE76 = 76 + NONE77 = 77 + NONE78 = 78 + NONE79 = 79 + TORCH_LIT = 80 + DOOR_TOP = 81 + DOOR_IRON_TOP = 82 + LADDER = 83 + TRAPDOOR = 84 + NONE85 = 85 + FARMLAND = 86 + FARMLAND_DRY = 87 + WHEAT_0 = 88 + WHEAT_1 = 89 + WHEAT_2 = 90 + WHEAT_3 = 91 + WHEAT_4 = 92 + WHEAT_5 = 93 + WHEAT_6 = 94 + WHEAT_7 = 95 + LEVER = 96 + DOOR_BOTTOM = 97 + DOOR_IRON_BOTTOM = 98 + TORCH_RED_STONE = 99 + NONE100 = 100 + NONE101 = 101 + PUMPKIN_TOP = 102 + BLOODSTONE = 103 + SOULSAND = 104 + GLOWSTONE = 105 + STICKY_PISTON = 106 + PISTON = 107 + NONE108 = 108 + NONE109 = 109 + NONE110 = 110 + NONE111 = 111 + RAIL_CURVED = 112 + CLOTH_112 = 113 + CLOTH_113 = 114 + TORCH_RED_STONE_OFF = 115 + LOG_SPRUCE = 116 + LOG_BIRCH = 117 + PUMPKIN_SIDE = 118 + PUMPKIN_FACE = 119 + PUMPKIN_FACE_LIT = 120 + CAKE_TOP = 121 + CAKE_SIDE = 122 + CAKE_SIDE_BIT = 123 + CAKE_BOTTOM = 124 + NONE125 = 125 + NONE126 = 126 + NONE127 = 127 + RAIL = 128 + + LAPIS = 144 + ORE_LAPIS = 160 + POWERED_RAIL = 163 + REDSTONE_DUST = 164 + + DETECTOR_RAIL = 195 + + SANDSTONE_TOP = 176 + SANDSTONE_SIDE = 192 + WATER = 205 + SANDSTONE_BOTTOM = 208 + + LAVA = 237 + + INFO_UPDATEGAME1 = 252 + INFO_UPDATEGAME2 = 253 + + LAVA_PLACEHOLDER = 255 + +@dataclass +class Tile: + block_id: BlockID + texture: Texture + +tiles = [ + Tile(BlockID.STONE, Texture.STONE), + Tile(BlockID.GRASS, Texture.GRASS_TOP), # fixme + Tile(BlockID.DIRT, Texture.DIRT), + Tile(BlockID.STONEBRICK, Texture.STONEBRICK), + Tile(BlockID.WOOD, Texture.PLANKS), + Tile(BlockID.BEDROCK, Texture.BEDROCK), + Tile(BlockID.WATER, Texture.WATER), # fixme + Tile(BlockID.WATER_CALM, Texture.WATER), # fixme + Tile(BlockID.LAVA, Texture.LAVA), # fixme + Tile(BlockID.LAVA_CALM, Texture.LAVA), # fixme + Tile(BlockID.SAND, Texture.SAND), + Tile(BlockID.GRAVEL, Texture.GRAVEL), + Tile(BlockID.ORE_GOLD, Texture.ORE_GOLD), + Tile(BlockID.ORE_IRON, Texture.ORE_IRON), + Tile(BlockID.ORE_COAL, Texture.ORE_COAL), + Tile(BlockID.TREE_TRUNK, Texture.LOG_SIDE), # fixme + Tile(BlockID.LEAVES, Texture.LEAVES_TRANSPARENT), # fixme + Tile(BlockID.GLASS, Texture.GLASS), + Tile(BlockID.ORE_LAPIS, Texture.ORE_LAPIS), + Tile(BlockID.BLOCK_LAPIS, Texture.LAPIS), + Tile(BlockID.SANDSTONE, Texture.SANDSTONE_SIDE), + Tile(BlockID.FLOWER, Texture.FLOWER), + Tile(BlockID.ROSE, Texture.ROSE), + Tile(BlockID.MUSHROOM_1, Texture.MUSHROOM_BROWN), + Tile(BlockID.MUSHROOM_2, Texture.MUSHROOM_RED), + Tile(BlockID.BLOCK_GOLD, Texture.GOLD), + Tile(BlockID.BLOCK_IRON, Texture.IRON), + Tile(BlockID.STONESLAB_FULL, Texture.STONE_SLAB_SIDE), # fixme + Tile(BlockID.STONESLAB_HALF, Texture.STONE_SLAB_SIDE), # fixme + Tile(BlockID.BRICKS, Texture.BRICKS), + Tile(BlockID.TNT, Texture.TNT_SIDE), + Tile(BlockID.BOOKSHELF, Texture.BOOKSHELF), + Tile(BlockID.MOSS_STONE, Texture.MOSSY_STONE), + Tile(BlockID.OBSIDIAN, Texture.OBSIDIAN), + Tile(BlockID.TORCH, Texture.TORCH_LIT), + Tile(BlockID.STAIRS_WOOD, Texture.PLANKS), # fixme + Tile(BlockID.ORE_EMERALD, Texture.ORE_EMERALD), + Tile(BlockID.BLOCK_EMERALD, Texture.EMERALD), + Tile(BlockID.FARMLAND, Texture.FARMLAND), # fixme + Tile(BlockID.DOOR_WOOD, Texture.DOOR_TOP), # fixme + Tile(BlockID.LADDER, Texture.LADDER), + Tile(BlockID.STAIRS_STONE, Texture.STONEBRICK), + Tile(BlockID.DOOR_IRON, Texture.DOOR_IRON_TOP), # fixme + Tile(BlockID.ORE_REDSTONE, Texture.ORE_RED_STONE), # fixme + Tile(BlockID.ORE_REDSTONE_LIT, Texture.ORE_RED_STONE), # fixme + Tile(BlockID.TOPSNOW, Texture.SNOW), + Tile(BlockID.ICE, Texture.ICE), + Tile(BlockID.SNOW, Texture.SNOW), + Tile(BlockID.CACTUS, Texture.CACTUS_SIDE), + Tile(BlockID.CLAY, Texture.CLAY), + Tile(BlockID.REEDS, Texture.REEDS), + Tile(BlockID.FENCE, Texture.PLANKS), + Tile(BlockID.INVISIBLE, Texture.STONE), + Tile(BlockID.WOOD, Texture.PLANKS), + Tile(BlockID.LEAVES_CARRIED, Texture.LEAVES_TRANSPARENT), # fixme + Tile(BlockID.FIRE, Texture.FIRE1), + Tile(BlockID.SAPLING, Texture.SAPLING), + Tile(BlockID.SPONGE, Texture.SPONGE), + Tile(BlockID.TALL_GRASS, Texture.TALL_GRASS), + Tile(BlockID.DEAD_BUSH, Texture.DEAD_BUSH), + Tile(BlockID.PUMPKIN, Texture.PUMPKIN_FACE), # fixme + Tile(BlockID.PUMPKIN_LIT, Texture.PUMPKIN_FACE_LIT), # fixme + Tile(BlockID.NETHERRACK, Texture.BLOODSTONE), + Tile(BlockID.SOUL_SAND, Texture.SOULSAND), + Tile(BlockID.GLOWSTONE, Texture.GLOWSTONE), + Tile(BlockID.COBWEB, Texture.COBWEB), + Tile(BlockID.WORKBENCH, Texture.WORKBENCH_TOP), # fixme + Tile(BlockID.WHEAT, Texture.WHEAT_0), +] + +tiles_by_id = { + tile.block_id: tile for tile in tiles +} diff --git a/minecraft/gen/mc.py b/minecraft/gen/mc.py index ad7dcfd..0225e32 100644 --- a/minecraft/gen/mc.py +++ b/minecraft/gen/mc.py @@ -7,6 +7,7 @@ from collections import defaultdict import mcregion import vec3 import vertex_buffer +import data def wrap_n(nc, chunk_c): if nc < 0: @@ -17,9 +18,15 @@ def wrap_n(nc, chunk_c): chunk_c = chunk_c + 1 return nc, chunk_c +non_solid_blocks = { + data.BlockID.TALL_GRASS, + data.BlockID.MUSHROOM_1, + data.BlockID.MUSHROOM_2, +} + def block_neighbors(level_table, chunk_x, chunk_z, block_index): block_id = level_table[(chunk_x, chunk_z)].blocks[block_index] - if block_id == 0: + if block_id == data.BlockID.AIR: return def neighbor_exists(nx, ny, nz): @@ -36,7 +43,9 @@ def block_neighbors(level_table, chunk_x, chunk_z, block_index): if key not in level_table: return True n_block_id = level_table[key].blocks[n_block_index] - return n_block_id != 0 + + has_neighbor = (n_block_id != data.BlockID.AIR) and (n_block_id not in non_solid_blocks) + return has_neighbor x, y, z = mcregion.xyz_from_block_index(block_index) @@ -49,7 +58,7 @@ def block_neighbors(level_table, chunk_x, chunk_z, block_index): yield i normal_indices = list(find_non_neighbors()) - if normal_indices: + if block_id in non_solid_blocks or normal_indices: yield center_position, block_id, normal_indices def devoxelize_region(level_table): @@ -82,31 +91,61 @@ def build_block_configuration_table(): indices.extend(vertex_buffer.faces_by_normal[vertex_buffer.normals[j]]) yield indices +non_cube_blocks = { + data.BlockID.TALL_GRASS, +} + +def pack_instance_data(position, block_id): + packed = struct.pack("= 0 for c in ptn), ptn + assert len(ptn) == 3, ptn + return ptn + +def parse_triangle(state, line): + indices = line.split() + assert len(indices) == 3, line + triangle = tuple(map(parse_ptn, indices)) + state.triangle.append(triangle) + +prefixes = [ + ("#", ignore), + ("o ", ignore), + ("s ", ignore), + ("v ", parse_position), + ("vn ", parse_normal), + ("vt ", parse_texture), + ("f ", parse_triangle), +] + +@dataclass +class ObjState: + position: list + normal: list + texture: list + triangle: list + + def __init__(self): + self.position = [] + self.normal = [] + self.texture = [] + self.triangle = [] + +def parse_obj(s): + state = ObjState() + lines = s.strip().split("\n") + for line in lines: + for prefix, func in prefixes: + if line.startswith(prefix): + line = line.removeprefix(prefix) + func(state, line) + break + else: + assert False, line + return state + +def parse_obj_from_filename(filename): + with open(filename, "r") as f: + buf = f.read() + return parse_obj(buf) diff --git a/minecraft/gen/obj_state.py b/minecraft/gen/obj_state.py new file mode 100644 index 0000000..8cdb164 --- /dev/null +++ b/minecraft/gen/obj_state.py @@ -0,0 +1,25 @@ +from collections import defaultdict +import obj + +def append_triangles(state, vertex_buffer, index_buffer, index_lookup): + for triangle in state.triangle: + for p_ix, t_ix, n_ix in triangle: + key = (p_ix, n_ix, t_ix) + if key not in index_lookup: + position = state.position[p_ix] + normal = state.normal[n_ix] + texture = state.texture[t_ix] + index = len(vertex_buffer) + index_lookup[key] = index + vertex_buffer.append((position, normal, texture)) + index_buffer.append(index_lookup[key]) + +def build_faces_by_normal(vertex_buffer, index_buffer): + by_normal = defaultdict(list) + for i in range(len(index_buffer) // 3): + tri = [index_buffer[i * 3 + n] for n in range(3)] + s = set(vertex_buffer[j][1] for j in tri) + assert len(s) == 1, s + normal, = iter(s) + by_normal[normal].extend(tri) + return by_normal diff --git a/minecraft/gen/tallgrass.obj b/minecraft/gen/tallgrass.obj new file mode 100644 index 0000000..3f84163 --- /dev/null +++ b/minecraft/gen/tallgrass.obj @@ -0,0 +1,24 @@ +# Blender 5.0.0 +# www.blender.org +o TallGrass +v 0.800011 0.600021 0.800011 +v 0.800011 -1.000000 0.800011 +v -0.800010 -1.000000 0.800011 +v -0.800011 0.600021 0.800011 +v -0.800011 0.600021 -0.800011 +v -0.800011 -1.000000 -0.800011 +v 0.800011 -1.000000 -0.800011 +v 0.800010 0.600022 -0.800011 +vn 0.7071 -0.0000 0.7071 +vn 0.7071 -0.0000 -0.7071 +vt 1.000000 1.000000 +vt 0.000000 -0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt -0.000000 1.000000 +vt 1.000000 0.000000 +s 0 +f 3/1/1 8/2/1 4/3/1 +f 5/2/2 2/4/2 6/5/2 +f 3/1/1 7/5/1 8/2/1 +f 5/2/2 1/6/2 2/4/2 diff --git a/minecraft/gen/vertex_buffer.py b/minecraft/gen/vertex_buffer.py index 1f1b5cd..93a5d88 100644 --- a/minecraft/gen/vertex_buffer.py +++ b/minecraft/gen/vertex_buffer.py @@ -1,41 +1,8 @@ import struct import vec3 - -vertex_table = [ - ((-1.0, 1.0, -1.0), (0.0, 1.0, 0.0), (1.0, 0.0)), - ((1.0, 1.0, 1.0), (0.0, 1.0, 0.0), (0.0, 1.0)), - ((1.0, 1.0, -1.0), (0.0, 1.0, 0.0), (0.0, 0.0)), - ((1.0, 1.0, 1.0), (0.0, 0.0, 1.0), (1.0, 1.0)), - ((-1.0, -1.0, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0)), - ((1.0, -1.0, 1.0), (0.0, 0.0, 1.0), (1.0, 0.0)), - ((-1.0, 1.0, 1.0), (-1.0, 0.0, 0.0), (1.0, 1.0)), - ((-1.0, -1.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 0.0)), - ((-1.0, -1.0, 1.0), (-1.0, 0.0, 0.0), (1.0, 0.0)), - ((1.0, -1.0, -1.0), (0.0, -1.0, 0.0), (1.0, 0.0)), - ((-1.0, -1.0, 1.0), (0.0, -1.0, 0.0), (0.0, 1.0)), - ((-1.0, -1.0, -1.0), (0.0, -1.0, 0.0), (0.0, 0.0)), - ((1.0, 1.0, -1.0), (1.0, 0.0, 0.0), (1.0, 1.0)), - ((1.0, -1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 0.0)), - ((1.0, -1.0, -1.0), (1.0, 0.0, 0.0), (1.0, 0.0)), - ((-1.0, 1.0, -1.0), (0.0, 0.0, -1.0), (1.0, 1.0)), - ((1.0, -1.0, -1.0), (0.0, 0.0, -1.0), (0.0, 0.0)), - ((-1.0, -1.0, -1.0), (0.0, 0.0, -1.0), (1.0, 0.0)), - ((-1.0, 1.0, 1.0), (0.0, 1.0, 0.0), (1.0, 1.0)), - ((-1.0, 1.0, 1.0), (0.0, 0.0, 1.0), (0.0, 1.0)), - ((-1.0, 1.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 1.0)), - ((1.0, -1.0, 1.0), (0.0, -1.0, 0.0), (1.0, 1.0)), - ((1.0, 1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0)), - ((1.0, 1.0, -1.0), (0.0, 0.0, -1.0), (0.0, 1.0)) -] - -faces_by_normal = { - (-1.0, 0.0, 0.0): [6, 7, 8, 6, 20, 7], - (0.0, -1.0, 0.0): [9, 10, 11, 9, 21, 10], - (0.0, 0.0, -1.0): [15, 16, 17, 15, 23, 16], - (0.0, 0.0, 1.0): [3, 4, 5, 3, 19, 4], - (0.0, 1.0, 0.0): [0, 1, 2, 0, 18, 1], - (1.0, 0.0, 0.0): [12, 13, 14, 12, 22, 13] -} +import obj +import obj_state +import sys normals = [ (-1.0, 0.0, 0.0), @@ -46,7 +13,9 @@ normals = [ (1.0, 0.0, 0.0), ] -def build_configuration_index_buffers(f): +def build_configuration_index_buffers(f, faces_by_normal): + assert(set(normals) == set(faces_by_normal.keys())) + offset = 0 configuration_offsets = [] for configuration in range(64): @@ -65,14 +34,37 @@ def build_configuration_index_buffers(f): if i % 8 == 7: print() -def build_vertex_buffer(f): - for position, normal, texture in vertex_table: +def build_vertex_buffer(f, vertex_buffer): + for position, normal, texture in vertex_buffer: position = vec3.mul(position, 0.5) f.write(struct.pack("