问题点
使用的point来渲染高度图点云,大数据图片无效渲染点多(可以通过八叉树过滤掉无效点增加效率,这个太复杂),但是胜在简单能用
效果图
code
代码可运行,无需npm
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js Heightmap Visualization</title>
<style>
body {
margin: 0; }
canvas {
display: block; }
</style>
</head>
<body>
<button id="loadImageButton">Load Image</button>
<!-- 引入Three.js和OrbitControls -->
<!-- <script src="https://cdn.jsdelivr.net/npm/three@v0.149.0/build/three.module.js" type="module"></script> -->
<script src="https://seikichi.github.io/tiff.js/tiff.min.js"></script>
<script src="orb.js"></script>
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three@v0.149.0/build/three.module.js";
console.log(THREE)
var {
OrbitControls, MapControls} = Orb(THREE.EventDispatcher,
THREE.MOUSE,
THREE.Quaternion,
THREE.Spherical,
THREE.TOUCH,
THREE.Vector2,
THREE.Vector3)
// 设置基本的Three.js场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// const OrbitControls = threeTsorbitControls;
// 创建 OrbitControls 控件,并绑定到相机和渲染器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 启用阻尼感(惯性效果)
controls.dampingFactor = 0.25; // 阻尼系数
controls.screenSpacePanning = true;
controls.maxPolarAngle = Math.PI;
camera.position.set(100, 100, 500); // 设置相机位置
camera.lookAt(0, 0, 0);
// 加载高度图
// const textureLoader = new THREE.TextureLoader();
// textureLoader.load('https://threejsfundamentals.org/threejs/resources/images/heightmap-96x64.png', );
const createGeometryFn = (texture) => {
const img = texture.image;
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
const imgData = ctx.getImageData(0, 0, img.width, img.height).data;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let y = 0; y < img.height; y++) {
for (let x = 0; x < img.width; x++) {
// 获取像素的灰度值作为高度
const index = (y * img.width + x) * 4;
const height = imgData[index] / 255 * 50; // 0-255映射为高度范围
// 设置每个点的位置 (x, y, height)
positions.push(x - img.width / 2, y - img.height / 2, height);
// 颜色映射,越高越鲜艳
const color = new THREE.Color(`hsl(${
(height / 50) * 240}, 100%, 50%)`);
colors.push(color.r, color.g, color.b);
}
}
// 将位置和颜色数据添加到BufferGeometry中
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 创建点材质,启用顶点颜色
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true
});
// 创建点云对象
const points = new THREE.Points(geometry, material);
scene.add(points);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
// 更新OrbitControls状态
controls.update();
// 渲染场景
renderer.render(scene, camera);
}
animate();
}
const createGeometryTiffFn = (canvas) => {
const img = texture.image;
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
const imgData = ctx.getImageData(0, 0, img.width, img.height).data;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let y = 0; y < img.height; y++) {
for (let x = 0; x < img.width; x++) {
// 获取像素的灰度值作为高度
const index = (y * img.width + x) * 4;
const height = imgData[index] / 255 * 50; // 0-255映射为高度范围
// 设置每个点的位置 (x, y, height)
positions.push(x - img.width / 2, y - img.height / 2, height);
// 颜色映射,越高越鲜艳
const color = new THREE.Color(`hsl(${
(height / 50) * 240}, 100%, 50%)`);
colors.push(color.r, color.g, color.b);
}
}
// 将位置和颜色数据添加到BufferGeometry中
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 创建点材质,启用顶点颜色
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true
});
// 创建点云对象
const points = new THREE.Points(geometry, material);
scene.add(points);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
// 更新OrbitControls状态
controls.update();
// 渲染场景
renderer.render(scene, camera);
}
animate();
}
Tiff.initialize({
TOTAL_MEMORY: 16777216 * 10});
function loadFile(){
const inputElement = document.createElement('input');
inputElement.type = 'file';
inputElement.accept = 'image/*';
inputElement.addEventListener('change', (event) => {
const file = event.target.files[0];
const reader = new FileReader();
console.log(file.name)
reader.onload = function(e) {
let fname = file.name
if(fname.includes('tif')){
//todo 我这里没有调试成功
const buffer = new Uint8Array(e.target.result);
var tiff = new Tiff({
buffer: buffer});
console.log(tiff)
var canvas = tiff.toCanvas();
createGeometryTiffFn(canvas)
}else{
const img = new Image();
img.src = e.target.result;
img.onload = function