UNPKG

@itwin/core-backend

Version:
264 lines • 13 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Elements */ import { Id64, JsonUtils } from "@itwin/core-bentley"; import { BisCodeSpec, Code, } from "@itwin/core-common"; import { DefinitionElement } from "./Element"; /* eslint-disable @typescript-eslint/naming-convention */ /** A PhysicalMaterial defines the matter that makes up physical elements. * @note See [[RenderMaterialElement]] for the DefinitionElement used to define rendering characteristics. * @public */ export class PhysicalMaterial extends DefinitionElement { static get className() { return "PhysicalMaterial"; } /** Create a Code for a PhysicalMaterial given a name that is meant to be unique within the scope of the specified DefinitionModel. * @param iModel The IModelDb * @param definitionModelId The Id of the DefinitionModel that will contain the PhysicalMaterial and provide the scope for its name. * @param name The name (codeValue) of the PhysicalMaterial */ static createCode(iModel, definitionModelId, name) { const codeSpec = iModel.codeSpecs.getByName(BisCodeSpec.physicalMaterial); return new Code({ spec: codeSpec.id, scope: definitionModelId, value: name }); } /** Create a PhysicalMaterial * @param iModelDb The IModelDb * @param definitionModelId The Id of the DefinitionModel that will contain the PhysicalMaterial and provide the scope for its name. * @param name The name (codeValue) of the PhysicalMaterial * @returns The newly constructed PhysicalMaterial * @throws [[IModelError]] if there is a problem creating the PhysicalMaterial */ static create(iModelDb, definitionModelId, name) { const elementProps = { classFullName: this.classFullName, model: definitionModelId, code: this.createCode(iModelDb, definitionModelId, name), }; return iModelDb.elements.createElement(elementProps); } } /** Defines a rendering material. * @note See [[PhysicalMaterial]] for the DefinitionElement used to define the matter that makes up physical elements. * @public */ export class RenderMaterialElement extends DefinitionElement { static get className() { return "RenderMaterial"; } /** The name of a palette that can be used to categorize multiple materials. */ paletteName; /** An optional description of the material. */ description; constructor(props, iModel) { super(props, iModel); this.paletteName = props.paletteName; this.description = props.description; } toJSON() { const val = super.toJSON(); val.paletteName = this.paletteName; val.description = this.description; return val; } /** * RenderMaterialElement custom HandledProps includes 'paletteName'. * @inheritdoc * @beta */ static _customHandledProps = [ { propertyName: "paletteName", source: "Class" }, ]; /** * RenderMaterialElement deserializes 'paletteName'. * @inheritdoc * @beta */ static deserialize(props) { const elProps = super.deserialize(props); const instance = props.row; elProps.paletteName = JsonUtils.asString(instance.paletteName); return elProps; } /** * RenderMaterialElement serializes 'paletteName'. * @inheritdoc * @beta */ static serialize(props, iModel) { const inst = super.serialize(props, iModel); inst.paletteName = props.paletteName; return inst; } /** Create a Code for a RenderMaterial given a name that is meant to be unique within the scope of the specified DefinitionModel. * @param iModel The IModelDb * @param scopeModelId The Id of the DefinitionModel that contains the RenderMaterial and provides the scope for its name. * @param name The RenderMaterial name */ static createCode(iModel, scopeModelId, name) { const codeSpec = iModel.codeSpecs.getByName(BisCodeSpec.renderMaterial); return 0 === name.length ? Code.createEmpty() : new Code({ spec: codeSpec.id, scope: scopeModelId, value: name }); } /** * Create a RenderMaterial with given parameters. * @param iModelDb The iModel * @param definitionModelId The [[DefinitionModel]] * @param materialName The name/CodeValue of the RenderMaterial * @param params Parameters object which describes how to construct the RenderMaterial * @returns The newly constructed RenderMaterial element. * @throws [[IModelError]] if unable to create the element. */ static create(iModelDb, definitionModelId, materialName, params) { let maps; const pbr_normal = params.normalMap?.scale; if (params.patternMap || params.normalMap) { function choose(obj, key) { const pat = params.patternMap; if (pat && undefined !== pat[key]) obj[key] = pat[key]; else if (params.normalMap && undefined !== params.normalMap[key]) obj[key] = params.normalMap[key]; } const baseProps = {}; choose(baseProps, "pattern_angle"); choose(baseProps, "pattern_u_flip"); choose(baseProps, "pattern_flip"); choose(baseProps, "pattern_scale"); choose(baseProps, "pattern_offset"); choose(baseProps, "pattern_scalemode"); choose(baseProps, "pattern_mapping"); choose(baseProps, "pattern_weight"); choose(baseProps, "pattern_useconstantlod"); choose(baseProps, "pattern_constantlod_repetitions"); choose(baseProps, "pattern_constantlod_offset"); choose(baseProps, "pattern_constantlod_mindistanceclamp"); choose(baseProps, "pattern_constantlod_maxdistanceclamp"); maps = {}; if (params.patternMap) maps.Pattern = { ...params.patternMap, ...baseProps }; if (params.normalMap) { maps.Normal = { ...params.normalMap, ...baseProps, }; delete maps.Normal.scale; } } const renderMaterialProps = { classFullName: this.classFullName, code: this.createCode(iModelDb, definitionModelId, materialName), paletteName: params.paletteName, description: params.description, jsonProperties: { materialAssets: { renderMaterial: { HasBaseColor: params.color !== undefined, color: params.color, HasSpecularColor: params.specularColor !== undefined, specular_color: params.specularColor, HasFinish: params.finish !== undefined, finish: params.finish, HasTransmit: params.transmit !== undefined ? true : undefined, transmit: params.transmit, HasDiffuse: params.diffuse !== undefined, diffuse: params.diffuse, HasSpecular: params.specular !== undefined, specular: params.specular, HasReflect: params.reflect !== undefined, reflect: params.reflect, HasReflectColor: params.reflectColor !== undefined, reflect_color: params.reflectColor, Map: maps, pbr_normal, }, }, }, model: definitionModelId, isPrivate: false, }; return new RenderMaterialElement(renderMaterialProps, iModelDb); } /** * Insert a new RenderMaterial into a model. * @param iModelDb Insert into this iModel * @param definitionModelId Insert the new Texture into this DefinitionModel * @param materialName The name/CodeValue of the RenderMaterial * @param params Parameters object which describes how to construct the RenderMaterial * @returns The Id of the newly inserted RenderMaterial element. * @throws [[IModelError]] if unable to insert the element. */ static insert(iModelDb, definitionModelId, materialName, params) { const renderMaterial = this.create(iModelDb, definitionModelId, materialName, params); return iModelDb.elements.insertElement(renderMaterial.toJSON()); } /** @beta */ static onCloned(context, sourceProps, targetProps) { super.onCloned(context, sourceProps, targetProps); for (const mapName in sourceProps.jsonProperties?.materialAssets?.renderMaterial?.Map ?? {}) { if (typeof mapName !== "string") continue; const sourceMap = sourceProps.jsonProperties.materialAssets.renderMaterial.Map[mapName]; // sourceMap could be null/undefined, keep it the same in targetProps if (!sourceMap) { targetProps.jsonProperties.materialAssets.renderMaterial.Map[mapName] = sourceMap; continue; } if (!Id64.isValid(sourceMap.TextureId) || sourceMap.TextureId === undefined) continue; targetProps.jsonProperties.materialAssets.renderMaterial.Map[mapName].TextureId = context.findTargetElementId(sourceMap.TextureId ?? Id64.invalid); } } } /** @public */ (function (RenderMaterialElement) { /** Parameters used to construct a [[RenderMaterial]]. * The persistent JSON representation - [RenderMaterialAssetProps]($common) - is quite verbose and unwieldy. This representation simplifies it somewhat. * @see [[RenderMaterialElement.create]] and [[RenderMaterialElement.insert]] to create a [[RenderMaterial]] from parameters of this type. * @deprecated in 3.6 - might be removed in next major version. Because it is not useful to use a `class` - just use [[RenderMaterialElementParams]] directly instead. */ class Params { /** A required palette name that categorizes this RenderMaterial */ paletteName; /** An optional description of this RenderMaterial */ description; /** If defined, the color to use for surface fill or diffuse illumination, overriding the surface's own color. */ color; /** The color to use for specular illumination. Default: black. */ specularColor; /** The specular exponent describing the surface's shininess, in the range 0 through 128. * Default: 0. */ finish; /** A transparency to be applied to the surface, ranging from 0 (fully opaque) to 1 (fully transparent). * If defined, then the material transparency overrides the transparency of whatever surface the material is applied to. * If undefined, the material has no effect on surface transparency. * Default: undefined. */ transmit; /** The surface's diffuse reflectivity from 0.0 to 1.0. Default: 0.6. */ diffuse; /** The surface's specular reflectivity from 0.0 to 1.0. Default: 0.0. */ specular; /** Currently unused. */ reflect; /** Currently unused. */ reflectColor; /** Specifies a texture image to map onto the surface, replacing or mixing with the surface's own color and transparency. * @note With the exception of `TextureId`, the [TextureMapProps]($common) of [[patternMap]] and [[normalMap]] are expected to be identical. If a property is defined in both * [[patternMap]]] and [[normalMap]], the value in [[patternMap]] takes precedence. */ patternMap; /** Specifies a [normal map](https://en.wikipedia.org/wiki/Normal_mapping) to apply to the surface to simulate more surface detail than is present in the * surface's geometry. * @note With the exception of `TextureId`, the [TextureMapProps]($common) of [[patternMap]] and [[normalMap]] are expected to be identical. If a property is defined in both * [[patternMap]]] and [[normalMap]], the value in [[patternMap]] takes precedence. */ normalMap; /** Construct a new RenderMaterial.Params object with the specified paletteName. Alter the public members on that object to specify settings. */ constructor(paletteName) { this.paletteName = paletteName; } } RenderMaterialElement.Params = Params; })(RenderMaterialElement || (RenderMaterialElement = {})); //# sourceMappingURL=Material.js.map