-
Notifications
You must be signed in to change notification settings - Fork 0
/
displaywidget.cpp
executable file
·213 lines (180 loc) · 6.2 KB
/
displaywidget.cpp
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include <QDebug>
#include "displaywidget.h"
#include "utils/glutils.h"
#include "implicitsphere.h"
DisplayWidget::DisplayWidget(QWidget *parent) :
QGLWidget(parent), m_selected(false), m_animate(false)
{
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(updateScene()));
}
DisplayWidget::~DisplayWidget() {
for (uint i = 0; i < m_polygonizer.numSurfaces(); i++) {
delete m_polygonizer.getSurface(i);
}
}
void DisplayWidget::initializeGL() {
//set background color to white
glClearColor(1.0, 1.0, 1.0, 1.0);
//nice looking anti-aliased lines
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLineWidth(1.25);
}
void DisplayWidget::resizeGL(int width, int height) {
//change viewport to new dimensions
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
//use an orthographic projection in the same dimensions as the draw surface
glOrtho(0, width, height, 0, -1, 0);
glMatrixMode(GL_MODELVIEW);
//change dimensions of the polygonizer to new screen dimensions
m_polygonizer.setBounds(0, 0, width, height);
}
void DisplayWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//polygonize the scene
m_polygonizer.polygonize();
//get the vertex and color buffers to draw
uint numVertices;
const float *vertices = m_polygonizer.getVertices(numVertices);
const float *colors = m_polygonizer.getColors(numVertices);
if (vertices == 0 || colors == 0) return;
//draw triangles
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);
glDrawArrays(GL_TRIANGLES, 0, numVertices);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
//draw selected surface with a dotted line
if (m_selected) {
Vector3f color = m_spheres[m_selectedIndex]->getColor();
Vector2f pos = m_spheres[m_selectedIndex]->getPosition();
float rad = m_spheres[m_selectedIndex]->getRadius();
glColor3f(color[0], color[1], color[2]);
glDrawDottedCircle(pos[0], pos[1], rad*3/2);
}
}
void DisplayWidget::mousePressEvent(QMouseEvent *event) {
//get position of mouse press
float x = (float)event->x();
float y = (float)event->y();
Vector2f v(x,y);
//used to determine if current object should be deselected
bool pressed = false;
bool lastSelected = m_selected;
//check if an existing sphere has been clicked
for (uint i = 0; i < m_spheres.size(); i++) {
Vector2f c = m_spheres[i]->getPosition();
float r = m_spheres[i]->getRadius();
if ((v-c).magnitude() <= r) {
m_selected = true;
pressed = true;
m_selectedIndex = i;
break;
}
}
if (m_selected && !pressed) {
//deselect current sphere
m_selected = false;
} else if (m_selected && event->button() & Qt::RightButton) {
//delete selected sphere
if (!lastSelected) {
m_spheres.erase(m_spheres.begin() + m_selectedIndex);
m_polygonizer.removeSurface(m_selectedIndex);
}
m_selected = false;
} else if (!m_selected && event->button() & Qt::LeftButton) {
//create and add random sphere to the scene
ImplicitSphere *sphere = createSphere(v);
m_spheres.push_back(sphere);
m_polygonizer.addSurface(sphere);
}
emit sphereSelected(m_selected && !m_animate ? m_spheres[m_selectedIndex] : 0);
repaint();
}
void DisplayWidget::mouseMoveEvent(QMouseEvent *event) {
//move currently selected sphere
if (m_selected && !m_animate) {
Vector2f pos(event->x(), event->y());
m_spheres[m_selectedIndex]->setPosition(pos);
m_polygonizer.invalidateCache();
repaint();
}
}
ImplicitSphere *DisplayWidget::createSphere(Vector2f pos) {
//randomly generate sphere attributes
float radius = RADIUS_MIN + (rand() / (float)RAND_MAX)*(RADIUS_MAX - RADIUS_MIN);
float weight = 1;
Vector3f color = randColor3f(radius*m_spheres.size());
float r1 = rand() / (float)RAND_MAX;
float r2 = rand() / (float)RAND_MAX;
float dV = VELOCITY_MAX - VELOCITY_MIN;
Vector2f velocity = Vector2f(VELOCITY_MIN + r1*dV, VELOCITY_MIN + r2*dV);
ImplicitSphere *sphere = new ImplicitSphere(pos, radius, color, velocity, weight);
return sphere;
}
void DisplayWidget::updateScene() {
//determine time since last update
float timestep = m_time.elapsed() / 1000.0;
m_time.restart();
//update all spheres in scene
for (uint i = 0; i < m_spheres.size(); i++) {
m_spheres[i]->update(Vector2f(0,0), Vector2f(width(), height()), timestep);
}
m_polygonizer.invalidateCache();
repaint();
}
void DisplayWidget::animate(bool on) {
m_animate = on;
if (m_animate) {
//start animation
m_timer->start();
m_time.restart();
if (m_selected)
emit sphereSelected(0);
} else {
//stop animation
m_timer->stop();
if (m_selected)
emit sphereSelected(m_spheres[m_selectedIndex]);
}
}
void DisplayWidget::changeRadius(float radius) {
if (m_selected) {
ImplicitSphere *s = m_spheres[m_selectedIndex];
s->setRadius(radius);
m_polygonizer.invalidateCache();
repaint();
}
}
void DisplayWidget::changeWeight(float weight) {
if (m_selected) {
ImplicitSphere *s = m_spheres[m_selectedIndex];
s->setWeight(weight);
m_polygonizer.invalidateCache();
repaint();
}
}
void DisplayWidget::changeVelocity(Vector2f velocity) {
if (m_selected) {
ImplicitSphere *s = m_spheres[m_selectedIndex];
s->setVelocity(velocity);
m_polygonizer.invalidateCache();
repaint();
}
}
void DisplayWidget::changeColor(Vector3f color) {
if (m_selected) {
ImplicitSphere *s = m_spheres[m_selectedIndex];
s->setColor(color);
m_polygonizer.invalidateCache();
repaint();
}
}