Exemplo n.º 1
0
    //-----------------------------------------------------------------------
    void BillboardChain::updateIndexBuffer(void)
    {

        setupBuffers();
        if (mIndexContentDirty)
        {
            HardwareBufferLockGuard indexLock(mIndexData->indexBuffer, HardwareBuffer::HBL_DISCARD);
            uint16* pShort = static_cast<uint16*>(indexLock.pData);
            mIndexData->indexCount = 0;
            // indexes
            for (ChainSegmentList::iterator segi = mChainSegmentList.begin();
                segi != mChainSegmentList.end(); ++segi)
            {
                ChainSegment& seg = *segi;

                // Skip 0 or 1 element segment counts
                if (seg.head != SEGMENT_EMPTY && seg.head != seg.tail)
                {
                    // Start from head + 1 since it's only useful in pairs
                    size_t laste = seg.head;
                    while(1) // until break
                    {
                        size_t e = laste + 1;
                        // Wrap forwards
                        if (e == mMaxElementsPerChain)
                            e = 0;
                        // indexes of this element are (e * 2) and (e * 2) + 1
                        // indexes of the last element are the same, -2
                        assert (((e + seg.start) * 2) < 65536 && "Too many elements!");
                        uint16 baseIdx = static_cast<uint16>((e + seg.start) * 2);
                        uint16 lastBaseIdx = static_cast<uint16>((laste + seg.start) * 2);
                        *pShort++ = lastBaseIdx;
                        *pShort++ = lastBaseIdx + 1;
                        *pShort++ = baseIdx;
                        *pShort++ = lastBaseIdx + 1;
                        *pShort++ = baseIdx + 1;
                        *pShort++ = baseIdx;

                        mIndexData->indexCount += 6;


                        if (e == seg.tail)
                            break; // last one

                        laste = e;

                    }
                }

            }

            mIndexContentDirty = false;
        }

    }
Exemplo n.º 2
0
Arquivo: spr2d.cpp Projeto: garinh/cs
void csSprite2DMeshObject::PreGetBuffer (csRenderBufferHolder* holder, csRenderBufferName buffer)
{
  if (!holder) return;
  csColoredVertices* vertices = GetCsVertices ();

  if (buffer == CS_BUFFER_INDEX)
  {
    size_t indexSize = vertices->GetSize ();
    if (!index_buffer.IsValid() || 
      (indicesSize != indexSize))
    {
      index_buffer = csRenderBuffer::CreateIndexRenderBuffer (
	indexSize, CS_BUF_DYNAMIC, 
	CS_BUFCOMP_UNSIGNED_INT, 0, vertices->GetSize () - 1);
      
      holder->SetRenderBuffer (CS_BUFFER_INDEX, index_buffer);

      csRenderBufferLock<uint> indexLock (index_buffer);
      uint* ptr = indexLock;

      for (size_t i = 0; i < vertices->GetSize (); i++)
      {
	*ptr++ = (uint)i;
      }
      indicesSize = indexSize;
    }
  }
  else if (buffer == CS_BUFFER_TEXCOORD0)
  {
    if (texels_dirty)
    {
      int texels_count;
      const csVector2 *uvani_uv = 0;
      if (!uvani)
	texels_count = (int)vertices->GetSize ();
      else
	uvani_uv = uvani->GetVertices (texels_count);
	  
      size_t texelSize = texels_count;
      if (!texel_buffer.IsValid() || (texel_buffer->GetSize()
      	!= texelSize * sizeof(float) * 2))
      {
	texel_buffer = csRenderBuffer::CreateRenderBuffer (
	  texelSize, CS_BUF_STATIC, CS_BUFCOMP_FLOAT, 2);
	holder->SetRenderBuffer (CS_BUFFER_TEXCOORD0, texel_buffer);
      }

      csRenderBufferLock<csVector2> texelLock (texel_buffer);

      for (size_t i = 0; i < (size_t)texels_count; i++)
      {
	csVector2& v = texelLock[i];
	if (!uvani)
	{
	  v.x = (*vertices)[i].u;
	  v.y = (*vertices)[i].v;
	}
	else
	{
	  v.x = uvani_uv[i].x;
	  v.y = uvani_uv[i].y;
	}
      }
      texels_dirty = false;
    }
  }
  else if (buffer == CS_BUFFER_COLOR)
  {
    if (colors_dirty)
    {
      size_t color_size = vertices->GetSize ();
      if (!color_buffer.IsValid() || (color_buffer->GetSize() 
	!= color_size * sizeof(float) * 2))
      {
	color_buffer = csRenderBuffer::CreateRenderBuffer (
	  color_size, CS_BUF_STATIC, 
	  CS_BUFCOMP_FLOAT, 3);
	holder->SetRenderBuffer (CS_BUFFER_COLOR, color_buffer);
      }

      csRenderBufferLock<csColor> colorLock (color_buffer);

      for (size_t i = 0; i < vertices->GetSize (); i++)
      {
	colorLock[i] = (*vertices)[i].color;
      }
      colors_dirty = false;
    }
  }
  else if (buffer == CS_BUFFER_POSITION)
  {
    if (vertices_dirty)
    {
      size_t vertices_size = vertices->GetSize ();
      if (!vertex_buffer.IsValid() || (vertex_buffer->GetSize() 
	!= vertices_size * sizeof(float) * 3))
      {
	vertex_buffer = csRenderBuffer::CreateRenderBuffer (
	  vertices_size, CS_BUF_STATIC, 
	  CS_BUFCOMP_FLOAT, 3);
	holder->SetRenderBuffer (CS_BUFFER_POSITION, vertex_buffer);
      }

      csRenderBufferLock<csVector3> vertexLock (vertex_buffer);

      for (size_t i = 0; i < vertices->GetSize (); i++)
      {
	vertexLock[i].Set ((*vertices)[i].pos.x, (*vertices)[i].pos.y, 0.0f);
      }
      vertices_dirty = false;
    }
  }
}
Exemplo n.º 3
0
    // ------------------------------------------------------------------------
    void ShadowCaster::generateShadowVolume(EdgeData* edgeData, 
        const HardwareIndexBufferSharedPtr& indexBuffer, size_t& indexBufferUsedSize, 
        const Light* light, ShadowRenderableList& shadowRenderables, unsigned long flags)
    {
        // Edge groups should be 1:1 with shadow renderables
        assert(edgeData->edgeGroups.size() == shadowRenderables.size());

        Light::LightTypes lightType = light->getType();

        // Whether to use the McGuire method, a triangle fan covering all silhouette
        // This won't work properly with multiple separate edge groups (should be one fan per group, not implemented)
        // or when light position is too close to light cap bound.
        bool useMcGuire = edgeData->edgeGroups.size() <= 1 && 
            (lightType == Light::LT_DIRECTIONAL || isBoundOkForMcGuire(getLightCapBounds(), light->getDerivedPosition()));
        EdgeData::EdgeGroupList::const_iterator egi, egiend;
        ShadowRenderableList::const_iterator si;

        // pre-count the size of index data we need since it makes a big perf difference
        // to GL in particular if we lock a smaller area of the index buffer
        size_t preCountIndexes = 0;

        si = shadowRenderables.begin();
        egiend = edgeData->edgeGroups.end();
        for (egi = edgeData->edgeGroups.begin(); egi != egiend; ++egi, ++si)
        {
            const EdgeData::EdgeGroup& eg = *egi;
            bool  firstDarkCapTri = true;

            EdgeData::EdgeList::const_iterator i, iend;
            iend = eg.edges.end();
            for (i = eg.edges.begin(); i != iend; ++i)
            {
                const EdgeData::Edge& edge = *i;

                // Silhouette edge, when two tris has opposite light facing, or
                // degenerate edge where only tri 1 is valid and the tri light facing
                char lightFacing = edgeData->triangleLightFacings[edge.triIndex[0]];
                if ((edge.degenerate && lightFacing) ||
                    (!edge.degenerate && (lightFacing != edgeData->triangleLightFacings[edge.triIndex[1]])))
                {

                    preCountIndexes += 3;

                    // Are we extruding to infinity?
                    if (!(lightType == Light::LT_DIRECTIONAL &&
                        flags & SRF_EXTRUDE_TO_INFINITY))
                    {
                        preCountIndexes += 3;
                    }

                    if(useMcGuire)
                    {
                        // Do dark cap tri
                        // Use McGuire et al method, a triangle fan covering all silhouette
                        // edges and one point (taken from the initial tri)
                        if (flags & SRF_INCLUDE_DARK_CAP)
                        {
                            if (firstDarkCapTri)
                            {
                                firstDarkCapTri = false;
                            }
                            else
                            {
                                preCountIndexes += 3;
                            }
                        }
                    }
                }

            }

            if(useMcGuire)
            {
                // Do light cap
                if (flags & SRF_INCLUDE_LIGHT_CAP) 
                {
                    // Iterate over the triangles which are using this vertex set
                    EdgeData::TriangleList::const_iterator ti, tiend;
                    EdgeData::TriangleLightFacingList::const_iterator lfi;
                    ti = edgeData->triangles.begin() + eg.triStart;
                    tiend = ti + eg.triCount;
                    lfi = edgeData->triangleLightFacings.begin() + eg.triStart;
                    for ( ; ti != tiend; ++ti, ++lfi)
                    {
                        assert(ti->vertexSet == eg.vertexSet);
                        // Check it's light facing
                        if (*lfi)
                        {
                            preCountIndexes += 3;
                        }
                    }

                }
            }
            else
            {
                // Do both caps
                int increment = ((flags & SRF_INCLUDE_DARK_CAP) ? 3 : 0) + ((flags & SRF_INCLUDE_LIGHT_CAP) ? 3 : 0);
                if(increment != 0)
                {
                    // Iterate over the triangles which are using this vertex set
                    EdgeData::TriangleList::const_iterator ti, tiend;
                    EdgeData::TriangleLightFacingList::const_iterator lfi;
                    ti = edgeData->triangles.begin() + eg.triStart;
                    tiend = ti + eg.triCount;
                    lfi = edgeData->triangleLightFacings.begin() + eg.triStart;
                    for ( ; ti != tiend; ++ti, ++lfi)
                    {
                        assert(ti->vertexSet == eg.vertexSet);
                        // Check it's light facing
                        if (*lfi)
                            preCountIndexes += increment;
                    }
                }
            }
        }
        // End pre-count
        
        //Check if index buffer is to small 
        if (preCountIndexes > indexBuffer->getNumIndexes())
        {
            LogManager::getSingleton().logWarning(
                "shadow index buffer size to small. Auto increasing buffer size to" +
                StringConverter::toString(sizeof(unsigned short) * preCountIndexes));

            SceneManager* pManager = Root::getSingleton()._getCurrentSceneManager();
            if (pManager)
            {
                pManager->setShadowIndexBufferSize(preCountIndexes);
            }
            
            //Check that the index buffer size has actually increased
            if (preCountIndexes > indexBuffer->getNumIndexes())
            {
                //increasing index buffer size has failed
                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
                    "Lock request out of bounds.",
                    "ShadowCaster::generateShadowVolume");
            }
        }
        else if(indexBufferUsedSize + preCountIndexes > indexBuffer->getNumIndexes())
        {
            indexBufferUsedSize = 0;
        }

        // Lock index buffer for writing, just enough length as we need
        HardwareBufferLockGuard indexLock(indexBuffer,
            sizeof(unsigned short) * indexBufferUsedSize, sizeof(unsigned short) * preCountIndexes,
            indexBufferUsedSize == 0 ? HardwareBuffer::HBL_DISCARD : HardwareBuffer::HBL_NO_OVERWRITE);
        unsigned short* pIdx = static_cast<unsigned short*>(indexLock.pData);
        size_t numIndices = indexBufferUsedSize;
        
        // Iterate over the groups and form renderables for each based on their
        // lightFacing
        si = shadowRenderables.begin();
        egiend = edgeData->edgeGroups.end();
        for (egi = edgeData->edgeGroups.begin(); egi != egiend; ++egi, ++si)
        {
            const EdgeData::EdgeGroup& eg = *egi;
            // Initialise the index start for this shadow renderable
            IndexData* indexData = (*si)->getRenderOperationForUpdate()->indexData;

            if (indexData->indexBuffer != indexBuffer)
            {
                (*si)->rebindIndexBuffer(indexBuffer);
                indexData = (*si)->getRenderOperationForUpdate()->indexData;
            }

            indexData->indexStart = numIndices;
            // original number of verts (without extruded copy)
            size_t originalVertexCount = eg.vertexData->vertexCount;
            bool  firstDarkCapTri = true;
            unsigned short darkCapStart = 0;

            EdgeData::EdgeList::const_iterator i, iend;
            iend = eg.edges.end();
            for (i = eg.edges.begin(); i != iend; ++i)
            {
                const EdgeData::Edge& edge = *i;

                // Silhouette edge, when two tris has opposite light facing, or
                // degenerate edge where only tri 1 is valid and the tri light facing
                char lightFacing = edgeData->triangleLightFacings[edge.triIndex[0]];
                if ((edge.degenerate && lightFacing) ||
                    (!edge.degenerate && (lightFacing != edgeData->triangleLightFacings[edge.triIndex[1]])))
                {
                    size_t v0 = edge.vertIndex[0];
                    size_t v1 = edge.vertIndex[1];
                    if (!lightFacing)
                    {
                        // Inverse edge indexes when t1 is light away
                        std::swap(v0, v1);
                    }

                    /* Note edge(v0, v1) run anticlockwise along the edge from
                    the light facing tri so to point shadow volume tris outward,
                    light cap indexes have to be backwards

                    We emit 2 tris if light is a point light, 1 if light 
                    is directional, because directional lights cause all
                    points to converge to a single point at infinity.

                    First side tri = near1, near0, far0
                    Second tri = far0, far1, near1

                    'far' indexes are 'near' index + originalVertexCount
                    because 'far' verts are in the second half of the 
                    buffer
                    */
                    assert(v1 < 65536 && v0 < 65536 && (v0 + originalVertexCount) < 65536 &&
                        "Vertex count exceeds 16-bit index limit!");
                    *pIdx++ = static_cast<unsigned short>(v1);
                    *pIdx++ = static_cast<unsigned short>(v0);
                    *pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount);
                    numIndices += 3;

                    // Are we extruding to infinity?
                    if (!(lightType == Light::LT_DIRECTIONAL &&
                        flags & SRF_EXTRUDE_TO_INFINITY))
                    {
                        // additional tri to make quad
                        *pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount);
                        *pIdx++ = static_cast<unsigned short>(v1 + originalVertexCount);
                        *pIdx++ = static_cast<unsigned short>(v1);
                        numIndices += 3;
                    }

                    if(useMcGuire)
                    {
                        // Do dark cap tri
                        // Use McGuire et al method, a triangle fan covering all silhouette
                        // edges and one point (taken from the initial tri)
                        if (flags & SRF_INCLUDE_DARK_CAP)
                        {
                            if (firstDarkCapTri)
                            {
                                darkCapStart = static_cast<unsigned short>(v0 + originalVertexCount);
                                firstDarkCapTri = false;
                            }
                            else
                            {
                                *pIdx++ = darkCapStart;
                                *pIdx++ = static_cast<unsigned short>(v1 + originalVertexCount);
                                *pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount);
                                numIndices += 3;
                            }

                        }
                    }
                }

            }

            if(!useMcGuire)
            {
                // Do dark cap
                if (flags & SRF_INCLUDE_DARK_CAP) 
                {
                    // Iterate over the triangles which are using this vertex set
                    EdgeData::TriangleList::const_iterator ti, tiend;
                    EdgeData::TriangleLightFacingList::const_iterator lfi;
                    ti = edgeData->triangles.begin() + eg.triStart;
                    tiend = ti + eg.triCount;
                    lfi = edgeData->triangleLightFacings.begin() + eg.triStart;
                    for ( ; ti != tiend; ++ti, ++lfi)
                    {
                        const EdgeData::Triangle& t = *ti;
                        assert(t.vertexSet == eg.vertexSet);
                        // Check it's light facing
                        if (*lfi)
                        {
                            assert(t.vertIndex[0] < 65536 && t.vertIndex[1] < 65536 &&
                                t.vertIndex[2] < 65536 && 
                                "16-bit index limit exceeded!");
                            *pIdx++ = static_cast<unsigned short>(t.vertIndex[1] + originalVertexCount);
                            *pIdx++ = static_cast<unsigned short>(t.vertIndex[0] + originalVertexCount);
                            *pIdx++ = static_cast<unsigned short>(t.vertIndex[2] + originalVertexCount);
                            numIndices += 3;
                        }
                    }

                }
            }

            // Do light cap
            if (flags & SRF_INCLUDE_LIGHT_CAP) 
            {
                // separate light cap?
                if ((*si)->isLightCapSeparate())
                {
                    // update index count for this shadow renderable
                    indexData->indexCount = numIndices - indexData->indexStart;

                    // get light cap index data for update
                    indexData = (*si)->getLightCapRenderable()->getRenderOperationForUpdate()->indexData;
                    // start indexes after the current total
                    indexData->indexStart = numIndices;
                }

                // Iterate over the triangles which are using this vertex set
                EdgeData::TriangleList::const_iterator ti, tiend;
                EdgeData::TriangleLightFacingList::const_iterator lfi;
                ti = edgeData->triangles.begin() + eg.triStart;
                tiend = ti + eg.triCount;
                lfi = edgeData->triangleLightFacings.begin() + eg.triStart;
                for ( ; ti != tiend; ++ti, ++lfi)
                {
                    const EdgeData::Triangle& t = *ti;
                    assert(t.vertexSet == eg.vertexSet);
                    // Check it's light facing
                    if (*lfi)
                    {
                        assert(t.vertIndex[0] < 65536 && t.vertIndex[1] < 65536 &&
                            t.vertIndex[2] < 65536 && 
                            "16-bit index limit exceeded!");
                        *pIdx++ = static_cast<unsigned short>(t.vertIndex[0]);
                        *pIdx++ = static_cast<unsigned short>(t.vertIndex[1]);
                        *pIdx++ = static_cast<unsigned short>(t.vertIndex[2]);
                        numIndices += 3;
                    }
                }

            }

            // update index count for current index data (either this shadow renderable or its light cap)
            indexData->indexCount = numIndices - indexData->indexStart;

        }

        // In debug mode, check we didn't overrun the index buffer
        assert(numIndices == indexBufferUsedSize + preCountIndexes);
        assert(numIndices <= indexBuffer->getNumIndexes() &&
            "Index buffer overrun while generating shadow volume!! "
            "You must increase the size of the shadow index buffer.");

        indexBufferUsedSize = numIndices;
    }