mirror of
https://github.com/MapMakersAndProgrammers/alternativa3d-archive.git
synced 2025-10-26 01:49:05 -07:00
142 lines
4.2 KiB
ActionScript
142 lines
4.2 KiB
ActionScript
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;
|
||
}
|
||
|
||
}
|
||
} |