|
@@ -1,96 +1,214 @@
|
|
|
-//import * as THREE from 'three';
|
|
|
|
|
-import * as THREE from '../js/three.module.js';
|
|
|
|
|
|
|
+import * as THREE from "../js/three.module.js";
|
|
|
|
|
|
|
|
-import initTinyUSDZ from '../js/tinyusdz.js';
|
|
|
|
|
|
|
+import initTinyUSDZ from "../js/tinyusdz.js";
|
|
|
|
|
|
|
|
-const urlAll =window.location.href.split('?m=')[1]
|
|
|
|
|
|
|
+import { OrbitControls } from "../js/OrbitControls.js";
|
|
|
|
|
|
|
|
-console.log(123456,urlAll);
|
|
|
|
|
|
|
+const urlAll = window.location.href.split("?m=")[1];
|
|
|
|
|
|
|
|
|
|
+// console.log(123456,urlAll);
|
|
|
|
|
|
|
|
const USDZ_FILEPATH = `https://4dkankan.oss-cn-shenzhen.aliyuncs.com/sxz/${urlAll}.usdz`;
|
|
const USDZ_FILEPATH = `https://4dkankan.oss-cn-shenzhen.aliyuncs.com/sxz/${urlAll}.usdz`;
|
|
|
|
|
|
|
|
-const usd_res = await fetch(USDZ_FILEPATH);
|
|
|
|
|
-const usd_data = await usd_res.arrayBuffer();
|
|
|
|
|
-
|
|
|
|
|
-const usd_binary = new Uint8Array(usd_data);
|
|
|
|
|
-
|
|
|
|
|
-initTinyUSDZ().then(function(TinyUSDZLoader) {
|
|
|
|
|
-
|
|
|
|
|
- const usd = new TinyUSDZLoader.TinyUSDZLoader(usd_binary);
|
|
|
|
|
- console.log(usd.numMeshes());
|
|
|
|
|
-
|
|
|
|
|
- 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 );
|
|
|
|
|
- renderer.setAnimationLoop( animate );
|
|
|
|
|
- document.body.appendChild( renderer.domElement );
|
|
|
|
|
-
|
|
|
|
|
- // First mesh only
|
|
|
|
|
- const mesh = usd.getMesh(0);
|
|
|
|
|
- //console.log("usd", usd)
|
|
|
|
|
- //console.log("mesh", mesh);
|
|
|
|
|
-
|
|
|
|
|
- //const geometry = new THREE.BoxGeometry( 1, 1, 1 );
|
|
|
|
|
- const geometry = new THREE.BufferGeometry();
|
|
|
|
|
- geometry.setAttribute( 'position', new THREE.BufferAttribute( mesh.points, 3 ) );
|
|
|
|
|
- // TODO: set normal from mesh
|
|
|
|
|
-
|
|
|
|
|
- if (mesh.hasOwnProperty('texcoords')) {
|
|
|
|
|
- console.log(mesh.texcoords);
|
|
|
|
|
- geometry.setAttribute( 'uv', new THREE.BufferAttribute( mesh.texcoords, 2 ) );
|
|
|
|
|
|
|
+document.addEventListener("DOMContentLoaded", async () => {
|
|
|
|
|
+ const loadingBar = document.getElementById("loading"); // 获取加载条元素
|
|
|
|
|
+ loadingBar.style.display = "block"; // 显示加载条
|
|
|
|
|
+
|
|
|
|
|
+ const usd_res = await fetch(USDZ_FILEPATH);
|
|
|
|
|
+ const totalBytes = parseInt(usd_res.headers.get("Content-Length"), 10); // 获取总字节数
|
|
|
|
|
+ const reader = usd_res.body.getReader(); // 获取读取器
|
|
|
|
|
+ const chunks = []; // 存储数据块
|
|
|
|
|
+ let receivedLength = 0; // 已接收字节数
|
|
|
|
|
+
|
|
|
|
|
+ let timeOut = -1;
|
|
|
|
|
+
|
|
|
|
|
+ // 更新加载条的函数
|
|
|
|
|
+ const updateLoadingBar = (loaded) => {
|
|
|
|
|
+ let percentage = (loaded / totalBytes) * 100;
|
|
|
|
|
+ if (percentage >= 100) {
|
|
|
|
|
+ percentage = 100;
|
|
|
|
|
+ // 隐藏加载条
|
|
|
|
|
+
|
|
|
|
|
+ clearTimeout(timeOut);
|
|
|
|
|
+ timeOut = setTimeout(() => {
|
|
|
|
|
+ const loadingBoxDom = document.querySelector(".loadingBox");
|
|
|
|
|
+ loadingBoxDom.style.opacity = 0;
|
|
|
|
|
+ loadingBoxDom.style.pointerEvents = "none";
|
|
|
|
|
+ }, 300);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ loadingBar.style.width = `${percentage}%`; // 更新加载条宽度
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 读取数据流
|
|
|
|
|
+ while (true) {
|
|
|
|
|
+ const { done, value } = await reader.read(); // 读取数据
|
|
|
|
|
+ if (done) break; // 如果读取完成,退出循环
|
|
|
|
|
+ chunks.push(value); // 存储数据块
|
|
|
|
|
+ receivedLength += value.length; // 更新已接收字节数
|
|
|
|
|
+ updateLoadingBar(receivedLength); // 更新加载条
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const usdMaterial = usd.getMaterial(mesh.materialId);
|
|
|
|
|
- //console.log("usdMat", usdMaterial);
|
|
|
|
|
- //if (usdMaterial.aaa) {
|
|
|
|
|
- // console.log("aaa");
|
|
|
|
|
- //}
|
|
|
|
|
-
|
|
|
|
|
- var material;
|
|
|
|
|
|
|
+ const usd_data = new Uint8Array(receivedLength); // 创建最终数据数组
|
|
|
|
|
+ let position = 0;
|
|
|
|
|
+ for (const chunk of chunks) {
|
|
|
|
|
+ usd_data.set(chunk, position); // 将数据块写入最终数组
|
|
|
|
|
+ position += chunk.length; // 更新位置
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (usdMaterial.hasOwnProperty('diffuseColorTextureId')) {
|
|
|
|
|
- const diffTex = usd.getTexture(usdMaterial.diffuseColorTextureId);
|
|
|
|
|
|
|
+ const usd_binary = new Uint8Array(usd_data);
|
|
|
|
|
|
|
|
- const img = usd.getImage(diffTex.textureImageId);
|
|
|
|
|
- console.log(img);
|
|
|
|
|
|
|
+ // 加载 TinyUSDZ
|
|
|
|
|
+ initTinyUSDZ().then(function (TinyUSDZLoader) {
|
|
|
|
|
+ const usd = new TinyUSDZLoader.TinyUSDZLoader(usd_data);
|
|
|
|
|
+ // console.log(usd.numMeshes());
|
|
|
|
|
|
|
|
- // assume RGBA for now.
|
|
|
|
|
- let image8Array = new Uint8ClampedArray(img.data);
|
|
|
|
|
- let imgData = new ImageData(image8Array, img.width, img.height);
|
|
|
|
|
|
|
+ const scene = new THREE.Scene();
|
|
|
|
|
+ const camera = new THREE.PerspectiveCamera(
|
|
|
|
|
+ 75,
|
|
|
|
|
+ window.innerWidth / window.innerHeight,
|
|
|
|
|
+ 0.1,
|
|
|
|
|
+ 1000
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
- const texture = new THREE.DataTexture( imgData, img.width, img.height );
|
|
|
|
|
- texture.flipY = true;
|
|
|
|
|
- texture.needsUpdate = true;
|
|
|
|
|
-
|
|
|
|
|
- material = new THREE.MeshBasicMaterial({
|
|
|
|
|
- map: texture
|
|
|
|
|
|
|
+ const renderer = new THREE.WebGLRenderer({
|
|
|
|
|
+ alpha: true, // 关键配置,设置背景透明
|
|
|
|
|
+ antialias: true, // 可选抗锯齿
|
|
|
});
|
|
});
|
|
|
- } else {
|
|
|
|
|
- material = new THREE.MeshNormalMaterial();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // Assume triangulated indices.
|
|
|
|
|
- geometry.setIndex( new THREE.Uint32BufferAttribute(mesh.faceVertexIndices, 1) );
|
|
|
|
|
-
|
|
|
|
|
- geometry.computeVertexNormals();
|
|
|
|
|
|
|
|
|
|
- //const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
|
|
|
|
|
- const cube = new THREE.Mesh( geometry, material );
|
|
|
|
|
- scene.add( cube );
|
|
|
|
|
|
|
+ renderer.setClearColor(0x000000, 0); // 第二个参数为透明度(0表示完全透明)
|
|
|
|
|
+
|
|
|
|
|
+ renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
|
|
+ renderer.setAnimationLoop(animate);
|
|
|
|
|
+ document.body.appendChild(renderer.domElement);
|
|
|
|
|
+
|
|
|
|
|
+ // First mesh only
|
|
|
|
|
+ const mesh = usd.getMesh(0);
|
|
|
|
|
+ //console.log("usd", usd)
|
|
|
|
|
+ //console.log("mesh", mesh);
|
|
|
|
|
+
|
|
|
|
|
+ //const geometry = new THREE.BoxGeometry( 1, 1, 1 );
|
|
|
|
|
+ const geometry = new THREE.BufferGeometry();
|
|
|
|
|
+ geometry.setAttribute(
|
|
|
|
|
+ "position",
|
|
|
|
|
+ new THREE.BufferAttribute(mesh.points, 3)
|
|
|
|
|
+ );
|
|
|
|
|
+ // TODO: set normal from mesh
|
|
|
|
|
+
|
|
|
|
|
+ if (mesh.hasOwnProperty("texcoords")) {
|
|
|
|
|
+ // console.log(mesh.texcoords);
|
|
|
|
|
+ geometry.setAttribute("uv", new THREE.BufferAttribute(mesh.texcoords, 2));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const usdMaterial = usd.getMaterial(mesh.materialId);
|
|
|
|
|
+ //console.log("usdMat", usdMaterial);
|
|
|
|
|
+ //if (usdMaterial.aaa) {
|
|
|
|
|
+ // console.log("aaa");
|
|
|
|
|
+ //}
|
|
|
|
|
+
|
|
|
|
|
+ var material;
|
|
|
|
|
+
|
|
|
|
|
+ if (usdMaterial.hasOwnProperty("diffuseColorTextureId")) {
|
|
|
|
|
+ const diffTex = usd.getTexture(usdMaterial.diffuseColorTextureId);
|
|
|
|
|
+
|
|
|
|
|
+ const img = usd.getImage(diffTex.textureImageId);
|
|
|
|
|
+ // console.log(img);
|
|
|
|
|
+
|
|
|
|
|
+ // assume RGBA for now.
|
|
|
|
|
+ let image8Array = new Uint8ClampedArray(img.data);
|
|
|
|
|
+ let imgData = new ImageData(image8Array, img.width, img.height);
|
|
|
|
|
+
|
|
|
|
|
+ const texture = new THREE.DataTexture(imgData, img.width, img.height);
|
|
|
|
|
+ texture.flipY = true;
|
|
|
|
|
+ texture.needsUpdate = true;
|
|
|
|
|
+
|
|
|
|
|
+ material = new THREE.MeshBasicMaterial({
|
|
|
|
|
+ map: texture,
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ material = new THREE.MeshNormalMaterial();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Assume triangulated indices.
|
|
|
|
|
+ geometry.setIndex(
|
|
|
|
|
+ new THREE.Uint32BufferAttribute(mesh.faceVertexIndices, 1)
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ geometry.computeVertexNormals();
|
|
|
|
|
+
|
|
|
|
|
+ //const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
|
|
|
|
|
+ const cube = new THREE.Mesh(geometry, material);
|
|
|
|
|
+ scene.add(cube);
|
|
|
|
|
+
|
|
|
|
|
+ //camera.position.z = 25;
|
|
|
|
|
+ camera.position.z = 1.0;
|
|
|
|
|
+
|
|
|
|
|
+ const controls = new OrbitControls(camera, renderer.domElement);
|
|
|
|
|
+
|
|
|
|
|
+ controls.enablePan = false; // 禁用右键平移功能
|
|
|
|
|
+
|
|
|
|
|
+ controls.enableZoom = false; // 必须禁用轨道控制器的默认缩放[1](@ref)
|
|
|
|
|
+
|
|
|
|
|
+ controls.enableDamping = true;
|
|
|
|
|
+ controls.dampingFactor = 0.25;
|
|
|
|
|
+ controls.screenSpacePanning = false;
|
|
|
|
|
+ controls.maxPolarAngle = Math.PI / 2;
|
|
|
|
|
+
|
|
|
|
|
+ // 兼容鼠标滚轮与触摸屏双指缩放
|
|
|
|
|
+ const handleZoom = (delta) => {
|
|
|
|
|
+ // console.log('--------',delta);
|
|
|
|
|
+
|
|
|
|
|
+ cube.scale.multiplyScalar(delta);
|
|
|
|
|
+ cube.scale.clampScalar(0.5, 2); // 限制缩放范围0.5-3倍[1,6](@ref)
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 鼠标滚轮事件
|
|
|
|
|
+ window.addEventListener(
|
|
|
|
|
+ "wheel",
|
|
|
|
|
+ (e) => {
|
|
|
|
|
+ e.preventDefault();
|
|
|
|
|
+ const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
|
|
|
|
|
+ handleZoom(zoomFactor);
|
|
|
|
|
+ },
|
|
|
|
|
+ { passive: false }
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // 触摸屏双指缩放
|
|
|
|
|
+ let initialDistance = 0;
|
|
|
|
|
+ window.addEventListener("touchstart", (e) => {
|
|
|
|
|
+ if (e.touches.length === 2) {
|
|
|
|
|
+ initialDistance = Math.hypot(
|
|
|
|
|
+ e.touches[0].pageX - e.touches[1].pageX,
|
|
|
|
|
+ e.touches[0].pageY - e.touches[1].pageY
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- //camera.position.z = 25;
|
|
|
|
|
- camera.position.z = 1.0;
|
|
|
|
|
|
|
+ window.addEventListener("touchmove", (e) => {
|
|
|
|
|
+ if (e.touches.length === 2) {
|
|
|
|
|
+ const currentDistance = Math.hypot(
|
|
|
|
|
+ e.touches[0].pageX - e.touches[1].pageX,
|
|
|
|
|
+ e.touches[0].pageY - e.touches[1].pageY
|
|
|
|
|
+ );
|
|
|
|
|
+ const zoomFactor = currentDistance > initialDistance ? 1.03 : 0.97;
|
|
|
|
|
+ handleZoom(zoomFactor);
|
|
|
|
|
+ initialDistance = currentDistance;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- function animate() {
|
|
|
|
|
|
|
+ function animate() {
|
|
|
|
|
+ //cube.rotation.x += 0.01;
|
|
|
|
|
+ // cube.rotation.y += 0.02;
|
|
|
|
|
|
|
|
- //cube.rotation.x += 0.01;
|
|
|
|
|
- cube.rotation.y += 0.02;
|
|
|
|
|
|
|
+ controls.update();
|
|
|
|
|
|
|
|
- renderer.render( scene, camera );
|
|
|
|
|
|
|
+ renderer.render(scene, camera);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ window.addEventListener("resize", () => {
|
|
|
|
|
+ camera.aspect = window.innerWidth / window.innerHeight;
|
|
|
|
|
+ camera.updateProjectionMatrix();
|
|
|
|
|
+ renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
});
|
|
});
|