Exemplo n.º 1
0
 def __init__(self,
              guid: Hex = None,
              texture: str = None,
              near_plane: float = 0.1,
              far_plane: float = 1.1,
              vertical_meters: float = None,
              horizontal_meters: float = None,
              decal_origin: Position = None,
              decal_orientation: list[float] = None,
              lod: float = 1.0):
     if vertical_meters is None:
         vertical_meters = 4.0 / 1.1 * far_plane
     if horizontal_meters is None:
         horizontal_meters = 4.0 / 1.1 * far_plane
     self.guid = guid
     self.texture = texture
     self.near_plane = near_plane
     self.far_plane = far_plane
     self.vertical_meters = vertical_meters
     self.horizontal_meters = horizontal_meters
     self.decal_origin = decal_origin if decal_origin is not None else Position(
         0, 1, 0, None)
     self.decal_orientation = decal_orientation if decal_orientation is not None else [
         0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0
     ]  # default orientation, no idea what these numbers mean
     self.lod = lod  # level of detail
Exemplo n.º 2
0
 def map_pos_to_node_pos(self, map_pos_x, map_pos_z):
     xnt = int(map_pos_x / self.TILE_SIZE)
     znt = int(map_pos_z / self.TILE_SIZE)
     node_tile = self.nodes_2d[xnt][znt]
     ntx = map_pos_x % self.TILE_SIZE - self.TILE_SIZE / 2
     ntz = map_pos_z % self.TILE_SIZE - self.TILE_SIZE / 2
     na = node_tile.turn_angle()
     ntxt, ntzt = self.turn(ntx, ntz, -na)
     nx = node_tile.offset[0] + ntxt
     nz = node_tile.offset[1] + ntzt
     node_pos = Position(nx, 10, nz, node_tile.node.guid)
     return node_pos
Exemplo n.º 3
0
def apply_progression_node_sets(tiles, tile_size_x, tile_size_z,
                                progression: Progression,
                                rt: RegionTiling) -> list[Decal]:
    # Apply node-sets from progression steps. TerrainNodes are already created at this point and have guids.
    max_size_xz = max(tile_size_x * rt.num_x, tile_size_z * rt.num_z)
    node_tiles: list[NodeTile] = []
    for col in tiles:
        node_tiles.extend([tile for tile in col if tile.node is not None])
    for tile in node_tiles:
        map_norm_x = (rt.cur_x * tile_size_x + tile.x +
                      2 / 4) / max_size_xz  # x on whole map, normalized (0-1)
        map_norm_z = (rt.cur_z * tile_size_z + tile.z +
                      2 / 4) / max_size_xz  # z on whole map, normalized (0-1)
        progression_step = progression.choose_progression_step(
            map_norm_x, map_norm_z, 'sharp')
        node: TerrainNode = tile.node
        node.texture_set = progression_step.node_set
    decals: list[Decal] = []
    for tile in node_tiles:
        node: TerrainNode = tile.node
        texture_set = node.texture_set
        assert texture_set in NODE_SET_PRIO
        for door in (1, 2, 3, 4):
            if door not in node.doors:
                continue
            floor_doors: dict[int, float] = FLOOR_DOORS[node.mesh_name]
            if door not in floor_doors:
                continue
            floor_door_height = floor_doors[door]
            neighbor_node, neighbor_door = node.doors[door]
            neighbor_texture_set = neighbor_node.texture_set
            assert neighbor_texture_set in NODE_SET_PRIO
            if NODE_SET_PRIO.index(texture_set) < NODE_SET_PRIO.index(
                    neighbor_texture_set):
                decal_x, decal_z = MapgenTerrain.turn(
                    0, -2, math.tau / 4 * (door - 1))
                if tile.node_mesh == 't_xxx_wal_12-thin':  # wtf
                    decal_x -= 7
                decal_position = Position(decal_x, floor_door_height + 2,
                                          decal_z, node.guid)
                decal = Decal(
                    guid=Hex.random(),
                    texture=f'Art\\Bitmaps\\Decals\\b_d_{texture_set}-a.%img%',
                    far_plane=2.2,
                    decal_origin=decal_position)
                decals.append(decal)
    return decals
Exemplo n.º 4
0
 def from_gas(cls, decal_section: Section) -> Decal:
     assert decal_section.header == 't:decal,n:*'
     guid = decal_section.get_attr_value('guid')
     texture = decal_section.get_attr_value('texture')
     near_plane = decal_section.get_attr_value('near_plane')
     far_plane = decal_section.get_attr_value('far_plane')
     vertical_meters = decal_section.get_attr_value('vertical_meters')
     horizontal_meters = decal_section.get_attr_value('horizontal_meters')
     decal_origin = Position.parse(
         decal_section.get_attr_value('decal_origin'))
     decal_orientation = [
         float(x) for x in decal_section.get_attr_value(
             'decal_orientation').split(',')
     ]
     lod = decal_section.get_attr_value('lod')
     return Decal(guid, texture, near_plane, far_plane, vertical_meters,
                  horizontal_meters, decal_origin, decal_orientation, lod)
Exemplo n.º 5
0
def create_region(map_name, region_name, node='t_xxx_flr_04x04-v0'):
    bits = Bits()
    m = bits.maps[map_name]
    region: Region = m.create_region(region_name, None)
    region.terrain = Terrain(TerrainNode(None, node))
    region.save()

    # start positions group
    if len(m.get_regions()) == 1 and m.start_positions is None:
        # 1st region, let's add a start pos
        position = Position(0, 0, 0, region.terrain.target_node.guid)
        m.start_positions = StartPositions(
            {
                'default':
                StartGroup(
                    'This is the default group.', False, 0, '',
                    [StartPos(1, position, Camera(0.5, 20, 0, position))])
            }, 'default')
        m.save()
Exemplo n.º 6
0
def generate_region(_map, region_name, size_x, size_z, args: Args,
                    rt: RegionTiling):
    print(f'generate region {region_name} {size_x}x{size_z} ({args})')

    # generate the region!
    region_data = generate_region_data(size_x, size_z, args, region_name, rt,
                                       _map.get_all_node_ids())
    if region_data is None:
        print('all tiles culled - not saving region')
        return
    terrain, plants, stitches, decals = region_data

    # add lighting
    ambient_color = Hex(0xff8080ff)
    ambient_intensity = 0.2
    terrain.ambient_light.terrain_intensity = ambient_intensity
    terrain.ambient_light.terrain_color = ambient_color
    terrain.ambient_light.object_intensity = ambient_intensity
    terrain.ambient_light.object_color = ambient_color
    terrain.ambient_light.actor_intensity = ambient_intensity
    terrain.ambient_light.actor_color = ambient_color
    dir_lights = [
        # daylight from south-east
        DirectionalLight(
            color=Color(0xffffffff),
            draw_shadow=True,
            intensity=1,
            occlude_geometry=True,
            on_timer=True,
            direction=DirectionalLight.direction_from_orbit_and_azimuth(
                225, 45)),
        # counter-light from north-west
        DirectionalLight(
            color=Color(0xffffffff),
            draw_shadow=False,
            intensity=0.5,
            occlude_geometry=False,
            on_timer=True,
            direction=DirectionalLight.direction_from_orbit_and_azimuth(
                45, 45))
    ]

    # save
    if region_name in _map.get_regions():
        print(f'deleting existing region {region_name}')
        _map.delete_region(region_name)
        _map.gas_dir.clear_cache()
    region_i = rt.cur_x * rt.num_z + rt.cur_z + 1
    region: Region = _map.create_region(region_name, region_i)
    region.terrain = terrain
    region.decals = DecalsGas(decals) if len(decals) > 0 else None
    region.lights = dir_lights
    region.generated_objects_non_interactive = []

    if args.start_pos is not None:
        pos = Position(0, 0, 0, terrain.target_node.guid)
        start_group_name = args.start_pos
        _map.load_start_positions()
        if start_group_name in _map.start_positions.start_groups:
            _map.start_positions.start_groups[
                start_group_name].start_positions = [
                    StartPos(1, pos, Camera(0.5, 20, 0, pos))
                ]
        else:
            sg_id = _map.start_positions.new_start_group_id()
            _map.start_positions.start_groups[start_group_name] = StartGroup(
                'Heightmap generated start pos', False, sg_id, 'Heightmap',
                [StartPos(1, pos, Camera(0.5, 20, 0, pos))])
            _map.start_positions.default = start_group_name
        region.generated_objects_non_interactive.append(
            GameObjectData(
                'trigger_change_mood_box',
                placement=Placement(position=pos),
                common=Common(instance_triggers=[
                    TriggerInstance(
                        'party_member_within_bounding_box(2,1,2,"on_every_enter")',
                        'mood_change("map_world_df_r0_2")')
                ])))
        _map.save()

    if plants is not None:
        region.generated_objects_non_interactive.extend([
            GameObjectData(
                plant.template_name,
                placement=Placement(position=plant.position,
                                    orientation=Quaternion.rad_to_quat(
                                        plant.orientation)),
                aspect=Aspect(scale_multiplier=plant.size)) for plant in plants
        ])

    if rt and (rt.num_x > 1 or rt.num_z > 1):
        top_stitches, left_stitches, bottom_stitches, right_stitches = stitches
        shg = StitchHelperGas(region.data.id, region_name)
        if top_stitches is not None:
            shg.stitch_editors.append(
                StitchEditor(rt.region_name(rt.cur_x, rt.cur_z - 1),
                             top_stitches))
        if left_stitches is not None:
            shg.stitch_editors.append(
                StitchEditor(rt.region_name(rt.cur_x - 1, rt.cur_z),
                             left_stitches))
        if bottom_stitches is not None:
            shg.stitch_editors.append(
                StitchEditor(rt.region_name(rt.cur_x, rt.cur_z + 1),
                             bottom_stitches))
        if right_stitches is not None:
            shg.stitch_editors.append(
                StitchEditor(rt.region_name(rt.cur_x + 1, rt.cur_z),
                             right_stitches))
        region.stitch_helper = shg

    region.save()
    print(f'new region {region_name} saved')
Exemplo n.º 7
0
def generate_plants(terrain: Terrain, plants_profile: dict[str, float],
                    include_nodes: list[NodeMask],
                    exclude_nodes) -> list[Plant]:
    mesh_info = load_mesh_info()

    terrain_nodes = terrain.nodes
    if len(include_nodes) > 0:
        terrain_nodes = [
            node for node in terrain_nodes if any([
                node_mask.matches(node.section, node.level, node.object)
                for node_mask in include_nodes
            ])
        ]
    if len(exclude_nodes) > 0:
        terrain_nodes = [
            node for node in terrain_nodes if not any([
                node_mask.matches(node.section, node.level, node.object)
                for node_mask in exclude_nodes
            ])
        ]

    unknown_meshes = set([
        node.mesh_name for node in terrain_nodes
        if node.mesh_name not in mesh_info
    ])
    if len(unknown_meshes) > 0:
        print(str(len(unknown_meshes)) + ' unknown meshes:')
        for unknown_mesh in sorted(unknown_meshes):
            print(unknown_mesh)
    plantable_nodes = [
        node for node in terrain_nodes if node.mesh_name in mesh_info
        and mesh_info[node.mesh_name] is not None
    ]
    print(
        f'nodes: {len(terrain.nodes)} total, {len(terrain_nodes)} included, {len(plantable_nodes)} plantable'
    )
    overall_plantable_area_size = 0
    for node in plantable_nodes:
        plantable_area_size = mesh_info[node.mesh_name].size()
        overall_plantable_area_size += plantable_area_size
    print(f'overall plantable area size: {overall_plantable_area_size} m²')

    plants = list()
    for template_name, density in plants_profile.items():
        num_plants = int(overall_plantable_area_size * density)
        print(template_name + ' density ' + str(density) +
              '/m² -> num plants: ' + str(num_plants))

        overall_weighted = 0
        weighted_area_dist = list()
        for node in plantable_nodes:
            weight = random.uniform(0, 2)
            weighted = mesh_info[node.mesh_name].size() * weight
            overall_weighted += weighted
            weighted_area_dist.append((overall_weighted, node))

        for i in range(num_plants):
            rand_val = random.uniform(0, overall_weighted)
            node = None
            for max_rand_val, n in weighted_area_dist:
                if max_rand_val > rand_val:
                    node = n
                    break
            plantable_area = mesh_info[node.mesh_name]
            x = random.uniform(plantable_area.x_min, plantable_area.x_max)
            z = random.uniform(plantable_area.z_min, plantable_area.z_max)
            y = plantable_area.y
            orientation = random.uniform(0, math.tau)
            size = random.uniform(0.8, 1.0) if random.choice(
                [True, False]) else random.uniform(1.0, 1.3)
            plant = Plant(template_name, Position(x, y, z, node.guid),
                          orientation, size)
            plants.append(plant)
    return plants