mirror of
https://github.com/3b1b/manim.git
synced 2025-11-13 18:37:49 +00:00
Only compute xyz-to-uv matrix in non-linear case
This commit is contained in:
parent
1c2ec03f7d
commit
909e515a2f
3 changed files with 57 additions and 41 deletions
|
|
@ -65,38 +65,40 @@ mat4 map_onto_x_axis(vec3 src0, vec3 src1){
|
|||
if(vect.x > 1 - 1e-6) return shift;
|
||||
|
||||
// Equivalent to cross(vect, vec3(1, 0, 0))
|
||||
vec3 axis = vec3(0.0, vect.z, -vect.y);
|
||||
mat4 rotate = rotation(normalize(axis), vect.x);
|
||||
vec3 axis = normalize(vec3(0.0, vect.z, -vect.y));
|
||||
mat4 rotate = rotation(axis, vect.x);
|
||||
return rotate * shift;
|
||||
}
|
||||
|
||||
|
||||
mat4 get_xyz_to_uv(vec3 b0, vec3 b1, vec3 b2, float temp_is_linear, out float is_linear){
|
||||
mat4 get_xyz_to_uv(
|
||||
vec3 b0, vec3 b1, vec3 b2,
|
||||
float threshold,
|
||||
out bool exceeds_threshold
|
||||
){
|
||||
/*
|
||||
Returns a matrix for an affine transformation which maps a set of quadratic
|
||||
bezier controls points into a new coordinate system such that the bezier curve
|
||||
coincides with y = x^2, or in the case of a linear curve, it's mapped to the x-axis.
|
||||
Populates the matrix `result` with an affine transformation which maps a set of
|
||||
quadratic bezier controls points into a new coordinate system such that the bezier
|
||||
curve coincides with y = x^2.
|
||||
|
||||
If the x-range under this part of the curve exceeds `threshold`, this returns false
|
||||
and populates result a matrix mapping b0 and b2 onto the x-axis
|
||||
*/
|
||||
is_linear = temp_is_linear;
|
||||
vec2 xs = xs_on_clean_parabola(b0, b1, b2);
|
||||
float x0 = xs[0];
|
||||
float x1 = 0.5 * (xs[0] + xs[1]);
|
||||
float x2 = xs[1];
|
||||
// Portions of the parabola y = x^2 where abs(x) exceeds
|
||||
// this value are treated as straight lines.
|
||||
float thresh = 2.0;
|
||||
if (!bool(is_linear)){
|
||||
vec2 xs = xs_on_clean_parabola(b0, b1, b2);
|
||||
float x0 = xs.x;
|
||||
float x2 = xs.y;
|
||||
if((x0 > thresh && x2 > thresh) || (x0 < -thresh && x2 < -thresh)){
|
||||
is_linear = 1.0;
|
||||
}else{
|
||||
// This triangle on the xy plane should be isometric
|
||||
// to (b0, b1, b2), and it should define a quadratic
|
||||
// bezier segment aligned with y = x^2
|
||||
vec3 dst0 = vec3(x0, x0 * x0, 0.0);
|
||||
vec3 dst1 = vec3(0.5 * (x0 + x2), x0 * x2, 0.0);
|
||||
vec3 dst2 = vec3(x2, x2 * x2, 0.0);
|
||||
return map_triangles(b0, b1, b2, dst0, dst1, dst2);
|
||||
}
|
||||
exceeds_threshold = (min(x0, x2) > threshold || max(x0, x2) < -threshold);
|
||||
if(exceeds_threshold){
|
||||
return map_onto_x_axis(b0, b2);
|
||||
}
|
||||
// Only lands here if is_linear is 1.0
|
||||
return map_onto_x_axis(b0, b2);
|
||||
// This triangle on the xy plane should be isometric
|
||||
// to (b0, b1, b2), and it should define a quadratic
|
||||
// bezier segment aligned with y = x^2
|
||||
vec3 dst0 = vec3(x0, x0 * x0, 0.0);
|
||||
vec3 dst1 = vec3(x1, x0 * x2, 0.0);
|
||||
vec3 dst2 = vec3(x2, x2 * x2, 0.0);
|
||||
return map_triangles(b0, b1, b2, dst0, dst1, dst2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,11 +79,13 @@ void emit_pentagon(
|
|||
}
|
||||
|
||||
// Compute xy_to_uv matrix, and potentially re-evaluate bezier degree
|
||||
mat4 xyz_to_uv = get_xyz_to_uv(p0, p1, p2, is_linear, is_linear);
|
||||
bool too_steep;
|
||||
mat4 xyz_to_uv = get_xyz_to_uv(p0, p1, p2, 10.0, too_steep);
|
||||
if(too_steep) is_linear = 1.0;
|
||||
uv_anti_alias_width = aaw * length(xyz_to_uv[0].xyz);
|
||||
|
||||
for(int i = 0; i < 5; i++){
|
||||
int j = int(sign(i - 1) + 1); // Maps i = [0, 1, 2, 3, 4] onto j = [0, 0, 1, 2, 2]
|
||||
int j = int[5](0, 0, 1, 2, 2)[i];
|
||||
vec3 corner = corners[i];
|
||||
uv_coords = (xyz_to_uv * vec4(corner, 1.0)).xy;
|
||||
emit_vertex_wrapper(corner, j, unit_normal);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ vec3 get_joint_unit_normal(vec4 joint_product){
|
|||
result = v_joint_product[1].xyz;
|
||||
}
|
||||
float norm = length(result);
|
||||
return (norm > 1e-10) ? result / norm : vec3(0.0, 0.0, 1.0);
|
||||
return (norm > 1e-5) ? result / norm : vec3(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -171,28 +171,40 @@ void main() {
|
|||
float cos_angle = v_joint_product[1].w;
|
||||
is_linear = float(cos_angle > COS_THRESHOLD);
|
||||
|
||||
// If the curve is flat, put the middle control in the midpoint
|
||||
if (bool(is_linear)) p1 = 0.5 * (p0 + p2);
|
||||
|
||||
// We want to change the coordinates to a space where the curve
|
||||
// coincides with y = x^2, between some values x0 and x2. Or, in
|
||||
// the case of a linear curve (bezier degree 1), just put it on
|
||||
// the x-axis
|
||||
mat4 xyz_to_uv = get_xyz_to_uv(p0, p1, p2, is_linear, is_linear);
|
||||
// the case of a linear curve just put it on the x-axis
|
||||
mat4 xyz_to_uv;
|
||||
float uv_scale_factor;
|
||||
if(!bool(is_linear)){
|
||||
bool too_steep;
|
||||
xyz_to_uv = get_xyz_to_uv(p0, p1, p2, 2.0, too_steep);
|
||||
if(too_steep) is_linear = 1.0;
|
||||
uv_scale_factor = length(xyz_to_uv[0].xyz);
|
||||
}
|
||||
|
||||
float uv_scale_factor = length(xyz_to_uv[0].xyz);
|
||||
float scaled_aaw = anti_alias_width * pixel_size;
|
||||
uv_anti_alias_width = uv_scale_factor * scaled_aaw;
|
||||
|
||||
vec3 corners[6];
|
||||
get_corners(p0, p1, p2, v01, v12, scaled_aaw, corners);
|
||||
|
||||
// Emit each corner
|
||||
for(int i = 0; i < 6; i++){
|
||||
int vert_index = i / 2;
|
||||
uv_coords = (xyz_to_uv * vec4(corners[i], 1)).xy;
|
||||
uv_stroke_width = uv_scale_factor * v_stroke_width[vert_index];
|
||||
color = finalize_color(v_color[vert_index], corners[i], unit_normal);
|
||||
float stroke_width = v_stroke_width[i / 2];
|
||||
|
||||
if(bool(is_linear)){
|
||||
float sign = vec2(-1, 1)[i % 2];
|
||||
// In this case, we only really care about
|
||||
// the v coordinate
|
||||
uv_coords = vec2(0, sign * (0.5 * stroke_width + scaled_aaw));
|
||||
uv_anti_alias_width = scaled_aaw;
|
||||
uv_stroke_width = stroke_width;
|
||||
}else{
|
||||
uv_coords = (xyz_to_uv * vec4(corners[i], 1.0)).xy;
|
||||
uv_stroke_width = uv_scale_factor * stroke_width;
|
||||
uv_anti_alias_width = uv_scale_factor * scaled_aaw;
|
||||
}
|
||||
|
||||
color = finalize_color(v_color[i / 2], corners[i], unit_normal);
|
||||
gl_Position = get_gl_Position(corners[i]);
|
||||
EmitVertex();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue