def __init__(self):
        ShowBase.__init__(self)

        PanditorDisableMouseFunc()
        camera.setPos(0.0, 0.0, 50.0)
        camera.lookAt(0.0)
        PanditorEnableMouseFunc()

        # 1) create GeomVertexData
        frmt = GeomVertexFormat.getV3n3cp()
        vdata = GeomVertexData('triangle', frmt, Geom.UHDynamic)

        # 2) create Writers/Rewriters (must all be created before any readers and readers are one-pass-temporary)
        vertex = GeomVertexRewriter(vdata, 'vertex')
        normal = GeomVertexRewriter(vdata, 'normal')
        color = GeomVertexRewriter(vdata, 'color')

        zUp = Vec3(0, 0, 1)
        wt = Vec4(1.0, 1.0, 1.0, 1.0)
        gr = Vec4(0.5, 0.5, 0.5, 1.0)

        # 3) write each column on the vertex data object (for speed, have a different writer for each column)
        def addPoint(x, y, z):
            vertex.addData3f(x, y, z)
            normal.addData3f(zUp)
            color.addData4f(wt)

        addPoint(0.0, 0.0, 0.0)
        addPoint(5.0, 0.0, 0.0)
        addPoint(0.0, 5.0, 0.0)
        addPoint(5.0, 5.0, 0.0)

        # 4) create a primitive and add the vertices via index (not truely associated with the actual vertex table, yet)
        tris = GeomTriangles(Geom.UHDynamic)
        tris.addVertices(0, 1, 2)
        tris.closePrimitive(
        )  # exception thrown if verts added != 3, other types inform Panda how many verts/primitive
        tris.addVertices(2, 1, 3)
        print "vdataPoints", vdata.getArrays()[0]
        # 5.1) (adding to scene) create a Geom and add primitives of like base-type i.e. triangles and triangle strips
        geom = Geom(vdata)
        geom.addPrimitive(tris)
        # 5.2) create a GeomNode to hold the Geom(s) and add the Geom(s)
        gn = GeomNode('gnode')
        gn.addGeom(geom)
        # 5.3) attache the node to the scene
        gnNodePath = render.attachNewNode(gn)

        geomPts = Geom(vdata)
        pts = GeomPoints(Geom.UHStatic)
        pts.addVertices(0, 1, 2)
        pts.closePrimitive()
        geomPts.addPrimitive(pts)
        pointsNode = GeomNode('points_node')
        pointsNode.addGeom(geomPts)
        pointsNP = render.attachNewNode(pointsNode)
        pointsNP.setZ(0.5)

        render.ls()
Beispiel #2
0
    def drawBody(self, pos, quat, radius=1, keepDrawing=True, numVertices=16):
        """
        this draws the body of the tree. This draws a ring of vertices and
        connects the rings with triangles to from the body.

        the keepDrawing parameter tells the function whether or not we're
        at an end
        if the vertices before were an end, don't draw branches to it
        """
        vdata = self.bodydata
        circleGeom = Geom(vdata)
        vertWriter = GeomVertexWriter(vdata, "vertex")
        normalWriter = GeomVertexWriter(vdata, "normal")
        texReWriter = GeomVertexRewriter(vdata, "texcoord")
        startRow = vdata.getNumRows()
        vertWriter.setRow(startRow)
        normalWriter.setRow(startRow)
        sCoord = 0
        if (startRow != 0):
            texReWriter.setRow(startRow - numVertices)
            sCoord = texReWriter.getData2f().getX() + 1
            draw = (startRow - numVertices) in self.drawFlags
            if not draw:
                sCoord -= 1
        drawIndex = startRow
        texReWriter.setRow(startRow)

        angleSlice = 2 * math.pi / numVertices
        currAngle = 0
        perp1 = quat.getRight()
        perp2 = quat.getForward()
        #vertex information is written here
        for i in xrange(numVertices + 1):
            #doubles the last vertex to fix UV seam
            adjCircle = pos + (perp1 * math.cos(currAngle) +
                               perp2 * math.sin(currAngle)) * radius
            normal = perp1 * math.cos(currAngle) + perp2 * math.sin(currAngle)
            normalWriter.addData3f(normal)
            vertWriter.addData3f(adjCircle)
            texReWriter.addData2f(1.0 * i / numVertices, sCoord)
            if keepDrawing:
                self.drawFlags.add(drawIndex)
            drawIndex += 1
            currAngle += angleSlice
        draw = (startRow - numVertices) in self.drawFlags
        #we cant draw quads directly so we use Tristrips
        if (startRow != 0) and draw:
            lines = GeomTristrips(Geom.UHStatic)
            for i in xrange(numVertices + 1):
                lines.addVertex(i + startRow)
                lines.addVertex(i + startRow - numVertices - 1)
            lines.addVertex(startRow)
            lines.addVertex(startRow - numVertices)
            lines.closePrimitive()
            #lines.decompose()
            circleGeom.addPrimitive(lines)
            circleGeomNode = GeomNode("Debug")
            circleGeomNode.addGeom(circleGeom)
            self.numPrimitives += numVertices * 2
            self.bodies.attachNewNode(circleGeomNode)
Beispiel #3
0
 def update_geom(self, points, colors, sizes):
     geom = self.instance.children[0].node().modify_geom(0)
     vdata = geom.modify_vertex_data()
     vdata.unclean_set_num_rows(len(points))
     vwriter = GeomVertexRewriter(vdata, InternalName.get_vertex())
     colorwriter = GeomVertexWriter(vdata, InternalName.get_color())
     sizewriter = GeomVertexWriter(vdata, InternalName.get_size())
     for (point, color, size) in zip(points, colors, sizes):
         vwriter.addData3f(*point)
         colorwriter.addData4f(*color)
         sizewriter.addData1f(size)
Beispiel #4
0
    def drawBody(self, pos, quat, radius=1,UVcoord=(1,1), numVertices=_polySize):
#        if isRoot:
#            self.bodydata = GeomVertexData("body vertices", GeomVertexFormat.getV3n3t2(), Geom.UHStatic)
        vdata = self.bodydata
        circleGeom = Geom(vdata) # this was originally a copy of all previous geom in vdata...
        vertWriter = GeomVertexWriter(vdata, "vertex")
        #colorWriter = GeomVertexWriter(vdata, "color")
        normalWriter = GeomVertexWriter(vdata, "normal")
#        drawReWriter = GeomVertexRewriter(vdata, "drawFlag")
        texReWriter = GeomVertexRewriter(vdata, "texcoord")

        startRow = vdata.getNumRows()
        vertWriter.setRow(startRow)
        #colorWriter.setRow(startRow)
        normalWriter.setRow(startRow)       
        texReWriter.setRow(startRow)   
       
        #axisAdj=Mat4.rotateMat(45, axis)*Mat4.scaleMat(radius)*Mat4.translateMat(pos)
        perp1 = quat.getRight()
        perp2 = quat.getForward()   
        
#TODO: PROPERLY IMPLEMENT RADIAL NOISE        
        #vertex information is written here
        angleSlice = 2 * pi / numVertices
        currAngle = 0
        for i in xrange(numVertices+1): 
            adjCircle = pos + (perp1 * cos(currAngle) + perp2 * sin(currAngle)) * radius * (.5+bNodeRadNoise*random.random())
            normal = perp1 * cos(currAngle) + perp2 * sin(currAngle)       

            normalWriter.addData3f(normal)
            vertWriter.addData3f(adjCircle)
            texReWriter.addData2f(float(UVcoord[0]*i) / numVertices,UVcoord[1])            # UV SCALE HERE!
            #colorWriter.addData4f(0.5, 0.5, 0.5, 1)
            currAngle += angleSlice 
        
        #we cant draw quads directly so we use Tristrips
        if (startRow != 0):
            lines = GeomTristrips(Geom.UHStatic)         
            for i in xrange(numVertices+1):
                lines.addVertex(i + startRow)
                lines.addVertex(i + startRow - numVertices-1)
            lines.addVertex(startRow)
            lines.addVertex(startRow - numVertices)
            lines.closePrimitive()
            #lines.decompose()
            circleGeom.addPrimitive(lines)           
            circleGeomNode = GeomNode("Debug")
            circleGeomNode.addGeom(circleGeom)   
            self.numPrimitives += numVertices * 2
            self.bodies.attachNewNode(circleGeomNode)
            return circleGeomNode
Beispiel #5
0
 def update_geom(self):
     geom = self.node.modify_geom(0)
     vdata = geom.modify_vertex_data()
     vwriter = GeomVertexRewriter(vdata, InternalName.get_vertex())
     #TODO: refactor with above code !!!
     delta = self.body.parent.get_local_position()
     if self.orbit.is_periodic():
         epoch = self.context.time.time_full - self.orbit.period
         step = self.orbit.period / (self.nbOfPoints - 1)
     else:
         #TODO: Properly calculate orbit start and end time
         epoch = self.orbit.get_time_of_perihelion() - self.orbit.period * 5.0
         step = self.orbit.period * 10.0 / (self.nbOfPoints - 1)
     for i in range(self.nbOfPoints):
         time = epoch + step * i
         pos = self.orbit.get_position_at(time) - delta
         vwriter.setData3f(*pos)
Beispiel #6
0
 def rain(self, task):
     # animate level
     self.flood()
     # Animate Rain
     speed = 1.0
     vertex = GeomVertexRewriter(self.rain_vdata, 'vertex')
     color = GeomVertexWriter(self.rain_vdata, 'color')
     moving = np.random.choice([0, 1],
                               size=(self.n_points, self.n_points),
                               p=[999 / 1000, 1. / 1000])
     moved = 0
     for j in range(self.n_points):
         for i in range(self.n_points):
             # rain
             v = vertex.getData3f()
             # start falling
             if v[2] == self.n_points:
                 if moving[j][i] == 1 and self.raining == True:
                     self.rz[j][i] -= speed
                     vertex.setData3f(v[0], v[1], self.rz[j][i])
                     color.setData4f(0.3, 0.3, 1, 1)
                     moved += 1
                 else:
                     vertex.setData3f(v[0], v[1], v[2])
                     color.setData4f(0.3, 0.3, 1, 0)
             # keep falling
             elif self.rz[j][i] > self.lz[j][i]:
                 if self.rz[j][i] - speed > self.lz[j][i]:
                     self.rz[j][i] -= speed
                 else:
                     self.rz[j][i] = self.lz[j][i]
                 vertex.setData3f(v[0], v[1], self.rz[j][i])
                 if self.rz[j][i] > self.wz[j][i]:
                     color.setData4f(0.3, 0.3, 1, 1)
                 else:
                     color.setData4f(0.3, 0.3, 1, 0)
                 moved += 1
             # stop falling
             else:
                 # handle rolling drops
                 v = list(map(int, v))
                 moved += self.rolling_drops(v, vertex, color, moved, i, j)
     if moved == 0:
         self.flooding = False
         return task.done
     return task.cont
Beispiel #7
0
    def __call__(self, mesh):
        vertex_writer = GeomVertexRewriter(mesh.data, "vertex")
        while not vertex_writer.isAtEnd():
            vertex = vertex_writer.getData4()
            vertex_writer.setData4(self.m.xform(vertex))

        return mesh
    def __init__(self, vertexName='ConstrainedDelaunayTriangles', vertexFormat=GeomVertexFormat.getV3(),
                  usage = Geom.UHDynamic, onVertexCreationCallback = None, universalZ = 0.0):
        self._vertexData = GeomVertexData(vertexName, vertexFormat, Geom.UHDynamic)
        self._geomTriangles = GeomTriangles(usage)
        self._geomTrianglesHoles = GeomTriangles(usage)
        self._vertexRewriter = GeomVertexRewriter(self._vertexData, 'vertex')  # user cannot have control of a writer

        if onVertexCreationCallback is None:
            onVertexCreationCallback = lambda x, y, z: None  # something to call without checking existence later
        self._vertexCallback = onVertexCreationCallback

        self._universalZ = universalZ
        self.__holes = [[]]
        self.__polygon = []
        inf = float('inf')
        negInf = float('-inf')
        self.bounds = {
            'minX': inf,
            'maxX': negInf,
            'minY': inf,
            'maxY': negInf,
        }
        self.lastStaticVertexIndex = -1
Beispiel #9
0
    def __call__(self, mesh):
        vertex_writer = GeomVertexRewriter(mesh.data, "vertex")
        while not vertex_writer.isAtEnd():
            vertex = vertex_writer.getData4()
            vertex_writer.setData4((
                vertex.x * self.v.x,
                vertex.y * self.v.y,
                vertex.z * self.v.z,
                vertex.w * self.v.w,
            ))

        return mesh
Beispiel #10
0
    def Car(carAppearance):

        newVisualCar = loader.loadModel("models/f1car")
        geomNodeCollection = newVisualCar.findAllMatches('**/+GeomNode')

        for nodePath in geomNodeCollection:
            geomNode = nodePath.node()
            for i in range(geomNode.getNumGeoms()):
                geom = geomNode.modifyGeom(i)
                state = geomNode.getGeomState(i)
                vdata = geom.modifyVertexData()
                color = GeomVertexRewriter(vdata, 'color')
                while not color.isAtEnd():
                    c = color.getData4f()
                    r, g, b, a = c
                    #f r==1.0 and g==0.0 and b==0.0:
                    #	g=1.0
                    #	b=1.0
                    if r == 0.0 and g == 1.0 and b == 0.0:
                        r = carAppearance[0]
                        g = carAppearance[1]
                        b = carAppearance[2]
                    elif r == 1.0 and g == 0.0 and b == 0.0:
                        r = carAppearance[3]
                        g = carAppearance[4]
                        b = carAppearance[5]
                    elif r == 1.0 and g == 1.0 and b == 1.0:
                        r = carAppearance[6]
                        g = carAppearance[7]
                        b = carAppearance[8]
                    elif r == 1.0 and g == 1.0 and b == 0:
                        r = carAppearance[9]
                        g = carAppearance[10]
                        b = carAppearance[11]

                    #print "c = %s" % (repr(c))
                    #print('r='+str(r)+' g='+str(g)+' b='+str(b))
                    color.setData4f(r, g, b, 1.0)

        return newVisualCar
Beispiel #11
0
 def __init__(self, objinit, cdtype="triangle", mass=.3, restitution=0, allowdeactivation=False, allowccd=True,
              friction=.2, dynamic=True, name="rbd"):
     """
     :param objinit: could be itself (copy), or an instance of collision model
     :param type: triangle or convex
     :param mass:
     :param restitution: bounce parameter
     :param friction:
     :param dynamic: only applicable to triangle type, if an object does not move with force, it is not dynamic
     :param name:
     author: weiwei
     date: 20190626, 20201119
     """
     super().__init__(name)
     if isinstance(objinit, gm.GeometricModel):
         if objinit._objtrm is None:
             raise ValueError("Only applicable to models with a trimesh!")
         self.com = objinit.objtrm.center_mass
         self.setMass(mass)
         self.setRestitution(restitution)
         self.setFriction(friction)
         self.setLinearDamping(.3)
         self.setAngularDamping(.3)
         if allowdeactivation:
             self.setDeactivationEnabled(True)
             self.setLinearSleepThreshold(0.001)
             self.setAngularSleepThreshold(0.001)
         else:
             self.setDeactivationEnabled(False)
         if allowccd:  # continuous collision detection
             self.setCcdMotionThreshold(1e-6)
             self.setCcdSweptSphereRadius(0.0005)
         gnd = objinit.objpdnp.getChild(0).find("+GeomNode")
         geom = copy.deepcopy(gnd.node().getGeom(0))
         vdata = geom.modifyVertexData()
         vertrewritter = GeomVertexRewriter(vdata, 'vertex')
         while not vertrewritter.isAtEnd():  # shift local coordinate to geom to correctly update dynamic changes
             v = vertrewritter.getData3f()
             vertrewritter.setData3f(v[0] - self.com[0], v[1] - self.com[1], v[2] - self.com[2])
         geomtf = gnd.getTransform()
         if cdtype is "triangle":
             geombmesh = BulletTriangleMesh()
             geombmesh.addGeom(geom)
             bulletshape = BulletTriangleMeshShape(geombmesh, dynamic=dynamic)
             bulletshape.setMargin(1e-6)
             self.addShape(bulletshape, geomtf)
         elif cdtype is "convex":
             bulletshape = BulletConvexHullShape()  # TODO: compute a convex hull?
             bulletshape.addGeom(geom, geomtf)
             bulletshape.setMargin(1e-6)
             self.addShape(bulletshape, geomtf)
         else:
             raise NotImplementedError
         pdmat4 = geomtf.getMat()
         pdv3 = pdmat4.xformPoint(Vec3(self.com[0], self.com[1], self.com[2]))
         homomat = dh.pdmat4_to_npmat4(pdmat4)
         pos = dh.pdv3_to_npv3(pdv3)
         homomat[:3, 3] = pos  # update center to com
         self.setTransform(TransformState.makeMat(dh.npmat4_to_pdmat4(homomat)))
     elif isinstance(objinit, BDBody):
         self.com = objinit.com.copy()
         self.setMass(objinit.getMass())
         self.setRestitution(objinit.restitution)
         self.setFriction(objinit.friction)
         self.setLinearDamping(.3)
         self.setAngularDamping(.3)
         if allowdeactivation:
             self.setDeactivationEnabled(True)
             self.setLinearSleepThreshold(0.001)
             self.setAngularSleepThreshold(0.001)
         else:
             self.setDeactivationEnabled(False)
         if allowccd:
             self.setCcdMotionThreshold(1e-6)
             self.setCcdSweptSphereRadius(0.0005)
         self.setTransform(TransformState.makeMat(dh.npmat4_to_pdmat4(objinit.gethomomat())))
         self.addShape(objinit.getShape(0), objinit.getShapeTransform(0))
Beispiel #12
0
def drawBody(nodePath, vdata, pos, vecList, radius=1, keepDrawing=True, numVertices=8):

    circleGeom = Geom(vdata)

    vertWriter = GeomVertexWriter(vdata, "vertex")
    colorWriter = GeomVertexWriter(vdata, "color")
    normalWriter = GeomVertexWriter(vdata, "normal")
    drawReWriter = GeomVertexRewriter(vdata, "drawFlag")
    texReWriter = GeomVertexRewriter(vdata, "texcoord")

    startRow = vdata.getNumRows()
    vertWriter.setRow(startRow)
    colorWriter.setRow(startRow)
    normalWriter.setRow(startRow)

    sCoord = 0

    if (startRow != 0):
        texReWriter.setRow(startRow - numVertices)
        sCoord = texReWriter.getData2f().getX() + 1

        drawReWriter.setRow(startRow - numVertices)
        if(drawReWriter.getData1f() == False):
            sCoord -= 1

    drawReWriter.setRow(startRow)
    texReWriter.setRow(startRow)

    angleSlice = 2 * math.pi / numVertices
    currAngle = 0

    #axisAdj=LMatrix4.rotateMat(45, axis)*LMatrix4.scaleMat(radius)*LMatrix4.translateMat(pos)

    perp1 = vecList[1]
    perp2 = vecList[2]

    # vertex information is written here
    for i in range(numVertices):
        adjCircle = pos + \
            (perp1 * math.cos(currAngle) + perp2 * math.sin(currAngle)) * \
            radius
        normal = perp1 * math.cos(currAngle) + perp2 * math.sin(currAngle)
        normalWriter.addData3f(normal)
        vertWriter.addData3f(adjCircle)
        texReWriter.addData2f(sCoord, (i + 0.001) / (numVertices - 1))
        colorWriter.addData4f(0.5, 0.5, 0.5, 1)
        drawReWriter.addData1f(keepDrawing)
        currAngle += angleSlice

    drawReader = GeomVertexReader(vdata, "drawFlag")
    drawReader.setRow(startRow - numVertices)

    # we cant draw quads directly so we use Tristrips
    if (startRow != 0) & (drawReader.getData1f() != False):
        lines = GeomTristrips(Geom.UHStatic)
        half = int(numVertices * 0.5)
        for i in range(numVertices):
            lines.addVertex(i + startRow)
            if i < half:
                lines.addVertex(i + startRow - half)
            else:
                lines.addVertex(i + startRow - half - numVertices)

        lines.addVertex(startRow)
        lines.addVertex(startRow - half)
        lines.closePrimitive()
        lines.decompose()
        circleGeom.addPrimitive(lines)

        circleGeomNode = GeomNode("Debug")
        circleGeomNode.addGeom(circleGeom)

        # I accidentally made the front-face face inwards. Make reverse makes the tree render properly and
        # should cause any surprises to any poor programmer that tries to use
        # this code
        circleGeomNode.setAttrib(CullFaceAttrib.makeReverse(), 1)
        global numPrimitives
        numPrimitives += numVertices * 2

        nodePath.attachNewNode(circleGeomNode)
Beispiel #13
0
    def __init__(self):
        ShowBase.__init__(self)
        winProps = WindowProperties()
        winProps.setTitle("Triangle and SimpleCircle Unittest")
        # base.win.requestProperties(winProps) (same as below e.g. self == base)
        self.win.requestProperties(winProps)


        zUp = Vec3(0.0, 0.0, 1.0)
        wt = Vec4(1.0, 1.0, 1.0, 1.0)

        def addToVertex(x, y, z):
            normal.addData3f(zUp)
            color.addData4f(wt)
        # BLOG post about these bullet points then delete them
        # 1) create GeomVertexData (inside the triangulator's constructor)
        frmt = GeomVertexFormat.getV3n3cp()
        triangulator = ConstrainedDelaunayTriangulator(vertexFormat = frmt, onVertexCreationCallback = addToVertex)
        vdata = triangulator.getGeomVertexData()

        # 2) create Writers/Rewriters (must all be created before any readers and readers are one-pass-temporary)
        normal = GeomVertexRewriter(vdata, 'normal')  # DOC 'vertex' is the only prohibited column for the user to use
        color = GeomVertexRewriter(vdata, 'color')

        # 3) write each column on the vertex data object (for speed, have a different writer for each column)

        # DOC 1.DT) create triangulator
        # DOC 2.DT) add vertices (before calling triangulate)
        # ############# NOT ANGLE OPTIMAL BELOW #####################
        # triangulator.addVertexToPolygon(5.0, 0.0, 0.0)
        # triangulator.addVertexToPolygon(0.0, 0.0, 0.0)
        # triangulator.addVertexToPolygon(1.5, 2.5, 0.0)
        # triangulator.addVertexToPolygon(0.0, 5.0, 0.0)
        # triangulator.addVertexToPolygon(5.0, 5.0, 0.0)
        # ############# NOT ANGLE OPTIMAL ABOVE #####################
        triangulator.addVertexToPolygon(5.0, 0.0, 0.0)
        triangulator.addVertexToPolygon(6.5, 6.5, 0.0)
        # triangulator.addVertexToPolygon(1.5, 2.5, 0.0)
        triangulator.addVertexToPolygon(0.0, 0.0, 0.0)
        triangulator.addVertexToPolygon(0.0, 5.0, 0.0)
        triangulator.addVertexToPolygon(5.0, 5.0, 0.0)

        # DOC 3.DT) add hole vertices (before calling triangulate)

        # DOC 4.DT) call triangulate
        triangulator.triangulate(makeDelaunay=True)
        # ######################## REMOVE ###################################

        # ######################## REMOVE ###################################
        assert triangulator.isTriangulated()
        adjLst = triangulator.getAdjacencyList()
        foundInvalidReference = []
        foundMissingReference = []  # so I can explicitly state all index references are correct

        for t in adjLst:
            # check that references with no neighbor haven't missed an edge
            noneEdges = []
            if t._neighbor0 is None:
                noneEdges.append(t.edgeIndices0)
            elif t._neighbor1 is None:
                noneEdges.append(t.edgeIndices1)
            elif t._neighbor2 is None:
                noneEdges.append(t.edgeIndices2)

            for tri_ in adjLst:
                for edge_ in noneEdges:
                    # the edge that should hold the reference is on t. The one that should get referenced is on tri_
                    missedCount = 0
                    if edge_[0] in tri_.edgeIndices0 and edge_[1] in tri_.edgeIndices0 and tri_ != t:
                        missedCount += 1
                    if edge_[0] in tri_.edgeIndices1 and edge_[1] in tri_.edgeIndices1 and tri_ != t:
                        missedCount += 1
                    if edge_[0] in tri_.edgeIndices2 and edge_[1] in tri_.edgeIndices2 and tri_ != t:
                        missedCount += 1
                    if missedCount == 1:
                        foundMissingReference.extend((t, tri_))
                        notify.warning(
                            "!MISSED REFERENCE TO NEIGHBOR\nreferrer: {} ptIndices: {} neighbors: {}\n".format(
                                t.index, t.getPointIndices(), t.getNeighbors(),
                            ) + "missed: {} ptIndices: {} neighbors: {}".format(
                                tri_.index, tri_.getPointIndices(), tri_.getNeighbors(),
                        ))
                    elif missedCount > 1:
                        foundMissingReference.extend((t, tri_))
                        notify.warning(
                            "!EXTRANEOUS & MISSED SHARED EDGES\nreferrer: {} ptIndices: {} neighbors: {}\n".format(
                                t.index, t.getPointIndices(), t.getNeighbors(),
                            ) + "missed: {} ptIndices: {} neighbors: {}".format(
                                tri_.index, tri_.getPointIndices(), tri_.getNeighbors(),
                        ))

            # check that neighbor relations point to correct triangles
            for n in t.getNeighbors(includeEmpties=False):
                neighbor = adjLst[n]
                otherInds = neighbor.getPointIndices()
                if neighbor.index == t._neighbor0:
                    edge = t.edgeIndices0
                elif neighbor.index == t._neighbor1:
                    edge = t.edgeIndices1
                elif neighbor.index == t._neighbor2:
                    edge = t.edgeIndices2
                if edge[0] not in otherInds and edge[1] not in otherInds:
                    foundInvalidReference.extend((t, neighbor))
                    notify.warning(
                        "!INVALID REFERENCE TO NEIGHBOR\nreferrer: {} indices: {} neighbors: {}".format(
                            t.index, t.getPointIndices(), t.getNeighbors(),
                        ) + "\nreferee: {} indices: {} neighbors: {}".format(
                            neighbor.index, neighbor.getPointIndices(), neighbor.getNeighbors()
                    ))

        if not foundMissingReference:
            notify.warning("No error missing reference in neighbors.")
        else:
            notify.warning("!!!ERROR missing reference in neighbor references.")

        if not foundInvalidReference:
            notify.warning("No error found in neighbors that were referenced.")
        else:
            notify.warning("!!!ERROR found in neighbors that were referenced.")

        foundPointInsideCircle = False
        trianglesWithInvalidPoint = set()
        for t in adjLst:
            circle_ = t.getCircumcircle()
            # cycle through triangles checking each point against each circle.center
            for e in adjLst:
                p0, p1, p2 = e.getPoints()

                if circle_.radius - (p0 - circle_.center).length() > EPSILON:
                    foundPointInsideCircle = True
                    notify.warning(
                        "!point in circumcircle point {0} circle {1}\ntriangle1: {2}\ntriangle2: {3}".format(
                            p0, circle_, t, e
                    ))
                    trianglesWithInvalidPoint |= set((t.index, ))

                if circle_.radius - (p1 - circle_.center).length() > EPSILON:
                    foundPointInsideCircle = True
                    notify.warning(
                        "!point in circumcircle point {0} circle {1}\ntriangle1: {2}\ntriangle2: {3}".format(
                            p1, circle_, t, e
                    ))
                    trianglesWithInvalidPoint |= set((t.index, ))

                if circle_.radius - (p2 - circle_.center).length() > EPSILON:
                    foundPointInsideCircle = True
                    notify.warning(
                        "!point in circumcircle point {0} circle {1}\ntriangle1: {2}\ntriangle2: {3}".format(
                            p2, circle_, t, e
                    ))
                    trianglesWithInvalidPoint |= set((t.index, ))
        if not foundPointInsideCircle:
            notify.warning("No point found inside circumcircle.")
        else:
            notify.warning("!!!ERROR found point inside circumcircle. Triangles: {}".format(trianglesWithInvalidPoint))
        # TODO test edges that reference no neighbor
        # triangles = triangulator.getGeomTriangles()
        # print "Triangulated:"
        # for tri in triangleList:
        #     print "\t{0}".format(tri)

        # 4) create a primitive and add the vertices via index (not truly associated with the actual vertex table, yet)
        # tris = GeomTriangles(Geom.UHDynamic)
        # t1 = Triangle(0, 1, 2, vdata, tris, vertex)
        # t2 = Triangle(2, 1, 3, vdata, tris, vertex)
        # c1 = t1.getCircumcircle()
        # t1AsEnum = t1.asPointsEnum()
        # r0 = (t1AsEnum.point0 - c1.center).length()
        # r1 = (t1AsEnum.point1 - c1.center).length()
        # r2 = (t1AsEnum.point2 - c1.center).length()
        # assert abs(r0 - r2) < utilities.EPSILON and abs(r0 - r1) < utilities.EPSILON
        # t2AsEnum = t2.asPointsEnum()
        # c2 = t2.getCircumcircle()
        # r0 = (t2AsEnum.point0 - c2.center).length()
        # r1 = (t2AsEnum.point1 - c2.center).length()
        # r2 = (t2AsEnum.point2 - c2.center).length()
        # assert abs(r0 - r2) < utilities.EPSILON and abs(r0 - r1) < utilities.EPSILON

        # assert t1.getAngleDeg0() == 90.0
        # assert t1.getAngleDeg1() == t1.getAngleDeg2()
        #
        # oldInd0 = t1.pointIndex0
        # oldInd1 = t1.pointIndex1
        # oldInd2 = t1.pointIndex2
        # t1.pointIndex0 = t1.pointIndex1
        # t1.pointIndex1 = oldInd0
        # assert t1.pointIndex0 == oldInd1
        # assert t1.pointIndex1 == oldInd0
        # assert t1.pointIndex0 != t1.pointIndex1
        # t1.reverse()
        # assert t1.pointIndex1 == oldInd2
        #
        gn = triangulator.getGeomNode('triangles')
        gnNodePath = render.attachNewNode(gn)

        # setup a wire frame
        wireNP = render.attachNewNode('wire')
        wireNP.setPos(0.0, 0.0, .1)
        wireNP.setColor(0.1, 0.1, 0.1, 1)
        wireNP.setRenderMode(RenderModeAttrib.MWireframe, .5, 0)
        gnNodePath.instanceTo(wireNP)
        #
        # # test and draw intersections and circles
        # pt1 = Point3(0.0, 5.0, 0.0)
        # pt2 = Point3(1.0, 5.0, 0.0)
        # intersection = t2.getIntersectionsWithCircumcircle(pt1, pt2)
        # circle = t2.getCircumcircle()
        # cuts = 128
        # border = circle.getBorder(cuts, closed=True)
        # assert len(border) == cuts or (len(border) == cuts + 1 and border[0] == border[len(border) - 1])
        # n = len(border)
        # xMid = yMid = 0
        # for p in border:
        #     xMid += p.x
        #     yMid += p.y
        # mid = Point3(xMid / n, yMid / n, border[0].z)
        # assert mid.almostEqual(circle.center, 0.06)
        # assert t2.isLeftWinding()
        # assert t1.containsPoint(c1.center) != t1.containsPoint(c1.center, includeEdges=False)
        #
        # circleSegs = LineSegs("circleLines")
        # circleSegs.setColor(1.0, 0.0, 0.0, 1.0)
        # for p in border:
        #     circleSegs.drawTo(*p)
        # circleNode = circleSegs.create(False)
        # circleNP = render.attachNewNode(circleNode)
        # circleNP.setZ(-5)
        #
        # originSpot = LineSegs("intersection")
        # originSpot.setColor(1.0, 0.0, 0.0, 1.0)
        # originSpot.setThickness(10)
        # for p in intersection:
        #     originSpot.drawTo(p)
        # spotNode = originSpot.create(False)
        # spotNP = render.attachNewNode(spotNode)
        # circleNP.setZ(-0.75)

        # fix the camera rot/pos
        PHF.PanditorDisableMouseFunc()
        camera.setPos(0.0, 0.0, 50.0)
        camera.lookAt(Point3(0.0))  # 2.5, 2.5, 0.0))
        PHF.PanditorEnableMouseFunc()

        # print "isLeftWinding()", triangulator.isLeftWinding()
        # TODO port the triangle-indices node func drawTriangleIndices(...)
        indsNp = ConstrainedDelaunayTriangulator.drawTriangleIndices(triangulator.getTriangleList())
        indsNp.setPos(0.0, 0.0, 0.3)
Beispiel #14
0
 def wave(self, task):
     # Compute physic
     step_np1 = self.water_physic()
     self.H += 0.1 * (np.mean(step_np1) - self.H)
     # render wave
     vertex = GeomVertexRewriter(self.water_vdata, 'vertex')
     normal = GeomVertexRewriter(self.water_vdata, 'normal')
     for j in range(0, self.n_points, self.details):
         for i in range(0, self.n_points, self.details):
             self.wz[j][i] = step_np1[j // self.details][i // self.details]
             v = vertex.getData3f()
             if j != 0 and i != 0 and j != self.n_points - self.details and \
                                         i != self.n_points - self.details:
                 vertex.setData3f(v[0], v[1], self.wz[j][i])
                 n = np.array([v[0], v[1], self.wz[j][i]])
             else:
                 vertex.setData3f(v[0], v[1], self.H)
                 n = np.array([v[0], v[1], self.H])
             norm = n / np.linalg.norm(n)
             normal.setData3f(norm[0], norm[1], norm[2])
     # Extend Water Borders
     vertex = GeomVertexRewriter(self.water_border_vdata, 'vertex')
     normal = GeomVertexRewriter(self.water_border_vdata, 'normal')
     for i in range(0, 8, 2):
         v = vertex.getData3f()
         vertex.setData3f(v[0], v[1], self.H)
         n = np.array([v[0], v[1], self.H])
         norm = n / np.linalg.norm(n)
         normal.setData3f(norm[0], norm[1], norm[2])
         v = vertex.getData3f()
         vertex.setData3f(v[0], v[1], 0)
         n = np.array([v[0], v[1], 1e-12])
         norm = n / np.linalg.norm(n)
         normal.setData3f(norm[0], norm[1], norm[2])
     # handle last puddles
     self.handle_last_puddles()
     return task.cont
Beispiel #15
0
    def drawBody(self,
                 pos,
                 quat,
                 radius=1,
                 UVcoord=(1, 1),
                 numVertices=_polySize):
        #        if isRoot:
        #            self.bodydata = GeomVertexData("body vertices", GeomVertexFormat.getV3n3t2(), Geom.UHStatic)
        vdata = self.bodydata
        circleGeom = Geom(
            vdata
        )  # this was originally a copy of all previous geom in vdata...
        vertWriter = GeomVertexWriter(vdata, "vertex")
        #colorWriter = GeomVertexWriter(vdata, "color")
        normalWriter = GeomVertexWriter(vdata, "normal")
        #        drawReWriter = GeomVertexRewriter(vdata, "drawFlag")
        texReWriter = GeomVertexRewriter(vdata, "texcoord")

        startRow = vdata.getNumRows()
        vertWriter.setRow(startRow)
        #colorWriter.setRow(startRow)
        normalWriter.setRow(startRow)
        texReWriter.setRow(startRow)

        #axisAdj=Mat4.rotateMat(45, axis)*Mat4.scaleMat(radius)*Mat4.translateMat(pos)
        perp1 = quat.getRight()
        perp2 = quat.getForward()

        #TODO: PROPERLY IMPLEMENT RADIAL NOISE
        #vertex information is written here
        angleSlice = 2 * pi / numVertices
        currAngle = 0
        for i in xrange(numVertices + 1):
            adjCircle = pos + (perp1 * cos(currAngle) +
                               perp2 * sin(currAngle)) * radius * (
                                   .5 + bNodeRadNoise * random.random())
            normal = perp1 * cos(currAngle) + perp2 * sin(currAngle)

            normalWriter.addData3f(normal)
            vertWriter.addData3f(adjCircle)
            texReWriter.addData2f(
                float(UVcoord[0] * i) / numVertices,
                UVcoord[1])  # UV SCALE HERE!
            #colorWriter.addData4f(0.5, 0.5, 0.5, 1)
            currAngle += angleSlice

        #we cant draw quads directly so we use Tristrips
        if (startRow != 0):
            lines = GeomTristrips(Geom.UHStatic)
            for i in xrange(numVertices + 1):
                lines.addVertex(i + startRow)
                lines.addVertex(i + startRow - numVertices - 1)
            lines.addVertex(startRow)
            lines.addVertex(startRow - numVertices)
            lines.closePrimitive()
            #lines.decompose()
            circleGeom.addPrimitive(lines)
            circleGeomNode = GeomNode("Debug")
            circleGeomNode.addGeom(circleGeom)
            self.numPrimitives += numVertices * 2
            self.bodies.attachNewNode(circleGeomNode)
            return circleGeomNode
    def movePmTo(self, dest_index):
        geom = self.geomPath.node().modifyGeom(0)
        vertdata = geom.modifyVertexData()
        prim = geom.modifyPrimitive(0)
        indexdata = prim.modifyVertices()
        
        indexrewriter = GeomVertexRewriter(indexdata)
        indexrewriter.setColumn(0)
        nextTriangleIndex = indexdata.getNumRows()
        
        vertwriter = GeomVertexWriter(vertdata, 'vertex')
        numverts = vertdata.getNumRows()
        vertwriter.setRow(numverts)
        normalwriter = GeomVertexWriter(vertdata, 'normal')
        normalwriter.setRow(numverts)
        uvwriter = GeomVertexWriter(vertdata, 'texcoord')
        uvwriter.setRow(numverts)
        
        while self.pm_index < dest_index:
            for op_index in range(len(self.pm_refinements[self.pm_index])):
                vals = self.pm_refinements[self.pm_index][op_index]
                op = vals[0]
                if op == PM_OP.TRIANGLE_ADDITION:
                    indexrewriter.setRow(nextTriangleIndex)
                    nextTriangleIndex += 3
                    indexrewriter.addData1i(vals[1])
                    indexrewriter.addData1i(vals[2])
                    indexrewriter.addData1i(vals[3])
                elif op == PM_OP.INDEX_UPDATE:
                    #TODO: ugly workaround for p3d 1.7 bug, change to below for 1.8
                    indexreader = GeomVertexReader(indexdata)
                    indexreader.setColumn(0)
                    indexreader.setRow(vals[1])
                    oldval = indexreader.getData1i()
                    del indexreader
                    
                    #indexrewriter.setRow(vals[1])
                    #oldval = indexrewriter.getData1i()
                    
                    indexrewriter.setRow(vals[1])
                    indexrewriter.setData1i(vals[2])
                    self.pm_refinements[self.pm_index][op_index] = (op, vals[1], oldval)
                elif op == PM_OP.VERTEX_ADDITION:
                    numverts += 1
                    vertwriter.addData3f(vals[1], vals[2], vals[3])
                    normalwriter.addData3f(vals[4], vals[5], vals[6])
                    uvwriter.addData2f(vals[7], vals[8])
                
            self.pm_index += 1

        while self.pm_index > dest_index:
            self.pm_index -= 1
            for op_index in range(len(self.pm_refinements[self.pm_index])):
                vals = self.pm_refinements[self.pm_index][op_index]
                op = vals[0]
                if op == PM_OP.TRIANGLE_ADDITION:
                    nextTriangleIndex -= 3
                elif op == PM_OP.INDEX_UPDATE:
                    #TODO: ugly workaround for p3d 1.7 bug, change to below for 1.8
                    indexreader = GeomVertexReader(indexdata)
                    indexreader.setColumn(0)
                    indexreader.setRow(vals[1])
                    oldval = indexreader.getData1i()
                    del indexreader
                    
                    #indexrewriter.setRow(vals[1])
                    #oldval = indexrewriter.getData1i()
                    
                    indexrewriter.setRow(vals[1])
                    indexrewriter.setData1i(vals[2])
                    self.pm_refinements[self.pm_index][op_index] = (op, vals[1], oldval)
                elif op == PM_OP.VERTEX_ADDITION:
                    numverts -= 1

        if nextTriangleIndex < indexdata.getNumRows():
            indexdata.setNumRows(nextTriangleIndex)
        if numverts < vertdata.getNumRows():
            vertdata.setNumRows(numverts)
Beispiel #17
0
    def movePmTo(self, dest_index):
        geom = self.geomPath.node().modifyGeom(0)
        vertdata = geom.modifyVertexData()
        prim = geom.modifyPrimitive(0)
        indexdata = prim.modifyVertices()

        indexrewriter = GeomVertexRewriter(indexdata)
        indexrewriter.setColumn(0)
        nextTriangleIndex = indexdata.getNumRows()

        vertwriter = GeomVertexWriter(vertdata, 'vertex')
        numverts = vertdata.getNumRows()
        vertwriter.setRow(numverts)
        normalwriter = GeomVertexWriter(vertdata, 'normal')
        normalwriter.setRow(numverts)
        uvwriter = GeomVertexWriter(vertdata, 'texcoord')
        uvwriter.setRow(numverts)

        while self.pm_index < dest_index:
            for op_index in range(len(self.pm_refinements[self.pm_index])):
                vals = self.pm_refinements[self.pm_index][op_index]
                op = vals[0]
                if op == PM_OP.TRIANGLE_ADDITION:
                    indexrewriter.setRow(nextTriangleIndex)
                    nextTriangleIndex += 3
                    indexrewriter.addData1i(vals[1])
                    indexrewriter.addData1i(vals[2])
                    indexrewriter.addData1i(vals[3])
                elif op == PM_OP.INDEX_UPDATE:
                    #TODO: ugly workaround for p3d 1.7 bug, change to below for 1.8
                    indexreader = GeomVertexReader(indexdata)
                    indexreader.setColumn(0)
                    indexreader.setRow(vals[1])
                    oldval = indexreader.getData1i()
                    del indexreader

                    #indexrewriter.setRow(vals[1])
                    #oldval = indexrewriter.getData1i()

                    indexrewriter.setRow(vals[1])
                    indexrewriter.setData1i(vals[2])
                    self.pm_refinements[self.pm_index][op_index] = (op,
                                                                    vals[1],
                                                                    oldval)
                elif op == PM_OP.VERTEX_ADDITION:
                    numverts += 1
                    vertwriter.addData3f(vals[1], vals[2], vals[3])
                    normalwriter.addData3f(vals[4], vals[5], vals[6])
                    uvwriter.addData2f(vals[7], vals[8])

            self.pm_index += 1

        while self.pm_index > dest_index:
            self.pm_index -= 1
            for op_index in range(len(self.pm_refinements[self.pm_index])):
                vals = self.pm_refinements[self.pm_index][op_index]
                op = vals[0]
                if op == PM_OP.TRIANGLE_ADDITION:
                    nextTriangleIndex -= 3
                elif op == PM_OP.INDEX_UPDATE:
                    #TODO: ugly workaround for p3d 1.7 bug, change to below for 1.8
                    indexreader = GeomVertexReader(indexdata)
                    indexreader.setColumn(0)
                    indexreader.setRow(vals[1])
                    oldval = indexreader.getData1i()
                    del indexreader

                    #indexrewriter.setRow(vals[1])
                    #oldval = indexrewriter.getData1i()

                    indexrewriter.setRow(vals[1])
                    indexrewriter.setData1i(vals[2])
                    self.pm_refinements[self.pm_index][op_index] = (op,
                                                                    vals[1],
                                                                    oldval)
                elif op == PM_OP.VERTEX_ADDITION:
                    numverts -= 1

        if nextTriangleIndex < indexdata.getNumRows():
            indexdata.setNumRows(nextTriangleIndex)
        if numverts < vertdata.getNumRows():
            vertdata.setNumRows(numverts)
Beispiel #18
0
    def draw_water_mesh(self):
        _format = GeomVertexFormat.get_v3n3cp()
        self.water_vdata = GeomVertexData('water', _format, Geom.UHDynamic)
        self.water_vdata.setNumRows((self.n_points // self.details)**2)
        vertex = GeomVertexWriter(self.water_vdata, 'vertex')
        normal = GeomVertexWriter(self.water_vdata, 'normal')
        color = GeomVertexWriter(self.water_vdata, 'color')

        for j in range(0, self.n_points, self.details):
            for i in range(0, self.n_points, self.details):
                if j == self.n_points - self.details:
                    j = self.n_points - 1
                if i == self.n_points - self.details:
                    i = self.n_points - 1
                # Water Vertices
                vertex.addData3f(self.x[j][i], self.y[j][i], self.wz[j][i])
                # Water Color
                color.addData4f(0.3, 0.3, 1, 0.8)
                # water Normals
                n = np.array([self.x[j][i], self.y[j][i], self.wz[j][i]])
                norm = n / np.linalg.norm(n)
                normal.addData3f(norm[0], norm[1], norm[2])
        # Water Primitive
        prim = GeomTriangles(Geom.UHDynamic)
        for j in range(self.n_points // self.details):
            for i in range(self.n_points // self.details):
                if j != (self.n_points // self.details) - 1 and i != (
                        self.n_points // self.details) - 1:
                    prim.add_vertices(
                        j * (self.n_points // self.details) + i,
                        j * (self.n_points // self.details) + (i + 1),
                        (j + 1) * (self.n_points // self.details) + i)
                    prim.add_vertices(
                        j * (self.n_points // self.details) + (i + 1),
                        (j + 1) * (self.n_points // self.details) + (i + 1),
                        (j + 1) * (self.n_points // self.details) + i)
        geom = Geom(self.water_vdata)
        prim.closePrimitive()
        geom.addPrimitive(prim)
        node = GeomNode('gnode')
        node.addGeom(geom)
        water_nodePath = render.attachNewNode(node)
        water_nodePath.setTransparency(TransparencyAttrib.MAlpha)
        water_nodePath.setAntialias(AntialiasAttrib.MAuto)
        water_nodePath.setPos(-50, -50, 0)

        # Border
        self.water_border_vdata = GeomVertexData('water_border', _format,
                                                 Geom.UHDynamic)
        self.water_border_vdata.setNumRows(8)
        vertex = GeomVertexWriter(self.water_border_vdata, 'vertex')
        normal = GeomVertexRewriter(self.water_border_vdata, 'normal')
        color = GeomVertexWriter(self.water_border_vdata, 'color')
        for i in [0, 99]:
            for j in range(1, -1, -1):
                # Borders Vertices
                vertex.addData3f(i, 0, j)
                # Borders Colors
                color.addData4f(0.3, 0.3, 1, 0.8)
                # Borders Normals
                n = np.array([i, 0, 1e-12 if j == 0 else 1])
                norm = n / np.linalg.norm(n)
                normal.addData3f(norm[0], norm[1], norm[2])
        for i in [99, 0]:
            for j in range(1, -1, -1):
                vertex.addData3f(i, 99, j)
                color.addData4f(0.3, 0.3, 1, 0.8)
                n = np.array([i, 99, 1e-12 if j == 0 else 1])
                norm = n / np.linalg.norm(n)
                normal.addData3f(norm[0], norm[1], norm[2])
        # Borders Primitive
        prim = GeomTriangles(Geom.UHDynamic)
        for i in range(0, 8, 2):
            prim.add_vertices(i, i+1 if i+1 < 8 else i+1-8, \
                i+2 if i+2 < 8 else i+2-8)
            prim.add_vertices(i+2 if i+2 < 8 else i+2-8, \
                i+1 if i+1 < 8 else i+1-8, i+3 if i+3 < 8 else i+3-8)
        geom = Geom(self.water_border_vdata)
        geom.addPrimitive(prim)
        node = GeomNode('gnode')
        node.addGeom(geom)
        water_border_nodePath = render.attachNewNode(node)
        water_border_nodePath.setTransparency(TransparencyAttrib.MAlpha)
        water_border_nodePath.setAntialias(AntialiasAttrib.MAuto)
        water_border_nodePath.setPos(-50, -50, 0)
Beispiel #19
0
 def flood(self, task=None):
     # Animate Water Surface
     step_np1 = self.water_physic()
     vertex = GeomVertexRewriter(self.water_vdata, 'vertex')
     normal = GeomVertexRewriter(self.water_vdata, 'normal')
     for j in range(0, self.n_points, self.details):
         for i in range(0, self.n_points, self.details):
             # Flood
             if j != 0 and i != 0 and j != self.n_points - self.details and \
                                     i != self.n_points - self.details:
                 self.wz[j][i] = step_np1[j // self.details][i //
                                                             self.details]
             else:
                 self.wz[j][i] = self.H  # borders condition
             v = vertex.getData3f()
             vertex.setData3f(v[0], v[1], self.wz[j][i])
             n = np.array([v[0], v[1], self.wz[j][i]])
             norm = n / np.linalg.norm(n)
             normal.setData3f(norm[0], norm[1], norm[2])
     # Extend Water Borders
     vertex = GeomVertexRewriter(self.water_border_vdata, 'vertex')
     normal = GeomVertexRewriter(self.water_border_vdata, 'normal')
     for i in range(0, 8, 2):
         v = vertex.getData3f()
         vertex.setData3f(v[0], v[1], self.H)
         n = np.array([v[0], v[1], self.H])
         norm = n / np.linalg.norm(n)
         normal.setData3f(norm[0], norm[1], norm[2])
         v = vertex.getData3f()
         vertex.setData3f(v[0], v[1], 0)
         n = np.array([v[0], v[1], 1e-12])
         norm = n / np.linalg.norm(n)
         normal.setData3f(norm[0], norm[1], norm[2])
     # animate level
     if self.flooding == True and self.flush == False and self.H < self.n_points:
         self.H += self.dt
     elif self.flush == True and self.H > 1:
         self.H -= self.dt
         # handle last puddles
         #self.handle_last_puddles()
     if task:
         return task.cont
Beispiel #20
0
def drawBody(nodePath,
             vdata,
             pos,
             vecList,
             radius=1,
             keepDrawing=True,
             numVertices=8):

    circleGeom = Geom(vdata)

    vertWriter = GeomVertexWriter(vdata, "vertex")
    colorWriter = GeomVertexWriter(vdata, "color")
    normalWriter = GeomVertexWriter(vdata, "normal")
    drawReWriter = GeomVertexRewriter(vdata, "drawFlag")
    texReWriter = GeomVertexRewriter(vdata, "texcoord")

    startRow = vdata.getNumRows()
    vertWriter.setRow(startRow)
    colorWriter.setRow(startRow)
    normalWriter.setRow(startRow)

    sCoord = 0

    if (startRow != 0):
        texReWriter.setRow(startRow - numVertices)
        sCoord = texReWriter.getData2f().getX() + 1

        drawReWriter.setRow(startRow - numVertices)
        if (drawReWriter.getData1f() == False):
            sCoord -= 1

    drawReWriter.setRow(startRow)
    texReWriter.setRow(startRow)

    angleSlice = 2 * math.pi / numVertices
    currAngle = 0

    #axisAdj=LMatrix4.rotateMat(45, axis)*LMatrix4.scaleMat(radius)*LMatrix4.translateMat(pos)

    perp1 = vecList[1]
    perp2 = vecList[2]

    # vertex information is written here
    for i in range(numVertices):
        adjCircle = pos + \
            (perp1 * math.cos(currAngle) + perp2 * math.sin(currAngle)) * \
            radius
        normal = perp1 * math.cos(currAngle) + perp2 * math.sin(currAngle)
        normalWriter.addData3f(normal)
        vertWriter.addData3f(adjCircle)
        texReWriter.addData2f(sCoord, (i + 0.001) / (numVertices - 1))
        colorWriter.addData4f(0.5, 0.5, 0.5, 1)
        drawReWriter.addData1f(keepDrawing)
        currAngle += angleSlice

    if startRow == 0:
        return

    drawReader = GeomVertexReader(vdata, "drawFlag")
    drawReader.setRow(startRow - numVertices)

    # we cant draw quads directly so we use Tristrips
    if drawReader.getData1i() != 0:
        lines = GeomTristrips(Geom.UHStatic)
        half = int(numVertices * 0.5)
        for i in range(numVertices):
            lines.addVertex(i + startRow)
            if i < half:
                lines.addVertex(i + startRow - half)
            else:
                lines.addVertex(i + startRow - half - numVertices)

        lines.addVertex(startRow)
        lines.addVertex(startRow - half)
        lines.closePrimitive()
        lines.decompose()
        circleGeom.addPrimitive(lines)

        circleGeomNode = GeomNode("Debug")
        circleGeomNode.addGeom(circleGeom)

        # I accidentally made the front-face face inwards. Make reverse makes the tree render properly and
        # should cause any surprises to any poor programmer that tries to use
        # this code
        circleGeomNode.setAttrib(CullFaceAttrib.makeReverse(), 1)
        global numPrimitives
        numPrimitives += numVertices * 2

        nodePath.attachNewNode(circleGeomNode)
class ConstrainedDelaunayTriangulator(object):
    """Creates a Constrained Delaunay Triangulation"""
    @staticmethod
    def drawTriangleIndices(adjLst, name='indsgroup'):
        from direct.gui.OnscreenText import OnscreenText
        indNP = render.attachNewNode(name)
        for i in range(0, len(adjLst)):
            center = getCenterOfPoints3D(adjLst[i].getPoints())
            dummy = indNP.attachNewNode(str(i))
            txt = OnscreenText(text=str(i), pos=center, scale=1)
            txt.reparentTo(dummy)
            dummy.setP(dummy.getP() - 90)

        return indNP

    @staticmethod
    def findContainingTriangle(point, startTriangle, fullList):
        triangles = collections.deque([])
        triangles.append(startTriangle)
        while triangles:
            tri = triangles.popleft()
            if tri.containsPoint(point):
                return tri
            triangles.extend([fullList[i] for i in tri.getNeighbors(includeEmpties=False)])
        raise ValueError("Point added that's outside of the bounded space {0}".format(point))

    def __init__(self, vertexName='ConstrainedDelaunayTriangles', vertexFormat=GeomVertexFormat.getV3(),
                  usage = Geom.UHDynamic, onVertexCreationCallback = None, universalZ = 0.0):
        self._vertexData = GeomVertexData(vertexName, vertexFormat, Geom.UHDynamic)
        self._geomTriangles = GeomTriangles(usage)
        self._geomTrianglesHoles = GeomTriangles(usage)
        self._vertexRewriter = GeomVertexRewriter(self._vertexData, 'vertex')  # user cannot have control of a writer

        if onVertexCreationCallback is None:
            onVertexCreationCallback = lambda x, y, z: None  # something to call without checking existence later
        self._vertexCallback = onVertexCreationCallback

        self._universalZ = universalZ
        self.__holes = [[]]
        self.__polygon = []
        inf = float('inf')
        negInf = float('-inf')
        self.bounds = {
            'minX': inf,
            'maxX': negInf,
            'minY': inf,
            'maxY': negInf,
        }
        self.lastStaticVertexIndex = -1

    def addHoleVertex(self, index):
        """Adds the next consecutive vertex of the current hole."""
        # we might not have holes but we should always have triangles after triangulation
        self.__holes[-1].append(index)

    def addPolygonVertex(self, index):
        """Adds the next consecutive vertex of the polygon."""
        self.__polygon.append(index)

    def _addVertex(self, x, y, z, bounded=True):
        # BLOG track bounds to create the encapsulating triangle rather than lexicographic ordering
        # BLOG could have used a heap while adding verts, then popped as we processed each vertex
        if x < self.bounds['minX'] and bounded:
            self.bounds['minX'] = x
        if x > self.bounds['maxX'] and bounded:
            self.bounds['maxX'] = x

        if y < self.bounds['minY'] and bounded:
            self.bounds['minY'] = y
        if y > self.bounds['maxY'] and bounded:
            self.bounds['maxY'] = y
        if not self._vertexRewriter.isAtEnd():
            self._vertexRewriter.setRow(self._vertexData.getNumRows())
        n = self._vertexRewriter.getWriteRow()
        self._vertexRewriter.addData3f(x, y, self._universalZ)
        self._vertexCallback(x, y, self._universalZ)

        return n

    def addVertex(self, pointOrX, y=None, z=None, bounded=True):
        """Adds a new vertex to the vertex pool."""
        if hasattr(pointOrX, 'y'):  # if the first argument is a point expand and call the backing function
            return self._addVertex(pointOrX.x, pointOrX.y, pointOrX.z, bounded=bounded)
        return self._addVertex(pointOrX, y, z, bounded=bounded)

    def addVertexToPolygon(self, pointOrX, y, z, bounded=True):
        """Adds a vertex to the pool and then adds its index to the polygon vertex index list."""
        n = self.addVertex(pointOrX, y, z, bounded=bounded)
        self.addPolygonVertex(n)
        return n

    def addVertexToHole(self, pointOrX, y, z):
        """Adds a vertex to the pool and then adds its index to the polygon vertex index list."""
        n = self.addVertex(pointOrX, y, z)
        self.addHoleVertex(n)
        return n
    
    def beginHole(self):
        """Finishes the previous hole, if any, and prepares to add a new hole."""
        if self.__holes[-1]:  # if the last hole (list of vertices) is empty use it as the next hole
            self.__holes.append([])  # if it's not empty append a new hole
    
    def clear(self):
        """Removes all vertices and polygon specifications from the Triangulator, and prepares it to start over."""
        raise NotImplementedError("""ConstrainedDelaunayTriangulator.clear() is not implemented.""")
    
    def clearPolygon(self):
        """Removes the current polygon definition (and its set of holes), but does not clear the vertex pool."""
        raise NotImplementedError("""ConstrainedDelaunayTriangulator.clearPolygon() is not implemented.""")

    def getAdjacencyList(self):
        """Returns a list of triangles, each referencing its own neighbors by their list index."""
        return self.__polygon

    def getGeomNode(self, name='ConstrainedDelaunayTriangles'):
        """returns a GeomNode, with the provided name, sufficient to put in the scene and draw."""
        # BLOG My TODO legend
        # DOC 1) (adding to scene) create a Geom and add primitives of like base-type i.e. triangles and triangle strips
        geom = Geom(self._vertexData)
        geom.addPrimitive(self._geomTriangles)
        # DOC 2) create a GeomNode to hold the Geom(s) and add the Geom(s)
        gn = GeomNode(name)
        gn.addGeom(geom)
        # DOC 3) attach the node to the scene (in the calling code)
        # gnNodePath = render.attachNewNode(gn)
        return gn
    
    def getNumTriangles(self):
        """Returns the number of triangles generated by the previous call to triangulate()."""
        if not self.isTriangulated():
            raise ValueError("Vertices must be added and triangulate() must be called before calling getNumTriangles()")
        return len(self.__polygon)
    
    def getNumVertices(self):
        """Returns the number of vertices in the pool."""
        return self._vertexData.getNumRows()

    def getVertexReader(self):
        """Returns a reader for the vertex column."""
        return GeomVertexReader(self._vertexData, 'vertex')
    
    def getTriangleV0(self, n):
        """Returns vertex 0 of the nth triangle generated by the previous call to triangulate()."""
        try:
            return self.__polygon[n].pointIndex0()
        except AttributeError:  # BLOG switching errors to clarify the cause
            raise LookupError("Must call triangulate() before querying for a triangle's vertices.")
    
    def getTriangleV1(self, n):
        """Returns vertex 1 of the nth triangle generated by the previous call to triangulate()."""
        try:
            return self.__polygon[n].pointIndex1()
        except AttributeError:  # BLOG switching errors to clarify the cause
            raise LookupError("Must call triangulate() before querying for a triangle's vertices.")
    
    def getTriangleV2(self, n):
        """Returns vertex 2 of the nth triangle generated by the previous call to triangulate()."""
        try:
            return self.__polygon[n].pointIndex2()
        except AttributeError:  # BLOG switching errors to clarify the cause
            raise LookupError("Must call triangulate() before querying for a triangle's vertices.")

    def getTriangleList(self):
        import copy
        return copy.copy(self.__polygon)

    def getVertex(self, n):
        """Returns the nth vertex."""
        self._vertexRewriter.setRow(n)
        return self._vertexRewriter.getData3f()

    def getGeomVertexData(self):
        return self._vertexData

    def getGeomTriangles(self):
        assert self.isTriangulated()
        return self._geomTriangles
    
    def getVertices(self):
        """Returns a list of vertices."""
        verts = []
        for i in range(0, self._vertexData.getNumRows()):
            self._vertexRewriter.setRow(i)
            verts.append(self._vertexRewriter.getData3f())
        return verts
    
    def isLeftWinding(self):
        """Returns true if the polygon vertices are listed in counterclockwise order,
        or false if they appear to be listed in clockwise order."""
        assert self.isTriangulated()
        return self.__polygon[0].isLeftWinding()

    def isTriangulated(self):
        """Guesses whether the polygon has been triangulated."""
        return len(self.__polygon) > 0 and isinstance(self.__polygon[0], ConstrainedDelaunayAdjacencyTriangle)
    
    def triangulate(self, makeDelaunay=True):
        """Does the work of triangulating the specified polygon."""
        global notify
        if self.isTriangulated():
            raise ValueError("triangulate() must only be called once.")
        notify.warning("bounds: minX, minY, maxX, maxY {0} {1} {2} {3}".format(self.bounds['minX'], self.bounds['minY'],
                                                                               self.bounds['maxX'], self.bounds['maxY']))
        h = abs(self.bounds['maxY'] - self.bounds['minY'])
        w = abs(self.bounds['maxX'] - self.bounds['minX'])
        topLeft = Point3(self.bounds['minX'] - 10*w,
                         self.bounds['maxY'] + 10*h,
                         self._universalZ)
        bottomRight = Point3(self.bounds['minX'] - 10*w,
                            self.bounds['minY'] - 10*h,
                            self._universalZ)
        farRight = Point3(self.bounds['maxX'] + 10*w, (self.bounds['maxY'] + self.bounds['minY'])/2, self._universalZ)
        # Other than the tree below, any vertices added after this are CDT as opposed to DT
        self.lastStaticVertexIndex = self.getNumVertices() - 1
        # these three will be removed later, thus will not be artificial restraints
        v0 = self.addVertex(topLeft, bounded=False)
        v1 = self.addVertex(bottomRight, bounded=False)
        v2 = self.addVertex(farRight, bounded=False)
        bounds = ConstrainedDelaunayAdjacencyTriangle(v0, v1, v2,
                                                      self._vertexData, self._geomTriangles, self._vertexRewriter)
        triangulated = [bounds]

        while True:
            try:
                pt = self.__polygon.pop()
            except IndexError:
                break
            self._vertexRewriter.setRow(pt)
            point = self._vertexRewriter.getData3f()
            notify.warning("\n######################## len {} TRIANGULATE {} ###########################\n".format(len(triangulated), point))
            notify.warning("\n########################## SO FAR\n{}\n############################\n".format([tr.index for tr in triangulated]))
            # find the triangle the point lays within
            found = ConstrainedDelaunayTriangulator.findContainingTriangle(point, bounds, triangulated)
            if found is not None:
                # BLOG heapq.merge() is useless as it returns an iterable which can't be indexed, but heaps require lists
                # BLOG Hence, it's probably faster to heap.push than to iterate (in C) a merge then iterate to recreate a list
                # BLOG if I use a heap
                # triangulate the point into the triangle, collecting any new triangles
                newTriangles = found.triangulatePoint(pt, triangulated)
                triangulated.extend(newTriangles)
                if makeDelaunay:
                    for tri in newTriangles:
                        tri.legalize(tri.point0, triangulated)  # point, triangulated)
                        tri.legalize(tri.point1, triangulated)
                        tri.legalize(tri.point2, triangulated)
            else:
                raise ValueError("Point given that's outside of original space.")
        notify.warning("triangulated: length: {} type: {}".format(len(triangulated), type(triangulated)))
        self.__polygon = triangulated