mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-12-01 03:47:07 -05:00
Added vertex pack/unpack support.
This commit is contained in:
parent
d4cd0ea4fa
commit
446686b48f
11 changed files with 351 additions and 192 deletions
|
@ -42,21 +42,6 @@ uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w)
|
||||||
return un.ui32;
|
return un.ui32;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unpackUint32(uint8_t _result[4], uint32_t _packed)
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t ui32;
|
|
||||||
uint8_t arr[4];
|
|
||||||
} un;
|
|
||||||
|
|
||||||
un.ui32 = _packed;
|
|
||||||
_result[0] = un.arr[0];
|
|
||||||
_result[1] = un.arr[1];
|
|
||||||
_result[2] = un.arr[2];
|
|
||||||
_result[3] = un.arr[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
|
uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
|
||||||
{
|
{
|
||||||
const uint8_t xx = uint8_t(_x*127.0f + 128.0f);
|
const uint8_t xx = uint8_t(_x*127.0f + 128.0f);
|
||||||
|
@ -66,16 +51,6 @@ uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
|
||||||
return packUint32(xx, yy, zz, ww);
|
return packUint32(xx, yy, zz, ww);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unpackF4u(float _result[4], uint32_t _packed)
|
|
||||||
{
|
|
||||||
uint8_t unpacked[4];
|
|
||||||
unpackUint32(unpacked, _packed);
|
|
||||||
_result[0] = (float(unpacked[0]) - 128.0f)/127.0f;
|
|
||||||
_result[1] = (float(unpacked[1]) - 128.0f)/127.0f;
|
|
||||||
_result[2] = (float(unpacked[2]) - 128.0f)/127.0f;
|
|
||||||
_result[3] = (float(unpacked[3]) - 128.0f)/127.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PosNormalTangentTexcoordVertex s_cubeVertices[24] =
|
static PosNormalTangentTexcoordVertex s_cubeVertices[24] =
|
||||||
{
|
{
|
||||||
{-1.0f, 1.0f, 1.0f, packF4u( 0.0f, 0.0f, 1.0f), 0, 0.0f, 0.0f },
|
{-1.0f, 1.0f, 1.0f, packF4u( 0.0f, 0.0f, 1.0f), 0, 0.0f, 0.0f },
|
||||||
|
@ -172,18 +147,42 @@ static const bgfx::Memory* loadTexture(const char* _name)
|
||||||
return load(filePath);
|
return load(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ty>
|
void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl, const uint16_t* _indices, uint32_t _numIndices)
|
||||||
void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices, uint16_t _numVertices)
|
|
||||||
{
|
{
|
||||||
|
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];
|
float* tangents = new float[6*_numVertices];
|
||||||
memset(tangents, 0, 6*_numVertices*sizeof(float) );
|
memset(tangents, 0, 6*_numVertices*sizeof(float) );
|
||||||
|
|
||||||
|
PosTexcoord v0;
|
||||||
|
PosTexcoord v1;
|
||||||
|
PosTexcoord v2;
|
||||||
|
|
||||||
for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii)
|
for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii)
|
||||||
{
|
{
|
||||||
const uint16_t* indices = &_indices[ii*3];
|
const uint16_t* indices = &_indices[ii*3];
|
||||||
const Ty& v0 = _vertices[indices[0] ];
|
uint32_t i0 = indices[0];
|
||||||
const Ty& v1 = _vertices[indices[1] ];
|
uint32_t i1 = indices[1];
|
||||||
const Ty& v2 = _vertices[indices[2] ];
|
uint32_t i2 = indices[2];
|
||||||
|
|
||||||
|
bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _decl, _vertices, i0);
|
||||||
|
bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i0);
|
||||||
|
|
||||||
|
bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _decl, _vertices, i1);
|
||||||
|
bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i1);
|
||||||
|
|
||||||
|
bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _decl, _vertices, i2);
|
||||||
|
bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i2);
|
||||||
|
|
||||||
const float bax = v1.m_x - v0.m_x;
|
const float bax = v1.m_x - v0.m_x;
|
||||||
const float bay = v1.m_y - v0.m_y;
|
const float bay = v1.m_y - v0.m_y;
|
||||||
|
@ -224,12 +223,11 @@ void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices,
|
||||||
|
|
||||||
for (uint32_t ii = 0; ii < _numVertices; ++ii)
|
for (uint32_t ii = 0; ii < _numVertices; ++ii)
|
||||||
{
|
{
|
||||||
Ty& v0 = _vertices[ii];
|
|
||||||
const float* tanu = &tangents[ii*6];
|
const float* tanu = &tangents[ii*6];
|
||||||
const float* tanv = &tangents[ii*6 + 3];
|
const float* tanv = &tangents[ii*6 + 3];
|
||||||
|
|
||||||
float normal[4];
|
float normal[4];
|
||||||
unpackF4u(normal, v0.m_normal);
|
bgfx::vertexUnpack(normal, bgfx::Attrib::Normal, _decl, _vertices, ii);
|
||||||
float ndt = vec3Dot(normal, tanu);
|
float ndt = vec3Dot(normal, tanu);
|
||||||
|
|
||||||
float nxt[3];
|
float nxt[3];
|
||||||
|
@ -240,13 +238,13 @@ void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices,
|
||||||
tmp[1] = tanu[1] - normal[1] * ndt;
|
tmp[1] = tanu[1] - normal[1] * ndt;
|
||||||
tmp[2] = tanu[2] - normal[2] * ndt;
|
tmp[2] = tanu[2] - normal[2] * ndt;
|
||||||
|
|
||||||
float tangent[3];
|
float tangent[4];
|
||||||
vec3Norm(tangent, tmp);
|
vec3Norm(tangent, tmp);
|
||||||
|
|
||||||
float tw = vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
|
tangent[3] = vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
|
||||||
v0.m_tangent = packF4u(tangent[0], tangent[1], tangent[2], tw);
|
bgfx::vertexPack(tangent, true, bgfx::Attrib::Tangent, _decl, _vertices, ii);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int _main_(int _argc, char** _argv)
|
int _main_(int _argc, char** _argv)
|
||||||
{
|
{
|
||||||
|
@ -293,14 +291,14 @@ int _main_(int _argc, char** _argv)
|
||||||
// Create vertex stream declaration.
|
// Create vertex stream declaration.
|
||||||
s_PosNormalTangentTexcoordDecl.begin();
|
s_PosNormalTangentTexcoordDecl.begin();
|
||||||
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
|
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float);
|
||||||
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true);
|
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true);
|
||||||
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true);
|
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true);
|
||||||
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
|
s_PosNormalTangentTexcoordDecl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float);
|
||||||
s_PosNormalTangentTexcoordDecl.end();
|
s_PosNormalTangentTexcoordDecl.end();
|
||||||
|
|
||||||
const bgfx::Memory* mem;
|
const bgfx::Memory* mem;
|
||||||
|
|
||||||
calcTangents(s_cubeIndices, countof(s_cubeIndices), s_cubeVertices, countof(s_cubeVertices) );
|
calcTangents(s_cubeVertices, countof(s_cubeVertices), s_PosNormalTangentTexcoordDecl, s_cubeIndices, countof(s_cubeIndices) );
|
||||||
|
|
||||||
// Create static vertex buffer.
|
// Create static vertex buffer.
|
||||||
mem = bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) );
|
mem = bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) );
|
||||||
|
|
|
@ -329,7 +329,10 @@ struct BgfxCallback : public bgfx::CallbackI
|
||||||
|
|
||||||
virtual void fatal(bgfx::Fatal::Enum _code, const char* _str) BX_OVERRIDE
|
virtual void fatal(bgfx::Fatal::Enum _code, const char* _str) BX_OVERRIDE
|
||||||
{
|
{
|
||||||
|
// Something unexpected happened, inform user and bail out.
|
||||||
dbgPrintf("Fatal error: 0x%08x: %s", _code, _str);
|
dbgPrintf("Fatal error: 0x%08x: %s", _code, _str);
|
||||||
|
|
||||||
|
// Must terminate, continuing will cause crash anyway.
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,14 +340,18 @@ struct BgfxCallback : public bgfx::CallbackI
|
||||||
{
|
{
|
||||||
char filePath[256];
|
char filePath[256];
|
||||||
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
|
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
|
||||||
|
|
||||||
|
// Use cache id as filename.
|
||||||
FILE* file = fopen(filePath, "rb");
|
FILE* file = fopen(filePath, "rb");
|
||||||
if (NULL != file)
|
if (NULL != file)
|
||||||
{
|
{
|
||||||
uint32_t size = fsize(file);
|
uint32_t size = fsize(file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
// Return size of shader file.
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return 0 if shader is not found.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,14 +359,20 @@ struct BgfxCallback : public bgfx::CallbackI
|
||||||
{
|
{
|
||||||
char filePath[256];
|
char filePath[256];
|
||||||
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
|
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
|
||||||
|
|
||||||
|
// Use cache id as filename.
|
||||||
FILE* file = fopen(filePath, "rb");
|
FILE* file = fopen(filePath, "rb");
|
||||||
if (NULL != file)
|
if (NULL != file)
|
||||||
{
|
{
|
||||||
|
// Read shader.
|
||||||
size_t result = fread(_data, 1, _size, file);
|
size_t result = fread(_data, 1, _size, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
|
// Make sure that read size matches requested size.
|
||||||
return result == _size;
|
return result == _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shader is not found in cache, needs to be rebuilt.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,9 +381,11 @@ struct BgfxCallback : public bgfx::CallbackI
|
||||||
char filePath[256];
|
char filePath[256];
|
||||||
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
|
bx::snprintf(filePath, sizeof(filePath), "%016" PRIx64, _id);
|
||||||
|
|
||||||
|
// Use cache id as filename.
|
||||||
FILE* file = fopen(filePath, "wb");
|
FILE* file = fopen(filePath, "wb");
|
||||||
if (NULL != file)
|
if (NULL != file)
|
||||||
{
|
{
|
||||||
|
// Write shader to cache location.
|
||||||
fwrite(_data, 1, _size, file);
|
fwrite(_data, 1, _size, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
@ -378,6 +393,7 @@ struct BgfxCallback : public bgfx::CallbackI
|
||||||
|
|
||||||
virtual void screenShot(const char* _filePath, uint32_t _width, uint32_t _height, uint32_t _pitch, const void* _data, uint32_t /*_size*/, bool _yflip) BX_OVERRIDE
|
virtual void screenShot(const char* _filePath, uint32_t _width, uint32_t _height, uint32_t _pitch, const void* _data, uint32_t /*_size*/, bool _yflip) BX_OVERRIDE
|
||||||
{
|
{
|
||||||
|
// Save screen shot as TGA.
|
||||||
saveTga(_filePath, _width, _height, _pitch, _data, false, _yflip);
|
saveTga(_filePath, _width, _height, _pitch, _data, false, _yflip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,7 +572,7 @@ int _main_(int _argc, char** _argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take screenshot at frame 150.
|
// Take screen shot at frame 150.
|
||||||
if (150 == frame)
|
if (150 == frame)
|
||||||
{
|
{
|
||||||
bgfx::saveScreenShot("frame150.tga");
|
bgfx::saveScreenShot("frame150.tga");
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -386,8 +386,8 @@ namespace bgfx
|
||||||
virtual void captureFrame(const void* _data, uint32_t _size) = 0;
|
virtual void captureFrame(const void* _data, uint32_t _size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline CallbackI::~CallbackI()
|
inline CallbackI::~CallbackI()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Memory
|
struct Memory
|
||||||
|
@ -442,10 +442,10 @@ namespace bgfx
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
/// Add attribute to VertexDecl. Note: Must be called between begin/end.
|
/// Add attribute to VertexDecl. Note: Must be called between begin/end.
|
||||||
void add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized = false);
|
void add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized = false, bool _asInt = false);
|
||||||
|
|
||||||
/// Decode attribute.
|
/// Decode attribute.
|
||||||
void decode(Attrib::Enum _attrib, uint8_t& _num, AttribType::Enum& _type, bool& _normalized) const;
|
void decode(Attrib::Enum _attrib, uint8_t& _num, AttribType::Enum& _type, bool& _normalized, bool& _asInt) const;
|
||||||
|
|
||||||
/// Returns true if VertexDecl contains attribute.
|
/// Returns true if VertexDecl contains attribute.
|
||||||
bool has(Attrib::Enum _attrib) const { return 0xff != m_attributes[_attrib]; }
|
bool has(Attrib::Enum _attrib) const { return 0xff != m_attributes[_attrib]; }
|
||||||
|
@ -465,6 +465,12 @@ namespace bgfx
|
||||||
uint8_t m_attributes[Attrib::Count];
|
uint8_t m_attributes[Attrib::Count];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Pack vec4 into vertex stream format.
|
||||||
|
void vertexPack(const float _input[4], bool _inputNormalized, Attrib::Enum _attr, const VertexDecl& _decl, void* _data, uint32_t _index = 0);
|
||||||
|
|
||||||
|
/// Unpack vec4 from vertex stream format.
|
||||||
|
void vertexUnpack(float _output[4], Attrib::Enum _attr, const VertexDecl& _decl, const void* _data, uint32_t _index = 0);
|
||||||
|
|
||||||
/// Returns renderer backend API type.
|
/// Returns renderer backend API type.
|
||||||
RendererType::Enum getRendererType();
|
RendererType::Enum getRendererType();
|
||||||
|
|
||||||
|
|
|
@ -229,7 +229,8 @@ namespace bgfx
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
AttribType::Enum type;
|
AttribType::Enum type;
|
||||||
bool normalized;
|
bool normalized;
|
||||||
_decl.decode(Attrib::Enum(attr), num, type, normalized);
|
bool asInt;
|
||||||
|
_decl.decode(Attrib::Enum(attr), num, type, normalized, asInt);
|
||||||
elem->Format = s_attribType[type][num-1][normalized];
|
elem->Format = s_attribType[type][num-1][normalized];
|
||||||
elem->AlignedByteOffset = _decl.m_offset[attr];
|
elem->AlignedByteOffset = _decl.m_offset[attr];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1045,7 +1045,8 @@ namespace bgfx
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
AttribType::Enum type;
|
AttribType::Enum type;
|
||||||
bool normalized;
|
bool normalized;
|
||||||
_decl.decode(Attrib::Enum(attr), num, type, normalized);
|
bool asInt;
|
||||||
|
_decl.decode(Attrib::Enum(attr), num, type, normalized, asInt);
|
||||||
|
|
||||||
memcpy(elem, &s_attrib[attr], sizeof(D3DVERTEXELEMENT9) );
|
memcpy(elem, &s_attrib[attr], sizeof(D3DVERTEXELEMENT9) );
|
||||||
|
|
||||||
|
|
|
@ -1269,7 +1269,8 @@ namespace bgfx
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
AttribType::Enum type;
|
AttribType::Enum type;
|
||||||
bool normalized;
|
bool normalized;
|
||||||
_vertexDecl.decode(attr, num, type, normalized);
|
bool asInt;
|
||||||
|
_vertexDecl.decode(attr, num, type, normalized, asInt);
|
||||||
|
|
||||||
if (-1 != loc
|
if (-1 != loc
|
||||||
&& 0xff != _vertexDecl.m_attributes[attr])
|
&& 0xff != _vertexDecl.m_attributes[attr])
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <bx/hash.h>
|
#include <bx/hash.h>
|
||||||
|
#include <bx/uint32_t.h>
|
||||||
|
|
||||||
#include "vertexdecl.h"
|
#include "vertexdecl.h"
|
||||||
|
|
||||||
|
@ -65,23 +66,25 @@ namespace bgfx
|
||||||
m_hash = bx::hashMurmur2A(m_attributes, sizeof(m_attributes) );
|
m_hash = bx::hashMurmur2A(m_attributes, sizeof(m_attributes) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexDecl::add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized)
|
void VertexDecl::add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized, bool _asInt)
|
||||||
{
|
{
|
||||||
const uint8_t encoded_norm = (_normalized&1)<<6;
|
const uint8_t encodedNorm = (_normalized&1)<<6;
|
||||||
const uint8_t encoded_type = (_type&3)<<3;
|
const uint8_t encodedType = (_type&3)<<3;
|
||||||
const uint8_t encoded_num = (_num-1)&3;
|
const uint8_t encodedNum = (_num-1)&3;
|
||||||
|
const uint8_t encodeAsInt = (_asInt&(!!"\x1\x1\x0\x0"[_type]) )<<7;
|
||||||
|
|
||||||
m_attributes[_attrib] = encoded_norm|encoded_type|encoded_num;
|
m_attributes[_attrib] = encodedNorm|encodedType|encodedNum|encodeAsInt;
|
||||||
m_offset[_attrib] = m_stride;
|
m_offset[_attrib] = m_stride;
|
||||||
m_stride += (*s_attribTypeSize[m_hash])[_type][_num-1];
|
m_stride += (*s_attribTypeSize[m_hash])[_type][_num-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexDecl::decode(Attrib::Enum _attrib, uint8_t& _num, AttribType::Enum& _type, bool& _normalized) const
|
void VertexDecl::decode(Attrib::Enum _attrib, uint8_t& _num, AttribType::Enum& _type, bool& _normalized, bool& _asInt) const
|
||||||
{
|
{
|
||||||
uint8_t val = m_attributes[_attrib];
|
uint8_t val = m_attributes[_attrib];
|
||||||
_num = (val&3)+1;
|
_num = (val&3)+1;
|
||||||
_type = AttribType::Enum((val>>3)&3);
|
_type = AttribType::Enum((val>>3)&3);
|
||||||
_normalized = !!(val&(1<<6) );
|
_normalized = !!(val&(1<<6) );
|
||||||
|
_asInt = !!(val&(1<<7) );
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* getAttribName(Attrib::Enum _attr)
|
const char* getAttribName(Attrib::Enum _attr)
|
||||||
|
@ -123,14 +126,16 @@ namespace bgfx
|
||||||
uint8_t num;
|
uint8_t num;
|
||||||
AttribType::Enum type;
|
AttribType::Enum type;
|
||||||
bool normalized;
|
bool normalized;
|
||||||
_decl.decode(Attrib::Enum(attr), num, type, normalized);
|
bool asInt;
|
||||||
|
_decl.decode(Attrib::Enum(attr), num, type, normalized, asInt);
|
||||||
|
|
||||||
BX_TRACE("\tattr %d - %s, num %d, type %d, norm %d, offset %d"
|
BX_TRACE("\tattr %d - %s, num %d, type %d, norm %d, asint %d, offset %d"
|
||||||
, attr
|
, attr
|
||||||
, getAttribName(Attrib::Enum(attr) )
|
, getAttribName(Attrib::Enum(attr) )
|
||||||
, num
|
, num
|
||||||
, type
|
, type
|
||||||
, normalized
|
, normalized
|
||||||
|
, asInt
|
||||||
, _decl.m_offset[attr]
|
, _decl.m_offset[attr]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -140,4 +145,218 @@ namespace bgfx
|
||||||
#endif // BGFX_CONFIG_DEBUG
|
#endif // BGFX_CONFIG_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vertexPack(const float _input[4], bool _inputNormalized, Attrib::Enum _attr, const VertexDecl& _decl, void* _data, uint32_t _index)
|
||||||
|
{
|
||||||
|
if (!_decl.has(_attr) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t stride = _decl.getStride();
|
||||||
|
uint8_t* data = (uint8_t*)_data + _index*stride + _decl.getOffset(_attr);
|
||||||
|
|
||||||
|
uint8_t num;
|
||||||
|
AttribType::Enum type;
|
||||||
|
bool normalized;
|
||||||
|
bool asInt;
|
||||||
|
_decl.decode(_attr, num, type, normalized, asInt);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case AttribType::Uint8:
|
||||||
|
{
|
||||||
|
uint8_t* packed = (uint8_t*)data;
|
||||||
|
if (_inputNormalized)
|
||||||
|
{
|
||||||
|
if (asInt)
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f);
|
||||||
|
case 3: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f);
|
||||||
|
case 2: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f);
|
||||||
|
case 1: *packed++ = uint8_t(*_input++ * 127.0f + 128.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *packed++ = uint8_t(*_input++ * 255.0f);
|
||||||
|
case 3: *packed++ = uint8_t(*_input++ * 255.0f);
|
||||||
|
case 2: *packed++ = uint8_t(*_input++ * 255.0f);
|
||||||
|
case 1: *packed++ = uint8_t(*_input++ * 255.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *packed++ = uint8_t(*_input++);
|
||||||
|
case 3: *packed++ = uint8_t(*_input++);
|
||||||
|
case 2: *packed++ = uint8_t(*_input++);
|
||||||
|
case 1: *packed++ = uint8_t(*_input++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AttribType::Uint16:
|
||||||
|
{
|
||||||
|
uint16_t* packed = (uint16_t*)data;
|
||||||
|
if (_inputNormalized)
|
||||||
|
{
|
||||||
|
if (asInt)
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *packed++ = uint16_t(*_input++ * 32767.0f + 32768.0f);
|
||||||
|
case 3: *packed++ = uint16_t(*_input++ * 32767.0f + 32768.0f);
|
||||||
|
case 2: *packed++ = uint16_t(*_input++ * 32767.0f + 32768.0f);
|
||||||
|
case 1: *packed++ = uint16_t(*_input++ * 32767.0f + 32768.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *packed++ = uint16_t(*_input++ * 65535.0f);
|
||||||
|
case 3: *packed++ = uint16_t(*_input++ * 65535.0f);
|
||||||
|
case 2: *packed++ = uint16_t(*_input++ * 65535.0f);
|
||||||
|
case 1: *packed++ = uint16_t(*_input++ * 65535.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *packed++ = uint16_t(*_input++);
|
||||||
|
case 3: *packed++ = uint16_t(*_input++);
|
||||||
|
case 2: *packed++ = uint16_t(*_input++);
|
||||||
|
case 1: *packed++ = uint16_t(*_input++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AttribType::Half:
|
||||||
|
{
|
||||||
|
uint16_t* packed = (uint16_t*)data;
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *packed++ = bx::halfFromFloat(*_input++);
|
||||||
|
case 3: *packed++ = bx::halfFromFloat(*_input++);
|
||||||
|
case 2: *packed++ = bx::halfFromFloat(*_input++);
|
||||||
|
case 1: *packed++ = bx::halfFromFloat(*_input++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AttribType::Float:
|
||||||
|
memcpy(data, _input, num*sizeof(float) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vertexUnpack(float _output[4], Attrib::Enum _attr, const VertexDecl& _decl, const void* _data, uint32_t _index)
|
||||||
|
{
|
||||||
|
if (!_decl.has(_attr) )
|
||||||
|
{
|
||||||
|
memset(_output, 0, 4*sizeof(float) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t stride = _decl.getStride();
|
||||||
|
uint8_t* data = (uint8_t*)_data + _index*stride + _decl.getOffset(_attr);
|
||||||
|
|
||||||
|
uint8_t num;
|
||||||
|
AttribType::Enum type;
|
||||||
|
bool normalized;
|
||||||
|
bool asInt;
|
||||||
|
_decl.decode(_attr, num, type, normalized, asInt);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case AttribType::Uint8:
|
||||||
|
{
|
||||||
|
uint8_t* packed = (uint8_t*)data;
|
||||||
|
if (asInt)
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f;
|
||||||
|
case 3: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f;
|
||||||
|
case 2: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f;
|
||||||
|
case 1: *_output++ = (float(*packed++) - 128.0f)*1.0f/127.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *_output++ = float(*packed++)*1.0f/255.0f;
|
||||||
|
case 3: *_output++ = float(*packed++)*1.0f/255.0f;
|
||||||
|
case 2: *_output++ = float(*packed++)*1.0f/255.0f;
|
||||||
|
case 1: *_output++ = float(*packed++)*1.0f/255.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AttribType::Uint16:
|
||||||
|
{
|
||||||
|
uint16_t* packed = (uint16_t*)data;
|
||||||
|
if (asInt)
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *_output++ = (float(*packed++) - 32768.0f)*1.0f/32767.0f;
|
||||||
|
case 3: *_output++ = (float(*packed++) - 32768.0f)*1.0f/32767.0f;
|
||||||
|
case 2: *_output++ = (float(*packed++) - 32768.0f)*1.0f/32767.0f;
|
||||||
|
case 1: *_output++ = (float(*packed++) - 32768.0f)*1.0f/32767.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *_output++ = float(*packed++)*1.0f/65535.0f;
|
||||||
|
case 3: *_output++ = float(*packed++)*1.0f/65535.0f;
|
||||||
|
case 2: *_output++ = float(*packed++)*1.0f/65535.0f;
|
||||||
|
case 1: *_output++ = float(*packed++)*1.0f/65535.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AttribType::Half:
|
||||||
|
{
|
||||||
|
uint16_t* packed = (uint16_t*)data;
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
default: *_output++ = bx::halfToFloat(*packed++);
|
||||||
|
case 3: *_output++ = bx::halfToFloat(*packed++);
|
||||||
|
case 2: *_output++ = bx::halfToFloat(*packed++);
|
||||||
|
case 1: *_output++ = bx::halfToFloat(*packed++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AttribType::Float:
|
||||||
|
memcpy(_output, data, num*sizeof(float) );
|
||||||
|
_output += num;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 1: *_output++ = 0.0f;
|
||||||
|
case 2: *_output++ = 0.0f;
|
||||||
|
case 3: *_output++ = 0.0f;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace bgfx
|
} // namespace bgfx
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
|
|
||||||
namespace bgfx
|
namespace bgfx
|
||||||
{
|
{
|
||||||
|
/// Returns attribute name.
|
||||||
const char* getAttribName(Attrib::Enum _attr);
|
const char* getAttribName(Attrib::Enum _attr);
|
||||||
|
|
||||||
|
/// Dump vertex declaration into debug output.
|
||||||
void dump(const VertexDecl& _decl);
|
void dump(const VertexDecl& _decl);
|
||||||
|
|
||||||
} // namespace bgfx
|
} // namespace bgfx
|
||||||
|
|
|
@ -133,95 +133,42 @@ void triangleReorder(uint16_t* _indices, uint32_t _numIndices, uint32_t _numVert
|
||||||
delete [] newIndexList;
|
delete [] newIndexList;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t packUint32(uint8_t _x, uint8_t _y, uint8_t _z, uint8_t _w)
|
void calcTangents(void* _vertices, uint16_t _numVertices, bgfx::VertexDecl _decl, const uint16_t* _indices, uint32_t _numIndices)
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t ui32;
|
|
||||||
uint8_t arr[4];
|
|
||||||
} un;
|
|
||||||
|
|
||||||
un.arr[0] = _x;
|
|
||||||
un.arr[1] = _y;
|
|
||||||
un.arr[2] = _z;
|
|
||||||
un.arr[3] = _w;
|
|
||||||
|
|
||||||
return un.ui32;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unpackUint32(uint8_t _result[4], uint32_t _packed)
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t ui32;
|
|
||||||
uint8_t arr[4];
|
|
||||||
} un;
|
|
||||||
|
|
||||||
un.ui32 = _packed;
|
|
||||||
_result[0] = un.arr[0];
|
|
||||||
_result[1] = un.arr[1];
|
|
||||||
_result[2] = un.arr[2];
|
|
||||||
_result[3] = un.arr[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t packF4u(float _x, float _y = 0.0f, float _z = 0.0f, float _w = 0.0f)
|
|
||||||
{
|
|
||||||
const uint8_t xx = uint8_t(_x*127.0f + 128.0f);
|
|
||||||
const uint8_t yy = uint8_t(_y*127.0f + 128.0f);
|
|
||||||
const uint8_t zz = uint8_t(_z*127.0f + 128.0f);
|
|
||||||
const uint8_t ww = uint8_t(_w*127.0f + 128.0f);
|
|
||||||
return packUint32(xx, yy, zz, ww);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unpackF4u(float _result[4], uint32_t _packed)
|
|
||||||
{
|
|
||||||
uint8_t unpacked[4];
|
|
||||||
unpackUint32(unpacked, _packed);
|
|
||||||
_result[0] = (float(unpacked[0]) - 128.0f)/127.0f;
|
|
||||||
_result[1] = (float(unpacked[1]) - 128.0f)/127.0f;
|
|
||||||
_result[2] = (float(unpacked[2]) - 128.0f)/127.0f;
|
|
||||||
_result[3] = (float(unpacked[3]) - 128.0f)/127.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t packF2h(float _x, float _y)
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t ui32;
|
|
||||||
uint16_t arr[2];
|
|
||||||
} un;
|
|
||||||
|
|
||||||
un.arr[0] = bx::halfFromFloat(_x);
|
|
||||||
un.arr[1] = bx::halfFromFloat(_y);
|
|
||||||
|
|
||||||
return un.ui32;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unpackF2h(float _result[2], uint32_t _packed)
|
|
||||||
{
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint32_t ui32;
|
|
||||||
uint16_t arr[2];
|
|
||||||
} un;
|
|
||||||
|
|
||||||
un.ui32 = _packed;
|
|
||||||
_result[0] = bx::halfToFloat(un.arr[0]);
|
|
||||||
_result[1] = bx::halfToFloat(un.arr[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ty>
|
|
||||||
void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices, uint16_t _numVertices)
|
|
||||||
{
|
{
|
||||||
|
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];
|
float* tangents = new float[6*_numVertices];
|
||||||
memset(tangents, 0, 6*_numVertices*sizeof(float) );
|
memset(tangents, 0, 6*_numVertices*sizeof(float) );
|
||||||
|
|
||||||
|
PosTexcoord v0;
|
||||||
|
PosTexcoord v1;
|
||||||
|
PosTexcoord v2;
|
||||||
|
|
||||||
for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii)
|
for (uint32_t ii = 0, num = _numIndices/3; ii < num; ++ii)
|
||||||
{
|
{
|
||||||
const uint16_t* indices = &_indices[ii*3];
|
const uint16_t* indices = &_indices[ii*3];
|
||||||
const Ty& v0 = _vertices[indices[0] ];
|
uint32_t i0 = indices[0];
|
||||||
const Ty& v1 = _vertices[indices[1] ];
|
uint32_t i1 = indices[1];
|
||||||
const Ty& v2 = _vertices[indices[2] ];
|
uint32_t i2 = indices[2];
|
||||||
|
|
||||||
|
bgfx::vertexUnpack(&v0.m_x, bgfx::Attrib::Position, _decl, _vertices, i0);
|
||||||
|
bgfx::vertexUnpack(&v0.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i0);
|
||||||
|
|
||||||
|
bgfx::vertexUnpack(&v1.m_x, bgfx::Attrib::Position, _decl, _vertices, i1);
|
||||||
|
bgfx::vertexUnpack(&v1.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i1);
|
||||||
|
|
||||||
|
bgfx::vertexUnpack(&v2.m_x, bgfx::Attrib::Position, _decl, _vertices, i2);
|
||||||
|
bgfx::vertexUnpack(&v2.m_u, bgfx::Attrib::TexCoord0, _decl, _vertices, i2);
|
||||||
|
|
||||||
const float bax = v1.m_x - v0.m_x;
|
const float bax = v1.m_x - v0.m_x;
|
||||||
const float bay = v1.m_y - v0.m_y;
|
const float bay = v1.m_y - v0.m_y;
|
||||||
|
@ -262,12 +209,11 @@ void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices,
|
||||||
|
|
||||||
for (uint32_t ii = 0; ii < _numVertices; ++ii)
|
for (uint32_t ii = 0; ii < _numVertices; ++ii)
|
||||||
{
|
{
|
||||||
Ty& v0 = _vertices[ii];
|
|
||||||
const float* tanu = &tangents[ii*6];
|
const float* tanu = &tangents[ii*6];
|
||||||
const float* tanv = &tangents[ii*6 + 3];
|
const float* tanv = &tangents[ii*6 + 3];
|
||||||
|
|
||||||
float normal[4];
|
float normal[4];
|
||||||
unpackF4u(normal, v0.m_normal);
|
bgfx::vertexUnpack(normal, bgfx::Attrib::Normal, _decl, _vertices, ii);
|
||||||
float ndt = vec3Dot(normal, tanu);
|
float ndt = vec3Dot(normal, tanu);
|
||||||
|
|
||||||
float nxt[3];
|
float nxt[3];
|
||||||
|
@ -278,11 +224,11 @@ void calcTangents(const uint16_t* _indices, uint32_t _numIndices, Ty* _vertices,
|
||||||
tmp[1] = tanu[1] - normal[1] * ndt;
|
tmp[1] = tanu[1] - normal[1] * ndt;
|
||||||
tmp[2] = tanu[2] - normal[2] * ndt;
|
tmp[2] = tanu[2] - normal[2] * ndt;
|
||||||
|
|
||||||
float tangent[3];
|
float tangent[4];
|
||||||
vec3Norm(tangent, tmp);
|
vec3Norm(tangent, tmp);
|
||||||
|
|
||||||
float tw = vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
|
tangent[3] = vec3Dot(nxt, tanv) < 0.0f ? -1.0f : 1.0f;
|
||||||
v0.m_tangent = packF4u(tangent[0], tangent[1], tangent[2], tw);
|
bgfx::vertexPack(tangent, true, bgfx::Attrib::Tangent, _decl, _vertices, ii);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,6 +698,8 @@ int main(int _argc, const char* _argv[])
|
||||||
|
|
||||||
if (hasNormal)
|
if (hasNormal)
|
||||||
{
|
{
|
||||||
|
hasTangent &= hasTexcoord;
|
||||||
|
|
||||||
switch (packNormal)
|
switch (packNormal)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -764,10 +712,10 @@ int main(int _argc, const char* _argv[])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true);
|
decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true);
|
||||||
if (hasTangent)
|
if (hasTangent)
|
||||||
{
|
{
|
||||||
decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true);
|
decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -828,6 +776,11 @@ int main(int _argc, const char* _argv[])
|
||||||
}
|
}
|
||||||
triReorderElapsed += bx::getHPCounter();
|
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, material, primitives);
|
||||||
primitives.clear();
|
primitives.clear();
|
||||||
|
|
||||||
|
@ -875,58 +828,14 @@ int main(int _argc, const char* _argv[])
|
||||||
uv[1] = -uv[1];
|
uv[1] = -uv[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (packUv)
|
bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, decl, vertices);
|
||||||
{
|
|
||||||
default:
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
float* texcoord0 = (float*)(vertices + texcoord0Offset);
|
|
||||||
memcpy(texcoord0, uv, 2*sizeof(float) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
uint32_t* texcoord0 = (uint32_t*)(vertices + texcoord0Offset);
|
|
||||||
*texcoord0 = packF2h(uv[0], uv[1]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasNormal)
|
if (hasNormal)
|
||||||
{
|
{
|
||||||
switch (packNormal)
|
float normal[4];
|
||||||
{
|
vec3Norm(normal, (float*)&normals[index.m_normal]);
|
||||||
default:
|
bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, decl, vertices);
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
float* normal = (float*)(vertices + normalOffset);
|
|
||||||
vec3Norm(normal, (float*)&normals[index.m_normal]);
|
|
||||||
|
|
||||||
if (hasTangent)
|
|
||||||
{
|
|
||||||
float* tangent = (float*)(vertices + tangentOffset);
|
|
||||||
memset(tangent, 0, 3*sizeof(float) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
float normal[3];
|
|
||||||
vec3Norm(normal, (float*)&normals[index.m_normal]);
|
|
||||||
uint32_t* nxyz0 = (uint32_t*)(vertices + normalOffset);
|
|
||||||
*nxyz0 = packF4u(normal[0], normal[1], normal[2]);
|
|
||||||
|
|
||||||
if (hasTangent)
|
|
||||||
{
|
|
||||||
uint32_t* txyz0 = (uint32_t*)(vertices + tangentOffset);
|
|
||||||
*txyz0 = packF4u(0.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vertices += stride;
|
vertices += stride;
|
||||||
|
@ -965,6 +874,11 @@ int main(int _argc, const char* _argv[])
|
||||||
}
|
}
|
||||||
triReorderElapsed += bx::getHPCounter();
|
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, material, primitives);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue