chiark / gitweb /
Fix crash bug.
[cura.git] / Cura / gui / sceneView.py
1 from __future__ import absolute_import
2 from __future__ import division
3
4 import wx
5
6 import OpenGL
7 OpenGL.ERROR_CHECKING = False
8 from OpenGL.GLU import *
9 from OpenGL.GL import *
10
11 from Cura.util import profile
12 from Cura.util import meshLoader
13 from Cura.gui.util import opengl
14 from Cura.gui.util import openglGui
15
16 class SceneView(openglGui.glGuiPanel):
17         def __init__(self, parent):
18                 super(SceneView, self).__init__(parent)
19
20                 self._yaw = 30
21                 self._pitch = 60
22                 self._zoom = 100
23                 self._objectList = []
24                 self._objectShader = None
25                 self._focusObj = None
26                 self._selectedObj = None
27                 self._objColors = [None,None,None,None]
28                 self._mouseX = -1
29                 self._mouseY = -1
30                 self.updateProfileToControls()
31
32         def loadScene(self, fileList):
33                 for filename in fileList:
34                         for obj in meshLoader.loadMeshes(filename):
35                                 self._objectList.append(obj)
36
37         def _deleteObject(self, obj):
38                 if obj == self._selectedObj:
39                         self._selectedObj = None
40                 if obj == self._focusObj:
41                         self._focusObj = None
42                 self._objectList.remove(obj)
43                 for m in obj._meshList:
44                         if m.vbo is not None:
45                                 self.glReleaseList.append(m.vbo)
46
47         def updateProfileToControls(self):
48                 self._objColors[0] = profile.getPreferenceColour('model_colour')
49                 self._objColors[1] = profile.getPreferenceColour('model_colour2')
50                 self._objColors[2] = profile.getPreferenceColour('model_colour3')
51                 self._objColors[3] = profile.getPreferenceColour('model_colour4')
52
53         def OnKeyChar(self, keyCode):
54                 if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
55                         if self._selectedObj is not None:
56                                 self._deleteObject(self._selectedObj)
57                                 self.Refresh()
58
59         def OnMouseDown(self,e):
60                 if self._focusObj is not None:
61                         self._selectedObj = self._focusObj
62
63         def OnMouseMotion(self,e):
64                 if e.Dragging() and e.LeftIsDown():
65                         self._yaw += e.GetX() - self._mouseX
66                         self._pitch -= e.GetY() - self._mouseY
67                         if self._pitch > 170:
68                                 self._pitch = 170
69                         if self._pitch < 10:
70                                 self._pitch = 10
71                 if e.Dragging() and e.RightIsDown():
72                         self._zoom += e.GetY() - self._mouseY
73                         if self._zoom < 1:
74                                 self._zoom = 1
75                         if self._zoom > 500:
76                                 self._zoom = 500
77                 self._mouseX = e.GetX()
78                 self._mouseY = e.GetY()
79
80         def _init3DView(self):
81                 # set viewing projection
82                 size = self.GetSize()
83                 glViewport(0, 0, size.GetWidth(), size.GetHeight())
84                 glLoadIdentity()
85
86                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
87
88                 glDisable(GL_RESCALE_NORMAL)
89                 glDisable(GL_LIGHTING)
90                 glDisable(GL_LIGHT0)
91                 glEnable(GL_DEPTH_TEST)
92                 glDisable(GL_CULL_FACE)
93                 glDisable(GL_BLEND)
94
95                 glClearColor(0.8, 0.8, 0.8, 1.0)
96                 glClearStencil(0)
97                 glClearDepth(1.0)
98
99                 glMatrixMode(GL_PROJECTION)
100                 glLoadIdentity()
101                 aspect = float(size.GetWidth()) / float(size.GetHeight())
102                 gluPerspective(45.0, aspect, 1.0, 1000.0)
103
104                 glMatrixMode(GL_MODELVIEW)
105                 glLoadIdentity()
106                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
107
108         def OnPaint(self,e):
109                 if self._objectShader is None:
110                         self._objectShader = opengl.GLShader("""
111 uniform float cameraDistance;
112 varying float light_amount;
113
114 void main(void)
115 {
116     gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
117     gl_FrontColor = gl_Color;
118
119         light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
120         light_amount *= 1 - (length(gl_Position.xyz - vec3(0,0,cameraDistance)) / 1.5 / cameraDistance);
121         light_amount += 0.2;
122 }
123                         ""","""
124 uniform float cameraDistance;
125 varying float light_amount;
126
127 void main(void)
128 {
129         gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
130 }
131                         """)
132                 self._init3DView()
133                 glTranslate(0,0,-self._zoom)
134                 glRotate(-self._pitch, 1,0,0)
135                 glRotate(self._yaw, 0,0,1)
136                 glTranslate(0,0,-15)
137                 glClearColor(1,1,1,1)
138                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
139
140                 for n in xrange(0, len(self._objectList)):
141                         obj = self._objectList[n]
142                         glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
143                         self._renderObject(obj)
144
145                 if self._mouseX > -1:
146                         n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
147                         if n < len(self._objectList):
148                                 self._focusObj = self._objectList[n]
149                         else:
150                                 self._focusObj = None
151
152                 self._init3DView()
153                 glTranslate(0,0,-self._zoom)
154                 glRotate(-self._pitch, 1,0,0)
155                 glRotate(self._yaw, 0,0,1)
156                 glTranslate(0,0,-15)
157
158                 self._objectShader.bind()
159                 self._objectShader.setUniform('cameraDistance', self._zoom)
160                 for obj in self._objectList:
161                         col = self._objColors[0]
162                         if self._selectedObj == obj:
163                                 col = map(lambda n: n * 1.3, col)
164                         elif self._focusObj == obj:
165                                 col = map(lambda n: n * 1.2, col)
166                         elif self._focusObj is not None or  self._selectedObj is not None:
167                                 col = map(lambda n: n * 0.8, col)
168                         glColor4f(col[0], col[1], col[2], col[3])
169                         self._renderObject(obj)
170                 self._objectShader.unbind()
171
172         def _renderObject(self, obj):
173                 glPushMatrix()
174                 offset = (obj.getMinimum() + obj.getMaximum()) / 2
175                 glTranslate(-offset[0], -offset[1], -obj.getMinimum()[2])
176                 for m in obj._meshList:
177                         if m.vbo is None:
178                                 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
179                         m.vbo.render()
180                 glPopMatrix()