def loadLevelData(self, inputData): """ processes the level asloaded from the file. it seperates the input data until the data for each tile is ready. """ rigidNode = RigidBodyCombiner("LevelNode") levelNode = NodePath(rigidNode) #deleting whitespaces and seperating the content for each tile into a list. inputData = inputData.replace("\n", "").strip().replace( " ", "").lstrip("<").rstrip(">").split("><") for tileData in inputData: tile = self.loadTile(tileData) if tile != None: tile.reparentTo(levelNode) tile.setPos(self.getPosFromTile(tile)) tile.setZ( tile, 0.00000001 ) # workaround for rigid body combiner so it does not assume the (0,0) tile as static else: print("ERROR, could not load tile with data: ", tileData) rigidNode.collect() inode = rigidNode.getInternalScene().node( ) # workaround for a boundingvolume issue with rigidbodycombiner inode.setBounds(OmniBoundingVolume()) # still workaround inode.setFinal(True) # still workaround return levelNode
def loadLevelData(self,inputData): """ processes the level asloaded from the file. it seperates the input data until the data for each tile is ready. each tile data will be passed to loadTile(). it returns a rigidNode optimized nodepath. """ rigidNode = RigidBodyCombiner("LevelNode") levelNode = NodePath(rigidNode) #rigidNode.reparentTo(levelNode) #this looks heavy but all it does is deleting whitespaces and seperating the content for each tile into a list. inputData = inputData.replace("\n","").strip().replace(" ","").lstrip("<").rstrip(">").split("><") for tileData in inputData: tile = self.loadTile(tileData) if tile != None: tile.reparentTo(levelNode) tile.setPos( self.getPosFromTile(tile) ) tile.setZ(tile,0.00000001) #workaround for rigid body combiner so it does not assume the (0,0) tile as static else: print("ERROR, could not load tile with data: ",tileData) rigidNode.collect() inode = rigidNode.getInternalScene().node() #workaround for a boundingvolume issue with rigidbodycombiner inode.setBounds(OmniBoundingVolume()) #still workaround inode.setFinal(True) #still workaround #levelNode.analyze() return levelNode
def _render_chunk(self, chunk: Chunk): # Create the chunk hierarchy in the scene graph. c_new_chunk = chunk.chunk_center chunk_path = self.path.attachNewNode( "chunk.%s.%s.%s" % (c_new_chunk[0], c_new_chunk[1], c_new_chunk[2])) chunk_model = chunk_path.attachNewNode('model') rbc = RigidBodyCombiner('chunk') rbcnp = NodePath(rbc) rbcnp.reparentTo(chunk_model) # Offset the matrix from the origin to the center of the new relative chunk. relative_spiral_matrix = np.array(self.cubic_spiral) spiral_matrix = relative_spiral_matrix + np.repeat( [c_new_chunk], repeats=relative_spiral_matrix.shape[0], axis=0) for ii, c_sp in enumerate(spiral_matrix): # TODO: remove the terrain generation and put in a generator class. center = (256, 256) o_x, o_y = cube_to_offset(c_sp) current_noise = self.terrain_noise[center[0] + o_x][center[1] + o_y] # TODO: noise times maximum height. work this out with the noise generation to make the jumps not drastic elevation = current_noise * 20 terrain = None if -1.0 <= current_noise <= -0.5: terrain = WaterTerrain(elevation=elevation) elif -0.9 <= current_noise <= 0.6: percent = (current_noise + 0.9) / 1.5 modulated_color = 0, 1 * percent, 0 terrain = GrassTerrain(elevation=elevation, color=modulated_color) else: # Cliff are steeper than most terrain. elevation = elevation * 1.5 terrain = CliffTerrain(elevation=elevation) c_rsp = relative_spiral_matrix[ii] loc = self.data_model.at_chunked(chunk.chunk_id, c_rsp) loc.major_terrain = terrain hex_loc = HexLocationComponent(chunk_path, loc, c_sp, self._hex_model) hex_loc.render(rbcnp, chunk_model) rbc.collect() return chunk_path
def setupPandaApp(mesh): scene_members = getSceneMembers(mesh) p3dApp = ShowBase() nodePath = getBaseNodePath(render) rotateNode = GeomNode("rotater") rotatePath = nodePath.attachNewNode(rotateNode) matrix = numpy.identity(4) if mesh.assetInfo.upaxis == collada.asset.UP_AXIS.X_UP: r = collada.scene.RotateTransform(0, 1, 0, 90) matrix = r.matrix elif mesh.assetInfo.upaxis == collada.asset.UP_AXIS.Y_UP: r = collada.scene.RotateTransform(1, 0, 0, 90) matrix = r.matrix rotatePath.setMat(Mat4(*matrix.T.flatten().tolist())) rbc = RigidBodyCombiner('combiner') rbcPath = rotatePath.attachNewNode(rbc) for geom, renderstate, mat4 in scene_members: node = GeomNode("primitive") node.addGeom(geom) if renderstate is not None: node.setGeomState(0, renderstate) geomPath = rbcPath.attachNewNode(node) geomPath.setMat(mat4) rbc.collect() ensureCameraAt(nodePath, base.camera) base.disableMouse() attachLights(render) render.setShaderAuto() render.setTransparency(TransparencyAttrib.MDual, 1) return p3dApp
def setupPandaApp(mesh): scene_members = getSceneMembers(mesh) p3dApp = ShowBase() nodePath = getBaseNodePath(render) rotateNode = GeomNode("rotater") rotatePath = nodePath.attachNewNode(rotateNode) matrix = numpy.identity(4) if mesh.assetInfo.upaxis == collada.asset.UP_AXIS.X_UP: r = collada.scene.RotateTransform(0,1,0,90) matrix = r.matrix elif mesh.assetInfo.upaxis == collada.asset.UP_AXIS.Y_UP: r = collada.scene.RotateTransform(1,0,0,90) matrix = r.matrix rotatePath.setMat(Mat4(*matrix.T.flatten().tolist())) rbc = RigidBodyCombiner('combiner') rbcPath = rotatePath.attachNewNode(rbc) for geom, renderstate, mat4 in scene_members: node = GeomNode("primitive") node.addGeom(geom) if renderstate is not None: node.setGeomState(0, renderstate) geomPath = rbcPath.attachNewNode(node) geomPath.setMat(mat4) rbc.collect() ensureCameraAt(nodePath, base.camera) base.disableMouse() attachLights(render) render.setShaderAuto() render.setTransparency(TransparencyAttrib.MDual, 1) return p3dApp
from direct.directbase.DirectStart import * from panda3d.core import RigidBodyCombiner, NodePath, Vec3 import random rbc = RigidBodyCombiner("rbc") rbcnp = NodePath(rbc) rbcnp.reparentTo(render) for i in range(200): pos = Vec3(random.uniform(-100, 100), random.uniform(-100, 100), random.uniform(-100, 100)) f = loader.loadModel("box.egg") f.setPos(pos) f.reparentTo(rbcnp) rbc.collect() run()
class WorldManager(object): """A world manager for heightmapped worlds stored as XML.""" def __init__(self): """Setup this world manager.""" Logger.info("Initializing world manager...") self.terrain = None self.portals = [] self.gates = [] self.objects = [] self.scenery = RigidBodyCombiner("scenery") self.scenery_np = render.attach_new_node(self.scenery) self.is_dirty = True base.task_mgr.add(self.run_logic) Logger.info("World manager initialized.") def load_map(self, map): """Load a map.""" #Unload the current map first self.unload_map() #Locate the XML file for the map Logger.info("Loading map '{}'...".format(map)) map_file = os.path.join(map, os.path.basename(map) + ".xml") if not os.path.exists(map_file): Logger.error("Failed to load map file '{}'.".format(map_file)) return False #Load the map XML file xml = etree.parse(map_file) root = xml.getroot() for child in root: #Terrain? if child.tag == "terrain": #Validate terrain if not ("size" in child.attrib and "spawnpos" in child.attrib and "heightmap" in child.attrib): Logger.error( "Terrain section must define 'size', 'spawnpos', and 'heightmap'." ) return False #Load terrain self.size = parse_vec(child.attrib["size"], 3) self.spawnpos = parse_vec(child.attrib["spawnpos"], 2) heightmap = os.path.join(map, child.attrib["heightmap"]) self.terrain = GeoMipTerrain("Terrain") self.terrain.set_block_size(64) self.terrain.set_bruteforce(True) if not self.terrain.set_heightfield(heightmap): Logger.error("Failed to load heightmap for terrain.") self.terrain = None return False self.terrain_np = self.terrain.get_root() self.terrain_np.set_scale(self.size[0] / 512, self.size[1] / 512, self.size[2]) tex = loader.load_texture( "./data/textures/terrain/grass_tex2.png") self.terrain_np.set_texture(tex) self.terrain_np.set_tex_scale(TextureStage.get_default(), self.size[0] / 512, self.size[1] / 512) tex.set_wrap_u(Texture.WM_repeat) tex.set_wrap_v(Texture.WM_repeat) self.terrain_np.reparent_to(render) self.terrain.generate() base.camera.set_pos(self.size[0] / 2, self.size[1] / 2, self.size[2]) #Portal? elif child.tag == "portal": #Validate portal if not ("pos" in child.attrib and "destmap" in child.attrib): Logger.warning("Portal must define 'pos' and 'destmap'.") continue #Load portal pos = parse_vec(child.attrib["pos"], 3) radius = parse_float( child.attrib["radius"]) if "radius" in child.attrib else 1 destmap = child.attrib["destmap"] self.add_portal(pos, radius, destmap) #Gate? elif child.tag == "gate": #Validate gate if not ("pos" in child.attrib and "destmap" in child.attrib and "destvec" in child.attrib): Logger.warning( "Gate must define 'pos', 'destmap', and 'destvec'.") continue #Load gate pos = parse_vec(child.attrib["pos"], 3) destmap = child.attrib["destmap"] destvec = parse_vec(child.attrib["destvec"], 3) material = child.attrib[ "material"] if "material" in child.attrib else "" self.add_gate(pos, destmap, destvec, material) #Object? elif child.tag == "object": #Validate object if not ("mesh" in child.attrib and "pos" in child.attrib): Logger.warning("Object must define 'mesh' and 'pos'.") continue #Load object mesh = child.attrib["mesh"] pos = parse_vec(child.attrib["pos"], 3) rot = parse_vec(child.attrib["rot"], 3) if "rot" in child.attrib else [0, 0, 0] scale = parse_vec(child.attrib["scale"], 3) if "scale" in child.attrib else [1, 1, 1] material = child.attrib[ "material"] if "material" in child.attrib else "" sound = child.attrib["sound"] if "sound" in child.attrib else "" self.add_object(mesh, pos, rot, scale, material, sound) #Object Group? elif child.tag == "objectgroup": #Validate object group if not ("mesh" in child.attrib): Logger.warning("Object group must define 'mesh'.") continue #Load object group mesh = child.attrib["mesh"] material = child.attrib[ "material"] if "material" in child.attrib else "" self.load_object_group(child, mesh, material) #Unknown? else: Logger.warning( "Unknown tag '{}' encountered in map '{}'.".format( child.tag, map)) #Map loaded Logger.info("Map '{}' loaded.".format(map)) return True def unload_map(self): """Unload the current map.""" if self.terrain is not None: self.terrain.get_root().remove_node() self.terrain = None self.size = [0, 0] self.spawnpos = [0, 0, 0] while len(self.portals) > 0: self.del_portal(self.portals[-1]) while len(self.gates) > 0: self.del_gate(self.gates[-1]) while len(self.objects) > 0: self.del_object(self.objects[-1]) def load_object_group(self, group, mesh, material): """Load a group of objects.""" for object in group: #Validate object if not ("pos" in object.attrib): Logger.warning("Group object must define 'pos'.") continue #Load object pos = parse_vec(object.attrib["pos"], 2) rot = parse_vec(object.attrib["rot"], 1) if "rot" in object.attrib else [0, 0, 0] scale = parse_vec(object.attrib["scale"], 1) if "scale" in object.attrib else [1, 1, 1] self.add_object(mesh, pos, rot, scale, material, "") def add_portal(self, pos, radius, dest): """Add a portal to this world.""" self.portals.append(Portal(pos, radius, dest)) self.is_dirty = True Logger.info("Added portal: pos = {}, radius = {}, dest = '{}'".format( pos, radius, dest)) def del_portal(self, portal): """Remove a portal from this world.""" self.portals.remove(portal) self.is_dirty = True Logger.info("Removed portal {}".format(portal)) def add_gate(self, pos, dest, destvec, material): """Add a gate to this world.""" self.gates.append(Gate(pos, dest, destvec, material)) self.is_dirty = True Logger.info( "Added gate: pos = {}, dest = '{}', destvec = {}, material = '{}'". format(pos, dest, destvec, material)) def del_gate(self, gate): """Remove a gate from this world.""" self.gates.remove(gate) self.is_dirty = True Logger.info("Removed gate {}".format(gate)) def add_object(self, mesh, pos, rot, scale, material, sound): """Add an object to this world.""" #Handle 2 coordinate position if len(pos) == 2: pos = [pos[0], pos[1], self.get_terrain_height(pos)] #Handle single coordinate rotation if len(rot) == 1: rot = [rot[0], 0, 0] #Handle single or double coordinate scale if len(scale) == 1: scale = [scale[0], scale[0], scale[0]] elif len(scale) == 2: scale = [scale[0], scale[1], 1] #Add the object self.objects.append(Object(mesh, pos, rot, scale, material, sound)) self.is_dirty = True Logger.info( "Added object: mesh = '{}', pos = {}, rot = {}, scale = {}, material = '{}', sound = '{}'" .format(mesh, pos, rot, scale, material, sound)) def del_object(self, object): """Delete an object from this world.""" self.objects.remove(object) self.is_dirty = True Logger.info("Removed object {}".format(object)) def get_terrain_height(self, pos): """Get the height of the terrain at the given point.""" #Is the position a list of 2 elements? if isinstance(pos, list) and len(pos) == 2: return self.terrain.get_elevation( pos[0] / (self.size[0] / 512), pos[1] / (self.size[1] / 512)) * self.size[2] #Assume it is a point object else: return self.terrain.get_elevation( pos[0] / (self.size[0] / 512), pos[1] / (self.size[1] / 512)) * self.size[2] def run_logic(self, task): """Run the logic for this world manager.""" #Optimize the scenery if self.is_dirty: self.scenery.collect() self.is_dirty = False Logger.info("Optimized the scenery.") return Task.cont