|
@@ -5,13 +5,17 @@ export const ThreeGridClass = {
|
|
|
this.webgl = options.webgl;
|
|
|
this.view = options.view;
|
|
|
this.extent = options.extent||{minX:-5000,maxX:5000,minY:-5000,maxY:5000}; // {minX, maxX, minY, maxY}
|
|
|
- this.height = options.height ||1000; // 网格总高度
|
|
|
- this.size = options.size ||50; // 单个立方体的尺寸
|
|
|
+ this.height = options.height ||1200; // 网格总高度
|
|
|
+ this.size = options.size ||200; // 单个立方体的尺寸
|
|
|
+ this.layerHeight = this.layerHeight || 400, // 每层的高度
|
|
|
+ this.layerColors = this.layerColors || [new THREE.Color(0xff0000), new THREE.Color(0x00ff00), new THREE.Color(0x0000ff)] // 自定义每层颜色
|
|
|
this.mesh = null;
|
|
|
this._camera = null;
|
|
|
},
|
|
|
|
|
|
+
|
|
|
initialize() {
|
|
|
+ this.layerColors = [new THREE.Color(0xff0000), new THREE.Color(0x00ff00), new THREE.Color(0x0000ff)];
|
|
|
this.renderer = new THREE.WebGLRenderer({
|
|
|
context: this.gl,
|
|
|
premultipliedAlpha: false,
|
|
@@ -63,98 +67,141 @@ export const ThreeGridClass = {
|
|
|
},
|
|
|
|
|
|
createInstancedMesh() {
|
|
|
- const geometry = new THREE.BoxGeometry(this.size, this.size, this.size);
|
|
|
-
|
|
|
+ const geometry = new THREE.BoxGeometry(this.layerHeight, this.size, this.size);
|
|
|
+
|
|
|
const material = new THREE.MeshPhongMaterial({
|
|
|
transparent: true,
|
|
|
- opacity: 0.8,
|
|
|
+ opacity: 0.5,
|
|
|
});
|
|
|
-
|
|
|
+
|
|
|
// 修改材质支持 instanceColor
|
|
|
material.onBeforeCompile = (shader) => {
|
|
|
shader.vertexShader = `
|
|
|
- attribute vec3 instanceColor;
|
|
|
- varying vec3 vColor;
|
|
|
- ` + shader.vertexShader;
|
|
|
-
|
|
|
+ attribute vec3 instanceColor;
|
|
|
+ varying vec3 vColor;
|
|
|
+ ` + shader.vertexShader;
|
|
|
+
|
|
|
shader.vertexShader = shader.vertexShader.replace(
|
|
|
`#include <begin_vertex>`,
|
|
|
`
|
|
|
- #include <begin_vertex>
|
|
|
- vColor = instanceColor;
|
|
|
- `
|
|
|
+ #include <begin_vertex>
|
|
|
+ vColor = instanceColor;
|
|
|
+ `
|
|
|
);
|
|
|
-
|
|
|
+
|
|
|
shader.fragmentShader = `
|
|
|
- varying vec3 vColor;
|
|
|
- ` + shader.fragmentShader;
|
|
|
-
|
|
|
+ varying vec3 vColor;
|
|
|
+ ` + shader.fragmentShader;
|
|
|
+
|
|
|
shader.fragmentShader = shader.fragmentShader.replace(
|
|
|
`#include <dithering_fragment>`,
|
|
|
`
|
|
|
- #include <dithering_fragment>
|
|
|
- gl_FragColor.rgb = vColor;
|
|
|
- `
|
|
|
+ #include <dithering_fragment>
|
|
|
+ gl_FragColor.rgb = vColor;
|
|
|
+ `
|
|
|
);
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
const xCount = Math.floor((this.extent.maxX - this.extent.minX) / this.size);
|
|
|
const yCount = Math.floor((this.extent.maxY - this.extent.minY) / this.size);
|
|
|
- const zCount = Math.floor(this.height / this.size);
|
|
|
+ const zCount = Math.floor(this.height / this.layerHeight);
|
|
|
const count = xCount * yCount * zCount;
|
|
|
-
|
|
|
+
|
|
|
this.mesh = new THREE.InstancedMesh(geometry, material, count);
|
|
|
-
|
|
|
+
|
|
|
// 为实例添加颜色属性
|
|
|
const instanceColors = new Float32Array(count * 3);
|
|
|
const dummy = new THREE.Object3D();
|
|
|
const color = new THREE.Color();
|
|
|
let index = 0;
|
|
|
-
|
|
|
+
|
|
|
+ // 存储合并后的线段
|
|
|
+ const mergedLines = [];
|
|
|
+
|
|
|
+ // 创建边框线的几何体 (LineSegments)
|
|
|
+ const edges = new THREE.EdgesGeometry(geometry);
|
|
|
+ const edgeMaterial = new THREE.LineBasicMaterial({
|
|
|
+ color: 0xffffff,
|
|
|
+ opacity: 0.8,
|
|
|
+ linewidth:8,
|
|
|
+ transparent: true
|
|
|
+ });
|
|
|
+
|
|
|
+ // 按照网格的格子来合并线段
|
|
|
for (let i = 0; i < xCount; i++) {
|
|
|
for (let j = 0; j < yCount; j++) {
|
|
|
for (let k = 0; k < zCount; k++) {
|
|
|
const worldX = this.extent.minX + i * this.size + this.size / 2;
|
|
|
const worldY = this.extent.minY + j * this.size + this.size / 2;
|
|
|
- const worldZ = k * this.size + this.size / 2;
|
|
|
-
|
|
|
+ const worldZ = k * this.layerHeight + this.layerHeight / 2;
|
|
|
+
|
|
|
let renderPos = [];
|
|
|
this.webgl.toRenderCoordinates(this.view, [worldX, worldY, worldZ], 0, this.view.spatialReference, renderPos, 0, 1);
|
|
|
-
|
|
|
+
|
|
|
dummy.position.set(renderPos[0], renderPos[1], renderPos[2]);
|
|
|
dummy.updateMatrix();
|
|
|
this.mesh.setMatrixAt(index, dummy.matrix);
|
|
|
-
|
|
|
- // 设置随机颜色
|
|
|
- color.setHSL(Math.random(), 0.8, 0.5);
|
|
|
+
|
|
|
+ // 分配颜色:由层数计算从红到绿的渐变
|
|
|
+ const layerFraction = k / (zCount - 1); // 当前层在总层数中的比例
|
|
|
+ color.setHSL(layerFraction * 0.33, 1, 0.5); // HSL中的H从0(红)到0.33(绿)
|
|
|
+
|
|
|
instanceColors[index * 3] = color.r;
|
|
|
instanceColors[index * 3 + 1] = color.g;
|
|
|
instanceColors[index * 3 + 2] = color.b;
|
|
|
-
|
|
|
+
|
|
|
+ // 将当前格子的边框添加到合并的线段列表中
|
|
|
+ const edgesArr = edges.attributes.position.array;
|
|
|
+ const startIndex = index * edgesArr.length;
|
|
|
+
|
|
|
+ for (let i = 0; i < edgesArr.length; i++) {
|
|
|
+ mergedLines.push(edgesArr[i] + dummy.position.toArray()[i % 3]);
|
|
|
+ }
|
|
|
+
|
|
|
index++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ // 为实例化的网格设置颜色
|
|
|
geometry.setAttribute('instanceColor', new THREE.InstancedBufferAttribute(instanceColors, 3));
|
|
|
geometry.attributes.instanceColor.needsUpdate = true;
|
|
|
this.mesh.instanceMatrix.needsUpdate = true;
|
|
|
+
|
|
|
+ // 创建合并后的线段几何体
|
|
|
+ const mergedLineGeometry = new THREE.BufferGeometry();
|
|
|
+ mergedLineGeometry.setAttribute('position', new THREE.Float32BufferAttribute(mergedLines, 3));
|
|
|
+ const mergedLineMesh = new THREE.LineSegments(mergedLineGeometry, edgeMaterial);
|
|
|
+
|
|
|
+ // 将网格和边框分别添加到场景中
|
|
|
+ this.scene.add(this.mesh);
|
|
|
+ this.scene.add(mergedLineMesh); // 添加边框线
|
|
|
+
|
|
|
+ // 网格的光照
|
|
|
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
|
|
|
+ this.scene.add(ambientLight);
|
|
|
+
|
|
|
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
|
|
|
+ directionalLight.position.set(10, 10, 10);
|
|
|
+ this.scene.add(directionalLight);
|
|
|
},
|
|
|
|
|
|
+
|
|
|
+
|
|
|
updateColors() {
|
|
|
const instanceColors = this.mesh.geometry.attributes.instanceColor.array;
|
|
|
const color = new THREE.Color();
|
|
|
-
|
|
|
- for (let i = 0; i < this.mesh.count; i++) {
|
|
|
- color.setHSL(Math.random(), 0.8, 0.5);
|
|
|
- instanceColors[i * 3] = color.r;
|
|
|
- instanceColors[i * 3 + 1] = color.g;
|
|
|
- instanceColors[i * 3 + 2] = color.b;
|
|
|
- }
|
|
|
-
|
|
|
+
|
|
|
+ // for (let i = 0; i < this.mesh.count; i++) {
|
|
|
+ // color.setHSL(Math.random(), 0.8, 0.5);
|
|
|
+ // instanceColors[i * 3] = color.r;
|
|
|
+ // instanceColors[i * 3 + 1] = color.g;
|
|
|
+ // instanceColors[i * 3 + 2] = color.b;
|
|
|
+ // }
|
|
|
+
|
|
|
// 标记颜色属性需要更新
|
|
|
this.mesh.geometry.attributes.instanceColor.needsUpdate = true;
|
|
|
-
|
|
|
+
|
|
|
// 触发重新渲染
|
|
|
this.requestRender();
|
|
|
},
|
|
@@ -177,5 +224,6 @@ export const ThreeGridClass = {
|
|
|
|
|
|
// cleanup
|
|
|
this.resetWebGLState();
|
|
|
- }
|
|
|
+ },
|
|
|
+
|
|
|
}
|