范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

前端图形入门在WebGL中实现3D物体的选中和操作

  最近一年一直在做3D图形相关的应用,入坑前端图形也了一年,想在这里跟大家分享一下自己学习到一些图形基础知识。今天跟大家分享一下在Web中实现3D物体的选中和移动旋转缩放操作。
  我们先看一下实现的最终效果:
  实现思路初始化3D场景 加载3D模型 处理mousemove事件和click事件 模型选中样式更新 菜单显示 菜单操作实现 实现说明初始化3D场景
  ThreeJS中的一些基本概念:场景、相机、灯光、渲染器、3D物体 Scene(场景):一个容器,用于放置各种物体:物体、灯等等 Camera(相机):模拟人眼观察,需要放置到场景中 Light(灯光):模拟各类灯光类型 Renderer(渲染器):用于渲染所有信息 Mesh(3D网格物体):Mesh信息
  首先我们需要在ThreeJS中初始化场景 // 创建一个场景 this._scene = new THREE.Scene(); this._scene.background = new THREE.Color( 0xbbbbbb ); // 创建渲染器 this._renderer = new THREE.WebGLRenderer({     canvas: this._canvas }); const { width, height } = this._domContainer.getBoundingClientRect(); this._renderer.setSize( width, height); this._renderer.setPixelRatio( window.devicePixelRatio ); // 相机 this._camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); this._camera.position.set(80, 60, 0); this._camera.lookAt(0,0,0);加载3D模型
  ThreeJS中可以使用API生成3D物体,也可以通过Loader加载其他3D格式的模型,如常见的obj模型或者其他glTF格式的模型数据, 创建本地3D模型 const geometry = new THREE.BoxGeometry(10, 10, 10); const material = new THREE.MeshBasicMaterial( { color: 0xc20053 } ); material.side = THREE.DoubleSide; const mesh = new THREE.Mesh( geometry, material );加载第三方3D模型 // 使用GLTFLoader加载模型 const loader = new GLTFLoader().setPath("assets/"); loader.load("Soldier.glb", (gltf: GLTF) => {     this._scene.add( gltf.scene ); });添加灯光
  在真实的世界中,我们能看到物体是因为眼睛接收到物体表面反射光,形成的图像,在我们这里使用HemisphereLight模拟一个简单的户外光照效果 const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 ); hemiLight.position.set( 0, 20, 0 ); this._scene.add(hemiLight);渲染
  渲染器、场景、物体、相机和灯光都准备好后,我们就可以在浏览器中渲染出这个模型 private _animationFrame = () => {     window.requestAnimationFrame(this._animationFrame);     if (this.application.renderNextFrame) {         this._renderer.render(this._scene, this._camera);     } };//帧循环渲染 window.requestAnimationFrame(this._animationFrame);
  提问:requestAnimationFrame属于微任务还是宏任务(字节面试题)?  处理mousemove事件和click事件
  经过上面的操作,我们已经可以在canvas中显示3D场景和物体了
  那我们要实现在不同角度对3D物体的选中,就需要在canvas中监听鼠标事件,根据鼠标的位置查找选中的物体信息
  在3D中实现对物体的选中,就是在鼠标所在的位置发出一条摄像,和场景中的物体做相交,ThreeJS中可以直接使用Raycaster this._mousePoint.x = event.clientX / this._domContainer.clientWidth * 2 - 1; this._mousePoint.y = - ( event.clientY / this._domContainer.clientHeight ) * 2 + 1; this._raycaster.setFromCamera( this._mousePoint, this._camera ); // this._meshes包含了所有物体信息 const intersects = this._raycaster.intersectObjects( this._meshes );
  这里setFromCamera就是在当前鼠标位置和相机设置设定射线发射器,raycaster.intersectObjects来做射线和指定的物体相交,返回检测到的物体列表
  需要注意的是 ,ThreeJS中,一个物体可能由N级单元构成,而射线只能检测到最小单元,在返回的intersects中,我们需要去找到对应的物体,所以在添加物体到场景中时,我们需要建立一个单元 -> 物体的映射// gltf.scene是加载出来的一个机器人整体 gltf.scene.traverse( ( object: THREE.Object3D ) => {     if (object instanceof THREE.Object3D) {         // meshes存储所有物体单元信息         this._meshes.push(object);         // 存储单元 -> 机器人的映射         this._objects.set(object.uuid, gltf.scene);     } });
  根据raycaster.intersectObjects返回的信息,我们可以拿到当前鼠标选中的物体 if (intersects.length > 0) {     // 选中的最小单元     const mesh = intersects[0].object;     // 找到对应的物体     const picked = this._objects.get(mesh.uuid); }模型选中样式更新
  这个时候我们已经拿到了选中的物体,那么就是要给个反馈呗,这里我们做个简单的样式更改,把选中的物体材质透明度改为原始值的一半,那么在下一帧刷新后,我们就可以看到一个透明的效果 mesh.traverse((child: THREE.Object3D) => {     if (child instanceof THREE.Mesh) {         const material = child.material as THREE.Material;         // 存储之前的透明度,鼠标移出后记得把材质修改回来         this._meshOpacity.set(child.uuid, material.opacity);         // 设置透明度         material.opacity = material.opacity / 3;         material.transparent = true;         material.needsUpdate = true;     } });菜单显示
  经过以上步骤后,我们就了解了在ThreeJS中如何去选中物体,那一般我们的业务需要选中后,有一些操作,就比如游戏中的走路,这里我们就来看看ThreeJS中最常见的三种变换:移动、旋转、缩放
  当我们在3D中选中物体后,告诉我们的菜单,这个时候你该出场了,我项目中用了一个简单的发布/订阅者模式,当物体选中后,会向系统发出物体选中事件 const selections = objects.map((mesh) => new J3DSelection(mesh)); this.application.addSelections(selections); this.application.emitSelectionAdd({     selections,     event });
  而在菜单功能那边,会监听选中事件 this._application.listenSelectionAdd(this._onSelectionAdded);
  从而在收到物体选中事件后,把自己show出来 private _updateMenu = (event: MouseEvent) => {     const { clientX, clientY } = event;     this.setState({         xPosition: clientX + 10,         yPosition: clientY + 10,         visible: this._application.selections.length > 0     }); };
  效果如下:
  菜单操作实现
  菜单展示出来后,点击对应的按钮,根据选中的物体信息执行相应的操作即可 移动private _move = (direction: number) => {     const delta: number = direction > 0 ? -5 : 5;     this._application.selections.forEach((item) => {         item.mesh.position.z = item.mesh.position.z + delta;     }); };旋转private _rotate = (direction: number) => {     const angle = direction > 0 ? -Math.PI / 4 : Math.PI / 4;     this._application.selections.forEach((item) => {         item.mesh.rotateY(angle);     }); };缩放private _scale = (direction: number) => {     const delta: number = direction > 0 ? 2 : 0.5;     this._application.selections.forEach((item) => {         const {x, y, z} = item.mesh.scale;         item.mesh.scale.set(x * delta, y * delta, z * delta);     }); };总结
  第一次写技术博客,主要是用一个直观的项目展示基于ThreeJS的3D基础知识,后续还会持续分享一些自己的前端和图形相关的知识,如有错误欢迎留言指正。 项目源码
  Github地址:GitHub - jaliy/j3d-pick: 在WebGL中实现3D物体的选中和操作(ThreeJS)
  官方文档ThreeJS:基于WebGL封装的一个3D JS库,关于ThreeJS,可以看ThreeJS官网Three.js – JavaScript 3D Library
  WebGL:基于OpenGL ES规范的Web端3D图形接口规范,更多知识可以看WebGL官网WebGL Overview - The Khronos Group Inc
  OpenGL:用于访问图形硬件(GPU)的接口标准,OpenGL官网OpenGL Overview - The Khronos Group Inc

雅马哈钢琴新品上市!b121SG2尽享原声音乐带来的美妙人生有人希望一边感受内心的悠闲,一边以自己的方式沉浸在弹奏钢琴的悠长时光中。也有人希望钢琴和音乐能成为孩子们漫长人生的心灵支柱。为了满足这些用户的愿望,我们一直在追求不拘束于时间,在保秋天的第一个头戴式降噪耳机漫步者W820NB开箱大家有没有发现,越来越多的手机厂商开始取消3。5mm耳机孔,尤其是各手机厂商旗舰机,都取消了3。5mm耳机孔,而目前的方案是,送你一个转接线。但是,转接线用起来,真的很不方便,但是GalaxyZFold3Flip3尝鲜价159998599元起8月11日2400,三星先行者计划正式开启,现在购机可享多重礼遇,其中GalaxyZFold35G12GB512GB版本尝鲜价15999元,0利率12期每期低至1334元,Gala苹果小米和OPPO引爆的可穿戴市场,哪些IoT芯片可以助力?笔者在实体店里看到,带有测试心率功能的华为运动手表Watch3的待机已经向两周的时间迈进。恰巧,笔者的一个好友最近购买了这款手表,显示在长跑阶段,其测速心率等性能相当不错。这款智能1。使用Blazor生成Web应用通过Blazor,C开发人员可运用自身技能使用C和Microsoft。NET生成Web应用。假设你正在生成客户端Web应用,并且拥有。NET开发人员团队。同时,假设你想要将应用部署京东与郎酒深化合作打造高端白酒会员体系每个酱香白酒爱好者心中都有一条溯源之路郎酒庄园之旅。在神秘的赤水河地带,沿途不仅仅有美丽的风景有四渡赤水的革命精神,还有令无数酱香白酒爱好者魂牵梦绕的郎酒庄园。不负每一分热爱京东始大魔王红米K50系列,搭配骁龙888和895,堆料依然十足很多了解红米的用户应该都知道,红米手机产品有数字系列,Note系列,以及现在主流高端K系列。而K系列机型可以说吊打有商小米数字机型而来。主要还是红米K系列在堆料方面基本做到了极致,扩大Beta版测试者范围,iOS15正式版发布在即据外媒报道,苹果上个月为所有想要预览iOS15iPadOS15macOS12MontereywatchOS8和tvOS15的用户推出了Beta版测试。近日,苹果为扩大Beta版测试三星发布GalaxyZFold35G和GalaxyZFlip35G两款新折叠屏手机丨钛快讯三星GalaxyZ折叠屏系列产品钛媒体8月11日消息,三星电子正式推出三星GalaxyZFold35G和三星GalaxyZFlip35G两款智能手机。作为第三代折叠屏手机,两款产品2021811APPSTORE苹果IOS限时免费APP关注我每日稳定更新。所有限免APP下载均为免费,若显示收费,不要下载说明限时免费已过。再请注意的是下载的时候认准APP图标logo,不要下错了。1搜图神器反向图片搜索(原价18)工品质保障,售后无忧抖音电商9大权益让用户安心购近日,抖音电商上线消费者权益产品安心购,推出正品保障七天无理由退货极速退款运费险上门取件等9项服务,为818新潮好物节保驾护航,让用户在购物的每个环节皆能安心,真正实现品质保障,售
打造有温度的智能驾驶,智己汽车IMAD智能驾驶系统伴你出行智能化浪潮下,智能驾驶成为了下一个风口。无论是造车新势力还是传统车企,甚至是互联网科技巨头们,都纷纷进军智能驾驶领域,使出浑身解数,拼资本拼技术拼硬件,在智能驾驶的道路越走越远,为爱普生全新A3彩色商务打印机,以绿色打印引领未来办公新趋势近年来,随着国家大力提倡可持续发展战略,实现碳中和的发展目标正逐步成为社会共识。各行各业积极推行绿色创新,致力于将环保举措融入工作生产的方方面面。在共建绿水青山的时代号召下,对于企平安普惠漯河分公司助力小微企业良性发展早些年,只有逢年过节才能吃上肉制品,现在,国民经济水平得到了质的飞跃,中国绝大多数家庭都已经实现肉制品自由。今天,为大家介绍一位从事猪肉批零的长先生的故事。长先生是漯河本地人,跟妻智驾进行时智己汽车打造智能交互新体验汽车诞生一百多年以来,其动力系统传动系统底盘系统车身设计,甚至全身上下每一个零件,都已经过数轮重大的进化革命。不过,新时代的汽车,不能仅仅满足于机械层面上的进化,更关键的是,作为人新款宝马4系正式上市,外观运动,价格配置有微调成功人士的选车路线总是绕不开BBA,而成功的年轻人,更是离不开宝马4系,对于预算在50万左右,又想拥有一辆跑车的年轻人来说,宝马4系可以说是他们的不二之选了。前不久,宝马正式公布了新款荣威RX5ePLUS来了,外观年轻时尚,售15。28万元起上汽荣威在设计领域一直是走在前沿的,荣威RX5便是一款设计非常成功的SUV,而在取得优异的成绩之后,荣威也并没有放下它,而是趁热打铁,推出了荣威RX5ePLUS,这对于荣威来说是一这款机械键盘,男生女生用着都很好看,洛斐小浪键盘上手测评作为辽宁渤海大学的学生党,虽然之前就入手了洛斐小翘键盘,也特别适合女性用户,不过男朋友一直吐槽,说洛斐为什么就不能出几款中性化的键盘呢,男生也能用,女生也能用,别总出看起来太女性化外观有点帅!捷尼赛思G70正式上市,搭2。0T四驱,售24。98万元起国内豪华品牌市场中,BBA可以说是区域了,那么非主流区域又在哪里呢?这就要说一下专攻个性路线的捷尼赛思了,在打开中国市场的大门时,捷尼赛思从一开始走的就是传统设计路线,而这种方式让奥迪Q5L新增40TRS套件燃速型,外观更运动,配专属标识2。0T引擎在BBA中,奥迪Q5L一直是豪华品牌中一款非常热销的SUV,而在同台竞争中的宝马和奔驰,对奥迪也一直是虎视眈眈,可以见得市场对奥迪Q5L车型的热情之高了。如今,一汽大众奥迪又新增了拍打式按摩新体验,仿真按摩,POSEZOO甫士筋膜枪双模青春版测评第一次接触筋膜枪还是今年的一月份,其实在2020年就听说过这类产品了,特别感兴趣,所以今年也是入手了一款某品牌的筋膜枪,你别说,敲打肌肉所带来的舒适感确实有,也让我对筋膜枪这类产品价格及配置有调整,2022款奥迪A6L上市,外观大气,售41。98万元起近日,从相关渠道获悉,2022款奥迪A6L上市,其中新车售价为41。98万元起。这次仅为改款,并非换代,所以在设计方面并没有太大的变化,只是对部分车型的价格以及配置做了一定的调整,