123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- import { Mesh } from "../Meshes/mesh.js";
- import { MultiMaterial } from "../Materials/multiMaterial.js";
- import { SerializationHelper } from "./decorators.serialization.js";
- import { Texture } from "../Materials/Textures/texture.js";
- import { Logger } from "./logger.js";
- let serializedGeometries = [];
- const SerializeGeometry = (geometry, serializationGeometries) => {
- if (geometry.doNotSerialize) {
- return;
- }
- serializationGeometries.vertexData.push(geometry.serializeVerticeData());
- serializedGeometries[geometry.id] = true;
- };
- const SerializeMesh = (mesh, serializationScene) => {
- const serializationObject = {};
- // Geometry
- const geometry = mesh._geometry;
- if (geometry) {
- if (!mesh.getScene().getGeometryById(geometry.id)) {
- // Geometry was in the memory but not added to the scene, nevertheless it's better to serialize to be able to reload the mesh with its geometry
- SerializeGeometry(geometry, serializationScene.geometries);
- }
- }
- // Custom
- if (mesh.serialize) {
- mesh.serialize(serializationObject);
- }
- return serializationObject;
- };
- const FinalizeSingleNode = (node, serializationObject) => {
- if (node._isMesh) {
- const mesh = node;
- //only works if the mesh is already loaded
- if (mesh.delayLoadState === 1 || mesh.delayLoadState === 0) {
- const serializeMaterial = (material) => {
- serializationObject.materials = serializationObject.materials || [];
- if (mesh.material && !serializationObject.materials.some((mat) => mat.id === mesh.material.id)) {
- serializationObject.materials.push(material.serialize());
- }
- };
- //serialize material
- if (mesh.material && !mesh.material.doNotSerialize) {
- if (mesh.material instanceof MultiMaterial) {
- serializationObject.multiMaterials = serializationObject.multiMaterials || [];
- if (!serializationObject.multiMaterials.some((mat) => mat.id === mesh.material.id)) {
- serializationObject.multiMaterials.push(mesh.material.serialize());
- for (const submaterial of mesh.material.subMaterials) {
- if (submaterial) {
- serializeMaterial(submaterial);
- }
- }
- }
- }
- else {
- serializeMaterial(mesh.material);
- }
- }
- else if (!mesh.material) {
- serializeMaterial(mesh.getScene().defaultMaterial);
- }
- //serialize geometry
- const geometry = mesh._geometry;
- if (geometry) {
- if (!serializationObject.geometries) {
- serializationObject.geometries = {};
- serializationObject.geometries.boxes = [];
- serializationObject.geometries.spheres = [];
- serializationObject.geometries.cylinders = [];
- serializationObject.geometries.toruses = [];
- serializationObject.geometries.grounds = [];
- serializationObject.geometries.planes = [];
- serializationObject.geometries.torusKnots = [];
- serializationObject.geometries.vertexData = [];
- }
- SerializeGeometry(geometry, serializationObject.geometries);
- }
- // Skeletons
- if (mesh.skeleton && !mesh.skeleton.doNotSerialize) {
- serializationObject.skeletons = serializationObject.skeletons || [];
- serializationObject.skeletons.push(mesh.skeleton.serialize());
- }
- //serialize the actual mesh
- serializationObject.meshes = serializationObject.meshes || [];
- serializationObject.meshes.push(SerializeMesh(mesh, serializationObject));
- }
- }
- else if (node.getClassName() === "TransformNode") {
- const transformNode = node;
- serializationObject.transformNodes.push(transformNode.serialize());
- }
- else if (node.getClassName().indexOf("Camera") !== -1) {
- const camera = node;
- serializationObject.cameras.push(camera.serialize());
- }
- else if (node.getClassName().indexOf("Light") !== -1) {
- const light = node;
- serializationObject.lights.push(light.serialize());
- }
- };
- /**
- * Class used to serialize a scene into a string
- */
- export class SceneSerializer {
- /**
- * Clear cache used by a previous serialization
- */
- static ClearCache() {
- serializedGeometries = [];
- }
- /**
- * Serialize a scene into a JSON compatible object
- * Note that if the current engine does not support synchronous texture reading (like WebGPU), you should use SerializeAsync instead
- * as else you may not retrieve the proper base64 encoded texture data (when using the Texture.ForceSerializeBuffers flag)
- * @param scene defines the scene to serialize
- * @returns a JSON compatible object
- */
- static Serialize(scene) {
- return SceneSerializer._Serialize(scene);
- }
- static _Serialize(scene, checkSyncReadSupported = true) {
- const serializationObject = {};
- if (checkSyncReadSupported && !scene.getEngine()._features.supportSyncTextureRead && Texture.ForceSerializeBuffers) {
- Logger.Warn("The serialization object may not contain the proper base64 encoded texture data! You should use the SerializeAsync method instead.");
- }
- SceneSerializer.ClearCache();
- // Scene
- serializationObject.useDelayedTextureLoading = scene.useDelayedTextureLoading;
- serializationObject.autoClear = scene.autoClear;
- serializationObject.clearColor = scene.clearColor.asArray();
- serializationObject.ambientColor = scene.ambientColor.asArray();
- serializationObject.gravity = scene.gravity.asArray();
- serializationObject.collisionsEnabled = scene.collisionsEnabled;
- serializationObject.useRightHandedSystem = scene.useRightHandedSystem;
- // Fog
- if (scene.fogMode && scene.fogMode !== 0) {
- serializationObject.fogMode = scene.fogMode;
- serializationObject.fogColor = scene.fogColor.asArray();
- serializationObject.fogStart = scene.fogStart;
- serializationObject.fogEnd = scene.fogEnd;
- serializationObject.fogDensity = scene.fogDensity;
- }
- //Physics
- if (scene.isPhysicsEnabled && scene.isPhysicsEnabled()) {
- const physicEngine = scene.getPhysicsEngine();
- if (physicEngine) {
- serializationObject.physicsEnabled = true;
- serializationObject.physicsGravity = physicEngine.gravity.asArray();
- serializationObject.physicsEngine = physicEngine.getPhysicsPluginName();
- }
- }
- // Metadata
- if (scene.metadata) {
- serializationObject.metadata = scene.metadata;
- }
- // Morph targets
- serializationObject.morphTargetManagers = [];
- for (const abstractMesh of scene.meshes) {
- const manager = abstractMesh.morphTargetManager;
- if (manager) {
- serializationObject.morphTargetManagers.push(manager.serialize());
- }
- }
- // Lights
- serializationObject.lights = [];
- let index;
- let light;
- for (index = 0; index < scene.lights.length; index++) {
- light = scene.lights[index];
- if (!light.doNotSerialize) {
- serializationObject.lights.push(light.serialize());
- }
- }
- // Cameras
- serializationObject.cameras = [];
- for (index = 0; index < scene.cameras.length; index++) {
- const camera = scene.cameras[index];
- if (!camera.doNotSerialize) {
- serializationObject.cameras.push(camera.serialize());
- }
- }
- if (scene.activeCamera) {
- serializationObject.activeCameraID = scene.activeCamera.id;
- }
- // Animations
- SerializationHelper.AppendSerializedAnimations(scene, serializationObject);
- // Animation Groups
- if (scene.animationGroups && scene.animationGroups.length > 0) {
- serializationObject.animationGroups = [];
- for (let animationGroupIndex = 0; animationGroupIndex < scene.animationGroups.length; animationGroupIndex++) {
- const animationGroup = scene.animationGroups[animationGroupIndex];
- serializationObject.animationGroups.push(animationGroup.serialize());
- }
- }
- // Reflection probes
- if (scene.reflectionProbes && scene.reflectionProbes.length > 0) {
- serializationObject.reflectionProbes = [];
- for (index = 0; index < scene.reflectionProbes.length; index++) {
- const reflectionProbe = scene.reflectionProbes[index];
- serializationObject.reflectionProbes.push(reflectionProbe.serialize());
- }
- }
- // Materials
- serializationObject.materials = [];
- serializationObject.multiMaterials = [];
- let material;
- for (index = 0; index < scene.materials.length; index++) {
- material = scene.materials[index];
- if (!material.doNotSerialize) {
- serializationObject.materials.push(material.serialize());
- }
- }
- // MultiMaterials
- serializationObject.multiMaterials = [];
- for (index = 0; index < scene.multiMaterials.length; index++) {
- const multiMaterial = scene.multiMaterials[index];
- serializationObject.multiMaterials.push(multiMaterial.serialize());
- }
- // Environment texture
- if (scene.environmentTexture) {
- if (scene.environmentTexture._files) {
- serializationObject.environmentTexture = scene.environmentTexture.serialize();
- }
- else {
- serializationObject.environmentTexture = scene.environmentTexture.name;
- serializationObject.environmentTextureRotationY = scene.environmentTexture.rotationY;
- }
- }
- // Environment Intensity
- serializationObject.environmentIntensity = scene.environmentIntensity;
- // Skeletons
- serializationObject.skeletons = [];
- for (index = 0; index < scene.skeletons.length; index++) {
- const skeleton = scene.skeletons[index];
- if (!skeleton.doNotSerialize) {
- serializationObject.skeletons.push(skeleton.serialize());
- }
- }
- // Transform nodes
- serializationObject.transformNodes = [];
- for (index = 0; index < scene.transformNodes.length; index++) {
- if (!scene.transformNodes[index].doNotSerialize) {
- serializationObject.transformNodes.push(scene.transformNodes[index].serialize());
- }
- }
- // Geometries
- serializationObject.geometries = {};
- serializationObject.geometries.boxes = [];
- serializationObject.geometries.spheres = [];
- serializationObject.geometries.cylinders = [];
- serializationObject.geometries.toruses = [];
- serializationObject.geometries.grounds = [];
- serializationObject.geometries.planes = [];
- serializationObject.geometries.torusKnots = [];
- serializationObject.geometries.vertexData = [];
- serializedGeometries = [];
- const geometries = scene.getGeometries();
- for (index = 0; index < geometries.length; index++) {
- const geometry = geometries[index];
- if (geometry.isReady()) {
- SerializeGeometry(geometry, serializationObject.geometries);
- }
- }
- // Meshes
- serializationObject.meshes = [];
- for (index = 0; index < scene.meshes.length; index++) {
- const abstractMesh = scene.meshes[index];
- if (abstractMesh instanceof Mesh) {
- const mesh = abstractMesh;
- if (!mesh.doNotSerialize) {
- if (mesh.delayLoadState === 1 || mesh.delayLoadState === 0) {
- serializationObject.meshes.push(SerializeMesh(mesh, serializationObject));
- }
- }
- }
- }
- // Particles Systems
- serializationObject.particleSystems = [];
- for (index = 0; index < scene.particleSystems.length; index++) {
- serializationObject.particleSystems.push(scene.particleSystems[index].serialize(false));
- }
- // Post processes
- serializationObject.postProcesses = [];
- for (index = 0; index < scene.postProcesses.length; index++) {
- serializationObject.postProcesses.push(scene.postProcesses[index].serialize());
- }
- // Action Manager
- if (scene.actionManager) {
- serializationObject.actions = scene.actionManager.serialize("scene");
- }
- // Components
- for (const component of scene._serializableComponents) {
- component.serialize(serializationObject);
- }
- // Sprites
- if (scene.spriteManagers) {
- serializationObject.spriteManagers = [];
- for (index = 0; index < scene.spriteManagers.length; index++) {
- serializationObject.spriteManagers.push(scene.spriteManagers[index].serialize(true));
- }
- }
- return serializationObject;
- }
- /**
- * Serialize a scene into a JSON compatible object
- * @param scene defines the scene to serialize
- * @returns a JSON promise compatible object
- */
- static SerializeAsync(scene) {
- const serializationObject = SceneSerializer._Serialize(scene, false);
- const promises = [];
- this._CollectPromises(serializationObject, promises);
- return Promise.all(promises).then(() => serializationObject);
- }
- static _CollectPromises(obj, promises) {
- if (Array.isArray(obj)) {
- for (let i = 0; i < obj.length; ++i) {
- const o = obj[i];
- if (o instanceof Promise) {
- promises.push(o.then((res) => (obj[i] = res)));
- }
- else if (o instanceof Object || Array.isArray(o)) {
- this._CollectPromises(o, promises);
- }
- }
- }
- else if (obj instanceof Object) {
- for (const name in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, name)) {
- const o = obj[name];
- if (o instanceof Promise) {
- promises.push(o.then((res) => (obj[name] = res)));
- }
- else if (o instanceof Object || Array.isArray(o)) {
- this._CollectPromises(o, promises);
- }
- }
- }
- }
- }
- /**
- * Serialize a mesh into a JSON compatible object
- * @param toSerialize defines the mesh to serialize
- * @param withParents defines if parents must be serialized as well
- * @param withChildren defines if children must be serialized as well
- * @returns a JSON compatible object
- */
- static SerializeMesh(toSerialize /* Mesh || Mesh[] */, withParents = false, withChildren = false) {
- const serializationObject = {};
- serializationObject.meshes = [];
- serializationObject.transformNodes = [];
- serializationObject.cameras = [];
- serializationObject.lights = [];
- SceneSerializer.ClearCache();
- toSerialize = toSerialize instanceof Array ? toSerialize : [toSerialize];
- if (withParents || withChildren) {
- //deliberate for loop! not for each, appended should be processed as well.
- for (let i = 0; i < toSerialize.length; ++i) {
- if (withChildren) {
- toSerialize[i].getDescendants().forEach((node) => {
- if (toSerialize.indexOf(node) < 0 && !node.doNotSerialize) {
- toSerialize.push(node);
- }
- });
- }
- //make sure the array doesn't contain the object already
- if (withParents && toSerialize[i].parent && toSerialize.indexOf(toSerialize[i].parent) < 0 && !toSerialize[i].parent.doNotSerialize) {
- toSerialize.push(toSerialize[i].parent);
- }
- }
- }
- toSerialize.forEach((mesh) => {
- FinalizeSingleNode(mesh, serializationObject);
- });
- return serializationObject;
- }
- }
- //# sourceMappingURL=sceneSerializer.js.map
|