StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
2.5 KiB
79 lines
2.5 KiB
precision highp float;
|
|
|
|
vec3 getOrthogonalVector(vec3 v) {
|
|
// Return up-vector for only-z vector.
|
|
// Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).
|
|
// From the above if-statement we have ||a|| > 0 U ||b|| > 0.
|
|
// Assign z = 0, x = -b, y = a:
|
|
// a*-b + b*a + c*0 = -ba + ba + 0 = 0
|
|
if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {
|
|
return normalize(vec3(-v.y, v.x, 0.0));
|
|
} else {
|
|
return normalize(vec3(0.0, v.z, -v.y));
|
|
}
|
|
}
|
|
|
|
// Calculate the cone vertex and normal at the given index.
|
|
//
|
|
// The returned vertex is for a cone with its top at origin and height of 1.0,
|
|
// pointing in the direction of the vector attribute.
|
|
//
|
|
// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.
|
|
// These vertices are used to make up the triangles of the cone by the following:
|
|
// segment + 0 top vertex
|
|
// segment + 1 perimeter vertex a+1
|
|
// segment + 2 perimeter vertex a
|
|
// segment + 3 center base vertex
|
|
// segment + 4 perimeter vertex a
|
|
// segment + 5 perimeter vertex a+1
|
|
// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.
|
|
// To go from index to segment, floor(index / 6)
|
|
// To go from segment to angle, 2*pi * (segment/segmentCount)
|
|
// To go from index to segment index, index - (segment*6)
|
|
//
|
|
vec3 getConePosition(vec3 d, float rawIndex, float coneOffset, out vec3 normal) {
|
|
|
|
const float segmentCount = 8.0;
|
|
|
|
float index = rawIndex - floor(rawIndex /
|
|
(segmentCount * 6.0)) *
|
|
(segmentCount * 6.0);
|
|
|
|
float segment = floor(0.001 + index/6.0);
|
|
float segmentIndex = index - (segment*6.0);
|
|
|
|
normal = -normalize(d);
|
|
|
|
if (segmentIndex > 2.99 && segmentIndex < 3.01) {
|
|
return mix(vec3(0.0), -d, coneOffset);
|
|
}
|
|
|
|
float nextAngle = (
|
|
(segmentIndex > 0.99 && segmentIndex < 1.01) ||
|
|
(segmentIndex > 4.99 && segmentIndex < 5.01)
|
|
) ? 1.0 : 0.0;
|
|
float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);
|
|
|
|
vec3 v1 = mix(d, vec3(0.0), coneOffset);
|
|
vec3 v2 = v1 - d;
|
|
|
|
vec3 u = getOrthogonalVector(d);
|
|
vec3 v = normalize(cross(u, d));
|
|
|
|
vec3 x = u * cos(angle) * length(d)*0.25;
|
|
vec3 y = v * sin(angle) * length(d)*0.25;
|
|
vec3 v3 = v2 + x + y;
|
|
if (segmentIndex < 3.0) {
|
|
vec3 tx = u * sin(angle);
|
|
vec3 ty = v * -cos(angle);
|
|
vec3 tangent = tx + ty;
|
|
normal = normalize(cross(v3 - v1, tangent));
|
|
}
|
|
|
|
if (segmentIndex == 0.0) {
|
|
return mix(d, vec3(0.0), coneOffset);
|
|
}
|
|
return v3;
|
|
}
|
|
|
|
#pragma glslify: export(getConePosition)
|
|
|