// ========== Three.js 相关模块引入 ==========
// 引入 Three.js 核心库及各类常用扩展
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; // 相机轨道控制器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; // GLTF模型加载器
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js"; // Draco模型解压器
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js"; // HDR环境贴图加载器
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js"; // 后处理合成器
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js"; // 渲染通道
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"; // 着色器通道
import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js"; // 抗锯齿着色器
import { Water } from "three/examples/jsm/objects/Water.js"; // 水面对象

// Three.js 线框及文本相关扩展
import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2.js";
import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeometry.js";
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
import {
  Line,
  LineDashedMaterial,
  BufferGeometry,
  Float32BufferAttribute,
} from "three";
import { FontLoader } from "three/examples/jsm/loaders/FontLoader.js"; // 字体加载器
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js"; // 文本几何体

/* ==========  3条虚线辅助函数  ========== */
/**
 * 为一个球体对象生成三条（x、y、z方向）虚线，指示该点到对应坐标平面的投影。
 * 每条虚线用LineDashedMaterial表示，便于后续动态更新端点坐标。
 * @param {Object3D} ball 目标球体
 * @param {Scene} scene   所属场景
 * @param {Object} opts   虚线样式参数
 */
function createDashedLinesForBall(
  ball,
  scene,
  { dashSize = 1, gapSize = 1, color = 0x7ec8ff } = {}
) {
  const makeLine = () => {
    // 用 BufferGeometry+LineDashedMaterial 创建一条虚线
    const geo = new BufferGeometry();
    geo.setAttribute(
      "position",
      new Float32BufferAttribute(new Float32Array(6), 3)
    ); // 两端点(共6元素)
    const mat = new LineDashedMaterial({
      color,
      dashSize,
      gapSize,
      transparent: true,
      opacity: 0.6,
    });
    const line = new Line(geo, mat);
    line.computeLineDistances();
    scene.add(line);
    return line;
  };
  // 记录在球体的 userData 里，便于后续动画时更新
  ball.userData.dashedLines = {
    down: makeLine(), // y方向到底面
    back: makeLine(), // z方向到后面
    left: makeLine(), // x方向到侧面
  };
}

/* ========== 创建自定义网格线（抗锯齿） ========== */
/**
 * 构建网格线条对象，可用于三维空间的不同面，支持自定义分段数与线宽。
 * @param {number} w      网格宽度
 * @param {number} h      网格高度
 * @param {number} divX   x方向分段数
 * @param {number} divY   y方向分段数
 * @param {color}  color  网格线颜色
 * @param {number} px     线宽（单位像素）
 * @returns {LineSegments2} 线段对象
 */
function createCustomGridAA(w, h, divX, divY, color = 0xffffff, px = 1.5) {
  // 按分段数生成所有线的端点坐标
  const pos = [];
  const stepX = w / divX,
    stepY = h / divY;
  for (let i = 0; i <= divX; i++) {
    const x = i * stepX;
    pos.push(x, 0, 0, x, h, 0); // 垂直线
  }
  for (let j = 0; j <= divY; j++) {
    const y = j * stepY;
    pos.push(0, y, 0, w, y, 0); // 水平线
  }
  // 线条材质用LineMaterial，支持屏幕分辨率感知，线宽不随缩放变化
  const geo = new LineSegmentsGeometry().setPositions(pos);
  const mat = new LineMaterial({
    color,
    linewidth: px,
    worldUnits: false,
    transparent: true,
    opacity: 0.5,
  });
  mat.resolution.set(window.innerWidth, window.innerHeight);
  return new LineSegments2(geo, mat);
}

/* ========== 坐标轴刻度文本构建 ========== */
/**
 * 在指定轴线上生成刻度文字，比如x轴、z轴等。
 * @param {Object} opts  选项对象，主要包括：轴类型、长度、刻度标签、字体、颜色等
 */
function buildVectorTicks({
  axis = "x",
  length = 50,
  labels = null,
  divisions = 5,
  fontUrl = "/fonts/helvetiker_regular.typeface.json",
  size = 2.5,
  height = 0.2,
  color = 0xffffff,
  offset = new THREE.Vector3(),
  parent = null,
} = {}) {
  if (!parent) return;

  // 异步加载字体，加载后批量生成刻度Mesh
  new FontLoader().load(fontUrl, (font) => {
    const group = new THREE.Group();
    parent.add(group);
    const arr =
      labels ?? Array.from({ length: divisions + 1 }, (_, i) => i.toString());
    const step = length / (arr.length - 1 || 1);

    arr.forEach((txt, i) => {
      // 文字居中

      const geo = new TextGeometry(txt, {
        font, // 字体（必须预先加载）
        size, // 文字大小（数字）
        height, // 文字的厚度/挤出深度（数字）
        curveSegments: 4, // 曲线分段数（默认是12，值越高越平滑）
      });

      geo.computeBoundingBox(); //  计算几何体 (TextGeometry) 的 边界框（boundingBox），用于确定文字的 实际尺寸范围（min 和 max 的坐标）
      geo.center(); //  将几何体的 原点居中 到其边界框的中心。
      const mesh = new THREE.Mesh(
        geo,
        new THREE.MeshBasicMaterial({
          color, // 文字颜色（如 0xff0000 或 'red'）
          toneMapped: false, // 禁用色调映射（保持颜色原始亮度）
          transparent: true, // 启用透明度
          opacity: 0.8, // 不透明度（0~1）
        })
      );
      const p = i * step;
      // 文字的布局方式，按不同轴区分
      if (axis === "x") {
        mesh.rotation.y = Math.PI / 2;
        mesh.position.set(offset.x, offset.y, offset.z + p);
      } else if (axis === "y") {
        mesh.position.set(offset.x, offset.y + p, offset.z);
      } else {
        mesh.position.set(offset.x + p, offset.y, offset.z);
      }
      group.add(mesh);
    });
  });
}

/* ========== Draco解压和GLTF加载器 ========== */
const dracoLoader = new DRACOLoader().setDecoderPath("/draco/"); // 设置Draco解码器路径
const gltfLoader = new GLTFLoader().setDRACOLoader(dracoLoader); // GLTF加载器关联Draco

/* ========== 主函数：画三维坐标轴及交互 ========== */
/**
 * 在传入的DOM元素内创建完整的三维坐标系、网格面、刻度、球体模型、交互、后处理、UI按钮等。
 * @param {Element} element 渲染容器
 * @param {Object}  options 配置参数
 * @returns {Object}        {scene, camera, renderer, dispose}
 */
export function drawAxes(element, options = {}) {
  // ========== 配置参数及默认值 ==========
  const {
    background = "#171717", // 背景色
    // background = 'transparent', // 背景色
    gridSize = { x: 50, y: 50, z: 50 }, // 三维网格尺寸
    // grid_uv_up = [5, 5],
    // grid_uv_down = [5, 5],
    grid_uv_left = [5, 5],
    // grid_uv_right = [5, 4],
    // grid_uv_front = [5, 4],
    grid_uv_back = [5, 5],
    show_water = true, // 是否显示水面
    water_height = 5, // 水面厚度
    data = {},
    labels_left = ["", "A", "B", "C", "D", "E"],
    labels_back = ["", "A", "B", "C", "D", "E"],
  } = options;

  /* ========== 场景/相机/渲染器初始化 ========== */
  const scene = new THREE.Scene();
  // scene.background = new THREE.Color(background);
  scene.position.set(-25, -25, -25); //  修改 场景 中心点
  const camera = new THREE.PerspectiveCamera(
    75,
    element.clientWidth / element.clientHeight,
    0.1,
    2000
  );
  // camera.position.set(77, 77, 77); // 俯视+侧视角
  camera.position.set(55, 55, 55); // 俯视+侧视角

  const renderer = new THREE.WebGLRenderer({
    alpha: true, // 启用透明度
    antialias: true,
  });
  const dpr = Math.min(window.devicePixelRatio || 1, 2);
  renderer.setPixelRatio(dpr);
  renderer.setSize(element.clientWidth, element.clientHeight);
  renderer.outputColorSpace = THREE.SRGBColorSpace;
  element.appendChild(renderer.domElement);

  // 轨道控制器（支持旋转/缩放/平移相机）
  const controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.minPolarAngle = 0;
  controls.maxPolarAngle = Math.PI / 2.8;

  /* ========== 后处理抗锯齿 ========== */
  const composer = new EffectComposer(renderer);
  composer.addPass(new RenderPass(scene, camera));
  const fxaa = new ShaderPass(FXAAShader);
  const updateFXAA = () =>
    fxaa.material.uniforms.resolution.value.set(
      1 / (element.clientWidth * dpr),
      1 / (element.clientHeight * dpr)
    );
  updateFXAA();
  composer.addPass(fxaa);

  /* ========== 环境光照/HDR环境贴图 ========== */
  new RGBELoader().load("/hdr/basic.hdr", (tex) => {
    tex.mapping = THREE.EquirectangularReflectionMapping;
    scene.environment = tex;
  });

  /* ========== 网格和水面生成 ========== */
  const { x: sizeX, y: sizeY, z: sizeZ } = gridSize;
  const gridGroup = new THREE.Group();
  scene.add(gridGroup);
  scene.userData.waterList = [];

  // 可选：底部加一块水面（水面动画来自 Water.js）
  if (show_water) {
    const waterNormals = new THREE.TextureLoader().load(
      "/textures/water.png",
      (t) => {
        t.wrapS = t.wrapT = THREE.RepeatWrapping;
      }
    );
    const water = new Water(new THREE.BoxGeometry(sizeX, water_height, sizeZ), {
      textureWidth: 1024,
      textureHeight: 1024,
      waterNormals,
      sunDirection: new THREE.Vector3(1, 1, 1).normalize(),
      sunColor: 0xffffff,
      waterColor: 0x1e90ff,
      distortionScale: 2.5,
      fog: scene.fog !== undefined,
    });
    water.position.set(sizeX / 2, -water_height / 2, sizeZ / 2);
    gridGroup.add(water);
    scene.userData.waterList.push(water);
  }

  // 根据配置添加每个面上的网格线
  const color = 0xffffff,
    px = 1.2;
  if (typeof grid_uv_down !== "undefined" && grid_uv_down) {
    // 底面
    const g = createCustomGridAA(sizeX, sizeZ, ...grid_uv_down, color, px);
    g.rotation.x = Math.PI / 2;
    g.position.set(0, 0, 0);
    gridGroup.add(g);
  }
  if (typeof grid_uv_left !== "undefined" && grid_uv_left) {
    // 左侧
    const g = createCustomGridAA(sizeZ, sizeY, ...grid_uv_left, color, px);
    g.rotation.y = -Math.PI / 2;
    g.position.set(0, 0, 0);
    gridGroup.add(g);
  }
  if (typeof grid_uv_right !== "undefined" && grid_uv_right) {
    // 右侧
    const g = createCustomGridAA(sizeZ, sizeY, ...grid_uv_right, color, px);
    g.rotation.y = -Math.PI / 2;
    g.position.set(sizeX, 0, 0);
    gridGroup.add(g);
  }
  if (typeof grid_uv_front !== "undefined" && grid_uv_front) {
    // 前侧
    const g = createCustomGridAA(sizeX, sizeY, ...grid_uv_front, color, px);
    g.position.set(0, 0, sizeZ);
    gridGroup.add(g);
  }
  if (typeof grid_uv_back !== "undefined" && grid_uv_back) {
    // 后侧
    const g = createCustomGridAA(sizeX, sizeY, ...grid_uv_back, color, px);
    g.position.set(0, 0, 0);
    gridGroup.add(g);
  }

  // X轴、Z轴上的刻度文本
  buildVectorTicks({
    axis: "x",
    length: sizeZ,
    labels: labels_left,
    offset: new THREE.Vector3(0, sizeY + 5, 0),
    parent: gridGroup,
  });
  buildVectorTicks({
    axis: "z",
    length: sizeZ,
    labels: labels_back,
    offset: new THREE.Vector3(0, sizeY + 5, 0),
    parent: gridGroup,
  });

  addPositiveAxes(scene, sizeY, sizeY);

  /* ========== 球体模型批量加载和放置 ========== */
  // 四种球用同一个glb，分别用不同位置数组、父分组存储

  let styleGroups = {};
  data.forEach((el) => {
    styleGroups[el.name] = null;
  });
  console.log(styleGroups, "styleGroups");

  const allBalls = [];
  let root = null;
  gltfLoader.load("/modle/all.glb", (gltf) => {
    root = gltf.scene;
    // rootModel = gltf.scene;
    console.log(root, "root");
    const cloneBall = (idx, list, key, name) => {
      if (!list) return;
      const g = new THREE.Group();
      scene.add(g);
      styleGroups[key] = g;
      styleGroups[key].name = name;
      // console.log(styleGroups, "styleGroups");

      list.forEach((p) => {
        // 每个球体用 glb 里不同索引的 mesh clone 出来

        const n = root.children[idx].clone(true);
        console.log(n, "nnnnnnnnnnnnnnn");
        console.log(p, "pppppppppppp");

        n.position.set(...p);
        n.userData.originalPos = new THREE.Vector3(...p); // 原始位置
        n.userData.groupKey = `${p[0]}_${p[1]}`; // 分组唯一key
        g.add(n);
        allBalls.push(n);
        createDashedLinesForBall(n, scene); // 给每个球加三条投影虚线
      });
    };
    const dataLength = Object.keys(data).length; // 获取对象的属性个数
    data.forEach((el, index) => {
      cloneBall(index, el.point, el.name, el.name);

    });
  });

  // 添加单个点位的方法
  function addSinglePoint(parent, position, modelIndex, groupName) {
    const ball = root.children[modelIndex].clone(true);
    ball.position.set(...position);
    ball.userData = {
      originalPos: new THREE.Vector3(...position),
      groupKey: `${position[0]}_${position[1]}`,
      groupName: groupName,
    };

    parent.add(ball);
    allBalls.push(ball);
    createDashedLinesForBall(ball, scene);

    return ball;
  }

  /* ========== 交互处理：射线检测吸附与复位 ========== */
  const raycaster = new THREE.Raycaster();
  const mouse = new THREE.Vector2();
  let hovered = null;

  // 组吸附与目标映射
  const activeGroups = new Set(); // 当前已吸附的分组key
  const groupTargets = new Map(); // 分组key -> 吸附目标位置（Vector3）

  // 鼠标移动时，更新 mouse 向量（归一化NDC坐标）
  function onMouseMove(e) {
    const rect = renderer.domElement.getBoundingClientRect();
    mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
  }
  window.addEventListener("mousemove", onMouseMove);

  // 鼠标点击时，判断是否有球在back面被点中，并吸附/释放
  function onClick() {
    ballCallBack(obj);
    raycaster.setFromCamera(mouse, camera);
    const inter = raycaster.intersectObjects(allBalls);
    if (inter.length === 0) return;
    const obj = inter[0].object;
    // 只允许在z约等于0（back面）的球体才可点击
    if (Math.abs(obj.position.z) > 1e-3) {
      ballCallBack(obj);
      return;
    }
    // if (Math.abs(obj.position.z) > 1e-3) return;
    const key = obj.userData.groupKey;
    if (activeGroups.has(key)) {
      // 若已吸附，则取消吸附（恢复原位）
      activeGroups.delete(key);
      groupTargets.delete(key);
    } else {
      // 未吸附，则将目标z设为0（吸附到back面）
      activeGroups.add(key);
      groupTargets.set(
        key,
        new THREE.Vector3(obj.position.x, obj.position.y, 0)
      );
    }
  }
  window.addEventListener("click", onClick);

  /* ========== UI：球体分组显示/隐藏按钮 ========== */
  // groupCallBack(styleGroups);
  // const btnContainer = document.createElement("div");
  // btnContainer.style.cssText =
  //   "position:absolute;top:10px;left:10px;display:flex;flex-direction:column;gap:10px;pointer-events:none;";
  // element.appendChild(btnContainer);
  // console.log(styleGroups, "styleGroups");

  // ["红球", "绿球", "蓝球", "灰球"].forEach((k) => {
  //   const b = document.createElement("button");
  //   b.textContent = k;
  //   b.style.cssText =
  //     "width:149px;height:49px;cursor:pointer;pointer-events:auto;";
  //   b.onclick = () => {
  //     if (styleGroups[k]) styleGroups[k].visible = !styleGroups[k].visible;
  //   };
  //   btnContainer.appendChild(b);
  // });

  /* ========== 视窗尺寸自适应处理 ========== */
  const onResize = () => {
    const w = element.clientWidth,
      h = element.clientHeight;
    camera.aspect = w / h;
    camera.updateProjectionMatrix();
    renderer.setPixelRatio(dpr);
    renderer.setSize(w, h);
    composer.setSize(w, h);
    updateFXAA();
    // 需同步网格线材质分辨率，否则线宽异常
    gridGroup.traverse((o) => {
      if (o.material?.isLineMaterial) o.material.resolution.set(w, h);
    });
  };
  window.addEventListener("resize", onResize);

  /* ========== 动画循环与实时状态刷新 ========== */
  let rafId;
  const animate = () => {
    rafId = requestAnimationFrame(animate);
    controls.update();
    // 水面动画（推动uniform的time）
    scene.userData.waterList.forEach(
      (w) => (w.material.uniforms.time.value += 1 / 60)
    );

    // 鼠标悬浮放大效果
    raycaster.setFromCamera(mouse, camera);
    const inter = raycaster.intersectObjects(allBalls);
    if (inter.length) {
      if (hovered !== inter[0].object) {
        hovered?.scale.set(1, 1, 1);
        hovered = inter[0].object;
        hovered.scale.set(1.2, 1.2, 1.2);
      }
    } else {
      hovered?.scale.set(1, 1, 1);
      hovered = null;
    }

    // 球体吸附（z=0）/复位动画插值
    allBalls.forEach((obj) => {
      const key = obj.userData.groupKey;
      if (activeGroups.has(key)) {
        obj.position.lerp(groupTargets.get(key), 0.1); // 吸附到指定目标点
      } else {
        obj.position.lerp(obj.userData.originalPos, 0.05); // 回到原始位置
      }
    });

    // 虚线端点动态刷新（始终连接球体当前坐标与投影点）
    allBalls.forEach((obj) => {
      const lines = obj.userData.dashedLines;
      if (!lines) return;
      const p = obj.position;

      // y方向（down）
      {
        const arr = lines.down.geometry.attributes.position.array;
        arr[0] = p.x;
        arr[1] = p.y;
        arr[2] = p.z;
        arr[3] = p.x;
        arr[4] = 0;
        arr[5] = p.z;
        lines.down.geometry.attributes.position.needsUpdate = true;
        lines.down.computeLineDistances();
      }
      // z方向（back）
      {
        const arr = lines.back.geometry.attributes.position.array;
        arr[0] = p.x;
        arr[1] = p.y;
        arr[2] = p.z;
        arr[3] = p.x;
        arr[4] = p.y;
        arr[5] = 0;
        lines.back.geometry.attributes.position.needsUpdate = true;
        lines.back.computeLineDistances();
      }
      // x方向（left）
      {
        const arr = lines.left.geometry.attributes.position.array;
        arr[0] = p.x;
        arr[1] = p.y;
        arr[2] = p.z;
        arr[3] = 0;
        arr[4] = p.y;
        arr[5] = p.z;
        lines.left.geometry.attributes.position.needsUpdate = true;
        lines.left.computeLineDistances();
      }
    });

    composer.render();
  };
  animate();

  /* ========== 销毁/资源回收接口 ========== */
  function dispose() {
    cancelAnimationFrame(rafId);
    window.removeEventListener("resize", onResize);
    window.removeEventListener("mousemove", onMouseMove);
    window.removeEventListener("click", onClick);
    controls.dispose();

    // 回收所有球的虚线资源
    allBalls.forEach((obj) => {
      const lines = obj.userData.dashedLines;
      if (!lines) return;
      Object.values(lines).forEach((l) => {
        l.geometry.dispose();
        l.material.dispose();
        scene.remove(l);
      });
    });

    // 场景资源释放
    scene.traverse((o) => {
      o.geometry?.dispose();
      (Array.isArray(o.material) ? o.material : [o.material]).forEach((m) =>
        m?.dispose()
      );
      o.texture?.dispose?.();
    });
    composer.dispose();
    renderer.dispose();
    element.removeChild(renderer.domElement);
    // element.removeChild(btnContainer);
  }
  return {
    scene,
    camera,
    renderer,
    dispose,
    getGroups: () => styleGroups,
    addPoint: (groupName, position, modelIndex) => {
      if (!styleGroups[groupName]) {
        styleGroups[groupName] = new THREE.Group();
        scene.add(styleGroups[groupName]);
        styleGroups[groupName].name = groupName;
      }
      return addSinglePoint(
        styleGroups[groupName],
        position,
        modelIndex,
        groupName
      );
    },
  };
}

//  创建坐标轴
async function addPositiveAxes(scene,axisLength) {
  // axisLength  坐标轴长度
  const tickInterval = 10; // 刻度间隔
  // 加载刻度图片（替换为你的图片路径）
  // const tickTexture = await loadTexture('/path/to/your/tick-image.png');
  // const tickTextureX = [
  //   require("@/assets/icon_xz/x01.png"),
  //   require("@/assets/icon_xz/x02.png"),
  //   require("@/assets/icon_xz/x03.png"),
  //   require("@/assets/icon_xz/x04.png"),
  //   require("@/assets/icon_xz/x05.png"),
  // ];
  // const tickTextureZ = [
  //   require("@/assets/icon_xz/z01.png"),
  //   require("@/assets/icon_xz/z02.png"),
  //   require("@/assets/icon_xz/z03.png"),
  //   require("@/assets/icon_xz/z04.png"),
  //   require("@/assets/icon_xz/z05.png"),
  // ];
  // 创建X轴（红色，只显示正向）
  const xAxis = new THREE.ArrowHelper(
    new THREE.Vector3(1, 0, 0), // 方向
    new THREE.Vector3(0, 0, 0), // 起点
    axisLength + 10, // 长度
    0xf6b501, // 颜色（黄色）
    2, // 头部长度
    1 // 头部宽度
  );
  scene.add(xAxis);
  // 创建Y轴（绿色，只显示正向）
  const yAxis = new THREE.ArrowHelper(
    new THREE.Vector3(0, 1, 0),
    new THREE.Vector3(0, 0, 0),
    axisLength + 10,
    0xd9ebff, // 颜色（色）
    2,
    1
  );
  scene.add(yAxis);
  // 创建Z轴（蓝色，只显示正向）
  const zAxis = new THREE.ArrowHelper(
    new THREE.Vector3(0, 0, 1),
    new THREE.Vector3(0, 0, 0),
    axisLength + 10,
    0x88f0ee, // 颜色（蓝色）
    2,
    1
  );
  scene.add(zAxis);

  // const texLoader = new THREE.TextureLoader();
  // // 添加X轴刻度图片
  // for (let i = 0; i <= tickTextureX.length; i += 1) {
  //   // .load()方法加载图像，返回一个纹理对象Texture
  //   // const texture = await new Promise(resolve => {
  //   //     texLoader.load(tickTextureX[i - 1], resolve);
  //   // });
  //   const texture = texLoader.load(tickTextureX[i - 1]);
  //   const tick = createImageTick(texture, tickInterval, 0, 0, "x");
  //   scene.add(tick);
  // }
  // // 添加Z轴刻度图片
  // for (let j = tickInterval; j <= axisLength; j += tickInterval) {
  //   // .load()方法加载图像，返回一个纹理对象Texture
  //   const texture = texLoader.load(tickTextureZ[j - 1]);
  //   const tick = createImageTick(texture, 0, 0, j, "z");
  //   scene.add(tick);
  // }
}
// 创建图片刻度
function createImageTick(texture, x, y, z, axis){
    const tickSize = 0.8;  // 刻度大小
          
    const material = new THREE.SpriteMaterial({ map: texture, transparent: true });
    const sprite = new THREE.Sprite(material);
    // 根据轴调整位置和旋转
    if (axis === 'x') {
        sprite.position.set(x, y, z);
    } else if (axis === 'z') {
        sprite.position.set(x, y, z);
    }
    sprite.scale.set(tickSize, tickSize, 1);
    return sprite;
}

/* ========== DEMO用例：直接渲染到页面的第一个div上 ========== */
// const demo1 = drawAxes(document.querySelector("div"), {});
// setInterval(()=>demo1.dispose(),2000); // 定时销毁示例（如需测试资源释放）
