Files
cup_edit/ios/include/geometry/TangentSpaceMesh.h
2023-03-03 20:54:32 +08:00

337 lines
12 KiB
C++

/*
* 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 <math/quat.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <utils/compiler.h>
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.
* <pre>
* INPUT ALGORITHM
* -----------------------------------------------------------
* normals FRISVAD
* positions + indices FLAT_SHADING
* normals + uvs + positions + indices MIKKTSPACE
* </pre>
*/
DEFAULT = 0,
/**
* mikktspace
*
* **Requires**: `normals + uvs + positions + indices` <br/>
* **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` <br/>
* **Reference**: Lengyel, E., 2019. Foundations of Game Engine Development: Rendering. Terathon
* Software LLC.. (Chapter 7)
*/
LENGYEL = 2,
/**
* Hughes-Moller method
*
* **Requires**: `normals` <br/>
* **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` <br/>
* **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` <br/>
* **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