- add slicing box

- new files: material.js, Picking.js, PlaneGeometry.js, Selection.js, SelectionBoxFace.js, SelectionBoxLine.js, shader.js, uniforms.js
- changed files: main.js
This commit is contained in:
Arno Kaimbacher 2021-02-17 18:15:15 +01:00
parent 8b4ace6763
commit 486896581c
9 changed files with 594 additions and 8 deletions

218
src/js/clip/Picking.js Normal file
View File

@ -0,0 +1,218 @@
import { Vector2 } from 'three/src/math/Vector2';
import { Vector3 } from 'three/src/math/Vector3';
import { Raycaster } from 'three/src/core/Raycaster';
import { PlaneGeometry } from 'three/src/geometries/PlaneGeometry';
import { Mesh } from 'three/src/objects/Mesh';
import * as material from '../clip/material';
import * as domEvent from '../core/domEvent';
import * as browser from '../core/browser';
export class Picking {
simulation;
intersected;
mouse;
ray;
normals;
plane;
touchCapable = false;
isDraging = false;
constructor(size, center, simulation) {
this.size = size;
this.center = center;
if (browser.touch && browser.mobile) {
this.touchCapable = true;
}
this.simulation = simulation;
this.intersected = null;
this.mouse = new Vector2();
this.ray = new Raycaster();
this.normals = {
x1: new Vector3(-1, 0, 0),
x2: new Vector3(1, 0, 0),
y1: new Vector3(0, -1, 0),
y2: new Vector3(0, 1, 0),
z1: new Vector3(0, 0, -1),
z2: new Vector3(0, 0, 1)
};
let planeGeometry = new PlaneGeometry(this.size, this.size, 4, 4);
this.plane = new Mesh(planeGeometry, material.Invisible);
simulation.scene.add(this.plane);
this.domElement = simulation.renderer.domElement;
if (this.touchCapable) {
domEvent.on(this.domElement, 'mousemove', this.mouseMove, this);
domEvent.on(this.domElement, 'touchstart', this.beginDrag, this);
} else {
domEvent.on(this.domElement, 'mousemove', this.mouseMove, this);
domEvent.on(this.domElement, 'mousedown', this.beginDrag, this);
}
}
_getOffset(element) {
if (!element.getClientRects().length) {
return { top: 0, left: 0 };
}
let rect = element.getBoundingClientRect();
let win = element.ownerDocument.defaultView;
return (
{
top: rect.top + win.pageYOffset,
left: rect.left + win.pageXOffset
});
}
_getCanvasPoint(event) {
let canvasOffset = this._getOffset(this.simulation.renderer.domElement);
let eventX = (event.clientX !== undefined) ? event.clientX : (event.touches && event.touches[0].clientX);
let eventY = (event.clientY !== undefined) ? event.clientY : (event.touches && event.touches[0].clientY);
let xClickedOnCanvas = eventX - canvasOffset.left;
let yClickedonCanvas = eventY - canvasOffset.top;
return {
x: xClickedOnCanvas,
y: yClickedonCanvas
}
}
mouseMove(event) {
if (this.isDraging == true) {
return;
}
let point = this._getCanvasPoint(event);
let width = this.simulation.renderer.domElement.clientWidth;
let height = this.simulation.renderer.domElement.clientHeight;
let x = (point.x / width) * 2 - 1;
let y = -(point.y / height) * 2 + 1;
this.mouse.set(x, y);
this.ray.setFromCamera(this.mouse, this.simulation.camera);
let intersects = this.ray.intersectObjects(this.simulation.selection.selectables);
if (intersects.length > 0) {
let candidate = intersects[0].object;
if (this.intersected !== candidate) {
if (this.intersected !== null) {
this.intersected.guardian.rayOut();
}
candidate.guardian.rayOver();
this.intersected = candidate;
this.simulation.renderer.domElement.style.cursor = 'pointer';
// this.simulation.throttledRender();
this.simulation.animate();
}
} else if (this.intersected !== null) {
// cursor is not selecting the box
this.intersected.guardian.rayOut();
this.intersected = null;
this.simulation.renderer.domElement.style.cursor = 'auto';
// this.simulation.throttledRender();
this.simulation.animate();
}
}
beginDrag(event) {
// this.mouse.setToNormalizedDeviceCoordinates(event, window);
let point = this._getCanvasPoint(event);
let width = this.simulation.renderer.domElement.clientWidth;
let height = this.simulation.renderer.domElement.clientHeight;
let x = (point.x / width) * 2 - 1;
let y = -(point.y / height) * 2 + 1;
this.mouse.set(x, y);
this.ray.setFromCamera(this.mouse, this.simulation.camera);
let intersects = this.ray.intersectObjects(this.simulation.selection.selectables);
if (intersects.length > 0) {
this.isDraging = true;
event.preventDefault();
event.stopPropagation();
this.simulation.map.enabled = false;
var intersectionPoint = intersects[0].point;
var axis = intersects[0].object.axis;
if (axis === 'x1' || axis === 'x2') {
// intersectionPoint.setX(0);
intersectionPoint.setX(this.center.x);
} else if (axis === 'y1' || axis === 'y2') {
// intersectionPoint.setY(0);
intersectionPoint.setY(this.center.y);
} else if (axis === 'z1' || axis === 'z2') {
// intersectionPoint.setZ(0);
intersectionPoint.setZ(this.center.z);
}
this.plane.position.copy(intersectionPoint);
let newNormal = this.simulation.camera.position.clone().sub(
this.simulation.camera.position.clone().projectOnVector(this.normals[axis])
);
this.plane.lookAt(newNormal.add(intersectionPoint));
this.simulation.renderer.domElement.style.cursor = 'grab';
// simulation.throttledRender();
this.simulation.animate();
let continueDrag = function (event) {
event.preventDefault();
event.stopPropagation();
// this.mouse.setToNormalizedDeviceCoordinates(event, window);
let point = this._getCanvasPoint(event);
let width = this.simulation.renderer.domElement.clientWidth;
let height = this.simulation.renderer.domElement.clientHeight;
let x = (point.x / width) * 2 - 1;
let y = -(point.y / height) * 2 + 1;
this.mouse.set(x, y);
this.ray.setFromCamera(this.mouse, this.simulation.camera);
let intersects = this.ray.intersectObject(this.plane);
if (intersects.length > 0) {
let value;
if (axis === 'x1' || axis === 'x2') {
value = intersects[0].point.x;
} else if (axis === 'y1' || axis === 'y2') {
value = intersects[0].point.y;
} else if (axis === 'z1' || axis === 'z2') {
value = intersects[0].point.z;
}
this.simulation.selection.setValue(axis, value);
// this.simulation.selection.setValue('x1', 4452960);
// this.simulation.throttledRender();
this.simulation.animate();
}
};
let endDrag = function (event) {
this.isDraging = false;
this.simulation.map.enabled = true;
this.simulation.renderer.domElement.style.cursor = 'pointer';
domEvent.off(this.domElement, "mousemove", continueDrag, this);
domEvent.off(this.domElement, "touchmove", continueDrag, this);
domEvent.off(this.domElement, "mouseup", endDrag, this);
domEvent.off(this.domElement, 'mouseleave', endDrag, this);
domEvent.off(this.domElement, 'touchend', endDrag, this);
domEvent.off(this.domElement, 'touchcancel', endDrag, this);
domEvent.off(this.domElement, 'touchleave', endDrag, this);
};
if (this.touchCapable) {
domEvent.on(this.domElement, 'touchmove', continueDrag, this);
domEvent.on(this.domElement, 'touchend', endDrag, this);
domEvent.on(this.domElement, 'touchcancel', endDrag, this);
domEvent.on(this.domElement, 'touchleave', endDrag, this);
} else {
domEvent.on(this.domElement, 'mousemove', continueDrag, this);
domEvent.on(this.domElement, 'mouseup', endDrag, this);
domEvent.on(this.domElement, 'mouseleave', endDrag, this);
}
}
}
}

View File

@ -0,0 +1,25 @@
import { BufferGeometry } from 'three/src/core/BufferGeometry';
import { Uint16BufferAttribute } from 'three/src/core/BufferAttribute';
export class PlaneGeometry extends BufferGeometry {
vertices = [];
constructor(v0, v1, v2, v3) {
super();
this.vertices.push(v0, v1, v2, v3);
this.setFromPoints(this.vertices);
let indexArray = [0, 1, 2, 0, 2, 3];
let indices = new Uint16BufferAttribute(indexArray, 1);//.setDynamic(true);
this.setIndex(indices);
this.computeVertexNormals();
}
update() {
this.setFromPoints(this.vertices);
this.attributes.position.needsUpdate = true;
this.computeBoundingSphere();
}
}

159
src/js/clip/Selection.js Normal file
View File

@ -0,0 +1,159 @@
import { BoxGeometry } from 'three/src/geometries/BoxGeometry';
import { Mesh } from 'three/src/objects/Mesh';
import * as material from './material';
import { Vector3 } from 'three/src/math/Vector3';
import { Object3D } from 'three/src/core/Object3D';
import { uniforms } from "./uniforms";
import { SelectionBoxFace } from './SelectionBoxFace';
import { SelectionBoxLine } from './SelectionBoxLine';
export class Selection {
limitLow;
limitHigh;
box;
boxMesh;
vertices;
touchMeshes; displayMeshes; meshGeometries; selectables;
faces;
constructor(low, high) {
this.limitLow = low;
this.limitHigh = high;
this.limit = {
x1: low.x,
y1: low.y,
x2: high.x,
y2: high.y
}
this.box = new BoxGeometry(1, 1, 1);
this.boxMesh = new Mesh(this.box, material.capMaterial);
this.vertices = [
new Vector3(), new Vector3(),
new Vector3(), new Vector3(),
new Vector3(), new Vector3(),
new Vector3(), new Vector3()
];
this.updateVertices();
let v = this.vertices;
this.touchMeshes = new Object3D();
this.displayMeshes = new Object3D();
this.meshGeometries = [];
this.lineGeometries = [];
this.selectables = [];
this.faces = [];
var f = this.faces;
this.faces.push(new SelectionBoxFace('y1', v[0], v[1], v[5], v[4], this));
this.faces.push(new SelectionBoxFace('z1', v[0], v[2], v[3], v[1], this));
this.faces.push(new SelectionBoxFace('x1', v[0], v[4], v[6], v[2], this));
this.faces.push(new SelectionBoxFace('x2', v[7], v[5], v[1], v[3], this));
this.faces.push(new SelectionBoxFace('y2', v[7], v[3], v[2], v[6], this));
this.faces.push(new SelectionBoxFace('z2', v[7], v[6], v[4], v[5], this));
this.boxLines = [];
this.boxLines.push(new SelectionBoxLine(v[0], v[1], f[0], f[1], this));
this.boxLines.push(new SelectionBoxLine(v[0], v[2], f[1], f[2], this));
this.boxLines.push(new SelectionBoxLine(v[0], v[4], f[0], f[2], this));
this.boxLines.push(new SelectionBoxLine(v[1], v[3], f[1], f[3], this));
this.boxLines.push(new SelectionBoxLine(v[1], v[5], f[0], f[3], this));
this.boxLines.push(new SelectionBoxLine(v[2], v[3], f[1], f[4], this));
this.boxLines.push(new SelectionBoxLine(v[2], v[6], f[2], f[4], this));
this.boxLines.push(new SelectionBoxLine(v[3], v[7], f[3], f[4], this));
this.boxLines.push(new SelectionBoxLine(v[4], v[5], f[0], f[5], this));
this.boxLines.push(new SelectionBoxLine(v[4], v[6], f[2], f[5], this));
this.boxLines.push(new SelectionBoxLine(v[5], v[7], f[3], f[5], this));
this.boxLines.push(new SelectionBoxLine(v[6], v[7], f[4], f[5], this));
this.setBox();
this.setUniforms();
}
updateVertices() {
this.vertices[0].set(this.limitLow.x, this.limitLow.y, this.limitLow.z);
this.vertices[1].set(this.limitHigh.x, this.limitLow.y, this.limitLow.z);
this.vertices[2].set(this.limitLow.x, this.limitHigh.y, this.limitLow.z);
this.vertices[3].set(this.limitHigh.x, this.limitHigh.y, this.limitLow.z);
this.vertices[4].set(this.limitLow.x, this.limitLow.y, this.limitHigh.z);
this.vertices[5].set(this.limitHigh.x, this.limitLow.y, this.limitHigh.z);
this.vertices[6].set(this.limitLow.x, this.limitHigh.y, this.limitHigh.z);
this.vertices[7].set(this.limitHigh.x, this.limitHigh.y, this.limitHigh.z);
}
updateGeometries() {
// for (var i = 0; i < this.meshGeometries.length; i++) {
// // this.meshGeometries[i].verticesNeedUpdate = true;
// // this.meshGeometries[i].getAttribute('position').needsUpdate = true;
// this.meshGeometries[i].attributes.position.needsUpdate = true;
// this.meshGeometries[i].index.needsUpdate = true;
// this.meshGeometries[i].computeBoundingSphere();
// this.meshGeometries[i].computeBoundingBox();
// }
for (let i = 0; i < this.faces.length; i++) {
this.faces[i].update();
}
// for (var i = 0; i < this.lineGeometries.length; i++) {
// // this.lineGeometries[i].verticesNeedUpdate = true;
// // this.meshGeometries[i].getAttribute('position').needsUpdate = true;
// this.lineGeometries[i].attributes.position.needsUpdate = true;
// this.lineGeometries[i].index.needsUpdate = true;
// this.lineGeometries[i].computeBoundingSphere();
// this.lineGeometries[i].computeBoundingBox();
// }
for (let i = 0; i < this.boxLines.length; i++) {
this.boxLines[i].update();
}
}
setBox() {
let width = new Vector3();
width.subVectors(this.limitHigh, this.limitLow);
this.boxMesh.scale.copy(width);
width.multiplyScalar(0.5).add(this.limitLow);
this.boxMesh.position.copy(width);
}
setUniforms() {
let unif = uniforms.clipping;
unif.clippingLow.value.copy(this.limitLow);
unif.clippingHigh.value.copy(this.limitHigh);
}
setValue(axis, value) {
let buffer = 1000;
let limit = 14000;
if (axis === 'x1') {
// this.limitLow.x = Math.max(-limit, Math.min(this.limitHigh.x - buffer, value));
this.limitLow.x = Math.max(this.limit.x1, Math.min(this.limitHigh.x - buffer, value));
} else if (axis === 'x2') {
// this.limitHigh.x = Math.max(this.limitLow.x + buffer, Math.min(limit, value));
this.limitHigh.x = Math.max(this.limitLow.x + buffer, Math.min(this.limit.x2, value));
} else if (axis === 'y1') {
// this.limitLow.y = Math.max(-limit, Math.min(this.limitHigh.y - buffer, value));
this.limitLow.y = Math.max(this.limit.y1, Math.min(this.limitHigh.y - buffer, value));
} else if (axis === 'y2') {
// this.limitHigh.y = Math.max(this.limitLow.y + buffer, Math.min(limit, value));
this.limitHigh.y = Math.max(this.limitLow.y + buffer, Math.min(this.limit.y2, value));
} else if (axis === 'z1') {
this.limitLow.z = Math.max(-limit, Math.min(this.limitHigh.z - buffer, value));
} else if (axis === 'z2') {
this.limitHigh.z = Math.max(this.limitLow.z + buffer, Math.min(limit, value));
}
this.setBox();
this.setUniforms();
this.updateVertices();
this.updateGeometries();
}
}

View File

@ -1,28 +1,34 @@
import { Mesh } from 'three/src/objects/Mesh';
import { PlaneGeometry } from './PlaneGeometry';
import * as material from './material';
export class SelectionBoxFace {
constructor(axis, v0, v1, v2, v3, selection) {
let frontFaceGeometry = new PlaneGeometry(v0, v1, v2, v3);
frontFaceGeometry.dynamic = true;
let frontFaceGeometry = this.fontFaceGeometry = new PlaneGeometry(v0, v1, v2, v3);
// frontFaceGeometry.dynamic = true;
selection.meshGeometries.push(frontFaceGeometry);
let frontFaceMesh = new Mesh(frontFaceGeometry, MATERIAL.Invisible);
let frontFaceMesh = new Mesh(frontFaceGeometry, material.Invisible);
frontFaceMesh.axis = axis;
frontFaceMesh.guardian = this;
selection.touchMeshes.add(frontFaceMesh);
selection.selectables.push(frontFaceMesh);
let backFaceGeometry = new PlaneGeometry(v3, v2, v1, v0);
backFaceGeometry.dynamic = true;
let backFaceGeometry = this.backFaceGeometry = new PlaneGeometry(v3, v2, v1, v0);
// backFaceGeometry.dynamic = true;
selection.meshGeometries.push(backFaceGeometry);
let backFaceMesh = new Mesh(backFaceGeometry, MATERIAL.BoxBackFace);
let backFaceMesh = new Mesh(backFaceGeometry, material.BoxBackFace);
selection.displayMeshes.add(backFaceMesh);
this.lines = new Array();
}
update() {
this.fontFaceGeometry.update();
this.backFaceGeometry.update();
}
rayOver() {
@ -39,4 +45,4 @@ export class SelectionBoxFace {
}
}
}
}

View File

@ -0,0 +1,37 @@
import { LineSegments } from 'three/src/objects/LineSegments';
// import { Float32BufferAttribute } from 'three/src/core/BufferAttribute';
import * as material from './material';
import { BufferGeometry } from 'three/src/core/BufferGeometry';
export class SelectionBoxLine {
// material;
constructor(v0, v1, f0, f1, selection) {
// var lineGeometry = new THREE.Geometry();
// lineGeometry.vertices.push(v0, v1);
// lineGeometry.computeLineDistances();
// lineGeometry.dynamic = true;
let vertices = this.vertices = [v0, v1];
let lineGeometry = this.lineGeometry = new BufferGeometry().setFromPoints(vertices);
selection.lineGeometries.push(lineGeometry);
lineGeometry.attributes.position.needsUpdate = true;
this.line = new LineSegments(lineGeometry, material.BoxWireframe);
selection.displayMeshes.add(this.line);
f0.lines.push(this);
f1.lines.push(this);
}
update() {
this.lineGeometry.setFromPoints(this.vertices);
this.lineGeometry.attributes.position.needsUpdate = true;
this.lineGeometry.computeBoundingSphere();
}
setHighlight(b) {
this.line.material = b ? material.BoxWireActive : material.BoxWireframe;
}
}

31
src/js/clip/material.js Normal file
View File

@ -0,0 +1,31 @@
import { MeshBasicMaterial } from 'three/src/materials/MeshBasicMaterial';
import { LineBasicMaterial } from 'three/src/materials/LineBasicMaterial';
import { ShaderMaterial } from 'three/src/materials/ShaderMaterial';
import { uniforms } from "./uniforms";
import { shader } from './shader';
import { DoubleSide } from 'three/src/constants';
let capMaterial = new ShaderMaterial({
uniforms: uniforms.caps,
vertexShader: shader.vertex,
fragmentShader: shader.fragment
});
let BoxBackFace = new MeshBasicMaterial({ color: 0xEEDDCC, transparent: true });
let BoxWireframe = new LineBasicMaterial({ color: 0x000000, linewidth: 2 });
// yellow select color
let BoxWireActive = new LineBasicMaterial({ color: 0xffff00, linewidth: 4, side: DoubleSide });
let Invisible = new ShaderMaterial({
vertexShader: shader.invisibleVertexShader,
fragmentShader: shader.invisibleFragmentShader,
side: DoubleSide
});
export {
capMaterial,
BoxBackFace,
BoxWireframe,
BoxWireActive,
Invisible
}

45
src/js/clip/shader.js Normal file
View File

@ -0,0 +1,45 @@
let shader = {
vertex: '\
uniform vec3 color;\
varying vec3 pixelNormal;\
\
void main() {\
\
pixelNormal = normal;\
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\
\
}',
fragment: '\
uniform vec3 color;\
varying vec3 pixelNormal;\
\
void main( void ) {\
\
float shade = (\
3.0 * pow ( abs ( pixelNormal.y ), 2.0 )\
+ 2.0 * pow ( abs ( pixelNormal.z ), 2.0 )\
+ 1.0 * pow ( abs ( pixelNormal.x ), 2.0 )\
) / 3.0;\
\
gl_FragColor = vec4( color * shade, 1.0 );\
\
}',
invisibleVertexShader: '\
void main() {\
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\
gl_Position = projectionMatrix * mvPosition;\
}',
invisibleFragmentShader: '\
void main( void ) {\
gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );\
discard;\
}'
}
export { shader };

17
src/js/clip/uniforms.js Normal file
View File

@ -0,0 +1,17 @@
import { Vector3 } from 'three/src/math/Vector3';
import { Color } from 'three/src/math/Color';
let uniforms = {
clipping: {
color: { type: "c", value: new Color(0x3d9ecb) },
clippingLow: { type: "v3", value: new Vector3(0, 0, 0) },
clippingHigh: { type: "v3", value: new Vector3(0, 0, 0) }
},
caps: {
color: { type: "c", value: new Color(0xf83610) }
}
};
export { uniforms };

View File

@ -22,6 +22,9 @@ import * as util from './core/utilities';
import * as browser from './core/browser';
import * as domUtil from './core/domUtil';
import { MobileDialog } from "./controls/MobileDialog";
import { Picking } from './clip/Picking';
import { Selection } from './clip/Selection';
import '../css/page.scss'; /* style loader will import it */
@ -33,7 +36,8 @@ class Application {
this.wireframeMode = false;
this.canvas;
this._canvasImageUrl;
this.downloadButton
this.downloadButton;
this.showCaps = true;
this.objects = [];
@ -90,6 +94,7 @@ class Application {
this.renderer = new WebGLRenderer({ alpha: true, antialias: true, preserveDrawingBuffer: true });
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(this.width, this.height);
this.renderer.autoClear = false;
this.renderer.setClearColor(0x000000, 0.0); // second param is opacity, 0 => transparent
// enable clipping
@ -100,6 +105,9 @@ class Application {
/* Scene: that will hold all our elements such as objects, cameras and lights. */
this.scene = new Scene();
this.capsScene = new Scene();
this.backStencil = new Scene();
this.frontStencil = new Scene();
this._buildDefaultLights(this.scene);
//app.scene.autoUpdate = false;
//// show axes in the screen
@ -160,6 +168,14 @@ class Application {
// create map
// let map = this.map = new Map(x, y, z, size, center, this.camera, this.scene, this.container, 'https://geusegdi01.geus.dk/meta3d/rpc/model_meta?modelid=20');
this.selection = new Selection(
// new Vector3(-7, -14, -14),
// new Vector3(14, 9, 3)
new Vector3(x.min, y.min, z.min),
new Vector3(x.max, y.max, z.max)
);
new Picking(size, center, this);
let map = this.map = await Map.build(x, y, z, center, this.camera, this.scene, this.container, 'https://geusegdi01.geus.dk/meta3d/rpc/model_meta_all?modelid=20');
this.mapTitle = document.querySelector('#map-title');
this.mapTitle.innerHTML += map.title;
@ -226,6 +242,16 @@ class Application {
//slice on x and y axes:
// this.slicer = new SlicerControl({ parentDiv: 'slicer-control' }).addTo(this.map);
// this.selection = new Selection(
// // new Vector3(-7, -14, -14),
// // new Vector3(14, 9, 3)
// new Vector3(x.min, y.min, z.min),
// new Vector3(x.max, y.max, z.max)
// );
this.capsScene.add(this.selection.boxMesh);
this.scene.add(this.selection.displayMeshes);
this.scene.add(this.selection.touchMeshes);
// domEvent.on(window, 'resize', this.onWindowResize, this);
// domEvent.on(window, 'keydown', this.keydown, this);
this.start();
@ -311,6 +337,28 @@ class Application {
}
animate() {
this.renderer.clear();
let gl = this.renderer.context;
// if (this.showCaps) {
// this.renderer.state.setStencilTest(true);
// this.renderer.state.setStencilFunc(gl.ALWAYS, 1, 0xff);
// this.renderer.state.setStencilOp(gl.KEEP, gl.KEEP, gl.INCR);
// // this.renderer.render(this.backStencil, this.camera);
// this.renderer.state.setStencilFunc(gl.ALWAYS, 1, 0xff);
// this.renderer.state.setStencilOp(gl.KEEP, gl.KEEP, gl.DECR);
// // this.renderer.render(this.frontStencil, this.camera);
// this.renderer.state.setStencilFunc(gl.EQUAL, 1, 0xff);
// this.renderer.state.setStencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
// this.renderer.render(this.capsScene, this.camera);
// this.renderer.state.setStencilTest(false);
// }
this.renderer.render(this.scene, this.camera);
this.northArrow.animate();
this.gridlayer.animate();