Exemplo n.º 1
0
    void LodOutputProviderBuffer::bakeLodLevel(LodData* data, int lodIndex)
    {
        unsigned short submeshCount = ushort(mBuffer.submesh.size());

        // Create buffers.
        for (unsigned short i = 0; i < submeshCount; i++) {
            vector<LodIndexBuffer>::type& lods = mBuffer.submesh[i].genIndexBuffers;
            size_t indexCount = data->mIndexBufferInfoList[i].indexCount;
            lods.reserve(lods.size() + 1);
            LodIndexBuffer& curLod = *lods.insert(lods.begin() + lodIndex, LodIndexBuffer());
            if (indexCount == 0) {
                curLod.indexCount = 3;
            } else {
                curLod.indexCount = indexCount;
            }
            curLod.indexStart = 0;
            curLod.indexSize = data->mIndexBufferInfoList[i].indexSize;
            curLod.indexBufferSize = 0; // It means same as index count
            curLod.indexBuffer = Ogre::SharedPtr<unsigned char>(new unsigned char[curLod.indexCount * curLod.indexSize]);
            // buf is an union, so pint=pshort
            data->mIndexBufferInfoList[i].buf.pshort = (unsigned short*) curLod.indexBuffer.get();

            if (indexCount == 0) {
                memset(data->mIndexBufferInfoList[i].buf.pshort, 0, 3 * data->mIndexBufferInfoList[i].indexSize);
            }
        }

        // Fill buffers.
        size_t triangleCount = data->mTriangleList.size();
        for (size_t i = 0; i < triangleCount; i++) {
            if (!data->mTriangleList[i].isRemoved) {
                if (data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].indexSize == 2) {
                    for (int m = 0; m < 3; m++) {
                        *(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].buf.pshort++) =
                            static_cast<unsigned short>(data->mTriangleList[i].vertexID[m]);
                    }
                } else {
                    for (int m = 0; m < 3; m++) {
                        *(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].buf.pint++) =
                            static_cast<unsigned int>(data->mTriangleList[i].vertexID[m]);
                    }
                }
            }
        }
    }
    void LodOutputProviderCompressedBuffer::bakeSecondPass(LodData* data, int lodIndex) {
        LodOutputBuffer& buffer = static_cast<LodOutputProviderBuffer*>(fallback)->getBuffer();
        unsigned short submeshCount = data->mIndexBufferInfoList.size();
        assert(mTriangleCacheList.size() == data->mTriangleList.size());
        assert(lodIndex > mLastIndexBufferID); // Implementation limitation

        // Create buffers.
        for (unsigned short i = 0; i < submeshCount; i++) {
            vector<LodIndexBuffer>::type& lods = buffer.submesh[i].genIndexBuffers;
            lods.reserve(lods.size() + 2);
            size_t indexCount = data->mIndexBufferInfoList[i].indexCount + data->mIndexBufferInfoList[i].prevOnlyIndexCount;
            assert(data->mIndexBufferInfoList[i].prevIndexCount >= data->mIndexBufferInfoList[i].indexCount);
            assert(data->mIndexBufferInfoList[i].prevIndexCount >= data->mIndexBufferInfoList[i].prevOnlyIndexCount);

            LodIndexBuffer& prevLod = *lods.insert(lods.begin() + mLastIndexBufferID, LodIndexBuffer());
            prevLod.indexStart = 0;
            prevLod.indexSize = data->mIndexBufferInfoList[i].indexSize;

            //If the index is empty we need to create a "dummy" triangle, just to keep the index buffer from being empty.
            //The main reason for this is that the OpenGL render system will crash with a segfault unless the index has some values.
            //This should hopefully be removed with future versions of Ogre. The most preferred solution would be to add the
            //ability for a submesh to be excluded from rendering for a given LOD (which isn't possible currently 2012-12-09).
            indexCount = std::max<size_t>(indexCount, 3);
            prevLod.indexCount = std::max<size_t>(data->mIndexBufferInfoList[i].prevIndexCount, 3u);
            prevLod.indexBufferSize = indexCount;
            prevLod.indexBuffer = Ogre::SharedPtr<unsigned char>(new unsigned char[indexCount * data->mIndexBufferInfoList[i].indexSize]);
            data->mIndexBufferInfoList[i].buf.pshort = (unsigned short*)prevLod.indexBuffer.get();

            //Check if we should fill it with a "dummy" triangle.
            if (indexCount == 3) {
                memset(data->mIndexBufferInfoList[i].buf.pshort, 0, 3 * data->mIndexBufferInfoList[i].indexSize);
            }

            LodIndexBuffer& curLod = *lods.insert(lods.begin() + lodIndex, LodIndexBuffer());
            curLod.indexSize = prevLod.indexSize;
            curLod.indexStart = indexCount - data->mIndexBufferInfoList[i].indexCount;
            curLod.indexCount = data->mIndexBufferInfoList[i].indexCount;
            curLod.indexBufferSize = prevLod.indexBufferSize;
            curLod.indexBuffer = prevLod.indexBuffer;
            if(curLod.indexCount == 0){
                curLod.indexStart-=3;
                curLod.indexCount=3;
            }

        }


        // Fill buffers.
        // Filling will be done in 3 parts.
        // 1. prevLod only indices.
        size_t triangleCount = data->mTriangleList.size();
        for (size_t i = 0; i < triangleCount; i++) {
            if (mTriangleCacheList[i].vertexChanged) {
                assert(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].prevIndexCount != 0);
                assert(mTriangleCacheList[i].vertexID[0] != mTriangleCacheList[i].vertexID[1]);
                assert(mTriangleCacheList[i].vertexID[1] != mTriangleCacheList[i].vertexID[2]);
                assert(mTriangleCacheList[i].vertexID[2] != mTriangleCacheList[i].vertexID[0]);
                if (data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].indexSize == 2) {
                    for (int m = 0; m < 3; m++) {
                        *(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].buf.pshort++) =
                            static_cast<unsigned short>(mTriangleCacheList[i].vertexID[m]);
                    }
                } else {
                    for (int m = 0; m < 3; m++) {
                        *(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].buf.pint++) =
                            static_cast<unsigned int>(mTriangleCacheList[i].vertexID[m]);
                    }
                }
            }
        }


        // 2. shared indices.
        for (size_t i = 0; i < triangleCount; i++) {
            if (!data->mTriangleList[i].isRemoved && !mTriangleCacheList[i].vertexChanged) {
                assert(mTriangleCacheList[i].vertexID[0] == data->mTriangleList[i].vertexID[0]);
                assert(mTriangleCacheList[i].vertexID[1] == data->mTriangleList[i].vertexID[1]);
                assert(mTriangleCacheList[i].vertexID[2] == data->mTriangleList[i].vertexID[2]);

                assert(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].indexCount != 0);
                assert(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].prevIndexCount != 0);
                if (data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].indexSize == 2) {
                    for (int m = 0; m < 3; m++) {
                        *(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].buf.pshort++) =
                            static_cast<unsigned short>(data->mTriangleList[i].vertexID[m]);
                    }
                } else {
                    for (int m = 0; m < 3; m++) {
                        *(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].buf.pint++) =
                            static_cast<unsigned int>(data->mTriangleList[i].vertexID[m]);
                    }
                }
            }
        }

        // 3. curLod indices only.
        for (size_t i = 0; i < triangleCount; i++) {
            if (!data->mTriangleList[i].isRemoved && mTriangleCacheList[i].vertexChanged) {
                assert(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].indexCount != 0);
                if (data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].indexSize == 2) {
                    for (int m = 0; m < 3; m++) {
                        *(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].buf.pshort++) =
                            static_cast<unsigned short>(data->mTriangleList[i].vertexID[m]);
                    }
                } else {
                    for (int m = 0; m < 3; m++) {
                        *(data->mIndexBufferInfoList[data->mTriangleList[i].submeshID].buf.pint++) =
                            static_cast<unsigned int>(data->mTriangleList[i].vertexID[m]);
                    }
                }
            }
        }
    }