完整案例与项目代码:gitee开源项目地址 https://gitee.com/jumping-world-line/01_threeJS_basic
随着浏览器性能和网络带宽的提升 使得3D技术不再是桌面的专利 打破传统平面展示模式
前端方向主要流向的3D图形库包括Three.js和WebGL
就像2G时代文字信息是主要传输媒介 3G时代的图片 4G时代的视频
随着硬件性能与技术的提升,未来的前端也一定是3D的
首先要有一定的前端开发基础以及开发环境 不多赘述
访问https://threejs.org/ 点击github


拷贝项目到本地即可查看文档 案例文件 使用编辑器等



就像前端需要webpack来进行模块化开发 three JS也需要一个对应的工具,他就是PARCEL https://www.parceljs.cn/
当然,也可以使用前端常用的webpack vite等 各有优劣
parcel的优势在于上手速度快 0配置

本地新建空文件夹 使用npm init 命令创建新的NPM包
npm install -g parcel-bundler 安装parcel
手动建立如图的目录结构与基础文件 参考


到此 使用parcel搭建的最基础的threeJS开发环境就完成了
可以拿到ThreeJS的各种接口 方法 常量等

打开上文提到的本地编辑器
。。。感觉和当年在学校学的unity很像,如果有过类似经验,理解上手会很快
相机,即使观察视角
场景,即被观察的物体

const camera = new THREE.PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )这些参数一起定义了摄像机的viewing frustum(视锥体)。

main.js案例代码
// 1.创建场景
const scene = new THREE.Scene()
// 2.创建并添加相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
camera.position.set(0,0,10) //设置相机位置
scene.add(camera)
// 3. 在场景中创建并添加物体
const cubGeometry = new THREE.BoxGeometry( 1, 1, 1 );// 创建几何立方体
const cubMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00} );// 添加材质
const cube = new THREE.Mesh( cubGeometry, cubMaterial );// 将几何体和材质组合为物体
scene.add( cube );
// 4.设置渲染器并渲染场景
const renderer = new THREE.WebGL1Renderer() //初始化渲染器
renderer.setSize(window.innerWidth,window.innerHeight) //设置渲染的尺寸大小
document.body.appendChild(renderer.domElement);// 将webgl渲染的内容添加到body
renderer.render(scene,camera) // 使用渲染器,通过相机将场景渲染进来
案例成功
在浏览器中会渲染出一个固定视角下观察到的,黑色场景内的绿色绿色正方体的一面。

// 引入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// 5.添加控制器-轨道控制器 可以使得相机围绕目标进行轨道运动 通过不断地重新渲染来实现移动视角的效果
const controls = new OrbitControls(camera,renderer.domElement);
function render(){//递归实现每一帧的重新渲染
renderer.render(scene,camera)
requestAnimationFrame(render);
}
render();

const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );

function render(){//递归实现每一帧的重新渲染
// 7.通过循环 不断修改物体的位置
cube.position.x += 0.1;
if(cube.position.x > 5){
cube.position.x = 0;
}
renderer.render(scene,camera)
requestAnimationFrame(render);
}

// 物体的缩放
cube.scale.set(3,2,1);//指物体在X,Y,Z轴上的缩放倍数
// 物体的旋转 ———— 欧拉角描述一个旋转变换,通过指定轴顺序和其各个轴向上的指定旋转角度来旋转一个物体。
cube.rotation.set(Math.PI/4,0,0,'XYZ')//物体沿X轴旋转90度

gsap 补间动画: https://www.npmjs.com/package/gsap
文档:https://greensock.com/ 动画速度调整
// 9.gsap 补间动画 —— 无需再手动计算时间做动画了 内置API自动生成 并能通过丰富的参数和回调进行控制
let animate_line = gsap.to(cube.position,{
x: 5 , //轴对象与动画值
duration: 5 , //持续时间
ease: "power1.inOut" , //速度
repeat:-1 , //重复次数
yoyo:true , //往返运动
delay:2 , //延迟动画开始时间
onComplete:()=>{ //动画完成的回调函数
},
onStart:()=>{ //动画开始的回调函数
}
});
let animate_rotat = gsap.to(cube.rotation,{ x: Math.PI*2 , duration: 5 , repeat:-1 , ease: "power1.inOut"});
window.addEventListener("click",()=>{//单击屏幕暂停
animate_line.isActive()?animate_line.pause():animate_line.resume()
animate_rotat.isActive()?animate_rotat.pause():animate_rotat.resume()
})
window.addEventListener("dbclick",()=>{//双击屏幕全屏/取消全屏
document.fullscreenElement?document.exitFullscreen():renderer.domElement.requestFullscreen()
})
function render(){//递归实现每一帧的重新渲染
// 8.制作动画 —— 时间动画原理(通过每一帧的生成时间为基准来渲染动画 clock函数或render自带时间参数) 较简单 略...
renderer.render(scene,camera)
requestAnimationFrame(render);
}
render();

// 10.设置控制器阻尼 更真实 需要在每一帧重新生成时调用controls.update();
controls.enableDamping = true;
// 11.监听画面变化渲染画面
window.addEventListener('resize',()=>{
camera.aspect = window.innerWidth/window.innerHeight//更新相机
camera.updateProjectionMatrix();//更新相机投影矩阵
renderer.setSize(window.innerWidth,window.innerHeight)//更新渲染器尺寸大小
renderer.setPixelRatio(window.devicePixelRatio)//设置渲染器像素比————就是缩放比
})

基本案例完成
总结主要步骤:
安装npm install dat.gui,
很方便的工具 感觉也可以用在echarts上
import * as dat from 'dat.gui';
// 12. GUI 实现开发中快速调试物体的效果
const gui = new dat.GUI();
// 折叠目录 设置文件夹
let folder = gui.addFolder('设置立方体')
//材质工具栏
folder.add(cube.material,'wireframe').name('材质');
//坐标轴工具栏
folder.add(cube.position,'x').min(0).max(5).step(0.001).name('移动X轴坐标').onChange((val)=>{
// 回调函数 val是修改后的值
}).onFinishChange((val)=>{
// 回调函数 val是修改后的值
});
//展示工具栏
folder.add(cube,'visible').name('是否展示')
const params = {
color:'#ffff00',
fn:()=>{//动画
gsap.to(cube.position,{
x: 5 , //轴对象与动画值
duration: 3 , //持续时间
ease: "power1.inOut" , //速度
repeat:-1 , //重复次数
yoyo:true , //往返运动
delay:2 , //延迟动画开始时间
onComplete:()=>{ //动画完成的回调函数
},
onStart:()=>{ //动画开始的回调函数
}
});
}
};
//颜色工具栏
folder.addColor(params,'color').onChange((val)=>{
// 回调函数 val是修改后的值
cube.material.color.set(val);
})
//动画工具栏 点击触发特定效果
folder.add(params,'fn').name('移动动画')

正方体坐标:最基础的正方体拥有六个面,每个面4个点,共24个点。每个点都需要xyz三轴的坐标,即72个坐标数据。
法相量:面的朝向角度

// 13. 通过顶点设置创建几何体矩形
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
-1.0,-1.0,1.0,
1.0,-1.0,1.0,
1.0,1.0,1.0,
1.0,1.0,1.0,
-1.0,1.0,1.0,
-1.0,-1.0,1.0
]);
geometry.setAttribute('position',new THREE.BufferAttribute(vertices,3));
const Material = new THREE.MeshBasicMaterial({color: 0x00ff00} );// 添加材质
const cube = new THREE.Mesh( geometry, Material );// 将几何体和材质组合为物体

立方缓冲几何体、圆形缓冲几何体、圆锥缓冲几何体、圆柱缓冲几何体、八面缓冲几何体、十二面缓冲几何体、二十面缓冲几何体、边缘缓冲几何体、挤压缓冲几何体、车削缓冲几何体、参数化缓冲几何体、平面缓冲几何体、多面缓冲几何体、圆环缓冲几何体、形状缓冲几何体、球缓冲几何体、圆环缓冲扭结几何体、管道缓冲几何体、网格几何体
物体=几何体+纹理与材质
相同的形状,加上不同的纹理即可表示不同的物体。例如长方体,可能是板砖,可能是烟盒,也可能是手机等
// 14 纹理与材质
// 导入纹理 通过图片加载
const textureLoader = new THREE.TextureLoader();
const wenliColorTexture = textureLoader.load('./textures/123.png')
// const wenliColorTexture = textureLoader.load(require('../assets/imgs/textures/123.pn'))
// 添加物体
const cubeGeometry = new THREE.BoxBufferGeometry(1,1,1)
//材质
const BasicMaterial = new THREE.MeshBasicMaterial({
color:'#ffff00',
map:wenliColorTexture,
})
const cube = new THREE.Mesh( cubeGeometry, BasicMaterial );// 将几何体和材质组合为物体
scene.add( cube );//在场景中添加物体

// 14 纹理与材质
// 导入纹理 通过图片加载
const textureLoader = new THREE.TextureLoader();
const wenliColorTexture = textureLoader.load(require('../assets/imgs/textures/123.png'));//纹理加载器
// 纹理常用属性
wenliColorTexture.offset.set(0.5,0.5);//偏移
wenliColorTexture.rotation = Math.PI/4;///旋转45°
wenliColorTexture.center.set(0.5,0.5);///旋转原点 默认(0,0)
wenliColorTexture.repeat.set(2,3);///重复次数
wenliColorTexture.wrapS = THREE.MirroredRepeatWrapping;///重复模式 水平方向 镜像重复
wenliColorTexture.wrapT = THREE.RepeatWrapping;///重复模式 垂直方向 无限重复

// 纹理的显示算法
// wenliColorTexture.minFilter = THREE.NearestFilter;//一纹素小于一像素时,贴图如何采样
// wenliColorTexture.magFilter = THREE.NearestFilter;//一纹素大于一像素时,贴图如何采样
wenliColorTexture.minFilter = THREE.LinearFilter;//默认值
wenliColorTexture.magFilter = THREE.LinearFilter;//默认值


类似铁栅栏场景 需要部分透明 遵循黑遮白显的原则
// 纹理的透明
const wenliAplhaTexture = textureLoader.load(require('../assets/imgs/alphaMap/alphaMap.png'));//纹理加载器加载不透明度灰阶图片
// 添加物体
const cubeGeometry = new THREE.BoxBufferGeometry(1,1,1)
//材质
const BasicMaterial = new THREE.MeshBasicMaterial({
color:'#ffff00',
map:wenliColorTexture,
alphaMap:wenliAplhaTexture,//控制表面透明度(黑色完全透明 白色完全不透明 灰阶代表不透明度)
transparent:true,//允许透明
})
const cube = new THREE.Mesh( cubeGeometry, BasicMaterial );// 将几何体和材质组合为物体
scene.add( cube );//在场景中添加物体
纹理图片

设置透明纹理图片

(用PS调整了半天 一开始图片没选好效果不尽如人意了23333)

基于物理渲染,通过计算环境光线使物体更真实
漫反射环境光
// 添加物体
const cubeGeometry = new THREE.BoxBufferGeometry(1,1,1)
// 14 纹理与材质 纹理常用属性 显示算法 纹理材质的透明
// 导入纹理 通过图片加载
const textureLoader = new THREE.TextureLoader();
const wenliColorTexture = textureLoader.load(require('../assets/imgs/textures/123.png'));//纹理加载器
// const BasicMaterial = new THREE.MeshBasicMaterial({//基础材质 MeshBasicMaterial
// 15. 标准物理网格材质 MeshStandardMaterial 🔺需要灯光和表面属性
const material = new THREE.MeshStandardMaterial({
map:wenliColorTexture,
color:'#62b5eb',
})
const cube = new THREE.Mesh( cubeGeometry, material );// 将几何体和材质组合为物体
scene.add( cube );//在场景中添加物体
// 16. 设置灯光
// 环境光(颜色 强度)
const light = new THREE.AmbientLight(0XFFFFFF,0.8);
// 直线平行光(颜色 强度 位置)
const directionLight = new THREE.DirectionalLight(0XFFFFFF,0.8);
directionLight.position.set(10,10,10)
scene.add( light );

漫反射平行光
// 16. 设置灯光
// 环境光(颜色 强度)
const light = new THREE.AmbientLight(0XFFFFFF,0.8);
// 直线平行光(颜色 强度 位置)
const directionLight = new THREE.DirectionalLight(0XFFFFFF,0.8);
directionLight.position.set(10,10,10)
scene.add( directionLight);

粗糙度
const material = new THREE.MeshStandardMaterial({
map:wenliColorTexture,
color:'#62b5eb',
roughness:0,//15.2 粗糙度 0-1 数值越小越光滑
// roughnessMap:0,//粗糙度贴图 暂无资源
})

金属度
const material = new THREE.MeshStandardMaterial({
map:wenliColorTexture,
color:'#62b5eb',
roughness:0,//15.2 粗糙度 0-1 数值越小越光滑
// roughnessMap:0,//粗糙度贴图 暂无资源
metalness:1,//15.3 金属度 0-1 数值越小越不像金属
// metalnessMap:0,//金属度贴图 暂无资源
})

法线:使得表面显得凹凸不平,用于添加表面细节,通过设置对应贴图后效果是不同区域内面对光的反射效果不同,使物体看起来更真实。无图片资源,下面仅作门的案例展示
设置法线贴图前

法线贴图

设置法线贴图后

到这里已经不难发现,再ThreeJS开发中,各种图片资源对于最终的效果呈现有着相当重要的作用。
这里有推介的资源网站:
http://arroway-textures.ch/textures/,注册EPIC 虚幻引擎账号可以免费试用资源
LoadingManager 跟踪已加载和待加载的数据
// 16 设置加载管理器LoadingManager 跟踪已加载和待加载的数据
let event = {}
event.onLoad = function(){
console.log('所有资源图片加载完成')
}
event.onProgress = function(url,num,total){
console.log(url+'加载完成')
console.log('加载进度:'+num)
console.log('资源总数:'+total)
console.log('加载进度百分比:'+(num/total*100).toFixed(2)+'%')
}
event.onError = function(e){
console.log(e)
console.log('图片加载错误')
}
const loadingManager = new THREE.LoadingManager(
event.onLoad,event.onProgress,event.onError
);
// 14 纹理与材质 纹理常用属性 显示算法 纹理材质的透明
// 导入纹理 通过图片加载
const textureLoader = new THREE.TextureLoader(loadingManager);

像镜子一样 将周围场景的图像映射在物体上
需要设置三个轴两个方向上的图片属性,共六张图片。
// 17. 环境贴图
const cubeTextureLoader = new THREE.CubeTextureLoader();
const envMapTetxture = cubeTextureLoader.load([
require('../assets/imgs/textures/envMapTetxture/px.jpg'),
require('../assets/imgs/textures/envMapTetxture/nx.jpg'),
require('../assets/imgs/textures/envMapTetxture/py.jpg'),
require('../assets/imgs/textures/envMapTetxture/ny.jpg'),
require('../assets/imgs/textures/envMapTetxture/pz.jpg'),
require('../assets/imgs/textures/envMapTetxture/nz.jpg'),
])
const spherGeometry = new THREE.SphereBufferGeometry(1,20,20);
const material = new THREE.MeshStandardMaterial({
metalness:0.7,//15.3 金属度 0-1 数值越小越不像金属
roughness:0.1,//15.2 粗糙度 0-1 数值越小越光滑
envMap:envMapTetxture,//17.1 物体环境贴图
});
//17.2 场景环境贴图 缺少资源 待续。。。
const sphere = new THREE.Mesh( spherGeometry, material );// 将几何体和材质组合为物体
scene.add( sphere );//在场景中添加物体

//17.2 给场景添加背景
scene.background = envMapTetxture;
//17.3 给场景所有物体添加默认的环境贴图
scene.environment = envMapTetxture;

待续。。。
纹理材质初步学习完成
总结:
我即将开始一个将录制和编辑音频文件的项目,我正在寻找一个好的库(最好是Ruby,但会考虑Java或.NET以外的任何库)以进行实时可视化波形。有人知道我应该从哪里开始搜索吗? 最佳答案 要流入浏览器的数据量很大。Flash或Flex图表可能是唯一能提高内存效率的解决方案。Javascript图表往往会因大型数据集而崩溃。 关于ruby-Ruby中的波形可视化,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶
我正在使用Ruby/Mechanize编写一个“自动填写表格”应用程序。它几乎可以工作。我可以使用精彩CharlesWeb代理以查看服务器和我的Firefox浏览器之间的交换。现在我想使用Charles查看服务器和我的应用程序之间的交换。Charles在端口8888上代理。假设服务器位于https://my.host.com。.一件不起作用的事情是:@agent||=Mechanize.newdo|agent|agent.set_proxy("my.host.com",8888)end这会导致Net::HTTP::Persistent::Error:...lib/net/http/pe
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?
文章目录1.自动驾驶实战:基于Paddle3D的点云障碍物检测1.1环境信息1.2准备点云数据1.3安装Paddle3D1.4模型训练1.5模型评估1.6模型导出1.7模型部署效果附录show_lidar_pred_on_image.py1.自动驾驶实战:基于Paddle3D的点云障碍物检测项目地址——自动驾驶实战:基于Paddle3D的点云障碍物检测课程地址——自动驾驶感知系统揭秘1.1环境信息硬件信息CPU:2核AI加速卡:v100总显存:16GB总内存:16GB总硬盘:100GB环境配置Python:3.7.4框架信息框架版本:PaddlePaddle2.4.0(项目默认框架版本为2.3
Asitcurrentlystands,thisquestionisnotagoodfitforourQ&Aformat.Weexpectanswerstobesupportedbyfacts,references,orexpertise,butthisquestionwilllikelysolicitdebate,arguments,polling,orextendeddiscussion.Ifyoufeelthatthisquestioncanbeimprovedandpossiblyreopened,visitthehelpcenter提供指导。11年前关闭。我是一位精通HTML
在Rails3.x应用程序中,我正在使用net::ssh并向远程pc运行一些命令。我想向用户的浏览器显示实时日志。比如,如果两个命令在net中运行::ssh执行即echo"Hello",echo"Bye"被传递然后"Hello"应该在执行后立即显示在浏览器中。这是代码我在rubyonrails应用程序中使用ssh连接和运行命令Net::SSH.start(@servers['local'],@machine_name,:password=>@machine_pwd,:timeout=>30)do|ssh|ssh.open_channeldo|channel|channel.requ