今日任务
今天的任务其实很简单,就是展现一个fbx,而不是之前的cube模型,在此之前,我们来看一个three.js和vue的数据驱动之前的兼容性
- 新做一个页面,里面展示的内容为fbx模型
- 做一个5秒的事件,在控制台中log一个字符串
- 五秒的时间改为读取另一个fbx
步骤
- 照常打开开发环境,并运行
- 准备两个fbx模型
- 抄袭three.js里面的的webgl_loader_fbx.html的代码
- 对照之前的
webgl_geometry_cube.html
,
- 完成我们的代码,LoadFBX.fbx
<template>
<div class="Create"></div>
</template>
<script>
import * as THREE from "three";
import Stats from "three/examples/jsm/libs/stats.module.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
export default {
name: "Create",
data() {
return {};
},
setup() {
let camera, scene, renderer, stats;
const clock = new THREE.Clock();
let mixer;
const init = () => {
const container = document.createElement("div");
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
2000
);
camera.position.set(100, 200, 300);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xa0a0a0);
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
hemiLight.position.set(0, 200, 0);
scene.add(hemiLight);
const dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(0, 200, 100);
dirLight.castShadow = true;
dirLight.shadow.camera.top = 180;
dirLight.shadow.camera.bottom = -100;
dirLight.shadow.camera.left = -120;
dirLight.shadow.camera.right = 120;
scene.add(dirLight);
// scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );
// ground
const mesh = new THREE.Mesh(
new THREE.PlaneGeometry(2000, 2000),
new THREE.MeshPhongMaterial({ color: 0x999999, depthWrite: false })
);
mesh.rotation.x = -Math.PI / 2;
mesh.receiveShadow = true;
scene.add(mesh);
const grid = new THREE.GridHelper(2000, 20, 0x000000, 0x000000);
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add(grid);
// model
//const mpath = require("/public/Samba Dancing.fbx");
const loader = new FBXLoader();
loader.load(
"http://localhost/myfbx.php?filepath=Samba Dancing.fbx",
function (object) {
mixer = new THREE.AnimationMixer(object);
if (object.animations[0] != null) {
const action = mixer.clipAction(object.animations[0]);
action.play();
}
object.traverse(function (child) {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
scene.add(object);
}
);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 100, 0);
controls.update();
window.addEventListener("resize", onWindowResize);
// stats
stats = new Stats();
container.appendChild(stats.dom);
};
const onWindowResize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
const animate = () => {
requestAnimationFrame(animate);
const delta = clock.getDelta();
if (mixer) mixer.update(delta);
renderer.render(scene, camera);
stats.update();
};
init();
animate();
},
};
</script>
- 遇到一个问题,fbx无法直接读取内部资源,所以需要通过接口的方式去调用,默认的方式只接受get,我们无法使用post(如果可以请告诉我),所以我就专门写了一个php用于返回fbx资源
<?php
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
readfile($_GET['filepath']);
- 可是遇到了跨域的问题,所以对应的接口需要添加一个域允许的header,完整代码如下.
<?php
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
header('Access-Control-Allow-Origin:' . $origin);
readfile($_GET['filepath']);
- 把对应的fbx文件放到资源目录中,现在就可以访问了,但是一直会报错,一个属性无法得到,经过研究,主要是因为有的fbx有动画,有的没有,判断一下就好了,整体代码放在上面的第5项中,下面为代码节选.
- 经过判断之后,就没有这个问题了,那么现在需要的是修改main.js和路由
路由
main.js
- 最终的效果为有动画的会自动播放,没有动画的不会自动播放
总结
第一次接触跨域的问题,解决了很久,因为了属性问题重叠了,所以被搞了很久,感觉自己一直写错,但是实际上是两个问题,后面类似的事情不能发生了,关于跨域的请求问题,如果可以的话,后面还是要学习一下axios的,跨域不应该是开发过程中的问题.
TODO
- 登录功能
- 登录判断
- 项目添加
- 上传fbx
- 上传相关资源
- 查看相关资源
- 下载fbx
- 创建项目