UpdateAdditionalStreamContent

From Multi Theft Auto: Wiki
Jump to navigation Jump to search

This C++ Function is found inside of CAdditionalVertexStreamManager.

It updates additional stream content.

It can be found in Client/Client Core/Sources/CAdditionalVertexStreamManager.cpp in Visual Studio.

Required Arguments

  • state: To be defined.
  • pAdditionalInfo: To be defined.
  • ReadOffsetStart: To be defined.
  • ReadSize: To be defined.
  • WriteOffsetStart: To be defined.
  • WriteSize: To be defined.

Returns

Returns a boolean whether additional stream content was updated or not.

Code

bool CAdditionalVertexStreamManager::UpdateAdditionalStreamContent ( SCurrentStateInfo& state, SAdditionalStreamInfo* pAdditionalInfo, uint ReadOffsetStart, uint ReadSize, uint WriteOffsetStart, uint WriteSize )
{
    //HRESULT hr;
    IDirect3DVertexBuffer9* pStreamDataPT = state.stream1.pStreamData;
    IDirect3DVertexBuffer9* pStreamDataN = pAdditionalInfo->pStreamData;
    uint StridePT = 20;
    uint StrideN = 12;
    uint NumVerts = ReadSize / StridePT;
    assert ( NumVerts == WriteSize / StrideN );

    // Get the source vertex bytes
    std::vector < uchar > sourceArray;
    sourceArray.resize ( ReadSize );
    uchar* pSourceArrayBytes = &sourceArray[0];
    {
        void* pVertexBytesPT = NULL;
        if ( FAILED( pStreamDataPT->Lock ( ReadOffsetStart, ReadSize, &pVertexBytesPT, D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY ) ) )
            return false;
        memcpy ( pSourceArrayBytes, pVertexBytesPT, ReadSize );
        pStreamDataPT->Unlock ();
    }

    // Create dest byte buffer
    std::vector < uchar > destArray;
    destArray.resize ( WriteSize );
    uchar* pDestArrayBytes = &destArray[0];

    // Compute dest bytes
    {
        // Get index buffer
        if ( FAILED( m_pDevice->GetIndices( &state.pIndexData ) ) )
            return false;

        // Get index buffer desc
        D3DINDEXBUFFER_DESC IndexBufferDesc;
        state.pIndexData->GetDesc ( &IndexBufferDesc );

        uint numIndices = state.args.primCount + 2;
        uint step = 1;
        if ( state.args.PrimitiveType == D3DPT_TRIANGLELIST )
        {
            numIndices = state.args.primCount * 3;
            step = 3;
        }
        assert ( IndexBufferDesc.Size >= ( numIndices + state.args.startIndex ) * 2 );

        // Get index buffer data
        std::vector < uchar > indexArray;
        indexArray.resize ( ReadSize );
        uchar* pIndexArrayBytes = &indexArray[0];
        {
            void* pIndexBytes = NULL;
            if ( FAILED( state.pIndexData->Lock ( state.args.startIndex*2, numIndices*2, &pIndexBytes, D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY ) ) )
                return false;
            memcpy ( pIndexArrayBytes, pIndexBytes, numIndices*2 );
            state.pIndexData->Unlock ();
        }

        // Calc normals
        std::vector < CVector > NormalList;
        NormalList.insert ( NormalList.end (), NumVerts, CVector () );

        std::map < long long, CVector > doneTrisMap;

        // For each triangle
        for ( uint i = 0 ; i < numIndices - 2 ; i += step )
        {
            // Get triangle vertex indici
            WORD v0 = ((WORD*)pIndexArrayBytes)[ i ];
            WORD v1 = ((WORD*)pIndexArrayBytes)[ i + 1 ];
            WORD v2 = ((WORD*)pIndexArrayBytes)[ i + 2 ];

            if ( v0 >= NumVerts || v1 >= NumVerts || v2 >= NumVerts )
                continue;   // vert index out of range

            if ( v0 == v1 || v0 == v2 || v1 == v2 )
                continue;   // degenerate tri

            // Get vertex positions from original stream
            CVector* pPos0 = (CVector*)( pSourceArrayBytes + v0 * 20 );
            CVector* pPos1 = (CVector*)( pSourceArrayBytes + v1 * 20 );
            CVector* pPos2 = (CVector*)( pSourceArrayBytes + v2 * 20 );

            // Calculate the normal
            CVector Dir1 = *pPos2 - *pPos1;
            CVector Dir2 = *pPos0 - *pPos1;

            CVector Normal = Dir1;
            Normal.CrossProduct ( &Dir2 );
            Normal.Normalize ();

            // Flip normal if triangle was flipped
            if ( state.args.PrimitiveType == D3DPT_TRIANGLESTRIP && ( i & 1 ) )
                Normal = -Normal;

            // Try to improve results by ignoring duplicated triangles
            long long key = getTriKey ( v0, v1, v2 );
            if ( CVector* pDoneTriPrevNormal = MapFind ( doneTrisMap, key ) )
            {
                // Already done this tri - Keep prev tri if it has a better 'up' rating
                if ( pDoneTriPrevNormal->fZ > Normal.fZ )
                    continue;

                // Remove effect of prev tri
                NormalList[ v0 ] -= *pDoneTriPrevNormal;
                NormalList[ v1 ] -= *pDoneTriPrevNormal;
                NormalList[ v2 ] -= *pDoneTriPrevNormal;
            }
            MapSet ( doneTrisMap, key, Normal );

            // Add normal weight to used vertices
            NormalList[ v0 ] += Normal;
            NormalList[ v1 ] += Normal;
            NormalList[ v2 ] += Normal;
        }

        // Validate normals and set dest data
        for ( uint i = 0 ; i < NumVerts ; i++ )
        {
            // Validate
            CVector& Normal = NormalList[i];
            if ( Normal.Normalize () < FLOAT_EPSILON )
                Normal = CVector ( 0, 0, 1 );

            // Set
            CVector* pNormal = (CVector*)( pDestArrayBytes + i * 12 );
            *pNormal = Normal;
        }
    }

    // Set the dest bytes
    {
        void* pVertexBytesN = NULL;
        if ( FAILED( pStreamDataN->Lock ( WriteOffsetStart, WriteSize, &pVertexBytesN, D3DLOCK_NOSYSLOCK ) ) )
            return false;
        memcpy ( pVertexBytesN, pDestArrayBytes, WriteSize );
        pStreamDataN->Unlock ();
    }

    return true;
}

See Also