/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef TNT_GEOMETRY_TANGENTSPACEMESH_H #define TNT_GEOMETRY_TANGENTSPACEMESH_H #include #include #include #include namespace filament { namespace geometry { struct TangentSpaceMeshInput; struct TangentSpaceMeshOutput; /* WARNING: WORK-IN-PROGRESS, PLEASE DO NOT USE */ /** * This class builds Filament-style TANGENTS buffers given an input mesh. * * This class enables the client to chose between several algorithms. The client can retrieve the * result through the `get` methods on the class. If the chosen algorithm did not remesh the input, * the client is advised to just use the data they provided instead of querying. For example, if * the chosen method is Algorithm::FRISVAD, then the client should not need to call getPositions(). * We will simply copy from the input `positions` in that case. * * If the client calls getPositions() and positions were not provided as input, we will throw * and exception. Similar behavior will apply to UVs. * * This class supersedes the implementation in SurfaceOrientation.h */ class TangentSpaceMesh { public: enum class Algorithm : uint8_t { /** * default * * Tries to select the best possible algorithm given the input. The corresponding algorithms * are detailed in the corresponding enums. *
         *   INPUT                                  ALGORITHM
         *   -----------------------------------------------------------
         *   normals                                FRISVAD
         *   positions + indices                    FLAT_SHADING
         *   normals + uvs + positions + indices    MIKKTSPACE
         * 
*/ DEFAULT = 0, /** * mikktspace * * **Requires**: `normals + uvs + positions + indices`
* **Reference**: * - Mikkelsen, M., 2008. Simulation of wrinkled surfaces revisited. * - https://github.com/mmikk/MikkTSpace * - https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview * * **Note**: Will remesh */ MIKKTSPACE = 1, /** * Lengyel's method * * **Requires**: `normals + uvs + positions + indices`
* **Reference**: Lengyel, E., 2019. Foundations of Game Engine Development: Rendering. Terathon * Software LLC.. (Chapter 7) */ LENGYEL = 2, /** * Hughes-Moller method * * **Requires**: `normals`
* **Reference**: * - Hughes, J.F. and Moller, T., 1999. Building an orthonormal basis from a unit * vector. journal of graphics tools, 4(4), pp.33-35. * - Parker, S.G., Bigler, J., Dietrich, A., Friedrich, H., Hoberock, J., Luebke, D., * McAllister, D., McGuire, M., Morley, K., Robison, A. and Stich, M., 2010. * Optix: a general purpose ray tracing engine. Acm transactions on graphics (tog), * 29(4), pp.1-13. * **Note**: We implement the Optix variant, which is documented in the second reference above. */ HUGHES_MOLLER = 3, /** * Frisvad's method * * **Requires**: `normals`
* **Reference**: * - Frisvad, J.R., 2012. Building an orthonormal basis from a 3D unit vector without * normalization. Journal of Graphics Tools, 16(3), pp.151-159. * - http://people.compute.dtu.dk/jerf/code/hairy/ */ FRISVAD = 4, /** * Flat Shading * * **Requires**: `positions + indices`
* **Note**: Will remesh */ FLAT_SHADING = 5 }; /** * Use this class to provide input to the TangentSpaceMesh computation. **Important**: * Computation of the tangent space is intended to be synchronous (working on the same thread). * Client is expected to keep the input immutable and in a good state for the duration of both * computation *and* query. That is, when querying the result of the tangent spaces, part of the * result might depend on the input data. */ class Builder { public: Builder() noexcept; ~Builder() noexcept; /** * Move constructor */ Builder(Builder&& that) noexcept; /** * Move constructor */ Builder& operator=(Builder&& that) noexcept; Builder(const Builder&) = delete; Builder& operator=(const Builder&) = delete; /** * Client must provide this parameter * * @param vertexCount The input number of vertcies */ Builder& vertexCount(size_t vertexCount) noexcept; /** * @param normals The input normals * @param stride The stride for iterating through `normals` * @return Builder */ Builder& normals(const filament::math::float3* normals, size_t stride = 0) noexcept; /** * @param tangents The input tangents. The `w` component is for use with * Algorithm::SIGN_OF_W. * @param stride The stride for iterating through `tangents` * @return Builder */ Builder& tangents(const filament::math::float4* tangents, size_t stride = 0) noexcept; /** * @param uvs The input uvs * @param stride The stride for iterating through `uvs` * @return Builder */ Builder& uvs(const filament::math::float2* uvs, size_t stride = 0) noexcept; /** * @param positions The input positions * @param stride The stride for iterating through `positions` * @return Builder */ Builder& positions(const filament::math::float3* positions, size_t stride = 0) noexcept; Builder& triangleCount(size_t triangleCount) noexcept; Builder& triangles(const filament::math::uint3* triangles) noexcept; Builder& triangles(const filament::math::ushort3* triangles) noexcept; Builder& algorithm(Algorithm algorithm) noexcept; /** * Computes the tangent space mesh. The resulting mesh object is owned by the callee. The * callee must call TangentSpaceMesh::destroy on the object once they are finished with it. * * The state of the Builder will be reset after each call to build(). The client needs to * populate the builder with parameters again if they choose to re-use it. * * @return A TangentSpaceMesh */ TangentSpaceMesh* build(); private: TangentSpaceMesh* mMesh = nullptr; }; /** * Destory the mesh object * @param mesh A pointer to a TangentSpaceMesh ready to be destroyed */ static void destroy(TangentSpaceMesh* mesh) noexcept; /** * Move constructor */ TangentSpaceMesh(TangentSpaceMesh&& that) noexcept; /** * Move constructor */ TangentSpaceMesh& operator=(TangentSpaceMesh&& that) noexcept; TangentSpaceMesh(const TangentSpaceMesh&) = delete; TangentSpaceMesh& operator=(const TangentSpaceMesh&) = delete; /** * Number of output vertices * * The number of output vertices can be the same as the input if the selected algorithm did not * "remesh" the input. * * @return The number of vertices */ size_t getVertexCount() const noexcept; /** * Get output vertex positions. * Assumes the `out` param is at least of getVertexCount() length (while accounting for * `stride`). The output vertices can be the same as the input if the selected algorithm did * not "remesh" the input. The remeshed vertices are not guarranteed to have correlation in * order with the input mesh. * * @param out Client-allocated array that will be used for copying out positions. * @param stride Stride for iterating through `out` */ void getPositions(filament::math::float3* out, size_t stride = 0) const; /** * Get output UVs. * Assumes the `out` param is at least of getVertexCount() length (while accounting for * `stride`). The output uvs can be the same as the input if the selected algorithm did * not "remesh" the input. The remeshed UVs are not guarranteed to have correlation in order * with the input mesh. * * @param out Client-allocated array that will be used for copying out UVs. * @param stride Stride for iterating through `out` */ void getUVs(filament::math::float2* out, size_t stride = 0) const; /** * Get output tangent space. * Assumes the `out` param is at least of getVertexCount() length (while accounting for * `stride`). * * @param out Client-allocated array that will be used for copying out tangent space in * 32-bit floating points. * @param stride Stride for iterating through `out` */ void getQuats(filament::math::quatf* out, size_t stride = 0) const noexcept; /** * Get output tangent space. * Assumes the `out` param is at least of getVertexCount() length (while accounting for * `stride`). * * @param out Client-allocated array that will be used for copying out tangent space in * 16-bit signed integers. * @param stride Stride for iterating through `out` */ void getQuats(filament::math::short4* out, size_t stride = 0) const noexcept; /** * Get output tangent space. * Assumes the `out` param is at least of getVertexCount() length (while accounting for * `stride`). * * @param out Client-allocated array that will be used for copying out tangent space in * 16-bit floating points. * @param stride Stride for iterating through `out` */ void getQuats(filament::math::quath* out, size_t stride = 0) const noexcept; /** * Get number of output triangles. * The number of output triangles is the same as the number of input triangles. However, when a * "remesh" is carried out the output triangles are not guarranteed to have any correlation with * the input. * * @return The number of vertices */ size_t getTriangleCount() const noexcept; /** * Get output triangles. * This method assumes that the `out` param provided by the client is at least of * getTriangleCount() length. If the client calls getTriangles() and triangles were not * provided as input, we will throw and exception. * * @param out Client's array for the output triangles in unsigned 32-bit indices. */ void getTriangles(filament::math::uint3* out) const; /** * Get output triangles. * This method assumes that the `out` param provided by the client is at least of * getTriangleCount() length. If the client calls getTriangles() and triangles were not * provided as input, we will throw and exception. * * @param out Client's array for the output triangles in unsigned 16-bit indices. */ void getTriangles(filament::math::ushort3* out) const; /** * @return The algorithm used to compute the output mesh. */ Algorithm getAlgorithm() const noexcept; private: ~TangentSpaceMesh() noexcept; TangentSpaceMesh() noexcept; TangentSpaceMeshInput* mInput; TangentSpaceMeshOutput* mOutput; friend class Builder; }; } // namespace geometry } // namespace filament #endif //TNT_GEOMETRY_TANGENTSPACEMESH_H