def completeQuadPath(self): self.geomNode.addGeom(self.geom) if self.triStrips.getNumPrimitives() == 0: return floorMesh = CollisionFloorMesh() vertexReader = GeomVertexReader(self.vertexData, 'vertex') 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 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 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 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 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 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 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 _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 _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 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 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 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 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 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 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 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 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 __init__(self, app, model_name): model_file_name = 'assets/cars/{}/{}.bam'.format( model_name, model_name) self.app = app def animation_path(model, animation): base_path = 'assets/cars/animations/{}/{}-{}.bam' return base_path.format(model, model, animation) self.model = Actor( model_file_name, { # AIRBRAKE: 'assets/cars/animations/{}-{}.bam'.format(model_name, AIRBRAKE), # AIRBRAKE: animation_path(model_name, AIRBRAKE), # STABILIZER_FINS: animation_path(model_name, STABILIZER_FINS), }) self.model.enableBlend() self.model.setControlEffect(AIRBRAKE, 1) self.model.setControlEffect(STABILIZER_FINS, 1) # FIXME: This code fails due to a bug in Actor # airbrake_joints = [joint.name # for joint in self.model.getJoints() # if joint.name.startswith(AIRBRAKE) # ] # self.model.makeSubpart(AIRBRAKE, airbrake_joints) # stabilizer_joints = [joint.name # for joint in self.model.getJoints() # if joint.name.startswith(STABILIZER_FINS) # ] # self.model.makeSubpart(STABILIZER_FINS, stabilizer_joints) puppet = self.app.loader.load_model(model_file_name) puppet.find("**/armature").hide() puppet.reparentTo(self.model) # Get the vehicle data self.vehicle_data = VehicleData(puppet, model_name, 'cars') # Configure the physics node self.physics_node = BulletRigidBodyNode('vehicle') self.physics_node.set_friction(self.vehicle_data.friction) self.physics_node.set_linear_sleep_threshold(0) self.physics_node.set_angular_sleep_threshold(0) self.physics_node.setCcdMotionThreshold(1e-7) self.physics_node.setCcdSweptSphereRadius(0.5) self.physics_node.setMass(self.vehicle_data.mass) shape = BulletConvexHullShape() for geom_node in self.model.find_all_matches("**/+GeomNode"): for geom in geom_node.node().get_geoms(): vertices = GeomVertexReader(geom.get_vertex_data(), 'vertex') while not vertices.is_at_end(): v_geom = vertices.getData3f() v_model = self.model.get_relative_point(geom_node, v_geom) shape.add_point(v_model) self.physics_node.add_shape(shape) self.vehicle = NodePath(self.physics_node) self.vehicle.set_collide_mask(CM_VEHICLE | CM_COLLIDE) self.model.reparent_to(self.vehicle) # Navigational aids self.target_node = self.app.loader.load_model('models/zup-axis') self.target_node.reparent_to(self.model) self.target_node.set_scale(1) self.target_node.set_render_mode_wireframe() self.target_node.hide() self.delta_node = self.app.loader.load_model('models/smiley') self.delta_node.set_pos(1, 10, 1) self.delta_node.reparent_to(base.cam) self.delta_node.hide() self.airbrake_state = 0.0 self.airbrake_factor = 0.5 self.airbrake_speed = 1 / self.vehicle_data.airbrake_duration self.stabilizer_fins_state = 0.0 self.stabilizer_fins_speed = 1 / self.vehicle_data.stabilizer_fins_duration self.centroid = base.loader.load_model('models/smiley') self.centroid.reparent_to(self.vehicle) self.centroid.hide() # Gyro sound sound_file = 'assets/cars/{}/{}.wav'.format( model_name, GYROSCOPE_SOUND, ) sound = base.audio3d.load_sfx(sound_file) self.model.set_python_tag(GYROSCOPE_SOUND, sound) base.audio3d.attach_sound_to_object(sound, self.model) sound.set_volume(0) sound.set_play_rate(0) sound.set_loop(True) sound.play() # Thruster limiting self.thruster_state = 0.0 self.thruster_heat = 0.0 for repulsor in self.vehicle_data.repulsor_nodes: self.add_repulsor(repulsor, model_name) for thruster in self.vehicle_data.thruster_nodes: self.add_thruster(thruster, model_name) # ECU data storage from frame to frame self.last_flight_height = None # FIXME: Move into a default controller self.inputs = { # Repulsors REPULSOR_ACTIVATION: 0.0, ACCELERATE: 0.0, TURN: 0.0, STRAFE: 0.0, HOVER: 0.0, FULL_REPULSORS: False, # Gyro ACTIVE_STABILIZATION_ON_GROUND: PASSIVE, ACTIVE_STABILIZATION_CUTOFF_ANGLE: PASSIVE, ACTIVE_STABILIZATION_IN_AIR: PASSIVE, TARGET_ORIENTATION: Vec3(0, 0, 0), # Thrust THRUST: 0.0, # Air foils AIRBRAKE: 0.0, STABILIZER_FINS: 0.0, } self.sensors = {} self.commands = {}
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 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 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 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 processModel(path): scene = loadModel(path) if scene.isEmpty(): print("Error converting `{0}`!".format(path)) return fPath = Filename.fromOsSpecific(path) outputPath = Filename.toOsSpecific( Filename("bam2smd/" + fPath.getDirname() + "/" + fPath.getBasenameWoExtension() + "/")) if not os.path.exists(outputPath): os.makedirs(outputPath) isCharacter = not scene.find("**/+Character").isEmpty() isAnimation = not scene.find("**/+AnimBundleNode").isEmpty() if not isAnimation: if isCharacter: nodes = Skeleton(scene.findAllMatches("**/+Character")) else: nodes = Skeleton(None) names = {} for geomNp in scene.findAllMatches("**/+GeomNode"): smd = "version 1\n" smd += str(nodes) smd += "skeleton\n" smd += "time 0\n" if isCharacter: boneIds = sorted(nodes.bones.keys()) for iBone in range(len(boneIds)): boneId = boneIds[iBone] bone = nodes.bones[boneId] if isinstance(bone, CharacterJoint): boneTform = bone.getTransformState() pos = boneTform.getPos() boneMat = boneTform.getMat().getUpper3() #boneMat.transposeInPlace() rot = mat3NormalizedToEulO(boneMat) else: pos = Vec3() rot = Vec3() smd += boneFrameString(boneId, pos, rot) else: smd += "0 0 0 0 0 0 0\n" smd += "end\n" smd += "triangles\n" for geom in geomNp.node().getGeoms(): geom = geom.decompose() vdata = geom.getVertexData() blendTable = vdata.getTransformBlendTable() for prim in geom.getPrimitives(): numTris = prim.getNumPrimitives() for nTri in range(numTris): start = prim.getPrimitiveStart(nTri) end = prim.getPrimitiveEnd(nTri) smd += "no_material\n" for primVert in range(start, end): vertIdx = prim.getVertex(primVert) reader = GeomVertexReader(vdata) reader.setColumn(InternalName.getVertex()) reader.setRow(vertIdx) pos = reader.getData3f() uv = Vec2(0, 0) if vdata.hasColumn(InternalName.getTexcoord()): reader.setColumn(InternalName.getTexcoord()) reader.setRow(vertIdx) uv = reader.getData2f() norm = Vec3.forward() if vdata.hasColumn(InternalName.getNormal()): reader.setColumn(InternalName.getNormal()) reader.setRow(vertIdx) norm = reader.getData3f() smd += "0 {0:.6f} {1:.6f} {2:.6f} {3:.6f} {4:.6f} {5:.6f} {6:.6f} {7:.6f} ".format( pos[0], pos[1], pos[2], norm[0], norm[1], norm[2], uv[0], uv[1]) if (isCharacter and blendTable and vdata.getNumArrays() > 1 and vdata.getArray(1).hasColumn( InternalName.getTransformBlend())): reader.setColumn( 1, vdata.getArray( 1).getArrayFormat().getColumn( InternalName.getTransformBlend())) reader.setRow(vertIdx) nBlend = reader.getData1i() blend = blendTable.getBlend(nBlend) numTransforms = blend.getNumTransforms() smd += "{0} ".format(numTransforms) for nTransform in range(numTransforms): transform = blend.getTransform(nTransform) if isinstance(transform, JointVertexTransform): boneId = nodes.getBoneId( transform.getJoint()) smd += "{0} {1:.6f} ".format( boneId, blend.getWeight(nTransform)) else: smd += "1 0 1.0" smd += "\n" smd += "end\n" smdFile = geomNp.getName() if len(smdFile) == 0: smdFile = getUnknownName() elif names.get(smdFile, 0) > 0: smdFile = smdFile + "_{0}".format(names[smdFile]) names[smdFile] += 1 else: names[smdFile] = 1 smdFile += ".smd" outFile = open(outputPath + "\\" + smdFile, "w") outFile.write(smd) outFile.flush() outFile.close() else: bundles = scene.findAllMatches("**/+AnimBundleNode") bundle = bundles[0].node().getBundle() nodes = Skeleton(bundles) smd = "version 1\n" smd += str(nodes) smd += "skeleton\n" numFrames = bundle.getNumFrames() boneIds = sorted(nodes.bones.keys()) for iFrame in range(numFrames): smd += "time {0}\n".format(iFrame) for iBone in range(len(boneIds)): bone = nodes.getBone(boneIds[iBone]) if isinstance(bone, AnimChannelACMatrixSwitchType): boneFrameMat = Mat4() bone.getValueNoScaleShear(iFrame, boneFrameMat) boneFrameTransform = TransformState.makeMat(boneFrameMat) pos = boneFrameTransform.getPos() rotMat = boneFrameMat.getUpper3() #rotMat.transposeInPlace() rot = mat3NormalizedToEulO(rotMat) smd += boneFrameString(boneIds[iBone], pos, rot) smd += "end\n" smdFile = fPath.getBasenameWoExtension() + ".smd" outFile = open(outputPath + "\\" + smdFile, "w") outFile.write(smd) outFile.flush() outFile.close()
def __init__(self): super().__init__() self.model = 'radiosity_test' # self.texture = 'project_browser_bg' self.scale *= 4 player = FirstPersonController() # self.vertices_colored = 0 # geomNodeCollection = self.model.findAllMatches('**/+GeomNode') for nodePath in geomNodeCollection: geomNode = nodePath.node() for i in range(geomNode.getNumGeoms()): # geom = geomNode.getGeom(i) # read geom = geomNode.modifyGeom(i) # vdata = geom.getVertexData() vdata = geom.modifyVertexData() vertex = GeomVertexReader(vdata, 'vertex') vert_color = GeomVertexReader(vdata, 'color') print(vert_color) normal = GeomVertexReader(vdata, 'normal') new_color = GeomVertexWriter(vdata, 'color') verts = list() while not vertex.isAtEnd(): v = vertex.getData3f() verts.append(v) n = normal.getData3f() try: c = vert_color.getData4f() if c == color.yellow: light_position = v # light_normal = n except: pass print(len(verts)) vertex = GeomVertexReader(vdata, 'vertex') # print(vertex) while not vertex.isAtEnd(): v = vertex.getData3f() n = normal.getData3f() try: c = vert_color.getData4f() if c != color.yellow: # if n[0] > .5: dist = distance(light_position, v) new_color.setData4f(color.color(0, 0, 1-dist/2)) # new_color.setData4f(color.rgba(n[0], n[1], n[2])) # break_outer = False # temp_point = v # for i in range(1): # if break_outer: # break # # temp_point = (temp_point[0] + n[0], temp_point[1] + n[1], temp_point[2] + n[2]) # # if distance(temp_point, light_position) < i * i * .2: # # new_color.setData4f(color.color(60, 1, i/10 , 1)) # # break # for p in verts: # dist = distance(temp_point, p) # if dist < .01: # print('hit self') # continue # elif dist < .5: # print('hit after', i) # break # break_outer = True # print('ignore') except: pass
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