For Surface, calculate normals with neighboring points

This commit is contained in:
Grant Sanderson 2024-08-22 15:21:40 -05:00
parent c8d5e91422
commit 9a7bfdd1c9
4 changed files with 27 additions and 42 deletions

View file

@ -28,9 +28,11 @@ class Surface(Mobject):
shader_folder: str = "surface" shader_folder: str = "surface"
data_dtype: np.dtype = np.dtype([ data_dtype: np.dtype = np.dtype([
('point', np.float32, (3,)), ('point', np.float32, (3,)),
('normal', np.float32, (3,)), ('du_point', np.float32, (3,)),
('dv_point', np.float32, (3,)),
('rgba', np.float32, (4,)), ('rgba', np.float32, (4,)),
]) ])
pointlike_data_keys = ['point', 'du_point', 'dv_point']
def __init__( def __init__(
self, self,
@ -46,7 +48,7 @@ class Surface(Mobject):
prefered_creation_axis: int = 1, prefered_creation_axis: int = 1,
# For du and dv steps. Much smaller and numerical error # For du and dv steps. Much smaller and numerical error
# can crop up in the shaders. # can crop up in the shaders.
epsilon: float = 1e-5, epsilon: float = 1e-4,
**kwargs **kwargs
): ):
self.u_range = u_range self.u_range = u_range
@ -95,10 +97,8 @@ class Surface(Mobject):
for grid in (uv_grid, uv_plus_du, uv_plus_dv) for grid in (uv_grid, uv_plus_du, uv_plus_dv)
] ]
self.set_points(points) self.set_points(points)
self.data["normal"] = normalize_along_axis(cross( self.data['du_point'][:] = du_points
(du_points - points) / self.epsilon, self.data['dv_point'][:] = dv_points
(dv_points - points) / self.epsilon,
), 1)
def apply_points_function(self, *args, **kwargs) -> Self: def apply_points_function(self, *args, **kwargs) -> Self:
super().apply_points_function(*args, **kwargs) super().apply_points_function(*args, **kwargs)
@ -128,36 +128,12 @@ class Surface(Mobject):
return self.triangle_indices return self.triangle_indices
def get_unit_normals(self) -> Vect3Array: def get_unit_normals(self) -> Vect3Array:
nu, nv = self.resolution
indices = np.arange(nu * nv)
if len(indices) == 0:
return np.zeros((3, 0))
# For each point, find two adjacent points at indices
# step1 and step2, such that crossing points[step1] - points
# with points[step1] - points gives a normal vector
step1 = indices + 1
step2 = indices + nu
# Right edge
step1[nu - 1::nu] = indices[nu - 1::nu] + nu
step2[nu - 1::nu] = indices[nu - 1::nu] - 1
# Bottom edge
step1[-nu:] = indices[-nu:] - nu
step2[-nu:] = indices[-nu:] + 1
# Lower right point
step1[-1] = indices[-1] - 1
step2[-1] = indices[-1] - nu
points = self.get_points() points = self.get_points()
crosses = cross( crosses = cross(
points[step2] - points, self.data['du_point'] - points,
points[step1] - points, self.data['dv_point'] - points,
) )
self.data["normal"] = normalize_along_axis(crosses, 1) return normalize_along_axis(crosses, 1)
return self.data["normal"]
@Mobject.affects_data @Mobject.affects_data
def pointwise_become_partial( def pointwise_become_partial(
@ -291,7 +267,8 @@ class TexturedSurface(Surface):
shader_folder: str = "textured_surface" shader_folder: str = "textured_surface"
data_dtype: Sequence[Tuple[str, type, Tuple[int]]] = [ data_dtype: Sequence[Tuple[str, type, Tuple[int]]] = [
('point', np.float32, (3,)), ('point', np.float32, (3,)),
('normal', np.float32, (3,)), ('du_point', np.float32, (3,)),
('dv_point', np.float32, (3,)),
('im_coords', np.float32, (2,)), ('im_coords', np.float32, (2,)),
('opacity', np.float32, (1,)), ('opacity', np.float32, (1,)),
] ]
@ -335,7 +312,8 @@ class TexturedSurface(Surface):
self.resize_points(surf.get_num_points()) self.resize_points(surf.get_num_points())
self.resolution = surf.resolution self.resolution = surf.resolution
self.data['point'][:] = surf.data['point'] self.data['point'][:] = surf.data['point']
self.data['normal'][:] = surf.data['normal'] self.data['du_point'][:] = surf.data['du_point']
self.data['dv_point'][:] = surf.data['dv_point']
self.data['opacity'][:, 0] = surf.data["rgba"][:, 3] self.data['opacity'][:, 0] = surf.data["rgba"][:, 3]
self.data["im_coords"] = np.array([ self.data["im_coords"] = np.array([
[u, v] [u, v]

View file

@ -3,7 +3,9 @@
uniform vec4 clip_plane; uniform vec4 clip_plane;
in vec3 point; in vec3 point;
in vec3 normal; in vec3 du_point;
in vec3 dv_point;
// in vec3 normal;
in vec4 rgba; in vec4 rgba;
out vec4 v_color; out vec4 v_color;
@ -14,6 +16,7 @@ out vec4 v_color;
void main(){ void main(){
emit_gl_Position(point); emit_gl_Position(point);
vec3 normal = cross(normalize(du_point - point), normalize(dv_point - point));
v_color = finalize_color(rgba, point, normalize(normal)); v_color = finalize_color(rgba, point, normalize(normal));
if(clip_plane.xyz != vec3(0.0, 0.0, 0.0)){ if(clip_plane.xyz != vec3(0.0, 0.0, 0.0)){

View file

@ -5,7 +5,7 @@ uniform sampler2D DarkTexture;
uniform float num_textures; uniform float num_textures;
in vec3 v_point; in vec3 v_point;
in vec3 v_normal; in vec3 v_unit_normal;
in vec2 v_im_coords; in vec2 v_im_coords;
in float v_opacity; in float v_opacity;
@ -21,7 +21,7 @@ void main() {
vec4 dark_color = texture(DarkTexture, v_im_coords); vec4 dark_color = texture(DarkTexture, v_im_coords);
float dp = dot( float dp = dot(
normalize(light_position - v_point), normalize(light_position - v_point),
normalize(v_normal) v_unit_normal
); );
float alpha = smoothstep(-dark_shift, dark_shift, dp); float alpha = smoothstep(-dark_shift, dark_shift, dp);
color = mix(dark_color, color, alpha); color = mix(dark_color, color, alpha);
@ -30,7 +30,7 @@ void main() {
frag_color = finalize_color( frag_color = finalize_color(
color, color,
v_point, v_point,
normalize(v_normal) v_unit_normal
); );
frag_color.a = v_opacity; frag_color.a = v_opacity;
} }

View file

@ -1,12 +1,13 @@
#version 330 #version 330
in vec3 point; in vec3 point;
in vec3 normal; in vec3 du_point;
in vec3 dv_point;
in vec2 im_coords; in vec2 im_coords;
in float opacity; in float opacity;
out vec3 v_point; out vec3 v_point;
out vec3 v_normal; out vec3 v_unit_normal;
out vec2 v_im_coords; out vec2 v_im_coords;
out float v_opacity; out float v_opacity;
@ -15,7 +16,10 @@ out float v_opacity;
void main(){ void main(){
v_point = point; v_point = point;
v_normal = normal; v_unit_normal = normalize(cross(
normalize(du_point - point),
normalize(dv_point - point)
));
v_im_coords = im_coords; v_im_coords = im_coords;
v_opacity = opacity; v_opacity = opacity;
emit_gl_Position(point); emit_gl_Position(point);