diff --git a/.gitignore b/.gitignore index 8bbb7db94..5c9ea4f03 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ archive examples/assets/.thumbs /examples/tmp /docs/_build +/docs/modules/functions.rst /warp_lang.egg-info exts/omni.warp/omni/warp/ogn/tests/usd build/lib/ diff --git a/PACKAGING.md b/PACKAGING.md index ea3691d33..bf2234945 100644 --- a/PACKAGING.md +++ b/PACKAGING.md @@ -1,86 +1,131 @@ # Release Instructions -## Updating the Github repository ----------------------- +## Versioning +------------- -1) Search/Replace the current version string (be sure not to update previous string in CHANGELOG.md) +Versions take the format X.Y.Z, similar to Python itself: -2) Update CHANGELOG.md from history +- Increments in X are reserved for major reworks of the project causing disruptive incompatibility. +- Increments in Y are for regular releases with a new set of features. +- Increments in Z are for bug fixes. In principle there are no new features. Can be omitted if 0 or not relevant. -3) Ensure docs have been built with `python build_docs.py` (prerequisites: `pip install sphinx sphinx_copybutton black furo`) +This is similar to [Semantic Versioning](https://semver.org/) but less strict around backward compatibility. +Like with Python, some breaking changes can be present between minor versions if well documented and gradually introduced. -4) Ensure that all changes are committed to `master` (including _static build files) +Note that prior to 0.11.0 this schema was not strictly adhered to. -5) Checkout `public` branch -6) Merge `master` to `public` using the following: +## Repositories +--------------- - `git merge --no-commit --allow-unrelated-histories --strategy-option theirs master` +Development happens internally on a GitLab repository (part of the Omniverse group), while releases are made public on GitHub. -7) Review the staged changes and ensure that no sensitive files are present (benchmarks, Gitlab config files, large assets, etc) +This document uses the following Git remote names: -8) Commit changes to `public` +* **omniverse**: `git remote add omniverse https://gitlab-master.nvidia.com/omniverse/warp.git` +* **github**: `git remote add github https://github.com/NVIDIA/warp.git` -9) Push changes to Gitlab branch `public` -10) Push changes to Github branch `main` - NOTE: the external facing Github release branch is called `main` *not* `public` +## GitLab Release Branch +------------------------ +1) Search & replace the current version string. -## Creating a Github Release Package ----------------------- + Be sure *not* to update previous strings in `CHANGELOG.md`. -1) Ensure both `master` and `public` branches are up to date as above, and pushed to Gitlab +2) Update `CHANGELOG.md` from Git history (since the last release branch). -2) Ensure all build configurations passed: +3) Commit and push to `master`. - https://teamcity.nvidia.com/project/Sandbox_mmacklin_Warp_Building?mode=builds +4) For new X.Y versions, create a release branch (note .Z maintenance versions remain on the same branch): -3) Manually trigger the binary deployment config: + `git checkout -b release-X.Y []` - https://teamcity.nvidia.com/buildConfiguration/Sandbox_mmacklin_Warp_Publishing_PublishSource?mode=builds + If branching from an older revision or reusing a branch, make sure to cherry-pick the version and changelog update. -4) Download artifacts .zip +5) Make any release-specific changes (e.g. disable/remove features not ready yet). -5) Test release .zip by extracting to a clean folder and doing: +6) Check that the last revision on the release branch passes TeamCity tests: - a) Run `cd warp` + https://teamcity.nvidia.com/project/Omniverse_Warp?mode=builds - b) Run `pip install .` + Fix issues until all tests pass. Cherry-pick fixes for `master` where applicable. - c) Run `cd examples` - d) Run `python example_mesh.py, etc` +## GitLab Public Branch +----------------------- - e) Run `python -m warp.tests` - -5) Create a new release on Github with tag of `v0.2.0` or equivalent and upload release .zip as an attachment +1) Manually trigger the `publish_bin` config on the `release-X.Y` branch: + https://teamcity.nvidia.com/buildConfiguration/Omniverse_Warp_Publishing_PublishSource?mode=builds -## Upload a PyPi build ----------------------- +2) Download artifacts .zip - it should contain a `.whl` file for each supported platform. + +3) Extract it to a clean folder and run tests for at least one platform: + + - Run `python -m pip install warp_lang--.whl` + - Run `python -m warp.tests` + + Check that the correct version number gets printed. + +4) If tests fail, make fixes on `release-X.Y` and where necessary cherry-pick to `master` before repeating from step (1). + +5) If all tests passed: + + * `git push github master:main` + * `git push github release-X.Y` + +6) Tag the release with `vX.Y.Z` on both `omniverse/release-X.Y` and `github/release-X.Y`. + + It is safest to push *just* the new tag using `git push vX.Y.Z`. + + In case of a mistake, tags can be moved using `git push vX.Y.Z -f`. + + +## Creating a GitHub Release Package +------------------------------------ + +Create a new release on [GitHub](https://github.com/NVIDIA/warp) with a tag of `vX.Y.Z` and upload the .whl artifacts as attachments. + + +## Upload a PyPI Release +------------------------ First time: -* Create a PyPi account -* Create a Token (write it down somewhere safe) -* Get an admin (mmacklin@nvidia.com) to give you write access to the project +* Create a [PyPI](https://pypi.org/) account. +* [Create a Token](https://pypi.org/manage/account/#api-tokens) for uploading to the `warp-lang` project (store it somewhere safe). +* Get an admin (mmacklin@nvidia.com) to give you write access to the project. + +Per release: + +Run `python -m twine upload *` from the unzipped .whl artifacts folder (on Windows make sure to use `cmd` shell; Git Bash doesn't work). + +* username: `__token__` +* password: `(your token string from PyPI)` + + +## Automated processes +---------------------- + +The following is just for your information. These steps should run automatically by CI/CD pipelines, but can be replicated manually if needed: -Release Steps: +### Building the documentation -1) Download artifacts as above and unzip +The contents of https://nvidia.github.io/warp/ is generated by a GitHub pipeline which runs `python build_docs.py` (prerequisites: `pip install sphinx sphinx_copybutton black furo`). -2) Run `cd warp` +### Building pip wheels -3) Run - ```bash - python -m build --wheel -C--build-option=-Pwindows-x86_64 && - python -m build --wheel -C--build-option=-Plinux-x86_64 && - python -m build --wheel -C--build-option=-Plinux-aarch64 && - python -m build --wheel -C--build-option=-Pmacos-universal - ``` +The TeamCity `publish_bin` configuration combines artifacts from each platform build, moving the contents of `warp/bin` to platform- and architecture-specific +subfolders; e.g. `warp/bin/linux-x86_64` and `warp/bin/linux-aarch64` both contain `warp.so` and `warp-clang.so` files. -4) Run `python -m twine upload dist/*` +Pip wheels are then built using: - * user: `__token__` - * pass: `(your token string from pypi)` +```bash +python -m build --wheel -C--build-option=-Pwindows-x86_64 +python -m build --wheel -C--build-option=-Plinux-x86_64 +python -m build --wheel -C--build-option=-Plinux-aarch64 +python -m build --wheel -C--build-option=-Pmacos-universal +``` +Selecting the correct library files for each wheel happens in [`setup.py`](setup.py). diff --git a/docs/modules/functions.rst b/docs/modules/functions.rst deleted file mode 100644 index 52e4f982e..000000000 --- a/docs/modules/functions.rst +++ /dev/null @@ -1,1992 +0,0 @@ -.. - Autogenerated File - Do not edit. Run build_docs.py to generate. - -.. functions: -.. currentmodule:: warp - -Kernel Reference -================ - -Scalar Types ------------- -.. class:: int8 -.. class:: uint8 -.. class:: int16 -.. class:: uint16 -.. class:: int32 -.. class:: uint32 -.. class:: int64 -.. class:: uint64 -.. class:: float16 -.. class:: float32 -.. class:: float64 -.. class:: bool - - -Vector Types ------------- -.. class:: vec2b -.. class:: vec2ub -.. class:: vec2s -.. class:: vec2us -.. class:: vec2i -.. class:: vec2ui -.. class:: vec2l -.. class:: vec2ul -.. class:: vec2h -.. class:: vec2f -.. class:: vec2d -.. class:: vec3b -.. class:: vec3ub -.. class:: vec3s -.. class:: vec3us -.. class:: vec3i -.. class:: vec3ui -.. class:: vec3l -.. class:: vec3ul -.. class:: vec3h -.. class:: vec3f -.. class:: vec3d -.. class:: vec4b -.. class:: vec4ub -.. class:: vec4s -.. class:: vec4us -.. class:: vec4i -.. class:: vec4ui -.. class:: vec4l -.. class:: vec4ul -.. class:: vec4h -.. class:: vec4f -.. class:: vec4d -.. class:: mat22h -.. class:: mat22f -.. class:: mat22d -.. class:: mat33h -.. class:: mat33f -.. class:: mat33d -.. class:: mat44h -.. class:: mat44f -.. class:: mat44d -.. class:: quath -.. class:: quatf -.. class:: quatd -.. class:: transformh -.. class:: transformf -.. class:: transformd -.. class:: spatial_vectorh -.. class:: spatial_vectorf -.. class:: spatial_vectord -.. class:: spatial_matrixh -.. class:: spatial_matrixf -.. class:: spatial_matrixd - -Generic Types -------------- -.. class:: Int -.. class:: Float -.. class:: Scalar -.. class:: Vector -.. class:: Matrix -.. class:: Quaternion -.. class:: Transformation -.. class:: Array - -Query Types -------------- -.. autoclass:: bvh_query_t -.. autoclass:: hash_grid_query_t -.. autoclass:: mesh_query_aabb_t -.. autoclass:: mesh_query_point_t -.. autoclass:: mesh_query_ray_t - - -Scalar Math ---------------- -.. function:: min(x: Scalar, y: Scalar) -> Scalar - - Return the minimum of two scalars. - - -.. function:: min(x: Vector[Any,Scalar], y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - Return the element-wise minimum of two vectors. - - -.. function:: min(v: Vector[Any,Scalar]) -> Scalar - :noindex: - :nocontentsentry: - - Return the minimum element of a vector ``v``. - - -.. function:: max(x: Scalar, y: Scalar) -> Scalar - - Return the maximum of two scalars. - - -.. function:: max(x: Vector[Any,Scalar], y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - Return the element-wise maximum of two vectors. - - -.. function:: max(v: Vector[Any,Scalar]) -> Scalar - :noindex: - :nocontentsentry: - - Return the maximum element of a vector ``v``. - - -.. function:: clamp(x: Scalar, a: Scalar, b: Scalar) -> Scalar - - Clamp the value of ``x`` to the range [a, b]. - - -.. function:: abs(x: Scalar) -> Scalar - - Return the absolute value of ``x``. - - -.. function:: sign(x: Scalar) -> Scalar - - Return -1 if ``x`` < 0, return 1 otherwise. - - -.. function:: step(x: Scalar) -> Scalar - - Return 1.0 if ``x`` < 0.0, return 0.0 otherwise. - - -.. function:: nonzero(x: Scalar) -> Scalar - - Return 1.0 if ``x`` is not equal to zero, return 0.0 otherwise. - - -.. function:: sin(x: Float) -> Float - - Return the sine of ``x`` in radians. - - -.. function:: cos(x: Float) -> Float - - Return the cosine of ``x`` in radians. - - -.. function:: acos(x: Float) -> Float - - Return arccos of ``x`` in radians. Inputs are automatically clamped to [-1.0, 1.0]. - - -.. function:: asin(x: Float) -> Float - - Return arcsin of ``x`` in radians. Inputs are automatically clamped to [-1.0, 1.0]. - - -.. function:: sqrt(x: Float) -> Float - - Return the square root of ``x``, where ``x`` is positive. - - -.. function:: cbrt(x: Float) -> Float - - Return the cube root of ``x``. - - -.. function:: tan(x: Float) -> Float - - Return the tangent of ``x`` in radians. - - -.. function:: atan(x: Float) -> Float - - Return the arctangent of ``x`` in radians. - - -.. function:: atan2(y: Float, x: Float) -> Float - - Return the 2-argument arctangent, atan2, of the point ``(x, y)`` in radians. - - -.. function:: sinh(x: Float) -> Float - - Return the sinh of ``x``. - - -.. function:: cosh(x: Float) -> Float - - Return the cosh of ``x``. - - -.. function:: tanh(x: Float) -> Float - - Return the tanh of ``x``. - - -.. function:: degrees(x: Float) -> Float - - Convert ``x`` from radians into degrees. - - -.. function:: radians(x: Float) -> Float - - Convert ``x`` from degrees into radians. - - -.. function:: log(x: Float) -> Float - - Return the natural logarithm (base-e) of ``x``, where ``x`` is positive. - - -.. function:: log2(x: Float) -> Float - - Return the binary logarithm (base-2) of ``x``, where ``x`` is positive. - - -.. function:: log10(x: Float) -> Float - - Return the common logarithm (base-10) of ``x``, where ``x`` is positive. - - -.. function:: exp(x: Float) -> Float - - Return the value of the exponential function :math:`e^x`. - - -.. function:: pow(x: Float, y: Float) -> Float - - Return the result of ``x`` raised to power of ``y``. - - -.. function:: round(x: Float) -> Float - - Return the nearest integer value to ``x``, rounding halfway cases away from zero. - This is the most intuitive form of rounding in the colloquial sense, but can be slower than other options like :func:`warp.rint()`. - Differs from :func:`numpy.round()`, which behaves the same way as :func:`numpy.rint()`. - - -.. function:: rint(x: Float) -> Float - - Return the nearest integer value to ``x``, rounding halfway cases to nearest even integer. - It is generally faster than :func:`warp.round()`. Equivalent to :func:`numpy.rint()`. - - -.. function:: trunc(x: Float) -> Float - - Return the nearest integer that is closer to zero than ``x``. - In other words, it discards the fractional part of ``x``. - It is similar to casting ``float(int(x))``, but preserves the negative sign when x is in the range [-0.0, -1.0). - Equivalent to :func:`numpy.trunc()` and :func:`numpy.fix()`. - - -.. function:: floor(x: Float) -> Float - - Return the largest integer that is less than or equal to ``x``. - - -.. function:: ceil(x: Float) -> Float - - Return the smallest integer that is greater than or equal to ``x``. - - -.. function:: frac(x: Float) -> Float - - Retrieve the fractional part of x. - In other words, it discards the integer part of x and is equivalent to ``x - trunc(x)``. - - - - -Vector Math ---------------- -.. function:: dot(x: Vector[Any,Scalar], y: Vector[Any,Scalar]) -> Scalar - - Compute the dot product between two vectors. - - -.. function:: dot(x: Quaternion[Float], y: Quaternion[Float]) -> Scalar - :noindex: - :nocontentsentry: - - Compute the dot product between two quaternions. - - -.. function:: ddot(x: Matrix[Any,Any,Scalar], y: Matrix[Any,Any,Scalar]) -> Scalar - - Compute the double dot product between two matrices. - - -.. function:: argmin(v: Vector[Any,Scalar]) -> uint32 - - Return the index of the minimum element of a vector ``v``. [1]_ - - -.. function:: argmax(v: Vector[Any,Scalar]) -> uint32 - - Return the index of the maximum element of a vector ``v``. [1]_ - - -.. function:: outer(x: Vector[Any,Scalar], y: Vector[Any,Scalar]) -> Matrix[Any,Any,Scalar] - - Compute the outer product ``x*y^T`` for two vectors. - - -.. function:: cross(x: Vector[3,Scalar], y: Vector[3,Scalar]) -> Vector[3,Scalar] - - Compute the cross product of two 3D vectors. - - -.. function:: skew(x: Vector[3,Scalar]) - - Compute the skew-symmetric 3x3 matrix for a 3D vector ``x``. - - -.. function:: length(x: Vector[Any,Float]) -> Scalar - - Compute the length of a vector ``x``. - - -.. function:: length(x: Quaternion[Float]) -> Scalar - :noindex: - :nocontentsentry: - - Compute the length of a quaternion ``x``. - - -.. function:: length_sq(x: Vector[Any,Scalar]) -> Scalar - - Compute the squared length of a 2D vector ``x``. - - -.. function:: length_sq(x: Quaternion[Scalar]) -> Scalar - :noindex: - :nocontentsentry: - - Compute the squared length of a quaternion ``x``. - - -.. function:: normalize(x: Vector[Any,Float]) -> Vector[Any,Scalar] - - Compute the normalized value of ``x``. If ``length(x)`` is 0 then the zero vector is returned. - - -.. function:: normalize(x: Quaternion[Float]) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - Compute the normalized value of ``x``. If ``length(x)`` is 0, then the zero quaternion is returned. - - -.. function:: transpose(m: Matrix[Any,Any,Scalar]) - - Return the transpose of the matrix ``m``. - - -.. function:: inverse(m: Matrix[2,2,Float]) -> Matrix[Any,Any,Float] - - Return the inverse of a 2x2 matrix ``m``. - - -.. function:: inverse(m: Matrix[3,3,Float]) -> Matrix[Any,Any,Float] - :noindex: - :nocontentsentry: - - Return the inverse of a 3x3 matrix ``m``. - - -.. function:: inverse(m: Matrix[4,4,Float]) -> Matrix[Any,Any,Float] - :noindex: - :nocontentsentry: - - Return the inverse of a 4x4 matrix ``m``. - - -.. function:: determinant(m: Matrix[2,2,Float]) -> Scalar - - Return the determinant of a 2x2 matrix ``m``. - - -.. function:: determinant(m: Matrix[3,3,Float]) -> Scalar - :noindex: - :nocontentsentry: - - Return the determinant of a 3x3 matrix ``m``. - - -.. function:: determinant(m: Matrix[4,4,Float]) -> Scalar - :noindex: - :nocontentsentry: - - Return the determinant of a 4x4 matrix ``m``. - - -.. function:: trace(m: Matrix[Any,Any,Scalar]) -> Scalar - - Return the trace of the matrix ``m``. - - -.. function:: diag(d: Vector[Any,Scalar]) -> Matrix[Any,Any,Scalar] - - Returns a matrix with the components of the vector ``d`` on the diagonal. - - -.. function:: get_diag(m: Matrix[Any,Any,Scalar]) -> Vector[Any,Scalar] - - Returns a vector containing the diagonal elements of the square matrix ``m``. - - -.. function:: cw_mul(x: Vector[Any,Scalar], y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - - Component-wise multiplication of two 2D vectors. - - -.. function:: cw_mul(x: Matrix[Any,Any,Scalar], y: Matrix[Any,Any,Scalar]) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - Component-wise multiplication of two 2D vectors. - - -.. function:: cw_div(x: Vector[Any,Scalar], y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - - Component-wise division of two 2D vectors. - - -.. function:: cw_div(x: Matrix[Any,Any,Scalar], y: Matrix[Any,Any,Scalar]) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - Component-wise division of two 2D vectors. - - -.. function:: vector(w: Vector[3,Float], v: Vector[3,Float]) - - Construct a 6D screw vector from two 3D vectors. - - -.. function:: vector(*arg_types: Scalar, length: int32, dtype: Scalar) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - Construct a vector of with given length and dtype. - - -.. function:: matrix(pos: Vector[3,Float], rot: Quaternion[Float], scale: Vector[3,Float]) -> Matrix[Any,Any,Float] - - Construct a 4x4 transformation matrix that applies the transformations as - Translation(pos)*Rotation(rot)*Scale(scale) when applied to column vectors, i.e.: y = (TRS)*x - - -.. function:: matrix(*arg_types: Scalar, shape: Tuple[int, int], dtype: Scalar) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - Construct a matrix. If the positional ``arg_types`` are not given, then matrix will be zero-initialized. - - -.. function:: identity(n: int32, dtype: Scalar) -> Matrix[Any,Any,Scalar] - - Create an identity matrix with shape=(n,n) with the type given by ``dtype``. - - -.. function:: svd3(A: Matrix[3,3,Float], U: Matrix[3,3,Float], sigma: Vector[3,Float], V: Matrix[3,3,Scalar]) -> None - - Compute the SVD of a 3x3 matrix ``A``. The singular values are returned in ``sigma``, - while the left and right basis vectors are returned in ``U`` and ``V``. - - -.. function:: qr3(A: Matrix[3,3,Float], Q: Matrix[3,3,Float], R: Matrix[3,3,Float]) -> None - - Compute the QR decomposition of a 3x3 matrix ``A``. The orthogonal matrix is returned in ``Q``, - while the upper triangular matrix is returned in ``R``. - - -.. function:: eig3(A: Matrix[3,3,Float], Q: Matrix[3,3,Float], d: Vector[3,Float]) -> None - - Compute the eigendecomposition of a 3x3 matrix ``A``. The eigenvectors are returned as the columns of ``Q``, - while the corresponding eigenvalues are returned in ``d``. - - - - -Other ---------------- -.. function:: lower_bound(arr: Array[Scalar], value: Scalar) -> int - - Search a sorted array ``arr`` for the closest element greater than or equal to ``value``. - - -.. function:: lower_bound(arr: Array[Scalar], arr_begin: int32, arr_end: int32, value: Scalar) -> int - :noindex: - :nocontentsentry: - - Search a sorted array ``arr`` in the range [arr_begin, arr_end) for the closest element greater than or equal to ``value``. - - - - -Quaternion Math ---------------- -.. function:: quaternion() -> Quaternion[Float] - - Construct a zero-initialized quaternion. Quaternions are laid out as - [ix, iy, iz, r], where ix, iy, iz are the imaginary part, and r the real part. - - -.. function:: quaternion(x: Float, y: Float, z: Float, w: Float) -> Quaternion[Float] - :noindex: - :nocontentsentry: - - Create a quaternion using the supplied components (type inferred from component type). - - -.. function:: quaternion(i: Vector[3,Float], r: Float) -> Quaternion[Float] - :noindex: - :nocontentsentry: - - Create a quaternion using the supplied vector/scalar (type inferred from scalar type). - - -.. function:: quaternion(q: Quaternion[Float]) - :noindex: - :nocontentsentry: - - Construct a quaternion of type dtype from another quaternion of a different dtype. - - -.. function:: quat_identity() -> quatf - - Construct an identity quaternion with zero imaginary part and real part of 1.0 - - -.. function:: quat_from_axis_angle(axis: Vector[3,Float], angle: Float) -> Quaternion[Scalar] - - Construct a quaternion representing a rotation of angle radians around the given axis. - - -.. function:: quat_to_axis_angle(q: Quaternion[Float], axis: Vector[3,Float], angle: Float) -> None - - Extract the rotation axis and angle radians a quaternion represents. - - -.. function:: quat_from_matrix(m: Matrix[3,3,Float]) -> Quaternion[Scalar] - - Construct a quaternion from a 3x3 matrix. - - -.. function:: quat_rpy(roll: Float, pitch: Float, yaw: Float) -> Quaternion[Scalar] - - Construct a quaternion representing a combined roll (z), pitch (x), yaw rotations (y) in radians. - - -.. function:: quat_inverse(q: Quaternion[Float]) -> Quaternion[Scalar] - - Compute quaternion conjugate. - - -.. function:: quat_rotate(q: Quaternion[Float], p: Vector[3,Float]) -> Vector[3,Scalar] - - Rotate a vector by a quaternion. - - -.. function:: quat_rotate_inv(q: Quaternion[Float], p: Vector[3,Float]) -> Vector[3,Scalar] - - Rotate a vector by the inverse of a quaternion. - - -.. function:: quat_slerp(q0: Quaternion[Float], q1: Quaternion[Float], t: Float) -> Quaternion[Scalar] - - Linearly interpolate between two quaternions. - - -.. function:: quat_to_matrix(q: Quaternion[Float]) -> Matrix[3,3,Scalar] - - Convert a quaternion to a 3x3 rotation matrix. - - - - -Transformations ---------------- -.. function:: transformation(p: Vector[3,Float], q: Quaternion[Float]) -> Transformation[Scalar] - - Construct a rigid-body transformation with translation part ``p`` and rotation ``q``. - - -.. function:: transform_identity() -> transformf - - Construct an identity transform with zero translation and identity rotation. - - -.. function:: transform_get_translation(t: Transformation[Float]) -> Vector[3,Scalar] - - Return the translational part of a transform ``t``. - - -.. function:: transform_get_rotation(t: Transformation[Float]) -> Quaternion[Scalar] - - Return the rotational part of a transform ``t``. - - -.. function:: transform_multiply(a: Transformation[Float], b: Transformation[Float]) -> Transformation[Scalar] - - Multiply two rigid body transformations together. - - -.. function:: transform_point(t: Transformation[Scalar], p: Vector[3,Scalar]) -> Vector[3,Scalar] - - Apply the transform to a point ``p`` treating the homogeneous coordinate as w=1 (translation and rotation). - - -.. function:: transform_point(m: Matrix[4,4,Scalar], p: Vector[3,Scalar]) -> Vector[3,Scalar] - :noindex: - :nocontentsentry: - - Apply the transform to a point ``p`` treating the homogeneous coordinate as w=1. - The transformation is applied treating ``p`` as a column vector, e.g.: ``y = M*p``. - Note this is in contrast to some libraries, notably USD, which applies transforms to row vectors, ``y^T = p^T*M^T``. - If the transform is coming from a library that uses row-vectors, then users should transpose the transformation - matrix before calling this method. - - -.. function:: transform_vector(t: Transformation[Scalar], v: Vector[3,Scalar]) -> Vector[3,Scalar] - - Apply the transform to a vector ``v`` treating the homogeneous coordinate as w=0 (rotation only). - - -.. function:: transform_vector(m: Matrix[4,4,Scalar], v: Vector[3,Scalar]) -> Vector[3,Scalar] - :noindex: - :nocontentsentry: - - Apply the transform to a vector ``v`` treating the homogeneous coordinate as w=0. - The transformation is applied treating ``v`` as a column vector, e.g.: ``y = M*v`` - note this is in contrast to some libraries, notably USD, which applies transforms to row vectors, ``y^T = v^T*M^T``. - If the transform is coming from a library that uses row-vectors, then users should transpose the transformation - matrix before calling this method. - - -.. function:: transform_inverse(t: Transformation[Float]) -> Transformation[Float] - - Compute the inverse of the transformation ``t``. - - - - -Spatial Math ---------------- -.. function:: spatial_adjoint(r: Matrix[3,3,Float], s: Matrix[3,3,Float]) -> Matrix[6,6,Scalar] - - Construct a 6x6 spatial inertial matrix from two 3x3 diagonal blocks. - - -.. function:: spatial_dot(a: Vector[6,Float], b: Vector[6,Float]) -> Scalar - - Compute the dot product of two 6D screw vectors. - - -.. function:: spatial_cross(a: Vector[6,Float], b: Vector[6,Float]) -> Vector[6,Float] - - Compute the cross product of two 6D screw vectors. - - -.. function:: spatial_cross_dual(a: Vector[6,Float], b: Vector[6,Float]) -> Vector[6,Float] - - Compute the dual cross product of two 6D screw vectors. - - -.. function:: spatial_top(a: Vector[6,Float]) - - Return the top (first) part of a 6D screw vector. - - -.. function:: spatial_bottom(a: Vector[6,Float]) - - Return the bottom (second) part of a 6D screw vector. - - -.. function:: spatial_jacobian(S: Array[Vector[6,Float]], joint_parents: Array[int32], joint_qd_start: Array[int32], joint_start: int32, joint_count: int32, J_start: int32, J_out: Array[Float]) -> None - - -.. function:: spatial_mass(I_s: Array[Matrix[6,6,Float]], joint_start: int32, joint_count: int32, M_start: int32, M: Array[Float]) -> None - - - - -Utility ---------------- -.. function:: mlp(weights: Array[float32], bias: Array[float32], activation: Callable, index: int32, x: Array[float32], out: Array[float32]) -> None - - Evaluate a multi-layer perceptron (MLP) layer in the form: ``out = act(weights*x + bias)``. - - :param weights: A layer's network weights with dimensions ``(m, n)``. - :param bias: An array with dimensions ``(n)``. - :param activation: A ``wp.func`` function that takes a single scalar float as input and returns a scalar float as output - :param index: The batch item to process, typically each thread will process one item in the batch, in which case - index should be ``wp.tid()`` - :param x: The feature matrix with dimensions ``(n, b)`` - :param out: The network output with dimensions ``(m, b)`` - - :note: Feature and output matrices are transposed compared to some other frameworks such as PyTorch. - All matrices are assumed to be stored in flattened row-major memory layout (NumPy default). - - -.. function:: printf() -> None - - Allows printing formatted strings using C-style format specifiers. - - -.. function:: print(value: Any) -> None - - Print variable to stdout - - -.. function:: breakpoint() -> None - - Debugger breakpoint - - -.. function:: tid() -> int - - Return the current thread index for a 1D kernel launch. Note that this is the *global* index of the thread in the range [0, dim) - where dim is the parameter passed to kernel launch. This function may not be called from user-defined Warp functions. - - -.. function:: tid() -> Tuple[int, int] - :noindex: - :nocontentsentry: - - Return the current thread indices for a 2D kernel launch. Use ``i,j = wp.tid()`` syntax to retrieve the - coordinates inside the kernel thread grid. This function may not be called from user-defined Warp functions. - - -.. function:: tid() -> Tuple[int, int, int] - :noindex: - :nocontentsentry: - - Return the current thread indices for a 3D kernel launch. Use ``i,j,k = wp.tid()`` syntax to retrieve the - coordinates inside the kernel thread grid. This function may not be called from user-defined Warp functions. - - -.. function:: tid() -> Tuple[int, int, int, int] - :noindex: - :nocontentsentry: - - Return the current thread indices for a 4D kernel launch. Use ``i,j,k,l = wp.tid()`` syntax to retrieve the - coordinates inside the kernel thread grid. This function may not be called from user-defined Warp functions. - - -.. function:: select(cond: bool, arg1: Any, arg2: Any) - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: bool, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: int8, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: uint8, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: int16, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: uint16, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: int32, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: uint32, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: int64, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(cond: uint64, arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2`` - - -.. function:: select(arr: Array[Any], arg1: Any, arg2: Any) - :noindex: - :nocontentsentry: - - Select between two arguments, if ``arr`` is null then return ``arg1``, otherwise return ``arg2`` - - -.. function:: atomic_add(a: Array[Any], i: int32, value: Any) - - Atomically add ``value`` onto ``a[i]``. - - -.. function:: atomic_add(a: Array[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j]``. - - -.. function:: atomic_add(a: Array[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j,k]``. - - -.. function:: atomic_add(a: Array[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j,k,l]``. - - -.. function:: atomic_add(a: FabricArray[Any], i: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i]``. - - -.. function:: atomic_add(a: FabricArray[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j]``. - - -.. function:: atomic_add(a: FabricArray[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j,k]``. - - -.. function:: atomic_add(a: FabricArray[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j,k,l]``. - - -.. function:: atomic_add(a: IndexedFabricArray[Any], i: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i]``. - - -.. function:: atomic_add(a: IndexedFabricArray[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j]``. - - -.. function:: atomic_add(a: IndexedFabricArray[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j,k]``. - - -.. function:: atomic_add(a: IndexedFabricArray[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically add ``value`` onto ``a[i,j,k,l]``. - - -.. function:: atomic_sub(a: Array[Any], i: int32, value: Any) - - Atomically subtract ``value`` onto ``a[i]``. - - -.. function:: atomic_sub(a: Array[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j]``. - - -.. function:: atomic_sub(a: Array[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j,k]``. - - -.. function:: atomic_sub(a: Array[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j,k,l]``. - - -.. function:: atomic_sub(a: FabricArray[Any], i: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i]``. - - -.. function:: atomic_sub(a: FabricArray[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j]``. - - -.. function:: atomic_sub(a: FabricArray[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j,k]``. - - -.. function:: atomic_sub(a: FabricArray[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j,k,l]``. - - -.. function:: atomic_sub(a: IndexedFabricArray[Any], i: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i]``. - - -.. function:: atomic_sub(a: IndexedFabricArray[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j]``. - - -.. function:: atomic_sub(a: IndexedFabricArray[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j,k]``. - - -.. function:: atomic_sub(a: IndexedFabricArray[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Atomically subtract ``value`` onto ``a[i,j,k,l]``. - - -.. function:: atomic_min(a: Array[Any], i: int32, value: Any) - - Compute the minimum of ``value`` and ``a[i]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: Array[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: Array[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j,k]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: Array[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j,k,l]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: FabricArray[Any], i: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: FabricArray[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: FabricArray[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j,k]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: FabricArray[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j,k,l]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: IndexedFabricArray[Any], i: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: IndexedFabricArray[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: IndexedFabricArray[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j,k]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_min(a: IndexedFabricArray[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the minimum of ``value`` and ``a[i,j,k,l]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: Array[Any], i: int32, value: Any) - - Compute the maximum of ``value`` and ``a[i]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: Array[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: Array[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j,k]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: Array[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j,k,l]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: FabricArray[Any], i: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: FabricArray[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: FabricArray[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j,k]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: FabricArray[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j,k,l]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: IndexedFabricArray[Any], i: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: IndexedFabricArray[Any], i: int32, j: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: IndexedFabricArray[Any], i: int32, j: int32, k: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j,k]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: atomic_max(a: IndexedFabricArray[Any], i: int32, j: int32, k: int32, l: int32, value: Any) - :noindex: - :nocontentsentry: - - Compute the maximum of ``value`` and ``a[i,j,k,l]`` and atomically update the array. - -Note that for vectors and matrices the operation is only atomic on a per-component basis. - - -.. function:: lerp(a: Float, b: Float, t: Float) -> Float - - Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t`` - - -.. function:: lerp(a: Vector[Any,Float], b: Vector[Any,Float], t: Float) -> Vector[Any,Float] - :noindex: - :nocontentsentry: - - Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t`` - - -.. function:: lerp(a: Matrix[Any,Any,Float], b: Matrix[Any,Any,Float], t: Float) -> Matrix[Any,Any,Float] - :noindex: - :nocontentsentry: - - Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t`` - - -.. function:: lerp(a: Quaternion[Float], b: Quaternion[Float], t: Float) -> Quaternion[Float] - :noindex: - :nocontentsentry: - - Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t`` - - -.. function:: lerp(a: Transformation[Float], b: Transformation[Float], t: Float) -> Transformation[Float] - :noindex: - :nocontentsentry: - - Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t`` - - -.. function:: smoothstep(edge0: Float, edge1: Float, x: Float) -> Float - - Smoothly interpolate between two values ``edge0`` and ``edge1`` using a factor ``x``, - and return a result between 0 and 1 using a cubic Hermite interpolation after clamping. - - -.. function:: expect_near(arg1: Float, arg2: Float, tolerance: Float) -> None - - Prints an error to stdout if ``arg1`` and ``arg2`` are not closer than tolerance in magnitude - - -.. function:: expect_near(arg1: vec3f, arg2: vec3f, tolerance: float32) -> None - :noindex: - :nocontentsentry: - - Prints an error to stdout if any element of ``arg1`` and ``arg2`` are not closer than tolerance in magnitude - - - - -Geometry ---------------- -.. function:: bvh_query_aabb(id: uint64, lower: vec3f, upper: vec3f) -> bvh_query_t - - Construct an axis-aligned bounding box query against a BVH object. This query can be used to iterate over all bounds - inside a BVH. - - :param id: The BVH identifier - :param lower: The lower bound of the bounding box in BVH space - :param upper: The upper bound of the bounding box in BVH space - - -.. function:: bvh_query_ray(id: uint64, start: vec3f, dir: vec3f) -> bvh_query_t - - Construct a ray query against a BVH object. This query can be used to iterate over all bounds - that intersect the ray. - - :param id: The BVH identifier - :param start: The start of the ray in BVH space - :param dir: The direction of the ray in BVH space - - -.. function:: bvh_query_next(query: bvh_query_t, index: int32) -> bool - - Move to the next bound returned by the query. - The index of the current bound is stored in ``index``, returns ``False`` if there are no more overlapping bound. - - -.. function:: mesh_query_point(id: uint64, point: vec3f, max_dist: float32) -> mesh_query_point_t - - Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. - - Identifies the sign of the distance using additional ray-casts to determine if the point is inside or outside. - This method is relatively robust, but does increase computational cost. - See below for additional sign determination methods. - - :param id: The mesh identifier - :param point: The point in space to query - :param max_dist: Mesh faces above this distance will not be considered by the query - - -.. function:: mesh_query_point_no_sign(id: uint64, point: vec3f, max_dist: float32) -> mesh_query_point_t - - Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. - - This method does not compute the sign of the point (inside/outside) which makes it faster than other point query methods. - - :param id: The mesh identifier - :param point: The point in space to query - :param max_dist: Mesh faces above this distance will not be considered by the query - - -.. function:: mesh_query_furthest_point_no_sign(id: uint64, point: vec3f, min_dist: float32) -> mesh_query_point_t - - Computes the furthest point on the mesh with identifier `id` to the given point in space. - - This method does not compute the sign of the point (inside/outside). - - :param id: The mesh identifier - :param point: The point in space to query - :param min_dist: Mesh faces below this distance will not be considered by the query - - -.. function:: mesh_query_point_sign_normal(id: uint64, point: vec3f, max_dist: float32, epsilon: float32) -> mesh_query_point_t - - Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. - - Identifies the sign of the distance (inside/outside) using the angle-weighted pseudo normal. - This approach to sign determination is robust for well conditioned meshes that are watertight and non-self intersecting. - It is also comparatively fast to compute. - - :param id: The mesh identifier - :param point: The point in space to query - :param max_dist: Mesh faces above this distance will not be considered by the query - :param epsilon: Epsilon treating distance values as equal, when locating the minimum distance vertex/face/edge, as a - fraction of the average edge length, also for treating closest point as being on edge/vertex default 1e-3 - - -.. function:: mesh_query_point_sign_winding_number(id: uint64, point: vec3f, max_dist: float32, accuracy: float32, threshold: float32) -> mesh_query_point_t - - Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given point in space. - - Identifies the sign using the winding number of the mesh relative to the query point. This method of sign determination is robust for poorly conditioned meshes - and provides a smooth approximation to sign even when the mesh is not watertight. This method is the most robust and accurate of the sign determination meshes - but also the most expensive. - - .. note:: The :class:`Mesh` object must be constructed with ``support_winding_number=True`` for this method to return correct results. - - :param id: The mesh identifier - :param point: The point in space to query - :param max_dist: Mesh faces above this distance will not be considered by the query - :param accuracy: Accuracy for computing the winding number with fast winding number method utilizing second-order dipole approximation, default 2.0 - :param threshold: The threshold of the winding number to be considered inside, default 0.5 - - -.. function:: mesh_query_ray(id: uint64, start: vec3f, dir: vec3f, max_t: float32) -> mesh_query_ray_t - - Computes the closest ray hit on the :class:`Mesh` with identifier ``id``. - - :param id: The mesh identifier - :param start: The start point of the ray - :param dir: The ray direction (should be normalized) - :param max_t: The maximum distance along the ray to check for intersections - - -.. function:: mesh_query_aabb(id: uint64, lower: vec3f, upper: vec3f) -> mesh_query_aabb_t - - Construct an axis-aligned bounding box query against a :class:`Mesh`. - This query can be used to iterate over all triangles inside a volume. - - :param id: The mesh identifier - :param lower: The lower bound of the bounding box in mesh space - :param upper: The upper bound of the bounding box in mesh space - - -.. function:: mesh_query_aabb_next(query: mesh_query_aabb_t, index: int32) -> bool - - Move to the next triangle overlapping the query bounding box. - The index of the current face is stored in ``index``, returns ``False`` if there are no more overlapping triangles. - - -.. function:: mesh_eval_position(id: uint64, face: int32, bary_u: float32, bary_v: float32) -> vec3f - - Evaluates the position on the :class:`Mesh` given a face index and barycentric coordinates. - - -.. function:: mesh_eval_velocity(id: uint64, face: int32, bary_u: float32, bary_v: float32) -> vec3f - - Evaluates the velocity on the :class:`Mesh` given a face index and barycentric coordinates. - - -.. function:: hash_grid_query(id: uint64, point: vec3f, max_dist: float32) -> hash_grid_query_t - - Construct a point query against a :class:`HashGrid`. This query can be used to iterate over all neighboring points within a fixed radius from the query point. - - -.. function:: hash_grid_query_next(query: hash_grid_query_t, index: int32) -> bool - - Move to the next point in the hash grid query. The index of the current neighbor is stored in ``index``, returns ``False`` - if there are no more neighbors. - - -.. function:: hash_grid_point_id(id: uint64, index: int32) -> int - - Return the index of a point in the :class:`HashGrid`. This can be used to reorder threads such that grid - traversal occurs in a spatially coherent order. - - Returns -1 if the :class:`HashGrid` has not been reserved. - - -.. function:: intersect_tri_tri(v0: vec3f, v1: vec3f, v2: vec3f, u0: vec3f, u1: vec3f, u2: vec3f) -> int - - Tests for intersection between two triangles (v0, v1, v2) and (u0, u1, u2) using Moller's method. Returns > 0 if triangles intersect. - - -.. function:: mesh_get(id: uint64) -> Mesh - - Retrieves the mesh given its index. [1]_ - - -.. function:: mesh_eval_face_normal(id: uint64, face: int32) -> vec3f - - Evaluates the face normal the mesh given a face index. - - -.. function:: mesh_get_point(id: uint64, index: int32) -> vec3f - - Returns the point of the mesh given a index. - - -.. function:: mesh_get_velocity(id: uint64, index: int32) -> vec3f - - Returns the velocity of the mesh given a index. - - -.. function:: mesh_get_index(id: uint64, index: int32) -> int - - Returns the point-index of the mesh given a face-vertex index. - - -.. function:: closest_point_edge_edge(p1: vec3f, q1: vec3f, p2: vec3f, q2: vec3f, epsilon: float32) -> vec3f - - Finds the closest points between two edges. Returns barycentric weights to the points on each edge, as well as the closest distance between the edges. - - :param p1: First point of first edge - :param q1: Second point of first edge - :param p2: First point of second edge - :param q2: Second point of second edge - :param epsilon: Zero tolerance for determining if points in an edge are degenerate. - :param out: vec3 output containing (s,t,d), where `s` in [0,1] is the barycentric weight for the first edge, `t` is the barycentric weight for the second edge, and `d` is the distance between the two edges at these two closest points. - - - - -Volumes ---------------- -.. function:: volume_sample_f(id: uint64, uvw: vec3f, sampling_mode: int32) -> float - - Sample the volume given by ``id`` at the volume local-space point ``uvw``. - Interpolation should be :attr:`warp.Volume.CLOSEST` or :attr:`wp.Volume.LINEAR.` - - -.. function:: volume_sample_grad_f(id: uint64, uvw: vec3f, sampling_mode: int32, grad: vec3f) -> float - - Sample the volume and its gradient given by ``id`` at the volume local-space point ``uvw``. - Interpolation should be :attr:`warp.Volume.CLOSEST` or :attr:`wp.Volume.LINEAR.` - - -.. function:: volume_lookup_f(id: uint64, i: int32, j: int32, k: int32) -> float - - Returns the value of voxel with coordinates ``i``, ``j``, ``k``. - If the voxel at this index does not exist, this function returns the background value - - -.. function:: volume_store_f(id: uint64, i: int32, j: int32, k: int32, value: float32) -> None - - Store ``value`` at the voxel with coordinates ``i``, ``j``, ``k``. - - -.. function:: volume_sample_v(id: uint64, uvw: vec3f, sampling_mode: int32) -> vec3f - - Sample the vector volume given by ``id`` at the volume local-space point ``uvw``. - Interpolation should be :attr:`warp.Volume.CLOSEST` or :attr:`wp.Volume.LINEAR.` - - -.. function:: volume_lookup_v(id: uint64, i: int32, j: int32, k: int32) -> vec3f - - Returns the vector value of voxel with coordinates ``i``, ``j``, ``k``. - If the voxel at this index does not exist, this function returns the background value. - - -.. function:: volume_store_v(id: uint64, i: int32, j: int32, k: int32, value: vec3f) -> None - - Store ``value`` at the voxel with coordinates ``i``, ``j``, ``k``. - - -.. function:: volume_sample_i(id: uint64, uvw: vec3f) -> int - - Sample the :class:`int32` volume given by ``id`` at the volume local-space point ``uvw``. - - -.. function:: volume_lookup_i(id: uint64, i: int32, j: int32, k: int32) -> int - - Returns the :class:`int32` value of voxel with coordinates ``i``, ``j``, ``k``. - If the voxel at this index does not exist, this function returns the background value. - - -.. function:: volume_store_i(id: uint64, i: int32, j: int32, k: int32, value: int32) -> None - - Store ``value`` at the voxel with coordinates ``i``, ``j``, ``k``. - - -.. function:: volume_index_to_world(id: uint64, uvw: vec3f) -> vec3f - - Transform a point ``uvw`` defined in volume index space to world space given the volume's intrinsic affine transformation. - - -.. function:: volume_world_to_index(id: uint64, xyz: vec3f) -> vec3f - - Transform a point ``xyz`` defined in volume world space to the volume's index space given the volume's intrinsic affine transformation. - - -.. function:: volume_index_to_world_dir(id: uint64, uvw: vec3f) -> vec3f - - Transform a direction ``uvw`` defined in volume index space to world space given the volume's intrinsic affine transformation. - - -.. function:: volume_world_to_index_dir(id: uint64, xyz: vec3f) -> vec3f - - Transform a direction ``xyz`` defined in volume world space to the volume's index space given the volume's intrinsic affine transformation. - - - - -Random ---------------- -.. function:: rand_init(seed: int32) -> uint32 - - Initialize a new random number generator given a user-defined seed. Returns a 32-bit integer representing the RNG state. - - -.. function:: rand_init(seed: int32, offset: int32) -> uint32 - :noindex: - :nocontentsentry: - - Initialize a new random number generator given a user-defined seed and an offset. - This alternative constructor can be useful in parallel programs, where a kernel as a whole should share a seed, - but each thread should generate uncorrelated values. In this case usage should be ``r = rand_init(seed, tid)`` - - -.. function:: randi(state: uint32) -> int - - Return a random integer in the range [0, 2^32). - - -.. function:: randi(state: uint32, min: int32, max: int32) -> int - :noindex: - :nocontentsentry: - - Return a random integer between [min, max). - - -.. function:: randf(state: uint32) -> float - - Return a random float between [0.0, 1.0). - - -.. function:: randf(state: uint32, min: float32, max: float32) -> float - :noindex: - :nocontentsentry: - - Return a random float between [min, max). - - -.. function:: randn(state: uint32) -> float - - Sample a normal distribution. - - -.. function:: sample_cdf(state: uint32, cdf: Array[float32]) -> int - - Inverse-transform sample a cumulative distribution function. - - -.. function:: sample_triangle(state: uint32) -> vec2f - - Uniformly sample a triangle. Returns sample barycentric coordinates. - - -.. function:: sample_unit_ring(state: uint32) -> vec2f - - Uniformly sample a ring in the xy plane. - - -.. function:: sample_unit_disk(state: uint32) -> vec2f - - Uniformly sample a disk in the xy plane. - - -.. function:: sample_unit_sphere_surface(state: uint32) -> vec3f - - Uniformly sample a unit sphere surface. - - -.. function:: sample_unit_sphere(state: uint32) -> vec3f - - Uniformly sample a unit sphere. - - -.. function:: sample_unit_hemisphere_surface(state: uint32) -> vec3f - - Uniformly sample a unit hemisphere surface. - - -.. function:: sample_unit_hemisphere(state: uint32) -> vec3f - - Uniformly sample a unit hemisphere. - - -.. function:: sample_unit_square(state: uint32) -> vec2f - - Uniformly sample a unit square. - - -.. function:: sample_unit_cube(state: uint32) -> vec3f - - Uniformly sample a unit cube. - - -.. function:: poisson(state: uint32, lam: float32) -> uint32 - - Generate a random sample from a Poisson distribution. - - :param state: RNG state - :param lam: The expected value of the distribution - - -.. function:: noise(state: uint32, x: float32) -> float - - Non-periodic Perlin-style noise in 1D. - - -.. function:: noise(state: uint32, xy: vec2f) -> float - :noindex: - :nocontentsentry: - - Non-periodic Perlin-style noise in 2D. - - -.. function:: noise(state: uint32, xyz: vec3f) -> float - :noindex: - :nocontentsentry: - - Non-periodic Perlin-style noise in 3D. - - -.. function:: noise(state: uint32, xyzt: vec4f) -> float - :noindex: - :nocontentsentry: - - Non-periodic Perlin-style noise in 4D. - - -.. function:: pnoise(state: uint32, x: float32, px: int32) -> float - - Periodic Perlin-style noise in 1D. - - -.. function:: pnoise(state: uint32, xy: vec2f, px: int32, py: int32) -> float - :noindex: - :nocontentsentry: - - Periodic Perlin-style noise in 2D. - - -.. function:: pnoise(state: uint32, xyz: vec3f, px: int32, py: int32, pz: int32) -> float - :noindex: - :nocontentsentry: - - Periodic Perlin-style noise in 3D. - - -.. function:: pnoise(state: uint32, xyzt: vec4f, px: int32, py: int32, pz: int32, pt: int32) -> float - :noindex: - :nocontentsentry: - - Periodic Perlin-style noise in 4D. - - -.. function:: curlnoise(state: uint32, xy: vec2f, octaves: uint32, lacunarity: float32, gain: float32) -> vec2f - - Divergence-free vector field based on the gradient of a Perlin noise function. [1]_ - - -.. function:: curlnoise(state: uint32, xyz: vec3f, octaves: uint32, lacunarity: float32, gain: float32) -> vec3f - :noindex: - :nocontentsentry: - - Divergence-free vector field based on the curl of three Perlin noise functions. [1]_ - - -.. function:: curlnoise(state: uint32, xyzt: vec4f, octaves: uint32, lacunarity: float32, gain: float32) -> vec3f - :noindex: - :nocontentsentry: - - Divergence-free vector field based on the curl of three Perlin noise functions. [1]_ - - - - -Operators ---------------- -.. function:: add(x: Scalar, y: Scalar) -> Scalar - - -.. function:: add(x: Vector[Any,Scalar], y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: add(x: Quaternion[Scalar], y: Quaternion[Scalar]) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: add(x: Matrix[Any,Any,Scalar], y: Matrix[Any,Any,Scalar]) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: add(x: Transformation[Scalar], y: Transformation[Scalar]) -> Transformation[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: sub(x: Scalar, y: Scalar) -> Scalar - - -.. function:: sub(x: Vector[Any,Scalar], y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: sub(x: Matrix[Any,Any,Scalar], y: Matrix[Any,Any,Scalar]) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: sub(x: Quaternion[Scalar], y: Quaternion[Scalar]) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: sub(x: Transformation[Scalar], y: Transformation[Scalar]) -> Transformation[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: bit_and(x: Int, y: Int) -> Int - - -.. function:: bit_or(x: Int, y: Int) -> Int - - -.. function:: bit_xor(x: Int, y: Int) -> Int - - -.. function:: lshift(x: Int, y: Int) -> Int - - -.. function:: rshift(x: Int, y: Int) -> Int - - -.. function:: invert(x: Int) -> Int - - -.. function:: mul(x: Scalar, y: Scalar) -> Scalar - - -.. function:: mul(x: Vector[Any,Scalar], y: Scalar) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Scalar, y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Quaternion[Scalar], y: Scalar) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Scalar, y: Quaternion[Scalar]) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Quaternion[Scalar], y: Quaternion[Scalar]) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Scalar, y: Matrix[Any,Any,Scalar]) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Matrix[Any,Any,Scalar], y: Scalar) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Matrix[Any,Any,Scalar], y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Vector[Any,Scalar], y: Matrix[Any,Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Matrix[Any,Any,Scalar], y: Matrix[Any,Any,Scalar]) - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Transformation[Scalar], y: Transformation[Scalar]) -> Transformation[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Scalar, y: Transformation[Scalar]) -> Transformation[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mul(x: Transformation[Scalar], y: Scalar) -> Transformation[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: mod(x: Scalar, y: Scalar) -> Scalar - - -.. function:: div(x: Scalar, y: Scalar) -> Scalar - - -.. function:: div(x: Vector[Any,Scalar], y: Scalar) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: div(x: Scalar, y: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: div(x: Matrix[Any,Any,Scalar], y: Scalar) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: div(x: Scalar, y: Matrix[Any,Any,Scalar]) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: div(x: Quaternion[Scalar], y: Scalar) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: div(x: Scalar, y: Quaternion[Scalar]) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: floordiv(x: Scalar, y: Scalar) -> Scalar - - -.. function:: pos(x: Scalar) -> Scalar - - -.. function:: pos(x: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: pos(x: Quaternion[Scalar]) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: pos(x: Matrix[Any,Any,Scalar]) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: neg(x: Scalar) -> Scalar - - -.. function:: neg(x: Vector[Any,Scalar]) -> Vector[Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: neg(x: Quaternion[Scalar]) -> Quaternion[Scalar] - :noindex: - :nocontentsentry: - - -.. function:: neg(x: Matrix[Any,Any,Scalar]) -> Matrix[Any,Any,Scalar] - :noindex: - :nocontentsentry: - - -.. function:: unot(b: bool) -> bool - - -.. function:: unot(b: int8) -> bool - :noindex: - :nocontentsentry: - - -.. function:: unot(b: uint8) -> bool - :noindex: - :nocontentsentry: - - -.. function:: unot(b: int16) -> bool - :noindex: - :nocontentsentry: - - -.. function:: unot(b: uint16) -> bool - :noindex: - :nocontentsentry: - - -.. function:: unot(b: int32) -> bool - :noindex: - :nocontentsentry: - - -.. function:: unot(b: uint32) -> bool - :noindex: - :nocontentsentry: - - -.. function:: unot(b: int64) -> bool - :noindex: - :nocontentsentry: - - -.. function:: unot(b: uint64) -> bool - :noindex: - :nocontentsentry: - - -.. function:: unot(a: Array[Any]) -> bool - :noindex: - :nocontentsentry: - - -.. rubric:: Footnotes -.. [1] Note: function gradients not implemented for backpropagation. diff --git a/merge.bat b/merge.bat deleted file mode 100644 index 9a09f521a..000000000 --- a/merge.bat +++ /dev/null @@ -1,6 +0,0 @@ -REM Following command will merge master -> public, first switch to public branch -REM run the following and then review changes before committing. - -git merge --no-commit --allow-unrelated-histories --strategy-option theirs master - - diff --git a/setup.py b/setup.py index 56a9500c6..c13c2ffc0 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,8 @@ import pathlib import platform import shutil +import sys + from typing import NamedTuple import setuptools @@ -18,7 +20,7 @@ args = parser.parse_known_args()[0] -# return a canonical machine architecture string +# returns a canonical machine architecture string # - "x86_64" for x86-64, aka. AMD64, aka. x64 # - "aarch64" for AArch64, aka. ARM64 def machine_architecture() -> str: @@ -30,6 +32,16 @@ def machine_architecture() -> str: raise RuntimeError(f"Unrecognized machine architecture {machine}") +def machine_os() -> str: + if sys.platform == "win32": + return "windows" + if sys.platform == "linux": + return "linux" + if sys.platform == "darwin": + return "macos" + raise RuntimeError(f"Unrecognized system platform {sys.platform}") + + class Platform(NamedTuple): os: str arch: str @@ -99,11 +111,19 @@ def detect_warp_libraries(): if wheel_platform is None: if len(detected_platforms) > 1: - print("Libraries for multiple platforms were detected. Picking the first one.") + print("Libraries for multiple platforms were detected.") print( "Run `python -m build --wheel -C--build-option=-P[windows|linux|macos]-[x86_64|aarch64|universal]` to select a specific one." ) - wheel_platform = next(iter(detected_platforms)) + # Select the libraries corresponding with the this machine's platform + for p in platforms: + if p.os == machine_os() and p.arch == machine_architecture(): + wheel_platform = p + break + + if wheel_platform is None: + # Just pick the first one + wheel_platform = next(iter(detected_platforms)) print("Creating Warp wheel for " + wheel_platform.fancy_name) diff --git a/warp/build_dll.py b/warp/build_dll.py index 2f311158c..09e00d348 100644 --- a/warp/build_dll.py +++ b/warp/build_dll.py @@ -14,7 +14,7 @@ from warp.utils import ScopedTimer -# return a canonical machine architecture string +# returns a canonical machine architecture string # - "x86_64" for x86-64, aka. AMD64, aka. x64 # - "aarch64" for AArch64, aka. ARM64 def machine_architecture() -> str: