예제 #1
0
파일: poly.py 프로젝트: gutioliveira/FGAme
def aabb_poly(A, B, collision_class=Collision):
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    A_poly = Rectangle(A.rect_coords)
    col = collision_poly(A_poly, B)
    if col is not None:
        return collision_class(A, B, pos=col.pos, normal=col.normal,
                               delta=col.delta)
    else:
        return None
예제 #2
0
def circle_aabb(A, B):
    '''Reutiliza a lógica de Circle/Poly para realizar a colisão com AABBs'''
    
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None
    
    B_poly = Rectangle(bbox=B.bbox)
    col = circle_poly(A, B_poly)
    if col is not None:
        return Collision(A, B, pos=col.pos, normal=col.normal, delta=col.delta)
    else:
        return None
예제 #3
0
def aabb_poly(A, B):
    '''Implementa a colisão entre um polígono arbitrário e uma caixa AABB'''

    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    A_poly = Rectangle(bbox=A.bbox)
    col = collision_poly(A_poly, B)
    if col is not None:
        return Collision(A, B, pos=col.pos, normal=col.normal, delta=col.delta)
    else:
        return None
예제 #4
0
def circle_poly(A, B):
    '''Implementa a colisão entre um círculo arbitrário um polígono.
    
    A normal resultante sempre sai do círculo na direção do polígono.
    '''
    
    # Verifica as AABB
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    # Procura o ponto mais próximo de B
    vertices = B.vertices
    N = len(vertices)
    center = A.pos
    normals = [(i, v - center, v) for i, v in enumerate(vertices)]
    idx, _, pos = min(normals, key=lambda x: x[1].norm())
    
    # A menor distância para o centro pode ser do tipo vértice-ponto ou 
    # aresta-ponto. Assumimos o vértice inicialmente.
    distance = (pos - center).norm()
    
    # Agora verificamos cada face
    P0 = pos
    P = vertices[(idx - 1) % N]
    v = center - P
    u = P0 - P
    L = u.norm()
    delta = v.cross(u) / L
    
    # Verifica se o ponto mais próximo se encontra no segmento
    if delta < distance and u.dot(v) < L**2:
        pos = P + (u.dot(v) / L**2) * u
        distance = delta
    
    # Mesmo teste para a face do ponto posterior
    P = vertices[(idx + 1) % N]
    v = center - P
    u = P0 - P
    L = u.norm()
    delta = -v.cross(u) / L
    if delta < distance and u.dot(v) < L ** 2:
        pos = P + (u.dot(v) / L ** 2) * u
        distance = delta
    
    # Verificamos se houve colisão ou não na direção esperada
    delta = A.radius - distance
    normal = (pos - center).normalized()
    
    if delta > 0:
        return Collision(A, B, pos=pos, normal=normal, delta=delta)
    else:
        return None
예제 #5
0
def aabb_poly(A, B, collision_class=Collision):
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    A_poly = Rectangle(A.rect_coords)
    col = collision_poly(A_poly, B)
    if col is not None:
        return collision_class(A,
                               B,
                               pos=col.pos,
                               normal=col.normal,
                               delta=col.delta)
    else:
        return None
예제 #6
0
파일: poly.py 프로젝트: gutioliveira/FGAme
def circle_poly(A, B, collision_class=Collision):
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    # Searches for the nearest point to B
    vertices = B.vertices
    center = A.pos
    normals = [(i, v - center, v) for i, v in enumerate(vertices)]
    idx, _, pos = min(normals, key=lambda x: x[1].norm())

    # The smaller distance to the center can be vertex-center or side-center.
    # We need to detect this.
    separation = (pos - center).norm()

    # Verify each face
    P0 = pos
    N = len(vertices)
    for idx in [(idx - 1) % N, (idx + 1) % N]:
        P = vertices[idx]
        v = center - P
        u = P0 - P
        L = u.norm()
        distance = abs(v.cross(u) / L)

        # Verify if closest point is inside segment
        if distance < separation and u.dot(v) < L ** 2:
            pos = P + (u.dot(v) / L ** 2) * u
            separation = distance

    # Verify if there is collision in the direction of smaller separation
    delta = A.radius - separation
    normal = (pos - center).normalize()

    if delta > 0:
        return collision_class(A, B, pos=pos, normal=normal, delta=delta)
    else:
        return None
예제 #7
0
def circle_poly(A, B, collision_class=Collision):
    if shadow_x(A, B) < 0 or shadow_y(A, B) < 0:
        return None

    # Searches for the nearest point to B
    vertices = B.vertices
    center = A.pos
    normals = [(i, v - center, v) for i, v in enumerate(vertices)]
    idx, _, pos = min(normals, key=lambda x: x[1].norm())

    # The smaller distance to the center can be vertex-center or side-center.
    # We need to detect this.
    separation = (pos - center).norm()

    # Verify each face
    P0 = pos
    N = len(vertices)
    for idx in [(idx - 1) % N, (idx + 1) % N]:
        P = vertices[idx]
        v = center - P
        u = P0 - P
        L = u.norm()
        distance = abs(v.cross(u) / L)

        # Verify if closest point is inside segment
        if distance < separation and u.dot(v) < L**2:
            pos = P + (u.dot(v) / L**2) * u
            separation = distance

    # Verify if there is collision in the direction of smaller separation
    delta = A.radius - separation
    normal = (pos - center).normalize()

    if delta > 0:
        return collision_class(A, B, pos=pos, normal=normal, delta=delta)
    else:
        return None
예제 #8
0
    def update(self, L):
        IS_SLEEP = flags.is_sleeping
        can_collide = self._collision_check
        col_idx = 0
        objects = sorted(L, key=lambda obj: obj.xmin)
        self._data[:] = []

        # Os objetos estão ordenados. Este loop detecta as colisões da CBB e
        # salva o resultado na lista broad collisions
        for i, A in enumerate(objects):
            A_right = A.xmax
            A_dynamic = A.is_dynamic()

            for j in range(i + 1, len(objects)):
                B = objects[j]
                if not can_collide(A, B):
                    continue

                # Procura na lista enquanto xmin de B for menor que xmax de A
                B_left = B.xmin
                if B_left > A_right:
                    break

                # Não detecta colisão entre dois objetos estáticos/cinemáticos
                if not A_dynamic and not B.is_dynamic():
                    continue
                if A.flags & B.flags & IS_SLEEP:
                    continue

                # Testa a colisão entre as AABBs
                if shadow_y(A, B) <= 0:
                    continue

                # Adiciona à lista de colisões grosseiras
                col_idx += 1
                self._data.append(AABBContact(A, B))
예제 #9
0
파일: broadphase.py 프로젝트: diegor2/FGAme
    def update(self, L):
        IS_SLEEP = BodyFlags.is_sleeping
        can_collide = self.world.can_collide
        col_idx = 0
        objects = sorted(L, key=lambda obj: obj.xmin)
        self._data[:] = []

        # Os objetos estão ordenados. Este loop detecta as colisões da CBB e
        # salva o resultado na lista broad collisions
        for i, A in enumerate(objects):
            A_right = A.xmax
            A_dynamic = A.is_dynamic()

            for j in range(i + 1, len(objects)):
                B = objects[j]
                if not can_collide(A, B):
                    continue

                # Procura na lista enquanto xmin de B for menor que xmax de A
                B_left = B.xmin
                if B_left > A_right:
                    break

                # Não detecta colisão entre dois objetos estáticos/cinemáticos
                if not A_dynamic and not B.is_dynamic():
                    continue
                if A.flags & B.flags & IS_SLEEP:
                    continue

                # Testa a colisão entre as AABBs
                if shadow_y(A, B) <= 0:
                    continue

                # Adiciona à lista de colisões grosseiras
                col_idx += 1
                self._data.append(AABBContact(A, B))