Esempio n. 1
0
class Simulator(ShowBase):
    def __init__(self, textboxes=({}), default_text_scale=.07, graph_objs={}):
        ShowBase.__init__(self)

        self.joys = self.devices.getDevices(InputDevice.DeviceClass.gamepad)
        #Attaches input devices to base
        for ind, joy in enumerate(self.joys):
            self.attachInputDevice(joy, prefix=str(ind))
        #Joystick reading variable
        self.joystick_readings = []

        #Add panda and background
        self.scene = self.loader.loadModel("models/environment")
        self.scene.reparentTo(self.render)
        self.scene.setScale(0.25, 0.25, 0.25)
        #Sets the scene position
        self.scene.setPos(-8, 48, 0)

        self.camera.setPos(-8, 48, -4)

        self.pandaActor = Actor("models/panda-model",
                                {"walk": "models/panda-walk4"})
        self.pandaActor.setScale(0.005, 0.005, 0.005)
        self.pandaActor.reparentTo(self.render)
        self.pandaLocation = [0, 0, 0]
        self.setPandaToLocation()
        #Lines to be rendered on the next frame
        self.lines = []
        self.lineNodes = []
        self.lineNodePaths = []
        #Text boxes which will be rendered every frame
        #Key is a node name, value is a dict with
        #arguments such as text, location, and scale
        #Hack to keep default argument immutable and prevent bugs
        if type(textboxes) == tuple:
            self.textboxes = textboxes[0]
        else:
            self.textboxes = textboxes
        self.textNodes = {}
        self.textNodePaths = {}
        self.default_text_scale = default_text_scale
        #Geometry drawing node
        self.geom_node = GeomNode("drawer")
        self.aspect2d.attach_new_node(self.geom_node)
        self.text_is_active = True
        #If the text toggle button has been up for more than one frame
        self.text_button_lifted = True
        #If changes that need to be made on text have taken place
        self.text_toggled = True
        #Loop the animation to the one loaded in the dictionary
        self.pandaActor.loop("walk")
        #Intantiates physics engine
        self.physics = physics.Swerve()
        self.taskMgr.add(self.updateJoysticks, "updateJoysticks")
        self.taskMgr.add(self.walkPandaToPhysics, "walkPandaToPhysics")
        self.taskMgr.add(self.update2dDisplay, "update2dDisplay")
        self.taskMgr.add(self.toggleText, "toggleText")
        #Creates a graph of y vectors
        self.graphs = graph_objs
        #Adds dummy value to graph to prevent crash
        self.graphs["y_graph"].update(0)
        self.graphs["vector_graph"].update(0, 0)

    def walkPanda(self, task):
        x = self.joystick_readings[0]["axes"]["left_x"]
        y = self.joystick_readings[0]["axes"]["left_y"]
        magnitude = sqrt(x**2 + y**2)
        self.pandaLocation[0] += x / 7
        self.pandaLocation[1] += y / 7
        angle = atan2(y, x) * (180 / pi)
        self.setPandaToLocation()
        self.pandaActor.setHpr(angle + 90, 0, 0)
        if not self.pandaActor.getCurrentAnim() == "walk":
            self.pandaActor.loop("walk")
        else:
            self.pandaActor.setPlayRate(magnitude * 2, "walk")
        return Task.cont

    def walkPandaToPhysics(self, task):
        """
    Makes panda walk based on inputs from physics enigne
    """
        x = self.joystick_readings[0]["axes"]["left_x"]
        y = self.joystick_readings[0]["axes"]["left_y"]
        z = self.joystick_readings[0]["axes"]["right_x"]
        self.physics.sendControls(x, y, z)
        self.physics.update()
        self.pandaLocation[0] = self.physics.position[0]
        self.pandaLocation[1] = self.physics.position[1]
        angle = self.physics.position[2] * (180 / pi)
        self.setPandaToLocation()
        self.pandaActor.setHpr(angle + 180, 0, 0)
        self.graphs["y_graph"].update(self.physics.velocities["frame"][1])
        magnitude = sqrt(x**2 + y**2)
        direction = atan2(y, x)
        self.graphs["vector_graph"].update(magnitude, direction)
        return Task.cont

    def setPandaToLocation(self):
        self.pandaActor.setPos(self.pandaLocation[0], self.pandaLocation[1],
                               self.pandaLocation[2])

    def updateJoysticks(self, task):
        joystick_readings = []
        for joystick in self.joys:
            joystick_readings.append(joy.readJoystickValues(joystick))
        self.joystick_readings = joystick_readings
        return Task.cont

    def update2dDisplay(self, task):
        """
    Updates the 2d heads-up overlay
    """
        #Removes all lines from the geometry node
        self.geom_node.removeAllGeoms()
        if self.text_is_active:
            frvector = "Mag: {}\nDir: {}\nTheta_acc: {}\nVel_x: {}\nVel_y: {}\nVel_t: {}\nPos: {}, {}\nRot: {}".format(
                round(self.physics.vectors["frame"].magnitude, 4),
                round(self.physics.vectors["frame"].direction, 4),
                round(self.physics.z_acceleration, 4),
                round(self.physics.velocities["frame"][0], 4),
                round(self.physics.velocities["frame"][1], 4),
                round(self.physics.z_velocity, 4),
                round(self.physics.position[0], 4),
                round(self.physics.position[1], 4),
                round(self.physics.position[2], 4))
            self.textboxes["frvector_value"]["text"] = frvector
            self.lines = []
            for graph_name in self.graphs:
                lines, strings = self.graphs[graph_name].render()
                #Splits the lines into pairs of points and assigns them to self.lines
                for line in lines:
                    self.lines += pairPoints(line)
                #Clears all graph generated strings from textboxes
                deleted = []
                for key in self.textboxes:
                    if graph_name in key:
                        deleted.append(key)
                for key in deleted:
                    self.textboxes.pop(key)
                #Processes strings into textboxes
                for ind, val in enumerate(strings):
                    location, string = val
                    self.textboxes["{}_{}".format(graph_name, str(ind))] = {
                        "location": location,
                        "text": string
                    }
            self.manageTextNodes()
            self.renderText()
            self.manageGeometry()
        return Task.cont

    def manageGeometry(self):
        """
    Manages geometry generation
    """
        #(Re)Renders all the lines which are in self.lines
        for line in self.lines:
            self.addLine(line)

    def addLine(self, points):
        """
    Adds a line to class GeomNode from a pair of points
    """
        #Creates objects needed to draw a geometry on the HUD
        #The vertex data which will define the rendered geometry
        vertex_data = GeomVertexData("graph", GeomVertexFormat.getV3(),
                                     Geom.UHStatic)
        #The object that writes vertexes the vertex data
        writer = GeomVertexWriter(vertex_data, "vertex")
        for point in points:
            writer.add_data3f(point[0], 0, point[1])
        #Defines that this geometry represents a polyline
        primitive = GeomLinestrips(Geom.UHStatic)
        #Tells geometry how many verticies will be added(?)
        primitive.add_consecutive_vertices(0, 2)
        primitive.close_primitive()
        geometry = Geom(vertex_data)
        geometry.add_primitive(primitive)
        #Draws a graph on the HUD
        self.geom_node.add_geom(geometry)

    def manageTextNodes(self):
        deleted = []
        for name in self.textboxes:
            if name not in self.textNodes:
                #If the name has not been given a textNode object, set it up
                self.textNodes[name] = TextNode(name)
                self.textNodePaths[name] = self.aspect2d.attachNewNode(
                    self.textNodes[name])
        #Checks if any textNodes no longer have their respective textbox object and should be deleted
        for name in self.textNodes:
            if name not in self.textboxes:
                deleted.append(name)
        for node in deleted:
            self.textNodePaths[node].removeNode()
            self.textNodePaths.pop(node)
            self.textNodes.pop(node)

    def renderText(self):
        for name in self.textboxes:
            if "location" in self.textboxes[name]:
                location = self.textboxes[name]["location"]
            else:
                location = (0, 0)
            if "scale" in self.textboxes[name]:
                scale = self.textboxes[name]["scale"]
            else:
                scale = self.default_text_scale
            if "text" in self.textboxes[name]:
                self.textNodes[name].setText(self.textboxes[name]["text"])
            self.textNodePaths[name].setScale(scale)
            self.textNodePaths[name].setPos(location[0], 0, location[1])

    def toggleText(self, task):
        if self.joystick_readings[0]["axes"][
                "right_trigger"] >= .05 and self.text_button_lifted:
            self.text_is_active = not self.text_is_active
            self.text_toggled = False
            self.text_button_lifted = False
        elif not self.joystick_readings[0]["axes"]["right_trigger"] >= .05:
            self.text_button_lifted = True
        if not self.text_toggled:
            if not self.text_is_active:
                for path in self.textNodePaths:
                    self.textNodePaths[path].detachNode()
                for path in self.lineNodePaths:
                    path.detachNode()
            else:
                for node in self.textNodes:
                    self.textNodePaths[node] = self.aspect2d.attachNewNode(
                        self.textNodes[node])
                for node in self.lineNodes:
                    self.aspect2d.attachNewNode(node)
        return Task.cont
Esempio n. 2
0
class Viewer(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        base.setBackgroundColor(0, 0, 0)

        # Disable default camera control.
        base.disableMouse()

        # Set relative mode and hide the cursor:
        self.toggle_mouse(True)
        self.accept('e', lambda: self.toggle_mouse(not self.capture_mouse))

        # Add an event handler to prompt for a model to load.
        self.accept('f', self.prompt_for_model)

        # Initialize the camera and add a task to control it.
        self.eye = Eye()
        self.update_camera()
        self.taskMgr.add(self.control_camera, "control_camera_task")

        self.load_default_model()
        self.setup_lights()

    def toggle_mouse(self, capture=True):
        win_props = WindowProperties()
        win_props.setCursorHidden(capture)
        base.win.requestProperties(win_props)
        self.capture_mouse = capture
        win_x, win_y = base.win.getXSize(), base.win.getYSize()
        base.win.movePointer(0, win_x // 2, win_y // 2)

    def update_camera(self):
        self.camera.setPos(*self.eye.pos)
        self.camera.setHpr(self.eye.yaw - 90.0, self.eye.pitch, 0)

    def control_camera(self, task):
        theta = self.eye.yaw / 180 * math.pi
        phi = self.eye.pitch / 180 * math.pi
        eye_dir = np.array([
            math.cos(theta) * math.cos(phi),
            math.sin(theta) * math.cos(phi),
            math.sin(phi),
        ])
        up_dir = np.array([0.0, 0.0, 1.0])
        side_dir = np.cross(eye_dir, up_dir)

        # Update camera based on
        move_speed = 10.0 * globalClock.get_dt()
        if base.mouseWatcherNode.is_button_down(KeyboardButton.shift()):
            move_speed *= 10.0
        if base.mouseWatcherNode.is_button_down(KeyboardButton.ascii_key('w')):
            self.eye.pos[:] += move_speed * eye_dir
        if base.mouseWatcherNode.is_button_down(KeyboardButton.ascii_key('s')):
            self.eye.pos[:] -= move_speed * eye_dir
        if base.mouseWatcherNode.is_button_down(KeyboardButton.ascii_key('d')):
            self.eye.pos[:] += move_speed * side_dir
        if base.mouseWatcherNode.is_button_down(KeyboardButton.ascii_key('a')):
            self.eye.pos[:] -= move_speed * side_dir

        if self.capture_mouse:
            view_speed = 10.0 * globalClock.get_dt()
            win_x, win_y = base.win.getXSize(), base.win.getYSize()
            cursor = base.win.getPointer(0)
            dx = cursor.getX() - base.win.getXSize() // 2
            dy = cursor.getY() - base.win.getYSize() // 2
            self.eye.yaw = (self.eye.yaw - view_speed * dx) % 360.0
            self.eye.pitch = min(85.0,
                                 max(-85.0, self.eye.pitch - move_speed * dy))
            base.win.movePointer(0, win_x // 2, win_y // 2)

        self.update_camera()

        return Task.cont

    def load_default_model(self):
        # Initialize the voxel geometry.
        t = pyskip.Tensor(shape=(3, 3, 3), val=0)
        t[0, 0, 0] = 1
        t[1, 0, 0] = 2
        t[1, 1, 0] = 1
        t[1, 2, 0] = 2

        # Define the color of each voxel type.
        config = voxels.VoxelConfig()
        config[0] = voxels.EmptyVoxel()
        config[1] = voxels.ColorVoxel(128, 0, 0)
        config[2] = voxels.ColorVoxel(0, 0, 128)

        # Map the tensor onto a mesh.
        mesh = voxels.to_mesh(t, config)

        # Load the mesh into a panda geometry node.
        self.model = GeomNode('mesh_node')
        self.model.addGeom(create_geometry_from_mesh(mesh))
        render.attachNewNode(self.model)

    def prompt_for_model(self):
        # Prompt for a model to load.
        root = tk.Tk()
        root.withdraw()
        file_path = filedialog.askopenfilename()

        # Load the corresponding level into a tensor.
        print(f"Loading level: {file_path}")
        level = minecraft.PySkipMinecraftLevel.load(file_path)
        print(f"Generating megatensor...")
        tensor = level.megatensor()

        # Create the corresponding color config.
        config = voxels.VoxelConfig()
        config[0] = voxels.EmptyVoxel()
        for i in range(1, 256):
            r, g, b = colors.color_for_id(i)
            config[i] = voxels.ColorVoxel(r, g, b)

        # Map the tensor onto a mesh.
        print(f"Building geometry...")
        mesh = voxels.to_mesh(tensor, config)

        # Load the mesh into a panda geometry node.
        self.model.removeAllGeoms()
        self.model.addGeom(create_geometry_from_mesh(mesh))
        print(f"Done.")

    def setup_lights(self):
        ambient_light = AmbientLight("ambient_light")
        ambient_light.setColor((0.3, 0.3, 0.3, 1))
        directional_light = DirectionalLight("directional_light")
        directional_light.setDirection(LVector3(0, 8, -2.5))
        directional_light.setColor((0.9, 0.8, 0.9, 1))
        render.setLight(render.attachNewNode(directional_light))
        render.setLight(render.attachNewNode(ambient_light))
Esempio n. 3
0
class RobotSim(ShowBase):
    def __init__(self, textboxes=({}), graph_objs={}, default_text_scale=.07):
        ShowBase.__init__(self)
        self.scene = self.loader.loadModel("field_1.obj", noCache=True)
        # Reparent the model to render.
        self.scene.reparentTo(self.render)
        self.scene.setPos(0, 0, 0)
        self.insertLight("MainLight", 0, 0, 75)
        self.insertLight("ExtraLight1", -50, 0, 75)
        self.resetSim()

        self.robot = SwerveBot()
        self.robot.loadModel()

        self.setupCones()
        #Joystick setup
        self.joys = self.devices.getDevices(InputDevice.DeviceClass.gamepad)
        #Attaches input devices to base
        for ind, joy in enumerate(self.joys):
            self.attachInputDevice(joy, prefix=str(ind))
        #Joystick reading variable
        self.joystick_readings = []
        #Text boxes which will be rendered every frame
        #Key is a node name, value is a dict with
        #arguments such as text, location, and scale
        #Hack to keep default argument immutable and prevent bugs
        if type(textboxes) == tuple:
            self.textboxes = textboxes[0]
        else:
            self.textboxes = textboxes
        self.textNodes = {}
        self.textNodePaths = {}
        self.default_text_scale = default_text_scale
        self.text_is_active = False
        #If the text toggle button has been up for more than one frame
        self.text_button_lifted = True
        #If changes that need to be made on text have taken place
        self.text_toggled = True
        #Graph drawing data
        #Lines to be rendered on the next frame
        self.lines = []
        self.lineNodes = []
        self.lineNodePaths = []
        self.graphs = graph_objs
        for graph in self.graphs:
            self.graphs[graph].dummyUpdate()
        #Init physics engine
        self.physics = physics.Swerve()
        #Geometry drawing node
        self.geom_node = GeomNode("drawer")
        self.aspect2d.attach_new_node(self.geom_node)
        #Tasks
        self.taskMgr.add(self.updateJoysticks, "updateJoysticks")
        self.taskMgr.add(self.driveRobot, "driveRobot")
        self.taskMgr.add(self.updateHud, "updateHud")
        self.taskMgr.add(self.toggleHud, "toggleHud")
        self.accept('r', self.reportStatus)
        self.accept('i', self.resetSim)
        self.accept('a', self.robot.toggleAutoDrive)

    def driveRobot(self, task):
        """
		Task to drive the robot
		"""
        x = self.joystick_readings[0]["axes"]["left_x"]
        y = self.joystick_readings[0]["axes"]["left_y"]
        z = self.joystick_readings[0]["axes"]["right_x"]
        self.physics.sendControls(x, y, z)
        self.physics.update()
        self.setRobotToLocation()
        return Task.cont

    def setRobotToLocation(self):
        x = self.physics.position[0]
        y = self.physics.position[1]
        angle = self.physics.position[2] * (2 * pi)
        self.robot.setPos(x, y, angle)
        caster_angle_1 = self.physics.positions["brswerve"] * (180 / pi) + 90
        caster_angle_2 = self.physics.positions["blswerve"] * (180 / pi) + 90
        caster_angle_3 = self.physics.positions["flswerve"] * (180 / pi) + 90
        caster_angle_4 = self.physics.positions["frswerve"] * (180 / pi) + 90
        self.robot.setCasterAngles(caster_angle_1, caster_angle_2,
                                   caster_angle_3, caster_angle_4)
        wheel_angle_1 = self.physics.positions["brwheel"] / (2 * pi)
        wheel_angle_2 = self.physics.positions["blwheel"] / (2 * pi)
        wheel_angle_3 = self.physics.positions["flwheel"] / (2 * pi)
        wheel_angle_4 = self.physics.positions["frwheel"] / (2 * pi)
        self.robot.setWheelTurns(wheel_angle_1, wheel_angle_2, wheel_angle_3,
                                 wheel_angle_4)

    def updateJoysticks(self, task):
        joystick_readings = []
        for joystick in self.joys:
            joystick_readings.append(joy.readJoystickValues(joystick))
        self.joystick_readings = joystick_readings
        return Task.cont

    def updateHud(self, task):
        #Removes all lines from the geometry node
        self.geom_node.removeAllGeoms()
        if self.text_is_active:
            frvector = "Mag: {}\nDir: {}\nTheta_acc: {}\nVel_x: {}\nVel_y: {}\nVel_t: {}\nPos: {}, {}\nRot: {}".format(
                round(self.physics.vectors["frame"].magnitude, 4),
                round(self.physics.vectors["frame"].direction, 4),
                round(self.physics.z_acceleration, 4),
                round(self.physics.velocities["frame"][0], 4),
                round(self.physics.velocities["frame"][1], 4),
                round(self.physics.z_velocity, 4),
                round(self.physics.position[0], 4),
                round(self.physics.position[1], 4),
                round(self.physics.position[2], 4))
            self.textboxes["frvector_value"]["text"] = frvector
            self.lines = []
            for graph_name in self.graphs:
                lines, strings = self.graphs[graph_name].render()
                #Splits the lines into pairs of points and assigns them to self.lines
                for line in lines:
                    self.lines += pairPoints(line)
#Clears all graph generated strings from textboxes
                deleted = []
                for key in self.textboxes:
                    if graph_name in key:
                        deleted.append(key)
                for key in deleted:
                    self.textboxes.pop(key)

#Processes strings into textboxes
                for ind, val in enumerate(strings):
                    location, string = val
                    self.textboxes["{}_{}".format(graph_name, str(ind))] = {
                        "location": location,
                        "text": string
                    }
            self.manageTextNodes()
            self.renderText()
            self.manageGeometry()
        return Task.cont

    def toggleHud(self, task):
        if self.joystick_readings[0]["axes"][
                "right_trigger"] >= .05 and self.text_button_lifted:
            self.text_is_active = not self.text_is_active
            self.text_toggled = False
            self.text_button_lifted = False
        elif not self.joystick_readings[0]["axes"]["right_trigger"] >= .05:
            self.text_button_lifted = True
        if not self.text_toggled:
            if not self.text_is_active:
                for path in self.textNodePaths:
                    self.textNodePaths[path].detachNode()
                for path in self.lineNodePaths:
                    path.detachNode()
            else:
                for node in self.textNodes:
                    self.textNodePaths[node] = self.aspect2d.attachNewNode(
                        self.textNodes[node])
                for node in self.lineNodes:
                    self.aspect2d.attachNewNode(node)
        return Task.cont

    def resetSim(self):
        base.disableMouse()
        self.resetCamPosition()
        self.allowMovement()

    def allowMovement(self):
        mat = Mat4(camera.getMat())
        mat.invertInPlace()
        base.mouseInterfaceNode.setMat(mat)
        base.enableMouse()
        #self.resetCamPosition()

    def insertLight(self, name, x, y, z):
        lightball = self.loader.loadModel("lightball_1.obj", noCache=True)
        lightball.reparentTo(self.render)
        lightball.setPos(x, y, z)
        plight = PointLight(name)
        plight.setColor(VBase4(1.0, 1.0, 1.0, 1))
        plnp = self.render.attachNewNode(plight)
        plnp.setPos(x, y, z)
        self.render.setLight(plnp)

    def setupCones(self):
        self.cones = []
        conepos = [(20, 20), (18, 0)]
        for cp in conepos:
            c = Cones()
            c.loadModel()
            x, y = cp
            c.setPos(x, y)
            self.cones.append(c)

    def reportStatus(self):
        x = base.camera.getX()
        y = base.camera.getY()
        z = base.camera.getZ()
        print("Camera Position", x, y, z)
        h = base.camera.getH()
        p = base.camera.getP()
        r = base.camera.getR()
        print("Camera Angle", h, p, r)

    def resetCamPosition(self):
        self.camPos = (-28, -23, 17)
        self.camAngle = (-51, -17, -12)
        x, y, z = self.camPos
        h, p, r = self.camAngle
        base.camera.setPos(x, y, z)
        base.camera.setHpr(h, p, r)
Esempio n. 4
0
class PointsSet(VisibleObject):
    tex = None

    def __init__(self,
                 use_sprites=True,
                 use_sizes=True,
                 points_size=2,
                 sprite=None,
                 background=None,
                 shader=None):
        self.gnode = GeomNode('starfield')
        self.use_sprites = use_sprites
        self.use_sizes = use_sizes
        self.background = background
        if shader is None:
            shader = BasicShader(lighting_model=FlatLightingModel(),
                                 point_shader=False)
        self.shader = shader

        self.reset()

        self.geom = self.makeGeom([], [], [])
        self.gnode.addGeom(self.geom)
        self.instance = NodePath(self.gnode)
        if self.use_sprites:
            if sprite is None:
                sprite = RoundDiskPointSprite()
            self.sprite = sprite
        else:
            self.sprite = SimplePoint(points_size)
        self.min_size = self.sprite.get_min_size()
        self.sprite.apply(self.instance)
        self.instance.setCollideMask(GeomNode.getDefaultCollideMask())
        self.instance.node().setPythonTag('owner', self)
        #TODO: Should not use ModelAppearance !
        self.appearance = ModelAppearance(vertex_color=True)
        if self.appearance is not None:
            self.appearance.bake()
            self.appearance.apply(self, self)
        if self.shader is not None:
            self.shader.apply(self, self.appearance)
        if self.use_sprites:
            self.instance.node().setBounds(OmniBoundingVolume())
            self.instance.node().setFinal(True)
        if self.background is not None:
            self.instance.setBin('background', self.background)
        self.instance.set_depth_write(False)

    def jobs_done_cb(self, patch):
        pass

    def reset(self):
        self.points = []
        self.colors = []
        self.sizes = []

    def add_point_scale(self, position, color, size):
        #Observer is at position (0, 0, 0)
        distance_to_obs = position.length()
        vector_to_obs = -position / distance_to_obs
        point, _, _ = self.get_real_pos_rel(position, distance_to_obs,
                                            vector_to_obs)
        self.points.append(point)
        self.colors.append(color)
        self.sizes.append(size)

    def add_point(self, position, color, size):
        self.points.append(position)
        self.colors.append(color)
        self.sizes.append(size)

    def update(self):
        self.update_arrays(self.points, self.colors, self.sizes)

    def makeGeom(self, points, colors, sizes):
        #format = GeomVertexFormat.getV3c4()
        array = GeomVertexArrayFormat()
        array.addColumn(InternalName.make('vertex'), 3, Geom.NTFloat32,
                        Geom.CPoint)
        array.addColumn(InternalName.make('color'), 4, Geom.NTFloat32,
                        Geom.CColor)
        if self.use_sizes:
            array.addColumn(InternalName.make('size'), 1, Geom.NTFloat32,
                            Geom.COther)
        format = GeomVertexFormat()
        format.addArray(array)
        format = GeomVertexFormat.registerFormat(format)
        vdata = GeomVertexData('vdata', format, Geom.UH_static)
        vdata.unclean_set_num_rows(len(points))
        self.vwriter = GeomVertexWriter(vdata, 'vertex')
        self.colorwriter = GeomVertexWriter(vdata, 'color')
        if self.use_sizes:
            self.sizewriter = GeomVertexWriter(vdata, 'size')
        geompoints = GeomPoints(Geom.UH_static)
        geompoints.reserve_num_vertices(len(points))
        index = 0
        for (point, color, size) in zip(points, colors, sizes):
            self.vwriter.addData3f(*point)
            #self.colorwriter.addData3f(color[0], color[1], color[2])
            self.colorwriter.addData4f(*color)
            if self.use_sizes:
                self.sizewriter.addData1f(size)
            geompoints.addVertex(index)
            geompoints.closePrimitive()
            index += 1
        geom = Geom(vdata)
        geom.addPrimitive(geompoints)
        return geom

    def update_arrays(self, points, colors, sizes):
        self.gnode.removeAllGeoms()
        self.geom = self.makeGeom(points, colors, sizes)
        self.gnode.addGeom(self.geom)
Esempio n. 5
0
class LineMesh:
	def __init__(self, game, color=(1,1,1,1)):
		self.game = game
		self.node = GeomNode("lines")
		self.np = NodePath(self.node)
		self.np.reparentTo(self.game.render)
		self.np.setShaderOff()
		self.format = makeVertexFormat()
		self.vertices = []
		self.lines = []
		self.color = color
		
	def getNbVertices(self):
		return len(self.vertices)
		
	def getNbLines(self):
		return len(self.lines)
	
	def getRandomColor(self):
		return getRandomColor()
		'''
		c1 = random.uniform(0,1)
		c2 = random.uniform(0,1)
		c3 = random.uniform(0,1)
		return (c1, c2, c3, 1)
		'''
		
	nbVertices = property(getNbVertices)
	nbLines = property(getNbLines)
	
	def reset(self):
		self.clearMesh()
		self.vertices = []
		self.lines = []
	
	def clearMesh(self):
		#if self.np:
		#	self.np.remove()
		self.node.removeAllGeoms()
		
		self.vdata = GeomVertexData ('name', self.format, Geom.UHStatic)
		self.vWriter = GeomVertexWriter (self.vdata, 'vertex')
		self.cWriter = GeomVertexWriter (self.vdata, 'color')
		
		self.geom = Geom(self.vdata)
		#self.node = GeomNode("lines")
		
		self.node.addGeom(self.geom)
		
		#self.np = NodePath(self.node)
		#self.np.reparentTo(self.game.render)
		
	def draw(self):
		self.clearMesh()
		#print "vertices : %s" % (self.vertices)
		
		for p in self.vertices:
			self.vWriter.addData3f(p[0], p[1], p[2])
			self.cWriter.addData4f(self.color)
			
		lines = GeomLinestrips (Geom.UHStatic)
		for line in self.lines:
			lines.addVertices(line[0], line[1])
			lines.closePrimitive()
		self.geom.addPrimitive (lines)
		
	def addLineStrip(self, pointList, closed = False):
		nbPts = len(pointList)
		if nbPts < 2:
			return
		
		nbV = self.nbVertices
		
		#for p in pointList:
		#	self.vertices.append(p)
		self.vertices.extend(pointList)
		
		for i in range(nbPts-1):
			self.lines.append((nbV + i, nbV + i + 1))
		if closed:
			self.lines.append((nbV + nbPts - 1, nbV))
	
	def addBox(self, size, pos, rot=0):
		x = size[0] / 2.0
		y = size[1] / 2.0
		z = size[2] / 2.0
		
		#print "drawing lines, x = %s" % (x)
		# base points
		p1 = Point3(-x,-y,-z)
		p2 = Point3(x,-y,-z)
		p3 = Point3(x,y,-z)
		p4 = Point3(-x,y,-z)
		# top points
		p1t = Point3(-x,-y,z)
		p2t = Point3(x,-y,z)
		p3t = Point3(x,y,z)
		p4t = Point3(-x,y,z)
		
		pList = [p1, p2, p3, p4, p1t, p2t, p3t, p4t]
		#dP = Point3(pos[0], pos[1], pos[2])
		newList = translatePoints(pList, dP)
		newList = rotatePoints(newList, rot)
		
		self.addLineStrip(newList[0:4], True)
		self.addLineStrip(newList[4:8], True)
		for i in range(4):
			self.addLineStrip([newList[i], newList[i+4]], False)
		
	
		
	def addSideWall(self, pointList, dh=2.0, closed = False):
		nbPts = len(pointList)
		if nbPts < 2:
			return
		try:
			dh = float(dh)
			dh = (0, 0, dh)
		except:
			pass
		
		topPointList = translatePoints(pointList, dh)
		self.addLineStrip(pointList, closed)
		self.addLineStrip(topPointList, closed)
		
		for i in range(nbPts):
			p1 = pointList[i]
			p1t = topPointList[i]
			self.addLineStrip([p1, p1t])
		
	def addThickWall(self, pointList, dh, thickness, closed, capped = False):
		rPointList, lPointList = getWallPoints(pointList, dh, thickness, closed, capped)
		
		if closed:
			self.addSideWall(rPointList, dh, True)
			self.addSideWall(lPointList, dh, True)
			
		else:
			newList = []
			newList.extend(rPointList)
			lPointList.reverse()
			newList.extend(lPointList)
			self.addSideWall(newList, dh, True)
		
			#print "adding wall, pointList = %s" % (newList)
		#self.addPrism(newList, h)
		
	def addPrism(self, pointList, dh = 0, pos=(0,0,0), rot=(0,0,0), closed = True):
		nbPts = len(pointList)
		if nbPts < 3:
			return
		try:
			dh = float(dh)
			dh = (0, 0, dh)
		except:
			pass
		
		topPointList = translatePoints(pointList, dh)
		
		pointList = rotatePoints(pointList, rot)
		topPointList = rotatePoints(topPointList, rot)
		
		pointList = translatePoints(pointList, pos)
		topPointList = translatePoints(topPointList, pos)
		
		self.addLineStrip(pointList, True)
		self.addLineStrip(topPointList, True)
		for i in range(nbPts):
			self.addLineStrip([pointList[i], topPointList[i+nbPts]], False)
		
		
	def addCylinder(self, pA, pB, radius = 2.0, nbSides = 16):
		normalVec = pB - pA
		basePoints = getCirclePoints(pA, radius, normalVec, nbSides)
		
		self.addPrism(basePoints, normalVec)
	
	def addCylinderShear(self, pA, normalVec, dh, radius = 2.0, nbSides = 16, pos=(0,0,0), rot=(0,0,0), closed = True):
		pointList = getCirclePoints(pA, radius, normalVec, nbSides)
		self.addPrism(pointList, dh, pos, rot, closed)
Esempio n. 6
0
class LineMesh:
    def __init__(self, game, color=(1, 1, 1, 1)):
        self.game = game
        self.node = GeomNode("lines")
        self.np = NodePath(self.node)
        self.np.reparentTo(self.game.render)
        self.np.setShaderOff()
        self.format = makeVertexFormat()
        self.vertices = []
        self.lines = []
        self.color = color

    def getNbVertices(self):
        return len(self.vertices)

    def getNbLines(self):
        return len(self.lines)

    def getRandomColor(self):
        return getRandomColor()
        '''
		c1 = random.uniform(0,1)
		c2 = random.uniform(0,1)
		c3 = random.uniform(0,1)
		return (c1, c2, c3, 1)
		'''

    nbVertices = property(getNbVertices)
    nbLines = property(getNbLines)

    def reset(self):
        self.clearMesh()
        self.vertices = []
        self.lines = []

    def clearMesh(self):
        #if self.np:
        #	self.np.remove()
        self.node.removeAllGeoms()

        self.vdata = GeomVertexData('name', self.format, Geom.UHStatic)
        self.vWriter = GeomVertexWriter(self.vdata, 'vertex')
        self.cWriter = GeomVertexWriter(self.vdata, 'color')

        self.geom = Geom(self.vdata)
        #self.node = GeomNode("lines")

        self.node.addGeom(self.geom)

        #self.np = NodePath(self.node)
        #self.np.reparentTo(self.game.render)

    def draw(self):
        self.clearMesh()
        #print "vertices : %s" % (self.vertices)

        for p in self.vertices:
            self.vWriter.addData3f(p[0], p[1], p[2])
            self.cWriter.addData4f(self.color)

        lines = GeomLinestrips(Geom.UHStatic)
        for line in self.lines:
            lines.addVertices(line[0], line[1])
            lines.closePrimitive()
        self.geom.addPrimitive(lines)

    def addLineStrip(self, pointList, closed=False):
        nbPts = len(pointList)
        if nbPts < 2:
            return

        nbV = self.nbVertices

        #for p in pointList:
        #	self.vertices.append(p)
        self.vertices.extend(pointList)

        for i in range(nbPts - 1):
            self.lines.append((nbV + i, nbV + i + 1))
        if closed:
            self.lines.append((nbV + nbPts - 1, nbV))

    def addBox(self, size, pos, rot=0):
        x = size[0] / 2.0
        y = size[1] / 2.0
        z = size[2] / 2.0

        #print "drawing lines, x = %s" % (x)
        # base points
        p1 = Point3(-x, -y, -z)
        p2 = Point3(x, -y, -z)
        p3 = Point3(x, y, -z)
        p4 = Point3(-x, y, -z)
        # top points
        p1t = Point3(-x, -y, z)
        p2t = Point3(x, -y, z)
        p3t = Point3(x, y, z)
        p4t = Point3(-x, y, z)

        pList = [p1, p2, p3, p4, p1t, p2t, p3t, p4t]
        #dP = Point3(pos[0], pos[1], pos[2])
        newList = translatePoints(pList, dP)
        newList = rotatePoints(newList, rot)

        self.addLineStrip(newList[0:4], True)
        self.addLineStrip(newList[4:8], True)
        for i in range(4):
            self.addLineStrip([newList[i], newList[i + 4]], False)

    def addSideWall(self, pointList, dh=2.0, closed=False):
        nbPts = len(pointList)
        if nbPts < 2:
            return
        try:
            dh = float(dh)
            dh = (0, 0, dh)
        except:
            pass

        topPointList = translatePoints(pointList, dh)
        self.addLineStrip(pointList, closed)
        self.addLineStrip(topPointList, closed)

        for i in range(nbPts):
            p1 = pointList[i]
            p1t = topPointList[i]
            self.addLineStrip([p1, p1t])

    def addThickWall(self, pointList, dh, thickness, closed, capped=False):
        rPointList, lPointList = getWallPoints(pointList, dh, thickness,
                                               closed, capped)

        if closed:
            self.addSideWall(rPointList, dh, True)
            self.addSideWall(lPointList, dh, True)

        else:
            newList = []
            newList.extend(rPointList)
            lPointList.reverse()
            newList.extend(lPointList)
            self.addSideWall(newList, dh, True)

            #print "adding wall, pointList = %s" % (newList)
        #self.addPrism(newList, h)

    def addPrism(self,
                 pointList,
                 dh=0,
                 pos=(0, 0, 0),
                 rot=(0, 0, 0),
                 closed=True):
        nbPts = len(pointList)
        if nbPts < 3:
            return
        try:
            dh = float(dh)
            dh = (0, 0, dh)
        except:
            pass

        topPointList = translatePoints(pointList, dh)

        pointList = rotatePoints(pointList, rot)
        topPointList = rotatePoints(topPointList, rot)

        pointList = translatePoints(pointList, pos)
        topPointList = translatePoints(topPointList, pos)

        self.addLineStrip(pointList, True)
        self.addLineStrip(topPointList, True)
        for i in range(nbPts):
            self.addLineStrip([pointList[i], topPointList[i + nbPts]], False)

    def addCylinder(self, pA, pB, radius=2.0, nbSides=16):
        normalVec = pB - pA
        basePoints = getCirclePoints(pA, radius, normalVec, nbSides)

        self.addPrism(basePoints, normalVec)

    def addCylinderShear(self,
                         pA,
                         normalVec,
                         dh,
                         radius=2.0,
                         nbSides=16,
                         pos=(0, 0, 0),
                         rot=(0, 0, 0),
                         closed=True):
        pointList = getCirclePoints(pA, radius, normalVec, nbSides)
        self.addPrism(pointList, dh, pos, rot, closed)