337 lines
12 KiB
C++
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
|