shaogen1995 9 месяцев назад
Родитель
Сommit
38501350de
7 измененных файлов с 1825 добавлено и 89 удалено
  1. 76 14
      index.html
  2. 1556 0
      js/OrbitControls.js
  3. 193 75
      js/main.js
  4. BIN
      usdz/UsdCookie.usdz
  5. BIN
      usdz/data.usdz
  6. BIN
      usdz/data2.usdz
  7. BIN
      usdz/test1.usdz

+ 76 - 14
index.html

@@ -1,16 +1,78 @@
 <!DOCTYPE html>
 <html lang="en">
-	<head>
-		<meta charset="utf-8">
-		<title>TinyUSDZ demo using three.js</title>
-		<style>
-			body { margin: 0; }
-		</style>
-	</head>
-	<body>
-		<script>
-		</script>
-
-		<script type="module" src="./js/main.js"></script>
-	</body>
-</html>
+
+<head>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
+	<title>TinyUSDZ demo using three.js</title>
+	<style>
+		* {
+			margin: 0;
+			padding: 0;
+			box-sizing: border-box;
+		}
+
+		canvas {
+			touch-action: none;
+			/* 禁用浏览器默认触摸行为 */
+		}
+
+		body {
+			background-color: #ccc;
+		}
+
+		.loadingBox {
+			position: absolute;
+			width: 90%;
+			max-width: 1200px;
+			height: 6px;
+			border-radius: 3px;
+			border: 1px solid #2dc0ef;
+			top: 50%;
+			left: 50%;
+			transform: translate(-50%, -50%);
+			opacity: 1;
+			pointer-events: auto;
+			transition: all 0.5s;
+		}
+
+		#loading {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 0;
+			height: 100%;
+			background-color: #2dc0ef;
+		}
+
+		/* @media screen and (max-width: 1000px) {
+			.loadingBox {
+				height: 10px;
+				border-radius: 5px;
+
+			}
+		} */
+	</style>
+</head>
+
+<body>
+	<script>
+	</script>
+	<div class="loadingBox">
+		<div id="loading"></div>
+	</div>
+	<script type="module" src="./js/main.js"></script>
+</body>
+<!-- 
+  <script>
+    window.onload = function () {
+      var script = document.createElement('script')
+      script.src = 'http://cdn.bootcss.com/eruda/1.5.4/eruda.min.js'
+      document.body.appendChild(script)
+      script.onload = function () {
+        eruda.init()
+      }
+    }
+  </script> -->
+
+</html>

Разница между файлами не показана из-за своего большого размера
+ 1556 - 0
js/OrbitControls.js


+ 193 - 75
js/main.js

@@ -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 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);
+    });
+  });
 });

BIN
usdz/UsdCookie.usdz


BIN
usdz/data.usdz


BIN
usdz/data2.usdz


BIN
usdz/test1.usdz