示例#1
0
    def __init__(self):
        VmfClass.__init__(self)
        self.mins = types.Vertex(99999, 99999, 99999)
        self.maxs = types.Vertex(-99999, -99999, -99999)
        self.active = types.Bool(0)

        self.auto_properties = ['mins', 'maxs', 'active']
示例#2
0
    def __init__(self,
                 source,
                 source_alphas=None,
                 origin=types.Vertex(),
                 size=types.Vertex(),
                 x_subdisplacements=4,
                 y_subdisplacements=4,
                 power=3,
                 add_nodraw_brush=False):
        # This is the data we will use to build our displacements.
        self.source = source
        # This is the data we use to build the alpha map
        self.source_alphas = source_alphas
        # This is the physical location of the DM's center.
        self.origin = origin
        # This is the length, width, and height of the DM
        self.size = size
        # This is the number of displacements we will have along the x and y axis, respectively.
        self.sub_displacements = (x_subdisplacements, y_subdisplacements)
        # This is whether we want to add nodraw brushes underneath the displacement to block visibility.
        self.add_nodraw_brush = add_nodraw_brush

        if power not in (2, 3, 4):
            raise ValueError(
                "Power of a DisplacementMap must be 2, 3, or 4, not {0}.".
                format(power))

        # The power of each subdisplacement. (2 ^ power) is the number of grid points the displacement will have.
        self.power = power

        self.source_width = (2**self.power * self.sub_displacements[0]) + 1
        self.source_height = (2**self.power * self.sub_displacements[1]) + 1

        # The actual grid-size of displacement brushes
        self.d_x_size = self.size[0] / self.sub_displacements[0]
        self.d_y_size = self.size[1] / self.sub_displacements[1]

        # The actual grid-distance between points
        self.d_x_p_size = self.d_x_size / (2**self.power)
        self.d_y_p_size = self.d_y_size / (2**self.power)

        self.material = ""
        self.displacement_brushes = []
        self.misc_brushes = []
示例#3
0
    def __init__(self,
                 origin=types.Vertex(),
                 size=types.Vertex(),
                 thickness=32):
        self.origin = origin

        for dim in size:
            if dim <= 0:
                raise ValueError("Solid cannot have negative size!")

        self.size = size
        self.thickness = thickness

        # Left wall
        self.left_wall = Block(
            types.Vertex(
                -self.thickness / 2 + self.origin[0] - self.size[0] / 2,
                self.origin[1], self.origin[2]),
            (self.thickness, self.size[1], self.size[2]))
        # Right wall
        self.right_wall = Block(
            types.Vertex(
                +self.thickness / 2 + self.origin[0] + self.size[0] / 2,
                self.origin[1], self.origin[2]),
            (self.thickness, self.size[1], self.size[2]))
        # Forward wall
        self.front_wall = Block(
            types.Vertex(
                self.origin[0],
                self.thickness / 2 + self.origin[1] + self.size[1] / 2,
                self.origin[2]),
            (self.size[0] + 2 * self.thickness, self.thickness, self.size[2]))
        # Rear wall
        self.back_wall = Block(
            types.Vertex(
                self.origin[0],
                -self.thickness / 2 + self.origin[1] - self.size[1] / 2,
                self.origin[2]),
            (self.size[0] + 2 * self.thickness, self.thickness, self.size[2]))

        # Ceiling
        self.ceiling = self.get_level_brush(
            self.size[2] / 2 + self.thickness / 2 + self.origin[2],
            self.thickness)
        # Floor
        self.floor = self.get_level_brush(
            -self.size[2] / 2 - self.thickness / 2 + self.origin[2],
            self.thickness)

        self.brushes = [
            self.left_wall, self.right_wall, self.front_wall, self.back_wall,
            self.ceiling, self.floor
        ]
示例#4
0
    def __init__(self,
                 origin=types.Vertex(),
                 dimensions=(64, 64, 64),
                 material='BRICK/BRICKFLOOR001A'):
        """Create a new Block at origin with dimensions and material."""
        self.origin = origin
        self.dimensions = dimensions

        # Create brush
        self.brush = brush.Solid()

        # Create (un-positioned) sides
        sides = []
        for i in range(6):
            sides.append(brush.Side(types.Plane(), material))
        self.brush.children.extend(sides)

        # Compute initial side planes
        self.update_sides()

        # Apply material
        self.set_material(material)
示例#5
0
    def update_sides(self):
        """Call this when the origin or dimensions have changed."""
        x = self.origin.x
        y = self.origin.y
        z = self.origin.z
        w, l, h = self.dimensions
        a = w / 2
        b = l / 2
        c = h / 2

        self.brush.children[0].plane = types.Plane(
            types.Vertex(x - a, y + b,
                         z + c), types.Vertex(x + a, y + b, z + c),
            types.Vertex(x + a, y - b, z + c))
        self.brush.children[1].plane = types.Plane(
            types.Vertex(x - a, y - b,
                         z - c), types.Vertex(x + a, y - b, z - c),
            types.Vertex(x + a, y + b, z - c))
        self.brush.children[2].plane = types.Plane(
            types.Vertex(x - a, y + b,
                         z + c), types.Vertex(x - a, y - b, z + c),
            types.Vertex(x - a, y - b, z - c))
        self.brush.children[3].plane = types.Plane(
            types.Vertex(x + a, y + b,
                         z - c), types.Vertex(x + a, y - b, z - c),
            types.Vertex(x + a, y - b, z + c))
        self.brush.children[4].plane = types.Plane(
            types.Vertex(x + a, y + b,
                         z + c), types.Vertex(x - a, y + b, z + c),
            types.Vertex(x - a, y + b, z - c))
        self.brush.children[5].plane = types.Plane(
            types.Vertex(x + a, y - b,
                         z - c), types.Vertex(x - a, y - b, z - c),
            types.Vertex(x - a, y - b, z + c))

        for side in self.brush.children:
            side.uaxis, side.vaxis = side.plane.sensible_axes()
示例#6
0
    def realize(self):
        """Actually create the displacements that this entity is made out of."""
        if len(self.displacement_brushes) > 0:
            raise ValueError(
                "Displacement map cannot be realized more than once!")

        rotation_counts = {
            (True, True): 3,
            (True, False): 0,
            (False, False): 1,
            (False, True): 2
        }
        for dx in range(self.sub_displacements[0]):
            for dy in range(self.sub_displacements[1]):

                power = 2**self.power

                x_offset = power * dx
                y_offset = power * dy

                # The actual position the displacement brush will be in
                x_pos = (dx - (self.sub_displacements[0] / 2) +
                         0.5) * self.d_x_size + self.origin.x
                y_pos = (dy - (self.sub_displacements[1] / 2) +
                         0.5) * self.d_y_size + self.origin.y

                # The modifications of which order we load the values into the array need to happen for some reason.
                # Source just wants things in a different order depending on which quadrant you're in I guess.

                forward_range = list(range(power + 1))
                backwards_range = list(range(power, -1, -1))

                x_range = forward_range
                y_range = backwards_range

                norms = []
                for i in x_range:
                    row = []
                    for j in y_range:
                        row.append(types.Vertex(0, 0, 1))
                    norms.append(row)
                dists = []
                for x in x_range:
                    row = []
                    for y in y_range:
                        rel_x = x + x_offset
                        rel_y = y + y_offset
                        row.append(self[rel_x, rel_y])
                    dists.append(row)
                if self.source_alphas:
                    alphas = []
                    for x in x_range:
                        alphas_row = []
                        for y in y_range:
                            rel_x = x + x_offset
                            rel_y = y + y_offset
                            alphas_row.append(self.source_alphas[rel_x, rel_y])
                        alphas.append(alphas_row)
                else:
                    alphas = None

                # There's a weird quirk where the displacement gets rotated depending on what quadrant it's origin is
                # in. I'm not sure whether this is something to do with the source engine, or the Block tool.
                # either way, the following StackOverflow-code accounts for it by rotating the displacement back.
                # (it's still wrong sometimes when the displacements' origin x or y are 0, so don't do that)
                rotation_count = rotation_counts[x_pos > 0, y_pos >= 0]
                for i in range(rotation_count):
                    dists = list(zip(*dists[::-1]))
                    norms = list(zip(*norms[::-1]))
                    if alphas:
                        alphas = list(zip(*alphas[::-1]))

                d = brush.DispInfo(self.power, norms, dists, alphas)

                floor = Block(types.Vertex(x_pos, y_pos, self.origin.z),
                              (self.d_x_size, self.d_y_size, self.size[2]))
                if self.material != "":
                    floor.set_material(self.material)
                floor.top().children.append(d)  # Add disp map to the ground
                # Store these in case they're needed.
                floor.x_offset = x_offset
                floor.y_offset = y_offset
                floor.displacement_distances = dists

                self.displacement_brushes.append(floor)
                if self.add_nodraw_brush:
                    lowest_height = int(min(map(min, dists))) - 1
                    if lowest_height > 1:
                        # Don't make any brushes that are too small.
                        nodraw_brush = Block(
                            types.Vertex(
                                x_pos, y_pos, self.origin.z + 0.5 *
                                (lowest_height + self.size[2])),
                            (self.d_x_size, self.d_y_size, int(lowest_height)),
                            "tools/toolsnodraw")
                        self.misc_brushes.append(nodraw_brush)
示例#7
0
 def get_level_brush(self, z_origin, z_size):
     """Returns a brush the horizontal size of this box, with z_position and z_height given.
     Think of filling the box part way with water, and letting it settle. That's what this function generates."""
     return Block(types.Vertex(self.origin[0], self.origin[1], z_origin),
                  (self.size[0], self.size[1], z_size))