~diresu/blender/blender-command-port

« back to all changes in this revision

Viewing changes to release/scripts/bpymodules/BPyWindow.py

  • Committer: theeth
  • Date: 2008-10-14 16:52:04 UTC
  • Revision ID: vcs-imports@canonical.com-20081014165204-r32w2gm6s0osvdhn
copy back trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import Blender
 
2
from Blender import Mathutils, Window, Scene, Draw, Mesh
 
3
from Blender.Mathutils import CrossVecs, Matrix, Vector, Intersect
 
4
 
 
5
# DESCRIPTION:
 
6
# screen_x, screen_y the origin point of the pick ray
 
7
# it is either the mouse location
 
8
# localMatrix is used if you want to have the returned values in an objects localspace.
 
9
#    this is usefull when dealing with an objects data such as verts.
 
10
# or if useMid is true, the midpoint of the current 3dview
 
11
# returns
 
12
# Origin - the origin point of the pick ray
 
13
# Direction - the direction vector of the pick ray
 
14
# in global coordinates
 
15
epsilon = 1e-3 # just a small value to account for floating point errors
 
16
 
 
17
def mouseViewRay(screen_x, screen_y, localMatrix=None, useMid = False):
 
18
        
 
19
        # Constant function variables
 
20
        p = mouseViewRay.p
 
21
        d = mouseViewRay.d
 
22
        
 
23
        for win3d in Window.GetScreenInfo(Window.Types.VIEW3D): # we search all 3dwins for the one containing the point (screen_x, screen_y) (could be the mousecoords for example) 
 
24
                win_min_x, win_min_y, win_max_x, win_max_y = win3d['vertices']
 
25
                # calculate a few geometric extents for this window
 
26
 
 
27
                win_mid_x  = (win_max_x + win_min_x + 1.0) * 0.5
 
28
                win_mid_y  = (win_max_y + win_min_y + 1.0) * 0.5
 
29
                win_size_x = (win_max_x - win_min_x + 1.0) * 0.5
 
30
                win_size_y = (win_max_y - win_min_y + 1.0) * 0.5
 
31
 
 
32
                #useMid is for projecting the coordinates when we subdivide the screen into bins
 
33
                if useMid: # == True
 
34
                        screen_x = win_mid_x
 
35
                        screen_y = win_mid_y
 
36
                
 
37
                # if the given screencoords (screen_x, screen_y) are within the 3dwin we fount the right one...
 
38
                if (win_max_x > screen_x > win_min_x) and (  win_max_y > screen_y > win_min_y):
 
39
                        # first we handle all pending events for this window (otherwise the matrices might come out wrong)
 
40
                        Window.QHandle(win3d['id'])
 
41
                        
 
42
                        # now we get a few matrices for our window...
 
43
                        # sorry - i cannot explain here what they all do
 
44
                        # - if you're not familiar with all those matrices take a look at an introduction to OpenGL...
 
45
                        pm      = Window.GetPerspMatrix()   # the prespective matrix
 
46
                        pmi  = Matrix(pm); pmi.invert() # the inverted perspective matrix
 
47
                        
 
48
                        if (1.0 - epsilon < pmi[3][3] < 1.0 + epsilon):
 
49
                                # pmi[3][3] is 1.0 if the 3dwin is in ortho-projection mode (toggled with numpad 5)
 
50
                                hms = mouseViewRay.hms
 
51
                                ortho_d = mouseViewRay.ortho_d
 
52
                                
 
53
                                # ortho mode: is a bit strange - actually there's no definite location of the camera ...
 
54
                                # but the camera could be displaced anywhere along the viewing direction.
 
55
                                
 
56
                                ortho_d.x, ortho_d.y, ortho_d.z = Window.GetViewVector()
 
57
                                ortho_d.w = 0
 
58
                                
 
59
                                # all rays are parallel in ortho mode - so the direction vector is simply the viewing direction
 
60
                                #hms.x, hms.y, hms.z, hms.w = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0
 
61
                                hms[:] = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0
 
62
                                
 
63
                                # these are the homogenious screencoords of the point (screen_x, screen_y) ranging from -1 to +1
 
64
                                p=(hms*pmi) + (1000*ortho_d)
 
65
                                p.resize3D()
 
66
                                d[:] = ortho_d[:3]
 
67
                                
 
68
 
 
69
                        # Finally we shift the position infinitely far away in
 
70
                        # the viewing direction to make sure the camera if outside the scene
 
71
                        # (this is actually a hack because this function
 
72
                        # is used in sculpt_mesh to initialize backface culling...)
 
73
                        else:
 
74
                                # PERSPECTIVE MODE: here everything is well defined - all rays converge at the camera's location
 
75
                                vmi  = Matrix(Window.GetViewMatrix()); vmi.invert() # the inverse viewing matrix
 
76
                                fp = mouseViewRay.fp
 
77
                                
 
78
                                dx = pm[3][3] * (((screen_x-win_min_x)/win_size_x)-1.0) - pm[3][0]
 
79
                                dy = pm[3][3] * (((screen_y-win_min_y)/win_size_y)-1.0) - pm[3][1]
 
80
                                
 
81
                                fp[:] = \
 
82
                                pmi[0][0]*dx+pmi[1][0]*dy,\
 
83
                                pmi[0][1]*dx+pmi[1][1]*dy,\
 
84
                                pmi[0][2]*dx+pmi[1][2]*dy
 
85
                                
 
86
                                # fp is a global 3dpoint obtained from "unprojecting" the screenspace-point (screen_x, screen_y)
 
87
                                #- figuring out how to calculate this took me quite some time.
 
88
                                # The calculation of dxy and fp are simplified versions of my original code
 
89
                                #- so it's almost impossible to explain what's going on geometrically... sorry
 
90
                                
 
91
                                p[:] = vmi[3][:3]
 
92
                                
 
93
                                # the camera's location in global 3dcoords can be read directly from the inverted viewmatrix
 
94
                                #d.x, d.y, d.z =normalize_v3(sub_v3v3(p, fp))
 
95
                                d[:] = p.x-fp.x, p.y-fp.y, p.z-fp.z
 
96
                                
 
97
                                #print 'd', d, 'p', p, 'fp', fp
 
98
                                
 
99
                        
 
100
                        # the direction vector is simply the difference vector from the virtual camera's position
 
101
                        #to the unprojected (screenspace) point fp
 
102
                        
 
103
                        # Do we want to return a direction in object's localspace?
 
104
                        
 
105
                        if localMatrix:
 
106
                                localInvMatrix = Matrix(localMatrix)
 
107
                                localInvMatrix.invert()
 
108
                                localInvMatrix_notrans = localInvMatrix.rotationPart()
 
109
                                p = p * localInvMatrix
 
110
                                d = d * localInvMatrix # normalize_v3
 
111
                                
 
112
                                # remove the translation from d
 
113
                                d.x -= localInvMatrix[3][0]
 
114
                                d.y -= localInvMatrix[3][1]
 
115
                                d.z -= localInvMatrix[3][2]
 
116
                                
 
117
                        
 
118
                        d.normalize()                   
 
119
                        '''
 
120
                        # Debugging
 
121
                        me = Blender.Mesh.New()
 
122
                        me.verts.extend([p[0:3]])
 
123
                        me.verts.extend([(p-d)[0:3]])
 
124
                        me.edges.extend([0,1])
 
125
                        ob = Blender.Scene.GetCurrent().objects.new(me)
 
126
                        '''
 
127
                        return True, p, d # Origin, Direction   
 
128
        
 
129
        # Mouse is not in any view, return None.
 
130
        return False, None, None
 
131
 
 
132
# Constant function variables
 
133
mouseViewRay.d = Vector(0,0,0) # Perspective, 3d
 
134
mouseViewRay.p = Vector(0,0,0)
 
135
mouseViewRay.fp = Vector(0,0,0)
 
136
 
 
137
mouseViewRay.hms = Vector(0,0,0,0) # ortho only 4d
 
138
mouseViewRay.ortho_d = Vector(0,0,0,0) # ortho only 4d
 
139
 
 
140
 
 
141
LMB= Window.MButs['L']
 
142
def mouseup():
 
143
        # Loop until click
 
144
        mouse_buttons = Window.GetMouseButtons()
 
145
        while not mouse_buttons & LMB:
 
146
                Blender.sys.sleep(10)
 
147
                mouse_buttons = Window.GetMouseButtons()
 
148
        while mouse_buttons & LMB:
 
149
                Blender.sys.sleep(10)
 
150
                mouse_buttons = Window.GetMouseButtons()
 
151
 
 
152
 
 
153
if __name__=='__main__':
 
154
        mouseup()
 
155
        x,y= Window.GetMouseCoords()
 
156
        isect, point, dir= mouseViewRay(x,y)
 
157
        if isect:
 
158
                scn= Blender.Scene.GetCurrent()
 
159
                me = Blender.Mesh.New()
 
160
                ob= Blender.Object.New('Mesh')
 
161
                ob.link(me)
 
162
                scn.link(ob)
 
163
                ob.sel= 1
 
164
                me.verts.extend([point, dir])
 
165
                me.verts[0].sel= 1
 
166
                
 
167
        print isect, point, dir
 
168
        
 
169
        
 
170
 
 
171
def spaceRect():
 
172
        '''
 
173
        Returns the space rect
 
174
        xmin,ymin,width,height
 
175
        '''
 
176
        
 
177
        __UI_RECT__ = Blender.BGL.Buffer(Blender.BGL.GL_FLOAT, 4)
 
178
        Blender.BGL.glGetFloatv(Blender.BGL.GL_SCISSOR_BOX, __UI_RECT__) 
 
179
        __UI_RECT__ = __UI_RECT__.list
 
180
        __UI_RECT__ = int(__UI_RECT__[0]), int(__UI_RECT__[1]), int(__UI_RECT__[2])-1, int(__UI_RECT__[3]) 
 
181
        
 
182
        return __UI_RECT__
 
183
 
 
184
def mouseRelativeLoc2d(__UI_RECT__= None):
 
185
        if not __UI_RECT__:
 
186
                __UI_RECT__ = spaceRect()
 
187
        
 
188
        mco = Window.GetMouseCoords()
 
189
        if      mco[0] > __UI_RECT__[0] and\
 
190
        mco[1] > __UI_RECT__[1] and\
 
191
        mco[0] < __UI_RECT__[0] + __UI_RECT__[2] and\
 
192
        mco[1] < __UI_RECT__[1] + __UI_RECT__[3]:
 
193
        
 
194
                return (mco[0] - __UI_RECT__[0], mco[1] - __UI_RECT__[1])
 
195
                
 
196
        else:
 
197
                return None
 
198
        
 
199
 
 
200
 
 
201
 
 
202
        
 
203
 
 
204
 
 
205
 
 
206
        
 
 
b'\\ No newline at end of file'