гитхаб-адресДобро пожаловать звезда!
В предыдущем проекте была использована проблема демонстрации 3D-модели, и предыдущее резюме обучения и ямы были отсортированы. 3D Frameworks включают старый двигатель Three.js и Microsoft Babylon.js
Для сравнения используйте более общий Three.js.Основные понятия Three.js
В основном из "Руководства по разработке Three.js"Также см. веб-сайт в Интернетеучебник по трем
3 основных понятия: сцена, камера и рендерер.
-
Сценарий смысла: сценарий — это носитель, контейнер, все, что работает внутри контейнера (хранение всех объектов рендеринга и источника света)
-
Роль камеры-камеры состоит в том, чтобы определять поле зрения, которое эквивалентно нашим глазам, и создавать снимки один за другим.Наиболее часто используемой является перспективная камера PerspectiveCamera, а также существуют другие матричные камеры ArrayCamera (включая несколько вспомогательных камер). , которые рендерятся с помощью этой группы подкамер. Камеры в основном делятся на две категории: ортогональные камеры и перспективные камеры.Для ортогональных камер все блоки рендерятся одинакового размера, расстояние между объектом и камерой не влияет на результат рендеринга, а перспективная камера близка к реальный мир, и объект будет иметь разную высоту
-
PerspectiveCamera Перспективная камера — имитирует зрение человеческого глаза в зависимости от расстояния до объекта от камеры.
- Средство рендеринга отвечает за то, как визуализировать изображение, использовать ли WegGL или Canvas, аналогично рендерингу в реакции, для создания фактического эффекта страницы.
некоторые другие понятия
- Сетчатая сетка: с помощью сцены и камеры вы можете видеть объекты в 3D-сцене.Наиболее часто используемые объекты в сцене называются сетками. Сетка состоит из двух частей: геометрии и материала.
- Материалы, текстуры. Поверхностные свойства объектов могут быть простыми цветами или сложными ситуациями, такими как отражение/прохождение/преломление и текстурные узоры. Например, текстура на внешней стороне коробки.
- Геометрия геометрия: threejs использует геометрию для определения геометрии объектов.На самом деле, ядром геометрии является набор точек.Причина, по которой существует так много геометрии, заключается в более удобном создании наборов точек различной формы.
- Освещение: Компоненты. Если нет источника света, мы не можем увидеть результаты рендеринга.Подробнее см.Световые эффекты и модель освещения Фонга. Некоторые часто используемые источники света:
- Источник окружающего света AmbientLight, относящийся к базовому источнику света, обеспечивает базовую яркость для всех объектов сцены.
- Параллельный источник света DirectionalLight: подобно солнечному свету, источники света параллельны.
- HemisphereLight Hemisphere Light: Только половина сферы будет излучать свет.
- PointLight Point Light: точка излучает вокруг себя источник света, обычно используемый для лампочек.
- Прожектор: конус света
- Примечание: Не каждый источник света может давать тени (Shadow): DirectionalLight, PointLight, SpotLight могут давать тени Кроме того, если вы хотите включить тень модели, модель состоит из нескольких мешей, и только родительский меш Тень неприемлема, и необходимо обойти все дочерние меши под родительским мешем, чтобы включить castShadow и receiveShadow для отбрасывания теней.
- Загрузчики: Импортированные файлы модели для разбора, распространенные: OBJLoader (загрузка файлов .obj), JSONLoader, MTLLoader
// 场景是所有物体的容器
var scene = new THREE.Scene();
// 相机,相机决定了场景中那个角度的景色会显示出来。相机就像人的眼睛一样,人站在不同位置,抬头或者低头都能够看到不同的景色。
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
// 渲染器renderer的domElement元素,表示渲染器中的画布,所有的渲染都是画在domElement上的
var renderer = new THREE.WebGLRenderer(); // 渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的大小为窗口的内宽度,也就是内容区的宽度
document.body.appendChild(renderer.domElement);
// 渲染循环
function animate() {
render();
// 调用 requestAnimationFrame 函数,传递一个 callback 参数,则在下一个动画帧时,会调用 callback 这个函数。
requestAnimationFrame( animate );
}
动画方案:
一:改变camera
function animation()
{
//renderer.clear();
camera.position.x =camera.position.x +1;
renderer.render(scene, camera);
requestAnimationFrame(animation);
}
// camera.position.x =camera.position.x +1;
// 将相机不断的沿着x轴移动1个单位,也就是相机向右移动,那么相机中物体是向左移动的。
// 调用requestAnimationFrame(animation)函数,这个函数又会在下一个动画帧出发animation()函数,这样就不断改变了相机的位置,从而物体看上去在移动了。
// 另外,必须要重视render函数,这个函数是重新绘制渲染结果,如果不调用这个函数,那么即使相机的位置变化了,但是没有重新绘制,仍然显示的是上一帧的动画 renderer.render(scene, camera);
二:改变物体自身位置--mesh
mesh就是指的物体,它有一个位置属性position,这个position是一个THREE.Vector3类型变量,所以你要把它向左移动,只需要将x的值不断的减少就可以了。这里我们减去的是1个单位。
// [渲染真实性---光源运用](http://www.hewebgl.com/article/getarticle/60)
THREE.Light ( hex )
它有一个参数hex,接受一个16进制的颜色值。例如要定义一种红色的光源,我们可以这样来定义:
Var redLight = new THREE.Light(0xFF0000);
// [文理--3D物体的皮肤:](http://www.hewebgl.com/article/getarticle/68)
纹理类由THREE.Texture表示,其构造函数如下所示:
THREE.Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy )
Вот основная концепция Three.js
Тогда приведи простой пример
// 引入 Three.js 库
<script src="https://unpkg.com/three"></script>
function init () {
// 获取浏览器窗口的宽高,后续会用
var width = window.innerWidth
var height = window.innerHeight
// 创建一个场景
var scene = new THREE.Scene()
// 创建一个具有透视效果的摄像机
var camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 800)
// 设置摄像机位置,并将其朝向场景中心
camera.position.x = 10
camera.position.y = 10
camera.position.z = 30
camera.lookAt(scene.position)
// 创建一个 WebGL 渲染器,Three.js 还提供 <canvas>, <svg>, CSS3D 渲染器。
var renderer = new THREE.WebGLRenderer()
// 设置渲染器的清除颜色(即背景色)和尺寸。
// 若想用 body 作为背景,则可以不设置 clearColor,然后在创建渲染器时设置 alpha: true,即 new THREE.WebGLRenderer({ alpha: true })
renderer.setClearColor(0xffffff)
renderer.setSize(width, height)
// 创建一个长宽高均为 4 个单位长度的立方体(几何体)
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4)
// 创建材质(该材质不受光源影响)
var cubeMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000
})
// 创建一个立方体网格(mesh):将材质包裹在几何体上
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
// 设置网格的位置
cube.position.x = 0
cube.position.y = -2
cube.position.z = 0
// 将立方体网格加入到场景中
scene.add(cube)
// 将渲染器的输出(此处是 canvas 元素)插入到 body 中
document.body.appendChild(renderer.domElement)
// 渲染,即摄像机拍下此刻的场景
renderer.render(scene, camera)
}
init()
Онлайн-примернажмите
практическое использование
три статистики монитора производительности
В основном используется для отображения номера кадра производительности
-
FPS: количество кадров за последнюю секунду, чем больше, тем плавнее
-
MS: время (в миллисекундах), необходимое для рендеринга кадра, чем меньше, тем лучше
-
МБ: информация о занятой памяти
-
ПОЛЬЗОВАТЕЛЬСКАЯ: Пользовательская панель
var stats = new Stats()
stats.showPanel(1)
document.body.appendChild(stats.dom)
function animate() {
requestAnimationFrame(animate)
}
requestAnimationFrame(animate)
Некоторые конкретные примеры, которые не нужно импортировать
допустимыйGitHub.com/Мистер не понимает ОО/Он и горячий…Скачайте файл и посмотрите пример в \three.js-master\examples, чтобы ознакомиться с соответствующим кодом
Пример импорта 3D-модели
Введение в импорт типов моделей
Для импорта файлов модели требуется соответствующий загрузчик, обычно используемыйФорматы экспорта 3D-программ, проект в основном использует типы OBJ и MTL, OBJ определяет геометрию, а MTL определяет материал
//当mtl中引用了dds类型的图片时,还需导入DDSLoader文件。
//这里的src路径视实际开发而定
<script src="js/loaders/DDSLoader.js"></script>
<script src="js/loaders/MTLLoader.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
//设置路径,也可不是设置,在load中加载完整路径也可
mtlLoader.setPath( 'obj/male02/' );
mtlLoader.load( 'male02_dds.mtl',
// 资源加载成功后执行的函数
//@params materials THREE.MTLLoader.MaterialCreator
function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'obj/male02/' );
objLoader.load( 'male02.obj', function ( object ) {
object.position.y = - 95;
scene.add( object );
});
});
Конкретные примеры можно посмотреть
Есть проблема с импортом OBJ, после экспорта модели в формат obj размер файла слишком велик (при размещении на сервере это вызовет серьезные проблемы с производительностью), и нужно импортировать дополнительные MTL, иначе только геометрическая модель будет отображаться
формат модели glTF
.obj является статической моделью, не поддерживает хранение данных анимации, не может использовать анимацию модели и является громоздким, glTF — это формат файлов 3D-моделей, разработанный Khronos Group, который характеризуется минимизацией размера файлов 3D-моделей, повышением эффективности передачи, загрузки и анализа файлов 3D-моделей, а также расширяемостью и функциональной совместимостью.
.gltf содержит описания иерархий узлов, камер, сеток, материалов и анимаций в сцене.
Использование формата glTF в Three.js требует дополнительного введения загрузчика GLTFLoader.js.
var gltfLoader = new THREE.gltfLoader()
gltfLoader.load('./assets/box.gltf', function(sence) {
var object = scene.gltf // 模型对象
scene.add(object) // 将模型添加到场景中
})
Модель glTF можно анимировать с помощью программного обеспечения для моделирования Blender.После экспорта используйте GLTFLoader, чтобы загрузить ее в Three.js, и вы можете получить массив анимаций, который содержит каждое действие анимации модели.
Для повышения производительности сети вы также можете использоватьDracoИнструмент сжатия рекомендуется только при наличии большого количества файлов модели (поскольку формат меняется после сжатия, необходимо использовать другие инструменты анализа)
анимация
Как упоминалось выше, анимация, что касается анимации, вы можете напрямую использовать стороннюю библиотеку анимации Tween, у которой есть соответствующие приложения в исследовании, предоставленном коллегой Сюй. Обычно в Three.js используется анимация requestAnimationFrame()Когда вам нужно обновить экран, вы можете вызвать этот метод. Функция обратного вызова перед следующей перерисовкой браузера. Номер обратного вызова обычно составляет 60 раз в секунду.
Для моделей рекомендуется использовать такие анимации, как затухание, масштабирование, смещение и вращение. GSAP чтобы было проще.
let tween = new TimelineMax()
tween
.to(box.scale, 1, { // 从 1 缩放至 2,花费 1 秒
x: 2,
y: 2,
z: 2,
ease: Power0.easeInOut, // 速度曲线
onStart: function() {
// 监听动画开始
},
onUpdate: function() {
// 监听动画过程
},
onComplete: function() {
// 监听动画结束
}
})
.to(box.position, 1, { // 缩放结束后,位移 x 至 10,花费 1 秒
x: 10,
y: 0,
z: 0
})
управление орбитой
Контроллер сцены, OrbitControls — это метод, используемый для отладки камеры. После создания экземпляра вы можете поворачивать угол объектива камеры, перетаскивая мышь. Колесо мыши может управлять расстоянием и расстоянием до объектива камеры. Поворот и расстояние основаны на центральная точка сцены. Предварительный просмотр намного проще.
// 引入文件
<script src="js/OrbitControls.js"></script>
//场景控制器初始化
function initControls() {
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enabled = true; // 鼠标控制是否可用
// 是否自动旋转
controls.autoRotate = true;
controls.autoRotateSpeed = 0.05;
//是否可旋转,旋转速度(鼠标左键)
controls.enableRotate = true;
controls.rotateSpeed = 0.3;
//controls.target = new THREE.Vector();//摄像机聚焦到某一个点
//最大最小相机移动距离(景深相机)
controls.minDistance = 10;
controls.maxDistance = 40;
//最大仰视角和俯视角
controls.minPolarAngle = Math.PI / 4; // 45度视角
controls.maxPolarAngle = Math.PI / 2.4; // 75度视角
//惯性滑动,滑动大小默认0.25
controls.enableDamping = true;
controls.dampingFactor = 0.25;
//是否可平移,默认移动速度为7px
controls.enablePan = true;
controls.panSpeed = 0.5;
//controls.screenSpacePanning = true;
//滚轮缩放控制
controls.enableZoom = true;
controls.zoomSpeed = 1.5;
//水平方向视角限制
//controls.minAzimuthAngle = -Math.PI/4;
//controls.maxAzimuthAngle = Math.PI/4;
}
Нажмите, чтобы взаимодействовать
В 3D-моделях щелчки мыши являются важным взаимодействием. Для Three.js он не имеет иерархических отношений, подобных DOM, и находится в трехмерной среде, поэтому нам нужно определить, выбран ли объект следующими способами.
function onDocumentMouseDown(event) {
// 点击位置创建一个 THREE.Vector3 向量
var vector = new THREE.Vector3(( event.clientX / window.innerWidth ) * 2 - 1, -( event.clientY / window.innerHeight ) * 2 + 1, 0.5);
// vector.unproject 方法将屏幕上的点击位置转换成 Three.js 场景中的坐标
vector = vector.unproject(camera);
// 使用 THREE.Raycaster 可以向场景中发射光线
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
// 使用 raycaster.intersectObjects 方法来判断指定的对象中哪些被该光线照射到的,
// 从而显示不同的颜色
var intersects = raycaster.intersectObjects([sphere, cylinder, cube]);
if (intersects.length > 0) {
console.log(intersects[0]);
// 点击后改变透明度
intersects[0].object.material.transparent = true;
intersects[0].object.material.opacity = 0.1;
<!--...... 在这里可以实现你所需要的交互-->
}
}
Практическое применение в реакции
// 引入相关的依赖
npm i -S three
<!--GisThree.js-->
<!--当然 这个代码还有很大的优化空间啊!-->
import React, { Component, Fragment } from 'react';
import './GisThree.less';
import OBJLoader from './threejsLibs/OBJLoader';
import Orbitcontrols from './threejsLibs/OrbitControls';
import MTLLoader from './threejsLibs/MTLLoader_module';
import { Icon } from 'antd';
import exhibitObj from './modal/exhibit2.obj';
import exhibitMtl from './modal/exhibit2.mtl';
let THREE = require('three');
Orbitcontrols(THREE);
OBJLoader(THREE);
MTLLoader(THREE);
// 排除这些名字的3D模型
const objectArrName = [ "房屋1101", "房屋1150", "房屋600", "房屋70", "房屋45", "房屋362", "房屋363", "房屋364", "房屋500" ];
class GisThree extends Component {
constructor( props ) {
super(props);
this.state = {
isModel: false,
currentName: '暂无名字',
clientX: 0,
clientY: 0
};
this.threeRef = React.createRef();
}
componentDidMount() {
const width = window.innerWidth;
const height = window.innerHeight;
// todo 初始化场景
const scene = new THREE.Scene();
// todo 加载相机
const camera = new THREE.PerspectiveCamera(60, width / height, 0.1, 80);
camera.position.set(0, 25, 25);
camera.lookAt(new THREE.Vector3(0, 0, 0));
//todo 加载光线
const ambLight = new THREE.AmbientLight(0x404040, 0.5);
const pointLight = new THREE.PointLight(0x404040, 0.8);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
pointLight.position.set(100, 10, 0);
pointLight.receiveShadow = true;
scene.add(ambLight);
scene.add(pointLight);
scene.add(directionalLight);
//todo renderer
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(width, height - 10);
//renderer.setClearColor(0xb9d3ff,1);
renderer.setClearColor(0x000000, 1.0);
//todo 加载模型model
let mtlLoader = new THREE.MTLLoader();
mtlLoader.load(exhibitMtl,
function ( materials ) {
console.log('sdj exhibit.obj', materials)
materials.preload();
let objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(exhibitObj, function ( object ) {
console.log('sdj exhibit.obj')
console.log('sdj exhibit.obj object', object);
for ( let i = 0; i < object.children.length; i++ ) {
let material = object.children[ i ].material;
let meshObj = new THREE.Mesh(object.children[ i ].geometry, material);
meshObj.receiveShadow = true;
meshObj.castShadow = true;
meshObj.scale.set(0.02, 0.02, 0.02);
meshObj.name = "房屋" + i;
meshObj.position.x = 0;
meshObj.position.y = 0;
meshObj.position.z = -20;
scene.add(meshObj);
}
});
}
);
// todo 场景控制器初始化
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enabled = true; // 鼠标控制是否可用
// 是否自动旋转
controls.autoRotate = true;
controls.autoRotateSpeed = 0.05;
//是否可旋转,旋转速度(鼠标左键)
controls.enableRotate = true;
controls.rotateSpeed = 0.3;
//controls.target = new THREE.Vector();//摄像机聚焦到某一个点
//最大最小相机移动距离(景深相机)
controls.minDistance = 10;
controls.maxDistance = 40;
//最大仰视角和俯视角
controls.minPolarAngle = Math.PI / 4; // 45度视角
controls.maxPolarAngle = Math.PI / 2.4; // 75度视角
//惯性滑动,滑动大小默认0.25
controls.enableDamping = true;
controls.dampingFactor = 0.25;
//是否可平移,默认移动速度为7px
controls.enablePan = true;
controls.panSpeed = 0.5;
//controls.screenSpacePanning = true;
//滚轮缩放控制
controls.enableZoom = true;
controls.zoomSpeed = 1.5;
//水平方向视角限制
//controls.minAzimuthAngle = -Math.PI/4;
//controls.maxAzimuthAngle = Math.PI/4;
//todo 绑定到类上
this.scene = scene;
this.camera = camera;
this.renderer = renderer;
this.controls = controls;
//鼠标移入和移出事件高亮显示选中的模型
this.currentObjectColor = null; //移入模型的颜色
this.currentObject = null; //鼠标移入的模型
// 初始化场景
// 加载到dom元素上
this.threeRef.current.appendChild(this.renderer.domElement)
this.start();
window.addEventListener('resize',this.resizeFunc1 ,false);
window.addEventListener('resize',this.resizeFunc2 ,false);
}
componentWillUnmount() {
this.stop();
this.threeRef.current.removeChild(this.renderer.domElement);
window.removeEventListener('resize',this.resizeFunc1 ,false);
window.removeEventListener('resize',this.resizeFunc2 ,false);
}
// 初始化
start = () => {
if(!this.frameId){
this.frameId = requestAnimationFrame(this.animate)
}
}
// 卸载组件的时候去除
stop = () => {
cancelAnimationFrame(this.frameId);
}
// 更新状态
animate = () => {
this.controls.update();
this.renderScene();
this.frameId = requestAnimationFrame(this.animate);
}
renderScene = () => {
this.renderer.render(this.scene, this.camera);
}
// 是否展示弹窗
changeModel = ( e ) => {
e.stopPropagation();
this.setState({
isModel: !this.state.isModel
})
}
closeModel = ( e ) => {
e.stopPropagation();
if (this.controls && !this.controls.autoRotate){
this.controls.autoRotate = true;
}
this.setState({
isModel: false
})
}
// 点击3D模型匹配
mouseClick = (e) => {
// 鼠标坐标映射到三维坐标
e.preventDefault();
const that = this;
const mouse = new THREE.Vector2();
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
if(!this.camera || !this.scene) return;
let vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(this.camera);
let raycaster = new THREE.Raycaster(this.camera.position, vector.sub(this.camera.position).normalize());
let intersects = raycaster.intersectObjects(this.scene.children, true); //选中的三维模型
console.log('sdj position',intersects)
if (intersects.length > 0) {
let SELECTED = intersects[0];
let currentName = SELECTED.object.name;
console.log('sdj position', e.clientX, e.clientY, e.screenX, e.screenY);
if (objectArrName.indexOf(currentName) == -1) {
if (this.controls.autoRotate){
this.controls.autoRotate = false;
}
that.changeModel(e);
that.setState({
currentName,
clientX: e.clientX,
clientY: (e.clientY - 60)
})
console.log("你选中的物体的名字是:" + currentName);
}
}
}
// 鼠标聚焦
mouseenterObject = (e) => {
// 鼠标坐标映射到三维坐标
e.preventDefault();
let mouse = new THREE.Vector2();
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
let vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(this.camera);
let raycaster = new THREE.Raycaster(this.camera.position, vector.sub(this.camera.position).normalize());
let intersects = raycaster.intersectObjects(this.scene.children, true); //选中的三维模型
if (!intersects.length && this.currentObjectColor && this.currentObject) { //从模型处移到外面
this.currentObject.object.material.color.setHex(this.currentObjectColor);
this.currentObjectColor = null;
this.currentObject = null;
}
if (intersects.length > 0) {
let SELECTED = intersects[0];
let currentName = SELECTED.object.name;
if (objectArrName.indexOf(currentName) == -1) {
if (this.currentObject && currentName === this.currentObject.object.name) {
return;
}
if (this.currentObjectColor && this.currentObject && currentName !== this.currentObject.object.name) { //color值是一个对象
this.currentObject.object.material.color.setHex(this.currentObjectColor);
}
this.currentObject = SELECTED;
this.currentObjectColor = SELECTED.object.material.color.getHex();
SELECTED.object.material.color.set(0x74bec1);
} else {
if (this.currentObjectColor && this.currentObject && currentName !== this.currentObject.object.name) { //color值是一个对象
this.currentObject.object.material.color.setHex(this.currentObjectColor);
}
this.currentObjectColor = null;
this.currentObject = null;
}
}
}
resizeFunc1 = () => {
this.controls.update();
}
resizeFunc2 = (e) => {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
render() {
return (
<Fragment>
<div
className={ this.props.className || 'three-component' }
id="d3"
ref={ this.threeRef }
onClick={this.mouseClick}
onMouseMove={this.mouseenterObject}
/>
{
this.state.isModel && (
<div
className="three-modal"
style={ {
top: this.state.clientY,
left: this.state.clientX
} }
>
<Icon
className="three-modal-close"
type="close" theme="outlined"
onClick={ this.closeModel }
/>
<ul>
<li>
<span className="modal-title">出租屋编码</span>
<span className="modal-data">{ this.state.currentName }</span>
</li>
<li>
<span className="modal-title">地址</span>
<span className="modal-data">社区一号</span>
</li>
<li>
<span className="modal-title">每层楼栋数</span>
<span className="modal-data">6</span>
</li>
<li>
<span className="modal-title">层数</span>
<span className="modal-data">16</span>
</li>
</ul>
</div>
)
}
</Fragment>
)
}
}
export default GisThree;
Ошибка возникает на сервере, а на локальном сервере проблем нет Ссылаться наstackoverflow.com/questions/4…
objLoader.js:624 Uncaught Error: THREE.OBJLoader: Unexpected line: "<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000"><link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico"><title>智慧社区_管理后台</title><link href="/static/css/main.bdb0e864.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="/config.js"></script><script type="text/javascript" src="/static/js/charts.24f90613.js"></script><script type="text/javascript" src="/static/js/vendor.0b9068d0.js"></script><script type="text/javascript" src="/static/js/main.cfa93993.js"></script></body></html>"
at OBJLoader.parse (objLoader.js:624)
at objLoader.js:385
at XMLHttpRequest.<anonymous> (three1.js:630)
objLoader.js:624 Uncaught Error: THREE.OBJLoader: Unexpected line: "<!doctype html>"
at OBJLoader.parse (objLoader.js:624)
at objLoader.js:385
at XMLHttpRequest.<anonymous> (three1.js:630)
Наконец, я обнаружил, что после того, как mtl-loader устарел (и был обновлен до webpack4), материал отображался правильно, и была проблема, что git игнорировал .obj, см.блог, проблема .obj игнорируется в глобальном gitignore_global.txt, какая яма! ! !
Если есть какие-либо ошибки или неточности, пожалуйста, обязательно исправьте их, большое спасибо!
Ссылаться на:
- Приступая к работе — Three.js сейчас изучаем сейчас продаем
- официальная документация по 3js
- Учебник по китайскому языку Three.js
- 1.плагин управления орбитой ---2. Подробное объяснение
- Импорт 3D-модели
- react three.js
- Первый проект threejs - руководство по заполнению ям для интерфейса в основном знакомит с C4D для json и некоторыми акцентами на анимационной модели.
- [Three.js] Плагин вращения OrbitControl
- Чтение модели блендера и импорт анимации
- Создайте трехмерный физический мир за десять минут