diff options
Diffstat (limited to 'indra/newview')
24 files changed, 1031 insertions, 447 deletions
diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 092b6e5d4b..7181c5fa53 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -69,9 +69,12 @@ void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix)      matMul(mMatrix, parentMatrix, mAssetMatrix);      mAssetMatrixInv = inverse(mAssetMatrix); +    S32 my_index = this - &asset.mNodes[0]; +      for (auto& childIndex : mChildren)      {          Node& child = asset.mNodes[childIndex]; +        child.mParent = my_index;          child.updateTransforms(asset, mAssetMatrix);      }  } @@ -208,4 +211,129 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,      return node_hit;  } +const Node& Node::operator=(const tinygltf::Node& src) +{ +    F32* dstMatrix = mMatrix.getF32ptr(); + +    if (src.matrix.size() == 16) +    { +        // Node has a transformation matrix, just copy it +        for (U32 i = 0; i < 16; ++i) +        { +            dstMatrix[i] = (F32)src.matrix[i]; +        } +    } +    else if (!src.rotation.empty() || !src.translation.empty() || !src.scale.empty()) +    { +        // node has rotation/translation/scale, convert to matrix +        glh::quaternionf rotation; +        if (src.rotation.size() == 4) +        { +            rotation = glh::quaternionf((F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2], (F32)src.rotation[3]); +        } + +        glh::vec3f translation; +        if (src.translation.size() == 3) +        { +            translation = glh::vec3f((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]); +        } + +        glh::vec3f scale; +        if (src.scale.size() == 3) +        { +            scale = glh::vec3f((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]); +        } +        else +        { +            scale.set_value(1.f, 1.f, 1.f); +        } + +        glh::matrix4f rot; +        rotation.get_value(rot); + +        glh::matrix4f trans; +        trans.set_translate(translation); + +        glh::matrix4f sc; +        sc.set_scale(scale); + +        glh::matrix4f t; +        //t = sc * rot * trans;  +        //t = trans * rot * sc; // best so far, still wrong on negative scale +        //t = sc * trans * rot; +        t = trans * sc * rot; + +        mMatrix.loadu(t.m); +    } +    else +    { +        // node specifies no transformation, set to identity +        mMatrix.setIdentity(); +    } + +    mChildren = src.children; +    mMesh = src.mesh; +    mName = src.name; + +    return *this; +} + +void Asset::render(bool opaque) +{ +    for (auto& node : mNodes) +    { +        if (node.mMesh != INVALID_INDEX) +        { +            Mesh& mesh = mMeshes[node.mMesh]; +            for (auto& primitive : mesh.mPrimitives) +            { +                gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); +                bool cull = true; +                if (primitive.mMaterial != INVALID_INDEX) +                { +                    Material& material = mMaterials[primitive.mMaterial]; + +                    if ((material.mMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND) == opaque) +                    { +                        continue; +                    } +                    material.mMaterial->bind(); +                    cull = !material.mMaterial->mDoubleSided; +                } +                else +                { +                    if (!opaque) +                    { +                        continue; +                    } +                    LLFetchedGLTFMaterial::sDefault.bind(); +                } + +                LLGLDisable cull_face(!cull ? GL_CULL_FACE : 0); + +                primitive.mVertexBuffer->setBuffer(); +                if (primitive.mVertexBuffer->getNumIndices() > 0) +                { +                    primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0); +                } +                else +                { +                    primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts()); +                } + +            } +        } +    } +} + +void Asset::renderOpaque() +{ +    render(true); +} + +void Asset::renderTransparent() +{ +    render(false); +} + diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index 0f1d4e8993..acf9ba77df 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -171,31 +171,12 @@ namespace LL              LLMatrix4a mAssetMatrixInv; //transform from asset to local space              std::vector<S32> mChildren; +            S32 mParent = INVALID_INDEX; +              S32 mMesh = INVALID_INDEX;              std::string mName; -            const Node& operator=(const tinygltf::Node& src) -            { -                F32* dstMatrix = mMatrix.getF32ptr(); - -                if (src.matrix.size() != 16) -                { -                    mMatrix.setIdentity(); -                } -                else -                { -                    for (U32 i = 0; i < 16; ++i) -                    { -                        dstMatrix[i] = (F32)src.matrix[i]; -                    } -                } -                 -                mChildren = src.children; -                mMesh = src.mesh; -                mName = src.name; - -                return *this; -            } +            const Node& operator=(const tinygltf::Node& src);              // Set mRenderMatrix to a transform that can be used for the current render pass              // modelview -- parent's render matrix @@ -314,21 +295,23 @@ namespace LL              void allocateGLResources(const std::string& filename, const tinygltf::Model& model)              { -                for (auto& mesh : mMeshes) -                { -                    mesh.allocateGLResources(*this); -                } - +                // do images first as materials may depend on images                  for (auto& image : mImages)                  {                      image.allocateGLResources();                  } +                // do materials before meshes as meshes may depend on materials                  for (U32 i = 0; i < mMaterials.size(); ++i)                  {                      mMaterials[i].allocateGLResources(*this);                      LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true);                  } + +                for (auto& mesh : mMeshes) +                { +                    mesh.allocateGLResources(*this); +                }              }              // update asset-to-node and node-to-asset transforms @@ -337,34 +320,9 @@ namespace LL              // update node render transforms              void updateRenderTransforms(const LLMatrix4a& modelview); -            void renderOpaque() -            { -                for (auto& node : mNodes) -                { -                    if (node.mMesh != INVALID_INDEX) -                    { -                        Mesh& mesh = mMeshes[node.mMesh]; -                        for (auto& primitive : mesh.mPrimitives) -                        { -                            gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); -                            if (primitive.mMaterial != INVALID_INDEX) -                            { -                                Material& material = mMaterials[primitive.mMaterial]; -                                material.mMaterial->bind(); -                            } -                            primitive.mVertexBuffer->setBuffer(); -                            if (primitive.mVertexBuffer->getNumIndices() > 0) -                            { -                                primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0); -                            } -                            else -                            { -                                primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts()); -                            } -                        } -                    } -                } -            } +            void render(bool opaque); +            void renderOpaque(); +            void renderTransparent();              // return the index of the node that the line segment intersects with, or -1 if no hit              // input and output values must be in this asset's local coordinate frame diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index 71654dcfdd..b5d59e1b24 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -162,10 +162,25 @@ void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider<T>& dst)      {          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() << "Unsupported component type" << LL_ENDL; +        LL_ERRS("GLTF") << "Unsupported component type" << LL_ENDL;      }  } @@ -179,11 +194,11 @@ void Primitive::allocateGLResources(Asset& asset)      // get the number of vertices      U32 numVertices = 0; -    for (auto& it : mAttributes) +    if (!mAttributes.empty())      { -        const Accessor& accessor = asset.mAccessors[it.second]; +        auto it = mAttributes.begin(); +        const Accessor& accessor = asset.mAccessors[it->second];          numVertices = accessor.mCount; -        break;      }      // get the number of indices @@ -294,6 +309,14 @@ void Primitive::allocateGLResources(Asset& asset)                  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; @@ -317,6 +340,22 @@ void Primitive::allocateGLResources(Asset& asset)          }      } +    // 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) +        { +            LLColor4 col = *dst; +            *dst = LLColor4U(baseColor * col); +            dst++; +        } +    } +      if (needs_texcoord)      { // set default texcoord          LLStrider<LLVector2> dst; @@ -368,15 +407,51 @@ void Primitive::allocateGLResources(Asset& asset)      mVertexBuffer->unmapBuffer();  } +void initOctreeTriangle(LLVolumeTriangle* tri, F32 scaler, S32 i0, S32 i1, S32 i2, const LLVector4a& v0, const LLVector4a& v1, const LLVector4a& v2) +{ +    //store pointers to vertex data +    tri->mV[0] = &v0; +    tri->mV[1] = &v1; +    tri->mV[2] = &v2; + +    //store indices +    tri->mIndex[0] = i0; +    tri->mIndex[1] = i1; +    tri->mIndex[2] = i2; + +    //get minimum point +    LLVector4a min = v0; +    min.setMin(min, v1); +    min.setMin(min, v2); + +    //get maximum point +    LLVector4a max = v0; +    max.setMax(max, v1); +    max.setMax(max, v2); + +    //compute center +    LLVector4a center; +    center.setAdd(min, max); +    center.mul(0.5f); + +    tri->mPositionGroup = center; + +    //compute "radius" +    LLVector4a size; +    size.setSub(max, min); + +    tri->mRadius = size.getLength3().getF32() * scaler; +} +  void Primitive::createOctree()  {      // create octree      mOctree = new LLVolumeOctree(); +    F32 scaler = 0.25f; +      if (mMode == TINYGLTF_MODE_TRIANGLES)      { -        F32 scaler = 0.25f; -          const U32 num_triangles = mVertexBuffer->getNumIndices() / 3;          // Initialize all the triangles we need          mOctreeTriangles.resize(num_triangles); @@ -388,47 +463,82 @@ void Primitive::createOctree()          { //for each triangle              const U32 index = triangle_index * 3;              LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; -            const LLVector4a& v0 = pos[indices[index]]; -            const LLVector4a& v1 = pos[indices[index + 1]]; -            const LLVector4a& v2 = pos[indices[index + 2]]; +            S32 i0 = indices[index]; +            S32 i1 = indices[index + 1]; +            S32 i2 = indices[index + 2]; + +            const LLVector4a& v0 = pos[i0]; +            const LLVector4a& v1 = pos[i1]; +            const LLVector4a& v2 = pos[i2]; +             +            initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); +             +            //insert +            mOctree->insert(tri); +        } +    } +    else if (mMode == TINYGLTF_MODE_TRIANGLE_STRIP) +    { +        const U32 num_triangles = mVertexBuffer->getNumIndices() - 2; +        // Initialize all the triangles we need +        mOctreeTriangles.resize(num_triangles); -            //store pointers to vertex data -            tri->mV[0] = &v0; -            tri->mV[1] = &v1; -            tri->mV[2] = &v2; +        LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); +        U16* indices = (U16*)mVertexBuffer->getMappedIndices(); -            //store indices -            tri->mIndex[0] = indices[index]; -            tri->mIndex[1] = indices[index + 1]; -            tri->mIndex[2] = indices[index + 2]; +        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]; + +            const LLVector4a& v0 = pos[i0]; +            const LLVector4a& v1 = pos[i1]; +            const LLVector4a& v2 = pos[i2]; -            //get minimum point -            LLVector4a min = v0; -            min.setMin(min, v1); -            min.setMin(min, v2); +            initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); -            //get maximum point -            LLVector4a max = v0; -            max.setMax(max, v1); -            max.setMax(max, v2); +            //insert +            mOctree->insert(tri); +        } +    } +    else if (mMode == TINYGLTF_MODE_TRIANGLE_FAN) +    { +        const U32 num_triangles = mVertexBuffer->getNumIndices() - 2; +        // Initialize all the triangles we need +        mOctreeTriangles.resize(num_triangles); -            //compute center -            LLVector4a center; -            center.setAdd(min, max); -            center.mul(0.5f); +        LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); +        U16* indices = (U16*)mVertexBuffer->getMappedIndices(); -            tri->mPositionGroup = center; +        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]; -            //compute "radius" -            LLVector4a size; -            size.setSub(max, min); +            const LLVector4a& v0 = pos[i0]; +            const LLVector4a& v1 = pos[i1]; +            const LLVector4a& v2 = pos[i2]; -            tri->mRadius = size.getLength3().getF32() * scaler; +            initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2);              //insert              mOctree->insert(tri);          }      } +    else if (mMode == TINYGLTF_MODE_POINTS || +            mMode == TINYGLTF_MODE_LINE || +        mMode == TINYGLTF_MODE_LINE_LOOP || +        mMode == TINYGLTF_MODE_LINE_STRIP) +    { +        // nothing to do, no volume... maybe add some collision geometry around these primitive types? +    } +          else      {          LL_ERRS() << "Unsupported Primitive mode" << LL_ENDL; diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index 6c44b83646..8273c707f9 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -91,7 +91,11 @@ void GLTFSceneManager::load(const std::string& filename)      if (obj)      { // assign to self avatar          obj->mGLTFAsset = asset; -        mObjects.push_back(obj); + +        if (std::find(mObjects.begin(), mObjects.end(), obj) == mObjects.end()) +        { +            mObjects.push_back(obj); +        }      }  } @@ -100,43 +104,17 @@ GLTFSceneManager::~GLTFSceneManager()      mObjects.clear();  } -LLMatrix4a getAssetToAgentTransform(LLViewerObject* obj) +void GLTFSceneManager::renderOpaque()  { -    LLMatrix4 root; -    root.initScale(obj->getScale()); -    root.rotate(obj->getRenderRotation()); -    root.translate(obj->getPositionAgent()); - -    LLMatrix4a mat; -    mat.loadu((F32*) root.mMatrix); - -    return mat; +    render(true);  } -LLMatrix4a getAgentToAssetTransform(LLViewerObject* obj) +void GLTFSceneManager::renderAlpha()  { -    LLMatrix4 root; -    LLVector3 scale = obj->getScale(); -    scale.mV[0] = 1.f / scale.mV[0]; -    scale.mV[1] = 1.f / scale.mV[1]; -    scale.mV[2] = 1.f / scale.mV[2]; -         -    root.translate(-obj->getPositionAgent()); -    root.rotate(~obj->getRenderRotation()); - -    LLMatrix4 scale_mat; -    scale_mat.initScale(scale); - -    root *= scale_mat; -     - -    LLMatrix4a mat; -    mat.loadu((F32*) root.mMatrix); - -    return mat; +    render(false);  } -void GLTFSceneManager::renderOpaque() +void GLTFSceneManager::render(bool opaque)  {      // for debugging, just render the whole scene as opaque      // by traversing the whole scenegraph @@ -158,7 +136,7 @@ void GLTFSceneManager::renderOpaque()          gGL.pushMatrix(); -        LLMatrix4a mat = getAssetToAgentTransform(mObjects[i]); +        LLMatrix4a mat = mObjects[i]->getGLTFAssetToAgentTransform();          LLMatrix4a modelview;          modelview.loadu(gGLModelView); @@ -166,7 +144,7 @@ void GLTFSceneManager::renderOpaque()          matMul(mat, modelview, modelview);          asset->updateRenderTransforms(modelview); -        asset->renderOpaque(); +        asset->render(opaque);          gGL.popMatrix();      } @@ -195,7 +173,7 @@ bool GLTFSceneManager::lineSegmentIntersect(LLVOVolume* obj, Asset* asset, const      LLVector4a local_start;      LLVector4a local_end; -    LLMatrix4a asset_to_agent = getAssetToAgentTransform(obj); +    LLMatrix4a asset_to_agent = obj->getGLTFAssetToAgentTransform();      LLMatrix4a agent_to_asset = inverse(asset_to_agent);      agent_to_asset.affineTransform(start, local_start); @@ -331,7 +309,7 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset)      gGL.pushMatrix();      // get raycast in asset space -    LLMatrix4a agent_to_asset = getAgentToAssetTransform(obj); +    LLMatrix4a agent_to_asset = obj->getAgentToGLTFAssetTransform();      LLVector4a start;      LLVector4a end; @@ -399,7 +377,8 @@ void GLTFSceneManager::renderDebug()  {      if (!gPipeline.hasRenderDebugMask(          LLPipeline::RENDER_DEBUG_BBOXES | -        LLPipeline::RENDER_DEBUG_RAYCAST)) +        LLPipeline::RENDER_DEBUG_RAYCAST | +        LLPipeline::RENDER_DEBUG_NODES))      {          return;      } @@ -412,6 +391,7 @@ void GLTFSceneManager::renderDebug()      gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);      gPipeline.disableLights(); +    // force update all mRenderMatrix, not just nodes with meshes      for (auto& obj : mObjects)      {          if (obj->isDead() || obj->mGLTFAsset == nullptr) @@ -419,20 +399,115 @@ void GLTFSceneManager::renderDebug()              continue;          } +        LLMatrix4a mat = obj->getGLTFAssetToAgentTransform(); + +        LLMatrix4a modelview; +        modelview.loadu(gGLModelView); + +        matMul(mat, modelview, modelview); +          Asset* asset = obj->mGLTFAsset; +        for (auto& node : asset->mNodes) +        { +            matMul(node.mAssetMatrix, modelview, node.mRenderMatrix); +        } +    } + +    for (auto& obj : mObjects) +    { +        if (obj->isDead() || obj->mGLTFAsset == nullptr) +        { +            continue; +        } + +        Asset* asset = obj->mGLTFAsset; -        LLMatrix4a mat = getAssetToAgentTransform(obj); +        LLMatrix4a mat = obj->getGLTFAssetToAgentTransform();          LLMatrix4a modelview;          modelview.loadu(gGLModelView);          matMul(mat, modelview, modelview); -        asset->updateRenderTransforms(modelview);          renderAssetDebug(obj, asset);      } +    if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_NODES)) +    { //render node hierarchy + +        for (U32 i = 0; i < 2; ++i) +        { +            LLGLDepthTest depth(GL_TRUE, i == 0 ? GL_FALSE : GL_TRUE, i == 0 ? GL_GREATER : GL_LEQUAL); +            LLGLState blend(GL_BLEND, i == 0 ? TRUE : FALSE); + + +            gGL.pushMatrix(); + +            for (auto& obj : mObjects) +            { +                if (obj->isDead() || obj->mGLTFAsset == nullptr) +                { +                    continue; +                } + +                LLMatrix4a mat = obj->getGLTFAssetToAgentTransform(); + +                LLMatrix4a modelview; +                modelview.loadu(gGLModelView); + +                matMul(mat, modelview, modelview); + +                Asset* asset = obj->mGLTFAsset; + +                for (auto& node : asset->mNodes) +                { +                    // force update all mRenderMatrix, not just nodes with meshes +                    matMul(node.mAssetMatrix, modelview, node.mRenderMatrix); + +                    gGL.loadMatrix(node.mRenderMatrix.getF32ptr()); +                    // render x-axis red, y-axis green, z-axis blue +                    gGL.color4f(1.f, 0.f, 0.f, 0.5f); +                    gGL.begin(LLRender::LINES); +                    gGL.vertex3f(0.f, 0.f, 0.f); +                    gGL.vertex3f(1.f, 0.f, 0.f); +                    gGL.end(); +                    gGL.flush(); + +                    gGL.color4f(0.f, 1.f, 0.f, 0.5f); +                    gGL.begin(LLRender::LINES); +                    gGL.vertex3f(0.f, 0.f, 0.f); +                    gGL.vertex3f(0.f, 1.f, 0.f); +                    gGL.end(); +                    gGL.flush(); + +                    gGL.begin(LLRender::LINES); +                    gGL.color4f(0.f, 0.f, 1.f, 0.5f); +                    gGL.vertex3f(0.f, 0.f, 0.f); +                    gGL.vertex3f(0.f, 0.f, 1.f); +                    gGL.end(); +                    gGL.flush(); + +                    // render path to child nodes cyan +                    gGL.color4f(0.f, 1.f, 1.f, 0.5f); +                    gGL.begin(LLRender::LINES); +                    for (auto& child_idx : node.mChildren) +                    { +                        Node& child = asset->mNodes[child_idx]; +                        gGL.vertex3f(0.f, 0.f, 0.f); +                        gGL.vertex3fv(child.mMatrix.getTranslation().getF32ptr()); +                    } +                    gGL.end(); +                    gGL.flush(); +                } +            } + +            gGL.popMatrix(); +        } + +    } + +      if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))      {          S32 node_hit = -1; diff --git a/indra/newview/gltfscenemanager.h b/indra/newview/gltfscenemanager.h index 50e1dd93da..4e9013834b 100644 --- a/indra/newview/gltfscenemanager.h +++ b/indra/newview/gltfscenemanager.h @@ -38,7 +38,9 @@ namespace LL          // load GLTF file from disk          void load(); // open filepicker to choose asset          void load(const std::string& filename); // load asset from filename +        void render(bool opaque);          void renderOpaque(); +        void renderAlpha();          LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,              BOOL pick_transparent, diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 8977b145d1..7ddf6c4390 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2525,7 +2525,7 @@ void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick)  {  	LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); -	if (objectp) +	if (objectp && pick.mGLTFNodeIndex == -1)  	{  		// focus on object plus designated offset  		// which may or may not be same as pick.mPosGlobal diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 41dc95a8cb..81014e9d6e 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -49,6 +49,7 @@  #include "llspatialpartition.h"  #include "llglcommonfunc.h"  #include "llvoavatar.h" +#include "gltfscenemanager.h"  #include "llenvironment.h" @@ -260,6 +261,12 @@ void LLDrawPoolAlpha::forwardRender(bool rigged)      mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;       // }      gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); +    if (write_depth) +    { // draw GLTF scene to depth buffer +        gPipeline.bindDeferredShader(gDeferredPBRAlphaProgram); +        LL::GLTFSceneManager::instance().renderAlpha(); +    } +      // If the face is more than 90% transparent, then don't update the Depth buffer for Dof      // We don't want the nearly invisible objects to cause of DoF effects      renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, false, rigged); diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 1ca7ffaec1..1dd1dbabbe 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -34,6 +34,9 @@  #include "llshadermgr.h"  #include "pipeline.h" +//static +LLFetchedGLTFMaterial LLFetchedGLTFMaterial::sDefault; +  LLFetchedGLTFMaterial::LLFetchedGLTFMaterial()      : LLGLTFMaterial()      , mExpectedFlusTime(0.f) diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index 42c835a416..7550c75b45 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -66,6 +66,8 @@ public:      std::set<LLTextureEntry*> mTextureEntires; +    // default material for when assets don't have one +    static LLFetchedGLTFMaterial sDefault;  protected:      // Lifetime management diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index feb691520f..8a284686ad 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -355,8 +355,14 @@ LLVector3 LLManip::getSavedPivotPoint() const  LLVector3 LLManip::getPivotPoint()  { -	if (mObjectSelection->getFirstObject() && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD) +    LLViewerObject* object = mObjectSelection->getFirstObject(); +	if (object && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD)  	{ +        LLSelectNode* select_node = mObjectSelection->getFirstNode(); +        if (select_node->mSelectedGLTFNode != -1) +        { +            return object->getGLTFNodePositionAgent(select_node->mSelectedGLTFNode); +        }  		return mObjectSelection->getFirstObject()->getPivotPositionAgent();  	}  	return LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent(); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 7f37f98568..1ac1992fe0 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -556,6 +556,7 @@ void LLManipRotate::drag( S32 x, S32 y )  	BOOL damped = mSmoothRotate;  	mSmoothRotate = FALSE; +    bool gltf_mode = false;  	for (LLObjectSelection::iterator iter = mObjectSelection->begin();  		 iter != mObjectSelection->end(); iter++) @@ -569,154 +570,177 @@ void LLManipRotate::drag( S32 x, S32 y )  			((root_object == NULL) || !root_object->isPermanentEnforced()) &&  			(object->isRootEdit() || selectNode->mIndividualSelection))  		{ -			if (!object->isRootEdit()) -			{ -				// child objects should not update if parent is selected -				LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); -				if (editable_root->isSelected()) -				{ -					// we will be moved properly by our parent, so skip -					continue; -				} -			} -			LLQuaternion new_rot = selectNode->mSavedRotation * mRotation; -			std::vector<LLVector3>& child_positions = object->mUnselectedChildrenPositions ; -			std::vector<LLQuaternion> child_rotations; -			if (object->isRootEdit() && selectNode->mIndividualSelection) -			{ -				object->saveUnselectedChildrenRotation(child_rotations) ; -				object->saveUnselectedChildrenPosition(child_positions) ;			 -			} +            if (selectNode->mSelectedGLTFNode != -1) +            { +                LLQuaternion new_rot = selectNode->mSavedRotation * mRotation; -			if (object->getParent() && object->mDrawable.notNull()) -			{ -				LLQuaternion invParentRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); -				invParentRotation.transQuat(); +                object->setGLTFNodeRotationAgent(selectNode->mSelectedGLTFNode, new_rot); -				object->setRotation(new_rot * invParentRotation, damped); -				rebuild(object); -			} -			else -			{ -				object->setRotation(new_rot, damped); -                LLVOAvatar* avatar = object->asAvatar(); -                if (avatar && avatar->isSelf() -                    && LLSelectMgr::getInstance()->mAllowSelectAvatar -                    && !object->getParent()) +                gltf_mode = true; +            } +            else if (!gltf_mode) +            { +                if (!object->isRootEdit())                  { -                    // Normal avatars use object's orienttion, but self uses -                    // separate LLCoordFrame -                    // See LVOAvatar::updateOrientation() -                    if (gAgentCamera.getFocusOnAvatar()) +                    // child objects should not update if parent is selected +                    LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); +                    if (editable_root->isSelected())                      { -                        //Don't rotate camera with avatar -                        gAgentCamera.setFocusOnAvatar(false, false, false); +                        // we will be moved properly by our parent, so skip +                        continue;                      } +                } -                    LLVector3 at_axis = mAgentSelfAtAxis; -                    at_axis *= mRotation; -                    at_axis.mV[VZ] = 0.f; -                    at_axis.normalize(); -                    gAgent.resetAxes(at_axis); +                LLQuaternion new_rot = selectNode->mSavedRotation * mRotation; +                std::vector<LLVector3>& child_positions = object->mUnselectedChildrenPositions; +                std::vector<LLQuaternion> child_rotations; +                if (object->isRootEdit() && selectNode->mIndividualSelection) +                { +                    object->saveUnselectedChildrenRotation(child_rotations); +                    object->saveUnselectedChildrenPosition(child_positions);                  } -				rebuild(object); -			} -			// for individually selected roots, we need to counterrotate all the children -			if (object->isRootEdit() && selectNode->mIndividualSelection) -			{ -				//RN: must do non-damped updates on these objects so relative rotation appears constant -				// instead of having two competing slerps making the child objects appear to "wobble" -				object->resetChildrenRotationAndPosition(child_rotations, child_positions) ; -			} +                if (object->getParent() && object->mDrawable.notNull()) +                { +                    LLQuaternion invParentRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); +                    invParentRotation.transQuat(); + +                    object->setRotation(new_rot * invParentRotation, damped); +                    rebuild(object); +                } +                else +                { +                    object->setRotation(new_rot, damped); +                    LLVOAvatar* avatar = object->asAvatar(); +                    if (avatar && avatar->isSelf() +                        && LLSelectMgr::getInstance()->mAllowSelectAvatar +                        && !object->getParent()) +                    { +                        // Normal avatars use object's orienttion, but self uses +                        // separate LLCoordFrame +                        // See LVOAvatar::updateOrientation() +                        if (gAgentCamera.getFocusOnAvatar()) +                        { +                            //Don't rotate camera with avatar +                            gAgentCamera.setFocusOnAvatar(false, false, false); +                        } + +                        LLVector3 at_axis = mAgentSelfAtAxis; +                        at_axis *= mRotation; +                        at_axis.mV[VZ] = 0.f; +                        at_axis.normalize(); +                        gAgent.resetAxes(at_axis); +                    } +                    rebuild(object); +                } + +                // for individually selected roots, we need to counterrotate all the children +                if (object->isRootEdit() && selectNode->mIndividualSelection) +                { +                    //RN: must do non-damped updates on these objects so relative rotation appears constant +                    // instead of having two competing slerps making the child objects appear to "wobble" +                    object->resetChildrenRotationAndPosition(child_rotations, child_positions); +                } +            }  		}  	}  	// update positions -	for (LLObjectSelection::iterator iter = mObjectSelection->begin(); -		 iter != mObjectSelection->end(); iter++) -	{ -		LLSelectNode* selectNode = *iter; -		LLViewerObject* object = selectNode->getObject(); -		LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); +    if (!gltf_mode) +    { +        for (LLObjectSelection::iterator iter = mObjectSelection->begin(); +            iter != mObjectSelection->end(); iter++) +        { +            LLSelectNode* selectNode = *iter; +            LLViewerObject* object = selectNode->getObject(); +            LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); -		// to avoid cumulative position changes we calculate the objects new position using its saved position -		if (object && object->permMove() && !object->isPermanentEnforced() && -			((root_object == NULL) || !root_object->isPermanentEnforced())) -		{ -			LLVector3 center   = gAgent.getPosAgentFromGlobal( mRotationCenter ); - -			LLVector3 old_position; -			LLVector3 new_position; - -			if (object->isAttachment() && object->mDrawable.notNull()) -			{  -				// need to work in drawable space to handle selected items from multiple attachments  -				// (which have no shared frame of reference other than their render positions) -				LLXform* parent_xform = object->mDrawable->getXform()->getParent(); -				new_position = (selectNode->mSavedPositionLocal * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); -				old_position = (object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();//object->getRenderPosition(); -			} -			else -			{ -				new_position = gAgent.getPosAgentFromGlobal( selectNode->mSavedPositionGlobal ); -				old_position = object->getPositionAgent(); -			} -			new_position = (new_position - center) * mRotation;		// new relative rotated position -			new_position += center; -			 -			if (object->isRootEdit() && !object->isAttachment()) -			{ -				LLVector3d new_pos_global = gAgent.getPosGlobalFromAgent(new_position); -				new_pos_global = LLWorld::getInstance()->clipToVisibleRegions(selectNode->mSavedPositionGlobal, new_pos_global); -				new_position = gAgent.getPosAgentFromGlobal(new_pos_global); -			} +            // to avoid cumulative position changes we calculate the objects new position using its saved position +            if (object && object->permMove() && !object->isPermanentEnforced() && +                ((root_object == NULL) || !root_object->isPermanentEnforced())) +            { +                LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter); -			// for individually selected child objects -			if (!object->isRootEdit() && selectNode->mIndividualSelection) -			{ -				LLViewerObject* parentp = (LLViewerObject*)object->getParent(); -				if (!parentp->isSelected()) -				{ -					if (object->isAttachment() && object->mDrawable.notNull()) -					{ -						// find position relative to render position of parent -						object->setPosition((new_position - parentp->getRenderPosition()) * ~parentp->getRenderRotation()); -						rebuild(object); -					} -					else -					{ -						object->setPositionParent((new_position - parentp->getPositionAgent()) * ~parentp->getRotationRegion()); -						rebuild(object); -					} -				} -			} -			else if (object->isRootEdit()) -			{ -				if (object->isAttachment() && object->mDrawable.notNull()) -				{ -					LLXform* parent_xform = object->mDrawable->getXform()->getParent(); -					object->setPosition((new_position - parent_xform->getWorldPosition()) * ~parent_xform->getWorldRotation()); -					rebuild(object); -				} -				else -				{ -					object->setPositionAgent(new_position); -					rebuild(object); -				} -			} +                LLVector3 old_position; +                LLVector3 new_position; -			// for individually selected roots, we need to counter-translate all unselected children -			if (object->isRootEdit() && selectNode->mIndividualSelection) -			{ -				// only offset by parent's translation as we've already countered parent's rotation -				rebuild(object); -				object->resetChildrenPosition(old_position - new_position) ;				 -			} -		} -	} +                if (selectNode->mSelectedGLTFNode != -1) +                { + +                } +                else +                { +                    if (object->isAttachment() && object->mDrawable.notNull()) +                    { +                        // need to work in drawable space to handle selected items from multiple attachments  +                        // (which have no shared frame of reference other than their render positions) +                        LLXform* parent_xform = object->mDrawable->getXform()->getParent(); +                        new_position = (selectNode->mSavedPositionLocal * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); +                        old_position = (object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();//object->getRenderPosition(); +                    } +                    else +                    { +                        new_position = gAgent.getPosAgentFromGlobal(selectNode->mSavedPositionGlobal); +                        old_position = object->getPositionAgent(); +                    } + +                    new_position = (new_position - center) * mRotation;		// new relative rotated position +                    new_position += center; + +                    if (object->isRootEdit() && !object->isAttachment()) +                    { +                        LLVector3d new_pos_global = gAgent.getPosGlobalFromAgent(new_position); +                        new_pos_global = LLWorld::getInstance()->clipToVisibleRegions(selectNode->mSavedPositionGlobal, new_pos_global); +                        new_position = gAgent.getPosAgentFromGlobal(new_pos_global); +                    } + +                    // for individually selected child objects +                    if (!object->isRootEdit() && selectNode->mIndividualSelection) +                    { +                        LLViewerObject* parentp = (LLViewerObject*)object->getParent(); +                        if (!parentp->isSelected()) +                        { +                            if (object->isAttachment() && object->mDrawable.notNull()) +                            { +                                // find position relative to render position of parent +                                object->setPosition((new_position - parentp->getRenderPosition()) * ~parentp->getRenderRotation()); +                                rebuild(object); +                            } +                            else +                            { +                                object->setPositionParent((new_position - parentp->getPositionAgent()) * ~parentp->getRotationRegion()); +                                rebuild(object); +                            } +                        } +                    } +                    else if (object->isRootEdit()) +                    { +                        if (object->isAttachment() && object->mDrawable.notNull()) +                        { +                            LLXform* parent_xform = object->mDrawable->getXform()->getParent(); +                            object->setPosition((new_position - parent_xform->getWorldPosition()) * ~parent_xform->getWorldRotation()); +                            rebuild(object); +                        } +                        else +                        { +                            object->setPositionAgent(new_position); +                            rebuild(object); +                        } +                    } + +                    // for individually selected roots, we need to counter-translate all unselected children +                    if (object->isRootEdit() && selectNode->mIndividualSelection) +                    { +                        // only offset by parent's translation as we've already countered parent's rotation +                        rebuild(object); +                        object->resetChildrenPosition(old_position - new_position); +                    } +                } +            } +        } +    }  	// store changes to override updates  	for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin(); @@ -725,12 +749,13 @@ void LLManipRotate::drag( S32 x, S32 y )  		LLSelectNode* selectNode = *iter;  		LLViewerObject*cur = selectNode->getObject();  		LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); -		if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && + +        if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() &&  			((root_object == NULL) || !root_object->isPermanentEnforced()) &&  			(!cur->isAvatar() || LLSelectMgr::getInstance()->mAllowSelectAvatar))  		{ -			selectNode->mLastRotation = cur->getRotation(); -			selectNode->mLastPositionLocal = cur->getPosition(); +           selectNode->mLastRotation = cur->getRotation(); +           selectNode->mLastPositionLocal = cur->getPosition();  		}  	}	 diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index cafb3fef67..9fc5ad502c 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -655,114 +655,125 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)  	LLVector3d clamped_relative_move = axis_magnitude * axis_d;	// scalar multiply  	LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply -	for (LLObjectSelection::iterator iter = mObjectSelection->begin(); -		 iter != mObjectSelection->end(); iter++) -	{ -		LLSelectNode* selectNode = *iter; -		LLViewerObject* object = selectNode->getObject(); -		 -		// Only apply motion to root objects and objects selected -		// as "individual". -		if (!object->isRootEdit() && !selectNode->mIndividualSelection) -		{ -			continue; -		} - -		if (!object->isRootEdit()) -		{ -			// child objects should not update if parent is selected -			LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); -			if (editable_root->isSelected()) -			{ -				// we will be moved properly by our parent, so skip -				continue; -			} -		} - -		LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); -		if (object->permMove() && !object->isPermanentEnforced() && -			((root_object == NULL) || !root_object->isPermanentEnforced())) -		{ -			// handle attachments in local space -			if (object->isAttachment() && object->mDrawable.notNull()) -			{ -				// calculate local version of relative move -				LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); -				objWorldRotation.transQuat(); - -				LLVector3 old_position_local = object->getPosition(); -				LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation); - -				//RN: I forget, but we need to do this because of snapping which doesn't often result -				// in position changes even when the mouse moves -				object->setPosition(new_position_local); -				rebuild(object); -				gAgentAvatarp->clampAttachmentPositions(); -				new_position_local = object->getPosition(); - -				if (selectNode->mIndividualSelection) -				{ -					// counter-translate child objects if we are moving the root as an individual -					object->resetChildrenPosition(old_position_local - new_position_local, TRUE) ;					 -				} -			} -			else -			{ -				// compute new position to send to simulators, but don't set it yet. -				// We need the old position to know which simulator to send the move message to. -				LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move; - -				// Don't let object centers go too far underground -				F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal()); -				if (new_position_global.mdV[VZ] < min_height) -				{ -					new_position_global.mdV[VZ] = min_height; -				} - -				// For safety, cap heights where objects can be dragged -				if (new_position_global.mdV[VZ] > MAX_OBJECT_Z) -				{ -					new_position_global.mdV[VZ] = MAX_OBJECT_Z; -				} - -				// Grass is always drawn on the ground, so clamp its position to the ground -				if (object->getPCode() == LL_PCODE_LEGACY_GRASS) -				{ -					new_position_global.mdV[VZ] = LLWorld::getInstance()->resolveLandHeightGlobal(new_position_global) + 1.f; -				} -				 -				if (object->isRootEdit()) -				{ -					new_position_global = LLWorld::getInstance()->clipToVisibleRegions(object->getPositionGlobal(), new_position_global); -				} - -				// PR: Only update if changed -				LLVector3 old_position_agent = object->getPositionAgent(); -				LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global); -				if (object->isRootEdit()) -				{ -					// finally, move parent object after children have calculated new offsets -					object->setPositionAgent(new_position_agent); -					rebuild(object); -				} -				else -				{ -					LLViewerObject* root_object = object->getRootEdit(); -					new_position_agent -= root_object->getPositionAgent(); -					new_position_agent = new_position_agent * ~root_object->getRotation(); -					object->setPositionParent(new_position_agent, FALSE); -					rebuild(object); -				} +    for (LLObjectSelection::iterator iter = mObjectSelection->begin(); +        iter != mObjectSelection->end(); iter++) +    { +        LLSelectNode* selectNode = *iter; +        LLViewerObject* object = selectNode->getObject(); + +        if (selectNode->mSelectedGLTFNode != -1) +        { +            // manipulating a GLTF node +            clamped_relative_move_f -= selectNode->mLastMoveLocal; +            object->moveGLTFNode(selectNode->mSelectedGLTFNode, clamped_relative_move_f); +            selectNode->mLastMoveLocal += clamped_relative_move_f; +        } +        else +        { +            // Only apply motion to root objects and objects selected +            // as "individual". +            if (!object->isRootEdit() && !selectNode->mIndividualSelection) +            { +                continue; +            } + +            if (!object->isRootEdit()) +            { +                // child objects should not update if parent is selected +                LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); +                if (editable_root->isSelected()) +                { +                    // we will be moved properly by our parent, so skip +                    continue; +                } +            } + +            LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); +            if (object->permMove() && !object->isPermanentEnforced() && +                ((root_object == NULL) || !root_object->isPermanentEnforced())) +            { +                // handle attachments in local space +                if (object->isAttachment() && object->mDrawable.notNull()) +                { +                    // calculate local version of relative move +                    LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); +                    objWorldRotation.transQuat(); + +                    LLVector3 old_position_local = object->getPosition(); +                    LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation); + +                    //RN: I forget, but we need to do this because of snapping which doesn't often result +                    // in position changes even when the mouse moves +                    object->setPosition(new_position_local); +                    rebuild(object); +                    gAgentAvatarp->clampAttachmentPositions(); +                    new_position_local = object->getPosition(); + +                    if (selectNode->mIndividualSelection) +                    { +                        // counter-translate child objects if we are moving the root as an individual +                        object->resetChildrenPosition(old_position_local - new_position_local, TRUE); +                    } +                } +                else +                { +                    // compute new position to send to simulators, but don't set it yet. +                    // We need the old position to know which simulator to send the move message to. +                    LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move; + +                    // Don't let object centers go too far underground +                    F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal()); +                    if (new_position_global.mdV[VZ] < min_height) +                    { +                        new_position_global.mdV[VZ] = min_height; +                    } + +                    // For safety, cap heights where objects can be dragged +                    if (new_position_global.mdV[VZ] > MAX_OBJECT_Z) +                    { +                        new_position_global.mdV[VZ] = MAX_OBJECT_Z; +                    } + +                    // Grass is always drawn on the ground, so clamp its position to the ground +                    if (object->getPCode() == LL_PCODE_LEGACY_GRASS) +                    { +                        new_position_global.mdV[VZ] = LLWorld::getInstance()->resolveLandHeightGlobal(new_position_global) + 1.f; +                    } + +                    if (object->isRootEdit()) +                    { +                        new_position_global = LLWorld::getInstance()->clipToVisibleRegions(object->getPositionGlobal(), new_position_global); +                    } + +                    // PR: Only update if changed +                    LLVector3 old_position_agent = object->getPositionAgent(); +                    LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global); +                    if (object->isRootEdit()) +                    { +                        // finally, move parent object after children have calculated new offsets +                        object->setPositionAgent(new_position_agent); +                        rebuild(object); +                    } +                    else +                    { +                        LLViewerObject* root_object = object->getRootEdit(); +                        new_position_agent -= root_object->getPositionAgent(); +                        new_position_agent = new_position_agent * ~root_object->getRotation(); +                        object->setPositionParent(new_position_agent, FALSE); +                        rebuild(object); +                    } + +                    if (selectNode->mIndividualSelection) +                    { +                        // counter-translate child objects if we are moving the root as an individual +                        object->resetChildrenPosition(old_position_agent - new_position_agent, TRUE); +                    } +                } +                selectNode->mLastPositionLocal = object->getPosition(); +            } +        } +    } -				if (selectNode->mIndividualSelection) -				{ -					// counter-translate child objects if we are moving the root as an individual -					object->resetChildrenPosition(old_position_agent - new_position_agent, TRUE) ;					 -				} -			} -			selectNode->mLastPositionLocal  = object->getPosition(); -		} -	}  	LLSelectMgr::getInstance()->updateSelectionCenter();  	gAgentCamera.clearFocusObject(); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 471601f16f..20b00974e1 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -456,7 +456,7 @@ void LLSelectMgr::overrideAvatarUpdates()  //-----------------------------------------------------------------------------  // Select just the object, not any other group members.  //----------------------------------------------------------------------------- -LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face) +LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face, S32 gltf_node, S32 gltf_primitive)  {  	llassert( object ); @@ -481,7 +481,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S3  	// Place it in the list and tag it.  	// This will refresh dialogs. -	addAsIndividual(object, face); +	addAsIndividual(object, face, TRUE, gltf_node, gltf_primitive);  	// Stop the object from moving (this anticipates changes on the  	// simulator in LLTask::userSelect) @@ -1033,7 +1033,7 @@ void LLSelectMgr::addAsFamily(std::vector<LLViewerObject*>& objects, BOOL add_to  //-----------------------------------------------------------------------------  // addAsIndividual() - a single object, face, etc  //----------------------------------------------------------------------------- -void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable) +void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable, S32 gltf_node, S32 gltf_primitive)  {  	// check to see if object is already in list  	LLSelectNode *nodep = mSelectedObjects->findNode(objectp); @@ -1080,6 +1080,13 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab  		return;  	} +    // Handle glTF node selection +    if (gltf_node >= 0) +    { +        nodep->selectGLTFNode(gltf_node, gltf_primitive, TRUE); +      +    } +  	saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);  	updateSelectionCenter();  	dialog_refresh_all(); @@ -5211,46 +5218,57 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type)  			{  				return true; // skip  			} -			selectNode->mSavedPositionLocal = object->getPosition(); -			if (object->isAttachment()) -			{ -				if (object->isRootEdit()) -				{ -					LLXform* parent_xform = object->mDrawable->getXform()->getParent(); -					if (parent_xform) -					{ -						selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition()); -					} -					else -					{ -						selectNode->mSavedPositionGlobal = object->getPositionGlobal(); -					} -				} -				else -				{ -					LLViewerObject* attachment_root = (LLViewerObject*)object->getParent(); -					LLXform* parent_xform = attachment_root ? attachment_root->mDrawable->getXform()->getParent() : NULL; -					if (parent_xform) -					{ -						LLVector3 root_pos = (attachment_root->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); -						LLQuaternion root_rot = (attachment_root->getRotation() * parent_xform->getWorldRotation()); -						selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * root_rot) + root_pos); -					} -					else -					{ -						selectNode->mSavedPositionGlobal = object->getPositionGlobal(); -					} -				} -				selectNode->mSavedRotation = object->getRenderRotation(); -			} -			else -			{ -				selectNode->mSavedPositionGlobal = object->getPositionGlobal(); -				selectNode->mSavedRotation = object->getRotationRegion(); -			} -		 -			selectNode->mSavedScale = object->getScale(); -			selectNode->saveTextureScaleRatios(mManager->mTextureChannel);			 + +            if (selectNode->mSelectedGLTFNode != -1) +            { +                // save GLTF node state +                object->getGLTFNodeTransformAgent(selectNode->mSelectedGLTFNode, &selectNode->mSavedPositionLocal, &selectNode->mSavedRotation, &selectNode->mSavedScale); +                selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent(selectNode->mSavedPositionLocal); +                selectNode->mLastMoveLocal.setZero(); +            } +            else +            { +                selectNode->mSavedPositionLocal = object->getPosition(); +                if (object->isAttachment()) +                { +                    if (object->isRootEdit()) +                    { +                        LLXform* parent_xform = object->mDrawable->getXform()->getParent(); +                        if (parent_xform) +                        { +                            selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition()); +                        } +                        else +                        { +                            selectNode->mSavedPositionGlobal = object->getPositionGlobal(); +                        } +                    } +                    else +                    { +                        LLViewerObject* attachment_root = (LLViewerObject*)object->getParent(); +                        LLXform* parent_xform = attachment_root ? attachment_root->mDrawable->getXform()->getParent() : NULL; +                        if (parent_xform) +                        { +                            LLVector3 root_pos = (attachment_root->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); +                            LLQuaternion root_rot = (attachment_root->getRotation() * parent_xform->getWorldRotation()); +                            selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * root_rot) + root_pos); +                        } +                        else +                        { +                            selectNode->mSavedPositionGlobal = object->getPositionGlobal(); +                        } +                    } +                    selectNode->mSavedRotation = object->getRenderRotation(); +                } +                else +                { +                    selectNode->mSavedPositionGlobal = object->getPositionGlobal(); +                    selectNode->mSavedRotation = object->getRotationRegion(); +                } + +                selectNode->mSavedScale = object->getScale(); +                selectNode->saveTextureScaleRatios(mManager->mTextureChannel); +            }  			return true;  		}  	} func(action_type, this); @@ -6682,8 +6700,7 @@ LLSelectNode::~LLSelectNode()          }      } - -	delete mPermissions; +    delete mPermissions;  	mPermissions = NULL;  } @@ -6711,6 +6728,17 @@ void LLSelectNode::selectTE(S32 te_index, BOOL selected)  	mLastTESelected = te_index;  } +void LLSelectNode::selectGLTFNode(S32 node_index, S32 primitive_index, bool selected) +{ +    if (node_index < 0) +    { +        return; +    } + +    mSelectedGLTFNode = node_index; +    mSelectedGLTFPrimitive = primitive_index; +} +  BOOL LLSelectNode::isTESelected(S32 te_index) const  {  	if (te_index < 0 || te_index >= mObject->getNumTEs()) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index f89209b437..66c794af4c 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -175,6 +175,7 @@ public:  	void selectAllTEs(BOOL b);  	void selectTE(S32 te_index, BOOL selected); +    void selectGLTFNode(S32 node_index, S32 primitive_index, bool selected);  	BOOL isTESelected(S32 te_index) const;  	bool hasSelectedTE() const { return TE_SELECT_MASK_ALL & mTESelectMask; }  	S32 getLastSelectedTE() const; @@ -217,6 +218,7 @@ public:  	S16				mInventorySerial;  	LLVector3		mSavedPositionLocal;	// for interactively modifying object position  	LLVector3		mLastPositionLocal; +    LLVector3		mLastMoveLocal;  	LLVector3d		mSavedPositionGlobal;	// for interactively modifying object position  	LLVector3		mSavedScale;			// for interactively modifying object scale  	LLVector3		mLastScale; @@ -240,11 +242,14 @@ public:  	std::vector<LLVector3>	mSilhouetteVertices;	// array of vertices to render silhouette of object  	std::vector<LLVector3>	mSilhouetteNormals;	// array of normals to render silhouette of object  	BOOL					mSilhouetteExists;	// need to generate silhouette? +    S32             mSelectedGLTFNode = -1; +    S32             mSelectedGLTFPrimitive = -1;  protected:  	LLPointer<LLViewerObject>	mObject;  	S32				mTESelectMask;  	S32				mLastTESelected; +      };  class LLObjectSelection : public LLRefCount @@ -533,7 +538,7 @@ public:  	LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE, BOOL ignore_select_owned = FALSE);  	// For when you want just a child object. -	LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES); +    LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES, S32 gltf_node = -1, S32 gltf_primitive = -1);  	// Same as above, but takes a list of objects.  Used by rectangle select.  	LLObjectSelectionHandle selectObjectAndFamily(const std::vector<LLViewerObject*>& object_list, BOOL send_to_sim = TRUE); @@ -833,7 +838,7 @@ public:  	void remove(std::vector<LLViewerObject*>& objects);  	void remove(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE);  	void removeAll(); -	void addAsIndividual(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE); +	void addAsIndividual(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE, S32 gltf_node = -1, S32 gltf_primitive = -1);  	void promoteSelectionToRoot();  	void demoteSelectionToIndividuals(); diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index 40e6f285a8..49c35165e6 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -87,20 +87,30 @@ void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material,      {          strip_alpha_channel(mr_img); -        if (occlusion_img && material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index) +        if (occlusion_img)          { -            // occlusion is a distinct texture from pbrMetallicRoughness -            // pack into mr red channel -            int occlusion_idx = material.occlusionTexture.index; -            int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index; -            if (occlusion_idx != mr_idx) +            if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index)              { -                //scale occlusion image to match resolution of mr image -                occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight()); - -                copy_red_channel(occlusion_img, mr_img); +                // occlusion is a distinct texture from pbrMetallicRoughness +                // pack into mr red channel +                int occlusion_idx = material.occlusionTexture.index; +                int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index; +                if (occlusion_idx != mr_idx) +                { +                    //scale occlusion image to match resolution of mr image +                    occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight()); + +                    copy_red_channel(occlusion_img, mr_img); +                }              }          } +        else +        { +            // no occlusion, make a white occlusion image +            occlusion_img = new LLImageRaw(mr_img->getWidth(), mr_img->getHeight(), 3); +            occlusion_img->clear(255, 255, 255); +            copy_red_channel(occlusion_img, mr_img); +        }      }      else if (occlusion_img)      { diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index f7455c6cb8..907cec4d17 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -173,7 +173,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi  			if ( ignore_group )  			{ -				LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES); +				LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES, pick.mGLTFNodeIndex, pick.mGLTFPrimitiveIndex);  			}  			else  			{ diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4cf948f20d..9f377ae3e7 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -996,6 +996,10 @@ U64 info_display_from_string(std::string info_display)  	{  		return LLPipeline::RENDER_DEBUG_OCTREE;  	} +    else if ("nodes" == info_display) +    { +        return LLPipeline::RENDER_DEBUG_NODES; +    }  	else if ("shadow frusta" == info_display)  	{  		return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index cee00db8eb..b66d4b1dab 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4374,6 +4374,168 @@ const LLVector3 &LLViewerObject::getPositionAgent() const  	return mPositionAgent;  } +LLMatrix4a LLViewerObject::getGLTFAssetToAgentTransform() const +{ +    LLMatrix4 root; +    root.initScale(getScale()); +    root.rotate(getRenderRotation()); +    root.translate(getPositionAgent()); + +    LLMatrix4a mat; +    mat.loadu((F32*)root.mMatrix); + +    return mat; +} + +LLVector3 LLViewerObject::getGLTFNodePositionAgent(S32 node_index) const +{ +    LLVector3 ret; +    getGLTFNodeTransformAgent(node_index, &ret, nullptr, nullptr); +    return ret; + +} + +LLMatrix4a LLViewerObject::getAgentToGLTFAssetTransform() const +{ +    LLMatrix4 root; +    LLVector3 scale = getScale(); +    scale.mV[0] = 1.f / scale.mV[0]; +    scale.mV[1] = 1.f / scale.mV[1]; +    scale.mV[2] = 1.f / scale.mV[2]; + +    root.translate(-getPositionAgent()); +    root.rotate(~getRenderRotation()); + +    LLMatrix4 scale_mat; +    scale_mat.initScale(scale); + +    root *= scale_mat; +    LLMatrix4a mat; +    mat.loadu((F32*)root.mMatrix); + +    return mat; +} + +LLMatrix4a LLViewerObject::getGLTFNodeTransformAgent(S32 node_index) const +{ +    LLMatrix4a mat; + +    if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) +    { +        auto& node = mGLTFAsset->mNodes[node_index]; + +        LLMatrix4a asset_to_agent = getGLTFAssetToAgentTransform(); +        LLMatrix4a node_to_agent; +        matMul(node.mAssetMatrix, asset_to_agent, node_to_agent); + +        mat = node_to_agent; +    } +    else +    { +        mat.setIdentity(); +    } + +    return mat; +} +void LLViewerObject::getGLTFNodeTransformAgent(S32 node_index, LLVector3* position, LLQuaternion* rotation, LLVector3* scale) const +{ +    LLMatrix4a node_to_agent = getGLTFNodeTransformAgent(node_index); + +    if (position) +    { +        LLVector4a p = node_to_agent.getTranslation(); +        position->set(p.getF32ptr()); +    } + +    if (rotation) +    { +        rotation->set(node_to_agent.asMatrix4()); +    } + +    if (scale) +    { +        scale->mV[0] = node_to_agent.mMatrix[0].getLength3().getF32(); +        scale->mV[1] = node_to_agent.mMatrix[1].getLength3().getF32(); +        scale->mV[2] = node_to_agent.mMatrix[2].getLength3().getF32(); +    } +} + +void decomposeMatrix(const LLMatrix4a& mat, LLVector3& position, LLQuaternion& rotation, LLVector3& scale) +{ +    LLVector4a p = mat.getTranslation(); +    position.set(p.getF32ptr()); + +    rotation.set(mat.asMatrix4()); + +    scale.mV[0] = mat.mMatrix[0].getLength3().getF32(); +    scale.mV[1] = mat.mMatrix[1].getLength3().getF32(); +    scale.mV[2] = mat.mMatrix[2].getLength3().getF32(); +} + +void LLViewerObject::setGLTFNodeRotationAgent(S32 node_index, const LLQuaternion& rotation) +{ +    if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) +    { +        auto& node = mGLTFAsset->mNodes[node_index]; + +        LLMatrix4a agent_to_asset = getAgentToGLTFAssetTransform(); +        LLMatrix4a agent_to_node = agent_to_asset; + +        if (node.mParent != -1) +        { +            auto& parent = mGLTFAsset->mNodes[node.mParent]; +            matMul(agent_to_asset, parent.mAssetMatrixInv, agent_to_node); +        } + +        LLQuaternion agent_to_node_rot(agent_to_node.asMatrix4()); +        LLQuaternion new_rot; + +        new_rot = rotation * agent_to_node_rot; +        new_rot.normalize(); + +        LLVector3 pos; +        LLQuaternion rot; +        LLVector3 scale; +        decomposeMatrix(node.mMatrix, pos, rot, scale); + +        node.mMatrix.asMatrix4().initAll(scale, new_rot, pos); + +        mGLTFAsset->updateTransforms(); +    } +} + +void LLViewerObject::moveGLTFNode(S32 node_index, const LLVector3& offset) +{ +    if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) +    { +        auto& node = mGLTFAsset->mNodes[node_index]; + +        LLMatrix4a agent_to_asset = getAgentToGLTFAssetTransform(); +        LLMatrix4a agent_to_node; +        matMul(agent_to_asset, node.mAssetMatrixInv, agent_to_node); + +        LLVector4a origin = LLVector4a::getZero(); +        LLVector4a offset_v; +        offset_v.load3(offset.mV); +         + +        agent_to_node.affineTransform(offset_v, offset_v); +        agent_to_node.affineTransform(origin, origin); + +        offset_v.sub(origin); +        offset_v.getF32ptr()[3] = 1.f; + +        LLMatrix4a trans; +        trans.setIdentity(); +        trans.mMatrix[3] = offset_v; + +        matMul(trans, node.mMatrix, node.mMatrix); + +        // TODO -- only update transforms for this node and its children (or use a dirty flag) +        mGLTFAsset->updateTransforms(); +    } +} +  const LLVector3 &LLViewerObject::getPositionRegion() const  {  	if (!isRoot()) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 3d6903d177..64c1ee6633 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -315,6 +315,18 @@ public:  	virtual const LLVector3 &getPositionAgent() const;  	virtual const LLVector3 getRenderPosition() const; +    LLMatrix4a getAgentToGLTFAssetTransform() const; +    LLMatrix4a getGLTFAssetToAgentTransform() const; +    LLVector3 getGLTFNodePositionAgent(S32 node_index) const; +    LLMatrix4a getGLTFNodeTransformAgent(S32 node_index) const; +    void getGLTFNodeTransformAgent(S32 node_index, LLVector3* position, LLQuaternion* rotation, LLVector3* scale) const; +     +    // move the node at the given index by the given offset in agent space +    void moveGLTFNode(S32 node_index, const LLVector3& offset); + +    // set the rotation in agent space of the given node +    void setGLTFNodeRotationAgent(S32 node_index, const LLQuaternion& rotation); +  	virtual const LLVector3 getPivotPositionAgent() const; // Usually = to getPositionAgent, unless like flex objects it's not  	LLViewerObject* getRootEdit() const; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1459686f10..a0b0fabb66 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -246,6 +246,8 @@ LLVector2        gDebugRaycastTexCoord;  LLVector4a       gDebugRaycastNormal;  LLVector4a       gDebugRaycastTangent;  S32				gDebugRaycastFaceHit; +S32             gDebugRaycastGLTFNodeHit; +S32             gDebugRaycastGLTFPrimitiveHit;  LLVector4a		 gDebugRaycastStart;  LLVector4a		 gDebugRaycastEnd; @@ -3348,9 +3350,11 @@ void LLViewerWindow::updateUI()  	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))  	{ -		gDebugRaycastFaceHit = -1; +		gDebugRaycastFaceHit = gDebugRaycastGLTFNodeHit = gDebugRaycastGLTFPrimitiveHit = -1;  		gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, FALSE,  											  &gDebugRaycastFaceHit, +                                              &gDebugRaycastGLTFNodeHit, +                                              &gDebugRaycastGLTFPrimitiveHit,  											  &gDebugRaycastIntersection,  											  &gDebugRaycastTexCoord,  											  &gDebugRaycastNormal, @@ -4343,6 +4347,8 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de                                                  BOOL pick_unselectable,                                                  BOOL pick_reflection_probe,  												S32* face_hit, +                                                S32* gltf_node_hit, +                                                S32* gltf_primitive_hit,  												LLVector4a *intersection,  												LLVector2 *uv,  												LLVector4a *normal, @@ -4436,7 +4442,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de  		if (!found) // if not found in HUD, look in world:  		{  			found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, -														  face_hit, intersection, uv, normal, tangent); +														  face_hit, gltf_node_hit, gltf_primitive_hit, intersection, uv, normal, tangent);  			if (found && !pick_transparent)  			{  				gDebugRaycastIntersection = *intersection; @@ -6140,8 +6146,8 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,  void LLPickInfo::fetchResults()  { -  	S32 face_hit = -1; +  	LLVector4a intersection, normal;  	LLVector4a tangent; @@ -6164,8 +6170,8 @@ void LLPickInfo::fetchResults()  	}  	LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, -									NULL, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &face_hit, -									&intersection, &uv, &normal, &tangent, &start, &end); +									nullptr, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &face_hit, &mGLTFNodeIndex, &mGLTFPrimitiveIndex, +                                &intersection, &uv, &normal, &tangent, &start, &end);  	mPickPt = mMousePt; @@ -6311,6 +6317,8 @@ void LLPickInfo::getSurfaceInfo()  		if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f,  										   objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe,  										   &mObjectFace, +                                           &mGLTFNodeIndex, +                                           &mGLTFPrimitiveIndex,  										   &intersection,  										   &mSTCoords,  										   &normal, diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ad634503ba..2e90c5faeb 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -119,6 +119,8 @@ public:  	LLUUID			mParticleOwnerID;  	LLUUID			mParticleSourceID;  	S32				mObjectFace; +    S32             mGLTFNodeIndex = -1; +    S32             mGLTFPrimitiveIndex = -1;  	LLHUDIcon*		mHUDIcon;  	LLVector3       mIntersection;  	LLVector2		mUVCoords; @@ -423,6 +425,8 @@ public:                                      BOOL pick_unselectable = TRUE,                                      BOOL pick_reflection_probe = TRUE,  									S32* face_hit = NULL, +                                    S32* gltf_node_hit = nullptr, +                                    S32* gltf_primitive_hit = nullptr,  									LLVector4a *intersection = NULL,  									LLVector2 *uv = NULL,  									LLVector4a *normal = NULL, diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ea40365c97..3adf2828f8 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6309,6 +6309,8 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,                                                          bool pick_unselectable,                                                          bool pick_reflection_probe,  														S32* face_hit, +                                                        S32* gltf_node_hit, +                                                        S32* gltf_primitive_hit,  														LLVector4a* intersection,         // return the intersection point  														LLVector2* tex_coord,            // return the texture coordinates of the intersection point  														LLVector4a* normal,               // return the surface normal at the intersection point @@ -6352,15 +6354,6 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,  		}  	} -    S32 node_hit = -1; -    S32 primitive_hit = -1; -    LLDrawable* hit = LL::GLTFSceneManager::instance().lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, &node_hit, &primitive_hit, &position, tex_coord, normal, tangent); -    if (hit) -    { -        drawable = hit; -        local_end = position; -    } -	  	if (!sPickAvatar)  	{  		//save hit info in case we need to restore @@ -6461,6 +6454,25 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,  		}  	} +    S32 node_hit = -1; +    S32 primitive_hit = -1; +    LLDrawable* hit = LL::GLTFSceneManager::instance().lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, &node_hit, &primitive_hit, &position, tex_coord, normal, tangent); +    if (hit) +    { +        drawable = hit; +        local_end = position; +    } + +    if (gltf_node_hit) +    { +        *gltf_node_hit = node_hit; +    } +     +    if (gltf_primitive_hit) +    { +        *gltf_primitive_hit = primitive_hit; +    } +  	if (intersection)  	{  		*intersection = position; @@ -7269,7 +7281,7 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)  					LLVector4a result;  					result.clear(); -					gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, NULL, &result); +					gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, nullptr, nullptr, nullptr, &result);  					focus_point.set(result.getF32ptr());  				} diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 817750b4a1..bfa4009a0b 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -210,6 +210,8 @@ public:                                                  bool pick_unselectable,                                                  bool pick_reflection_probe,  												S32* face_hit,                          // return the face hit +                                                S32* gltf_node_hit = nullptr,           // return the gltf node hit +                                                S32* gltf_primitive_hit = nullptr,      // return the gltf primitive hit  												LLVector4a* intersection = NULL,         // return the intersection point  												LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point  												LLVector4a* normal = NULL,               // return the surface normal at the intersection point @@ -615,12 +617,12 @@ public:  		RENDER_DEBUG_PHYSICS_SHAPES     =  0x02000000,  		RENDER_DEBUG_NORMALS	        =  0x04000000,  		RENDER_DEBUG_LOD_INFO	        =  0x08000000, -		RENDER_DEBUG_ATTACHMENT_BYTES	=  0x20000000, // not used +        RENDER_DEBUG_NODES              =  0x20000000,  		RENDER_DEBUG_TEXEL_DENSITY		=  0x40000000,  		RENDER_DEBUG_TRIANGLE_COUNT		=  0x80000000,  		RENDER_DEBUG_IMPOSTORS			= 0x100000000,          RENDER_DEBUG_REFLECTION_PROBES  = 0x200000000, -        RENDER_DEBUG_PROBE_UPDATES      = 0x400000000 +        RENDER_DEBUG_PROBE_UPDATES      = 0x400000000,  	};  public: diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index c2f04231fc..a366e78a2d 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2889,6 +2889,16 @@ function="World.EnvPreset"             parameter="octree" />          </menu_item_check>          <menu_item_check +         label="GLTF Nodes" +         name="GLTF Nodes"> +          <menu_item_check.on_check +           function="Advanced.CheckInfoDisplay" +           parameter="nodes" /> +          <menu_item_check.on_click +           function="Advanced.ToggleInfoDisplay" +           parameter="nodes" /> +        </menu_item_check> +        <menu_item_check           label="Shadow Frusta"           name="Shadow Frusta">            <menu_item_check.on_check  | 
