1699 lines
58 KiB
C++
1699 lines
58 KiB
C++
|
/*============================================================================
|
||
|
*
|
||
|
* Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: drawgrid.cpp
|
||
|
* Content: Implementation for high order surfaces
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include "pch.cpp"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// RDHOCoeffs::operator=
|
||
|
//-----------------------------------------------------------------------------
|
||
|
RDHOCoeffs& RDHOCoeffs::operator=(const RDHOCoeffs &coeffs)
|
||
|
{
|
||
|
m_Width = coeffs.m_Width;
|
||
|
m_Height = coeffs.m_Height;
|
||
|
m_Stride = coeffs.m_Stride;
|
||
|
m_Basis = coeffs.m_Basis;
|
||
|
m_Order = coeffs.m_Order;
|
||
|
if(coeffs.m_pNumSegs != 0)
|
||
|
{
|
||
|
m_pNumSegs = new FLOAT[4];
|
||
|
if(m_pNumSegs != 0)
|
||
|
{
|
||
|
memcpy(m_pNumSegs, coeffs.m_pNumSegs, sizeof(FLOAT) * 4);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pNumSegs = 0;
|
||
|
}
|
||
|
for(unsigned i = 0; i < RD_MAX_NUMSTREAMS; ++i)
|
||
|
{
|
||
|
if(coeffs.m_pData[i] != 0)
|
||
|
{
|
||
|
m_DataSize[i] = coeffs.m_DataSize[i];
|
||
|
m_pData[i] = new BYTE[m_DataSize[i]];
|
||
|
if(m_pData[i] != 0)
|
||
|
{
|
||
|
memcpy(m_pData[i], coeffs.m_pData[i], m_DataSize[i]);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pData[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// RefDev::DrawRectPatch
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
RefDev::DrawRectPatch( LPD3DHAL_DP2DRAWRECTPATCH pDP )
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
|
||
|
{
|
||
|
//
|
||
|
// The legacy FVF style: The Zero'th Stream is implied
|
||
|
//
|
||
|
DWORD dwFVF = m_CurrentVShaderHandle;
|
||
|
RDVStream& Stream = m_VStream[0];
|
||
|
DWORD dwStride = Stream.m_dwStride;
|
||
|
DWORD dwFVFSize = GetFVFVertexSize( dwFVF );
|
||
|
|
||
|
if( Stream.m_pData == NULL || dwStride == 0 )
|
||
|
{
|
||
|
DPFERR("Zero'th stream doesnt have valid VB set");
|
||
|
return DDERR_INVALIDPARAMS;
|
||
|
}
|
||
|
if( dwStride < dwFVFSize )
|
||
|
{
|
||
|
DPFERR("The stride set for the vertex stream is less than the FVF vertex size");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FLOAT *pSegs;
|
||
|
D3DRECTPATCH_INFO Info, *pInfo;
|
||
|
BYTE *TempData[RD_MAX_NUMSTREAMS + 1];
|
||
|
|
||
|
if(pDP->Handle != 0)
|
||
|
{
|
||
|
if((pDP->Flags & RTPATCHFLAG_HASINFO) != 0) // Is either a first time or a recompute
|
||
|
{
|
||
|
HR_RET( m_HOSCoeffs.Grow(pDP->Handle) );
|
||
|
|
||
|
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
|
||
|
{
|
||
|
pInfo = (D3DRECTPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 4));
|
||
|
pSegs = (FLOAT*)(pDP + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pInfo = (D3DRECTPATCH_INFO*)(pDP + 1);
|
||
|
pSegs = 0;
|
||
|
}
|
||
|
|
||
|
RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
|
||
|
coeffs.m_Width = pInfo->Width;
|
||
|
coeffs.m_Height = pInfo->Height;
|
||
|
coeffs.m_Stride = pInfo->Width;
|
||
|
coeffs.m_Basis = pInfo->Basis;
|
||
|
coeffs.m_Order = pInfo->Order;
|
||
|
|
||
|
delete[] coeffs.m_pNumSegs;
|
||
|
if(pSegs != 0)
|
||
|
{
|
||
|
coeffs.m_pNumSegs = new FLOAT[4];
|
||
|
if(coeffs.m_pNumSegs == 0)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
memcpy(coeffs.m_pNumSegs, pSegs, sizeof(FLOAT) * 4);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
coeffs.m_pNumSegs = 0;
|
||
|
}
|
||
|
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
|
||
|
{
|
||
|
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
|
||
|
if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
|
||
|
{
|
||
|
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
|
||
|
delete[] coeffs.m_pData[StreamDecl.m_dwStreamIndex];
|
||
|
coeffs.m_DataSize[StreamDecl.m_dwStreamIndex] = pInfo->Width * pInfo->Height * Stream.m_dwStride;
|
||
|
coeffs.m_pData[StreamDecl.m_dwStreamIndex] = new BYTE[coeffs.m_DataSize[StreamDecl.m_dwStreamIndex]];
|
||
|
if(coeffs.m_pData[StreamDecl.m_dwStreamIndex] == 0)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
for(unsigned k = 0; k < pInfo->Height; ++k)
|
||
|
{
|
||
|
memcpy(&coeffs.m_pData[StreamDecl.m_dwStreamIndex][k * pInfo->Width * Stream.m_dwStride],
|
||
|
&Stream.m_pData[((pInfo->StartVertexOffsetHeight + k) * pInfo->Stride + pInfo->StartVertexOffsetWidth) * Stream.m_dwStride],
|
||
|
pInfo->Width * Stream.m_dwStride);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Guard against bad handles
|
||
|
if(pDP->Handle >= m_HOSCoeffs.GetSize())
|
||
|
{
|
||
|
DPFERR("Invalid patch handle specified in Draw*Patch call");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
|
||
|
Info.StartVertexOffsetWidth = 0;
|
||
|
Info.StartVertexOffsetHeight = 0;
|
||
|
Info.Width = coeffs.m_Width;
|
||
|
Info.Height = coeffs.m_Height;
|
||
|
Info.Stride = coeffs.m_Stride;
|
||
|
Info.Basis = coeffs.m_Basis;
|
||
|
Info.Order = coeffs.m_Order;
|
||
|
pInfo = &Info;
|
||
|
|
||
|
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
|
||
|
{
|
||
|
pSegs = (FLOAT*)(pDP + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pSegs = coeffs.m_pNumSegs;
|
||
|
}
|
||
|
|
||
|
// Save current data stream pointers and replace with
|
||
|
// pointer to tessellation output
|
||
|
hr = LinkCachedTessellatorOutput(pDP->Handle, TempData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if((pDP->Flags & RTPATCHFLAG_HASINFO) == 0)
|
||
|
{
|
||
|
DPFERR("Need patch info if handle is zero");
|
||
|
return DDERR_INVALIDPARAMS;
|
||
|
}
|
||
|
|
||
|
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
|
||
|
{
|
||
|
pInfo = (D3DRECTPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 4));
|
||
|
pSegs = (FLOAT*)(pDP + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pInfo = (D3DRECTPATCH_INFO*)(pDP + 1);
|
||
|
pSegs = 0;
|
||
|
}
|
||
|
|
||
|
// Save current data stream pointers and replace with
|
||
|
// pointer to tessellation output
|
||
|
hr = LinkTessellatorOutput();
|
||
|
}
|
||
|
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
switch(pInfo->Basis)
|
||
|
{
|
||
|
case D3DBASIS_BSPLINE:
|
||
|
hr = ProcessBSpline(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
|
||
|
pInfo->Width, pInfo->Height,
|
||
|
pInfo->Stride, pInfo->Order,
|
||
|
pSegs);
|
||
|
break;
|
||
|
case D3DBASIS_BEZIER:
|
||
|
hr = ProcessBezier(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
|
||
|
pInfo->Width, pInfo->Height,
|
||
|
pInfo->Stride, pInfo->Order,
|
||
|
pSegs,
|
||
|
false);
|
||
|
break;
|
||
|
case D3DBASIS_INTERPOLATE:
|
||
|
hr = ProcessCatRomSpline(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
|
||
|
pInfo->Width, pInfo->Height,
|
||
|
pInfo->Stride,
|
||
|
pSegs);
|
||
|
break;
|
||
|
default:
|
||
|
hr = E_NOTIMPL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(pDP->Handle != 0)
|
||
|
{
|
||
|
// Restore back saved pointer
|
||
|
UnlinkCachedTessellatorOutput(TempData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Restore back saved pointer
|
||
|
UnlinkTessellatorOutput();
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// RefDev::ConvertLinearTriBezierToRectBezier
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
RefDev::ConvertLinearTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
|
||
|
{
|
||
|
DWORD dwElements = 0;
|
||
|
switch(dwDataType)
|
||
|
{
|
||
|
case D3DVSDT_FLOAT4:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT3:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT2:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT1:
|
||
|
++dwElements;
|
||
|
{
|
||
|
// Replicate first point twice to get a singular edge
|
||
|
for(unsigned i = 0; i < 2; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 2; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case D3DVSDT_D3DCOLOR:
|
||
|
case D3DVSDT_UBYTE4:
|
||
|
dwElements = 4;
|
||
|
{
|
||
|
// Replicate first point twice to get a singular edge
|
||
|
for(unsigned i = 0; i < 2; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 2; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case D3DVSDT_SHORT4:
|
||
|
dwElements += 2;
|
||
|
case D3DVSDT_SHORT2:
|
||
|
dwElements += 2;
|
||
|
{
|
||
|
// Replicate first point twice to get a singular edge
|
||
|
for(unsigned i = 0; i < 2; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 2; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
_ASSERT(FALSE, "Ununderstood vertex element data type");
|
||
|
return DDERR_INVALIDPARAMS;
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// RefDev::ConvertCubicTriBezierToRectBezier
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
RefDev::ConvertCubicTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
|
||
|
{
|
||
|
DWORD dwElements = 0;
|
||
|
switch(dwDataType)
|
||
|
{
|
||
|
case D3DVSDT_FLOAT4:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT3:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT2:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT1:
|
||
|
++dwElements;
|
||
|
{
|
||
|
// Replicate first point four times to get a singular edge
|
||
|
for(unsigned i = 0; i < 4; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// For the next row, we simply copy the second point
|
||
|
// followed by two interpolated control points
|
||
|
// followed by the third point
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
FLOAT *B021 = (FLOAT*)B, *B120 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B021[i] * 2.0 + B120[i]) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B021[i] + B120[i] * 2.0) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
FLOAT *B012 = (FLOAT*)B, *B111 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B012[i] + B111[i] * 2.0) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
FLOAT *B210 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B111[i] * 2.0 + B210[i]) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 4; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case D3DVSDT_D3DCOLOR:
|
||
|
case D3DVSDT_UBYTE4:
|
||
|
dwElements = 4;
|
||
|
{
|
||
|
// Replicate first point four times to get a singular edge
|
||
|
for(unsigned i = 0; i < 4; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// For the next row, we simply copy the second point
|
||
|
// followed by two interpolated control points
|
||
|
// followed by the third point
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
BYTE *B021 = (BYTE*)B, *B120 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B021[i] * 2.0 + B120[i]) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B021[i] + B120[i] * 2.0) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
BYTE *B012 = (BYTE*)B, *B111 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B012[i] + B111[i] * 2.0) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
BYTE *B210 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B111[i] * 2.0 + B210[i]) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 4; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case D3DVSDT_SHORT4:
|
||
|
dwElements += 2;
|
||
|
case D3DVSDT_SHORT2:
|
||
|
dwElements += 2;
|
||
|
{
|
||
|
// Replicate first point four times to get a singular edge
|
||
|
for(unsigned i = 0; i < 4; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// For the next row, we simply copy the second point
|
||
|
// followed by two interpolated control points
|
||
|
// followed by the third point
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
SHORT *B021 = (SHORT*)B, *B120 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B021[i] * 2.0 + B120[i]) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B021[i] + B120[i] * 2.0) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
SHORT *B012 = (SHORT*)B, *B111 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B012[i] + B111[i] * 2.0) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
SHORT *B210 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B111[i] * 2.0 + B210[i]) / 3.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 4; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
_ASSERT(FALSE, "Ununderstood vertex element data type");
|
||
|
return DDERR_INVALIDPARAMS;
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// RefDev::ConvertQuinticTriBezierToRectBezier
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
RefDev::ConvertQuinticTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
|
||
|
{
|
||
|
DWORD dwElements = 0;
|
||
|
switch(dwDataType)
|
||
|
{
|
||
|
case D3DVSDT_FLOAT4:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT3:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT2:
|
||
|
++dwElements;
|
||
|
case D3DVSDT_FLOAT1:
|
||
|
++dwElements;
|
||
|
{
|
||
|
// Replicate first point six times to get a singular edge
|
||
|
for(unsigned i = 0; i < 6; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// For the next row, we simply copy the second point
|
||
|
// followed by four interpolated control points
|
||
|
// followed by the fifth point
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
FLOAT *B041 = (FLOAT*)B, *B140 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B041[i] * 4.0 + B140[i]) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B041[i] + B140[i] * 4.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
FLOAT *B032 = (FLOAT*)B, *B131 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
FLOAT *B230 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
FLOAT *B023 = (FLOAT*)B, *B122 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
FLOAT *B221 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
FLOAT *B320 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
FLOAT *B014 = (FLOAT*)B, *B113 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B014[i] + B113[i] * 4.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
FLOAT *B212 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
FLOAT *B311 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
FLOAT *B410 = (FLOAT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((FLOAT*)Q)[i] = FLOAT((B311[i] * 4.0 + B410[i]) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 6; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(FLOAT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case D3DVSDT_UBYTE4:
|
||
|
case D3DVSDT_D3DCOLOR:
|
||
|
dwElements = 4;
|
||
|
{
|
||
|
// Replicate first point six times to get a singular edge
|
||
|
for(unsigned i = 0; i < 6; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// For the next row, we simply copy the second point
|
||
|
// followed by four interpolated control points
|
||
|
// followed by the fifth point
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
BYTE *B041 = (BYTE*)B, *B140 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B041[i] * 4.0 + B140[i]) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B041[i] + B140[i] * 4.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
BYTE *B032 = (BYTE*)B, *B131 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
BYTE *B230 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
BYTE *B023 = (BYTE*)B, *B122 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
BYTE *B221 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
BYTE *B320 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
BYTE *B014 = (BYTE*)B, *B113 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B014[i] + B113[i] * 4.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
BYTE *B212 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
BYTE *B311 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
BYTE *B410 = (BYTE*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((BYTE*)Q)[i] = BYTE((B311[i] * 4.0 + B410[i]) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 6; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(BYTE) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case D3DVSDT_SHORT4:
|
||
|
dwElements += 2;
|
||
|
case D3DVSDT_SHORT2:
|
||
|
dwElements += 2;
|
||
|
{
|
||
|
// Replicate first point six times to get a singular edge
|
||
|
for(unsigned i = 0; i < 6; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
}
|
||
|
B += dwStride;
|
||
|
|
||
|
// For the next row, we simply copy the second point
|
||
|
// followed by four interpolated control points
|
||
|
// followed by the fifth point
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
SHORT *B041 = (SHORT*)B, *B140 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B041[i] * 4.0 + B140[i]) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B041[i] + B140[i] * 4.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
SHORT *B032 = (SHORT*)B, *B131 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
SHORT *B230 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
SHORT *B023 = (SHORT*)B, *B122 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
SHORT *B221 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
SHORT *B320 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Again, we copy the edge points and interpolate
|
||
|
// the central ones
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
|
||
|
SHORT *B014 = (SHORT*)B, *B113 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B014[i] + B113[i] * 4.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
SHORT *B212 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
SHORT *B311 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
SHORT *B410 = (SHORT*)(B + dwStride);
|
||
|
for(i = 0; i < dwElements; ++i)
|
||
|
{
|
||
|
((SHORT*)Q)[i] = SHORT((B311[i] * 4.0 + B410[i]) / 5.0);
|
||
|
}
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
|
||
|
// Finally we just copy the last row
|
||
|
for(i = 0; i < 6; ++i)
|
||
|
{
|
||
|
memcpy(Q, B, sizeof(SHORT) * dwElements);
|
||
|
Q += dwStride;
|
||
|
B += dwStride;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
_ASSERT(FALSE, "Ununderstood vertex element data type");
|
||
|
return DDERR_INVALIDPARAMS;
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// RefDev::DrawTriPatch
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
RefDev::DrawTriPatch( LPD3DHAL_DP2DRAWTRIPATCH pDP )
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
|
||
|
{
|
||
|
//
|
||
|
// The legacy FVF style: The Zero'th Stream is implied
|
||
|
//
|
||
|
DWORD dwFVF = m_CurrentVShaderHandle;
|
||
|
RDVStream& Stream = m_VStream[0];
|
||
|
DWORD dwStride = Stream.m_dwStride;
|
||
|
DWORD dwFVFSize = GetFVFVertexSize( dwFVF );
|
||
|
|
||
|
if( Stream.m_pData == NULL || dwStride == 0 )
|
||
|
{
|
||
|
DPFERR("Zero'th stream doesnt have valid VB set");
|
||
|
return DDERR_INVALIDPARAMS;
|
||
|
}
|
||
|
if( dwStride < dwFVFSize )
|
||
|
{
|
||
|
DPFERR("The stride set for the vertex stream is less than the FVF vertex size");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FLOAT *pSegs;
|
||
|
D3DRECTPATCH_INFO Info;
|
||
|
BYTE *TempData[RD_MAX_NUMSTREAMS + 1];
|
||
|
|
||
|
if(pDP->Handle == 0 && (pDP->Flags & RTPATCHFLAG_HASINFO) == 0)
|
||
|
{
|
||
|
DPFERR("Need patch info if handle is zero");
|
||
|
return DDERR_INVALIDPARAMS;
|
||
|
}
|
||
|
|
||
|
if((pDP->Flags & RTPATCHFLAG_HASINFO) != 0) // Is either a first time or a recompute
|
||
|
{
|
||
|
HR_RET( m_HOSCoeffs.Grow(pDP->Handle) );
|
||
|
|
||
|
D3DTRIPATCH_INFO *pInfo;
|
||
|
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
|
||
|
{
|
||
|
pInfo = (D3DTRIPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 3));
|
||
|
pSegs = (FLOAT*)(pDP + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pInfo = (D3DTRIPATCH_INFO*)(pDP + 1);
|
||
|
pSegs = 0;
|
||
|
}
|
||
|
|
||
|
RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
|
||
|
coeffs.m_Width = (DWORD)pInfo->Order + 1;
|
||
|
coeffs.m_Height = (DWORD)pInfo->Order + 1;
|
||
|
coeffs.m_Stride = (DWORD)pInfo->Order + 1;
|
||
|
coeffs.m_Basis = pInfo->Basis;
|
||
|
coeffs.m_Order = pInfo->Order;
|
||
|
|
||
|
delete[] coeffs.m_pNumSegs;
|
||
|
if(pSegs != 0)
|
||
|
{
|
||
|
coeffs.m_pNumSegs = new FLOAT[4];
|
||
|
if(coeffs.m_pNumSegs == 0)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
coeffs.m_pNumSegs[0] = pSegs[2];
|
||
|
memcpy(&coeffs.m_pNumSegs[1], pSegs, sizeof(FLOAT) * 3);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
coeffs.m_pNumSegs = 0;
|
||
|
}
|
||
|
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
|
||
|
// Allocate memory to hold rect patches rather than tri patches
|
||
|
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
|
||
|
{
|
||
|
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
|
||
|
if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
|
||
|
{
|
||
|
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
|
||
|
delete[] coeffs.m_pData[StreamDecl.m_dwStreamIndex];
|
||
|
coeffs.m_DataSize[StreamDecl.m_dwStreamIndex] = coeffs.m_Width * coeffs.m_Height * Stream.m_dwStride;
|
||
|
coeffs.m_pData[StreamDecl.m_dwStreamIndex] = new BYTE[coeffs.m_DataSize[StreamDecl.m_dwStreamIndex]];
|
||
|
if(coeffs.m_pData[StreamDecl.m_dwStreamIndex] == 0)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now go through tri patch data, convert it to rect patch and store it in
|
||
|
// in the space that we allocated above
|
||
|
for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
|
||
|
{
|
||
|
RDVElement &velem = Decl.m_VertexElements[e];
|
||
|
if(!velem.m_bIsTessGen)
|
||
|
{
|
||
|
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
|
||
|
LPBYTE Q = coeffs.m_pData[velem.m_dwStreamIndex] + velem.m_dwOffset;
|
||
|
LPBYTE B = vstream.m_pData + pInfo->StartVertexOffset * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
if(pInfo->Order == D3DORDER_LINEAR)
|
||
|
{
|
||
|
hr = ConvertLinearTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
DPFERR("Conversion from Linear Tri Patch to Rect Patch failed");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
else if(pInfo->Order == D3DORDER_CUBIC)
|
||
|
{
|
||
|
hr = ConvertCubicTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
DPFERR("Conversion from Cubic Tri Patch to Rect Patch failed");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
else if(pInfo->Order == D3DORDER_QUINTIC)
|
||
|
{
|
||
|
hr = ConvertQuinticTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
DPFERR("Conversion from Quintic Tri Patch to Rect Patch failed");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DPFERR("Only cubic Bezier patches currently supported");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Guard against bad handles
|
||
|
if(pDP->Handle >= m_HOSCoeffs.GetSize())
|
||
|
{
|
||
|
DPFERR("Invalid patch handle specified in Draw*Patch call");
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
|
||
|
Info.StartVertexOffsetWidth = 0;
|
||
|
Info.StartVertexOffsetHeight = 0;
|
||
|
Info.Width = coeffs.m_Width;
|
||
|
Info.Height = coeffs.m_Height;
|
||
|
Info.Stride = coeffs.m_Stride;
|
||
|
Info.Basis = coeffs.m_Basis;
|
||
|
Info.Order = coeffs.m_Order;
|
||
|
D3DRECTPATCH_INFO *pInfo = &Info;
|
||
|
|
||
|
FLOAT Segs[4];
|
||
|
if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
|
||
|
{
|
||
|
Segs[0] = ((FLOAT*)(pDP + 1))[2];
|
||
|
memcpy(&Segs[1], pDP + 1, sizeof(FLOAT) * 3);
|
||
|
pSegs = &Segs[0];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pSegs = coeffs.m_pNumSegs;
|
||
|
}
|
||
|
|
||
|
// Save current data stream pointers and replace with
|
||
|
// pointer to tessellation output
|
||
|
hr = LinkCachedTessellatorOutput(pDP->Handle, TempData);
|
||
|
if( SUCCEEDED(hr) )
|
||
|
{
|
||
|
switch(pInfo->Basis)
|
||
|
{
|
||
|
case D3DBASIS_BEZIER:
|
||
|
hr = ProcessBezier(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
|
||
|
pInfo->Width, pInfo->Height,
|
||
|
pInfo->Stride, pInfo->Order,
|
||
|
pSegs,
|
||
|
true);
|
||
|
break;
|
||
|
default:
|
||
|
hr = E_NOTIMPL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Restore back saved pointer
|
||
|
UnlinkCachedTessellatorOutput(TempData);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------
|
||
|
// RefDev::LinkTessellatorOutput
|
||
|
//---------------------------------------------------------------------
|
||
|
HRESULT RefDev::LinkTessellatorOutput()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
|
||
|
{
|
||
|
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
|
||
|
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
|
||
|
// Make space for four vertices
|
||
|
hr |= Stream.m_TessOut.Grow(StreamDecl.m_dwStride * 4);
|
||
|
Stream.m_pSavedData = Stream.m_pData;
|
||
|
Stream.m_pData = &Stream.m_TessOut[0];
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------
|
||
|
// RefDev::LinkCachedTessellatorOutput
|
||
|
//---------------------------------------------------------------------
|
||
|
HRESULT RefDev::LinkCachedTessellatorOutput(DWORD Handle, BYTE **pTempData)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
|
||
|
{
|
||
|
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
|
||
|
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
|
||
|
// Make space for four vertices
|
||
|
hr |= Stream.m_TessOut.Grow(StreamDecl.m_dwStride * 4);
|
||
|
if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
|
||
|
{
|
||
|
Stream.m_pSavedData = m_HOSCoeffs[Handle].m_pData[StreamDecl.m_dwStreamIndex];
|
||
|
if(Stream.m_pSavedData == 0)
|
||
|
{
|
||
|
DPFERR("Deleted or unspecified patch was requested to be drawn");
|
||
|
hr |= E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Stream.m_pSavedData = 0;
|
||
|
}
|
||
|
pTempData[StreamDecl.m_dwStreamIndex] = Stream.m_pData;
|
||
|
Stream.m_pData = &Stream.m_TessOut[0];
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------
|
||
|
// RefDev::UnlinkTessellatorOuput
|
||
|
//---------------------------------------------------------------------
|
||
|
void RefDev::UnlinkTessellatorOutput()
|
||
|
{
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
|
||
|
{
|
||
|
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
|
||
|
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
|
||
|
Stream.m_pData = Stream.m_pSavedData;
|
||
|
Stream.m_pSavedData = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------
|
||
|
// RefDev::UnlinkTessellatorOuput
|
||
|
//---------------------------------------------------------------------
|
||
|
void RefDev::UnlinkCachedTessellatorOutput(BYTE **pTempData)
|
||
|
{
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
|
||
|
{
|
||
|
RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
|
||
|
RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
|
||
|
Stream.m_pData = pTempData[StreamDecl.m_dwStreamIndex];
|
||
|
Stream.m_pSavedData = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------
|
||
|
// RefDev::DrawTessQuad
|
||
|
//---------------------------------------------------------------------
|
||
|
HRESULT RefDev::DrawTessQuad( const RDBSpline &Surf, DWORD dwOffW, DWORD dwOffH, DWORD dwStride,
|
||
|
const unsigned *m, const unsigned *n,
|
||
|
double u0, double v0, double u1, double v1,
|
||
|
double tu0, double tv0, double tu1, double tv1,
|
||
|
bool bDegenerate )
|
||
|
{
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
|
||
|
{
|
||
|
RDVElement &velem = Decl.m_VertexElements[e];
|
||
|
if(velem.m_bIsTessGen)
|
||
|
{
|
||
|
if((velem.m_dwToken & 0x10000000) == 0) // Check if token is D3DVSD_TESSNORMAL
|
||
|
{
|
||
|
RDVStream &vstrmin = m_VStream[velem.m_dwStreamIndexIn];
|
||
|
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
|
||
|
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
|
||
|
LPBYTE B = vstrmin.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
|
||
|
Surf.SampleNormal(velem.m_dwDataType, u0, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstrmin.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
|
||
|
Surf.SampleNormal(velem.m_dwDataType, u1, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstrmin.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
|
||
|
Surf.SampleNormal(velem.m_dwDataType, u1, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstrmin.m_pSavedData + ((dwOffH + n[3]) * dwStride + (dwOffW + m[3])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
|
||
|
Surf.SampleNormal(velem.m_dwDataType, u0, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
}
|
||
|
else // it is D3DVSD_TESSUV
|
||
|
{
|
||
|
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
|
||
|
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
|
||
|
if(bDegenerate)
|
||
|
{
|
||
|
((FLOAT*)Q)[0] = (FLOAT)(tu0 * tv0);
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
((FLOAT*)Q)[0] = (FLOAT)tu0;
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv0;
|
||
|
}
|
||
|
Q += vstream.m_dwStride;
|
||
|
if(bDegenerate)
|
||
|
{
|
||
|
((FLOAT*)Q)[0] = (FLOAT)(tu1 * tv0);
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
((FLOAT*)Q)[0] = (FLOAT)tu1;
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv0;
|
||
|
}
|
||
|
Q += vstream.m_dwStride;
|
||
|
if(bDegenerate)
|
||
|
{
|
||
|
((FLOAT*)Q)[0] = (FLOAT)(tu1 * tv1);
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
((FLOAT*)Q)[0] = (FLOAT)tu1;
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv1;
|
||
|
}
|
||
|
Q += vstream.m_dwStride;
|
||
|
if(bDegenerate)
|
||
|
{
|
||
|
((FLOAT*)Q)[0] = (FLOAT)(tu0 * tv1);
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
((FLOAT*)Q)[0] = (FLOAT)tu0;
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
|
||
|
LPBYTE B = vstream.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
|
||
|
Surf.Sample(velem.m_dwDataType, u0, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstream.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
Surf.Sample(velem.m_dwDataType, u1, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstream.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
Surf.Sample(velem.m_dwDataType, u1, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstream.m_pSavedData + ((dwOffH + n[3]) * dwStride + (dwOffW + m[3])) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
Surf.Sample(velem.m_dwDataType, u0, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT hr;
|
||
|
if( m_pCurrentVShader->IsFixedFunction() )
|
||
|
{
|
||
|
//
|
||
|
// With declaration for Fixed Function pipeline, DX8 style
|
||
|
//
|
||
|
hr = ProcessPrimitive( D3DPT_TRIANGLEFAN, 0, 4, 0, 0 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Pure Vertex Shader
|
||
|
//
|
||
|
hr = ProcessPrimitiveVVM( D3DPT_TRIANGLEFAN, 0, 4, 0, 0 );
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------
|
||
|
// RefDev::DrawTessTri
|
||
|
//---------------------------------------------------------------------
|
||
|
HRESULT RefDev::DrawTessTri( const RDBSpline &Surf, DWORD dwOffW, DWORD dwOffH, DWORD dwStride,
|
||
|
const unsigned *m, const unsigned *n,
|
||
|
double u0, double v0, double u1, double v1, double u2, double v2,
|
||
|
double tu0, double tv0, double tu1, double tv1, double tu2, double tv2,
|
||
|
bool bDegenerate0, bool bDegenerate1, bool bDegenerate2 )
|
||
|
{
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
|
||
|
{
|
||
|
RDVElement &velem = Decl.m_VertexElements[e];
|
||
|
if(velem.m_bIsTessGen)
|
||
|
{
|
||
|
if((velem.m_dwToken & 0x10000000) == 0) // Check if token is D3DVSD_TESSNORMAL
|
||
|
{
|
||
|
RDVStream &vstrmin = m_VStream[velem.m_dwStreamIndexIn];
|
||
|
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
|
||
|
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
|
||
|
LPBYTE B = vstrmin.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
|
||
|
if(bDegenerate0)
|
||
|
{
|
||
|
Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Surf.SampleNormal(velem.m_dwDataType, u0, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
}
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstrmin.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
|
||
|
if(bDegenerate1)
|
||
|
{
|
||
|
Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Surf.SampleNormal(velem.m_dwDataType, u1, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
}
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstrmin.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
|
||
|
if(bDegenerate2)
|
||
|
{
|
||
|
Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Surf.SampleNormal(velem.m_dwDataType, u2, v2, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
|
||
|
}
|
||
|
}
|
||
|
else // it is D3DVSD_TESSUV
|
||
|
{
|
||
|
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
|
||
|
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
|
||
|
((FLOAT*)Q)[0] = (FLOAT)tu0;
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv0;
|
||
|
Q += vstream.m_dwStride;
|
||
|
((FLOAT*)Q)[0] = (FLOAT)tu1;
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv1;
|
||
|
Q += vstream.m_dwStride;
|
||
|
((FLOAT*)Q)[0] = (FLOAT)tu2;
|
||
|
((FLOAT*)Q)[1] = (FLOAT)tv2;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
|
||
|
LPBYTE B = vstream.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
|
||
|
Surf.Sample(velem.m_dwDataType, u0, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstream.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
Surf.Sample(velem.m_dwDataType, u1, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
B = vstream.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
Surf.Sample(velem.m_dwDataType, u2, v2, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT hr;
|
||
|
if( m_pCurrentVShader->IsFixedFunction() )
|
||
|
{
|
||
|
//
|
||
|
// With declaration for Fixed Function pipeline, DX8 style
|
||
|
//
|
||
|
hr = ProcessPrimitive( D3DPT_TRIANGLELIST, 0, 3, 0, 0 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Pure Vertex Shader
|
||
|
//
|
||
|
hr = ProcessPrimitiveVVM( D3DPT_TRIANGLELIST, 0, 3, 0, 0 );
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------
|
||
|
// RefDev::DrawNPatch
|
||
|
//---------------------------------------------------------------------
|
||
|
HRESULT RefDev::DrawNPatch(const RDNPatch &Patch, DWORD dwStride,
|
||
|
const unsigned *m, const unsigned *n, unsigned segs)
|
||
|
{
|
||
|
for(unsigned i = 0; i < segs; ++i)
|
||
|
{
|
||
|
double v0 = double(i) / double(segs);
|
||
|
double v1 = v0;
|
||
|
double v2 = double(i + 1) / double(segs);
|
||
|
double v3 = v2;
|
||
|
for(unsigned j = 0; j < segs - i; ++j)
|
||
|
{
|
||
|
double u0 = double(j + 1) / double(segs);
|
||
|
double u1 = double(j) / double(segs);
|
||
|
double u2 = u1;
|
||
|
double u3 = u0;
|
||
|
RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
|
||
|
for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
|
||
|
{
|
||
|
RDVElement &velem = Decl.m_VertexElements[e];
|
||
|
RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
|
||
|
LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
|
||
|
if(velem.m_dwRegister == D3DVSDE_POSITION)
|
||
|
{
|
||
|
Patch.SamplePosition(u0, v0, (FLOAT*)Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.SamplePosition(u1, v1, (FLOAT*)Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.SamplePosition(u2, v2, (FLOAT*)Q);
|
||
|
if(j != segs - i - 1)
|
||
|
{
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.SamplePosition(u3, v3, (FLOAT*)Q);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
if(velem.m_dwRegister == D3DVSDE_NORMAL)
|
||
|
{
|
||
|
BYTE* B[3];
|
||
|
B[0] = vstream.m_pSavedData + (n[0] * dwStride + m[0]) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
B[1] = vstream.m_pSavedData + (n[1] * dwStride + m[1]) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
B[2] = vstream.m_pSavedData + (n[2] * dwStride + m[2]) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
|
||
|
Patch.SampleNormal(u0, v0, B, (FLOAT*)Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.SampleNormal(u1, v1, B, (FLOAT*)Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.SampleNormal(u2, v2, B, (FLOAT*)Q);
|
||
|
if(j != segs - i - 1)
|
||
|
{
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.SampleNormal(u3, v3, B, (FLOAT*)Q);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BYTE *B[3];
|
||
|
B[0] = vstream.m_pSavedData + (n[0] * dwStride + m[0]) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
B[1] = vstream.m_pSavedData + (n[1] * dwStride + m[1]) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
B[2] = vstream.m_pSavedData + (n[2] * dwStride + m[2]) * vstream.m_dwStride + velem.m_dwOffset;
|
||
|
Patch.Sample(velem.m_dwDataType, u0, v0, B, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.Sample(velem.m_dwDataType, u1, v1, B, Q);
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.Sample(velem.m_dwDataType, u2, v2, B, Q);
|
||
|
if(j != segs - i - 1)
|
||
|
{
|
||
|
Q += vstream.m_dwStride;
|
||
|
Patch.Sample(velem.m_dwDataType, u3, v3, B, Q);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
DWORD cVerts = (j != segs - i - 1) ? 4 : 3;
|
||
|
HRESULT hr;
|
||
|
if( m_pCurrentVShader->IsFixedFunction() )
|
||
|
{
|
||
|
//
|
||
|
// With declaration for Fixed Function pipeline, DX8 style
|
||
|
//
|
||
|
hr = ProcessPrimitive( D3DPT_TRIANGLEFAN, 0, cVerts, 0, 0 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Pure Vertex Shader
|
||
|
//
|
||
|
hr = ProcessPrimitiveVVM( D3DPT_TRIANGLEFAN, 0, cVerts, 0, 0 );
|
||
|
}
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|