Mr Anonymous
Mr Anonymous

Reputation: 71

Drawing Clockwise Triangles Reordering Points

I was making a ray tracer in c++ and was coming across an issue when I downloaded objects because it would only render some of the triangles because they were drawn counter-clockwise.

I looked up this being an issue since it would be back facing. But Im confused on how you are actually supposed to know just by the vertices. If anyone could help me make a function to take in three vectors for each point of the triangle and reorder them so that It would be drawn clockwise.

Thank you.

Upvotes: 3

Views: 350

Answers (1)

Reblochon Masque
Reblochon Masque

Reputation: 36682

You can calculate the signed area formed by the triangle defined by the three points - this is equivalent to the 2D 'cross product' of the vectors representing the edges (sometimes called perp product):

Here is a naive implementation in python that shows the calculation; you can transcribe it to C++ at your leisure.

From there, swapping the position of two points in the triangle will invert the turn from ccw to cw, and vice-versa

class CollinearpointsError(ValueError):
    pass


def ccw(triangle):
    """returns True if the triangle points are counter clock wise,
    False otherwise, and raises a CollinearpointsError when the 
    three points are collinear 
    """
    A, B, C = triangle
    ax, ay = A
    bx, by = B
    cx, cy = C
    
    AB = (bx - ax, by - ay)
    AC = (cx - ax, cy - ay)

    a, b = AB
    c, d = AC
    
    signed_area_x2 = a * d - b * c
    if signed_area == 0:
        raise CollinearpointsError('the three points are collinear')

    return (a * d - b * c) > 0


def cw(triangle):
    """returns True if the triangle points are clock wise,
    False otherwise, and raises a CollinearpointsError when the 
    three points are collinear 
    """
    return not ccw(triangle)


A = (0, 0)
B = (0, 1)
C = (1, 0)

triangle = (A, B, C)
print(cw(triangle))

triangle = (A, C, B)
print(cw(triangle))

triangle = (A, B, (0, 2))
print(cw(triangle))

output:

True
False
CollinearpointsError: the three points are collinear

Upvotes: 2

Related Questions