mirror of
				https://github.com/MapMakersAndProgrammers/alternativa3d-archive.git
				synced 2025-10-31 01:06:16 -07:00 
			
		
		
		
	more versions added
This commit is contained in:
		
							
								
								
									
										285
									
								
								Alternativa3D5/5.4.1/alternativa/engine3d/loaders/LoaderMTL.as
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								Alternativa3D5/5.4.1/alternativa/engine3d/loaders/LoaderMTL.as
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,285 @@ | ||||
| package alternativa.engine3d.loaders { | ||||
| 	import alternativa.engine3d.*; | ||||
| 	import alternativa.types.Map; | ||||
| 	import alternativa.utils.ColorUtils; | ||||
| 	 | ||||
| 	import flash.display.Bitmap; | ||||
| 	import flash.display.BitmapData; | ||||
| 	import flash.display.Loader; | ||||
| 	import flash.events.ErrorEvent; | ||||
| 	import flash.events.Event; | ||||
| 	import flash.events.EventDispatcher; | ||||
| 	import flash.events.IOErrorEvent; | ||||
| 	import flash.events.SecurityErrorEvent; | ||||
| 	import flash.geom.Point; | ||||
| 	import flash.net.URLLoader; | ||||
| 	import flash.net.URLRequest; | ||||
| 	import flash.system.LoaderContext; | ||||
| 	 | ||||
| 	use namespace alternativa3d; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * @private | ||||
| 	 * Загрузчик библиотеки материалов из файлов в формате MTL material format (Lightwave, OBJ). | ||||
| 	 * <p> | ||||
| 	 * На данный момент обеспечивается загрузка цвета, прозрачности и диффузной текстуры материала. | ||||
| 	 */ | ||||
| 	internal class LoaderMTL extends EventDispatcher { | ||||
| 		 | ||||
| 		private static const COMMENT_CHAR:String = "#"; | ||||
| 		private static const CMD_NEW_MATERIAL:String = "newmtl"; | ||||
| 		private static const CMD_DIFFUSE_REFLECTIVITY:String = "Kd"; | ||||
| 		private static const CMD_DISSOLVE:String = "d"; | ||||
| 		private static const CMD_MAP_DIFFUSE:String = "map_Kd"; | ||||
| 		 | ||||
| 		private static const REGEXP_TRIM:RegExp = /^\s*(.*?)\s*$/; | ||||
| 		private static const REGEXP_SPLIT_FILE:RegExp = /\r*\n/; | ||||
| 		private static const REGEXP_SPLIT_LINE:RegExp = /\s+/; | ||||
| 		 | ||||
| 		// Загрузчик файла MTL | ||||
| 		private var fileLoader:URLLoader; | ||||
| 		// Загрузчик файлов текстур | ||||
| 		private var bitmapLoader:Loader; | ||||
| 		// Контекст загрузки для bitmapLoader | ||||
| 		private var loaderContext:LoaderContext; | ||||
| 		// Базовый URL файла MTL | ||||
| 		private var baseUrl:String; | ||||
|  | ||||
| 		// Библиотека загруженных материалов | ||||
| 		private var _library:Map; | ||||
| 		// Список материалов, имеющих диффузные текстуры | ||||
| 		private var diffuseMaps:Map; | ||||
| 		// Имя текущего материала | ||||
| 		private var materialName:String; | ||||
| 		// параметры текущего материала | ||||
| 		private var currentMaterialInfo:MaterialInfo = new MaterialInfo(); | ||||
| 		 | ||||
| 		alternativa3d static var stubBitmapData:BitmapData; | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Создаёт новый экземпляр класса. | ||||
| 		 */ | ||||
| 		public function LoaderMTL() { | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Прекращение текущей загрузки. | ||||
| 		 */ | ||||
| 		public function close():void { | ||||
| 			try { | ||||
| 				fileLoader.close(); | ||||
| 			} catch (e:Error) { | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Библиотека материалов. Ключами являются наименования материалов, значениями -- объекты, наследники класса | ||||
| 		 * <code>alternativa.engine3d.loaders.MaterialInfo</code>. | ||||
| 		 * @see alternativa.engine3d.loaders.MaterialInfo | ||||
| 		 */ | ||||
| 		public function get library():Map { | ||||
| 			return _library; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Метод выполняет загрузку файла материалов, разбор его содержимого, загрузку текстур при необходимости и | ||||
| 		 * формирование библиотеки материалов. После окончания работы метода посылается сообщение | ||||
| 		 * <code>Event.COMPLETE</code> и становится доступна библиотека материалов через свойство <code>library</code>. | ||||
| 		 * <p> | ||||
| 		 * При возникновении ошибок, связанных с вводом-выводом или с безопасностью, посылаются сообщения <code>IOErrorEvent.IO_ERROR</code> и  | ||||
| 		 * <code>SecurityErrorEvent.SECURITY_ERROR</code> соответственно. | ||||
| 		 * <p> | ||||
| 		 * Если происходит ошибка при загрузке файла текстуры, то соответствующая текстура заменяется на текстуру-заглушку. | ||||
| 		 * <p> | ||||
| 		 * @param url URL MTL-файла | ||||
| 		 * @param loaderContext LoaderContext для загрузки файлов текстур | ||||
| 		 *   | ||||
| 		 * @see #library | ||||
| 		 */ | ||||
| 		public function load(url:String, loaderContext:LoaderContext = null):void { | ||||
| 			this.loaderContext = loaderContext; | ||||
| 			baseUrl = url.substring(0, url.lastIndexOf("/") + 1); | ||||
|  | ||||
| 			if (fileLoader == null) { | ||||
| 				fileLoader = new URLLoader(); | ||||
| 				fileLoader.addEventListener(Event.COMPLETE, parseMTLFile); | ||||
| 				fileLoader.addEventListener(IOErrorEvent.IO_ERROR, onError); | ||||
| 				fileLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError); | ||||
|  | ||||
| 				bitmapLoader = new Loader(); | ||||
| 				bitmapLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBitmapLoadComplete); | ||||
| 				bitmapLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onBitmapLoadComplete); | ||||
| 				bitmapLoader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onBitmapLoadComplete); | ||||
| 			} | ||||
| 			 | ||||
| 			try { | ||||
| 				fileLoader.close(); | ||||
| 				bitmapLoader.close(); | ||||
| 			} catch (e:Error) { | ||||
| 				// Пропуск ошибки при попытке закрытия неактивных загрузчиков | ||||
| 			} | ||||
| 			 | ||||
| 			fileLoader.load(new URLRequest(url)); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Разбор содержимого загруженного файла материалов. | ||||
| 		 */ | ||||
| 		private function parseMTLFile(e:Event = null):void { | ||||
| 			var lines:Array = fileLoader.data.split(REGEXP_SPLIT_FILE); | ||||
| 			_library = new Map(); | ||||
| 			diffuseMaps = new Map(); | ||||
| 			for each (var line:String in lines) { | ||||
| 				parseLine(line); | ||||
| 			} | ||||
| 			defineMaterial(); | ||||
| 			 | ||||
| 			if (diffuseMaps.isEmpty()) { | ||||
| 				// Текстур нет, загрузка окончена | ||||
| 				dispatchEvent(new Event(Event.COMPLETE)); | ||||
| 			} else { | ||||
| 				// Загрузка файлов текстур | ||||
| 				loadNextBitmap(); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Разбор строки файла. | ||||
| 		 *  | ||||
| 		 * @param line строка файла | ||||
| 		 */ | ||||
| 		private	function parseLine(line:String):void { | ||||
| 			line = line.replace(REGEXP_TRIM,"$1") | ||||
| 			if (line.length == 0 || line.charAt(0) == COMMENT_CHAR) { | ||||
| 				return; | ||||
| 			} | ||||
| 			var parts:Array = line.split(REGEXP_SPLIT_LINE); | ||||
| 			switch (parts[0]) { | ||||
| 				case CMD_NEW_MATERIAL: | ||||
| 					defineMaterial(parts); | ||||
| 					break; | ||||
| 				case CMD_DIFFUSE_REFLECTIVITY: | ||||
| 					readDiffuseReflectivity(parts); | ||||
| 					break; | ||||
| 				case CMD_DISSOLVE: | ||||
| 					readAlpha(parts); | ||||
| 					break; | ||||
| 				case CMD_MAP_DIFFUSE: | ||||
| 					parseDiffuseMapLine(parts); | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Определение нового материала. | ||||
| 		 */		 | ||||
| 		private function defineMaterial(parts:Array = null):void { | ||||
| 			if (materialName != null) { | ||||
| 				_library[materialName] = currentMaterialInfo; | ||||
| 			} | ||||
| 			if (parts != null) { | ||||
| 				materialName = parts[1]; | ||||
| 				currentMaterialInfo = new MaterialInfo(); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Чтение коэффициентов диффузного отражения. Считываются только коэффициенты, заданные в формате r g b. Для текущей | ||||
| 		 * версии движка данные коэффициенты преобразуются в цвет материала. | ||||
| 		 */ | ||||
| 		private function readDiffuseReflectivity(parts:Array):void { | ||||
| 			var r:Number = Number(parts[1]); | ||||
| 			// Проверка, заданы ли коэффициенты в виде r g b | ||||
| 			if (!isNaN(r)) { | ||||
| 				var g:Number = Number(parts[2]); | ||||
| 				var b:Number = Number(parts[3]); | ||||
| 				currentMaterialInfo.color = ColorUtils.rgb(255 * r, 255 * g, 255 * b);  | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/** | ||||
| 		 * Чтение коэффициента непрозрачности. Считывается только коэффициент, заданный числом | ||||
| 		 * (не поддерживается параметр -halo). | ||||
| 		 */ | ||||
| 		private function readAlpha(parts:Array):void { | ||||
| 			var alpha:Number = Number(parts[1]); | ||||
| 			if (!isNaN(alpha)) { | ||||
| 				currentMaterialInfo.alpha = alpha; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Разбор строки, задающей текстурную карту для диффузного отражения. | ||||
| 		 */ | ||||
| 		private function parseDiffuseMapLine(parts:Array):void { | ||||
| 			var info:MTLTextureMapInfo = MTLTextureMapInfo.parse(parts); | ||||
| 			diffuseMaps[materialName] = info; | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Загрузка файла следующей текстуры. | ||||
| 		 */ | ||||
| 		private function loadNextBitmap():void { | ||||
| 			// Установка имени текущего текстурного материала, для которого выполняется загрузка текстуры | ||||
| 			for (materialName in diffuseMaps) { | ||||
| 				break; | ||||
| 			} | ||||
| 			bitmapLoader.load(new URLRequest(baseUrl + diffuseMaps[materialName].fileName), loaderContext); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 *  | ||||
| 		 */ | ||||
| 		private function createStubBitmap():void { | ||||
| 			if (stubBitmapData == null) { | ||||
| 				var size:uint = 10; | ||||
| 				stubBitmapData = new BitmapData(size, size, false, 0); | ||||
| 				for (var i:uint = 0; i < size; i++) { | ||||
| 					for (var j:uint = 0; j < size; j+=2) { | ||||
| 						stubBitmapData.setPixel((i % 2) ? j : (j+1), i, 0xFF00FF); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Обработка результата загрузки файла текстуры. | ||||
| 		 */ | ||||
| 		private function onBitmapLoadComplete(e:Event):void { | ||||
| 			var bmd:BitmapData; | ||||
| 			 | ||||
| 			if (e is ErrorEvent) { | ||||
| 				if (stubBitmapData == null) { | ||||
| 					createStubBitmap(); | ||||
| 				} | ||||
| 				bmd = stubBitmapData; | ||||
| 			} else { | ||||
| 				bmd = Bitmap(bitmapLoader.content).bitmapData; | ||||
| 			} | ||||
| 			 | ||||
| 			var mtlInfo:MTLTextureMapInfo = diffuseMaps[materialName]; | ||||
| 			delete diffuseMaps[materialName]; | ||||
| 			var info:MaterialInfo = _library[materialName]; | ||||
| 			 | ||||
| 			info.bitmapData = bmd; | ||||
| 			info.repeat = mtlInfo.repeat; | ||||
| 			info.mapOffset = new Point(mtlInfo.offsetU, mtlInfo.offsetV); | ||||
| 			info.mapSize = new Point(mtlInfo.sizeU, mtlInfo.sizeV); | ||||
| 			info.textureFileName = mtlInfo.fileName; | ||||
| 	 | ||||
| 			if (diffuseMaps.isEmpty()) { | ||||
| 				dispatchEvent(new Event(Event.COMPLETE)); | ||||
| 			} else { | ||||
| 				loadNextBitmap(); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 *  | ||||
| 		 * @param e | ||||
| 		 */ | ||||
| 		private function onError(e:IOErrorEvent):void { | ||||
| 			dispatchEvent(e); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Tubix
					Tubix