Browse Source

Added index buffer compression support.

Branimir Karadžić 11 years ago
parent
commit
c6efb167ba

+ 0 - 2
3rdparty/ib-compress/indexbuffercompression.cpp

@@ -524,8 +524,6 @@ void CompressTriangleCodes1( const Ty* triangles,
 				verticesRead += 3;
 				break;
 			}
-
-			default: break;
 			}
 
 			// populate the edge fifo with the 3 most recent edges

+ 6 - 6
3rdparty/ib-compress/readbitstream.h

@@ -71,8 +71,8 @@ private:
 
 inline ReadBitstream::ReadBitstream( const uint8_t* buffer, size_t bufferSize )
 {
-	m_cursor =
-		m_buffer = buffer;
+	m_cursor     =
+	m_buffer     = buffer;
 	m_bufferSize = bufferSize;
 
 	if ( bufferSize >= 8 )
@@ -98,8 +98,8 @@ inline ReadBitstream::ReadBitstream( const uint8_t* buffer, size_t bufferSize )
 
 RBS_INLINE uint32_t ReadBitstream::Read( uint32_t bitCount )
 {
-	uint64_t mask = ( 1 << bitCount ) - 1;
-	uint32_t result = static_cast< uint32_t >( ( m_bitBuffer >> ( 64 - m_bitsLeft ) ) & mask );
+	uint64_t mask   = ( uint64_t( 1 ) << bitCount ) - 1;
+	uint32_t result = static_cast< uint32_t >( ( m_bitBuffer >> ( 64 - m_bitsLeft ) & ( m_bitsLeft == 0 ? 0 : 0xFFFFFFFFFFFFFFFF ) ) & mask );
 
 	if ( m_bitsLeft < bitCount )
 	{
@@ -114,8 +114,8 @@ RBS_INLINE uint32_t ReadBitstream::Read( uint32_t bitCount )
 
 		m_cursor += 8;
 
-		result |= static_cast< uint32_t >( m_bitBuffer << m_bitsLeft ) & mask;
-		m_bitsLeft = 64 - ( bitCount - m_bitsLeft );
+		result     |= static_cast< uint32_t >( m_bitBuffer << m_bitsLeft ) & mask;
+		m_bitsLeft  = 64 - ( bitCount - m_bitsLeft );
 	}
 	else
 	{

+ 13 - 13
3rdparty/ib-compress/writebitstream.h

@@ -45,11 +45,11 @@ public:
 	WriteBitstream( size_t initialBufferCapacity = 16 )
 	{
 		m_bufferCursor =
-			m_buffer = new uint8_t[ initialBufferCapacity ];
-		m_bufferEnd = m_buffer + initialBufferCapacity;
-		m_size = 0;
-		m_bitsLeft = 64;
-		m_bitBuffer = 0;
+		m_buffer       = new uint8_t[ initialBufferCapacity ];
+		m_bufferEnd    = m_buffer + initialBufferCapacity;
+		m_size         = 0;
+		m_bitsLeft     = 64;
+		m_bitBuffer    = 0;
 	}
 
 	~WriteBitstream()
@@ -96,7 +96,7 @@ private:
 
 WBS_INLINE void WriteBitstream::Write( uint32_t value, uint32_t bitCount )
 {
-	m_bitBuffer |= static_cast<uint64_t>( value ) << ( 64 - m_bitsLeft );
+    m_bitBuffer |= ( static_cast<uint64_t>( value ) << ( 64 - m_bitsLeft ) ) & ( m_bitsLeft == 0 ? 0 : 0xFFFFFFFFFFFFFFFF );
 
 	if ( bitCount > m_bitsLeft )
 	{
@@ -116,8 +116,8 @@ WBS_INLINE void WriteBitstream::Write( uint32_t value, uint32_t bitCount )
 
 		m_bufferCursor += 8;
 
-		m_bitBuffer = value >> ( m_bitsLeft );
-		m_bitsLeft = 64 - ( bitCount - m_bitsLeft );
+        m_bitBuffer = value >> ( m_bitsLeft );
+		m_bitsLeft  = 64 - ( bitCount - m_bitsLeft );
 	}
 	else
 	{
@@ -161,18 +161,18 @@ inline void WriteBitstream::Finish()
 
 WBS_INLINE void WriteBitstream::GrowBuffer()
 {
-	size_t    bufferSize = m_bufferEnd - m_buffer;
-	size_t    newBufferSize = bufferSize * 2;
+	size_t    bufferSize     = m_bufferEnd - m_buffer;
+	size_t    newBufferSize  = bufferSize * 2;
 	size_t    bufferPosition = m_bufferCursor - m_buffer;
-	uint8_t*  newBuffer = new uint8_t[ newBufferSize ];
+	uint8_t*  newBuffer      = new uint8_t[ newBufferSize ];
 
 	::memcpy( reinterpret_cast<void*>( newBuffer ), reinterpret_cast<void*>( m_buffer ), bufferSize );
 
 	delete[] m_buffer;
 
-	m_buffer = newBuffer;
+	m_buffer       = newBuffer;
 	m_bufferCursor = m_buffer + bufferPosition;
-	m_bufferEnd = m_buffer + newBufferSize;
+	m_bufferEnd    = m_buffer + newBufferSize;
 }
 
 #endif // -- WRITE_BIT_STREAM_H__

+ 5 - 204
examples/18-ibl/ibl.cpp

@@ -100,207 +100,8 @@ struct Uniforms
 	bgfx::UniformHandle u_rgbDiff;
 	bgfx::UniformHandle u_rgbSpec;
 };
-static Uniforms s_uniforms;
-
-struct Aabb
-{
-	float m_min[3];
-	float m_max[3];
-};
-
-struct Obb
-{
-	float m_mtx[16];
-};
-
-struct Sphere
-{
-	float m_center[3];
-	float m_radius;
-};
-
-struct Primitive
-{
-	uint32_t m_startIndex;
-	uint32_t m_numIndices;
-	uint32_t m_startVertex;
-	uint32_t m_numVertices;
-
-	Sphere m_sphere;
-	Aabb m_aabb;
-	Obb m_obb;
-};
-
-typedef std::vector<Primitive> PrimitiveArray;
-
-struct Group
-{
-	Group()
-	{
-		reset();
-	}
-
-	void reset()
-	{
-		m_vbh.idx = bgfx::invalidHandle;
-		m_ibh.idx = bgfx::invalidHandle;
-		m_prims.clear();
-	}
-
-	bgfx::VertexBufferHandle m_vbh;
-	bgfx::IndexBufferHandle m_ibh;
-	Sphere m_sphere;
-	Aabb m_aabb;
-	Obb m_obb;
-	PrimitiveArray m_prims;
-};
-
-namespace bgfx
-{
-	int32_t read(bx::ReaderI* _reader, bgfx::VertexDecl& _decl);
-}
-
-struct Mesh
-{
-	void load(const char* _filePath)
-	{
-#define BGFX_CHUNK_MAGIC_VB  BX_MAKEFOURCC('V', 'B', ' ', 0x1)
-#define BGFX_CHUNK_MAGIC_IB  BX_MAKEFOURCC('I', 'B', ' ', 0x0)
-#define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
-
-		bx::CrtFileReader reader;
-		reader.open(_filePath);
-
-		Group group;
-
-		uint32_t chunk;
-		while (4 == bx::read(&reader, chunk) )
-		{
-			switch (chunk)
-			{
-			case BGFX_CHUNK_MAGIC_VB:
-				{
-					bx::read(&reader, group.m_sphere);
-					bx::read(&reader, group.m_aabb);
-					bx::read(&reader, group.m_obb);
-
-					bgfx::read(&reader, m_decl);
-					uint16_t stride = m_decl.getStride();
-
-					uint16_t numVertices;
-					bx::read(&reader, numVertices);
-					const bgfx::Memory* mem = bgfx::alloc(numVertices*stride);
-					bx::read(&reader, mem->data, mem->size);
-
-					group.m_vbh = bgfx::createVertexBuffer(mem, m_decl);
-				}
-				break;
-
-			case BGFX_CHUNK_MAGIC_IB:
-				{
-					uint32_t numIndices;
-					bx::read(&reader, numIndices);
-					const bgfx::Memory* mem = bgfx::alloc(numIndices*2);
-					bx::read(&reader, mem->data, mem->size);
-					group.m_ibh = bgfx::createIndexBuffer(mem);
-				}
-				break;
-
-			case BGFX_CHUNK_MAGIC_PRI:
-				{
-					uint16_t len;
-					bx::read(&reader, len);
-
-					std::string material;
-					material.resize(len);
-					bx::read(&reader, const_cast<char*>(material.c_str() ), len);
-
-					uint16_t num;
-					bx::read(&reader, num);
-
-					for (uint32_t ii = 0; ii < num; ++ii)
-					{
-						bx::read(&reader, len);
-
-						std::string name;
-						name.resize(len);
-						bx::read(&reader, const_cast<char*>(name.c_str() ), len);
-
-						Primitive prim;
-						bx::read(&reader, prim.m_startIndex);
-						bx::read(&reader, prim.m_numIndices);
-						bx::read(&reader, prim.m_startVertex);
-						bx::read(&reader, prim.m_numVertices);
-						bx::read(&reader, prim.m_sphere);
-						bx::read(&reader, prim.m_aabb);
-						bx::read(&reader, prim.m_obb);
-
-						group.m_prims.push_back(prim);
-					}
-
-					m_groups.push_back(group);
-					group.reset();
-				}
-				break;
-
-			default:
-				DBG("%08x at %d", chunk, reader.seek() );
-				break;
-			}
-		}
-
-		reader.close();
-	}
-
-	void unload()
-	{
-		for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
-		{
-			const Group& group = *it;
-			bgfx::destroyVertexBuffer(group.m_vbh);
-
-			if (bgfx::isValid(group.m_ibh) )
-			{
-				bgfx::destroyIndexBuffer(group.m_ibh);
-			}
-		}
-		m_groups.clear();
-	}
 
-	void submit(uint8_t _view, bgfx::ProgramHandle _program, float* _mtx)
-	{
-		for (GroupArray::const_iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
-		{
-			const Group& group = *it;
-
-			// Set uniforms.
-			s_uniforms.submitPerDrawUniforms();
-
-			// Set model matrix for rendering.
-			bgfx::setTransform(_mtx);
-			bgfx::setProgram(_program);
-			bgfx::setIndexBuffer(group.m_ibh);
-			bgfx::setVertexBuffer(group.m_vbh);
-
-			// Set render states.
-			bgfx::setState(0
-				| BGFX_STATE_RGB_WRITE
-				| BGFX_STATE_ALPHA_WRITE
-				| BGFX_STATE_DEPTH_WRITE
-				| BGFX_STATE_DEPTH_TEST_LESS
-				| BGFX_STATE_CULL_CCW
-				| BGFX_STATE_MSAA
-				);
-
-			// Submit primitive for rendering to view 0.
-			bgfx::submit(_view);
-		}
-	}
-
-	bgfx::VertexDecl m_decl;
-	typedef std::vector<Group> GroupArray;
-	GroupArray m_groups;
-};
+static Uniforms s_uniforms;
 
 struct PosColorTexCoord0Vertex
 {
@@ -469,8 +270,8 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 	bgfx::ProgramHandle programMesh = loadProgram("vs_ibl_mesh",   "fs_ibl_mesh");
 	bgfx::ProgramHandle programSky  = loadProgram("vs_ibl_skybox", "fs_ibl_skybox");
 
-	Mesh meshBunny;
-	meshBunny.load("meshes/bunny.bin");
+	Mesh* meshBunny;
+	meshBunny = meshLoad("meshes/pony.bin");
 
 	struct Settings
 	{
@@ -710,14 +511,14 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		bgfx::setTexture(4, u_texCube,    lightProbes[currentLightProbe].m_tex);
 		bgfx::setTexture(5, u_texCubeIrr, lightProbes[currentLightProbe].m_texIrr);
-		meshBunny.submit(1, programMesh, mtx);
+		meshSubmit(meshBunny, 1, programMesh, mtx);
 
 		// Advance to next frame. Rendering thread will be kicked to
 		// process submitted rendering primitives.
 		bgfx::frame();
 	}
 
-	meshBunny.unload();
+	meshUnload(meshBunny);
 
 	// Cleanup.
 	bgfx::destroyProgram(programMesh);

+ 6 - 0
examples/assets/meshes/makefile

@@ -29,5 +29,11 @@ GEOMETRY_BIN=$(addprefix $(RUNTIME_DIR)/meshes/, $(addsuffix .bin, $(basename $(
 
 all: $(GEOMETRY_BIN)
 
+clean:
+	@echo Cleaning...
+	@-rm -vf $(GEOMETRY_BIN)
+
+rebuild: clean all
+
 $(RUNTIME_DIR)/meshes/%.bin : %.obj
 	$(SILENT) $(GEOMETRYC) -f $(<) -o $(@) --packnormal 1

+ 26 - 0
examples/common/bgfx_utils.cpp

@@ -14,6 +14,7 @@ namespace stl = tinystl;
 #include <bx/readerwriter.h>
 #include <bx/fpumath.h>
 #include "entry/entry.h"
+#include <ib-compress/indexbufferdecompression.h>
 
 void* load(bx::FileReaderI* _reader, const char* _filePath)
 {
@@ -279,6 +280,7 @@ struct Mesh
 	{
 #define BGFX_CHUNK_MAGIC_VB  BX_MAKEFOURCC('V', 'B', ' ', 0x1)
 #define BGFX_CHUNK_MAGIC_IB  BX_MAKEFOURCC('I', 'B', ' ', 0x0)
+#define BGFX_CHUNK_MAGIC_IBC BX_MAKEFOURCC('I', 'B', 'C', 0x0)
 #define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
 
 		using namespace bx;
@@ -320,6 +322,30 @@ struct Mesh
 				}
 				break;
 
+			case BGFX_CHUNK_MAGIC_IBC:
+				{
+					uint32_t numIndices;
+					bx::read(_reader, numIndices);
+
+					const bgfx::Memory* mem = bgfx::alloc(numIndices*2);
+
+					uint32_t compressedSize;
+					bx::read(_reader, compressedSize);
+
+					bx::CrtAllocator allocator;
+					void* compressedIndices = BX_ALLOC(&allocator, compressedSize);
+
+					bx::read(_reader, compressedIndices, compressedSize);
+
+					ReadBitstream rbs( (const uint8_t*)compressedIndices, compressedSize);
+					DecompressIndexBuffer( (uint16_t*)mem->data, numIndices / 3, rbs);
+
+					BX_FREE(&allocator, compressedIndices);
+
+					group.m_ibh = bgfx::createIndexBuffer(mem);
+				}
+				break;
+
 			case BGFX_CHUNK_MAGIC_PRI:
 				{
 					uint16_t len;

+ 2 - 0
scripts/example-common.lua

@@ -14,6 +14,8 @@ project ("example-common")
 	}
 
 	files {
+		BGFX_DIR .. "3rdparty/ib-compress/**.cpp",
+		BGFX_DIR .. "3rdparty/ib-compress/**.h",
 		BGFX_DIR .. "examples/common/**.cpp",
 		BGFX_DIR .. "examples/common/**.h",
 	}

+ 1 - 2
scripts/geometryc.lua

@@ -10,8 +10,7 @@ project "geometryc"
 	includedirs {
 		BX_DIR   .. "include",
 		BGFX_DIR .. "include",
-		BGFX_DIR .. "3rdparty/forsyth-too",
-		BGFX_DIR .. "3rdparty/ib-compress",
+		BGFX_DIR .. "3rdparty",
 		BGFX_DIR .. "examples/common",
 	}
 

+ 123 - 20
tools/geometryc/geometryc.cpp

@@ -15,9 +15,11 @@
 
 #include <tinystl/allocator.h>
 #include <tinystl/unordered_map.h>
+#include <tinystl/unordered_set.h>
 namespace stl = tinystl;
 
-#include <forsythtriangleorderoptimizer.h>
+#include <forsyth-too/forsythtriangleorderoptimizer.h>
+#include <ib-compress/indexbuffercompression.h>
 
 #if 0
 #	define BX_TRACE(_format, ...) \
@@ -116,6 +118,7 @@ static uint32_t s_obbSteps = 17;
 #define BGFX_CHUNK_MAGIC_GEO BX_MAKEFOURCC('G', 'E', 'O', 0x0)
 #define BGFX_CHUNK_MAGIC_VB  BX_MAKEFOURCC('V', 'B', ' ', 0x1)
 #define BGFX_CHUNK_MAGIC_IB  BX_MAKEFOURCC('I', 'B', ' ', 0x0)
+#define BGFX_CHUNK_MAGIC_IBC BX_MAKEFOURCC('I', 'B', 'C', 0x0)
 #define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
 
 long int fsize(FILE* _file)
@@ -135,6 +138,36 @@ void triangleReorder(uint16_t* _indices, uint32_t _numIndices, uint32_t _numVert
 	delete [] newIndexList;
 }
 
+void triangleCompress(bx::WriterI* _writer, uint16_t* _indices, uint32_t _numIndices, uint8_t* _vertexData, uint32_t _numVertices, uint16_t _stride)
+{
+	uint32_t* vertexRemap = (uint32_t*)malloc(_numVertices*sizeof(uint32_t) );
+
+	WriteBitstream writer;
+	CompressIndexBuffer(_indices, _numIndices/3, vertexRemap, _numVertices, IBCF_PER_TRIANGLE_1, writer);
+	writer.Finish();
+	printf( "uncompressed: %10d, compressed: %10d, ratio: %0.2f%%\n"
+		, _numIndices * 2
+		, writer.ByteSize()
+		, 100.0f - float( writer.ByteSize() ) / float( _numIndices * 2 )*100.0f
+		);
+
+	BX_UNUSED(_vertexData, _stride);
+	uint8_t* outVertexData = (uint8_t*)malloc(_numVertices*_stride);
+	for (uint32_t ii = 0; ii < _numVertices; ++ii)
+	{
+		if (UINT32_MAX != vertexRemap[ii])
+		{
+			memcpy(&outVertexData[vertexRemap[ii]*_stride], &_vertexData[ii*_stride], _stride);
+		}
+	}
+	memcpy(_vertexData, outVertexData, _numVertices*_stride);
+	free(outVertexData);
+
+	free(vertexRemap);
+
+	bx::write(_writer, writer.RawData(), (uint32_t)writer.ByteSize() );
+}
+
 void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl, const uint16_t* _indices, uint32_t _numIndices)
 {
 	struct PosTexcoord
@@ -262,7 +295,17 @@ void write(bx::WriterI* _writer, const void* _vertices, uint32_t _numVertices, u
 	bx::write(_writer, obb);
 }
 
-void write(bx::WriterI* _writer, const uint8_t* _vertices, uint32_t _numVertices, const bgfx::VertexDecl& _decl, const uint16_t* _indices, uint32_t _numIndices, const std::string& _material, const PrimitiveArray& _primitives)
+void write(bx::WriterI* _writer
+		, const uint8_t* _vertices
+		, uint32_t _numVertices
+		, const bgfx::VertexDecl& _decl
+		, const uint16_t* _indices
+		, uint32_t _numIndices
+		, const uint8_t* _compressedIndices
+		, uint32_t _compressedSize
+		, const std::string& _material
+		, const PrimitiveArray& _primitives
+		)
 {
 	using namespace bx;
 	using namespace bgfx;
@@ -276,9 +319,19 @@ void write(bx::WriterI* _writer, const uint8_t* _vertices, uint32_t _numVertices
 	write(_writer, uint16_t(_numVertices) );
 	write(_writer, _vertices, _numVertices*stride);
 
-	write(_writer, BGFX_CHUNK_MAGIC_IB);
-	write(_writer, _numIndices);
-	write(_writer, _indices, _numIndices*2);
+	if (NULL != _compressedIndices)
+	{
+		write(_writer, BGFX_CHUNK_MAGIC_IBC);
+		write(_writer, _numIndices);
+		write(_writer, _compressedSize);
+		write(_writer, _compressedIndices, _compressedSize);
+	}
+	else
+	{
+		write(_writer, BGFX_CHUNK_MAGIC_IB);
+		write(_writer, _numIndices);
+		write(_writer, _indices, _numIndices*2);
+	}
 
 	write(_writer, BGFX_CHUNK_MAGIC_PRI);
 	uint16_t nameLen = uint16_t(_material.size() );
@@ -336,6 +389,7 @@ void help(const char* _error = NULL)
 		  "           0 - unpacked 8 bytes (default).\n"
 		  "           1 - packed 4 bytes.\n"
 		  "      --tangent            Calculate tangent vectors (packing mode is the same as normal).\n"
+		  "  -c, --compress           Compress indices.\n"
 
 		  "\n"
 		  "For additional information, see https://github.com/bkaradzic/bgfx\n"
@@ -384,6 +438,8 @@ int main(int _argc, const char* _argv[])
 		scale = (float)atof(scaleArg);
 	}
 
+	bool compress = cmdLine.hasArg('c', "compress");
+
 	cmdLine.hasArg(s_obbSteps, '\0', "obb");
 	s_obbSteps = bx::uint32_min(bx::uint32_max(s_obbSteps, 1), 90);
 
@@ -755,10 +811,13 @@ int main(int _argc, const char* _argv[])
 
 	Primitive prim;
 	prim.m_startVertex = 0;
-	prim.m_startIndex = 0;
+	prim.m_startIndex  = 0;
 
 	uint32_t positionOffset = decl.getOffset(bgfx::Attrib::Position);
-	uint32_t color0Offset = decl.getOffset(bgfx::Attrib::Color0);
+	uint32_t color0Offset   = decl.getOffset(bgfx::Attrib::Color0);
+
+	bx::CrtAllocator crtAllocator;
+	bx::MemoryBlock  memBlock(&crtAllocator);
 
 	uint32_t ii = 0;
 	for (GroupArray::const_iterator groupIt = groups.begin(); groupIt != groups.end(); ++groupIt, ++ii)
@@ -769,26 +828,48 @@ int main(int _argc, const char* _argv[])
 			||  65533 < numVertices)
 			{
 				prim.m_numVertices = numVertices - prim.m_startVertex;
-				prim.m_numIndices = numIndices - prim.m_startIndex;
+				prim.m_numIndices  = numIndices  - prim.m_startIndex;
 				if (0 < prim.m_numVertices)
 				{
 					primitives.push_back(prim);
 				}
 
+				if (hasTangent)
+				{
+					calcTangents(vertexData, numVertices, decl, indexData, numIndices);
+				}
+
+				bx::MemoryWriter memWriter(&memBlock);
+
 				triReorderElapsed -= bx::getHPCounter();
 				for (PrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt)
 				{
 					const Primitive& prim = *primIt;
 					triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32);
+					if (compress)
+					{
+						triangleCompress(&memWriter
+							, indexData  + prim.m_startIndex
+							, prim.m_numIndices
+							, vertexData + prim.m_startVertex
+							, numVertices
+							, stride
+							);
+					}
 				}
 				triReorderElapsed += bx::getHPCounter();
 
-				if (hasTangent)
-				{
-					calcTangents(vertexData, numVertices, decl, indexData, numIndices);
-				}
-
-				write(&writer, vertexData, numVertices, decl, indexData, numIndices, material, primitives);
+				write(&writer
+					, vertexData
+					, numVertices
+					, decl
+					, indexData
+					, numIndices
+					, (uint8_t*)memBlock.more()
+					, memBlock.getSize()
+					, material
+					, primitives
+					);
 				primitives.clear();
 
 				for (Index3Map::iterator indexIt = indexMap.begin(); indexIt != indexMap.end(); ++indexIt)
@@ -873,20 +954,42 @@ int main(int _argc, const char* _argv[])
 
 	if (0 < primitives.size() )
 	{
+		if (hasTangent)
+		{
+			calcTangents(vertexData, numVertices, decl, indexData, numIndices);
+		}
+
+		bx::MemoryWriter memWriter(&memBlock);
+
 		triReorderElapsed -= bx::getHPCounter();
 		for (PrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt)
 		{
 			const Primitive& prim = *primIt;
 			triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32);
+			if (compress)
+			{
+				triangleCompress(&memWriter
+					, indexData  + prim.m_startIndex
+					, prim.m_numIndices
+					, vertexData + prim.m_startVertex
+					, numVertices
+					, stride
+					);
+			}
 		}
 		triReorderElapsed += bx::getHPCounter();
 
-		if (hasTangent)
-		{
-			calcTangents(vertexData, numVertices, decl, indexData, numIndices);
-		}
-
-		write(&writer, vertexData, numVertices, decl, indexData, numIndices, material, primitives);
+		write(&writer
+			, vertexData
+			, numVertices
+			, decl
+			, indexData
+			, numIndices
+			, (uint8_t*)memBlock.more()
+			, memBlock.getSize()
+			, material
+			, primitives
+			);
 	}
 
 	printf("size: %d\n", uint32_t(writer.seek() ) );