mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Reorganize methods and how triangulation gets refreshed
This commit is contained in:
parent
f314054081
commit
d4c89e520f
1 changed files with 92 additions and 81 deletions
|
@ -90,13 +90,6 @@ class VMobject(Mobject):
|
||||||
"unit_normal": np.zeros((1, 3))
|
"unit_normal": np.zeros((1, 3))
|
||||||
})
|
})
|
||||||
|
|
||||||
def set_points(self, points):
|
|
||||||
old_points = self.get_points()
|
|
||||||
super().set_points(points)
|
|
||||||
if not np.all(points == old_points):
|
|
||||||
self.refresh_triangulation()
|
|
||||||
return self
|
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
def init_colors(self):
|
def init_colors(self):
|
||||||
self.set_fill(
|
self.set_fill(
|
||||||
|
@ -458,19 +451,6 @@ class VMobject(Mobject):
|
||||||
self.resize_data(len(self.get_points() - 1))
|
self.resize_data(len(self.get_points() - 1))
|
||||||
self.append_points(new_points)
|
self.append_points(new_points)
|
||||||
|
|
||||||
# TODO, how to be smart about tangents here?
|
|
||||||
def apply_function(self, function):
|
|
||||||
Mobject.apply_function(self, function)
|
|
||||||
if self.make_smooth_after_applying_functions:
|
|
||||||
self.make_smooth()
|
|
||||||
self.refresh_triangulation()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def flip(self, *args, **kwargs):
|
|
||||||
super().flip(*args, **kwargs)
|
|
||||||
self.refresh_unit_normal()
|
|
||||||
self.refresh_triangulation()
|
|
||||||
|
|
||||||
#
|
#
|
||||||
def consider_points_equals(self, p0, p1):
|
def consider_points_equals(self, p0, p1):
|
||||||
return get_norm(p1 - p0) < self.tolerance_for_point_equality
|
return get_norm(p1 - p0) < self.tolerance_for_point_equality
|
||||||
|
@ -761,6 +741,98 @@ class VMobject(Mobject):
|
||||||
vmob.pointwise_become_partial(self, a, b)
|
vmob.pointwise_become_partial(self, a, b)
|
||||||
return vmob
|
return vmob
|
||||||
|
|
||||||
|
# Related to triangulation
|
||||||
|
|
||||||
|
def refresh_triangulation(self):
|
||||||
|
for mob in self.get_family():
|
||||||
|
mob.needs_new_triangulation = True
|
||||||
|
return self
|
||||||
|
|
||||||
|
def get_triangulation(self, normal_vector=None):
|
||||||
|
# Figure out how to triangulate the interior to know
|
||||||
|
# how to send the points as to the vertex shader.
|
||||||
|
# First triangles come directly from the points
|
||||||
|
if normal_vector is None:
|
||||||
|
normal_vector = self.get_unit_normal()
|
||||||
|
|
||||||
|
if not self.needs_new_triangulation:
|
||||||
|
return self.triangulation
|
||||||
|
|
||||||
|
points = self.get_points()
|
||||||
|
|
||||||
|
if len(points) <= 1:
|
||||||
|
self.triangulation = np.zeros(0, dtype='i4')
|
||||||
|
self.needs_new_triangulation = False
|
||||||
|
return self.triangulation
|
||||||
|
|
||||||
|
# Rotate points such that unit normal vector is OUT
|
||||||
|
# TODO, 99% of the time this does nothing. Do a check for that?
|
||||||
|
points = np.dot(points, z_to_vector(normal_vector))
|
||||||
|
indices = np.arange(len(points), dtype=int)
|
||||||
|
|
||||||
|
b0s = points[0::3]
|
||||||
|
b1s = points[1::3]
|
||||||
|
b2s = points[2::3]
|
||||||
|
v01s = b1s - b0s
|
||||||
|
v12s = b2s - b1s
|
||||||
|
|
||||||
|
crosses = cross2d(v01s, v12s)
|
||||||
|
convexities = np.sign(crosses)
|
||||||
|
|
||||||
|
atol = self.tolerance_for_point_equality
|
||||||
|
end_of_loop = np.zeros(len(b0s), dtype=bool)
|
||||||
|
end_of_loop[:-1] = (np.abs(b2s[:-1] - b0s[1:]) > atol).any(1)
|
||||||
|
end_of_loop[-1] = True
|
||||||
|
|
||||||
|
concave_parts = convexities < 0
|
||||||
|
|
||||||
|
# These are the vertices to which we'll apply a polygon triangulation
|
||||||
|
inner_vert_indices = np.hstack([
|
||||||
|
indices[0::3],
|
||||||
|
indices[1::3][concave_parts],
|
||||||
|
indices[2::3][end_of_loop],
|
||||||
|
])
|
||||||
|
inner_vert_indices.sort()
|
||||||
|
rings = np.arange(1, len(inner_vert_indices) + 1)[inner_vert_indices % 3 == 2]
|
||||||
|
|
||||||
|
# Triangulate
|
||||||
|
inner_verts = points[inner_vert_indices]
|
||||||
|
inner_tri_indices = inner_vert_indices[earclip_triangulation(inner_verts, rings)]
|
||||||
|
|
||||||
|
tri_indices = np.hstack([indices, inner_tri_indices])
|
||||||
|
self.triangulation = tri_indices
|
||||||
|
self.needs_new_triangulation = False
|
||||||
|
return tri_indices
|
||||||
|
|
||||||
|
def triggers_refreshed_triangulation(func):
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
old_points = self.get_points()
|
||||||
|
func(self, *args, **kwargs)
|
||||||
|
if not np.all(self.get_points() == old_points):
|
||||||
|
self.refresh_triangulation()
|
||||||
|
self.refresh_unit_normal()
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
@triggers_refreshed_triangulation
|
||||||
|
def set_points(self, points):
|
||||||
|
super().set_points(points)
|
||||||
|
|
||||||
|
@triggers_refreshed_triangulation
|
||||||
|
def set_data(self, data):
|
||||||
|
super().set_data(data)
|
||||||
|
|
||||||
|
# TODO, how to be smart about tangents here?
|
||||||
|
@triggers_refreshed_triangulation
|
||||||
|
def apply_function(self, function):
|
||||||
|
super().apply_function(function)
|
||||||
|
if self.make_smooth_after_applying_functions:
|
||||||
|
self.make_smooth()
|
||||||
|
return self
|
||||||
|
|
||||||
|
@triggers_refreshed_triangulation
|
||||||
|
def flip(self, *args, **kwargs):
|
||||||
|
super().flip(*args, **kwargs)
|
||||||
|
|
||||||
# For shaders
|
# For shaders
|
||||||
def init_shader_data(self):
|
def init_shader_data(self):
|
||||||
self.fill_data = np.zeros(0, dtype=self.fill_dtype)
|
self.fill_data = np.zeros(0, dtype=self.fill_dtype)
|
||||||
|
@ -849,67 +921,6 @@ class VMobject(Mobject):
|
||||||
|
|
||||||
return self.stroke_data
|
return self.stroke_data
|
||||||
|
|
||||||
def refresh_triangulation(self):
|
|
||||||
for mob in self.get_family():
|
|
||||||
mob.needs_new_triangulation = True
|
|
||||||
return self
|
|
||||||
|
|
||||||
def get_triangulation(self, normal_vector=None):
|
|
||||||
# Figure out how to triangulate the interior to know
|
|
||||||
# how to send the points as to the vertex shader.
|
|
||||||
# First triangles come directly from the points
|
|
||||||
if normal_vector is None:
|
|
||||||
normal_vector = self.get_unit_normal()
|
|
||||||
|
|
||||||
if not self.needs_new_triangulation:
|
|
||||||
return self.triangulation
|
|
||||||
|
|
||||||
points = self.get_points()
|
|
||||||
|
|
||||||
if len(points) <= 1:
|
|
||||||
self.triangulation = np.zeros(0, dtype='i4')
|
|
||||||
self.needs_new_triangulation = False
|
|
||||||
return self.triangulation
|
|
||||||
|
|
||||||
# Rotate points such that unit normal vector is OUT
|
|
||||||
# TODO, 99% of the time this does nothing. Do a check for that?
|
|
||||||
points = np.dot(points, z_to_vector(normal_vector))
|
|
||||||
indices = np.arange(len(points), dtype=int)
|
|
||||||
|
|
||||||
b0s = points[0::3]
|
|
||||||
b1s = points[1::3]
|
|
||||||
b2s = points[2::3]
|
|
||||||
v01s = b1s - b0s
|
|
||||||
v12s = b2s - b1s
|
|
||||||
|
|
||||||
crosses = cross2d(v01s, v12s)
|
|
||||||
convexities = np.sign(crosses)
|
|
||||||
|
|
||||||
atol = self.tolerance_for_point_equality
|
|
||||||
end_of_loop = np.zeros(len(b0s), dtype=bool)
|
|
||||||
end_of_loop[:-1] = (np.abs(b2s[:-1] - b0s[1:]) > atol).any(1)
|
|
||||||
end_of_loop[-1] = True
|
|
||||||
|
|
||||||
concave_parts = convexities < 0
|
|
||||||
|
|
||||||
# These are the vertices to which we'll apply a polygon triangulation
|
|
||||||
inner_vert_indices = np.hstack([
|
|
||||||
indices[0::3],
|
|
||||||
indices[1::3][concave_parts],
|
|
||||||
indices[2::3][end_of_loop],
|
|
||||||
])
|
|
||||||
inner_vert_indices.sort()
|
|
||||||
rings = np.arange(1, len(inner_vert_indices) + 1)[inner_vert_indices % 3 == 2]
|
|
||||||
|
|
||||||
# Triangulate
|
|
||||||
inner_verts = points[inner_vert_indices]
|
|
||||||
inner_tri_indices = inner_vert_indices[earclip_triangulation(inner_verts, rings)]
|
|
||||||
|
|
||||||
tri_indices = np.hstack([indices, inner_tri_indices])
|
|
||||||
self.triangulation = tri_indices
|
|
||||||
self.needs_new_triangulation = False
|
|
||||||
return tri_indices
|
|
||||||
|
|
||||||
def get_fill_shader_data(self):
|
def get_fill_shader_data(self):
|
||||||
points = self.get_points()
|
points = self.get_points()
|
||||||
if len(self.fill_data) != len(points):
|
if len(self.fill_data) != len(points):
|
||||||
|
|
Loading…
Add table
Reference in a new issue