Track unit normal for fill

This commit is contained in:
Grant Sanderson
2023-01-27 12:35:43 -08:00
parent 1c432dd6dc
commit 86fb69c5bb
4 changed files with 42 additions and 12 deletions

View File

@ -62,8 +62,9 @@ class VMobject(Mobject):
('joint_product', np.float32, (4,)), ('joint_product', np.float32, (4,)),
('fill_rgba', np.float32, (4,)), ('fill_rgba', np.float32, (4,)),
('base_point', np.float32, (3,)), ('base_point', np.float32, (3,)),
('unit_normal', np.float32, (3,)),
]) ])
fill_data_names = ['point', 'fill_rgba', 'base_point'] fill_data_names = ['point', 'fill_rgba', 'base_point', 'unit_normal']
stroke_data_names = ['point', 'stroke_rgba', 'stroke_width', 'joint_product'] stroke_data_names = ['point', 'stroke_rgba', 'stroke_width', 'joint_product']
fill_render_primitive: int = moderngl.TRIANGLE_STRIP fill_render_primitive: int = moderngl.TRIANGLE_STRIP
@ -827,8 +828,25 @@ class VMobject(Mobject):
points[1] - points[0], points[1] - points[0],
points[2] - points[1], points[2] - points[1],
) )
self.data["unit_normal"][:] = normal
return normal return normal
def refresh_unit_normal(self):
self.get_unit_normal()
return self
def rotate(
self,
angle: float,
axis: Vect3 = OUT,
about_point: Vect3 | None = None,
**kwargs
):
super().rotate(angle, axis, about_point, **kwargs)
for mob in self.get_family():
mob.refresh_unit_normal()
return self
def ensure_positive_orientation(self, recurse=True): def ensure_positive_orientation(self, recurse=True):
for mob in self.get_family(recurse): for mob in self.get_family(recurse):
if mob.get_unit_normal()[2] < 0: if mob.get_unit_normal()[2] < 0:
@ -1148,6 +1166,7 @@ class VMobject(Mobject):
self.refresh_triangulation() self.refresh_triangulation()
if refresh_joints: if refresh_joints:
self.get_joint_products(refresh=True) self.get_joint_products(refresh=True)
self.get_unit_normal()
return self return self
@triggers_refreshed_triangulation @triggers_refreshed_triangulation
@ -1157,16 +1176,14 @@ class VMobject(Mobject):
return self return self
@triggers_refreshed_triangulation @triggers_refreshed_triangulation
def reverse_points(self): def reverse_points(self, recurse: bool = True):
# This will reset which anchors are # This will reset which anchors are
# considered path ends # considered path ends
for mob in self.get_family(): for mob in self.get_family(recurse):
if not mob.has_points(): if not mob.has_points():
continue continue
inner_ends = mob.get_subpath_end_indices()[:-1] inner_ends = mob.get_subpath_end_indices()[:-1]
mob.data["point"][inner_ends + 1] = mob.data["point"][inner_ends + 2] mob.data["point"][inner_ends + 1] = mob.data["point"][inner_ends + 2]
super().reverse_points()
return self
@triggers_refreshed_triangulation @triggers_refreshed_triangulation
def set_data(self, data: np.ndarray): def set_data(self, data: np.ndarray):
@ -1248,11 +1265,12 @@ class VMobject(Mobject):
back_stroke_data = [] back_stroke_data = []
for submob in family: for submob in family:
if submob.has_fill(): if submob.has_fill():
submob.data["base_point"][:] = submob.data["point"][0] data = submob.data[fill_names]
fill_datas.append(submob.data[fill_names]) data["base_point"][:] = data["point"][0]
fill_datas.append(data)
if self._use_winding_fill: if self._use_winding_fill:
# Add dummy # Add dummy
fill_datas.append(submob.data[fill_names][-1:]) fill_datas.append(data[-1:])
else: else:
fill_indices.append(submob.get_triangulation()) fill_indices.append(submob.get_triangulation())
if submob.has_stroke(): if submob.has_stroke():

View File

@ -7,6 +7,7 @@ in float fill_all;
in float orientation; in float orientation;
in vec2 uv_coords; in vec2 uv_coords;
in vec3 point; in vec3 point;
in vec3 unit_normal;
out vec4 frag_color; out vec4 frag_color;
@ -14,7 +15,7 @@ out vec4 frag_color;
void main() { void main() {
if (color.a == 0) discard; if (color.a == 0) discard;
frag_color = finalize_color(color, point, vec3(0.0, 0.0, 1.0)); frag_color = finalize_color(color, point, unit_normal);
/* /*
We want negatively oriented triangles to be canceled with positively We want negatively oriented triangles to be canceled with positively
oriented ones. The easiest way to do this is to give them negative alpha, oriented ones. The easiest way to do this is to give them negative alpha,

View File

@ -9,11 +9,13 @@ in vec3 verts[3];
in vec4 v_color[3]; in vec4 v_color[3];
in vec3 v_base_point[3]; in vec3 v_base_point[3];
in float v_vert_index[3]; in float v_vert_index[3];
in vec3 v_unit_normal[3];
out vec4 color; out vec4 color;
out float fill_all; out float fill_all;
out float orientation; out float orientation;
out vec3 point; out vec3 point;
out vec3 unit_normal;
// uv space is where the curve coincides with y = x^2 // uv space is where the curve coincides with y = x^2
out vec2 uv_coords; out vec2 uv_coords;
@ -26,12 +28,18 @@ const vec2 SIMPLE_QUADRATIC[3] = vec2[3](
// Analog of import for manim only // Analog of import for manim only
#INSERT get_gl_Position.glsl #INSERT get_gl_Position.glsl
#INSERT get_unit_normal.glsl
void emit_triangle(vec3 points[3], vec4 v_color[3]){ void emit_triangle(vec3 points[3], vec4 v_color[3]){
vec3 unit_normal = get_unit_normal(points[0], points[1], points[2]); unit_normal = v_unit_normal[1];
orientation = winding ? sign(unit_normal.z) : 1.0; orientation = 1.0;
if(winding){
orientation = sign(determinant(mat3(
v_unit_normal[1],
points[1] - points[0],
points[2] - points[0]
)));
}
for(int i = 0; i < 3; i++){ for(int i = 0; i < 3; i++){
uv_coords = SIMPLE_QUADRATIC[i]; uv_coords = SIMPLE_QUADRATIC[i];

View File

@ -3,15 +3,18 @@
in vec3 point; in vec3 point;
in vec4 fill_rgba; in vec4 fill_rgba;
in vec3 base_point; in vec3 base_point;
in vec3 unit_normal;
out vec3 verts; // Bezier control point out vec3 verts; // Bezier control point
out vec4 v_color; out vec4 v_color;
out vec3 v_base_point; out vec3 v_base_point;
out vec3 v_unit_normal;
out float v_vert_index; out float v_vert_index;
void main(){ void main(){
verts = point; verts = point;
v_color = fill_rgba; v_color = fill_rgba;
v_base_point = base_point; v_base_point = base_point;
v_unit_normal = unit_normal;
v_vert_index = gl_VertexID; v_vert_index = gl_VertexID;
} }