def _parse_geom(cls, geom): primitive = geom.get_primitives()[0] vertex_data = geom.get_vertex_data() vertex_reader = GeomVertexReader(vertex_data, 'vertex') triangle_count = primitive.get_num_primitives() triangles = [] vertex_positions = {} # Get triangles and vertex positions for triangle_index in range(triangle_count): start_index = primitive.get_primitive_start(triangle_index) end_index = primitive.get_primitive_end(triangle_index) vertex_indices = [] for i in range(start_index, end_index): vertex_index = primitive.get_vertex(i) vertex_reader.set_row(vertex_index) vertex_position = Vector(vertex_reader.getData3f()) vertex_positions[vertex_index] = vertex_position.freeze() vertex_indices.append(vertex_index) triangles.append(tuple(vertex_indices)) triangles_to_neighbours = cls._build_neighbours(triangles) return cls._build_nodes(triangles_to_neighbours, vertex_positions)
def gen_polygons_cdnp(pdnp, name='cdnp_polygons', radius=.01): """ :param trimeshmodel: :param name: :param radius: TODO :return: author: weiwei date: 20210204 """ collision_node = CollisionNode(name) # counter = 0 for geom in pdnp.findAllMatches('**/+GeomNode'): geom_node = geom.node() for g in range(geom_node.getNumGeoms()): geom = geom_node.getGeom(g).decompose() vdata = geom.getVertexData() vreader = GeomVertexReader(vdata, 'vertex') for p in range(geom.getNumPrimitives()): prim = geom.getPrimitive(p) for p2 in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p2) e = prim.getPrimitiveEnd(p2) v = [] for vi in range(s, e): vreader.setRow(prim.getVertex(vi)) # TODO expand radius by moving along normal directions v.append(vreader.getData3f()) col_poly = CollisionPolygon(*v) collision_node.addSolid(col_poly) # print("polygon ", counter) # counter += 1 return collision_node
def completePath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() tris = self.triStrips.decompose() p = 0 vertexReader = GeomVertexReader(self.vertexData, "vertex") for i in range(tris.getNumPrimitives()): v0 = tris.getPrimitiveStart(i) ve = tris.getPrimitiveEnd(i) if v0 < ve: vertexReader.setRow(tris.getVertex(v0)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0 + 1)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(tris.getVertex(v0 + 2)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p, p + 1, p + 2) p += 3 self.floorCollNode.addSolid(floorMesh)
def _parse_geom(cls, geom): primitive = geom.get_primitives()[0] vertex_data = geom.get_vertex_data() vertex_reader = GeomVertexReader(vertex_data, 'vertex') triangle_count = primitive.get_num_primitives() triangles = [] vertex_positions = {} # Get triangles and vertex positions for triangle_index in range(triangle_count): start_index = primitive.get_primitive_start(triangle_index) end_index = primitive.get_primitive_end(triangle_index) vertex_indices = [] for i in range(start_index, end_index): vertex_index = primitive.get_vertex(i) vertex_reader.set_row(vertex_index) vertex_position = Vector(vertex_reader.getData3f()) vertex_positions[vertex_index] = vertex_position vertex_indices.append(vertex_index) triangles.append(tuple(vertex_indices)) triangles_to_neighbours = cls._build_neighbours(triangles) return cls._build_nodes(triangles_to_neighbours, vertex_positions)
def normals(self): vertex_reader = GeomVertexReader(self.vertex_data, 'normal') vertices = list() while not vertex_reader.isAtEnd(): v = vertex_reader.getData3f() v = Vec3(v[0], v[2], v[1]) vertices.append(v) return vertices
def make_nav_graph(self, mesh, edge_neighbors_only=True, draw_graph=False): '''Creates a navigation graph from a 3D mesh, A node is created for each triangle in the mesh, nodes are connected either by shared edges (edge_neighbors_only=True), or by shared vertex (edge_neighbors_only=False). ''' _get_center=self._get_center _get_neighbors=self._get_neighbors _distance=self._distance _round_vec3_to_tuple=self._round_vec3_to_tuple #make a list of the triangles #get the id of each vert in each triangle and #get the position of each vert triangles=[] vert_dict=defaultdict(set) #only works ok with one geom so flatten the mesh befor comming here geom=self.find_first_geom(mesh) vdata = geom.getVertexData() vertex = GeomVertexReader(vdata, 'vertex') for prim in geom.getPrimitives(): num_primitives=prim.getNumPrimitives() for p in range(num_primitives): #print ('primitive {} of {}'.format(p, num_primitives)) s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) triangle={'vertex_id':[], 'vertex_pos':[]} for i in range(s, e): vi = prim.getVertex(i) vertex.setRow(vi) v =[round(i, 4) for i in vertex.getData3f() ] vertex_id=tuple([round(i*4.0)/4.0 for i in v]) triangle['vertex_pos'].append(v) triangle['vertex_id'].append(vertex_id) vert_dict[vertex_id].add(len(triangles))#len(self.triangles) is the triangle id triangles.append(triangle) #get centers and neighbors for i, triangle in enumerate(triangles): #print ('triangle ', i ,' of ', len(self.triangles) ) triangle['center']=_get_center(triangle['vertex_pos']) triangle['neighbors']=_get_neighbors(triangle['vertex_id'], vert_dict, i, edge_neighbors_only) #construct the dict edges={} cost={} positions={} for i, triangle in enumerate(triangles): #print ('neighbor ', i) edges[i]=triangle['neighbors'] cost[i]={} start=triangle['center'] positions[i]=start for neighbor in triangle['neighbors']: cost[i][neighbor]=_distance(start, triangles[neighbor]['center']) lookup={_round_vec3_to_tuple(value):key for (key, value) in positions.items()} self.graph= {'neighbors':edges, 'cost':cost, 'pos':positions, 'lookup':lookup} if draw_graph: self.draw_connections()
def getTriangleAsPoints(self, ind, vreader=None): if vreader is None: vreader = GeomVertexReader(self.vdata, 'vertex') pts = [] for vi in self.getTriangleVertexIndices(ind): vreader.setRow(vi) pt = vreader.getData3f() pts.append(Point3(*pt)) return Triangle.TriangleTuple(pts[0], pts[1], pts[2])
def processVertexData(vdata, mesh): vertex = GeomVertexReader(vdata, 'vertex') # texcoord = GeomVertexReader(vdata, 'texcoord') while not vertex.isAtEnd(): v = vertex.getData3f() # t = texcoord.getData2f() # print "v = %s, t = %s" % (repr(v), repr(t)) print("v = %s" % (repr(v))) mesh.add_vertex((v[0], v[1], v[2]))
def getTriangleAsPoints(self, ind, vreader=None): if vreader is None: vreader = GeomVertexReader(self.vdata, 'vertex') pts = [] for vi in self.getTriangleVertexIndices(ind): vreader.setRow(vi) pt = vreader.getData3f() pts.append(Point3(*pt)) return Triangle.TriangleTuple(pts[0], pts[1], pts[2])
def __read_Model(self, field): data = [] vdata = self.node.getGeom(0).getVertexData() reader = GeomVertexReader(vdata, field) get_data, v_type = self.get_dict[field] while not reader.isAtEnd(): datum = v_type(get_data(reader)) data.append(datum) return data
def vertex_colors(self): try: vcol_reader = GeomVertexReader(self.model.findAllMatches('**/+GeomNode')[0].node().getGeom(0).getVertexData(), 'color') vcols = list() while not vcol_reader.isAtEnd(): vcols.append([e for e in vcol_reader.getData4f()]) return vcols except: print(f'{self.name}.model has no vertex colors') return None
def __read_Model(self, field): data = [] vdata = self.node.getGeom(0).getVertexData() reader = GeomVertexReader(vdata, field) get_data, v_type = self.get_dict[field] while not reader.isAtEnd(): datum = v_type(get_data(reader)) data.append(datum) return data
def generate(self): '''(Re)generate the entire terrain erasing any current changes''' factor = self.blockSize*self.chunkSize #print "Factor:", factor for terrain in self.terrains: terrain.getRoot().removeNode() self.terrains = [] # Breaking master heightmap into subimages heightmaps = [] self.xchunks = (self.heightfield.getXSize()-1)/factor self.ychunks = (self.heightfield.getYSize()-1)/factor #print "X,Y chunks:", self.xchunks, self.ychunks n = 0 for y in range(0, self.ychunks): for x in range(0, self.xchunks): heightmap = PNMImage(factor+1, factor+1) heightmap.copySubImage(self.heightfield, 0, 0, xfrom = x*factor, yfrom = y*factor) heightmaps.append(heightmap) n += 1 # Generate GeoMipTerrains n = 0 y = self.ychunks-1 x = 0 for heightmap in heightmaps: terrain = GeoMipTerrain(str(n)) terrain.setHeightfield(heightmap) terrain.setBruteforce(self.bruteForce) terrain.setBlockSize(self.blockSize) terrain.generate() self.terrains.append(terrain) root = terrain.getRoot() root.reparentTo(self.root) root.setPos(n%self.xchunks*factor, (y)*factor, 0) # In order to texture span properly we need to reiterate through every vertex # and redefine the uv coordinates based on our size, not the subGeoMipTerrain's root = terrain.getRoot() children = root.getChildren() for child in children: geomNode = child.node() for i in range(geomNode.getNumGeoms()): geom = geomNode.modifyGeom(i) vdata = geom.modifyVertexData() texcoord = GeomVertexWriter(vdata, 'texcoord') vertex = GeomVertexReader(vdata, 'vertex') while not vertex.isAtEnd(): v = vertex.getData3f() t = texcoord.setData2f((v[0]+ self.blockSize/2 + self.blockSize*x)/(self.xsize - 1), (v[1] + self.blockSize/2 + self.blockSize*y)/(self.ysize - 1)) x += 1 if x >= self.xchunks: x = 0 y -= 1 n += 1
def calculateProfiles(self): vertexToPlane = {} # init dict for p in self.planedata: vertexToPlane[p] = [[], []] geomNodeCollection = self.trench.findAllMatches('**/+GeomNode') print(geomNodeCollection) # 0 will be the trench - change later geomNode = geomNodeCollection[0].node() for i in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(i) state = geomNode.getGeomState(i) vdata = geom.getVertexData() vertex = GeomVertexReader(vdata, 'vertex') while not vertex.isAtEnd(): v = vertex.getData3f() # calculate distance to planes for p in self.planedata: if self.deltaInclude(v, p): if v[1] not in vertexToPlane[p][ 0]: # prevent double addition of x values vertexToPlane[p][0].append(v[1]) vertexToPlane[p][1].append(v[2]) #print(vertexToPlane[1]) # filter xy coordinates #new_x, new_y = self.deltaFilter() i = 0 for p in self.planedata: plt.figure(i) # sort x coordinates L = sorted(zip(vertexToPlane[p][0], vertexToPlane[p][1])) new_x, new_y = zip(*L) # signal process y values yhat = savgol_filter(new_y, 21, 5) #81,5 # 1d interpolation f = interp1d(new_x, yhat, 'quadratic') i += 1 #print(new_x) plt.plot(new_x, new_y, color='k', alpha=0.5, linewidth=0.8) plt.plot(new_x, yhat, color='b', alpha=0.5, linewidth=0.8) plt.plot(new_x, f(new_x), color='r', alpha=0.5, linewidth=2.0) plt.legend(['original', 'savgol_filter', 'interpolated (cubic)']) #plt.plot(new_x, new_y) #plt.plot(new_x, f(new_x)) plt.show()
def processVertexData(self): vreader = GeomVertexReader(self.vdata, 'vertex') nvreader = GeomVertexReader(self.vdata, 'normal') tvreader = GeomVertexReader(self.vdata, 'texcoord') while not vreader.isAtEnd(): v = vreader.getData3f() n = nvreader.getData3f() t = tvreader.getData2f() self.vertices.append(v) self.normals.append(n) self.texcoords.append(t)
def getGeomData(geomNode, scale=1): """ returns a dict : data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []} with the data found inside the GeomNode's Geom's GeomPrimitive """ if not geomNode: return None data = {"prims": [], "vertices": [], "normals": [], "texcoords": []} if geomNode.getNumGeoms() != 1: print "error : num geoms = %s" % (geomNode.getNumGeoms()) return None geom = geomNode.getGeom(0) prim = geom.getPrimitive(0) prims = {} #print "before decompose : prim = %s" % (prim) prim = prim.decompose() #print "after decompose : prim = %s" % (prim) for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) vertexList = [] #print "adding vertices from %s to %s" % (s, e) for i in range(s, e): ''' vi = prim.getVertex(i) vreader.setRow(vi) v = vreader.getData3f() v = VBase3(v[0]*scale, v[1]*scale, v[2]*scale) vertexList.append(v) ''' vi = prim.getVertex(i) vertexList.append(vi) prims[p] = vertexList data["prims"].append(vertexList) vdata = geom.getVertexData() vreader = GeomVertexReader(vdata, 'vertex') nvreader = GeomVertexReader(vdata, 'normal') tvreader = GeomVertexReader(vdata, 'texcoord') while not vreader.isAtEnd(): v = vreader.getData3f() n = nvreader.getData3f() t = tvreader.getData2f() data["vertices"].append(v) data["normals"].append(n) data["texcoords"].append(t) return data
def _read_vertices(self, mod, path): """Read the model vertices and return their positions. Args: mod (panda3d.core.NodePath): Model to read vertices from. path (str): Model filename. Returns: dict: Dict with two lists of points: "wide" - most part of the block, and "narrow" - smaller part of the block with big paddings on every side. """ v_reader = GeomVertexReader( mod.findAllMatches("**/+GeomNode")[0].node().getGeom(0).getVertexData(), "vertex", ) surf_vertices = {"wide": [], "narrow": []} while not v_reader.isAtEnd(): pos = v_reader.getData3() if pos.is_nan(): continue if ( # don't remember coordinates of vertices # on which rails will be set abs(pos.getX()) < 3.99 and abs(pos.getY()) < 3.99 and not ("turn" in path and abs(pos.getZ()) < 0.0001) and not ("fork" in path and abs(pos.getZ()) < 0.02) and not ("surface4" in path and pos.getZ() > 0.08) and not ("surface5" in path and (pos.getZ() > 0.03 or pos.getZ() < 0)) # don't remember vertices of station and city models and not ("station" in path and abs(pos.getY()) < 2.1) and not ( "surface8" in path and pos.getX() > -1.5 and pos.getX() < 0.25 and pos.getY() > -3.5 and pos.getY() < -1.75 ) and not ("city" in path and abs(pos.getY()) < 2.1) ): surf_vertices["wide"].append(pos) if abs(pos.getX()) < 3 and abs(pos.getY()) < 3: surf_vertices["narrow"].append(pos) return surf_vertices
def createOdeEnv(self, model): geomNodeCollection = model.findAllMatches('**/+GeomNode') for nodePath in geomNodeCollection: geomNode = nodePath.node() #print "\n\nGeomNode: ", geomNode.getName() for i in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(i) #state = geomNode.getGeomState(i) T = geomNode.getTransform() #print " - ", T pos = T.getPos() if T.hasComponents(): Q = T.getQuat() S = T.getScale() vdata = geom.getVertexData() vertex = GeomVertexReader(vdata, 'vertex') #mins and maxes for MBB minX = 1e10 maxX = -1e10 minY = 1e10 maxY = -1e10 minZ = 1e10 maxZ = -1e10 while not vertex.isAtEnd(): v = vertex.getData3f() minX = min(minX,v[0]) minY = min(minY,v[1]) minZ = min(minZ,v[2]) maxX = max(maxX,v[0]) maxY = max(maxY,v[1]) maxZ = max(maxZ,v[2]) #print "v = %s" % (repr(v)) #print "X:(%f->%f) Y(%f->%f) Z(%f->%f)" % (minX, maxX, minY, maxY, minZ, maxZ) minX *= S[0] maxX *= S[0] minY *= S[1] maxY *= S[1] minZ *= S[2] maxZ *= S[2] #print "X:(%f->%f) Y(%f->%f) Z(%f->%f)" % (minX, maxX, minY, maxY, minZ, maxZ) box = OdeBoxGeom(self.space, maxX-minX, maxY-minY, maxZ-minZ) box.setPosition(pos) box.setQuaternion(Q) self.odeBoxes.append(box) else: print "Error Transform does not have components - skipping"
def getVertices(self,node,gnode): geomNode = gnode.node() ts = node.getTransform() m = ts.getMat().getUpper3() p = ts.getMat().getRow3(3) points=[] geom = geomNode.getGeoms()[0] vdata = geom.getVertexData() reader = GeomVertexReader(vdata, 'vertex') while not reader.isAtEnd(): v = reader.getData3f() v = m.xform(v) + p points.append(Point3(v)) return numpy.array(points,dtype=numpy.float32)
def get3DPointsFromModel(model): geomNodes = model.findAllMatches('**/+GeomNode') pts = [] for nodePath in geomNodes: nodePts = [] geomNode = nodePath.node() for i in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(i) vdata = geom.getVertexData() vertex = GeomVertexReader(vdata, 'vertex') while not vertex.isAtEnd(): v = vertex.getData3f() nodePts.append([v.x, v.y, v.z]) pts.append(nodePts) return np.array(pts)
def processPrimitive(prim, vdata, mesh): vertex = GeomVertexReader(vdata, 'vertex') prim = prim.decompose() for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) vertices = [] for i in range(s, e): vi = prim.getVertex(i) vertices.append(vi) vertex.setRow(vi) v = vertex.getData3f() print("prim %s has vertex %s: %s" % (p, vi, repr(v))) mesh.add_face(f=vertices)
def registerObject(self, obj): """ Registers a new dynamic object, this will store an index for every vertex, which can be used to read and store last position data in order to compute the velocity. This method also assigns the standard animated shader to the node """ self.debug("Registering dynamic object") # Find all GeomNodes for node in obj.findAllMatches("**/+GeomNode"): geomNode = node.node() geomCount = geomNode.getNumGeoms() # Find all Geoms for i in xrange(geomCount): # Modify vertex data geom = geomNode.modifyGeom(i) geomVertexData = geom.modifyVertexData() # Add a new column named "dovindex" to the vertex data formatArray = GeomVertexArrayFormat() formatArray.addColumn(InternalName.make("dovindex"), 1, GeomEnums.NTUint32, GeomEnums.CIndex) newArrayFormat = GeomVertexFormat(geomVertexData.getFormat()) newArrayFormat.addArray(formatArray) newArrayFormat = GeomVertexFormat.registerFormat( newArrayFormat) # Convert the old vertex data and assign the new vertex data convertedVertexData = geomVertexData.convertTo(newArrayFormat) geom.setVertexData(convertedVertexData) # Write the per-vertex indices the dovindex column newVertexData = geom.modifyVertexData() vtxReader = GeomVertexReader(newVertexData, "vertex") indexWriter = GeomVertexWriter(newVertexData, "dovindex") while not vtxReader.isAtEnd(): data = vtxReader.getData3f() indexWriter.setData1i(self.currentIndex) self.currentIndex += 1 if self.currentIndex > self.maxVertexCount: self.error("Max dynamic vertex count of", self.maxVertexCount, "reached!")
def get3DTrianglesFromModel(model): # Calculate the net transformation transform = model.getNetTransform() transformMat = transform.getMat() # Get geometry data from GeomNode instances inside the model geomNodes = model.findAllMatches('**/+GeomNode') triangles = [] for nodePath in geomNodes: geomNode = nodePath.node() for n in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(n) vdata = geom.getVertexData() for k in range(geom.getNumPrimitives()): prim = geom.getPrimitive(k) vertex = GeomVertexReader(vdata, 'vertex') assert isinstance(prim, (GeomTristrips, GeomTriangles)) # Decompose into triangles prim = prim.decompose() for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) triPts = [] for i in range(s, e): vi = prim.getVertex(i) vertex.setRow(vi) v = vertex.getData3f() # Apply transformation v = transformMat.xformPoint(v) triPts.append([v.x, v.y, v.z]) triangles.append(triPts) triangles = np.array(triangles) return triangles
def processPrimitive(prim, vdata): vertex = GeomVertexReader(vdata, 'vertex') prim = prim.decompose() for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) last = None roadBuilder.addPrim() for i in range(s, e): vi = prim.getVertex(i) vertex.setRow(vi) v = vertex.getData3() if last is not None: self.road_segments.append([last, v]) roadBuilder.addSegment(last, v) last = v
def __read_Model(self, field): get_dict = { 'vertex':(GeomVertexReader.getData3f, LPoint3f), 'normal':(GeomVertexReader.getData3f, LVector3f), 'color':(GeomVertexReader.getData4f, LVector4f), 'texcoord':(GeomVertexReader.getData2f, LVector2f), 'info':(GeomVertexReader.getData4f, list), 'ref':(GeomVertexReader.getData3f, LPoint3f), 'nbr':(GeomVertexReader.getData4f, list)} data = [] vdata = self.NP.node().getGeom(0).getVertexData() reader = GeomVertexReader(vdata, field) get_data, v_type = get_dict[field] while not reader.isAtEnd(): datum = v_type(get_data(reader)) data.append(datum) return data
def registerObject(self, obj): """ Registers a new dynamic object, this will store an index for every vertex, which can be used to read and store last position data in order to compute the velocity. This method also assigns the standard animated shader to the node """ self.debug("Registering dynamic object") # Find all GeomNodes for node in obj.findAllMatches("**/+GeomNode"): geomNode = node.node() geomCount = geomNode.getNumGeoms() # Find all Geoms for i in xrange(geomCount): # Modify vertex data geom = geomNode.modifyGeom(i) geomVertexData = geom.modifyVertexData() # Add a new column named "dovindex" to the vertex data formatArray = GeomVertexArrayFormat() formatArray.addColumn(InternalName.make("dovindex"), 1, GeomEnums.NTUint32, GeomEnums.CIndex) newArrayFormat = GeomVertexFormat(geomVertexData.getFormat()) newArrayFormat.addArray(formatArray) newArrayFormat = GeomVertexFormat.registerFormat(newArrayFormat) # Convert the old vertex data and assign the new vertex data convertedVertexData = geomVertexData.convertTo(newArrayFormat) geom.setVertexData(convertedVertexData) # Write the per-vertex indices the dovindex column newVertexData = geom.modifyVertexData() vtxReader = GeomVertexReader(newVertexData, "vertex") indexWriter = GeomVertexWriter(newVertexData, "dovindex") while not vtxReader.isAtEnd(): data = vtxReader.getData3f() indexWriter.setData1i(self.currentIndex) self.currentIndex += 1 if self.currentIndex > self.maxVertexCount: self.error("Max dynamic vertex count of", self.maxVertexCount, "reached!")
def deriveModelVertices(modelFilename): newVisualCar = loader.loadModel(modelFilename) geomNodeCollection = newVisualCar.findAllMatches('**/+GeomNode') simpleVertices=[] for nodePath in geomNodeCollection: geomNode = nodePath.node() for i in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(i) vdata = geom.getVertexData() vertex = GeomVertexReader(vdata, 'vertex') while not vertex.isAtEnd(): v=vertex.getData3f() vertexModelX,vertexModelY,vertexModelZ=v simpleVertices.append([vertexModelX,vertexModelY,vertexModelZ]) self.unmodifiedVertexData=simpleVertices
def rebuildGeomNodesToColPolys(incomingNode, relativeTo=None, filter=lambda n: True): ''' Converts GeomNodes into CollisionPolys in a straight 1-to-1 conversion Returns a new NodePath containing the CollisionNodes If the geometry is at all complex, running the result of this through colTree should improve performance. ''' parent = NodePath('cGeomConversionParent') for c in incomingNode.findAllMatches('**/+GeomNode'): if not filter(c): continue if relativeTo: xform = c.getMat(relativeTo).xformPoint else: xform = (c.getMat(incomingNode) * (incomingNode.getMat())).xformPoint geomNode = c.node() for g in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(g).decompose() vdata = geom.getVertexData() vreader = GeomVertexReader(vdata, 'vertex') cChild = CollisionNode("") for p in range(geom.getNumPrimitives()): prim = geom.getPrimitive(p) for p2 in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p2) e = prim.getPrimitiveEnd(p2) if e - s > 2: v = [] for vi in range(s, e): vreader.setRow(prim.getVertex(vi)) v.append(Point3(xform(vreader.getData3f()))) colPoly = CollisionPolygon(*v) cChild.addSolid(colPoly) n = parent.attachNewNode(cChild) return parent
def processVertexData(self): vreader = GeomVertexReader(self.vdata, 'vertex') nvreader = GeomVertexReader(self.vdata, 'normal') tvreader = GeomVertexReader(self.vdata, 'texcoord') while not vreader.isAtEnd(): v = vreader.getData3f() n = nvreader.getData3f() t = tvreader.getData2f() self.vertices.append(v) self.normals.append(n) self.texcoords.append(t)
def deriveModelVertices(modelFilename): newVisualCar = loader.loadModel(modelFilename) geomNodeCollection = newVisualCar.findAllMatches('**/+GeomNode') simpleVertices = [] for nodePath in geomNodeCollection: geomNode = nodePath.node() for i in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(i) vdata = geom.getVertexData() vertex = GeomVertexReader(vdata, 'vertex') while not vertex.isAtEnd(): v = vertex.getData3f() vertexModelX, vertexModelY, vertexModelZ = v simpleVertices.append( [vertexModelX, vertexModelY, vertexModelZ]) self.unmodifiedVertexData = simpleVertices
def rebuildGeomNodesToColPolys (incomingNode,relativeTo=None): ''' Converts GeomNodes into CollisionPolys in a straight 1-to-1 conversion Returns a new NodePath containing the CollisionNodes ''' parent = NodePath('cGeomConversionParent') for c in incomingNode.findAllMatches('**/+GeomNode'): if relativeTo: xform=c.getMat(relativeTo).xformPoint else: xform=(c.getMat(incomingNode)*(incomingNode.getMat())).xformPoint gni = 0 geomNode = c.node() for g in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(g).decompose() vdata = geom.getVertexData() vreader = GeomVertexReader(vdata, 'vertex') cChild = CollisionNode('cGeom-%s-gni%i' % (c.getName(), gni)) gni += 1 for p in range(geom.getNumPrimitives()): prim = geom.getPrimitive(p) for p2 in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p2) e = prim.getPrimitiveEnd(p2) v = [] for vi in range (s, e): vreader.setRow(prim.getVertex(vi)) v.append (xform(vreader.getData3f())) colPoly = CollisionPolygon(*v) cChild.addSolid(colPoly) n=parent.attachNewNode (cChild) #n.show() return parent
def getGeomData(geomNode, scale=1): """ returns a dict : data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []} with the data found inside the GeomNode's Geom's GeomPrimitive """ if not geomNode: return None data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []} if geomNode.getNumGeoms()!=1: print "error : num geoms = %s" % (geomNode.getNumGeoms()) return None geom = geomNode.getGeom(0) prim = geom.getPrimitive(0) prims = {} #print "before decompose : prim = %s" % (prim) prim = prim.decompose() #print "after decompose : prim = %s" % (prim) for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) vertexList = [] #print "adding vertices from %s to %s" % (s, e) for i in range(s, e): ''' vi = prim.getVertex(i) vreader.setRow(vi) v = vreader.getData3f() v = VBase3(v[0]*scale, v[1]*scale, v[2]*scale) vertexList.append(v) ''' vi = prim.getVertex(i) vertexList.append(vi) prims[p]=vertexList data["prims"].append(vertexList) vdata = geom.getVertexData() vreader = GeomVertexReader(vdata, 'vertex') nvreader = GeomVertexReader(vdata, 'normal') tvreader = GeomVertexReader(vdata, 'texcoord') while not vreader.isAtEnd(): v = vreader.getData3f() n = nvreader.getData3f() t = tvreader.getData2f() data["vertices"].append(v) data["normals"].append(n) data["texcoords"].append(t) return data
def getSurfaceAreaFromGeom(geom, transform=None): totalArea = 0.0 for k in range(geom.getNumPrimitives()): prim = geom.getPrimitive(k) vdata = geom.getVertexData() vertex = GeomVertexReader(vdata, 'vertex') assert isinstance(prim, (GeomTristrips, GeomTriangles)) # Decompose into triangles prim = prim.decompose() for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) triPts = [] for i in range(s, e): vi = prim.getVertex(i) vertex.setRow(vi) v = vertex.getData3f() # Apply transformation if transform is not None: v = transform.xformPoint(v) triPts.append([v.x, v.y, v.z]) triPts = np.array(triPts) # calculate the semi-perimeter and area a = np.linalg.norm(triPts[0] - triPts[1], 2) b = np.linalg.norm(triPts[1] - triPts[2], 2) c = np.linalg.norm(triPts[2] - triPts[0], 2) s = (a + b + c) / 2 area = (s*(s-a)*(s-b)*(s-c)) ** 0.5 totalArea += area return totalArea
def rebuildGeomNodesToColPolys (incomingNode,relativeTo=None,filter=lambda n:True): ''' Converts GeomNodes into CollisionPolys in a straight 1-to-1 conversion Returns a new NodePath containing the CollisionNodes If the geometry is at all complex, running the result of this through colTree should improve performance. ''' parent = NodePath('cGeomConversionParent') for c in incomingNode.findAllMatches('**/+GeomNode'): if not filter(c): continue if relativeTo: xform=c.getMat(relativeTo).xformPoint else: xform=(c.getMat(incomingNode)*(incomingNode.getMat())).xformPoint geomNode = c.node() for g in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(g).decompose() vdata = geom.getVertexData() vreader = GeomVertexReader(vdata, 'vertex') cChild = CollisionNode("") for p in range(geom.getNumPrimitives()): prim = geom.getPrimitive(p) for p2 in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p2) e = prim.getPrimitiveEnd(p2) if e-s>2: v = [] for vi in range (s, e): vreader.setRow(prim.getVertex(vi)) v.append(Point3(xform(vreader.getData3f())) ) colPoly = CollisionPolygon(*v) cChild.addSolid(colPoly) n=parent.attachNewNode(cChild) return parent
def getGeomData(geom=None): """ returns a dict : data = {"prims":[], "vertices" : [], "normals" : [], "texcoords" : []} with the data found inside the Geom's GeomPrimitive """ if not geom: return None data = {"vertices" : [], "normals" : [], "texcoords" : [], "colors" : [], "tangents":[], "binormals":[], "lines":[], "triangles":[], "tristrips":[], "trifans":[]} #prim = geom.getPrimitive(0) #prims = {} #print "before decompose : prim = %s" % (prim) #prim = prim.decompose() #print "after decompose : prim = %s" % (prim) for gPrim in geom.getPrimitives(): for p in range(gPrim.getNumPrimitives()): s = gPrim.getPrimitiveStart(p) e = gPrim.getPrimitiveEnd(p) vertexList = [] for i in range(s, e): vi = gPrim.getVertex(i) vertexList.append(vi) if type(gPrim) is GeomLinestrips: data["lines"].append(vertexList) elif type(gPrim) is GeomTriangles: data["triangles"].append(vertexList) elif type(gPrim) is GeomTristrips: data["tristrips"].append(vertexList) elif type(gPrim) is GeomTrifans: data["trifans"].append(vertexList) #print "appended primitive number %s, type is %s" % (p, type(gPrim)) vdata = geom.getVertexData() vreader = GeomVertexReader(vdata, 'vertex') nreader = GeomVertexReader(vdata, 'normal') treader = GeomVertexReader(vdata, 'texcoord') creader = GeomVertexReader(vdata, 'color') tanReader = GeomVertexReader(vdata, 'tangent') binReader = GeomVertexReader(vdata, 'binormal') while not vreader.isAtEnd(): v = vreader.getData3f() n = nreader.getData3f() t = treader.getData2f() c = creader.getData4f() tangent = tanReader.getData3f() binormal = binReader.getData3f() data["vertices"].append(v) data["normals"].append(n) data["texcoords"].append(t) data["colors"].append(c) data["tangents"].append(tangent) data["binormals"].append(binormal) return data
def uvs(self): vertex_reader = GeomVertexReader(self.vertex_data, 'texcoord') vertices = list() while not vertex_reader.isAtEnd(): vertices.append([e for e in vertex_reader.getData2f()]) return vertices
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)
def draw_shape(angles, width, radius): res = 10 if radius == 0: point = GeomNode('gnode') vdata = GeomVertexData('occ', GeomVertexFormat.getV3(), Geom.UHStatic) vdata.setNumRows(1) vertex = GeomVertexWriter(vdata, 'vertex') vertex.addData3f(0, 0, 0) geom = Geom(vdata) g = GeomPoints(Geom.UHStatic) g.addVertex(0) geom.addPrimitive(g) point.addGeom(geom) return point, point #first, sort angles in ascending order #if negative is given, translate to range of 2pi for i in range(len(angles)): if angles[i] < 0: angles[i] = 360 + angles[i] angles.sort() angles = [math.radians(a) for a in angles] angles.append(angles[0]) #read first angle to account for wrapping around #function = 'w/sin(theta)' vdata = GeomVertexData('occ', GeomVertexFormat.getV3(), Geom.UHStatic) vdata.setNumRows(1) vertex = GeomVertexWriter(vdata, 'vertex') numverts = [3] * (len(angles) - 1 ) #center, and two points on function lines for i in range(len(angles) - 1): #find center point #L = [None,None] #sign = [-1,1] #for p in range(2): # theta1 = angles[i+p] - sign[p]*math.pi/2 # theta2 = angles[i+p] + sign[p]*math.pi/4 # x1 = width*math.cos(theta1) # y1 = width*math.sin(theta1) # r = math.sqrt(2*width**2) # x2 = r*math.cos(theta2) # y2 = r*math.sin(theta2) # L[p] = line([x1,y1], [x2,y2]) #R = intersection(L[0],L[1]) #if R is False: # R = [x1,y1] #if parallel, shift both lines down by y_width #vertex.addData3f(R[0],R[1],1) difang = (angles[i + 1] - angles[i]) / 2 l = width / math.sin(difang) avgang = (angles[i] + angles[i + 1]) / 2 x0 = l * math.cos(avgang) y0 = l * math.sin(avgang) vertex.addData3f(x0, y0, 1) newang1 = angles[i] + (math.pi / 2 - math.acos(width / radius)) x = radius * math.cos(newang1) y = radius * math.sin(newang1) vertex.addData3f(x, y, 1) newang2 = angles[i + 1] - (math.pi / 2 - math.acos(width / radius)) for angle in arc(newang1, newang2, res): vertex.addData3f(radius * math.cos(math.radians(angle)), radius * math.sin(math.radians(angle)), 1) numverts[i] = numverts[i] + 1 x = radius * math.cos(newang2) y = radius * math.sin(newang2) vertex.addData3f(x, y, 1) #copy all data to the bottom, moving it down to z = -1 vertread = GeomVertexReader(vdata, 'vertex') while not vertread.isAtEnd(): v = vertread.getData3f() vertex.addData3f(v[0], v[1], -1) #draw geom = Geom(vdata) #draw top for i in range(len(angles) - 1): for j in range(numverts[i] - 2): ind = sum(numverts[0:i]) + j g = GeomTriangles(Geom.UHStatic) g.add_vertices(ind - j, ind + 1, ind + 2) geom.addPrimitive(g) #draw bottom for i in range(len(angles) - 1): for j in range(numverts[i] - 2): ind = sum(numverts) + sum(numverts[0:i]) + j g = GeomTriangles(Geom.UHStatic) g.add_vertices(ind - j, ind + 2, ind + 1) geom.addPrimitive(g) #draw edges for i in range(len(angles) - 1): for j in range(numverts[i] - 1): ind = sum(numverts[0:i]) + j g = GeomTriangles(Geom.UHStatic) g.add_vertices(ind, ind + sum(numverts), ind + 1) g.add_vertices(ind + sum(numverts), ind + 1 + sum(numverts), ind + 1) geom.addPrimitive(g) g = GeomTriangles(Geom.UHStatic) ind = sum(numverts[0:i]) indx = sum(numverts[0:i + 1]) g.add_vertices(indx - 1, indx + sum(numverts) - 1, ind) g.add_vertices(indx + sum(numverts) - 1, sum(numverts) + ind, ind) geom.addPrimitive(g) #outline object lines = Geom(vdata) l = GeomLines(Geom.UHStatic) for i in range(len(angles) - 1): for j in range(numverts[i] - 1): ind = sum(numverts[0:i]) + j l.add_vertices(ind, ind + 1) l.add_vertices(sum(numverts) + ind, sum(numverts) + ind + 1) ind = sum(numverts[0:i]) indx = sum(numverts[0:i + 1]) l.add_vertices(ind, indx - 1) l.add_vertices(sum(numverts) + ind, sum(numverts) + indx - 1) l.add_vertices(ind + 1, sum(numverts) + ind + 1) l.add_vertices(indx - 1, sum(numverts) + indx - 1) lines.addPrimitive(l) node = GeomNode('gnode') node.addGeom(geom) nodeL = GeomNode('gnode') nodeL.addGeom(lines) return node, nodeL
def generateNode(self): self.destroy() self.node = NodePath('gameobjectnode') self.node.setTwoSided(True) self.node.reparentTo(self.parent.node) if self.properties['avoidable'] == True: self.node.setTag("avoidable", 'true') else: self.node.setTag("avoidable", 'false') #setting scripting part self.node.setTag("onWalked", self.onWalked) self.node.setTag("onPicked", self.onPicked) #set unique id self.node.setTag("id", self.properties['id']) tex = loader.loadTexture(resourceManager.getResource(self.properties['url'])+'.png') tex.setWrapV(Texture.WM_clamp) tex.setWrapU(Texture.WM_clamp) #this is true pixel art #change to FTLinear for linear interpolation between pixel colors tex.setMagfilter(Texture.FTNearest) tex.setMinfilter(Texture.FTNearest) xorig = tex.getOrigFileXSize() / self.baseDimension yorig = tex.getOrigFileYSize() / self.baseDimension xscaled = (tex.getOrigFileXSize() / self.baseDimension) * self.properties['scale'] yscaled = (tex.getOrigFileYSize() / self.baseDimension) * self.properties['scale'] self.node.setTag("xscaled", str(xscaled)) self.node.setTag("yscaled", str(yscaled)) cm = CardMaker("tileobject") cm.setFrame(0,xorig,0,yorig) ts = TextureStage('ts') ts.setMode(TextureStage.MDecal) # distinguish between 3d collisions (for objects with an height and sensible self.properties['inclination']) # and 2d collisions for plain sprites if self.properties['walkable'] == 'false': if self.properties['collisionmode'] == "3d": #must handle differently objects which are small and big if xscaled < 1: self.collisionTube = CollisionBox(LPoint3f(0.5 - xscaled/2 - self.properties['offsetwidth'],0,0),LPoint3f(0.5 + xscaled/2 + self.properties['offsetwidth'],0.1,0.3 + self.properties['offsetheight'])) if xscaled >= 1: self.collisionTube = CollisionBox(LPoint3f(0 - self.properties['offsetwidth'],0,0),LPoint3f(xscaled + self.properties['offsetwidth'],0.1,0.3 + self.properties['offsetheight'])) self.collisionNode = CollisionNode('objectSphere') self.collisionNode.addSolid(self.collisionTube) self.collisionNodeNp = self.node.attachNewNode(self.collisionNode) self.collisionNodeNp.setX(self.properties['offsethorizontal']) self.collisionNodeNp.setZ(self.properties['offsetvertical']) self.collisionNodeNp.setX(self.collisionNodeNp.getX()+self.properties['offsetcollisionh']) self.collisionNodeNp.setZ(self.collisionNodeNp.getZ()+self.properties['offsetcollisionv']+0.1) if main.editormode: self.collisionNodeNp.show() elif self.properties['collisionmode'] == "2d": #must handle differently objects which are small and big if xscaled < 1: self.collisionTube = CollisionBox(LPoint3f(0.5 - xscaled/2 - self.properties['offsetwidth'],0,0),LPoint3f(0.5 + xscaled/2 + self.properties['offsetwidth'],yscaled + self.properties['offsetheight'],0.3)) if xscaled >= 1: self.collisionTube = CollisionBox(LPoint3f(0 - self.properties['offsetwidth'],0,0),LPoint3f(xscaled + self.properties['offsetwidth'],yscaled + self.properties['offsetheight'],0.3)) self.collisionNode = CollisionNode('objectSphere') self.collisionNode.addSolid(self.collisionTube) self.collisionNodeNp = self.node.attachNewNode(self.collisionNode) self.collisionNodeNp.setP(-(270-int(self.properties['inclination']))) self.collisionNodeNp.setX(self.properties['offsethorizontal']) self.collisionNodeNp.setZ(self.properties['offsetvertical']) self.collisionNodeNp.setX(self.collisionNodeNp.getX()+self.properties['offsetcollisionh']) self.collisionNodeNp.setZ(self.collisionNodeNp.getZ()+self.properties['offsetcollisionv']+0.1) if main.editormode: self.collisionNodeNp.show() geomnode = NodePath(cm.generate()) if geomnode.node().isGeomNode(): vdata = geomnode.node().modifyGeom(0).modifyVertexData() writer = GeomVertexWriter(vdata, 'vertex') reader = GeomVertexReader(vdata, 'vertex') ''' this part apply rotation flattening to the perspective view by modifying directly structure vertices ''' i = 0 #counter while not reader.isAtEnd(): v = reader.getData3f() x = v[0] y = v[1] z = v[2] newx = x newy = y newz = z if self.properties['rotation'] == -90.0: if i == 0: newx = math.fabs(math.cos(math.radians(self.properties['inclination']))) * z newz = 0 ssen = math.fabs(math.sin(math.radians(self.properties['inclination']))) * z sparsen = math.fabs(math.sin(math.radians(self.properties['inclination']))) * ssen spercos = math.fabs(math.cos(math.radians(self.properties['inclination']))) * ssen newy -= spercos newz += sparsen if i == 2: newx += math.fabs(math.cos(math.radians(self.properties['inclination']))) * z newz = 0 ssen = math.fabs(math.sin(math.radians(self.properties['inclination']))) * z sparsen = math.fabs(math.sin(math.radians(self.properties['inclination']))) * ssen spercos = math.fabs(math.cos(math.radians(self.properties['inclination']))) * ssen newy -= spercos newz += sparsen writer.setData3f(newx, newy, newz) i += 1 #increase vertex counter if xscaled >= 1: geomnode.setX(0) if xscaled < 1: geomnode.setX(0.5 - xscaled/2) geomnode.setScale(self.properties['scale']) geomnode.setX(geomnode.getX()+self.properties['offsethorizontal']) geomnode.setZ(geomnode.getZ()+self.properties['offsetvertical']) geomnode.setY(-self.properties['elevation']) geomnode.setP(int(self.properties['inclination'])-360) geomnode.setTexture(tex) geomnode.setTransparency(TransparencyAttrib.MAlpha) geomnode.reparentTo(self.node) self.node.setR(self.properties['rotation'])
def getColorAttributesFromVertexData(geom, transform=None): colorsTotalAreas = dict() for k in range(geom.getNumPrimitives()): prim = geom.getPrimitive(k) vdata = geom.getVertexData() assert isinstance(prim, (GeomTristrips, GeomTriangles)) # Check if color is defined for vertex isColorDefined = False for i, geomVertexCol in enumerate(vdata.getFormat().getColumns()): if geomVertexCol.getContents() == GeomEnums.CColor: isColorDefined = True break assert isColorDefined vertex = GeomVertexReader(vdata, 'vertex') vertexColor = GeomVertexReader(vdata, 'color') # Decompose into triangles prim = prim.decompose() for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) color = None triPts = [] for i in range(s, e): vi = prim.getVertex(i) vertex.setRow(vi) vertexColor.setRow(vi) v = vertex.getData3f() # NOTE: all vertex of the same polygon (triangles) should have the same color, # so only grab it once. if color is None: color = vertexColor.getData4f() color = (color[0], color[1], color[2], color[3]) triPts.append([v.x, v.y, v.z]) triPts = np.array(triPts) # Apply transformation if transform is not None: v = transform.xformPoint(v) # calculate the semi-perimeter and area a = np.linalg.norm(triPts[0] - triPts[1], 2) b = np.linalg.norm(triPts[1] - triPts[2], 2) c = np.linalg.norm(triPts[2] - triPts[0], 2) s = (a + b + c) / 2 area = (s*(s-a)*(s-b)*(s-c)) ** 0.5 if color in colorsTotalAreas: colorsTotalAreas[color] += area else: colorsTotalAreas[color] = area areas = [] rgbColors = [] transparencies = [] for color, area in colorsTotalAreas.iteritems(): areas.append(area) rgbColors.append(list(color[:3])) # Check transparency isTransparent = color[3] < 1.0 transparencies.append(isTransparent) return areas, rgbColors, transparencies
def __init__(self, mainReference): self.mainRef = mainReference # fog experiment myFog = Fog("Mist") myFog.setColor(0.6, 0.6, 0.6) myFog.setExpDensity(0.0007) render.setFog(myFog) # loading H_Block self.H_Block = loader.loadModel("../../models/H_Block/H_Block") self.H_Block.reparentTo(self.mainRef.render) # loading H_Block's colision mesh self.H_Block_col = loader.loadModel("../../models/H_Block/H_Block_collision") self.H_Block_col.ls() # creating triangle meshes for all static nodes self.hBlockRoomGeom = self.H_Block_col.getChild(0).getNode(0).getGeom(0) self.hBlockBulletMesh = BulletTriangleMesh() self.hBlockBulletMesh.addGeom(self.hBlockRoomGeom) self.hBlockBulletShape = BulletTriangleMeshShape(self.hBlockBulletMesh, dynamic=False) self.bulletHBlockNode = BulletRigidBodyNode('hBlockNode') self.bulletHBlockNode.addShape(self.hBlockBulletShape) self.mainRef.world.attachRigidBody(self.bulletHBlockNode) self.mainRef.render.attachNewNode(self.bulletHBlockNode).setCollideMask(BitMask32.allOn()) # arrays containing all regions and portals dividing those regions self.convexRegions = [] self.portals = [] self.convexRegionsGeometry = loader.loadModel("../../models/H_Block/ConvexRegions2") self.portalsGeometry = loader.loadModel("../../models/H_Block/Portals2") # self.portalsGeometry.reparentTo(self.mainRef.render) # Regions self.convexRegions.append( Region(0) ) # Just making the access to convexRegions easier for convexRegion in self.convexRegionsGeometry.getChild(0).getChildren(): regionNode = convexRegion.getNode(0) regionID = int( regionNode.getTag("prop") ) self.convexRegions.append( Region(regionID) ) # Get vertices that define the convex region vertexReader = GeomVertexReader(regionNode.getGeom(0).getVertexData(), InternalName.getVertex()) while( not(vertexReader.isAtEnd() ) ): data = vertexReader.getData3() X = data.getX() Y = data.getY() Z = data.getZ() self.convexRegions[-1].vertices.append(Vec3(X,Y,Z)) self.convexRegions = sorted(self.convexRegions, key=lambda convexRegion: convexRegion.regionID) # Debug # for cr in self.convexRegions: # print cr.regionID # Portals for portal in self.portalsGeometry.getChild(0).getChildren(): portalNode = portal.getNode(0) # Get vertices that define the portal frontiers = [] vertexReader = GeomVertexReader(portalNode.getGeom(0).getVertexData(), InternalName.getVertex()) for i in range(2): # We got 2 vertices per portal data = vertexReader.getData3() X = data.getX() Y = data.getY() frontiers.append(Vec2(X,Y)) connectedRegionsIDs = map(int, portalNode.getTag("prop").split(',')) self.portals.append( Portal(connectedRegionsIDs, frontiers) ) self.convexRegions[ connectedRegionsIDs[0] ].portalEntrancesList.append( PortalEntrance( self.portals[-1], connectedRegionsIDs[1] ) ) self.convexRegions[ connectedRegionsIDs[1] ].portalEntrancesList.append( PortalEntrance( self.portals[-1], connectedRegionsIDs[0] ) )
def get_writer(geom: Geom, column_name: ArrayFormatColunm) -> GeomVertexReader: vertex_data = geom.modifyVertexData() return GeomVertexReader(vertex_data, column_name.value)
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)
def createModelClone(self,modelFilename): newVisualCar = loader.loadModel(modelFilename) geomNodeCollection = newVisualCar.findAllMatches('**/+GeomNode') simpleTris=[] self.unmodifiedVertexData=[] for nodePath in geomNodeCollection: geomNode = nodePath.node() for i in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(i) vdata = geom.getVertexData() vertex = GeomVertexReader(vdata, 'vertex') while not vertex.isAtEnd(): v=vertex.getData3f() vertexModelX,vertexModelY,vertexModelZ=v self.unmodifiedVertexData.append([vertexModelX,vertexModelY,vertexModelZ]) for primitiveIndex in range(geom.getNumPrimitives()): prim=geom.getPrimitive(primitiveIndex) prim=prim.decompose() for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) singleTriData=[] for i in range(s, e): vertex.setRow(prim.getVertex(s)) vi = prim.getVertex(i) singleTriData.append(vi) simpleTris.append(singleTriData) simpleVertices=self.unmodifiedVertexData format=GeomVertexFormat.getV3() vdata=GeomVertexData('shadow', format, Geom.UHDynamic) self.pandaVertexData=vdata vertex=GeomVertexWriter(vdata, 'vertex') for vertexIndex in range(len(simpleVertices)): simpleVertex=simpleVertices[vertexIndex] vertex.addData3f(0,0,0) tris=GeomTriangles(Geom.UHStatic) for index in range(len(simpleTris)): simpleTri=simpleTris[index] tris.addVertex(simpleTri[0]) tris.addVertex(simpleTri[1]) tris.addVertex(simpleTri[2]) tris.closePrimitive() shadow=Geom(vdata) shadow.addPrimitive(tris) snode=GeomNode('shadow') snode.addGeom(shadow) self.snode=snode
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)
def __init__(self, entity, mesh=None, center=(0,0,0)): super().__init__() center = Vec3(center) if mesh == None and entity.model: mesh = entity.model # print('''auto generating mesh collider from entity's mesh''') self.node_path = entity.attachNewNode(CollisionNode('CollisionNode')) self.collision_polygons = [] if isinstance(mesh, Mesh): if mesh.triangles: triangles = mesh.triangles if not isinstance(mesh.triangles[0], tuple): triangles = [triangles[i:i + 3] for i in range(0, len(triangles), 3)] # group into groups of three for tri in triangles: if len(tri) == 3: poly = CollisionPolygon( Vec3(mesh.vertices[tri[2]]), Vec3(mesh.vertices[tri[1]]), Vec3(mesh.vertices[tri[0]]), ) self.collision_polygons.append(poly) elif len(tri) == 4: poly = CollisionPolygon( Vec3(mesh.vertices[tri[3]]), Vec3(mesh.vertices[tri[2]]), Vec3(mesh.vertices[tri[1]]), Vec3(mesh.vertices[tri[0]])) self.collision_polygons.append(poly) elif mesh.mode == 'triangle': # no triangle list, so take 3 and 3 vertices for i in range(0, len(mesh.vertices), 3): poly = CollisionPolygon( Vec3(mesh.vertices[i+2]), Vec3(mesh.vertices[i+1]), Vec3(mesh.vertices[i]), ) self.collision_polygons.append(poly) else: print('error: mesh collider does not support', mesh.mode, 'mode') return None elif isinstance(mesh, NodePath): from panda3d.core import GeomVertexReader verts = [] geomNodeCollection = mesh.findAllMatches('**/+GeomNode') for nodePath in geomNodeCollection: geomNode = nodePath.node() for i in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(i) vdata = geom.getVertexData() for i in range(geom.getNumPrimitives()): prim = geom.getPrimitive(i) vertex_reader = GeomVertexReader(vdata, 'vertex') prim = prim.decompose() for p in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p) e = prim.getPrimitiveEnd(p) for i in range(s, e): vi = prim.getVertex(i) vertex_reader.setRow(vi) verts.append(vertex_reader.getData3()) for i in range(0, len(verts)-3, 3): p = CollisionPolygon(Vec3(verts[i+2]), Vec3(verts[i+1]), Vec3(verts[i])) self.collision_polygons.append(p) node = self.node_path.node() for poly in self.collision_polygons: node.addSolid(poly) self.visible = False
def completeTunnelPath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() vertexReader = GeomVertexReader(self.vertexData, 'vertex') print "Original prims:",self.triStrips.getNumPrimitives() p = 0 for i in range(self.triStrips.getNumPrimitives()): v0 = self.triStrips.getPrimitiveStart(i) ve = self.triStrips.getPrimitiveEnd(i) j = v0 + 4 # add the bottom triangles vertexReader.setRow(self.triStrips.getVertex(j)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(self.triStrips.getVertex(j+1)) floorMesh.addVertex(Point3(vertexReader.getData3f())) vertexReader.setRow(self.triStrips.getVertex(j+2)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p, p+1, p+2) vertexReader.setRow(self.triStrips.getVertex(j+3)) floorMesh.addVertex(Point3(vertexReader.getData3f())) floorMesh.addTriangle(p+1, p+3, p+2) p += 4 # this adds every triangle, but is not appropriate for a closed path # tris = self.triStrips.decompose() # print "Decomposed prims:",tris.getNumPrimitives() # p = 0 # for i in range(tris.getNumPrimitives()): # v0 = tris.getPrimitiveStart(i) # ve = tris.getPrimitiveEnd(i) # if v0 < ve: # vertexReader.setRow(tris.getVertex(v0)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # vertexReader.setRow(tris.getVertex(v0+1)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # vertexReader.setRow(tris.getVertex(v0+2)) # floorMesh.addVertex(Point3(vertexReader.getData3f())) # floorMesh.addTriangle(p, p+1, p+2) # p += 3 self.floorCollNode.addSolid(floorMesh)
def generate(self): '''(Re)generate the entire terrain erasing any current changes''' factor = self.blockSize * self.chunkSize #print "Factor:", factor for terrain in self.terrains: terrain.getRoot().removeNode() self.terrains = [] # Breaking master heightmap into subimages heightmaps = [] self.xchunks = (self.heightfield.getXSize() - 1) / factor self.ychunks = (self.heightfield.getYSize() - 1) / factor #print "X,Y chunks:", self.xchunks, self.ychunks n = 0 for y in range(0, self.ychunks): for x in range(0, self.xchunks): heightmap = PNMImage(factor + 1, factor + 1) heightmap.copySubImage(self.heightfield, 0, 0, xfrom=x * factor, yfrom=y * factor) heightmaps.append(heightmap) n += 1 # Generate GeoMipTerrains n = 0 y = self.ychunks - 1 x = 0 for heightmap in heightmaps: terrain = GeoMipTerrain(str(n)) terrain.setHeightfield(heightmap) terrain.setBruteforce(self.bruteForce) terrain.setBlockSize(self.blockSize) terrain.generate() self.terrains.append(terrain) root = terrain.getRoot() root.reparentTo(self.root) root.setPos(n % self.xchunks * factor, (y) * factor, 0) # In order to texture span properly we need to reiterate through every vertex # and redefine the uv coordinates based on our size, not the subGeoMipTerrain's root = terrain.getRoot() children = root.getChildren() for child in children: geomNode = child.node() for i in range(geomNode.getNumGeoms()): geom = geomNode.modifyGeom(i) vdata = geom.modifyVertexData() texcoord = GeomVertexWriter(vdata, 'texcoord') vertex = GeomVertexReader(vdata, 'vertex') while not vertex.isAtEnd(): v = vertex.getData3f() t = texcoord.setData2f( (v[0] + self.blockSize / 2 + self.blockSize * x) / (self.xsize - 1), (v[1] + self.blockSize / 2 + self.blockSize * y) / (self.ysize - 1)) x += 1 if x >= self.xchunks: x = 0 y -= 1 n += 1