summaryrefslogtreecommitdiff
path: root/indra/newview/gltf/primitive.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/gltf/primitive.cpp')
-rw-r--r--indra/newview/gltf/primitive.cpp488
1 files changed, 147 insertions, 341 deletions
diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp
index b5d59e1b24..b57a0af18d 100644
--- a/indra/newview/gltf/primitive.cpp
+++ b/indra/newview/gltf/primitive.cpp
@@ -27,163 +27,12 @@
#include "../llviewerprecompiledheaders.h"
#include "asset.h"
+#include "buffer_util.h"
+
#include "../lltinygltfhelper.h"
using namespace LL::GLTF;
-#ifdef _MSC_VER
-#define LL_FUNCSIG __FUNCSIG__
-#else
-#define LL_FUNCSIG __PRETTY_FUNCTION__
-#endif
-
-// copy one vec3 from src to dst
-template<class S, class T>
-void copyVec2(S* src, T& dst)
-{
- LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL;
-}
-
-// copy one vec3 from src to dst
-template<class S, class T>
-void copyVec3(S* src, T& dst)
-{
- LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL;
-}
-
-// copy one vec4 from src to dst
-template<class S, class T>
-void copyVec4(S* src, T& dst)
-{
- LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL;
-}
-
-template<>
-void copyVec2<F32, LLVector2>(F32* src, LLVector2& dst)
-{
- dst.set(src[0], src[1]);
-}
-
-template<>
-void copyVec3<F32, LLVector4a>(F32* src, LLVector4a& dst)
-{
- dst.load3(src);
-}
-
-template<>
-void copyVec3<U16, LLColor4U>(U16* src, LLColor4U& dst)
-{
- dst.set(src[0], src[1], src[2], 255);
-}
-
-template<>
-void copyVec4<F32, LLVector4a>(F32* src, LLVector4a& dst)
-{
- dst.loadua(src);
-}
-
-// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy
-template<class S, class T>
-void copyVec2(S* src, LLStrider<T> dst, S32 stride, S32 count)
-{
- for (S32 i = 0; i < count; ++i)
- {
- copyVec2(src, *dst);
- dst++;
- src = (S*)((U8*)src + stride);
- }
-}
-
-// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy
-template<class S, class T>
-void copyVec3(S* src, LLStrider<T> dst, S32 stride, S32 count)
-{
- for (S32 i = 0; i < count; ++i)
- {
- copyVec3(src, *dst);
- dst++;
- src = (S*)((U8*)src + stride);
- }
-}
-
-// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy
-template<class S, class T>
-void copyVec4(S* src, LLStrider<T> dst, S32 stride, S32 count)
-{
- for (S32 i = 0; i < count; ++i)
- {
- copyVec3(src, *dst);
- dst++;
- src = (S*)((U8*)src + stride);
- }
-}
-
-template<class S, class T>
-void copyAttributeArray(Asset& asset, const Accessor& accessor, const S* src, LLStrider<T>& dst, S32 byteStride)
-{
- if (accessor.mType == TINYGLTF_TYPE_VEC2)
- {
- S32 stride = byteStride == 0 ? sizeof(S) * 2 : byteStride;
- copyVec2((S*)src, dst, stride, accessor.mCount);
- }
- else if (accessor.mType == TINYGLTF_TYPE_VEC3)
- {
- S32 stride = byteStride == 0 ? sizeof(S) * 3 : byteStride;
- copyVec3((S*)src, dst, stride, accessor.mCount);
- }
- else if (accessor.mType == TINYGLTF_TYPE_VEC4)
- {
- S32 stride = byteStride == 0 ? sizeof(S) * 4 : byteStride;
- copyVec4((S*)src, dst, stride, accessor.mCount);
- }
- else
- {
- LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL;
- }
-}
-
-template <class T>
-void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider<T>& dst)
-{
- const Accessor& accessor = asset.mAccessors[accessorIdx];
- const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView];
- const Buffer& buffer = asset.mBuffers[bufferView.mBuffer];
- const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset;
-
- if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_FLOAT)
- {
- copyAttributeArray(asset, accessor, (const F32*)src, dst, bufferView.mByteStride);
- }
- else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
- {
- copyAttributeArray(asset, accessor, (const U16*)src, dst, bufferView.mByteStride);
- }
- else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT)
- {
- copyAttributeArray(asset, accessor, (const U32*)src, dst, bufferView.mByteStride);
- }
- else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)
- {
- copyAttributeArray(asset, accessor, (const U8*)src, dst, bufferView.mByteStride);
- }
- else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_SHORT)
- {
- copyAttributeArray(asset, accessor, (const S16*)src, dst, bufferView.mByteStride);
- }
- else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_BYTE)
- {
- copyAttributeArray(asset, accessor, (const S8*)src, dst, bufferView.mByteStride);
- }
- else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_DOUBLE)
- {
- copyAttributeArray(asset, accessor, (const F64*)src, dst, bufferView.mByteStride);
- }
- else
- {
- LL_ERRS("GLTF") << "Unsupported component type" << LL_ENDL;
- }
-}
-
void Primitive::allocateGLResources(Asset& asset)
{
// allocate vertex buffer
@@ -192,219 +41,138 @@ void Primitive::allocateGLResources(Asset& asset)
// For our engine, though, it's better to rearrange the buffers at load time into a layout that's more consistent.
// The GLTF native approach undoubtedly works well if you can count on VAOs, but VAOs perform much worse with our scenes.
- // get the number of vertices
- U32 numVertices = 0;
- if (!mAttributes.empty())
- {
- auto it = mAttributes.begin();
- const Accessor& accessor = asset.mAccessors[it->second];
- numVertices = accessor.mCount;
- }
-
- // get the number of indices
- U32 numIndices = 0;
- if (mIndices != INVALID_INDEX)
- {
- const Accessor& accessor = asset.mAccessors[mIndices];
- numIndices = accessor.mCount;
- }
-
- // create vertex buffer
- mVertexBuffer = new LLVertexBuffer(ATTRIBUTE_MASK);
- mVertexBuffer->allocateBuffer(numVertices, numIndices);
-
- bool needs_color = true;
- bool needs_texcoord = true;
- bool needs_normal = true;
- bool needs_tangent = true;
-
// load vertex data
for (auto& it : mAttributes)
{
const std::string& attribName = it.first;
+ Accessor& accessor = asset.mAccessors[it.second];
// load vertex data
if (attribName == "POSITION")
{
- // load position data
- LLStrider<LLVector4a> dst;
- mVertexBuffer->getVertexStrider(dst);
-
- copyAttribute(asset, it.second, dst);
+ copy(asset, accessor, mPositions);
}
else if (attribName == "NORMAL")
{
- needs_normal = false;
- // load normal data
- LLStrider<LLVector4a> dst;
- mVertexBuffer->getNormalStrider(dst);
-
- copyAttribute(asset, it.second, dst);
+ copy(asset, accessor, mNormals);
}
else if (attribName == "TANGENT")
{
- needs_tangent = false;
- // load tangent data
-
- LLStrider<LLVector4a> dst;
- mVertexBuffer->getTangentStrider(dst);
-
- copyAttribute(asset, it.second, dst);
+ copy(asset, accessor, mTangents);
}
else if (attribName == "COLOR_0")
{
- needs_color = false;
- // load color data
-
- LLStrider<LLColor4U> dst;
- mVertexBuffer->getColorStrider(dst);
-
- copyAttribute(asset, it.second, dst);
+ copy(asset, accessor, mColors);
}
else if (attribName == "TEXCOORD_0")
{
- needs_texcoord = false;
- // load texcoord data
- LLStrider<LLVector2> dst;
- mVertexBuffer->getTexCoord0Strider(dst);
-
- LLStrider<LLVector2> tc = dst;
- copyAttribute(asset, it.second, dst);
-
- // convert to OpenGL coordinate space
- for (U32 i = 0; i < numVertices; ++i)
- {
- tc->mV[1] = 1.0f - tc->mV[1];;
- tc++;
- }
+ copy(asset, accessor, mTexCoords);
+ }
+ else if (attribName == "JOINTS_0")
+ {
+ copy(asset, accessor, mJoints);
+ }
+ else if (attribName == "WEIGHTS_0")
+ {
+ copy(asset, accessor, mWeights);
}
}
// copy index buffer
if (mIndices != INVALID_INDEX)
{
- const Accessor& accessor = asset.mAccessors[mIndices];
- const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView];
- const Buffer& buffer = asset.mBuffers[bufferView.mBuffer];
+ Accessor& accessor = asset.mAccessors[mIndices];
+ copy(asset, accessor, mIndexArray);
+ }
- const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset;
+ U32 mask = ATTRIBUTE_MASK;
+
+ if (!mWeights.empty())
+ {
+ mask |= LLVertexBuffer::MAP_WEIGHT4;
+ }
- LLStrider<U16> dst;
- mVertexBuffer->getIndexStrider(dst);
- mIndexArray.resize(numIndices);
+ mVertexBuffer = new LLVertexBuffer(mask);
+ mVertexBuffer->allocateBuffer(mPositions.size(), mIndexArray.size()*2); // double the size of the index buffer for 32-bit indices
- if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT)
- {
- for (U32 i = 0; i < numIndices; ++i)
- {
- *(dst++) = (U16) * (U32*)src;
- src += sizeof(U32);
- }
- }
- else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT)
- {
- for (U32 i = 0; i < numIndices; ++i)
- {
- *(dst++) = *(U16*)src;
- src += sizeof(U16);
- }
- }
- else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)
- {
- for (U32 i = 0; i < numIndices; ++i)
- {
- *(dst++) = *(U8*)src;
- src += sizeof(U8);
- }
- }
- else
- {
- LL_ERRS("GLTF") << "Unsupported component type for indices" << LL_ENDL;
- }
+ mVertexBuffer->setBuffer();
+ mVertexBuffer->setPositionData(mPositions.data());
- U16* idx = (U16*)mVertexBuffer->getMappedIndices();
- for (U32 i = 0; i < numIndices; ++i)
- {
- mIndexArray[i] = idx[i];
- }
+ if (!mIndexArray.empty())
+ {
+ mVertexBuffer->setIndexData(mIndexArray.data());
}
- // fill in default values for missing attributes
- if (needs_color)
- { // set default color
- LLStrider<LLColor4U> dst;
- mVertexBuffer->getColorStrider(dst);
- for (U32 i = 0; i < numVertices; ++i)
- {
- *(dst++) = LLColor4U(255, 255, 255, 255);
- }
+ if (mTexCoords.empty())
+ {
+ mTexCoords.resize(mPositions.size());
+ }
+
+ // flip texcoord y, upload, then flip back (keep the off-spec data in vram only)
+ for (auto& tc : mTexCoords)
+ {
+ tc[1] = 1.f - tc[1];
}
+ mVertexBuffer->setTexCoordData(mTexCoords.data());
+ for (auto& tc : mTexCoords)
+ {
+ tc[1] = 1.f - tc[1];
+ }
+
+ if (mColors.empty())
+ {
+ mColors.resize(mPositions.size(), LLColor4U::white);
+ }
+
// bake material basecolor into color array
if (mMaterial != INVALID_INDEX)
{
const Material& material = asset.mMaterials[mMaterial];
LLColor4 baseColor = material.mMaterial->mBaseColor;
- LLStrider<LLColor4U> dst;
- mVertexBuffer->getColorStrider(dst);
-
- for (U32 i = 0; i < numVertices; ++i)
+ for (auto& dst : mColors)
{
- LLColor4 col = *dst;
- *dst = LLColor4U(baseColor * col);
- dst++;
+ dst = LLColor4U(baseColor * LLColor4(dst));
}
}
- if (needs_texcoord)
- { // set default texcoord
- LLStrider<LLVector2> dst;
- mVertexBuffer->getTexCoord0Strider(dst);
- for (U32 i = 0; i < numVertices; ++i)
- {
- *(dst++) = LLVector2(0.0f, 0.0f);
- }
- }
+ mVertexBuffer->setColorData(mColors.data());
- if (needs_normal)
- { // set default normal
- LLStrider<LLVector4a> dst;
- mVertexBuffer->getNormalStrider(dst);
- for (U32 i = 0; i < numVertices; ++i)
- {
- *(dst++) = LLVector4a(0.0f, 0.0f, 1.0f, 0.0f);
- }
+ if (mNormals.empty())
+ {
+ mNormals.resize(mPositions.size(), LLVector4a(0, 0, 1, 0));
}
+
+ mVertexBuffer->setNormalData(mNormals.data());
- if (needs_tangent)
- { // TODO: generate tangents if needed
- LLStrider<LLVector4a> dst;
- mVertexBuffer->getTangentStrider(dst);
- for (U32 i = 0; i < numVertices; ++i)
- {
- *(dst++) = LLVector4a(1.0f, 0.0f, 0.0f, 1.0f);
- }
+ if (mTangents.empty())
+ {
+ // TODO: generate tangents if needed
+ mTangents.resize(mPositions.size(), LLVector4a(1, 0, 0, 1));
}
- mPositions.resize(numVertices);
- mTexCoords.resize(numVertices);
- mNormals.resize(numVertices);
- mTangents.resize(numVertices);
+ mVertexBuffer->setTangentData(mTangents.data());
- LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX));
- LLVector2* tc = (LLVector2*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TEXCOORD0));
- LLVector4a* norm = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_NORMAL));
- LLVector4a* tangent = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TANGENT));
- for (U32 i = 0; i < numVertices; ++i)
+ if (!mWeights.empty())
{
- mPositions[i] = pos[i];
- mTexCoords[i] = tc[i];
- mNormals[i] = norm[i];
- mTangents[i] = tangent[i];
+ std::vector<LLVector4a> weight_data;
+ weight_data.resize(mWeights.size());
+
+ F32 max_weight = 1.f - FLT_EPSILON*100.f;
+ LLVector4a maxw(max_weight, max_weight, max_weight, max_weight);
+ for (U32 i = 0; i < mWeights.size(); ++i)
+ {
+ LLVector4a& w = weight_data[i];
+ w.setMin(mWeights[i], maxw);
+ w.add(mJoints[i]);
+ };
+
+ mVertexBuffer->setWeight4Data(weight_data.data());
}
+
createOctree();
- mVertexBuffer->unmapBuffer();
+ mVertexBuffer->unbind();
}
void initOctreeTriangle(LLVolumeTriangle* tri, F32 scaler, S32 i0, S32 i1, S32 i2, const LLVector4a& v0, const LLVector4a& v1, const LLVector4a& v2)
@@ -456,20 +224,17 @@ void Primitive::createOctree()
// Initialize all the triangles we need
mOctreeTriangles.resize(num_triangles);
- LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX));
- U16* indices = (U16*)mVertexBuffer->getMappedIndices();
-
for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index)
{ //for each triangle
const U32 index = triangle_index * 3;
LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index];
- S32 i0 = indices[index];
- S32 i1 = indices[index + 1];
- S32 i2 = indices[index + 2];
+ S32 i0 = mIndexArray[index];
+ S32 i1 = mIndexArray[index + 1];
+ S32 i2 = mIndexArray[index + 2];
- const LLVector4a& v0 = pos[i0];
- const LLVector4a& v1 = pos[i1];
- const LLVector4a& v2 = pos[i2];
+ const LLVector4a& v0 = mPositions[i0];
+ const LLVector4a& v1 = mPositions[i1];
+ const LLVector4a& v2 = mPositions[i2];
initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2);
@@ -483,20 +248,17 @@ void Primitive::createOctree()
// Initialize all the triangles we need
mOctreeTriangles.resize(num_triangles);
- LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX));
- U16* indices = (U16*)mVertexBuffer->getMappedIndices();
-
for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index)
{ //for each triangle
const U32 index = triangle_index + 2;
LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index];
- S32 i0 = indices[index];
- S32 i1 = indices[index - 1];
- S32 i2 = indices[index - 2];
+ S32 i0 = mIndexArray[index];
+ S32 i1 = mIndexArray[index - 1];
+ S32 i2 = mIndexArray[index - 2];
- const LLVector4a& v0 = pos[i0];
- const LLVector4a& v1 = pos[i1];
- const LLVector4a& v2 = pos[i2];
+ const LLVector4a& v0 = mPositions[i0];
+ const LLVector4a& v1 = mPositions[i1];
+ const LLVector4a& v2 = mPositions[i2];
initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2);
@@ -510,20 +272,17 @@ void Primitive::createOctree()
// Initialize all the triangles we need
mOctreeTriangles.resize(num_triangles);
- LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX));
- U16* indices = (U16*)mVertexBuffer->getMappedIndices();
-
for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index)
{ //for each triangle
const U32 index = triangle_index + 2;
LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index];
- S32 i0 = indices[0];
- S32 i1 = indices[index - 1];
- S32 i2 = indices[index - 2];
+ S32 i0 = mIndexArray[0];
+ S32 i1 = mIndexArray[index - 1];
+ S32 i2 = mIndexArray[index - 2];
- const LLVector4a& v0 = pos[i0];
- const LLVector4a& v1 = pos[i1];
- const LLVector4a& v2 = pos[i2];
+ const LLVector4a& v0 = mPositions[i0];
+ const LLVector4a& v1 = mPositions[i1];
+ const LLVector4a& v2 = mPositions[i2];
initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2);
@@ -571,7 +330,7 @@ const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start,
face.mTexCoords = mTexCoords.data();
face.mNormals = mNormals.data();
face.mTangents = mTangents.data();
- face.mIndices = mIndexArray.data();
+ face.mIndices = nullptr; // unreferenced
face.mNumIndices = mIndexArray.size();
face.mNumVertices = mPositions.size();
@@ -592,3 +351,50 @@ Primitive::~Primitive()
mOctree = nullptr;
}
+
+const Primitive& Primitive::operator=(const tinygltf::Primitive& src)
+{
+ // load material
+ mMaterial = src.material;
+
+ // load mode
+ mMode = src.mode;
+
+ // load indices
+ mIndices = src.indices;
+
+ // load attributes
+ for (auto& it : src.attributes)
+ {
+ mAttributes[it.first] = it.second;
+ }
+
+ switch (mMode)
+ {
+ case TINYGLTF_MODE_POINTS:
+ mGLMode = LLRender::POINTS;
+ break;
+ case TINYGLTF_MODE_LINE:
+ mGLMode = LLRender::LINES;
+ break;
+ case TINYGLTF_MODE_LINE_LOOP:
+ mGLMode = LLRender::LINE_LOOP;
+ break;
+ case TINYGLTF_MODE_LINE_STRIP:
+ mGLMode = LLRender::LINE_STRIP;
+ break;
+ case TINYGLTF_MODE_TRIANGLES:
+ mGLMode = LLRender::TRIANGLES;
+ break;
+ case TINYGLTF_MODE_TRIANGLE_STRIP:
+ mGLMode = LLRender::TRIANGLE_STRIP;
+ break;
+ case TINYGLTF_MODE_TRIANGLE_FAN:
+ mGLMode = LLRender::TRIANGLE_FAN;
+ break;
+ default:
+ mGLMode = GL_TRIANGLES;
+ }
+
+ return *this;
+}