diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index f3542a1e3c20d686fa758f6f5802153ae9e07a53..0d6cee99ea5671ff8358ebbc3fac0df5d4f16f95 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -848,6 +848,7 @@ const uint8_t g_triangleWeightLengthChroma[2][2] = { { 5, 7 }, { 3, 3 } };
 
       uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
 
+#if !JVET_M0883_TRIANGLE_SIGNALING
 const uint8_t g_triangleCombination[TRIANGLE_MAX_NUM_CANDS][3] =
 {
   { 0, 1, 0 }, { 1, 0, 1 }, { 1, 0, 2 }, { 0, 0, 1 }, { 0, 2, 0 }, 
@@ -867,4 +868,5 @@ const uint8_t g_triangleIdxBins[TRIANGLE_MAX_NUM_CANDS] =
    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
   10, 10, 10, 10, 10, 10, 10, 10, 10, 10
 };
+#endif
 //! \}
diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h
index eea194c33899c8b776e0ae534f949b7f200113f9..63520f58e341698dc48697f9fa38263bd9aa8cf7 100644
--- a/source/Lib/CommonLib/Rom.h
+++ b/source/Lib/CommonLib/Rom.h
@@ -253,8 +253,10 @@ extern const uint8_t g_triangleWeightLengthLuma[2];
 extern const uint8_t g_triangleWeightLengthChroma[2][2];
 #endif
 extern       uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2];
+#if !JVET_M0883_TRIANGLE_SIGNALING
 extern const uint8_t g_triangleCombination[TRIANGLE_MAX_NUM_CANDS][3];
 extern const uint8_t g_triangleIdxBins[TRIANGLE_MAX_NUM_CANDS];
+#endif
 
 #endif  //__TCOMROM__
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 06c4f8ccf7e6966252afa1d720446fcb8dbd8cc1..f3d93f64a93ff0360dce5a0d09c61691bd54b9c8 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -59,6 +59,7 @@
 #define JVET_M0063_BDOF_FIX                               1 // BDOF bitdepth bugfix
 
 #define JVET_M0265_MV_ROUNDING_CLEANUP                    1 // Unify MV roundings and make SW/WD allignment
+#define JVET_M0883_TRIANGLE_SIGNALING                     1 // Using regular merge index signaling for triangle mode
 
 #define JVET_M0228_REMOVE_CPMV_COMPARE                    1 // Remove CPMV comparisons for construnted affine merge candidates from JVET-M0228, M0166, M0477
 
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index ecaf89ca16990d33b31fcee0e1c6c86d1e0c0d15..ed5f3620d2533279b3321ad3cfe5121cc363e1cf 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -343,6 +343,11 @@ void PredictionUnit::initData()
   // inter data
   mergeFlag   = false;
   mergeIdx    = MAX_UCHAR;
+#if JVET_M0883_TRIANGLE_SIGNALING
+  triangleSplitDir  = MAX_UCHAR;
+  triangleMergeIdx0 = MAX_UCHAR;
+  triangleMergeIdx1 = MAX_UCHAR;
+#endif
   mmvdMergeFlag = false;
   mmvdMergeIdx = MAX_UINT;
   interDir    = MAX_UCHAR;
@@ -388,6 +393,11 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData)
 {
   mergeFlag   = predData.mergeFlag;
   mergeIdx    = predData.mergeIdx;
+#if JVET_M0883_TRIANGLE_SIGNALING
+  triangleSplitDir  = predData.triangleSplitDir  ;
+  triangleMergeIdx0 = predData.triangleMergeIdx0 ;
+  triangleMergeIdx1 = predData.triangleMergeIdx1 ;
+#endif
   mmvdMergeFlag = predData.mmvdMergeFlag;
   mmvdMergeIdx = predData.mmvdMergeIdx;
   interDir    = predData.interDir;
@@ -428,6 +438,11 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
 
   mergeFlag   = other.mergeFlag;
   mergeIdx    = other.mergeIdx;
+#if JVET_M0883_TRIANGLE_SIGNALING
+  triangleSplitDir  = other.triangleSplitDir  ;
+  triangleMergeIdx0 = other.triangleMergeIdx0 ;
+  triangleMergeIdx1 = other.triangleMergeIdx1 ;
+#endif
   mmvdMergeFlag = other.mmvdMergeFlag;
   mmvdMergeIdx = other.mmvdMergeIdx;
   interDir    = other.interDir;
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index 4eb057dde4a9cfe99bc1f4970d4f1e29e9f9613d..db48ffdc6fa9a1252355b6ce62320c37a295b16f 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -358,6 +358,11 @@ struct InterPredictionData
 {
   bool      mergeFlag;
   uint8_t     mergeIdx;
+#if JVET_M0883_TRIANGLE_SIGNALING
+  uint8_t     triangleSplitDir;
+  uint8_t     triangleMergeIdx0;
+  uint8_t     triangleMergeIdx1;
+#endif
   bool           mmvdMergeFlag;
   uint32_t       mmvdMergeIdx;
   uint8_t     interDir;
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 84381632a3c07841b7f90f4adcaee74563ac865e..c997743d28bb1a2ecbc822daa5269f517b7de351 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -3988,7 +3988,6 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl
       candCount++;
     }
   }
-  
   // put uni-prediction candidate to the triangle candidate list
   for( int32_t i = 0; i < candCount; i++ )
   { 
@@ -4150,9 +4149,19 @@ bool PU::getTriangleWeights( const PredictionUnit& pu, MergeCtx &triangleMrgCtx,
 }
 #endif
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
+#else
 void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const uint8_t mergeIdx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
+#endif
 {
+#if JVET_M0883_TRIANGLE_SIGNALING
+  pu.triangleSplitDir = splitDir;
+  pu.triangleMergeIdx0 = candIdx0;
+  pu.triangleMergeIdx1 = candIdx1;
+#else
   pu.mergeIdx  = mergeIdx;
+#endif
   MotionBuf mb = pu.getMotionBuf();
 
   MotionInfo biMv;
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index 4b255d844f1a2a03fc20055866988873bce993d7..3795ed91c9decc2c1068c12130746a8b73bac5af 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -163,7 +163,11 @@ namespace PU
 #if !JVET_M0328_KEEP_ONE_WEIGHT_GROUP
   bool getTriangleWeights             (const PredictionUnit &pu, MergeCtx &triangleMrgCtx, const uint8_t candIdx0, const uint8_t candIdx1);
 #endif
+#if JVET_M0883_TRIANGLE_SIGNALING
+  void spanTriangleMotionInfo         (      PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1);
+#else
   void spanTriangleMotionInfo         (      PredictionUnit &pu, MergeCtx &triangleMrgCtx, const uint8_t mergeIdx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1);
+#endif
   int32_t mappingRefPic               (const PredictionUnit &pu, int32_t refPicPoc, bool targetRefPicList);
   void getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred);
   bool getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv);
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 7f57b25d50054957d4a3adfb2925760ab830a814..265d98ded7b171f372acf87b64cbba858c489921 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -1637,6 +1637,38 @@ void CABACReader::merge_idx( PredictionUnit& pu )
   if( pu.cu->triangle )
   {
     RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__TRIANGLE_INDEX );
+#if JVET_M0883_TRIANGLE_SIGNALING
+    bool    splitDir;
+    uint8_t candIdx0;
+    uint8_t candIdx1;
+    splitDir = m_BinDecoder.decodeBinEP();
+    auto decodeOneIdx = [this](int numCandminus1) -> uint8_t
+    {
+      uint8_t decIdx = 0;
+      if( numCandminus1 > 0 )
+      {
+        if( this->m_BinDecoder.decodeBin( Ctx::MergeIdx() ) )
+        {
+          decIdx++;
+          for( ; decIdx < numCandminus1; decIdx++ )
+          {
+            if( !this->m_BinDecoder.decodeBinEP() )
+              break;
+          }
+        }
+      }
+      return decIdx;
+    };
+    candIdx0 = decodeOneIdx(TRIANGLE_MAX_NUM_UNI_CANDS - 1);
+    candIdx1 = decodeOneIdx(TRIANGLE_MAX_NUM_UNI_CANDS - 2);
+    candIdx1 += candIdx1 >= candIdx0 ? 1 : 0;
+    DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_split_dir=%d\n", splitDir );
+    DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx0=%d\n", candIdx0 );
+    DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx1=%d\n", candIdx1 );
+    pu.triangleSplitDir = splitDir;
+    pu.triangleMergeIdx0 = candIdx0;
+    pu.triangleMergeIdx1 = candIdx1;
+#else
     if( m_BinDecoder.decodeBin( Ctx::TriangleIdx() ) == 0 )
     {
       pu.mergeIdx += m_BinDecoder.decodeBinEP();
@@ -1647,6 +1679,7 @@ void CABACReader::merge_idx( PredictionUnit& pu )
     }
 
     DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx=%d\n", pu.mergeIdx );
+#endif
     return;
   }
 
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 6913f67f690f184b7f47a0e3664118494d989372..b36cb3207e8d2c10913f78b4826506b09c758e22 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -352,12 +352,22 @@ void DecCu::xReconInter(CodingUnit &cu)
 {
   if( cu.triangle )
   {
+#if JVET_M0883_TRIANGLE_SIGNALING
+    const bool    splitDir = cu.firstPU->triangleSplitDir;
+    const uint8_t candIdx0 = cu.firstPU->triangleMergeIdx0;
+    const uint8_t candIdx1 = cu.firstPU->triangleMergeIdx1;
+#else
     const uint8_t mergeIdx = cu.firstPU->mergeIdx;
     const bool    splitDir = g_triangleCombination[mergeIdx][0];
     const uint8_t candIdx0 = g_triangleCombination[mergeIdx][1];
     const uint8_t candIdx1 = g_triangleCombination[mergeIdx][2];
+#endif
     m_pcInterPred->motionCompensation4Triangle( cu, m_triangleMrgCtx, splitDir, candIdx0, candIdx1 );
+#if JVET_M0883_TRIANGLE_SIGNALING
+    PU::spanTriangleMotionInfo( *cu.firstPU, m_triangleMrgCtx, splitDir, candIdx0, candIdx1 );
+#else
     PU::spanTriangleMotionInfo( *cu.firstPU, m_triangleMrgCtx, mergeIdx, splitDir, candIdx0, candIdx1 );
+#endif
   }
   else
   {
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 862ed9835939e286b518776f3f6c1381e626fa7b..010808ea87a76da78ca9084ce4e34f4690cf7a86 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -1519,6 +1519,38 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
   {
     if( pu.cu->triangle )
     {
+#if JVET_M0883_TRIANGLE_SIGNALING
+      bool    splitDir = pu.triangleSplitDir;
+      uint8_t candIdx0 = pu.triangleMergeIdx0;
+      uint8_t candIdx1 = pu.triangleMergeIdx1;
+      DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_split_dir=%d\n", splitDir );
+      DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx0=%d\n", candIdx0 );
+      DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx1=%d\n", candIdx1 );
+      candIdx1 -= candIdx1 < candIdx0 ? 0 : 1;
+      auto encodeOneIdx = [this](uint8_t mrgIdx, int numCandminus1)
+      {
+        if(mrgIdx == 0)
+        {
+          this->m_BinEncoder.encodeBin( 0, Ctx::MergeIdx() );
+          return;
+        }
+        else
+        {
+          this->m_BinEncoder.encodeBin( 1, Ctx::MergeIdx() );
+          for( unsigned idx = 1; idx < numCandminus1; idx++ )
+          {
+            this->m_BinEncoder.encodeBinEP( mrgIdx == idx ? 0 : 1 );
+            if( mrgIdx == idx )
+            {
+              break;
+            }
+          }
+        }
+      };
+      m_BinEncoder.encodeBinEP(splitDir);
+      encodeOneIdx(candIdx0, TRIANGLE_MAX_NUM_UNI_CANDS - 1);
+      encodeOneIdx(candIdx1, TRIANGLE_MAX_NUM_UNI_CANDS - 2);
+#else
       if( pu.mergeIdx < 2 )
       {
         m_BinEncoder.encodeBin( 0, Ctx::TriangleIdx() );
@@ -1531,6 +1563,7 @@ void CABACWriter::merge_idx( const PredictionUnit& pu )
       }
 
       DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() triangle_idx=%d\n", pu.mergeIdx );
+#endif
       return;
     }
   int numCandminus1 = int( pu.cs->slice->getMaxNumMergeCand() ) - 1;
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 048a4fb642d43ecea5036288c951ff829519b89c..018eb4d4f00a2ce7dab68fc11d827980bf5a0cb4 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -64,6 +64,19 @@ extern std::recursive_mutex g_cache_mutex;
 // ====================================================================================================================
 // Constructor / destructor / create / destroy
 // ====================================================================================================================
+#if JVET_M0883_TRIANGLE_SIGNALING
+const TriangleMotionInfo  EncCu::m_triangleModeTest[TRIANGLE_MAX_NUM_CANDS] = 
+{
+  TriangleMotionInfo( 0, 1, 0 ), TriangleMotionInfo( 1, 0, 1 ), TriangleMotionInfo( 1, 0, 2 ), TriangleMotionInfo( 0, 0, 1 ), TriangleMotionInfo( 0, 2, 0 ),
+  TriangleMotionInfo( 1, 0, 3 ), TriangleMotionInfo( 1, 0, 4 ), TriangleMotionInfo( 1, 1, 0 ), TriangleMotionInfo( 0, 3, 0 ), TriangleMotionInfo( 0, 4, 0 ),
+  TriangleMotionInfo( 0, 0, 2 ), TriangleMotionInfo( 0, 1, 2 ), TriangleMotionInfo( 1, 1, 2 ), TriangleMotionInfo( 0, 0, 4 ), TriangleMotionInfo( 0, 0, 3 ),
+  TriangleMotionInfo( 0, 1, 3 ), TriangleMotionInfo( 0, 1, 4 ), TriangleMotionInfo( 1, 1, 4 ), TriangleMotionInfo( 1, 1, 3 ), TriangleMotionInfo( 1, 2, 1 ),
+  TriangleMotionInfo( 1, 2, 0 ), TriangleMotionInfo( 0, 2, 1 ), TriangleMotionInfo( 0, 4, 3 ), TriangleMotionInfo( 1, 3, 0 ), TriangleMotionInfo( 1, 3, 2 ),
+  TriangleMotionInfo( 1, 3, 4 ), TriangleMotionInfo( 1, 4, 0 ), TriangleMotionInfo( 1, 3, 1 ), TriangleMotionInfo( 1, 2, 3 ), TriangleMotionInfo( 1, 4, 1 ),
+  TriangleMotionInfo( 0, 4, 1 ), TriangleMotionInfo( 0, 2, 3 ), TriangleMotionInfo( 1, 4, 2 ), TriangleMotionInfo( 0, 3, 2 ), TriangleMotionInfo( 1, 4, 3 ),
+  TriangleMotionInfo( 0, 3, 1 ), TriangleMotionInfo( 0, 2, 4 ), TriangleMotionInfo( 1, 2, 4 ), TriangleMotionInfo( 0, 4, 2 ), TriangleMotionInfo( 0, 3, 4 ),
+};
+#endif
 
 void EncCu::create( EncCfg* encCfg )
 {
@@ -147,6 +160,20 @@ void EncCu::create( EncCfg* encCfg )
   {
     m_acRealMergeBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxWidth, uiMaxHeight));
   }
+#if JVET_M0883_TRIANGLE_SIGNALING
+  for( unsigned ui = 0; ui < TRIANGLE_MAX_NUM_UNI_CANDS; ui++ )
+  {
+    for( unsigned uj = 0; uj < TRIANGLE_MAX_NUM_UNI_CANDS; uj++ )
+    {
+      if(ui == uj)
+        continue;
+      uint8_t idxBits0 = ui + (ui == TRIANGLE_MAX_NUM_UNI_CANDS - 1 ? 0 : 1);
+      uint8_t candIdx1Enc = uj - (uj > ui ? 1 : 0);
+      uint8_t idxBits1 = candIdx1Enc + (candIdx1Enc == TRIANGLE_MAX_NUM_UNI_CANDS - 2 ? 0 : 1);
+      m_triangleIdxBins[1][ui][uj] = m_triangleIdxBins[0][ui][uj] = 1 + idxBits0 + idxBits1;
+    }
+  }
+#endif
   for( unsigned ui = 0; ui < TRIANGLE_MAX_NUM_CANDS; ui++ )
   {
     m_acTriangleWeightedBuffer[ui].create( chromaFormat, Area( 0, 0, uiMaxWidth, uiMaxHeight ) );
@@ -2363,11 +2390,23 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
 
     for( uint8_t mergeCand = 0; mergeCand < numTriangleCandidate; mergeCand++ )
     {
+#if JVET_M0883_TRIANGLE_SIGNALING
+      bool    splitDir = m_triangleModeTest[mergeCand].m_splitDir;
+      uint8_t candIdx0 = m_triangleModeTest[mergeCand].m_candIdx0;
+      uint8_t candIdx1 = m_triangleModeTest[mergeCand].m_candIdx1;
+#else
       bool    splitDir = g_triangleCombination[mergeCand][0];
       uint8_t candIdx0 = g_triangleCombination[mergeCand][1];
       uint8_t candIdx1 = g_triangleCombination[mergeCand][2];
+#endif
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+      pu.triangleSplitDir = splitDir;
+      pu.triangleMergeIdx0 = candIdx0;
+      pu.triangleMergeIdx1 = candIdx1;
+#else
       pu.mergeIdx  = mergeCand;
+#endif
       pu.mergeFlag = true;
       triangleWeightedBuffer[mergeCand] = m_acTriangleWeightedBuffer[mergeCand].getBuf( localUnitArea );
       triangleBuffer[candIdx0] = m_acMergeBuffer[candIdx0].getBuf( localUnitArea );
@@ -2382,7 +2421,11 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
 
       Distortion uiSad = distParam.distFunc( distParam );
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+      uint32_t uiBitsCand = m_triangleIdxBins[splitDir][candIdx0][candIdx1];
+#else
       uint32_t uiBitsCand = g_triangleIdxBins[mergeCand];
+#endif
 
       double cost = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass;
 
@@ -2406,11 +2449,23 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
     for( uint8_t i = 0; i < triangleNumMrgSATDCand; i++ )
     {
       uint8_t  mergeCand = triangleRdModeList[i];
+#if JVET_M0883_TRIANGLE_SIGNALING
+      bool     splitDir  = m_triangleModeTest[mergeCand].m_splitDir;
+      uint8_t  candIdx0  = m_triangleModeTest[mergeCand].m_candIdx0;
+      uint8_t  candIdx1  = m_triangleModeTest[mergeCand].m_candIdx1;
+#else
       bool     splitDir  = g_triangleCombination[mergeCand][0];
       uint8_t  candIdx0  = g_triangleCombination[mergeCand][1];
       uint8_t  candIdx1  = g_triangleCombination[mergeCand][2];
+#endif
         
+#if JVET_M0883_TRIANGLE_SIGNALING
+      pu.triangleSplitDir = splitDir;
+      pu.triangleMergeIdx0 = candIdx0;
+      pu.triangleMergeIdx1 = candIdx1;
+#else
       pu.mergeIdx  = mergeCand;
+#endif
       pu.mergeFlag = true;
                 
 #if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
@@ -2437,9 +2492,15 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
           continue;
         }
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+        bool    splitDir = m_triangleModeTest[mergeCand].m_splitDir;
+        uint8_t candIdx0 = m_triangleModeTest[mergeCand].m_candIdx0;
+        uint8_t candIdx1 = m_triangleModeTest[mergeCand].m_candIdx1;
+#else
         bool    splitDir = g_triangleCombination[mergeCand][0];
         uint8_t candIdx0 = g_triangleCombination[mergeCand][1];
         uint8_t candIdx1 = g_triangleCombination[mergeCand][2];
+#endif
 
         CodingUnit &cu = tempCS->addCU(tempCS->area, partitioner.chType);
 
@@ -2458,10 +2519,20 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
         cu.GBiIdx   = GBI_DEFAULT;
         PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType);
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+        pu.triangleSplitDir = splitDir;
+        pu.triangleMergeIdx0 = candIdx0;
+        pu.triangleMergeIdx1 = candIdx1;
+#else
         pu.mergeIdx = mergeCand;
+#endif
         pu.mergeFlag = true;
 
+#if JVET_M0883_TRIANGLE_SIGNALING
+        PU::spanTriangleMotionInfo(pu, triangleMrgCtx, splitDir, candIdx0, candIdx1 );
+#else
         PU::spanTriangleMotionInfo(pu, triangleMrgCtx, mergeCand, splitDir, candIdx0, candIdx1 );
+#endif
 
         if( tempBufSet )
         {
diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h
index f6abe2736cd9727c69596fc5d9c232707d3622fe..920e0eca595016e272842c99c0eb4cf9f29e72dd 100644
--- a/source/Lib/EncoderLib/EncCu.h
+++ b/source/Lib/EncoderLib/EncCu.h
@@ -68,6 +68,16 @@ class EncSlice;
 // ====================================================================================================================
 
 /// CU encoder class
+#if JVET_M0883_TRIANGLE_SIGNALING
+struct TriangleMotionInfo
+{
+  uint8_t   m_splitDir;
+  uint8_t   m_candIdx0;
+  uint8_t   m_candIdx1;
+
+  TriangleMotionInfo ( uint8_t splitDir, uint8_t candIdx0, uint8_t candIdx1 ): m_splitDir(splitDir), m_candIdx0(candIdx0), m_candIdx1(candIdx1) { }
+};
+#endif
 class EncCu
 #if REUSE_CU_RESULTS
   : DecCu
@@ -135,6 +145,10 @@ private:
 #endif
   int                   m_bestGbiIdx[2];
   double                m_bestGbiCost[2];
+#if JVET_M0883_TRIANGLE_SIGNALING
+  static const TriangleMotionInfo  m_triangleModeTest[TRIANGLE_MAX_NUM_CANDS];
+  uint8_t                          m_triangleIdxBins[2][TRIANGLE_MAX_NUM_UNI_CANDS][TRIANGLE_MAX_NUM_UNI_CANDS];
+#endif
 #if SHARP_LUMA_DELTA_QP
   void    updateLambda      ( Slice* slice, double dQP );
 #endif