forked from bartvdbraak/blender
531cd7c0fc
updated bvh import which was modified to account for that. as well as other minor changes.
196 lines
6.5 KiB
Python
Executable File
196 lines
6.5 KiB
Python
Executable File
import Blender
|
|
from Blender import Mathutils, Window, Scene, Draw, Mesh
|
|
from Blender.Mathutils import CrossVecs, Matrix, Vector, Intersect, LineIntersect
|
|
|
|
# DESCRIPTION:
|
|
# screen_x, screen_y the origin point of the pick ray
|
|
# it is either the mouse location
|
|
# localMatrix is used if you want to have the returned values in an objects localspace.
|
|
# this is usefull when dealing with an objects data such as verts.
|
|
# or if useMid is true, the midpoint of the current 3dview
|
|
# returns
|
|
# Origin - the origin point of the pick ray
|
|
# Direction - the direction vector of the pick ray
|
|
# in global coordinates
|
|
epsilon = 1e-3 # just a small value to account for floating point errors
|
|
|
|
def mouseViewRay(screen_x, screen_y, localMatrix=None, useMid = False):
|
|
|
|
# Constant function variables
|
|
p = mouseViewRay.p
|
|
d = mouseViewRay.d
|
|
|
|
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)
|
|
win_min_x, win_min_y, win_max_x, win_max_y = win3d['vertices']
|
|
# calculate a few geometric extents for this window
|
|
|
|
win_mid_x = (win_max_x + win_min_x + 1.0) * 0.5
|
|
win_mid_y = (win_max_y + win_min_y + 1.0) * 0.5
|
|
win_size_x = (win_max_x - win_min_x + 1.0) * 0.5
|
|
win_size_y = (win_max_y - win_min_y + 1.0) * 0.5
|
|
|
|
#useMid is for projecting the coordinates when we subdivide the screen into bins
|
|
if useMid: # == True
|
|
screen_x = win_mid_x
|
|
screen_y = win_mid_y
|
|
|
|
# if the given screencoords (screen_x, screen_y) are within the 3dwin we fount the right one...
|
|
if (win_max_x > screen_x > win_min_x) and ( win_max_y > screen_y > win_min_y):
|
|
# first we handle all pending events for this window (otherwise the matrices might come out wrong)
|
|
Window.QHandle(win3d['id'])
|
|
|
|
# now we get a few matrices for our window...
|
|
# sorry - i cannot explain here what they all do
|
|
# - if you're not familiar with all those matrices take a look at an introduction to OpenGL...
|
|
pm = Window.GetPerspMatrix() # the prespective matrix
|
|
pmi = Matrix(pm); pmi.invert() # the inverted perspective matrix
|
|
|
|
if (1.0 - epsilon < pmi[3][3] < 1.0 + epsilon):
|
|
# pmi[3][3] is 1.0 if the 3dwin is in ortho-projection mode (toggled with numpad 5)
|
|
hms = mouseViewRay.hms
|
|
ortho_d = mouseViewRay.ortho_d
|
|
|
|
# ortho mode: is a bit strange - actually there's no definite location of the camera ...
|
|
# but the camera could be displaced anywhere along the viewing direction.
|
|
|
|
ortho_d.x, ortho_d.y, ortho_d.z = Window.GetViewVector()
|
|
ortho_d.w = 0
|
|
|
|
# all rays are parallel in ortho mode - so the direction vector is simply the viewing direction
|
|
#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
|
|
hms[:] = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0
|
|
|
|
# these are the homogenious screencoords of the point (screen_x, screen_y) ranging from -1 to +1
|
|
p=(hms*pmi) + (1000*ortho_d)
|
|
p.resize3D()
|
|
d[:] = ortho_d[:3]
|
|
|
|
|
|
# Finally we shift the position infinitely far away in
|
|
# the viewing direction to make sure the camera if outside the scene
|
|
# (this is actually a hack because this function
|
|
# is used in sculpt_mesh to initialize backface culling...)
|
|
else:
|
|
# PERSPECTIVE MODE: here everything is well defined - all rays converge at the camera's location
|
|
vmi = Matrix(Window.GetViewMatrix()); vmi.invert() # the inverse viewing matrix
|
|
fp = mouseViewRay.fp
|
|
|
|
dx = pm[3][3] * (((screen_x-win_min_x)/win_size_x)-1.0) - pm[3][0]
|
|
dy = pm[3][3] * (((screen_y-win_min_y)/win_size_y)-1.0) - pm[3][1]
|
|
|
|
fp[:] = \
|
|
pmi[0][0]*dx+pmi[1][0]*dy,\
|
|
pmi[0][1]*dx+pmi[1][1]*dy,\
|
|
pmi[0][2]*dx+pmi[1][2]*dy
|
|
|
|
# fp is a global 3dpoint obtained from "unprojecting" the screenspace-point (screen_x, screen_y)
|
|
#- figuring out how to calculate this took me quite some time.
|
|
# The calculation of dxy and fp are simplified versions of my original code
|
|
#- so it's almost impossible to explain what's going on geometrically... sorry
|
|
|
|
p[:] = vmi[3][:3]
|
|
|
|
# the camera's location in global 3dcoords can be read directly from the inverted viewmatrix
|
|
#d.x, d.y, d.z =normalize_v3(sub_v3v3(p, fp))
|
|
d[:] = p.x-fp.x, p.y-fp.y, p.z-fp.z
|
|
|
|
#print 'd', d, 'p', p, 'fp', fp
|
|
|
|
|
|
# the direction vector is simply the difference vector from the virtual camera's position
|
|
#to the unprojected (screenspace) point fp
|
|
|
|
# Do we want to return a direction in object's localspace?
|
|
|
|
if localMatrix:
|
|
localInvMatrix = Matrix(localMatrix)
|
|
localInvMatrix.invert()
|
|
p = p*localInvMatrix
|
|
d = d*localInvMatrix # normalize_v3
|
|
p.x += localInvMatrix[3][0]
|
|
p.y += localInvMatrix[3][1]
|
|
p.z += localInvMatrix[3][2]
|
|
|
|
#else: # Worldspace, do nothing
|
|
|
|
d.normalize()
|
|
return True, p, d # Origin, Direction
|
|
|
|
# Mouse is not in any view, return None.
|
|
return False, None, None
|
|
|
|
# Constant function variables
|
|
mouseViewRay.d = Vector(0,0,0) # Perspective, 3d
|
|
mouseViewRay.p = Vector(0,0,0)
|
|
mouseViewRay.fp = Vector(0,0,0)
|
|
|
|
mouseViewRay.hms = Vector(0,0,0,0) # ortho only 4d
|
|
mouseViewRay.ortho_d = Vector(0,0,0,0) # ortho only 4d
|
|
|
|
|
|
LMB= Window.MButs['L']
|
|
def mouseup():
|
|
# Loop until click
|
|
mouse_buttons = Window.GetMouseButtons()
|
|
while not mouse_buttons & LMB:
|
|
Blender.sys.sleep(10)
|
|
mouse_buttons = Window.GetMouseButtons()
|
|
while mouse_buttons & LMB:
|
|
Blender.sys.sleep(10)
|
|
mouse_buttons = Window.GetMouseButtons()
|
|
|
|
|
|
if __name__=='__main__':
|
|
mouseup()
|
|
x,y= Window.GetMouseCoords()
|
|
isect, point, dir= mouseViewRay(x,y)
|
|
if isect:
|
|
scn= Blender.Scene.GetCurrent()
|
|
me = Blender.Mesh.New()
|
|
ob= Blender.Object.New('Mesh')
|
|
ob.link(me)
|
|
scn.link(ob)
|
|
ob.sel= 1
|
|
me.verts.extend([point, dir])
|
|
me.verts[0].sel= 1
|
|
|
|
print isect, point, dir
|
|
|
|
|
|
|
|
def spaceRect():
|
|
'''
|
|
Returns the space rect
|
|
xmin,ymin,width,height
|
|
'''
|
|
|
|
__UI_RECT__ = Blender.BGL.Buffer(Blender.BGL.GL_FLOAT, 4)
|
|
Blender.BGL.glGetFloatv(Blender.BGL.GL_SCISSOR_BOX, __UI_RECT__)
|
|
__UI_RECT__ = __UI_RECT__.list
|
|
__UI_RECT__ = int(__UI_RECT__[0]), int(__UI_RECT__[1]), int(__UI_RECT__[2])-1, int(__UI_RECT__[3])
|
|
|
|
return __UI_RECT__
|
|
|
|
def mouseRelativeLoc2d(__UI_RECT__= None):
|
|
if not __UI_RECT__:
|
|
__UI_RECT__ = spaceRect()
|
|
|
|
mco = Window.GetMouseCoords()
|
|
if mco[0] > __UI_RECT__[0] and\
|
|
mco[1] > __UI_RECT__[1] and\
|
|
mco[0] < __UI_RECT__[0] + __UI_RECT__[2] and\
|
|
mco[1] < __UI_RECT__[1] + __UI_RECT__[3]:
|
|
|
|
return (mco[0] - __UI_RECT__[0], mco[1] - __UI_RECT__[1])
|
|
|
|
else:
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|