//---------------------------------------------------------------------------- void SEVertexBuffer::BuildCompatibleArray(const SEAttributes& rIAttributes, bool bPackARGB, int& rChannels, float*& rCompatible) const { // 注意这里使用unsigned int来存储数据, // 从而允许同时存储float和32位ARGB格式的unsigned int数据, // 把float指针显示类型转换为unsigned int指针然后取*操作没有任何问题, // 但反过来把unsigned int指针显示类型转换为float指针并取*操作, // 则取出的数据可能为非法浮点数据, // 因此如果使用std::vector<float>将可能存在数据非正常转换的问题 std::vector<unsigned int> tempCompatible; const unsigned int* puiData; float fOne = 1.0f; unsigned int* puiOne = (unsigned int*)&fOne; int iUnit, iIChannels, iVBChannels; for( int i = 0, j; i < m_iVertexCount; i++ ) { // 填充顶点 if( rIAttributes.HasPosition() ) { iIChannels = rIAttributes.GetPositionChannels(); iVBChannels = m_Attributes.GetPositionChannels(); puiData = (unsigned int*)PositionTuple(i); if( iVBChannels < iIChannels ) { for( j = 0; j < iVBChannels; j++ ) { tempCompatible.push_back(*puiData++); } for( j = iVBChannels; j < iIChannels; j++ ) { // 将w分量填充为1.0,从而成为齐次空间顶点 tempCompatible.push_back(*puiOne); } } else { for( j = 0; j < iIChannels; j++ ) { tempCompatible.push_back(*puiData++); } } } // 填充法线 if( rIAttributes.HasNormal() ) { iIChannels = rIAttributes.GetNormalChannels(); iVBChannels = m_Attributes.GetNormalChannels(); puiData = (unsigned int*)NormalTuple(i); if( iVBChannels < iIChannels ) { for( j = 0; j < iVBChannels; j++ ) { tempCompatible.push_back(*puiData++); } for( j = iVBChannels; j < iIChannels; j++ ) { // 将w分量填充为0.0,从而成为齐次空间向量 tempCompatible.push_back(0); } } else { for( j = 0; j < iIChannels; j++ ) { tempCompatible.push_back(*puiData++); } } } // 填充若干组颜色 for( iUnit = 0; iUnit < (int)rIAttributes.GetMaxColors(); iUnit++ ) { if( rIAttributes.HasColor(iUnit) ) { unsigned int auiColor[4], uiPackColor, uiValue; float fValue; iIChannels = rIAttributes.GetColorChannels(iUnit); iVBChannels = m_Attributes.GetColorChannels(iUnit); puiData = (unsigned int*)ColorTuple(iUnit, i); if( iVBChannels < iIChannels ) { for( j = 0; j < iVBChannels; j++ ) { tempCompatible.push_back(*puiData++); } for( j = iVBChannels; j < iIChannels; j++ ) { // 将a分量填充为1.0,成为不透明颜色 tempCompatible.push_back(*puiOne); } if( bPackARGB ) { for( j = iIChannels; j < 4; j++ ) { // 将a分量填充为1.0,成为不透明颜色 tempCompatible.push_back(*puiOne); } // 从[0.0f, 1.0f]映射到[0,255] for( j = 3; j >= 0; j-- ) { uiValue = tempCompatible.back(); fValue = *(float*)&uiValue; auiColor[j] = (unsigned int)(255.0f * fValue); tempCompatible.pop_back(); } uiPackColor = (auiColor[2] ) | // blue (auiColor[1] << 8) | // green (auiColor[0] << 16) | // red (auiColor[3] << 24); // alpha tempCompatible.push_back(uiPackColor); } } else { for( j = 0; j < iIChannels; j++ ) { tempCompatible.push_back(*puiData++); } if( bPackARGB ) { for( j = iIChannels; j < 4; j++ ) { // 将a分量填充为1.0,成为不透明颜色 tempCompatible.push_back(*puiOne); } // 从[0.0f, 1.0f]映射到[0,255] for( j = 3; j >= 0; j-- ) { uiValue = tempCompatible.back(); fValue = *(float*)&uiValue; auiColor[j] = (unsigned int)(255.0f * fValue); tempCompatible.pop_back(); } uiPackColor = (auiColor[2] ) | // blue (auiColor[1] << 8) | // green (auiColor[0] << 16) | // red (auiColor[3] << 24); // alpha tempCompatible.push_back(uiPackColor); } } } } // 填充若干组纹理坐标 for( iUnit = 0; iUnit < (int)rIAttributes.GetMaxTCoords(); iUnit++ ) { if( rIAttributes.HasTCoord(iUnit) ) { iIChannels = rIAttributes.GetTCoordChannels(iUnit); iVBChannels = m_Attributes.GetTCoordChannels(iUnit); puiData = (unsigned int*)TCoordTuple(iUnit, i); if( iVBChannels < iIChannels ) { for( j = 0; j < iVBChannels; j++ ) { tempCompatible.push_back(*puiData++); } for( j = iVBChannels; j < iIChannels; j++ ) { // 填充为0,从而高维纹理坐标兼容低维纹理坐标 tempCompatible.push_back(0); } } else { for( j = 0; j < iIChannels; j++ ) { tempCompatible.push_back(*puiData++); } } } } } rChannels = (int)tempCompatible.size(); if( !rCompatible ) { // 调用者有责任释放该内存 rCompatible = SE_NEW float[rChannels]; }