├── .cargo └── config.toml ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── ci.yaml ├── .gitignore ├── .gitmodules ├── .mergify.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── clippy.toml ├── deny.toml ├── images └── example-ball.png ├── physx-sys ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── LICENSE-APACHE ├── LICENSE-BSD ├── LICENSE-MIT ├── README.md ├── build.rs ├── examples │ └── ball.rs ├── make-sources.sh ├── migration-4-5.md ├── pxbind │ ├── Cargo.toml │ ├── src │ │ ├── consumer.rs │ │ ├── consumer │ │ │ ├── enums.rs │ │ │ ├── functions.rs │ │ │ ├── record.rs │ │ │ └── templates.rs │ │ ├── dump.rs │ │ ├── generator.rs │ │ ├── generator │ │ │ ├── comment.rs │ │ │ ├── enums.rs │ │ │ ├── functions.rs │ │ │ └── record.rs │ │ ├── lib.rs │ │ └── main.rs │ └── tests │ │ ├── data │ │ ├── all_the_things.h │ │ ├── enum │ │ │ ├── flags.h │ │ │ ├── i32.h │ │ │ ├── simple.h │ │ │ └── u32.h │ │ ├── functions │ │ │ ├── constructors.h │ │ │ ├── destructors.h │ │ │ ├── functions.h │ │ │ └── methods_complex.h │ │ └── record │ │ │ ├── abstract.h │ │ │ ├── complex.h │ │ │ ├── ptr_only.h │ │ │ ├── ref_fields.h │ │ │ └── templates.h │ │ ├── enums.rs │ │ ├── functions.rs │ │ ├── methods.rs │ │ ├── records.rs │ │ ├── snapshots │ │ ├── enums__flags.snap │ │ ├── enums__i32.snap │ │ ├── enums__simple.snap │ │ ├── enums__u32.snap │ │ ├── functions__plain_functions-2.snap │ │ ├── functions__plain_functions.snap │ │ ├── methods__constructors-2.snap │ │ ├── methods__constructors.snap │ │ ├── methods__destructor-2.snap │ │ ├── methods__destructor.snap │ │ ├── methods__methods_complex-2.snap │ │ ├── methods__methods_complex.snap │ │ ├── records__abstract_-2.snap │ │ ├── records__abstract_-3.snap │ │ ├── records__abstract_.snap │ │ ├── records__complex-2.snap │ │ ├── records__complex-3.snap │ │ ├── records__complex.snap │ │ ├── records__ptr_only-2.snap │ │ ├── records__ptr_only-3.snap │ │ ├── records__ptr_only.snap │ │ ├── records__ref_fields-2.snap │ │ ├── records__ref_fields-3.snap │ │ ├── records__ref_fields.snap │ │ ├── records__simple_templates-2.snap │ │ ├── records__simple_templates-3.snap │ │ ├── records__simple_templates.snap │ │ ├── records__templates-2.snap │ │ ├── records__templates-3.snap │ │ ├── records__templates.snap │ │ ├── structgen__all_the_things-2.snap │ │ ├── structgen__all_the_things-3.snap │ │ ├── structgen__all_the_things.snap │ │ ├── structgen__many_things-2.snap │ │ ├── structgen__many_things-3.snap │ │ └── structgen__many_things.snap │ │ ├── structgen.hpp │ │ └── structgen.rs ├── release.toml ├── sources │ ├── common │ ├── cooking │ ├── cooking_convex │ ├── core │ ├── extensions │ ├── extensions_binary │ ├── extensions_serialization │ ├── extensions_tet │ ├── extensions_xml │ ├── fastxml │ ├── foundation │ ├── foundation_unix │ ├── foundation_windows │ ├── geomutils │ ├── geomutils_ccd │ ├── geomutils_common │ ├── geomutils_contact │ ├── geomutils_convex │ ├── geomutils_cooking │ ├── geomutils_distance │ ├── geomutils_gjk │ ├── geomutils_hf │ ├── geomutils_intersection │ ├── geomutils_mesh │ ├── geomutils_pcm │ ├── geomutils_sweep │ ├── lowlevel_pipeline │ ├── lowlevel_software │ ├── lowlevelaabb │ ├── lowleveldynamics │ ├── physxcharacterkinematic │ ├── pvd │ ├── scenequery │ ├── simulationcontroller │ ├── task │ ├── vehicle │ └── vehicle_metadata └── src │ ├── generated │ ├── unix │ │ ├── structgen.rs │ │ └── structgen_out.hpp │ └── x86_64-pc-windows-msvc │ │ ├── structgen.rs │ │ └── structgen_out.hpp │ ├── lib.rs │ ├── physx_api.cpp │ ├── physx_generated.hpp │ ├── physx_generated.rs │ └── structgen │ ├── structgen.cpp │ └── structgen.hpp ├── physx ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples │ ├── assert_handler.rs │ ├── ball_physx.rs │ ├── error_callback.rs │ └── profiler.rs ├── migration-4-5.md ├── release.toml ├── src │ ├── actor.rs │ ├── aggregate.rs │ ├── articulation.rs │ ├── articulation_cache.rs │ ├── articulation_joint_reduced_coordinate.rs │ ├── articulation_link.rs │ ├── articulation_reduced_coordinate.rs │ ├── base.rs │ ├── bvh.rs │ ├── constraint.rs │ ├── controller.rs │ ├── controller_manager.rs │ ├── convex_mesh.rs │ ├── cooking.rs │ ├── foundation.rs │ ├── geometry.rs │ ├── height_field.rs │ ├── lib.rs │ ├── material.rs │ ├── math.rs │ ├── math │ │ ├── glam.rs │ │ ├── quat.rs │ │ ├── transform.rs │ │ └── vec3.rs │ ├── owner.rs │ ├── physics.rs │ ├── physics │ │ ├── assert_handler.rs │ │ ├── error_callback.rs │ │ └── profiler.rs │ ├── prelude.rs │ ├── pruning_structure.rs │ ├── rigid_actor.rs │ ├── rigid_body.rs │ ├── rigid_dynamic.rs │ ├── rigid_static.rs │ ├── scene.rs │ ├── shape.rs │ ├── simulation_event_callback.rs │ ├── traits.rs │ ├── traits │ │ ├── class.rs │ │ ├── descriptor.rs │ │ └── user_data.rs │ ├── triangle_mesh.rs │ └── visual_debugger.rs └── tests │ └── bug-180.rs └── regen.sh /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(all())'] 2 | rustflags = [ 3 | # BEGIN - Embark standard lints v6 for Rust 1.55+ 4 | # do not change or add/remove here, but one can add exceptions after this section 5 | # for more info see: 6 | "-Dunsafe_code", 7 | "-Wclippy::all", 8 | "-Wclippy::await_holding_lock", 9 | "-Wclippy::char_lit_as_u8", 10 | "-Wclippy::checked_conversions", 11 | "-Wclippy::dbg_macro", 12 | "-Wclippy::debug_assert_with_mut_call", 13 | "-Wclippy::doc_markdown", 14 | "-Wclippy::empty_enum", 15 | "-Wclippy::enum_glob_use", 16 | "-Wclippy::exit", 17 | "-Wclippy::expl_impl_clone_on_copy", 18 | "-Wclippy::explicit_deref_methods", 19 | "-Wclippy::explicit_into_iter_loop", 20 | "-Wclippy::fallible_impl_from", 21 | "-Wclippy::filter_map_next", 22 | "-Wclippy::flat_map_option", 23 | "-Wclippy::float_cmp_const", 24 | "-Wclippy::fn_params_excessive_bools", 25 | "-Wclippy::from_iter_instead_of_collect", 26 | "-Wclippy::if_let_mutex", 27 | "-Wclippy::implicit_clone", 28 | "-Wclippy::imprecise_flops", 29 | "-Wclippy::inefficient_to_string", 30 | "-Wclippy::invalid_upcast_comparisons", 31 | "-Wclippy::large_digit_groups", 32 | "-Wclippy::large_stack_arrays", 33 | "-Wclippy::large_types_passed_by_value", 34 | "-Wclippy::let_unit_value", 35 | "-Wclippy::linkedlist", 36 | "-Wclippy::lossy_float_literal", 37 | "-Wclippy::macro_use_imports", 38 | "-Wclippy::manual_ok_or", 39 | "-Wclippy::map_err_ignore", 40 | "-Wclippy::map_flatten", 41 | "-Wclippy::map_unwrap_or", 42 | "-Wclippy::match_on_vec_items", 43 | "-Wclippy::match_same_arms", 44 | "-Wclippy::match_wild_err_arm", 45 | "-Wclippy::match_wildcard_for_single_variants", 46 | "-Wclippy::mem_forget", 47 | "-Wclippy::mismatched_target_os", 48 | "-Wclippy::missing_enforced_import_renames", 49 | "-Wclippy::mut_mut", 50 | "-Wclippy::mutex_integer", 51 | "-Wclippy::needless_borrow", 52 | "-Wclippy::needless_continue", 53 | "-Wclippy::needless_for_each", 54 | "-Wclippy::option_option", 55 | "-Wclippy::path_buf_push_overwrite", 56 | "-Wclippy::ptr_as_ptr", 57 | "-Wclippy::rc_mutex", 58 | "-Wclippy::ref_option_ref", 59 | "-Wclippy::rest_pat_in_fully_bound_structs", 60 | "-Wclippy::same_functions_in_if_condition", 61 | "-Wclippy::semicolon_if_nothing_returned", 62 | "-Wclippy::single_match_else", 63 | "-Wclippy::string_add_assign", 64 | "-Wclippy::string_add", 65 | "-Wclippy::string_lit_as_bytes", 66 | "-Wclippy::string_to_string", 67 | "-Wclippy::todo", 68 | "-Wclippy::trait_duplication_in_bounds", 69 | "-Wclippy::unimplemented", 70 | "-Wclippy::unnested_or_patterns", 71 | "-Wclippy::unused_self", 72 | "-Wclippy::useless_transmute", 73 | "-Wclippy::verbose_file_reads", 74 | "-Wclippy::zero_sized_map_values", 75 | "-Wfuture_incompatible", 76 | "-Wnonstandard_style", 77 | "-Wrust_2018_idioms", 78 | # END - Embark standard lints v6 for Rust 1.55+ 79 | ] 80 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # configure GitHub linguist (language bar) https://github.com/github/linguist#overrides 2 | physx-sys/PhysX/* linguist-vendored 3 | physx-sys/pxbind/fmt/* linguist-vendored 4 | physx-sys/src/* linguist-generated=true 5 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @tgolsson @blunzn @bpaberg 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Device:** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | tags: 6 | - "*" 7 | pull_request: 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 11 | cancel-in-progress: true 12 | 13 | name: CI 14 | jobs: 15 | lint: 16 | name: Lint 17 | runs-on: ubuntu-22.04 18 | steps: 19 | - uses: actions/checkout@v3 20 | with: 21 | submodules: true 22 | - uses: dtolnay/rust-toolchain@stable 23 | with: 24 | components: "clippy, rustfmt" 25 | - uses: Swatinem/rust-cache@v2 26 | # make sure all code has been formatted with rustfmt 27 | - run: cargo fmt -- --check --color always 28 | 29 | # run clippy to verify we have no warnings 30 | - run: cargo clippy --all-features --all-targets -- -D warnings 31 | 32 | cargo-deny: 33 | runs-on: ubuntu-22.04 34 | steps: 35 | - uses: actions/checkout@v3 36 | - uses: EmbarkStudios/cargo-deny-action@v1 37 | 38 | test_debug: 39 | name: Test (Debug) 40 | strategy: 41 | matrix: 42 | include: 43 | - os: ubuntu-22.04 44 | target: x86_64-unknown-linux-gnu 45 | - os: ubuntu-22.04 46 | target: aarch64-unknown-linux-gnu 47 | container: ghcr.io/cross-rs/aarch64-unknown-linux-gnu:edge 48 | - os: windows-2022 49 | target: x86_64-pc-windows-msvc 50 | - os: macOS-12 51 | target: x86_64-apple-darwin 52 | runs-on: ${{ matrix.os }} 53 | container: ${{ matrix.container }} 54 | env: 55 | TARGET_CXX: "${{ matrix.target == 'aarch64-unknown-linux-gnu' && 'g++' || 'clang++' }}" 56 | steps: 57 | - uses: actions/checkout@v3 58 | with: 59 | submodules: true 60 | - uses: dtolnay/rust-toolchain@stable 61 | with: 62 | target: ${{ matrix.target }} 63 | - uses: Swatinem/rust-cache@v2 64 | - run: cargo fetch --target ${{ matrix.target }} 65 | - name: test - no features 66 | run: cargo test --workspace --exclude pxbind 67 | - name: test - all features 68 | run: cargo test --all-features --workspace --exclude pxbind 69 | - name: ball all features 70 | run: cargo run --example ball --all-features 71 | - name: ball no features 72 | run: cargo run --example ball 73 | - name: ball just structgen 74 | run: cargo run -p physx --example ball_physx --features structgen 75 | 76 | build_debug_aarch64_apple_darwin: 77 | name: Build aarch64-apple-darwin 78 | strategy: 79 | matrix: 80 | include: 81 | - os: macOS-12 82 | target: aarch64-apple-darwin 83 | runs-on: ${{ matrix.os }} 84 | steps: 85 | - uses: actions/checkout@v3 86 | with: 87 | submodules: true 88 | - uses: dtolnay/rust-toolchain@stable 89 | with: 90 | target: ${{ matrix.target }} 91 | - uses: Swatinem/rust-cache@v2 92 | - run: cargo fetch --target ${{ matrix.target }} 93 | - name: build 94 | run: cargo build -p physx 95 | 96 | package: 97 | name: Package 98 | runs-on: ubuntu-22.04 99 | steps: 100 | - uses: actions/checkout@v3 101 | with: 102 | submodules: true 103 | - uses: dtolnay/rust-toolchain@stable 104 | - uses: Swatinem/rust-cache@v2 105 | - run: cargo package --manifest-path ./physx-sys/Cargo.toml 106 | 107 | build_android_release: 108 | name: Build (Release) (aarch64-linux-android) 109 | runs-on: ubuntu-20.04 110 | steps: 111 | - uses: actions/checkout@v3 112 | with: 113 | submodules: true 114 | - name: Set up NDK 21.4.7075529 115 | run: | 116 | ANDROID_ROOT=/usr/local/lib/android 117 | ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk 118 | ANDROID_NDK_ROOT=${ANDROID_SDK_ROOT}/ndk-bundle 119 | SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager 120 | echo "y" | $SDKMANAGER "ndk;21.4.7075529" 121 | ln -sfn ${ANDROID_SDK_ROOT}/ndk/21.4.7075529 ${ANDROID_NDK_ROOT} 122 | echo "ANDROID_NDK_HOME=${ANDROID_NDK_ROOT}" >> $GITHUB_ENV 123 | - uses: actions/checkout@v3 124 | with: 125 | submodules: true 126 | - uses: dtolnay/rust-toolchain@stable 127 | with: 128 | target: aarch64-linux-android 129 | - uses: Swatinem/rust-cache@v2 130 | - run: cargo fetch --target aarch64-linux-android --manifest-path physx/Cargo.toml 131 | - name: build - no features 132 | env: 133 | LD_aarch64_linux_android: ${{env.ANDROID_NDK_HOME }}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ld 134 | CC_aarch64_linux_android: ${{env.ANDROID_NDK_HOME }}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang 135 | CXX_aarch64_linux_android: ${{env.ANDROID_NDK_HOME }}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++ 136 | AR_aarch64_linux_android: ${{env.ANDROID_NDK_HOME }}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar 137 | run: cargo build --target aarch64-linux-android --release -p physx 138 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/target 2 | Cargo.lock 3 | .vscode/settings.json 4 | 5 | # exclude `insta` snapshot new files 6 | *.snap.new 7 | 8 | # we use this while iterating 9 | ast-dump.json 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "physx-sys/physx"] 2 | path = physx-sys/physx 3 | url = https://github.com/EmbarkStudios/Physx-5 4 | branch = main 5 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: automatic merge when CI passes and 1 reviews 3 | conditions: 4 | - "#approved-reviews-by>=1" 5 | - "#review-requested=0" 6 | - "#changes-requested-reviews-by=0" 7 | - "#commented-reviews-by=0" 8 | - base=main 9 | - label!=work-in-progress 10 | actions: 11 | merge: 12 | method: squash 13 | - name: delete head branch after merge 14 | conditions: [] 15 | actions: 16 | delete_head_branch: {} 17 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Embark Contributor Guidelines 2 | 3 | Welcome! This project is created by the team at [Embark Studios](https://embark.games). We're glad you're interested in contributing! We welcome contributions from people of all backgrounds who are interested in making great software with us. 4 | 5 | At Embark, we aspire to empower everyone to create interactive experiences. To do this, we're exploring and pushing the boundaries of new technologies, and sharing our learnings with the open source community. 6 | 7 | If you have any difficulties getting involved or finding answers to your questions, please don't hesitate to ask your questions in our [Discord server](https://discord.com/invite/8TW9nfF). 8 | 9 | If you have ideas for collaboration, email us at opensource@embark-studios.com. 10 | 11 | We're also hiring full-time engineers to work with us in Stockholm! Check out our current job postings [here](https://www.embark-studios.com/jobs). 12 | 13 | ## Issues 14 | 15 | ### Feature Requests 16 | 17 | If you have ideas or how to improve our projects, you can suggest features by opening a GitHub issue. Make sure to include details about the feature or change, and describe any uses cases it would enable. 18 | 19 | Feature requests will be tagged as `enhancement` and their status will be updated in the comments of the issue. 20 | 21 | ### Bugs 22 | 23 | When reporting a bug or unexpected behaviour in a project, make sure your issue descibes steps to reproduce the behaviour, including the platform you were using, what steps you took, and any error messages. 24 | 25 | Reproducible bugs will be tagged as `bug` and their status will be updated in the comments of the issue. 26 | 27 | ### Wontfix 28 | 29 | Issues will be closed and tagged as `wontfix` if we decide that we do not wish to implement it, usually due to being misaligned with the project vision or out of scope. We will comment on the issue with more detailed reasoning. 30 | 31 | ## Contribution Workflow 32 | 33 | ### Open Issues 34 | 35 | If you're ready to contribute, start by looking at our open issues tagged as [`help wanted`](../../issues?q=is%3Aopen+is%3Aissue+label%3A"help+wanted") or [`good first issue`](../../issues?q=is%3Aopen+is%3Aissue+label%3A"good+first+issue"). 36 | 37 | You can comment on the issue to let others know you're interested in working on it or to ask questions. 38 | 39 | ### Making Changes 40 | 41 | 1. Fork the repository. 42 | 43 | 2. Create a new feature branch. 44 | 45 | 3. Make your changes. Ensure that there are no build errors by running the project with your changes locally. 46 | 47 | 4. Open a pull request with a name and description of what you did. You can read more about working with pull requests on GitHub [here](https://help.github.com/en/articles/creating-a-pull-request-from-a-fork). 48 | 49 | 5. A maintainer will review your pull request and may ask you to make changes. 50 | 51 | ## Licensing 52 | 53 | Unless otherwise specified, all Embark open source projects are licensed under a dual MIT OR Apache-2.0 license, allowing licensees to chose either at their option. You can read more in each project's respective README. 54 | 55 | ## Code of Conduct 56 | 57 | Please note that our projects are released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md) to ensure that they are welcoming places for everyone to contribute. By participating in any Embark open source project, you agree to abide by these terms. 58 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = ["physx", "physx-sys", "physx-sys/pxbind"] 4 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Embark Studios 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | doc-valid-idents = ["PhysX"] 2 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | [bans] 2 | multiple-versions = "deny" 3 | deny = [ 4 | { name = "openssl" }, 5 | 6 | # library choices we've made 7 | { name = "nalgebra" }, # we use glam as math library, not nalgebra 8 | { name = "nalgebra-glm" }, # we use glam as math library, not nalgebra 9 | { name = "ncollide3d" }, # we use PhysX, not nphysics/nalgebra 10 | { name = "nphysics" }, # we use PhysX, not nphysics/nalgebra 11 | 12 | # deprecated/abandoned 13 | { name = "term" }, # term is not fully maintained, and termcolor is replacing it 14 | { name = "quickersort" }, # explicitly deprecated 15 | { name = "build-helper" }, # abandoned, and doesn't add much value 16 | { name = "app_dirs" }, # abandoned, use app_dirs2 instead 17 | { name = "colored" }, # not actively maintained? slow to merge update fixes in and has lots of old dependencies 18 | { name = "floating-duration" }, # not needed with Rust 1.38, and very few users and commits 19 | { name = "mopa" }, # abandoned, have not been updated for 4 years 20 | ] 21 | skip = [] 22 | skip-tree = [ 23 | # window-sys duplicates, only used by pxbind, doesn't affect physx-sys/physx itself 24 | { name = "windows-sys" }, 25 | 26 | 27 | # rustix duplicates, 28 | # latest tempfile uses rustix v0.37.23, while latest env_logger v0.10.0 uses 0.38.3 29 | # only used by pxbind 30 | { name = "rustix" }, 31 | ] 32 | 33 | [licenses] 34 | unlicensed = "deny" 35 | allow-osi-fsf-free = "neither" 36 | # We want really high confidence when inferring licenses from text 37 | confidence-threshold = 0.92 38 | allow = ["Apache-2.0", "BSD-3-Clause", "MIT"] 39 | 40 | exceptions = [{ allow = ["Unicode-DFS-2016"], name = "unicode-ident" }] 41 | -------------------------------------------------------------------------------- /images/example-ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmbarkStudios/physx-rs/d0d571ee61ea44750bf58df96464f49b466da46e/images/example-ball.png -------------------------------------------------------------------------------- /physx-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "physx-sys" 3 | description = "Unsafe bindings for NVIDIA PhysX C++ SDK" 4 | version = "0.11.5" 5 | authors = [ 6 | "Embark ", 7 | "Tomasz Stachowiak ", 8 | ] 9 | license = "(MIT OR Apache-2.0) AND BSD-3-Clause" 10 | repository = "https://github.com/EmbarkStudios/physx-rs" 11 | edition = "2021" 12 | build = "build.rs" 13 | readme = "README.md" 14 | keywords = ["physics"] 15 | categories = ["external-ffi-bindings", "simulation", "game-engines"] 16 | exclude = [ 17 | "PhysX/**/*.bat", 18 | "PhysX/**/*.html", 19 | "PhysX/**/*.sh", 20 | "PhysX/*demo/**/*", 21 | "PhysX/externals/cg-linux/**/*", 22 | "PhysX/externals/clang-physxmetadata/**/*", 23 | "PhysX/externals/glew-linux/**/*", 24 | "PhysX/externals/glew/**/*", 25 | "PhysX/externals/opengl-linux/**/*", 26 | "PhysX/externals/targa/**/*", 27 | "PhysX/externals/vswhere/**/*", 28 | "PhysX/physx/bin/**/*", 29 | "PhysX/physx/buildtools/**/*", 30 | "PhysX/physx/documentation/**/*", 31 | "PhysX/physx/samples/**/*", 32 | "PhysX/physx/snippets/**/*", 33 | "PhysX/physx/tools/**/*", 34 | ] 35 | 36 | [lib] 37 | doctest = false 38 | 39 | [features] 40 | # This feature will build and run the structgen program, generating C++ and Rust 41 | # code to ensure the record types used in FFI match exactly and can be transparently 42 | # memcopied. This feature is not normally needed for tier 1 platforms and Android 43 | # as the crate includes pre-generated ones 44 | structgen = [] 45 | profile = [] 46 | # Enables `Debug` derivations for the FFI structures, which can be useful for 47 | # print debugging 48 | debug-structs = [] 49 | # Enables warnings in when compiling the C++ code. This is not something you should care about 50 | cpp-warnings = [] 51 | 52 | [dependencies] 53 | # The PhysX API exposes several enums used as flags 54 | bitflags = "1.3" 55 | 56 | [build-dependencies] 57 | cc = { version = "1.0", features = ["parallel"] } 58 | -------------------------------------------------------------------------------- /physx-sys/LICENSE: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: (MIT OR Apache-2.0) AND BSD-3-Clause 2 | -------------------------------------------------------------------------------- /physx-sys/LICENSE-BSD: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023, NVIDIA Corporation 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | * Neither the name of NVIDIA CORPORATION nor the names of its 18 | contributors may be used to endorse or promote products derived 19 | from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY 22 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 29 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /physx-sys/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Embark Studios 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /physx-sys/examples/ball.rs: -------------------------------------------------------------------------------- 1 | use physx_sys::*; 2 | use std::ptr::null_mut; 3 | 4 | fn main() { 5 | #[allow(unsafe_code)] 6 | // SAFETY: It works...but is it safe? :D 7 | unsafe { 8 | let foundation = physx_create_foundation(); 9 | let physics = physx_create_physics(foundation); 10 | 11 | let mut scene_desc = PxSceneDesc_new(PxPhysics_getTolerancesScale(physics)); 12 | scene_desc.gravity = PxVec3 { 13 | x: 0.0, 14 | y: -9.81, 15 | z: 0.0, 16 | }; 17 | 18 | let dispatcher = phys_PxDefaultCpuDispatcherCreate( 19 | 1, 20 | null_mut(), 21 | PxDefaultCpuDispatcherWaitForWorkMode::WaitForWork, 22 | 0, 23 | ); 24 | scene_desc.cpuDispatcher = dispatcher.cast(); 25 | scene_desc.filterShader = get_default_simulation_filter_shader(); 26 | 27 | let scene = PxPhysics_createScene_mut(physics, &scene_desc); 28 | 29 | let material = PxPhysics_createMaterial_mut(physics, 0.5, 0.5, 0.6); 30 | let ground_plane = 31 | phys_PxCreatePlane(physics, &PxPlane_new_1(0.0, 1.0, 0.0, 0.0), material); 32 | PxScene_addActor_mut(scene, ground_plane.cast(), null_mut()); 33 | 34 | let sphere_geo = PxSphereGeometry_new(10.0); 35 | let sphere = phys_PxCreateDynamic( 36 | physics, 37 | &PxTransform_new_1(&PxVec3 { 38 | x: 0.0, 39 | y: 40.0, 40 | z: 100.0, 41 | }), 42 | (&sphere_geo as *const PxSphereGeometry).cast(), 43 | material, 44 | 10.0, 45 | &PxTransform_new_2(PxIDENTITY::PxIdentity), 46 | ); 47 | PxRigidBody_setAngularDamping_mut(sphere.cast(), 0.5); 48 | PxScene_addActor_mut(scene, sphere.cast(), null_mut()); 49 | 50 | let filter_data = PxQueryFilterData_new(); 51 | let mut raycast_hits = Vec::new(); 52 | 53 | let heights_over_time = (0..100) 54 | .map(|_| { 55 | PxScene_simulate_mut(scene, 0.1, null_mut(), null_mut(), 0, true); 56 | let mut error: u32 = 0; 57 | PxScene_fetchResults_mut(scene, true, &mut error); 58 | assert!(error == 0, "fetchResults has failed"); 59 | 60 | let mut hit = std::mem::MaybeUninit::uninit(); 61 | 62 | if physx_sys::PxSceneQueryExt_raycastSingle( 63 | scene, 64 | &PxVec3 { 65 | x: 0.0, 66 | y: 100.0, 67 | z: 100.0, 68 | }, // origin 69 | &PxVec3 { 70 | x: 0.0, 71 | y: -1.0, 72 | z: 0.0, 73 | }, // dir 74 | 1000.0, // max distance 75 | PxHitFlags::Default, 76 | hit.as_mut_ptr(), 77 | &filter_data, 78 | null_mut(), 79 | null_mut(), 80 | ) { 81 | let hit = hit.assume_init(); 82 | raycast_hits.push(hit); 83 | } 84 | 85 | let pose = PxRigidActor_getGlobalPose(sphere.cast()); 86 | (pose.p.y) as i32 - 10 87 | }) 88 | .collect::>(); 89 | let max_h = 18; 90 | (0..max_h) 91 | .map(|h| { 92 | let h = max_h - 1 - h; 93 | heights_over_time 94 | .iter() 95 | .enumerate() 96 | .map(|(_t, p)| if h == *p { 'o' } else { ' ' }) 97 | .collect::() 98 | }) 99 | .for_each(|line| { 100 | println!("{line}"); 101 | }); 102 | PxScene_release_mut(scene); 103 | PxDefaultCpuDispatcher_release_mut(dispatcher); 104 | PxPhysics_release_mut(physics); 105 | 106 | for hit in raycast_hits { 107 | eprintln!("Raycast hit object {:.02}m away", hit.distance); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /physx-sys/make-sources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # This script finds all of the cpp files in a and generates a rust 5 | # array of strings into physx-sys/sources/ that is used by the build script 6 | # to compile all of the source files when compiling physx-sys 7 | # 8 | # usage: make-sources.sh 9 | dir=$1 10 | file="$(dirname "$0")/sources/$2" 11 | 12 | printf "[\n" > "$file" 13 | 14 | for entry in "$dir"/*.cpp 15 | do 16 | printf " \"%s\",\n" "$(echo "$entry" | sed -r "s/.+\/(.+)\..+/\1/")" >> "$file" 17 | done 18 | 19 | printf "]\n" >> "$file" 20 | -------------------------------------------------------------------------------- /physx-sys/pxbind/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pxbind" 3 | version = "0.1.0" 4 | edition = "2021" 5 | license = "MIT OR Apache-2.0" 6 | publish = false 7 | 8 | [dependencies] 9 | anyhow = "1.0" 10 | clang-ast = "0.1" 11 | env_logger = "0.10" 12 | heck = "0.4" 13 | log = "0.4" 14 | serde = { version = "1.0", features = ["derive"] } 15 | serde_json = "1.0" 16 | 17 | [dev-dependencies] 18 | insta = "1.26" 19 | tempfile = "3.6" 20 | -------------------------------------------------------------------------------- /physx-sys/pxbind/src/consumer/templates.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | 3 | use crate::Node; 4 | 5 | use super::{AstConsumer, Builtin, QualType, Record}; 6 | use anyhow::Context as _; 7 | use std::borrow::Cow; 8 | 9 | #[derive(PartialEq)] 10 | pub enum TemplateArg<'ast> { 11 | Type(QualType<'ast>), 12 | Value(u32), 13 | } 14 | 15 | struct TemplateParam<'ast> { 16 | name: &'ast str, 17 | builtin: Option, 18 | } 19 | 20 | enum TemplateItemKind<'ast> { 21 | Concrete(QualType<'ast>), 22 | Parameterized(&'ast str), 23 | } 24 | 25 | struct TemplateItem<'ast> { 26 | name: &'ast str, 27 | kind: TemplateItemKind<'ast>, 28 | } 29 | 30 | struct TemplateMethod<'ast> { 31 | name: String, 32 | params: Vec>, 33 | } 34 | 35 | struct TemplateStamp<'ast> { 36 | name: Cow<'ast, str>, 37 | args: Vec>, 38 | } 39 | 40 | pub struct Template<'ast> { 41 | params: Vec>, 42 | instanced: Vec>, 43 | /// This is the 44 | top_record: &'ast Record, 45 | def_record: &'ast Node, 46 | } 47 | 48 | impl<'ast> Template<'ast> { 49 | fn parse_template_args( 50 | &self, 51 | ast: &AstConsumer<'ast>, 52 | qt: &'ast str, 53 | ) -> anyhow::Result>> { 54 | let begin = qt.find('<').context("not a template")?; 55 | let end = qt.rfind('>').context("not a template")?; 56 | 57 | let mut targs = Vec::new(); 58 | for (arg, param) in qt[begin + 1..end].split(',').zip(self.params.iter()) { 59 | // We don't really do error checking here, if the templates are messed 60 | // up PhysX won't compile 61 | if param.builtin.is_some() { 62 | targs.push(TemplateArg::Value(arg.parse()?)); 63 | } else { 64 | targs.push(TemplateArg::Type(ast.parse_type(arg, &[])?)); 65 | } 66 | } 67 | 68 | Ok(targs) 69 | } 70 | 71 | #[inline] 72 | fn get_stamped(&self, args: &[TemplateArg<'ast>]) -> Option> { 73 | self.instanced 74 | .iter() 75 | .find_map(|i| (i.args == args).then(|| i.name.clone())) 76 | } 77 | } 78 | 79 | impl<'ast> AstConsumer<'ast> { 80 | pub(super) fn consume_template_instance( 81 | &mut self, 82 | qual_type: &'ast str, 83 | name: Option<&'ast str>, 84 | ) -> anyhow::Result> { 85 | let qual_type = if let Some(stripped) = qual_type.strip_prefix("const ") { 86 | stripped 87 | } else { 88 | qual_type 89 | }; 90 | 91 | let begin = qual_type.find('<').context("this isn't a template")?; 92 | 93 | let template_name = &qual_type[..begin]; 94 | let tdecl = self 95 | .templates 96 | .get(template_name) 97 | .with_context(|| format!("template decl '{template_name}' has not been consumed"))?; 98 | 99 | let targs = tdecl.parse_template_args(self, qual_type)?; 100 | 101 | // If we've already stamped out this template just return the name it was given 102 | if let Some(stamped) = tdecl.get_stamped(&targs) { 103 | return Ok(stamped); 104 | } 105 | 106 | let instance_name = name.map_or_else( 107 | || Cow::Owned(format!("{template_name}_T{}", tdecl.instanced.len())), 108 | Cow::Borrowed, 109 | ); 110 | 111 | let mut mappings: Vec<_> = targs 112 | .iter() 113 | .zip(tdecl.params.iter()) 114 | .map(|(ta, tp)| (tp.name, ta)) 115 | .collect(); 116 | 117 | let mut fields = Vec::new(); 118 | self.get_fields(tdecl.def_record, tdecl.top_record, &mappings, &mut fields)?; 119 | 120 | Ok(instance_name) 121 | } 122 | 123 | pub(super) fn consume_template_decl( 124 | &mut self, 125 | node: &'ast Node, 126 | name: &'ast str, 127 | ) -> anyhow::Result<()> { 128 | anyhow::ensure!( 129 | !self.templates.contains_key(name), 130 | "template '{name}' has already been consumed" 131 | ); 132 | 133 | unreachable!(); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /physx-sys/pxbind/src/dump.rs: -------------------------------------------------------------------------------- 1 | use crate::Node; 2 | use anyhow::Context as _; 3 | 4 | pub fn get_repo_root() -> anyhow::Result { 5 | let mut git = std::process::Command::new("git"); 6 | git.args(["rev-parse", "--show-toplevel"]); 7 | git.stdout(std::process::Stdio::piped()); 8 | let captured = git 9 | .output() 10 | .context("failed to run git to find repo root")?; 11 | 12 | let mut rr = String::from_utf8(captured.stdout).context("git output was non-utf8")?; 13 | // Removing trailing newline 14 | rr.pop(); 15 | Ok(rr) 16 | } 17 | 18 | #[inline] 19 | pub fn get_include_dir() -> anyhow::Result { 20 | // Acquire the repo root so we don't need to care about where we are executing 21 | // this from (eg root, tests, wherever) 22 | let repo_root = get_repo_root()?; 23 | 24 | Ok(format!("{repo_root}/physx-sys/physx/physx/include")) 25 | } 26 | 27 | pub fn get_ast(header: impl AsRef) -> anyhow::Result> { 28 | let mut cmd = std::process::Command::new("clang++"); 29 | 30 | let include_dir = get_include_dir()?; 31 | 32 | cmd.args([ 33 | "-Xclang", 34 | // Requests the AST dump 35 | "-ast-dump=json", 36 | // We aren't actually compiling, just gathering type info 37 | "-fsyntax-only", 38 | // clang will complain about all physx headers when we are in C++ 39 | // mode because it treats .h as "c headers", this is useless 40 | "-xc++-header", 41 | // Define PX_DEPRECATED so that the attribute is emitted into the AST 42 | "-DPX_DEPRECATED=__attribute__((deprecated()))", 43 | // Ignore all warnings, we don't care about C++ shenanigans 44 | "-w", 45 | // We don't want this 46 | "-DDISABLE_CUDA_PHYSX", 47 | "-fcolor-diagnostics", 48 | // Add the root include directory so that clang knows how to find 49 | // all of the includes 50 | "-I", 51 | &include_dir, 52 | // Sigh, physx asserts that this is defined :p 53 | "-DNDEBUG", 54 | ]); 55 | cmd.arg(header.as_ref()); 56 | 57 | // note that this is _terribly_ slow but hopefully fixed in 1.69? 58 | // https://github.com/rust-lang/rust/issues/108223 59 | cmd.stdout(std::process::Stdio::piped()); 60 | cmd.stderr(std::process::Stdio::piped()); 61 | 62 | let captured = cmd 63 | .output() 64 | .context("failed to run clang++ to gather AST")?; 65 | 66 | anyhow::ensure!( 67 | captured.status.success(), 68 | "clang++ failed to gather AST {:?}\n{}", 69 | captured.status, 70 | String::from_utf8(captured.stderr).unwrap_or_default(), 71 | ); 72 | 73 | Ok(captured.stdout) 74 | } 75 | 76 | /// Dump the AST of a header and all of its includes and parses it into a [`Node`] 77 | pub fn get_parsed_ast(header: impl AsRef) -> anyhow::Result<(Node, Vec)> { 78 | log::info!("Gathering AST via clang..."); 79 | let t = std::time::Instant::now(); 80 | let ast = get_ast(header)?; 81 | log::info!("Gathered AST in {}ms", t.elapsed().as_millis()); 82 | 83 | log::info!("Parsing AST..."); 84 | let t = std::time::Instant::now(); 85 | let root_node: Node = serde_json::from_slice(&ast).context("failed to parse AST")?; 86 | log::info!("Parsed AST in {}ms", t.elapsed().as_millis()); 87 | Ok((root_node, ast)) 88 | } 89 | -------------------------------------------------------------------------------- /physx-sys/pxbind/src/generator/comment.rs: -------------------------------------------------------------------------------- 1 | use super::Indent; 2 | 3 | impl<'ast> crate::consumer::Comment<'ast> { 4 | pub(super) fn emit_rust(&self, writer: &mut String, level: u32) { 5 | let indent = Indent(level); 6 | 7 | let emit_lines = |w: &mut String, lines: &[&str]| { 8 | for line in lines { 9 | if line.is_empty() { 10 | writesln!(w, "{indent}///"); 11 | // PhysX _tends_ to use `#type::field/variant` style intralinks 12 | // so attempt to convert them to proper rustdoc style intralinks 13 | } else if let Some(ind) = line.find('#') { 14 | writes!(w, "{indent}/// {}", &line[..ind]); 15 | writes!(w, "[`"); 16 | match line[ind + 1..] 17 | .find(|c: char| !c.is_alphanumeric() && c != ':' && c != '_') 18 | { 19 | Some(end) => { 20 | writes!(w, "{}`]", &line[ind + 1..ind + end + 1]); 21 | writesln!(w, "{}", &line[ind + end + 1..]); 22 | } 23 | None => { 24 | writesln!(w, "{}`]", &line[ind + 1..]); 25 | } 26 | }; 27 | } else { 28 | writesln!(w, "{indent}/// {line}"); 29 | } 30 | } 31 | }; 32 | 33 | emit_lines(writer, self.summary.as_slice()); 34 | 35 | if !self.additional.is_empty() { 36 | writesln!(writer, "{indent}///"); 37 | emit_lines(writer, self.additional.as_slice()); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /physx-sys/pxbind/src/generator/enums.rs: -------------------------------------------------------------------------------- 1 | use crate::consumer::{Builtin, EnumBinding}; 2 | 3 | use super::Indent; 4 | 5 | /// Fixes enum variant names from the ugly C++ style of `eWHY_ARE_YOU_SHOUTING` 6 | /// to `WhyAreYouShouting` 7 | fn fix_variant_name(s: &str) -> String { 8 | let no_e = s 9 | .strip_prefix('e') 10 | .filter(|s| s.chars().next().unwrap().is_ascii_alphabetic()) 11 | .unwrap_or(s); 12 | 13 | use heck::ToUpperCamelCase; 14 | no_e.to_upper_camel_case() 15 | } 16 | 17 | impl<'ast> EnumBinding<'ast> { 18 | pub fn emit_rust(&self, w: &mut String, level: u32) { 19 | if let Some(com) = &self.comment { 20 | com.emit_rust(w, level); 21 | } 22 | 23 | let indent = Indent(level); 24 | let indent1 = Indent(level + 1); 25 | writesln!(w, "{indent}#[derive(Debug, Clone, Copy, PartialEq, Eq)]"); 26 | writesln!(w, "{indent}#[repr({})]", self.repr.rust_type()); 27 | writesln!(w, "{indent}pub enum {} {{", self.name); 28 | 29 | for var in &self.variants { 30 | if let Some(com) = &var.comment { 31 | com.emit_rust(w, level + 1); 32 | } 33 | 34 | writesln!( 35 | w, 36 | "{indent1}{} = {},", 37 | fix_variant_name(var.name), 38 | var.value 39 | ); 40 | } 41 | 42 | writesln!(w, "{indent}}}"); 43 | } 44 | 45 | pub fn emit_rust_conversion(&self, w: &mut String, level: u32, from: Builtin, default: &str) { 46 | let indent = Indent(level); 47 | let indent1 = Indent(level + 1); 48 | let indent2 = Indent(level + 2); 49 | 50 | let int_type = from.rust_type(); 51 | 52 | writesln!(w, "{indent}impl From<{int_type}> for {} {{", self.name); 53 | writesln!(w, "{indent1}fn from(val: {int_type}) -> Self {{"); 54 | writesln!(w, "{indent2}#[allow(clippy::match_same_arms)]"); 55 | writesln!(w, "{indent2}match val {{"); 56 | 57 | let indentm = Indent(level + 3); 58 | 59 | for var in &self.variants { 60 | writesln!( 61 | w, 62 | "{indentm}{} => Self::{},", 63 | var.value, 64 | fix_variant_name(var.name) 65 | ); 66 | } 67 | 68 | writesln!(w, "{indentm}_ => Self::{default},"); 69 | writesln!(w, "{indent2}}}"); 70 | writesln!(w, "{indent1}}}"); 71 | writesln!(w, "{indent}}}"); 72 | } 73 | } 74 | 75 | impl<'ast> crate::consumer::FlagsBinding<'ast> { 76 | pub fn emit_rust(&self, enum_binding: &EnumBinding<'ast>, w: &mut String, level: u32) { 77 | let indent = Indent(level); 78 | let indent1 = Indent(level + 1); 79 | let indent2 = Indent(level + 2); 80 | writesln!(w, "{indent}bitflags::bitflags! {{"); 81 | writesln!(w, "{indent1}/// Flags for [`{}`]", enum_binding.name); 82 | writesln!(w, "{indent1}#[derive(Default)]"); 83 | writesln!(w, "{indent1}#[repr(transparent)]"); 84 | writesln!( 85 | w, 86 | "{indent1}pub struct {}: {} {{", 87 | self.name, 88 | self.storage_type.rust_type() 89 | ); 90 | 91 | for var in &enum_binding.variants { 92 | // If used as flags, ignore emitting any zero value, see 93 | // https://docs.rs/bitflags/1.3.2/bitflags/#zero-flags 94 | if var.value == 0 { 95 | continue; 96 | } 97 | 98 | // if let Some(com) = &var.comment { 99 | // com.emit_rust(writer, level + 2)?; 100 | // } 101 | 102 | writes!(w, "{indent2}const {} = ", fix_variant_name(var.name)); 103 | 104 | // Since bitflags are made up of power of 2 values that can 105 | // be combined, and the PhysX API sometimes defines named 106 | // combinations of flags, reconstruct the bitflags to be 107 | // easier to read 108 | let val = var.value as u64; 109 | if val & (val - 1) == 0 { 110 | writes!(w, "1 << {}", val.ilog2()); 111 | } else { 112 | let mut is_combo = false; 113 | // If we're not a power of 2, we're a combination of flags, 114 | // find which ones and emit them in a friendly way 115 | for (i, which) in enum_binding 116 | .variants 117 | .iter() 118 | .filter_map(|var| { 119 | let prev = var.value as u64; 120 | (prev & (prev - 1) == 0 && (prev & val) != 0).then_some(var.name) 121 | }) 122 | .enumerate() 123 | { 124 | is_combo = true; 125 | if i > 0 { 126 | writes!(w, " | "); 127 | } 128 | 129 | writes!(w, "Self::{}.bits", fix_variant_name(which)); 130 | } 131 | 132 | // There are a couple of cases where they're not combos, so just 133 | // emit the raw value 134 | if !is_combo { 135 | writes!(w, "0x{val:08x}"); 136 | } 137 | } 138 | 139 | writesln!(w, ";"); 140 | } 141 | 142 | writesln!(w, "{indent1}}}\n{indent}}}"); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /physx-sys/pxbind/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod consumer; 2 | mod dump; 3 | pub mod generator; 4 | 5 | pub use dump::*; 6 | 7 | pub type Node = clang_ast::Node; 8 | -------------------------------------------------------------------------------- /physx-sys/pxbind/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Context as _; 2 | 3 | fn main() -> anyhow::Result<()> { 4 | env_logger::init(); 5 | 6 | // It takes clang++ around 30 seconds to dump the JSON, so just keep a file 7 | // around to reduce iteration times 8 | let root = if let Ok(json) = std::fs::read("ast-dump.json") { 9 | serde_json::from_slice(&json).context("failed to parse ast-dump.json")? 10 | } else { 11 | // This is the root API include that includes all the other public APIs 12 | let api_h = format!("{}/PxPhysicsAPI.h", pxbind::get_include_dir()?); 13 | let (root, raw) = pxbind::get_parsed_ast(api_h)?; 14 | 15 | std::fs::write("ast-dump.json", raw).context("failed to write ast-dump.json")?; 16 | 17 | root 18 | }; 19 | 20 | let mut ast = pxbind::consumer::AstConsumer::default(); 21 | ast.consume(&root)?; 22 | 23 | let rr: std::path::PathBuf = pxbind::get_repo_root()?.into(); 24 | 25 | use std::fs::File; 26 | 27 | let mut structgen = File::create(rr.join("physx-sys/src/structgen/structgen.cpp"))?; 28 | let mut cpp = File::create(rr.join("physx-sys/src/physx_generated.hpp"))?; 29 | let mut rust = File::create(rr.join("physx-sys/src/physx_generated.rs"))?; 30 | 31 | let generator = pxbind::generator::Generator::default(); 32 | generator.generate_all(&ast, &mut structgen, &mut cpp, &mut rust)?; 33 | 34 | Ok(()) 35 | } 36 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/all_the_things.h: -------------------------------------------------------------------------------- 1 | #include "PxPhysicsAPI.h" 2 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/enum/flags.h: -------------------------------------------------------------------------------- 1 | #include "foundation/PxFlags.h" 2 | #include "PxArticulationReducedCoordinate.h" 3 | 4 | namespace physx { 5 | // From PxActorData.h 6 | 7 | /** 8 | \brief Identifies each type of information for retrieving from actor. 9 | @see PxScene::applyActorData 10 | */ 11 | struct PxActorCacheFlag 12 | { 13 | enum Enum 14 | { 15 | eACTOR_DATA = (1 << 0), //include transform and velocity 16 | eFORCE = (1 << 2), 17 | eTORQUE = (1 << 3) 18 | }; 19 | }; 20 | 21 | /** 22 | \brief Collection of set bits defined in PxActorCacheFlag. 23 | 24 | @see PxActorCacheFlag 25 | */ 26 | typedef PxFlags PxActorCacheFlags; 27 | 28 | // From PxArticulationFlags.h 29 | 30 | /** 31 | \brief Flags which affect the behavior of PxShapes. 32 | 33 | @see PxShape PxShape.setFlag() 34 | */ 35 | struct PxShapeFlag 36 | { 37 | enum Enum 38 | { 39 | /** 40 | \brief The shape will partake in collision in the physical simulation. 41 | 42 | \note It is illegal to raise the eSIMULATION_SHAPE and eTRIGGER_SHAPE flags. 43 | In the event that one of these flags is already raised the sdk will reject any 44 | attempt to raise the other. To raise the eSIMULATION_SHAPE first ensure that 45 | eTRIGGER_SHAPE is already lowered. 46 | 47 | \note This flag has no effect if simulation is disabled for the corresponding actor (see #PxActorFlag::eDISABLE_SIMULATION). 48 | 49 | @see PxSimulationEventCallback.onContact() PxScene.setSimulationEventCallback() PxShape.setFlag(), PxShape.setFlags() 50 | */ 51 | eSIMULATION_SHAPE = (1<<0), 52 | 53 | /** 54 | \brief The shape will partake in scene queries (ray casts, overlap tests, sweeps, ...). 55 | */ 56 | eSCENE_QUERY_SHAPE = (1<<1), 57 | 58 | /** 59 | \brief The shape is a trigger which can send reports whenever other shapes enter/leave its volume. 60 | 61 | \note Triangle meshes and heightfields can not be triggers. Shape creation will fail in these cases. 62 | 63 | \note Shapes marked as triggers do not collide with other objects. If an object should act both 64 | as a trigger shape and a collision shape then create a rigid body with two shapes, one being a 65 | trigger shape and the other a collision shape. It is illegal to raise the eTRIGGER_SHAPE and 66 | eSIMULATION_SHAPE flags on a single PxShape instance. In the event that one of these flags is already 67 | raised the sdk will reject any attempt to raise the other. To raise the eTRIGGER_SHAPE flag first 68 | ensure that eSIMULATION_SHAPE flag is already lowered. 69 | 70 | \note Trigger shapes will no longer send notification events for interactions with other trigger shapes. 71 | 72 | \note Shapes marked as triggers are allowed to participate in scene queries, provided the eSCENE_QUERY_SHAPE flag is set. 73 | 74 | \note This flag has no effect if simulation is disabled for the corresponding actor (see #PxActorFlag::eDISABLE_SIMULATION). 75 | 76 | @see PxSimulationEventCallback.onTrigger() PxScene.setSimulationEventCallback() PxShape.setFlag(), PxShape.setFlags() 77 | */ 78 | eTRIGGER_SHAPE = (1<<2), 79 | 80 | /** 81 | \brief Enable debug renderer for this shape 82 | 83 | @see PxScene.getRenderBuffer() PxRenderBuffer PxVisualizationParameter 84 | */ 85 | eVISUALIZATION = (1<<3) 86 | }; 87 | }; 88 | 89 | /** 90 | \brief collection of set bits defined in PxShapeFlag. 91 | 92 | @see PxShapeFlag 93 | */ 94 | typedef PxFlags PxShapeFlags; 95 | } 96 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/enum/i32.h: -------------------------------------------------------------------------------- 1 | // From PxBroadPhase.h 2 | 3 | namespace physx { 4 | 5 | /** 6 | \brief Broad phase algorithm used in the simulation 7 | 8 | eSAP is a good generic choice with great performance when many objects are sleeping. Performance 9 | can degrade significantly though, when all objects are moving, or when large numbers of objects 10 | are added to or removed from the broad phase. This algorithm does not need world bounds to be 11 | defined in order to work. 12 | 13 | eMBP is an alternative broad phase algorithm that does not suffer from the same performance 14 | issues as eSAP when all objects are moving or when inserting large numbers of objects. However 15 | its generic performance when many objects are sleeping might be inferior to eSAP, and it requires 16 | users to define world bounds in order to work. 17 | 18 | eABP is a revisited implementation of MBP, which automatically manages broad-phase regions. 19 | It offers the convenience of eSAP (no need to define world bounds or regions) and the performance 20 | of eMBP when a lot of objects are moving. While eSAP can remain faster when most objects are 21 | sleeping and eMBP can remain faster when it uses a large number of properly-defined regions, 22 | eABP often gives the best performance on average and the best memory usage. 23 | 24 | ePABP is a parallel implementation of ABP. It can often be the fastest (CPU) broadphase, but it 25 | can use more memory than ABP. 26 | 27 | eGPU is a GPU implementation of the incremental sweep and prune approach. Additionally, it uses a ABP-style 28 | initial pair generation approach to avoid large spikes when inserting shapes. It not only has the advantage 29 | of traditional SAP approch which is good for when many objects are sleeping, but due to being fully parallel, 30 | it also is great when lots of shapes are moving or for runtime pair insertion and removal. It can become a 31 | performance bottleneck if there are a very large number of shapes roughly projecting to the same values 32 | on a given axis. If the scene has a very large number of shapes in an actor, e.g. a humanoid, it is recommended 33 | to use an aggregate to represent multi-shape or multi-body actors to minimize stress placed on the broad phase. 34 | */ 35 | struct PxBroadPhaseType 36 | { 37 | enum Enum 38 | { 39 | eSAP, //!< 3-axes sweep-and-prune 40 | eMBP, //!< Multi box pruning 41 | eABP, //!< Automatic box pruning 42 | ePABP, //!< Parallel automatic box pruning 43 | eGPU, //!< GPU broad phase 44 | eLAST 45 | }; 46 | }; 47 | 48 | } // physx 49 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/enum/simple.h: -------------------------------------------------------------------------------- 1 | namespace physx { 2 | 3 | /** enum for empty constructor tag*/ 4 | enum PxEMPTY 5 | { 6 | PxEmpty 7 | }; 8 | 9 | } // physx -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/enum/u32.h: -------------------------------------------------------------------------------- 1 | namespace physx { 2 | 3 | // From PxThread.h 4 | 5 | struct PxThreadPriority 6 | { 7 | enum Enum 8 | { 9 | eHIGH = 0, //!< High priority 10 | eABOVE_NORMAL = 1, //!< Above Normal priority 11 | eNORMAL = 2, //!< Normal/default priority 12 | eBELOW_NORMAL = 3, //!< Below Normal priority 13 | eLOW = 4, //!< Low priority. 14 | eFORCE_DWORD = 0xffFFffFF 15 | }; 16 | }; 17 | 18 | // From PxShape.h 19 | 20 | /** 21 | \brief Flags which affect the behavior of PxShapes. 22 | 23 | @see PxShape PxShape.setFlag() 24 | */ 25 | struct PxShapeFlag 26 | { 27 | enum Enum 28 | { 29 | /** 30 | \brief The shape will partake in collision in the physical simulation. 31 | 32 | \note It is illegal to raise the eSIMULATION_SHAPE and eTRIGGER_SHAPE flags. 33 | In the event that one of these flags is already raised the sdk will reject any 34 | attempt to raise the other. To raise the eSIMULATION_SHAPE first ensure that 35 | eTRIGGER_SHAPE is already lowered. 36 | 37 | \note This flag has no effect if simulation is disabled for the corresponding actor (see #PxActorFlag::eDISABLE_SIMULATION). 38 | 39 | @see PxSimulationEventCallback.onContact() PxScene.setSimulationEventCallback() PxShape.setFlag(), PxShape.setFlags() 40 | */ 41 | eSIMULATION_SHAPE = (1<<0), 42 | 43 | /** 44 | \brief The shape will partake in scene queries (ray casts, overlap tests, sweeps, ...). 45 | */ 46 | eSCENE_QUERY_SHAPE = (1<<1), 47 | 48 | /** 49 | \brief The shape is a trigger which can send reports whenever other shapes enter/leave its volume. 50 | 51 | \note Triangle meshes and heightfields can not be triggers. Shape creation will fail in these cases. 52 | 53 | \note Shapes marked as triggers do not collide with other objects. If an object should act both 54 | as a trigger shape and a collision shape then create a rigid body with two shapes, one being a 55 | trigger shape and the other a collision shape. It is illegal to raise the eTRIGGER_SHAPE and 56 | eSIMULATION_SHAPE flags on a single PxShape instance. In the event that one of these flags is already 57 | raised the sdk will reject any attempt to raise the other. To raise the eTRIGGER_SHAPE flag first 58 | ensure that eSIMULATION_SHAPE flag is already lowered. 59 | 60 | \note Trigger shapes will no longer send notification events for interactions with other trigger shapes. 61 | 62 | \note Shapes marked as triggers are allowed to participate in scene queries, provided the eSCENE_QUERY_SHAPE flag is set. 63 | 64 | \note This flag has no effect if simulation is disabled for the corresponding actor (see #PxActorFlag::eDISABLE_SIMULATION). 65 | 66 | @see PxSimulationEventCallback.onTrigger() PxScene.setSimulationEventCallback() PxShape.setFlag(), PxShape.setFlags() 67 | */ 68 | eTRIGGER_SHAPE = (1<<2), 69 | 70 | /** 71 | \brief Enable debug renderer for this shape 72 | 73 | @see PxScene.getRenderBuffer() PxRenderBuffer PxVisualizationParameter 74 | */ 75 | eVISUALIZATION = (1<<3) 76 | }; 77 | }; 78 | 79 | } // physx 80 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/functions/constructors.h: -------------------------------------------------------------------------------- 1 | #include "characterkinematic/PxController.h" 2 | 3 | namespace physx { 4 | /** 5 | \brief Descriptor for a box character controller. 6 | 7 | @see PxBoxController PxControllerDesc 8 | */ 9 | class PxBoxControllerDesc : public PxControllerDesc 10 | { 11 | public: 12 | /** 13 | \brief constructor sets to default. 14 | */ 15 | PX_INLINE PxBoxControllerDesc(); 16 | PX_INLINE virtual ~PxBoxControllerDesc() {} 17 | 18 | /** 19 | \brief copy constructor. 20 | */ 21 | PX_INLINE PxBoxControllerDesc(const PxBoxControllerDesc&); 22 | 23 | /** 24 | \brief assignment operator. 25 | */ 26 | PX_INLINE PxBoxControllerDesc& operator=(const PxBoxControllerDesc&); 27 | 28 | /** 29 | \brief (re)sets the structure to the default. 30 | */ 31 | PX_INLINE virtual void setToDefault(); 32 | 33 | /** 34 | \brief returns true if the current settings are valid 35 | 36 | \return True if the descriptor is valid. 37 | */ 38 | PX_INLINE virtual bool isValid() const; 39 | 40 | /** 41 | \brief Half height 42 | 43 | Default: 1.0 44 | */ 45 | PxF32 halfHeight; // Half-height in the "up" direction 46 | 47 | /** 48 | \brief Half side extent 49 | 50 | Default: 0.5 51 | */ 52 | PxF32 halfSideExtent; // Half-extent in the "side" direction 53 | 54 | /** 55 | \brief Half forward extent 56 | 57 | Default: 0.5 58 | */ 59 | PxF32 halfForwardExtent; // Half-extent in the "forward" direction 60 | 61 | protected: 62 | PX_INLINE void copy(const PxBoxControllerDesc&); 63 | }; 64 | 65 | PX_INLINE PxBoxControllerDesc::PxBoxControllerDesc() : 66 | PxControllerDesc (PxControllerShapeType::eBOX), 67 | halfHeight (1.0f), 68 | halfSideExtent (0.5f), 69 | halfForwardExtent (0.5f) 70 | { 71 | } 72 | 73 | PX_INLINE PxBoxControllerDesc::PxBoxControllerDesc(const PxBoxControllerDesc& other) : PxControllerDesc(other) 74 | { 75 | copy(other); 76 | } 77 | 78 | PX_INLINE PxBoxControllerDesc& PxBoxControllerDesc::operator=(const PxBoxControllerDesc& other) 79 | { 80 | PxControllerDesc::operator=(other); 81 | copy(other); 82 | return *this; 83 | } 84 | 85 | PX_INLINE void PxBoxControllerDesc::copy(const PxBoxControllerDesc& other) 86 | { 87 | halfHeight = other.halfHeight; 88 | halfSideExtent = other.halfSideExtent; 89 | halfForwardExtent = other.halfForwardExtent; 90 | } 91 | 92 | PX_INLINE void PxBoxControllerDesc::setToDefault() 93 | { 94 | *this = PxBoxControllerDesc(); 95 | } 96 | 97 | PX_INLINE bool PxBoxControllerDesc::isValid() const 98 | { 99 | if(!PxControllerDesc::isValid()) return false; 100 | if(halfHeight<=0.0f) return false; 101 | if(halfSideExtent<=0.0f) return false; 102 | if(halfForwardExtent<=0.0f) return false; 103 | if(stepOffset>2.0f*halfHeight) return false; // Prevents obvious mistakes 104 | return true; 105 | } 106 | } -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/functions/destructors.h: -------------------------------------------------------------------------------- 1 | #include "common/PxBase.h" 2 | #include "foundation/PxMath.h" 3 | 4 | namespace physx { 5 | class PxJointLimitParameters 6 | { 7 | public: 8 | PxReal restitution; 9 | PxReal bounceThreshold; 10 | PxReal stiffness; 11 | PxReal damping; 12 | PxReal contactDistance_deprecated; 13 | 14 | PxJointLimitParameters() : 15 | restitution (0.0f), 16 | bounceThreshold (0.0f), 17 | stiffness (0.0f), 18 | damping (0.0f), 19 | contactDistance_deprecated (0.0f) 20 | { 21 | } 22 | 23 | PxJointLimitParameters(const PxJointLimitParameters& p) : 24 | restitution (p.restitution), 25 | bounceThreshold (p.bounceThreshold), 26 | stiffness (p.stiffness), 27 | damping (p.damping), 28 | contactDistance_deprecated (p.contactDistance_deprecated) 29 | { 30 | } 31 | 32 | /** 33 | \brief Returns true if the current settings are valid. 34 | 35 | \return true if the current settings are valid 36 | */ 37 | PX_INLINE bool isValid() const 38 | { 39 | return PxIsFinite(restitution) && restitution >= 0 && restitution <= 1 && 40 | PxIsFinite(stiffness) && stiffness >= 0 && 41 | PxIsFinite(damping) && damping >= 0 && 42 | PxIsFinite(bounceThreshold) && bounceThreshold >= 0 && 43 | PxIsFinite(contactDistance_deprecated) && contactDistance_deprecated >= 0; 44 | } 45 | 46 | PX_INLINE bool isSoft() const 47 | { 48 | return damping>0 || stiffness>0; 49 | } 50 | 51 | protected: 52 | ~PxJointLimitParameters() {} 53 | }; 54 | 55 | class PxJointAngularLimitPair : public PxJointLimitParameters 56 | { 57 | public: 58 | PxReal upper, lower; 59 | 60 | PxJointAngularLimitPair(PxReal lowerLimit, PxReal upperLimit, PxReal contactDist_deprecated = -1.0f) : 61 | upper(upperLimit), 62 | lower(lowerLimit) 63 | { 64 | PxJointLimitParameters::contactDistance_deprecated = contactDist_deprecated ==-1.0f ? PxMin(0.1f, 0.49f*(upperLimit-lowerLimit)) : contactDist_deprecated; 65 | bounceThreshold = 0.5f; 66 | } 67 | 68 | /** 69 | \brief Returns true if the limit is valid. 70 | 71 | \return true if the current settings are valid 72 | */ 73 | PX_INLINE bool isValid() const 74 | { 75 | return PxJointLimitParameters::isValid() && 76 | PxIsFinite(upper) && PxIsFinite(lower) && upper >= lower; 77 | } 78 | }; 79 | } 80 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/functions/functions.h: -------------------------------------------------------------------------------- 1 | #include "PxPhysics.h" 2 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/functions/methods_complex.h: -------------------------------------------------------------------------------- 1 | #include "PxShape.h" 2 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/record/abstract.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace physx { 4 | 5 | /** 6 | \brief Abstract base class for an application defined memory allocator that can be used by the Nv library. 7 | 8 | \note The SDK state should not be modified from within any allocation/free function. 9 | 10 | Threading: All methods of this class should be thread safe as it can be called from the user thread 11 | or the physics processing thread(s). 12 | */ 13 | 14 | class PxAllocatorCallback 15 | { 16 | public: 17 | 18 | virtual ~PxAllocatorCallback() 19 | { 20 | } 21 | 22 | /** 23 | \brief Allocates size bytes of memory, which must be 16-byte aligned. 24 | 25 | This method should never return NULL. If you run out of memory, then 26 | you should terminate the app or take some other appropriate action. 27 | 28 | Threading: This function should be thread safe as it can be called in the context of the user thread 29 | and physics processing thread(s). 30 | 31 | \param size Number of bytes to allocate. 32 | \param typeName Name of the datatype that is being allocated 33 | \param filename The source file which allocated the memory 34 | \param line The source line which allocated the memory 35 | \return The allocated block of memory. 36 | */ 37 | virtual void* allocate(size_t size, const char* typeName, const char* filename, int line) = 0; 38 | 39 | /** 40 | \brief Frees memory previously allocated by allocate(). 41 | 42 | Threading: This function should be thread safe as it can be called in the context of the user thread 43 | and physics processing thread(s). 44 | 45 | \param ptr Memory to free. 46 | */ 47 | virtual void deallocate(void* ptr) = 0; 48 | }; 49 | 50 | } // namespace physx 51 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/record/complex.h: -------------------------------------------------------------------------------- 1 | #include "solver/PxSolverDefs.h" 2 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/record/ptr_only.h: -------------------------------------------------------------------------------- 1 | namespace physx { 2 | 3 | class PxAllocatorCallback; 4 | 5 | class PxAllocatorCallback 6 | { 7 | public: 8 | 9 | virtual ~PxAllocatorCallback() 10 | { 11 | } 12 | 13 | virtual void deallocate(void* ptr) = 0; 14 | }; 15 | 16 | class MemoryBuffer; 17 | 18 | } // namespace physx 19 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/record/ref_fields.h: -------------------------------------------------------------------------------- 1 | #include "common/PxPhysXCommonConfig.h" 2 | #include "foundation/PxVecTransform.h" 3 | 4 | 5 | namespace physx { 6 | class PxReffyMcRefface 7 | { 8 | public: 9 | PxVec3 shapeSpaceCenterOfMass; 10 | const PxTransform& transform; 11 | const PxMat33& vertex2Shape; 12 | const PxMat33& shape2Vertex; 13 | const bool isIdentityScale; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/data/record/templates.h: -------------------------------------------------------------------------------- 1 | #include "PxQueryReport.h" 2 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/enums.rs: -------------------------------------------------------------------------------- 1 | fn gen_enums(which: &str, to_emit: &'static [&str]) -> anyhow::Result { 2 | let (ast, _) = pxbind::get_parsed_ast(format!("tests/data/enum/{which}"))?; 3 | 4 | let mut consumer = pxbind::consumer::AstConsumer::default(); 5 | consumer.consume(&ast)?; 6 | 7 | let generated = { 8 | let record_filter = |_rb: &pxbind::consumer::RecBinding<'_>| false; 9 | let enum_filter = |eb: &pxbind::consumer::EnumBinding<'_>| { 10 | to_emit.is_empty() || to_emit.iter().any(|te| *te == eb.name) 11 | }; 12 | 13 | let generator = pxbind::generator::Generator { 14 | record_filter: Box::new(record_filter), 15 | enum_filter: Box::new(enum_filter), 16 | ..Default::default() 17 | }; 18 | 19 | let mut buffer = Vec::new(); 20 | generator.generate_rust_enums(&consumer, &mut buffer, 0)?; 21 | String::from_utf8(buffer)? 22 | }; 23 | 24 | Ok(generated) 25 | } 26 | 27 | /// Verifies we can generate appropriate Rust enums for vanilla, i32 default C++ enums 28 | #[test] 29 | fn i32() { 30 | insta::assert_snapshot!(gen_enums("i32.h", &[]).unwrap()); 31 | } 32 | 33 | /// Verifies we can generate appropriate Rust enums for C++ enums that have been 34 | /// old school style forced to be u32 35 | #[test] 36 | fn u32() { 37 | insta::assert_snapshot!(gen_enums("u32.h", &[]).unwrap()); 38 | } 39 | 40 | /// Verifies that enums not scoped to a struct can be parsed 41 | #[test] 42 | fn simple() { 43 | insta::assert_snapshot!(gen_enums("simple.h", &[]).unwrap()); 44 | } 45 | 46 | /// Verifies that enums and their `PxFlags<>` wrappers can be properly bound 47 | #[test] 48 | fn flags() { 49 | insta::assert_snapshot!(gen_enums( 50 | "flags.h", 51 | &[ 52 | "PxActorCacheFlag", 53 | "PxArticulationCacheFlag", 54 | "PxShapeFlag", 55 | "PxArticulationSensorFlag" 56 | ] 57 | ) 58 | .unwrap()); 59 | } 60 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/functions.rs: -------------------------------------------------------------------------------- 1 | struct Functions { 2 | cpp: String, 3 | rust: String, 4 | } 5 | 6 | fn gen_functions(which: &str) -> anyhow::Result { 7 | let (ast, _) = pxbind::get_parsed_ast(format!("tests/data/functions/{which}"))?; 8 | 9 | let mut consumer = pxbind::consumer::AstConsumer::default(); 10 | consumer.consume(&ast)?; 11 | 12 | let record_filter = |_rb: &pxbind::consumer::RecBinding<'_>| false; 13 | let enum_filter = |_eb: &pxbind::consumer::EnumBinding<'_>| false; 14 | let func_filter = |fb: &pxbind::consumer::FuncBinding<'_>| fb.owning_class().is_none(); 15 | 16 | let generator = pxbind::generator::Generator { 17 | record_filter: Box::new(record_filter), 18 | enum_filter: Box::new(enum_filter), 19 | func_filter: Box::new(func_filter), 20 | }; 21 | 22 | let cpp = { 23 | let mut buffer = Vec::new(); 24 | generator.generate_cpp_functions(&consumer, &mut buffer, 0)?; 25 | String::from_utf8(buffer)? 26 | }; 27 | 28 | let rust = { 29 | let mut buffer = Vec::new(); 30 | generator.generate_rust_functions(&consumer, &mut buffer, 0)?; 31 | String::from_utf8(buffer)? 32 | }; 33 | 34 | Ok(Functions { cpp, rust }) 35 | } 36 | 37 | /// Verifies we can collect free functions 38 | #[test] 39 | fn plain_functions() { 40 | let mo = gen_functions("functions.h").unwrap(); 41 | 42 | insta::assert_snapshot!(mo.cpp); 43 | insta::assert_snapshot!(mo.rust); 44 | } 45 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/methods.rs: -------------------------------------------------------------------------------- 1 | struct Functions { 2 | cpp: String, 3 | rust: String, 4 | } 5 | 6 | fn gen_functions(which: &str, to_emit: &'static [&str]) -> anyhow::Result { 7 | let (ast, _) = pxbind::get_parsed_ast(format!("tests/data/functions/{which}"))?; 8 | 9 | let mut consumer = pxbind::consumer::AstConsumer::default(); 10 | consumer.consume(&ast)?; 11 | 12 | let record_filter = |_rb: &pxbind::consumer::RecBinding<'_>| false; 13 | let enum_filter = |_eb: &pxbind::consumer::EnumBinding<'_>| false; 14 | let func_filter = |fb: &pxbind::consumer::FuncBinding<'_>| { 15 | if let Some(cname) = fb.owning_class() { 16 | to_emit.is_empty() || to_emit.iter().any(|te| *te == cname) 17 | } else { 18 | false 19 | } 20 | }; 21 | 22 | let generator = pxbind::generator::Generator { 23 | record_filter: Box::new(record_filter), 24 | enum_filter: Box::new(enum_filter), 25 | func_filter: Box::new(func_filter), 26 | }; 27 | 28 | let cpp = { 29 | let mut buffer = Vec::new(); 30 | generator.generate_cpp_functions(&consumer, &mut buffer, 0)?; 31 | String::from_utf8(buffer)? 32 | }; 33 | 34 | let rust = { 35 | let mut buffer = Vec::new(); 36 | generator.generate_rust_functions(&consumer, &mut buffer, 0)?; 37 | String::from_utf8(buffer)? 38 | }; 39 | 40 | Ok(Functions { cpp, rust }) 41 | } 42 | 43 | /// Verifies that reference fields are reflected in the size and layout, but aren't 44 | /// actually publicly exposed 45 | #[test] 46 | fn methods_complex() { 47 | let mo = gen_functions("methods_complex.h", &["PxShape", "PxThreadImpl"]).unwrap(); 48 | 49 | insta::assert_snapshot!(mo.cpp); 50 | insta::assert_snapshot!(mo.rust); 51 | } 52 | 53 | /// Verifies constructors of various kinds are properly bound, and properly 54 | /// named to avoid clashes 55 | #[test] 56 | fn constructors() { 57 | let mo = gen_functions("constructors.h", &["PxBoxControllerDesc", "PxFilterData"]).unwrap(); 58 | 59 | insta::assert_snapshot!(mo.cpp); 60 | insta::assert_snapshot!(mo.rust); 61 | } 62 | 63 | /// Verifies destructors are properly emitted or omitted 64 | #[test] 65 | fn destructor() { 66 | let mo = gen_functions( 67 | "destructors.h", 68 | &[ 69 | "PxActor", 70 | "PxJointLimitParameters", 71 | "PxJointAngularLimitPair", 72 | ], 73 | ) 74 | .unwrap(); 75 | 76 | insta::assert_snapshot!(mo.cpp); 77 | insta::assert_snapshot!(mo.rust); 78 | } 79 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/records.rs: -------------------------------------------------------------------------------- 1 | struct RecordOutput { 2 | structgen: String, 3 | size_asserts: String, 4 | rust_decls: String, 5 | } 6 | 7 | fn gen_records(which: &str, to_emit: &'static [&str]) -> anyhow::Result { 8 | let (ast, _) = pxbind::get_parsed_ast(format!("tests/data/record/{which}"))?; 9 | 10 | let mut consumer = pxbind::consumer::AstConsumer::default(); 11 | consumer.consume(&ast)?; 12 | 13 | let record_filter = |rb: &pxbind::consumer::RecBinding<'_>| { 14 | to_emit.is_empty() || to_emit.iter().any(|te| rb == *te) 15 | }; 16 | 17 | let generator = pxbind::generator::Generator { 18 | record_filter: Box::new(record_filter), 19 | ..Default::default() 20 | }; 21 | 22 | let structgen = { 23 | let mut sg = Vec::new(); 24 | generator.generate_structgen(&consumer, &mut sg)?; 25 | String::from_utf8(sg)? 26 | }; 27 | 28 | let size_asserts = { 29 | let mut sa = Vec::new(); 30 | generator.generate_size_asserts(&consumer, &mut sa)?; 31 | String::from_utf8(sa)? 32 | }; 33 | 34 | let rust_decls = { 35 | let mut rd = Vec::new(); 36 | generator.generate_rust_records(&consumer, &mut rd)?; 37 | String::from_utf8(rd)? 38 | }; 39 | 40 | Ok(RecordOutput { 41 | structgen, 42 | size_asserts, 43 | rust_decls, 44 | }) 45 | } 46 | 47 | /// Verifies that abstract base classes with no fields are properly bound 48 | #[test] 49 | fn abstract_() { 50 | let ro = gen_records("abstract.h", &[]).unwrap(); 51 | 52 | insta::assert_snapshot!(ro.structgen); 53 | insta::assert_snapshot!(ro.size_asserts); 54 | insta::assert_snapshot!(ro.rust_decls); 55 | } 56 | 57 | /// Verifies that reference fields are reflected in the size and layout, but aren't 58 | /// actually publicly exposed 59 | #[test] 60 | fn ref_fields() { 61 | let ro = gen_records("ref_fields.h", &["PxReffyMcRefface"]).unwrap(); 62 | 63 | insta::assert_snapshot!(ro.structgen); 64 | insta::assert_snapshot!(ro.size_asserts); 65 | insta::assert_snapshot!(ro.rust_decls); 66 | } 67 | 68 | /// Ensures we can generate PODs that wrap types that are only exposed publicly 69 | /// via pointer 70 | #[test] 71 | fn ptr_only() { 72 | let ro = gen_records("ptr_only.h", &[]).unwrap(); 73 | 74 | insta::assert_snapshot!(ro.structgen); 75 | insta::assert_snapshot!(ro.size_asserts); 76 | insta::assert_snapshot!(ro.rust_decls); 77 | } 78 | 79 | /// Ensure we can parse templates, template specializations, and template parameters 80 | /// and stamp out unique types for each template + template param 81 | #[test] 82 | #[ignore] 83 | fn templates() { 84 | let ro = gen_records( 85 | "templates.h", 86 | &[ 87 | "PxRaycastCallback", 88 | "PxOverlapCallback", 89 | "PxSweepCallback", 90 | "PxRaycastBuffer", 91 | "PxOverlapBuffer", 92 | ], 93 | ) 94 | .unwrap(); 95 | 96 | insta::assert_snapshot!(ro.structgen); 97 | insta::assert_snapshot!(ro.size_asserts); 98 | insta::assert_snapshot!(ro.rust_decls); 99 | } 100 | 101 | /// More complicated records with multiple levels of inheritance 102 | #[test] 103 | fn complex() { 104 | let ro = gen_records("complex.h", &[]).unwrap(); 105 | 106 | insta::assert_snapshot!(ro.structgen); 107 | insta::assert_snapshot!(ro.size_asserts); 108 | insta::assert_snapshot!(ro.rust_decls); 109 | } 110 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/enums__i32.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/enums.rs 3 | expression: "gen_enums(\"i32.h\", &[]).unwrap()" 4 | --- 5 | /// Broad phase algorithm used in the simulation 6 | /// 7 | /// eSAP is a good generic choice with great performance when many objects are sleeping. Performance 8 | /// can degrade significantly though, when all objects are moving, or when large numbers of objects 9 | /// are added to or removed from the broad phase. This algorithm does not need world bounds to be 10 | /// defined in order to work. 11 | /// 12 | /// eMBP is an alternative broad phase algorithm that does not suffer from the same performance 13 | /// issues as eSAP when all objects are moving or when inserting large numbers of objects. However 14 | /// its generic performance when many objects are sleeping might be inferior to eSAP, and it requires 15 | /// users to define world bounds in order to work. 16 | /// 17 | /// eABP is a revisited implementation of MBP, which automatically manages broad-phase regions. 18 | /// It offers the convenience of eSAP (no need to define world bounds or regions) and the performance 19 | /// of eMBP when a lot of objects are moving. While eSAP can remain faster when most objects are 20 | /// sleeping and eMBP can remain faster when it uses a large number of properly-defined regions, 21 | /// eABP often gives the best performance on average and the best memory usage. 22 | /// 23 | /// ePABP is a parallel implementation of ABP. It can often be the fastest (CPU) broadphase, but it 24 | /// can use more memory than ABP. 25 | /// 26 | /// eGPU is a GPU implementation of the incremental sweep and prune approach. Additionally, it uses a ABP-style 27 | /// initial pair generation approach to avoid large spikes when inserting shapes. It not only has the advantage 28 | /// of traditional SAP approch which is good for when many objects are sleeping, but due to being fully parallel, 29 | /// it also is great when lots of shapes are moving or for runtime pair insertion and removal. It can become a 30 | /// performance bottleneck if there are a very large number of shapes roughly projecting to the same values 31 | /// on a given axis. If the scene has a very large number of shapes in an actor, e.g. a humanoid, it is recommended 32 | /// to use an aggregate to represent multi-shape or multi-body actors to minimize stress placed on the broad phase. 33 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 34 | #[repr(i32)] 35 | pub enum PxBroadPhaseType { 36 | /// 3-axes sweep-and-prune 37 | Sap = 0, 38 | /// Multi box pruning 39 | Mbp = 1, 40 | /// Automatic box pruning 41 | Abp = 2, 42 | /// Parallel automatic box pruning 43 | Pabp = 3, 44 | /// GPU broad phase 45 | Gpu = 4, 46 | Last = 5, 47 | } 48 | 49 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/enums__simple.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/enums.rs 3 | expression: "gen_enums(\"simple.h\", &[]).unwrap()" 4 | --- 5 | /// enum for empty constructor tag 6 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 7 | #[repr(i32)] 8 | pub enum PxEMPTY { 9 | PxEmpty = 0, 10 | } 11 | 12 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/enums__u32.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/enums.rs 3 | expression: "gen_enums(\"u32.h\", &[]).unwrap()" 4 | --- 5 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 6 | #[repr(u32)] 7 | pub enum PxThreadPriority { 8 | /// High priority 9 | High = 0, 10 | /// Above Normal priority 11 | AboveNormal = 1, 12 | /// Normal/default priority 13 | Normal = 2, 14 | /// Below Normal priority 15 | BelowNormal = 3, 16 | /// Low priority. 17 | Low = 4, 18 | ForceDword = 4294967295, 19 | } 20 | 21 | /// Flags which affect the behavior of PxShapes. 22 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 23 | #[repr(i32)] 24 | pub enum PxShapeFlag { 25 | /// The shape will partake in collision in the physical simulation. 26 | /// 27 | /// It is illegal to raise the eSIMULATION_SHAPE and eTRIGGER_SHAPE flags. 28 | /// In the event that one of these flags is already raised the sdk will reject any 29 | /// attempt to raise the other. To raise the eSIMULATION_SHAPE first ensure that 30 | /// eTRIGGER_SHAPE is already lowered. 31 | /// 32 | /// This flag has no effect if simulation is disabled for the corresponding actor (see [`PxActorFlag::eDISABLE_SIMULATION`]). 33 | SimulationShape = 1, 34 | /// The shape will partake in scene queries (ray casts, overlap tests, sweeps, ...). 35 | SceneQueryShape = 2, 36 | /// The shape is a trigger which can send reports whenever other shapes enter/leave its volume. 37 | /// 38 | /// Triangle meshes and heightfields can not be triggers. Shape creation will fail in these cases. 39 | /// 40 | /// Shapes marked as triggers do not collide with other objects. If an object should act both 41 | /// as a trigger shape and a collision shape then create a rigid body with two shapes, one being a 42 | /// trigger shape and the other a collision shape. It is illegal to raise the eTRIGGER_SHAPE and 43 | /// eSIMULATION_SHAPE flags on a single PxShape instance. In the event that one of these flags is already 44 | /// raised the sdk will reject any attempt to raise the other. To raise the eTRIGGER_SHAPE flag first 45 | /// ensure that eSIMULATION_SHAPE flag is already lowered. 46 | /// 47 | /// Trigger shapes will no longer send notification events for interactions with other trigger shapes. 48 | /// 49 | /// Shapes marked as triggers are allowed to participate in scene queries, provided the eSCENE_QUERY_SHAPE flag is set. 50 | /// 51 | /// This flag has no effect if simulation is disabled for the corresponding actor (see [`PxActorFlag::eDISABLE_SIMULATION`]). 52 | TriggerShape = 4, 53 | /// Enable debug renderer for this shape 54 | Visualization = 8, 55 | } 56 | 57 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/functions__plain_functions-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/functions.rs 3 | expression: mo.rust 4 | --- 5 | extern "C" { 6 | /// Creates a collection object. 7 | /// 8 | /// Objects can only be serialized or deserialized through a collection. 9 | /// For serialization, users must add objects to the collection and serialize the collection as a whole. 10 | /// For deserialization, the system gives back a collection of deserialized objects to users. 11 | /// 12 | /// The new collection object. 13 | pub fn phys_PxCreateCollection() -> *mut PxCollection; 14 | 15 | pub fn phys_PxGetAssertHandler() -> *mut PxAssertHandler; 16 | 17 | pub fn phys_PxSetAssertHandler(handler: *mut PxAssertHandler); 18 | 19 | /// Sets the bytes of the provided buffer to zero. 20 | /// 21 | /// Pointer to memory block (same as input) 22 | pub fn phys_PxMemZero(dest: *mut std::ffi::c_void, count: u32) -> *mut std::ffi::c_void; 23 | 24 | /// Sets the bytes of the provided buffer to the specified value. 25 | /// 26 | /// Pointer to memory block (same as input) 27 | pub fn phys_PxMemSet(dest: *mut std::ffi::c_void, c: i32, count: u32) -> *mut std::ffi::c_void; 28 | 29 | /// Copies the bytes of one memory block to another. The memory blocks must not overlap. 30 | /// 31 | /// Use [`PxMemMove`] if memory blocks overlap. 32 | /// 33 | /// Pointer to destination memory block 34 | pub fn phys_PxMemCopy(dest: *mut std::ffi::c_void, src: *const std::ffi::c_void, count: u32) -> *mut std::ffi::c_void; 35 | 36 | /// Copies the bytes of one memory block to another. The memory blocks can overlap. 37 | /// 38 | /// Use [`PxMemCopy`] if memory blocks do not overlap. 39 | /// 40 | /// Pointer to destination memory block 41 | pub fn phys_PxMemMove(dest: *mut std::ffi::c_void, src: *const std::ffi::c_void, count: u32) -> *mut std::ffi::c_void; 42 | 43 | /// Mark a specified amount of memory with 0xcd pattern. This is used to check that the meta data 44 | /// definition for serialized classes is complete in checked builds. 45 | pub fn phys_PxMarkSerializedMemory(ptr: *mut std::ffi::c_void, byteSize: u32); 46 | 47 | /// For internal use 48 | pub fn phys_PxCustomGeometry_getUniqueID() -> u32; 49 | 50 | pub fn phys_PxGetAggregateFilterHint(type_: PxAggregateType, enableSelfCollision: bool) -> u32; 51 | 52 | pub fn phys_PxGetAggregateSelfCollisionBit(hint: u32) -> u32; 53 | 54 | pub fn phys_PxGetAggregateType(hint: u32) -> PxAggregateType; 55 | 56 | /// Creates an instance of the physics SDK. 57 | /// 58 | /// Creates an instance of this class. May not be a class member to avoid name mangling. 59 | /// Pass the constant [`PX_PHYSICS_VERSION`] as the argument. 60 | /// There may be only one instance of this class per process. Calling this method after an instance 61 | /// has been created already will result in an error message and NULL will be returned. 62 | /// 63 | /// Calling this will register all optional code modules (Articulations and HeightFields), preparing them for use. 64 | /// If you do not need some of these modules, consider calling PxCreateBasePhysics() instead and registering needed 65 | /// modules manually. 66 | /// 67 | /// PxPhysics instance on success, NULL if operation failed 68 | pub fn phys_PxCreatePhysics(version: u32, foundation: *mut PxFoundation, scale: *const PxTolerancesScale, trackOutstandingAllocations: bool, pvd: *mut PxPvd, omniPvd: *mut PxOmniPvd) -> *mut PxPhysics; 69 | 70 | pub fn phys_PxGetPhysics() -> *mut PxPhysics; 71 | 72 | } 73 | 74 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/functions__plain_functions.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/functions.rs 3 | expression: mo.cpp 4 | --- 5 | extern "C" { 6 | physx_PxCollection_Pod* phys_PxCreateCollection() { 7 | physx::PxCollection* return_val = PxCreateCollection(); 8 | auto return_val_pod = reinterpret_cast(return_val); 9 | return return_val_pod; 10 | } 11 | 12 | physx_PxAssertHandler_Pod* phys_PxGetAssertHandler() { 13 | physx::PxAssertHandler& return_val = PxGetAssertHandler(); 14 | auto return_val_pod = reinterpret_cast(&return_val); 15 | return return_val_pod; 16 | } 17 | 18 | void phys_PxSetAssertHandler(physx_PxAssertHandler_Pod* handler_pod) { 19 | physx::PxAssertHandler& handler = reinterpret_cast(*handler_pod); 20 | PxSetAssertHandler(handler); 21 | } 22 | 23 | void* phys_PxMemZero(void* dest, uint32_t count) { 24 | void* return_val = PxMemZero(dest, count); 25 | return return_val; 26 | } 27 | 28 | void* phys_PxMemSet(void* dest, int32_t c, uint32_t count) { 29 | void* return_val = PxMemSet(dest, c, count); 30 | return return_val; 31 | } 32 | 33 | void* phys_PxMemCopy(void* dest, void const* src, uint32_t count) { 34 | void* return_val = PxMemCopy(dest, src, count); 35 | return return_val; 36 | } 37 | 38 | void* phys_PxMemMove(void* dest, void const* src, uint32_t count) { 39 | void* return_val = PxMemMove(dest, src, count); 40 | return return_val; 41 | } 42 | 43 | void phys_PxMarkSerializedMemory(void* ptr, uint32_t byteSize) { 44 | PxMarkSerializedMemory(ptr, byteSize); 45 | } 46 | 47 | uint32_t phys_PxCustomGeometry_getUniqueID() { 48 | uint32_t return_val = PxCustomGeometry_getUniqueID(); 49 | return return_val; 50 | } 51 | 52 | uint32_t phys_PxGetAggregateFilterHint(int32_t type_pod, bool enableSelfCollision) { 53 | auto type = static_cast(type_pod); 54 | uint32_t return_val = PxGetAggregateFilterHint(type, enableSelfCollision); 55 | return return_val; 56 | } 57 | 58 | uint32_t phys_PxGetAggregateSelfCollisionBit(uint32_t hint) { 59 | uint32_t return_val = PxGetAggregateSelfCollisionBit(hint); 60 | return return_val; 61 | } 62 | 63 | int32_t phys_PxGetAggregateType(uint32_t hint) { 64 | physx::PxAggregateType::Enum return_val = PxGetAggregateType(hint); 65 | int32_t return_val_pod; 66 | memcpy(&return_val_pod, &return_val, sizeof(return_val_pod)); 67 | return return_val_pod; 68 | } 69 | 70 | physx_PxPhysics_Pod* phys_PxCreatePhysics(uint32_t version, physx_PxFoundation_Pod* foundation_pod, physx_PxTolerancesScale_Pod const* scale_pod, bool trackOutstandingAllocations, physx_PxPvd_Pod* pvd_pod, physx_PxOmniPvd_Pod* omniPvd_pod) { 71 | physx::PxFoundation& foundation = reinterpret_cast(*foundation_pod); 72 | physx::PxTolerancesScale const& scale = reinterpret_cast(*scale_pod); 73 | physx::PxPvd* pvd = reinterpret_cast(pvd_pod); 74 | physx::PxOmniPvd* omniPvd = reinterpret_cast(omniPvd_pod); 75 | physx::PxPhysics* return_val = PxCreatePhysics(version, foundation, scale, trackOutstandingAllocations, pvd, omniPvd); 76 | auto return_val_pod = reinterpret_cast(return_val); 77 | return return_val_pod; 78 | } 79 | 80 | physx_PxPhysics_Pod* phys_PxGetPhysics() { 81 | physx::PxPhysics& return_val = PxGetPhysics(); 82 | auto return_val_pod = reinterpret_cast(&return_val); 83 | return return_val_pod; 84 | } 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/methods__constructors-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/methods.rs 3 | expression: mo.rust 4 | --- 5 | extern "C" { 6 | pub fn PxFilterData_new(anon_param0: PxEMPTY) -> PxFilterData; 7 | 8 | /// Default constructor. 9 | pub fn PxFilterData_new_1() -> PxFilterData; 10 | 11 | /// Constructor to set filter data initially. 12 | pub fn PxFilterData_new_2(w0: u32, w1: u32, w2: u32, w3: u32) -> PxFilterData; 13 | 14 | /// (re)sets the structure to the default. 15 | pub fn PxFilterData_setToDefault_mut(self_: *mut PxFilterData); 16 | 17 | /// constructor sets to default. 18 | pub fn PxBoxControllerDesc_new_alloc() -> *mut PxBoxControllerDesc; 19 | 20 | pub fn PxBoxControllerDesc_delete(self_: *mut PxBoxControllerDesc); 21 | 22 | /// (re)sets the structure to the default. 23 | pub fn PxBoxControllerDesc_setToDefault_mut(self_: *mut PxBoxControllerDesc); 24 | 25 | /// returns true if the current settings are valid 26 | /// 27 | /// True if the descriptor is valid. 28 | pub fn PxBoxControllerDesc_isValid(self_: *const PxBoxControllerDesc) -> bool; 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/methods__constructors.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/methods.rs 3 | expression: mo.cpp 4 | --- 5 | extern "C" { 6 | physx_PxFilterData_Pod PxFilterData_new(int32_t anon_param0_pod) { 7 | auto anon_param0 = static_cast(anon_param0_pod); 8 | PxFilterData return_val(anon_param0); 9 | physx_PxFilterData_Pod return_val_pod; 10 | memcpy(&return_val_pod, &return_val, sizeof(return_val_pod)); 11 | return return_val_pod; 12 | } 13 | 14 | physx_PxFilterData_Pod PxFilterData_new_1() { 15 | PxFilterData return_val; 16 | physx_PxFilterData_Pod return_val_pod; 17 | memcpy(&return_val_pod, &return_val, sizeof(return_val_pod)); 18 | return return_val_pod; 19 | } 20 | 21 | physx_PxFilterData_Pod PxFilterData_new_2(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3) { 22 | PxFilterData return_val(w0, w1, w2, w3); 23 | physx_PxFilterData_Pod return_val_pod; 24 | memcpy(&return_val_pod, &return_val, sizeof(return_val_pod)); 25 | return return_val_pod; 26 | } 27 | 28 | void PxFilterData_setToDefault_mut(physx_PxFilterData_Pod* self__pod) { 29 | physx::PxFilterData* self_ = reinterpret_cast(self__pod); 30 | self_->setToDefault(); 31 | } 32 | 33 | physx_PxBoxControllerDesc_Pod* PxBoxControllerDesc_new_alloc() { 34 | auto return_val = new physx::PxBoxControllerDesc(); 35 | auto return_val_pod = reinterpret_cast(return_val); 36 | return return_val_pod; 37 | } 38 | 39 | void PxBoxControllerDesc_delete(physx_PxBoxControllerDesc_Pod* self__pod) { 40 | physx::PxBoxControllerDesc* self_ = reinterpret_cast(self__pod); 41 | delete self_; 42 | } 43 | 44 | void PxBoxControllerDesc_setToDefault_mut(physx_PxBoxControllerDesc_Pod* self__pod) { 45 | physx::PxBoxControllerDesc* self_ = reinterpret_cast(self__pod); 46 | self_->setToDefault(); 47 | } 48 | 49 | bool PxBoxControllerDesc_isValid(physx_PxBoxControllerDesc_Pod const* self__pod) { 50 | physx::PxBoxControllerDesc const* self_ = reinterpret_cast(self__pod); 51 | bool return_val = self_->isValid(); 52 | return return_val; 53 | } 54 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/methods__destructor-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/methods.rs 3 | expression: mo.rust 4 | --- 5 | extern "C" { 6 | pub fn PxJointLimitParameters_new_alloc() -> *mut PxJointLimitParameters; 7 | 8 | /// Returns true if the current settings are valid. 9 | /// 10 | /// true if the current settings are valid 11 | pub fn PxJointLimitParameters_isValid(self_: *const PxJointLimitParameters) -> bool; 12 | 13 | pub fn PxJointLimitParameters_isSoft(self_: *const PxJointLimitParameters) -> bool; 14 | 15 | pub fn PxJointAngularLimitPair_new(lowerLimit: f32, upperLimit: f32, contactDist_deprecated: f32) -> PxJointAngularLimitPair; 16 | 17 | /// Returns true if the limit is valid. 18 | /// 19 | /// true if the current settings are valid 20 | pub fn PxJointAngularLimitPair_isValid(self_: *const PxJointAngularLimitPair) -> bool; 21 | 22 | pub fn PxJointAngularLimitPair_delete(self_: *mut PxJointAngularLimitPair); 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/methods__destructor.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/methods.rs 3 | expression: mo.cpp 4 | --- 5 | extern "C" { 6 | physx_PxJointLimitParameters_Pod* PxJointLimitParameters_new_alloc() { 7 | auto return_val = new physx::PxJointLimitParameters(); 8 | auto return_val_pod = reinterpret_cast(return_val); 9 | return return_val_pod; 10 | } 11 | 12 | bool PxJointLimitParameters_isValid(physx_PxJointLimitParameters_Pod const* self__pod) { 13 | physx::PxJointLimitParameters const* self_ = reinterpret_cast(self__pod); 14 | bool return_val = self_->isValid(); 15 | return return_val; 16 | } 17 | 18 | bool PxJointLimitParameters_isSoft(physx_PxJointLimitParameters_Pod const* self__pod) { 19 | physx::PxJointLimitParameters const* self_ = reinterpret_cast(self__pod); 20 | bool return_val = self_->isSoft(); 21 | return return_val; 22 | } 23 | 24 | physx_PxJointAngularLimitPair_Pod PxJointAngularLimitPair_new(float lowerLimit, float upperLimit, float contactDist_deprecated) { 25 | PxJointAngularLimitPair return_val(lowerLimit, upperLimit, contactDist_deprecated); 26 | physx_PxJointAngularLimitPair_Pod return_val_pod; 27 | memcpy(&return_val_pod, &return_val, sizeof(return_val_pod)); 28 | return return_val_pod; 29 | } 30 | 31 | bool PxJointAngularLimitPair_isValid(physx_PxJointAngularLimitPair_Pod const* self__pod) { 32 | physx::PxJointAngularLimitPair const* self_ = reinterpret_cast(self__pod); 33 | bool return_val = self_->isValid(); 34 | return return_val; 35 | } 36 | 37 | void PxJointAngularLimitPair_delete(physx_PxJointAngularLimitPair_Pod* self__pod) { 38 | physx::PxJointAngularLimitPair* self_ = reinterpret_cast(self__pod); 39 | delete self_; 40 | } 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__abstract_-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.size_asserts 4 | --- 5 | using namespace physx; 6 | #include "structgen_out.hpp" 7 | 8 | static_assert(sizeof(physx::PxAllocatorCallback) == sizeof(physx_PxAllocatorCallback_Pod), "POD wrapper for `physx::PxAllocatorCallback` has incorrect size"); 9 | 10 | 11 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__abstract_-3.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.rust_decls 4 | --- 5 | 6 | #[derive(Clone, Copy)] 7 | #[cfg_attr(feature = "debug-structs", derive(Debug))] 8 | #[repr(C)] 9 | pub struct PxAllocatorCallback { 10 | vtable_: *const std::ffi::c_void, 11 | } 12 | 13 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__abstract_.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.structgen 4 | --- 5 | // Automatically generated by pxbind 6 | #include "PxPhysicsAPI.h" 7 | 8 | using namespace physx; 9 | 10 | #define unsafe_offsetof(st, m) ((size_t) ( (char *)&((st *)(0))->m - (char *)0 )) 11 | #include "structgen.hpp" 12 | 13 | int main() { 14 | PodStructGen sg; 15 | sg.pass_thru("struct physx_PxAllocatorCallback_Pod {\n void* vtable_;\n};\n"); 16 | sg.finish(); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__ptr_only-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.size_asserts 4 | --- 5 | using namespace physx; 6 | #include "structgen_out.hpp" 7 | 8 | static_assert(sizeof(physx::PxAllocatorCallback) == sizeof(physx_PxAllocatorCallback_Pod), "POD wrapper for `physx::PxAllocatorCallback` has incorrect size"); 9 | 10 | 11 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__ptr_only-3.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.rust_decls 4 | --- 5 | 6 | #[derive(Clone, Copy)] 7 | #[cfg_attr(feature = "debug-structs", derive(Debug))] 8 | #[repr(C)] 9 | pub struct PxAllocatorCallback { 10 | vtable_: *const std::ffi::c_void, 11 | } 12 | 13 | #[derive(Copy, Clone)] 14 | #[repr(C)] 15 | pub struct MemoryBuffer { 16 | _unused: [u8; 0], 17 | } 18 | 19 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__ptr_only.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.structgen 4 | --- 5 | // Automatically generated by pxbind 6 | #include "PxPhysicsAPI.h" 7 | 8 | using namespace physx; 9 | 10 | #define unsafe_offsetof(st, m) ((size_t) ( (char *)&((st *)(0))->m - (char *)0 )) 11 | #include "structgen.hpp" 12 | 13 | int main() { 14 | PodStructGen sg; 15 | sg.pass_thru("struct physx_PxAllocatorCallback_Pod;\n"); 16 | sg.pass_thru("struct physx_PxAllocatorCallback_Pod {\n void* vtable_;\n};\n"); 17 | sg.pass_thru("struct physx_MemoryBuffer_Pod;\n"); 18 | sg.finish(); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__ref_fields-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.size_asserts 4 | --- 5 | using namespace physx; 6 | #include "structgen_out.hpp" 7 | 8 | static_assert(sizeof(physx::PxReffyMcRefface) == sizeof(physx_PxReffyMcRefface_Pod), "POD wrapper for `physx::PxReffyMcRefface` has incorrect size"); 9 | 10 | 11 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__ref_fields-3.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.rust_decls 4 | --- 5 | 6 | 7 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__ref_fields.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.structgen 4 | --- 5 | // Automatically generated by pxbind 6 | #include "PxPhysicsAPI.h" 7 | 8 | using namespace physx; 9 | 10 | #define unsafe_offsetof(st, m) ((size_t) ( (char *)&((st *)(0))->m - (char *)0 )) 11 | #include "structgen.hpp" 12 | 13 | int main() { 14 | PodStructGen sg; 15 | struct physx_PxReffyMcRefface_Pod: public physx::PxReffyMcRefface { 16 | static void dump_layout(PodStructGen& sg) { 17 | sg.begin_struct("physx_PxReffyMcRefface_Pod", "PxReffyMcRefface"); 18 | sg.add_field("physx_PxVec3_Pod shapeSpaceCenterOfMass", "shapeSpaceCenterOfMass", "PxVec3", sizeof(physx::PxVec3), unsafe_offsetof(physx_PxReffyMcRefface_Pod, shapeSpaceCenterOfMass)); 19 | sg.add_field("bool isIdentityScale", "isIdentityScale", "bool", sizeof(bool), unsafe_offsetof(physx_PxReffyMcRefface_Pod, isIdentityScale)); 20 | sg.end_struct(sizeof(physx::PxReffyMcRefface)); 21 | } 22 | }; 23 | physx_PxReffyMcRefface_Pod::dump_layout(sg); 24 | 25 | sg.finish(); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__simple_templates-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.size_asserts 4 | --- 5 | using namespace physx; 6 | #include "structgen_out.hpp" 7 | 8 | static_assert(sizeof(physx::PxVec3) == sizeof(physx_PxVec3_Pod), "POD wrapper for `physx::PxVec3` has incorrect size"); 9 | static_assert(sizeof(physx::PxVec3Padded) == sizeof(physx_PxVec3Padded_Pod), "POD wrapper for `physx::PxVec3Padded` has incorrect size"); 10 | static_assert(sizeof(physx::PxVec4) == sizeof(physx_PxVec4_Pod), "POD wrapper for `physx::PxVec4` has incorrect size"); 11 | static_assert(sizeof(physx::PxMat44) == sizeof(physx_PxMat44_Pod), "POD wrapper for `physx::PxMat44` has incorrect size"); 12 | static_assert(sizeof(physx::PxQuat) == sizeof(physx_PxQuat_Pod), "POD wrapper for `physx::PxQuat` has incorrect size"); 13 | 14 | 15 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__simple_templates-3.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.rust_decls 4 | --- 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__simple_templates.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.structgen 4 | --- 5 | // Automatically generated by pxbind 6 | #include "PxPhysicsAPI.h" 7 | 8 | using namespace physx; 9 | 10 | #define unsafe_offsetof(st, m) ((size_t) ( (char *)&((st *)(0))->m - (char *)0 )) 11 | #include "structgen.hpp" 12 | 13 | int main() { 14 | PodStructGen sg; 15 | struct physx_PxVec3_Pod: public physx::PxVec3 { 16 | static void dump_layout(PodStructGen& sg) { 17 | sg.begin_struct("physx_PxVec3_Pod", "PxVec3"); 18 | sg.add_field("float x", "x", "f32", sizeof(float), unsafe_offsetof(physx_PxVec3_Pod, x)); 19 | sg.add_field("float y", "y", "f32", sizeof(float), unsafe_offsetof(physx_PxVec3_Pod, y)); 20 | sg.add_field("float z", "z", "f32", sizeof(float), unsafe_offsetof(physx_PxVec3_Pod, z)); 21 | sg.end_struct(sizeof(physx::PxVec3)); 22 | } 23 | }; 24 | physx_PxVec3_Pod::dump_layout(sg); 25 | 26 | struct physx_PxVec3Padded_Pod: public physx::PxVec3Padded { 27 | static void dump_layout(PodStructGen& sg) { 28 | sg.begin_struct("physx_PxVec3Padded_Pod", "PxVec3Padded"); 29 | sg.add_field("float x", "x", "f32", sizeof(float), unsafe_offsetof(physx_PxVec3Padded_Pod, x)); 30 | sg.add_field("float y", "y", "f32", sizeof(float), unsafe_offsetof(physx_PxVec3Padded_Pod, y)); 31 | sg.add_field("float z", "z", "f32", sizeof(float), unsafe_offsetof(physx_PxVec3Padded_Pod, z)); 32 | sg.add_field("uint32_t padding", "padding", "u32", sizeof(uint32_t), unsafe_offsetof(physx_PxVec3Padded_Pod, padding)); 33 | sg.end_struct(sizeof(physx::PxVec3Padded)); 34 | } 35 | }; 36 | physx_PxVec3Padded_Pod::dump_layout(sg); 37 | 38 | struct physx_PxVec4_Pod: public physx::PxVec4 { 39 | static void dump_layout(PodStructGen& sg) { 40 | sg.begin_struct("physx_PxVec4_Pod", "PxVec4"); 41 | sg.add_field("float x", "x", "f32", sizeof(float), unsafe_offsetof(physx_PxVec4_Pod, x)); 42 | sg.add_field("float y", "y", "f32", sizeof(float), unsafe_offsetof(physx_PxVec4_Pod, y)); 43 | sg.add_field("float z", "z", "f32", sizeof(float), unsafe_offsetof(physx_PxVec4_Pod, z)); 44 | sg.add_field("float w", "w", "f32", sizeof(float), unsafe_offsetof(physx_PxVec4_Pod, w)); 45 | sg.end_struct(sizeof(physx::PxVec4)); 46 | } 47 | }; 48 | physx_PxVec4_Pod::dump_layout(sg); 49 | 50 | struct physx_PxMat44_Pod: public physx::PxMat44 { 51 | static void dump_layout(PodStructGen& sg) { 52 | sg.begin_struct("physx_PxMat44_Pod", "PxMat44"); 53 | sg.add_field("physx_PxVec4_Pod column0", "column0", "glam::Vec4", sizeof(physx::PxVec4), unsafe_offsetof(physx_PxMat44_Pod, column0)); 54 | sg.add_field("physx_PxVec4_Pod column1", "column1", "glam::Vec4", sizeof(physx::PxVec4), unsafe_offsetof(physx_PxMat44_Pod, column1)); 55 | sg.add_field("physx_PxVec4_Pod column2", "column2", "glam::Vec4", sizeof(physx::PxVec4), unsafe_offsetof(physx_PxMat44_Pod, column2)); 56 | sg.add_field("physx_PxVec4_Pod column3", "column3", "glam::Vec4", sizeof(physx::PxVec4), unsafe_offsetof(physx_PxMat44_Pod, column3)); 57 | sg.end_struct(sizeof(physx::PxMat44)); 58 | } 59 | }; 60 | physx_PxMat44_Pod::dump_layout(sg); 61 | 62 | struct physx_PxQuat_Pod: public physx::PxQuat { 63 | static void dump_layout(PodStructGen& sg) { 64 | sg.begin_struct("physx_PxQuat_Pod", "PxQuat"); 65 | sg.add_field("float x", "x", "f32", sizeof(float), unsafe_offsetof(physx_PxQuat_Pod, x)); 66 | sg.add_field("float y", "y", "f32", sizeof(float), unsafe_offsetof(physx_PxQuat_Pod, y)); 67 | sg.add_field("float z", "z", "f32", sizeof(float), unsafe_offsetof(physx_PxQuat_Pod, z)); 68 | sg.add_field("float w", "w", "f32", sizeof(float), unsafe_offsetof(physx_PxQuat_Pod, w)); 69 | sg.end_struct(sizeof(physx::PxQuat)); 70 | } 71 | }; 72 | physx_PxQuat_Pod::dump_layout(sg); 73 | 74 | sg.finish(); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__templates-2.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.size_asserts 4 | --- 5 | using namespace physx; 6 | #include "structgen_out.hpp" 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__templates-3.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.rust_decls 4 | --- 5 | 6 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/snapshots/records__templates.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: physx-sys/pxbind/tests/records.rs 3 | expression: ro.structgen 4 | --- 5 | // Automatically generated by pxbind 6 | #include "PxPhysicsAPI.h" 7 | 8 | using namespace physx; 9 | 10 | #define unsafe_offsetof(st, m) ((size_t) ( (char *)&((st *)(0))->m - (char *)0 )) 11 | #include "structgen.hpp" 12 | 13 | int main() { 14 | PodStructGen sg; 15 | sg.finish(); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/structgen.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct RustCheck { 7 | const char* rname; 8 | uint32_t size; 9 | }; 10 | 11 | struct PodStructGen { 12 | PodStructGen() { 13 | cfile = fopen("structgen_out.hpp", "w"); 14 | rfile = fopen("structgen_out.rs", "w"); 15 | } 16 | 17 | void finish() { 18 | fclose(cfile); 19 | 20 | fputs("#[cfg(test)]\nmod sizes {\n #[test]\n fn check_sizes() {\n", rfile); 21 | for (const auto& rc : rust_checks) { 22 | fprintf( 23 | rfile, 24 | " assert_eq!(std::mem::size_of::<%s>(), %u);\n", 25 | rc.rname, 26 | rc.size 27 | ); 28 | } 29 | fputs(" }\n}\n", rfile); 30 | fclose(rfile); 31 | } 32 | 33 | void pass_thru(const char* code) { fputs(code, cfile); } 34 | 35 | void begin_struct(const char* cname, const char* rname) { 36 | fprintf(cfile, "struct %s {\n", cname); 37 | 38 | fprintf(rfile, "#[derive(Clone, Copy)]\n"); 39 | fprintf(rfile, "#[repr(C)]\n"); 40 | fprintf(rfile, "pub struct %s {\n", rname); 41 | 42 | this->rname = rname; 43 | pos = 0; 44 | padIdx = 0; 45 | } 46 | 47 | void emit_padding(uint32_t bytes) { 48 | fprintf(cfile, " char structgen_pad%u[%u];\n", padIdx, bytes); 49 | fprintf(rfile, " pub structgen_pad%u: [u8; %u],\n", padIdx, bytes); 50 | ++padIdx; 51 | } 52 | 53 | void add_field( 54 | const char* cppDecl, 55 | const char* rustName, 56 | const char* rustType, 57 | size_t size, 58 | size_t offset) { 59 | assert(offset >= pos); 60 | if (offset > pos) { 61 | emit_padding(uint32_t(offset - pos)); 62 | pos = offset; 63 | } 64 | fprintf(cfile, " %s;\n", cppDecl); 65 | fprintf(rfile, " pub %s: %s,\n", rustName, rustType); 66 | pos += size; 67 | } 68 | 69 | void end_struct(size_t size) { 70 | assert(size >= pos); 71 | if (size > pos) { 72 | emit_padding(uint32_t(size - pos)); 73 | } 74 | fputs("};\n", cfile); 75 | fputs("}\n", rfile); 76 | 77 | rust_checks.emplace_back(RustCheck { rname, uint32_t(size) }); 78 | } 79 | 80 | private: 81 | std::vector rust_checks; 82 | FILE* cfile; 83 | FILE* rfile; 84 | const char* rname; 85 | size_t pos; 86 | uint32_t padIdx; 87 | }; 88 | -------------------------------------------------------------------------------- /physx-sys/pxbind/tests/structgen.rs: -------------------------------------------------------------------------------- 1 | fn gen_structgen(which: &str, _to_emit: &'static [&str]) -> anyhow::Result { 2 | let (ast, _) = pxbind::get_parsed_ast(format!("tests/data/{which}"))?; 3 | 4 | let mut consumer = pxbind::consumer::AstConsumer::default(); 5 | consumer.consume(&ast)?; 6 | 7 | let record_filter = |rb: &pxbind::consumer::RecBinding<'_>| rb.name().starts_with("Px"); 8 | 9 | let generator = pxbind::generator::Generator { 10 | record_filter: Box::new(record_filter), 11 | ..Default::default() 12 | }; 13 | 14 | let structgen = { 15 | let mut sg = Vec::new(); 16 | generator.generate_structgen(&consumer, &mut sg)?; 17 | String::from_utf8(sg)? 18 | }; 19 | 20 | Ok(structgen) 21 | } 22 | 23 | struct StructgenOut { 24 | cpp: String, 25 | rust: String, 26 | } 27 | 28 | fn run_structgen(sg: String) -> anyhow::Result { 29 | let td = tempfile::tempdir()?; 30 | let tp = td.path(); 31 | let sg_src = tp.join("structgen.cpp"); 32 | 33 | std::fs::write(&sg_src, sg)?; 34 | std::fs::copy("tests/structgen.hpp", tp.join("structgen.hpp"))?; 35 | 36 | // Compile the structgen program for the host target 37 | let mut cmd = std::process::Command::new("clang++"); 38 | cmd.current_dir(&td); 39 | 40 | let include_dir = pxbind::get_include_dir()?; 41 | cmd.args([ 42 | "-fuse-ld=lld", 43 | "-std=c++11", 44 | "-fcolor-diagnostics", 45 | "-o", 46 | "structgen", 47 | "-DNDEBUG", 48 | "-I", 49 | ]); 50 | cmd.arg(include_dir); 51 | cmd.arg(&sg_src); 52 | 53 | anyhow::ensure!(cmd.status()?.success(), "failed to compile structgen"); 54 | 55 | let mut sg = std::process::Command::new(tp.join("structgen")); 56 | sg.current_dir(tp); 57 | 58 | anyhow::ensure!(sg.status()?.success(), "failed to run structgen"); 59 | 60 | let cpp = std::fs::read_to_string(tp.join("structgen_out.hpp"))?; 61 | let rust = std::fs::read_to_string(tp.join("structgen_out.rs"))?; 62 | 63 | Ok(StructgenOut { cpp, rust }) 64 | } 65 | 66 | #[test] 67 | fn many_things() { 68 | let sg = gen_structgen("functions/methods_complex.h", &[]).unwrap(); 69 | 70 | insta::assert_snapshot!(sg); 71 | 72 | let generated = run_structgen(sg).unwrap(); 73 | 74 | insta::assert_snapshot!(generated.cpp); 75 | insta::assert_snapshot!(generated.rust); 76 | } 77 | 78 | #[test] 79 | fn all_the_things() { 80 | let sg = gen_structgen("all_the_things.h", &[]).unwrap(); 81 | 82 | insta::assert_snapshot!(sg); 83 | 84 | let generated = run_structgen(sg).unwrap(); 85 | 86 | insta::assert_snapshot!(generated.cpp); 87 | insta::assert_snapshot!(generated.rust); 88 | } 89 | -------------------------------------------------------------------------------- /physx-sys/release.toml: -------------------------------------------------------------------------------- 1 | pre-release-commit-message = "Release {{crate_name}} v{{version}}" 2 | tag-message = "Release {{crate_name}} {{version}}" 3 | tag-name = "{{crate_name}}-v{{version}}" 4 | pre-release-replacements = [ 5 | { file = "CHANGELOG.md", search = "Unreleased", replace = "{{version}}" }, 6 | { file = "CHANGELOG.md", search = "\\.\\.\\.HEAD", replace = "...{{tag_name}}" }, 7 | { file = "CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}" }, 8 | { file = "CHANGELOG.md", search = "", replace = "\n## [Unreleased] - ReleaseDate" }, 9 | { file = "CHANGELOG.md", search = "", replace = "\n[Unreleased]: https://github.com/EmbarkStudios/physx-rs/compare/{{tag_name}}...HEAD" }, 10 | ] 11 | -------------------------------------------------------------------------------- /physx-sys/sources/common: -------------------------------------------------------------------------------- 1 | [ 2 | "CmCollection", 3 | "CmPtrTable", 4 | "CmRadixSort", 5 | "CmSerialize", 6 | "CmVisualization", 7 | ] -------------------------------------------------------------------------------- /physx-sys/sources/cooking: -------------------------------------------------------------------------------- 1 | [ 2 | "Cooking", 3 | ] -------------------------------------------------------------------------------- /physx-sys/sources/cooking_convex: -------------------------------------------------------------------------------- 1 | [ 2 | "BigConvexDataBuilder", 3 | "ConvexHullBuilder", 4 | "ConvexHullLib", 5 | "ConvexHullUtils", 6 | "ConvexMeshBuilder", 7 | "ConvexPolygonsBuilder", 8 | "QuickHullConvexHullLib", 9 | "VolumeIntegration", 10 | ] 11 | -------------------------------------------------------------------------------- /physx-sys/sources/core: -------------------------------------------------------------------------------- 1 | [ 2 | "NpActor", 3 | "NpAggregate", 4 | "NpArticulationJointReducedCoordinate", 5 | "NpArticulationLink", 6 | "NpArticulationReducedCoordinate", 7 | "NpArticulationSensor", 8 | "NpArticulationTendon", 9 | "NpBounds", 10 | "NpCheck", 11 | "NpConstraint", 12 | "NpDebugViz", 13 | "NpFactory", 14 | "NpFEMCloth", 15 | "NpFEMClothMaterial", 16 | "NpFEMSoftBodyMaterial", 17 | "NpFLIPMaterial", 18 | "NpHairSystem", 19 | "NpMaterial", 20 | "NpMetaData", 21 | "NpMPMMaterial", 22 | "NpParticleSystem", 23 | "NpPBDMaterial", 24 | "NpPhysics", 25 | "NpPruningStructure", 26 | "NpPvdSceneClient", 27 | "NpPvdSceneQueryCollector", 28 | "NpRigidDynamic", 29 | "NpRigidStatic", 30 | "NpScene", 31 | "NpSceneFetchResults", 32 | "NpSceneQueries", 33 | "NpSerializerAdapter", 34 | "NpShape", 35 | "NpShapeManager", 36 | "NpSoftBody", 37 | "PvdMetaDataPvdBinding", 38 | "PvdPhysicsClient", 39 | ] 40 | -------------------------------------------------------------------------------- /physx-sys/sources/extensions: -------------------------------------------------------------------------------- 1 | [ 2 | "ExtBroadPhase", 3 | "ExtCollection", 4 | "ExtContactJoint", 5 | "ExtConvexMeshExt", 6 | "ExtCpuWorkerThread", 7 | "ExtCustomGeometryExt", 8 | "ExtCustomSceneQuerySystem", 9 | "ExtD6Joint", 10 | "ExtD6JointCreate", 11 | "ExtDefaultCpuDispatcher", 12 | "ExtDefaultErrorCallback", 13 | "ExtDefaultSimulationFilterShader", 14 | "ExtDefaultStreams", 15 | "ExtDistanceJoint", 16 | "ExtExtensions", 17 | "ExtFixedJoint", 18 | "ExtGearJoint", 19 | "ExtGjkQueryExt", 20 | "ExtJoint", 21 | "ExtMetaData", 22 | "ExtPrismaticJoint", 23 | "ExtPvd", 24 | "ExtPxStringTable", 25 | "ExtRackAndPinionJoint", 26 | "ExtRaycastCCD", 27 | "ExtRemeshingExt", 28 | "ExtRevoluteJoint", 29 | "ExtRigidActorExt", 30 | "ExtRigidBodyExt", 31 | "ExtSampling", 32 | "ExtSceneQueryExt", 33 | "ExtSceneQuerySystem", 34 | "ExtSimpleFactory", 35 | "ExtSmoothNormals", 36 | "ExtSoftBodyExt", 37 | "ExtSphericalJoint", 38 | "ExtSqManager", 39 | "ExtSqQuery", 40 | "ExtTetMakerExt", 41 | "ExtTetrahedronMeshExt", 42 | "ExtTriangleMeshExt", 43 | ] 44 | -------------------------------------------------------------------------------- /physx-sys/sources/extensions_binary: -------------------------------------------------------------------------------- 1 | [ 2 | "SnBinaryDeserialization", 3 | "SnBinarySerialization", 4 | "SnConvX", 5 | "SnConvX_Align", 6 | "SnConvX_Convert", 7 | "SnConvX_Error", 8 | "SnConvX_MetaData", 9 | "SnConvX_Output", 10 | "SnConvX_Union", 11 | "SnSerializationContext", 12 | ] 13 | -------------------------------------------------------------------------------- /physx-sys/sources/extensions_serialization: -------------------------------------------------------------------------------- 1 | [ 2 | "SnSerialization", 3 | "SnSerializationRegistry", 4 | "SnSerialUtils", 5 | ] 6 | -------------------------------------------------------------------------------- /physx-sys/sources/extensions_tet: -------------------------------------------------------------------------------- 1 | [ 2 | "ExtBVH", 3 | "ExtDelaunayBoundaryInserter", 4 | "ExtDelaunayTetrahedralizer", 5 | "ExtFastWindingNumber", 6 | "ExtInsideTester", 7 | "ExtMeshSimplificator", 8 | "ExtOctreeTetrahedralizer", 9 | "ExtRemesher", 10 | "ExtTetSplitting", 11 | "ExtTetUnionFind", 12 | "ExtUtilities", 13 | "ExtVoxelTetrahedralizer", 14 | ] -------------------------------------------------------------------------------- /physx-sys/sources/extensions_xml: -------------------------------------------------------------------------------- 1 | [ 2 | "SnJointRepXSerializer", 3 | "SnRepXCoreSerializer", 4 | "SnRepXUpgrader", 5 | "SnXmlSerialization", 6 | ] 7 | -------------------------------------------------------------------------------- /physx-sys/sources/fastxml: -------------------------------------------------------------------------------- 1 | ["PsFastXml"] 2 | -------------------------------------------------------------------------------- /physx-sys/sources/foundation: -------------------------------------------------------------------------------- 1 | [ 2 | "FdAllocator", 3 | "FdAssert", 4 | "FdFoundation", 5 | "FdMathUtils", 6 | "FdString", 7 | "FdTempAllocator", 8 | ] -------------------------------------------------------------------------------- /physx-sys/sources/foundation_unix: -------------------------------------------------------------------------------- 1 | [ 2 | "FdUnixAtomic", 3 | "FdUnixFPU", 4 | "FdUnixMutex", 5 | "FdUnixPrintString", 6 | "FdUnixSList", 7 | "FdUnixSocket", 8 | "FdUnixSync", 9 | "FdUnixThread", 10 | "FdUnixTime", 11 | ] -------------------------------------------------------------------------------- /physx-sys/sources/foundation_windows: -------------------------------------------------------------------------------- 1 | [ 2 | "FdWindowsAtomic", 3 | "FdWindowsFPU", 4 | "FdWindowsMutex", 5 | "FdWindowsPrintString", 6 | "FdWindowsSList", 7 | "FdWindowsSocket", 8 | "FdWindowsSync", 9 | "FdWindowsThread", 10 | "FdWindowsTime", 11 | ] -------------------------------------------------------------------------------- /physx-sys/sources/geomutils: -------------------------------------------------------------------------------- 1 | [ 2 | "GuAABBPruner", 3 | "GuAABBTree", 4 | "GuAABBTreeUpdateMap", 5 | "GuActorShapeMap", 6 | "GuBounds", 7 | "GuBox", 8 | "GuBucketPruner", 9 | "GuBVH", 10 | "GuCapsule", 11 | "GuCCTSweepTests", 12 | "GuCookingSDF", 13 | "GuExtendedBucketPruner", 14 | "GuFactory", 15 | "GuGeometryQuery", 16 | "GuGjkQuery", 17 | "GuIncrementalAABBPrunerCore", 18 | "GuIncrementalAABBPruner", 19 | "GuIncrementalAABBTree", 20 | "GuInternal", 21 | "GuMaverickNode", 22 | "GuMeshFactory", 23 | "GuMetaData", 24 | "GuMTD", 25 | "GuOverlapTests", 26 | "GuPruningPool", 27 | "GuQuerySystem", 28 | "GuRaycastTests", 29 | "GuSAH", 30 | "GuSDF", 31 | "GuSecondaryPruner", 32 | "GuSqInternal", 33 | "GuSweepMTD", 34 | "GuSweepSharedTests", 35 | "GuSweepTests", 36 | "GuWindingNumber", 37 | ] 38 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_ccd: -------------------------------------------------------------------------------- 1 | [ 2 | "GuCCDSweepConvexMesh", 3 | "GuCCDSweepPrimitives", 4 | ] -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_common: -------------------------------------------------------------------------------- 1 | [ 2 | "GuAdjacencies", 3 | "GuBarycentricCoordinates", 4 | "GuEdgeList", 5 | "GuMeshAnalysis", 6 | "GuMeshCleaner", 7 | "GuQuantizer", 8 | "GuSeparatingAxes", 9 | "GuVertexReducer", 10 | ] 11 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_contact: -------------------------------------------------------------------------------- 1 | [ 2 | "GuContactBoxBox", 3 | "GuContactCapsuleBox", 4 | "GuContactCapsuleCapsule", 5 | "GuContactCapsuleConvex", 6 | "GuContactCapsuleMesh", 7 | "GuContactConvexConvex", 8 | "GuContactConvexMesh", 9 | "GuContactCustomGeometry", 10 | "GuContactPlaneBox", 11 | "GuContactPlaneCapsule", 12 | "GuContactPlaneConvex", 13 | "GuContactPolygonPolygon", 14 | "GuContactSphereBox", 15 | "GuContactSphereCapsule", 16 | "GuContactSphereMesh", 17 | "GuContactSpherePlane", 18 | "GuContactSphereSphere", 19 | "GuFeatureCode", 20 | ] 21 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_convex: -------------------------------------------------------------------------------- 1 | [ 2 | "GuBigConvexData", 3 | "GuConvexHelper", 4 | "GuConvexMesh", 5 | "GuConvexSupportTable", 6 | "GuConvexUtilsInternal", 7 | "GuHillClimbing", 8 | "GuShapeConvex", 9 | ] -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_cooking: -------------------------------------------------------------------------------- 1 | [ 2 | "GuCookingBigConvexDataBuilder", 3 | "GuCookingBVH", 4 | "GuCookingConvexHullBuilder", 5 | "GuCookingConvexHullLib", 6 | "GuCookingConvexHullUtils", 7 | "GuCookingConvexMeshBuilder", 8 | "GuCookingConvexMesh", 9 | "GuCookingConvexPolygonsBuilder", 10 | "GuCookingHF", 11 | "GuCookingQuickHullConvexHullLib", 12 | "GuCookingTetrahedronMesh", 13 | "GuCookingTriangleMesh", 14 | "GuCookingVolumeIntegration", 15 | "GuRTreeCooking", 16 | ] 17 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_distance: -------------------------------------------------------------------------------- 1 | [ 2 | "GuDistancePointBox", 3 | "GuDistancePointTetrahedron", 4 | "GuDistancePointTriangle", 5 | "GuDistanceSegmentBox", 6 | "GuDistanceSegmentSegment", 7 | "GuDistanceSegmentTriangle", 8 | ] 9 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_gjk: -------------------------------------------------------------------------------- 1 | [ 2 | "GuEPA", 3 | "GuGJKSimplex", 4 | "GuGJKTest", 5 | ] 6 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_hf: -------------------------------------------------------------------------------- 1 | [ 2 | "GuHeightField", 3 | "GuHeightFieldUtil", 4 | "GuOverlapTestsHF", 5 | "GuSweepsHF", 6 | ] 7 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_intersection: -------------------------------------------------------------------------------- 1 | [ 2 | "GuIntersectionBoxBox", 3 | "GuIntersectionCapsuleTriangle", 4 | "GuIntersectionEdgeEdge", 5 | "GuIntersectionRayBox", 6 | "GuIntersectionRayCapsule", 7 | "GuIntersectionRaySphere", 8 | "GuIntersectionSphereBox", 9 | "GuIntersectionTetrahedronBox", 10 | "GuIntersectionTriangleBox", 11 | "GuIntersectionTriangleTriangle", 12 | ] 13 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_mesh: -------------------------------------------------------------------------------- 1 | [ 2 | "GuBV32Build", 3 | "GuBV32", 4 | "GuBV4_AABBSweep", 5 | "GuBV4_BoxOverlap", 6 | "GuBV4Build", 7 | "GuBV4_CapsuleSweepAA", 8 | "GuBV4_CapsuleSweep", 9 | "GuBV4", 10 | "GuBV4_MeshMeshOverlap", 11 | "GuBV4_OBBSweep", 12 | "GuBV4_Raycast", 13 | "GuBV4_SphereOverlap", 14 | "GuBV4_SphereSweep", 15 | "GuMeshQuery", 16 | "GuMidphaseBV4", 17 | "GuMidphaseRTree", 18 | "GuOverlapTestsMesh", 19 | "GuRTree", 20 | "GuRTreeQueries", 21 | "GuSweepsMesh", 22 | "GuTetrahedronMesh", 23 | "GuTriangleMeshBV4", 24 | "GuTriangleMesh", 25 | "GuTriangleMeshRTree", 26 | ] 27 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_pcm: -------------------------------------------------------------------------------- 1 | [ 2 | "GuPCMContactBoxBox", 3 | "GuPCMContactBoxConvex", 4 | "GuPCMContactCapsuleBox", 5 | "GuPCMContactCapsuleCapsule", 6 | "GuPCMContactCapsuleConvex", 7 | "GuPCMContactCapsuleHeightField", 8 | "GuPCMContactCapsuleMesh", 9 | "GuPCMContactConvexCommon", 10 | "GuPCMContactConvexConvex", 11 | "GuPCMContactConvexHeightField", 12 | "GuPCMContactConvexMesh", 13 | "GuPCMContactCustomGeometry", 14 | "GuPCMContactGenBoxConvex", 15 | "GuPCMContactGenSphereCapsule", 16 | "GuPCMContactGenUtil", 17 | "GuPCMContactPlaneBox", 18 | "GuPCMContactPlaneCapsule", 19 | "GuPCMContactPlaneConvex", 20 | "GuPCMContactSphereBox", 21 | "GuPCMContactSphereCapsule", 22 | "GuPCMContactSphereConvex", 23 | "GuPCMContactSphereHeightField", 24 | "GuPCMContactSphereMesh", 25 | "GuPCMContactSpherePlane", 26 | "GuPCMContactSphereSphere", 27 | "GuPCMShapeConvex", 28 | "GuPCMTriangleContactGen", 29 | "GuPersistentContactManifold", 30 | ] 31 | -------------------------------------------------------------------------------- /physx-sys/sources/geomutils_sweep: -------------------------------------------------------------------------------- 1 | [ 2 | "GuSweepBoxBox", 3 | "GuSweepBoxSphere", 4 | "GuSweepBoxTriangle_FeatureBased", 5 | "GuSweepBoxTriangle_SAT", 6 | "GuSweepCapsuleBox", 7 | "GuSweepCapsuleCapsule", 8 | "GuSweepCapsuleTriangle", 9 | "GuSweepSphereCapsule", 10 | "GuSweepSphereSphere", 11 | "GuSweepSphereTriangle", 12 | "GuSweepTriangleUtils", 13 | ] 14 | -------------------------------------------------------------------------------- /physx-sys/sources/lowlevel_pipeline: -------------------------------------------------------------------------------- 1 | [ 2 | "PxcContactCache", 3 | "PxcContactMethodImpl", 4 | "PxcMaterialMethodImpl", 5 | "PxcNpBatch", 6 | "PxcNpCacheStreamPair", 7 | "PxcNpContactPrepShared", 8 | "PxcNpMemBlockPool", 9 | "PxcNpThreadContext", 10 | ] -------------------------------------------------------------------------------- /physx-sys/sources/lowlevel_software: -------------------------------------------------------------------------------- 1 | [ 2 | "PxsCCD", 3 | "PxsContactManager", 4 | "PxsContext", 5 | "PxsDefaultMemoryManager", 6 | "PxsIslandSim", 7 | "PxsNphaseImplementationContext", 8 | "PxsSimpleIslandManager", 9 | ] -------------------------------------------------------------------------------- /physx-sys/sources/lowlevelaabb: -------------------------------------------------------------------------------- 1 | [ 2 | "BpAABBManagerBase", 3 | "BpAABBManager", 4 | "BpBroadPhaseABP", 5 | "BpBroadPhase", 6 | "BpBroadPhaseMBP", 7 | "BpBroadPhaseSapAux", 8 | "BpBroadPhaseSap", 9 | "BpBroadPhaseShared", 10 | "BpBroadPhaseUpdate", 11 | "BpFiltering", 12 | ] 13 | -------------------------------------------------------------------------------- /physx-sys/sources/lowleveldynamics: -------------------------------------------------------------------------------- 1 | [ 2 | "DyArticulationContactPrep", 3 | "DyArticulationContactPrepPF", 4 | "DyFeatherstoneArticulation", 5 | "DyFeatherstoneForwardDynamic", 6 | "DyFeatherstoneInverseDynamic", 7 | "DyConstraintPartition", 8 | "DyConstraintSetup", 9 | "DyConstraintSetupBlock", 10 | "DyContactPrep", 11 | "DyContactPrep4", 12 | "DyContactPrep4PF", 13 | "DyContactPrepPF", 14 | "DyDynamics", 15 | "DyFrictionCorrelation", 16 | "DyRigidBodyToSolverBody", 17 | "DySolverConstraints", 18 | "DySolverConstraintsBlock", 19 | "DySolverControl", 20 | "DySolverControlPF", 21 | "DySolverPFConstraints", 22 | "DySolverPFConstraintsBlock", 23 | "DyThreadContext", 24 | "DyThresholdTable", 25 | "DyTGSDynamics", 26 | "DyTGSContactPrep", 27 | "DyTGSContactPrepBlock", 28 | ] -------------------------------------------------------------------------------- /physx-sys/sources/physxcharacterkinematic: -------------------------------------------------------------------------------- 1 | [ 2 | "CctBoxController", 3 | "CctCapsuleController", 4 | "CctCharacterController", 5 | "CctCharacterControllerCallbacks", 6 | "CctCharacterControllerManager", 7 | "CctController", 8 | "CctObstacleContext", 9 | "CctSweptBox", 10 | "CctSweptCapsule", 11 | "CctSweptVolume", 12 | ] -------------------------------------------------------------------------------- /physx-sys/sources/pvd: -------------------------------------------------------------------------------- 1 | [ 2 | "PxProfileEventImpl", 3 | "PxPvd", 4 | "PxPvdDataStream", 5 | "PxPvdDefaultFileTransport", 6 | "PxPvdDefaultSocketTransport", 7 | "PxPvdImpl", 8 | "PxPvdMemClient", 9 | "PxPvdObjectModelMetaData", 10 | "PxPvdObjectRegistrar", 11 | "PxPvdProfileZoneClient", 12 | "PxPvdUserRenderer", 13 | ] 14 | -------------------------------------------------------------------------------- /physx-sys/sources/scenequery: -------------------------------------------------------------------------------- 1 | [ 2 | "SqCompoundPruner", 3 | "SqCompoundPruningPool", 4 | "SqFactory", 5 | "SqManager", 6 | "SqQuery", 7 | ] 8 | -------------------------------------------------------------------------------- /physx-sys/sources/simulationcontroller: -------------------------------------------------------------------------------- 1 | [ 2 | "ScActorCore", 3 | "ScActorSim", 4 | "ScArticulationCore", 5 | "ScArticulationJointCore", 6 | "ScArticulationJointSim", 7 | "ScArticulationSensorSim", 8 | "ScArticulationSim", 9 | "ScArticulationTendonCore", 10 | "ScArticulationTendonJointCore", 11 | "ScArticulationTendonSim", 12 | "ScBodyCore", 13 | "ScBodySim", 14 | "ScCCD", 15 | "ScConstraintCore", 16 | "ScConstraintGroupNode", 17 | "ScConstraintInteraction", 18 | "ScConstraintProjectionManager", 19 | "ScConstraintProjectionTree", 20 | "ScConstraintSim", 21 | "ScElementInteractionMarker", 22 | "ScElementSim", 23 | "ScFEMClothCore", 24 | "ScFEMClothShapeSim", 25 | "ScFEMClothSim", 26 | "ScHairSystemCore", 27 | "ScHairSystemShapeCore", 28 | "ScHairSystemShapeSim", 29 | "ScHairSystemSim", 30 | "ScInteraction", 31 | "ScIterators", 32 | "ScMetaData", 33 | "ScNPhaseCore", 34 | "ScParticleSystemCore", 35 | "ScParticleSystemShapeCore", 36 | "ScParticleSystemShapeSim", 37 | "ScParticleSystemSim", 38 | "ScPhysics", 39 | "ScRigidCore", 40 | "ScRigidSim", 41 | "ScScene", 42 | "ScShapeCore", 43 | "ScShapeInteraction", 44 | "ScShapeSimBase", 45 | "ScShapeSim", 46 | "ScSimStats", 47 | "ScSimulationController", 48 | "ScSoftBodyCore", 49 | "ScSoftBodyShapeSim", 50 | "ScSoftBodySim", 51 | "ScSqBoundsManager", 52 | "ScStaticCore", 53 | "ScTriggerInteraction", 54 | ] 55 | -------------------------------------------------------------------------------- /physx-sys/sources/task: -------------------------------------------------------------------------------- 1 | ["TaskManager"] -------------------------------------------------------------------------------- /physx-sys/sources/vehicle: -------------------------------------------------------------------------------- 1 | [ 2 | "PxVehicleComponents", 3 | "PxVehicleDrive", 4 | "PxVehicleDrive4W", 5 | "PxVehicleDriveNW", 6 | "PxVehicleDriveTank", 7 | "PxVehicleMetaData", 8 | "PxVehicleNoDrive", 9 | "PxVehicleSDK", 10 | "PxVehicleSerialization", 11 | "PxVehicleSuspWheelTire4", 12 | "PxVehicleTireFriction", 13 | "PxVehicleUpdate", 14 | "PxVehicleWheels", 15 | "VehicleUtilControl", 16 | "VehicleUtilSetup", 17 | "VehicleUtilTelemetry", 18 | ] 19 | -------------------------------------------------------------------------------- /physx-sys/sources/vehicle_metadata: -------------------------------------------------------------------------------- 1 | [ 2 | "PxVehicleAutoGeneratedMetaDataObjects", 3 | "PxVehicleMetaDataObjects", 4 | ] 5 | -------------------------------------------------------------------------------- /physx-sys/src/structgen/structgen.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct RustCheck { 7 | const char* rname; 8 | uint32_t size; 9 | }; 10 | 11 | struct PodStructGen { 12 | PodStructGen() { 13 | cfile = fopen("structgen_out.hpp", "w"); 14 | rfile = fopen("structgen_out.rs", "w"); 15 | } 16 | 17 | void finish() { 18 | fclose(cfile); 19 | 20 | fputs("#[cfg(test)]\nmod sizes {\n use super::*;\n use std::mem::size_of;\n #[test]\n fn check_sizes() {\n", rfile); 21 | for (const auto& rc : rust_checks) { 22 | fprintf( 23 | rfile, 24 | " assert_eq!(size_of::<%s>(), %u);\n", 25 | rc.rname, 26 | rc.size 27 | ); 28 | } 29 | fputs(" }\n}\n", rfile); 30 | fclose(rfile); 31 | } 32 | 33 | void pass_thru(const char* code) { fputs(code, cfile); } 34 | 35 | void begin_struct(const char* cname, const char* rname) { 36 | fprintf(cfile, "struct %s {\n", cname); 37 | 38 | fprintf(rfile, "#[derive(Clone, Copy)]\n"); 39 | fprintf(rfile, "#[cfg_attr(feature = \"debug-structs\", derive(Debug))]\n"); 40 | fprintf(rfile, "#[repr(C)]\n"); 41 | fprintf(rfile, "pub struct %s {\n", rname); 42 | 43 | this->rname = rname; 44 | pos = 0; 45 | padIdx = 0; 46 | } 47 | 48 | void emit_padding(uint32_t bytes) { 49 | fprintf(cfile, " char structgen_pad%u[%u];\n", padIdx, bytes); 50 | fprintf(rfile, " pub structgen_pad%u: [u8; %u],\n", padIdx, bytes); 51 | ++padIdx; 52 | } 53 | 54 | void add_field( 55 | const char* cppDecl, 56 | const char* rustName, 57 | const char* rustType, 58 | size_t size, 59 | size_t offset) { 60 | assert(offset >= pos); 61 | if (offset > pos) { 62 | emit_padding(uint32_t(offset - pos)); 63 | pos = offset; 64 | } 65 | fprintf(cfile, " %s;\n", cppDecl); 66 | fprintf(rfile, " pub %s: %s,\n", rustName, rustType); 67 | pos += size; 68 | } 69 | 70 | void end_struct(size_t size) { 71 | assert(size >= pos); 72 | if (size > pos) { 73 | emit_padding(uint32_t(size - pos)); 74 | } 75 | fputs("};\n", cfile); 76 | fputs("}\n", rfile); 77 | 78 | rust_checks.emplace_back(RustCheck { rname, uint32_t(size) }); 79 | } 80 | 81 | private: 82 | std::vector rust_checks; 83 | FILE* cfile; 84 | FILE* rfile; 85 | const char* rname; 86 | size_t pos; 87 | uint32_t padIdx; 88 | }; 89 | -------------------------------------------------------------------------------- /physx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "physx" 3 | description = "High-level Rust interface for Nvidia PhysX" 4 | version = "0.19.0" 5 | authors = ["Embark "] 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/EmbarkStudios/physx-rs" 8 | edition = "2021" 9 | readme = "README.md" 10 | keywords = ["physics"] 11 | categories = ["api-bindings", "simulation", "game-engines"] 12 | 13 | [lib] 14 | doctest = false 15 | 16 | [features] 17 | # During building of the sys crate, this additional program can be built which 18 | # is used to autogenerate Rust code from the physx headers. Normal use of the 19 | # physx crate would never need to use this feature. 20 | structgen = ["physx-sys/structgen"] 21 | # Enables `Debug` derivations for the FFI structures, which can be useful for 22 | # print debugging 23 | debug-structs = ["physx-sys/debug-structs"] 24 | 25 | [dependencies] 26 | physx-sys = { version = "0.11.5", path = "../physx-sys" } 27 | 28 | bitflags = "1.3" 29 | log = "0.4" 30 | glam = { version = "0.23", optional = true } 31 | thiserror = "1.0" 32 | -------------------------------------------------------------------------------- /physx/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /physx/README.md: -------------------------------------------------------------------------------- 1 | # 🎳 physx 2 | 3 | ![Build Status](https://github.com/EmbarkStudios/physx-rs/workflows/CI/badge.svg) 4 | [![Crates.io](https://img.shields.io/crates/v/physx.svg)](https://crates.io/crates/physx) 5 | [![Docs](https://docs.rs/physx/badge.svg)](https://docs.rs/physx) 6 | [![Contributor Covenant](https://img.shields.io/badge/contributor%20covenant-v1.4%20adopted-ff69b4.svg)](../CODE_OF_CONDUCT.md) 7 | [![Embark](https://img.shields.io/badge/embark-open%20source-blueviolet.svg)](http://embark.games) 8 | [![Embark](https://img.shields.io/badge/discord-ark-%237289da.svg?logo=discord)](https://discord.gg/dAuKfZS) 9 | 10 | [**This is a work in progress** 🚧](https://github.com/EmbarkStudios/physx-rs/issues/3) 11 | 12 | `physx` is intended to be an easy to use high-level wrapper for the [`physx-sys`](https://crates.io/crates/physx) bindings. The goal of this is to make ownership clearer and leverage the safety of Rust. 13 | 14 | The overall goal is to maintain a close mapping to the underlying PhysX API 15 | while improving safety and reliability of the code. This means, for example, 16 | that we do not expose the `PxLoadExtensions()` function but rather attach this 17 | to the [`Physics`](src/physics.rs) builder. 18 | 19 | Please also see the [repository](https://github.com/EmbarkStudios/physx-rs) containing an unsafe low-level binding. 20 | 21 | ## Example 22 | 23 | ## Basic usage 24 | 25 | ``` rust 26 | let mut physics = PhysicsFoundation::default(); 27 | 28 | let mut scene = physics.create( 29 | SceneDescriptor { 30 | gravity: PxVec3::new(0.0, 0.0, -9.81), 31 | ..SceneDescriptor::new(MySceneUserData::default()) 32 | } 33 | ); 34 | 35 | // Your physics simulation goes here 36 | ``` 37 | 38 | For a full example, have a look at the [bouncing ball example](examples/ball_physx.rs) 39 | and compare it to the [raw sys example](../physx-sys/examples/ball.rs). 40 | 41 | ## How it works 42 | 43 | Wrapping a C++ API in Rust is not straightforward, and requires some extra steps 44 | to work. The first, and most basic one is creating a C wrapper over the C++ API. 45 | Using C as an intermediary allows us to leverage a stable ABI through which C++ 46 | and Rust can communicate. The `physx-sys` crate provides this interface. 47 | 48 | `PhysX` makes significant use of inheritance, which isn't directly translatable to Rust. The class interfaces are directly translated into traits with full default implementations that are just calls to the unsafe FFI functions. These traits are bounded by their super class trait, as well as a `Class` trait, where `T` is the class data struct found in `physx_sys`. The class interface methods all take pointers to self, and the `Class` trait provides `as_ptr` and `as_mut_ptr` methods to retrieve `*const` and `*mut` pointers to `T`. Types that have a `userData` class member also have a `UserData` trait bound. 49 | 50 | ```Rust 51 | trait RigidDynamic: RigidActor + Class + UserData { 52 | fn get_sleep_threshold(&self) -> f32 { 53 | unsafe { PxRigidDynamic_getSleepThreshold(self.as_ptr()) } 54 | } 55 | // ... 56 | } 57 | ``` 58 | 59 | ## License 60 | 61 | Licensed under either of 62 | 63 | * Apache License, Version 2.0, ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 64 | * MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 65 | 66 | at your option. 67 | 68 | Note that the [PhysX C++ SDK](https://github.com/NVIDIAGameWorks/PhysX) has it's [own BSD 3 license](https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxguide/Manual/License.html) and depends on [additional C++ third party libraries](https://github.com/NVIDIAGameWorks/PhysX/tree/4.1/externals). 69 | 70 | ### Contribution 71 | 72 | Unless you explicitly state otherwise, any contribution intentionally 73 | submitted for inclusion in the work by you, as defined in the Apache-2.0 74 | license, shall be dual licensed as above, without any additional terms or 75 | conditions. 76 | -------------------------------------------------------------------------------- /physx/examples/assert_handler.rs: -------------------------------------------------------------------------------- 1 | use physx::{physics::PhysicsFoundationBuilder, prelude::*}; 2 | use std::ffi::CString; 3 | 4 | type PxMaterial = physx::material::PxMaterial<()>; 5 | type PxShape = physx::shape::PxShape<(), PxMaterial>; 6 | 7 | struct AssertHandler; 8 | 9 | impl physx::physics::AssertHandler for AssertHandler { 10 | fn on_assert(&self, expr: &str, file: &str, line: u32, should_ignore: &mut bool) { 11 | eprintln!("[{file:}:{line:}] Assertion failed: {expr:} ({should_ignore})"); 12 | *should_ignore = true; 13 | } 14 | } 15 | 16 | fn main() { 17 | // Holds a PxFoundation and a PxPhysics. 18 | // Also has an optional Pvd and transport, not enabled by default. 19 | // The default allocator is the one provided by PhysX. 20 | let builder = PhysicsFoundationBuilder::default(); 21 | let mut physics: PhysicsFoundation = 22 | builder.build().expect("a foundation being built"); 23 | 24 | physics.set_assert_handler(AssertHandler); 25 | 26 | #[allow(unsafe_code)] 27 | // SAFETY: Calling assertion handlers explicitly since they are not part of 28 | // of the safe API of physx since they are only normally called from within 29 | // the SDK itself 30 | unsafe { 31 | let assert_handler = physx_sys::phys_PxGetAssertHandler(); 32 | 33 | let expr = CString::new("1 != 2").unwrap(); 34 | let file = CString::new(file!()).unwrap(); 35 | 36 | let mut should_ignore = false; 37 | physx_sys::PxAssertHandler_opCall_mut( 38 | assert_handler, 39 | expr.as_ptr(), 40 | file.as_ptr(), 41 | line!() as _, 42 | &mut should_ignore as *mut _, 43 | ); 44 | 45 | let expr = CString::new("false").unwrap(); 46 | physx_sys::PxAssertHandler_opCall_mut( 47 | assert_handler, 48 | expr.as_ptr(), 49 | file.as_ptr(), 50 | line!() as _, 51 | &mut should_ignore as *mut _, 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /physx/examples/error_callback.rs: -------------------------------------------------------------------------------- 1 | use physx::{physics::PhysicsFoundationBuilder, prelude::*, traits::Class}; 2 | use physx_sys::PxErrorCode; 3 | use std::ffi::CString; 4 | 5 | type PxMaterial = physx::material::PxMaterial<()>; 6 | type PxShape = physx::shape::PxShape<(), PxMaterial>; 7 | 8 | struct ErrorCallback; 9 | 10 | impl physx::physics::ErrorCallback for ErrorCallback { 11 | fn report_error(&self, code: PxErrorCode, message: &str, file: &str, line: u32) { 12 | eprintln!("[{file:}:{line:}] {code:40?}: {message:}"); 13 | } 14 | } 15 | fn main() { 16 | // Holds a PxFoundation and a PxPhysics. 17 | // Also has an optional Pvd and transport, not enabled by default. 18 | // The default allocator is the one provided by PhysX. 19 | let mut builder = PhysicsFoundationBuilder::default(); 20 | builder.with_error_callback(ErrorCallback); 21 | let mut physics: PhysicsFoundation = 22 | builder.build().expect("a foundation being built"); 23 | 24 | #[allow(unsafe_code)] 25 | // SAFETY: Invoking the underlying error reporting functions to demonstrate 26 | // the error callback, this code is not part of the safe API since it is 27 | // normally only invoked by the underlying SDK 28 | unsafe { 29 | let error_callback = 30 | physx_sys::PxFoundation_getErrorCallback_mut(physics.foundation_mut().as_mut_ptr()); 31 | let msg = CString::new("this is just a warning").unwrap(); 32 | let file = CString::new(file!()).unwrap(); 33 | 34 | physx_sys::PxErrorCallback_reportError_mut( 35 | error_callback, 36 | PxErrorCode::DebugWarning, 37 | msg.as_ptr(), 38 | file.as_ptr(), 39 | line!() as _, 40 | ); 41 | 42 | let msg = CString::new("this is an invalid operation").unwrap(); 43 | physx_sys::PxErrorCallback_reportError_mut( 44 | error_callback, 45 | PxErrorCode::InvalidOperation, 46 | msg.as_ptr(), 47 | file.as_ptr(), 48 | line!() as _, 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /physx/migration-4-5.md: -------------------------------------------------------------------------------- 1 | # physx-sys 4.1 -> 5.1 migration guide 2 | 3 | This is a migration guide for the `physx` crate from the version (0.16.*) that was wrapping PhysX SDK 4.1, and the version (0.17) that transition to PhysX SDK 5.1.3. (see [PR#183] for the PR that actually made a bulk of the transition) 4 | 5 | See the [`physx-sys`](../physx-sys/migration-4-5.md) migration guide for more in depth information on the FFI API changes. 6 | 7 | Note that there is a migration guide from NVidia for the C++ code [here](https://nvidia-omniverse.github.io/PhysX/physx/5.1.3/docs/MigrationTo51.html). 8 | 9 | ## Enums changes 10 | 11 | All enums are now re-exported from `physx-sys` as the C++ enums are now both bound as normal Rust enums with the appropriately sized integer representation, and all of the enum variants are now named in `UpperCamelCase` to make them pleasant to use directly in Rust. 12 | 13 | ```diff 14 | -#[bitflags] 15 | -#[derive(Debug, Copy, Clone)] 16 | -#[repr(u8)] 17 | -pub enum ActorFlag { 18 | - Visualization = 1, 19 | - DisableGravity = 2, 20 | - SendSleepNotifies = 4, 21 | - DisableSimulation = 8, 22 | -} 23 | 24 | -impl From for PxActorFlag::Enum { 25 | - fn from(value: ActorFlag) -> Self { 26 | - match value { 27 | - ActorFlag::Visualization => 1, 28 | - ActorFlag::DisableGravity => 2, 29 | - ActorFlag::SendSleepNotifies => 4, 30 | - ActorFlag::DisableSimulation => 8, 31 | - } 32 | - } 33 | -} 34 | 35 | -impl From for ActorFlag { 36 | - fn from(other: PxActorFlag::Enum) -> Self { 37 | - match other { 38 | - 1 => ActorFlag::Visualization, 39 | - 2 => ActorFlag::DisableGravity, 40 | - 4 => ActorFlag::SendSleepNotifies, 41 | - 8 => ActorFlag::DisableSimulation, 42 | - _ => unreachable!("InvalidActorFlag"), 43 | - } 44 | - } 45 | -} 46 | +pub use physx_sys::PxActorFlag as ActorFlag; 47 | ``` 48 | 49 | ## Flags changes 50 | 51 | Previously the `physx` crate used `enumflags2` to create bitsets for the various enums that acted as flags in the API. These have all been removed as the `physx-sys` crate now creates these automatically during binding generation, with a few exceptions (ie `physx::foundation::ErrorCodes`, `physx::physics::AggregateFilterHint`, and `physx::shape::CollisionLayers`), and are directly reexported from the physx-sys crate with the same name as it had in the previous version of the `physx` crate. 52 | 53 | ```diff 54 | -pub type ActorFlags = BitFlags; 55 | - 56 | -impl PxFlags for ActorFlags { 57 | - type Target = PxActorFlags; 58 | - 59 | - fn into_px(self) -> Self::Target { 60 | - PxActorFlags { mBits: self.bits() } 61 | - } 62 | - 63 | - fn from_px(flags: Self::Target) -> Self { 64 | - BitFlags::from_bits_truncate(flags.mBits) 65 | - } 66 | -} 67 | +pub use physx_sys::PxActorFlags as ActorFlags; 68 | ``` 69 | 70 | The API for [`bitflags`](https://docs.rs/bitflags/1.3.2/bitflags/#methods) is largely the same as [`enumflags2`](https://docs.rs/enumflags2/latest/enumflags2/struct.BitFlags.html) so this change should mostly be transparent. 71 | 72 | This also means that the `PxFlags` trait has been completely removed as it is no longer needed. 73 | 74 | ## Deprecated 75 | 76 | - The `PxCooking` structure has been marked as `#[deprecated]`. It is deprecated in the underlying C++ SDK and we will replace it in a future version. 77 | 78 | ## Removed 79 | 80 | - `ArticulationBase` and `Articulation` have been removed from PhysX, with some of their functionality moving into `ArticulationReducedCoordinate` 81 | - `ArticulationMap` has been removed 82 | - `ArticulationJointBase` and `ArticulationJoint` have been removed from PhysX, with some of their functionality moving into `ArticulationJointReducedCoordinate` 83 | - `JointMap` has been removed 84 | - `ArticulationLink::get_inbound_joint` has been _temporarily_ removed 85 | 86 | ## Renamed 87 | 88 | - `BvhStructure` has been renamed to `Bvh`, methods have that operate on `Bvh` have also been renamed 89 | - `PxBvhStructureDesc` has been renamed to `PxBVHDesc` 90 | -------------------------------------------------------------------------------- /physx/release.toml: -------------------------------------------------------------------------------- 1 | pre-release-commit-message = "Release {{crate_name}} v{{version}}" 2 | tag-message = "Release {{crate_name}} {{version}}" 3 | tag-name = "{{crate_name}}-v{{version}}" 4 | pre-release-replacements = [ 5 | { file = "CHANGELOG.md", search = "Unreleased", replace = "{{version}}" }, 6 | { file = "CHANGELOG.md", search = "\\.\\.\\.HEAD", replace = "...{{tag_name}}" }, 7 | { file = "CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}" }, 8 | { file = "CHANGELOG.md", search = "", replace = "\n## [Unreleased] - ReleaseDate" }, 9 | { file = "CHANGELOG.md", search = "", replace = "\n[Unreleased]: https://github.com/EmbarkStudios/physx-rs/compare/{{tag_name}}...HEAD" }, 10 | ] 11 | -------------------------------------------------------------------------------- /physx/src/articulation_joint_reduced_coordinate.rs: -------------------------------------------------------------------------------- 1 | // Author: Tom Olsson 2 | // Copyright © 2019, Embark Studios, all rights reserved. 3 | // Created: 2 April 2019 4 | 5 | use super::traits::Class; 6 | 7 | #[rustfmt::skip] 8 | use physx_sys::{ 9 | PxArticulationDrive, 10 | PxArticulationJointReducedCoordinate_getJointType, 11 | PxArticulationJointReducedCoordinate_setDriveParams_mut, 12 | PxArticulationJointReducedCoordinate_setDriveTarget_mut, 13 | PxArticulationJointReducedCoordinate_setJointType_mut, 14 | PxArticulationJointReducedCoordinate_setLimitParams_mut, 15 | PxArticulationJointReducedCoordinate_setMotion_mut, 16 | PxArticulationLimit, 17 | }; 18 | 19 | pub use physx_sys::{ 20 | PxArticulationAxis as ArticulationAxis, PxArticulationDriveType as ArticulationDriveType, 21 | PxArticulationJointType as ArticulationJointType, PxArticulationMotion as ArticulationMotion, 22 | }; 23 | 24 | /// PxArticulationJointReducedCoordinate new type wrapper. 25 | #[repr(transparent)] 26 | pub struct ArticulationJointReducedCoordinate { 27 | obj: physx_sys::PxArticulationJointReducedCoordinate, 28 | } 29 | 30 | crate::DeriveClassForNewType!( 31 | ArticulationJointReducedCoordinate: PxArticulationJointReducedCoordinate, 32 | PxBase 33 | ); 34 | 35 | unsafe impl Send for ArticulationJointReducedCoordinate {} 36 | unsafe impl Sync for ArticulationJointReducedCoordinate {} 37 | 38 | impl ArticulationJointReducedCoordinate { 39 | /// Set target angle around axis for this joint 40 | #[inline] 41 | pub fn set_drive_target(&mut self, rot: f32, axis: ArticulationAxis) { 42 | unsafe { 43 | PxArticulationJointReducedCoordinate_setDriveTarget_mut( 44 | self.as_mut_ptr(), 45 | axis, 46 | rot, 47 | true, // autowake, this is the default value, physx 4 didn't have this parameter 48 | ) 49 | }; 50 | } 51 | 52 | /// Set the Joint type. 53 | #[inline] 54 | pub fn set_joint_type(&mut self, joint_type: ArticulationJointType) { 55 | unsafe { 56 | PxArticulationJointReducedCoordinate_setJointType_mut(self.as_mut_ptr(), joint_type) 57 | } 58 | } 59 | 60 | /// Get the joint type. 61 | #[inline] 62 | pub fn get_joint_type(&self) -> ArticulationJointType { 63 | unsafe { PxArticulationJointReducedCoordinate_getJointType(self.as_ptr()) } 64 | } 65 | 66 | /// Set motion limits for Axis 67 | #[inline] 68 | pub fn set_limit(&mut self, axis: ArticulationAxis, min: f32, max: f32) { 69 | let limit = PxArticulationLimit { 70 | low: min, 71 | high: max, 72 | }; 73 | unsafe { 74 | PxArticulationJointReducedCoordinate_setLimitParams_mut( 75 | self.as_mut_ptr(), 76 | axis, 77 | &limit, 78 | ); 79 | } 80 | } 81 | 82 | /// set drive type of the associated joints 83 | #[inline] 84 | pub fn set_drive( 85 | &mut self, 86 | axis: ArticulationAxis, 87 | stiffness: f32, 88 | damping: f32, 89 | max_force: f32, 90 | drive_type: ArticulationDriveType, 91 | ) { 92 | let params = PxArticulationDrive { 93 | stiffness, 94 | damping, 95 | maxForce: max_force, 96 | driveType: drive_type, 97 | }; 98 | 99 | unsafe { 100 | PxArticulationJointReducedCoordinate_setDriveParams_mut( 101 | self.as_mut_ptr(), 102 | axis, 103 | ¶ms, 104 | ) 105 | } 106 | } 107 | 108 | /// Set the ArticulationMotion for an axis. 109 | #[inline] 110 | pub fn set_motion(&mut self, axis: ArticulationAxis, motion: ArticulationMotion) { 111 | unsafe { 112 | PxArticulationJointReducedCoordinate_setMotion_mut(self.as_mut_ptr(), axis, motion); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /physx/src/articulation_link.rs: -------------------------------------------------------------------------------- 1 | // Author: Tom Olsson 2 | // Copyright © 2019, Embark Studios, all rights reserved. 3 | // Created: 2 April 2019 4 | 5 | use crate::{ 6 | owner::Owner, 7 | rigid_actor::RigidActor, 8 | rigid_body::RigidBody, 9 | shape::{Shape, ShapeFlag}, 10 | traits::{Class, UserData}, 11 | }; 12 | 13 | use std::{marker::PhantomData, ptr::drop_in_place}; 14 | 15 | #[rustfmt::skip] 16 | use physx_sys::{ 17 | PxArticulationLink_getChildren, 18 | PxArticulationLink_getInboundJointDof, 19 | PxArticulationLink_getLinkIndex, 20 | PxArticulationLink_getNbChildren, 21 | PxArticulationLink_release_mut, 22 | }; 23 | 24 | /// A new type wrapper for PxArticulationLink. 25 | /// 26 | /// Parametrized by its user data type, and the type of its Shapes. 27 | #[repr(transparent)] 28 | pub struct PxArticulationLink { 29 | pub(crate) obj: physx_sys::PxArticulationLink, 30 | phantom_user_data: PhantomData<(L, Geom)>, 31 | } 32 | 33 | unsafe impl UserData for PxArticulationLink { 34 | type UserData = L; 35 | 36 | #[inline] 37 | fn user_data_ptr(&self) -> &*mut std::ffi::c_void { 38 | &self.obj.userData 39 | } 40 | 41 | #[inline] 42 | fn user_data_ptr_mut(&mut self) -> &mut *mut std::ffi::c_void { 43 | &mut self.obj.userData 44 | } 45 | } 46 | 47 | impl Drop for PxArticulationLink { 48 | fn drop(&mut self) { 49 | unsafe { 50 | drop_in_place(self.get_user_data_mut() as *mut _); 51 | PxArticulationLink_release_mut(self.as_mut_ptr()); 52 | } 53 | } 54 | } 55 | 56 | unsafe impl Class

for PxArticulationLink 57 | where 58 | physx_sys::PxArticulationLink: Class

, 59 | { 60 | #[inline] 61 | fn as_ptr(&self) -> *const P { 62 | self.obj.as_ptr() 63 | } 64 | 65 | #[inline] 66 | fn as_mut_ptr(&mut self) -> *mut P { 67 | self.obj.as_mut_ptr() 68 | } 69 | } 70 | 71 | unsafe impl Send for PxArticulationLink {} 72 | unsafe impl Sync for PxArticulationLink {} 73 | 74 | impl RigidActor for PxArticulationLink { 75 | type Shape = Geom; 76 | } 77 | 78 | impl ArticulationLink for PxArticulationLink {} 79 | 80 | pub trait ArticulationLink: Class + RigidBody + UserData { 81 | /// # Safety 82 | /// 83 | /// Owner's own the pointer they wrap, using the pointer after dropping the Owner, 84 | /// or creating multiple Owners from the same pointer will cause UB. Use `into_ptr` to 85 | /// retrieve the pointer and consume the Owner without dropping the pointee. 86 | /// Initializes user data. 87 | unsafe fn from_raw( 88 | ptr: *mut physx_sys::PxArticulationLink, 89 | user_data: Self::UserData, 90 | ) -> Option> { 91 | unsafe { Owner::from_raw((ptr as *mut Self).as_mut()?.init_user_data(user_data)) } 92 | } 93 | 94 | /// Get the user data. 95 | #[inline] 96 | fn get_user_data(&self) -> &Self::UserData { 97 | // Safety: all construction goes through from_raw, which calls init_user_data 98 | unsafe { UserData::get_user_data(self) } 99 | } 100 | 101 | /// Get the user data. 102 | #[inline] 103 | fn get_user_data_mut(&mut self) -> &mut Self::UserData { 104 | // Safety: all construction goes through from_raw, which calls init_user_data 105 | unsafe { UserData::get_user_data_mut(self) } 106 | } 107 | 108 | /// Enable collisions for this link. Equivalent to setting SimulationShape to false for all attached shapes. 109 | #[inline] 110 | fn enable_collision(&mut self, enable: bool) { 111 | for shape in self.get_shapes_mut() { 112 | shape.set_flag(ShapeFlag::SimulationShape, enable); 113 | } 114 | } 115 | 116 | // Get inbound joint for this link 117 | // #[inline] 118 | // fn get_inbound_joint(&self) -> Option<&JointMap> { 119 | // unsafe { 120 | // (&PxArticulationLink_getInboundJoint(self.as_ptr()) 121 | // as *const *mut physx_sys::PxArticulationJointReducedCoordinate 122 | // as *const JointMap) 123 | // .as_ref() 124 | // } 125 | // } 126 | 127 | /// Get the index of the this link in it's parent articulation's link list. 128 | #[inline] 129 | fn get_link_index(&self) -> u32 { 130 | unsafe { PxArticulationLink_getLinkIndex(self.as_ptr()) } 131 | } 132 | 133 | /// Get the degrees of freedom of the inbound joint. 134 | #[inline] 135 | fn get_inbound_joint_dof(&self) -> u32 { 136 | unsafe { PxArticulationLink_getInboundJointDof(self.as_ptr()) } 137 | } 138 | 139 | /// Get the number of children links this link has. 140 | #[inline] 141 | fn get_nb_children(&self) -> u32 { 142 | unsafe { PxArticulationLink_getNbChildren(self.as_ptr()) } 143 | } 144 | 145 | /// Gets a Vec of the child links of this link. 146 | #[inline] 147 | fn get_children(&self) -> Vec<&Self> { 148 | let capacity = self.get_nb_children(); 149 | let mut buffer: Vec<&Self> = Vec::with_capacity(capacity as usize); 150 | unsafe { 151 | let new_len = PxArticulationLink_getChildren( 152 | self.as_ptr(), 153 | buffer.as_mut_ptr() as *mut *mut _, 154 | capacity, 155 | 0, 156 | ); 157 | buffer.set_len(new_len as usize); 158 | buffer 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /physx/src/base.rs: -------------------------------------------------------------------------------- 1 | use crate::traits::Class; 2 | pub(crate) use physx_sys::{PxBase, PxRefCounted}; 3 | 4 | #[rustfmt::skip] 5 | use physx_sys::{ 6 | PxBase_getBaseFlags, 7 | PxBase_getConcreteType, 8 | PxBase_getConcreteTypeName, 9 | PxBase_isReleasable, 10 | PxBase_setBaseFlag_mut, 11 | PxBase_setBaseFlags_mut, 12 | PxRefCounted_acquireReference_mut, 13 | PxRefCounted_getReferenceCount, 14 | PxRefCounted_release_mut, 15 | }; 16 | 17 | pub use physx_sys::{ 18 | PxBaseFlag as BaseFlag, PxBaseFlags as BaseFlags, PxConcreteType as ConcreteType, 19 | }; 20 | 21 | impl Base for T where T: Class + Sized {} 22 | 23 | pub trait Base: Class + Sized { 24 | /// Get the name of the real type referenced by this pointer, or None if the returned string is not valid 25 | fn get_concrete_type_name(&self) -> Option<&str> { 26 | unsafe { 27 | std::ffi::CStr::from_ptr(PxBase_getConcreteTypeName(self.as_ptr() as *const _) as _) 28 | .to_str() 29 | .ok() 30 | } 31 | } 32 | 33 | /// Returns an enumerated value identifying the type. 34 | /// 35 | /// This may return [`ConcreteType::Undefined`] in surprising situations, 36 | /// notably this does not seem to work with `get_active_actors`. Use 37 | /// `get_type` for actors if possible. 38 | #[inline] 39 | fn get_concrete_type(&self) -> ConcreteType { 40 | unsafe { PxBase_getConcreteType(self.as_ptr()).into() } 41 | } 42 | 43 | /// Set or unset the specified flag on this object. 44 | fn set_base_flag(&mut self, flag: BaseFlag, value: bool) { 45 | unsafe { 46 | PxBase_setBaseFlag_mut(self.as_mut_ptr() as *mut _, flag, value); 47 | } 48 | } 49 | 50 | /// Set the BaseFlags of this object. Note that replaces all flags currently 51 | /// on the object. Use `set_base_flag` to set individual flags. 52 | fn set_base_flags(&mut self, in_flags: BaseFlags) { 53 | unsafe { 54 | PxBase_setBaseFlags_mut(self.as_mut_ptr() as *mut _, in_flags); 55 | } 56 | } 57 | 58 | /// Read the BaseFlags of this object 59 | fn get_base_flags(&self) -> BaseFlags { 60 | unsafe { PxBase_getBaseFlags(self.as_ptr() as *const _) } 61 | } 62 | 63 | //////////////////////////////////////////////////////////////////////////////// 64 | 65 | /// Returns true if this object can be released, i.e., it is not subordinate. 66 | fn is_releasable(&self) -> bool { 67 | unsafe { PxBase_isReleasable(self.as_ptr() as *const _) } 68 | } 69 | } 70 | 71 | impl RefCounted for T where T: Class + Sized {} 72 | 73 | pub trait RefCounted: Class + Sized { 74 | /// Decrements the reference count of the object and releases it if the new reference count is zero. 75 | #[inline] 76 | fn release(&mut self) { 77 | unsafe { PxRefCounted_release_mut(self.as_mut_ptr().cast()) } 78 | } 79 | 80 | /// Returns the reference count of the object. 81 | /// 82 | /// At creation, the reference count of the object is 1. Every other object 83 | /// referencing this object increments the count by 1. When the reference 84 | /// count reaches 0, and only then, the object gets destroyed automatically. 85 | fn get_reference_count(&self) -> u32 { 86 | unsafe { PxRefCounted_getReferenceCount(self.as_ptr().cast()) } 87 | } 88 | 89 | /// Acquires a counted reference to this object. 90 | /// 91 | /// This method increases the reference count of the object by 1. Decrement 92 | /// the reference count by calling [`Self::release`] 93 | fn acquire_reference(&mut self) { 94 | unsafe { PxRefCounted_acquireReference_mut(self.as_mut_ptr().cast()) } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /physx/src/bvh.rs: -------------------------------------------------------------------------------- 1 | use crate::{math::PxBounds3, owner::Owner, traits::Class}; 2 | 3 | use physx_sys::{PxBVH_getBounds, PxBVH_getNbBounds, PxBase_release_mut}; 4 | 5 | #[repr(transparent)] 6 | pub struct Bvh { 7 | obj: physx_sys::PxBVH, 8 | } 9 | 10 | crate::DeriveClassForNewType!(Bvh: PxBVH, PxBase); 11 | 12 | impl Bvh { 13 | /// # Safety 14 | /// 15 | /// Owner's own the pointer they wrap, using the pointer after dropping the Owner, 16 | /// or creating multiple Owners from the same pointer will cause UB. Use `into_ptr` to 17 | /// retrieve the pointer and consume the Owner without dropping the pointee. 18 | pub(crate) unsafe fn from_raw(ptr: *mut physx_sys::PxBVH) -> Option> { 19 | unsafe { Owner::from_raw(ptr as *mut Self) } 20 | } 21 | } 22 | 23 | unsafe impl Send for Bvh {} 24 | unsafe impl Sync for Bvh {} 25 | 26 | impl Drop for Bvh { 27 | fn drop(&mut self) { 28 | unsafe { PxBase_release_mut(self.as_mut_ptr()) } 29 | } 30 | } 31 | 32 | impl Bvh { 33 | /// Get the bounds in the BvhStructure. 34 | pub fn get_bounds(&self) -> &[PxBounds3] { 35 | unsafe { 36 | std::slice::from_raw_parts( 37 | PxBVH_getBounds(self.as_ptr()) as *const PxBounds3, 38 | PxBVH_getNbBounds(self.as_ptr()) as usize, 39 | ) 40 | } 41 | } 42 | 43 | /// Get the number of bounds in the BvhStructure. 44 | pub fn get_nb_bounds(&self) -> u32 { 45 | unsafe { PxBVH_getNbBounds(self.as_ptr()) } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /physx/src/constraint.rs: -------------------------------------------------------------------------------- 1 | use crate::{owner::Owner, traits::Class}; 2 | 3 | use physx_sys::PxConstraint_release_mut; 4 | 5 | #[repr(transparent)] 6 | pub struct Constraint { 7 | obj: physx_sys::PxConstraint, 8 | } 9 | 10 | crate::DeriveClassForNewType!(Constraint: PxConstraint, PxBase); 11 | 12 | impl Constraint { 13 | /// # Safety 14 | /// Owner's own the pointer they wrap, using the pointer after dropping the Owner, 15 | /// or creating multiple Owners from the same pointer will cause UB. Use `into_ptr` to 16 | /// retrieve the pointer and consume the Owner without dropping the pointee. 17 | #[allow(dead_code)] 18 | pub(crate) unsafe fn from_raw(ptr: *mut physx_sys::PxConstraint) -> Option> { 19 | unsafe { Owner::from_raw(ptr as *mut Self) } 20 | } 21 | } 22 | 23 | unsafe impl Send for Constraint {} 24 | unsafe impl Sync for Constraint {} 25 | 26 | impl Drop for Constraint { 27 | fn drop(&mut self) { 28 | unsafe { PxConstraint_release_mut(self.as_mut_ptr()) } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /physx/src/controller_manager.rs: -------------------------------------------------------------------------------- 1 | use crate::{controller::Controller, owner::Owner, traits::Class}; 2 | 3 | use std::{marker::PhantomData, ptr::drop_in_place}; 4 | 5 | #[rustfmt::skip] 6 | use physx_sys::{ 7 | PxControllerManager_createController_mut, 8 | PxControllerManager_getController_mut, 9 | PxControllerManager_getNbControllers, 10 | PxControllerManager_purgeControllers_mut, 11 | PxControllerManager_release_mut, 12 | }; 13 | 14 | #[repr(transparent)] 15 | pub struct PxControllerManager 16 | where 17 | C: Controller, 18 | { 19 | obj: physx_sys::PxControllerManager, 20 | phantom_controller_types: PhantomData, 21 | } 22 | 23 | unsafe impl Class for PxControllerManager 24 | where 25 | physx_sys::PxControllerManager: Class, 26 | C: Controller, 27 | { 28 | fn as_ptr(&self) -> *const T { 29 | self.obj.as_ptr() 30 | } 31 | 32 | fn as_mut_ptr(&mut self) -> *mut T { 33 | self.obj.as_mut_ptr() 34 | } 35 | } 36 | 37 | impl ControllerManager for PxControllerManager { 38 | type Controller = C; 39 | } 40 | 41 | pub trait ControllerManager: Class + Sized { 42 | type Controller: Controller; 43 | 44 | /// # Safety 45 | /// 46 | /// the pointee will be dropped when the Owner is dropped. Use `into_ptr` to 47 | /// retrieve the pointer from the Owner without dropping it. 48 | unsafe fn from_raw(ptr: *mut physx_sys::PxControllerManager) -> Option> { 49 | unsafe { Owner::from_raw(ptr as *mut Self) } 50 | } 51 | 52 | /// Create a controller. 53 | fn create_controller( 54 | &mut self, 55 | desc: Owner<::Descriptor>, 56 | ) -> Option<&mut Self::Controller> { 57 | unsafe { 58 | (PxControllerManager_createController_mut(self.as_mut_ptr(), desc.into_ptr()) 59 | as *mut Self::Controller) 60 | .as_mut() 61 | } 62 | } 63 | 64 | /// Get the number of controllers currently being managed. 65 | fn get_nb_controllers(&self) -> u32 { 66 | unsafe { PxControllerManager_getNbControllers(self.as_ptr()) } 67 | } 68 | 69 | /// Get a controller by index. Returns `None` 70 | fn get_controller(&mut self, idx: u32) -> Option<&mut Self::Controller> { 71 | unsafe { 72 | if idx < self.get_nb_controllers() { 73 | (PxControllerManager_getController_mut(self.as_mut_ptr(), idx) 74 | as *mut Self::Controller) 75 | .as_mut() 76 | } else { 77 | None 78 | } 79 | } 80 | } 81 | 82 | /// Get a Vec of all the controllers being managed. 83 | fn get_controllers(&mut self) -> Vec<&mut Self::Controller> { 84 | let count = self.get_nb_controllers(); 85 | let mut vec = Vec::with_capacity(count as usize); 86 | for idx in 0..count { 87 | vec.push(unsafe { 88 | &mut *(PxControllerManager_getController_mut(self.as_mut_ptr(), idx) 89 | as *mut Self::Controller) 90 | }); 91 | } 92 | vec 93 | } 94 | } 95 | 96 | unsafe impl Send for PxControllerManager {} 97 | unsafe impl Sync for PxControllerManager {} 98 | 99 | impl Drop for PxControllerManager { 100 | fn drop(&mut self) { 101 | unsafe { 102 | for controller in self.get_controllers() { 103 | drop_in_place(controller as *mut _); 104 | } 105 | PxControllerManager_purgeControllers_mut(self.as_mut_ptr()); 106 | PxControllerManager_release_mut(self.as_mut_ptr()); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /physx/src/convex_mesh.rs: -------------------------------------------------------------------------------- 1 | use std::mem::MaybeUninit; 2 | 3 | use crate::{ 4 | math::{PxBounds3, PxVec3}, 5 | owner::Owner, 6 | traits::Class, 7 | }; 8 | 9 | use physx_sys::{ 10 | PxConvexMesh_getIndexBuffer, 11 | PxConvexMesh_getLocalBounds, 12 | PxConvexMesh_getMassInformation, 13 | PxConvexMesh_getNbPolygons, 14 | PxConvexMesh_getNbVertices, 15 | PxConvexMesh_getPolygonData, 16 | PxConvexMesh_getVertices, 17 | // TODO: SDF getters 18 | //PxConvexMesh_getSDF, 19 | //PxConvexMesh_getConcreteTypeName, 20 | PxConvexMesh_isGpuCompatible, 21 | PxConvexMesh_release_mut, 22 | // TODO: high level wrapper for PxMassProperties 23 | PxMassProperties, 24 | }; 25 | 26 | #[repr(transparent)] 27 | pub struct ConvexMesh { 28 | obj: physx_sys::PxConvexMesh, 29 | } 30 | 31 | crate::DeriveClassForNewType!(ConvexMesh: PxConvexMesh, PxBase); 32 | 33 | impl ConvexMesh { 34 | /// # Safety 35 | /// 36 | /// Owner's own the pointer they wrap, using the pointer after dropping the Owner, 37 | /// or creating multiple Owners from the same pointer will cause UB. Use `into_ptr` to 38 | /// retrieve the pointer and consume the Owner without dropping the pointee. 39 | pub unsafe fn from_raw(ptr: *mut physx_sys::PxConvexMesh) -> Option> { 40 | unsafe { Owner::from_raw(ptr as *mut Self) } 41 | } 42 | 43 | /// Returns the number of vertices. 44 | pub fn get_nb_vertices(&self) -> u32 { 45 | unsafe { PxConvexMesh_getNbVertices(self.as_ptr()) } 46 | } 47 | 48 | /// Returns the vertices. 49 | pub fn get_vertices(&self) -> &[PxVec3] { 50 | unsafe { 51 | std::slice::from_raw_parts( 52 | PxConvexMesh_getVertices(self.as_ptr()) as *const PxVec3, 53 | self.get_nb_vertices() as usize, 54 | ) 55 | } 56 | } 57 | 58 | /// Returns the index buffer. 59 | pub fn get_index_buffer(&self) -> &[u8] { 60 | let polygon_count = self.get_nb_polygons(); 61 | 62 | // for each polygon index buffer contains its points, 63 | // so we take last polygon's index offset plus its length to calculate total size 64 | let index_buffer_length = if polygon_count > 0 { 65 | let last_polygon = self.get_polygon_data(polygon_count - 1).unwrap(); 66 | last_polygon.index_base as usize + last_polygon.nb_verts as usize 67 | } else { 68 | 0 69 | }; 70 | 71 | unsafe { 72 | std::slice::from_raw_parts( 73 | PxConvexMesh_getIndexBuffer(self.as_ptr()), 74 | index_buffer_length, 75 | ) 76 | } 77 | } 78 | 79 | /// Returns the number of polygons. 80 | pub fn get_nb_polygons(&self) -> u32 { 81 | unsafe { PxConvexMesh_getNbPolygons(self.as_ptr()) } 82 | } 83 | 84 | /// Returns the polygon data. 85 | pub fn get_polygon_data(&self, index: u32) -> Option { 86 | let mut polygon = MaybeUninit::uninit(); 87 | 88 | if unsafe { PxConvexMesh_getPolygonData(self.as_ptr(), index, polygon.as_mut_ptr()) } { 89 | Some(unsafe { polygon.assume_init() }.into()) 90 | } else { 91 | None 92 | } 93 | } 94 | 95 | /// Returns the mass properties of the mesh assuming unit density. 96 | pub fn get_mass_information(&self) -> PxMassProperties { 97 | let mut mass = MaybeUninit::uninit(); 98 | let mut local_inertia = MaybeUninit::uninit(); 99 | let mut local_center_of_mass = MaybeUninit::uninit(); 100 | 101 | unsafe { 102 | PxConvexMesh_getMassInformation( 103 | self.as_ptr(), 104 | mass.as_mut_ptr(), 105 | local_inertia.as_mut_ptr(), 106 | local_center_of_mass.as_mut_ptr(), 107 | ); 108 | 109 | PxMassProperties { 110 | inertiaTensor: local_inertia.assume_init(), 111 | centerOfMass: local_center_of_mass.assume_init(), 112 | mass: mass.assume_init(), 113 | } 114 | } 115 | } 116 | 117 | /// Returns the local-space (vertex space) AABB from the convex mesh. 118 | pub fn get_local_bounds(&self) -> PxBounds3 { 119 | unsafe { PxConvexMesh_getLocalBounds(self.as_ptr()) }.into() 120 | } 121 | 122 | /// This method decides whether a convex mesh is gpu compatible. 123 | pub fn is_gpu_compatible(&self) -> bool { 124 | unsafe { PxConvexMesh_isGpuCompatible(self.as_ptr()) } 125 | } 126 | } 127 | 128 | unsafe impl Send for ConvexMesh {} 129 | unsafe impl Sync for ConvexMesh {} 130 | 131 | impl Drop for ConvexMesh { 132 | fn drop(&mut self) { 133 | unsafe { PxConvexMesh_release_mut(self.as_mut_ptr()) } 134 | } 135 | } 136 | 137 | #[derive(Debug, Clone)] 138 | pub struct HullPolygon { 139 | /// Plane equation for this polygon. 140 | pub plane: [f32; 4], 141 | /// Number of vertices/edges in the polygon. 142 | pub nb_verts: u16, 143 | /// Offset in index buffer. 144 | pub index_base: u16, 145 | } 146 | 147 | impl From for HullPolygon { 148 | fn from(value: physx_sys::PxHullPolygon) -> Self { 149 | Self { 150 | plane: value.mPlane, 151 | nb_verts: value.mNbVerts, 152 | index_base: value.mIndexBase, 153 | } 154 | } 155 | } 156 | 157 | impl From for physx_sys::PxHullPolygon { 158 | fn from(value: HullPolygon) -> Self { 159 | Self { 160 | mPlane: value.plane, 161 | mNbVerts: value.nb_verts, 162 | mIndexBase: value.index_base, 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /physx/src/math.rs: -------------------------------------------------------------------------------- 1 | // Author: Tom Olsson 2 | // Copyright © 2019, Embark Studios, all rights reserved. 3 | // Created: 17 June 2019 4 | 5 | mod transform; 6 | pub use transform::PxTransform; 7 | mod quat; 8 | pub use quat::PxQuat; 9 | mod vec3; 10 | pub use vec3::PxVec3; 11 | #[cfg(feature = "glam")] 12 | mod glam; 13 | 14 | #[derive(Copy, Clone)] 15 | #[repr(transparent)] 16 | pub struct PxExtendedVec3 { 17 | obj: physx_sys::PxExtendedVec3, 18 | } 19 | 20 | crate::DeriveClassForNewType!(PxExtendedVec3: PxExtendedVec3); 21 | 22 | impl From<(f64, f64, f64)> for PxExtendedVec3 { 23 | fn from(vec: (f64, f64, f64)) -> Self { 24 | Self { 25 | obj: physx_sys::PxExtendedVec3 { 26 | x: vec.0, 27 | y: vec.1, 28 | z: vec.2, 29 | }, 30 | } 31 | } 32 | } 33 | 34 | impl From for PxExtendedVec3 { 35 | fn from(bounds: physx_sys::PxExtendedVec3) -> Self { 36 | PxExtendedVec3 { obj: bounds } 37 | } 38 | } 39 | 40 | impl From for physx_sys::PxExtendedVec3 { 41 | fn from(value: PxExtendedVec3) -> Self { 42 | value.obj 43 | } 44 | } 45 | 46 | use crate::traits::Class; 47 | 48 | #[repr(transparent)] 49 | pub struct PxBounds3 { 50 | obj: physx_sys::PxBounds3, 51 | } 52 | 53 | impl PxBounds3 { 54 | /// Creates largest bounds that avoid floating point exceptions. 55 | pub fn max_bounds_extents() -> Self { 56 | unsafe { 57 | physx_sys::PxBounds3_new_1( 58 | &physx_sys::PxVec3_new_2(-f32::MAX / 4.0), 59 | &physx_sys::PxVec3_new_2(f32::MAX / 4.0), 60 | ) 61 | .into() 62 | } 63 | } 64 | } 65 | 66 | crate::DeriveClassForNewType!(PxBounds3: PxBounds3); 67 | 68 | impl From for PxBounds3 { 69 | fn from(bounds: physx_sys::PxBounds3) -> Self { 70 | PxBounds3 { obj: bounds } 71 | } 72 | } 73 | 74 | impl From for physx_sys::PxBounds3 { 75 | fn from(value: PxBounds3) -> Self { 76 | value.obj 77 | } 78 | } 79 | 80 | impl Default for PxBounds3 { 81 | fn default() -> Self { 82 | Self::max_bounds_extents() 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /physx/src/math/glam.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use ::glam::*; 3 | 4 | impl From for PxExtendedVec3 { 5 | fn from(vec: Vec3) -> Self { 6 | Self { 7 | obj: physx_sys::PxExtendedVec3 { 8 | x: vec.x as f64, 9 | y: vec.y as f64, 10 | z: vec.z as f64, 11 | }, 12 | } 13 | } 14 | } 15 | 16 | impl From for PxQuat { 17 | fn from(quat: Quat) -> Self { 18 | let (x, y, z, w) = quat.into(); 19 | Self::new(x, y, z, w) 20 | } 21 | } 22 | 23 | impl From for Quat { 24 | fn from(value: PxQuat) -> Self { 25 | let physx_sys::PxQuat { x, y, z, w } = value.obj; 26 | Quat::from_xyzw(x, y, z, w) 27 | } 28 | } 29 | 30 | impl From for PxTransform { 31 | fn from(mat: Mat4) -> Self { 32 | let (_, rotation, translation) = mat.to_scale_rotation_translation(); 33 | Self::from_translation_rotation(&translation.into(), &rotation.into()) 34 | } 35 | } 36 | 37 | impl From for Mat4 { 38 | fn from(value: PxTransform) -> Self { 39 | Self::from_rotation_translation(value.rotation().into(), value.translation().into()) 40 | } 41 | } 42 | 43 | impl From for PxVec3 { 44 | fn from(v: Vec3) -> Self { 45 | let (x, y, z) = v.into(); 46 | Self::new(x, y, z) 47 | } 48 | } 49 | 50 | impl From for Vec3 { 51 | fn from(value: PxVec3) -> Self { 52 | let physx_sys::PxVec3 { x, y, z } = value.obj; 53 | Vec3::new(x, y, z) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /physx/src/math/quat.rs: -------------------------------------------------------------------------------- 1 | use crate::{math::PxVec3, traits::Class}; 2 | 3 | #[rustfmt::skip] 4 | use physx_sys::{ 5 | PxQuat_dot, 6 | PxQuat_getAngle, 7 | PxQuat_getAngle_1, 8 | PxQuat_getBasisVector0, 9 | PxQuat_getBasisVector1, 10 | PxQuat_getBasisVector2, 11 | PxQuat_getConjugate, 12 | PxQuat_getImaginaryPart, 13 | PxQuat_getNormalized, 14 | PxQuat_isFinite, 15 | PxQuat_isIdentity, 16 | PxQuat_isSane, 17 | PxQuat_isUnit, 18 | PxQuat_magnitude, 19 | PxQuat_magnitudeSquared, 20 | PxQuat_new_1, 21 | PxQuat_new_3, 22 | PxQuat_new_4, 23 | PxQuat_normalize_mut, 24 | PxQuat_rotate, 25 | PxQuat_rotateInv, 26 | PxQuat_toRadiansAndUnitAxis, 27 | }; 28 | 29 | #[derive(Copy, Clone)] 30 | #[repr(transparent)] 31 | pub struct PxQuat { 32 | pub(super) obj: physx_sys::PxQuat, 33 | } 34 | 35 | crate::DeriveClassForNewType!(PxQuat: PxQuat); 36 | 37 | impl Default for PxQuat { 38 | fn default() -> PxQuat { 39 | unsafe { PxQuat_new_1(physx_sys::PxIDENTITY::PxIdentity).into() } 40 | } 41 | } 42 | 43 | impl From for PxQuat { 44 | fn from(quat: physx_sys::PxQuat) -> Self { 45 | Self { obj: quat } 46 | } 47 | } 48 | 49 | impl From for physx_sys::PxQuat { 50 | fn from(value: PxQuat) -> Self { 51 | value.obj 52 | } 53 | } 54 | 55 | impl PxQuat { 56 | pub fn new(x: f32, y: f32, z: f32, w: f32) -> PxQuat { 57 | unsafe { PxQuat_new_3(x, y, z, w).into() } 58 | } 59 | 60 | pub fn x(&self) -> f32 { 61 | self.obj.x 62 | } 63 | 64 | pub fn y(&self) -> f32 { 65 | self.obj.y 66 | } 67 | 68 | pub fn z(&self) -> f32 { 69 | self.obj.z 70 | } 71 | 72 | pub fn w(&self) -> f32 { 73 | self.obj.w 74 | } 75 | 76 | pub fn x_mut(&mut self) -> &mut f32 { 77 | &mut self.obj.x 78 | } 79 | 80 | pub fn y_mut(&mut self) -> &mut f32 { 81 | &mut self.obj.y 82 | } 83 | 84 | pub fn z_mut(&mut self) -> &mut f32 { 85 | &mut self.obj.z 86 | } 87 | 88 | pub fn w_mut(&mut self) -> &mut f32 { 89 | &mut self.obj.w 90 | } 91 | 92 | pub fn dot(&self, other: &PxQuat) -> f32 { 93 | unsafe { PxQuat_dot(self.as_ptr(), other.as_ptr()) } 94 | } 95 | 96 | pub fn get_identity_angle(&self) -> f32 { 97 | unsafe { PxQuat_getAngle(self.as_ptr()) } 98 | } 99 | 100 | pub fn get_angle(&self, other: &PxQuat) -> f32 { 101 | unsafe { PxQuat_getAngle_1(self.as_ptr(), other.as_ptr()) } 102 | } 103 | 104 | pub fn get_basis_vector_x(&self) -> PxVec3 { 105 | unsafe { PxQuat_getBasisVector0(self.as_ptr()).into() } 106 | } 107 | 108 | pub fn get_basis_vector_y(&self) -> PxVec3 { 109 | unsafe { PxQuat_getBasisVector1(self.as_ptr()).into() } 110 | } 111 | 112 | pub fn get_basis_vector_z(&self) -> PxVec3 { 113 | unsafe { PxQuat_getBasisVector2(self.as_ptr()).into() } 114 | } 115 | 116 | pub fn get_conjugate(&self) -> PxQuat { 117 | unsafe { PxQuat_getConjugate(self.as_ptr()).into() } 118 | } 119 | 120 | pub fn get_imaginary_part(&self) -> PxVec3 { 121 | unsafe { PxQuat_getImaginaryPart(self.as_ptr()).into() } 122 | } 123 | 124 | pub fn get_normalized(&self) -> PxQuat { 125 | unsafe { PxQuat_getNormalized(self.as_ptr()).into() } 126 | } 127 | 128 | pub fn is_finite(&self) -> bool { 129 | unsafe { PxQuat_isFinite(self.as_ptr()) } 130 | } 131 | 132 | pub fn is_identity(&self) -> bool { 133 | unsafe { PxQuat_isIdentity(self.as_ptr()) } 134 | } 135 | 136 | pub fn is_sane(&self) -> bool { 137 | unsafe { PxQuat_isSane(self.as_ptr()) } 138 | } 139 | 140 | pub fn is_unit(&self) -> bool { 141 | unsafe { PxQuat_isUnit(self.as_ptr()) } 142 | } 143 | 144 | pub fn magnitude(&self) -> f32 { 145 | unsafe { PxQuat_magnitude(self.as_ptr()) } 146 | } 147 | 148 | pub fn magnitude_squared(&self) -> f32 { 149 | unsafe { PxQuat_magnitudeSquared(self.as_ptr()) } 150 | } 151 | 152 | /// Returns the magnitude of the quaternion before normalization. 153 | pub fn normalize(&mut self) -> f32 { 154 | unsafe { PxQuat_normalize_mut(self.as_mut_ptr()) } 155 | } 156 | 157 | /// Rotates the vector. 158 | pub fn rotate(&self, vector: &PxVec3) -> PxVec3 { 159 | unsafe { PxQuat_rotate(self.as_ptr(), vector.as_ptr()).into() } 160 | } 161 | 162 | pub fn rotate_inverse(&self, vector: &PxVec3) -> PxVec3 { 163 | unsafe { PxQuat_rotateInv(self.as_ptr(), vector.as_ptr()).into() } 164 | } 165 | 166 | /// returns the angle in radians and a normalized axis vector 167 | #[allow(clippy::wrong_self_convention)] 168 | pub fn to_angle_axis(&self) -> (f32, PxVec3) { 169 | let mut angle = 0.0; 170 | let mut axis = PxVec3::default(); 171 | unsafe { 172 | PxQuat_toRadiansAndUnitAxis(self.as_ptr(), &mut angle, axis.as_mut_ptr()); 173 | } 174 | (angle, axis) 175 | } 176 | 177 | pub fn from_angle_axis(angle: f32, axis: PxVec3) -> PxQuat { 178 | unsafe { PxQuat_new_4(angle, axis.as_ptr()).into() } 179 | } 180 | } 181 | 182 | unsafe impl Send for PxQuat {} 183 | unsafe impl Sync for PxQuat {} 184 | -------------------------------------------------------------------------------- /physx/src/math/transform.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | math::{PxQuat, PxVec3}, 3 | traits::Class, 4 | }; 5 | 6 | #[rustfmt::skip] 7 | use physx_sys::{ 8 | PxPlane, 9 | PxPlane_inverseTransform, 10 | PxPlane_transform, 11 | PxTransform_getInverse, 12 | PxTransform_getNormalized, 13 | PxTransform_isFinite, 14 | PxTransform_isSane, 15 | PxTransform_isValid, 16 | PxTransform_new_1, 17 | PxTransform_new_2, 18 | PxTransform_new_3, 19 | PxTransform_new_5, 20 | PxTransform_rotate, 21 | PxTransform_rotateInv, 22 | PxTransform_transform, 23 | PxTransform_transformInv, 24 | PxTransform_transformInv_1, 25 | PxTransform_transform_1, 26 | }; 27 | 28 | #[derive(Copy, Clone)] 29 | #[repr(transparent)] 30 | pub struct PxTransform { 31 | obj: physx_sys::PxTransform, 32 | } 33 | 34 | crate::DeriveClassForNewType!(PxTransform: PxTransform); 35 | 36 | impl Default for PxTransform { 37 | fn default() -> Self { 38 | unsafe { 39 | Self { 40 | obj: PxTransform_new_2(physx_sys::PxIDENTITY::PxIdentity), 41 | } 42 | } 43 | } 44 | } 45 | 46 | impl From for PxTransform { 47 | fn from(transform: physx_sys::PxTransform) -> Self { 48 | PxTransform { obj: transform } 49 | } 50 | } 51 | 52 | impl From for physx_sys::PxTransform { 53 | fn from(value: PxTransform) -> Self { 54 | value.obj 55 | } 56 | } 57 | 58 | impl PxTransform { 59 | pub fn translation(&self) -> PxVec3 { 60 | self.obj.p.into() 61 | } 62 | 63 | pub fn rotation(&self) -> PxQuat { 64 | self.obj.q.into() 65 | } 66 | 67 | pub fn translation_mut(&mut self) -> &mut PxVec3 { 68 | // Safety: PxVec3 is a new-type wrapper around physx_sys::PxVec3, they are identical. 69 | unsafe { &mut *(&mut self.obj.p as *mut _ as *mut _) } 70 | } 71 | 72 | pub fn rotation_mut(&mut self) -> &mut PxQuat { 73 | // Safety: PxQuat is a new-type wrapper around physx_sys::PxQuat, they are identical. 74 | unsafe { &mut *(&mut self.obj.q as *mut _ as *mut _) } 75 | } 76 | 77 | pub fn from_translation(translation: &PxVec3) -> PxTransform { 78 | unsafe { PxTransform_new_1(translation.as_ptr()).into() } 79 | } 80 | 81 | pub fn from_rotation(rotation: &PxQuat) -> PxTransform { 82 | unsafe { PxTransform_new_3(rotation.as_ptr()).into() } 83 | } 84 | 85 | pub fn from_translation_rotation(translation: &PxVec3, rotation: &PxQuat) -> PxTransform { 86 | unsafe { PxTransform_new_5(translation.as_ptr(), rotation.as_ptr()).into() } 87 | } 88 | 89 | pub fn get_inverse(&self) -> PxTransform { 90 | unsafe { PxTransform_getInverse(self.as_ptr()).into() } 91 | } 92 | 93 | pub fn get_normalized(&self) -> PxTransform { 94 | unsafe { PxTransform_getNormalized(self.as_ptr()).into() } 95 | } 96 | 97 | pub fn is_finite(&self) -> bool { 98 | unsafe { PxTransform_isFinite(self.as_ptr()) } 99 | } 100 | 101 | pub fn is_sane(&self) -> bool { 102 | unsafe { PxTransform_isSane(self.as_ptr()) } 103 | } 104 | 105 | pub fn is_valid(&self) -> bool { 106 | unsafe { PxTransform_isValid(self.as_ptr()) } 107 | } 108 | 109 | pub fn rotate(&self, vector: &PxVec3) -> PxVec3 { 110 | unsafe { PxTransform_rotate(self.as_ptr(), vector.as_ptr()).into() } 111 | } 112 | 113 | pub fn rotate_inv(&self, vector: &PxVec3) -> PxVec3 { 114 | unsafe { PxTransform_rotateInv(self.as_ptr(), vector.as_ptr()).into() } 115 | } 116 | 117 | pub fn transform(&self, other: &PxTransform) -> PxTransform { 118 | unsafe { PxTransform_transform_1(self.as_ptr(), other.as_ptr()).into() } 119 | } 120 | 121 | pub fn transform_inv(&self, other: &PxTransform) -> PxTransform { 122 | unsafe { PxTransform_transformInv_1(self.as_ptr(), other.as_ptr()).into() } 123 | } 124 | 125 | pub fn transform_vector(&self, vector: &PxVec3) -> PxVec3 { 126 | unsafe { PxTransform_transform(self.as_ptr(), vector.as_ptr()).into() } 127 | } 128 | 129 | pub fn transform_vector_inv(&self, vector: &PxVec3) -> PxVec3 { 130 | unsafe { PxTransform_transformInv(self.as_ptr(), vector.as_ptr()).into() } 131 | } 132 | 133 | pub fn transform_plane(&self, plane: &PxPlane) -> PxPlane { 134 | unsafe { PxPlane_transform(plane, self.as_ptr()) } 135 | } 136 | 137 | pub fn transform_plane_inv(&self, plane: &PxPlane) -> PxPlane { 138 | unsafe { PxPlane_inverseTransform(plane, self.as_ptr()) } 139 | } 140 | } 141 | 142 | unsafe impl Send for PxTransform {} 143 | unsafe impl Sync for PxTransform {} 144 | -------------------------------------------------------------------------------- /physx/src/math/vec3.rs: -------------------------------------------------------------------------------- 1 | use crate::traits::Class; 2 | 3 | #[rustfmt::skip] 4 | use physx_sys::{ 5 | PxVec3_abs, 6 | PxVec3_cross, 7 | PxVec3_dot, 8 | PxVec3_getNormalized, 9 | PxVec3_isFinite, 10 | PxVec3_isNormalized, 11 | PxVec3_isZero, 12 | PxVec3_magnitude, 13 | PxVec3_magnitudeSquared, 14 | PxVec3_maxElement, 15 | PxVec3_maximum, 16 | PxVec3_minElement, 17 | PxVec3_minimum, 18 | PxVec3_multiply, 19 | PxVec3_new_1, 20 | PxVec3_new_3, 21 | PxVec3_normalize_mut, 22 | }; 23 | 24 | #[derive(Copy, Clone)] 25 | #[repr(transparent)] 26 | pub struct PxVec3 { 27 | pub(super) obj: physx_sys::PxVec3, 28 | } 29 | 30 | crate::DeriveClassForNewType!(PxVec3: PxVec3); 31 | 32 | impl Default for PxVec3 { 33 | fn default() -> Self { 34 | unsafe { PxVec3_new_1(physx_sys::PxZERO::PxZero).into() } 35 | } 36 | } 37 | 38 | impl From for PxVec3 { 39 | fn from(vec3: physx_sys::PxVec3) -> Self { 40 | PxVec3 { obj: vec3 } 41 | } 42 | } 43 | 44 | impl From for physx_sys::PxVec3 { 45 | fn from(value: PxVec3) -> Self { 46 | value.obj 47 | } 48 | } 49 | 50 | impl From for PxVec3 { 51 | fn from(vec3: physx_sys::PxExtendedVec3) -> Self { 52 | PxVec3 { 53 | obj: physx_sys::PxVec3 { 54 | x: vec3.x as f32, 55 | y: vec3.y as f32, 56 | z: vec3.z as f32, 57 | }, 58 | } 59 | } 60 | } 61 | 62 | impl From for physx_sys::PxExtendedVec3 { 63 | fn from(value: PxVec3) -> Self { 64 | Self { 65 | x: value.obj.x as f64, 66 | y: value.obj.y as f64, 67 | z: value.obj.z as f64, 68 | } 69 | } 70 | } 71 | 72 | impl PxVec3 { 73 | pub fn x(&self) -> f32 { 74 | self.obj.x 75 | } 76 | 77 | pub fn y(&self) -> f32 { 78 | self.obj.y 79 | } 80 | 81 | pub fn z(&self) -> f32 { 82 | self.obj.z 83 | } 84 | 85 | pub fn x_mut(&mut self) -> &mut f32 { 86 | &mut self.obj.x 87 | } 88 | 89 | pub fn y_mut(&mut self) -> &mut f32 { 90 | &mut self.obj.y 91 | } 92 | 93 | pub fn z_mut(&mut self) -> &mut f32 { 94 | &mut self.obj.z 95 | } 96 | 97 | pub fn new(x: f32, y: f32, z: f32) -> PxVec3 { 98 | unsafe { 99 | PxVec3 { 100 | obj: PxVec3_new_3(x, y, z), 101 | } 102 | } 103 | } 104 | 105 | pub fn abs(&self) -> PxVec3 { 106 | unsafe { PxVec3_abs(self.as_ptr()).into() } 107 | } 108 | 109 | pub fn cross(&self, other: &PxVec3) -> PxVec3 { 110 | unsafe { PxVec3_cross(self.as_ptr(), other.as_ptr()).into() } 111 | } 112 | 113 | pub fn dot(&self, other: &PxVec3) -> f32 { 114 | unsafe { PxVec3_dot(self.as_ptr(), other.as_ptr()) } 115 | } 116 | 117 | pub fn get_normalized(&self) -> PxVec3 { 118 | unsafe { PxVec3_getNormalized(self.as_ptr()).into() } 119 | } 120 | 121 | pub fn is_finite(&self) -> bool { 122 | unsafe { PxVec3_isFinite(self.as_ptr()) } 123 | } 124 | 125 | pub fn is_normalized(&self) -> bool { 126 | unsafe { PxVec3_isNormalized(self.as_ptr()) } 127 | } 128 | 129 | pub fn is_zero(&self) -> bool { 130 | unsafe { PxVec3_isZero(self.as_ptr()) } 131 | } 132 | 133 | pub fn magnitude(&self) -> f32 { 134 | unsafe { PxVec3_magnitude(self.as_ptr()) } 135 | } 136 | 137 | pub fn magnitude_squared(&self) -> f32 { 138 | unsafe { PxVec3_magnitudeSquared(self.as_ptr()) } 139 | } 140 | 141 | pub fn max_element(&self) -> f32 { 142 | unsafe { PxVec3_maxElement(self.as_ptr()) } 143 | } 144 | 145 | pub fn maximum(&self, other: &PxVec3) -> PxVec3 { 146 | unsafe { PxVec3_maximum(self.as_ptr(), other.as_ptr()).into() } 147 | } 148 | 149 | pub fn min_element(&self) -> f32 { 150 | unsafe { PxVec3_minElement(self.as_ptr()) } 151 | } 152 | 153 | pub fn minimum(&self, other: &PxVec3) -> PxVec3 { 154 | unsafe { PxVec3_minimum(self.as_ptr(), other.as_ptr()).into() } 155 | } 156 | 157 | pub fn multiply(&self, other: &PxVec3) -> PxVec3 { 158 | unsafe { PxVec3_multiply(self.as_ptr(), other.as_ptr()).into() } 159 | } 160 | 161 | /// normalize in place and returns the original magnitude. 162 | pub fn normalize(&mut self) -> f32 { 163 | unsafe { PxVec3_normalize_mut(self.as_mut_ptr()) } 164 | } 165 | } 166 | 167 | unsafe impl Send for PxVec3 {} 168 | unsafe impl Sync for PxVec3 {} 169 | -------------------------------------------------------------------------------- /physx/src/owner.rs: -------------------------------------------------------------------------------- 1 | use std::ptr::{drop_in_place, NonNull}; 2 | 3 | use crate::traits::Class; 4 | 5 | /// An owning wrapper around a pointer. PhysX object creation returns pointers 6 | /// which in normal Rust would be a Box, but Box cannot be used here because it 7 | /// has specific allocation requirements that the C++ code does not fulfill. 8 | #[repr(transparent)] 9 | pub struct Owner { 10 | ptr: NonNull, 11 | } 12 | 13 | impl Owner { 14 | /// Create a new owner from a raw pointer. Use the `from_raw` method on the type! 15 | /// 16 | /// # Safety 17 | /// 18 | /// Only one of these may be constructed per pointer. In particular, 19 | /// this must not be called on a pointer attained via Class::as_mut_ptr. The 20 | /// intended pattern is to wrap the raw FFI constructors in this call, so that 21 | /// the amount of time spent dealing with raw pointers is as little as possible. 22 | pub(crate) unsafe fn from_raw(ptr: *mut T) -> Option { 23 | Some(Self { 24 | ptr: NonNull::new(ptr)?, 25 | }) 26 | } 27 | 28 | /// Consumes the Owner without calling Drop and returns the raw pointer it was wrapping. 29 | #[allow(clippy::mem_forget)] 30 | pub fn into_ptr(mut self) -> *mut S 31 | where 32 | T: Class, 33 | { 34 | let ptr = self.as_mut_ptr(); 35 | std::mem::forget(self); 36 | ptr 37 | } 38 | } 39 | 40 | unsafe impl Class for Owner 41 | where 42 | T: Class, 43 | { 44 | fn as_ptr(&self) -> *const S { 45 | self.as_ref().as_ptr() 46 | } 47 | 48 | fn as_mut_ptr(&mut self) -> *mut S { 49 | self.as_mut().as_mut_ptr() 50 | } 51 | } 52 | 53 | unsafe impl Send for Owner {} 54 | unsafe impl Sync for Owner {} 55 | 56 | impl Drop for Owner { 57 | fn drop(&mut self) { 58 | unsafe { drop_in_place(self.ptr.as_ptr()) } 59 | } 60 | } 61 | 62 | impl AsRef for Owner { 63 | fn as_ref(&self) -> &T { 64 | unsafe { self.ptr.as_ref() } 65 | } 66 | } 67 | 68 | impl AsMut for Owner { 69 | fn as_mut(&mut self) -> &mut T { 70 | unsafe { self.ptr.as_mut() } 71 | } 72 | } 73 | 74 | impl std::ops::Deref for Owner { 75 | type Target = T; 76 | 77 | fn deref(&self) -> &Self::Target { 78 | self.as_ref() 79 | } 80 | } 81 | 82 | impl std::ops::DerefMut for Owner { 83 | fn deref_mut(&mut self) -> &mut Self::Target { 84 | self.as_mut() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /physx/src/physics/assert_handler.rs: -------------------------------------------------------------------------------- 1 | use std::ffi::{c_void, CStr}; 2 | 3 | use physx_sys::{create_assert_handler, PxAssertHandler}; 4 | 5 | /// This represents the (deprecated) PxAssertHandler interface. 6 | pub trait AssertHandler: Sized { 7 | /// Called as a result of a failed assert in PhysX. 8 | /// 9 | /// The `should_ignore` parameter is a static bool in C++ and can be used to disable asserts when received. 10 | fn on_assert(&self, expr: &str, file: &str, line: u32, should_ignore: &mut bool); 11 | 12 | /// # Safety 13 | /// 14 | /// Do not override this method. 15 | unsafe fn into_px(self) -> *mut PxAssertHandler { 16 | unsafe extern "C" fn on_message_shim( 17 | expr: *const i8, 18 | file: *const i8, 19 | line: u32, 20 | should_ignore: *mut bool, 21 | this: *const c_void, 22 | ) { 23 | unsafe { 24 | let this = &*this.cast::(); 25 | let expr = CStr::from_ptr(expr.cast()); 26 | let expr = expr.to_string_lossy(); 27 | 28 | let file = CStr::from_ptr(file.cast()); 29 | let file = file.to_string_lossy(); 30 | 31 | this.on_assert(&expr, &file, line, &mut *should_ignore); 32 | } 33 | } 34 | 35 | unsafe { 36 | create_assert_handler( 37 | on_message_shim::, 38 | Box::into_raw(Box::new(self)) as *mut c_void, 39 | ) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /physx/src/physics/error_callback.rs: -------------------------------------------------------------------------------- 1 | use physx_sys::{create_error_callback, PxErrorCallback, PxErrorCode}; 2 | use std::ffi::{c_void, CStr}; 3 | 4 | pub trait ErrorCallback: Sized { 5 | fn report_error(&self, code: PxErrorCode, message: &str, file: &str, line: u32); 6 | /// # Safety 7 | /// 8 | /// Do not override this method. 9 | unsafe fn into_px(self) -> *mut PxErrorCallback { 10 | unsafe extern "C" fn on_message_shim( 11 | code: PxErrorCode, 12 | message: *const i8, 13 | file: *const i8, 14 | line: u32, 15 | this: *const c_void, 16 | ) { 17 | unsafe { 18 | let this = &*this.cast::(); 19 | let msg = CStr::from_ptr(message.cast()); 20 | let msg = msg.to_string_lossy(); 21 | 22 | let file = CStr::from_ptr(file.cast()); 23 | let file = file.to_string_lossy(); 24 | 25 | this.report_error(code, &msg, &file, line); 26 | } 27 | } 28 | 29 | unsafe { 30 | create_error_callback( 31 | on_message_shim::, 32 | Box::into_raw(Box::new(self)) as *mut c_void, 33 | ) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /physx/src/physics/profiler.rs: -------------------------------------------------------------------------------- 1 | use physx_sys::{create_profiler_callback, PxProfilerCallback}; 2 | use std::ffi::c_void; 3 | 4 | /// A trait for creating profiler callbacks for PhysX. 5 | /// 6 | #[allow(clippy::missing_safety_doc)] 7 | pub unsafe trait ProfilerCallback: Sized { 8 | /// # Safety 9 | /// 10 | /// The name is a static string. If detached, consider threading support of your allocators. Not all support 11 | /// cross-thread events. 12 | unsafe extern "C" fn zone_start( 13 | name: *const i8, 14 | detached: bool, 15 | context_id: u64, 16 | user_data: *const c_void, 17 | ) -> *mut c_void; 18 | 19 | /// # Safety 20 | /// 21 | /// The name is a static string. If detached, consider threading support of your allocators. Not all support 22 | /// cross-thread events. Context is the value return from `ProfilerCallback::zone_start`. 23 | unsafe extern "C" fn zone_end( 24 | context: *const c_void, 25 | name: *const i8, 26 | detached: bool, 27 | context_id: u64, 28 | user_data: *const c_void, 29 | ); 30 | 31 | /// # Safety 32 | /// 33 | /// Do not override this method. 34 | unsafe fn into_px(self) -> *mut PxProfilerCallback { 35 | unsafe { 36 | create_profiler_callback( 37 | Self::zone_start, 38 | Self::zone_end, 39 | Box::into_raw(Box::new(self)) as *mut c_void, 40 | ) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /physx/src/prelude.rs: -------------------------------------------------------------------------------- 1 | // Author: Tom Olsson 2 | // Copyright © 2019, Embark Studios, all rights reserved. 3 | // Created: 9 May 2019 4 | 5 | pub use crate::actor::{Actor, ActorFlag, ActorFlags}; 6 | pub use crate::aggregate::Aggregate; 7 | pub use crate::articulation_cache::*; 8 | pub use crate::articulation_joint_reduced_coordinate::*; 9 | pub use crate::articulation_link::ArticulationLink; 10 | pub use crate::articulation_reduced_coordinate::{ 11 | ArticulationFlag, ArticulationFlags, ArticulationReducedCoordinate, 12 | }; 13 | pub use crate::base::{Base, BaseFlag, ConcreteType}; 14 | pub use crate::controller::Controller; 15 | pub use crate::controller_manager::ControllerManager; 16 | pub use crate::foundation::{AllocatorCallback, Foundation, ScratchBuffer}; 17 | pub use crate::geometry::*; 18 | pub use crate::height_field::*; 19 | pub use crate::math::*; 20 | pub use crate::owner::Owner; 21 | pub use crate::physics::{Physics, PhysicsFoundation, PX_PHYSICS_VERSION}; 22 | pub use crate::rigid_actor::RigidActor; 23 | pub use crate::rigid_body::{ForceMode, RigidBody, RigidBodyFlag, RigidBodyFlags}; 24 | pub use crate::rigid_dynamic::{RigidDynamic, RigidDynamicLockFlag, RigidDynamicLockFlags}; 25 | pub use crate::rigid_static::RigidStatic; 26 | pub use crate::scene::{ 27 | BroadPhaseType, FilterShaderDescriptor, PairFilteringMode, PruningStructureType, Scene, 28 | SceneFlag, SimulationThreadType, SolverType, 29 | }; 30 | pub use crate::shape::{CollisionLayers, Shape, ShapeFlag, ShapeFlags}; 31 | pub use crate::simulation_event_callback::{ 32 | AdvanceCallback, CollisionCallback, ConstraintBreakCallback, PxSimulationEventCallback, 33 | TriggerCallback, WakeSleepCallback, 34 | }; 35 | pub use crate::traits::descriptor::{ 36 | ConstraintDescriptor, MaterialDescriptor, PlaneDescriptor, RigidDynamicDescriptor, 37 | RigidStaticDescriptor, SceneDescriptor, ShapeDescriptor, 38 | }; 39 | -------------------------------------------------------------------------------- /physx/src/pruning_structure.rs: -------------------------------------------------------------------------------- 1 | use crate::{owner::Owner, traits::Class}; 2 | 3 | use physx_sys::PxPruningStructure_release_mut; 4 | 5 | #[repr(transparent)] 6 | pub struct PruningStructure { 7 | obj: physx_sys::PxPruningStructure, 8 | } 9 | 10 | crate::DeriveClassForNewType!(PruningStructure: PxPruningStructure, PxBase); 11 | 12 | impl PruningStructure { 13 | /// # Safety 14 | /// Owner's own the pointer they wrap, using the pointer after dropping the Owner, 15 | /// or creating multiple Owners from the same pointer will cause UB. Use `into_ptr` to 16 | /// retrieve the pointer and consume the Owner without dropping the pointee. 17 | pub(crate) unsafe fn from_raw( 18 | ptr: *mut physx_sys::PxPruningStructure, 19 | ) -> Option> { 20 | unsafe { Owner::from_raw(ptr as *mut Self) } 21 | } 22 | } 23 | 24 | unsafe impl Send for PruningStructure {} 25 | unsafe impl Sync for PruningStructure {} 26 | 27 | impl Drop for PruningStructure { 28 | fn drop(&mut self) { 29 | unsafe { PxPruningStructure_release_mut(self.as_mut_ptr()) } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /physx/src/rigid_actor.rs: -------------------------------------------------------------------------------- 1 | // Author: Tom Olsson 2 | // Copyright © 2019, Embark Studios, all rights reserved. 3 | // Created: 15 April 2019 4 | 5 | use super::{ 6 | actor::Actor, 7 | constraint::Constraint, 8 | math::{PxQuat, PxTransform, PxVec3}, 9 | shape::{CollisionLayers, Shape}, 10 | traits::Class, 11 | }; 12 | 13 | #[rustfmt::skip] 14 | use physx_sys::{ 15 | PxRigidActor, 16 | PxRigidActor_attachShape_mut, 17 | PxRigidActor_detachShape_mut, 18 | PxRigidActor_getConstraints, 19 | PxRigidActor_getGlobalPose, 20 | PxRigidActor_getNbConstraints, 21 | PxRigidActor_getNbShapes, 22 | PxRigidActor_getShapes, 23 | PxRigidActor_setGlobalPose_mut, 24 | }; 25 | 26 | pub trait RigidActor: Class + Actor { 27 | type Shape: Shape; 28 | 29 | /// Get the number of constraints on this rigid actor. 30 | fn get_nb_constraints(&self) -> u32 { 31 | unsafe { PxRigidActor_getNbConstraints(self.as_ptr()) } 32 | } 33 | 34 | /// Get the constraints effecting this rigid actor. 35 | fn get_constraints(&mut self) -> Vec<&mut Constraint> { 36 | let capacity = self.get_nb_constraints(); 37 | let mut buffer: Vec<&mut Constraint> = Vec::with_capacity(capacity as usize); 38 | unsafe { 39 | let len = PxRigidActor_getConstraints( 40 | self.as_ptr(), 41 | buffer.as_mut_ptr() as *mut *mut _, 42 | capacity, 43 | 0, 44 | ); 45 | buffer.set_len(len as usize); 46 | } 47 | buffer 48 | } 49 | 50 | /// Get the global pose of this rigid actor. The scale is implicitly 1.0. 51 | fn get_global_pose(&self) -> PxTransform { 52 | unsafe { PxRigidActor_getGlobalPose(self.as_ptr()).into() } 53 | } 54 | 55 | /// Get the global pose of this rigid actor. 56 | fn get_global_position(&self) -> PxVec3 { 57 | unsafe { PxRigidActor_getGlobalPose(self.as_ptr()).p.into() } 58 | } 59 | 60 | /// Get the global rotation of this rigid actor. 61 | fn get_global_rotation(&self) -> PxQuat { 62 | unsafe { PxRigidActor_getGlobalPose(self.as_ptr()).q.into() } 63 | } 64 | 65 | /// Set the global pose of this rigid actor 66 | fn set_global_pose(&mut self, pose: &PxTransform, autowake: bool) { 67 | unsafe { 68 | PxRigidActor_setGlobalPose_mut(self.as_mut_ptr(), pose.as_ptr(), autowake); 69 | } 70 | } 71 | 72 | /// Get number of attached shapes 73 | fn get_nb_shapes(&self) -> u32 { 74 | unsafe { PxRigidActor_getNbShapes(self.as_ptr()) } 75 | } 76 | 77 | /// Get a reference to every Shape attached to this actor. 78 | fn get_shapes(&self) -> Vec<&Self::Shape> { 79 | let capacity = self.get_nb_shapes(); 80 | let mut buffer: Vec<&Self::Shape> = Vec::with_capacity(capacity as usize); 81 | unsafe { 82 | let len = PxRigidActor_getShapes( 83 | self.as_ptr(), 84 | buffer.as_mut_ptr() as *mut *mut _, 85 | capacity, 86 | 0, 87 | ); 88 | buffer.set_len(len as usize); 89 | } 90 | buffer 91 | } 92 | 93 | /// Get a mutable reference to every Shape attached to this actor. 94 | fn get_shapes_mut(&mut self) -> Vec<&mut Self::Shape> { 95 | let capacity = self.get_nb_shapes(); 96 | let mut buffer: Vec<&mut Self::Shape> = Vec::with_capacity(capacity as usize); 97 | unsafe { 98 | let len = PxRigidActor_getShapes( 99 | self.as_ptr(), 100 | buffer.as_mut_ptr() as *mut *mut _, 101 | capacity, 102 | 0, 103 | ); 104 | buffer.set_len(len as usize); 105 | } 106 | buffer 107 | } 108 | 109 | /// Set the collision filter. Collisions will only occur if this_layers & other_layers != 0. 110 | fn set_collision_filter( 111 | &mut self, 112 | this_layers: CollisionLayers, 113 | other_layers: CollisionLayers, 114 | word3: u32, 115 | word4: u32, 116 | ) { 117 | for shape in self.get_shapes_mut() { 118 | shape.set_simulation_filter_data(this_layers, other_layers, word3, word4); 119 | } 120 | } 121 | 122 | /// Set the query filter. Queries will only find this item if queried with one of the flags. 123 | fn set_query_filter(&mut self, this_layers: CollisionLayers) { 124 | for shape in self.get_shapes_mut() { 125 | shape.set_query_filter_data(this_layers); 126 | } 127 | } 128 | 129 | /// Attach a shape. 130 | fn attach_shape(&mut self, shape: &mut Self::Shape) -> bool { 131 | unsafe { PxRigidActor_attachShape_mut(self.as_mut_ptr(), shape.as_mut_ptr()) } 132 | } 133 | 134 | /// Detach a shape. 135 | fn detach_shape(&mut self, shape: &mut Self::Shape) { 136 | unsafe { PxRigidActor_detachShape_mut(self.as_mut_ptr(), shape.as_mut_ptr(), true) }; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /physx/src/rigid_static.rs: -------------------------------------------------------------------------------- 1 | // Author: Tom Olsson 2 | // Copyright © 2019, Embark Studios, all rights reserved. 3 | // Created: 15 April 2019 4 | 5 | use std::{marker::PhantomData, ptr::drop_in_place}; 6 | 7 | use crate::{ 8 | geometry::PxGeometry, 9 | math::PxTransform, 10 | owner::Owner, 11 | physics::Physics, 12 | rigid_actor::RigidActor, 13 | shape::Shape, 14 | traits::{Class, UserData}, 15 | }; 16 | 17 | #[rustfmt::skip] 18 | use physx_sys::{ 19 | phys_PxCreateStatic, 20 | PxRigidActor_release_mut, 21 | PxRigidStatic_getConcreteTypeName, 22 | }; 23 | 24 | /// A new type wrapper for PxArticulation. Parametrized by it's user data type, 25 | /// and the type of it's Shapes. 26 | #[repr(transparent)] 27 | pub struct PxRigidStatic { 28 | pub(crate) obj: physx_sys::PxRigidStatic, 29 | phantom_user_data: PhantomData<(S, Geom)>, 30 | } 31 | 32 | unsafe impl UserData for PxRigidStatic { 33 | type UserData = U; 34 | 35 | fn user_data_ptr(&self) -> &*mut std::ffi::c_void { 36 | &self.obj.userData 37 | } 38 | 39 | fn user_data_ptr_mut(&mut self) -> &mut *mut std::ffi::c_void { 40 | &mut self.obj.userData 41 | } 42 | } 43 | 44 | impl Drop for PxRigidStatic { 45 | fn drop(&mut self) { 46 | unsafe { 47 | drop_in_place(self.get_user_data_mut() as *mut _); 48 | PxRigidActor_release_mut(self.as_mut_ptr()) 49 | } 50 | } 51 | } 52 | 53 | unsafe impl Class

for PxRigidStatic 54 | where 55 | physx_sys::PxRigidStatic: Class

, 56 | { 57 | fn as_ptr(&self) -> *const P { 58 | self.obj.as_ptr() 59 | } 60 | 61 | fn as_mut_ptr(&mut self) -> *mut P { 62 | self.obj.as_mut_ptr() 63 | } 64 | } 65 | 66 | unsafe impl Send for PxRigidStatic {} 67 | unsafe impl Sync for PxRigidStatic {} 68 | 69 | impl RigidActor for PxRigidStatic { 70 | type Shape = Geom; 71 | } 72 | 73 | impl RigidStatic for PxRigidStatic {} 74 | 75 | pub trait RigidStatic: Class + RigidActor + UserData { 76 | /// Create a new RigidStatic. 77 | fn new( 78 | physics: &mut impl Physics, 79 | transform: PxTransform, 80 | geometry: &impl Class, 81 | material: &mut ::Material, 82 | shape_transform: PxTransform, 83 | user_data: Self::UserData, 84 | ) -> Option> { 85 | unsafe { 86 | Self::from_raw( 87 | phys_PxCreateStatic( 88 | physics.as_mut_ptr(), 89 | transform.as_ptr(), 90 | geometry.as_ptr(), 91 | material.as_mut_ptr(), 92 | shape_transform.as_ptr(), 93 | ), 94 | user_data, 95 | ) 96 | } 97 | } 98 | 99 | /// # Safety 100 | /// Owner's own the pointer they wrap, using the pointer after dropping the Owner, 101 | /// or creating multiple Owners from the same pointer will cause UB. Use `into_ptr` to 102 | /// retrieve the pointer and consume the Owner without dropping the pointee. 103 | /// Initializes user data. 104 | unsafe fn from_raw( 105 | ptr: *mut physx_sys::PxRigidStatic, 106 | user_data: Self::UserData, 107 | ) -> Option> { 108 | unsafe { 109 | let actor = (ptr as *mut Self).as_mut(); 110 | Owner::from_raw(actor?.init_user_data(user_data)) 111 | } 112 | } 113 | 114 | /// Get the user data. 115 | fn get_user_data(&self) -> &Self::UserData { 116 | // Safety: all construction goes through from_raw, which calls init_user_data 117 | unsafe { UserData::get_user_data(self) } 118 | } 119 | 120 | /// Get the user data. 121 | fn get_user_data_mut(&mut self) -> &mut Self::UserData { 122 | // Safety: all construction goes through from_raw, which calls init_user_data 123 | unsafe { UserData::get_user_data_mut(self) } 124 | } 125 | 126 | /// Get the name of the real type referenced by this pointer, or None if the returned string is not valid 127 | fn get_concrete_type_name(&self) -> Option<&str> { 128 | unsafe { 129 | std::ffi::CStr::from_ptr(PxRigidStatic_getConcreteTypeName(self.as_ptr()) as _) 130 | .to_str() 131 | .ok() 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /physx/src/traits.rs: -------------------------------------------------------------------------------- 1 | // Author: Tom Olsson 2 | // Copyright © 2019, Embark Studios, all rights reserved. 3 | // Created: 12 June 2019 4 | 5 | mod class; 6 | pub use class::Class; 7 | pub(crate) use class::DeriveClassForNewType; 8 | 9 | mod user_data; 10 | pub(crate) use user_data::UserData; 11 | 12 | pub mod descriptor; 13 | pub(crate) use descriptor::*; 14 | -------------------------------------------------------------------------------- /physx/src/traits/user_data.rs: -------------------------------------------------------------------------------- 1 | use std::{ffi::c_void, mem::size_of}; 2 | 3 | /// UserData allows easy access and initialization of userData *mut c_void fields on Px objects. 4 | /// Not all Px objects with user data expose them as a field, so not all objects with user data can use this. 5 | /// 6 | /// # Safety 7 | /// 8 | /// all constructors of implementing types must call `init_user_data` during construction. 9 | /// If this does not happen, calling get_user_data or get_user_data_mut may return garbage data, or 10 | /// dereference an invalid pointer. If UserData is larger than a *mut ptr it will be stored on the heap, 11 | /// and it may need to be explicitly dropped by turning the field back into a Box and droppig it. 12 | /// If UserData implements Drop, this may be as simple as calling `get_user_data_mut` and then calling drop(), 13 | /// but implementation is left to the concrete type's Drop impl. 14 | pub unsafe trait UserData: Sized { 15 | type UserData; 16 | /// Returns a reference to the userData field 17 | fn user_data_ptr(&self) -> &*mut c_void; 18 | /// Returns a mutable reference to the userData field. 19 | fn user_data_ptr_mut(&mut self) -> &mut *mut c_void; 20 | 21 | unsafe fn init_user_data(&mut self, user_data: Self::UserData) -> &mut Self { 22 | if size_of::() > size_of::<*mut c_void>() { 23 | // Too big to pack into a *mut c_void, kick it to the heap. 24 | let data = Box::into_raw(Box::new(user_data)); 25 | *(self.user_data_ptr_mut() as *mut *mut c_void as *mut *mut Self::UserData) = data; 26 | } else { 27 | // DATA_SIZE <= VOID_SIZE 28 | *(self.user_data_ptr_mut() as *mut *mut c_void as *mut Self::UserData) = user_data; 29 | } 30 | self 31 | } 32 | 33 | /// # Safety 34 | /// 35 | /// The user data field must have previously been initialized via `init_user_data`. 36 | unsafe fn get_user_data(this: &Self) -> &Self::UserData { 37 | unsafe { 38 | if size_of::() > size_of::<*mut c_void>() { 39 | &*((*this.user_data_ptr()) as *const Self::UserData) 40 | } else { 41 | // DATA_SIZE <= VOID_SIZE 42 | // Data is stored directly in the userData field. 43 | &*(this.user_data_ptr() as *const *mut c_void as *const Self::UserData) 44 | } 45 | } 46 | } 47 | 48 | /// # Safety 49 | /// 50 | /// The user data field must have previously been initialized via `init_user_data`. 51 | unsafe fn get_user_data_mut(this: &mut Self) -> &mut Self::UserData { 52 | unsafe { 53 | if size_of::() > size_of::<*mut c_void>() { 54 | // Data is stored in a Box on the heap, and userData is just a pointer to it. 55 | &mut *((*this.user_data_ptr_mut()) as *mut Self::UserData) 56 | } else { 57 | // DATA_SIZE <= VOID_SIZE 58 | // Data is stored directly in the userData field. 59 | &mut *(this.user_data_ptr_mut() as *mut *mut c_void as *mut Self::UserData) 60 | } 61 | } 62 | } 63 | } 64 | 65 | #[cfg(test)] 66 | mod tests { 67 | use std::{ffi::c_void, fmt::Debug, marker::PhantomData, ptr::null_mut}; 68 | 69 | use super::UserData; 70 | 71 | struct TestUserData { 72 | user_data: *mut c_void, 73 | phantom: PhantomData, 74 | } 75 | 76 | impl Default for TestUserData { 77 | fn default() -> Self { 78 | Self { 79 | user_data: null_mut(), 80 | phantom: PhantomData, 81 | } 82 | } 83 | } 84 | 85 | unsafe impl UserData for TestUserData { 86 | type UserData = U; 87 | 88 | fn user_data_ptr(&self) -> &*mut c_void { 89 | &self.user_data 90 | } 91 | 92 | fn user_data_ptr_mut(&mut self) -> &mut *mut c_void { 93 | &mut self.user_data 94 | } 95 | } 96 | 97 | fn do_test(user_data: U) { 98 | unsafe { 99 | let mut object: TestUserData = TestUserData::default(); 100 | object.init_user_data(user_data.clone()); 101 | 102 | assert_eq!(UserData::get_user_data(&object), &user_data); 103 | assert_eq!(UserData::get_user_data_mut(&mut object), &user_data); 104 | } 105 | } 106 | 107 | #[test] 108 | fn test_user_data() { 109 | do_test(()); // unit type 110 | do_test(100u8); // smaller than pointer 111 | do_test(100usize); // same size as pointer 112 | do_test([100usize; 4]); // larger than pointer 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /physx/tests/bug-180.rs: -------------------------------------------------------------------------------- 1 | use physx::{base::RefCounted, prelude::*}; 2 | 3 | type PxMaterial = physx::material::PxMaterial<()>; 4 | type PxShape = physx::shape::PxShape<(), PxMaterial>; 5 | 6 | #[test] 7 | fn test_double_free() { 8 | let mut physics = PhysicsFoundation::<_, PxShape>::default(); 9 | 10 | let mut material = physics.create_material(0.5, 0.5, 0.6, ()).unwrap(); 11 | let geometry = PxBoxGeometry::new(1., 1., 1.); 12 | let flags = 13 | ShapeFlags::SceneQueryShape | ShapeFlags::SimulationShape | ShapeFlags::Visualization; 14 | 15 | let shape = physics 16 | .create_shape(&geometry, &mut [&mut material], false, flags, ()) 17 | .unwrap(); 18 | 19 | assert_eq!(material.get_reference_count(), 2); 20 | drop(shape); 21 | 22 | assert_eq!(material.get_reference_count(), 1); 23 | drop(material); 24 | } 25 | -------------------------------------------------------------------------------- /regen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Regenerates the physx_generated.hpp and physx_generated.rs files, as well 5 | # as compiling and running structgen to regenerate the POD layouts. This script 6 | # is only intended to work on Linux 7 | 8 | if [[ -n "$1" && -f ast-dump.json ]]; then 9 | rm ast-dump.json 10 | fi 11 | 12 | # note we use nightly as obtaining command output on linux is horrendously slow 13 | # in stable, which is a problem given the size of the JSON AST output 14 | RUST_LOG=debug cargo +nightly run --release -p pxbind 15 | 16 | out=$(mktemp -d) 17 | 18 | # Compile and run structgen for linux 19 | clang++ -std=c++14 -fuse-ld=lld -w -o "$out/structgen" \ 20 | -DPX_PHYSX_STATIC_LIB -DNDEBUG \ 21 | -I physx-sys/physx/physx/include \ 22 | physx-sys/src/structgen/structgen.cpp 23 | 24 | (cd $out && ./structgen) 25 | 26 | generated=physx-sys/src/generated 27 | 28 | mv $out/structgen_out.hpp $generated/unix 29 | mv $out/structgen_out.rs $generated/unix/structgen.rs 30 | 31 | # Compile and run structgen for windows 32 | # clang-cl -fuse-ld=lld-link --target=x86_64-pc-windows-msvc '/std:c++14' '/w' -o "$out/structgen.exe" \ 33 | # -DPX_PHYSX_STATIC_LIB -DNDEBUG \ 34 | # -I physx-sys/physx/physx/include \ 35 | # physx-sys/src/structgen/structgen.cpp 36 | 37 | # (cd $out && wine structgen.exe) 38 | 39 | # generated=$generated/x86_64-pc-windows-msvc 40 | 41 | # mv $out/structgen_out.hpp $generated 42 | # mv $out/structgen_out.rs $generated/structgen.rs 43 | --------------------------------------------------------------------------------