<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8" />

  <title>PLY Viewer</title>

  <style>

    body { margin: 0; overflow: hidden; }

    canvas { display: block; }

  </style>

</head>

<body>

<script type="module">

import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js';

import { OrbitControls } from 'https://unpkg.com/three@0.160.0/examples/jsm/controls/OrbitControls.js';

import { PLYLoader } from 'https://unpkg.com/three@0.160.0/examples/jsm/loaders/PLYLoader.js';


const scene = new THREE.Scene();

scene.background = new THREE.Color(0xf5f5f5);


const camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 0.1, 1000);

camera.position.set(0, 0, 3);


const renderer = new THREE.WebGLRenderer({ antialias: true });

renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);


const controls = new OrbitControls(camera, renderer.domElement);

controls.enableDamping = true;


scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 1));

const dirLight = new THREE.DirectionalLight(0xffffff, 1);

dirLight.position.set(1, 1, 1);

scene.add(dirLight);


const loader = new PLYLoader();

loader.load('https://your-bucket.r2.cloudflarestorage.com/model.ply', geometry => {

  geometry.computeVertexNormals();

  const material = new THREE.MeshStandardMaterial({ color: 0x999999 });

  const mesh = new THREE.Mesh(geometry, material);


  geometry.center();

  scene.add(mesh);

});


function animate() {

  requestAnimationFrame(animate);

  controls.update();

  renderer.render(scene, camera);

}

animate();


window.addEventListener('resize', () => {

  camera.aspect = window.innerWidth / window.innerHeight;

  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);

});

</script>

</body>

</html>