Three加载3D模型贴图
Three加载3D模型贴图
准备阶段
- 3D模型
- three 库文件
- 纹理图片
相关资料
- 官方开发文档: https://threejs.org/docs
- 官网编辑3D模型:https://threejs.org/editor/ 可以在这里创建一个3D模型导出
gltf
或obj
都可以 - 纹理图片:https://3dtextures.me/ 、https://ambientcg.com/view?id=Bricks075A
- 官网示例代码:https://github.com/mrdoob/three.js/
- 学习 three.js 代码(第四版):https://github.com/PacktPublishing/Learn-Three.js-Fourth-edition
- web 浮动面板控制器:https://lil-gui.georgealways.com/#
效果图
核心代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>房屋平面室内图</title>
</head>
<body>
</body>
<script type="importmap">
{
"imports": {
"three":"/js/three.module.js",
"three/addons/": "/examples/jsm/"
}
}
</script>
<script type="module">
import GUI from 'https://cdn.jsdelivr.net/npm/lil-gui@0.18/+esm';
import * as THREE from 'three';
// 加载 gltf 模型
import {
GLTFLoader
} from 'three/addons/loaders/GLTFLoader.js';
// 加载 obj 模型
import {
OBJLoader
} from 'three/addons/loaders/OBJLoader.js';
// 轨道控制器
import {
OrbitControls
} from 'three/addons/controls/OrbitControls.js';
// 创建场景
const scene = new THREE.Scene();
// 创建透视相机
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.set(0, 20, 200)
camera.scale.x = 1
camera.scale.y = 1
camera.scale.z = 1
// camera.zoom=0.5
// 更新相机
camera.updateProjectionMatrix()
// 创建渲染器,透明背景
const renderer = new THREE.WebGLRenderer({
alpha: true
});
// 场景灯光
const directionalLight = new THREE.DirectionalLight()
directionalLight.penumbra = 0.4
directionalLight.position.set(10, 14, 5)
directionalLight.distance = 0
directionalLight.castShadow = true
directionalLight.intensity = 1
directionalLight.shadow.camera.near = 1
directionalLight.shadow.camera.far = 25
directionalLight.shadow.camera.right = 10
directionalLight.shadow.camera.left = -10
directionalLight.shadow.camera.top = 10
directionalLight.shadow.camera.bottom = -10
directionalLight.shadow.mapSize.width = 2048
directionalLight.shadow.mapSize.height = 2048
directionalLight.shadow.bias = -0.01
scene.add(directionalLight);
// 纹理可以加载。TextureLoader
const textureLoader = new THREE.TextureLoader();
textureLoader.load('/assets/wood/floor-parquet-pattern-172292.jpg', (loaded) => {
loaded.encoding = THREE.sRGBEncoding
scene.background = loaded
scene.environment = null
})
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const gui = new GUI();
const obj = {
left: '/model/textures/12.jpg',
right: '/model/textures/12.jpg',
bottom: '/model/textures/9.jpg',
back: '/model/textures/13.jpg',
bed: '/model/textures/5.jpg',
table: '/model/textures/1.jpg',
}
const mm = {
'material1': '/model/textures/1.jpg',
'material2': '/model/textures/2.png',
'material3': '/model/textures/3.jpg',
'material4': '/model/textures/4.png',
'material5': '/model/textures/5.jpg',
'material6': '/model/textures/6.jpg',
'material7': '/model/textures/7.jpg',
'material8': '/model/textures/8.jpg',
'material9': '/model/textures/9.jpg',
'material10': '/model/textures/10.jpg',
'material11': '/model/textures/11.jpg',
'material12': '/model/textures/12.jpg',
'material13': '/model/textures/13.jpg',
'material14': '/model/textures/14.jpg',
}
const folder = gui.addFolder( 'textures' );
folder.add(obj, 'left', mm)
folder.add(obj, 'right', mm)
folder.add(obj, 'bottom', mm)
folder.add(obj, 'back', mm)
folder.add(obj, 'bed', mm)
folder.add(obj, 'table', mm)
folder.onChange(event => {
console.log(event)
const key = event.property;
const value = event.value;
const mesh = scene.getObjectByName(key);
if (mesh) {
const material = new THREE.MeshBasicMaterial({
map: textureLoader.load(value)
});
mesh.material = material;
mesh.castShadow=true;
}
});
const backgroundColor = gui.addFolder( 'scene' );
backgroundColor.add({'backGround':'White'},'backGround', ['White', 'Black', 'Null', 'Color', 'Texture','自定义纹理', 'Cubemap'])
.onChange((event) => handleBackgroundChange(event, scene))
const handleBackgroundChange = (setting, scene) => {
switch (setting) {
case 'White':
scene.background = new THREE.Color(0xffffff)
break
case 'Black':
scene.background = new THREE.Color(0x000000)
break
case 'Null':
scene.background = null
break
case 'Color':
scene.background = new THREE.Color(0x44ff44)
break
case 'Texture':
textureLoader.load('/assets/wood/abstract-antique-backdrop-164005.jpg', (loaded) => {
loaded.encoding = THREE.sRGBEncoding
scene.background = loaded
scene.environment = null
})
break
case '自定义纹理':
textureLoader.load('/assets/wood/floor-parquet-pattern-172292.jpg', (loaded) => {
loaded.encoding = THREE.sRGBEncoding
scene.background = loaded
scene.environment = null
})
break
case 'Cubemap':
textureLoader.load('/assets/equi.jpeg', (loaded) => {
loaded.mapping = THREE.EquirectangularReflectionMapping
scene.background = loaded
scene.environment = loaded
})
break
default:
break
}
}
const loader = new GLTFLoader();
// 滑轨控制
const controller = new OrbitControls(camera, renderer.domElement)
controller.enableDamping = true
controller.dampingFactor = 0.05
controller.minDistance = 1
controller.maxDistance = 100
controller.minPolarAngle = 0
controller.maxPolarAngle = Math.PI
loader.load(
'/model/plan_room.gltf',
function(gltf) {
gltf.scene.traverse(function(child) {
if (child instanceof THREE.Mesh) {
// 加载模型时,添加对于的纹理贴图
for (let key in obj) {
if (child.name === key) {
const material = new THREE.MeshBasicMaterial({
map: textureLoader.load(obj[key])
});
child.material = material;
continue;
}
}
}
})
gltf.scene.scale.x = 0.5
gltf.scene.scale.y = 0.5
gltf.scene.scale.z = 0.5
scene.add(gltf.scene);
},
function(xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
},
function(error) {
console.error(error);
}
);
function animate() {
requestAnimationFrame(animate);
controller.update();
renderer.render(scene, camera);
}
animate();
</script>
</html>
源码传送
下载:https://864000.lanzouy.com/ipX7D0woxeqf 密码:3bi0
根目录执行
http-server -p9001
浏览器访问http://127.0.0.1:9001
C:\Users\mac\OneDrive\three-1>http-server -p9001
Starting up http-server, serving ./
http-server version: 14.1.1
http-server settings:
CORS: disabled
Cache: 3600 seconds
Connection Timeout: 120 seconds
Directory Listings: visible
AutoIndex: visible
Serve GZIP Files: false
Serve Brotli Files: false
Default File Extension: none
Available on:
http://192.168.31.156:9001
http://127.0.0.1:9001
Three加载3D模型贴图的更多相关文章
- 使用 Assimp 库加载 3D 模型
前言 要想让自己的 3D 之旅多一点乐趣,肯定得想办法找一些有意思一点的 3D 模型.3D 模型有各种各样的格式,obj的,stl的,fbx的等等不一而足.特别是 obj 格式的 3D 模型,完全是纯 ...
- cesium加载gltf模型点击以及列表点击定位弹窗
前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 之 ...
- WPF动态加载3D 放大-旋转-平移
原文:WPF动态加载3D 放大-旋转-平移 WavefrontObjLoader.cs 第二步:ModelVisual3DWithName.cs public class ModelVisual3DW ...
- 6_1 持久化模型与再次加载_探讨(1)_三种持久化模型加载方式以及import_meta_graph方式加载持久化模型会存在的变量管理命名混淆的问题
笔者提交到gitHub上的问题描述地址是:https://github.com/tensorflow/tensorflow/issues/20140 三种持久化模型加载方式的一个小结论 加载持久化模型 ...
- xBIM 实战01 在浏览器中加载IFC模型文件
系列目录 [已更新最新开发文章,点击查看详细] 一.创建Web项目 打开VS,新建Web项目,选择 .NET Framework 4.5 选择一个空的项目 新建完成后,项目结构如下: 二.添 ...
- OpenGL(二十二) gluBuild2DMipmaps 加载Mip纹理贴图
当纹理被用于渲染一个面积比它本身小很多的对象时,会由于纹理图像的降采样率不足而导致混叠现象,主要的表现特征是纹理图像的闪烁,出现纹理躁动.特别是在场景远近移动变换时,这种闪烁情况更为明显,严重可能会影 ...
- WPF绘制深度不同颜色的3D模型填充图和线框图
原文:WPF绘制深度不同颜色的3D模型填充图和线框图 在机械测量过程中,测量的数据需要进行软件处理.通常测量一个零件之后,需要重建零件的3D模型,便于观察测量结果是否与所测工件一致. 重建的3D模型需 ...
- cesium加载gltf模型
cesium加载gltf模型 一.采用vue-cesium:在项目里加载依赖包.命令如下: npm i --save vue-cesium 在main.js中加入如下代码: https://www.n ...
- WebGL three.js学习笔记 加载外部模型以及Tween.js动画
WebGL three.js学习笔记 加载外部模型以及Tween.js动画 本文的程序实现了加载外部stl格式的模型,以及学习了如何把加载的模型变为一个粒子系统,并使用Tween.js对该粒子系统进行 ...
- 使用 Babylon.js 在 HTML 页面加载 3D 对象
五一 Windwos Blogs 推了一篇博客, Babylon.js v3.2 发布了.因为一直有想要在自己博客上加载 3D 对象的冲动,这两天正好看到了,就动手研究研究.本人之前也并没有接触过 W ...
随机推荐
- 战“码”先锋直播预告丨如何成为一名优秀的OpenHamrony贡献者?
OpenAtom OpenHarmony(以下简称"OpenHarmony")工作委员会首度发起「OpenHarmony开源贡献者计划」,旨在鼓励开发者参与OpenHarmony开 ...
- 深入学习 XML 解析器及 DOM 操作技术
所有主要的浏览器都内置了一个XML解析器,用于访问和操作XML XML 解析器 在访问XML文档之前,必须将其加载到XML DOM对象中 所有现代浏览器都有一个内置的XML解析器,可以将文本转换为XM ...
- 编译opencv: Linux编译opencv
opencv官网:https://opencv.org/releases/ github下载地址:https://github.com/opencv/opencv/releases mkdir ...
- Mongoose介绍
官网 Mongoose.js中文网 (mongoosejs.net) 基本使用 安装 最新的是mongoose8.0.0版本,基于Promise,以前的版本是基于回调函数. npm npm i mon ...
- C# 冻结Excel窗口以锁定行列、或解除冻结
在处理大型Excel工作簿时,有时候我们需要在工作表中冻结窗格,这样可以在滚动查看数据的同时保持某些行或列固定不动.冻结窗格可以帮助我们更容易地导航和理解复杂的数据集.相反,当你不需要冻结窗格时,你可 ...
- PIL.Image, numpy, tensor, cv2 之间的互转,以及在cv2在图片上画各种形状的线
''' PIL.Image, numpy, tensor, cv2 之间的互转 ''' import cv2 import torch from PIL import Image import num ...
- 力扣349(java&python)-两个数组的交集(简单)
题目: 给定两个数组 nums1 和 nums2 ,返回 它们的交集 .输出结果中的每个元素一定是 唯一 的.我们可以 不考虑输出结果的顺序 . 示例 1: 输入:nums1 = [1,2,2,1], ...
- 阿里云2020上云采购季,你最pick哪个产品组合?
阿里云2020上云采购季如火如荼进行中,活动还剩最后10天啦,你的云产品都买好了吗? 还没买的,还没逛的,请戳:https://www.aliyun.com/sale-season/2020/proc ...
- 怀里橘猫柴犬,掌上代码江湖——对话阿里云 MVP郭旭东
简介: 跟郭旭东聊过之后,我对程序员的敬佩又多一分.这个92年的开发者,难能可贵地兼备朝气蓬勃的技术能量与长远深刻的行业洞见.独自承担DevOps平台从0到1的所有工作,我打趣说超级开发者不过如此,他 ...
- Quick BI产品核心功能大图(五)移动端:让数据在更多业务场景中流通
简介:将数据更好的融入日常工作中,一个重要的前提条件就是多端多渠道的数据触达和办公协同能力. Quick BI凭借移动端交互体验,帮助用户随时随地便捷查看报表,并通过在线协同方式,追踪策略的执行落地 ...