예제 #1
0
def beam_hole_split(axis: str, min_pos: Vec, max_pos: Vec):
    """Break up floor beams to fit around holes."""

    # Go along the shape. For each point, check if a hole is present,
    # and split at that.
    # Our positions are centered, but we return ones at the ends.

    # Inset in 4 units from each end to not overlap with the frames.
    start_pos = min_pos - Vec.with_axes(axis, 60)
    if HOLES:
        hole_size_large = vbsp_options.get(float, 'glass_hole_size_large') / 2
        hole_size_small = vbsp_options.get(float, 'glass_hole_size_small') / 2

        # Extract normal from the z-axis.
        grid_height = min_pos.z // 128 * 128 + 64
        if grid_height < min_pos.z:
            normal = (0, 0, 1)
        else:
            normal = (0, 0, -1)
        import vbsp
        for pos in min_pos.iter_line(max_pos, 128):
            try:
                hole_type = HOLES[(pos.x, pos.y, grid_height), normal]
            except KeyError:
                continue
            else:
                if hole_type is HoleType.SMALL:
                    size = hole_size_small
                elif hole_type is HoleType.LARGE:
                    size = hole_size_large
                else:
                    raise AssertionError(hole_type)

                yield start_pos, pos - Vec.with_axes(axis, size)
                start_pos = pos + Vec.with_axes(axis, size)

    # Last segment, or all if no holes.
    yield start_pos, max_pos + Vec.with_axes(axis, 60)
예제 #2
0
def beam_hole_split(axis: str, min_pos: Vec, max_pos: Vec):
    """Break up floor beams to fit around holes."""

    # Go along the shape. For each point, check if a hole is present,
    # and split at that.
    # Our positions are centered, but we return ones at the ends.

    # Inset in 4 units from each end to not overlap with the frames.
    start_pos = min_pos - Vec.with_axes(axis, 60)
    if HOLES:
        hole_size_large = vbsp_options.get(float, 'glass_hole_size_large') / 2
        hole_size_small = vbsp_options.get(float, 'glass_hole_size_small') / 2

        # Extract normal from the z-axis.
        grid_height = min_pos.z // 128 * 128 + 64
        if grid_height < min_pos.z:
            normal = (0, 0, 1)
        else:
            normal = (0, 0, -1)
        import vbsp
        for pos in min_pos.iter_line(max_pos, 128):
            try:
                hole_type = HOLES[(pos.x, pos.y, grid_height), normal]
            except KeyError:
                continue
            else:
                if hole_type is HoleType.SMALL:
                    size = hole_size_small
                elif hole_type is HoleType.LARGE:
                    size = hole_size_large
                else:
                    raise AssertionError(hole_type)

                yield start_pos, pos - Vec.with_axes(axis, size)
                start_pos = pos + Vec.with_axes(axis, size)

    # Last segment, or all if no holes.
    yield start_pos, max_pos + Vec.with_axes(axis, 60)
예제 #3
0
    def export(self, vmf: VMF, *, wall_conf: AntType, floor_conf: AntType) -> None:
        """Add the antlines into the map."""

        # First, do some optimisation. If corners aren't defined, try and
        # optimise those antlines out by merging the straight segment
        # before/after it into the corners.

        collapse_line: list[Segment | None]
        if not wall_conf.tex_corner or not floor_conf.tex_corner:
            collapse_line = list(self.line)
            for i, seg in enumerate(collapse_line):
                if seg is None or seg.type is not SegType.STRAIGHT:
                    continue
                if (floor_conf if seg.on_floor else wall_conf).tex_corner:
                    continue
                for corner_ind in [i-1, i+1]:
                    if i == -1:
                        continue
                    try:
                        corner = collapse_line[corner_ind]
                    except IndexError:
                        # Each end of the list.
                        continue

                    if (
                        corner is not None and
                        corner.type is SegType.CORNER and
                        corner.normal == seg.normal
                    ):
                        corner_pos = corner.start
                        if (seg.start - corner_pos).mag_sq() == 8 ** 2:
                            # The line segment is at the border between them,
                            # the corner is at the center. So move double the
                            # distance towards the corner, so it reaches to the
                            # other side of the corner and replaces it.
                            seg.start += 2 * (corner_pos - seg.start)
                            # Remove corner by setting to None, so we aren't
                            # resizing the list constantly.
                            collapse_line[corner_ind] = None
                            # Now merge together the tiledefs.
                            seg.tiles.update(corner.tiles)
                        elif (seg.end - corner_pos).mag_sq() == 8 ** 2:
                            seg.end += 2 * (corner_pos - seg.end)
                            collapse_line[corner_ind] = None
                            seg.tiles.update(corner.tiles)

            self.line[:] = [seg for seg in collapse_line if seg is not None]
            LOGGER.info('Collapsed {} antline corners', collapse_line.count(None))

        for seg in self.line:
            conf = floor_conf if seg.on_floor else wall_conf
            # Check tiledefs in the voxels, and assign just in case.
            # antline corner items don't have them defined, and some embedfaces don't work
            # properly. But we keep any segments actually defined also.
            mins, maxs = Vec.bbox(seg.start, seg.end)
            norm_axis = seg.normal.axis()
            u_axis, v_axis = Vec.INV_AXIS[norm_axis]
            for pos in Vec.iter_line(mins, maxs, 128):
                pos[u_axis] = pos[u_axis] // 128 * 128 + 64
                pos[v_axis] = pos[v_axis] // 128 * 128 + 64
                pos -= 64 * seg.normal
                try:
                    tile = tiling.TILES[pos.as_tuple(), seg.normal.as_tuple()]
                except KeyError:
                    pass
                else:
                    seg.tiles.add(tile)

            rng = rand.seed(b'antline', seg.start, seg.end)
            if seg.type is SegType.CORNER:
                mat: AntTex
                if rng.randrange(100) < conf.broken_chance:
                    mat = rng.choice(conf.broken_corner or conf.broken_straight)
                else:
                    mat = rng.choice(conf.tex_corner or conf.tex_straight)

                # Because we can, apply a random rotation to mix up the texture.
                orient = Matrix.from_angle(seg.normal.to_angle(
                    rng.choice((0.0, 90.0, 180.0, 270.0))
                ))
                self._make_overlay(
                    vmf,
                    seg,
                    seg.start,
                    16.0 * orient.left(),
                    16.0 * orient.up(),
                    mat,
                )
            else:  # Straight
                # TODO: Break up these segments.
                for a, b, is_broken in seg.broken_iter(conf.broken_chance):
                    if is_broken:
                        mat = rng.choice(conf.broken_straight)
                    else:
                        mat = rng.choice(conf.tex_straight)
                    self._make_straight(
                        vmf,
                        seg,
                        a,
                        b,
                        mat,
                    )