Skip to content

Commit

Permalink
geometry: Add TangentSpaceMesh class outline (google#6476)
Browse files Browse the repository at this point in the history
 - Defined class with documentation in comments
 - Implemented algorithm selection
 - No actual algorithms written yet

Part of google#6358
  • Loading branch information
poweifeng authored and plepers committed Dec 9, 2023
1 parent d9d5e23 commit 112f820
Show file tree
Hide file tree
Showing 3 changed files with 648 additions and 0 deletions.
2 changes: 2 additions & 0 deletions libs/geometry/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ set(PUBLIC_HDR_DIR include)
# ==================================================================================================
set(PUBLIC_HDRS
include/geometry/SurfaceOrientation.h
include/geometry/TangentSpaceMesh.h
include/geometry/Transcoder.h
)

set(SRCS
src/SurfaceOrientation.cpp
src/TangentSpaceMesh.cpp
src/Transcoder.cpp
)

Expand Down
328 changes: 328 additions & 0 deletions libs/geometry/include/geometry/TangentSpaceMesh.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
/*
* 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 + tangents SIGN_OF_W
* 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**: Möller, T. and Hughes, J.F., 1999. Efficiently building a matrix to rotate one
* vector to another. Journal of graphics tools, 4(4), pp.1-4.
*/
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,

/**
* Sign of W
*
* **Requires**: `normals + tangents` <br/>
* **Note**: The sign of W determines the orientation of the bitangent.
*/
SIGN_OF_W = 6
};

/**
* 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.
* @return A TangentSpaceMesh
*/
TangentSpaceMesh* build();

private:
TangentSpaceMesh* mMesh = nullptr;
};

~TangentSpaceMesh() noexcept;

/**
* Move constructor
*/
TangentSpaceMesh(TangentSpaceMesh&& that) noexcept;

/**
* Move constructor
*/
TangentSpaceMesh& operator=(TangentSpaceMesh&& that) noexcept;

/**
* 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(const TangentSpaceMesh&) = delete;
TangentSpaceMesh& operator=(const TangentSpaceMesh&) = delete;
TangentSpaceMeshInput* mInput;
TangentSpaceMeshOutput* mOutput;

friend class Builder;
};

} // namespace geometry
} // namespace filament

#endif //TNT_GEOMETRY_TANGENTSPACEMESH_H
Loading

0 comments on commit 112f820

Please sign in to comment.