コード例 #1
0
 def paste(self, f):
     self.plane = Plane(f.plane)
     self.isSelected = f.isSelected
     self.setMaterial(f.material.clone())
     self.solid = f.solid
     self.vertices = []
     for i in range(len(f.vertices)):
         newVert = f.vertices[i].clone()
         newVert.face = self
         self.vertices.append(newVert)
     self.generate()
コード例 #2
0
ファイル: BaseBrush.py プロジェクト: tsp-team/panda3d
    def makeSolid(self, generator, faces, material, temp = False, color = None):
        solid = Solid(generator.getNextID())
        solid.setTemporary(temp)
        if color is not None:
            solid.setColor(color)
        for arr in faces:
            face = SolidFace(generator.getNextFaceID(),
                             Plane.fromVertices(arr[0], arr[1], arr[2]),
                             solid)
            face.setMaterial(material)
            for vert in arr:
                face.vertices.append(SolidVertex(vert, face))
            solid.faces.append(face)
            face.alignTextureToFace()
            if temp:
                face.setPreviewState()
                face.generate()

        if not temp:
            solid.setToSolidOrigin()
            solid.generateFaces()
            solid.recalcBoundingBox()
        else:
            solid.reparentTo(base.render)

        return solid
コード例 #3
0
    def __init__(self, id = 0, plane = Plane(0, 0, 1, 0), solid = None):
        MapWritable.__init__(self, base.document)
        self.id = id
        self.material = FaceMaterial()
        self.vertices = []
        self.isSelected = False
        self.plane = plane
        self.solid = solid
        self.hasGeometry = False
        self.vdata = None

        # Different primitive representations of this face.
        self.geom3D = None
        self.geom3DLines = None
        self.geom2D = None

        # Index into the Solid's GeomNode of the Geoms we render for this face.
        self.index3D = -1
        self.index3DLines = -1
        self.index2D = -1

        # RenderState for each Geom we render for this face.
        self.state3D = RenderState.makeEmpty()
        self.state3DLines = RenderState.make(AntialiasAttrib.make(AntialiasAttrib.MLine), ColorAttrib.makeFlat(Vec4(1, 1, 0, 1)))
        self.state2D = RenderState.makeEmpty()
        if solid:
            self.setColor(self.solid.color)

        # Not None if face is a displacement.
        self.dispInfo = None
コード例 #4
0
 def copy(self, generator):
     f = SolidFace(generator.getNextID(), Plane(self.plane), self.solid)
     f.isSelected = self.isSelected
     f.setFaceMaterial(self.material.clone())
     for i in range(len(self.vertices)):
         newVert = self.vertices[i].clone()
         newVert.face = f
         f.vertices.append(newVert)
     return f
コード例 #5
0
    def readKeyValues(self, kv):
        self.id = int(self.id)
        base.document.reserveFaceID(self.id)

        p0 = Point3()
        p1 = Point3()
        p2 = Point3()
        kv.parsePlanePoints(kv.getValue("plane"), p0, p1, p2)
        self.plane = Plane.fromVertices(p0, p1, p2)

        self.material.readKeyValues(kv)
        self.setMaterial(self.material.material)
コード例 #6
0
ファイル: ClipTool.py プロジェクト: tsp-team/panda3d
    def confirmClip(self):
        if self.point1 is None or self.point2 is None or self.point3 is None:
            self.reset()
            return

        clipPlane = Plane.fromVertices(self.point1, self.point2, self.point3)
        side = ClipSide(self.side)
        self.reset()
        solids = []
        for obj in base.selectionMgr.selectedObjects:
            if obj.ObjectName == "solid":
                solids.append(obj)
        base.actionMgr.performAction("Clip %i solid(s)" % len(solids), Clip(solids, clipPlane, side != ClipSide.Back, side != ClipSide.Front))
        self.side = side
コード例 #7
0
ファイル: Solid.py プロジェクト: tsp-team/panda3d
    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
コード例 #8
0
ファイル: ClipTool.py プロジェクト: tsp-team/panda3d
    def updateClipPlane(self):
        self.clearClipPlane()

        if self.point1 == self.point2 or self.point1 == self.point3 or self.point2 == self.point3:
            return
        plane = Plane.fromVertices(self.point1, self.point2, self.point3)
        tempGen = IDGenerator()

        for obj in base.selectionMgr.selectedObjects:
            if obj.ObjectName != "solid":
                continue
            ret, back, front = obj.split(plane, tempGen, True)
            if ret:
                front.np.reparentTo(self.doc.render)
                back.np.reparentTo(self.doc.render)
                self.tempSolids.append((obj, front, back))
                # Hide the original solid
                obj.np.stash()

        self.updateClipSide(self.side)
コード例 #9
0
 def flip(self):
     self.vertices.reverse()
     self.plane = Plane.fromVertices(self.vertices[0].pos, self.vertices[1].pos, self.vertices[2].pos)
     if self.hasGeometry:
         self.regenerateGeometry()
コード例 #10
0
 def getWorldPlane(self):
     plane = Plane(self.plane)
     plane.xform(self.solid.np.getMat(NodePath()))
     return plane
コード例 #11
0
class SolidFace(MapWritable):

    ObjectName = "side"

    def __init__(self, id = 0, plane = Plane(0, 0, 1, 0), solid = None):
        MapWritable.__init__(self, base.document)
        self.id = id
        self.material = FaceMaterial()
        self.vertices = []
        self.isSelected = False
        self.plane = plane
        self.solid = solid
        self.hasGeometry = False
        self.vdata = None

        # Different primitive representations of this face.
        self.geom3D = None
        self.geom3DLines = None
        self.geom2D = None

        # Index into the Solid's GeomNode of the Geoms we render for this face.
        self.index3D = -1
        self.index3DLines = -1
        self.index2D = -1

        # RenderState for each Geom we render for this face.
        self.state3D = RenderState.makeEmpty()
        self.state3DLines = RenderState.make(AntialiasAttrib.make(AntialiasAttrib.MLine), ColorAttrib.makeFlat(Vec4(1, 1, 0, 1)))
        self.state2D = RenderState.makeEmpty()
        if solid:
            self.setColor(self.solid.color)

        # Not None if face is a displacement.
        self.dispInfo = None

        #self.generateNodes()

    def setPreviewState(self):
        self.state3D = self.state3D.setAttrib(TransparencyAttrib.make(True))
        self.state3D = self.state3D.setAttrib(ColorScaleAttrib.make(Vec4(1, 1, 1, PreviewAlpha)))
        self.state2D = self.state2D.setAttrib(ColorAttrib.makeFlat(LEGlobals.PreviewBrush2DColor))

    def isDisplacement(self):
        return self.dispInfo is not None

    def getBounds(self, other = None):
        return self.solid.getBounds(other)

    def setSolid(self, solid):
        self.solid = solid

    def getOrientation(self):
        plane = self.getWorldPlane()

        # The normal must have a nonzero length!
        if plane[0] == 0 and plane[1] == 0 and plane[2] == 0:
            return FaceOrientation.Invalid

        #
        # Find the axis that the surface normal has the greatest projection onto.
        #

        orientation = FaceOrientation.Invalid
        normal = plane.getNormal()

        maxDot = 0
        for i in range(6):
            dot = normal.dot(FaceNormals[i])

            if (dot >= maxDot):
                maxDot = dot
                orientation = FaceOrientation(i)

        return orientation

    def showClipVisRemove(self):
        self.geom3D.setDraw(False)
        self.state3DLines = self.state3DLines.setAttrib(ColorAttrib.makeFlat(Vec4(1, 0, 0, 1)))
        self.state2D = self.state2D.setAttrib(ColorAttrib.makeFlat(Vec4(1, 0, 0, 1)))
        self.solid.setFaceGeomState(self.geom3DLines, self.state3DLines)
        self.solid.setFaceGeomState(self.geom2D, self.state2D)

    def showClipVisKeep(self):
        self.geom3D.setDraw(True)
        self.state3DLines = self.state3DLines.setAttrib(ColorAttrib.makeFlat(Vec4(1, 1, 0, 1)))
        self.state2D = self.state2D.setAttrib(ColorAttrib.makeFlat(Vec4(1, 1, 1, 1)))
        self.solid.setFaceGeomState(self.geom3DLines, self.state3DLines)
        self.solid.setFaceGeomState(self.geom2D, self.state2D)

    def show3DLines(self):
        if self.geom3DLines:
            self.geom3DLines.setDraw(True)

    def hide3DLines(self):
        if self.geom3DLines:
            self.geom3DLines.setDraw(False)

    def copy(self, generator):
        f = SolidFace(generator.getNextID(), Plane(self.plane), self.solid)
        f.isSelected = self.isSelected
        f.setFaceMaterial(self.material.clone())
        for i in range(len(self.vertices)):
            newVert = self.vertices[i].clone()
            newVert.face = f
            f.vertices.append(newVert)
        return f

    def clone(self):
        f = self.copy(IDGenerator())
        f.id = self.id
        return f

    def paste(self, f):
        self.plane = Plane(f.plane)
        self.isSelected = f.isSelected
        self.setMaterial(f.material.clone())
        self.solid = f.solid
        self.vertices = []
        for i in range(len(f.vertices)):
            newVert = f.vertices[i].clone()
            newVert.face = self
            self.vertices.append(newVert)
        self.generate()

    def unclone(self, f):
        self.paste(f)
        self.id = f.id

    def xform(self, mat):
        for vert in self.vertices:
            vert.xform(mat)
        self.plane.xform(mat)
        self.calcTextureCoordinates(True)
        if self.hasGeometry:
            self.regenerateGeometry()

    def getAbsOrigin(self):
        avg = Point3(0)
        for vert in self.vertices:
            avg += vert.getWorldPos()
        avg /= len(self.vertices)
        return avg

    def getWorldPlane(self):
        plane = Plane(self.plane)
        plane.xform(self.solid.np.getMat(NodePath()))
        return plane

    def getName(self):
        return "Solid face"

    def select(self):
        self.state3D = self.state3D.setAttrib(ColorScaleAttrib.make(Vec4(1, 0.75, 0.75, 1)))
        self.state2D = self.state2D.setAttrib(ColorAttrib.makeFlat(Vec4(1, 0, 0, 1)))
        self.state2D = self.state2D.setAttrib(CullBinAttrib.make("fixed", LEGlobals.SelectedSort))
        self.state2D = self.state2D.setAttrib(DepthWriteAttrib.make(False))
        self.state2D = self.state2D.setAttrib(DepthTestAttrib.make(False))
        self.solid.setFaceGeomState(self.geom3D, self.state3D)
        self.solid.setFaceGeomState(self.geom2D, self.state2D)
        self.show3DLines()
        self.isSelected = True

    def deselect(self):
        self.state3D = self.state3D.removeAttrib(ColorScaleAttrib)
        self.state2D = self.state2D.setAttrib(ColorAttrib.makeFlat(self.solid.color))
        self.state2D = self.state2D.removeAttrib(DepthWriteAttrib)
        self.state2D = self.state2D.removeAttrib(DepthTestAttrib)
        self.state2D = self.state2D.removeAttrib(CullBinAttrib)
        self.solid.setFaceGeomState(self.geom3D, self.state3D)
        self.solid.setFaceGeomState(self.geom2D, self.state2D)
        self.hide3DLines()
        self.isSelected = False

    def readKeyValues(self, kv):
        self.id = int(self.id)
        base.document.reserveFaceID(self.id)

        p0 = Point3()
        p1 = Point3()
        p2 = Point3()
        kv.parsePlanePoints(kv.getValue("plane"), p0, p1, p2)
        self.plane = Plane.fromVertices(p0, p1, p2)

        self.material.readKeyValues(kv)
        self.setMaterial(self.material.material)

    def writeKeyValues(self, kv):
        kv.setKeyValue("id", str(self.id))

        # Write out the first three vertices to define the plane in world space
        vert0 = self.vertices[0].getWorldPos()
        vert1 = self.vertices[1].getWorldPos()
        vert2 = self.vertices[2].getWorldPos()
        kv.setKeyValue("plane", "(%f %f %f) (%f %f %f) (%f %f %f)" % (
            vert0.x, vert0.y, vert0.z,
            vert1.x, vert1.y, vert1.z,
            vert2.x, vert2.y, vert2.z
        ))

        # Write out material values
        self.material.writeKeyValues(kv)

    def generate(self):
        self.regenerateGeometry()

    def setMaterial(self, mat):
        self.material.material = mat
        if mat:
            self.state3D = self.state3D.setAttrib(BSPMaterialAttrib.make(mat.material))
            if mat.material.hasKeyvalue("$translucent") and bool(int(mat.material.getKeyvalue("$translucent"))):
                self.state3D = self.state3D.setAttrib(TransparencyAttrib.make(TransparencyAttrib.MDual))
            if self.geom3D:
                self.solid.setFaceGeomState(self.geom3D, self.state3D)
                #if mat.material.hasKeyvalue("$basetexture") and "tools" in mat.material.getKeyvalue("$basetexture"):
                #    self.geom3D.setDraw(False)

    def setColor(self, color):
        self.state2D = self.state2D.setAttrib(ColorAttrib.makeFlat(color))
        if self.geom2D:
            self.solid.setFaceGeomState(self.geom2D, self.state2D)

    def setFaceMaterial(self, faceMat):
        self.material = faceMat
        self.setMaterial(self.material.material)
        self.calcTextureCoordinates(True)
        self.send('faceMaterialChanged', [self])

    def alignTextureToFace(self):
        self.material.alignTextureToFace(self)
        self.calcTextureCoordinates(True)

    def alignTextureToWorld(self):
        self.material.alignTextureToWorld(self)
        self.calcTextureCoordinates(True)

    def calcTextureCoordinates(self, minimizeShiftValues):
        if minimizeShiftValues:
            self.minimizeTextureShiftValues()

        for vert in self.vertices:
            vert.uv.set(0, 0)

        if self.material.material is None:
            return
        if self.material.material.size.x == 0 or self.material.material.size.y == 0:
            return
        if self.material.scale.x == 0 or self.material.scale.y == 0:
            return

        for vert in self.vertices:
            vertPos = vert.getWorldPos()
            #
            # projected s, t (u, v) texture coordinates
            #
            s = self.material.uAxis.dot(vertPos) / self.material.scale.x + self.material.shift.x
            t = self.material.vAxis.dot(vertPos) / self.material.scale.y + self.material.shift.y

            #
            # "normalize" the texture coordinates
            #
            vert.uv.x = s / self.material.material.size.x
            vert.uv.y = -t / self.material.material.size.y

        self.calcTangentSpaceAxes()

        if self.hasGeometry:
            self.modifyGeometryUVs()

    def calcTangentSpaceAxes(self):
        #
        # Create the axes from texture space axes
        #
        plane = self.getWorldPlane()
        normal = plane.getNormal()
        self.material.binormal = Vec3(self.material.vAxis).normalized()
        self.material.tangent = normal.cross(self.material.binormal).normalized()
        self.material.binormal = self.material.tangent.cross(normal).normalized()

        #
        # Adjust tangent for "backwards" mapping if need be
        #
        tmp = self.material.uAxis.cross(self.material.vAxis)
        if normal.dot(tmp) > 0.0:
            self.material.tangent = -self.material.tangent

    def modifyGeometryUVs(self):
        # Modifies the geometry vertex UVs in-place
        twriter = GeomVertexWriter(self.vdata, InternalName.getTexcoord())
        tanwriter = GeomVertexWriter(self.vdata, InternalName.getTangent())
        bwriter = GeomVertexWriter(self.vdata, InternalName.getBinormal())

        for i in range(len(self.vertices)):
            twriter.setData2f(self.vertices[i].uv)
            tanwriter.setData3f(self.material.tangent)
            bwriter.setData3f(self.material.binormal)

    def minimizeTextureShiftValues(self):
        if self.material.material is None:
            return

        # Keep the shift values to a minimum
        self.material.shift.x %= self.material.material.size.x
        self.material.shift.y %= self.material.material.size.y

        if self.material.shift.x < -self.material.material.size.x / 2:
            self.material.shift.x += self.material.material.size.x
        if self.material.shift.y < -self.material.material.size.y / 2:
            self.material.shift.y += self.material.material.size.y

    def classifyAgainstPlane(self, plane):
        front = back = onplane = 0
        count = len(self.vertices)

        for vert in self.vertices:
            test = plane.onPlane(vert.getWorldPos())
            if test <= 0:
                back += 1
            if test >= 0:
                front += 1
            if test == 0:
                onplane += 1

        if onplane == count:
            return PlaneClassification.OnPlane
        if front == count:
            return PlaneClassification.Front
        if back == count:
            return PlaneClassification.Back
        return PlaneClassification.Spanning

    def flip(self):
        self.vertices.reverse()
        self.plane = Plane.fromVertices(self.vertices[0].pos, self.vertices[1].pos, self.vertices[2].pos)
        if self.hasGeometry:
            self.regenerateGeometry()

    def regenerateGeometry(self):
        #
        # Generate vertex data
        #

        numVerts = len(self.vertices)

        vdata = GeomVertexData("SolidFace", getFaceFormat(), GeomEnums.UHStatic)
        vdata.uncleanSetNumRows(len(self.vertices))

        vwriter = GeomVertexWriter(vdata, InternalName.getVertex())
        twriter = GeomVertexWriter(vdata, InternalName.getTexcoord())
        nwriter = GeomVertexWriter(vdata, InternalName.getNormal())
        tanwriter = GeomVertexWriter(vdata, InternalName.getTangent())
        bwriter = GeomVertexWriter(vdata, InternalName.getBinormal())

        for i in range(len(self.vertices)):
            vert = self.vertices[i]
            vwriter.setData3f(vert.pos)
            twriter.setData2f(vert.uv)
            nwriter.setData3f(self.plane.getNormal())
            tanwriter.setData3f(self.material.tangent)
            bwriter.setData3f(self.material.binormal)

        #
        # Generate indices
        #

        # Triangles in 3D view
        prim3D = GeomTriangles(GeomEnums.UHStatic)
        prim3D.reserveNumVertices((numVerts - 2) * 3)
        for i in range(1, numVerts - 1):
            prim3D.addVertices(i + 1, i, 0)
            prim3D.closePrimitive()

        # Line loop in 2D view.. using line strips
        prim2D = GeomLinestrips(GeomEnums.UHStatic)
        prim2D.reserveNumVertices(numVerts + 1)
        for i in range(numVerts):
            prim2D.addVertex(i)
        # Close off the line strip with the first vertex.. creating a line loop
        prim2D.addVertex(0)
        prim2D.closePrimitive()

        #
        # Generate mesh objects
        #

        geom3D = SolidFaceGeom(vdata)
        geom3D.setDrawMask(VIEWPORT_3D_MASK)
        geom3D.setPlaneCulled(True)
        geom3D.setPlane(self.plane)
        geom3D.addPrimitive(prim3D)
        self.index3D = self.solid.addFaceGeom(geom3D, self.state3D)

        geom3DLines = SolidFaceGeom(vdata)
        geom3DLines.addPrimitive(prim2D)
        geom3DLines.setDrawMask(VIEWPORT_3D_MASK)
        geom3DLines.setDraw(False)
        self.index3DLines = self.solid.addFaceGeom(geom3DLines, self.state3DLines)

        geom2D = SolidFaceGeom(vdata)
        geom2D.addPrimitive(prim2D)
        geom2D.setDrawMask(VIEWPORT_2D_MASK)
        self.index2D = self.solid.addFaceGeom(geom2D, self.state2D)

        self.geom3D = geom3D
        self.geom3DLines = geom3DLines
        self.geom2D = geom2D

        self.vdata = vdata

        self.hasGeometry = True

    def delete(self):
        for vert in self.vertices:
            vert.delete()
        self.vertices = None
        self.id = None
        self.material.cleanup()
        self.material = None
        self.color = None
        self.index2D = None
        self.index3D = None
        self.index3DLines = None
        self.geom3D = None
        self.geom3DLines = None
        self.geom2D = None
        self.state3D = None
        self.state3DLines = None
        self.state2D = None
        self.solid = None
        self.isSelected = None
        self.plane = None
        self.vdata = None
        self.hasGeometry = None
コード例 #12
0
ファイル: Solid.py プロジェクト: tsp-team/panda3d
    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]