Ejemplo n.º 1
0
    def raycast(self, origin, direction=(0,0,1), dist=math.inf, traverse_target=scene, ignore=list(), debug=False):
        self.position = origin
        self.look_at(self.position + direction)
        # need to do this for it to work for some reason
        self._collision_ray.set_origin(Vec3(0,0,0))
        self._collision_ray.set_direction(Vec3(0,1,0))

        if debug:
            self._pickerNP.show()
        else:
            self._pickerNP.hide()

        self._picker.traverse(traverse_target)

        if self._pq.get_num_entries() == 0:
            self.hit = Hit(hit=False)
            return self.hit

        self._pq.sort_entries()
        self.entries = [        # filter out ignored entities
            e for e in self._pq.getEntries()
            if e.get_into_node_path().parent not in ignore
            ]

        if len(self.entries) == 0:
            self.hit = Hit(hit=False)
            return self.hit

        self.collision = self.entries[0]
        nP = self.collision.get_into_node_path().parent
        point = self.collision.get_surface_point(nP)
        point = Vec3(point[0], point[2], point[1])
        world_point = self.collision.get_surface_point(render)
        world_point = Vec3(world_point[0], world_point[2], world_point[1])
        hit_dist = self.distance(self.world_position, world_point)
        if hit_dist <= dist:
            if nP.name.endswith('.egg'):
                nP = nP.parent

            self.hit = Hit(hit=True)
            for e in scene.entities:
                if e == nP:
                    # print('cast nP to Entity')
                    self.hit.entity = e

            self.hit.point = point
            self.hit.world_point = world_point
            self.hit.distance = hit_dist
            normal = self.collision.get_surface_normal(self.collision.get_into_node_path().parent)
            self.hit.normal = (normal[0], normal[2], normal[1])
            normal = self.collision.get_surface_normal(render)
            self.hit.world_normal = (normal[0], normal[2], normal[1])
            return self.hit

        self.hit = Hit(hit=False)
        return self.hit
Ejemplo n.º 2
0
    def boxcast(self,
                origin,
                direction=(0, 0, 1),
                distance=math.inf,
                thickness=(1, 1),
                traverse_target=scene,
                ignore=list(),
                debug=False):
        if isinstance(thickness, (int, float, complex)):
            thickness = (thickness, thickness)
        resolution = 3
        rays = list()
        debugs = list()

        for y in range(3):
            for x in range(3):
                pos = origin + Vec3(
                    lerp(-(thickness[0] / 2), thickness[0] / 2, x / (3 - 1)),
                    lerp(-(thickness[1] / 2), thickness[1] / 2, y /
                         (3 - 1)), 0)
                ray = self.raycast(pos, direction, distance, traverse_target,
                                   ignore, False)
                rays.append(ray)

                if debug and ray.hit:
                    d = Entity(model='cube',
                               origin_z=-.5,
                               position=pos,
                               scale=(.02, .02, distance),
                               ignore=True)
                    d.look_at(pos + Vec3(direction))
                    debugs.append(d)
                    # print(pos, hit.point)
                    if ray.hit and ray.distance > 0:
                        d.scale_z = ray.distance
                        d.color = color.green

        from ursina import destroy
        # [destroy(e, 1/60) for e in debugs]

        rays.sort(key=lambda x: x.distance)
        closest = rays[0]

        return Hit(
            hit=sum([int(e.hit) for e in rays]) > 0,
            entity=closest.entity,
            point=closest.point,
            world_point=closest.world_point,
            distance=closest.distance,
            normal=closest.normal,
            world_normal=closest.world_normal,
            hits=[e.hit for e in rays],
            entities=list(set([e.entity
                               for e in rays])),  # get unique entities hit
        )
Ejemplo n.º 3
0
    def find_collision(self):
        if not self.raycast:
            return
        self._pq.sortEntries()
        if len(self._pq.get_entries()) == 0:
            self.collision = None
            return

        self.collisions = list()
        for entry in self._pq.getEntries():
            # print(entry.getIntoNodePath().parent)
            for entity in scene.entities:
                if entry.getIntoNodePath().parent == entity:
                    if entity.collision:
                        self.collisions.append(
                            Hit(
                                hit=entry.collided(),
                                entity=entity,
                                distance=0,
                                point=entry.getSurfacePoint(entity),
                                world_point=entry.getSurfacePoint(scene),
                                normal=entry.getSurfaceNormal(entity),
                                world_normal=entry.getSurfaceNormal(scene),
                            ))
                        break

        self.collision = self._pq.getEntry(0)
        nP = self.collision.getIntoNodePath().parent

        for entity in scene.entities:
            if not hasattr(entity, 'collision'
                           ) or not entity.collision or not entity.collider:
                continue
            # if hit entity is not hovered, call on_mouse_enter()
            if entity == nP:
                if not entity.hovered:
                    entity.hovered = True
                    self.hovered_entity = entity
                    # print(entity.name)
                    if hasattr(entity, 'on_mouse_enter'):
                        entity.on_mouse_enter()
                    for s in entity.scripts:
                        if hasattr(s, 'on_mouse_enter'):
                            s.on_mouse_enter()
            # unhover the rest
            else:
                if entity.hovered:
                    entity.hovered = False
                    if hasattr(entity, 'on_mouse_exit'):
                        entity.on_mouse_exit()
                    for s in entity.scripts:
                        if hasattr(s, 'on_mouse_exit'):
                            s.on_mouse_exit()
Ejemplo n.º 4
0
    def find_collision(self):
        self.collisions = list()
        self.collision = None
        if not self.raycast or self._pq.get_num_entries() == 0:
            self.unhover_everything_not_hit()
            return False

        self._pq.sortEntries()

        for entry in self._pq.getEntries():
            for entity in scene.entities:
                if entry.getIntoNodePath(
                ).parent == entity and entity.collision:
                    if entity.collision:
                        hit = Hit(
                            hit=entry.collided(),
                            entity=entity,
                            distance=distance(entry.getSurfacePoint(scene),
                                              camera.getPos()),
                            point=entry.getSurfacePoint(entity),
                            world_point=entry.getSurfacePoint(scene),
                            normal=entry.getSurfaceNormal(entity),
                            world_normal=entry.getSurfaceNormal(scene),
                        )
                        hit.point = Vec3(hit.point[0], hit.point[2],
                                         hit.point[1])
                        hit.world_point = Vec3(hit.world_point[0],
                                               hit.world_point[2],
                                               hit.world_point[1])
                        hit.normal = Vec3(hit.normal[0], hit.normal[2],
                                          hit.normal[1])
                        hit.world_normal = Vec3(hit.world_normal[0],
                                                hit.world_normal[2],
                                                hit.world_normal[1])
                        self.collisions.append(hit)
                        break

        if self.collisions:
            self.collision = self.collisions[0]
            self.hovered_entity = self.collision.entity
            if not self.hovered_entity.hovered:
                self.hovered_entity.hovered = True
                if hasattr(self.hovered_entity, 'on_mouse_enter'):
                    self.hovered_entity.on_mouse_enter()
                for s in self.hovered_entity.scripts:
                    if hasattr(s, 'on_mouse_enter'):
                        s.on_mouse_enter()

        self.unhover_everything_not_hit()
Ejemplo n.º 5
0
    def raycast(self,
                origin,
                direction=(0, 0, 1),
                distance=math.inf,
                traverse_target=scene,
                ignore=list(),
                debug=False):
        self.position = origin
        self.look_at(self.position + direction)
        self._pickerNode.clearSolids()
        # if thickness == (0,0):
        if distance == math.inf:
            ray = CollisionRay()
            ray.setOrigin(Vec3(0, 0, 0))
            ray.setDirection(Vec3(0, 1, 0))
        else:
            ray = CollisionSegment(Vec3(0, 0, 0), Vec3(0, distance, 0))

        self._pickerNode.addSolid(ray)

        if debug:
            self._pickerNP.show()
        else:
            self._pickerNP.hide()

        self._picker.traverse(traverse_target)

        if self._pq.get_num_entries() == 0:
            self.hit = Hit(hit=False)
            return self.hit

        ignore += tuple([e for e in scene.entities if not e.collision])

        self._pq.sort_entries()
        self.entries = [  # filter out ignored entities
            e for e in self._pq.getEntries()
            if e.get_into_node_path().parent not in ignore
        ]

        if len(self.entries) == 0:
            self.hit = Hit(hit=False)
            return self.hit

        self.collision = self.entries[0]
        nP = self.collision.get_into_node_path().parent
        point = self.collision.get_surface_point(nP)
        point = Vec3(point[0], point[2], point[1])
        world_point = self.collision.get_surface_point(render)
        world_point = Vec3(world_point[0], world_point[2], world_point[1])
        hit_dist = self.distance(self.world_position, world_point)

        if nP.name.endswith('.egg'):
            nP = nP.parent

        self.hit = Hit(hit=True)
        for e in scene.entities:
            if e == nP:
                # print('cast nP to Entity')
                self.hit.entity = e

        self.hit.point = point
        self.hit.world_point = world_point
        self.hit.distance = hit_dist

        normal = self.collision.get_surface_normal(
            self.collision.get_into_node_path().parent)
        self.hit.normal = (normal[0], normal[2], normal[1])

        normal = self.collision.get_surface_normal(render)
        self.hit.world_normal = (normal[0], normal[2], normal[1])
        return self.hit

        self.hit = Hit(hit=False)
        return self.hit