Fill leaves with objects described in obj_def

Property definitions

gamnit $ BuildModelFromObj :: fill_leaves
	# Fill `leaves` with objects described in `obj_def`
	fun fill_leaves(target_model: ModelAsset)
	do
		var leaves = target_model.leaves_cache

		# Sort faces by material
		var obj_mtl_to_faces = new Map[ObjObj, MultiHashMap[String, ObjFace]]
		for obj in obj_def.objects do
			var mtl_to_faces = new MultiHashMap[String, ObjFace]
			obj_mtl_to_faces[obj] = mtl_to_faces
			for face in obj.faces do
				var mtl_lib_name = face.material_lib
				var mtl_name = face.material_name

				var full_name = ""
				if mtl_lib_name != null and mtl_name != null then full_name = mtl_lib_name / mtl_name

				mtl_to_faces[full_name].add face
			end
		end

		# Load material libs
		var mtl_libs = sys.mtl_libs
		var lib_names = obj_def.material_libs
		for name in lib_names do
			var asset_path = self.path.dirname / name
			var lib_asset = new TextAsset(asset_path)
			lib_asset.load

			var error = lib_asset.error
			if error != null then
				errors.add error
				continue
			end

			var mtl_parser = new MtlFileParser(lib_asset.to_s)
			var mtl_lib = mtl_parser.parse
			mtl_libs[asset_path] = mtl_lib
		end

		# Create 1 mesh per material per object, and prepare materials
		var mesh_to_mtl = new Map[Mesh, nullable MtlDef]
		var mesh_to_name = new Map[Mesh, String]
		var texture_names = new Set[String]
		for obj in obj_def.objects do
			var mtl_to_faces = obj_mtl_to_faces[obj]
			for mtl_path, faces in mtl_to_faces do

				# Create mesh
				var mesh = new Mesh
				mesh.vertices = vertices(faces)
				mesh.normals = normals(faces)
				mesh.texture_coords = texture_coords(faces)

				# Material
				var mtl_def = null

				var mtl_lib_name = faces.first.material_lib
				var mtl_name = faces.first.material_name
				if mtl_lib_name != null and mtl_name != null then
					var asset_path = self.path.dirname / mtl_lib_name
					var mtl_lib = mtl_libs[asset_path]
					var mtl = mtl_lib.get_or_null(mtl_name)
					if mtl != null then
						mtl_def = mtl

						for e in mtl.maps do
							texture_names.add self.path.dirname / e
						end
					else
						errors.add new Error("Error loading model at '{path}': mtl '{mtl_name}' not found in '{asset_path}'")
					end
				end

				mesh_to_mtl[mesh] = mtl_def
				mesh_to_name[mesh] = obj.name
			end
		end

		# Load textures need for these materials
		for name in texture_names do
			if not asset_textures_by_name.keys.has(name) then
				var tex = new TextureAsset(name)
				asset_textures_by_name[name] = tex

				tex.load
				var error = tex.error
				if error != null then errors.add error
			end
		end

		# Create final `Materials` from defs and textures
		var materials = new Map[MtlDef, Material]
		for mtl in mesh_to_mtl.values do
			if mtl == null then continue

			var ambient = mtl.ambient.to_a
			ambient.add 1.0

			var diffuse = mtl.diffuse.to_a
			diffuse.add 1.0

			var specular = mtl.specular.to_a
			specular.add 1.0

			var material = new TexturedMaterial(ambient, diffuse, specular)
			materials[mtl] = material

			var tex_name = mtl.map_ambient
			if tex_name != null then
				tex_name = self.path.dirname / tex_name
				material.ambient_texture = asset_textures_by_name[tex_name]
			end

			tex_name = mtl.map_diffuse
			if tex_name != null then
				tex_name = self.path.dirname / tex_name
				material.diffuse_texture = asset_textures_by_name[tex_name]
			end

			tex_name = mtl.map_specular
			if tex_name != null then
				tex_name = self.path.dirname / tex_name
				material.specular_texture = asset_textures_by_name[tex_name]
			end
		end

		# Create models and store them
		var name_to_leaves = new MultiHashMap[String, LeafModel]
		for mesh, mtl_def in mesh_to_mtl do

			var material = materials.get_or_null(mtl_def)
			if material == null then material = new Material

			var model = new LeafModel(mesh, material)
			leaves.add model

			name_to_leaves[mesh_to_name[mesh]].add model
		end

		# Collect objects with a name
		for name, models in name_to_leaves do
			if models.length == 1 then
				target_model.named_leaves_cache[name] = models.first
			else
				var named_model = new CompositeModel
				named_model.leaves.add_all models
				target_model.named_leaves_cache[name] = named_model
			end
		end
	end
lib/gamnit/depth/more_models.nit:141,2--291,4