Пример #1
0
    def CreateBox(self, vector, colour):

        # Create the geometry and collision
        line = NodePath(Line((0, 0, 0), vector))
        box = NodePath(Box(0.1, 0.1, 0.1, vector * 0.05))
        collSphere = CollisionSphere(Point3(vector * -0.05), 0.1)

        # Create the axis, add the geometry and collision
        axis = Axis(self.name, vector, colour)
        axis.AddGeometry(line, colour=GREY, highlight=False, sizeStyle=SCALE)
        axis.AddGeometry(box, vector, colour)
        axis.AddCollisionSolid(collSphere, vector)
        axis.reparentTo(self)

        return axis
Пример #2
0
 def CreateArrow( self, vec, colour ):
     
     # Create the geometry and collision
     vec.normalize()
     line = pm.NodePath( Line( (0, 0, 0), vec ) )
     cone = pm.NodePath( Cone( 0.05, 0.25, axis=vec, origin=vec * 0.125 ) )
     collTube = pm.CollisionTube( (0,0,0), pm.Point3( vec ) * 0.95, 0.05 )
     
     # Create the axis, add the geometry and collision
     axis = Axis( self.name, vec, colour )
     axis.AddGeometry( line, sizeStyle=SCALE )
     axis.AddGeometry( cone, vec, colour )
     axis.AddCollisionSolid( collTube, sizeStyle=TRANSLATE_POINT_B )
     axis.reparentTo( self )
     
     return axis
Пример #3
0
    def CreateCenter(self, vector, colour):

        # Create the axis, add the geometry and collision
        axis = Axis(self.name, vector, colour, default=True)
        axis.AddGeometry(NodePath(Box(0.1, 0.1, 0.1)), sizeStyle=NONE)
        axis.AddCollisionSolid(CollisionSphere(0, 0.1), sizeStyle=NONE)
        axis.reparentTo(self)

        return axis
Пример #4
0
 def CreateSquare( self, vec, colour ):
     
     # Create the geometry and collision
     self.square = pm.NodePath( Square( 0.2, 0.2, pm.Vec3(0, 1, 0) ) )
     self.square.setBillboardPointEye()
     collSphere = pm.CollisionSphere( 0, 0.125 )
     
     # Create the axis, add the geometry and collision
     axis = Axis( self.name, CAMERA_VECTOR, colour, planar=True, default=True )
     axis.AddGeometry( self.square, sizeStyle=NONE )
     axis.AddCollisionSolid( collSphere, sizeStyle=NONE )
     axis.reparentTo( self )
     
     return axis
Пример #5
0
 def CreateRing( self, vector, colour, rot ):
     
     # Create an arc
     arc = Arc( numSegs=32, degrees=180, axis=Vec3(0, 0, 1) )
     arc.setH( 180 )
     
     # Create the axis from the arc
     axis = Axis( self.name, vector, colour )
     axis.AddGeometry( arc, sizeStyle=SCALE )
     axis.AddCollisionSolid( self.collSphere, sizeStyle=SCALE )
     axis.reparentTo( self )
     
     # Create the billboard effect and apply it to the arc. We need an
     # extra NodePath to help the billboard effect so it orients properly.
     hlpr = NodePath( 'helper' )
     hlpr.setHpr( rot )
     hlpr.reparentTo( self )
     arc.reparentTo( hlpr )
     bbe = BillboardEffect.make( Vec3(0, 0, 1), False, True, 0, 
                                 self.camera, (0, 0, 0) )
     arc.setEffect( bbe )
     
     return axis
Пример #6
0
class Rotation( Base ):
    
    def __init__( self, *args, **kwargs ):
        Base.__init__( self, *args, **kwargs )
        
        # Create the 'ball' border
        self.border = self.CreateCircle( GREY, 1 )
        
        # Create the collision sphere - except for the camera normal, all axes
        # will use this single collision object
        self.collSphere = CollisionSphere( 0, 1 )
        
        # Create x, y, z and camera normal axes
        self.axes.append( self.CreateRing( Vec3(1, 0, 0), RED, 
                                           Vec3(0, 0, 90) ) )
        self.axes.append( self.CreateRing( Vec3(0, 1, 0), GREEN, 
                                           Vec3(0, 90, 0) ) )
        self.axes.append( self.CreateRing( Vec3(0, 0, 1), BLUE, 
                                           Vec3(0, 0, 0) ) )
        
        # DEBUG
        self.foobar = self.CreateCamCircle( TEAL, 1.2 )
        self.axes.append( self.foobar )
    
    def CreateRing( self, vector, colour, rot ):
        
        # Create an arc
        arc = Arc( numSegs=32, degrees=180, axis=Vec3(0, 0, 1) )
        arc.setH( 180 )
        
        # Create the axis from the arc
        axis = Axis( self.name, vector, colour )
        axis.AddGeometry( arc, sizeStyle=SCALE )
        axis.AddCollisionSolid( self.collSphere, sizeStyle=SCALE )
        axis.reparentTo( self )
        
        # Create the billboard effect and apply it to the arc. We need an
        # extra NodePath to help the billboard effect so it orients properly.
        hlpr = NodePath( 'helper' )
        hlpr.setHpr( rot )
        hlpr.reparentTo( self )
        arc.reparentTo( hlpr )
        bbe = BillboardEffect.make( Vec3(0, 0, 1), False, True, 0, 
                                    self.camera, (0, 0, 0) )
        arc.setEffect( bbe )
        
        return axis
    
    def CreateCircle( self, colour, radius ):
        
        # Create a circle
        arc = Arc( radius, numSegs=64, axis=Vec3(0, 1, 0) )
        arc.setColorScale( colour )
        arc.setLightOff()
        arc.reparentTo( self )
        
        # Set the billboard effect
        arc.setBillboardPointEye()
        
        return arc
    
    def CreateCamCircle( self, colour, radius ):
        
        # Create the geometry and collision
        circle = self.CreateCircle( colour, radius )
        collPoly = CollisionPolygon( Point3(-1.2, 0, -1.2), Point3(-1.25, 0, 1.25), Point3(1.25, 0, 1.25), Point3(1.25, 0, -1.25) )
        
        # Create the axis, add the geometry and collision
        self.camAxis = Axis( self.name, CAMERA_VECTOR, colour, planar=True, default=True )
        self.camAxis.AddGeometry( circle,  sizeStyle=SCALE )
        self.camAxis.AddCollisionSolid( collPoly, sizeStyle=SCALE )
        self.camAxis.reparentTo( self )
        
        return self.camAxis
        
    def SetSize( self, factor ):
        Base.SetSize( self, factor )
        
        # Scale up any additional geo
        self.border.setScale( self.size )
    
    def GetAxis( self, collEntry ):
        axis = Base.GetAxis( self, collEntry )
        
        # Return None if the axis is None
        if axis is None:
            return None
        
        if axis.vector != CAMERA_VECTOR:
            
            # Return the axis from the specified normal within a tolerance of 
            # degrees
            normal = collEntry.getSurfaceNormal( self )
            normal.normalize()
            for axis in self.axes:
                if math.fabs( normal.angleDeg( axis.vector ) - 90 ) < ( 2.5 / self.size ):
                    return axis
        else:
            
            # Get the collision point on the poly, return the axis if the
            # mouse is within tolerance of the circle
            point = collEntry.getSurfacePoint( collEntry.getIntoNodePath() )
            length = Vec3( point / 1.25 ).length()
            if length > 0.9 and length < 1:
                return axis
        
    def Update( self, task ):
        Base.Update( self, task )
        
        # DEBUG - make the camera normal collision plane look at the camera.
        # Probably should be a better way to do this.
        self.camAxis.collNodePaths[0].lookAt( self.camera )
        
        return task.cont
        
    def Transform( self ):
        
        startVec = self.startVec
        
        axis = self.GetSelectedAxis()
        if axis is not None and axis.vector == CAMERA_VECTOR:
            endVec = self.getRelativeVector( self.rootNp, self.GetAxisPoint( axis ) - self.getPos() )
            
            cross = startVec.cross( endVec )
            direction = self.getRelativeVector( self.camera, Vec3(0, -1, 0) ).dot( cross )
            sign = math.copysign( 1, direction )
            
            # Get the rotation axis
            rotAxis = self.getRelativeVector( self.camera, Vec3(0, -1, 0) ) * sign
        else:
            if self.collEntry.getIntoNode() == self.initCollEntry.getIntoNode():
                endVec = self.collEntry.getSurfaceNormal( self )
            else:
                endVec = self.getRelativeVector( self.rootNp, self.GetAxisPoint( self.foobar ) - self.getPos() )
            
            # If an axis is selected then constrain the vectors by projecting
            # them onto a plane whose normal is the axis vector
            if axis is not None:
                plane = Plane( axis.vector, Point3( 0 ) )
                startVec = Vec3( plane.project( Point3( startVec ) ) )
                endVec = Vec3( plane.project( Point3( endVec )  ) )
            
            # Get the rotation axis
            rotAxis = endVec.cross( startVec ) * -1
            
        # Return if the rotation vector is not valid, ie it does not have any
        # length
        if not rotAxis.length():
            return
        
        # Normalize all vectors
        startVec.normalize()
        endVec.normalize()
        rotAxis.normalize()

        # Get the amount of degrees to rotate
        degs = startVec.angleDeg( endVec )
        
        # Transform the gizmo if in local rotation mode
        newRotMat = Mat4().rotateMat( degs, rotAxis )
        if self.local:
            self.setMat( newRotMat * self.getMat() )
            
        # Transform all attached node paths
        for i, np in enumerate( self.attachedNps ):
            
            # Split the transform into scale, rotation and translation
            # matrices
            transMat, rotMat, scaleMat = commonUtils.GetTrsMatrices( np.getTransform() )
            
            # Perform transforms in local or world space
            if self.local:
                np.setMat( scaleMat * newRotMat * rotMat * transMat )
            else:
                self.initNpXforms[i].getQuat().extractToMatrix( rotMat )
                np.setMat( scaleMat * rotMat * newRotMat * transMat )
                    
    def OnNodeMouse1Down( self, planar, collEntry ):
        Base.OnNodeMouse1Down( self, planar, collEntry )
        
        # Store the initial collision entry
        self.initCollEntry = collEntry
        
        # If the selected axis is the camera vector then use a point on the
        # plane whose normal is the camera vector as the starting vector,
        # otherwise use the surface normal from the collision with the sphere
        axis = self.GetSelectedAxis()
        if axis is not None and axis.vector == CAMERA_VECTOR:
            self.startVec = self.getRelativeVector( self.rootNp, self.startAxisPoint - self.getPos() )
        else:
            self.startVec = self.initCollEntry.getSurfaceNormal( self )
        
    def OnMouse2Down( self ):
        Base.OnMouse2Down( self )
        
        axis = self.GetSelectedAxis()
        if ( hasattr( self, 'collEntry' ) and hasattr( self, 'initCollEntry' ) and 
             self.collEntry.getIntoNode() != self.initCollEntry.getIntoNode() ):
            self.startVec = self.getRelativeVector( self.rootNp, self.GetAxisPoint( self.foobar ) - self.getPos() )
        else:
            self.startVec = self.getRelativeVector( self.rootNp, self.startAxisPoint - self.getPos() )
    
    def OnNodeMouseOver( self, collEntry ):
        Base.OnNodeMouseOver( self, collEntry )
        
        # Store the collision entry
        self.collEntry = collEntry