-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathClippingUtility.java
More file actions
77 lines (66 loc) · 2.65 KB
/
Copy pathClippingUtility.java
File metadata and controls
77 lines (66 loc) · 2.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package util;
import world.Triangle4D;
import java.util.*;
import java.util.List;
public class ClippingUtility {
private enum VertexClipCase {
INSIDE, OUTSIDE, BEHIND
}
private static VertexClipCase getVertexClipCase(Vec4 v) {
if (Math.abs(v.z) > 1) return VertexClipCase.BEHIND;
return (v.y * v.y > v.w * v.w) ?
VertexClipCase.OUTSIDE : VertexClipCase.INSIDE;
}
private static Vec4 interpolateToViewport(Vec4 src, Vec4 dst) {
double s_pos = (-src.y + src.w) / ((dst.y - src.y) - (dst.w - src.w));
double s_neg = (-src.y - src.w) / ((dst.y - src.y) + (dst.w - src.w));
if (s_pos > 0 && s_pos <= 1) {
return Vec4.interpolateLine(src, dst, s_pos);
} else if (s_neg > 0 && s_neg <= 1) {
return Vec4.interpolateLine(src, dst, s_neg);
} else {
throw new RuntimeException("NO INTERCEPT");
}
}
public static List<Triangle4D> applyPrimitiveClipping (Triangle4D triangle) {
List<Vec4> insideVertices = new ArrayList<>();
List<Vec4> outsideVertices = new ArrayList<>();
for (Vec4 v : triangle.getVertices()) {
if (getVertexClipCase(v).equals(VertexClipCase.INSIDE)) {
insideVertices.add(v);
} else {
outsideVertices.add(v);
}
}
if (outsideVertices.isEmpty()) {
// implies insideVertices.size() = 3
return List.of(triangle);
}
if (insideVertices.isEmpty() || outsideVertices
.stream()
.anyMatch( v -> getVertexClipCase(v).equals(VertexClipCase.BEHIND))
) {
// case: all vertices outside
return Collections.emptyList();
} else if (insideVertices.size() == 1) {
// case: two vertices outside
Vec4 in = insideVertices.getFirst();
Vec4 vp1 = interpolateToViewport(in, outsideVertices.get(0));
Vec4 vp2 = interpolateToViewport(in, outsideVertices.get(1));
return List.of(new Triangle4D(in, vp1, vp2));
} else if (insideVertices.size() == 2) {
// case: one vertex outside
Vec4 in1 = insideVertices.get(0);
Vec4 in2 = insideVertices.get(1);
Vec4 out = outsideVertices.getFirst();
Vec4 vp1 = interpolateToViewport(in1, out);
Vec4 vp2 = interpolateToViewport(in2, out);
return List.of(
new Triangle4D(in1, vp1, vp2),
new Triangle4D(in1, in2, vp2)
);
} else {
throw new RuntimeException("ILLEGAL VERTEX STATE");
}
}
}