mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
trying and failing andad trying and rince and repeat
This commit is contained in:
parent
c12115bfda
commit
392e2ff535
4 changed files with 38 additions and 79 deletions
|
@ -585,7 +585,6 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
|||
|
||||
FBXMesh& fbxMesh = extractedMesh;
|
||||
graphics::MeshPointer mesh(new graphics::Mesh());
|
||||
bool hasBlendShapes = !fbxMesh.blendshapes.empty();
|
||||
int numVerts = extractedMesh.vertices.size();
|
||||
|
||||
if (!fbxMesh.normals.empty() && fbxMesh.tangents.empty()) {
|
||||
|
@ -761,33 +760,7 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
|||
bool interleavePositions = true;
|
||||
bool interleaveNormalsTangents = true;
|
||||
|
||||
// TODO: We are using the same vertex format layout for all meshes because this is more efficient
|
||||
// This work is going into rc73 release which is meant to be used for the SPot500 event and we are picking the format
|
||||
// that works best for blendshaped and skinned meshes aka the avatars.
|
||||
// We will improve this technique in a hot fix to 73.
|
||||
hasBlendShapes = false;
|
||||
|
||||
// If has blend shapes allocate and assign buffers for pos and tangents now
|
||||
if (hasBlendShapes) {
|
||||
auto posBuffer = std::make_shared<gpu::Buffer>();
|
||||
posBuffer->setData(positionsSize, (const gpu::Byte*) vertBuffer->getData() + positionsOffset);
|
||||
vertexBufferStream->addBuffer(posBuffer, 0, positionElement.getSize());
|
||||
|
||||
auto normalsAndTangentsBuffer = std::make_shared<gpu::Buffer>();
|
||||
normalsAndTangentsBuffer->setData(normalsAndTangentsSize, (const gpu::Byte*) vertBuffer->getData() + normalsAndTangentsOffset);
|
||||
vertexBufferStream->addBuffer(normalsAndTangentsBuffer, 0, normalsAndTangentsStride);
|
||||
|
||||
// update channels and attribBuffer size accordingly
|
||||
interleavePositions = false;
|
||||
interleaveNormalsTangents = false;
|
||||
|
||||
tangentChannel = 1;
|
||||
attribChannel = 2;
|
||||
|
||||
totalAttribBufferSize = totalVertsSize - positionsSize - normalsAndTangentsSize;
|
||||
}
|
||||
|
||||
// Define the vertex format, compute the offset for each attributes as we append them to the vertex format
|
||||
// Define the vertex format, compute the offset for each attributes as we append them to the vertex format
|
||||
gpu::Offset bufOffset = 0;
|
||||
if (positionsSize) {
|
||||
vertexFormat->setAttribute(gpu::Stream::POSITION, posChannel, positionElement, bufOffset);
|
||||
|
|
|
@ -26,52 +26,53 @@ struct BlendshapeOffset {
|
|||
|
||||
const float oneOver511 = 1.0 / 511.0;
|
||||
|
||||
vec3 unpackSnorm3x10_1x2(int packedX10Y10Z10A2) {
|
||||
vec4 my_unpacked = vec4(
|
||||
clamp( float( (packedX10Y10Z10A2 & 0x000003FF) - 511 ) / 511.0, -1.0, 1.0),
|
||||
clamp( float( ((packedX10Y10Z10A2 >> 10) & 0x000003FF) - 511 ) / 511.0, -1.0, 1.0),
|
||||
clamp( float( ((packedX10Y10Z10A2 >> 20) & 0x000003FF) - 511 ) / 511.0, -1.0, 1.0),
|
||||
0.0//clamp( float( int((packedX10Y10Z10A2 >> 30) & 0x00000003) - 1 ), -1.0, 1.0)
|
||||
vec3 unpackSnorm3x10_1x2(int packed) {
|
||||
vec4 _unpacked = vec4(
|
||||
clamp( float( bitfieldExtract(packed, 0, 10)) * oneOver511, -1.0, 1.0),
|
||||
clamp( float( bitfieldExtract(packed, 10, 10)) * oneOver511, -1.0, 1.0),
|
||||
clamp( float( bitfieldExtract(packed, 20, 10)) * oneOver511, -1.0, 1.0),
|
||||
0.0
|
||||
);
|
||||
return my_unpacked.xyz;
|
||||
return _unpacked.xyz;
|
||||
}
|
||||
|
||||
#if defined(GPU_GL410)
|
||||
layout(binding=0) uniform samplerBuffer blendshapeOffsetsBuffer;
|
||||
|
||||
vec2 gpu_unpackHalf2x16(uint packed) {
|
||||
return unpackHalf2x16(packed);
|
||||
}
|
||||
|
||||
BlendshapeOffset getBlendshapeOffset(int i) {
|
||||
vec4 fetched = texelFetch(blendshapeOffsetsBuffer, i);
|
||||
ivec4 elem_packed = ivec4(floatBitsToUint(fetched.x), floatBitsToUint(fetched.y), floatBitsToUint(fetched.z), floatBitsToUint(fetched.w));
|
||||
uvec4 elem_packed = uvec4(floatBitsToUint(fetched.x), floatBitsToUint(fetched.y), floatBitsToUint(fetched.z), floatBitsToUint(fetched.w));
|
||||
|
||||
BlendshapeOffset unpacked;
|
||||
vec2 pZnZ = unpackHalf2x16(uint(elem_packed.y));
|
||||
unpacked.position = vec3(unpackHalf2x16(uint(elem_packed.x)), pZnZ.x);
|
||||
unpacked.position = vec3(gpu_unpackHalf2x16((elem_packed.x)), gpu_unpackHalf2x16(uint(elem_packed.y)).x);
|
||||
<@if USE_NORMAL@>
|
||||
unpacked.normal = vec3(unpackHalf2x16(uint(elem_packed.z)), pZnZ.y);
|
||||
//unpacked.normal = unpackSnorm3x10_1x2((elem_packed.z)).xyz;
|
||||
unpacked.normal = unpackSnorm3x10_1x2(int(elem_packed.z)).xyz;
|
||||
<@endif@>
|
||||
<@if USE_TANGENT@>
|
||||
unpacked.tangent = unpackSnorm3x10_1x2((elem_packed.w)).xyz;
|
||||
unpacked.tangent = unpackSnorm3x10_1x2(int(elem_packed.w)).xyz;
|
||||
<@endif@>
|
||||
|
||||
return unpacked;
|
||||
}
|
||||
#else
|
||||
layout(std140, binding=0) buffer blendshapeOffsetsBuffer {
|
||||
ivec4 _packedBlendshapeOffsets[];
|
||||
uvec4 _packedBlendshapeOffsets[];
|
||||
};
|
||||
BlendshapeOffset getBlendshapeOffset(int i) {
|
||||
|
||||
ivec4 elem_packed = _packedBlendshapeOffsets[i];
|
||||
uvec4 elem_packed = _packedBlendshapeOffsets[i];
|
||||
|
||||
BlendshapeOffset unpacked;
|
||||
vec2 pZnZ = unpackHalf2x16(uint(elem_packed.y));
|
||||
unpacked.position = vec3(unpackHalf2x16(uint(elem_packed.x)), pZnZ.x);
|
||||
unpacked.position = vec3(unpackHalf2x16((elem_packed.x)), unpackHalf2x16(uint(elem_packed.y)).x);
|
||||
<@if USE_NORMAL@>
|
||||
unpacked.normal = vec3(unpackHalf2x16(uint(elem_packed.z)), pZnZ.y);
|
||||
//unpacked.normal = unpackSnorm3x10_1x2((elem_packed.z)).xyz;
|
||||
unpacked.normal = unpackSnorm3x10_1x2(int(elem_packed.z)).xyz;
|
||||
<@endif@>
|
||||
<@if USE_TANGENT@>
|
||||
unpacked.tangent = unpackSnorm3x10_1x2((elem_packed.w)).xyz;
|
||||
unpacked.tangent = unpackSnorm3x10_1x2(int(elem_packed.w)).xyz;
|
||||
<@endif@>
|
||||
|
||||
return unpacked;
|
||||
|
@ -92,7 +93,7 @@ void evalBlendshape(int i, vec4 inPosition, out vec4 position
|
|||
normal = normalize(inNormal + blendshapeOffset.normal.xyz);
|
||||
<@endif@>
|
||||
<@if USE_TANGENT@>
|
||||
tangent = normalize(inTangent /*+ blendshapeOffset.tangent.xyz*/);
|
||||
tangent = normalize(inTangent + blendshapeOffset.tangent.xyz);
|
||||
<@endif@>
|
||||
}
|
||||
|
||||
|
|
|
@ -1633,6 +1633,8 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe
|
|||
}
|
||||
|
||||
|
||||
//#define DEBUG_PACKED_BLENDSHAPE_OFFSET 1
|
||||
|
||||
void Blender::run() {
|
||||
QVector<BlendshapeOffset> blendshapeOffsets;
|
||||
if (_model && _model->isLoaded()) {
|
||||
|
@ -1651,8 +1653,7 @@ void Blender::run() {
|
|||
offset += modelMeshBlendshapeOffsets->second.size();
|
||||
std::vector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets(modelMeshBlendshapeOffsets->second.size());
|
||||
|
||||
// const float NORMAL_COEFFICIENT_SCALE = 0.01f;
|
||||
const float NORMAL_COEFFICIENT_SCALE = 1.0f;
|
||||
const float NORMAL_COEFFICIENT_SCALE = 0.01f;
|
||||
for (int i = 0, n = qMin(_blendshapeCoefficients.size(), mesh.blendshapes.size()); i < n; i++) {
|
||||
float vertexCoefficient = _blendshapeCoefficients.at(i);
|
||||
const float EPSILON = 0.0001f;
|
||||
|
@ -1668,38 +1669,37 @@ void Blender::run() {
|
|||
for (auto j = range.begin(); j < range.end(); j++) {
|
||||
int index = blendshape.indices.at(j);
|
||||
|
||||
#ifdef PACKED_BLENDSHAPE_OFFSET
|
||||
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[index];
|
||||
currentBlendshapeOffset.positionOffsetAndSpare += blendshape.vertices.at(j) * vertexCoefficient;
|
||||
|
||||
currentBlendshapeOffset.normalOffsetAndSpare += blendshape.normals.at(j) * normalCoefficient;
|
||||
if (doTangent) {
|
||||
currentBlendshapeOffset.tangentOffsetAndSpare += blendshape.tangents.at(j) * normalCoefficient;
|
||||
}
|
||||
#else
|
||||
auto& currentBlendshapeOffset = blendshapeOffsets[index];
|
||||
currentBlendshapeOffset.positionOffsetAndSpare += glm::vec4(blendshape.vertices.at(j) * vertexCoefficient, 0.0f);
|
||||
|
||||
currentBlendshapeOffset.normalOffsetAndSpare += glm::vec4(blendshape.normals.at(j) * normalCoefficient, 0.0f);
|
||||
if (index < mesh.tangents.size()) {
|
||||
if ((int)j < blendshape.tangents.size()) {
|
||||
currentBlendshapeOffset.tangentOffsetAndSpare += glm::vec4(blendshape.tangents.at(j) * normalCoefficient, 0.0f);
|
||||
currentBlendshapeOffset.tangentOffsetAndSpare += blendshape.tangents.at(j) * normalCoefficient;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PACKED_BLENDSHAPE_OFFSET
|
||||
if (glm::any(glm::greaterThan(glm::abs(currentBlendshapeOffset.normalOffsetAndSpare), glm::vec3(1.0f)))) {
|
||||
currentBlendshapeOffset.normalOffsetAndSpare = glm::clamp(currentBlendshapeOffset.normalOffsetAndSpare, glm::vec3(-1.0f), glm::vec3(1.0f));
|
||||
}
|
||||
if (glm::any(glm::greaterThan(glm::abs(currentBlendshapeOffset.tangentOffsetAndSpare), glm::vec3(1.0f)))) {
|
||||
currentBlendshapeOffset.tangentOffsetAndSpare = glm::clamp(currentBlendshapeOffset.tangentOffsetAndSpare, glm::vec3(-1.0f), glm::vec3(1.0f));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef PACKED_BLENDSHAPE_OFFSET
|
||||
// Blendshape offsets are generrated, now let's pack it on its way to gpu
|
||||
tbb::parallel_for(tbb::blocked_range<int>(0, (int) unpackedBlendshapeOffsets.size()), [&](const tbb::blocked_range<int>& range) {
|
||||
auto unpacked = unpackedBlendshapeOffsets.data() + range.begin();
|
||||
auto packed = meshBlendshapeOffsets + range.begin();
|
||||
for (auto j = range.begin(); j < range.end(); j++) {
|
||||
(*packed).packedPosNorTan = glm::uvec4(
|
||||
glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare)),
|
||||
glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare.z, unpacked->normalOffsetAndSpare.z)),
|
||||
glm::packHalf2x16(glm::vec2(unpacked->normalOffsetAndSpare)),
|
||||
glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare.z, 0.0f)),
|
||||
glm::packSnorm3x10_1x2(glm::vec4(unpacked->normalOffsetAndSpare, 0.0f)),
|
||||
glm::packSnorm3x10_1x2(glm::vec4(unpacked->tangentOffsetAndSpare, 0.0f))
|
||||
);
|
||||
|
||||
|
@ -1707,8 +1707,6 @@ void Blender::run() {
|
|||
packed++;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
// post the result to the ModelBlender, which will dispatch to the model if still alive
|
||||
|
|
|
@ -75,10 +75,6 @@ struct SortedTriangleSet {
|
|||
int subMeshIndex;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define PACKED_BLENDSHAPE_OFFSET 1
|
||||
#ifdef PACKED_BLENDSHAPE_OFFSET
|
||||
struct BlendshapeOffsetPacked {
|
||||
glm::uvec4 packedPosNorTan;
|
||||
};
|
||||
|
@ -90,15 +86,6 @@ struct BlendshapeOffsetUnpacked {
|
|||
};
|
||||
|
||||
using BlendshapeOffset = BlendshapeOffsetPacked;
|
||||
#else
|
||||
|
||||
struct BlendshapeOffsetUnpacked {
|
||||
glm::vec4 positionOffsetAndSpare;
|
||||
glm::vec4 normalOffsetAndSpare;
|
||||
glm::vec4 tangentOffsetAndSpare;
|
||||
};
|
||||
using BlendshapeOffset = BlendshapeOffsetUnpacked;
|
||||
#endif
|
||||
|
||||
/// A generic 3D model displaying geometry loaded from a URL.
|
||||
class Model : public QObject, public std::enable_shared_from_this<Model>, public scriptable::ModelProvider {
|
||||
|
|
Loading…
Reference in a new issue