This commit is contained in:
Pyogenics
2024-09-28 17:40:49 +01:00
parent c2b65211bd
commit ecf60d961b
49 changed files with 6864 additions and 0 deletions

View File

@@ -0,0 +1,405 @@
package alternativa.engine3d.core {
import alternativa.engine3d.*;
import alternativa.types.Set;
import alternativa.utils.ObjectUtils;
import alternativa.engine3d.sorting.SortingLevel;
use namespace alternativa3d;
/**
* Сцена является контейнером 3D-объектов, с которыми ведётся работа. Все взаимодействия объектов
* происходят в пределах одной сцены. Класс обеспечивает работу системы сигналов и реализует алгоритм построения
* BSP-дерева для содержимого сцены.
*/
public class Scene3D {
// Инкремент количества сцен
private static var counter:uint = 0;
/**
* @private
* Наименование
*/
alternativa3d var _name:String;
/**
* @private
* Пространство сцены
*/
alternativa3d var _space:Space;
/**
* @private
* Реестр камер сцены
*/
alternativa3d var cameras:Set = new Set();
/**
* @private
* Списки сигналов
*/
alternativa3d var objectsToTransform:Set = new Set();
alternativa3d var objectsToMove:Set = new Set();
// alternativa3d var verticesToMove:Set = new Set();
alternativa3d var spacesToGlobalTransform:Set = new Set();
alternativa3d var spacesToChangeSortingMode:Set = new Set();
alternativa3d var spacesToChangeSortingLevel:Set = new Set();
alternativa3d var spacesToChangeMaterial:Set = new Set();
/*
alternativa3d var spritesToChangeSortingMode:Set = new Set();
alternativa3d var spritesToChangeSortingLevel:Set = new Set();
alternativa3d var spritesToChangeMaterial:Set = new Set();
alternativa3d var surfacesToChangeSortingMode:Set = new Set();
alternativa3d var surfacesToChangeSortingLevel:Set = new Set();
alternativa3d var surfacesToChangeMaterial:Set = new Set();
alternativa3d var surfacesToChangeBSPLevel:Set = new Set();
alternativa3d var facesToChangeSurface:Set = new Set();
alternativa3d var facesToTransform:Set = new Set();
*/
//alternativa3d var spacesToCalculate:Set = new Set();
alternativa3d var levelsToCalculate:Set = new Set();
//alternativa3d var spacesToRender:Set = new Set();
alternativa3d var spacesToUpdateMaterial:Set = new Set();
alternativa3d var camerasToRender:Set = new Set();
alternativa3d var levelsToClear:Set = new Set();
/**
* Создание экземпляра сцены.
*/
public function Scene3D(name:String = null) {
// Имя по-умолчанию
_name = (name != null) ? name : defaultName();
}
/**
* Расчёт сцены. Метод анализирует все изменения, произошедшие с момента предыдущего расчёта, формирует список
* команд и исполняет их в необходимой последовательности. В результате расчёта происходит перерисовка во всех
* областях вывода, к которым подключены находящиеся в сцене камеры.
*/
public function calculate():void {
trace("----------------------------- calculate -------------------------------------");
var key:*;
var object:Object3D;
var method:Function;
// var vertex:Vertex;
// var face:Face;
// var surface:Surface;
// var sprite:Sprite3D;
var space:Space;
var level:SortingLevel;
var camera:Camera3D;
// Трансформация объектов
if (!objectsToTransform.isEmpty()) {
trace("objectsToTransform:", objectsToTransform.length);
}
while ((object = objectsToTransform.peek()) != null) {
// Ищем, нет ли выше в пространстве объектов на трансформацию или перемещение
method = object.transformBranch;
while ((object = object._parent) != null && !(object is Space)) {
method = objectsToTransform[object] ? object.transformBranch : (objectsToMove[object] ? object.moveBranch : method);
}
method();
}
// Перемещение объектов
if (!objectsToMove.isEmpty()) {
trace("objectsToMove:", objectsToMove.length);
}
while ((object = objectsToMove.peek()) != null) {
// Ищем, нет ли выше в пространстве объектов на перемещение
method = object.moveBranch;
while ((object = object._parent) != null && !(object is Space)) {
method = objectsToMove[object] ? object.moveBranch : method;
}
method();
}
/*
// Перемещение вершин
if (!verticesToMove.isEmpty()) {
trace("verticesToMove:", verticesToMove.length);
}
for (key in verticesToMove) {
vertex = key;
vertex.move();
}
*/
// Глобальная трансформация пространств
if (!spacesToGlobalTransform.isEmpty()) {
trace("spacesToGlobalTransform:", spacesToGlobalTransform.length);
}
while ((space = spacesToGlobalTransform.peek()) != null) {
method = space.globalTransform;
// Ищем, нет ли выше пространства на глобальную трансформацию
while ((space = space.space) != null) {
method = spacesToGlobalTransform[space] ? space.globalTransform : method;
}
method();
}
// Изменение режима сортировки пространств
if (!spacesToChangeSortingMode.isEmpty()) {
trace("spacesToChangeSortingMode:", spacesToChangeSortingMode.length);
}
for (key in spacesToChangeSortingMode) {
space = key;
space.changeSortingMode();
}
// Изменение уровней пространств
if (!spacesToChangeSortingLevel.isEmpty()) {
trace("spacesToChangeSortingLevel:", spacesToChangeSortingLevel.length);
}
for (key in spacesToChangeSortingLevel) {
space = key;
space.changeSortingLevel();
}
// Изменение материалов пространств
if (!spacesToChangeMaterial.isEmpty()) {
trace("spacesToChangeMaterial:", spacesToChangeMaterial.length);
}
for (key in spacesToChangeMaterial) {
space = key;
space.changeMaterial();
}
/*
// Изменение режима сортировки спрайтов
if (!spritesToChangeSortingMode.isEmpty()) {
trace("spritesToChangeSortingMode:", spritesToChangeSortingMode.length);
}
for (key in spritesToChangeSortingMode) {
sprite = key;
sprite.changeSortingMode();
}
// Изменение уровней спрайтов
if (!spritesToChangeSortingLevel.isEmpty()) {
trace("spritesToChangeSortingLevel:", spritesToChangeSortingLevel.length);
}
for (key in spritesToChangeSortingLevel) {
sprite = key;
sprite.changeSortingLevel();
}
// Изменение материалов спрайтов
if (!spritesToChangeMaterial.isEmpty()) {
trace("spritesToChangeMaterial:", spritesToChangeMaterial.length);
}
for (key in spritesToChangeMaterial) {
sprite = key;
sprite.changeMaterial();
}
// Изменение режима сортировки поверхностей
if (!surfacesToChangeSortingMode.isEmpty()) {
trace("surfacesToChangeSortingMode:", surfacesToChangeSortingMode.length);
}
for (key in surfacesToChangeSortingMode) {
surface = key;
surface.changeSortingMode();
}
// Изменение уровней поверхностей
if (!surfacesToChangeSortingLevel.isEmpty()) {
trace("surfacesToChangeSortingLevel:", surfacesToChangeSortingLevel.length);
}
for (key in surfacesToChangeSortingLevel) {
surface = key;
surface.changeSortingLevel();
}
// Изменение материалов поверхностей
if (!surfacesToChangeMaterial.isEmpty()) {
trace("surfacesToChangeMaterial:", surfacesToChangeMaterial.length);
}
for (key in surfacesToChangeMaterial) {
surface = key;
surface.changeMaterial();
}
// Изменение мобильности поверхностей
if (!surfacesToChangeBSPLevel.isEmpty()) {
trace("surfacesToChangeBSPLevel:", surfacesToChangeBSPLevel.length);
}
for (key in surfacesToChangeBSPLevel) {
surface = key;
surface.changeBSPLevel();
}
// Изменение поверхности граней
if (!facesToChangeSurface.isEmpty()) {
trace("facesToChangeSurface:", facesToChangeSurface.length);
}
for (key in facesToChangeSurface) {
face = key;
face.changeSurface();
}
// Трансформация граней
if (!facesToTransform.isEmpty()) {
trace("facesToTransform:", facesToTransform.length);
}
for (key in facesToTransform) {
face = key;
face.transform();
}
*/
// Расчёт BSP пространств
if (!levelsToCalculate.isEmpty()) {
trace("levelsToCalculate:", levelsToCalculate.length);
}
for (key in levelsToCalculate) {
level = key;
level.calculate();
}
/*
// Отрисовка пространств
if (!spacesToRender.isEmpty()) {
trace("spacesToRender:", spacesToRender.length);
}
while ((space = spacesToRender.peek()) != null) {
var s:Space = space;
// Ищем, нет ли выше пространства на отрисовку
while ((space = space.space) != null) {
s = spacesToRender[space] ? space : s;
}
// Отрисовка пространства
s.render();
}
*/
// Обновление материалов пространств
if (!spacesToUpdateMaterial.isEmpty()) {
trace("spacesToUpdateMaterial:", spacesToUpdateMaterial.length);
}
for (key in spacesToUpdateMaterial) {
space = key;
space.updateMaterial();
}
// Отрисовка камер
if (!camerasToRender.isEmpty()) {
trace("camerasToRender:", camerasToRender.length);
}
for (key in camerasToRender) {
camera = key;
camera.render();
}
// Очистка изменений уровней
if (!levelsToClear.isEmpty()) {
trace("levelsToClear:", levelsToClear.length);
}
for (key in levelsToClear) {
level = key;
level.clear();
}
// Отложенное удаление примитивов в коллекторы
//FaceNonePrimitive.destroyDeferred();
//FaceDistancePrimitive.destroyDeferred();
//FaceBSPPrimitive.destroyDeferred();
//SpaceDistancePrimitive.destroyDeferred();
//SpriteDistancePrimitive.destroyDeferred();
trace("-----------------------------------------------------------------------------");
}
public function hasChanges():Boolean {
//return !objectsToLocate.isEmpty() || !objectsToChangeMobility.isEmpty() || !objectsToTransform.isEmpty() || !objectsToMove.isEmpty() || !verticesToMove.isEmpty() || !facesToChangeSurface.isEmpty() || !facesToTransform.isEmpty();
return true;
}
/**
* Имя сцены.
*/
public function get name():String {
return _name;
}
/**
* @private
*/
public function set name(value:String):void {
_name = value;
}
/**
* Корневой объект сцены.
*/
public function get space():Space {
return _space;
}
/**
* @private
*/
public function set space(value:Space):void {
// Если ещё не является пространством сцены
if (_space != value) {
// Если у сцены было пространство
if (_space != null) {
// Удаляем у него ссылку на сцену
_space.setScene(null);
}
// Если устанавливаем пространство
if (value != null) {
// Если пространство было в другом объекте
if (value._parent != null) {
// Удалить его оттуда
value._parent._children.remove(value);
} else {
// Если пространство было пространством в другой сцене
if (value._scene != null) {
value._scene.space = null;
}
}
// Удаляем ссылку на родителя
value._parent = null;
// Указываем сцену
value.setScene(this);
// Если у пространства есть материал, помечаем его на обновление
if (value._material != null) {
spacesToUpdateMaterial[value] = true;
}
}
// Сохраняем пространство
_space = value;
}
}
/**
* Строковое представление сцены.
*
* @return строковое представление сцены
*/
public function toString():String {
return "[" + ObjectUtils.getClassName(this) + " " + _name + "]";
}
/**
* Имя сцены по умолчанию.
*
* @return имя сцены по умолчанию
*/
protected function defaultName():String {
return "scene" + ++counter;
}
}
}