-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDemoViewer.java
More file actions
151 lines (124 loc) · 5.36 KB
/
DemoViewer.java
File metadata and controls
151 lines (124 loc) · 5.36 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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
public class DemoViewer {
private static final int WINDOW_WIDTH = 600;
private static final int WINDOW_HEIGHT = 600;
private static final double IMPORT_SCALE = 200.0;
private static final JFileChooser FILE_CHOOSER = createFileChooser();
public static void main(String[] args) {
JFrame frame = new JFrame("OBJ Viewer");
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
// Top panel for buttons
JPanel topPanel = new JPanel();
JButton openButton = new JButton("Open OBJ");
topPanel.add(openButton);
JButton inflateButton = new JButton("Inflate");
topPanel.add(inflateButton);
pane.add(topPanel, BorderLayout.NORTH);
// slider to control horizontal rotation
JSlider horizontalSlider = new JSlider(0, 360, 180);
pane.add(horizontalSlider, BorderLayout.SOUTH);
// slider to control vertical rotation
JSlider verticalSlider = new JSlider(JSlider.VERTICAL, -180, 180, 0);
pane.add(verticalSlider, BorderLayout.EAST);
RenderPanel renderPanel = new RenderPanel();
renderPanel.setModel(makeDefaultTetrahedron());
renderPanel.setRotation(horizontalSlider.getValue(), verticalSlider.getValue());
openButton.addActionListener(e -> openObjFile(frame, renderPanel));
inflateButton.addActionListener(e -> {
List<Triangle> inflated = inflate(renderPanel.getModel());
renderPanel.setModel(inflated);
renderPanel.repaint();
});
horizontalSlider.addChangeListener(e -> {
renderPanel.setRotation(horizontalSlider.getValue(), verticalSlider.getValue());
renderPanel.repaint();
});
verticalSlider.addChangeListener(e -> {
renderPanel.setRotation(horizontalSlider.getValue(), verticalSlider.getValue());
renderPanel.repaint();
});
pane.add(renderPanel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static List<Triangle> inflate(List<Triangle> tris) {
List<Triangle> result = new ArrayList<>();
for (Triangle t : tris) {
Vertex m1 =
new Vertex((t.v1.x + t.v2.x)/2, (t.v1.y + t.v2.y)/2, (t.v1.z + t.v2.z)/2);
Vertex m2 =
new Vertex((t.v2.x + t.v3.x)/2, (t.v2.y + t.v3.y)/2, (t.v2.z + t.v3.z)/2);
Vertex m3 =
new Vertex((t.v1.x + t.v3.x)/2, (t.v1.y + t.v3.y)/2, (t.v1.z + t.v3.z)/2);
result.add(new Triangle(t.v1, m1, m3, t.color));
result.add(new Triangle(t.v2, m1, m2, t.color));
result.add(new Triangle(t.v3, m2, m3, t.color));
result.add(new Triangle(m1, m2, m3, t.color));
}
for (Triangle t : result) {
for (Vertex v : new Vertex[] { t.v1, t.v2, t.v3 }) {
double l = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z) / Math.sqrt(30000);
v.x /= l;
v.y /= l;
v.z /= l;
}
}
return result;
}
private static List<Triangle> makeDefaultTetrahedron() {
List<Triangle> tris = new ArrayList<>();
tris.add(new Triangle(new Vertex(100, 100, 100),
new Vertex(-100, -100, 100),
new Vertex(-100, 100, -100),
Color.WHITE));
tris.add(new Triangle(new Vertex(100, 100, 100),
new Vertex(-100, -100, 100),
new Vertex(100, -100, -100),
Color.RED));
tris.add(new Triangle(new Vertex(-100, 100, -100),
new Vertex(100, -100, -100),
new Vertex(100, 100, 100),
Color.GREEN));
tris.add(new Triangle(new Vertex(-100, 100, -100),
new Vertex(100, -100, -100),
new Vertex(-100, -100, 100),
Color.BLUE));
return tris;
}
private static void openObjFile(JFrame frame, RenderPanel renderPanel) {
int result = FILE_CHOOSER.showOpenDialog(frame);
if (result != JFileChooser.APPROVE_OPTION) {
return;
}
File selectedFile = FILE_CHOOSER.getSelectedFile();
try {
List<Triangle> loaded = ObjLoader.loadObj(selectedFile.getPath(), Color.WHITE);
loaded = ObjLoader.centerAndScale(loaded, IMPORT_SCALE);
renderPanel.setModel(loaded);
renderPanel.repaint();
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(
frame,
"Failed to load OBJ file:\n" + ex.getMessage(),
"Load Error",
JOptionPane.ERROR_MESSAGE
);
}
}
private static JFileChooser createFileChooser() {
JFileChooser chooser = new JFileChooser(new File("models"));
chooser.setDialogTitle("Choose an OBJ file");
chooser.setFileFilter(new FileNameExtensionFilter("OBJ files", "obj"));
return chooser;
}
}