Files
alternativa3d-archive/Alternativa3D2/2.0/com/alternativagame/engine3d/object/light/Omni3D.as
2024-10-05 12:11:16 +01:00

142 lines
4.2 KiB
ActionScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.alternativagame.engine3d.object.light {
import com.alternativagame.engine3d.material.HelperMaterial;
import com.alternativagame.engine3d.material.Material;
import com.alternativagame.engine3d.skin.OmniSkin;
import com.alternativagame.type.RGB;
import com.alternativagame.type.Vector;
import com.alternativagame.engine3d.skin.Skin;
import com.alternativagame.engine3d.object.Object3D;
import com.alternativagame.engine3d.Math3D;
import com.alternativagame.engine3d.engine3d;
use namespace engine3d;
public class Omni3D extends Light3D {
use namespace engine3d;
// Расстояния влияния источника света
private var _near:Number;
private var _far:Number;
// Квадраты расстояний влияния
engine3d var nearSqr:Number;
engine3d var farSqr:Number;
// Предпросчитанная обратная разница расстояний влияния
engine3d var farNearSqr:Number;
// Параметры в системе камеры
engine3d var canvasNear:Number;
engine3d var canvasFar:Number;
engine3d var canvasNearSqr:Number;
engine3d var canvasFarSqr:Number;
engine3d var canvasFarNearSqr:Number;
// Часто изменяемый источник
private var _mobile:Boolean = false;
public function Omni3D(color:RGB = null, near:Number = 0, far:Number = 100, material:HelperMaterial = null) {
super(color, material);
_near = near;
_far = far;
calculateParams();
}
override protected function updateTransform():void {
super.updateTransform();
calculateCanvasParams();
}
override protected function createSkin():Skin {
return new OmniSkin(this);
}
// Освещение в заданной точке (null, если нет)
override engine3d function getLightColor(coords:Vector, normal:Vector):RGB {
// Находим вектор до точки из источника
var vector:Vector = new Vector(coords.x - transform.d, coords.y - transform.h, coords.z - transform.l);
// Находим квадрат расстояния
var length:Number = Math3D.vectorLengthSquare(vector);
// Если за пределами влияния
if (length > canvasFarSqr) {
return null;
} else {
Math3D.normalize(vector);
var res:RGB = calculateLightColor(normal, vector);
// Если в промежутке near и far
if (res != null && length > canvasNearSqr) {
res.multiply(canvasFarNearSqr*(canvasFarSqr - length));
}
return res;
}
}
// Обновление предпросчитанных параметров
private function calculateParams():void {
nearSqr = _near * _near;
farSqr = _far * _far;
farNearSqr = 1/(farSqr - nearSqr);
}
// Обновление предпросчитанных параметров с учётом масштаба камеры
private function calculateCanvasParams():void {
canvasNear = _near * view.zoom;
canvasFar = _far * view.zoom;
canvasNearSqr = canvasNear * canvasNear;
canvasFarSqr = canvasFar * canvasFar;
canvasFarNearSqr = 1/(canvasFarSqr - canvasNearSqr);
}
public function set near(value:Number):void {
_near = value;
calculateParams();
updateSkin();
applyToSolidObjects();
}
public function get near():Number {
return _near;
}
public function set far(value:Number):void {
_far = value;
calculateParams();
updateSkin();
applyToSolidObjects();
}
public function get far():Number {
return _far;
}
public function get mobile():Boolean {
return _mobile;
}
public function set mobile(value:Boolean):void {
if (_mobile != value) {
_mobile = value;
applyToSolidObjects();
}
}
// Клон
override public function clone():Object3D {
var res:Omni3D = new Omni3D();
cloneParams(res);
return res;
}
// Клонировать параметры
override protected function cloneParams(object:*):void {
var obj:Omni3D = Omni3D(object);
super.cloneParams(obj);
obj.far = far;
obj.near = near;
obj.mobile = mobile;
}
}
}