| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421 |
- /*
- * Copyright 2011-2020 Branimir Karadzic. All rights reserved.
- * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
- */
- #include <algorithm>
- #include <bx/string.h>
- #include <bgfx/bgfx.h>
- #include "../../src/vertexlayout.h"
- #include <tinystl/allocator.h>
- #include <tinystl/string.h>
- #include <tinystl/vector.h>
- namespace stl = tinystl;
- #include <meshoptimizer/src/meshoptimizer.h>
- #define CGLTF_IMPLEMENTATION
- #include <cgltf/cgltf.h>
- #define BGFX_GEOMETRYC_VERSION_MAJOR 1
- #define BGFX_GEOMETRYC_VERSION_MINOR 0
- #if 0
- # define BX_TRACE(_format, ...) \
- do { \
- bx::printf(BX_FILE_LINE_LITERAL "BGFX " _format "\n", ##__VA_ARGS__); \
- } while(0)
- # define BX_WARN(_condition, _format, ...) \
- do { \
- if (!(_condition) ) \
- { \
- BX_TRACE(BX_FILE_LINE_LITERAL "WARN " _format, ##__VA_ARGS__); \
- } \
- } while(0)
- # define BX_CHECK(_condition, _format, ...) \
- do { \
- if (!(_condition) ) \
- { \
- BX_TRACE(BX_FILE_LINE_LITERAL "CHECK " _format, ##__VA_ARGS__); \
- bx::debugBreak(); \
- } \
- } while(0)
- #endif // 0
- #include <bx/bx.h>
- #include <bx/debug.h>
- #include <bx/commandline.h>
- #include <bx/timer.h>
- #include <bx/hash.h>
- #include <bx/uint32_t.h>
- #include <bx/math.h>
- #include <bx/file.h>
- #include "bounds.h"
- typedef stl::vector<bx::Vec3> Vec3Array;
- struct Index3
- {
- int32_t m_position;
- int32_t m_texcoord;
- int32_t m_normal;
- int32_t m_vbc; // Barycentric ID. Holds either 0, 1 or 2.
- };
- struct TriIndices
- {
- Index3 m_index[3];
- };
- typedef stl::vector<TriIndices> TriangleArray;
- struct Group
- {
- uint32_t m_startTriangle;
- uint32_t m_numTriangles;
- stl::string m_name;
- stl::string m_material;
- };
- typedef stl::vector<Group> GroupArray;
- struct Primitive
- {
- uint32_t m_startVertex;
- uint32_t m_startIndex;
- uint32_t m_numVertices;
- uint32_t m_numIndices;
- stl::string m_name;
- };
- typedef stl::vector<Primitive> PrimitiveArray;
- struct Axis
- {
- enum Enum
- {
- NegativeX,
- PositiveX,
- NegativeY,
- PositiveY,
- NegativeZ,
- PositiveZ,
- };
- };
- static bx::Vec3 s_axisVectors[6] =
- {
- bx::Vec3(-1.0f, 0.0f, 0.0f),
- bx::Vec3( 1.0f, 0.0f, 0.0f),
- bx::Vec3( 0.0f,-1.0f, 0.0f),
- bx::Vec3( 0.0f, 1.0f, 0.0f),
- bx::Vec3( 0.0f, 0.0f,-1.0f),
- bx::Vec3( 0.0f, 0.0f, 1.0f),
- };
- struct CoordinateSystem
- {
- bx::Handness::Enum m_handness;
- Axis::Enum m_up;
- Axis::Enum m_forward;
- };
- struct CoordinateSystemMapping
- {
- const char* m_param;
- CoordinateSystem m_coordinateSystem;
- };
- static const CoordinateSystemMapping s_coordinateSystemMappings[] =
- {
- { "lh-up+y", { bx::Handness::Left, Axis::PositiveY, Axis::PositiveZ } } ,
- { "lh-up+z", { bx::Handness::Left, Axis::PositiveZ, Axis::PositiveY } },
- { "rh-up+y", { bx::Handness::Right, Axis::PositiveY, Axis::PositiveZ } },
- { "rh-up+z", { bx::Handness::Right, Axis::PositiveZ, Axis::PositiveY } },
- };
- struct Mesh
- {
- Vec3Array m_positions;
- Vec3Array m_normals;
- Vec3Array m_texcoords;
- TriangleArray m_triangles;
- GroupArray m_groups;
- CoordinateSystem m_coordinateSystem;
- };
- static uint32_t s_obbSteps = 17;
- #define BGFX_CHUNK_MAGIC_VB BX_MAKEFOURCC('V', 'B', ' ', 0x1)
- #define BGFX_CHUNK_MAGIC_VBC BX_MAKEFOURCC('V', 'B', 'C', 0x0)
- #define BGFX_CHUNK_MAGIC_IB BX_MAKEFOURCC('I', 'B', ' ', 0x0)
- #define BGFX_CHUNK_MAGIC_IBC BX_MAKEFOURCC('I', 'B', 'C', 0x1)
- #define BGFX_CHUNK_MAGIC_PRI BX_MAKEFOURCC('P', 'R', 'I', 0x0)
- void optimizeVertexCache(uint16_t* _indices, uint32_t _numIndices, uint32_t _numVertices)
- {
- uint16_t* newIndexList = new uint16_t[_numIndices];
- meshopt_optimizeVertexCache(newIndexList, _indices, _numIndices, _numVertices);
- bx::memCopy(_indices, newIndexList, _numIndices * 2);
- delete[] newIndexList;
- }
- uint32_t optimizeVertexFetch(uint16_t* _indices, uint32_t _numIndices, uint8_t* _vertexData, uint32_t _numVertices, uint16_t _stride)
- {
- unsigned char* newVertices = (unsigned char*)malloc(_numVertices * _stride );
- size_t vertexCount = meshopt_optimizeVertexFetch(newVertices, _indices, _numIndices, _vertexData, _numVertices, _stride);
- bx::memCopy(_vertexData, newVertices, _numVertices * _stride);
- free(newVertices);
- return uint32_t(vertexCount);
- }
- void writeCompressedIndices(bx::WriterI* _writer, const uint16_t* _indices, uint32_t _numIndices, uint32_t _numVertices)
- {
- size_t maxSize = meshopt_encodeIndexBufferBound(_numIndices, _numVertices);
- unsigned char* compressedIndices = (unsigned char*)malloc(maxSize);
- size_t compressedSize = meshopt_encodeIndexBuffer(compressedIndices, maxSize, _indices, _numIndices);
- bx::printf( "indices uncompressed: %10d, compressed: %10d, ratio: %0.2f%%\n"
- , _numIndices*2
- , (uint32_t)compressedSize
- , 100.0f - float(compressedSize ) / float(_numIndices*2)*100.0f
- );
- bx::write(_writer, (uint32_t)compressedSize);
- bx::write(_writer, compressedIndices, (uint32_t)compressedSize );
- free(compressedIndices);
- }
- void writeCompressedVertices(bx::WriterI* _writer, const uint8_t* _vertices, uint32_t _numVertices, uint16_t _stride)
- {
- size_t maxSize = meshopt_encodeVertexBufferBound(_numVertices, _stride);
- unsigned char* compressedVertices = (unsigned char*)malloc(maxSize);
- size_t compressedSize = meshopt_encodeVertexBuffer(compressedVertices, maxSize, _vertices, _numVertices, _stride);
- bx::printf("vertices uncompressed: %10d, compressed: %10d, ratio: %0.2f%%\n"
- , _numVertices * _stride
- , (uint32_t)compressedSize
- , 100.0f - float(compressedSize) / float(_numVertices * _stride)*100.0f
- );
- bx::write(_writer, (uint32_t)compressedSize);
- bx::write(_writer, compressedVertices, (uint32_t)compressedSize );
- free(compressedVertices);
- }
- void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexLayout _layout, const uint16_t* _indices, uint32_t _numIndices)
- {
- struct PosTexcoord
- {
- float m_x;
- float m_y;
- float m_z;
- float m_pad0;
- float m_u;
- float m_v;
- float m_pad1;
- float m_pad2;
- };
- float* tangents = new float[6*_numVertices];
- bx::memSet(tangents, 0, 6*_numVertices*sizeof(float) );
- PosTexcoord v0;
- PosTexcoord v1;
- PosTexcoord v2;
- for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii)
- {
- const uint16_t* indices = &_indices[ii*3];
- uint32_t i0 = indices[0];
- uint32_t i1 = indices[1];
- uint32_t i2 = indices[2];
- bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _layout, _vertices, i0);
- bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i0);
- bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _layout, _vertices, i1);
- bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i1);
- bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _layout, _vertices, i2);
- bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _layout, _vertices, i2);
- const float bax = v1.m_x - v0.m_x;
- const float bay = v1.m_y - v0.m_y;
- const float baz = v1.m_z - v0.m_z;
- const float bau = v1.m_u - v0.m_u;
- const float bav = v1.m_v - v0.m_v;
- const float cax = v2.m_x - v0.m_x;
- const float cay = v2.m_y - v0.m_y;
- const float caz = v2.m_z - v0.m_z;
- const float cau = v2.m_u - v0.m_u;
- const float cav = v2.m_v - v0.m_v;
- const float det = (bau * cav - bav * cau);
- const float invDet = 1.0f / det;
- const float tx = (bax * cav - cax * bav) * invDet;
- const float ty = (bay * cav - cay * bav) * invDet;
- const float tz = (baz * cav - caz * bav) * invDet;
- const float bx = (cax * bau - bax * cau) * invDet;
- const float by = (cay * bau - bay * cau) * invDet;
- const float bz = (caz * bau - baz * cau) * invDet;
- for (uint32_t jj = 0; jj < 3; ++jj)
- {
- float* tanu = &tangents[indices[jj]*6];
- float* tanv = &tanu[3];
- tanu[0] += tx;
- tanu[1] += ty;
- tanu[2] += tz;
- tanv[0] += bx;
- tanv[1] += by;
- tanv[2] += bz;
- }
- }
- for (uint32_t ii = 0; ii < _numVertices; ++ii)
- {
- const bx::Vec3 tanu = bx::load<bx::Vec3>(&tangents[ii*6]);
- const bx::Vec3 tanv = bx::load<bx::Vec3>(&tangents[ii*6 + 3]);
- float nxyzw[4];
- bgfx::vertexUnpack(nxyzw, bgfx::Attrib::Normal, _layout, _vertices, ii);
- const bx::Vec3 normal = bx::load<bx::Vec3>(nxyzw);
- const float ndt = bx::dot(normal, tanu);
- const bx::Vec3 nxt = bx::cross(normal, tanu);
- const bx::Vec3 tmp = bx::sub(tanu, bx::mul(normal, ndt) );
- float tangent[4];
- bx::store(tangent, bx::normalize(tmp) );
- tangent[3] = bx::dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
- bgfx::vertexPack(tangent, true, bgfx::Attrib::Tangent, _layout, _vertices, ii);
- }
- delete [] tangents;
- }
- void write(bx::WriterI* _writer, const void* _vertices, uint32_t _numVertices, uint32_t _stride)
- {
- Sphere maxSphere;
- calcMaxBoundingSphere(maxSphere, _vertices, _numVertices, _stride);
- Sphere minSphere;
- calcMinBoundingSphere(minSphere, _vertices, _numVertices, _stride);
- if (minSphere.radius > maxSphere.radius)
- {
- bx::write(_writer, maxSphere);
- }
- else
- {
- bx::write(_writer, minSphere);
- }
- Aabb aabb;
- toAabb(aabb, _vertices, _numVertices, _stride);
- bx::write(_writer, aabb);
- Obb obb;
- calcObb(obb, _vertices, _numVertices, _stride, s_obbSteps);
- bx::write(_writer, obb);
- }
- void write(bx::WriterI* _writer
- , const uint8_t* _vertices
- , uint32_t _numVertices
- , const bgfx::VertexLayout& _layout
- , const uint16_t* _indices
- , uint32_t _numIndices
- , bool _compress
- , const stl::string& _material
- , const PrimitiveArray& _primitives
- )
- {
- using namespace bx;
- using namespace bgfx;
- uint32_t stride = _layout.getStride();
- if (_compress)
- {
- write(_writer, BGFX_CHUNK_MAGIC_VBC);
- write(_writer, _vertices, _numVertices, stride);
- write(_writer, _layout);
- write(_writer, uint16_t(_numVertices) );
- writeCompressedVertices(_writer, _vertices, _numVertices, uint16_t(stride));
- }
- else
- {
- write(_writer, BGFX_CHUNK_MAGIC_VB);
- write(_writer, _vertices, _numVertices, stride);
- write(_writer, _layout);
- write(_writer, uint16_t(_numVertices) );
- write(_writer, _vertices, _numVertices*stride);
- }
- if (_compress)
- {
- write(_writer, BGFX_CHUNK_MAGIC_IBC);
- write(_writer, _numIndices);
- writeCompressedIndices(_writer, _indices, _numIndices, _numVertices);
- }
- 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() );
- write(_writer, nameLen);
- write(_writer, _material.c_str(), nameLen);
- write(_writer, uint16_t(_primitives.size() ) );
- for (PrimitiveArray::const_iterator primIt = _primitives.begin(); primIt != _primitives.end(); ++primIt)
- {
- const Primitive& prim = *primIt;
- nameLen = uint16_t(prim.m_name.size() );
- write(_writer, nameLen);
- write(_writer, prim.m_name.c_str(), nameLen);
- write(_writer, prim.m_startIndex);
- write(_writer, prim.m_numIndices);
- write(_writer, prim.m_startVertex);
- write(_writer, prim.m_numVertices);
- write(_writer, &_vertices[prim.m_startVertex*stride], prim.m_numVertices, stride);
- }
- }
- inline uint32_t rgbaToAbgr(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a)
- {
- return (uint32_t(_r)<<0)
- | (uint32_t(_g)<<8)
- | (uint32_t(_b)<<16)
- | (uint32_t(_a)<<24)
- ;
- }
- struct GroupSortByMaterial
- {
- bool operator()(const Group& _lhs, const Group& _rhs)
- {
- return 0 < bx::strCmp(_lhs.m_material.c_str(), _rhs.m_material.c_str() );
- }
- };
- void mtxCoordinateTransform(float* _result, const CoordinateSystem& _cs)
- {
- bx::Vec3 up = s_axisVectors[_cs.m_up];
- bx::Vec3 forward = s_axisVectors[_cs.m_forward];
- bx::Vec3 right = cross(forward,up);
- if ( _cs.m_handness == bx::Handness::Left)
- {
- right = bx::mul(right, -1.0f);
- }
- bx::mtxIdentity(_result);
- bx::store(&_result[0], right);
- bx::store(&_result[4], forward);
- bx::store(&_result[8], up);
- }
- float mtxDeterminant(const float* _a)
- {
- const float xx = _a[ 0];
- const float xy = _a[ 1];
- const float xz = _a[ 2];
- const float xw = _a[ 3];
- const float yx = _a[ 4];
- const float yy = _a[ 5];
- const float yz = _a[ 6];
- const float yw = _a[ 7];
- const float zx = _a[ 8];
- const float zy = _a[ 9];
- const float zz = _a[10];
- const float zw = _a[11];
- const float wx = _a[12];
- const float wy = _a[13];
- const float wz = _a[14];
- const float ww = _a[15];
- float det = 0.0f;
- det += xx * (yy*(zz*ww - zw*wz) - yz*(zy*ww - zw*wy) + yw*(zy*wz - zz*wy) );
- det -= xy * (yx*(zz*ww - zw*wz) - yz*(zx*ww - zw*wx) + yw*(zx*wz - zz*wx) );
- det += xz * (yx*(zy*ww - zw*wy) - yy*(zx*ww - zw*wx) + yw*(zx*wy - zy*wx) );
- det -= xw * (yx*(zy*wz - zz*wy) - yy*(zx*wz - zz*wx) + yz*(zx*wy - zy*wx) );
- return det;
- }
- void parseObj(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc)
- {
- // Reference(s):
- // - Wavefront .obj file
- // https://en.wikipedia.org/wiki/Wavefront_.obj_file
- // Coordinate system is right-handed, but up/forward is not defined, but +Y Up, +Z Forward seems to be a common default
- _mesh->m_coordinateSystem.m_handness = bx::Handness::Right;
- _mesh->m_coordinateSystem.m_up = Axis::PositiveY;
- _mesh->m_coordinateSystem.m_forward = Axis::PositiveZ;
- uint32_t num = 0;
- Group group;
- group.m_startTriangle = 0;
- group.m_numTriangles = 0;
- char commandLine[2048];
- uint32_t len = sizeof(commandLine);
- int argc;
- char* argv[64];
- for (bx::StringView next(_data, _size); !next.isEmpty(); )
- {
- next = bx::tokenizeCommandLine(next, commandLine, len, argc, argv, BX_COUNTOF(argv), '\n');
- if (0 < argc)
- {
- if (0 == bx::strCmp(argv[0], "#") )
- {
- if (2 < argc
- && 0 == bx::strCmp(argv[2], "polygons") )
- {
- }
- }
- else if (0 == bx::strCmp(argv[0], "f") )
- {
- TriIndices triangle;
- bx::memSet(&triangle, 0, sizeof(TriIndices) );
- const int numNormals = (int)_mesh->m_normals.size();
- const int numTexcoords = (int)_mesh->m_texcoords.size();
- const int numPositions = (int)_mesh->m_positions.size();
- for (uint32_t edge = 0, numEdges = argc-1; edge < numEdges; ++edge)
- {
- Index3 index;
- index.m_texcoord = -1;
- index.m_normal = -1;
- if (_hasBc)
- {
- index.m_vbc = edge < 3 ? edge : (1+(edge+1) )&1;
- }
- else
- {
- index.m_vbc = 0;
- }
- {
- bx::StringView triplet(argv[edge + 1]);
- bx::StringView vertex(triplet);
- bx::StringView texcoord = bx::strFind(triplet, '/');
- if (!texcoord.isEmpty())
- {
- vertex.set(vertex.getPtr(), texcoord.getPtr());
- const bx::StringView normal = bx::strFind(bx::StringView(texcoord.getPtr() + 1, triplet.getTerm()), '/');
- if (!normal.isEmpty())
- {
- int32_t nn;
- bx::fromString(&nn, bx::StringView(normal.getPtr() + 1, triplet.getTerm()));
- index.m_normal = (nn < 0) ? nn + numNormals : nn - 1;
- }
- texcoord.set(texcoord.getPtr() + 1, normal.getPtr());
- // Reference(s):
- // - Wavefront .obj file / Vertex normal indices without texture coordinate indices
- // https://en.wikipedia.org/wiki/Wavefront_.obj_file#Vertex_Normal_Indices_Without_Texture_Coordinate_Indices
- if (!texcoord.isEmpty())
- {
- int32_t tex;
- bx::fromString(&tex, texcoord);
- index.m_texcoord = (tex < 0) ? tex + numTexcoords : tex - 1;
- }
- }
- int32_t pos;
- bx::fromString(&pos, vertex);
- index.m_position = (pos < 0) ? pos + numPositions : pos - 1;
- }
- switch (edge)
- {
- case 0: case 1: case 2:
- triangle.m_index[edge] = index;
- if (2 == edge)
- {
- _mesh->m_triangles.push_back(triangle);
- }
- break;
- default:
- triangle.m_index[1] = triangle.m_index[2];
- triangle.m_index[2] = index;
- _mesh->m_triangles.push_back(triangle);
- break;
- }
- }
- }
- else if (0 == bx::strCmp(argv[0], "g") )
- {
- group.m_name = argv[1];
- }
- else if (*argv[0] == 'v')
- {
- group.m_numTriangles = (uint32_t)(_mesh->m_triangles.size() ) - group.m_startTriangle;
- if (0 < group.m_numTriangles)
- {
- _mesh->m_groups.push_back(group);
- group.m_startTriangle = (uint32_t)(_mesh->m_triangles.size() );
- group.m_numTriangles = 0;
- }
- if (0 == bx::strCmp(argv[0], "vn") )
- {
- bx::Vec3 normal;
- bx::fromString(&normal.x, argv[1]);
- bx::fromString(&normal.y, argv[2]);
- bx::fromString(&normal.z, argv[3]);
- _mesh->m_normals.push_back(normal);
- }
- else if (0 == bx::strCmp(argv[0], "vp") )
- {
- static bool once = true;
- if (once)
- {
- once = false;
- bx::printf("warning: 'parameter space vertices' are unsupported.\n");
- }
- }
- else if (0 == bx::strCmp(argv[0], "vt") )
- {
- bx::Vec3 texcoord;
- texcoord.y = 0.0f;
- texcoord.z = 0.0f;
- bx::fromString(&texcoord.x, argv[1]);
- switch (argc)
- {
- case 4:
- bx::fromString(&texcoord.z, argv[3]);
- BX_FALLTHROUGH;
- case 3:
- bx::fromString(&texcoord.y, argv[2]);
- break;
- default:
- break;
- }
- _mesh->m_texcoords.push_back(texcoord);
- }
- else
- {
- float px, py, pz, pw;
- bx::fromString(&px, argv[1]);
- bx::fromString(&py, argv[2]);
- bx::fromString(&pz, argv[3]);
- if (argc == 5 || argc == 8)
- {
- bx::fromString(&pw, argv[4]);
- }
- else
- {
- pw = 1.0f;
- }
- float invW = 1.0f/pw;
- px *= invW;
- py *= invW;
- pz *= invW;
- bx::Vec3 pos;
- pos.x = px;
- pos.y = py;
- pos.z = pz;
- _mesh->m_positions.push_back(pos);
- }
- }
- else if (0 == bx::strCmp(argv[0], "usemtl") )
- {
- stl::string material(argv[1]);
- if (0 != bx::strCmp(material.c_str(), group.m_material.c_str() ) )
- {
- group.m_numTriangles = (uint32_t)(_mesh->m_triangles.size() ) - group.m_startTriangle;
- if (0 < group.m_numTriangles)
- {
- _mesh->m_groups.push_back(group);
- group.m_startTriangle = (uint32_t)(_mesh->m_triangles.size() );
- group.m_numTriangles = 0;
- }
- }
- group.m_material = material;
- }
- // unsupported tags
- // else if (0 == bx::strCmp(argv[0], "mtllib") )
- // {
- // }
- // else if (0 == bx::strCmp(argv[0], "o") )
- // {
- // }
- // else if (0 == bx::strCmp(argv[0], "s") )
- // {
- // }
- }
- ++num;
- }
- group.m_numTriangles = (uint32_t)(_mesh->m_triangles.size() ) - group.m_startTriangle;
- if (0 < group.m_numTriangles)
- {
- _mesh->m_groups.push_back(group);
- group.m_startTriangle = (uint32_t)(_mesh->m_triangles.size() );
- group.m_numTriangles = 0;
- }
- bx::printf("obj parser # %d\n"
- , num );
- }
- void gltfReadFloat(const float* _accessorData, cgltf_size _accessorNumComponents, cgltf_size _index, cgltf_float* _out, cgltf_size _outElementSize)
- {
- const float* input = &_accessorData[_accessorNumComponents * _index];
- for (cgltf_size ii = 0; ii < _outElementSize; ++ii)
- {
- _out[ii] = (ii < _accessorNumComponents) ? input[ii] : 0.0f;
- }
- }
- void processGltfNode(cgltf_node* _node, Mesh* _mesh, Group* _group, bool _hasBc)
- {
- cgltf_mesh* mesh = _node->mesh;
- if (NULL != mesh)
- {
- float nodeToWorld[16];
- cgltf_node_transform_world(_node, nodeToWorld);
- float nodeToWorldNormal[16];
- bx::mtxCofactor(nodeToWorldNormal, nodeToWorld);
- for (cgltf_size primitiveIndex = 0; primitiveIndex < mesh->primitives_count; ++primitiveIndex)
- {
- cgltf_primitive* primitive = &mesh->primitives[primitiveIndex];
- cgltf_size numVertex = primitive->attributes[0].data->count;
- int32_t basePositionIndex = (int32_t)_mesh->m_positions.size();
- int32_t baseNormalIndex = (int32_t)_mesh->m_normals.size();
- int32_t baseTexcoordIndex = (int32_t)_mesh->m_texcoords.size();
- bool hasNormal = false;
- bool hasTexcoord = false;
- for (cgltf_size attributeIndex = 0; attributeIndex < primitive->attributes_count; ++attributeIndex)
- {
- cgltf_attribute* attribute = &primitive->attributes[attributeIndex];
- cgltf_accessor* accessor = attribute->data;
- cgltf_size accessorCount = accessor->count;
- BX_CHECK(numVertex == accessorCount, "Invalid attribute count");
- cgltf_size floatCount = cgltf_accessor_unpack_floats(accessor, NULL, 0);
- float* accessorData = (float*)malloc(floatCount * sizeof(float));
- cgltf_accessor_unpack_floats(accessor, accessorData, floatCount);
- cgltf_size numComponents = cgltf_num_components(accessor->type);
- if (attribute->type == cgltf_attribute_type_position && attribute->index == 0)
- {
- _mesh->m_positions.reserve(_mesh->m_positions.size() + accessorCount);
- bx::Vec3 pos;
- for(cgltf_size v=0;v<accessorCount;++v)
- {
- gltfReadFloat(accessorData, numComponents, v, &pos.x, 3);
- pos = mul(pos, nodeToWorld);
- _mesh->m_positions.push_back(pos);
- }
- }
- else if (attribute->type == cgltf_attribute_type_normal && attribute->index == 0)
- {
- _mesh->m_normals.reserve(_mesh->m_normals.size() + accessorCount);
- hasNormal = true;
- bx::Vec3 normal;
- for(cgltf_size v=0;v<accessorCount;++v)
- {
- gltfReadFloat(accessorData, numComponents, v, &normal.x, 3);
- normal = mul(normal, nodeToWorldNormal);
- _mesh->m_normals.push_back(normal);
- }
- }
- else if (attribute->type == cgltf_attribute_type_texcoord && attribute->index == 0)
- {
- _mesh->m_texcoords.reserve(_mesh->m_texcoords.size() + accessorCount);
- hasTexcoord = true;
- bx::Vec3 texcoord;
- for(cgltf_size v=0;v<accessorCount;++v)
- {
- gltfReadFloat(accessorData, numComponents, v, &texcoord.x, 3);
- _mesh->m_texcoords.push_back(texcoord);
- }
- }
- free(accessorData);
- }
- if ( primitive->indices != NULL )
- {
- cgltf_accessor* accessor = primitive->indices;
- for(cgltf_size v=0;v<accessor->count; v+=3)
- {
- TriIndices triangle;
- for(int i=0;i<3;++i)
- {
- Index3 index;
- int32_t vertexIndex = int32_t(cgltf_accessor_read_index(accessor, v+i));
- index.m_position = basePositionIndex + vertexIndex;
- index.m_normal = hasNormal ? baseNormalIndex + vertexIndex : -1;
- index.m_texcoord = hasTexcoord ? baseTexcoordIndex + vertexIndex : -1;
- index.m_vbc = _hasBc ? i : 0;
- triangle.m_index[i] = index;
- }
- _mesh->m_triangles.push_back(triangle);
- }
- }
- else
- {
- for(cgltf_size v=0;v<numVertex; v+=3)
- {
- TriIndices triangle;
- for(int i=0;i<3;++i)
- {
- Index3 index;
- int32_t vertexIndex = int32_t(v * 3 + i);
- index.m_position = basePositionIndex + vertexIndex;
- index.m_normal = hasNormal ? baseNormalIndex + vertexIndex : -1;
- index.m_texcoord = hasTexcoord ? baseTexcoordIndex + vertexIndex : -1;
- index.m_vbc = _hasBc ? i : 0;
- triangle.m_index[i] = index;
- }
- _mesh->m_triangles.push_back(triangle);
- }
- }
- _group->m_numTriangles = (uint32_t)(_mesh->m_triangles.size() ) - _group->m_startTriangle;
- if (0 < _group->m_numTriangles)
- {
- _mesh->m_groups.push_back(*_group);
- _group->m_startTriangle = (uint32_t)(_mesh->m_triangles.size() );
- _group->m_numTriangles = 0;
- }
- }
- }
- for (cgltf_size childIndex = 0; childIndex < _node->children_count; ++childIndex)
- processGltfNode(_node->children[childIndex], _mesh, _group, _hasBc);
- }
- void parseGltf(char* _data, uint32_t _size, Mesh* _mesh, bool _hasBc, const bx::StringView& _path)
- {
- // Reference(s):
- // - Gltf 2.0 specification
- // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
- _mesh->m_coordinateSystem.m_handness = bx::Handness::Right;
- _mesh->m_coordinateSystem.m_forward = Axis::PositiveZ;
- _mesh->m_coordinateSystem.m_up = Axis::PositiveY;
- Group group;
- group.m_startTriangle = 0;
- group.m_numTriangles = 0;
- cgltf_options options = { };
- cgltf_data* data = NULL;
- cgltf_result result = cgltf_parse(&options, _data, _size, &data);
- if (result == cgltf_result_success)
- {
- char* path = (char*)malloc(_path.getLength()+1);
- bx::memCopy(path, _path.getPtr(), _path.getLength());
- path[_path.getLength()] = 0;
- result = cgltf_load_buffers(&options, data, path);
- free(path);
- if (result == cgltf_result_success)
- {
- for (cgltf_size sceneIndex = 0; sceneIndex < data->scenes_count; ++sceneIndex)
- {
- cgltf_scene* scene = &data->scenes[sceneIndex];
- for (cgltf_size nodeIndex = 0; nodeIndex < scene->nodes_count; ++nodeIndex)
- {
- cgltf_node* node = scene->nodes[nodeIndex];
- processGltfNode(node, _mesh, &group, _hasBc);
- }
- }
- }
- cgltf_free(data);
- }
- }
- void help(const char* _error = NULL)
- {
- if (NULL != _error)
- {
- bx::printf("Error:\n%s\n\n", _error);
- }
- bx::printf(
- "geometryc, bgfx geometry compiler tool, version %d.%d.%d.\n"
- "Copyright 2011-2020 Branimir Karadzic. All rights reserved.\n"
- "License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause\n\n"
- , BGFX_GEOMETRYC_VERSION_MAJOR
- , BGFX_GEOMETRYC_VERSION_MINOR
- , BGFX_API_VERSION
- );
- bx::printf(
- "Usage: geometryc -f <in> -o <out>\n"
- "\n"
- "Supported input file types:\n"
- " *.obj Wavefront\n"
- " *.gltf,*.glb glTF 2.0\n"
- "\n"
- "Options:\n"
- " -h, --help Help.\n"
- " -v, --version Version information only.\n"
- " -f <file path> Input file path.\n"
- " -o <file path> Output file path.\n"
- " -s, --scale <num> Scale factor.\n"
- " --ccw Front face is counter-clockwise winding order.\n"
- " --flipv Flip texture coordinate V.\n"
- " --obb <num> Number of steps for calculating oriented bounding box.\n"
- " Default value is 17. Less steps less precise OBB is.\n"
- " More steps slower calculation.\n"
- " --packnormal <num> Normal packing.\n"
- " 0 - unpacked 12 bytes (default).\n"
- " 1 - packed 4 bytes.\n"
- " --packuv <num> Texture coordinate packing.\n"
- " 0 - unpacked 8 bytes (default).\n"
- " 1 - packed 4 bytes.\n"
- " --tangent Calculate tangent vectors (packing mode is the same as normal).\n"
- " --barycentric Adds barycentric vertex attribute (packed in bgfx::Attrib::Color1).\n"
- " -c, --compress Compress indices.\n"
- " --[l/r]h-up+[y/z] Coordinate system. Default is '--lh-up+y' Left-Handed +Y is up.\n"
- "\n"
- "For additional information, see https://github.com/bkaradzic/bgfx\n"
- );
- }
- int main(int _argc, const char* _argv[])
- {
- bx::CommandLine cmdLine(_argc, _argv);
- if (cmdLine.hasArg('v', "version"))
- {
- bx::printf(
- "geometryc, bgfx geometry compiler tool, version %d.%d.%d.\n"
- , BGFX_GEOMETRYC_VERSION_MAJOR
- , BGFX_GEOMETRYC_VERSION_MINOR
- , BGFX_API_VERSION
- );
- return bx::kExitSuccess;
- }
- if (cmdLine.hasArg('h', "help"))
- {
- help();
- return bx::kExitFailure;
- }
- const char* filePath = cmdLine.findOption('f');
- if (NULL == filePath)
- {
- help("Input file name must be specified.");
- return bx::kExitFailure;
- }
- const char* outFilePath = cmdLine.findOption('o');
- if (NULL == outFilePath)
- {
- help("Output file name must be specified.");
- return bx::kExitFailure;
- }
- float scale = 1.0f;
- const char* scaleArg = cmdLine.findOption('s', "scale");
- if (NULL != scaleArg)
- {
- if (!bx::fromString(&scale, scaleArg))
- {
- scale = 1.0f;
- }
- }
- bool compress = cmdLine.hasArg('c', "compress");
- cmdLine.hasArg(s_obbSteps, '\0', "obb");
- s_obbSteps = bx::uint32_min(bx::uint32_max(s_obbSteps, 1), 90);
- uint32_t packNormal = 0;
- cmdLine.hasArg(packNormal, '\0', "packnormal");
- uint32_t packUv = 0;
- cmdLine.hasArg(packUv, '\0', "packuv");
- bool ccw = cmdLine.hasArg("ccw");
- bool flipV = cmdLine.hasArg("flipv");
- bool hasTangent = cmdLine.hasArg("tangent");
- bool hasBc = cmdLine.hasArg("barycentric");
- CoordinateSystem outputCoordinateSystem;
- outputCoordinateSystem.m_handness = bx::Handness::Left;
- outputCoordinateSystem.m_forward = Axis::PositiveZ;
- outputCoordinateSystem.m_up = Axis::PositiveY;
- for (uint32_t ii = 0; ii < BX_COUNTOF(s_coordinateSystemMappings); ++ii)
- {
- if (cmdLine.hasArg(s_coordinateSystemMappings[ii].m_param))
- {
- outputCoordinateSystem = s_coordinateSystemMappings[ii].m_coordinateSystem;
- }
- }
- bx::FileReader fr;
- if (!bx::open(&fr, filePath) )
- {
- bx::printf("Unable to open input file '%s'.", filePath);
- return bx::kExitFailure;
- }
- int64_t parseElapsed = -bx::getHPCounter();
- int64_t triReorderElapsed = 0;
- uint32_t size = (uint32_t)bx::getSize(&fr);
- char* data = new char[size+1];
- size = bx::read(&fr, data, size);
- data[size] = '\0';
- bx::close(&fr);
- Mesh mesh;
- bx::StringView ext = bx::FilePath(filePath).getExt();
- if (0 == bx::strCmpI(ext, ".obj"))
- {
- parseObj(data, size, &mesh, hasBc);
- }
- else if (0 == bx::strCmpI(ext, ".gltf") || 0 == bx::strCmpI(ext, ".glb"))
- {
- parseGltf(data, size, &mesh, hasBc, bx::FilePath(filePath).getPath());
- }
- else
- {
- bx::printf("Unsupported input file format '%s'.", filePath);
- exit(bx::kExitFailure);
- }
- delete [] data;
- int64_t now = bx::getHPCounter();
- parseElapsed += now;
- int64_t convertElapsed = -now;
- std::sort(mesh.m_groups.begin(), mesh.m_groups.end(), GroupSortByMaterial() );
- bool changeWinding = ccw;
- if (scale != 1.0f)
- {
- for (Vec3Array::iterator it = mesh.m_positions.begin(), itEnd = mesh.m_positions.end(); it != itEnd; ++it)
- {
- it->x *= scale;
- it->y *= scale;
- it->z *= scale;
- }
- }
- {
- float meshTransform[16];
- mtxCoordinateTransform(meshTransform, mesh.m_coordinateSystem);
- float meshInvTranform[16];
- bx::mtxTranspose(meshInvTranform, meshTransform);
- float outTransform[16];
- mtxCoordinateTransform(outTransform, outputCoordinateSystem);
- float transform[16];
- bx::mtxMul(transform, meshInvTranform, outTransform);
- if ( mtxDeterminant(transform) < 0.0f )
- {
- changeWinding = !changeWinding;
- }
- float identity[16];
- bx::mtxIdentity(identity);
- if ( 0 != bx::memCmp(identity, transform, sizeof(transform) ) )
- {
- for (Vec3Array::iterator it = mesh.m_positions.begin(), itEnd = mesh.m_positions.end(); it != itEnd; ++it)
- {
- *it = bx::mul(*it, transform);
- }
- for (Vec3Array::iterator it = mesh.m_normals.begin(), itEnd = mesh.m_normals.end(); it != itEnd; ++it)
- {
- *it = bx::mul(*it, transform);
- }
- }
- }
- bool hasColor = false;
- bool hasNormal = false;
- bool hasTexcoord = false;
- {
- for (TriangleArray::iterator jt = mesh.m_triangles.begin(), jtEnd = mesh.m_triangles.end(); jt != jtEnd && !hasTexcoord; ++jt)
- {
- for (uint32_t i = 0; i < 3; ++i)
- {
- hasTexcoord |= -1 != jt->m_index[i].m_texcoord;
- }
- }
- for (TriangleArray::iterator jt = mesh.m_triangles.begin(), jtEnd = mesh.m_triangles.end(); jt != jtEnd && !hasNormal; ++jt)
- {
- for (uint32_t i = 0; i < 3; ++i)
- {
- hasNormal |= -1 != jt->m_index[i].m_normal;
- }
- }
- if (changeWinding)
- {
- for (TriangleArray::iterator jt = mesh.m_triangles.begin(), jtEnd = mesh.m_triangles.end(); jt != jtEnd; ++jt)
- {
- bx::swap(jt->m_index[1], jt->m_index[2]);
- }
- }
- }
- bgfx::VertexLayout layout;
- layout.begin();
- layout.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
- if (hasColor)
- {
- layout.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true);
- }
- if (hasBc)
- {
- layout.add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Uint8, true);
- }
- if (hasTexcoord)
- {
- switch (packUv)
- {
- default:
- case 0:
- layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
- break;
- case 1:
- layout.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Half);
- break;
- }
- }
- if (hasNormal)
- {
- hasTangent &= hasTexcoord;
- switch (packNormal)
- {
- default:
- case 0:
- layout.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float);
- if (hasTangent)
- {
- layout.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Float);
- }
- break;
- case 1:
- layout.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true);
- if (hasTangent)
- {
- layout.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true);
- }
- break;
- }
- }
- layout.end();
- uint32_t stride = layout.getStride();
- uint8_t* vertexData = new uint8_t[mesh.m_triangles.size() * 3 * stride];
- uint16_t* indexData = new uint16_t[mesh.m_triangles.size() * 3];
- int32_t numVertices = 0;
- int32_t numIndices = 0;
- int32_t writtenPrimitives = 0;
- int32_t writtenVertices = 0;
- int32_t writtenIndices = 0;
- uint8_t* vertices = vertexData;
- uint16_t* indices = indexData;
- const uint32_t tableSize = 65536 * 2;
- const uint32_t hashmod = tableSize - 1;
- uint32_t* table = new uint32_t[tableSize];
- bx::memSet(table, 0xff, tableSize * sizeof(uint32_t));
- stl::string material = mesh.m_groups.empty() ? "" : mesh.m_groups.begin()->m_material;
- PrimitiveArray primitives;
- bx::FileWriter writer;
- if (!bx::open(&writer, outFilePath) )
- {
- bx::printf("Unable to open output file '%s'.", outFilePath);
- exit(bx::kExitFailure);
- }
- Primitive prim;
- prim.m_startVertex = 0;
- prim.m_startIndex = 0;
- uint32_t positionOffset = layout.getOffset(bgfx::Attrib::Position);
- uint32_t color0Offset = layout.getOffset(bgfx::Attrib::Color0);
- Group sentinelGroup;
- sentinelGroup.m_startTriangle = 0;
- sentinelGroup.m_numTriangles = UINT32_MAX;
- mesh.m_groups.push_back(sentinelGroup);
- uint32_t ii = 0;
- for (GroupArray::const_iterator groupIt = mesh.m_groups.begin(); groupIt != mesh.m_groups.end(); ++groupIt, ++ii)
- {
- bool sentinel = groupIt->m_startTriangle == 0 && groupIt->m_numTriangles == UINT32_MAX;
- for (uint32_t tri = groupIt->m_startTriangle, end = tri + groupIt->m_numTriangles; tri < end; ++tri)
- {
- if (0 != bx::strCmp(material.c_str(), groupIt->m_material.c_str() )
- || sentinel
- || 65533 <= numVertices)
- {
- prim.m_numVertices = numVertices - prim.m_startVertex;
- prim.m_numIndices = numIndices - prim.m_startIndex;
- if (0 < prim.m_numVertices)
- {
- primitives.push_back(prim);
- }
- if (hasTangent)
- {
- calcTangents(vertexData, uint16_t(numVertices), layout, indexData, numIndices);
- }
- triReorderElapsed -= bx::getHPCounter();
- for (PrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt)
- {
- const Primitive& prim1 = *primIt;
- optimizeVertexCache(indexData + prim1.m_startIndex, prim1.m_numIndices, numVertices);
- }
- numVertices = optimizeVertexFetch(indexData, numIndices, vertexData, numVertices, uint16_t(stride));
- triReorderElapsed += bx::getHPCounter();
- if ( numVertices > 0 && numIndices > 0 )
- {
- write(&writer
- , vertexData
- , numVertices
- , layout
- , indexData
- , numIndices
- , compress
- , material
- , primitives
- );
- }
- primitives.clear();
- bx::memSet(table, 0xff, tableSize * sizeof(uint32_t));
- ++writtenPrimitives;
- writtenVertices += numVertices;
- writtenIndices += numIndices;
- vertices = vertexData;
- indices = indexData;
- numVertices = 0;
- numIndices = 0;
- prim.m_startVertex = 0;
- prim.m_startIndex = 0;
- material = groupIt->m_material;
- if (sentinel)
- break;
- }
- TriIndices& triangle = mesh.m_triangles[tri];
- for (uint32_t edge = 0; edge < 3; ++edge)
- {
- Index3& index = triangle.m_index[edge];
- float* position = (float*)(vertices + positionOffset);
- bx::memCopy(position, &mesh.m_positions[index.m_position], 3*sizeof(float) );
- if (hasColor)
- {
- uint32_t* color0 = (uint32_t*)(vertices + color0Offset);
- *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff);
- }
- if (hasBc)
- {
- const float bc[4] =
- {
- (index.m_vbc == 0) ? 1.0f : 0.0f,
- (index.m_vbc == 1) ? 1.0f : 0.0f,
- (index.m_vbc == 2) ? 1.0f : 0.0f,
- 0.0f
- };
- bgfx::vertexPack(bc, true, bgfx::Attrib::Color1, layout, vertices);
- }
- if (hasTexcoord)
- {
- float uv[2];
- bx::memCopy(uv, &mesh.m_texcoords[index.m_texcoord == -1 ? 0 : index.m_texcoord], 2*sizeof(float) );
- if (flipV)
- {
- uv[1] = -uv[1];
- }
- bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, layout, vertices);
- }
- if (hasNormal)
- {
- float normal[4];
- bx::store(normal, bx::normalize(bx::load<bx::Vec3>(&mesh.m_normals[index.m_normal == -1 ? 0 : index.m_normal]) ) );
- normal[3] = 0.0f;
- bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, layout, vertices);
- }
- uint32_t hash = bx::hash<bx::HashMurmur2A>(vertices, stride);
- size_t bucket = hash & hashmod;
- uint32_t vertexIndex = UINT32_MAX;
- for (size_t probe = 0; probe <= hashmod; ++probe)
- {
- uint32_t& item = table[bucket];
- if (item == ~0u)
- {
- vertices += stride;
- item = numVertices++;
- vertexIndex = item;
- break;
- }
- if (0 == bx::memCmp(vertexData + item * stride, vertices, stride))
- {
- vertexIndex = item;
- break;
- }
- bucket = (bucket + probe + 1) & hashmod;
- }
- if ( vertexIndex == UINT32_MAX )
- {
- bx::printf("hash table insert failed");
- exit(bx::kExitFailure);
- }
- *indices++ = (uint16_t)vertexIndex;
- ++numIndices;
- }
- }
- prim.m_numVertices = numVertices - prim.m_startVertex;
- if (0 < prim.m_numVertices)
- {
- prim.m_numIndices = numIndices - prim.m_startIndex;
- prim.m_name = groupIt->m_name;
- primitives.push_back(prim);
- prim.m_startVertex = numVertices;
- prim.m_startIndex = numIndices;
- }
- BX_TRACE("%3d: s %5d, n %5d, %s\n"
- , ii
- , groupIt->m_startTriangle
- , groupIt->m_numTriangles
- , groupIt->m_material.c_str()
- );
- }
- BX_CHECK(0 == primitives.size(), "Not all primitives are written");
- bx::printf("size: %d\n", uint32_t(bx::seek(&writer) ) );
- bx::close(&writer);
- delete [] table;
- delete [] indexData;
- delete [] vertexData;
- now = bx::getHPCounter();
- convertElapsed += now;
- bx::printf("parse %f [s]\ntri reorder %f [s]\nconvert %f [s]\ng %d, p %d, v %d, i %d\n"
- , double(parseElapsed)/bx::getHPFrequency()
- , double(triReorderElapsed)/bx::getHPFrequency()
- , double(convertElapsed)/bx::getHPFrequency()
- , uint32_t(mesh.m_groups.size()-1)
- , writtenPrimitives
- , writtenVertices
- , writtenIndices
- );
- return bx::kExitSuccess;
- }
|