@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
203 lines (136 loc) • 6.31 kB
JavaScript
import { assert } from "../../../../core/assert.js";
import { objectKeyByValue } from "../../../../core/model/object/objectKeyByValue.js";
import { BinaryClassSerializationAdapter } from "../../storage/binary/BinaryClassSerializationAdapter.js";
import { GridTransformKind } from "../ecs/GridTransformKind.js";
import { TerrainLayer } from "../ecs/layers/TerrainLayer.js";
import Terrain from "../ecs/Terrain.js";
import { TerrainFlags } from "../ecs/TerrainFlags.js";
export class TerrainSerializationAdapter extends BinaryClassSerializationAdapter {
klass = Terrain;
version = 2;
/**
*
* @type {TerrainSystem}
*/
system = null;
initialize(system) {
this.system = system;
}
/**
*
* @param {BinaryBuffer} buffer
* @param {Terrain} value
*/
serialize(buffer, value) {
buffer.writeUintVar(value.size.x);
buffer.writeUintVar(value.size.y);
buffer.writeFloat32(value.gridScale);
buffer.writeUintVar(value.resolution);
buffer.writeUTF8String(value.preview.url);
buffer.writeFloat64(value.preview.offset.x);
buffer.writeFloat64(value.preview.offset.y);
buffer.writeFloat64(value.preview.scale.x);
buffer.writeFloat64(value.preview.scale.y);
//extra metadata
const extra = {
gridTransform: objectKeyByValue(GridTransformKind, value.gridTransformKind)
};
if (value.lightMapURL !== null) {
extra.lightMapURL = value.lightMapURL;
}
buffer.writeUTF8String(JSON.stringify(extra));
//height map
buffer.writeUintVar(value.samplerHeight.width);
buffer.writeUintVar(value.samplerHeight.height);
const heightBytes = new Uint8Array(value.samplerHeight.data.buffer);
assert.equal(heightBytes.length, value.samplerHeight.width * value.samplerHeight.height * 4, `Incorrect height data size`);
buffer.writeBytes(heightBytes, 0, heightBytes.length);
const layerCount = value.layers.count();
buffer.writeUintVar(layerCount);
//splats
const splat_size = value.splat.size;
buffer.writeUintVar(splat_size.x);
buffer.writeUintVar(splat_size.y);
const weightData = value.splat.weightData;
const splat_cell_count = splat_size.x * splat_size.y * layerCount;
buffer.writeBytes(weightData, 0, splat_cell_count);
//layers
buffer.writeUintVar(value.layers.resolution.x);
buffer.writeUintVar(value.layers.resolution.y);
for (let i = 0; i < layerCount; i++) {
const terrainLayer = value.layers.get(i);
buffer.writeUTF8String(terrainLayer.textureDiffuseURL);
buffer.writeFloat32(terrainLayer.size.x);
buffer.writeFloat32(terrainLayer.size.y);
buffer.writeUTF8String(JSON.stringify(terrainLayer.extra));
}
}
/**
*
* @param {BinaryBuffer} buffer
* @param {Terrain} value
*/
deserialize(buffer, value) {
const size_x = buffer.readUintVar();
const size_y = buffer.readUintVar();
const grid_scale = buffer.readFloat32();
const resolution = buffer.readUintVar();
const preview_url = buffer.readUTF8String();
const preview_offset_x = buffer.readFloat64();
const preview_offset_y = buffer.readFloat64();
const preview_scale_x = buffer.readFloat64();
const preview_scale_y = buffer.readFloat64();
const extra = buffer.readUTF8String();
value.size.set(size_x, size_y);
value.gridScale = grid_scale;
value.resolution = resolution;
value.preview.url = preview_url;
value.preview.offset.set(preview_offset_x, preview_offset_y);
value.preview.scale.set(preview_scale_x, preview_scale_y);
const extraMetadata = JSON.parse(extra);
if (extraMetadata.legacy_v0 !== undefined) {
console.warn("Terrain v0 legacy metadata detected, ignoring");
}
if (extraMetadata.lightMapURL !== undefined) {
value.lightMapURL = extraMetadata.lightMapURL;
} else {
value.lightMapURL = null;
}
if (extraMetadata.gridTransform !== undefined) {
value.gridTransformKind = GridTransformKind[extraMetadata.gridTransform];
} else {
value.gridTransformKind = GridTransformKind.Legacy;
}
// Read height map
const height_sampler_width = buffer.readUintVar();
const height_sampler_height = buffer.readUintVar();
value.samplerHeight.resize(height_sampler_width, height_sampler_height);
const heightUint8Array = new Uint8Array(value.samplerHeight.data.buffer);
buffer.readBytes(heightUint8Array, 0, heightUint8Array.length);
const layer_count = buffer.readUintVar();
// Read splats
const splat_size_x = buffer.readUintVar();
const splat_size_y = buffer.readUintVar();
value.splat.resize(splat_size_x, splat_size_y, layer_count, false);
const weightData = value.splat.weightData;
const cell_count = splat_size_x * splat_size_y * layer_count;
buffer.readBytes(weightData, 0, cell_count);
// Read layers
const layers_resolution_x = buffer.readUintVar();
const layers_resolution_y = buffer.readUintVar();
value.layers.resolution.set(layers_resolution_x, layers_resolution_y);
value.layers.clear();
for (let i = 0; i < layer_count; i++) {
const layer = new TerrainLayer();
layer.textureDiffuseURL = buffer.readUTF8String();
const size_x = buffer.readFloat32();
const size_y = buffer.readFloat32();
layer.size.set(size_x, size_y);
const layer_extra_string = buffer.readUTF8String();
layer.extra = JSON.parse(layer_extra_string);
value.layers.addLayer(layer);
}
// mark for rebuilding
value.clearFlag(TerrainFlags.Built);
}
}