Fixed culling to take scale into consideration 56/67856/13
authorFerran Sole <ferran.sole@samsung.com>
Thu, 28 Apr 2016 16:43:28 +0000 (17:43 +0100)
committerFerran Sole <ferran.sole@samsung.com>
Thu, 5 May 2016 13:27:24 +0000 (14:27 +0100)
- Culling wasn't considering world scale
- Optimized world space bounding sphere calculation for nodes in the scene

Change-Id: Icf5e7918e038a662bb5e63b7b48a404da5c63d86

dali/internal/common/math.cpp [new file with mode: 0644]
dali/internal/common/math.h [new file with mode: 0644]
dali/internal/file.list
dali/internal/render/common/render-item.h
dali/internal/update/manager/prepare-render-instructions.cpp
dali/internal/update/manager/transform-manager.cpp
dali/internal/update/manager/transform-manager.h
dali/internal/update/nodes/node.h

diff --git a/dali/internal/common/math.cpp b/dali/internal/common/math.cpp
new file mode 100644 (file)
index 0000000..1e3c051
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/math.h>
+
+//EXTERNAL INCLUDES
+#include <cmath>
+
+void Dali::Internal::TransformVector3( Vec3 result, const Mat4 m, const Vec3 v )
+{
+#ifndef __ARM_NEON__
+
+  result[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8];
+  result[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9];
+  result[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10];
+
+#else
+
+  Vec4 temp = { v[0], v[1], v[2], 0.0f };
+  Vec4 tempResult;
+
+  asm volatile ( "VLD1.F32   {q0}, [%1]     \n\t"  //Load "temp" from memory to register q0
+                 "VLD1.F32   {q1}, [%0]!    \n\t"  //Load first row of the matrix from memory to register q1
+                 "VMUL.F32   q2, q1, d0[0]  \n\t"  //q2 = (m[0..3] * v.x)
+                 "VLD1.F32   {q1}, [%0]!    \n\t"  //Load second row of the matrix from memory
+                 "VMLA.F32   q2, q1, d0[1]  \n\t"  //q2 = (m[0..3] * v.x) + (m[4..7] * v.y)
+                 "VLD1.F32   {q1}, [%0]!    \n\t"  //Load third row of the matrix from memory
+                 "VMLA.F32   q2, q1, d1[0]  \n\t"  //q2 = (m[0..3] * v.x) + (m[4..7] * v.y) + (m[8...11] * v.z)
+                 "VST1.F32   {q2}, [%2]     \n\t"  //Write the result back to memory
+                 :
+                 : "r"(m), "r"(temp), "r"(tempResult)
+                 : "q0", "q1", "q2", "memory" );
+
+  result[0] = tempResult[0];
+  result[1] = tempResult[1];
+  result[2] = tempResult[2];
+
+#endif
+}
+
+float Dali::Internal::Length( const Vec3 v )
+{
+  return sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+}
diff --git a/dali/internal/common/math.h b/dali/internal/common/math.h
new file mode 100644 (file)
index 0000000..ebb6291
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __DALI_INTERNAL_MATH_H__
+#define __DALI_INTERNAL_MATH_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef float Vec3[3];
+typedef float Vec4[4];
+typedef float Mat4[16];
+
+/**
+ * @brief Applies a transformation matrix to a vector
+ *
+ * @param[out] result The transformed vector
+ * @param[in] m The transformation matrix
+ * @param[in] v The vector to transform
+ */
+void TransformVector3( Vec3 result, const Mat4 m, const Vec3 v );
+
+/**
+ * @brief Computes the length of a vector3
+ *
+ * @param[in] v The vector
+ * @return The lenght of the vector
+ */
+float Length( const Vec3 v );
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif  //__DALI_INTERNAL_MATH_H__
index b60aeff..611fb10 100644 (file)
@@ -4,6 +4,7 @@ internal_src_files = \
   $(internal_src_dir)/common/blending-options.cpp \
   $(internal_src_dir)/common/core-impl.cpp \
   $(internal_src_dir)/common/internal-constants.cpp \
+  $(internal_src_dir)/common/math.cpp \
   $(internal_src_dir)/common/message-buffer.cpp \
   $(internal_src_dir)/common/mutex-impl.cpp \
   $(internal_src_dir)/common/image-sampler.cpp \
index 85c6fb9..a309f3a 100644 (file)
@@ -137,19 +137,19 @@ public:
   }
 
   /**
-   * Sets the size of the render item
-   * @param[in] size The size of the render item
+   * Retrives the size of the render item
+   * @return The size of the render item
    */
-  void SetSize( const Vector3& size)
+  const Vector3& GetSize() const
   {
-    mSize = size;
+    return mSize;
   }
 
   /**
    * Retrives the size of the render item
    * @return The size of the render item
    */
-  const Vector3& GetSize() const
+  Vector3& GetSize()
   {
     return mSize;
   }
index 0ba1729..2b393e0 100644 (file)
@@ -70,16 +70,11 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
                                      bool cull )
 {
   bool inside( true );
-
-  const Matrix& worldMatrix = renderable.mNode->GetWorldMatrix( updateBufferIndex );
-  const Vector3& size = renderable.mNode->GetSize( updateBufferIndex );
   if ( cull && !renderable.mRenderer->GetShader().HintEnabled( Dali::Shader::HINT_MODIFIES_GEOMETRY ) )
   {
-    const Vector3& position = worldMatrix.GetTranslation3();
-    float radius( size.Length() * 0.5f );
-
-    inside = (radius > Math::MACHINE_EPSILON_1000) &&
-        (cameraAttachment.CheckSphereInFrustum( updateBufferIndex, position, radius ) );
+    const Vector4& boundingSphere = renderable.mNode->GetBoundingSphere();
+    inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) &&
+             (cameraAttachment.CheckSphereInFrustum( updateBufferIndex, Vector3(boundingSphere), boundingSphere.w ) );
   }
 
   if ( inside )
@@ -102,8 +97,8 @@ inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
         item.SetDepthIndex( renderable.mRenderer->GetDepthIndex() + static_cast<int>( renderable.mNode->GetDepth() ) * Dali::Layer::TREE_DEPTH_MULTIPLIER );
       }
       // save MV matrix onto the item
+      const Matrix& worldMatrix = renderable.mNode->GetWorldMatrixAndSize( item.GetSize() );
       Matrix::Multiply( item.GetModelViewMatrix(), worldMatrix, viewMatrix );
-      item.SetSize( size );
     }
   }
 }
index 4d76f33..09a70e1 100644 (file)
@@ -25,6 +25,7 @@
 //INTERNAL INCLUDES
 #include <dali/public-api/common/constants.h>
 #include <dali/public-api/common/compile-time-assert.h>
+#include <dali/internal/common/math.h>
 
 namespace Dali
 {
@@ -71,6 +72,7 @@ TransformId TransformManager::CreateTransform()
     mParent.PushBack(INVALID_TRANSFORM_ID);
     mWorld.PushBack(Matrix::IDENTITY);
     mLocal.PushBack(Matrix::IDENTITY);
+    mBoundingSpheres.PushBack( Vector4(0.0f,0.0f,0.0f,0.0f) );
     mTxComponentAnimatableBaseValue.PushBack(TransformComponentAnimatable());
     mSizeBase.PushBack(Vector3(0.0f,0.0f,0.0f));
     mComponentDirty.PushBack(false);
@@ -88,6 +90,7 @@ TransformId TransformManager::CreateTransform()
     mParent[mComponentCount] = INVALID_TRANSFORM_ID;
     mLocal[mComponentCount].SetIdentity();
     mWorld[mComponentCount].SetIdentity();
+    mBoundingSpheres[mComponentCount] = Vector4(0.0f,0.0f,0.0f,0.0f);
     mSizeBase[mComponentCount] = Vector3(0.0f,0.0f,0.0f);
     mComponentDirty[mComponentCount] = false;
     mLocalMatrixDirty[mComponentCount] = false;
@@ -113,6 +116,7 @@ void TransformManager::RemoveTransform(TransformId id)
   mSizeBase[index] = mSizeBase[mComponentCount];
   mComponentDirty[index] = mComponentDirty[mComponentCount];
   mLocalMatrixDirty[index] = mLocalMatrixDirty[mComponentCount];
+  mBoundingSpheres[index] = mBoundingSpheres[mComponentCount];
 
   TransformId lastItemId = mComponentId[mComponentCount];
   mIds[ lastItemId ] = index;
@@ -227,6 +231,7 @@ void TransformManager::Update()
           mLocal[i].SetTransformComponents( mTxComponentAnimatable[i].mScale,mTxComponentAnimatable[i].mOrientation, localPosition );
         }
 
+        //Update the world matrix
         Matrix::Multiply( mWorld[i], mLocal[i], mWorld[parentIndex]);
       }
       else
@@ -276,6 +281,14 @@ void TransformManager::Update()
       localPosition = mTxComponentAnimatable[i].mPosition + anchorPosition;
       mWorld[i].SetTransformComponents( mTxComponentAnimatable[i].mScale, mTxComponentAnimatable[i].mOrientation, localPosition );
     }
+
+    //Update the bounding sphere
+    Vec3 centerToEdge = { mSize[i].Length() * 0.5f, 0.0f, 0.0f };
+    Vec3 centerToEdgeWorldSpace;
+    TransformVector3( centerToEdgeWorldSpace, mWorld[i].AsFloat(), centerToEdge );
+
+    mBoundingSpheres[i] = mWorld[i].GetTranslation();
+    mBoundingSpheres[i].w = Length( centerToEdgeWorldSpace );
   }
 }
 
@@ -291,6 +304,7 @@ void TransformManager::SwapComponents( unsigned int i, unsigned int j )
   std::swap( mSizeBase[i], mSizeBase[j] );
   std::swap( mLocal[i], mLocal[j] );
   std::swap( mComponentDirty[i], mComponentDirty[j] );
+  std::swap( mBoundingSpheres[i], mBoundingSpheres[j] );
 
   mIds[ mComponentId[i] ] = i;
   mIds[ mComponentId[j] ] = j;
@@ -811,6 +825,18 @@ void TransformManager::BakeRelativeQuaternionPropertyValue( TransformId id, cons
   mComponentDirty[ index ] = true;
 }
 
+const Vector4& TransformManager::GetBoundingSphere( TransformId id ) const
+{
+  return mBoundingSpheres[ mIds[id] ];
+}
+
+const Matrix& TransformManager::GetWorldMatrixAndSize( TransformId id, Vector3& size ) const
+{
+  unsigned int index = mIds[id];
+  size = mSize[index];
+  return mWorld[index];
+}
+
 } //namespace SceneGraph
 } //namespace Internal
 } //namespace Dali
index 445b103..45bc00d 100644 (file)
@@ -324,6 +324,21 @@ public:
    */
   void BakeRelativeQuaternionPropertyValue( TransformId id, const Quaternion& q );
 
+  /**
+   * Get the bounding sphere, in world coordinates, of a given component
+   * @param[in] id Id of the transform component
+   * @return The world space bounding sphere of the component
+   */
+  const Vector4& GetBoundingSphere( TransformId id ) const;
+
+  /**
+   * Get the world matrix and size of a given component
+   * @param[in] id Id of the transform component
+   * @param[out] size size of the component
+   * @return The world matrix of the component
+   */
+  const Matrix& GetWorldMatrixAndSize( TransformId id, Vector3& size ) const;
+
 private:
 
   //Helper struct to order components
@@ -358,13 +373,13 @@ private:
   Vector<TransformId> mParent;                                 ///< Parent of the components
   Vector<Matrix> mWorld;                                       ///< Local to world transform of the components
   Vector<Matrix> mLocal;                                       ///< Local to parent space transform of the components
+  Vector<Vector4> mBoundingSpheres;                            ///< Bounding spheres. xyz is the center and w is the radius
   Vector<TransformComponentAnimatable> mTxComponentAnimatableBaseValue;  ///< Base values for the animatable part of the components
   Vector<Vector3> mSizeBase;                                             ///< Base value for the size of the components
   Vector<bool> mComponentDirty;    ///< 1u if some of the parts of the component has changed in this frame, 0 otherwise
   Vector<bool> mLocalMatrixDirty;  ///< 1u if the local matrix has been updated in this frame, 0 otherwise
   Vector<SOrderItem> mOrderedComponents;   ///< Used to reorder components when hierarchy changes
   bool mReorder;                           ///< Flag to determine if the components have to reordered in the next Update
-
 };
 
 } //namespace SceneGraph
index 534a40a..9b239e0 100644 (file)
@@ -605,6 +605,35 @@ public:
   }
 
   /**
+   * Retrieve the bounding sphere of the node
+   * @return A vector4 describing the bounding sphere. XYZ is the center and W is the radius
+   */
+  const Vector4& GetBoundingSphere() const
+  {
+    if( mTransformId != INVALID_TRANSFORM_ID )
+    {
+      return mTransformManager->GetBoundingSphere( mTransformId );
+    }
+
+    return Vector4::ZERO;
+  }
+
+  /**
+   * Retrieve world matrix and size of the node
+   *
+   * @param[out] size The current size of the node
+   * @return The local to world matrix of the node
+   */
+  const Matrix& GetWorldMatrixAndSize( Vector3& size ) const
+  {
+    if( mTransformId != INVALID_TRANSFORM_ID )
+    {
+      return mTransformManager->GetWorldMatrixAndSize( mTransformId, size );
+    }
+    return Matrix::IDENTITY;
+  }
+
+  /**
    * Checks if local matrix has changed since last update
    * @return true if local matrix has changed, false otherwise
    */