【rust/bevy】使用points构造ConvexMesh

这篇具有很好参考价值的文章主要介绍了【rust/bevy】使用points构造ConvexMesh。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

说在前面

  • 操作系统:win11
  • rust版本:rustc 1.77.0-nightly
  • bevy版本:0.12
  • github:这里

问题提出

  • three.js中,可以通过使用ConvexGeometry从给定的三维点集合生成凸包(Convex Hull)

    import { ConvexGeometry } from 'three/addons/geometries/ConvexGeometry.js';
    

    例如:

    const geometry = new ConvexGeometry( points );
    const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
    const mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );
    

    【rust/bevy】使用points构造ConvexMesh,Rust,rust,开发语言,游戏引擎

  • 但是在bevy中如何实现呢?

Rapier

  • 在当前bevy的版本中,并没有类似的实现,目前支持的shape也比three.js少:
    • Box
    • Capsule
    • Circle
    • Cube
    • Cylinder
    • Icosphere
    • Plane
    • Quad
    • RegularPolygon
    • Torus
    • UVSphere
  • 所以,如果要构造ConvexHull,只能借助第三方库(或者自己实现,可以参考three.js实现)
  • 这里我们借助一个物理库rapier来实现
  • 关于rapier
    这里

具体实现

  • 首先我们通过点集构造ConvexHullrapier可以直接完成这一步:

    let collider = Collider::convex_hull(&points);
    

    但是该方法构造的是一个Collider,实际上是无法直接当成Mesh使用的

  • 然后我们将其转换成ConvexPolyhedron

    let convex = c.as_convex_polyhedron().unwrap();
    
  • 该结构中包含一个凸包的所有属性,例如点、边、面等,事实上,它提供了一个方法,能够直接转换成TriangleMesh所需要的数据:

    impl ConvexPolyhedron {
        /// Discretize the boundary of this convex polyhedron as a triangle-mesh.
        pub fn to_trimesh(&self) -> (Vec<Point3<Real>>, Vec<[u32; 3]>) {
            let mut indices = Vec::new();
    
            for face in self.faces() {
                let i1 = face.first_vertex_or_edge;
                let i2 = i1 + face.num_vertices_or_edges;
                let first_id = self.vertices_adj_to_face()[i1 as usize] as u32;
    
                for idx in self.vertices_adj_to_face()[i1 as usize + 1..i2 as usize].windows(2) {
                    indices.push([first_id, idx[0] as u32, idx[1] as u32]);
                }
            }
    
            (self.points().to_vec(), indices)
        }
    }
    

    但是不包含normal数据,导致光照对其没有作用
    【rust/bevy】使用points构造ConvexMesh,Rust,rust,开发语言,游戏引擎

  • 所以我们需要自己实现一个相似的方法,首先我们来看看测试数据,实际上它有20个点,共12个面,每个面是一个正五边形,所以使用TriangleMesh来表达的话,一共是36个三角形

  • 再让我们来看看bevy中构造一个TriangleMesh需要哪些数据:

    fn create_simple_parallelogram() -> Mesh {
        // Create a new mesh using a triangle list topology, where each set of 3 vertices composes a triangle.
        Mesh::new(PrimitiveTopology::TriangleList)
            // 顶点数据
            .with_inserted_attribute(
                Mesh::ATTRIBUTE_POSITION,
                vec![[0.0, 0.0, 0.0], [1.0, 2.0, 0.0], [2.0, 2.0, 0.0], [1.0, 0.0, 0.0]]
            )
            // uv数据 在本文中我们并不需要
            .with_inserted_attribute(
                Mesh::ATTRIBUTE_UV_0,
                vec![[0.0, 1.0], [0.5, 0.0], [1.0, 0.0], [0.5, 1.0]]
            )
            // 法线
            .with_inserted_attribute(
                Mesh::ATTRIBUTE_NORMAL,
                vec![[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]
            )
            // 三角形的顶点索引
            .with_indices(Some(Indices::U32(vec![
                0, 3, 1,
                1, 3, 2
            ])))
    }
    
  • 对比我们需要的数据,以及to_trimesh方法,发现我们少了normal数据,不过这个数据在face中就有,那么所有条件就具备了

  • 完整代码

    let plist: Vec<f32> = vec![0., 3.568220853805542, 9.341723442077637, 5.773502826690674, 5.773502826690674, 5.773502826690674, -5.773502826690674, 5.773502826690674, 5.773502826690674, 3.568220853805542, 9.341723442077637, 0., -3.568220853805542, 9.341723442077637, 0., 9.341723442077637, 0., 3.568220853805542, 9.341723442077637, 0., -3.568220853805542, 5.773502826690674, 5.773502826690674, -5.773502826690674, 5.773502826690674, -5.773502826690674, -5.773502826690674, 0., -3.568220853805542, -9.341723442077637, 0., 3.568220853805542, -9.341723442077637, -5.773502826690674, -5.773502826690674, -5.773502826690674, -9.341723442077637, 0., -3.568220853805542, -5.773502826690674, 5.773502826690674, -5.773502826690674, -3.568220853805542, -9.341723442077637, 0., -5.773502826690674, -5.773502826690674, 5.773502826690674, -9.341723442077637, 0., 3.568220853805542, 0., -3.568220853805542, 9.341723442077637, 3.568220853805542, -9.341723442077637, 0., 5.773502826690674, -5.773502826690674, 5.773502826690674];
    let points: Vec<Vec3> = plist
        .array_chunks()
        .into_iter()
        .map(|&v: &[f32; 3]| Vec3::from_array(v))
        .collect();
    // 通过点集构造convex hull
    let collider = Collider::convex_hull(&points);
    if let Some(c) = collider {
        let convex = c.as_convex_polyhedron().unwrap();
        // 取convex hull的所有面
        let faces = convex.raw.faces();
        // 取点集
        let points = convex.raw.points();
        // 取映射关系
        let face_to_vertices = convex.raw.vertices_adj_to_face();
    	
        let mut positions = Vec::new();
        // 法向量 用于处理光照
        let mut normals = Vec::new();
        let mut indices = Vec::new();
        // 遍历所有的面
        for face in faces {
            let i1 = face.first_vertex_or_edge;
            let i2 = i1 + face.num_vertices_or_edges;
    
            for idx in i1..i2 {
                let point = points[face_to_vertices[idx as usize] as usize];
                // 重新构造点集 points是原始点集
                positions.push([point.x, point.y, point.z]);
                // 面上的所有点的朝向与面相同
                normals.push([face.normal.x, face.normal.y, face.normal.z]);
            }
    
            for idx in i1 + 1..i2 - 1 {
            	// 构造顶点索引
                indices.push([i1, idx as u32, idx + 1 as u32]);
            }
        }
    	// 构造Mesh
        let mesh = Mesh::new(PrimitiveTopology::TriangleList)
            .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
            .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
            .with_indices(Some(Indices::U32(indices.concat())));
    
        commands.spawn(PbrBundle {
            mesh: meshes.add(mesh),
            material: materials.add(Color::rgb_u8(124, 144, 255).into()),
            transform: Transform::from_xyz(0.0, 1., 0.0).with_scale(Vec3::new(0.1, 0.1, 0.1)),
            ..default()
        });
    }
    
  • 结果(gif)
    【rust/bevy】使用points构造ConvexMesh,Rust,rust,开发语言,游戏引擎文章来源地址https://www.toymoban.com/news/detail-810329.html

参考

  • ConvexGeometry

到了这里,关于【rust/bevy】使用points构造ConvexMesh的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Rust软件外包开发语言的特点

    Rust 是一种系统级编程语言,强调性能、安全性和并发性的编程语言,适用于广泛的应用领域,特别是那些需要高度可靠性和高性能的场景。下面和大家分享 Rust 语言的一些主要特点以及适用的场合,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公

    2024年02月12日
    浏览(47)
  • Rust 笔记:Rust 语言中哈希结构(哈希映射,HashMap)、集合(哈希集,HashSet)及其使用

    Rust 笔记 Rust 语言中映射(HashMap)与集合(HashSet)及其用法 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/130876735 【介绍】:本文介绍 Rust 中哈希结构相关概念及其使用。在 R

    2024年02月09日
    浏览(50)
  • 使用 Rust 开发一个微型游戏

    建立项目 实现 Game loop 不同的游戏模式 添加玩家 添加障碍和计分 汇总 为了让游戏流畅、顺滑的运行,需要使用 Game loop Game loop: 初始化窗口、图形和其它资源 每当屏幕刷新(通常是每秒 30、60或更多次),它都会运行 每次通过循环,它都会调用游戏的 tick() 函数 开始 - 配

    2024年02月06日
    浏览(34)
  • 使用Rust开发命令行工具

    生成二进制文件,将其扔到环境变量的path下即可~ 用rust打造实时天气命令行工具 [1] 找到合适的API 使用 该api [2] 如请求 api.openweathermap.org/data/2.5/weather?q=Beijingappid=your_key : 初始化项目coding 使用 cargo new rust_weather 初始化一个项目。 对于 cargo.toml 文件: 对于 src/main.rs 文件: 使用

    2024年02月11日
    浏览(37)
  • 使用Cargo国内镜像提升Rust开发效率

    Rust是一门现代化的系统编程语言,而Cargo则是Rust的官方包管理工具。在进行Rust项目开发时,由于网络原因,从Crates.io下载依赖可能会很慢。为了提高开发效率,我们可以配置Cargo使用国内的镜像源,以加速包的下载和构建过程。 步骤一:进入Cargo配置目录 打开终端或命令提

    2024年02月21日
    浏览(49)
  • 在win10上,配置 Rust 开发环境(使用 mingw64编译器) 和 idea 配置 Rust 插件

    2.1、编译器 mingw 与 visual studio 之间的选择 Rust 底层是依赖C/C++的 编译器,所以需要先安装C/C++编译环境。 Windows上C/C++ 的 编译器 有两种: 微软 的 Visual Studio (msvc) GNU 的 Mingw (gnu): 官网地址:https://www.mingw-w64.org/ Rust 默认使用的是 Visual Studio, 使用默认选项就能安装上,

    2024年02月02日
    浏览(50)
  • 【从零开始的rust web开发之路 一】axum学习使用

    第一章 axum学习使用 本职java开发,兼架构设计。空闲时间学习了rust,目前还不熟练掌握。想着用urst开发个web服务,正好熟悉一下rust语言开发。 目前rust 语言web开发相关的框架已经有很多,但还是和java,go语言比不了。 这个系列想完整走一遍web开发,后续有时间就出orm,还

    2024年02月12日
    浏览(52)
  • 在Ubuntu-12.04环境下使用新的Rust开发工具

    在老旧的系统环境下使用Rust开发工具 笔者的一台硬件资源紧张的旧电脑安装了Ubuntu-12.04,希望在其上运行比较新的Rust开发工具,但却发现其因glibc较老,不能正常运行cargo工具,结果如下: 如上, cargo 可执行文件对 glibc 最低版本要求是 GLIBC_2.17 ,而Ubuntu-12.04系统的 glibc 版

    2024年02月20日
    浏览(41)
  • 【rust语言】rust多态实现方式

    学习rust当中遇到了这个问题,记录一下,不对地方望指正 多态是面向对象程序设计中的一个重要概念,指同一个行为或操作在不同实例上具有不同的行为或结果。简单来说,多态就是指同一种类型的对象,在不同的上下文中有不同的行为。多态性使得程序可以更加灵活、可

    2024年02月11日
    浏览(46)
  • Rust UI开发(一):使用iced构建UI时,如何在界面显示中文字符

    注:此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库,用于为rust语言程序构建UI界面。   iced的基本逻辑是: UI交互产生消息message,message传递给后台的update,在这个函数中编写逻辑,然后通过View函数更新UI。 Take the result of our view logic and layout its widgets. 获取视图逻

    2024年02月03日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包