mirror of
https://github.com/MapMakersAndProgrammers/alternativa3d-archive.git
synced 2025-10-27 18:29:07 -07:00
164 lines
5.6 KiB
ActionScript
164 lines
5.6 KiB
ActionScript
package alternativa.engine3d.core {
|
|
|
|
import __AS3__.vec.Vector;
|
|
|
|
import alternativa.engine3d.alternativa3d;
|
|
|
|
import flash.geom.Matrix3D;
|
|
|
|
use namespace alternativa3d;
|
|
|
|
/**
|
|
* Базовый контейнер трёхмерных объектов.
|
|
* Логика контейнеров и child-parent-отношений идентична логике
|
|
* displayObject'ов во Flash.
|
|
*/
|
|
public class Object3DContainer extends Object3D {
|
|
/**
|
|
* @private
|
|
*/
|
|
alternativa3d var _numChildren:int = 0;
|
|
/**
|
|
* @private
|
|
*/
|
|
alternativa3d var children:Vector.<Object3D> = new Vector.<Object3D>();
|
|
|
|
protected var numVisibleChildren:int = 0;
|
|
protected var visibleChildren:Vector.<Object3D> = new Vector.<Object3D>();
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
override alternativa3d function get canDraw():Boolean {
|
|
return _numChildren > 0;
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
override alternativa3d function draw(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
|
// Определяем видимые объекты
|
|
numVisibleChildren = 0;
|
|
calculateVisibleChildren(camera, object);
|
|
// Если нет видимых дочерних объектов выходим без отрисовки
|
|
if (numVisibleChildren == 0) return;
|
|
// Расчёт порядка вывода видимых объектов
|
|
calculateOrder(camera, object);
|
|
// Отрисовка видимых объектов
|
|
drawVisibleChildren(camera, object, parentCanvas);
|
|
}
|
|
|
|
protected function calculateVisibleChildren(camera:Camera3D, object:Object3D):void {
|
|
var i:int = 0, child:Object3D;
|
|
while (i < _numChildren) {
|
|
child = children[i++];
|
|
if (child.visible && child.canDraw) {
|
|
child.cameraMatrix.identity();
|
|
child.cameraMatrix.prepend(object.cameraMatrix);
|
|
child.cameraMatrix.prepend(child.matrix);
|
|
if (child.cullingInCamera(camera, object.culling) >= 0) {
|
|
visibleChildren[numVisibleChildren++] = child;
|
|
}
|
|
}
|
|
}
|
|
// Подрезаем список видимых детей
|
|
visibleChildren.length = numVisibleChildren;
|
|
}
|
|
|
|
protected function calculateOrder(camera:Camera3D, object:Object3D):void {}
|
|
|
|
// Отрисовка сзади детей
|
|
protected function drawBack(camera:Camera3D, object:Object3D, canvas:Canvas):void {}
|
|
|
|
// Отрисовка перед детьми
|
|
protected function drawFront(camera:Camera3D, object:Object3D, canvas:Canvas):void {}
|
|
|
|
// Отрисовка видимых детей
|
|
protected function drawVisibleChildren(camera:Camera3D, object:Object3D, parentCanvas:Canvas):void {
|
|
|
|
// Подготовка канваса
|
|
var canvas:Canvas = parentCanvas.getChildCanvas(false, true, object.alpha, object.blendMode, object.colorTransform, object.filters);
|
|
canvas.numDraws = 0;
|
|
|
|
/*if (Debug.bounds) {
|
|
object.drawBoundBox(camera, canvas.getChildCanvas(true, false, 1, "normal", null, null));
|
|
}*/
|
|
|
|
// Отрисовываем перед детьми
|
|
drawFront(camera, object, canvas);
|
|
|
|
// Отрисовываем видимые дочерние объекты от ближних к дальним
|
|
for (var i:int = numVisibleChildren - 1; i >= 0; i--) {
|
|
var child:Object3D = visibleChildren[i];
|
|
if (camera.debugMode) child.debug(camera, child, canvas);
|
|
child.draw(camera, child, canvas);
|
|
}
|
|
|
|
// Отрисовываем после детей
|
|
drawBack(camera, object, canvas);
|
|
|
|
// Если не было отрисовки
|
|
if (canvas.numDraws == 0) {
|
|
parentCanvas.numDraws--;
|
|
return; //??????
|
|
}
|
|
|
|
// Зачищаем остатки
|
|
canvas.removeChildren(canvas.numDraws);
|
|
}
|
|
|
|
override public function calculateBoundBox(matrix:Matrix3D = null, boundBox:BoundBox = null):BoundBox {
|
|
var m:Matrix3D = matrix != null ? matrix.clone() : new Matrix3D();
|
|
// Если указан баунд-бокс
|
|
if (boundBox != null) {
|
|
boundBox.infinity();
|
|
} else {
|
|
boundBox = new BoundBox();
|
|
}
|
|
// Расчитываем баунды объектов
|
|
var childBoundBox:BoundBox = new BoundBox();
|
|
var childMatrix:Matrix3D = new Matrix3D();
|
|
for (var i:int = 0; i < _numChildren; i++) {
|
|
var child:Object3D = children[i];
|
|
childMatrix.identity();
|
|
childMatrix.prepend(m);
|
|
childMatrix.prepend(child.matrix);
|
|
child.calculateBoundBox(childMatrix, childBoundBox);
|
|
boundBox.minX = (childBoundBox.minX < boundBox.minX) ? childBoundBox.minX : boundBox.minX;
|
|
boundBox.minY = (childBoundBox.minY < boundBox.minY) ? childBoundBox.minY : boundBox.minY;
|
|
boundBox.minZ = (childBoundBox.minZ < boundBox.minZ) ? childBoundBox.minZ : boundBox.minZ;
|
|
boundBox.maxX = (childBoundBox.maxX > boundBox.maxX) ? childBoundBox.maxX : boundBox.maxX;
|
|
boundBox.maxY = (childBoundBox.maxY > boundBox.maxY) ? childBoundBox.maxY : boundBox.maxY;
|
|
boundBox.maxZ = (childBoundBox.maxZ > boundBox.maxZ) ? childBoundBox.maxZ : boundBox.maxZ;
|
|
}
|
|
return boundBox;
|
|
}
|
|
|
|
public function addChild(child:Object3D):void {
|
|
children[_numChildren++] = child;
|
|
child._parent = this;
|
|
}
|
|
|
|
public function removeChild(child:Object3D):void {
|
|
var i:int = children.indexOf(child);
|
|
if (i < 0) throw new ArgumentError("Child not found");
|
|
_numChildren--;
|
|
for (; i < _numChildren; i++) children[i] = children[int(i + 1)];
|
|
children.length = _numChildren;
|
|
child._parent = null;
|
|
}
|
|
|
|
public function hasChild(child:Object3D):Boolean {
|
|
return children.indexOf(child) > -1;
|
|
}
|
|
|
|
public function getChildAt(index:uint):Object3D {
|
|
return children[index];
|
|
}
|
|
|
|
public function get numChildren():uint {
|
|
return _numChildren;
|
|
}
|
|
|
|
}
|
|
} |