Example #1
1
def triangulate(vertices):
    t = Triangulator()
    for i, v in enumerate(vertices):
        t.add_vertex(v)
        t.add_polygon_vertex(i)

    t.triangulate()

    # Make sure that the result is consistent by starting each triangle with
    # the lowest index value.  That makes it easier to use predetermined values
    # in the test cases.
    result = set()

    for n in range(t.get_num_triangles()):
        # Switch to lowest matching index value in case of duplicates.
        v0 = vertices.index(vertices[t.get_triangle_v0(n)])
        v1 = vertices.index(vertices[t.get_triangle_v1(n)])
        v2 = vertices.index(vertices[t.get_triangle_v2(n)])
        if v1 < v0:
            v0, v1, v2 = v1, v2, v0
        if v1 < v0:
            v0, v1, v2 = v1, v2, v0
        result.add((v0, v1, v2))

    return result
Example #2
0
def getTriangulatorGeomData(pointList, normalVec):
	"""
	takes a list of points and a normal vector,
	gets the corresponding triangulated polygon,
	returns a dict with the data of that triangulated polygon :
	data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []}
	"""
	data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []}
	#prim = GeomTriangles(Geom.UHStatic)
	trig = Triangulator()
	#vdata = GeomVertexData('trig', GeomVertexFormat.getV3n3c4t2(), Geom.UHStatic)
	#vwriter = GeomVertexWriter(vdata, 'vertex')
	#nvwriter = GeomVertexWriter(vdata, 'normal')
	#tvwriter = GeomVertexWriter(vdata, 'texcoord')
	
	for x, y, z in pointList:
		vi = trig.addVertex(x, y)
		#vwriter.addData3f(x, y, z)
		data["vertices"].append(Point3(x, y, z))
		#nvwriter.addData3f(normalVec)
		data["normals"].append(normalVec)
		#tvwriter.addData2f(x,y)
		data["texcoords"].append(Point2(x, y))
		trig.addPolygonVertex(vi)
		#print "added vertex vi = %s" % (vi)
	try:
		trig.triangulate()
	except:
		return None
	
	#prim = GeomTriangles(Geom.UHStatic)
	for i in range(trig.getNumTriangles()):
		A, B, C = trig.getTriangleV0(i), trig.getTriangleV1(i), trig.getTriangleV2(i)
		#print "triangle %s : %s, %s, %s" % (i, A, B, C)
		
		
		if normalVec[2]<0:
			#prim.addVertices(A, B, C)
			data["prims"].append((A, B, C))
		else:
			#prim.addVertices(A, C, B)
			data["prims"].append((A, C, B))
		
		
		#prim.closePrimitive()
	
	return data
Example #3
0
 def makeNode(self, pointmap=(lambda x, y: (x, y, 0))):
     vt = tuple(self.vertices)
     t = Triangulator()
     fmt = GeomVertexFormat.getV3()
     vdata = GeomVertexData('name', fmt, Geom.UHStatic)
     vertex = GeomVertexWriter(vdata, 'vertex')
     for x, y in vt:
         t.addPolygonVertex(t.addVertex(x, y))
         vertex.addData3f(pointmap(x, y))
     t.triangulate()
     prim = GeomTriangles(Geom.UHStatic)
     for n in xrange(t.getNumTriangles()):
         prim.addVertices(t.getTriangleV0(n),t.getTriangleV1(n),t.getTriangleV2(n))
     prim.closePrimitive()
     geom = Geom(vdata)
     geom.addPrimitive(prim)
     node = GeomNode('gnode')
     node.addGeom(geom)
     return node
Example #4
0
def create_GeomNode_Simple_Polygon_without_Hole(symbol_geometries):

    color_vec4 = Vec4(1., 1., 1., 1.)

    outerpolygon_contour_points = 0.1 * symbol_geometries[0][0]
    # inner_hole_contour_points = 0.1 * symbol_geometries[0][1]

    # outerpolygon_contour_points = (
    #     np.array([[0, 1], [-1, 0], [0, -1], [1, 0]], dtype=np.float64))

    # inner_hole_contour_points = (
    #     0.5 * np.array([[0, 1], [-1, 0], [0, -1], [1, 0]], dtype=np.float64))

    from panda3d.core import Triangulator, LPoint2d
    
    tr = Triangulator()

    for vertex in outerpolygon_contour_points: 
        vi = tr.addVertex(vertex[0], vertex[1])
        tr.addPolygonVertex(vi)

    # tr.beginHole()
    # for vertex in inner_hole_contour_points:
    #     vi = tr.addVertex(vertex[0], vertex[1])
    #     tr.addHoleVertex(vi)

    tr.triangulate()
    
    vertices = tr.getVertices()

    indices = []
    num_triangles = tr.getNumTriangles()
    for i in range(num_triangles):
        indices.append([tr.getTriangleV0(i), tr.getTriangleV1(i), tr.getTriangleV2(i)])

    # Own Geometry

    # format = GeomVertexFormat.getV3c4t2()
    format = GeomVertexFormat.getV3c4()
    vdata = GeomVertexData("colored_polygon", format, Geom.UHStatic)
    vdata.setNumRows(4)
    
    # let's also add color to each vertex
    colorWriter = GeomVertexWriter(vdata, "color")
    vertexPosWriter = GeomVertexWriter(vdata, "vertex")

    for v in vertices: 
        vertexPosWriter.addData3f(v[0], 0, v[1])
        colorWriter.addData4f(color_vec4)

    # make primitives and assign vertices to them (primitives and primitive
    # groups can be made independently from vdata, and are later assigned
    # to vdata)
    tris = GeomTriangles(Geom.UHStatic) 
    

    for index_triple in indices: 
        tris.addVertices(index_triple[0], index_triple[1], index_triple[2])

    tris.closePrimitive()

    # make a Geom object to hold the primitives
    polygonGeom = Geom(vdata)  # vdata contains the vertex position/color/... buffers
    polygonGeom.addPrimitive(tris)  # tris contains the index buffer

    # now put quadGeom in a GeomNode. You can now position your geometry
    # in the scene graph.
    polygonGeomNode = GeomNode("colored_polygon_node")
    polygonGeomNode.addGeom(polygonGeom)

    return polygonGeomNode
Example #5
0
def create_GeomNode_Simple_Polygon_with_Hole(symbol_geometries):

    color_vec4 = Vec4(1., 1., 1., 1.)

    outerpolygon_contour_points = 0.1 * symbol_geometries[0][0]
    inner_hole_contour_points = 0.1 * symbol_geometries[0][1]


    from itertools import groupby

    inner_hole_contour_points = [k for k,g in groupby(inner_hole_contour_points.tolist())]
    # inner_hole_contour_points.append(inner_hole_contour_points[0])
    inner_hole_contour_points = np.array(inner_hole_contour_points)[:-1]
    outerpolygon_contour_points = [k for k,g in groupby(outerpolygon_contour_points.tolist())]
    # outerpolygon_contour_points.append(outerpolygon_contour_points[0])
    outerpolygon_contour_points = np.array(outerpolygon_contour_points)[:-1]

    # remove consecutive doubles in contour 

    # outerpolygon_contour_points = inner_hole_contour_points

    # outerpolygon_contour_points = (
    #     np.array([[0, 1], [-1, 0], [0, -1], [1, 0]], dtype=np.float64))

    # inner_hole_contour_points = (
    #     0.5 * np.array([[0, 1], [-1, 0], [0, -1], [1, 0]], dtype=np.float64))

    
    tr = Triangulator()

    # very simple triangular hole
    # v1 = np.array([ 
    #     np.amax(outerpolygon_contour_points[:, 0]), 
    #     np.amax(outerpolygon_contour_points[:, 1]), 
    # ]) + np.array([-0.2, -0.15]) 
    # v2 = v1 + np.array([-0.05, -0.05])
    # v3 = v1 + np.array([0.0, -0.05])
    # inner_hole_contour_points = [v1, v2, v3]

    for vertex in outerpolygon_contour_points: 
        vi = tr.addVertex(vertex[0], vertex[1])
        tr.addPolygonVertex(vi)

    tr.beginHole()
    for vertex in inner_hole_contour_points:
        vi = tr.addVertex(vertex[0], vertex[1])
        tr.addHoleVertex(vi)


    tr.triangulate()
    
    vertices = tr.getVertices()

    indices = []
    num_triangles = tr.getNumTriangles()
    for i in range(num_triangles):
        indices.append([tr.getTriangleV0(i), tr.getTriangleV1(i), tr.getTriangleV2(i)])

    # Own Geometry

    # format = GeomVertexFormat.getV3c4t2()
    format = GeomVertexFormat.getV3c4()
    vdata = GeomVertexData("colored_polygon", format, Geom.UHStatic)
    vdata.setNumRows(4)
    
    # let's also add color to each vertex
    colorWriter = GeomVertexWriter(vdata, "color")
    vertexPosWriter = GeomVertexWriter(vdata, "vertex")

    for v in vertices: 
        vertexPosWriter.addData3f(v[0], 0, v[1])
        colorWriter.addData4f(color_vec4)

    # make primitives and assign vertices to them (primitives and primitive
    # groups can be made independently from vdata, and are later assigned
    # to vdata)
    tris = GeomTriangles(Geom.UHStatic) 

    for index_triple in indices: 
        tris.addVertices(index_triple[0], index_triple[1], index_triple[2])

    tris.closePrimitive()

    # make a Geom object to hold the primitives
    geom = Geom(vdata)  # vdata contains the vertex position/color/... buffers
    geom.addPrimitive(tris)  # tris contains the index buffer

    # now put geom in a GeomNode
    geom_node = GeomNode("colored_polygon_node")
    geom_node.addGeom(geom)

    return geom_node
Example #6
0
    def reconstruct(self):
        trianglator = Triangulator()

        #Add vertices to the trianglator
        for vertex in self.vertices:
            trianglator.addPolygonVertex(trianglator.addVertex(vertex))

        trianglator.triangulate()

        #Prepare to create the primative
        self.vdata = GeomVertexData('floor', GeomVertexFormat.getV3n3cpt2(),
                                    Geom.UHStatic)
        vertexW = GeomVertexWriter(self.vdata, 'vertex')
        normalW = GeomVertexWriter(self.vdata, 'normal')
        colorW = GeomVertexWriter(self.vdata, 'color')
        texcoordW = GeomVertexWriter(self.vdata, 'texcoord')

        #Add vertices to the primative
        i = 0
        while i < trianglator.getNumVertices():
            vertex = trianglator.getVertex(i)
            vertexW.addData3f(vertex.x, vertex.y, 0.0)
            normalW.addData3f(0, 0, 1)
            colorW.addData4f(0.1, 0.1, 0.1, 0.5)
            texcoordW.addData2f(0.0, 1.0)
            i += 1

        self.geom = Geom(self.vdata)

        #Add triangles to the primative
        i = 0
        print(trianglator.getNumTriangles())
        while i < trianglator.getNumTriangles():
            tri = GeomTriangles(Geom.UHStatic)
            tri.addVertices(trianglator.getTriangleV0(i),
                            trianglator.getTriangleV1(i),
                            trianglator.getTriangleV2(i))
            tri.closePrimitive()
            self.geom.addPrimitive(tri)
            i += 1

        self.addGeom(self.geom)
Example #7
0
    def create_geom_node(self):
        xyzero = False

        i = 0
        for i, x in enumerate(self.normal):
            if x == 1:
                xyzero = True
                break

        # vt=tuple(self.vertices)

        t = Triangulator()
        fmt = GeomVertexFormat.getV3cp()
        vdata = GeomVertexData('name', fmt, Geom.UHStatic)
        vertex = GeomVertexWriter(vdata, 'vertex')
        _ = GeomVertexWriter(vdata, 'color')

        for point in self._vertices:
            (x, y, z) = point
            v = (x, y)
            if not xyzero:
                v = (x, y)
            elif i == 0:
                v = (y, z)
            elif i == 1:
                v = (x, z)
            elif i == 2:
                v = (x, y)

            t.addPolygonVertex(t.addVertex(*v))
            vertex.addData3f(x, y, z)
        t.triangulate()
        prim = GeomTriangles(Geom.UHStatic)

        for n in range(t.getNumTriangles()):
            prim.addVertices(t.getTriangleV0(n), t.getTriangleV1(n),
                             t.getTriangleV2(n))

        prim.closePrimitive()
        geom = Geom(vdata)
        geom.addPrimitive(prim)
        node = GeomNode('gnode')
        node.addGeom(geom)

        return node
Example #8
0
def create_plane_mesh(vertices, vertices_floor, textures, texture_floor, texture_ceiling,
    delta_height, ignore_ceiling=False):
    # create mesh for 3D floorplan visualization
    triangles = []
    triangle_uvs = []

    # the number of vertical walls
    num_walls = len(vertices)

    # 1. vertical wall (always rectangle)
    num_vertices = 0
    for i in range(len(vertices)):
        # hardcode triangles for each vertical wall
        triangle = np.array([[0, 2, 1], [2, 0, 3]])
        triangles.append(triangle + num_vertices)
        num_vertices += 4

        triangle_uv = np.array(
            [
                [i / (num_walls + 2), 0], 
                [i / (num_walls + 2), 1], 
                [(i+1) / (num_walls + 2), 1], 
                [(i+1) / (num_walls + 2), 0]
            ],
            dtype=np.float32
        )
        triangle_uvs.append(triangle_uv)

    # 2. floor and ceiling
    # Since the floor and ceiling may not be a rectangle, triangulate the polygon first.
    tri = Triangulator()
    for i in range(len(vertices_floor)):
        tri.add_vertex(vertices_floor[i, 0], vertices_floor[i, 1])

    for i in range(len(vertices_floor)):
        tri.add_polygon_vertex(i)

    tri.triangulate()

    # polygon triangulation
    triangle = []
    for i in range(tri.getNumTriangles()):
        triangle.append([tri.get_triangle_v0(i), tri.get_triangle_v1(i), tri.get_triangle_v2(i)])
    triangle = np.array(triangle)

    # add triangles for floor and ceiling
    triangles.append(triangle + num_vertices)
    num_vertices += len(np.unique(triangle))
    if not ignore_ceiling:
        triangles.append(triangle + num_vertices)

    # texture for floor and ceiling
    vertices_floor_min = np.min(vertices_floor[:, :2], axis=0)
    vertices_floor_max = np.max(vertices_floor[:, :2], axis=0)
    
    # normalize to [0, 1]
    triangle_uv = (vertices_floor[:, :2] - vertices_floor_min) / (vertices_floor_max - vertices_floor_min)
    triangle_uv[:, 0] = (triangle_uv[:, 0] + num_walls) / (num_walls + 2) 

    triangle_uvs.append(triangle_uv)

    # normalize to [0, 1]
    triangle_uv = (vertices_floor[:, :2] - vertices_floor_min) / (vertices_floor_max - vertices_floor_min)
    triangle_uv[:, 0] = (triangle_uv[:, 0] + num_walls + 1) / (num_walls + 2)

    triangle_uvs.append(triangle_uv)

    # 3. Merge wall, floor, and ceiling
    vertices.append(vertices_floor)
    vertices.append(vertices_floor + delta_height)
    vertices = np.concatenate(vertices, axis=0)

    triangles = np.concatenate(triangles, axis=0)

    textures.append(texture_floor)
    textures.append(texture_ceiling)
    textures = np.concatenate(textures, axis=1)

    triangle_uvs = np.concatenate(triangle_uvs, axis=0)

    mesh = open3d.geometry.TriangleMesh(
        vertices=open3d.utility.Vector3dVector(vertices),
        triangles=open3d.utility.Vector3iVector(triangles)
    )
    mesh.compute_vertex_normals()

    mesh.texture = open3d.geometry.Image(textures)
    mesh.triangle_uvs = np.array(triangle_uvs[triangles.reshape(-1), :], dtype=np.float64)
    return mesh
Example #9
0
	def reconstruct(self):
		trianglator = Triangulator()

		#Add vertices to the trianglator
		for vertex in self.vertices:
			trianglator.addPolygonVertex(trianglator.addVertex(vertex))
		
		trianglator.triangulate()

		#Prepare to create the primative
		self.vdata = GeomVertexData('floor', GeomVertexFormat.getV3n3cpt2(), Geom.UHStatic)
		vertexW = GeomVertexWriter(self.vdata, 'vertex')
		normalW = GeomVertexWriter(self.vdata, 'normal')
		colorW = GeomVertexWriter(self.vdata, 'color')
		texcoordW = GeomVertexWriter(self.vdata, 'texcoord')

		#Add vertices to the primative
		i = 0
		while i < trianglator.getNumVertices():
			vertex = trianglator.getVertex(i)
			vertexW.addData3f(vertex.x,vertex.y,0.0)
			normalW.addData3f(0,0,1)
			colorW.addData4f(0.1,0.1,0.1,0.5)
			texcoordW.addData2f(0.0, 1.0)	
			i+=1

		self.geom = Geom(self.vdata)

		#Add triangles to the primative
		i = 0
		print(trianglator.getNumTriangles())
		while i < trianglator.getNumTriangles():
			tri = GeomTriangles(Geom.UHStatic)
			tri.addVertices(trianglator.getTriangleV0(i),trianglator.getTriangleV1(i),trianglator.getTriangleV2(i))
			tri.closePrimitive()
			self.geom.addPrimitive(tri)
			i+=1

		self.addGeom(self.geom)
Example #10
0
def triangulate_outer_polygon_with_hole_polygons(
        outerPolygonWithInnerHolePolygons):

    # TODO: this needs to be all changed, and support for holes needs to be
    # integrated
    tr = Triangulator()

    for vertex in outerPolygonWithInnerHolePolygons.outer_polygon.getVertices(
    ):
        vi = tr.addVertex(vertex[0], vertex[1])
        tr.addPolygonVertex(vi)

    for inner_hole_polygon in outerPolygonWithInnerHolePolygons.inner_hole_polygons:
        tr.beginHole()  # finish the last hole, and add to the next
        for vertex in inner_hole_polygon.getVertices():
            vi = tr.addVertex(vertex[0], vertex[1])
            tr.addHoleVertex(vi)

    # tr.beginHole()  # finish the last hole?
    tr.triangulate()

    # --- BEGIN getting the triangles vertices and indices ----

    def get_vertices_and_indices_from_p3d_triangulated_object(tr):

        # first linear array of triangle points
        triangles_indices = np.array([])
        num_triangles = tr.getNumTriangles()
        for i in range(num_triangles):
            triangle = np.array([])
            # 2d vertices
            triangle = np.append(triangle, tr.getTriangleV0(i))
            triangle = np.append(triangle, tr.getTriangleV1(i))
            triangles_indices = np.append(triangles_indices, triangle)

        # reshape it
        triangles_indices = np.reshape(triangles_indices, (-1, 2))
        triangles_indices = np.array(triangles_indices, np.int32)

        # print(tr.isLeftWinding())
        # print(tr.getNumTriangles())
        # print(tr.getNumVertices())

        # return all vertices and indices needed to create a GeomPrimitive

        vertices = tr.getVertices()
        return vertices, triangles_indices

    return get_vertices_and_indices_from_p3d_triangulated_object(tr)
Example #11
0
def makeTriMesh( verts, holeVerts=[[]]):
    pointmap = (lambda x, y: (x, y, 0))
    if not hasattr(holeVerts[0], '__iter__'):
        holeVerts = [holeVerts]

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

    vertex = GeomVertexWriter(vdata, 'vertex')
    normal = GeomVertexWriter(vdata, 'normal')
    color = GeomVertexWriter(vdata, 'color')

    bl = Vec4(50, 50, 50, 255)
    gr = Vec4(256/2 - 1, 256/2 - 1, 256/2 - 1, 255)

    trilator = Triangulator()
    zUp = Vec3(0, 0, 1)

    for i in verts:
        #print "verts", verts
        trilator.addPolygonVertex(trilator.addVertex(i.x, i.y))
        vertex.addData3f(pointmap(i.x, i.y))
        normal.addData3f(zUp)
        color.addData4f(bl)
    #if len(holeVerts) != 1 and holeVerts[0] != []:
    for w in holeVerts:
        trilator.beginHole()
        print "new hole"
        for j in w:
            # print(j)  # ###################### PRINT #######################
            trilator.addHoleVertex(trilator.addVertex(j.x, j.y))
            vertex.addData3f(pointmap(j.x, j.y))
            normal.addData3f(zUp)
            color.addData4f(gr)

    # try:
    trilator.triangulate()
    triVerts = trilator.getVertices()
    p = trilator.getTriangleV0(0)
    print "trilator return", p
    # except AssertionError:
    #     pass
    # TODO:re-triangulate here and change AdjacencyList to expect a list of triangles rather than call Triangulator funcs
    trilator = makeDelaunayTriangulation(trilator)


    prim = GeomTriangles(Geom.UHStatic)
    if isinstance(trilator, Triangulator):
        # HACK just to switch back and forth from the non-Delaunay to the Delaunay for school
        for n in xrange(trilator.getNumTriangles()):
            prim.addVertices(trilator.getTriangleV0(n),
                             trilator.getTriangleV1(n),
                             trilator.getTriangleV2(n))
    else:  # it's an adjacency list

        for n in xrange(len(trilator.adjLst)):
            for v in range(0, len(triVerts)):
                print "\ncurr", triVerts[v], "\nv0", Point2D(trilator.adjLst[n].tri[0].x, trilator.adjLst[n].tri[0].y),\
                    "\nv1", Point2D(trilator.adjLst[n].tri[1].x, trilator.adjLst[n].tri[1].y),\
                    "\nv2", Point2D(trilator.adjLst[n].tri[2].x, trilator.adjLst[n].tri[2].y)
                    # trilator.adjLst[n].tri[0].getXy(),\
                    # "\nv1", trilator.adjLst[n].tri[1].getXy(),\
                    # "\nv2", trilator.adjLst[n].tri[2].getXy()
                # v0 = v1 = v2 = -1
                if Point2D(trilator.adjLst[n].tri[0].x, trilator.adjLst[n].tri[0].y) == triVerts[v]:
                    v0 = v  # we need indices into the vertex pool
                    print "found v0", v0

                if Point2D(trilator.adjLst[n].tri[1].x, trilator.adjLst[n].tri[1].y) == triVerts[v]:
                    v1 = v
                    print "found v1", v1

                if Point2D(trilator.adjLst[n].tri[2].x, trilator.adjLst[n].tri[2].y) == triVerts[v]:
                    v2 = v
                    print "found v2", v2
            # if v0 == -1 or v1 == -1 or v2 == -1:
            #     print "pass", v0, v1, v2
            #     pass
            # else:
            #     print "add"

            # i = triVerts[v0]
            # vertex.addData3f(pointmap(i.x, i.y))
            # normal.addData3f(zUp)
            # color.addData4f(bl)
            # i = triVerts[v1]
            # vertex.addData3f(pointmap(i.x, i.y))
            # normal.addData3f(zUp)
            # color.addData4f(bl)
            # i = triVerts[v2]
            # vertex.addData3f(pointmap(i.x, i.y))
            # normal.addData3f(zUp)
            # color.addData4f(bl)
            print "v 1 2 3", v0, v1, v2
            prim.addVertices(v0, v1, v2)

    prim.closePrimitive()
    geom = Geom(vdata)
    geom.addPrimitive(prim)
    node = GeomNode('gnode')
    node.addGeom(geom)

    # print trilator.isLeftWinding()
    # HACK just for school
    if hasattr(trilator, "adLst"):
        return tuple((node, trilator.adjLst))
    else:
        return tuple((node, trilator))
Example #12
0
def getTriangulatorGeomData(pointList,
                            normalVec,
                            texScale=(1, 1),
                            color=(1, 1, 1, 1)):
    """
	takes a list of points and a normal vector,
	gets the corresponding triangulated polygon,
	returns a dict with the data of that triangulated polygon :
	data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []}
	"""
    data = {
        "prims": [],
        "vertices": [],
        "normals": [],
        "texcoords": [],
        "colors": []
    }
    normalVec = Vec3(normalVec)
    normalVec.normalize()
    u, v = texScale
    trig = Triangulator()

    for x, y, z in pointList:
        if normalVec[2] > 0:
            vi = trig.addVertex(x, y)
            data["texcoords"].append(Point2(x * u, y * u))
        elif normalVec[1] > 0:
            vi = trig.addVertex(x, z)
            data["texcoords"].append(Point2(x * u, z * u))
        else:
            vi = trig.addVertex(y, z)
            data["texcoords"].append(Point2(y * u, z * u))
        data["vertices"].append(Point3(x, y, z))
        data["normals"].append(normalVec)
        data["colors"].append(color)
        trig.addPolygonVertex(vi)

    trig.triangulate()

    for i in xrange(trig.getNumTriangles()):
        A, B, C = trig.getTriangleV0(i), trig.getTriangleV1(
            i), trig.getTriangleV2(i)
        data["prims"].append((A, B, C))
        #if normalVec[2]>0:
        #	data["prims"].append((A, B, C))
        #else:
        #	data["prims"].append((A, C, B))

    return data
Example #13
0
def getTriangulatorGeomData(pointList, normalVec):
    """
	takes a list of points and a normal vector,
	gets the corresponding triangulated polygon,
	returns a dict with the data of that triangulated polygon :
	data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []}
	"""
    data = {"prims": [], "vertices": [], "normals": [], "texcoords": []}
    #prim = GeomTriangles(Geom.UHStatic)
    trig = Triangulator()
    #vdata = GeomVertexData('trig', GeomVertexFormat.getV3n3c4t2(), Geom.UHStatic)
    #vwriter = GeomVertexWriter(vdata, 'vertex')
    #nvwriter = GeomVertexWriter(vdata, 'normal')
    #tvwriter = GeomVertexWriter(vdata, 'texcoord')

    for x, y, z in pointList:
        vi = trig.addVertex(x, y)
        #vwriter.addData3f(x, y, z)
        data["vertices"].append(Point3(x, y, z))
        #nvwriter.addData3f(normalVec)
        data["normals"].append(normalVec)
        #tvwriter.addData2f(x,y)
        data["texcoords"].append(Point2(x, y))
        trig.addPolygonVertex(vi)
        #print "added vertex vi = %s" % (vi)
    try:
        trig.triangulate()
    except:
        return None

    #prim = GeomTriangles(Geom.UHStatic)
    for i in range(trig.getNumTriangles()):
        A, B, C = trig.getTriangleV0(i), trig.getTriangleV1(
            i), trig.getTriangleV2(i)
        #print "triangle %s : %s, %s, %s" % (i, A, B, C)

        if normalVec[2] < 0:
            #prim.addVertices(A, B, C)
            data["prims"].append((A, B, C))
        else:
            #prim.addVertices(A, C, B)
            data["prims"].append((A, C, B))

        #prim.closePrimitive()

    return data
Example #14
0
def getTriangulatorGeomData(pointList, normalVec, texScale=(1,1), color=(1,1,1,1)):
	"""
	takes a list of points and a normal vector,
	gets the corresponding triangulated polygon,
	returns a dict with the data of that triangulated polygon :
	data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []}
	"""
	data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : [], "colors" : []}
	normalVec = Vec3(normalVec)
	normalVec.normalize()
	u, v = texScale
	trig = Triangulator()
	
	for x, y, z in pointList:
		if normalVec[2]>0:
			vi = trig.addVertex(x, y)
			data["texcoords"].append(Point2(x*u, y*u))
		elif normalVec[1]>0:
			vi = trig.addVertex(x, z)
			data["texcoords"].append(Point2(x*u, z*u))
		else:
			vi = trig.addVertex(y, z)
			data["texcoords"].append(Point2(y*u, z*u))
		data["vertices"].append(Point3(x, y, z))
		data["normals"].append(normalVec)
		data["colors"].append(color)
		trig.addPolygonVertex(vi)
	
	trig.triangulate()
	
	for i in xrange(trig.getNumTriangles()):
		A, B, C = trig.getTriangleV0(i), trig.getTriangleV1(i), trig.getTriangleV2(i)
		data["prims"].append((A, B, C))
		#if normalVec[2]>0:
		#	data["prims"].append((A, B, C))
		#else:
		#	data["prims"].append((A, C, B))
		
	return data
Example #15
0
    def __init__(self,
                 items,
                 parent=None,
                 buttonThrower=None,
                 onDestroy=None,
                 font=None,
                 baselineOffset=.0,
                 scale=.05,
                 itemHeight=1.,
                 leftPad=.0,
                 separatorHeight=.5,
                 underscoreThickness=1,
                 BGColor=(0, 0, 0, .7),
                 BGBorderColor=(1, .85, .4, 1),
                 separatorColor=(1, 1, 1, 1),
                 frameColorHover=(1, .85, .4, 1),
                 frameColorPress=(0, 1, 0, 1),
                 textColorReady=(1, 1, 1, 1),
                 textColorHover=(0, 0, 0, 1),
                 textColorPress=(0, 0, 0, 1),
                 textColorDisabled=(.5, .5, .5, 1),
                 minZ=None,
                 useMouseZ=True):
        '''
      items : a collection of menu items
         Item format :
            ( 'Item text', 'path/to/image', command )
                        OR
            ( 'Item text', 'path/to/image', command, arg1,arg2,.... )
         If you don't want to use an image, pass 0.

         To create disabled item, pass 0 for the command :
            ( 'Item text', 'path/to/image', 0 )
         so, you can easily switch between enabled or disabled :
            ( 'Item text', 'path/to/image', command if commandEnabled else 0 )
                        OR
            ( 'Item text', 'path/to/image', (0,command)[commandEnabled] )

         To create submenu, pass a sequence of submenu items for the command.
         To create disabled submenu, pass an empty sequence for the command.

         To enable hotkey, insert an underscore before the character,
         e.g. hotkey of 'Item te_xt' is 'x' key.

         To add shortcut key text at the right side of the item, append it at the end of
         the item text, separated by "more than" sign, e.g. 'Item text>Ctrl-T'.

         To insert separator line, pass 0 for the whole item.


      parent : where to attach the menu, defaults to aspect2d

      buttonThrower : button thrower whose thrown events are blocked temporarily
                      when the menu is displayed. If not given, the default
                      button thrower is used

      onDestroy : user function which will be called after the menu is fully destroyed
      
      font           : text font
      baselineOffset : text's baseline Z offset

      scale       : text scale
      itemHeight  : spacing between items, defaults to 1
      leftPad     : blank space width before text
      separatorHeight : separator line height, relative to itemHeight

      underscoreThickness : underscore line thickness

      BGColor, BGBorderColor, separatorColor, frameColorHover, frameColorPress,
      textColorReady, textColorHover, textColorPress, textColorDisabled
      are some of the menu components' color

      minZ : minimum Z position to restrain menu's bottom from going offscreen (-1..1).
             If it's None, it will be set a little above the screen's bottom.
      '''
        self.parent = parent if parent else aspect2d
        self.onDestroy = onDestroy
        self.BT = buttonThrower if buttonThrower else base.buttonThrowers[
            0].node()
        self.menu = NodePath('menu-%s' % id(self))
        self.parentMenu = None
        self.submenu = None
        self.BTprefix = self.menu.getName() + '>'
        self.submenuCreationTaskName = 'createSubMenu-' + self.BTprefix
        self.submenuRemovalTaskName = 'removeSubMenu-' + self.BTprefix
        self.font = font if font else TextNode.getDefaultFont()
        self.baselineOffset = baselineOffset
        if isinstance(scale, (float, int)):
            scale = (scale, 1.0, scale)
        self.scale = scale
        self.itemHeight = itemHeight
        self.leftPad = leftPad
        self.separatorHeight = separatorHeight
        self.underscoreThickness = underscoreThickness
        self.BGColor = BGColor
        self.BGBorderColor = BGBorderColor
        self.separatorColor = separatorColor
        self.frameColorHover = frameColorHover
        self.frameColorPress = frameColorPress
        self.textColorReady = textColorReady
        self.textColorHover = textColorHover
        self.textColorPress = textColorPress
        self.textColorDisabled = textColorDisabled
        self.minZ = minZ
        self.mpos = Point2(base.mouseWatcherNode.getMouse())

        self.itemCommand = []
        self.hotkeys = {}
        self.numItems = 0
        self.sel = -1
        self.selByKey = False

        bgPad = self.bgPad = .0125
        texMargin = self.font.getTextureMargin() * self.scale[0] * .25
        b = DirectButton(parent=NodePath(''),
                         text='^|g_',
                         text_font=self.font,
                         scale=self.scale)
        fr = b.node().getFrame()
        b.getParent().removeNode()
        baselineToCenter = (fr[2] + fr[3]) * self.scale[0]
        LH = (fr[3] - fr[2]) * self.itemHeight * self.scale[2]
        imageHalfHeight = .5 * (fr[3] - fr[2]) * self.itemHeight * .85
        arrowHalfHeight = .5 * (fr[3] - fr[2]) * self.itemHeight * .5
        baselineToTop = (fr[3] * self.itemHeight * self.scale[2] /
                         LH) / (1. + self.baselineOffset)
        baselineToBot = LH / self.scale[2] - baselineToTop
        itemZcenter = (baselineToTop - baselineToBot) * .5
        separatorHalfHeight = .5 * separatorHeight * LH
        LSseparator = LineSegs()
        LSseparator.setColor(.5, .5, .5, .2)

        arrowVtx = [
            (0, itemZcenter),
            (-2 * arrowHalfHeight, itemZcenter + arrowHalfHeight),
            (-arrowHalfHeight, itemZcenter),
            (-2 * arrowHalfHeight, itemZcenter - arrowHalfHeight),
        ]
        tri = Triangulator()
        vdata = GeomVertexData('trig', GeomVertexFormat.getV3(), Geom.UHStatic)
        vwriter = GeomVertexWriter(vdata, 'vertex')
        for x, z in arrowVtx:
            vi = tri.addVertex(x, z)
            vwriter.addData3f(x, 0, z)
            tri.addPolygonVertex(vi)
        tri.triangulate()
        prim = GeomTriangles(Geom.UHStatic)
        for i in range(tri.getNumTriangles()):
            prim.addVertices(tri.getTriangleV0(i), tri.getTriangleV1(i),
                             tri.getTriangleV2(i))
            prim.closePrimitive()
        geom = Geom(vdata)
        geom.addPrimitive(prim)
        geomNode = GeomNode('arrow')
        geomNode.addGeom(geom)
        realArrow = NodePath(geomNode)
        z = -baselineToTop * self.scale[2] - bgPad
        maxWidth = .1 / self.scale[0]
        shortcutTextMaxWidth = 0
        anyImage = False
        anyArrow = False
        anyShortcut = False
        arrows = []
        shortcutTexts = []
        loadPrcFileData('', 'text-flatten 0')
        for item in items:
            if item:
                t, imgPath, f = item[:3]
                haveSubmenu = type(f) in SEQUENCE_TYPES
                anyArrow |= haveSubmenu
                anyImage |= isinstance(imgPath, bool) or bool(imgPath)
                disabled = not len(f) if haveSubmenu else not callable(f)
                args = item[3:]
                underlinePos = t.find('_')
                t = t.replace('_', '')
                shortcutSepPos = t.find('>')
                if shortcutSepPos > -1:
                    if haveSubmenu:
                        print(
                            "\nA SHORTCUT KEY POINTING TO A SUBMENU IS NON-SENSE, DON'T YOU AGREE ?"
                        )
                    else:
                        shortcutText = NodePath(
                            OnscreenText(
                                parent=self.menu,
                                text=t[shortcutSepPos + 1:],
                                font=self.font,
                                scale=1,
                                fg=(1, 1, 1, 1),
                                align=TextNode.ARight,
                            ))
                        shortcutTextMaxWidth = max(
                            shortcutTextMaxWidth,
                            abs(shortcutText.getTightBounds()[0][0]))
                        anyShortcut = True
                    t = t[:shortcutSepPos]
                else:
                    shortcutText = ''
                EoLcount = t.count('\n')
                arrowZpos = -self.font.getLineHeight() * EoLcount * .5
                if disabled:
                    b = NodePath(
                        OnscreenText(
                            parent=self.menu,
                            text=t,
                            font=self.font,
                            scale=1,
                            fg=textColorDisabled,
                            align=TextNode.ALeft,
                        ))
                    # don't pass the scale and position to OnscreenText constructor,
                    # to maintain correctness between the OnscreenText and DirectButton items
                    # due to the new text generation implementation
                    b.setScale(self.scale)
                    b.setZ(z)
                    maxWidth = max(maxWidth,
                                   b.getTightBounds()[1][0] / self.scale[0])
                    if shortcutText:
                        shortcutText.reparentTo(b)
                        shortcutText.setColor(Vec4(*textColorDisabled), 1)
                        shortcutText.setZ(arrowZpos)
                        shortcutTexts.append(shortcutText)
                else:
                    b = DirectButton(
                        parent=self.menu,
                        text=t,
                        text_font=self.font,
                        scale=self.scale,
                        pos=(0, 0, z),
                        text_fg=textColorReady,
                        # text color when mouse over
                        text2_fg=textColorHover,
                        # text color when pressed
                        text1_fg=textColorHover
                        if haveSubmenu else textColorPress,
                        # framecolor when pressed
                        frameColor=frameColorHover
                        if haveSubmenu else frameColorPress,
                        commandButtons=[DGG.LMB, DGG.RMB],
                        command=(lambda: 0)
                        if haveSubmenu else self.__runCommand,
                        extraArgs=[] if haveSubmenu else [f, args],
                        text_align=TextNode.ALeft,
                        relief=DGG.FLAT,
                        rolloverSound=0,
                        clickSound=0,
                        pressEffect=0)
                    b.stateNodePath[2].setColor(
                        *frameColorHover)  # framecolor when mouse over
                    b.stateNodePath[0].setColor(0, 0, 0,
                                                0)  # framecolor when ready
                    bframe = Vec4(b.node().getFrame())
                    if EoLcount:
                        bframe.setZ(EoLcount * 10)
                        b['frameSize'] = bframe
                    maxWidth = max(maxWidth, bframe[1])
                    if shortcutText:
                        for snpi, col in ((0, textColorReady),
                                          (1, textColorPress),
                                          (2, textColorHover)):
                            sct = shortcutText.copyTo(b.stateNodePath[snpi],
                                                      sort=10)
                            sct.setColor(Vec4(*col), 1)
                            sct.setZ(arrowZpos)
                            shortcutTexts.append(sct)
                        shortcutText.removeNode()
                if isinstance(imgPath, bool):
                    if imgPath:
                        if disabled:
                            fg = textColorDisabled
                        else:
                            fg = textColorReady
                        tick = NodePath(
                            OnscreenText(
                                parent=b,
                                text=u"\u2714",
                                font=self.font,
                                scale=1,
                                fg=fg,
                                align=TextNode.ALeft,
                            ))
                        tick.setX(-2 * imageHalfHeight - leftPad)
                elif imgPath:
                    img = loader.loadTexture(imgPath, okMissing=True)
                    if img is not None:
                        if disabled:
                            if imgPath in PopupMenu.grayImages:
                                img = PopupMenu.grayImages[imgPath]
                            else:
                                pnm = PNMImage()
                                img.store(pnm)
                                pnm.makeGrayscale(.2, .2, .2)
                                img = Texture()
                                img.load(pnm)
                                PopupMenu.grayImages[imgPath] = img
                        img.setMinfilter(Texture.FTLinearMipmapLinear)
                        img.setWrapU(Texture.WMClamp)
                        img.setWrapV(Texture.WMClamp)
                        CM = CardMaker('')
                        CM.setFrame(-2 * imageHalfHeight - leftPad, -leftPad,
                                    itemZcenter - imageHalfHeight,
                                    itemZcenter + imageHalfHeight)
                        imgCard = b.attachNewNode(CM.generate())
                        imgCard.setTexture(img)
                if underlinePos > -1:
                    oneLineText = t[:underlinePos + 1]
                    oneLineText = oneLineText[oneLineText.rfind('\n') + 1:]
                    tn = TextNode('')
                    tn.setFont(self.font)
                    tn.setText(oneLineText)
                    tnp = NodePath(tn.getInternalGeom())
                    underlineXend = tnp.getTightBounds()[1][0]
                    tnp.removeNode()
                    tn.setText(t[underlinePos])
                    tnp = NodePath(tn.getInternalGeom())
                    b3 = tnp.getTightBounds()
                    underlineXstart = underlineXend - (b3[1] - b3[0])[0]
                    tnp.removeNode()
                    underlineZpos = -.7 * baselineToBot - self.font.getLineHeight(
                    ) * t[:underlinePos].count('\n')
                    LSunder = LineSegs()
                    LSunder.setThickness(underscoreThickness)
                    LSunder.moveTo(underlineXstart + texMargin, 0,
                                   underlineZpos)
                    LSunder.drawTo(underlineXend - texMargin, 0, underlineZpos)
                    if disabled:
                        underline = b.attachNewNode(LSunder.create())
                        underline.setColor(Vec4(*textColorDisabled), 1)
                    else:
                        underline = b.stateNodePath[0].attachNewNode(
                            LSunder.create())
                        underline.setColor(Vec4(*textColorReady), 1)
                        underline.copyTo(b.stateNodePath[1], 10).setColor(
                            Vec4(*textColorHover
                                 if haveSubmenu else textColorPress), 1)
                        underline.copyTo(b.stateNodePath[2],
                                         10).setColor(Vec4(*textColorHover), 1)
                        hotkey = t[underlinePos].lower()
                        if hotkey in self.hotkeys:
                            self.hotkeys[hotkey].append(self.numItems)
                        else:
                            self.hotkeys[hotkey] = [self.numItems]
                            self.accept(self.BTprefix + hotkey,
                                        self.__processHotkey, [hotkey])
                            self.accept(self.BTprefix + 'alt-' + hotkey,
                                        self.__processHotkey, [hotkey])
                if haveSubmenu:
                    if disabled:
                        arrow = realArrow.instanceUnderNode(b, '')
                        arrow.setColor(Vec4(*textColorDisabled), 1)
                        arrow.setZ(arrowZpos)
                    else:
                        arrow = realArrow.instanceUnderNode(
                            b.stateNodePath[0], 'r')
                        arrow.setColor(Vec4(*textColorReady), 1)
                        arrow.setZ(arrowZpos)
                        arrPress = realArrow.instanceUnderNode(
                            b.stateNodePath[1], 'p')
                        arrPress.setColor(Vec4(*textColorHover), 1)
                        arrPress.setZ(arrowZpos)
                        arrHover = realArrow.instanceUnderNode(
                            b.stateNodePath[2], 'h')
                        arrHover.setColor(Vec4(*textColorHover), 1)
                        arrHover.setZ(arrowZpos)
                        # weird, if sort order is 0, it's obscured by the frame
                        for a in (arrPress, arrHover):
                            a.reparentTo(a.getParent(), sort=10)
                if not disabled:
                    extraArgs = [self.numItems, f if haveSubmenu else 0]
                    self.accept(DGG.ENTER + b.guiId, self.__hoverOnItem,
                                extraArgs)
                    self.accept(DGG.EXIT + b.guiId, self.__offItem)
                    #~ self.itemCommand.append((None,0) if haveSubmenu else (f,args))
                    self.itemCommand.append((f, args))
                    if self.numItems == 0:
                        self.firstButtonIdx = int(b.guiId[2:])
                    self.numItems += 1
                z -= LH + self.font.getLineHeight() * self.scale[2] * EoLcount
            else:  # SEPARATOR LINE
                z += LH - separatorHalfHeight - baselineToBot * self.scale[2]
                LSseparator.moveTo(0, 0, z)
                LSseparator.drawTo(self.scale[0] * .5, 0, z)
                LSseparator.drawTo(self.scale[0], 0, z)
                z -= separatorHalfHeight + baselineToTop * self.scale[2]
        maxWidth += 7 * arrowHalfHeight * (
            anyArrow or anyShortcut) + .2 + shortcutTextMaxWidth
        arrowXpos = maxWidth - arrowHalfHeight
        realArrow.setX(arrowXpos)
        if anyImage:
            leftPad += 2 * imageHalfHeight + leftPad
        for sct in shortcutTexts:
            sct.setX(maxWidth - 2 * (arrowHalfHeight * anyArrow + .2))
        for c in asList(self.menu.findAllMatches('**/DirectButton*')):
            numLines = c.node().getFrame()[2]
            c.node().setFrame(
                Vec4(
                    -leftPad, maxWidth, -baselineToBot -
                    (numLines * .1 * self.itemHeight if numLines >= 10 else 0),
                    baselineToTop))
        loadPrcFileData('', 'text-flatten 1')

        try:
            minZ = self.menu.getChild(0).getRelativePoint(
                b, Point3(0, 0,
                          b.node().getFrame()[2]))[2]
        except:
            minZ = self.menu.getChild(0).getRelativePoint(
                self.menu, Point3(
                    0, 0,
                    b.getTightBounds()[0][2]))[2] - baselineToBot * .5
        try:
            top = self.menu.getChild(0).node().getFrame()[3]
        except:
            top = self.menu.getChild(0).getZ() + baselineToTop
        l, r, b, t = -leftPad - bgPad / self.scale[
            0], maxWidth + bgPad / self.scale[0], minZ - bgPad / self.scale[
                2], top + bgPad / self.scale[2]
        menuBG = DirectFrame(parent=self.menu.getChild(0),
                             frameSize=(l, r, b, t),
                             frameColor=BGColor,
                             state=DGG.NORMAL,
                             suppressMouse=1)
        menuBorder = self.menu.getChild(0).attachNewNode('border')
        borderVtx = (
            (l, 0, b),
            (l, 0, .5 * (b + t)),
            (l, 0, t),
            (.5 * (l + r), 0, t),
            (r, 0, t),
            (r, 0, .5 * (b + t)),
            (r, 0, b),
            (.5 * (l + r), 0, b),
            (l, 0, b),
        )
        LSborderBG = LineSegs()
        LSborderBG.setThickness(4)
        LSborderBG.setColor(0, 0, 0, .7)
        LSborderBG.moveTo(*(borderVtx[0]))
        for v in borderVtx[1:]:
            LSborderBG.drawTo(*v)
        # fills the gap at corners
        for v in range(0, 7, 2):
            LSborderBG.moveTo(*(borderVtx[v]))
        menuBorder.attachNewNode(LSborderBG.create())
        LSborder = LineSegs()
        LSborder.setThickness(2)
        LSborder.setColor(*BGBorderColor)
        LSborder.moveTo(*(borderVtx[0]))
        for v in borderVtx[1:]:
            LSborder.drawTo(*v)
        menuBorder.attachNewNode(LSborder.create())
        for v in range(1, 8, 2):
            LSborderBG.setVertexColor(v, Vec4(0, 0, 0, .1))
            LSborder.setVertexColor(v, Vec4(.3, .3, .3, .5))
        menuBorderB3 = menuBorder.getTightBounds()
        menuBorderDims = menuBorderB3[1] - menuBorderB3[0]
        menuBG.wrtReparentTo(self.menu, sort=-1)
        self.menu.reparentTo(self.parent)
        x = -menuBorderB3[0][0] * self.scale[0]
        for c in asList(self.menu.getChildren()):
            c.setX(x)
        self.maxWidth = maxWidth = menuBorderDims[0]
        self.height = menuBorderDims[2]
        maxWidthR2D = maxWidth * self.menu.getChild(0).getSx(render2d)
        separatorLines = self.menu.attachNewNode(LSseparator.create(), 10)
        separatorLines.setSx(maxWidth)
        for v in range(1, LSseparator.getNumVertices(), 3):
            LSseparator.setVertexColor(v, Vec4(*separatorColor))
        x = clamp(-.98, .98 - maxWidthR2D, self.mpos[0] - maxWidthR2D * .5)
        minZ = (-.98 if self.minZ is None else self.minZ)
        z = clamp(
            minZ +
            menuBorderDims[2] * self.scale[2] * self.parent.getSz(render2d),
            .98, self.mpos[1] if useMouseZ else -1000)
        self.menu.setPos(render2d, x, 0, z)
        self.menu.setTransparency(1)

        self.origBTprefix = self.BT.getPrefix()
        self.BT.setPrefix(self.BTprefix)
        self.accept(self.BTprefix + 'escape', self.destroy)
        for e in ('mouse1', 'mouse3'):
            self.accept(self.BTprefix + e, self.destroy, [True])
        self.accept(self.BTprefix + 'arrow_down', self.__nextItem)
        self.accept(self.BTprefix + 'arrow_down-repeat', self.__nextItem)
        self.accept(self.BTprefix + 'arrow_up', self.__prevItem)
        self.accept(self.BTprefix + 'arrow_up-repeat', self.__prevItem)
        self.accept(self.BTprefix + 'enter', self.__runSelItemCommand)
        self.accept(self.BTprefix + 'space', self.__runSelItemCommand)
Example #16
0
def makeTriMesh( verts, holeVerts=[[]]):
    pointmap = (lambda x, y: (x, y, 0))
    if not holeVerts:
        holeVerts = [[]]

    if not hasattr(holeVerts[0], '__iter__'):
        holeVerts = [holeVerts]

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

    vertex = GeomVertexWriter(vdata, 'vertex')
    normal = GeomVertexWriter(vdata, 'normal')
    color = GeomVertexWriter(vdata, 'color')

    bl = Vec4(50, 50, 50, 255)
    gr = Vec4(256/2 - 1, 256/2 - 1, 256/2 - 1, 255)

    trilator = Triangulator()
    zUp = Vec3(0, 0, 1)

    for i in verts:
        #print "verts", verts
        trilator.addPolygonVertex(trilator.addVertex(i.x, i.y))
        vertex.addData3f(pointmap(i.x, i.y))
        normal.addData3f(zUp)
        color.addData4f(bl)
    #if len(holeVerts) != 1 and holeVerts[0] != []:
    for w in holeVerts:
        trilator.beginHole()
        print "new hole"
        for j in w:
            # print(j)  # ###################### PRINT #######################
            trilator.addHoleVertex(trilator.addVertex(j.x, j.y))
            vertex.addData3f(pointmap(j.x, j.y))
            normal.addData3f(zUp)
            color.addData4f(gr)

    # try:
    trilator.triangulate()
    triVerts = trilator.getVertices()
    p = trilator.getTriangleV0(0)
    print "trilator return", p
    # except AssertionError:
    #     pass
    # TODO:re-triangulate here and change AdjacencyList to expect a list of triangles rather than call Triangulator funcs
    trilator = makeDelaunayTriangulation(trilator)


    prim = GeomTriangles(Geom.UHStatic)
    if isinstance(trilator, Triangulator):
        # HACK just to switch back and forth from the non-Delaunay to the Delaunay for school
        for n in xrange(trilator.getNumTriangles()):
            prim.addVertices(trilator.getTriangleV0(n),
                             trilator.getTriangleV1(n),
                             trilator.getTriangleV2(n))
    else:  # it's an adjacency list

        for n in xrange(len(trilator.adjLst)):
            for v in range(0, len(triVerts)):
                print "\ncurr", triVerts[v], "\nv0", Point2D(trilator.adjLst[n].tri[0].x, trilator.adjLst[n].tri[0].y),\
                    "\nv1", Point2D(trilator.adjLst[n].tri[1].x, trilator.adjLst[n].tri[1].y),\
                    "\nv2", Point2D(trilator.adjLst[n].tri[2].x, trilator.adjLst[n].tri[2].y)
                    # trilator.adjLst[n].tri[0].getXy(),\
                    # "\nv1", trilator.adjLst[n].tri[1].getXy(),\
                    # "\nv2", trilator.adjLst[n].tri[2].getXy()
                # v0 = v1 = v2 = -1
                if Point2D(trilator.adjLst[n].tri[0].x, trilator.adjLst[n].tri[0].y) == triVerts[v]:
                    v0 = v  # we need indices into the vertex pool
                    print "found v0", v0

                if Point2D(trilator.adjLst[n].tri[1].x, trilator.adjLst[n].tri[1].y) == triVerts[v]:
                    v1 = v
                    print "found v1", v1

                if Point2D(trilator.adjLst[n].tri[2].x, trilator.adjLst[n].tri[2].y) == triVerts[v]:
                    v2 = v
                    print "found v2", v2
            # if v0 == -1 or v1 == -1 or v2 == -1:
            #     print "pass", v0, v1, v2
            #     pass
            # else:
            #     print "add"

            # i = triVerts[v0]
            # vertex.addData3f(pointmap(i.x, i.y))
            # normal.addData3f(zUp)
            # color.addData4f(bl)
            # i = triVerts[v1]
            # vertex.addData3f(pointmap(i.x, i.y))
            # normal.addData3f(zUp)
            # color.addData4f(bl)
            # i = triVerts[v2]
            # vertex.addData3f(pointmap(i.x, i.y))
            # normal.addData3f(zUp)
            # color.addData4f(bl)
            print "v 1 2 3", v0, v1, v2
            prim.addVertices(v0, v1, v2)

    prim.closePrimitive()
    geom = Geom(vdata)
    geom.addPrimitive(prim)
    node = GeomNode('gnode')
    node.addGeom(geom)

    # print trilator.isLeftWinding()
    # HACK just for school
    if hasattr(trilator, "adLst"):
        return tuple((node, trilator.adjLst))
    else:
        return tuple((node, trilator))