Ejemplo n.º 1
0
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()
				localInvMatrix_notrans = localInvMatrix.rotationPart()
				p = p * localInvMatrix
				d = d * localInvMatrix # normalize_v3
				
				# remove the translation from d
				d.x -= localInvMatrix[3][0]
				d.y -= localInvMatrix[3][1]
				d.z -= localInvMatrix[3][2]
				
			
			d.normalize()			
			'''
			# Debugging
			me = Blender.Mesh.New()
			me.verts.extend([p[0:3]])
			me.verts.extend([(p-d)[0:3]])
			me.edges.extend([0,1])
			ob = Blender.Scene.GetCurrent().objects.new(me)
			'''
			return True, p, d # Origin, Direction	
	
	# Mouse is not in any view, return None.
	return False, None, None
Ejemplo n.º 2
0
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()
                localInvMatrix_notrans = localInvMatrix.rotationPart()
                p = p * localInvMatrix
                d = d * localInvMatrix  # normalize_v3

                # remove the translation from d
                d.x -= localInvMatrix[3][0]
                d.y -= localInvMatrix[3][1]
                d.z -= localInvMatrix[3][2]

            d.normalize()
            '''
			# Debugging
			me = Blender.Mesh.New()
			me.verts.extend([p[0:3]])
			me.verts.extend([(p-d)[0:3]])
			me.edges.extend([0,1])
			ob = Blender.Scene.GetCurrent().objects.new(me)
			'''
            return True, p, d  # Origin, Direction

    # Mouse is not in any view, return None.
    return False, None, None