materials.js 8.75 KB
import {
    MeshStandardMaterial,
    DoubleSide,
    Plane,
    Vector3,
    MeshBasicMaterial,
    AlwaysStencilFunc,
    BackSide,
    FrontSide,
    IncrementWrapStencilOp,
    DecrementWrapStencilOp,
    Mesh,
    NotEqualStencilFunc,
    ReplaceStencilOp,
    PlaneGeometry
} from 'three';
import { PLATFORMRANGE } from './platform-range';

// const MODEL_COLOR = 0xf8f4d6;
export const MODEL_COLOR = 0xfffac9;
export const SLECTED_MODEL_COLOR = 0x79a4fe;
export const BOUNDARYBOX_COLOR = 0xea5505;

export const PLATFORMRANGE_LINE_COLOR = 0x8f8f8f;

const STENCIL_PLANE_COLOR = 0xc85718;

export const slicingPlaneTop = new Plane(new Vector3(0, 0, -1), 0);
export const slicingPlaneBottom = new Plane(new Vector3(0, 0, 1), 0);
export const slicePlane = new Plane(new Vector3(0, 0, -1), 0);

const clippingPlane = new Plane(new Vector3(0, 0, 1), -0.03);

const { x, y, z } = PLATFORMRANGE;

const xClippingPlane = new Plane(new Vector3(1, 0, 0), x * 0.5);
const xnClippingPlane = new Plane(new Vector3(-1, 0, 0), x * 0.5);

const yClippingPlane = new Plane(new Vector3(0, 1, 0), y * 0.5);
const ynClippingPlane = new Plane(new Vector3(0, -1, 0), y * 0.5);

const zClippingPlane = new Plane(new Vector3(0, 0, -1), z);
const znClippingPlane = new Plane(new Vector3(0, 0, 1), 0.01);

let clippingPlanes = [
    slicingPlaneTop,
    slicingPlaneBottom,
    clippingPlane,
    xClippingPlane,
    xnClippingPlane,
    yClippingPlane,
    ynClippingPlane,
    zClippingPlane,
    znClippingPlane
];

export const updateClipPlanes = (range) => {
    xClippingPlane.constant = range.x * 0.5;
    xnClippingPlane.constant = range.x * 0.5;
    yClippingPlane.constant = range.y * 0.5;
    ynClippingPlane.constant = range.y * 0.5;
    zClippingPlane.constant = range.z;
    znClippingPlane.constant = 0.01;
    clippingPlanes = [
        slicingPlaneTop,
        slicingPlaneBottom,
        clippingPlane,
        xClippingPlane,
        xnClippingPlane,
        yClippingPlane,
        ynClippingPlane,
        zClippingPlane,
        znClippingPlane
    ];
    return clippingPlanes;
};

// 0.023, 0.474, 0.301
export const getSceneMeshMaterials = (color = MODEL_COLOR) => {
    return new MeshStandardMaterial({
        color,
        side: DoubleSide,
        roughness: 0.4,
        metalness: 0.1,
        transparent: false,
        opacity: 1
        // flatShading: true
        /*
        clippingPlanes,
        onBeforeCompile: (shader) => {
            shader.fragmentShader = shader.fragmentShader.replace('#include <clipping_planes_fragment>', '').replace(
                '#include <color_fragment>',
                `#include <color_fragment>
            vec4 xPlane = clippingPlanes[ 3 ];
            float xpDot = dot( vClipPosition, xPlane.xyz );

            vec4 xnPlane = clippingPlanes[ 4 ];
            float xnpDot = dot( vClipPosition, xnPlane.xyz );

            vec4 yPlane = clippingPlanes[ 5 ];
            float ypDot = dot( vClipPosition, yPlane.xyz );

            vec4 ynPlane = clippingPlanes[ 6 ];
            float ynpDot = dot( vClipPosition, ynPlane.xyz );

            vec4 zPlane = clippingPlanes[ 7 ];
            float zpDot = dot( vClipPosition, zPlane.xyz );

            vec4 znPlane = clippingPlanes[ 8 ];
            float znpDot = dot( vClipPosition, znPlane.xyz );

            vec4 plane = clippingPlanes[ 2 ];
            float pDot = dot( vClipPosition, plane.xyz );
            if( pDot  >= plane.w){
                diffuseColor.rgb = vec3(0.023, 0.474, 0.301);
            }
            if( xpDot  >= xPlane.w ||  xnpDot  >= xnPlane.w || ypDot  >= yPlane.w || ynpDot  >= ynPlane.w || zpDot  >= zPlane.w || znpDot  >= znPlane.w){
                diffuseColor.rgb = vec3(0.529, 0.031, 0.031);
            }

            vec4 slicingPlaneTop = clippingPlanes[ 0 ];
            float slicingTopDot = dot( vClipPosition, slicingPlaneTop.xyz );
            if( slicingTopDot > slicingPlaneTop.w){
                discard;
            }

            vec4 slicingPlaneBottom = clippingPlanes[ 1 ];
            float slicingBottomDot = dot( vClipPosition, slicingPlaneBottom.xyz );
            if( slicingBottomDot > slicingPlaneBottom.w){
                discard;
            }
        `
            );
        }
        */
    });
};

export const getSceneMeshMaterial = (color) => {
    return new MeshStandardMaterial({
        color,
        side: DoubleSide,
        roughness: 0.4,
        metalness: 0.1,
        vertexColors: false,
        transparent: false,
        opacity: 1
        // flatShading: true
        /*
        clippingPlanes,
        onBeforeCompile: (shader) => {
            shader.fragmentShader = shader.fragmentShader.replace('#include <clipping_planes_fragment>', '').replace(
                '#include <color_fragment>',
                `#include <color_fragment>
                vec4 xPlane = clippingPlanes[ 3 ];
                float xpDot = dot( vClipPosition, xPlane.xyz );
    
                vec4 xnPlane = clippingPlanes[ 4 ];
                float xnpDot = dot( vClipPosition, xnPlane.xyz );
    
                vec4 yPlane = clippingPlanes[ 5 ];
                float ypDot = dot( vClipPosition, yPlane.xyz );
    
                vec4 ynPlane = clippingPlanes[ 6 ];
                float ynpDot = dot( vClipPosition, ynPlane.xyz );
    
                vec4 zPlane = clippingPlanes[ 7 ];
                float zpDot = dot( vClipPosition, zPlane.xyz );
    
                vec4 znPlane = clippingPlanes[ 8 ];
                float znpDot = dot( vClipPosition, znPlane.xyz );
    
                vec4 plane = clippingPlanes[ 2 ];
                float pDot = dot( vClipPosition, plane.xyz );
                if( pDot  >= plane.w){
                    diffuseColor.rgb = vec3(0.023, 0.474, 0.301);
                }
                if( xpDot  >= xPlane.w ||  xnpDot  >= xnPlane.w || ypDot  >= yPlane.w || ynpDot  >= ynPlane.w || zpDot  >= zPlane.w || znpDot  >= znPlane.w){
                    diffuseColor.rgb = vec3(0.529, 0.031, 0.031);
                }
    
                vec4 slicingPlaneTop = clippingPlanes[ 0 ];
                float slicingTopDot = dot( vClipPosition, slicingPlaneTop.xyz );
                if( slicingTopDot > slicingPlaneTop.w){
                    discard;
                }
    
                vec4 slicingPlaneBottom = clippingPlanes[ 1 ];
                float slicingBottomDot = dot( vClipPosition, slicingPlaneBottom.xyz );
                if( slicingBottomDot > slicingPlaneBottom.w){
                    discard;
                }
            `
            );
        }*/
    });
};

// the geometry on cut plane faces
export const buildPlaneStencil = (geometry, plane, renderOrder) => {
    const baseMat = new MeshBasicMaterial();
    baseMat.depthWrite = false;
    baseMat.depthTest = false;
    baseMat.colorWrite = false;
    baseMat.stencilWrite = true;
    baseMat.stencilFunc = AlwaysStencilFunc;
    baseMat.flatShading = true;

    const backMaterial = baseMat.clone();
    backMaterial.side = BackSide;
    backMaterial.clippingPlanes = [plane];
    backMaterial.stencilFail = IncrementWrapStencilOp;
    backMaterial.stencilZPass = IncrementWrapStencilOp;

    const frontMaterial = baseMat.clone();
    frontMaterial.side = FrontSide;
    frontMaterial.clippingPlanes = [plane];
    frontMaterial.stencilFail = DecrementWrapStencilOp;
    frontMaterial.stencilZPass = DecrementWrapStencilOp;

    const backMesh = new Mesh(geometry, backMaterial);
    const frontMesh = new Mesh(geometry, frontMaterial);

    backMesh.renderOrder = renderOrder;
    frontMesh.renderOrder = renderOrder;

    return {
        backMesh,
        frontMesh
    };
};

const stencilPlaneMaterial = new MeshBasicMaterial({
    color: STENCIL_PLANE_COLOR,
    stencilWrite: true,
    stencilRef: 0,
    stencilFunc: NotEqualStencilFunc,
    stencilFail: ReplaceStencilOp,
    stencilZFail: ReplaceStencilOp,
    stencilZPass: ReplaceStencilOp
});

const materialTop = stencilPlaneMaterial.clone();
const materialBottom = stencilPlaneMaterial.clone();
materialBottom.depthTest = false;

export const stencilDisplayFacesPlaneTop = new Mesh(new PlaneGeometry(x, y), materialTop);
export const stencilDisplayFacesPlaneBottom = new Mesh(new PlaneGeometry(x, y), materialBottom);

stencilDisplayFacesPlaneTop.renderOrder = 3;
stencilDisplayFacesPlaneBottom.renderOrder = 4;

const sliceMaterial = new MeshBasicMaterial({
    color: 0xffffff,
    stencilWrite: true,
    stencilRef: 0,
    stencilFunc: NotEqualStencilFunc,
    flatShading: true,
    polygonOffset: true,
    polygonOffsetFactor: -1, // positive value pushes polygon further away
    polygonOffsetUnits: 4,
    stencilFail: ReplaceStencilOp,
    stencilZFail: ReplaceStencilOp,
    stencilZPass: ReplaceStencilOp,
    depthTest: false
});
export const stencilDisplayFacesSlicePlane = new Mesh(new PlaneGeometry(x, y), sliceMaterial);
stencilDisplayFacesSlicePlane.renderOrder = 3;