初见物理引擎库Cannon.js:与Cesium的整合

Cesium入门之六:Cesium加载影像图层(ArcGIS、Bing、Mapbox、高德地图、腾讯地图、天地图等各类影像图) 详细介绍了Cesium加载影像图层的类、方法和步骤,举例说明加载ArcGIS地图、Bing地图、Mapbox地图、高德地图、腾讯地图、天地图等各类影像图的加载方法 阅读详情

0 前言

本文是“初见物理引擎库Cannon.js”系列的第四篇文章,在本文中主要讲解Cannon.js和Cesium的整合方法。

1 在线地址

[ Live Demo ]:Cannon - Cesium (syzdev.cn)

在这里插入图片描述

2 整合步骤

2.1 Cesium和Three的整合

由于Cannon.js是要基于Three来使用的,因此第一步要完成Cesium和Three的整合,详见:最新的Cesium和Three的整合方法。

2.2 Cannon.js的基本使用

可以参考作者之前的两篇文章:

  1. 初见物理引擎库Cannon.js:基本使用;
  2. 初见物理引擎库Cannon.js:使用dat.gui修改物体属性

这两篇文章中包含详细的说明和完整代码,本文中不再赘述。

2.3 注意事项

根据 最新的Cesium和Three的整合方法 ,所有的Three.js Mesh都需要转换成_3DObject对象:

function _3DObject() {
  this.threeMesh = null // Three.js 3DObject.mesh
  this.minWGS84 = null // location bounding box
  this.maxWGS84 = null
}

再将_3DObject对象添加到_3Dobjects数组中,并在每次renderThreeObj()方法中更新Mesh的位置,但问题在于这种方法是针对于静态物体的,对于物理引擎来说,需要实时更新物体的位置和旋转,见 初见物理引擎库Cannon.js:基本使用:

// 更新MeshBodyToUpdate中的Mesh和Body,使其位置和旋转同步
for (const object of MeshBodyToUpdate) {
  object.mesh.position.copy(object.body.position)
  object.mesh.quaternion.copy(object.body.quaternion)
}

物理引擎Cannon.js计算的位置和旋转是基于Three.js的坐标的,因此若将MeshBodyToUpdate中的动态物体也添加到_3Dobjects中,那么每次在renderThreeObj()方法中更新Mesh的位置就不是在Cesium场景下的正确位置。

解决该问题,可以在每次“更新MeshBodyToUpdate中的Mesh和Body,使其位置和旋转同步”操作之前,添加一个位置转换方法,类似于renderThreeObj()方法,先将物理引擎计算的位置转换成Cesium坐标下的位置,再进行位置和旋转的同步。

由于作者没有深入研究该问题,这里提供的思路仅为抛砖引玉。因此在示例程序中,并没有将Mesh添加到_3Dobjects数组中,相当于在renderThreeObj()方法中下面这段代码是没有被执行的:

// Configure Three.js meshes to stand against globe center position up direction
for (let id in _3Dobjects) {
  minWGS84 = _3Dobjects[id].minWGS84
  maxWGS84 = _3Dobjects[id].maxWGS84
  // convert lat/long center position to Cartesian3
  let center = Cesium.Cartesian3.fromDegrees(
    (minWGS84[0] + maxWGS84[0]) / 2,
    (minWGS84[1] + maxWGS84[1]) / 2
  )
  // get forward direction for orienting model
  let centerHigh = Cesium.Cartesian3.fromDegrees(
    (minWGS84[0] + maxWGS84[0]) / 2,
    (minWGS84[1] + maxWGS84[1]) / 2,
    1
  )
  // use direction from bottom left to top left as up-vector
  let bottomLeft = cartToVec(
    Cesium.Cartesian3.fromDegrees(minWGS84[0], minWGS84[1])
  )
  let topLeft = cartToVec(
    Cesium.Cartesian3.fromDegrees(minWGS84[0], maxWGS84[1])
  )
  let latDir = new THREE.Vector3().subVectors(bottomLeft, topLeft).normalize()
  // configure entity position and orientation
  _3Dobjects[id].threeMesh.position.copy(center)
  _3Dobjects[id].threeMesh.lookAt(centerHigh.x, centerHigh.y, centerHigh.z)
  _3Dobjects[id].threeMesh.up.copy(latDir)
}

示例程序中是通过地球半径来确定Three.js物体在Cesium坐标中的位置的,虽然现实中地球是一个不规则的椭球:
在这里插入图片描述
但是在Cesium中将地球模拟为一个规则的球体,球体的球心就是坐标原点,在 最新的Cesium和Three的整合方法 中,Three的坐标原点就是Cesium地球的球心,可以添加AxesHelper查看坐标轴:

// 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
const axesHelper = new THREE.AxesHelper(64410000)
three.scene.add(axesHelper)

[ Live Demo ]:Cannon - Cesium-axes (syzdev.cn)

在这里插入图片描述
因此把物体的坐标按照坐标轴进行调整,以地球半径作为长度,即可将物体置于地表,如:

let cannonGroundBody = new CANNON.Body({
  mass: 0,
  position: new CANNON.Vec3(0, 6371000, 0), // 置于地表Y轴
  shape: cannonGroundShape,
  material: cannonDefaultMaterial,
})

在这里插入图片描述

3 完整代码

cesium-docs-demo - syzdev

let three = {
  renderer: null,
  camera: null,
  scene: null,
}

let cesium = {
  viewer: null,
}

let cannon = {
  world: null,
}
const cannonDefaultMaterial = new CANNON.Material()
let cannonDefaultCantactMaterial = null // 关联材质
let cannonSphereBody = null // 小球
let threeSphereMaterial = null // 小球材质
let friction = 0.5
let restitution = 0.7
const MeshBodyToUpdate = []

let minWGS84 = [115.23, 39.55];
let maxWGS84 = [116.23, 41.55];

let cesiumContainer = document.getElementById('cesiumContainer')
let ThreeContainer = document.getElementById('ThreeContainer')
let _3Dobjects = [] // Could be any Three.js object mesh

function _3DObject() {
  this.threeMesh = null // Three.js 3DObject.mesh
  this.minWGS84 = null // location bounding box
  this.maxWGS84 = null
}

function initCannon() {
  cannon.world = new CANNON.World()
  cannon.world.gravity.set(0, -90000.8, 0)
  cannon.world.broadphase = new CANNON.NaiveBroadphase()
  cannonDefaultCantactMaterial = new CANNON.ContactMaterial(
    cannonDefaultMaterial,
    cannonDefaultMaterial,
    {
      friction,
      restitution,
    }
  )
  cannon.world.addContactMaterial(cannonDefaultCantactMaterial)
}

function addPlane() {
  // 添加CannonPlane地板
  let cannonGroundShape = new CANNON.Plane()
  let cannonGroundBody = new CANNON.Body({
    mass: 0,
    position: new CANNON.Vec3(0, 6371000, 0),
    shape: cannonGroundShape,
    material: cannonDefaultMaterial,
  })
  cannonGroundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2)
  cannon.world.add(cannonGroundBody)
  // 添加ThreePlaneGeometry地板
  let threeGroundGeometry = new THREE.PlaneGeometry(20, 20, 32)
  let threeGroundMaterial = new THREE.MeshLambertMaterial({
    color: 0xf5f5f5,
    side: THREE.DoubleSide,
  })
  let threeGroundMesh = new THREE.Mesh(threeGroundGeometry, threeGroundMaterial)
  threeGroundMesh.rotation.x = -Math.PI / 2
  threeGroundMesh.position.set(0, 6371000, 0)
  threeGroundMesh.receiveShadow = true
  threeGroundMesh.scale.set(2500, 2500, 2500)
  three.scene.add(threeGroundMesh)
}

function addShpere() {
  // 添加CannonSphere小球
  let cannonSphereShape = new CANNON.Sphere(1000)
  cannonSphereBody = new CANNON.Body({
    mass: 5,
    shape: cannonSphereShape,
    position: new CANNON.Vec3(0, 6420000, 0),
    material: cannonDefaultMaterial,
  })
  cannon.world.add(cannonSphereBody)
  // 添加ThreeSphereGeometry小球
  let threeSphereGeometry = new THREE.SphereGeometry(1, 32, 32)
  threeSphereMaterial = new THREE.MeshStandardMaterial({ color: 0xFFB6C1 })
  let threeSphereMesh = new THREE.Mesh(threeSphereGeometry, threeSphereMaterial)
  threeSphereMesh.castShadow = true
  threeSphereMesh.scale.set(1000, 1000, 1000)
  three.scene.add(threeSphereMesh)
  // 添加到MeshBodyToUpdate
  MeshBodyToUpdate.push({
    body: cannonSphereBody,
    mesh: threeSphereMesh,
  })
}

function initCesium() {
  cesium.viewer = new Cesium.Viewer(cesiumContainer, {
    useDefaultRenderLoop: false,
    selectionIndicator: false,
    homeButton: false,
    sceneModePicker: false,
    infoBox: false,
    navigationHelpButton: false,
    navigationInstructionsInitiallyVisible: false,
    animation: false,
    timeline: false,
    fullscreenButton: false,
    allowTextureFilterAnisotropic: false,
    baseLayerPicker: false,

    // contextOptions: {
    //   webgl: {
    //     alpha: false,
    //     antialias: true,
    //     preserveDrawingBuffer: true,
    //     failIfMajorPerformanceCaveat: false,
    //     depth: true,
    //     stencil: false,
    //     anialias: false,
    //   },
    // },

    targetFrameRate: 60,
    // resolutionScale: 0.1,
    orderIndependentTranslucency: true,
    geocoder: false,
    imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
      url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer',
    }),
    automaticallyTrackDataSourceClocks: false,
    // creditContainer : "hidecredit", // Cannot read properties of null (reading 'appendChild')
    dataSources: null,
    clock: null,
    terrainShadows: Cesium.ShadowMode.DISABLED,
  })
  cesium.viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(
      90.015299, 0.000161, 150000
    ),
  })
}

function initDatGui() {
  let gui = new dat.GUI()

  let controls = {
    resetBall: () => {
      cannonSphereBody.position.set(0, 6420000, 0) // 重置小球位置
      cannonSphereBody.velocity.set(0, 0, 0) // 重置小球速度
      cannonDefaultCantactMaterial.friction = friction // 修改摩擦力
      cannonDefaultCantactMaterial.restitution = restitution // 修改弹性系数
    },
    friction,
    restitution,
    color: threeSphereMaterial.color.getStyle()
  }

  gui.add(controls, 'resetBall').name('重置小球下落')
  gui.add(controls, 'friction', 0, 2).name('摩擦力').onChange((e) => {
    friction = e
  })
  gui.add(controls, 'restitution', 0, 2).name('弹性系数').onChange((e) => {
    restitution = e
  })
  gui.addColor(controls, 'color').name('小球颜色').onChange((e) => {
    threeSphereMaterial.color.setStyle(e)
  })
}

function initThree() {
  let fov = 45
  let width = window.innerWidth
  let height = window.innerHeight
  let aspect = width / height
  let near = 50
  let far = 10 * 1000 * 10000
  three.scene = new THREE.Scene()
  three.camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
  three.renderer = new THREE.WebGLRenderer({ alpha: true })
  three.renderer.shadowMap.enabled = true
  ThreeContainer.appendChild(three.renderer.domElement)
  // 创建环境光
  let Amlight = new THREE.AmbientLight(0x444444, 1)
  three.scene.add(Amlight)
  // 创建点光源
  let spotLight = new THREE.SpotLight(0x999999, 1)
  spotLight.position.set(0, 6441000, -20000)
  spotLight.castShadow = true
  spotLight.shadow.camera.near = 1
  spotLight.shadow.camera.far = 30000000
  spotLight.shadow.camera.fov = 90
  three.scene.add(spotLight)
  let spotLightHelper = new THREE.SpotLightHelper(spotLight)
  three.scene.add(spotLightHelper)
}

function renderCesium() {
  cesium.viewer.render()
}

function renderThreeObj() {
  // register Three.js scene with Cesium
  three.camera.fov = Cesium.Math.toDegrees(cesium.viewer.camera.frustum.fovy) // ThreeJS FOV is vertical
  // three.camera.updateProjectionMatrix();
  let cartToVec = function (cart) {
    return new THREE.Vector3(cart.x, cart.y, cart.z)
  }

  // Configure Three.js meshes to stand against globe center position up direction
  for (let id in _3Dobjects) {
    minWGS84 = _3Dobjects[id].minWGS84
    maxWGS84 = _3Dobjects[id].maxWGS84
    // convert lat/long center position to Cartesian3
    let center = Cesium.Cartesian3.fromDegrees(
      (minWGS84[0] + maxWGS84[0]) / 2,
      (minWGS84[1] + maxWGS84[1]) / 2
    )
    // get forward direction for orienting model
    let centerHigh = Cesium.Cartesian3.fromDegrees(
      (minWGS84[0] + maxWGS84[0]) / 2,
      (minWGS84[1] + maxWGS84[1]) / 2,
      1
    )
    // use direction from bottom left to top left as up-vector
    let bottomLeft = cartToVec(
      Cesium.Cartesian3.fromDegrees(minWGS84[0], minWGS84[1])
    )
    let topLeft = cartToVec(
      Cesium.Cartesian3.fromDegrees(minWGS84[0], maxWGS84[1])
    )
    let latDir = new THREE.Vector3().subVectors(bottomLeft, topLeft).normalize()
    // configure entity position and orientation
    _3Dobjects[id].threeMesh.position.copy(center)
    _3Dobjects[id].threeMesh.lookAt(centerHigh.x, centerHigh.y, centerHigh.z)
    _3Dobjects[id].threeMesh.up.copy(latDir)
  }
  // Clone Cesium Camera projection position so the
  // Three.js Object will appear to be at the same place as above the Cesium Globe
  three.camera.matrixAutoUpdate = false
  let cvm = cesium.viewer.camera.viewMatrix
  let civm = cesium.viewer.camera.inverseViewMatrix

  three.camera.lookAt(0, 0, 0)

  three.camera.matrixWorld.set(
    civm[0],
    civm[4],
    civm[8],
    civm[12],
    civm[1],
    civm[5],
    civm[9],
    civm[13],
    civm[2],
    civm[6],
    civm[10],
    civm[14],
    civm[3],
    civm[7],
    civm[11],
    civm[15]
  )

  three.camera.matrixWorldInverse.set(
    cvm[0],
    cvm[4],
    cvm[8],
    cvm[12],
    cvm[1],
    cvm[5],
    cvm[9],
    cvm[13],
    cvm[2],
    cvm[6],
    cvm[10],
    cvm[14],
    cvm[3],
    cvm[7],
    cvm[11],
    cvm[15]
  )

  let width = cesiumContainer.clientWidth
  let height = cesiumContainer.clientHeight

  let aspect = width / height
  three.camera.aspect = aspect
  three.camera.updateProjectionMatrix()
  three.renderer.setSize(width, height)
  three.renderer.clear()
  three.renderer.render(three.scene, three.camera)
}

function loop() {
  cannon.world.step(1.0 / 60.0)

  // 更新MeshBodyToUpdate中的Mesh和Body,使其位置和旋转同步
  for (const object of MeshBodyToUpdate) {
    object.mesh.position.copy(object.body.position)
    object.mesh.quaternion.copy(object.body.quaternion)
  }

  requestAnimationFrame(loop)
  renderCesium()
  renderThreeObj()
}

initCesium() // Initialize Cesium renderer
initThree() // Initialize Three.js renderer
initCannon()
addShpere()
addPlane()
initDatGui()
loop() // Looping renderer
Threejs + CannonJS物理引擎 第一个案例教程 Body。 阅读详情

相关推荐

使用 Cannon.js 实现物理模拟效果

Three.js 场景搭建:从初始化场景到添加光源,为物理模拟提供了直观的三维展示平台。Cannon.js 物理世界创建:学会了定义刚体、设置物理属性,并实现物体的碰撞和运动模拟。物理与渲染的同步:理解了如何将物理引擎的计算结果同步到三维模型中,实现了视觉与物理效果的一致性。

1349

Three.js--》探寻Cannon.js构建震撼的3D物理交互体验(一)

我们用three.js可以绘制出各种酷炫的画面,但是当我们想要一个更加真实的物理效果的话,这个时候我们就需要一个物理的库,接下来我们就讲解一下今天要学习的canon,它可以给我们提供一个更加真实的物理效果,像物体的张力、摩擦力、拉伸、反弹等等各种真实的物理效果。该库都能够有一个非常好的模拟。

ztK63LrD的博客 4007

BIM轻量化引擎选型:Unity与Three.js技术对比与实战指南

在建筑信息模型(BIM)与Web3D可视化领域,实现高精度模型在浏览器端的流畅展示是核心技术挑战。其原理在于通过几何压缩、数据剥离与LOD(细节层次)生成等技术,将庞大的原始模型转换为适合网络传输与实时渲染的轻量化格式。这项技术的核心价值在于打通了BIM数据从设计端到Web端、移动端协同应用的关键路径,极大地拓展了其在数字孪生、智慧城市及在线审阅等场景的应用范围。面对这一需求,技术选型成为项目成败的关键,尤其是Unity与Three.js这两大主流渲染方案。Unity凭借其强大的图形引擎与成熟的工具链,在需

weixin_34327223的博客 1435

Cannon.js

详细内容请访问 Cannon.js 官方文档 关于 Cannon.js Web的轻量级3D物理 本身只有398KB Cannon.js的制作者受three.js和ammo.js的启发,并由于缺乏支持浏览器的物理引擎,最终cannon.js出现了。Cannon.js物理引擎包括简单的碰撞检测,各种体形,接触,摩擦和约束。 Cannon.js是用于游戏的刚体模拟库。程序员可以使用它来使他们的游戏对...

木·本的博客 7829

CesiumJS【Pro】- #15模型爆炸

cesium 飞机爆炸效果

AlanL的专栏 2152

前端3D物理引擎-Cannon.js项目实践指南

Cannon.js是一个轻量级的、易于使用的3D物理引擎,专为WebGL应用设计。它适用于各种复杂度的物理模拟,从简单的碰撞检测到大规模的刚体模拟,Cannon.js都能提供高效的解决方案。该引擎主要利用基于约束的方法来求解物理问题,并且设计简洁,易于扩展,使得开发者能够在保持性能的同时增加自定义的功能。本章将带你了解Cannon.js的核心概念和如何快速开始使用这个库。

weixin_36235398的博客 1742

Cannon.js -- 3d物理引擎

本篇将介绍的基础使用,并用与写一个简单的demo 在使用Cannon.js时通常会与其它3d库同时使用,因为Cannon.js就和后端差不多只负责数据 3d库则负责展示效果。我们这里将使用three.js来进行演示 首先我们需要下载Cannon.js 我们可以直接下载js文件或者使用CDN也可以使用npm直接安装相关示例 2.由于Cannonjs物理引擎库他只是负责数据而不负责显示,这时我们需要使用其它3d库来进行数据效果的显示 相关代码: 最后我们将Cannonjs代码与three.js代码合并

z1783883121的博客 6690

cannonjs.org:Cannon.js 网站

cannonjs.org

初见物理引擎库Cannon.js:基本使用

物理引擎库Cannon.js的基本使用方法

syzdev的博客 1万+

银河麒麟V10系统下VLC播放器安装全攻略(附3.0.9.2版本离线包下载)

本文详细介绍了在银河麒麟V10操作系统无网络环境下,从零开始编译安装VLC 3.0.9.2播放器的完整攻略。通过构建本地YUM仓库解决依赖问题,提供离线资源包下载,并逐步指导完成编译环境配置、软件编译与安装,帮助用户在国产麒麟系统上成功部署强大的多媒体播放能力。

a2b3c4d5e的博客 1201

【上海大学计算机组成原理实验报告】一、数据传送实验

将58H写入A寄存器//将6BH写入W寄存器//将C3H写入R1寄存器//将C3H写入R1寄存器//了解实验仪器数据总线的控制方式//掌握数据传送的基本原理//掌握各寄存器的结构、工作原理及其控制方法//数据传送实验

HackerKevon的博客 3509

【亲测免费】 Cannon.js: 轻量级3D物理引擎

Cannon.js是一个轻量级的JavaScript 3D 物理引擎,用于WebGL应用程序和游戏开发。它提供了一个简单易用的API,支持多种物理效果,如刚体、弹性碰撞、摩擦力等,让开发者可以轻松地在Web浏览器中创建逼真的物理模拟场景。 ## 用途 Cannon.js主要用于创建基于WebGL的应用程序和游戏,其中需要进行复杂的3D物理模拟。例如: - 3D游戏中的角色和物体运动。 - 建...

gitblog_00022的博客 836

零差云控关节模组:EtherCAT+preempt-RT实现微秒级同步

关节模组是协作机器人、外骨骼与高精度服务机器人的核心执行单元,其性能瓶颈常在于多轴运动的时序一致性与实时闭环能力。实现‘零差’同步依赖于确定性通信(如EtherCAT)与硬实时操作系统支持(如Linux preempt-RT),前者保障指令与状态在微秒级时间戳下全局对齐,后者消除内核调度抖动,使PID控制、电流采样、编码器反馈等关键路径具备纳秒级可预测性。技术价值体现在相位偏差<±0.01°、端到端控制周期稳定1ms、连续运行温漂<±1.2℃等工程指标,广泛应用于力控装配、康复训练、远程遥操作等对动态精度与

weixin_34192816的博客 1197

Cesium 和 Three.js 集成的官方教程的中文翻译

这篇文章介绍了如何将 Cesium 和 Three.js 集成到一起。通过将两个框架分为不同的视图层,并将它们的控制器组合在同一个坐标系中,可以轻松地将两个渲染引擎集成到一个主场景中。这篇文章还提供了代码示例。

BI 1760

如何利用 多 张 GPU 高效运行 Ollama

通过以上步骤,我们可以确保系统尽可能地利用所有 多张GPU 来运行 Ollama。如果在配置过程中遇到问题,建议查阅 Ollama 的官方文档,确认其是否支持多 GPU 并行计算,或者对系统性能进行进一步的优化。充分利用多 GPU 的并行计算能力,可以显著提升 Ollama 的运行效率,加快模型的推理和训练速度。希望本文能帮助你顺利实现 多张 GPU 的高效利用。

weixin_44997264的博客 8031

Flink项目基础配置指南

在大数据处理领域,Apache Flink凭借强大的实时流处理和批处理能力,成为众多开发者的首选工具。在日常工作中,开发Flink Jar任务是常见需求,但每次都需重复配置日志、梳理pom依赖、设置打包插件等,流程繁琐且易出错。为提升开发效率,减少重复劳动,将这些基础配置进行整理归纳十分必要。本文将围绕Flink项目的本地日志配置、pom依赖及插件配置展开详细介绍,为开发者提供一套可直接复用的基础配置方案,助力Flink项目高效开发。在Flink项目中,日志是了解任务运行状态、排查问题的重要依据。本地日志配

qq_42773076的博客 1210

5个常用的物理仿真JavaScript插件

以上介绍的是五个常用的 JavaScript 物理引擎插件。每个库都有其独特的优势和适用场景。如果你需要一个功能全面且成熟的 2D 物理引擎,可以选择 Matter.js;如果你正在开发复杂的游戏并需要 3D 物理仿真,Cannon.js 是一个很好的选择;对于需要高性能和复杂物理仿真的 2D 游戏,p2.js 和 Box2D 都是非常好的选项;而如果你正在寻找一个全面的游戏开发框架,Phaser 提供了丰富的功能,包括物理引擎。选择哪个库取决于你的具体需求和偏好。

大剑师兰特的GIS世界 2400

STM32F4使用CUBEMX ADC定时采样+DMA

STM32、FFT、ADC、TIM

m0_62379750的博客 4222

使用cannon.js开发具有物理特性的汽车

cannon.js cannon.js是一个Web端的轻量级物理引擎,其官方网站提供了大量的例子供我们学习。使用cannon.js搭配three.js或Babylon.js,可以开发出具有物理效果的3D Web应用程序。 RaycastVehicle RaycastVehicle是cannon.js提供了一个车辆对象。并且官方给我们提供了demo。 何为Raycast 为何称为RaycastVehicle呢?这与该对象的物理模拟原理有关系。该对象使用刚体(CANNON.Body)作为车身,从刚体的四个角处向

LiSharpsong的博客 3399

【agent实战教程】OpenClaw多个agent一文通

一个合格的独立agent,必须具备6个完全独立的专属组件独立组件路径规则核心要求不独立的严重后果唯一agentId配置文件中全局唯一,不能重复,建议用英文+数字,不要有特殊字符agent配置冲突,消息派单错误,会话串线独立工作区(workspace)建议每个agent一个独立文件夹,不要共用人设、记忆、规则混在一起,agent人设崩塌,对话串线独立状态目录(agentDir)固定系统自动生成,绝对禁止多个agent复用同一个agentDir。

海兰 649

【华为OD机试真题 新系统】1021、API请求日志去重分析 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)

【华为OD机试真题 新系统】1021、API请求日志去重分析 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS) 华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2026e卷,od机试,2026E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2026华为od,如何备

KJ.JK 145

分享three.js和cannon.js构建Web 3D场景

这个集合的目标是提供一组基本的、有指导意义的示例,介绍Three.js中的各种功能。每个页面的源代码都包含详细的注释。

通达的博客 3013

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

cannon.js

cannon.js官网:http://www.cannonjs.org/ 使用初衷: 开发微信3d小游戏,使用three.js做3d渲染,某些情况需要物理引擎。微信对游戏代码大小有限制,4M。虽然许多教程推荐Physijs,该引擎基于ammo.js,对three.js进行了封装,易用,但是在微信小游戏中,需要修改源码进行适配,适配运行时一般的手机不是一般得卡(未细研究,估计是由于该引擎使用we...

weixin_42811951的博客 4855

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

浏览器也可以支持物理引擎?Cannon.js了解一下

游戏开发中必须了解的物理引擎,碰撞效果,外置api,一篇文章轻松搞定

2501_90625062的博客 1363

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

three.js应用cannon物理引擎设置物体的相互作用

Cannon.js是一个基于JavaScript的,可以用于。它提供了一系列的物理模拟功能,包括等。Cannon.js 的Cannon.js 是一个功能强大、灵活且易于使用的 3D 物理引擎,它可以帮助开发者轻松实现真实世界中的物理效果,并在浏览器中展示出来。无论是游戏开发还是模拟应用程序,Cannon.js 都是一个优秀的选择。这个示例展示了如何使用Cannon.js和Three.js实现鼠标拾取功能。鼠标拾取是指通过鼠标点击来选择和交互3D场景中的物体。

jieyucx的博客 2493

cannon.js_如何使用Cannon.js和Three.js创建基于物理的3D布

cannon.jsView demo 查看演示Download Source 下载源Following my previous experiment where I’ve showed you how to build a 3D physics-based menu, let’s now take a look at how to turn an image...

culiao9310的博客 1424
上一篇: 初见物理引擎库Cannon.js:CannonDebugRenderer的基本使用
下一篇: 三维文件格式知多少
syzdev
博客等级 码龄9年 852粉丝 149原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值