Skip to content

Commit

Permalink
add fill clipped geometry with color (#94)
Browse files Browse the repository at this point in the history
  • Loading branch information
ostatni5 committed Sep 24, 2021
1 parent 41b562e commit ccc8b98
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/ThreeEditor/js/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function Editor() {
//YAPTIDE zones
zoneAdded: new Signal(),
zoneChanged: new Signal(),
zoneGeometryChanged: new Signal(),
zoneRemoved: new Signal(),

cameraAdded: new Signal(),
Expand Down
123 changes: 122 additions & 1 deletion src/ThreeEditor/js/Viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ export function Viewport(
}

let sceneViewHelpers = new THREE.Scene();
let clippedScene = new THREE.Scene();

var skyColor = 0x00aaff; // Deep Sky Blue
var groundColor = 0xffaa00; // Orange
var intensity = 1;

var light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
light.name = 'HemisphereLight';

light.position.set(10000, 10000, 0);
clippedScene.add(light)


let container = new UIPanel();
container.setId('ViewPanel');
Expand Down Expand Up @@ -94,6 +106,9 @@ export function Viewport(
},
set [planePosProperty](v) {

po.translateZ(v - globalPlane.constant);
console.log(v - globalPlane.constant, po.position);

globalPlane.constant = v;

signals.viewportConfigChanged.dispatch({ name, globalPlaneConstant: v });
Expand Down Expand Up @@ -123,9 +138,113 @@ export function Viewport(
gui.domElement.style.position = "absolute";
gui.domElement.style.top = "35px";
gui.domElement.style.right = "-5px";


function createPlaneStencilGroup(geometry, plane, renderOrder) {

const group = new THREE.Group();
const baseMat = new THREE.MeshBasicMaterial();
baseMat.depthWrite = false;
baseMat.depthTest = false;
baseMat.colorWrite = false;
baseMat.stencilWrite = true;
baseMat.stencilFunc = THREE.AlwaysStencilFunc;

// back faces
const mat0 = baseMat.clone();
mat0.side = THREE.BackSide;
mat0.clippingPlanes = [plane];
mat0.stencilFail = THREE.IncrementWrapStencilOp;
mat0.stencilZFail = THREE.IncrementWrapStencilOp;
mat0.stencilZPass = THREE.IncrementWrapStencilOp;

const mesh0 = new THREE.Mesh(geometry, mat0);
mesh0.renderOrder = renderOrder;
group.add(mesh0);

// front faces
const mat1 = baseMat.clone();
mat1.side = THREE.FrontSide;
mat1.clippingPlanes = [plane];
mat1.stencilFail = THREE.DecrementWrapStencilOp;
mat1.stencilZFail = THREE.DecrementWrapStencilOp;
mat1.stencilZPass = THREE.DecrementWrapStencilOp;

const mesh1 = new THREE.Mesh(geometry, mat1);
mesh1.renderOrder = renderOrder;

group.add(mesh1);

return group;

}

const planeGeom = new THREE.PlaneGeometry(10, 10);

const clippedObjects = new THREE.Group();
clippedScene.add(clippedObjects);


const poGroup = new THREE.Group();



zonesManager.children.forEach((zone) => {
const stencilGroup = createPlaneStencilGroup(zone.geometry, globalPlane, 1);
stencilGroup.name = zone.uuid;
clippedObjects.add(stencilGroup);
});

signals.zoneGeometryChanged.add(function (zone) {
clippedObjects.remove(clippedObjects.getObjectByName(zone.uuid));

const stencilGroup = createPlaneStencilGroup(zone.geometry, globalPlane, 1);
stencilGroup.name = zone.uuid;
clippedObjects.add(stencilGroup);

});

// plane is clipped by the other clipping planes
const planeMat =
new THREE.MeshStandardMaterial({

color: 0x00ff00,
metalness: 0.1,
roughness: 0.75,

stencilWrite: true,
stencilRef: 0,
stencilFunc: THREE.NotEqualStencilFunc,
stencilFail: THREE.ReplaceStencilOp,
stencilZFail: THREE.ReplaceStencilOp,
stencilZPass: THREE.ReplaceStencilOp,

});
const po = new THREE.Mesh(planeGeom, planeMat);
po.onAfterRender = function (renderer) {

renderer.clearStencil();

};
po.renderOrder = 1.1;
poGroup.add(po);
clippedScene.add(poGroup);

globalPlane.coplanarPoint(po.position);
po.lookAt(
po.position.x - globalPlane.normal.x,
po.position.y - globalPlane.normal.y,
po.position.z - globalPlane.normal.z,
);
po.translateZ(-.01)


}





let cachedRenderer = null;

function render(renderer = cachedRenderer) {
Expand All @@ -147,6 +266,8 @@ export function Viewport(

renderer.autoClear = false;

renderer.render(clippedScene, camera);

config.showZones && renderer.render(zonesManager, camera);

renderer.clippingPlanes = []; // clear clipping planes for next renders
Expand Down Expand Up @@ -528,7 +649,7 @@ export function Viewport(

render();
})

signals.selectModeChanged.add((mode) => {
//TODO: clicking on zones selects them if zoneSelectionMode is enabled
})
Expand Down
40 changes: 21 additions & 19 deletions src/ThreeEditor/util/CSG/CSGZone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class CSGZone extends THREE.Mesh {
geometryChanged: Signal<THREE.Object3D>;
sceneGraphChanged: Signal;
zoneAdded: Signal<CSGZone>;
zoneGeometryChanged: Signal<CSGZone>;
zoneRemoved: Signal<CSGZone>;
CSGManagerStateChanged: Signal;
};
Expand All @@ -43,29 +44,29 @@ export class CSGZone extends THREE.Mesh {
) {
super();
this.type = "Zone";
this.editor = editor;
this.signals = editor.signals;
this.name = name || "CSGZone";
this.material = new THREE.MeshNormalMaterial();
this.subscribedObjectsUuid = subscribedObjectsUuid || new Set();
this.unionOperations = unionOperations
? (() => {
// If operations are specified, we have to populate set of subscribed UUID's
subscribedObjectsUuid ||
unionOperations.forEach((op1) =>
op1
.map((op2) => op2.object.uuid)
.forEach(
this.subscribedObjectsUuid.add,
this.subscribedObjectsUuid
)
);
return unionOperations;
})()
// If operations are specified, we have to populate set of subscribed UUID's
subscribedObjectsUuid ||
unionOperations.forEach((op1) =>
op1
.map((op2) => op2.object.uuid)
.forEach(
this.subscribedObjectsUuid.add,
this.subscribedObjectsUuid
)
);
return unionOperations;
})()
: [];

// If operations are specified, we have to generate fist geometry manually.
unionOperations && this.updateGeometry();
this.editor = editor;
this.signals = editor.signals;

this.signals.geometryChanged.add((object) => this.handleSignal(object));
this.signals.objectChanged.add((object) => this.handleSignal(object));
Expand Down Expand Up @@ -124,6 +125,7 @@ export class CSGZone extends THREE.Mesh {
this.geometry = geometryResult;
this.geometry.computeBoundingSphere();
this.updateMatrixWorld(true);
this.signals.zoneGeometryChanged.dispatch(this);
console.timeEnd("CSGZone");
}

Expand Down Expand Up @@ -209,11 +211,11 @@ export class CSGZone extends THREE.Mesh {
let subscribedObjectsUuid = Array.isArray(data.subscribedObjectsUuid)
? new Set(data.subscribedObjectsUuid)
: (() => {
throw Error(
"SubscribedObjectsId is not array" +
data.subscribedObjectsUuid
);
})();
throw Error(
"SubscribedObjectsId is not array" +
data.subscribedObjectsUuid
);
})();

let zone = new CSGZone(
editor,
Expand Down

0 comments on commit ccc8b98

Please sign in to comment.