| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_UI_LIB_ESCHER_MESH_TESSELLATION_H_ |
| #define SRC_UI_LIB_ESCHER_MESH_TESSELLATION_H_ |
| |
| #include <vector> |
| |
| #include "src/ui/lib/escher/forward_declarations.h" |
| #include "src/ui/lib/escher/geometry/types.h" |
| #include "src/ui/lib/escher/mesh/indexed_triangle_mesh.h" |
| |
| namespace escher { |
| |
| // Tessellate a circle. The coarsest circle (i.e. subdivisions == 0) is a |
| // square; increasing the number of subdivisions doubles the number of vertices. |
| MeshPtr NewCircleMesh(MeshBuilderFactory* factory, BatchGpuUploader* gpu_uploader, |
| const MeshSpec& spec, int subdivisions, vec2 center, float radius, |
| float offset_magnitude = 0.f); |
| |
| // Tessellate a circle and return it as an IndexedTriangleMesh suitable for |
| // further processing on the CPU. |
| IndexedTriangleMesh2d<vec2> NewCircleIndexedTriangleMesh(const MeshSpec& spec, |
| uint32_t subdivisions, vec2 center, |
| float radius); |
| |
| // Tessellate a rectangle with multiple vertices along the top and bottom edges. |
| // Increasing subdivisions by 1 doubles the number of vertices. If the spec |
| // has kPositionOffset, the top offset points up and the bottom points down. |
| MeshPtr NewRectangleMesh(MeshBuilderFactory* factory, BatchGpuUploader* gpu_uploader, |
| const MeshSpec& spec, int subdivisions, vec2 extent, |
| vec2 top_left = vec2(0.f, 0.f), float top_offset_magnitude = 0.f, |
| float bottom_offset_magnitude = 0.f); |
| |
| // Tessellate a ring whose area is bounded by an inner and an outer circle. |
| // Increasing subdivisions by 1 doubles the number of vertices. If the spec |
| // has kPositionOffset, the outer offset points outward (away from the center of |
| // the ring) and the inner offset points inward (toward the center of the ring). |
| MeshPtr NewRingMesh(MeshBuilderFactory* factory, BatchGpuUploader* gpu_uploader, |
| const MeshSpec& spec, int subdivisions, vec2 center, float outer_radius, |
| float inner_radius, float outer_offset_magnitude = 0.f, |
| float inner_offset_magnitude = 0.f); |
| |
| // Tessellate a full-screen mesh. The returned mesh has only position and UV |
| // coordinates. |
| MeshPtr NewFullScreenMesh(MeshBuilderFactory* factory, BatchGpuUploader* gpu_uploader); |
| |
| // Tessellate a sphere with the specified center and radius. If subdivisions == |
| // 0, the result is a regular octahedron. Increasing the number of subdivisions |
| // by 1 subdivides each triangle into 3 by adding a vertex at the triangle |
| // midpoint, and moving it outward to match the desired radius. |
| // |
| // If UV-coordinates are to be generated, the surface is parameterized as |
| // follows. Looking at the un-subdivided octahedron from the right (i.e. in the |
| // direction of the negative X-axis), the 4 visible faces are mapped to the |
| // rotated square with corners (0, .5), (.5, 0), (1, .5), (.5, 1), and the |
| // vertex at (radius, 0, 0) is mapped to the center of the texture: (.5, .5). |
| // The unmapped 4 corners of the texture are "folded over" to map to the 4 |
| // hidden faces of the octahedron. During subdivision, the UV coordinates are |
| // linearly interpolated for each new vertex. |
| // |
| // TODO(fxbug.dev/7329): the approach described above is wrong: the newly-inserted |
| // vertices are correct positions, but the all of the initial octahedron edges |
| // are left untouched. The proper approach is to double the number of vertices |
| // at each subdivision level (and quadruple the triangle count) by splitting |
| // each edge at the mid-point. However, doing this with an indexed mesh (i.e. |
| // without inserting two vertices for every edge, one at each half-edge) is |
| // non-trivial, especially without a traversal-friendly mesh representation such |
| // as Rossignac's "corner table". |
| MeshPtr NewSphereMesh(MeshBuilderFactory* factory, BatchGpuUploader* gpu_uploader, |
| const MeshSpec& spec, int subdivisions, vec3 center, float radius); |
| |
| // This returns a cube shaped mesh, with it's min-bounds point at the origin. |
| // To get boxes of different dimensions, this mesh can just be scaled in a |
| // non-uniform manner in the (x,y,z) directions with its transformation matrix. |
| IndexedTriangleMesh3d<vec2> NewCubeIndexedTriangleMesh(const MeshSpec& spec); |
| |
| // Tessellate a basic rectangle on the XY plane with no depth. The origin refers |
| // to the top-left hand corner of rectangle, and the extent is the width and height. |
| // UV coordinates are also provided directly by the caller. |
| IndexedTriangleMesh2d<vec2> NewFlatRectangleMesh(vec2 origin, vec2 extent, |
| vec2 top_left_uv = vec2(0, 0), |
| vec2 bottom_right_uv = vec2(1, 1)); |
| |
| // The following functions are used for convenience during unit testing. |
| IndexedTriangleMesh2d<vec2> GetStandardTestMesh2d(); |
| IndexedTriangleMesh3d<vec2> GetStandardTestMesh3d(); |
| |
| } // namespace escher |
| |
| #endif // SRC_UI_LIB_ESCHER_MESH_TESSELLATION_H_ |