Exemple #1
0
class SpotLight(Light, DebugObject):

    """ This light type simulates a SpotLight. It has a position
    and an orientation. """

    def __init__(self):
        """ Creates a new spot light. """
        Light.__init__(self)
        DebugObject.__init__(self, "SpotLight")
        self.typeName = "SpotLight"

        self.nearPlane = 0.5
        self.radius = 30.0
        self.spotSize = Vec2(30, 30)

        # Used to compute the MVP
        self.ghostCamera = Camera("PointLight")
        self.ghostCamera.setActive(False)
        self.ghostLens = PerspectiveLens()
        self.ghostLens.setFov(130)
        self.ghostCamera.setLens(self.ghostLens)
        self.ghostCameraNode = NodePath(self.ghostCamera)
        self.ghostCameraNode.reparentTo(Globals.render)
        self.ghostCameraNode.hide()

    def getLightType(self):
        """ Internal method to fetch the type of this light, used by Light """
        return LightType.Spot

    def _updateLens(self):
        """ Internal method which gets called when the lens properties changed """
        for source in self.shadowSources:
            source.rebuildMatrixCache()

    def cleanup(self):
        """ Internal method which gets called when the light got deleted """
        self.ghostCameraNode.removeNode()
        Light.cleanup(self)

    def setFov(self, fov):
        """ Sets the field of view of the spotlight """
        assert(fov > 1 and fov < 180)
        self.ghostLens.setFov(fov)
        self._updateLens()

    def setPos(self, pos):
        """ Sets the position of the spotlight """
        self.ghostCameraNode.setPos(pos)
        Light.setPos(self, pos)

    def lookAt(self, pos):
        """ Makes the spotlight look at the given position """
        self.ghostCameraNode.lookAt(pos)

    def _computeAdditionalData(self):
        """ Internal method to recompute the spotlight MVP """
        self.ghostCameraNode.setPos(self.position)

        projMat = self.ghostLens.getProjectionMat()

        modelViewMat = Globals.render.getTransform(self.ghostCameraNode).getMat()
        self.mvp = modelViewMat * projMat

    def _computeLightBounds(self):
        """ Recomputes the bounds of this light. For a SpotLight, we for now
        use a simple BoundingSphere """
        self.bounds = BoundingSphere(Point3(self.position), self.radius * 2.0)

    def setNearFar(self, near, far):
        """ Sets the near and far plane of the spotlight """
        self.nearPlane = near
        self.radius = far
        self.ghostLens.setNearFar(near, far)
        self._updateLens()

    def _updateDebugNode(self):
        """ Internal method to generate new debug geometry. """
        debugNode = NodePath("SpotLightDebugNode")

        # Create the inner image 
        cm = CardMaker("SpotLightDebug")
        cm.setFrameFullscreenQuad()
        innerNode = NodePath(cm.generate())
        innerNode.setTexture(Globals.loader.loadTexture("Data/GUI/Visualization/SpotLight.png"))
        innerNode.setBillboardPointEye()
        innerNode.reparentTo(debugNode)
        innerNode.setPos(self.position)
        innerNode.setColorScale(1,1,0,1)

        # Create the outer lines
        lineNode = debugNode.attachNewNode("lines")

        currentNodeTransform = render.getTransform(self.ghostCameraNode).getMat()
        currentCamTransform = self.ghostLens.getProjectionMat()
        currentRelativeCamPos = self.ghostCameraNode.getPos(render)
        currentCamBounds = self.ghostLens.makeBounds()
        currentCamBounds.xform(self.ghostCameraNode.getMat(render))

        p = lambda index: currentCamBounds.getPoint(index)

        # Make a circle at the bottom
        frustumBottomCenter = (p(0) + p(1) + p(2) + p(3)) * 0.25
        upVector = (p(0) + p(1)) / 2 - frustumBottomCenter
        rightVector = (p(1) + p(2)) / 2 - frustumBottomCenter
        points = []
        for idx in xrange(64):
            rad = idx / 64.0 * math.pi * 2.0
            pos = upVector * math.sin(rad) + rightVector * math.cos(rad)
            pos += frustumBottomCenter
            points.append(pos)
        frustumLine = self._createDebugLine(points, True)
        frustumLine.setColorScale(1,1,0,1)
        frustumLine.reparentTo(lineNode)


        # Create frustum lines which connect the origin to the bottom circle
        pointArrays = [
            [self.position, frustumBottomCenter + upVector],
            [self.position, frustumBottomCenter - upVector],
            [self.position, frustumBottomCenter + rightVector],
            [self.position, frustumBottomCenter - rightVector],
        ]

        for pointArray in pointArrays:
            frustumLine = self._createDebugLine(pointArray, False)
            frustumLine.setColorScale(1,1,0,1)
            frustumLine.reparentTo(lineNode)

        # Create line which is in the direction of the spot light
        startPoint = (p(0) + p(1) + p(2) + p(3)) * 0.25
        endPoint = (p(4) + p(5) + p(6) + p(7)) * 0.25
        line = self._createDebugLine([startPoint, endPoint], False)
        line.setColorScale(1,1,1,1)
        line.reparentTo(lineNode)

        # Remove the old debug node
        self.debugNode.node().removeAllChildren()

        # Attach the new debug node
        debugNode.reparentTo(self.debugNode)
        # self.debugNode.flattenStrong()

    def _initShadowSources(self):
        """ Internal method to init the shadow sources """
        source = ShadowSource()
        source.setResolution(self.shadowResolution)
        source.setLens(self.ghostLens)
        self._addShadowSource(source)

    def _updateShadowSources(self):
        """ Recomputes the position of the shadow source """
        self.shadowSources[0].setPos(self.position)
        self.shadowSources[0].setHpr(self.ghostCameraNode.getHpr())

    def __repr__(self):
        """ Generates a string representation of this instance """
        return "SpotLight[]"
Exemple #2
0
        ("id", ("object", "matrix")))(("mypanda2", mymatrix))
    do_spawn = dragonfly.std.transistor(("id", ("object", "matrix")))()
    connect(v_spawn, do_spawn)
    connect(do_spawn, pandaspawn.spawn_matrix)
    key_z = dragonfly.io.keyboardsensor_trigger("Z")
    connect(key_z, do_spawn)


main = myhive().getinstance()
main.build("main")

main.scene.import_mesh_EGG("models/environment")
a = NodePath("")
a.setScale(0.25)
a.setPos(-8, 42, 0)
mat = a.getMat()
m = (mat.getRow3(3), mat.getRow3(0), mat.getRow3(1), mat.getRow3(2))
main.scene.add_model_MATRIX(matrix=m)

main.scene.import_mesh_EGG("models/panda-model")
a = NodePath("")
a.setScale(0.005)
mat = a.getMat()
m = (mat.getRow3(3), mat.getRow3(0), mat.getRow3(1), mat.getRow3(2))
main.scene.add_actor_MATRIX(matrix=m, entityname="mypanda")
main.scene.import_mesh_EGG("models/panda-walk4")
main.scene.add_animation("walk")

main.scene.import_mesh_EGG("models/panda-model")
a = NodePath("")
a.setScale(0.005)
Exemple #3
0
    connect(walk, animation.animation_name)

    key_w = dragonfly.io.keyboardsensor_trigger("W")
    connect(key_w, animation.loop)
    key_s = dragonfly.io.keyboardsensor_trigger("S")
    connect(key_s, animation.stop)


main = myhive().getinstance()
main.build("main")

main.scene.import_mesh_EGG("models/environment")
a = NodePath("")
a.setScale(0.25)
a.setPos(-8, 42, 0)
mat = a.getMat()
m = (mat.getRow3(3), mat.getRow3(0), mat.getRow3(1), mat.getRow3(2))
main.scene.add_model_MATRIX(matrix=m)

main.scene.import_mesh_EGG("models/panda-model")
a = NodePath("")
a.setScale(0.005)
mat = a.getMat()
m = (mat.getRow3(3), mat.getRow3(0), mat.getRow3(1), mat.getRow3(2))
main.scene.add_actor_MATRIX(matrix=m, entityname="mypanda")
main.scene.import_mesh_EGG("models/panda-walk4")
main.scene.add_animation("walk")

main.place()
main.close()
main.init()
Exemple #4
0
class Solid(MapObject):

    ObjectName = "solid"

    def __init__(self, id):
        MapObject.__init__(self, id)
        self.np = NodePath(SolidGeomNode("solid.%i" % id))
        self.np.setPythonTag("mapobject", self)
        self.np.node().setFinal(True)

        self.coll3D = self.np.attachNewNode(CollisionNode("coll3D"))
        self.coll3D.setCollideMask(LEGlobals.ObjectMask | LEGlobals.FaceMask
                                   | LEGlobals.Mask3D)
        #self.coll2D = self.np.attachNewNode(CollisionNode("coll2D"))
        #self.coll2D.setCollideMask(LEGlobals.ObjectMask | LEGlobals.FaceMask | LEGlobals.Mask2D)

        # CollisionSolid -> SolidFace
        self.faceCollSolids = {}

        self.geomIndices = {}
        self.faces = []

        self.pickRandomColor()

        self.addProperty(VisOccluder(self))

    def pickRandomColor(self):
        # Picks a random shade of blue/green for this solid.
        self.setColor(LEUtils.getRandomSolidColor())

    def setColor(self, color):
        self.color = color
        for face in self.faces:
            face.setColor(color)

    def getFaceFromCollisionSolid(self, solid):
        return self.faceCollSolids[solid]

    def addFaceGeom(self, geom, state):
        index = self.np.node().getNumGeoms()
        self.geomIndices[geom] = index
        self.np.node().addGeom(geom, state)
        return index

    def setFaceGeomState(self, geom, state):
        index = self.geomIndices[geom]
        self.np.node().setGeomState(index, state)

    def alignTexturesToFaces(self):
        for face in self.faces:
            face.alignTextureToFace()

    def alignTexturesToWorld(self):
        for face in self.faces:
            face.alignTextureToWorld()

    def copy(self, generator):
        s = Solid(generator.getNextID())
        self.copyBase(s, generator)
        for face in self.faces:
            f = face.copy(generator)
            f.setSolid(s)
            s.faces.append(f)
        s.generateFaces()
        return s

    def generateFaces(self):
        for face in self.faces:
            face.generate()
        if not self.temporary:
            self.createFaceCollisions()

    def writeKeyValues(self, keyvalues):
        MapObject.writeKeyValues(self, keyvalues)

        # Write or faces or "sides"
        for face in self.faces:
            faceKv = CKeyValues("side", keyvalues)
            face.writeKeyValues(faceKv)

    def readKeyValues(self, kv):
        MapObject.readKeyValues(self, kv)

        numChildren = kv.getNumChildren()
        for i in range(numChildren):
            child = kv.getChild(i)
            if child.getName() == "side":
                face = SolidFace(solid=self)
                face.readKeyValues(child)
                self.faces.append(face)

        self.createVerticesFromFacePlanes()
        self.createFaceCollisions()

    # Creates the collision objects that will be tested against for selecting solid faces.
    def createFaceCollisions(self):
        self.coll3D.node().clearSolids()
        #self.coll2D.node().clearSolids()

        self.faceCollSolids = {}

        for face in self.faces:

            numVerts = len(face.vertices)

            # Tris in 3D for ray->face selection
            for i in range(1, numVerts - 1):
                poly = CollisionPolygon(face.vertices[i + 1].pos,
                                        face.vertices[i].pos,
                                        face.vertices[0].pos)
                self.coll3D.node().addSolid(poly)
                self.faceCollSolids[poly] = face

            # Lines in 2D for box->edge selection
            #for i in range(len(face.vertices)):
            #    a = face.vertices[i].pos
            #    b = face.vertices[(i+1) % numVerts].pos
            #    if a == b:
            #        continue
            #    segment = CollisionSegment(a, b)
            #    self.coll2D.node().addSolid(segment)
            #    self.faceCollSolids[face][1].append(segment)

    def createVerticesFromFacePlanes(self):
        for i in range(len(self.faces)):
            face = self.faces[i]
            w = Winding.fromPlaneAndRadius(face.plane)

            for j in range(len(self.faces)):
                if i == j:
                    continue
                other = self.faces[j]
                #
                # Flip the plane, because we want to keep the back side.
                #
                w.splitInPlace(-other.plane)
            w.roundPoints()
            # The final winding is the face
            for j in range(len(w.vertices)):
                face.vertices.append(SolidVertex(w.vertices[j], face))
            face.calcTextureCoordinates(True)
            face.generate()

    def showClipVisRemove(self):
        for face in self.faces:
            face.showClipVisRemove()

    def showClipVisKeep(self):
        for face in self.faces:
            face.showClipVisKeep()

    def showBoundingBox(self):
        for face in self.faces:
            face.show3DLines()

    def hideBoundingBox(self):
        for face in self.faces:
            face.hide3DLines()

    def select(self):
        MapObject.select(self)
        for face in self.faces:
            face.select()

    def deselect(self):
        MapObject.deselect(self)
        for face in self.faces:
            face.deselect()

    def getAbsSolidOrigin(self):
        avg = Point3(0)
        for face in self.faces:
            avg += face.getAbsOrigin()
        avg /= len(self.faces)
        return avg

    def setToSolidOrigin(self):
        # Moves the solid origin to median of all face vertex positions,
        # and transforms all faces to be relative to the median position.
        # Resets angles, scale, and shear.
        origin = self.getAbsSolidOrigin()
        self.setAbsOrigin(origin)
        self.setAbsAngles(Vec3(0))
        self.setAbsScale(Vec3(1))
        self.setAbsShear(Vec3(0))
        mat = self.np.getMat(NodePath())
        mat.invertInPlace()
        for face in self.faces:
            face.xform(mat)

    def getName(self):
        return "Solid"

    def getDescription(self):
        return "Convex solid geometry."

    def delete(self):
        MapObject.delete(self)
        self.coll3D.removeNode()
        self.coll3D = None
        #self.coll2D.removeNode()
        #self.coll2D = None
        self.faceCollSolids = None
        for face in self.faces:
            face.delete()
        self.faces = None
        self.color = None

    # Splits this solid into two solids by intersecting against a plane.
    def split(self, plane, generator, temp=False):
        back = front = None

        # Check that this solid actually spans the plane
        classifications = []
        for face in self.faces:
            classify = face.classifyAgainstPlane(plane)
            if classify not in classifications:
                classifications.append(classify)
        if PlaneClassification.Spanning not in classifications:
            if PlaneClassification.Back in classifications:
                back = self
            elif PlaneClassification.Front in classifications:
                front = self
            return [False, back, front]

        backPlanes = [plane]
        flippedFront = Plane(plane)
        flippedFront.flip()
        frontPlanes = [flippedFront]

        for face in self.faces:
            classify = face.classifyAgainstPlane(plane)
            if classify != PlaneClassification.Back:
                frontPlanes.append(face.getWorldPlane())
            if classify != PlaneClassification.Front:
                backPlanes.append(face.getWorldPlane())

        back = Solid.createFromIntersectingPlanes(backPlanes, generator, False,
                                                  temp)
        front = Solid.createFromIntersectingPlanes(frontPlanes, generator,
                                                   False, temp)
        if not temp:
            # copyBase() will set the transform to what we're copying from, but we already
            # figured out a transform for the solids. Store the current transform so we can
            # set it back.
            bTrans = back.np.getTransform()
            fTrans = front.np.getTransform()
            self.copyBase(back, generator)
            self.copyBase(front, generator)
            back.np.setTransform(bTrans)
            front.np.setTransform(fTrans)

        unionOfFaces = front.faces + back.faces
        for face in unionOfFaces:
            face.material = self.faces[0].material.clone()
            face.setMaterial(face.material.material)
            face.alignTextureToFace()

        # Restore textures (match the planes up on each face)
        for orig in self.faces:
            for face in back.faces:
                classify = face.classifyAgainstPlane(orig.getWorldPlane())
                if classify != PlaneClassification.OnPlane:
                    continue
                face.material = orig.material.clone()
                face.setMaterial(face.material.material)
                face.alignTextureToFace()
                break
            for face in front.faces:
                classify = face.classifyAgainstPlane(orig.getWorldPlane())
                if classify != PlaneClassification.OnPlane:
                    continue
                face.material = orig.material.clone()
                face.setMaterial(face.material.material)
                face.alignTextureToFace()
                break

        back.generateFaces()
        front.generateFaces()

        if not temp:
            back.recalcBoundingBox()
            front.recalcBoundingBox()

        return [True, back, front]

    @staticmethod
    def createFromIntersectingPlanes(planes,
                                     generator,
                                     generateFaces=True,
                                     temp=False):
        solid = Solid(generator.getNextID())
        solid.setTemporary(temp)
        for i in range(len(planes)):
            # Split the winding by all the other planes
            w = Winding.fromPlaneAndRadius(planes[i])
            for j in range(len(planes)):
                if i != j:
                    # Flip the plane, because we want to keep the back.
                    w.splitInPlace(-planes[j])

            # Round vertices a bit for sanity
            w.roundPoints()

            # The final winding is the face
            face = SolidFace(generator.getNextFaceID(), Plane(planes[i]),
                             solid)
            for j in range(len(w.vertices)):
                face.vertices.append(SolidVertex(w.vertices[j], face))
            solid.faces.append(face)

        if not temp:
            solid.setToSolidOrigin()

            # Ensure all faces point outwards
            origin = Point3(0)
            for face in solid.faces:
                # The solid origin should be on or behind the face plane.
                # If the solid origin is in front of the face plane, flip the face.
                if face.plane.distToPlane(origin) > 0:
                    face.flip()

        if generateFaces:
            solid.alignTexturesToFaces()
            solid.generateFaces()
            if not temp:
                solid.recalcBoundingBox()

        return solid
Exemple #5
0
class DirectionHandle(PandaNode, MouseEventListener):
    geomNode = makeGeomNode()
    clickableGeomNode = makeClickableGeom()

    def __init__(self, parent, color, hpr, dim):
        PandaNode.__init__(self, dim+'handle')
        self.path = NodePath(self)
        self.parent = parent
        self.dim = dim

        arrow = GeomNode('gnode')
        arrow.addGeomsFrom(self.geomNode)
        arrownp = self.path.attachNewNode(arrow)
        arrownp.hide(BitMask32(1))
        
        clickNode = ClickableNode('clicknode')
        clickNode.setDepthLevel(0.5)
        clickNode.addMouseListener(self)
        clicknp = self.path.attachNewNode(clickNode)
        
        clickgeom = clicknp.attachNewNode(GeomNode('clicknode'))
        clickgeom.hide(BitMask32(7))
        clickgeom.node().addGeomsFrom(self.clickableGeomNode)

        linesegs = LineSegs()
        linesegs.setColor(color)
        linesegs.setThickness(2)
        linesegs.moveTo(Vec3(0, 0, -30))
        linesegs.drawTo(Vec3(0, 0, -0.5))
        linesegs.moveTo(Vec3(0, 0, 0.5))
        linesegs.drawTo(Vec3(0, 0, 30))
        lines = self.path.attachNewNode(linesegs.create())
        lines.show(BitMask32(1))
        lines.hide(BitMask32(2|4|8|16))
        lines.setBin('opaque', 30, 100)
        lines.setAntialias(AntialiasAttrib.MNone)

        self.path.setColor(color)
        self.path.setHpr(hpr)
        
        self.mDownPos = Vec2()

    def mouseEntered(self, event):
        self.path.setColorScale(2, 2, 2, 2)

    def mouseExited(self, event):
        self.path.setColorScale(1, 1, 1, 1)

    def mousePressed(self, event):
        self.parent.beginTransformation()
       
        lens = base.cam.node().getLens()

        scale = Mat4.scaleMat(self.path.getScale(base.camera))
        descale = Mat4()
        descale.invertAffineFrom(scale)
        mvMat = descale * self.path.getMat(base.camera)

        origin = Point3(mvMat.xformPoint(Point3()))
        dir = Vec3(mvMat.xformVec(Vec3(0, 0, 1)))
        xprod = dir.cross(origin)
        planeNorm = xprod.cross(dir)
        planeNorm.normalize()
        d = planeNorm.dot(origin)
        self.dir = dir
        self.origin = origin
        self.planeNorm = planeNorm
        self.d = d
        self.lens = lens

        self.fromCam = base.camera.getMat(self.parent.path) * scale
        
        transl = self.mouse2Vec(event.pos)
        self.origin = transl + self.origin

    def mouseMoved(self, event):
        transl = self.fromCam.xformVec(self.mouse2Vec(event.pos))
        self.parent.transform(Mat4.translateMat(transl))

    def mouse2Vec(self, mpos):
        ray = Vec3()
        ray.xz = self.lens.getFilmSize()
        ray.x = mpos.x * ray.x / 2
        ray.z = mpos.y * ray.z / 2
        ray.y = self.lens.getFocalLength()
        ray.normalize()
        k = self.d/(ray.dot(self.planeNorm))
        return self.dir * (ray*k - self.origin).dot(self.dir)
Exemple #6
0
class Handle(PandaNode, MouseEventListener):
    
    def __init__(self):
        PandaNode.__init__(self, 'PositionHandle')

        CameraController.getInstance().addEventHandler(EVT_CAMERA_MOVE,
                self._fixScale)
        self.path = NodePath(self)

        self.xHandle = DirectionHandle(self, Vec4(1, 0, 0, 0.6),
                Vec3(0, 0, 90), 'x')
        self.addChild(self.xHandle)

        self.yHandle = DirectionHandle(self, Vec4(0, 1, 0, 0.6),
                Vec3(0, -90, 0), 'y')
        self.addChild(self.yHandle)
        
        self.zHandle = DirectionHandle(self, Vec4(0, 0, 1, 0.6),
                Vec3(0, 0, 0), 'z')
        self.addChild(self.zHandle)
        
        self.hHandle = RotationHandle(self, Vec4(0, 0, 1, 0.6),
                Vec3(0, 0, 0), 'z')
        self.addChild(self.hHandle)
        NodePath(self.hHandle).setScale(1.02)

        self.pHandle = RotationHandle(self, Vec4(0, 1, 0, 0.6),
                Vec3(0, -90, 0), 'y')
        self.addChild(self.pHandle)
        NodePath(self.pHandle).setScale(0.98)

        self.rHandle = RotationHandle(self, Vec4(1, 0, 0, 0.6),
                Vec3(0, 0, 90), 'x')
        self.addChild(self.rHandle)
        self._tPressed()
        
        self.path.setTransparency(1)
        self.path.setBin('transparent', 30, 50)
        #self.path.setDepthTest(False)
        self.path.setLightOff()
        self.path.setRenderModeThickness(2)
        self.setClients([])

        self.evtWatcher = DirectObject.DirectObject()
        self.evtWatcher.accept(base.win.getWindowEvent(),
            self._windowEventHandler)
        self.evtWatcher.accept('r', self._rPressed)
        self.evtWatcher.accept('t', self._tPressed)

        self.originalPos = self.path.getPos()
        self.fLenPx = base.cam.node().getLens().getFocalLength() * base.win.getXSize()
        self._fixScale()

    def _rPressed(self):
        self.xHandle.path.stash()
        self.yHandle.path.stash()
        self.zHandle.path.stash()
        self.hHandle.path.unstash()
        self.pHandle.path.unstash()
        self.rHandle.path.unstash()

    def _tPressed(self):
        self.xHandle.path.unstash()
        self.yHandle.path.unstash()
        self.zHandle.path.unstash()
        self.hHandle.path.stash()
        self.pHandle.path.stash()
        self.rHandle.path.stash()

    def setClients(self, clients, center=Vec3()):
        if clients:
            self.path.show(BitMask32(1|4|16))
            self.path.setPos(center)
            self._fixScale()
        else:
            self.path.hide(BitMask32(1|2|4|8|16))
        self.clients = [[client, None] for client in clients]

    def beginTransformation(self):
        self.originalMat = Mat4(Mat4.identMat())
        self.originalMat.setRow(3, self.path.getMat(render).getRow(3))
        self.originalMatInv = Mat4()
        self.originalMatInv.invertAffineFrom(self.originalMat)
        for i in xrange(len(self.clients)):
            print 'Their matrix * My matrix'
            print self.clients[i][0].getMat(self.path) * self.path.getMat()
            print 'Total matrix:'
            print self.clients[i][0].getMat()
            #self.clients[i][1] = self.clients[i][0].getMat(self.path)
            self.clients[i][1] = (self.clients[i][0].getMat() *
                    self.originalMatInv)

    def transform(self, xform):
        transl = Mat4(Mat4.identMat())
        transl.setRow(3, xform.getRow3(3))
        self.path.setMat(render, transl * self.originalMat)
        self._fixScale()
        xform.setRow(3, Vec3())
        for client, originalMat in self.clients:
            #client.setMat(self.path, originalMat * xform)
            client.setMat(originalMat * xform * transl * self.originalMat)

    def _fixScale(self, camera=base.camera):
        myPos = self.path.getPos()
        dist = (camera.getPos() - myPos).length()
        self.path.setScale(dist * HANDLE_SIZE / self.fLenPx)

    def _windowEventHandler(self, window):
        self.fLenPx = (base.cam.node().getLens().getFocalLength() *
                 window.getXSize())
        self._fixScale()
Exemple #7
0
class RotationHandle(PandaNode, MouseEventListener):
    geomNode = makeRotationGeomNode()
    
    def __init__(self, parent, color, hpr, dim):
        PandaNode.__init__(self, dim+'rotHandle')
        self.path = NodePath(self)
        self.parent = parent
        self.dim = dim

        circle = GeomNode('gnode')
        circle.addGeomsFrom(self.geomNode)

        self.clickable = ClickableNode('clickable')
        self.clickable.addChild(circle)
        self.clickable.addMouseListener(self)
        circlenp = self.path.attachNewNode(self.clickable)

        self.path.setColor(color)
        self.path.setHpr(hpr)
        self.mDownPos = Vec2()

    def mouseEntered(self, event):
        self.path.setColorScale(2, 2, 2, 2)

    def mouseExited(self, event):
        self.path.setColorScale(1, 1, 1, 1)

    def mousePressed(self, event):
        self.parent.beginTransformation()
       
        self.lens = base.cam.node().getLens()

        scale = Mat4.scaleMat(self.path.getScale(base.camera))
        descale = Mat4()
        descale.invertAffineFrom(scale)
        mvMat = descale * self.path.getMat(base.camera)

        self.origin = Point3(mvMat.xformPoint(Point3()))
        self.planeNorm = Vec3(mvMat.xformVec(Vec3(0, 0, 1)))
        self.planeNorm.normalize()
        self.d = self.planeNorm.dot(self.origin)

        self.fromCam = base.camera.getMat(self.parent.path) * scale
        
        self.dir = Vec3(self.mouse2Vec(event.pos))
        self.dir.normalize()

    def mouseMoved(self, event):
        transl = Vec3(self.mouse2Vec(event.pos))
        transl.normalize()
        angle = self.dir.signedAngleDeg(transl, self.planeNorm)
        axis = Vec3()
        setattr(axis, self.dim, 1)
        self.parent.transform(Mat4.rotateMatNormaxis(angle, axis))

    def mouse2Vec(self, mpos):
        ray = Vec3()
        ray.xz = self.lens.getFilmSize()
        ray.x = mpos.x * ray.x / 2
        ray.z = mpos.y * ray.z / 2
        ray.y = self.lens.getFocalLength()
        ray.normalize()
        k = self.d/ray.dot(self.planeNorm)
        return ray*k - self.origin
Exemple #8
0
class Handle(PandaNode, MouseEventListener):
    def __init__(self):
        PandaNode.__init__(self, 'PositionHandle')

        CameraController.getInstance().addEventHandler(EVT_CAMERA_MOVE,
                                                       self._fixScale)
        self.path = NodePath(self)

        self.xHandle = DirectionHandle(self, Vec4(1, 0, 0, 0.6),
                                       Vec3(0, 0, 90), 'x')
        self.addChild(self.xHandle)

        self.yHandle = DirectionHandle(self, Vec4(0, 1, 0, 0.6),
                                       Vec3(0, -90, 0), 'y')
        self.addChild(self.yHandle)

        self.zHandle = DirectionHandle(self, Vec4(0, 0, 1, 0.6), Vec3(0, 0, 0),
                                       'z')
        self.addChild(self.zHandle)

        self.hHandle = RotationHandle(self, Vec4(0, 0, 1, 0.6), Vec3(0, 0, 0),
                                      'z')
        self.addChild(self.hHandle)
        NodePath(self.hHandle).setScale(1.02)

        self.pHandle = RotationHandle(self, Vec4(0, 1, 0, 0.6),
                                      Vec3(0, -90, 0), 'y')
        self.addChild(self.pHandle)
        NodePath(self.pHandle).setScale(0.98)

        self.rHandle = RotationHandle(self, Vec4(1, 0, 0, 0.6), Vec3(0, 0, 90),
                                      'x')
        self.addChild(self.rHandle)
        self._tPressed()

        self.path.setTransparency(1)
        self.path.setBin('transparent', 30, 50)
        #self.path.setDepthTest(False)
        self.path.setLightOff()
        self.path.setRenderModeThickness(2)
        self.setClients([])

        self.evtWatcher = DirectObject.DirectObject()
        self.evtWatcher.accept(base.win.getWindowEvent(),
                               self._windowEventHandler)
        self.evtWatcher.accept('r', self._rPressed)
        self.evtWatcher.accept('t', self._tPressed)

        self.originalPos = self.path.getPos()
        self.fLenPx = base.cam.node().getLens().getFocalLength(
        ) * base.win.getXSize()
        self._fixScale()

    def _rPressed(self):
        self.xHandle.path.stash()
        self.yHandle.path.stash()
        self.zHandle.path.stash()
        self.hHandle.path.unstash()
        self.pHandle.path.unstash()
        self.rHandle.path.unstash()

    def _tPressed(self):
        self.xHandle.path.unstash()
        self.yHandle.path.unstash()
        self.zHandle.path.unstash()
        self.hHandle.path.stash()
        self.pHandle.path.stash()
        self.rHandle.path.stash()

    def setClients(self, clients, center=Vec3()):
        if clients:
            self.path.show(BitMask32(1 | 4 | 16))
            self.path.setPos(center)
            self._fixScale()
        else:
            self.path.hide(BitMask32(1 | 2 | 4 | 8 | 16))
        self.clients = [[client, None] for client in clients]

    def beginTransformation(self):
        self.originalMat = Mat4(Mat4.identMat())
        self.originalMat.setRow(3, self.path.getMat(render).getRow(3))
        self.originalMatInv = Mat4()
        self.originalMatInv.invertAffineFrom(self.originalMat)
        for i in xrange(len(self.clients)):
            print 'Their matrix * My matrix'
            print self.clients[i][0].getMat(self.path) * self.path.getMat()
            print 'Total matrix:'
            print self.clients[i][0].getMat()
            #self.clients[i][1] = self.clients[i][0].getMat(self.path)
            self.clients[i][1] = (self.clients[i][0].getMat() *
                                  self.originalMatInv)

    def transform(self, xform):
        transl = Mat4(Mat4.identMat())
        transl.setRow(3, xform.getRow3(3))
        self.path.setMat(render, transl * self.originalMat)
        self._fixScale()
        xform.setRow(3, Vec3())
        for client, originalMat in self.clients:
            #client.setMat(self.path, originalMat * xform)
            client.setMat(originalMat * xform * transl * self.originalMat)

    def _fixScale(self, camera=base.camera):
        myPos = self.path.getPos()
        dist = (camera.getPos() - myPos).length()
        self.path.setScale(dist * HANDLE_SIZE / self.fLenPx)

    def _windowEventHandler(self, window):
        self.fLenPx = (base.cam.node().getLens().getFocalLength() *
                       window.getXSize())
        self._fixScale()
Exemple #9
0
class DirectionHandle(PandaNode, MouseEventListener):
    geomNode = makeGeomNode()
    clickableGeomNode = makeClickableGeom()

    def __init__(self, parent, color, hpr, dim):
        PandaNode.__init__(self, dim + 'handle')
        self.path = NodePath(self)
        self.parent = parent
        self.dim = dim

        arrow = GeomNode('gnode')
        arrow.addGeomsFrom(self.geomNode)
        arrownp = self.path.attachNewNode(arrow)
        arrownp.hide(BitMask32(1))

        clickNode = ClickableNode('clicknode')
        clickNode.setDepthLevel(0.5)
        clickNode.addMouseListener(self)
        clicknp = self.path.attachNewNode(clickNode)

        clickgeom = clicknp.attachNewNode(GeomNode('clicknode'))
        clickgeom.hide(BitMask32(7))
        clickgeom.node().addGeomsFrom(self.clickableGeomNode)

        linesegs = LineSegs()
        linesegs.setColor(color)
        linesegs.setThickness(2)
        linesegs.moveTo(Vec3(0, 0, -30))
        linesegs.drawTo(Vec3(0, 0, -0.5))
        linesegs.moveTo(Vec3(0, 0, 0.5))
        linesegs.drawTo(Vec3(0, 0, 30))
        lines = self.path.attachNewNode(linesegs.create())
        lines.show(BitMask32(1))
        lines.hide(BitMask32(2 | 4 | 8 | 16))
        lines.setBin('opaque', 30, 100)
        lines.setAntialias(AntialiasAttrib.MNone)

        self.path.setColor(color)
        self.path.setHpr(hpr)

        self.mDownPos = Vec2()

    def mouseEntered(self, event):
        self.path.setColorScale(2, 2, 2, 2)

    def mouseExited(self, event):
        self.path.setColorScale(1, 1, 1, 1)

    def mousePressed(self, event):
        self.parent.beginTransformation()

        lens = base.cam.node().getLens()

        scale = Mat4.scaleMat(self.path.getScale(base.camera))
        descale = Mat4()
        descale.invertAffineFrom(scale)
        mvMat = descale * self.path.getMat(base.camera)

        origin = Point3(mvMat.xformPoint(Point3()))
        dir = Vec3(mvMat.xformVec(Vec3(0, 0, 1)))
        xprod = dir.cross(origin)
        planeNorm = xprod.cross(dir)
        planeNorm.normalize()
        d = planeNorm.dot(origin)
        self.dir = dir
        self.origin = origin
        self.planeNorm = planeNorm
        self.d = d
        self.lens = lens

        self.fromCam = base.camera.getMat(self.parent.path) * scale

        transl = self.mouse2Vec(event.pos)
        self.origin = transl + self.origin

    def mouseMoved(self, event):
        transl = self.fromCam.xformVec(self.mouse2Vec(event.pos))
        self.parent.transform(Mat4.translateMat(transl))

    def mouse2Vec(self, mpos):
        ray = Vec3()
        ray.xz = self.lens.getFilmSize()
        ray.x = mpos.x * ray.x / 2
        ray.z = mpos.y * ray.z / 2
        ray.y = self.lens.getFocalLength()
        ray.normalize()
        k = self.d / (ray.dot(self.planeNorm))
        return self.dir * (ray * k - self.origin).dot(self.dir)
Exemple #10
0
class RotationHandle(PandaNode, MouseEventListener):
    geomNode = makeRotationGeomNode()

    def __init__(self, parent, color, hpr, dim):
        PandaNode.__init__(self, dim + 'rotHandle')
        self.path = NodePath(self)
        self.parent = parent
        self.dim = dim

        circle = GeomNode('gnode')
        circle.addGeomsFrom(self.geomNode)

        self.clickable = ClickableNode('clickable')
        self.clickable.addChild(circle)
        self.clickable.addMouseListener(self)
        circlenp = self.path.attachNewNode(self.clickable)

        self.path.setColor(color)
        self.path.setHpr(hpr)
        self.mDownPos = Vec2()

    def mouseEntered(self, event):
        self.path.setColorScale(2, 2, 2, 2)

    def mouseExited(self, event):
        self.path.setColorScale(1, 1, 1, 1)

    def mousePressed(self, event):
        self.parent.beginTransformation()

        self.lens = base.cam.node().getLens()

        scale = Mat4.scaleMat(self.path.getScale(base.camera))
        descale = Mat4()
        descale.invertAffineFrom(scale)
        mvMat = descale * self.path.getMat(base.camera)

        self.origin = Point3(mvMat.xformPoint(Point3()))
        self.planeNorm = Vec3(mvMat.xformVec(Vec3(0, 0, 1)))
        self.planeNorm.normalize()
        self.d = self.planeNorm.dot(self.origin)

        self.fromCam = base.camera.getMat(self.parent.path) * scale

        self.dir = Vec3(self.mouse2Vec(event.pos))
        self.dir.normalize()

    def mouseMoved(self, event):
        transl = Vec3(self.mouse2Vec(event.pos))
        transl.normalize()
        angle = self.dir.signedAngleDeg(transl, self.planeNorm)
        axis = Vec3()
        setattr(axis, self.dim, 1)
        self.parent.transform(Mat4.rotateMatNormaxis(angle, axis))

    def mouse2Vec(self, mpos):
        ray = Vec3()
        ray.xz = self.lens.getFilmSize()
        ray.x = mpos.x * ray.x / 2
        ray.z = mpos.y * ray.z / 2
        ray.y = self.lens.getFocalLength()
        ray.normalize()
        k = self.d / ray.dot(self.planeNorm)
        return ray * k - self.origin
Exemple #11
0
class TQGraphicsNodePath:
    """ Anything that fundamentally is a only a graphics object in this engine should have these properties.

    Kwargs:
        TQGraphicsNodePath_creation_parent_node : this is assigned in the constructor, and after makeObject and the return of
        the p3d Nodepath, each TQGraphicsNodePath object has to call set_p3d_node """

    def __init__(self, **kwargs):
        """ """
        self.TQGraphicsNodePath_creation_parent_node = None
        self.p3d_nodepath = NodePath("empty")
        self.p3d_nodepath_changed_post_init_p = False
        self.p3d_parent_nodepath = NodePath("empty")

        self.node_p3d = None

        self.p3d_nodepath.reparentTo(self.p3d_parent_nodepath)

        self.apply_kwargs(**kwargs)

    def apply_kwargs(self, **kwargs):
        """ """
        if 'color' in kwargs:
            TQGraphicsNodePath.setColor(self, kwargs.get('color'))
        else:
            TQGraphicsNodePath.setColor(self, Vec4(1., 1., 1., 1.))

    def attach_to_render(self):
        """ """
        # assert self.p3d_nodepath
        # self.p3d_nodepath.reparentTo(render)
        assert self.p3d_nodepath
        self.reparentTo(engine.tq_graphics_basics.tq_render)

    def attach_to_aspect2d(self):
        """ """
        # assert self.p3d_nodepath
        # self.p3d_nodepath.reparentTo(aspect2d)
        assert self.p3d_nodepath
        self.reparentTo(engine.tq_graphics_basics.tq_aspect2d)

    def _set_p3d_nodepath_plain_post_init(p3d_nodepath):
        """ """
        self.p3d_nodepath = p3d_nodepath
        self.p3d_nodepath_changed_post_init_p = True

    @staticmethod
    def from_p3d_nodepath(p3d_nodepath, **tq_graphics_nodepath_kwargs):
        """ factory """
        go = TQGraphicsNodePath(**tq_graphics_nodepath_kwargs)
        go.set_p3d_nodepath(p3d_nodepath)
        return go

    def set_parent_node_for_nodepath_creation(
            self, TQGraphicsNodePath_creation_parent_node):
        """ when calling attachNewNode_p3d, a new node pat is generated.
        E.g.: To attach a line to render (3d world) is different than attaching
        it to aspect2d (2d GUI plane), since the aspect2d children are not directly
        affected by camera movements
        Args:
        - TQGraphicsNodePath_creation_parent_node : the NodePath to attach the TQGraphicsNodePath to
                                          (e.g. render or aspect2d in p3d)
        """

        # self.set_parent_node_for_nodepath_creation(self.TQGraphicsNodePath_creation_parent_node)
        self.TQGraphicsNodePath_creation_parent_node = TQGraphicsNodePath_creation_parent_node

    def set_p3d_nodepath(self, p3d_nodepath, remove_old_nodepath=True):
        """ """
        self.p3d_nodepath = p3d_nodepath

    def get_p3d_nodepath(self):
        """ """
        return self.p3d_nodepath

    def set_render_above_all(self, p):
        """ set render order to be such that it renders normally (false), or above all (true)
        Args:
            p: True or False to enable or disable the 'above all' rendering mode """

        try:
            if p == True:
                self.p3d_nodepath.setBin("fixed", 0)
                self.p3d_nodepath.setDepthTest(False)
                self.p3d_nodepath.setDepthWrite(False)
            else:
                self.p3d_nodepath.setBin("default", 0)
                self.p3d_nodepath.setDepthTest(True)
                self.p3d_nodepath.setDepthWrite(True)
        except NameError:       # if p3d_nodepath is not yet defined
            print("NameError in set_render_above_all()")

    def remove(self):
        """ """
        self.p3d_nodepath.removeNode()

    def setPos(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setPos(*args, **kwargs)

    def getPos(self):
        """ """
        return self.p3d_nodepath.getPos()

    def setScale(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setScale(*args, **kwargs)

    def getScale(self):
        """ """
        return self.p3d_nodepath.getScale()

    def setMat(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setMat(*args, **kwargs)

    def setMat_normal(self, mat4x4_normal_np):
        """ normal convention (numpy array), i.e. convert to forrowvecs convention for p3d setMat call """
        return self.p3d_nodepath.setMat(math_utils.to_forrowvecs(mat4x4_normal_np))


    def getMat(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getMat(*args, **kwargs)

    def getMat_normal(self, *args, **kwargs):
        """ """
        return math_utils.from_forrowvecs(self.p3d_nodepath.getMat(*args, **kwargs))

    def setTexture(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setTexture(*args, **kwargs)

    def setColor(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setColor(*args, **kwargs)

    def setTwoSided(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setTwoSided(*args, **kwargs)

    def setRenderModeWireframe(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setRenderModeWireframe(*args, **kwargs)

    def reparentTo(self, *args, **kwargs):
        """ """
        new_args = list(args)
        new_args[0] = new_args[0].p3d_nodepath
        return self.p3d_nodepath.reparentTo(*new_args, **kwargs)

    def reparentTo_p3d(self, *args, **kwargs):
        """ input a p3d nodepath directly """
        # new_args = list(args)
        # new_args[0] = new_args[0].p3d_nodepath
        return self.p3d_nodepath.reparentTo(*args, **kwargs)

    def get_node_p3d(self):
        """ """
        # return self.p3d_nodepath.node()
        return self.node_p3d

    def set_node_p3d(self, node_p3d):
        """ not available in p3d NodePath class """
        self.node_p3d = node_p3d

    def setRenderModeFilled(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setRenderModeFilled(*args, **kwargs)

    def setLightOff(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setLightOff(*args, **kwargs)

    def show(self):
        """ """
        return self.p3d_nodepath.show()

    def hide(self):
        """ """
        return self.p3d_nodepath.hide()

    def setRenderModeThickness(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setRenderModeThickness(*args, **kwargs)

    def removeNode(self):
        """ """
        return self.p3d_nodepath.removeNode()

    def setHpr(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setHpr(*args, **kwargs)

    def showBounds(self):
        """ """
        return self.p3d_nodepath.showBounds()

    def setCollideMask(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setCollideMask(*args, **kwargs)

    def getParent_p3d(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getParent(*args, **kwargs)

    def wrtReparentTo(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.wrtReparentTo(*args, **kwargs)

    def setBin(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setBin(*args, **kwargs)

    def setDepthTest(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setDepthTest(*args, **kwargs)

    def setDepthWrite(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setDepthWrite(*args, **kwargs)

    def get_children_p3d(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.get_children(*args, **kwargs)

    def attachNewNode_p3d(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.attachNewNode(*args, **kwargs)

    def lookAt(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.lookAt(*args, **kwargs)

    def setLight(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setLight(*args, **kwargs)

    def setAntialias(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setAntialias(*args, **kwargs)

    def getRelativeVector(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getRelativeVector(*args, **kwargs)

    def setTransparency(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setTransparency(*args, **kwargs)

    def getHpr(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getHpr(*args, **kwargs)

    def setHpr(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setHpr(*args, **kwargs)

    def getTightBounds(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getTightBounds(*args, **kwargs)

    def showTightBounds(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.showTightBounds(*args, **kwargs)