3D个人简历网站 4.小岛

news2025/5/19 6:33:32

1.模型素材

在Sketchfab上下载狐狸岛模型,然后转换为素材资源asset,嫌麻烦直接在网盘链接下载素材,

  • Fox’s islands
  • https://sketchfab.com/3d-models/foxs-islands-163b68e09fcc47618450150be7785907
  • https://gltf.pmnd.rs/

素材夸克网盘:

链接:https://pan.quark.cn/s/f02d30f07286

提取码:Yn3k


在 vite.config.js 或 vite.config.ts 文件里添加 assetsInclude 配置项,让 Vite 把 .glb 文件当作静态资源处理。
vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  assetsInclude: ['**/*.glb']
})

2.小岛代码

src下创建文件夹models,models下创建Island.jsx

Island.jsx

/**
 * IMPORTANT: 将 glTF 模型加载到 Three.js 场景中是一项复杂的工作。
 * 在我们能够配置或动画化模型的网格之前,需要遍历模型网格的每个部分并单独保存。
 *
 * 但幸运的是,有一个工具可以将 gltf 或 glb 文件转换为 jsx 组件。
 * 对于这个模型,请访问 https://gltf.pmnd.rs/ 
 * 获取代码,然后添加其余内容。
 * 你不必从零开始编写所有代码
 */

// 从 @react-spring/three 库导入 a 组件,用于创建动画效果
import { a } from "@react-spring/three";
// 从 react 库导入 useEffect 和 useRef 钩子,useEffect 用于处理副作用,useRef 用于创建可变引用
import { useEffect, useRef } from "react";
// 从 @react-three/drei 库导入 useGLTF 钩子,用于加载 glTF 模型
import { useGLTF } from "@react-three/drei";
// 从 @react-three/fiber 库导入 useFrame 和 useThree 钩子,useFrame 用于在每一帧更新时执行代码,useThree 用于获取 Three.js 上下文
import { useFrame, useThree } from "@react-three/fiber";

// 导入岛屿模型的 glb 文件
import islandScene from "../assets/3d/island.glb";

/**
 * Island 组件,用于渲染 3D 岛屿模型,并处理模型的旋转交互和阶段设置。
 * @param {Object} props - 组件的属性对象
 * @param {boolean} props.isRotating - 指示岛屿是否正在旋转的状态
 * @param {Function} props.setIsRotating - 用于设置岛屿旋转状态的函数
 * @param {Function} props.setCurrentStage - 用于设置当前阶段的函数
 * @param {*} props.currentFocusPoint - 当前焦点点
 * @returns {JSX.Element} 渲染的 3D 岛屿模型元素
 */
export function Island({
  isRotating,
  setIsRotating,
  setCurrentStage,
  currentFocusPoint,
  ...props
}) {
  // 创建一个 ref 用于引用岛屿模型
  const islandRef = useRef();
  // 使用 useThree 钩子获取 Three.js 渲染器和视口信息
  const { gl, viewport } = useThree();
  // 使用 useGLTF 钩子加载岛屿模型,获取模型的节点和材质
  const { nodes, materials } = useGLTF(islandScene);

  // 创建一个 ref 用于存储上一次鼠标的 x 坐标
  const lastX = useRef(0);
  // 创建一个 ref 用于存储旋转速度
  const rotationSpeed = useRef(0);
  // 定义阻尼因子,用于控制旋转减速效果
  const dampingFactor = 0.95;

  // 处理指针(鼠标或触摸)按下事件
  const handlePointerDown = (event) => {
    // 阻止事件冒泡和默认行为
    event.stopPropagation();
    event.preventDefault();
    // 设置岛屿为旋转状态
    setIsRotating(true);

    // 根据事件类型(触摸或鼠标)获取当前指针的 x 坐标
    const clientX = event.touches ? event.touches[0].clientX : event.clientX;

    // 存储当前指针的 x 坐标,供后续计算使用
    lastX.current = clientX;
  };

  // 处理指针(鼠标或触摸)抬起事件
  const handlePointerUp = (event) => {
    // 阻止事件冒泡和默认行为
    event.stopPropagation();
    event.preventDefault();
    // 设置岛屿为停止旋转状态
    setIsRotating(false);
  };

  // 处理指针(鼠标或触摸)移动事件
  const handlePointerMove = (event) => {
    // 阻止事件冒泡和默认行为
    event.stopPropagation();
    event.preventDefault();
    if (isRotating) {
      // 如果岛屿正在旋转,根据事件类型(触摸或鼠标)获取当前指针的 x 坐标
      const clientX = event.touches ? event.touches[0].clientX : event.clientX;

      // 计算指针在水平方向上的移动距离,相对于视口宽度的比例
      const delta = (clientX - lastX.current) / viewport.width;

      // 根据指针移动距离更新岛屿的旋转角度
      islandRef.current.rotation.y += delta * 0.01 * Math.PI;

      // 更新上一次指针的 x 坐标
      lastX.current = clientX;

      // 更新旋转速度
      rotationSpeed.current = delta * 0.01 * Math.PI;
    }
  };

  // 处理键盘按下事件
  const handleKeyDown = (event) => {
    if (event.key === "ArrowLeft") {
      // 如果按下左箭头键,且岛屿未旋转,则设置为旋转状态
      if (!isRotating) setIsRotating(true);

      // 向左旋转岛屿
      islandRef.current.rotation.y += 0.005 * Math.PI;
      // 设置旋转速度
      rotationSpeed.current = 0.007;
    } else if (event.key === "ArrowRight") {
      // 如果按下右箭头键,且岛屿未旋转,则设置为旋转状态
      if (!isRotating) setIsRotating(true);

      // 向右旋转岛屿
      islandRef.current.rotation.y -= 0.005 * Math.PI;
      // 设置旋转速度
      rotationSpeed.current = -0.007;
    }
  };

  // 处理键盘抬起事件
  const handleKeyUp = (event) => {
    if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
      // 如果松开左箭头键或右箭头键,设置岛屿为停止旋转状态
      setIsRotating(false);
    }
  };

  // 处理触摸开始事件,用于移动设备
  const handleTouchStart = (e) => {
    // 阻止事件冒泡和默认行为
    e.stopPropagation();
    e.preventDefault();
    // 设置岛屿为旋转状态
    setIsRotating(true);
  
    // 获取触摸点的 x 坐标
    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
    // 存储当前触摸点的 x 坐标
    lastX.current = clientX;
  }

  // 处理触摸结束事件,用于移动设备
  const handleTouchEnd = (e) => {
    // 阻止事件冒泡和默认行为
    e.stopPropagation();
    e.preventDefault();
    // 设置岛屿为停止旋转状态
    setIsRotating(false);
  }

  // 处理触摸移动事件,用于移动设备
  const handleTouchMove = (e) => {
    // 阻止事件冒泡和默认行为
    e.stopPropagation();
    e.preventDefault();
  
    if (isRotating) {
      // 如果岛屿正在旋转,获取触摸点的 x 坐标
      const clientX = e.touches ? e.touches[0].clientX : e.clientX;
      // 计算触摸点在水平方向上的移动距离,相对于视口宽度的比例
      const delta = (clientX - lastX.current) / viewport.width;
  
      // 根据触摸移动距离更新岛屿的旋转角度
      islandRef.current.rotation.y += delta * 0.01 * Math.PI;
      // 更新上一次触摸点的 x 坐标
      lastX.current = clientX;
      // 更新旋转速度
      rotationSpeed.current = delta * 0.01 * Math.PI;
    }
  }

  // 使用 useEffect 钩子添加和移除事件监听器
  useEffect(() => {
    // 获取 Three.js 渲染器的画布元素
    const canvas = gl.domElement;
    // 添加指针按下、抬起、移动事件监听器
    canvas.addEventListener("pointerdown", handlePointerDown);
    canvas.addEventListener("pointerup", handlePointerUp);
    canvas.addEventListener("pointermove", handlePointerMove);
    // 添加键盘按下、抬起事件监听器
    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("keyup", handleKeyUp);
    // 添加触摸开始、结束、移动事件监听器
    canvas.addEventListener("touchstart", handleTouchStart);
    canvas.addEventListener("touchend", handleTouchEnd);
    canvas.addEventListener("touchmove", handleTouchMove);

    // 组件卸载时移除事件监听器,避免内存泄漏
    return () => {
      canvas.removeEventListener("pointerdown", handlePointerDown);
      canvas.removeEventListener("pointerup", handlePointerUp);
      canvas.removeEventListener("pointermove", handlePointerMove);
      window.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("keyup", handleKeyUp);
      canvas.removeEventListener("touchstart", handleTouchStart);
      canvas.removeEventListener("touchend", handleTouchEnd);
      canvas.removeEventListener("touchmove", handleTouchMove);
    };
  }, [gl, handlePointerDown, handlePointerUp, handlePointerMove]);

  // 使用 useFrame 钩子在每一帧更新时执行代码
  useFrame(() => {
    // 如果岛屿未旋转,应用阻尼效果使旋转逐渐减速
    if (!isRotating) {
      // 应用阻尼因子,降低旋转速度
      rotationSpeed.current *= dampingFactor;

      // 当旋转速度非常小时,停止旋转
      if (Math.abs(rotationSpeed.current) < 0.001) {
        rotationSpeed.current = 0;
      }

      // 根据旋转速度更新岛屿的旋转角度
      islandRef.current.rotation.y += rotationSpeed.current;
    } else {
      // 当岛屿正在旋转时,根据岛屿的朝向确定当前阶段
      const rotation = islandRef.current.rotation.y;

      /**
       * 对旋转值进行归一化处理,确保其保持在 [0, 2 * Math.PI] 范围内。
       * 目的是保证旋转值在特定范围内,避免出现非常大或负的旋转值导致的潜在问题。
       * 以下是这段代码的分步解释:
       * 1. rotation % (2 * Math.PI) 计算旋转值除以 2 * Math.PI 的余数。
       *    这实际上会在旋转值达到一整圈(360 度)时将其环绕,使其保持在 0 到 2 * Math.PI 的范围内。
       * 2. (rotation % (2 * Math.PI)) + 2 * Math.PI 将步骤 1 的结果加上 2 * Math.PI。
       *    这样做是为了确保即使在步骤 1 的取模运算后结果为负,该值仍然为正且在 0 到 2 * Math.PI 的范围内。
       * 3. 最后,((rotation % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI) 对步骤 2 得到的值再次应用取模运算。
       *    这一步保证了该值始终保持在 0 到 2 * Math.PI 的范围内,这在弧度制中相当于一整圈。
       */
      const normalizedRotation =
        ((rotation % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);

      // 根据岛屿的朝向设置当前阶段
      switch (true) {
        case normalizedRotation >= 5.45 && normalizedRotation <= 5.85:
          setCurrentStage(4);
          break;
        case normalizedRotation >= 0.85 && normalizedRotation <= 1.3:
          setCurrentStage(3);
          break;
        case normalizedRotation >= 2.4 && normalizedRotation <= 2.6:
          setCurrentStage(2);
          break;
        case normalizedRotation >= 4.25 && normalizedRotation <= 4.75:
          setCurrentStage(1);
          break;
        default:
          setCurrentStage(null);
      }
    }
  });

  return (
    // {岛屿 3D 模型来源: https://sketchfab.com/3d-models/foxs-islands-163b68e09fcc47618450150be7785907}
    // 使用 a.group 组件包裹岛屿模型,支持动画效果
    <a.group ref={islandRef} {...props}>
      <mesh
        geometry={nodes.polySurface944_tree_body_0.geometry}
        material={materials.PaletteMaterial001}
      />
      <mesh
        geometry={nodes.polySurface945_tree1_0.geometry}
        material={materials.PaletteMaterial001}
      />
      <mesh
        geometry={nodes.polySurface946_tree2_0.geometry}
        material={materials.PaletteMaterial001}
      />
      <mesh
        geometry={nodes.polySurface947_tree1_0.geometry}
        material={materials.PaletteMaterial001}
      />
      <mesh
        geometry={nodes.polySurface948_tree_body_0.geometry}
        material={materials.PaletteMaterial001}
      />
      <mesh
        geometry={nodes.polySurface949_tree_body_0.geometry}
        material={materials.PaletteMaterial001}
      />
      <mesh
        geometry={nodes.pCube11_rocks1_0.geometry}
        material={materials.PaletteMaterial001}
      />
    </a.group>
  );
}

// 导出 Island 组件作为默认导出,方便其他文件引入使用
export default Island

3.主页代码

Home.jsx

// 导入 React 库和 Suspense 组件,Suspense 用于处理异步组件加载
// 当异步组件还未加载完成时,可显示一个 fallback 组件
import React, { Suspense } from 'react'
// 从 @react-three/fiber 库中导入 Canvas 组件,用于创建 Three.js 渲染上下文,
// 借助该组件能在 React 应用里渲染 3D 场景
import { Canvas } from '@react-three/fiber'
// 从 ../components/Loader 路径导入 Loader 组件,该组件会在异步加载时显示加载状态
import Loader from '../components/Loader'
// 从 ../models/Island 路径导入 Island 组件,此组件用于渲染 3D 岛屿模型
import { Island } from "../models/Island"

// <div className='absolute top-28 left-0 right-0 z-10 flex items-center justify-center'>
//   弹出窗口
// </div>

/**
 * Home 组件,作为应用的主页组件。
 * 该组件会依据屏幕尺寸对 Island 组件的缩放、位置和旋转进行调整,
 * 并且在 Canvas 中渲染 Island 组件,同时处理异步加载状态。
 * @returns {JSX.Element} 渲染后的 JSX 元素
 */
const Home = () => {
  /**
   * 根据屏幕尺寸调整 Island 组件的缩放、位置和旋转。
   * @returns {Array} 包含屏幕缩放比例、位置和旋转值的数组
   */
  const adjustIslandForScreenSize = () => {
    // 初始化屏幕缩放比例,初始值设为 null
    let screenScale = null
    // 初始化 Island 组件的位置,默认值为 [0, -6.5, -43]
    let screenPosition = [0, -6.5, -43]
    // 初始化 Island 组件的旋转值,默认值为 [0.1, 4.7, 0]
    let rotation = [0.1, 4.7, 0]

    // 判断当前窗口宽度是否小于 768px
    if (window.innerWidth < 768) {
      // 若窗口宽度小于 768px,将屏幕缩放比例设置为 [0.9, 0.9, 0.9]
      screenScale = [0.9, 0.9, 0.9];
    } else {
      // 若窗口宽度大于等于 768px,将屏幕缩放比例设置为 [1, 1, 1]
      screenScale = [1, 1, 1];
    }

    // 返回包含屏幕缩放比例、位置和旋转值的数组
    return [screenScale, screenPosition, rotation];
  }

  // 调用 adjustIslandForScreenSize 函数,获取调整后的岛屿缩放、位置和旋转参数
  const [islandScale, islandPosition, islandRotation] = adjustIslandForScreenSize();

  return (
    // 创建一个 section 元素,宽度和高度占满整个屏幕,且采用相对定位
    <section className='w-full h-screen relative'>
      {/* 创建 Three.js 渲染画布,宽度和高度占满整个屏幕,背景透明,
          并设置相机的近裁剪面和远裁剪面 */}
      <Canvas
        className='w-full h-screen bg-transparent'
        camera={{ near:0.1, far:1000 }}
      >
        {/* 使用 Suspense 组件处理异步加载,当 Island 组件未加载完成时,显示 Loader 组件 */}
        <Suspense fallback={<Loader/>}>
          {/* 添加定向光,为场景提供有方向的光照 */}
          <directionalLight/>
          {/* 添加环境光,为场景提供全局均匀的光照 */}
          <ambientLight />
          {/* 添加点光源,从一个点向四周发射光线 */}
          <pointLight />
          {/* 添加聚光灯,发射出类似圆锥形的光线 */}
          <spotLight />
          {/* 添加半球光,模拟天空和地面的光照效果 */}
          <hemisphereLight />

          {/* 渲染 Island 组件,设置其位置、缩放和旋转属性 */}
          <Island
            position={islandPosition}
            scale={islandScale}
            rotation={islandRotation}
          />
        </Suspense>
      </Canvas>
    </section>
  )
}

// 导出 Home 组件,供其他文件引入使用
export default Home

4.安装依赖运行

npm install @react-spring/three
npm run dev

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2379085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

创建型:原型模式

目录 1、核心思想 2、实现方式 2.1 基本结构 2.2 代码示例&#xff08;Java&#xff09; 3、适用场景 4、new与clone实际场景建议 1、核心思想 目的&#xff1a;通过复制&#xff08;克隆&#xff09;现有对象来创建新对象&#xff0c;而不是通过new关键字实例化。对于那…

Tapered Off-Policy REINFORCE_ 如何为LLM实现稳定高效的策略优化?

Tapered Off-Policy REINFORCE: 如何为LLM实现稳定高效的策略优化&#xff1f; 在大语言模型&#xff08;LLM&#xff09;的微调领域&#xff0c;强化学习&#xff08;RL&#xff09;正成为提升复杂任务性能的核心方法。本文聚焦于一篇突破性论文&#xff0c;其提出的Tapered …

[Java实战]Spring Boot整合Elasticsearch(二十六)

[Java实战]Spring Boot整合Elasticsearch&#xff08;二十六&#xff09; 摘要&#xff1a;本文通过完整的实战演示&#xff0c;详细讲解如何在Spring Boot项目中整合Elasticsearch&#xff0c;实现数据的存储、检索和复杂查询功能。包含版本适配方案、Spring Data Elasticsea…

图像分割(1)U-net

一、整体结构 虽然说是几年前的产品&#xff0c;但是现在还在用&#xff0c;因为深度学习很多时候越是简单的网络用起来效果越好&#xff0c;而且一般是目标比较小的时候产生的分割问题。u-net的优势就是网络结构简单&#xff0c;适合小目标分割&#xff0c;所以一直用到现在&a…

2025抓包工具Reqable手机抓包HTTPS亲测简单好用-快速跑通

前言 自安卓7.0高版本系统不在信任用户证书&#xff0c;https抓包方式市面查找方法太过复杂手机要root等&#xff0c;前置条件要求太高太复杂&#xff0c;看的头痛&#xff0c;今天一台电脑按步骤操作完即可抓包https,给大家搞定抓包https问题。支持直接编辑修改请求参…

使用 Auto-Keras 进行自动化机器学习

使用 Auto-Keras 进行自动化机器学习 了解自动化机器学习以及如何使用 auto-keras 完成它。如今&#xff0c;机器学习并不是一个非常罕见的术语&#xff0c;因为像 DataCamp、Coursera、Udacity 等组织一直在努力提高他们的效率和灵活性&#xff0c;以便将机器学习的教育带给普…

简单使用Slidev和PPTist

简单使用Slidev和PPTist 1 简介 前端PPT制作有很多优秀的工具包&#xff0c;例如&#xff1a;Slidev、revealjs、PPTist等&#xff0c;Slidev对Markdown格式支持较好&#xff0c;适合与大模型结合使用&#xff0c;选哟二次封装&#xff1b;revealjs适合做数据切换&#xff0c…

RISC-V 开发板 MUSE Pi Pro V2D图像加速器测试,踩坑介绍

视频讲解&#xff1a; RISC-V 开发板 MUSE Pi Pro V2D图像加速器测试&#xff0c;踩坑介绍 今天测试下V2D&#xff0c;这是K1特有的硬件级别的2D图像加速器&#xff0c;参考如下文档&#xff0c;但文档中描述的部分有不少问题&#xff0c;后面会讲下 https://bianbu-linux.spa…

c++多线程debug

debug demo 命令行查看 ps -eLf|grep cam_det //查看当前运行的轻量级进程 ps -aux | grep 执行文件 //查看当前运行的进程 ps -aL | grep 执行文件 //查看当前运行的轻量级进程 pstree -p 主线程ID //查看主线程和新线程的关系 查看线程栈结构 pstack 线程ID 步骤&…

如何畅通需求收集渠道,获取用户反馈?

要畅通需求收集渠道、有效获取用户反馈&#xff0c;核心在于多样化反馈入口、闭环反馈机制、用户分层管理、反馈数据结构化分析等四个方面。其中&#xff0c;多样化反馈入口至关重要&#xff0c;不同用户有不同的沟通偏好&#xff0c;只有覆盖多个反馈路径&#xff0c;才能捕捉…

设备预测性维护的停机时间革命:中讯烛龙如何用AI重构工业设备管理范式

在工业4.0的智能化浪潮中&#xff0c;非计划停机每年吞噬企业3%-8%的产值。中讯烛龙预测性维护系统通过多模态感知矩阵分布式智能体的创新架构&#xff0c;实现设备健康管理的范式跃迁&#xff0c;帮助制造企业将停机时间压缩70%以上。本文将深度解析技术实现路径与行业级实践方…

Python数据分析三剑客:NumPy、Pandas与Matplotlib安装指南与实战入门

Python数据分析三剑客&#xff1a;NumPy、Pandas与Matplotlib安装指南与实战入门 1. 引言 Python数据分析生态&#xff1a;NumPy、Pandas、Matplotlib是数据科学领域的核心工具链。适用场景&#xff1a;数值计算、数据处理、可视化分析&#xff08;如金融分析、机器学习、科研…

Spring-Beans的生命周期的介绍

目录 1、Spring核心组件 2、Bean组件 2.1、Bean的定义 2.2、Bean的生命周期 1、实例化 2、属性填充 3、初始化 4、销毁 2.3、Bean的执行时间 2.4、Bean的作用域 3、常见问题解决方案 4、与Java对象区别 前言 关于bean的生命周期&#xff0c;如下所示&#xff1a; …

Android 自定义悬浮拖动吸附按钮

一个悬浮的拨打电话按钮&#xff0c;使用CardViewImageView可能会出现适配问题&#xff0c;也就是图片显示不全&#xff0c;出现这种问题&#xff0c;就直接替换控件了&#xff0c;因为上述的组合控件没有FloatingActionButton使用方便&#xff0c;还可以有拖动和吸附效果不是更…

一种开源的高斯泼溅实现库——gsplat: An Open-Source Library for Gaussian Splatting

一种开源的高斯泼溅实现库——gsplat: An Open-Source Library for Gaussian Splatting 文章目录 一种开源的高斯泼溅实现库——gsplat: An Open-Source Library for Gaussian Splatting摘要Abstract1. 基本思想1.1 设计1.2 特点 2. Nerfstudio&Splatfacto2.1 Nerfstudio2.…

ARM A64 STR指令

ARM A64 STR指令 1 STR (immediate)1.1 Post-index1.1.1 32-bit variant1.1.2 64-bit variant 1.2 Pre-index1.2.1 32-bit variant1.2.2 64-bit variant 1.3 Unsigned offset1.3.1 32-bit variant1.3.2 64-bit variant 1.4 Assembler symbols 2 STR (register)2.1 32-bit varia…

Linux wlan 单频段 dual wifi创建

环境基础 TP LINK WN722N V1网卡linux 主机 查看设备是否支持双ap managed&#xff1a;客户端模式&#xff08;连接路由器/AP&#xff09;AP&#xff1a;接入点模式&#xff08;创建热点&#xff09;AP/VLAN&#xff1a;支持带VLAN标签的虚拟AP{ AP, mesh point, P2P-GO } &l…

【CSS】使用 CSS 绘制三角形

一、Border 边框法&#xff08;最常用&#xff09; 原理&#xff1a;通过设置元素的宽高为 0&#xff0c;利用透明边框相交形成三角形。 .triangle {width: 0;height: 0;border-left: 50px solid transparent; /* 左侧边框透明 */border-right: 50px solid transparent; /* …

信奥赛-刷题笔记-栈篇-T2-P3056括号调整问题0518

总题单 ​ 本部分总题单如下 【腾讯文档】副本-CSP-JSNOI 题单 (未完待续) https://docs.qq.com/sheet/DSmJuVXR4RUNVWWhW?tabBB08J2 栈篇题单 P3056 [USACO12NOV] Clumsy Cows S https://www.luogu.com.cn/problem/P3056 题目描述 Bessie the cow is trying to type …

inverse-design-of-grating-coupler-3d

一、设计和优化3D光栅耦合器 1.1 代码讲解 通过预定义的环形间距参数(distances数组),在FDTD中生成椭圆光栅结构,并通过用户交互确认几何正确性后,可进一步执行参数扫描优化。 # os:用于操作系统相关功能(如文件路径操作) import os import sys# lumapi:Lumerical 的…