more versions added

This commit is contained in:
Tubix
2024-10-05 12:11:16 +01:00
parent 413f563f33
commit c32c7e8c34
7661 changed files with 1343635 additions and 0 deletions

View 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);
}
}
}