//updates the vertex buffer containing the per instance data size_t InstanceBatchHW_VTF::updateInstanceDataBuffer(bool isFirstTime, Camera* currentCamera) { size_t visibleEntityCount = 0; bool useMatrixLookup = useBoneMatrixLookup(); if (isFirstTime ^ useMatrixLookup) { //update the mTransformLookupNumber value in the entities if needed updateSharedLookupIndexes(); const float texWidth = static_cast<float>(mMatrixTexture->getWidth()); const float texHeight = static_cast<float>(mMatrixTexture->getHeight()); //Calculate the texel offsets to correct them offline //Awkwardly enough, the offset is needed in OpenGL too Vector2 texelOffsets; //RenderSystem *renderSystem = Root::getSingleton().getRenderSystem(); texelOffsets.x = /*renderSystem->getHorizontalTexelOffset()*/ -0.5f / texWidth; texelOffsets.y = /*renderSystem->getHorizontalTexelOffset()*/ -0.5f / texHeight; float *thisVec = static_cast<float*>(mInstanceVertexBuffer->lock(HardwareBuffer::HBL_DISCARD)); const size_t maxPixelsPerLine = std::min( mMatrixTexture->getWidth(), mMaxFloatsPerLine >> 2 ); //Calculate UV offsets, which change per instance for( size_t i=0; i<mInstancesPerBatch; ++i ) { InstancedEntity* entity = useMatrixLookup ? mInstancedEntities[i] : NULL; if //Update if we are not using a lookup bone matrix method. In this case the function will //be called only once (!useMatrixLookup || //Update if we are in the visible range of the camera (for look up bone matrix method //and static mode). (entity->findVisible(currentCamera))) { size_t matrixIndex = useMatrixLookup ? entity->mTransformLookupNumber : i; size_t instanceIdx = matrixIndex * mMatricesPerInstance * mRowLength; *thisVec = ((instanceIdx % maxPixelsPerLine) / texWidth) - (float)(texelOffsets.x); *(thisVec + 1) = ((instanceIdx / maxPixelsPerLine) / texHeight) - (float)(texelOffsets.y); thisVec += 2; if (useMatrixLookup) { const Matrix4& mat = entity->_getParentNodeFullTransform(); *(thisVec) = static_cast<float>( mat[0][0] ); *(thisVec + 1) = static_cast<float>( mat[0][1] ); *(thisVec + 2) = static_cast<float>( mat[0][2] ); *(thisVec + 3) = static_cast<float>( mat[0][3] ); *(thisVec + 4) = static_cast<float>( mat[1][0] ); *(thisVec + 5) = static_cast<float>( mat[1][1] ); *(thisVec + 6) = static_cast<float>( mat[1][2] ); *(thisVec + 7) = static_cast<float>( mat[1][3] ); *(thisVec + 8) = static_cast<float>( mat[2][0] ); *(thisVec + 9) = static_cast<float>( mat[2][1] ); *(thisVec + 10)= static_cast<float>( mat[2][2] ); *(thisVec + 11)= static_cast<float>( mat[2][3] ); if(currentCamera && mManager->getCameraRelativeRendering()) // && useMatrixLookup { const Vector3 &cameraRelativePosition = currentCamera->getDerivedPosition(); *(thisVec + 3) -= static_cast<float>( cameraRelativePosition.x ); *(thisVec + 7) -= static_cast<float>( cameraRelativePosition.y ); *(thisVec + 11) -= static_cast<float>( cameraRelativePosition.z ); } thisVec += 12; } ++visibleEntityCount; } } mInstanceVertexBuffer->unlock(); }
//----------------------------------------------------------------------- void InstanceBatchHW_VTF::fillVertexBufferLUT( const MovableObjectArray *culledInstances ) { //update the mTransformLookupNumber value in the entities if needed updateSharedLookupIndexes(); const float texWidth = static_cast<float>(mMatrixTexture->getWidth()); const float texHeight = static_cast<float>(mMatrixTexture->getHeight()); //Calculate the texel offsets to correct them offline //Awkwardly enough, the offset is needed in OpenGL too Vector2 texelOffsets; //RenderSystem *renderSystem = Root::getSingleton().getRenderSystem(); texelOffsets.x = /*renderSystem->getHorizontalTexelOffset()*/ -0.5f / texWidth; texelOffsets.y = /*renderSystem->getHorizontalTexelOffset()*/ -0.5f / texHeight; float *thisVec = static_cast<float*>(mInstanceVertexBuffer->lock(HardwareBuffer::HBL_DISCARD)); const size_t maxPixelsPerLine = std::min( mMatrixTexture->getWidth(), static_cast<uint32>(mMaxFloatsPerLine >> 2) ); MovableObjectArray::const_iterator itor = culledInstances->begin(); MovableObjectArray::const_iterator end = culledInstances->end(); while( itor != end ) { assert( dynamic_cast<InstancedEntity*>(*itor) ); const InstancedEntity *entity = static_cast<InstancedEntity*>(*itor); size_t matrixIndex = entity->mTransformLookupNumber; size_t instanceIdx = matrixIndex * mMatricesPerInstance * mRowLength; *thisVec = ((instanceIdx % maxPixelsPerLine) / texWidth) - (float)(texelOffsets.x); *(thisVec + 1) = ((instanceIdx / maxPixelsPerLine) / texHeight) - (float)(texelOffsets.y); thisVec += 2; const Matrix4& mat = entity->_getParentNodeFullTransform(); *(thisVec) = static_cast<float>( mat[0][0] ); *(thisVec + 1) = static_cast<float>( mat[0][1] ); *(thisVec + 2) = static_cast<float>( mat[0][2] ); *(thisVec + 3) = static_cast<float>( mat[0][3] ); *(thisVec + 4) = static_cast<float>( mat[1][0] ); *(thisVec + 5) = static_cast<float>( mat[1][1] ); *(thisVec + 6) = static_cast<float>( mat[1][2] ); *(thisVec + 7) = static_cast<float>( mat[1][3] ); *(thisVec + 8) = static_cast<float>( mat[2][0] ); *(thisVec + 9) = static_cast<float>( mat[2][1] ); *(thisVec + 10)= static_cast<float>( mat[2][2] ); *(thisVec + 11)= static_cast<float>( mat[2][3] ); //TODO: This hurts my eyes (reading back from write-combining memory) /*if(currentCamera && mManager->getCameraRelativeRendering()) // && useMatrixLookup { const Vector3 &cameraRelativePosition = currentCamera->getDerivedPosition(); *(thisVec + 3) -= static_cast<float>( cameraRelativePosition.x ); *(thisVec + 7) -= static_cast<float>( cameraRelativePosition.y ); *(thisVec + 11) -= static_cast<float>( cameraRelativePosition.z ); }*/ thisVec += 12; ++itor; } mInstanceVertexBuffer->unlock(); }