//---------------------------------------------------------------------------- SEParticles::SEParticles(const SEAttributes& rAttr, SEVector3fArray* pLocations, SEFloatArray* pSizes) : Locations(pLocations), Sizes(pSizes) { // 分配模型空间顶点存储,每个粒子使用4个顶点构成一个quad广告牌. int iLCount = Locations->GetCount(); int iVCount = 4*iLCount; VBuffer = SE_NEW SEVertexBuffer(rAttr, iVCount); // 为这些quad广告牌设置2D纹理坐标. int i, j; for( int iUnit = 0; iUnit < rAttr.GetMaxTCoords(); iUnit++ ) { if( rAttr.HasTCoord(iUnit) && rAttr.GetTCoordChannels(iUnit) == 2 ) { for( i = 0, j = 0; i < iLCount; i++ ) { VBuffer->TCoord2(iUnit, j++) = SEVector2f(0.0f, 1.0f); VBuffer->TCoord2(iUnit, j++) = SEVector2f(0.0f, 0.0f); VBuffer->TCoord2(iUnit, j++) = SEVector2f(1.0f, 0.0f); VBuffer->TCoord2(iUnit, j++) = SEVector2f(1.0f, 1.0f); } } } // 为这些quad广告牌创建IB. int iICount = 6*iLCount; IBuffer = SE_NEW SEIndexBuffer(iICount); int* aiIndex = IBuffer->GetData(); for( i = 0, j = 0; i < iLCount; i++ ) { int iFI = 4*i, iFIp1 = iFI+1, iFIp2 = iFI+2, iFIp3 = iFI+3; aiIndex[j++] = iFI; aiIndex[j++] = iFIp1; aiIndex[j++] = iFIp3; aiIndex[j++] = iFIp1; aiIndex[j++] = iFIp2; aiIndex[j++] = iFIp3; } // 根据全部粒子的模型空间位置计算出一个包含这些位置的BV. ModelBound->ComputeFromData(Locations); SizeAdjust = 1.0f; m_iActiveCount = iLCount; }
//---------------------------------------------------------------------------- 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]; }