123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- import { SpotLight } from "babylonjs/Lights/spotLight";
- import { Vector3, Color3, Quaternion } from "babylonjs/Maths/math";
- import { Light } from "babylonjs/Lights/light";
- import { Node } from "babylonjs/node";
- import { ShadowLight } from "babylonjs/Lights/shadowLight";
- import { IChildRootProperty } from "babylonjs-gltf2interface";
- import { INode } from "babylonjs-gltf2interface";
- import { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
- import { _Exporter } from "../glTFExporter";
- import { Logger } from "babylonjs/Misc/logger";
- import { _GLTFUtilities } from "../glTFUtilities";
- const NAME = "KHR_lights_punctual";
- enum LightType {
- DIRECTIONAL = "directional",
- POINT = "point",
- SPOT = "spot"
- }
- interface ILightReference {
- light: number;
- }
- interface ILight extends IChildRootProperty {
- type: LightType;
- color?: number[];
- intensity?: number;
- range?: number;
- spot?: {
- innerConeAngle?: number;
- outerConeAngle?: number;
- };
- }
- interface ILights {
- lights: ILight[];
- }
- /**
- * [Specification](https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_lights_punctual/README.md)
- */
- export class KHR_lights_punctual implements IGLTFExporterExtensionV2 {
- /** The name of this extension. */
- public readonly name = NAME;
- /** Defines whether this extension is enabled. */
- public enabled = true;
- /** Defines whether this extension is required */
- public required = false;
- /** Reference to the glTF exporter */
- private _exporter: _Exporter;
- private _lights: ILights;
- /** @hidden */
- constructor(exporter: _Exporter) {
- this._exporter = exporter;
- }
- /** @hidden */
- public dispose() {
- delete this._exporter;
- delete this._lights;
- }
- /** @hidden */
- public onExporting(): void {
- if (this._lights) {
- if (this._exporter._glTF.extensionsUsed == null) {
- this._exporter._glTF.extensionsUsed = [];
- }
- if (this._exporter._glTF.extensionsUsed.indexOf(NAME) === -1) {
- this._exporter._glTF.extensionsUsed.push(NAME);
- }
- if (this.required) {
- if (this._exporter._glTF.extensionsRequired == null) {
- this._exporter._glTF.extensionsRequired = [];
- }
- if (this._exporter._glTF.extensionsRequired.indexOf(NAME) === -1) {
- this._exporter._glTF.extensionsRequired.push(NAME);
- }
- }
- if (this._exporter._glTF.extensions == null) {
- this._exporter._glTF.extensions = {};
- }
- this._exporter._glTF.extensions[NAME] = this._lights;
- }
- }
- /**
- * Define this method to modify the default behavior when exporting a node
- * @param context The context when exporting the node
- * @param node glTF node
- * @param babylonNode BabylonJS node
- * @returns nullable INode promise
- */
- public postExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<INode> {
- return new Promise((resolve, reject) => {
- if (babylonNode instanceof ShadowLight) {
- const babylonLight: ShadowLight = babylonNode;
- let light: ILight;
- const lightType = (
- babylonLight.getTypeID() == Light.LIGHTTYPEID_POINTLIGHT ? LightType.POINT : (
- babylonLight.getTypeID() == Light.LIGHTTYPEID_DIRECTIONALLIGHT ? LightType.DIRECTIONAL : (
- babylonLight.getTypeID() == Light.LIGHTTYPEID_SPOTLIGHT ? LightType.SPOT : null
- )));
- if (lightType == null) {
- Logger.Warn(`${context}: Light ${babylonLight.name} is not supported in ${NAME}`);
- }
- else {
- const lightPosition = babylonLight.position.clone();
- if (!lightPosition.equals(Vector3.Zero())) {
- if (this._exporter._convertToRightHandedSystem) {
- _GLTFUtilities._GetRightHandedPositionVector3FromRef(lightPosition);
- }
- node.translation = lightPosition.asArray();
- }
- if (lightType !== LightType.POINT) {
- const localAxis = babylonLight.direction;
- const yaw = -Math.atan2(localAxis.z, localAxis.x) + Math.PI / 2;
- const len = Math.sqrt(localAxis.x * localAxis.x + localAxis.z * localAxis.z);
- const pitch = -Math.atan2(localAxis.y, len);
- const lightRotationQuaternion = Quaternion.RotationYawPitchRoll(yaw, pitch, 0);
- if (this._exporter._convertToRightHandedSystem) {
- _GLTFUtilities._GetRightHandedQuaternionFromRef(lightRotationQuaternion);
- }
- if (!lightRotationQuaternion.equals(Quaternion.Identity())) {
- node.rotation = lightRotationQuaternion.asArray();
- }
- }
- if (babylonLight.falloffType !== Light.FALLOFF_GLTF) {
- Logger.Warn(`${context}: Light falloff for ${babylonLight.name} does not match the ${NAME} specification!`);
- }
- light = {
- type: lightType
- };
- if (!babylonLight.diffuse.equals(Color3.White())) {
- light.color = babylonLight.diffuse.asArray();
- }
- if (babylonLight.intensity !== 1.0) {
- light.intensity = babylonLight.intensity;
- }
- if (babylonLight.range !== Number.MAX_VALUE) {
- light.range = babylonLight.range;
- }
- if (lightType === LightType.SPOT) {
- const babylonSpotLight = babylonLight as SpotLight;
- if (babylonSpotLight.angle !== Math.PI / 2.0) {
- if (light.spot == null) {
- light.spot = {};
- }
- light.spot.outerConeAngle = babylonSpotLight.angle / 2.0;
- }
- if (babylonSpotLight.innerAngle !== 0) {
- if (light.spot == null) {
- light.spot = {};
- }
- light.spot.innerConeAngle = babylonSpotLight.innerAngle / 2.0;
- }
- }
- if (this._lights == null) {
- this._lights = {
- lights: []
- };
- }
- this._lights.lights.push(light);
- if (node.extensions == null) {
- node.extensions = {};
- }
- const lightReference: ILightReference = {
- light: this._lights.lights.length - 1
- };
- node.extensions[NAME] = lightReference;
- }
- }
- resolve(node);
- });
- }
- }
- _Exporter.RegisterExtension(NAME, (exporter) => new KHR_lights_punctual(exporter));
|