forked from UofT-Seismic-Design-Team/Autobuilder-3.0
-
Notifications
You must be signed in to change notification settings - Fork 0
/
View3DEngine.py
204 lines (144 loc) · 6.34 KB
/
View3DEngine.py
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
from PyQt5.QtCore import * # core Qt functionality
from PyQt5.QtWidgets import *
from PyQt5.QtGui import * # extends QtCore with GUI functionality
from PyQt5.QtOpenGL import * # provides QGLWidget, a special OpenGL QWidget
from OpenGL.GL import * # python wrapping of OpenGL
from OpenGL.GLU import * # OpenGL Utility Library, extends OpenGL functionality
from OpenGL.arrays import vbo
from Model import * # tower and other design components
from ProjectSettings import * # project settings data
from Definition import Algebra# constants
import numpy as np
import math as m
import sys
class View3DGLWidget(QGLWidget):
def __init__(self, *args, **kwargs):
super().__init__()
self.tower = Tower()
self.projectSettingsData = ProjectSettingsData()
# Member variables to control the states of the 3D view ----------------
self.rotMultiplier_x = -90 # show the XZ Plane in the beginning
self.rotMultiplier_y = 0
self.rotMultiplier_z = 0
self.scalingFactor_x = 1/4
self.scalingFactor_y = 1/4
self.scalingFactor_z = 1/4
self.translation_z = 0
#For panel nodes to be highlighted
self.nodes =[]
# Color
self.color = {
'Column': (0,0,0), # black
'Beam': (1,0,1), # green
'Panel': (0,0,1), # blue
}
# ----------------------------------------------------------------------
# Save the previous location of the cursor
self.last_x, self.last_y = None, None
def initializeGL(self):
self.qglClearColor(QColor('White')) # initialize the screen to black
glEnable(GL_DEPTH_TEST) # enable depth testing
def resizeGL(self, width, height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
aspect = width / (float(height) + Algebra.EPSILON)
# Sample: gluPerspective(field_of_view, aspect_ratio, z_near, z_far)
gluPerspective(45.0, aspect, 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
def paintGL(self):
# pre-rendering housekeeping
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix() # push the current matrix to the current stack
# Note: tranlate the object before rotating it
glTranslate(0, 0, -30) # third, translate cube to specified depth
glRotate(self.rotMultiplier_x, 1, 0, 0)
glRotate(self.rotMultiplier_y, 0, 1, 0)
glRotate(self.rotMultiplier_z, 0, 0, 1)
glScale(self.scalingFactor_x, self.scalingFactor_y, self.scalingFactor_z)
self.renderTowerSkeleton()
glPopMatrix() # restore the previous modelview matrix
def setTower(self, tower):
# Tower model
self.tower = tower
def setProjectSettingsData(self, projectSettingsData):
self.projectSettingsData = projectSettingsData
def renderTowerSkeleton(self):
glLineWidth(2)
glBegin(GL_LINES)
centerX = self.projectSettingsData.renderX/2
centerY = self.projectSettingsData.renderY/2
centerZ = self.projectSettingsData.renderZ/2
# Render the floor plan
for elev in self.tower.floors:
floor = self.tower.floors[elev]
# will draw lines between the two points
for floorPlan in floor.floorPlans:
for member in floorPlan.members:
start_node = member.start_node
end_node = member.end_node
glColor3fv(self.color['Beam'])
vertex1 = (start_node.x-centerX, start_node.y-centerY, elev-centerZ+self.translation_z)
glVertex3fv(vertex1)
vertex2 = (end_node.x-centerX, end_node.y-centerY, elev-centerZ+self.translation_z)
glVertex3fv(vertex2)
# Render the columns
for column_id in self.tower.columns:
column = self.tower.columns[column_id]
start_node = column.start_node
end_node = column.end_node
glColor3fv(self.color['Column'])
vertex1 = (start_node.x-centerX, start_node.y-centerY, start_node.z-centerZ+self.translation_z)
glVertex3fv(vertex1)
vertex2 = (end_node.x-centerX, end_node.y-centerY, end_node.z-centerZ+self.translation_z)
glVertex3fv(vertex2)
glEnd()
#Render the Panel if any
glBegin(GL_QUADS) # GL_QUADS: take 4 vertices as input
for node in self.nodes:
start_node = node[0]
end_node = node[1]
glColor3fv(self.color['Panel'])
vertex1 = (start_node.x-centerX, start_node.y-centerY, start_node.z-centerZ+self.translation_z)
glVertex3fv(vertex1)
vertex2 = (end_node.x-centerX, end_node.y-centerY, end_node.z-centerZ+self.translation_z)
glVertex3fv(vertex2)
glEnd()
def rotate(self, delta_x, delta_y):
sumOfChange = abs(delta_x) + abs(delta_y) + Algebra.EPSILON
self.rotMultiplier_z += delta_x / sumOfChange * 5
self.rotMultiplier_x += delta_y / sumOfChange * 5
def moveUp(self):
self.translation_z -= self.projectSettingsData.renderZ/20
def moveDown(self):
self.translation_z += self.projectSettingsData.renderZ/20
def mouseMoveEvent(self, e):
if self.last_x is None:
self.last_x = e.x()
self.last_y = e.y()
return # Ignore the first time.
change_x = e.x() - self.last_x
change_y = e.y() - self.last_y
self.rotate(change_x, change_y)
# Update the origin for next time.
self.last_x = e.x()
self.last_y = e.y()
self.update()
def mouseReleaseEvent(self, e):
self.last_x = None
self.last_y = None
def wheelEvent(self, e):
scrollDirection = e.angleDelta().y()/120
# if you scroll up, zoom in
if scrollDirection > 0:
factor = 1.1
else:
# otherwise, zoom out
factor = 1/1.1
self.scalingFactor_x *= factor
self.scalingFactor_y *= factor
self.scalingFactor_z *= factor
def mouseDoubleClickEvent(self, e):
self.scalingFactor_x = 1/4
self.scalingFactor_y = 1/4
self.scalingFactor_z = 1/4