text: // This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
  #include "meshoptimizer.h"
  
  #include <assert.h>
  #include <string.h>
  
  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)
  {
  	assert(index_count % 3 == 0);
  	assert(cache_size >= 3);
  	assert(warp_size == 0 || warp_size >= 3);
  
  	meshopt_VertexCacheStatistics result = {};
  
  	unsigned int warp_offset = 0;
  	unsigned int primgroup_offset = 0;
  
  	meshopt_Buffer<unsigned int> cache_timestamps(vertex_count);
  	memset(cache_timestamps.data, 0, vertex_count * sizeof(unsigned int));
  
  	unsigned int timestamp = cache_size + 1;
  
  	for (size_t i = 0; i < index_count; i += 3)
  	{
  		unsigned int a = indices[i + 0], b = indices[i + 1], c = indices[i + 2];
  		assert(a < vertex_count && b < vertex_count && c < vertex_count);
  
  		bool ac = (timestamp - cache_timestamps[a]) > cache_size;
  		bool bc = (timestamp - cache_timestamps[b]) > cache_size;
  		bool cc = (timestamp - cache_timestamps[c]) > cache_size;
  
  		// flush cache if triangle doesn't fit into warp or into the primitive buffer
  		if ((primgroup_size && primgroup_offset == primgroup_size) || (warp_size && warp_offset + ac + bc + cc > warp_size))
  		{
  			result.warps_executed += warp_offset > 0;
  
  			warp_offset = 0;
  			primgroup_offset = 0;
  
  			// reset cache
  			timestamp += cache_size + 1;
  		}
  
  		// update cache and add vertices to warp
  		for (int j = 0; j < 3; ++j)
  		{
  			unsigned int index = indices[i + j];
  
  			if (timestamp - cache_timestamps[index] > cache_size)
  			{
  				cache_timestamps[index] = timestamp++;
  				result.vertices_transformed++;
  				warp_offset++;
  			}
  		}
  
  		primgroup_offset++;
  	}
  
  	result.warps_executed += warp_offset > 0;
  
  	result.acmr = index_count == 0 ? 0 : float(result.vertices_transformed) / float(index_count / 3);
  	result.atvr = vertex_count == 0 ? 0 : float(result.vertices_transformed) / float(vertex_count);
  
  	return result;
  }
  