예제 #1
0
    uint32 DiInstanceBatchHardware::UpdateVertexBuffer( DiCamera *currentCamera )
    {
        size_t retVal = 0;
        DiVertexBuffer* vb = mSourceData.back();
        float *pDest = static_cast<float*>(vb->Lock(0,vb->GetBufferSize()));

        InstancedModelVec::const_iterator itor = mInstancedModels.begin();
        InstancedModelVec::const_iterator end  = mInstancedModels.end();

        while( itor != end )
        {
            if( (*itor)->IsInUse()/* && (*itor)->FindVisible( currentCamera )*/ )
            {
                const size_t floatsWritten = (*itor)->GetTransforms3x4( pDest );

                pDest += floatsWritten;

                ++retVal;
            }
            ++itor;
        }

        vb->Unlock();

        DI_ASSERT(mSourceData.size() > 1);
        for (size_t i=0; i < mSourceData.size()-1; i++)
        {
            mSourceData[i]->SetInstanceNum(retVal);
        }

        return retVal;
    }
예제 #2
0
    void DiInstanceBatchHardware::SetupVertices( const DiSubMesh* baseSubMesh )
    {
        mRemoveOwnVertexData = true;    

        mVerticesNum = baseSubMesh->GetVerticeNum();

        DiVertexElements elements = baseSubMesh->GetVertexElements();
        int blendSource = RemoveBlendData(elements);

        mVertexDecl = Driver->CreateVertexDeclaration();
        mVertexDecl->AddElements(elements);
        uint16 nextFreeStream = 0;
        
        if (blendSource != -1)
            nextFreeStream = (uint16)blendSource;
        else
            nextFreeStream = mVertexDecl->GetElements().GetStreams();

        uint16 nextFreeUV = mVertexDecl->GetElements().GetNextFreeTexcoord();
        if (nextFreeUV > 8-2)
        {
            DI_WARNING("No enough rooms for texcoords");
            return;
        }

        mVertexDecl->AddElement(nextFreeStream, VERT_TYPE_FLOAT4, VERT_USAGE_TEXCOORD,5);
        mVertexDecl->AddElement(nextFreeStream, VERT_TYPE_FLOAT4, VERT_USAGE_TEXCOORD,6);
        mVertexDecl->AddElement(nextFreeStream, VERT_TYPE_FLOAT4, VERT_USAGE_TEXCOORD,7);
        mVertexDecl->Create();

        DiSubMesh::SourceDataIterator si = baseSubMesh->GetSourceDataIterator();
        while (si.HasMoreElements())
        {
            DiSubMesh::SourceData sd = si.GetNext();

            if ((int)(sd.stream) == blendSource)
            {
                continue;
            }

            DiVertexBuffer* buf = Driver->CreateVertexBuffer();
            uint32 size = sd.GetSize();
            buf->SetStride(sd.stride);
            buf->Create(size,RU_WRITE_ONLY,sd.stream);
            buf->WriteData(0, size, sd.data);
            buf->SetInstanceState(SOURCE_INSTANCE_INDEX);
            buf->SetInstanceNum(mInstancesPerBatch);
            mSourceData.push_back(buf);
        }

        DiVertexBuffer* buf = Driver->CreateVertexBuffer();
        uint32 stride = mVertexDecl->GetElements().GetStreamElementsSize(nextFreeStream);
        uint32 size = mInstancesPerBatch * stride ;
        buf->SetStride(stride);
        buf->Create(size, RU_WRITE_ONLY, nextFreeStream);
        buf->SetInstanceState(SOURCE_INSTANCE_DATA);
        mSourceData.push_back(buf);
    }
예제 #3
0
    void DiInstanceBatchShader::SetupNoSkinned( const DiSubMesh* baseSubMesh )
    {
        mVertexDecl = Driver->CreateVertexDeclaration();
        mVertexDecl->AddElements(baseSubMesh->GetVertexElements());
        mVertexDecl->AddElement(mVertexDecl->GetElements().GetStreams(),VERT_TYPE_UBYTE4,VERT_USAGE_BLENDINDICES,0);
        mVertexDecl->Create();

        DiSubMesh::SourceDataIterator si = baseSubMesh->GetSourceDataIterator();
        while (si.HasMoreElements())
        {
            DiSubMesh::SourceData sd = si.GetNext();

            DiVertexBuffer* buf = Driver->CreateVertexBuffer();
            uint32 size = sd.GetSize() * mInstancesPerBatch;
            buf->SetStride(sd.stride);
            buf->Create(size,RU_WRITE_ONLY,sd.stream);
            BYTE* data = (BYTE*)buf->Lock(0,size);
            for( size_t j=0; j < mInstancesPerBatch; ++j )
            {
                memcpy(data + sd.GetSize()*j,sd.data,sd.GetSize());
            }
            buf->Unlock();
            mSourceData.push_back(buf);
        }

        uint16 lastStream = mVertexDecl->GetElements().GetStreams()-1;
        DiVertexBuffer* buf = Driver->CreateVertexBuffer();
        uint32 stride = mVertexDecl->GetElements().GetStreamElementsSize(lastStream);
        uint32 size = baseSubMesh->GetVerticeNum() * stride * mInstancesPerBatch;
        buf->SetStride(stride);
        buf->Create(size, RU_WRITE_ONLY, lastStream);
        char* thisBuf = static_cast<char*>(buf->Lock(0,size));
        for( size_t j=0; j < mInstancesPerBatch; ++j )
        {
            for( size_t k=0; k<baseSubMesh->GetVerticeNum(); ++k )
            {
                *thisBuf++ = mInstancesPerBatch - j - 1;
                *thisBuf++ = mInstancesPerBatch - j - 1;
                *thisBuf++ = mInstancesPerBatch - j - 1;
                *thisBuf++ = mInstancesPerBatch - j - 1;
            }
        }
        buf->Unlock();
        mSourceData.push_back(buf);
    }
예제 #4
0
    void DiInstanceBatchShader::SetupHardwareSkinned( const DiSubMesh* baseSubMesh )
    {
        const size_t numBones = mMotionReference->GetSkeleton()->GetNumBones();//baseSubMesh->GetBlendIndexToBoneIndexMap().size();
        m_usNumWorldMatrices = mInstancesPerBatch * numBones;


        DiVertexElements eles = baseSubMesh->GetVertexElements();

        uint16 nextFreeUV = eles.GetNextFreeTexcoord();
        if (nextFreeUV > 8-1)
        {
            DI_WARNING("No enough rooms of texcoord");
            return;
        }

        uint16 blendstream = eles.GetTypeUsageAtStream(VERT_TYPE_UBYTE4,VERT_USAGE_BLENDINDICES);
        eles.AddElement(blendstream, VERT_TYPE_FLOAT1, VERT_USAGE_TEXCOORD, 7);    //instanceID
        mVertexDecl = Driver->CreateVertexDeclaration();
        mVertexDecl->AddElements(eles);
        mVertexDecl->Create();

        DiSubMesh::SourceDataIterator si = baseSubMesh->GetSourceDataIterator();
        while (si.HasMoreElements())
        {
            DiSubMesh::SourceData sd = si.GetNext();

            DiVertexElements& ves = const_cast<DiSubMesh*>(baseSubMesh)->GetVertexElements();
            DiVertexElements::ElementsList elementlist = ves.GetElementsAtStream(sd.stream);

            DiVertexBuffer* buf = Driver->CreateVertexBuffer();
            uint32 size = sd.GetSize() * mInstancesPerBatch;
            buf->SetStride(sd.stride);
            buf->Create(size, RU_WRITE_ONLY, sd.stream);
            BYTE* startBuf = (BYTE*)buf->Lock(0,size);
            BYTE* data = startBuf;
            BYTE* startSrcBuf = (BYTE*)sd.data;
            BYTE* dataSrc = startSrcBuf;

            for( size_t j=0; j < mInstancesPerBatch; ++j )
            {
                dataSrc = startSrcBuf;
                for (uint32 v = 0; v < sd.numVertices; v++)
                {
                    for (size_t ei = 0; ei < elementlist.size(); ei++)
                    {
                        if (elementlist[ei].Usage == VERT_USAGE_BLENDINDICES)
                        {
                            *(data + elementlist[ei].Offset + 0) = *(dataSrc + elementlist[ei].Offset + 0) + j * numBones;
                            *(data + elementlist[ei].Offset + 1) = *(dataSrc + elementlist[ei].Offset + 1) + j * numBones;
                            *(data + elementlist[ei].Offset + 2) = *(dataSrc + elementlist[ei].Offset + 2) + j * numBones;
                            *(data + elementlist[ei].Offset + 3) = *(dataSrc + elementlist[ei].Offset + 3) + j * numBones;
                        }
                        else if (elementlist[ei].Usage == VERT_USAGE_TEXCOORD && elementlist[ei].UsageIndex == 7)
                        {
                            float* d = (float*)(data + elementlist[ei].Offset);
                            *d = (float)(j*numBones);
                        }
                        else
                        {
                            memcpy(data + elementlist[ei].Offset,dataSrc + elementlist[ei].Offset,
                                DiVertexElements::GetElementTypeSize(DiVertexType(elementlist[ei].Type)));
                        }
                    }
                    data    += const_cast<DiSubMesh*>(baseSubMesh)->GetVertexElements().GetStreamElementsSize(sd.stream);
                    dataSrc += const_cast<DiSubMesh*>(baseSubMesh)->GetVertexElements().GetStreamElementsSize(sd.stream);
                }
            }
            buf->Unlock();
            mSourceData.push_back(buf);
        }
    }
예제 #5
0
    void DiFoliageLayerBatch::GenerateGrassQuad( const float *grassPositions, unsigned int grassCount )
    {
        ReleaseVertexDeclaration();
        ReleaseSourceData();
        ReleaseIndexBuffer();

        unsigned int quadCount;
        quadCount = grassCount;

        unsigned int maxUInt16 = std::numeric_limits<uint16>::max();
        if(grassCount > maxUInt16)
        {
            return;
        }
        if(quadCount > maxUInt16)
        {
            return;
        }
        if (quadCount <= 0)
        {
            mVerticesNum = 0;
            mPrimitiveCount = 0;
            return;
        }

        mVerticesNum        = 4 * quadCount;
        mPrimitiveCount    = 2 * quadCount;

        mVertexDecl = Driver->CreateVertexDeclaration();
        mVertexDecl->AddElement(0,VERT_TYPE_FLOAT3,    VERT_USAGE_POSITION);
        mVertexDecl->AddElement(0,VERT_TYPE_FLOAT2,    VERT_USAGE_TEXCOORD);
        mVertexDecl->Create();

        uint32 vertSize = mVertexDecl->GetElements().GetStreamElementsSize(0);
        uint32 size = vertSize * mVerticesNum;
        DiVertexBuffer* vb = Driver->CreateVertexBuffer();
        vb->Create(size);
        vb->SetStride(vertSize);
        mSourceData.push_back(vb);

        DiVec2 chunkPos = mParent->mParent->GetTerrainMap()->GetChunkCenterPos(mParent->mChunkID.x,mParent->mChunkID.y);

        float* pReal = static_cast<float*>(vb->Lock(0,size));
        
        float rndWidth    = mLayer->mDesc->mMaxWidth  - mLayer->mDesc->mMinWidth;
        float rndHeight = mLayer->mDesc->mMaxHeight - mLayer->mDesc->mMinHeight;

        float minY = DiMath::POS_INFINITY, maxY = DiMath::NEG_INFINITY;

        const float *posPtr = grassPositions;
        for (uint16 i = 0; i < grassCount; ++i)
        {
            float x = *posPtr++;
            float z = *posPtr++;

            float rnd = *posPtr++;
            float halfScaleX = (mLayer->mDesc->mMinWidth + rndWidth * rnd) * 0.5f;
            float scaleY = (mLayer->mDesc->mMinHeight + rndHeight * rnd);

            float angle = *posPtr++;
            float xTrans = DiMath::Cos(angle) * halfScaleX;
            float zTrans = DiMath::Sin(angle) * halfScaleX;

            float x1 = x - xTrans, z1 = z - zTrans;
            float x2 = x + xTrans, z2 = z + zTrans;

            float height = 0;
            mParent->mParent->GetTerrainMap()->GetHeight(chunkPos.x+x,chunkPos.y+z,height);
            float y1 = height;
            float y2 = height;


            *pReal++ = float(x1);
            *pReal++ = float(y1 + scaleY);
            *pReal++ = float(z1);   //pos

            *pReal++ = 0.f; *pReal++ = 0.f;              //uv

            *pReal++ = float(x2);
            *pReal++ = float(y2 + scaleY);
            *pReal++ = float(z2);   //pos
            *pReal++ = 1.f; *pReal++ = 0.f;              //uv

            *pReal++ = float(x1);
            *pReal++ = float(y1);
            *pReal++ = float(z1);   //pos
            *pReal++ = 0.f; *pReal++ = 1.f;              //uv

            *pReal++ = float(x2);
            *pReal++ = float(y2);
            *pReal++ = float(z2);   //pos
            *pReal++ = 1.f; *pReal++ = 1.f;              //uv

            if (y1 < minY)
            {
                minY = y1;
            }
            if (y2 < minY) 
            {
                minY = y2;
            }
            if (y1 + scaleY > maxY) 
            {
                maxY = y1 + scaleY;
            }
            if (y2 + scaleY > maxY) 
            {
                maxY = y2 + scaleY;
            }
        }

        vb->Unlock();

        uint32 ibsize = 6 * quadCount * sizeof(uint16);
        mIndexBuffer = Driver->CreateIndexBuffer();
        mIndexBuffer->Create(ibsize);
        uint16* pI = static_cast<uint16*>(mIndexBuffer->Lock(0,ibsize));

        for (uint16 i = 0; i < quadCount; ++i)
        {
            uint16 offset = i * 4;

            *pI++ = 0 + offset;
            *pI++ = 2 + offset;
            *pI++ = 1 + offset;

            *pI++ = 1 + offset;
            *pI++ = 2 + offset;
            *pI++ = 3 + offset;
        }
        mIndexBuffer->Unlock();
    }