import { RESOLUTION, HIGHLIGHT_COLORS, VISIBILITY_PROPERTY_DEFINE, HIGHLIGHT_PROPERTY_DEFINE
// ORTHO_SIZE_DISTANCE_EFFECT_CUTOFF,
// PERSPECTIVE_SIZE_DISTANCE_EFFECT_CUTOFF
 } from '../ShaderConstants';
import { packedNormalPackSize } from '../PackedNormal';
import { Color4, Vector3, Color3, Vector2, Matrix, Camera } from '../babylonjs-import';
import { clipPlanesStrings } from './CullingMaterial';
import { DitheringMaterial } from './DitheringMaterial';
import { ifcShader } from './shaders/IfcShader';
export var IfcMaterialRenderProperty;
(function (IfcMaterialRenderProperty) {
    IfcMaterialRenderProperty[IfcMaterialRenderProperty["depthWriteIgnoresVisibility"] = 24] = "depthWriteIgnoresVisibility"; /* 0b00001 */
    IfcMaterialRenderProperty[IfcMaterialRenderProperty["visibility"] = 25] = "visibility"; /* 0b00010 */
    IfcMaterialRenderProperty[IfcMaterialRenderProperty["highlight"] = 26] = "highlight";
    IfcMaterialRenderProperty[IfcMaterialRenderProperty["outline"] = 28] = "outline"; /* 0b01000 */
    IfcMaterialRenderProperty[IfcMaterialRenderProperty["ignoreClipPlanes"] = 29] = "ignoreClipPlanes"; /* 0b10000 */
})(IfcMaterialRenderProperty || (IfcMaterialRenderProperty = {}));
export var IfcMaterialHighlightIndex;
(function (IfcMaterialHighlightIndex) {
    IfcMaterialHighlightIndex[IfcMaterialHighlightIndex["None"] = 0] = "None";
    IfcMaterialHighlightIndex[IfcMaterialHighlightIndex["One"] = 1] = "One";
    IfcMaterialHighlightIndex[IfcMaterialHighlightIndex["Two"] = 2] = "Two";
    IfcMaterialHighlightIndex[IfcMaterialHighlightIndex["Three"] = 3] = "Three"; // 3
})(IfcMaterialHighlightIndex || (IfcMaterialHighlightIndex = {}));
const DIFFUSE_SAMPLER = 'diffuseSampler';
const PROPERTIES_SAMPLER = 'propertiesSampler';
const DIRECTIONAL_LIGHT_WORLD_SPACE_DIRECTION = 'directionalLightWorldSpaceDirection';
const DIRECTIONAL_LIGHT_DEPTH_VALUES = 'directionalLightDepthValues';
const DIRECTIONAL_LIGHT_COLOR = 'directionalLightColor';
const DIRECTIONAL_LIGHT_STRENGTH = 'directionalLightStrength';
const DIRECTIONAL_LIGHT_LAMBERT_STRENGTH = 'directionalLightLambertStrength';
const DIRECTIONAL_LIGHT_SPECULAR_STRENGTH = 'directionalLightSpecularStrength';
const HEMISPHERIC_LIGHT_WORLD_SPACE_DIRECTION = 'hemisphericLightWorldSpace';
const HEMISPHERIC_LIGHT_COLOR = 'hemisphericLightColor';
const HEMISPHERIC_LIGHT_STRENGTH = 'hemisphericLightStrength';
const SIZE = 'size';
const PACK_SIZE = 'packSize';
const WORLD_MATRIX = 'worldMatrix';
const EYE_POSITION_WORLD_SPACE = 'eyePositionW';
const AMBIENT_COLOR = 'ambientColor';
const GROUND_COLOR = 'groundColor';
const CAMERA_POSITION_WORLD_SPACE = 'cameraPositionW';
const MATERIAL_DIFFUSE_COLOR = 'materialDiffuseColor';
const FAR_PLANE = 'farPlane';
const NEAR_PLANE = 'nearPlane';
const IS_PERSPECTIVE_CAMERA = 'isPerspective';
const ORTHO_CAMERA_FRUSTUM_SIZE = 'orthoSize';
const MATERIAL_DIFFUSE_COLOR_DEFAULT_VALUE = new Color4(0.93, 0.93, 0.93, 1.0);
export class IfcMaterial extends DitheringMaterial {
    diffuseTexture;
    propertiesTexture;
    ditherTexture;
    static _tmp = {
        vectorA: Vector3.Zero(),
        colorA: Color3.White(),
        matrixA: Matrix.Identity()
    };
    constructor(name, scene, renderingInfo, diffuseTexture, propertiesTexture, ditherTexture) {
        super(name, scene, renderingInfo, {
            attributes: ['position', 'uv'],
            samplers: []
        }, ditherTexture, true, false);
        this.diffuseTexture = diffuseTexture;
        this.propertiesTexture = propertiesTexture;
        this.ditherTexture = ditherTexture;
        this._isDitherModeEnabled = true;
        this.visualSettings.ifc.color.onPropertyChanged.add(() => {
            this.isDirty = true;
        });
    }
    getUniformsAndDefinesAndSamplers() {
        const defines = [
            'DITHERING_OPACITY_COEFFICIENT 1.0 / 3.0',
            VISIBILITY_PROPERTY_DEFINE,
            HIGHLIGHT_PROPERTY_DEFINE
        ];
        const uniforms = [
            'worldViewProjection',
            SIZE,
            PACK_SIZE,
            WORLD_MATRIX,
            EYE_POSITION_WORLD_SPACE,
            AMBIENT_COLOR,
            GROUND_COLOR,
            MATERIAL_DIFFUSE_COLOR,
            HEMISPHERIC_LIGHT_WORLD_SPACE_DIRECTION,
            HEMISPHERIC_LIGHT_COLOR,
            HEMISPHERIC_LIGHT_STRENGTH,
            DIRECTIONAL_LIGHT_COLOR,
            DIRECTIONAL_LIGHT_WORLD_SPACE_DIRECTION,
            DIRECTIONAL_LIGHT_STRENGTH,
            DIRECTIONAL_LIGHT_LAMBERT_STRENGTH,
            DIRECTIONAL_LIGHT_SPECULAR_STRENGTH,
            DIRECTIONAL_LIGHT_DEPTH_VALUES,
            CAMERA_POSITION_WORLD_SPACE,
            FAR_PLANE,
            NEAR_PLANE,
            IS_PERSPECTIVE_CAMERA,
            ORTHO_CAMERA_FRUSTUM_SIZE
        ];
        const samplers = [DIFFUSE_SAMPLER, PROPERTIES_SAMPLER];
        // Babylonjs need to have every index of uniform arrays addded to the list of uniforms used by the shader
        for (let i = 0; i < 3; i++) {
            uniforms.push(HIGHLIGHT_COLORS + '[' + i + ']');
        }
        const uniformsAndSamplers = super.getUniformsAndDefinesAndSamplers();
        const aggregatedUniformsAndSamplers = {
            uniforms: [...uniformsAndSamplers.uniforms, ...uniforms],
            defines: [...uniformsAndSamplers.defines, ...defines],
            samplers: [...uniformsAndSamplers.samplers, ...samplers]
        };
        this.visualSettings.ifc.color._insertUniformsAndDefines(aggregatedUniformsAndSamplers);
        return aggregatedUniformsAndSamplers;
    }
    bindFunction(mesh) {
        super.bindFunction(mesh);
        const scene = this.getScene();
        const camera = scene.activeCamera;
        if (!camera) {
            throw new Error('Active scene with no active camera?');
        }
        const effect = this.getEffect();
        effect.setTexture(PROPERTIES_SAMPLER, this.propertiesTexture.getTexture(mesh.getScene()));
        effect.setTexture(DIFFUSE_SAMPLER, this.diffuseTexture.getTexture(mesh.getScene()));
        effect.setFloat(PACK_SIZE, packedNormalPackSize);
        effect.setFloat(FAR_PLANE, camera.maxZ);
        effect.setFloat(NEAR_PLANE, camera.minZ);
        effect.setBool(IS_PERSPECTIVE_CAMERA, camera.mode === Camera.PERSPECTIVE_CAMERA);
        if (camera.twinfinity.viewer && camera.mode === Camera.ORTHOGRAPHIC_CAMERA) {
            const deltaVert = camera.orthoTop - camera.orthoBottom;
            const deltaHorizontal = camera.orthoRight - camera.orthoLeft;
            effect.setFloat(ORTHO_CAMERA_FRUSTUM_SIZE, deltaVert + deltaHorizontal);
        }
        // The shader calculates normals in the fragment shader. To do so it is passed
        // the world position of the vertex. If the world positions are very large then
        // the precision of calculated the normals will suffer. To avoid we
        // subtract the camera position from the worldMatrix. That way
        // if the camera is close the the objects we get "small" coordinates in the calculated position
        // values and therefore the normal calculations do not get precision issues.
        // When calculating the normals it does not matter that its not the "real" world
        // coordinates.
        const wm = IfcMaterial._tmp.matrixA.copyFrom(mesh.getWorldMatrix());
        const { x, y, z } = camera.position;
        wm.addTranslationFromFloats(-x, -y, -z);
        effect.setMatrix(WORLD_MATRIX, wm);
        effect.setVector3(EYE_POSITION_WORLD_SPACE, camera.position);
        this.setColor4(MATERIAL_DIFFUSE_COLOR, MATERIAL_DIFFUSE_COLOR_DEFAULT_VALUE);
        effect.setColor3(AMBIENT_COLOR, this.visualSettings.ifc.lighting.ambient);
        const hemisphericLight = this.visualSettings.lighting.hemisphericLight;
        const directionalLight = this.visualSettings.lighting.directionalLight;
        const worldSpaceDirectionalLightDirection = directionalLight.direction;
        const groundColor = IfcMaterial._tmp.colorA
            .copyFrom(hemisphericLight.groundColor)
            .scale(hemisphericLight.intensity); // Since Color3.scale is inplace op we must copy the light color first.
        effect.setColor3(GROUND_COLOR, groundColor);
        effect.setColor3(HEMISPHERIC_LIGHT_COLOR, hemisphericLight.diffuse);
        effect.setVector3(HEMISPHERIC_LIGHT_WORLD_SPACE_DIRECTION, hemisphericLight.direction);
        effect.setVector3(CAMERA_POSITION_WORLD_SPACE, camera.position);
        effect.setVector2(RESOLUTION, new Vector2(scene.getEngine().getRenderWidth(), scene.getEngine().getRenderHeight()));
        effect.setColor3(DIRECTIONAL_LIGHT_COLOR, directionalLight.diffuse);
        effect.setFloat(DIRECTIONAL_LIGHT_STRENGTH, this.visualSettings.ifc.lighting.directionalLightStrength);
        effect.setFloat(DIRECTIONAL_LIGHT_LAMBERT_STRENGTH, this.visualSettings.ifc.lighting.directionalLightLambertStrength);
        effect.setFloat(DIRECTIONAL_LIGHT_SPECULAR_STRENGTH, this.visualSettings.ifc.lighting.directionalLightSpecularStrength);
        effect.setFloat(HEMISPHERIC_LIGHT_STRENGTH, this.visualSettings.ifc.lighting.hemisphericLightStrength);
        effect.setVector3(DIRECTIONAL_LIGHT_WORLD_SPACE_DIRECTION, worldSpaceDirectionalLightDirection);
        this.visualSettings.ifc.color._setEffectValues(effect);
        this.visualSettings.ifc._setEffectValues(effect);
    }
    getFragmentSource() {
        return ifcShader.fragment({
            clipPlaneUniforms: () => {
                return clipPlanesStrings.CLIP_PLANE_UNIFORMS;
            },
            clipPlaneDiscarding: () => {
                return clipPlanesStrings.CLIP_PLANE_DISCARDING;
            },
            clipPlaneColorBlending: () => {
                return clipPlanesStrings.CLIP_PLANE_COLOR_BLENDING;
            }
        });
    }
    getVertexSource() {
        return ifcShader.vertex();
    }
}
//# sourceMappingURL=IfcMaterial.js.map