I just read this sentence:
From this topic and started to think about how hard would it be to implement such functionality.Another often wanted navigation style is fly mode (I would call it FPS navigation). Not done yet, too, but perfectly doable.
After an hour or so, I have the first working script:
How to use it:
-Create a new document
-Switch to perspective visualization
-Paste at Python console or run the code below as a macro
-Left click anywhere inside the 3D view window
-Use mouse to look around, WASD to move
Code: Select all
"""
FPS-like navigation
Javier Martinez Garcia 2015 GPL
"""
import FreeCAD
from pivy import coin
import Part
from math import sin, cos, pi
# create cube scenery and ground ###############################################
import random
cube_list = []
for i in range(200):
b = Part.makeBox( 5, 5, 5, FreeCAD.Vector( random.uniform( -100, 100),
random.uniform( -100, 100),
random.uniform( -100, 100) ) )
cube_list.append(b)
ground = Part.makePlane( 10000, 10000, FreeCAD.Vector( -5000, -5000, -150 ) )
g_o = FreeCAD.ActiveDocument.addObject( 'Part::Feature', 'Ground' )
g_o.Shape = ground
g_o.ViewObject.ShapeColor = (0.60,0.29,0.00)
g_o.ViewObject.Selectable = False
g_o.ViewObject.Transparency = 30
Part.show(Part.makeCompound( cube_list ) )
################################################################################
# FPS style camera -------------------------------------------------------------
class cameraUpdate:
def __init__(self, view):
self.view = view
# retrieve camera
self.cam = FreeCADGui.ActiveDocument.ActiveView.getCameraNode()
# keyboard variables
self.x = 0
self.y = 0
self.z = 0
self.look_at_vector = (1,0,0)
# mouse variables
self.Alpha = 0.0 # azimut
self.Beta = 0.0 # elevacion
self.da_0 = 0.0
self.db_0 = 0.0
def mousePosition(self, info):
pos = info["Position"]
da = int( pos[0] )
db = int( pos[1] )
# azimut update
self.Alpha = self.Alpha + ( self.da_0 - da )*0.008
self.da_0 = da
# elevation update
self.Beta = self.Beta + ( self.db_0 - db )*0.008
self.db_0 = db
cam_pos = self.cam.position.getValue()
self.look_at_vector = ( cam_pos[0] + cos( self.Alpha ),
cam_pos[1] + sin( self.Alpha ),
cam_pos[2] + sin( self.Beta ) )
self.cam.pointAt( coin.SbVec3f( self.look_at_vector[0],
self.look_at_vector[1],
self.look_at_vector[2] ),
coin.SbVec3f( 0, 0, 1 ) )
def keyboardPosition( self, info ):
key = info["Key"]
down = (info["State"] == "DOWN" )
# key logic
if key == 'w':# and (down):
self.x = self.x + cos( self.Alpha )
self.y = self.y + sin( self.Alpha )
self.z = self.z + sin( self.Beta )
if key == 's':# and (down):
self.x = self.x - cos( self.Alpha )
self.y = self.y - sin( self.Alpha )
self.z = self.z - sin( self.Beta )
if key == 'a':# and (down):
self.x = self.x + cos( self.Alpha + pi/2.0)
self.y = self.y + sin( self.Alpha + pi/2.0)
if key == 'd': #and (down):
self.x = self.x - cos( self.Alpha + pi/2.0)
self.y = self.y - sin( self.Alpha + pi/2.0)
if key == 'r': #and (down):
self.z = self.z + 1
if key == 'f': #and (down):
self.z = self.z - 1
# compose vector
self.cam.position.setValue( (self.x, self.y, self.z) )
v=Gui.activeDocument().activeView()
o = cameraUpdate(v)
c = v.addEventCallback("SoLocation2Event",o.mousePosition)
d = v.addEventCallback("SoKeyboardEvent", o.keyboardPosition)
https://www.youtube.com/watch?v=mKy9Mb0tB_U
Javier.