LCOV - code coverage report
Current view: top level - home/lbartoletti/qgis/external/meshOptimizer - meshoptimizer.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 13 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : 
       2                 :            : /**
       3                 :            :  * meshoptimizer - version 0.13
       4                 :            :  *
       5                 :            :  * Copyright (C) 2016-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
       6                 :            :  * Report bugs and download new versions at https://github.com/zeux/meshoptimizer
       7                 :            :  *
       8                 :            :  * This library is distributed under the MIT License. See notice at the end of this file.
       9                 :            :  */
      10                 :            : #pragma once
      11                 :            : 
      12                 :            : #include <assert.h>
      13                 :            : #include <stddef.h>
      14                 :            : 
      15                 :            : /* Version macro; major * 1000 + minor * 10 + patch */
      16                 :            : #define MESHOPTIMIZER_VERSION 130
      17                 :            : 
      18                 :            : /* If no API is defined, assume default */
      19                 :            : #ifndef MESHOPTIMIZER_API
      20                 :            : #define MESHOPTIMIZER_API
      21                 :            : #endif
      22                 :            : 
      23                 :            : /* Experimental APIs have unstable interface and might have implementation that's not fully tested or optimized */
      24                 :            : #define MESHOPTIMIZER_EXPERIMENTAL MESHOPTIMIZER_API
      25                 :            : 
      26                 :            : /* C interface */
      27                 :            : #ifdef __cplusplus
      28                 :            : extern "C" {
      29                 :            : #endif
      30                 :            : 
      31                 :            : /**
      32                 :            :  * Vertex attribute stream, similar to glVertexPointer
      33                 :            :  * Each element takes size bytes, with stride controlling the spacing between successive elements.
      34                 :            :  */
      35                 :            : struct meshopt_Stream
      36                 :            : {
      37                 :            :   const void *data;
      38                 :            :   size_t size;
      39                 :            :   size_t stride;
      40                 :            : };
      41                 :            : 
      42                 :            : /**
      43                 :            :  * Generates a vertex remap table from the vertex buffer and an optional index buffer and returns number of unique vertices
      44                 :            :  * As a result, all vertices that are binary equivalent map to the same (new) location, with no gaps in the resulting sequence.
      45                 :            :  * Resulting remap table maps old vertices to new vertices and can be used in meshopt_remapVertexBuffer/meshopt_remapIndexBuffer.
      46                 :            :  *
      47                 :            :  * destination must contain enough space for the resulting remap table (vertex_count elements)
      48                 :            :  * indices can be NULL if the input is unindexed
      49                 :            :  */
      50                 :            : MESHOPTIMIZER_API size_t meshopt_generateVertexRemap( unsigned int *destination, const unsigned int *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size );
      51                 :            : 
      52                 :            : /**
      53                 :            :  * Generates a vertex remap table from multiple vertex streams and an optional index buffer and returns number of unique vertices
      54                 :            :  * As a result, all vertices that are binary equivalent map to the same (new) location, with no gaps in the resulting sequence.
      55                 :            :  * Resulting remap table maps old vertices to new vertices and can be used in meshopt_remapVertexBuffer/meshopt_remapIndexBuffer.
      56                 :            :  * To remap vertex buffers, you will need to call meshopt_remapVertexBuffer for each vertex stream.
      57                 :            :  *
      58                 :            :  * destination must contain enough space for the resulting remap table (vertex_count elements)
      59                 :            :  * indices can be NULL if the input is unindexed
      60                 :            :  */
      61                 :            : MESHOPTIMIZER_API size_t meshopt_generateVertexRemapMulti( unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count, const struct meshopt_Stream *streams, size_t stream_count );
      62                 :            : 
      63                 :            : /**
      64                 :            :  * Generates vertex buffer from the source vertex buffer and remap table generated by meshopt_generateVertexRemap
      65                 :            :  *
      66                 :            :  * destination must contain enough space for the resulting vertex buffer (unique_vertex_count elements, returned by meshopt_generateVertexRemap)
      67                 :            :  * vertex_count should be the initial vertex count and not the value returned by meshopt_generateVertexRemap
      68                 :            :  */
      69                 :            : MESHOPTIMIZER_API void meshopt_remapVertexBuffer( void *destination, const void *vertices, size_t vertex_count, size_t vertex_size, const unsigned int *remap );
      70                 :            : 
      71                 :            : /**
      72                 :            :  * Generate index buffer from the source index buffer and remap table generated by meshopt_generateVertexRemap
      73                 :            :  *
      74                 :            :  * destination must contain enough space for the resulting index buffer (index_count elements)
      75                 :            :  * indices can be NULL if the input is unindexed
      76                 :            :  */
      77                 :            : MESHOPTIMIZER_API void meshopt_remapIndexBuffer( unsigned int *destination, const unsigned int *indices, size_t index_count, const unsigned int *remap );
      78                 :            : 
      79                 :            : /**
      80                 :            :  * Generate index buffer that can be used for more efficient rendering when only a subset of the vertex attributes is necessary
      81                 :            :  * All vertices that are binary equivalent (wrt first vertex_size bytes) map to the first vertex in the original vertex buffer.
      82                 :            :  * This makes it possible to use the index buffer for Z pre-pass or shadowmap rendering, while using the original index buffer for regular rendering.
      83                 :            :  *
      84                 :            :  * destination must contain enough space for the resulting index buffer (index_count elements)
      85                 :            :  */
      86                 :            : MESHOPTIMIZER_API void meshopt_generateShadowIndexBuffer( unsigned int *destination, const unsigned int *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size, size_t vertex_stride );
      87                 :            : 
      88                 :            : /**
      89                 :            :  * Generate index buffer that can be used for more efficient rendering when only a subset of the vertex attributes is necessary
      90                 :            :  * All vertices that are binary equivalent (wrt specified streams) map to the first vertex in the original vertex buffer.
      91                 :            :  * This makes it possible to use the index buffer for Z pre-pass or shadowmap rendering, while using the original index buffer for regular rendering.
      92                 :            :  *
      93                 :            :  * destination must contain enough space for the resulting index buffer (index_count elements)
      94                 :            :  */
      95                 :            : MESHOPTIMIZER_API void meshopt_generateShadowIndexBufferMulti( unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count, const struct meshopt_Stream *streams, size_t stream_count );
      96                 :            : 
      97                 :            : /**
      98                 :            :  * Vertex transform cache optimizer
      99                 :            :  * Reorders indices to reduce the number of GPU vertex shader invocations
     100                 :            :  * If index buffer contains multiple ranges for multiple draw calls, this functions needs to be called on each range individually.
     101                 :            :  *
     102                 :            :  * destination must contain enough space for the resulting index buffer (index_count elements)
     103                 :            :  */
     104                 :            : MESHOPTIMIZER_API void meshopt_optimizeVertexCache( unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count );
     105                 :            : 
     106                 :            : /**
     107                 :            :  * Vertex transform cache optimizer for FIFO caches
     108                 :            :  * Reorders indices to reduce the number of GPU vertex shader invocations
     109                 :            :  * Generally takes ~3x less time to optimize meshes but produces inferior results compared to meshopt_optimizeVertexCache
     110                 :            :  * If index buffer contains multiple ranges for multiple draw calls, this functions needs to be called on each range individually.
     111                 :            :  *
     112                 :            :  * destination must contain enough space for the resulting index buffer (index_count elements)
     113                 :            :  * cache_size should be less than the actual GPU cache size to avoid cache thrashing
     114                 :            :  */
     115                 :            : MESHOPTIMIZER_API void meshopt_optimizeVertexCacheFifo( unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count, unsigned int cache_size );
     116                 :            : 
     117                 :            : /**
     118                 :            :  * Overdraw optimizer
     119                 :            :  * Reorders indices to reduce the number of GPU vertex shader invocations and the pixel overdraw
     120                 :            :  * If index buffer contains multiple ranges for multiple draw calls, this functions needs to be called on each range individually.
     121                 :            :  *
     122                 :            :  * destination must contain enough space for the resulting index buffer (index_count elements)
     123                 :            :  * indices must contain index data that is the result of meshopt_optimizeVertexCache (*not* the original mesh indices!)
     124                 :            :  * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
     125                 :            :  * threshold indicates how much the overdraw optimizer can degrade vertex cache efficiency (1.05 = up to 5%) to reduce overdraw more efficiently
     126                 :            :  */
     127                 :            : MESHOPTIMIZER_API void meshopt_optimizeOverdraw( unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, float threshold );
     128                 :            : 
     129                 :            : /**
     130                 :            :  * Vertex fetch cache optimizer
     131                 :            :  * Reorders vertices and changes indices to reduce the amount of GPU memory fetches during vertex processing
     132                 :            :  * Returns the number of unique vertices, which is the same as input vertex count unless some vertices are unused
     133                 :            :  * This functions works for a single vertex stream; for multiple vertex streams, use meshopt_optimizeVertexFetchRemap + meshopt_remapVertexBuffer for each stream.
     134                 :            :  *
     135                 :            :  * destination must contain enough space for the resulting vertex buffer (vertex_count elements)
     136                 :            :  * indices is used both as an input and as an output index buffer
     137                 :            :  */
     138                 :            : MESHOPTIMIZER_API size_t meshopt_optimizeVertexFetch( void *destination, unsigned int *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size );
     139                 :            : 
     140                 :            : /**
     141                 :            :  * Vertex fetch cache optimizer
     142                 :            :  * Generates vertex remap to reduce the amount of GPU memory fetches during vertex processing
     143                 :            :  * Returns the number of unique vertices, which is the same as input vertex count unless some vertices are unused
     144                 :            :  * The resulting remap table should be used to reorder vertex/index buffers using meshopt_remapVertexBuffer/meshopt_remapIndexBuffer
     145                 :            :  *
     146                 :            :  * destination must contain enough space for the resulting remap table (vertex_count elements)
     147                 :            :  */
     148                 :            : MESHOPTIMIZER_API size_t meshopt_optimizeVertexFetchRemap( unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count );
     149                 :            : 
     150                 :            : /**
     151                 :            :  * Index buffer encoder
     152                 :            :  * Encodes index data into an array of bytes that is generally much smaller (<1.5 bytes/triangle) and compresses better (<1 bytes/triangle) compared to original.
     153                 :            :  * Returns encoded data size on success, 0 on error; the only error condition is if buffer doesn't have enough space
     154                 :            :  * For maximum efficiency the index buffer being encoded has to be optimized for vertex cache and vertex fetch first.
     155                 :            :  *
     156                 :            :  * buffer must contain enough space for the encoded index buffer (use meshopt_encodeIndexBufferBound to compute worst case size)
     157                 :            :  */
     158                 :            : MESHOPTIMIZER_API size_t meshopt_encodeIndexBuffer( unsigned char *buffer, size_t buffer_size, const unsigned int *indices, size_t index_count );
     159                 :            : MESHOPTIMIZER_API size_t meshopt_encodeIndexBufferBound( size_t index_count, size_t vertex_count );
     160                 :            : 
     161                 :            : /**
     162                 :            :  * Index buffer decoder
     163                 :            :  * Decodes index data from an array of bytes generated by meshopt_encodeIndexBuffer
     164                 :            :  * Returns 0 if decoding was successful, and an error code otherwise
     165                 :            :  * The decoder is safe to use for untrusted input, but it may produce garbage data (e.g. out of range indices).
     166                 :            :  *
     167                 :            :  * destination must contain enough space for the resulting index buffer (index_count elements)
     168                 :            :  */
     169                 :            : MESHOPTIMIZER_API int meshopt_decodeIndexBuffer( void *destination, size_t index_count, size_t index_size, const unsigned char *buffer, size_t buffer_size );
     170                 :            : 
     171                 :            : /**
     172                 :            :  * Vertex buffer encoder
     173                 :            :  * Encodes vertex data into an array of bytes that is generally smaller and compresses better compared to original.
     174                 :            :  * Returns encoded data size on success, 0 on error; the only error condition is if buffer doesn't have enough space
     175                 :            :  * This function works for a single vertex stream; for multiple vertex streams, call meshopt_encodeVertexBuffer for each stream.
     176                 :            :  *
     177                 :            :  * buffer must contain enough space for the encoded vertex buffer (use meshopt_encodeVertexBufferBound to compute worst case size)
     178                 :            :  */
     179                 :            : MESHOPTIMIZER_API size_t meshopt_encodeVertexBuffer( unsigned char *buffer, size_t buffer_size, const void *vertices, size_t vertex_count, size_t vertex_size );
     180                 :            : MESHOPTIMIZER_API size_t meshopt_encodeVertexBufferBound( size_t vertex_count, size_t vertex_size );
     181                 :            : 
     182                 :            : /**
     183                 :            :  * Vertex buffer decoder
     184                 :            :  * Decodes vertex data from an array of bytes generated by meshopt_encodeVertexBuffer
     185                 :            :  * Returns 0 if decoding was successful, and an error code otherwise
     186                 :            :  * The decoder is safe to use for untrusted input, but it may produce garbage data.
     187                 :            :  *
     188                 :            :  * destination must contain enough space for the resulting vertex buffer (vertex_count * vertex_size bytes)
     189                 :            :  */
     190                 :            : MESHOPTIMIZER_API int meshopt_decodeVertexBuffer( void *destination, size_t vertex_count, size_t vertex_size, const unsigned char *buffer, size_t buffer_size );
     191                 :            : 
     192                 :            : /**
     193                 :            :  * Experimental: Mesh simplifier
     194                 :            :  * Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible
     195                 :            :  * The algorithm tries to preserve mesh topology and can stop short of the target goal based on topology constraints or target error.
     196                 :            :  * If not all attributes from the input mesh are required, it's recommended to reindex the mesh using meshopt_generateShadowIndexBuffer prior to simplification.
     197                 :            :  * Returns the number of indices after simplification, with destination containing new index data
     198                 :            :  * The resulting index buffer references vertices from the original vertex buffer.
     199                 :            :  * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended.
     200                 :            :  *
     201                 :            :  * destination must contain enough space for the *source* index buffer (since optimization is iterative, this means index_count elements - *not* target_index_count!)
     202                 :            :  * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
     203                 :            :  */
     204                 :            : MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify( unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error );
     205                 :            : 
     206                 :            : /**
     207                 :            :  * Experimental: Mesh simplifier (sloppy)
     208                 :            :  * Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance
     209                 :            :  * The algorithm doesn't preserve mesh topology but is always able to reach target triangle count.
     210                 :            :  * Returns the number of indices after simplification, with destination containing new index data
     211                 :            :  * The resulting index buffer references vertices from the original vertex buffer.
     212                 :            :  * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended.
     213                 :            :  *
     214                 :            :  * destination must contain enough space for the target index buffer
     215                 :            :  * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
     216                 :            :  */
     217                 :            : MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy( unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count );
     218                 :            : 
     219                 :            : /**
     220                 :            :  * Experimental: Point cloud simplifier
     221                 :            :  * Reduces the number of points in the cloud to reach the given target
     222                 :            :  * Returns the number of points after simplification, with destination containing new index data
     223                 :            :  * The resulting index buffer references vertices from the original vertex buffer.
     224                 :            :  * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended.
     225                 :            :  *
     226                 :            :  * destination must contain enough space for the target index buffer
     227                 :            :  * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
     228                 :            :  */
     229                 :            : MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyPoints( unsigned int *destination, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_vertex_count );
     230                 :            : 
     231                 :            : /**
     232                 :            :  * Mesh stripifier
     233                 :            :  * Converts a previously vertex cache optimized triangle list to triangle strip, stitching strips using restart index or degenerate triangles
     234                 :            :  * Returns the number of indices in the resulting strip, with destination containing new index data
     235                 :            :  * For maximum efficiency the index buffer being converted has to be optimized for vertex cache first.
     236                 :            :  * Using restart indices can result in ~10% smaller index buffers, but on some GPUs restart indices may result in decreased performance.
     237                 :            :  *
     238                 :            :  * destination must contain enough space for the target index buffer, worst case can be computed with meshopt_stripifyBound
     239                 :            :  * restart_index should be 0xffff or 0xffffffff depending on index size, or 0 to use degenerate triangles
     240                 :            :  */
     241                 :            : MESHOPTIMIZER_API size_t meshopt_stripify( unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count, unsigned int restart_index );
     242                 :            : MESHOPTIMIZER_API size_t meshopt_stripifyBound( size_t index_count );
     243                 :            : 
     244                 :            : /**
     245                 :            :  * Mesh unstripifier
     246                 :            :  * Converts a triangle strip to a triangle list
     247                 :            :  * Returns the number of indices in the resulting list, with destination containing new index data
     248                 :            :  *
     249                 :            :  * destination must contain enough space for the target index buffer, worst case can be computed with meshopt_unstripifyBound
     250                 :            :  */
     251                 :            : MESHOPTIMIZER_API size_t meshopt_unstripify( unsigned int *destination, const unsigned int *indices, size_t index_count, unsigned int restart_index );
     252                 :            : MESHOPTIMIZER_API size_t meshopt_unstripifyBound( size_t index_count );
     253                 :            : 
     254                 :            : struct meshopt_VertexCacheStatistics
     255                 :            : {
     256                 :            :   unsigned int vertices_transformed;
     257                 :            :   unsigned int warps_executed;
     258                 :            :   float acmr; /* transformed vertices / triangle count; best case 0.5, worst case 3.0, optimum depends on topology */
     259                 :            :   float atvr; /* transformed vertices / vertex count; best case 1.0, worst case 6.0, optimum is 1.0 (each vertex is transformed once) */
     260                 :            : };
     261                 :            : 
     262                 :            : /**
     263                 :            :  * Vertex transform cache analyzer
     264                 :            :  * Returns cache hit statistics using a simplified FIFO model
     265                 :            :  * Results may not match actual GPU performance
     266                 :            :  */
     267                 :            : MESHOPTIMIZER_API struct meshopt_VertexCacheStatistics meshopt_analyzeVertexCache( const unsigned int *indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int primgroup_size );
     268                 :            : 
     269                 :            : struct meshopt_OverdrawStatistics
     270                 :            : {
     271                 :            :   unsigned int pixels_covered;
     272                 :            :   unsigned int pixels_shaded;
     273                 :            :   float overdraw; /* shaded pixels / covered pixels; best case 1.0 */
     274                 :            : };
     275                 :            : 
     276                 :            : /**
     277                 :            :  * Overdraw analyzer
     278                 :            :  * Returns overdraw statistics using a software rasterizer
     279                 :            :  * Results may not match actual GPU performance
     280                 :            :  *
     281                 :            :  * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
     282                 :            :  */
     283                 :            : MESHOPTIMIZER_API struct meshopt_OverdrawStatistics meshopt_analyzeOverdraw( const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride );
     284                 :            : 
     285                 :            : struct meshopt_VertexFetchStatistics
     286                 :            : {
     287                 :            :   unsigned int bytes_fetched;
     288                 :            :   float overfetch; /* fetched bytes / vertex buffer size; best case 1.0 (each byte is fetched once) */
     289                 :            : };
     290                 :            : 
     291                 :            : /**
     292                 :            :  * Vertex fetch cache analyzer
     293                 :            :  * Returns cache hit statistics using a simplified direct mapped model
     294                 :            :  * Results may not match actual GPU performance
     295                 :            :  */
     296                 :            : MESHOPTIMIZER_API struct meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch( const unsigned int *indices, size_t index_count, size_t vertex_count, size_t vertex_size );
     297                 :            : 
     298                 :            : struct meshopt_Meshlet
     299                 :            : {
     300                 :            :   unsigned int vertices[64];
     301                 :            :   unsigned char indices[126][3];
     302                 :            :   unsigned char triangle_count;
     303                 :            :   unsigned char vertex_count;
     304                 :            : };
     305                 :            : 
     306                 :            : /**
     307                 :            :  * Experimental: Meshlet builder
     308                 :            :  * Splits the mesh into a set of meshlets where each meshlet has a micro index buffer indexing into meshlet vertices that refer to the original vertex buffer
     309                 :            :  * The resulting data can be used to render meshes using NVidia programmable mesh shading pipeline, or in other cluster-based renderers.
     310                 :            :  * For maximum efficiency the index buffer being converted has to be optimized for vertex cache first.
     311                 :            :  *
     312                 :            :  * destination must contain enough space for all meshlets, worst case size can be computed with meshopt_buildMeshletsBound
     313                 :            :  * max_vertices and max_triangles can't exceed limits statically declared in meshopt_Meshlet (max_vertices <= 64, max_triangles <= 126)
     314                 :            :  */
     315                 :            : MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_buildMeshlets( struct meshopt_Meshlet *destination, const unsigned int *indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles );
     316                 :            : MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_buildMeshletsBound( size_t index_count, size_t max_vertices, size_t max_triangles );
     317                 :            : 
     318                 :            : struct meshopt_Bounds
     319                 :            : {
     320                 :            :   /* bounding sphere, useful for frustum and occlusion culling */
     321                 :            :   float center[3];
     322                 :            :   float radius;
     323                 :            : 
     324                 :            :   /* normal cone, useful for backface culling */
     325                 :            :   float cone_apex[3];
     326                 :            :   float cone_axis[3];
     327                 :            :   float cone_cutoff; /* = cos(angle/2) */
     328                 :            : 
     329                 :            :   /* normal cone axis and cutoff, stored in 8-bit SNORM format; decode using x/127.0 */
     330                 :            :   signed char cone_axis_s8[3];
     331                 :            :   signed char cone_cutoff_s8;
     332                 :            : };
     333                 :            : 
     334                 :            : /**
     335                 :            :  * Experimental: Cluster bounds generator
     336                 :            :  * Creates bounding volumes that can be used for frustum, backface and occlusion culling.
     337                 :            :  *
     338                 :            :  * For backface culling with orthographic projection, use the following formula to reject backfacing clusters:
     339                 :            :  *   dot(view, cone_axis) >= cone_cutoff
     340                 :            :  *
     341                 :            :  * For perspective projection, you can the formula that needs cone apex in addition to axis & cutoff:
     342                 :            :  *   dot(normalize(cone_apex - camera_position), cone_axis) >= cone_cutoff
     343                 :            :  *
     344                 :            :  * Alternatively, you can use the formula that doesn't need cone apex and uses bounding sphere instead:
     345                 :            :  *   dot(normalize(center - camera_position), cone_axis) >= cone_cutoff + radius / length(center - camera_position)
     346                 :            :  * or an equivalent formula that doesn't have a singularity at center = camera_position:
     347                 :            :  *   dot(center - camera_position, cone_axis) >= cone_cutoff * length(center - camera_position) + radius
     348                 :            :  *
     349                 :            :  * The formula that uses the apex is slightly more accurate but needs the apex; if you are already using bounding sphere
     350                 :            :  * to do frustum/occlusion culling, the formula that doesn't use the apex may be preferable.
     351                 :            :  *
     352                 :            :  * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
     353                 :            :  * index_count should be less than or equal to 256*3 (the function assumes clusters of limited size)
     354                 :            :  */
     355                 :            : MESHOPTIMIZER_EXPERIMENTAL struct meshopt_Bounds meshopt_computeClusterBounds( const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride );
     356                 :            : MESHOPTIMIZER_EXPERIMENTAL struct meshopt_Bounds meshopt_computeMeshletBounds( const struct meshopt_Meshlet *meshlet, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride );
     357                 :            : 
     358                 :            : /**
     359                 :            :  * Experimental: Spatial sorter
     360                 :            :  * Generates a remap table that can be used to reorder points for spatial locality.
     361                 :            :  * Resulting remap table maps old vertices to new vertices and can be used in meshopt_remapVertexBuffer.
     362                 :            :  *
     363                 :            :  * destination must contain enough space for the resulting remap table (vertex_count elements)
     364                 :            :  */
     365                 :            : MESHOPTIMIZER_EXPERIMENTAL void meshopt_spatialSortRemap( unsigned int *destination, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride );
     366                 :            : 
     367                 :            : /**
     368                 :            :  * Experimental: Spatial sorter
     369                 :            :  * Reorders triangles for spatial locality, and generates a new index buffer. The resulting index buffer can be used with other functions like optimizeVertexCache.
     370                 :            :  *
     371                 :            :  * destination must contain enough space for the resulting index buffer (index_count elements)
     372                 :            :  * indices must contain index data that is the result of meshopt_optimizeVertexCache (*not* the original mesh indices!)
     373                 :            :  * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
     374                 :            :  */
     375                 :            : MESHOPTIMIZER_EXPERIMENTAL void meshopt_spatialSortTriangles( unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride );
     376                 :            : 
     377                 :            : /**
     378                 :            :  * Set allocation callbacks
     379                 :            :  * These callbacks will be used instead of the default operator new/operator delete for all temporary allocations in the library.
     380                 :            :  * Note that all algorithms only allocate memory for temporary use.
     381                 :            :  * allocate/deallocate are always called in a stack-like order - last pointer to be allocated is deallocated first.
     382                 :            :  */
     383                 :            : MESHOPTIMIZER_API void meshopt_setAllocator( void *( *allocate )( size_t ), void ( *deallocate )( void * ) );
     384                 :            : 
     385                 :            : #ifdef __cplusplus
     386                 :            : } /* extern "C" */
     387                 :            : #endif
     388                 :            : 
     389                 :            : /* Quantization into commonly supported data formats */
     390                 :            : #ifdef __cplusplus
     391                 :            : 
     392                 :            : /**
     393                 :            :  * Quantize a float in [0..1] range into an N-bit fixed point unorm value
     394                 :            :  * Assumes reconstruction function (q / (2^N-1)), which is the case for fixed-function normalized fixed point conversion
     395                 :            :  * Maximum reconstruction error: 1/2^(N+1)
     396                 :            :  */
     397                 :            : inline int meshopt_quantizeUnorm( float v, int N );
     398                 :            : 
     399                 :            : /**
     400                 :            :  * Quantize a float in [-1..1] range into an N-bit fixed point snorm value
     401                 :            :  * Assumes reconstruction function (q / (2^(N-1)-1)), which is the case for fixed-function normalized fixed point conversion (except early OpenGL versions)
     402                 :            :  * Maximum reconstruction error: 1/2^N
     403                 :            :  */
     404                 :            : inline int meshopt_quantizeSnorm( float v, int N );
     405                 :            : 
     406                 :            : /**
     407                 :            :  * Quantize a float into half-precision floating point value
     408                 :            :  * Generates +-inf for overflow, preserves NaN, flushes denormals to zero, rounds to nearest
     409                 :            :  * Representable magnitude range: [6e-5; 65504]
     410                 :            :  * Maximum relative reconstruction error: 5e-4
     411                 :            :  */
     412                 :            : inline unsigned short meshopt_quantizeHalf( float v );
     413                 :            : 
     414                 :            : /**
     415                 :            :  * Quantize a float into a floating point value with a limited number of significant mantissa bits
     416                 :            :  * Generates +-inf for overflow, preserves NaN, flushes denormals to zero, rounds to nearest
     417                 :            :  * Assumes N is in a valid mantissa precision range, which is 1..23
     418                 :            :  */
     419                 :            : inline float meshopt_quantizeFloat( float v, int N );
     420                 :            : #endif
     421                 :            : 
     422                 :            : /**
     423                 :            :  * C++ template interface
     424                 :            :  *
     425                 :            :  * These functions mirror the C interface the library provides, providing template-based overloads so that
     426                 :            :  * the caller can use an arbitrary type for the index data, both for input and output.
     427                 :            :  * When the supplied type is the same size as that of unsigned int, the wrappers are zero-cost; when it's not,
     428                 :            :  * the wrappers end up allocating memory and copying index data to convert from one type to another.
     429                 :            :  */
     430                 :            : #if defined(__cplusplus) && !defined(MESHOPTIMIZER_NO_WRAPPERS)
     431                 :            : template <typename T>
     432                 :            : inline size_t meshopt_generateVertexRemap( unsigned int *destination, const T *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size );
     433                 :            : template <typename T>
     434                 :            : inline size_t meshopt_generateVertexRemapMulti( unsigned int *destination, const T *indices, size_t index_count, size_t vertex_count, const meshopt_Stream *streams, size_t stream_count );
     435                 :            : template <typename T>
     436                 :            : inline void meshopt_remapIndexBuffer( T *destination, const T *indices, size_t index_count, const unsigned int *remap );
     437                 :            : template <typename T>
     438                 :            : inline void meshopt_generateShadowIndexBuffer( T *destination, const T *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size, size_t vertex_stride );
     439                 :            : template <typename T>
     440                 :            : inline void meshopt_generateShadowIndexBufferMulti( T *destination, const T *indices, size_t index_count, size_t vertex_count, const meshopt_Stream *streams, size_t stream_count );
     441                 :            : template <typename T>
     442                 :            : inline void meshopt_optimizeVertexCache( T *destination, const T *indices, size_t index_count, size_t vertex_count );
     443                 :            : template <typename T>
     444                 :            : inline void meshopt_optimizeVertexCacheFifo( T *destination, const T *indices, size_t index_count, size_t vertex_count, unsigned int cache_size );
     445                 :            : template <typename T>
     446                 :            : inline void meshopt_optimizeOverdraw( T *destination, const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, float threshold );
     447                 :            : template <typename T>
     448                 :            : inline size_t meshopt_optimizeVertexFetchRemap( unsigned int *destination, const T *indices, size_t index_count, size_t vertex_count );
     449                 :            : template <typename T>
     450                 :            : inline size_t meshopt_optimizeVertexFetch( void *destination, T *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size );
     451                 :            : template <typename T>
     452                 :            : inline size_t meshopt_encodeIndexBuffer( unsigned char *buffer, size_t buffer_size, const T *indices, size_t index_count );
     453                 :            : template <typename T>
     454                 :            : inline int meshopt_decodeIndexBuffer( T *destination, size_t index_count, const unsigned char *buffer, size_t buffer_size );
     455                 :            : template <typename T>
     456                 :            : inline size_t meshopt_simplify( T *destination, const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error );
     457                 :            : template <typename T>
     458                 :            : inline size_t meshopt_simplifySloppy( T *destination, const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count );
     459                 :            : template <typename T>
     460                 :            : inline size_t meshopt_stripify( T *destination, const T *indices, size_t index_count, size_t vertex_count, T restart_index );
     461                 :            : template <typename T>
     462                 :            : inline size_t meshopt_unstripify( T *destination, const T *indices, size_t index_count, T restart_index );
     463                 :            : template <typename T>
     464                 :            : inline meshopt_VertexCacheStatistics meshopt_analyzeVertexCache( const T *indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int buffer_size );
     465                 :            : template <typename T>
     466                 :            : inline meshopt_OverdrawStatistics meshopt_analyzeOverdraw( const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride );
     467                 :            : template <typename T>
     468                 :            : inline meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch( const T *indices, size_t index_count, size_t vertex_count, size_t vertex_size );
     469                 :            : template <typename T>
     470                 :            : inline size_t meshopt_buildMeshlets( meshopt_Meshlet *destination, const T *indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles );
     471                 :            : template <typename T>
     472                 :            : inline meshopt_Bounds meshopt_computeClusterBounds( const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride );
     473                 :            : template <typename T>
     474                 :            : inline void meshopt_spatialSortTriangles( T *destination, const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride );
     475                 :            : #endif
     476                 :            : 
     477                 :            : /* Inline implementation */
     478                 :            : #ifdef __cplusplus
     479                 :            : inline int meshopt_quantizeUnorm( float v, int N )
     480                 :            : {
     481                 :            :   const float scale = float( ( 1 << N ) - 1 );
     482                 :            : 
     483                 :            :   v = ( v >= 0 ) ? v : 0;
     484                 :            :   v = ( v <= 1 ) ? v : 1;
     485                 :            : 
     486                 :            :   return int( v * scale + 0.5f );
     487                 :            : }
     488                 :            : 
     489                 :            : inline int meshopt_quantizeSnorm( float v, int N )
     490                 :            : {
     491                 :            :   const float scale = float( ( 1 << ( N - 1 ) ) - 1 );
     492                 :            : 
     493                 :            :   float round = ( v >= 0 ? 0.5f : -0.5f );
     494                 :            : 
     495                 :            :   v = ( v >= -1 ) ? v : -1;
     496                 :            :   v = ( v <= +1 ) ? v : +1;
     497                 :            : 
     498                 :            :   return int( v * scale + round );
     499                 :            : }
     500                 :            : 
     501                 :            : inline unsigned short meshopt_quantizeHalf( float v )
     502                 :            : {
     503                 :            :   union { float f; unsigned int ui; } u = {v};
     504                 :            :   unsigned int ui = u.ui;
     505                 :            : 
     506                 :            :   int s = ( ui >> 16 ) & 0x8000;
     507                 :            :   int em = ui & 0x7fffffff;
     508                 :            : 
     509                 :            :   /* bias exponent and round to nearest; 112 is relative exponent bias (127-15) */
     510                 :            :   int h = ( em - ( 112 << 23 ) + ( 1 << 12 ) ) >> 13;
     511                 :            : 
     512                 :            :   /* underflow: flush to zero; 113 encodes exponent -14 */
     513                 :            :   h = ( em < ( 113 << 23 ) ) ? 0 : h;
     514                 :            : 
     515                 :            :   /* overflow: infinity; 143 encodes exponent 16 */
     516                 :            :   h = ( em >= ( 143 << 23 ) ) ? 0x7c00 : h;
     517                 :            : 
     518                 :            :   /* NaN; note that we convert all types of NaN to qNaN */
     519                 :            :   h = ( em > ( 255 << 23 ) ) ? 0x7e00 : h;
     520                 :            : 
     521                 :            :   return ( unsigned short )( s | h );
     522                 :            : }
     523                 :            : 
     524                 :            : inline float meshopt_quantizeFloat( float v, int N )
     525                 :            : {
     526                 :            :   union { float f; unsigned int ui; } u = {v};
     527                 :            :   unsigned int ui = u.ui;
     528                 :            : 
     529                 :            :   const int mask = ( 1 << ( 23 - N ) ) - 1;
     530                 :            :   const int round = ( 1 << ( 23 - N ) ) >> 1;
     531                 :            : 
     532                 :            :   int e = ui & 0x7f800000;
     533                 :            :   unsigned int rui = ( ui + round ) & ~mask;
     534                 :            : 
     535                 :            :   /* round all numbers except inf/nan; this is important to make sure nan doesn't overflow into -0 */
     536                 :            :   ui = e == 0x7f800000 ? ui : rui;
     537                 :            : 
     538                 :            :   /* flush denormals to zero */
     539                 :            :   ui = e == 0 ? 0 : ui;
     540                 :            : 
     541                 :            :   u.ui = ui;
     542                 :            :   return u.f;
     543                 :            : }
     544                 :            : #endif
     545                 :            : 
     546                 :            : /* Internal implementation helpers */
     547                 :            : #ifdef __cplusplus
     548                 :            : class meshopt_Allocator
     549                 :            : {
     550                 :            :   public:
     551                 :            :     template <typename T>
     552                 :            :     struct StorageT
     553                 :            :     {
     554                 :            :       static void *( *allocate )( size_t );
     555                 :            :       static void ( *deallocate )( void * );
     556                 :            :     };
     557                 :            : 
     558                 :            :     typedef StorageT<void> Storage;
     559                 :            : 
     560                 :          0 :     meshopt_Allocator()
     561                 :          0 :       : blocks()
     562                 :          0 :       , count( 0 )
     563                 :            :     {
     564                 :          0 :     }
     565                 :            : 
     566                 :          0 :     ~meshopt_Allocator()
     567                 :            :     {
     568                 :          0 :       for ( size_t i = count; i > 0; --i )
     569                 :          0 :         Storage::deallocate( blocks[i - 1] );
     570                 :          0 :     }
     571                 :            : 
     572                 :          0 :     template <typename T> T *allocate( size_t size )
     573                 :            :     {
     574                 :          0 :       assert( count < sizeof( blocks ) / sizeof( blocks[0] ) );
     575                 :          0 :       T *result = static_cast<T *>( Storage::allocate( size > size_t( -1 ) / sizeof( T ) ? size_t( -1 ) : size * sizeof( T ) ) );
     576                 :          0 :       blocks[count++] = result;
     577                 :          0 :       return result;
     578                 :            :     }
     579                 :            : 
     580                 :            :   private:
     581                 :            :     void *blocks[16];
     582                 :            :     size_t count;
     583                 :            : };
     584                 :            : 
     585                 :            : // This makes sure that allocate/deallocate are lazily generated in translation units that need them and are deduplicated by the linker
     586                 :            : template <typename T> void *( *meshopt_Allocator::StorageT<T>::allocate )( size_t ) = operator new;
     587                 :            : template <typename T> void ( *meshopt_Allocator::StorageT<T>::deallocate )( void * ) = operator delete;
     588                 :            : #endif
     589                 :            : 
     590                 :            : /* Inline implementation for C++ templated wrappers */
     591                 :            : #if defined(__cplusplus) && !defined(MESHOPTIMIZER_NO_WRAPPERS)
     592                 :            : template <typename T, bool ZeroCopy = sizeof( T ) == sizeof( unsigned int )>
     593                 :            : struct meshopt_IndexAdapter;
     594                 :            : 
     595                 :            : template <typename T>
     596                 :            : struct meshopt_IndexAdapter<T, false>
     597                 :            : {
     598                 :            :   T *result;
     599                 :            :   unsigned int *data;
     600                 :            :   size_t count;
     601                 :            : 
     602                 :            :   meshopt_IndexAdapter( T *result_, const T *input, size_t count_ )
     603                 :            :     : result( result_ )
     604                 :            :     , data( 0 )
     605                 :            :     , count( count_ )
     606                 :            :   {
     607                 :            :     size_t size = count > size_t( -1 ) / sizeof( unsigned int ) ? size_t( -1 ) : count * sizeof( unsigned int );
     608                 :            : 
     609                 :            :     data = static_cast<unsigned int *>( meshopt_Allocator::Storage::allocate( size ) );
     610                 :            : 
     611                 :            :     if ( input )
     612                 :            :     {
     613                 :            :       for ( size_t i = 0; i < count; ++i )
     614                 :            :         data[i] = input[i];
     615                 :            :     }
     616                 :            :   }
     617                 :            : 
     618                 :            :   ~meshopt_IndexAdapter()
     619                 :            :   {
     620                 :            :     if ( result )
     621                 :            :     {
     622                 :            :       for ( size_t i = 0; i < count; ++i )
     623                 :            :         result[i] = T( data[i] );
     624                 :            :     }
     625                 :            : 
     626                 :            :     meshopt_Allocator::Storage::deallocate( data );
     627                 :            :   }
     628                 :            : };
     629                 :            : 
     630                 :            : template <typename T>
     631                 :            : struct meshopt_IndexAdapter<T, true>
     632                 :            : {
     633                 :            :   unsigned int *data;
     634                 :            : 
     635                 :            :   meshopt_IndexAdapter( T *result, const T *input, size_t )
     636                 :            :     : data( reinterpret_cast<unsigned int *>( result ? result : const_cast<T *>( input ) ) )
     637                 :            :   {
     638                 :            :   }
     639                 :            : };
     640                 :            : 
     641                 :            : template <typename T>
     642                 :            : inline size_t meshopt_generateVertexRemap( unsigned int *destination, const T *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size )
     643                 :            : {
     644                 :            :   meshopt_IndexAdapter<T> in( 0, indices, indices ? index_count : 0 );
     645                 :            : 
     646                 :            :   return meshopt_generateVertexRemap( destination, indices ? in.data : 0, index_count, vertices, vertex_count, vertex_size );
     647                 :            : }
     648                 :            : 
     649                 :            : template <typename T>
     650                 :            : inline size_t meshopt_generateVertexRemapMulti( unsigned int *destination, const T *indices, size_t index_count, size_t vertex_count, const meshopt_Stream *streams, size_t stream_count )
     651                 :            : {
     652                 :            :   meshopt_IndexAdapter<T> in( 0, indices, indices ? index_count : 0 );
     653                 :            : 
     654                 :            :   return meshopt_generateVertexRemapMulti( destination, indices ? in.data : 0, index_count, vertex_count, streams, stream_count );
     655                 :            : }
     656                 :            : 
     657                 :            : template <typename T>
     658                 :            : inline void meshopt_remapIndexBuffer( T *destination, const T *indices, size_t index_count, const unsigned int *remap )
     659                 :            : {
     660                 :            :   meshopt_IndexAdapter<T> in( 0, indices, indices ? index_count : 0 );
     661                 :            :   meshopt_IndexAdapter<T> out( destination, 0, index_count );
     662                 :            : 
     663                 :            :   meshopt_remapIndexBuffer( out.data, indices ? in.data : 0, index_count, remap );
     664                 :            : }
     665                 :            : 
     666                 :            : template <typename T>
     667                 :            : inline void meshopt_generateShadowIndexBuffer( T *destination, const T *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size, size_t vertex_stride )
     668                 :            : {
     669                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     670                 :            :   meshopt_IndexAdapter<T> out( destination, 0, index_count );
     671                 :            : 
     672                 :            :   meshopt_generateShadowIndexBuffer( out.data, in.data, index_count, vertices, vertex_count, vertex_size, vertex_stride );
     673                 :            : }
     674                 :            : 
     675                 :            : template <typename T>
     676                 :            : inline void meshopt_generateShadowIndexBufferMulti( T *destination, const T *indices, size_t index_count, size_t vertex_count, const meshopt_Stream *streams, size_t stream_count )
     677                 :            : {
     678                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     679                 :            :   meshopt_IndexAdapter<T> out( destination, 0, index_count );
     680                 :            : 
     681                 :            :   meshopt_generateShadowIndexBufferMulti( out.data, in.data, index_count, vertex_count, streams, stream_count );
     682                 :            : }
     683                 :            : 
     684                 :            : template <typename T>
     685                 :            : inline void meshopt_optimizeVertexCache( T *destination, const T *indices, size_t index_count, size_t vertex_count )
     686                 :            : {
     687                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     688                 :            :   meshopt_IndexAdapter<T> out( destination, 0, index_count );
     689                 :            : 
     690                 :            :   meshopt_optimizeVertexCache( out.data, in.data, index_count, vertex_count );
     691                 :            : }
     692                 :            : 
     693                 :            : template <typename T>
     694                 :            : inline void meshopt_optimizeVertexCacheFifo( T *destination, const T *indices, size_t index_count, size_t vertex_count, unsigned int cache_size )
     695                 :            : {
     696                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     697                 :            :   meshopt_IndexAdapter<T> out( destination, 0, index_count );
     698                 :            : 
     699                 :            :   meshopt_optimizeVertexCacheFifo( out.data, in.data, index_count, vertex_count, cache_size );
     700                 :            : }
     701                 :            : 
     702                 :            : template <typename T>
     703                 :            : inline void meshopt_optimizeOverdraw( T *destination, const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, float threshold )
     704                 :            : {
     705                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     706                 :            :   meshopt_IndexAdapter<T> out( destination, 0, index_count );
     707                 :            : 
     708                 :            :   meshopt_optimizeOverdraw( out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, threshold );
     709                 :            : }
     710                 :            : 
     711                 :            : template <typename T>
     712                 :            : inline size_t meshopt_optimizeVertexFetchRemap( unsigned int *destination, const T *indices, size_t index_count, size_t vertex_count )
     713                 :            : {
     714                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     715                 :            : 
     716                 :            :   return meshopt_optimizeVertexFetchRemap( destination, in.data, index_count, vertex_count );
     717                 :            : }
     718                 :            : 
     719                 :            : template <typename T>
     720                 :            : inline size_t meshopt_optimizeVertexFetch( void *destination, T *indices, size_t index_count, const void *vertices, size_t vertex_count, size_t vertex_size )
     721                 :            : {
     722                 :            :   meshopt_IndexAdapter<T> inout( indices, indices, index_count );
     723                 :            : 
     724                 :            :   return meshopt_optimizeVertexFetch( destination, inout.data, index_count, vertices, vertex_count, vertex_size );
     725                 :            : }
     726                 :            : 
     727                 :            : template <typename T>
     728                 :            : inline size_t meshopt_encodeIndexBuffer( unsigned char *buffer, size_t buffer_size, const T *indices, size_t index_count )
     729                 :            : {
     730                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     731                 :            : 
     732                 :            :   return meshopt_encodeIndexBuffer( buffer, buffer_size, in.data, index_count );
     733                 :            : }
     734                 :            : 
     735                 :            : template <typename T>
     736                 :            : inline int meshopt_decodeIndexBuffer( T *destination, size_t index_count, const unsigned char *buffer, size_t buffer_size )
     737                 :            : {
     738                 :            :   char index_size_valid[sizeof( T ) == 2 || sizeof( T ) == 4 ? 1 : -1];
     739                 :            :   ( void )index_size_valid;
     740                 :            : 
     741                 :            :   return meshopt_decodeIndexBuffer( destination, index_count, sizeof( T ), buffer, buffer_size );
     742                 :            : }
     743                 :            : 
     744                 :            : template <typename T>
     745                 :            : inline size_t meshopt_simplify( T *destination, const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error )
     746                 :            : {
     747                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     748                 :            :   meshopt_IndexAdapter<T> out( destination, 0, index_count );
     749                 :            : 
     750                 :            :   return meshopt_simplify( out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error );
     751                 :            : }
     752                 :            : 
     753                 :            : template <typename T>
     754                 :            : inline size_t meshopt_simplifySloppy( T *destination, const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count )
     755                 :            : {
     756                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     757                 :            :   meshopt_IndexAdapter<T> out( destination, 0, target_index_count );
     758                 :            : 
     759                 :            :   return meshopt_simplifySloppy( out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count );
     760                 :            : }
     761                 :            : 
     762                 :            : template <typename T>
     763                 :            : inline size_t meshopt_stripify( T *destination, const T *indices, size_t index_count, size_t vertex_count, T restart_index )
     764                 :            : {
     765                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     766                 :            :   meshopt_IndexAdapter<T> out( destination, 0, ( index_count / 3 ) * 5 );
     767                 :            : 
     768                 :            :   return meshopt_stripify( out.data, in.data, index_count, vertex_count, unsigned( restart_index ) );
     769                 :            : }
     770                 :            : 
     771                 :            : template <typename T>
     772                 :            : inline size_t meshopt_unstripify( T *destination, const T *indices, size_t index_count, T restart_index )
     773                 :            : {
     774                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     775                 :            :   meshopt_IndexAdapter<T> out( destination, 0, ( index_count - 2 ) * 3 );
     776                 :            : 
     777                 :            :   return meshopt_unstripify( out.data, in.data, index_count, unsigned( restart_index ) );
     778                 :            : }
     779                 :            : 
     780                 :            : template <typename T>
     781                 :            : inline meshopt_VertexCacheStatistics meshopt_analyzeVertexCache( const T *indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int buffer_size )
     782                 :            : {
     783                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     784                 :            : 
     785                 :            :   return meshopt_analyzeVertexCache( in.data, index_count, vertex_count, cache_size, warp_size, buffer_size );
     786                 :            : }
     787                 :            : 
     788                 :            : template <typename T>
     789                 :            : inline meshopt_OverdrawStatistics meshopt_analyzeOverdraw( const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride )
     790                 :            : {
     791                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     792                 :            : 
     793                 :            :   return meshopt_analyzeOverdraw( in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride );
     794                 :            : }
     795                 :            : 
     796                 :            : template <typename T>
     797                 :            : inline meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch( const T *indices, size_t index_count, size_t vertex_count, size_t vertex_size )
     798                 :            : {
     799                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     800                 :            : 
     801                 :            :   return meshopt_analyzeVertexFetch( in.data, index_count, vertex_count, vertex_size );
     802                 :            : }
     803                 :            : 
     804                 :            : template <typename T>
     805                 :            : inline size_t meshopt_buildMeshlets( meshopt_Meshlet *destination, const T *indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles )
     806                 :            : {
     807                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     808                 :            : 
     809                 :            :   return meshopt_buildMeshlets( destination, in.data, index_count, vertex_count, max_vertices, max_triangles );
     810                 :            : }
     811                 :            : 
     812                 :            : template <typename T>
     813                 :            : inline meshopt_Bounds meshopt_computeClusterBounds( const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride )
     814                 :            : {
     815                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     816                 :            : 
     817                 :            :   return meshopt_computeClusterBounds( in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride );
     818                 :            : }
     819                 :            : 
     820                 :            : template <typename T>
     821                 :            : inline void meshopt_spatialSortTriangles( T *destination, const T *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride )
     822                 :            : {
     823                 :            :   meshopt_IndexAdapter<T> in( 0, indices, index_count );
     824                 :            :   meshopt_IndexAdapter<T> out( destination, 0, index_count );
     825                 :            : 
     826                 :            :   meshopt_spatialSortTriangles( out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride );
     827                 :            : }
     828                 :            : #endif
     829                 :            : 
     830                 :            : /**
     831                 :            :  * Copyright (c) 2016-2019 Arseny Kapoulkine
     832                 :            :  *
     833                 :            :  * Permission is hereby granted, free of charge, to any person
     834                 :            :  * obtaining a copy of this software and associated documentation
     835                 :            :  * files (the "Software"), to deal in the Software without
     836                 :            :  * restriction, including without limitation the rights to use,
     837                 :            :  * copy, modify, merge, publish, distribute, sublicense, and/or sell
     838                 :            :  * copies of the Software, and to permit persons to whom the
     839                 :            :  * Software is furnished to do so, subject to the following
     840                 :            :  * conditions:
     841                 :            :  *
     842                 :            :  * The above copyright notice and this permission notice shall be
     843                 :            :  * included in all copies or substantial portions of the Software.
     844                 :            :  *
     845                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     846                 :            :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     847                 :            :  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     848                 :            :  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     849                 :            :  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     850                 :            :  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     851                 :            :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     852                 :            :  * OTHER DEALINGS IN THE SOFTWARE.
     853                 :            :  */

Generated by: LCOV version 1.14