611 lines
24 KiB
C++
611 lines
24 KiB
C++
/*============================================================================
|
|
*
|
|
* Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: bspline.cpp
|
|
* Content: Implementation for B-Splines
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// RefDev::ProcessBSpline
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT RefDev::ProcessBSpline( DWORD dwOffW, DWORD dwOffH,
|
|
DWORD dwWidth, DWORD dwHeight,
|
|
DWORD dwStride, DWORD order,
|
|
FLOAT *pPrimSegments )
|
|
{
|
|
if(order == 0)
|
|
{
|
|
order = 2;
|
|
}
|
|
else
|
|
{
|
|
++order;
|
|
}
|
|
|
|
int u_range = dwWidth - (order - 1);
|
|
int v_range = dwHeight - (order - 1);
|
|
|
|
if(u_range <= 0 || v_range <= 0)
|
|
{
|
|
DPFERR("Insufficient control vertices for current order");
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
RDBSpline bsp(dwWidth, dwHeight, order, order);
|
|
|
|
static const unsigned M[4] = {0, 0, 0, 0}, N[4] = {0, 0, 0, 0};
|
|
|
|
unsigned u_segs, v_segs, u_start, v_start;
|
|
|
|
if(pPrimSegments != 0)
|
|
{
|
|
u_segs = unsigned(double(unsigned(pPrimSegments[0]) + unsigned(pPrimSegments[2])) / 2.0 + 0.5);
|
|
v_segs = unsigned(double(unsigned(pPrimSegments[1]) + unsigned(pPrimSegments[3])) / 2.0 + 0.5);
|
|
if(u_segs == 0)
|
|
{
|
|
u_segs = 1;
|
|
}
|
|
if(v_segs == 0)
|
|
{
|
|
v_segs = 1;
|
|
}
|
|
if(unsigned(pPrimSegments[0]) != unsigned(pPrimSegments[2]) || unsigned(pPrimSegments[1]) != unsigned(pPrimSegments[3]))
|
|
{
|
|
// First, gulp, the irregular outside
|
|
// To make life easier, we don't want to deal with the case when u_segs or v_segs is one
|
|
// This ensures that there is at least one inside point
|
|
if(u_segs == 1)
|
|
{
|
|
u_segs = 2;
|
|
}
|
|
if(v_segs == 1)
|
|
{
|
|
v_segs = 2;
|
|
}
|
|
// Start with top edge
|
|
unsigned segs = unsigned(pPrimSegments[0]);
|
|
unsigned k_outer = 0;
|
|
unsigned k_inner = 1;
|
|
unsigned outer_inc = u_segs - 2;
|
|
unsigned inner_inc = segs;
|
|
unsigned outer = 0;
|
|
unsigned inner = 0;
|
|
double u0, v0, u1, v1, u2, v2;
|
|
while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer < segs))
|
|
{
|
|
if(inner < outer)
|
|
{
|
|
_ASSERT(k_inner < u_segs - 1, "Error in logic");
|
|
u0 = double(u_range * k_inner) / double(u_segs) + double(order - 1);
|
|
v0 = double(v_range) / double(v_segs) + double(order - 1);
|
|
u1 = double(u_range * k_outer) / double(segs) + double(order - 1);
|
|
v1 = double(order - 1);
|
|
u2 = double(u_range * (k_inner + 1)) / double(u_segs) + double(order - 1);
|
|
v2 = v0;
|
|
++k_inner;
|
|
inner += inner_inc;
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(k_outer < segs, "Error in logic");
|
|
u0 = double(u_range * k_inner) / double(u_segs) + double(order - 1);
|
|
v0 = double(v_range) / double(v_segs) + double(order - 1);
|
|
u1 = double(u_range * k_outer) / double(segs) + double(order - 1);
|
|
v1 = double(order - 1);
|
|
u2 = double(u_range * (k_outer + 1)) / double(segs) + double(order - 1);
|
|
v2 = v1;
|
|
++k_outer;
|
|
outer += outer_inc;
|
|
}
|
|
HRESULT hr = DrawTessTri(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
|
|
bsp.TexCoordU(u0), bsp.TexCoordV(v0),
|
|
bsp.TexCoordU(u1), bsp.TexCoordV(v1),
|
|
bsp.TexCoordU(u2), bsp.TexCoordV(v2),
|
|
false, false, false);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
// bottom edge
|
|
segs = unsigned(pPrimSegments[2]);
|
|
k_outer = segs;
|
|
k_inner = u_segs - 1;
|
|
inner_inc = segs;
|
|
outer = 0;
|
|
inner = 0;
|
|
while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer > 0))
|
|
{
|
|
if(inner < outer)
|
|
{
|
|
_ASSERT(k_inner > 1, "Error in logic");
|
|
u0 = double(u_range * k_inner) / double(u_segs) + double(order - 1);
|
|
v0 = double(v_range * (v_segs - 1)) / double(v_segs) + double(order - 1);
|
|
u1 = double(u_range * k_outer) / double(segs) + double(order - 1);
|
|
v1 = double(v_range + order - 1);
|
|
u2 = double(u_range * (k_inner - 1)) / double(u_segs) + double(order - 1);
|
|
v2 = v0;
|
|
--k_inner;
|
|
inner += inner_inc;
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(k_outer > 0, "Error in logic");
|
|
u0 = double(u_range * k_inner) / double(u_segs) + double(order - 1);
|
|
v0 = double(v_range * (v_segs - 1)) / double(v_segs) + double(order - 1);
|
|
u1 = double(u_range * k_outer) / double(segs) + double(order - 1);
|
|
v1 = double(v_range + order - 1);
|
|
u2 = double(u_range * (k_outer - 1)) / double(segs) + double(order - 1);
|
|
v2 = v1;
|
|
--k_outer;
|
|
outer += outer_inc;
|
|
}
|
|
HRESULT hr = DrawTessTri(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
|
|
bsp.TexCoordU(u0), bsp.TexCoordV(v0),
|
|
bsp.TexCoordU(u1), bsp.TexCoordV(v1),
|
|
bsp.TexCoordU(u2), bsp.TexCoordV(v2),
|
|
false, false, false);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
// right edge
|
|
segs = unsigned(pPrimSegments[1]);
|
|
k_outer = 0;
|
|
k_inner = 1;
|
|
outer_inc = v_segs - 2;
|
|
inner_inc = segs;
|
|
outer = 0;
|
|
inner = 0;
|
|
while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer < segs))
|
|
{
|
|
if(inner < outer)
|
|
{
|
|
_ASSERT(k_inner < v_segs - 1, "Error in logic");
|
|
u0 = double(u_range * (u_segs - 1)) / double(u_segs) + double(order - 1);
|
|
v0 = double(v_range * k_inner) / double(v_segs) + double(order - 1);
|
|
u1 = double(u_range + order - 1);
|
|
v1 = double(v_range * k_outer) / double(segs) + double(order - 1);
|
|
u2 = u0;
|
|
v2 = double(v_range * (k_inner + 1)) / double(v_segs) + double(order - 1);
|
|
++k_inner;
|
|
inner += inner_inc;
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(k_outer < segs, "Error in logic");
|
|
u0 = double(u_range * (u_segs - 1)) / double(u_segs) + double(order - 1);
|
|
v0 = double(v_range * k_inner) / double(v_segs) + double(order - 1);
|
|
u1 = double(u_range + order - 1);
|
|
v1 = double(v_range * k_outer) / double(segs) + double(order - 1);
|
|
u2 = u1;
|
|
v2 = double(v_range * (k_outer + 1)) / double(segs) + double(order - 1);
|
|
++k_outer;
|
|
outer += outer_inc;
|
|
}
|
|
HRESULT hr = DrawTessTri(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
|
|
bsp.TexCoordU(u0), bsp.TexCoordV(v0),
|
|
bsp.TexCoordU(u1), bsp.TexCoordV(v1),
|
|
bsp.TexCoordU(u2), bsp.TexCoordV(v2),
|
|
false, false, false);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
// left edge
|
|
segs = unsigned(pPrimSegments[3]);
|
|
k_outer = segs;
|
|
k_inner = v_segs - 1;
|
|
inner_inc = segs;
|
|
outer = 0;
|
|
inner = 0;
|
|
while(outer_inc != 0 ? (inner != inner_inc * outer_inc || outer != inner_inc * outer_inc) : (k_outer > 0))
|
|
{
|
|
if(inner < outer)
|
|
{
|
|
_ASSERT(k_inner > 1, "Error in logic");
|
|
u0 = double(u_range) / double(u_segs) + double(order - 1);
|
|
v0 = double(v_range * k_inner) / double(v_segs) + double(order - 1);
|
|
u1 = double(order - 1);
|
|
v1 = double(v_range * k_outer) / double(segs) + double(order - 1);
|
|
u2 = u0;
|
|
v2 = double(v_range * (k_inner - 1)) / double(v_segs) + double(order - 1);
|
|
--k_inner;
|
|
inner += inner_inc;
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(k_outer > 0, "Error in logic");
|
|
u0 = double(u_range) / double(u_segs) + double(order - 1);
|
|
v0 = double(v_range * k_inner) / double(v_segs) + double(order - 1);
|
|
u1 = double(order - 1);
|
|
v1 = double(v_range * k_outer) / double(segs) + double(order - 1);
|
|
u2 = u1;
|
|
v2 = double(v_range * (k_outer - 1)) / double(segs) + double(order - 1);
|
|
--k_outer;
|
|
outer += outer_inc;
|
|
}
|
|
HRESULT hr = DrawTessTri(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1, u2, v2,
|
|
bsp.TexCoordU(u0), bsp.TexCoordV(v0),
|
|
bsp.TexCoordU(u1), bsp.TexCoordV(v1),
|
|
bsp.TexCoordU(u2), bsp.TexCoordV(v2),
|
|
false, false, false);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
// Now do the regular interior
|
|
u_start = 1;
|
|
v_start = 1;
|
|
}
|
|
else
|
|
{
|
|
// It can be done regularly
|
|
u_start = 0;
|
|
v_start = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned segs = unsigned(GetRSf()[D3DRS_PATCHSEGMENTS]);
|
|
if(segs == 0)
|
|
{
|
|
segs = 1;
|
|
}
|
|
u_start = 0;
|
|
v_start = 0;
|
|
u_segs = segs;
|
|
v_segs = segs;
|
|
}
|
|
|
|
for(unsigned i = v_start; i < v_segs - v_start; ++i)
|
|
{
|
|
double v0 = double(v_range * i) / double(v_segs) + double(order - 1);
|
|
double v1 = double(v_range * (i + 1)) / double(v_segs) + double(order - 1);
|
|
for(unsigned j = u_start; j < u_segs - u_start; ++j)
|
|
{
|
|
double u0 = double(u_range * j) / double(u_segs) + double(order - 1);
|
|
double u1 = double(u_range * (j + 1)) / double(u_segs) + double(order - 1);
|
|
HRESULT hr = DrawTessQuad(bsp, dwOffW, dwOffH, dwStride, M, N, u0, v0, u1, v1,
|
|
bsp.TexCoordU(u0), bsp.TexCoordV(v0),
|
|
bsp.TexCoordU(u1), bsp.TexCoordV(v1),
|
|
false);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// RDBSpline::Sample
|
|
//-----------------------------------------------------------------------------
|
|
void RDBSpline::Sample(DWORD dwDataType, double u, double v, const BYTE *pRow, DWORD dwStride, DWORD dwPitch, BYTE *Q) const
|
|
{
|
|
double Acc[4] = {0.0, 0.0, 0.0, 0.0};
|
|
unsigned dwElements = 0;
|
|
switch(dwDataType)
|
|
{
|
|
case D3DVSDT_FLOAT4:
|
|
++dwElements;
|
|
case D3DVSDT_FLOAT3:
|
|
++dwElements;
|
|
case D3DVSDT_FLOAT2:
|
|
++dwElements;
|
|
case D3DVSDT_FLOAT1:
|
|
++dwElements;
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double N = Basis(i, m_dwOrderV, v);
|
|
const BYTE *pCol = pRow;
|
|
for(unsigned j = 0; j < m_dwWidth; ++j)
|
|
{
|
|
double NM = N * Basis(j, m_dwOrderU, u);
|
|
const FLOAT *B = (FLOAT*)pCol;
|
|
for(unsigned e = 0; e < dwElements; ++e)
|
|
{
|
|
Acc[e] += double(B[e]) * NM;
|
|
}
|
|
pCol += dwStride;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
for(unsigned e = 0; e < dwElements; ++e)
|
|
{
|
|
((FLOAT*)Q)[e] = FLOAT(Acc[e]);
|
|
}
|
|
}
|
|
break;
|
|
case D3DVSDT_D3DCOLOR:
|
|
case D3DVSDT_UBYTE4:
|
|
dwElements = 4;
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double N = Basis(i, m_dwOrderV, v);
|
|
const BYTE *pCol = pRow;
|
|
for(unsigned j = 0; j < m_dwWidth; ++j)
|
|
{
|
|
double NM = N * Basis(j, m_dwOrderU, u);
|
|
const BYTE *B = pCol;
|
|
for(unsigned e = 0; e < 4; ++e)
|
|
{
|
|
Acc[e] += double(B[e]) * NM;
|
|
}
|
|
pCol += dwStride;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
for(unsigned e = 0; e < 4; ++e)
|
|
{
|
|
int t = int(Acc[e]);
|
|
Q[e] = BYTE(t < 0 ? 0 : (t > 255 ? 255 : t));
|
|
}
|
|
}
|
|
break;
|
|
case D3DVSDT_SHORT4:
|
|
dwElements += 2;
|
|
case D3DVSDT_SHORT2:
|
|
dwElements += 2;
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double N = Basis(i, m_dwOrderV, v);
|
|
const BYTE *pCol = pRow;
|
|
for(unsigned j = 0; j < m_dwWidth; ++j)
|
|
{
|
|
double NM = N * Basis(j, m_dwOrderU, u);
|
|
const SHORT *B = (SHORT*)pCol;
|
|
for(unsigned e = 0; e < dwElements; ++e)
|
|
{
|
|
Acc[e] += double(B[e]) * NM;
|
|
}
|
|
pCol += dwStride;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
for(unsigned e = 0; e < dwElements; ++e)
|
|
{
|
|
((SHORT*)Q)[e] = SHORT(Acc[e]);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
_ASSERT(FALSE, "Ununderstood vertex element data type");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// RDBSpline::SampleNormal
|
|
//-----------------------------------------------------------------------------
|
|
void RDBSpline::SampleNormal(DWORD dwDataType, double u, double v, const BYTE *pRow, DWORD dwStride, DWORD dwPitch, BYTE *Q) const
|
|
{
|
|
double Acc[2][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
|
|
// Fudge u and v if they are on the boundary. This is because the derivative is discontinuous on the boundary
|
|
// and we really want it to be slightly inside the boundary.
|
|
if(v == double(m_dwHeight))
|
|
{
|
|
v -= v * DBL_EPSILON;
|
|
}
|
|
if(u == double(m_dwWidth))
|
|
{
|
|
u -= u * DBL_EPSILON;
|
|
}
|
|
switch(dwDataType)
|
|
{
|
|
case D3DVSDT_FLOAT4:
|
|
case D3DVSDT_FLOAT3:
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double N = Basis(i, m_dwOrderV, v);
|
|
double NPrime = BasisPrime(i, m_dwOrderV, v);
|
|
const BYTE *pCol = pRow;
|
|
for(unsigned j = 0; j < m_dwWidth; ++j)
|
|
{
|
|
double NMPrime = N * BasisPrime(j, m_dwOrderU, u);
|
|
double NPrimeM = NPrime * Basis(j, m_dwOrderU, u);
|
|
const FLOAT *B = (FLOAT*)pCol;
|
|
for(unsigned e = 0; e < 3; ++e)
|
|
{
|
|
Acc[0][e] += double(B[e]) * NMPrime;
|
|
Acc[1][e] += double(B[e]) * NPrimeM;
|
|
}
|
|
pCol += dwStride;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
|
|
((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
|
|
((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
|
|
}
|
|
break;
|
|
case D3DVSDT_D3DCOLOR:
|
|
case D3DVSDT_UBYTE4:
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double N = Basis(i, m_dwOrderV, v);
|
|
double NPrime = BasisPrime(i, m_dwOrderV, v);
|
|
const BYTE *pCol = pRow;
|
|
for(unsigned j = 0; j < m_dwWidth; ++j)
|
|
{
|
|
double NMPrime = N * BasisPrime(j, m_dwOrderU, u);
|
|
double NPrimeM = NPrime * Basis(j, m_dwOrderU, u);
|
|
const BYTE *B = pCol;
|
|
for(unsigned e = 0; e < 3; ++e)
|
|
{
|
|
Acc[0][e] += double(B[e]) * NMPrime;
|
|
Acc[1][e] += double(B[e]) * NPrimeM;
|
|
}
|
|
pCol += dwStride;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
|
|
((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
|
|
((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
|
|
}
|
|
break;
|
|
case D3DVSDT_SHORT4:
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double N = Basis(i, m_dwOrderV, v);
|
|
double NPrime = BasisPrime(i, m_dwOrderV, v);
|
|
const BYTE *pCol = pRow;
|
|
for(unsigned j = 0; j < m_dwWidth; ++j)
|
|
{
|
|
double NMPrime = N * BasisPrime(j, m_dwOrderU, u);
|
|
double NPrimeM = NPrime * Basis(j, m_dwOrderU, u);
|
|
const SHORT *B = (SHORT*)pCol;
|
|
for(unsigned e = 0; e < 3; ++e)
|
|
{
|
|
Acc[0][e] += double(B[e]) * NMPrime;
|
|
Acc[1][e] += double(B[e]) * NPrimeM;
|
|
}
|
|
pCol += dwStride;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
|
|
((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
|
|
((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
|
|
}
|
|
break;
|
|
case D3DVSDT_SHORT2:
|
|
case D3DVSDT_FLOAT2:
|
|
case D3DVSDT_FLOAT1:
|
|
default:
|
|
_ASSERT(FALSE, "Ununderstood vertex element data type");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// RDBSpline::SampleDegenerateNormal
|
|
//-----------------------------------------------------------------------------
|
|
void RDBSpline::SampleDegenerateNormal(DWORD dwDataType, const BYTE *pRow, DWORD dwStride, DWORD dwPitch, BYTE *Q) const
|
|
{
|
|
double Acc[2][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
|
|
switch(dwDataType)
|
|
{
|
|
case D3DVSDT_FLOAT4:
|
|
case D3DVSDT_FLOAT3:
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double JPrime = BasisPrime(i, m_dwOrderV, 0.0);
|
|
const FLOAT *B1 = (FLOAT*)pRow;
|
|
const FLOAT *B2 = (FLOAT*)(pRow + (m_dwWidth - 1) * dwStride);
|
|
for(unsigned e = 0; e < 3; ++e)
|
|
{
|
|
Acc[0][e] += double(B2[e]) * JPrime;
|
|
Acc[1][e] += double(B1[e]) * JPrime;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
|
|
((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
|
|
((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
|
|
}
|
|
break;
|
|
case D3DVSDT_D3DCOLOR:
|
|
case D3DVSDT_UBYTE4:
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double JPrime = BasisPrime(i, m_dwOrderV, 0.0);
|
|
const BYTE *B1 = pRow;
|
|
const BYTE *B2 = pRow + (m_dwWidth - 1) * dwStride;
|
|
for(unsigned e = 0; e < 3; ++e)
|
|
{
|
|
Acc[0][e] += double(B2[e]) * JPrime;
|
|
Acc[1][e] += double(B1[e]) * JPrime;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
|
|
((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
|
|
((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
|
|
}
|
|
break;
|
|
case D3DVSDT_SHORT4:
|
|
{
|
|
for(unsigned i = 0; i < m_dwHeight; ++i)
|
|
{
|
|
double JPrime = BasisPrime(i, m_dwOrderV, 0.0);
|
|
const SHORT *B1 = (SHORT*)pRow;
|
|
const SHORT *B2 = (SHORT*)(pRow + (m_dwWidth - 1) * dwStride);
|
|
for(unsigned e = 0; e < 3; ++e)
|
|
{
|
|
Acc[0][e] += double(B2[e]) * JPrime;
|
|
Acc[1][e] += double(B1[e]) * JPrime;
|
|
}
|
|
pRow += dwPitch;
|
|
}
|
|
((FLOAT*)Q)[0] = FLOAT(Acc[0][1] * Acc[1][2] - Acc[0][2] * Acc[1][1]);
|
|
((FLOAT*)Q)[1] = FLOAT(Acc[0][2] * Acc[1][0] - Acc[0][0] * Acc[1][2]);
|
|
((FLOAT*)Q)[2] = FLOAT(Acc[0][0] * Acc[1][1] - Acc[0][1] * Acc[1][0]);
|
|
}
|
|
break;
|
|
case D3DVSDT_FLOAT2:
|
|
case D3DVSDT_FLOAT1:
|
|
case D3DVSDT_SHORT2:
|
|
default:
|
|
_ASSERT(FALSE, "Ununderstood vertex element data type");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// RDBSpline::Basis
|
|
//-----------------------------------------------------------------------------
|
|
double RDBSpline::Basis(unsigned i, unsigned k, double s) const
|
|
{
|
|
if(k == 1)
|
|
{
|
|
if(Knot(i) <= s && s < Knot(i + 1))
|
|
{
|
|
return 1.0;
|
|
}
|
|
else
|
|
{
|
|
return 0.0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(k != 0, "Arithmatic error in RDBSpline::Basis");
|
|
return ((s - Knot(i)) * Basis(i, k - 1, s)) / (Knot(i + k - 1) - Knot(i)) +
|
|
((Knot(i + k) - s) * Basis(i + 1, k - 1, s)) / (Knot(i + k) - Knot(i + 1));
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// RDBSpline::BasisPrime
|
|
//-----------------------------------------------------------------------------
|
|
double RDBSpline::BasisPrime(unsigned i, unsigned k, double s) const
|
|
{
|
|
if(k == 1)
|
|
{
|
|
return 0.0;
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(k != 0, "Arithmatic error in RDBSpline::BasisPrime");
|
|
return (Basis(i, k - 1, s) + (s - Knot(i)) * BasisPrime(i, k - 1, s)) / (Knot(i + k - 1) - Knot(i)) +
|
|
((Knot(i + k) - s) * BasisPrime(i + 1, k - 1, s) - Basis(i + 1, k - 1, s)) / (Knot(i + k) - Knot(i + 1));
|
|
}
|
|
}
|