def test_materialattrib_compare(): mat1 = core.Material() mat2 = core.Material() # Two empty attribs mattr1 = core.MaterialAttrib.make_off() mattr2 = core.MaterialAttrib.make_off() assert mattr1.compare_to(mattr2) == 0 assert mattr2.compare_to(mattr1) == 0 # One empty attrib, one with a material mattr1 = core.MaterialAttrib.make_off() mattr2 = core.MaterialAttrib.make(mat1) assert mattr1 != mattr2 assert mattr1.compare_to(mattr2) != 0 assert mattr2.compare_to(mattr1) != 0 assert mattr1.compare_to(mattr2) == -mattr2.compare_to(mattr1) # Two attribs with same material mattr1 = core.MaterialAttrib.make(mat1) mattr2 = core.MaterialAttrib.make(mat1) assert mattr1.compare_to(mattr2) == 0 assert mattr2.compare_to(mattr1) == 0 # Two different materials mattr1 = core.MaterialAttrib.make(mat1) mattr2 = core.MaterialAttrib.make(mat2) assert mattr1 != mattr2 assert mattr1.compare_to(mattr2) != 0 assert mattr2.compare_to(mattr1) != 0 assert mattr1.compare_to(mattr2) == -mattr2.compare_to(mattr1)
def material_attrib(request): """Returns two MaterialAttribs: one with material, one without. It shouldn't really matter what we set them to, since the tests in here do not use lighting, and therefore the material should be ignored.""" if request.param == "mat:off": return core.MaterialAttrib.make_off() elif request.param == "mat:empty": return core.MaterialAttrib.make(core.Material()) elif request.param == "mat:amb": mat = core.Material() mat.ambient = (0.1, 1, 0.5, 1) return core.MaterialAttrib.make(mat) elif request.param == "mat:diff": mat = core.Material() mat.diffuse = (0.1, 1, 0.5, 1) return core.MaterialAttrib.make(mat) elif request.param == "mat:both": mat = core.Material() mat.diffuse = (0.1, 1, 0.5, 1) mat.ambient = (0.1, 1, 0.5, 1) return core.MaterialAttrib.make(mat)
def test_color_transparency_no_light(color_region, shader_attrib): mat = core.Material() mat.diffuse = (1, 1, 1, 0.75) material_attrib = core.MaterialAttrib.make(mat) state = core.RenderState.make( core.TransparencyAttrib.make(core.TransparencyAttrib.M_alpha), shader_attrib, material_attrib, ) result = render_color_pixel(color_region, state) assert result.x == pytest.approx(1.0, 0.1)
def update_graph(self, scene_graph, materials_only): """Update scene graph. This function rebuild scene completely each time when something changed. TODO: update changed nodes instead. Arguments: scene_graph {SceneGraph} -- scene description materials_only {bool} -- update only shape materials """ for uid, model_np in self._nodes.items(): model_np.detach_node() self._nodes = {} self._seg_node_map = {} for uid, link in scene_graph.nodes.items(): model_np = self._render.attach_new_node( p3d.ModelNode(f'#link_{link.body}_{link.link}')) model_np.node().set_preserve_transform(p3d.ModelNode.PTLocal) self._nodes[uid] = model_np for shape in link.shapes: if shape.mesh is None: mesh = Mesh.from_trimesh(primitive_mesh(shape)) elif shape.mesh.data is None: filename = os.path.abspath(shape.mesh.filename) mesh = self._loader.load_sync(filename) else: mesh = Mesh.from_mesh_data(shape.mesh.data) mesh_np = model_np.attach_new_node(mesh) mesh_np.set_mat((*shape.pose.matrix.ravel(), )) if shape.material is not None: mesh_np.set_color((*shape.material.diffuse_color, )) material = p3d.Material() material.set_diffuse((*shape.material.diffuse_color, )) material.set_ambient((*shape.material.diffuse_color, )) material.set_specular( (*shape.material.specular_color, 0.0)) material.set_roughness(0.4) mesh_np.set_material(material, 1) if shape.material.diffuse_color[3] < 1.0: mesh_np.set_transparency( p3d.TransparencyAttrib.M_alpha) if shape.material.diffuse_texture: filename = os.path.abspath( shape.material.diffuse_texture.filename) texture = p3d.TexturePool.load_texture(filename) mesh_np.set_texture(texture, 1)
def test_color_transparency_flat(color_region, shader_attrib, light_attrib): mat = core.Material() mat.diffuse = (1, 1, 1, 0.75) material_attrib = core.MaterialAttrib.make(mat) state = core.RenderState.make( core.TransparencyAttrib.make(core.TransparencyAttrib.M_alpha), core.ColorAttrib.make_flat(TEST_COLOR), light_attrib, shader_attrib, material_attrib, ) result = render_color_pixel(color_region, state) assert result.x == pytest.approx(0.75, 0.1)
def test_property2(): # This is a property defined by MAKE_PROPERTY2, that can be None. mat = core.Material() mat.ambient = (1, 0, 0, 1) assert mat.ambient == (1, 0, 0, 1) mat.ambient = None assert mat.ambient is None with pytest.raises(TypeError): mat.ambient = "nonsense" with pytest.raises(TypeError): del mat.ambient
def init_terrain(self, entity): component = entity[Terrain] noise = core.StackedPerlinNoise2() scaled_size = int(component.size * component.resolution) heightmap_size = scaled_size # + 1 print(f"Terrain complexity: {scaled_size}") max_mag = 0.0 for mag, scale in component.octaves: if mag > max_mag: max_mag = mag for mag, scale in component.octaves: scale /= component.size noise.add_level( core.PerlinNoise2(scale, scale, 256, component.seed), mag / max_mag) heightfield = core.PNMImage(heightmap_size, heightmap_size, 1) heightfield.set_maxval(0xffff) #heightfield.perlin_noise_fill(noise) status = heightfield.read( core.Filename.expand_from( '$MAIN_DIR/assets/textures/heightmap.png')) assert status, "Could not read heightmap" #heightfield.make_grayscale() #assert heightfield.is_grayscale() # We use GeoMipTerrain just for determining the normals at the moment. heightfield2 = core.PNMImage(heightmap_size + 1, heightmap_size + 1, 1) heightfield2.set_maxval(0xffff) heightfield2.copy_sub_image(heightfield, 0, 0) terrain = core.GeoMipTerrain(entity._uid.name) terrain.set_heightfield(heightfield2) terrain.set_bruteforce(True) terrain.set_block_size(min(32, scaled_size)) #terrain.set_color_map(heightfield) # Store both height and normal in the same texture. nimg = core.PNMImage(heightmap_size, heightmap_size, 4, color_space=core.CS_linear) for x in range(heightmap_size): for y in range(heightmap_size): normal = terrain.get_normal(x, y) normal.x *= component.resolution normal.y *= component.resolution normal.z /= max_mag normal.normalize() nimg.set_xel(x, y, normal * 0.5 + 0.5) #nimg.set_alpha(x, y, terrain.get_elevation(x, y)) nimg.set_alpha(x, y, heightfield.get_gray(x, y)) ntex = core.Texture("normal") ntex.load(nimg) ntex.wrap_u = core.SamplerState.WM_repeat ntex.wrap_v = core.SamplerState.WM_repeat ntex.set_keep_ram_image(True) component._peeker = ntex.peek() root = terrain.get_root() root.set_scale(1.0 / component.resolution, 1.0 / component.resolution, max_mag) #root.reparent_to(base.render) #root.set_texture(htex) #terrain.generate() mat = core.Material() #mat.base_color = (0.16, 0.223, 0.076, 1) mat.base_color = (0.4, 0.6, 0.4, 1) mat.base_color = (41.6 / 255.0, 73.7 / 255.0, 29.0 / 255.0, 1) #print(mat.base_color) mat.roughness = 1 #root.set_material(mat) simg = core.PNMImage(64, 64, 1) simg.fill(1) component._sat_img = simg component._sat_tex = core.Texture() component._sat_tex.load(simg) component._scale = core.VBase3(component.resolution / scaled_size, component.resolution / scaled_size, max_mag) component._wind_map = loader.load_texture("assets/textures/wind.png") component._wind_sound = loader.load_sfx("assets/sfx/wind-low.ogg") component._wind_sound.set_loop(True) grass_root = render.attach_new_node("grass") grass_root.set_shader( core.Shader.load(core.Shader.SL_GLSL, "assets/shaders/grass.vert", "assets/shaders/grass.frag"), 20) render.set_shader_input("scale", component.resolution / scaled_size, component.resolution / scaled_size, max_mag) grass_root.set_shader_input("terrainmap", ntex) render.set_shader_input("windmap", component._wind_map) grass_root.set_material(mat) grass_root.set_shader_input("player", 0, 0, 0) render.set_shader_input("satmap", component._sat_tex) #grass_root.node().set_bounds(core.BoundingSphere()) #grass_root.node().set_final(True) grass_root.set_bin('background', 10) if base.quality == 0: patch = loader.load_model("assets/models/patch-potato.bam") elif base.quality == 1: patch = loader.load_model("assets/models/patch-low.bam") else: patch = loader.load_model("assets/models/patch.bam") patch_size = int(patch.get_tag('patch_size')) self._r_build_grass_octree(grass_root, patch, patch_size, component.size * 2) grass_root.set_pos(-0.5 * component.size, -0.5 * component.size, 8) component._grass_root = grass_root
def setup_terrain(self): self.heightfield = self.noise.terrain() f = sdf.circle((30, 30), 15) avg = np.max(self.heightfield[713:743, 713:743]) self.heightfield[713:743, 713:743][f] = avg # self.heightfield[self.__bounds] -= 0.1 # self.heightfield = np.clip(self.heightfield, 0, 1) hf = (self.heightfield * 255).astype(np.uint8) f = core.TemporaryFile(core.Filename('assets', 'terrain.png')) im = Image.fromarray(hf) im.save(f.get_filename().get_fullpath()) self.terrain = core.GeoMipTerrain('terrain') self.terrain.set_heightfield(f.get_filename()) self.terrain.set_block_size(32) self.terrain.set_near(2) self.terrain.set_far(100) self.terrain.set_focal_point(self.camera) self.terrain_root = self.terrain.get_root() self.terrain_root.reparent_to(self.render) self.terrain_root.set_scale(common.T_XY_SCALE, common.T_XY_SCALE, common.T_Z_SCALE) offset = common.T_XY * common.T_XY_SCALE / 2 self.terrain_offset = core.Vec3(-offset, -offset, 0) self.terrain_root.set_pos(self.terrain_offset) tex = self.loader.load_texture('grass.jpg') tex.set_minfilter(core.SamplerState.FT_linear_mipmap_linear) tex.set_anisotropic_degree(2) self.terrain_root.set_texture(tex, 1) self.terrain_root.set_tex_scale(core.TextureStage.get_default(), 50) self.terrain.generate() # Stones where the tower is... rot = self.render.attach_new_node('rot') d = rot.attach_new_node('d') for i in range(40): d.set_y(random.uniform(common.T_ST_Y_MIN, common.T_ST_Y_MAX)) rot.set_h(360 / 40 * (i + random.random() - 0.5)) node_path = modelgen.stone( core.Vec2( random.uniform(common.T_ST_MIN_SIZE, common.T_ST_MAX_SIZE), random.uniform(common.T_ST_MIN_SIZE, common.T_ST_MAX_SIZE))) node_path.reparent_to(self.render) node_path.set_pos(d.get_pos(self.render)) node_path.set_hpr(random.uniform(0, 360), random.uniform(0, 360), random.uniform(0, 360)) node_path.set_z( self.sample_terrain_z(*tuple(node_path.get_pos().xy)) - 1) # Obelisks mat = core.Material('mat') mat.set_emission(core.Vec4(0.2, 0.4, 0.1, 1)) for i, (x, y) in enumerate(self.ob_coords): stone_circle = modelgen.stone_circle(20, 30) node_path = modelgen.obelisk() node_path.reparent_to(stone_circle) stone_circle.reparent_to(self.render) node_path.set_material(mat) hs = common.T_XY * common.T_XY_SCALE / 2 wx = x * common.T_XY_SCALE - hs stone_circle.set_x(wx) wy = y * common.T_XY_SCALE - hs stone_circle.set_y(wy) stone_circle.set_z(self.sample_terrain_z(wx, wy)) self.collision.add( collision.CollisionCircle( core.Vec2(wx, wy), 2, )) self.collision.add( collision.CollisionCircle(core.Vec2(wx, wy), 30, (self.__obelisk_found_event, (i, )), ghost=True)) self.collision.add( collision.CollisionCircle(core.Vec2(wx, wy), 12, (self.__toggle_nonogram, (i, )), ghost=True)) self.task_mgr.add(self.__update_terrain, 'update_task')
from panda3d import core mat = core.Material() mat.base_color = (2.0, 0.75, 0.6, 1) model = core.NodePath(core.ModelPool.load_model("assets/models/flower.bam")) model.find('**/petals').set_material(mat, 10000000) model.find('**/petals').set_light_off(100) model.find('**/leafs').remove_node() model.find('**/vine').remove_node() # Work around blend2bam bug that manifests when flattening for gnode in model.find_all_matches("**/+GeomNode"): for geom in gnode.node().modify_geoms(): vdata = geom.modify_vertex_data() if not vdata.get_format().has_column("transform_blend") and vdata.get_transform_blend_table(): vdata.clear_transform_blend_table() model.flatten_strong() gnode = model.find("**/+GeomNode") gnode.name = "flower" #character = model.get_child(0) #model = core.NodePath(core.LODNode("flower")) #model.node().add_child(character.node()) #model.node().add_switch(50, 0) model.write_bam_file("assets/models/flower.bam") sga = core.SceneGraphAnalyzer() sga.add_node(model.node())