vue3+threejs入门

首先是创建一个vue3项目

npm create vue@latest

这一指令将会安装并执行 create-vue,它是 Vue 官方的项目脚手架工具。你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示:

✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add an End-to-End Testing Solution? … No / Cypress / Nightwatch / Playwright
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
✔ Add Vue DevTools 7 extension for debugging? (experimental) … No / Yes

Scaffolding project in ./<your-project-name>...
Done.

如果不确定是否要开启某个功能,你可以直接按下回车键选择 No

创建之后就能得到一个这样的项目

npm run dev

可运行项目

下一步开始导入threejs

npm install three cannon cannon-es

或者使用yarn来导入依赖

yarn install three cannon cannon-es

然后直接上代码

<template></template>

<script setup>
import * as THREE from "three";
import { onMounted } from "vue";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 导入connon引擎
import * as CANNON from "cannon-es";
// 创建物理世界
const world = new CANNON.World();
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
const controls = new OrbitControls(camera, renderer.domElement);
scene.background = new THREE.Color(0x000000);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.outputEncoding = THREE.sRGBEncoding;
// 设置时钟
const clock = new THREE.Clock();
onMounted(() => {
  init();
});


function init() {
  camera.position.set(0, 5, 10);
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
  // 创建球和平面
  const sphereGeometry = new THREE.SphereGeometry(1, 26, 26); // 球的几何形状
  const sphereMaterial = new THREE.MeshStandardMaterial();

  const sphereGeometry1 = new THREE.SphereGeometry(1, 26, 26); // 球的几何形状
  const sphereMaterial1 = new THREE.MeshStandardMaterial();
  const sphere1 = new THREE.Mesh(sphereGeometry1, sphereMaterial1);
  sphere1.castShadow = true; // 阴影
  sphere1.position.set(2, 7, 2.5); // 球的位置
  scene.add(sphere1);

  const cjSphere = new THREE.SphereGeometry(1, 26, 26);
  const cjMaterial = new THREE.MeshStandardMaterial();
  const cjMesh = new THREE.Mesh(cjSphere,cjMaterial);
  cjMesh.castShadow = true;
  cjMesh.position.set(2,3,2.5)
  scene.add(cjMesh)

  const xs = new THREE.SphereGeometry(2,24,24)
  const xm = new THREE.MeshStandardMaterial();
  const xmesh = new THREE.Mesh(xs,xm)
  xmesh.castShadow = true;
  xmesh.position.set(2,2,2)
  scene.add(xmesh)

  // 定义两个材料
  const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  sphere.castShadow = true; // 阴影
  sphere.position.set(0, 5, 0.5); // 球的位置
  scene.add(sphere);

  const floorMaterial = new THREE.MeshStandardMaterial({
    // map: texture,
    color: 0xe4e4e4,
    transparent: true,
    opacity: 0.5,
  });
  const floor = new THREE.Mesh(new THREE.PlaneGeometry(20, 20), floorMaterial);
  floor.position.set(0, -5, 0);
  floor.rotation.x = -Math.PI / 2;
  floor.receiveShadow = true; // 接收阴影
  scene.add(floor);
  // 设置物理世界的重力
  world.gravity.set(0, -9.8, 0);
  // 创建物理小球形状
  // const sphereShape = new CANNON.Sphere(1)
  const sphereShape = new CANNON.Sphere(sphereGeometry.parameters.radius); // 使用场景中小球的半径
  //设置物体材质
  // const sphereWorldMaterial = new CANNON.Material()
  const sphereWorldMaterial = new CANNON.Material("sphereMaterial");
  const groundWorldMaterial = new CANNON.Material("groundMaterial");
  // 创建物理世界的物体
  const sphereBody = new CANNON.Body({
    shape: sphereShape,
    position: new CANNON.Vec3(0, 5, 0.5),
    //   小球质量
    mass: 1,
    //   物体材质
    material: sphereWorldMaterial,
  });
  // 将物体添加至物理世界
  world.addBody(sphereBody);

  const sphereShape1 = new CANNON.Sphere(sphereGeometry1.parameters.radius); // 使用场景中小球的半径
  //设置物体材质
  // const sphereWorldMaterial1 = new CANNON.Material()
  const sphereWorldMaterial1 = new CANNON.Material("sphereMaterial1");
//   const groundWorldMaterial1 = new CANNON.Material("groundMaterial1");
  // 创建物理世界的物体
  const sphereBody1 = new CANNON.Body({
    shape: sphereShape1,
    position: new CANNON.Vec3(2, 7, 2.5),
    //   小球质量
    mass: 10,
    //   物体材质
    material: sphereWorldMaterial1,
  });
  // 将物体添加至物理世界
  world.addBody(sphereBody1);

  const world_shape = new CANNON.Sphere(1)
  const world_material = new CANNON.Material('cjMaterial')
  const worldBody = new CANNON.Body({
	shape:world_shape,
	position:new CANNON.Vec3(2,3,2.5),
	mass:1,
	material:world_material
  });
  world.addBody(worldBody);

  const wm = new CANNON.Material('xm')
  const wb = new CANNON.Body({
	shape:new CANNON.Sphere(2),
	position:new CANNON.Vec3(4,2,4),
	mass:10,
	material:wm
  })
  world.addBody(wb)


  //添加环境光和平行光
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  scene.add(ambientLight);
  const dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
  dirLight.castShadow = true; // 阴影
  scene.add(dirLight);
  // 开启场景中的阴影贴图
  renderer.shadowMap.enabled = true;
  // 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
  controls.enableDamping = true;
  // 物理世界创建地面
  const floorShape = new CANNON.Plane();
  const floorBody = new CANNON.Body();
  floorBody.material = groundWorldMaterial;
  // 当质量为0的时候,可以使得物体保持不动
  floorBody.mass = 0;
  floorBody.addShape(floorShape);
  // 地面位置
  floorBody.position.set(0, -5, 0);
  // 旋转地面的位置
  floorBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2);
  world.addBody(floorBody);
  //创建联系材质
  const concretePlasticMaterial = new CANNON.ContactMaterial(
    sphereWorldMaterial,
    groundWorldMaterial,
    {
      friction: 0.1,
      restitution: 0.6,
    }
  );
  const fx = new CANNON.ContactMaterial(
	wm,groundWorldMaterial,{friction:0.1,restitution:0.6}
  );
  //添加联系材质
  world.addContactMaterial(concretePlasticMaterial);
  world.addContactMaterial(fx);
  function render() {
    let deltaTime = clock.getDelta();
    // 更新物理引擎里世界的物体
    world.step(1 / 120, deltaTime); // 更新
    controls.update();
    sphere.position.copy(sphereBody.position); // 渲染引擎复制物理引擎中的数据
    sphere1.position.copy(sphereBody1.position); // 渲染引擎复制物理引擎中的数据
	cjMesh.position.copy(worldBody.position);
	xmesh.position.copy(wb.position)

    renderer.render(scene, camera);
    //   渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render);
  }

  render();
}
</script>

小白的话,可以直接将这段代码放入到App.vue中,直接替换掉app.vue,就能够直接运行,

接下来说一下原理:

        threejs首先是场景,也就是能够看到的界面,我们可以生成一个物体放入到场景中,这样我们就能在场景中看到这个物体,通过设置这个物体的属性,可以改变物体的形状、材质、位置,

        还有一个是物理世界,这个在页面中是看不到的,但是能够展示一些物理效果,比如设置重力、碰撞等等。

        物理世界中同样需要放入物体,设置物体的一些属性

        如果这个时候看网页的话,就会发现页面中有一个物体,但是并不会动,因为场景物体和物理世界物体并没有关联,但是物理世界的物体是真实存在的

        这样就关联上了

        但是物体之间的碰撞没有效果

        

        增加物体之间的关联,这样物体之间碰撞就有效果了

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Vue3和Three.js渲染室内地图有几个主要步骤。 首先,你需要准备好室内地图的数据。这可以是一个包含房间、墙壁、家具等元素的3D模型文件,如OBJ或GLTF格式。你还可以考虑将地图数据转换为JSON格式,并使用自定义脚本生成3D对象。 接下来,在Vue3中创建一个Three.js的场景(Scene)。你可以使用Vue Composition API来创建一个自定义的Vue组件,该组件将负责Three.js的初始化和场景的绘制。在这个组件中,你将使用Three.js的PerspectiveCamera来设置透视投影相机,并使用OrbitControls插件来实现用户交互控制。 然后,你需要加载地图数据并将其转换为Three.js的3D对象。你可以使用Three.js提供的加载器(Loader)来加载3D模型文件。完成加载后,你可以将模型添加到场景中,并设置其位置、旋转等属性。 最后,你可以根据需要添加光源、阴影效果、材质等来提高渲染效果。你可以通过创建Three.js的光源对象,如DirectionalLight或SpotLight,来模拟现实世界的光照。你可以使用Three.js的材质(Material)来定义模型的外观和反射属性,如颜色、贴图等。 通过以上步骤,你可以在Vue3应用中使用Three.js渲染室内地图。不过,请注意,使用Three.js进行复杂的渲染可能对性能有一定要求,你可能需要优化性能,如使用LOD(多级细分)模型、合并几何体等技术来提高性能并避免卡顿。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值