playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
128 lines (127 loc) • 4.61 kB
JavaScript
import { Color } from "../../../core/math/color.js";
import { Vec2 } from "../../../core/math/vec2.js";
import { Vec3 } from "../../../core/math/vec3.js";
import { Texture } from "../../../platform/graphics/texture.js";
import { BoundingBox } from "../../../core/shape/bounding-box.js";
import { StandardMaterial } from "../../../scene/materials/standard-material.js";
import { StandardMaterialValidator } from "../../../scene/materials/standard-material-validator.js";
import { standardMaterialParameterTypes } from "../../../scene/materials/standard-material-parameters.js";
class JsonStandardMaterialParser {
constructor() {
this._validator = null;
}
parse(input) {
const migrated = this.migrate(input);
const validated = this._validate(migrated);
const material = new StandardMaterial();
this.initialize(material, validated);
return material;
}
/**
* Initialize material properties from the material data block e.g. Loading from server.
*
* @param {StandardMaterial} material - The material to be initialized.
* @param {object} data - The data block that is used to initialize.
*/
initialize(material, data) {
if (!data.validated) {
data = this._validate(data);
}
if (data.chunks) {
if (data.chunks && Object.keys(data.chunks).length > 0) {
const dstMap = material.shaderChunks.glsl;
Object.entries(data.chunks).forEach(([key, value]) => dstMap.set(key, value));
}
}
for (const key in data) {
const type = standardMaterialParameterTypes[key];
const value = data[key];
if (type === "vec2") {
material[key] = new Vec2(value[0], value[1]);
} else if (type === "rgb") {
material[key] = new Color(value[0], value[1], value[2]);
} else if (type === "texture") {
if (value instanceof Texture) {
material[key] = value;
} else if (!(material[key] instanceof Texture && typeof value === "number" && value > 0)) {
material[key] = null;
}
} else if (type === "cubemap") {
if (value instanceof Texture) {
material[key] = value;
} else if (!(material[key] instanceof Texture && typeof value === "number" && value > 0)) {
material[key] = null;
}
if (key === "cubeMap" && !value) {
material.prefilteredCubemaps = null;
}
} else if (type === "boundingbox") {
const center = new Vec3(value.center[0], value.center[1], value.center[2]);
const halfExtents = new Vec3(value.halfExtents[0], value.halfExtents[1], value.halfExtents[2]);
material[key] = new BoundingBox(center, halfExtents);
} else {
material[key] = data[key];
}
}
material.update();
}
// convert any properties that are out of date
// or from old versions into current version
migrate(data) {
if (data.shader) delete data.shader;
if (data.mapping_format) {
data.mappingFormat = data.mapping_format;
delete data.mapping_format;
}
let i;
const RENAMED_PROPERTIES = [
["bumpMapFactor", "bumpiness"],
["aoUvSet", "aoMapUv"],
["aoMapVertexColor", "aoVertexColor"],
["diffuseMapVertexColor", "diffuseVertexColor"],
["emissiveMapVertexColor", "emissiveVertexColor"],
["specularMapVertexColor", "specularVertexColor"],
["metalnessMapVertexColor", "metalnessVertexColor"],
["opacityMapVertexColor", "opacityVertexColor"],
["glossMapVertexColor", "glossVertexColor"],
["lightMapVertexColor", "lightVertexColor"],
["specularMapTint", "specularTint"],
["metalnessMapTint", "metalnessTint"],
["clearCoatGlossiness", "clearCoatGloss"]
];
for (i = 0; i < RENAMED_PROPERTIES.length; i++) {
const _old = RENAMED_PROPERTIES[i][0];
const _new = RENAMED_PROPERTIES[i][1];
if (data[_old] !== void 0) {
if (data[_new] === void 0) {
data[_new] = data[_old];
}
delete data[_old];
}
}
const DEPRECATED_PROPERTIES = [
"fresnelFactor",
"shadowSampleType"
];
for (i = 0; i < DEPRECATED_PROPERTIES.length; i++) {
const name = DEPRECATED_PROPERTIES[i];
if (data.hasOwnProperty(name)) {
delete data[name];
}
}
return data;
}
// check for invalid properties
_validate(data) {
if (!data.validated) {
if (!this._validator) {
this._validator = new StandardMaterialValidator();
}
this._validator.validate(data);
}
return data;
}
}
export {
JsonStandardMaterialParser
};