nanogl-gltf
Version:
140 lines (139 loc) • 4.88 kB
JavaScript
import { mat3 } from "gl-matrix";
import DirectionalLight from "nanogl-pbr/lighting/DirectionalLight";
import PointLight from "nanogl-pbr/lighting/PointLight";
import SpotLight from "nanogl-pbr/lighting/SpotLight";
import GltfTypes from "../../types/GltfTypes";
const M3 = mat3.create();
const EXT_ID = 'KHR_lights_punctual';
// ===========================================
// Data Spec
// ===========================================
var IKHR_LP_LightType;
(function (IKHR_LP_LightType) {
IKHR_LP_LightType["Directional"] = "directional";
IKHR_LP_LightType["Point"] = "point";
IKHR_LP_LightType["Spot"] = "spot";
})(IKHR_LP_LightType || (IKHR_LP_LightType = {}));
/**
* Class to manage a collection of lights
*/
export class LightCollection {
constructor() {
this.list = [];
this._items = [];
}
/**
* Add a light to the collection
* @param light Light to add
* @param name Light's name
*/
addLight(light, name = undefined) {
this.list.push(light);
this._items.push({ name: name, index: this.list.length - 1 });
}
/**
* Get a light from this collection by its name
* @param name Light's name to get
*/
getLightByName(name) {
let out;
for (let i = 0; i < this._items.length; i++) {
if (this._items[i].name == name) {
out = this.list[this._items[i].index];
break;
}
}
return out;
}
/**
* Get a list of lights from this collection by their name
* @param name Lights' name to get
*/
getLightsByName(name) {
const out = [];
for (let i = 0; i < this._items.length; i++) {
if (this._items[i].name == name) {
out.push(this.list[this._items[i].index]);
}
}
return out;
}
}
class Instance {
constructor(gltfLoader) {
this.name = EXT_ID;
this.priority = 1;
this.loader = gltfLoader;
this.lights = new LightCollection();
gltfLoader.gltf.extras.lights = this.lights;
}
_getLightData(index) {
var _a;
const lightDatas = (_a = this.loader._data.extensions) === null || _a === void 0 ? void 0 : _a[EXT_ID];
if (lightDatas === undefined)
throw new Error(EXT_ID + ' no extension data');
return lightDatas.lights[index];
}
_createDirectional(lightData) {
return new DirectionalLight();
}
_createPoint(lightData) {
var _a;
const l = new PointLight();
l.radius = (_a = lightData.range) !== null && _a !== void 0 ? _a : -1;
return l;
}
_createSpot(lightData) {
var _a, _b, _c, _d, _e;
const l = new SpotLight();
l.radius = (_a = lightData.range) !== null && _a !== void 0 ? _a : -1;
l.innerAngle = (_c = (_b = lightData.spot) === null || _b === void 0 ? void 0 : _b.innerConeAngle) !== null && _c !== void 0 ? _c : 0;
l.outerAngle = (_e = (_d = lightData.spot) === null || _d === void 0 ? void 0 : _d.outerConeAngle) !== null && _e !== void 0 ? _e : 0;
return l;
}
_createLightInstance(lightData) {
switch (lightData.type) {
case IKHR_LP_LightType.Directional: return this._createDirectional(lightData);
case IKHR_LP_LightType.Point: return this._createPoint(lightData);
case IKHR_LP_LightType.Spot: return this._createSpot(lightData);
}
}
_createLight(node, iData) {
var _a, _b;
const lightData = this._getLightData(iData.light);
const light = this._createLightInstance(lightData);
const color = (_a = lightData.color) !== null && _a !== void 0 ? _a : [1, 1, 1];
const intensity = (_b = lightData.intensity) !== null && _b !== void 0 ? _b : 1;
color[0] *= intensity;
color[1] *= intensity;
color[2] *= intensity;
light._color.set(color);
node.add(light);
const name = lightData.name;
this.lights.addLight(light, name);
return light;
}
acceptElement(data, element) {
if (element.gltftype === GltfTypes.NODE && data.extensions && data.extensions[EXT_ID]) {
const node = element;
this._createLight(node, data.extensions[EXT_ID]);
}
return null;
}
loadElement(data) {
return null;
}
}
/**
* This extension allows to define in a glTF file a set of lights that can be used by the scene.
* The 3 possible types of lights (directional, spot and point) will be created as nanogl-pbr DirectionalLight,
* SpotLight and PointLight, and added to the Node they are linked to.
*/
export default class KHR_lights_punctual {
constructor() {
this.name = EXT_ID;
}
createInstance(gltfLoader) {
return new Instance(gltfLoader);
}
}