def make_plane(size=(1.0, 1.0)): """Make a plane geometry. Arguments: size {tuple} -- plane size x,y Returns: Geom -- p3d geometry """ vformat = GeomVertexFormat.get_v3n3t2() vdata = GeomVertexData('vdata', vformat, Geom.UHStatic) vdata.uncleanSetNumRows(4) vertex = GeomVertexWriter(vdata, 'vertex') normal = GeomVertexWriter(vdata, 'normal') tcoord = GeomVertexWriter(vdata, 'texcoord') quad = ((0, 0), (1, 0), (0, 1), (1, 1)) for u, v in quad: vertex.addData3((u - 0.5) * size[0], (v - 0.5) * size[1], 0) normal.addData3(0, 0, 1) tcoord.addData2(u, v) prim = GeomTriangles(Geom.UHStatic) prim.addVertices(0, 1, 2) prim.addVertices(2, 1, 3) geom = Geom(vdata) geom.addPrimitive(prim) return geom
def make_box(): """Make a uniform box geometry. Returns: Geom -- p3d geometry """ vformat = GeomVertexFormat.get_v3n3t2() vdata = GeomVertexData('vdata', vformat, Geom.UHStatic) vdata.uncleanSetNumRows(24) vertex = GeomVertexWriter(vdata, 'vertex') normal = GeomVertexWriter(vdata, 'normal') tcoord = GeomVertexWriter(vdata, 'texcoord') axes = itertools.permutations(np.eye(3), r=2) quad = ((0, 0), (1, 0), (0, 1), (1, 1)) for x, y in axes: z = np.cross(x, y) for u, v in quad: vertex.addData3(*(x * (u - 0.5) + y * (v - 0.5) + z * 0.5)) normal.addData3(*z) tcoord.addData2(u, v) prim = GeomTriangles(Geom.UHStatic) for i in range(0, 24, 4): prim.addVertices(i + 0, i + 1, i + 2) prim.addVertices(i + 2, i + 1, i + 3) geom = Geom(vdata) geom.addPrimitive(prim) return geom
def _get_geom_data_plate(build_plate_size: LVector2d, name: str = "") -> GeomVertexData: """Generate build plate GeomVertexData. Parameters ---------- build_plate_size : LVector2d Build plate size. name : str Name for the generated GeomVertexData. """ # noinspection PyArgumentList geom_data = GeomVertexData(name, GeomVertexFormat.get_v3t2(), Geom.UHStatic) geom_data.setNumRows(4) writer_vertex = GeomVertexWriter(geom_data, "vertex") writer_texture = GeomVertexWriter(geom_data, "texcoord") # Add build plate vertices writer_vertex.addData3d(0, 0, 0) writer_vertex.addData3d(build_plate_size.x, 0, 0) writer_vertex.addData3d(build_plate_size.x, build_plate_size.y, 0) writer_vertex.addData3d(0, build_plate_size.y, 0) for uv in [(0, 0), (1, 0), (1, 1), (0, 1)]: writer_texture.addData2(*uv) return geom_data
def make_capsule(radius, length, num_segments=16, num_rings=16): """Make capsule geometry. Arguments: radius {float} -- capsule radius length {float} -- capsule length Keyword Arguments: num_segments {int} -- segments number (default: {16}) num_rings {int} -- rings number (default: {16}) Returns: Geom -- p3d geometry """ vformat = GeomVertexFormat.get_v3n3t2() vdata = GeomVertexData('vdata', vformat, Geom.UHStatic) vdata.uncleanSetNumRows(num_segments * num_rings) vertex = GeomVertexWriter(vdata, 'vertex') normal = GeomVertexWriter(vdata, 'normal') tcoord = GeomVertexWriter(vdata, 'texcoord') for u in np.linspace(0, np.pi, num_rings): for v in np.linspace(0, 2 * np.pi, num_segments): x, y, z = np.cos(v) * np.sin(u), np.sin(v) * np.sin(u), np.cos(u) offset = np.sign(z) * 0.5 * length vertex.addData3(x * radius, y * radius, z * radius + offset) normal.addData3(x, y, z) tcoord.addData2(u / np.pi, v / (2 * np.pi)) prim = GeomTriangles(Geom.UHStatic) for i in range(num_rings - 1): for j in range(num_segments - 1): r0 = i * num_segments + j r1 = r0 + num_segments if i < num_rings - 2: prim.addVertices(r0, r1, r1 + 1) if i > 0: prim.addVertices(r0, r1 + 1, r0 + 1) geom = Geom(vdata) geom.addPrimitive(prim) return geom
def make_cylinder(num_segments=16, closed=True): """Make a uniform cylinder geometry. Keyword Arguments: num_segments {int} -- segments number (default: {16}) closed {bool} -- add caps (default: {True}) Returns: Geom -- p3d geometry """ vformat = GeomVertexFormat.get_v3n3t2() vdata = GeomVertexData('vdata', vformat, Geom.UHStatic) vertex = GeomVertexWriter(vdata, 'vertex') normal = GeomVertexWriter(vdata, 'normal') tcoord = GeomVertexWriter(vdata, 'texcoord') cyl_rows = num_segments * 2 cap_rows = num_segments + 1 if closed: vdata.uncleanSetNumRows(cyl_rows + 2 * cap_rows) else: vdata.uncleanSetNumRows(cyl_rows) for phi in np.linspace(0, 2 * np.pi, num_segments): x, y = np.cos(phi), np.sin(phi) for z in (-1, 1): vertex.addData3(x, y, z * 0.5) normal.addData3(x, y, 0) tcoord.addData2(phi / (2 * np.pi), (z + 1) / 2) prim = GeomTriangles(Geom.UHStatic) for i in range(num_segments - 1): prim.addVertices(i * 2, i * 2 + 3, i * 2 + 1) prim.addVertices(i * 2, i * 2 + 2, i * 2 + 3) if closed: for z in (-1, 1): vertex.addData3(0, 0, z * 0.5) normal.addData3(0, 0, z) tcoord.addData2(0, 0) for phi in np.linspace(0, 2 * np.pi, num_segments): x, y = np.cos(phi), np.sin(phi) vertex.addData3(x, y, z * 0.5) normal.addData3(0, 0, z) tcoord.addData2(x, y) for i in range(num_segments): r0 = cyl_rows r1 = r0 + cap_rows prim.addVertices(r0, r0 + i + 1, r0 + i) prim.addVertices(r1, r1 + i, r1 + i + 1) geom = Geom(vdata) geom.addPrimitive(prim) return geom
def gen_geom(self, mesh_json): # Create vertex format geom_array = GeomVertexArrayFormat() geom_array.add_column("vertex", 3, Geom.NTFloat32, Geom.CPoint) has_normals = False has_texcoords = False has_weights = False if "normals" in mesh_json: geom_array.add_column("normal", 3, Geom.NTFloat32, Geom.CNormal) has_normals = True if "texcoords" in mesh_json: geom_array.add_column("texcoord", 3, Geom.NTFloat32, Geom.CTexcoord) has_texcoords = True if "weights" in mesh_json: geom_array.add_column("joint", 4, Geom.NTUint8, Geom.CIndex) geom_array.add_column("weight", 4, Geom.NTFloat32, Geom.COther) has_weights = True geom_format = GeomVertexFormat() geom_format.add_array(geom_array) geom_format = GeomVertexFormat.register_format(geom_format) # Set up vertex data vdata = GeomVertexData( str(random.randint(0, 255)) + "_vdata", geom_format, Geom.UHStatic) vcount = len(mesh_json["vertices"]) // 3 vdata.setNumRows(vcount) vertex = GeomVertexWriter(vdata, "vertex") for i in range(vcount): vertex.addData3(mesh_json["vertices"][3 * i], mesh_json["vertices"][3 * i + 1], mesh_json["vertices"][3 * i + 2]) if has_normals: normal = GeomVertexWriter(vdata, "normal") for i in range(vcount): normal.addData3(mesh_json["normals"][3 * i], mesh_json["normals"][3 * i + 1], mesh_json["normals"][3 * i + 2]) if has_texcoords: texcoord = GeomVertexWriter(vdata, "texcoord") for i in range(vcount): texcoord.addData2(mesh_json["texcoords"][2 * i], mesh_json["texcoords"][2 * i + 1]) if has_weights: joint = GeomVertexWriter(vdata, "joint") weight = GeomVertexWriter(vdata, "weight") for i in range(vcount): joint_count = len(mesh_json["joints"][i]) joint.addData4( 0 if joint_count < 1 else mesh_json["joints"][i][0], 0 if joint_count < 2 else mesh_json["joints"][i][1], 0 if joint_count < 3 else mesh_json["joints"][i][2], 0 if joint_count < 4 else mesh_json["joints"][i][3]) weight.addData4( 0 if joint_count < 1 else mesh_json["weights"][i][0], 0 if joint_count < 2 else mesh_json["weights"][i][1], 0 if joint_count < 3 else mesh_json["weights"][i][2], 0 if joint_count < 4 else mesh_json["weights"][i][3]) # Create primitive prim = GeomTriangles(Geom.UHStatic) for i in range(vcount // 3): prim.addVertices(3 * i, 3 * i + 1, 3 * i + 2) geom = Geom(vdata) geom.add_primitive(prim) # Load texture tex = None if "texture" in mesh_json: tex = Loader(EComponent.base).loadTexture( (Path("resources") / mesh_json["texture"]).absolute()) tex.setMagfilter(SamplerState.FT_nearest) tex.setMinfilter(SamplerState.FT_nearest) # Create new geometry node geom_node = GeomNode(str(random.randint(0, 255)) + "_node") if tex is None: geom_node.addGeom(geom) else: attrib = TextureAttrib.make(tex) state = RenderState.make(attrib) geom_node.addGeom(geom, state) if EComponent.panda_root_node is not None: self.geom_path = EComponent.panda_root_node.attach_new_node( geom_node) self.geom_path.set_shader_input("object_id", self.object_id) # Set shader if has_weights and self.geom_path is not None: self.geom_path.setTag("shader type", "skinned") bone_mats = PTA_LMatrix4f() for _ in range(100): bone_mats.push_back(helper.np_mat4_to_panda(np.identity(4))) self.geom_path.set_shader_input(f"boneMats", bone_mats) # Disable culling self.geom_path.node().setBounds(OmniBoundingVolume()) self.geom_path.node().setFinal(True)
class RoadBuilder(): def __init__(self): self.debugSphere = render.find("scene.dae").find("Scene").find( "debug_sphere") self.debugVector = render.find("scene.dae").find("Scene").find( "debug_vector") self.vdata = GeomVertexData('road', GeomVertexFormat.getV3t2(), Geom.UHStatic) # TODO: call this with right number of rows when it is known # self.vdata.setNumRows() self.vertex = GeomVertexWriter(self.vdata, 'vertex') self.texcoord = GeomVertexWriter(self.vdata, 'texcoord') self.prim = None self.prims = [] self.lastv = 0 self.vertices = [] self.lru_vertices = [] def addPrim(self): if self.prim is not None: for vertex in self.vertices: self.prim.addVertex(vertex) self.prims.append(self.prim) self.prim = GeomTriangles(Geom.UHStatic) def snapToExisting(self, point, tolerance=0.1): CACHE_SIZE = 1024 for i in self.lru_vertices: if (point - i).length() < tolerance: return i self.lru_vertices.append(point) if len(self.lru_vertices) > CACHE_SIZE: self.lru_vertices = self.lru_vertices[0:CACHE_SIZE] return point def updateTask(self, dt): self.nodepath.setShaderInput("time", (globalClock.getFrameTime())) return Task.cont def addSegment(self, p0, p1): width = HALF_ROAD_WIDTH side = -(p1 - p0).cross(Vec3().up()).normalized() * width length = (p1 - p0) h = (p1 - p0).length() v1 = side v2 = side + length v3 = -side + length v4 = -side v1 += p0 v2 += p0 v3 += p0 v4 += p0 v1 = self.snapToExisting(v1) v2 = self.snapToExisting(v2) v3 = self.snapToExisting(v3) v4 = self.snapToExisting(v4) self.vertex.addData3(v1) self.texcoord.addData2(1, 0) self.vertex.addData3(v2) self.texcoord.addData2(1, 1) self.vertex.addData3(v3) self.texcoord.addData2(0, 1) self.vertex.addData3(v4) self.texcoord.addData2(0, 0) lastv = self.lastv self.vertices.append(0 + lastv) self.vertices.append(1 + lastv) self.vertices.append(2 + lastv) self.vertices.append(3 + lastv) self.vertices.append(2 + lastv) self.vertices.append(0 + lastv) self.lastv += 4 def finish(self): self.geom = Geom(self.vdata) for prim in self.prims: self.geom.addPrimitive(prim) self.road_visual_node = GeomNode('road_node') visnode = self.road_visual_node visnode.addGeom(self.geom) self.road_visual_nodePath = render.attachNewNode(visnode) nodepath = self.road_visual_nodePath nodepath.setTwoSided(True) nodepath.setShader( Shader.load(Shader.SL_GLSL, vertex="shaders/road.vert", fragment="shaders/road.frag")) pleaseMakeTransparent(nodepath) self.nodepath = nodepath taskMgr.add(self.updateTask, "updateTask") self.lru_vertices = []
def __init__(self): ShowBase.__init__(self) props = WindowProperties() props.setTitle("The Rat Cave") self.win.requestProperties(props) self.win.setClearColor((0.5, 0.5, 0.9, 1.0)) self.disableMouse() self.locked = False lens = PerspectiveLens() lens.set_fov(70) self.cam.node().setLens(lens) self.position = [30, 30, 30] self.velocity = [0, 0, 0] self.setFrameRateMeter(True) self.myFog = Fog("Fog Name") self.myFog.setColor(0.5, 0.5, 0.9) self.myFog.setExpDensity(0.005) render.setFog(self.myFog) #cool bg #b=OnscreenImage(parent=render2d, image="space.png") #base.cam.node().getDisplayRegion(0).setSort(20) render.setAntialias(AntialiasAttrib.MMultisample) debugNode = BulletDebugNode('Debug') debugNode.showWireframe(True) debugNode.showConstraints(True) debugNode.showBoundingBoxes(False) debugNode.showNormals(False) debugNP = render.attachNewNode(debugNode) debugNP.show() self.world = BulletWorld() self.world.setGravity(Vec3(0, 0, -80)) #self.world.setDebugNode(debugNP.node()) loader = Loader(self) myShader = Shader.load(Shader.SL_GLSL, vertex="vertshader.vert", fragment="fragshader.frag") floorMesh = BulletTriangleMesh() texs = [ loader.loadTexture("flatstone.png"), loader.loadTexture("flatstone2.png"), loader.loadTexture("flatgrass.png"), loader.loadTexture("flatgrass2.png"), loader.loadTexture("flatrock.png"), loader.loadTexture("flatrock2.png"), loader.loadTexture("flatsnow.png"), loader.loadTexture("flatsand.png"), loader.loadTexture("flatsand2.png") ] hmap = generator.generate(200, 200, 50, 0.01, 5) groundTypes = [[] for x in range(9)] for thing in hmap: groundTypes[thing[3]].append(thing[0:3]) for i in range(len(groundTypes)): if len(groundTypes[i]) == 0: continue format = GeomVertexFormat.get_v3n3t2() format = GeomVertexFormat.registerFormat(format) vdata = GeomVertexData('name', format, Geom.UHStatic) vdata.setNumRows(3) vertex = GeomVertexWriter(vdata, 'vertex') normal = GeomVertexWriter(vdata, 'normal') texcoord = GeomVertexWriter(vdata, 'texcoord') prim = GeomTriangles(Geom.UHStatic) for grid in groundTypes[i]: v0 = (grid[0][0], grid[0][2], grid[0][1]) vertex.addData3(v0) if grid[1][2] < 0: normal.addData3(grid[1][0], grid[1][2], grid[1][1]) else: normal.addData3(-grid[1][0], -grid[1][2], -grid[1][1]) texcoord.addData2(grid[2][0], grid[2][1]) v1 = (grid[0][3], grid[0][5], grid[0][4]) vertex.addData3(v1) if grid[1][5] < 0: normal.addData3(grid[1][3], grid[1][5], grid[1][4]) else: normal.addData3(-grid[1][3], -grid[1][5], -grid[1][4]) texcoord.addData2(grid[2][2], grid[2][3]) v2 = (grid[0][6], grid[0][8], grid[0][7]) vertex.addData3(v2) if grid[1][8] < 0: normal.addData3(grid[1][6], grid[1][8], grid[1][7]) else: normal.addData3(-grid[1][6], -grid[1][8], -grid[1][7]) texcoord.addData2(grid[2][4], grid[2][5]) floorMesh.addTriangle(v0, v1, v2) prim.add_next_vertices(3) geom = Geom(vdata) geom.addPrimitive(prim) node = GeomNode('gnode') node.addGeom(geom) nodePath = render.attachNewNode(node) nodePath.setTexture(texs[i]) nodePath.setShader(myShader) vdata2 = GeomVertexData('wata', format, Geom.UHStatic) vdata2.setNumRows(3) prim2 = GeomTriangles(Geom.UHStatic) vertex2 = GeomVertexWriter(vdata2, 'vertex') normal2 = GeomVertexWriter(vdata2, 'normal') texcoord2 = GeomVertexWriter(vdata2, 'texcoord') vertex2.addData3((0, 0, 0)) vertex2.addData3((200, 0, 0)) vertex2.addData3((0, 200, 0)) normal2.addData3((0, 0, 1)) normal2.addData3((0, 0, 1)) normal2.addData3((0, 0, 1)) texcoord2.addData2((0, 0)) texcoord2.addData2((1, 0)) texcoord2.addData2((0, 1)) prim2.addNextVertices(3) vertex2.addData3((200, 200, 0)) vertex2.addData3((0, 200, 0)) vertex2.addData3((200, 0, 0)) normal2.addData3((0, 0, 1)) normal2.addData3((0, 0, 1)) normal2.addData3((0, 0, 1)) texcoord2.addData2((1, 1)) texcoord2.addData2((0, 1)) texcoord2.addData2((1, 0)) prim2.addNextVertices(3) water = Geom(vdata2) water.addPrimitive(prim2) waterNode = GeomNode('water') waterNode.addGeom(water) waterNodePath = render.attachNewNode(waterNode) waterNodePath.setTransparency(True) waterNodePath.setTexture(loader.loadTexture("water.png")) floorMeshShape = BulletTriangleMeshShape(floorMesh, dynamic=False) fNode = BulletRigidBodyNode('floor') fNode.addShape(floorMeshShape) self.floorPhysNode = render.attachNewNode(fNode) self.world.attachRigidBody(fNode) for i in range(25): rat = loader.loadModel("deer.obj") rat.setScale((0.003, 0.003, 0.003)) rat.setHpr((0, 90, 0)) rat.setPos((0, 0, -0.8)) rat.setTexture(texs[5]) shape = BulletSphereShape(1) node = BulletRigidBodyNode('ratBox') #node.setAngularFactor((0,0,1)) node.setMass(10.0) node.addShape(shape) node.setActive(False) #node.friction = 1 np = render.attachNewNode(node) np.setPos((i % 5) * 2 + 40, int(i / 5) * 2 + 40, 50) self.world.attachRigidBody(node) rat.flattenLight() rat.reparentTo(np) #posInterval1 = rat.hprInterval(0.1, # Point3(10, 90, 0), # startHpr=Point3(-10, 90, 0)) #posInterval2 = rat.hprInterval(0.1, # Point3(-10, 90, 0), # startHpr=Point3(10,90,0)) #pandaPace = Sequence(posInterval1, posInterval2, # name="pandaPace" + str(i)) #pandaPace.loop() self.ratto = np self.deer = loader.loadModel("rat.obj") self.deer.setScale((0.15, 0.15, 0.15)) self.deer.setHpr((0, 90, 0)) self.deer.setPos((0, 0, -2)) self.deerShape = BulletBoxShape((3, 1, 3)) self.deerNode = BulletRigidBodyNode('deerBox') self.deerNode.setAngularFactor((0, 0, 1)) self.deerNode.setMass(10.0) self.deerNode.setFriction(1) self.deerNode.addShape(self.deerShape) self.deerNodePath = render.attachNewNode(self.deerNode) self.deerNodePath.setPos((30, 30, 130)) self.world.attachRigidBody(self.deerNode) self.deer.reparentTo(self.deerNodePath) self.keyMap = { "w": False, "s": False, "a": False, "d": False, "space": False, "lshift": False, "p": False, "o": False } self.accept("w", self.setKey, ["w", True]) self.accept("s", self.setKey, ["s", True]) self.accept("a", self.setKey, ["a", True]) self.accept("d", self.setKey, ["d", True]) self.accept("space", self.setKey, ["space", True]) self.accept("lshift", self.setKey, ["lshift", True]) self.accept("e", self.lockMouse) self.accept("p", self.setKey, ["p", True]) self.accept("o", self.setKey, ["o", True]) self.accept("w-up", self.setKey, ["w", False]) self.accept("s-up", self.setKey, ["s", False]) self.accept("a-up", self.setKey, ["a", False]) self.accept("d-up", self.setKey, ["d", False]) self.accept("space-up", self.setKey, ["space", False]) self.accept("lshift-up", self.setKey, ["lshift", False]) self.accept("e-up", self.setKey, ["e", False]) self.accept('escape', sys.exit) self.accept("p-up", self.setKey, ["p", False]) self.accept("o-up", self.setKey, ["o", False]) # Add the spinCameraTask procedure to the task manager. self.taskMgr.add(self.cameraControl, "CameraControl") self.camera.setPos(tuple(self.position))