windows-nt/Source/XPSP1/NT/public/sdk/inc/dxhelp3.cpp

339 lines
10 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// DXHELP3.cpp : Contains routines shared by multiple 3D effects
#include "dxhelp3.h"
#include <malloc.h>
#include <math.h>
#include <stdio.h>
void Rotate::Set(D3DVECTOR d3dvctrNormal, double dAngle)
{
#ifdef _DEBUG
float NormalSum = d3dvctrNormal.x * d3dvctrNormal.x +
d3dvctrNormal.y * d3dvctrNormal.y +
d3dvctrNormal.z * d3dvctrNormal.z;
_ASSERT(NormalSum == 0.0f || (0.99f < NormalSum && NormalSum < 1.01f));
#endif
// The following transformation matrix routines are from
// Graphics Gems (the first one) page 466 (Converting
// between Matrix and Axis-Amount Representations)
float s = (float)sin(dAngle), c = (float)cos(dAngle);
float t = 1.0f - c;
m_d3dvctrXComponent.x = t * d3dvctrNormal.x * d3dvctrNormal.x + c;
m_d3dvctrXComponent.y = t * d3dvctrNormal.x * d3dvctrNormal.y - s * d3dvctrNormal.z;
m_d3dvctrXComponent.z = t * d3dvctrNormal.x * d3dvctrNormal.z + s * d3dvctrNormal.y;
m_d3dvctrYComponent.x = t * d3dvctrNormal.x * d3dvctrNormal.y + s * d3dvctrNormal.z;
m_d3dvctrYComponent.y = t * d3dvctrNormal.y * d3dvctrNormal.y + c;
m_d3dvctrYComponent.z = t * d3dvctrNormal.y * d3dvctrNormal.z - s * d3dvctrNormal.x;
m_d3dvctrZComponent.x = t * d3dvctrNormal.x * d3dvctrNormal.z - s * d3dvctrNormal.y;
m_d3dvctrZComponent.y = t * d3dvctrNormal.y * d3dvctrNormal.z + s * d3dvctrNormal.x;
m_d3dvctrZComponent.z = t * d3dvctrNormal.z * d3dvctrNormal.z + c;
}
static HRESULT DecoupleOneMeshBuilder(void *lpThis /* Ignored */,
IDirect3DRMMeshBuilder3 *lpMeshBuilderOut,
IDirect3DRMMeshBuilder3 *lpMeshBuilderIn)
{
HRESULT hr = lpMeshBuilderOut->SetAppData(lpMeshBuilderIn->GetAppData());
if(FAILED(hr))
{
return hr;
}
const int ciOutputFaceCount = lpMeshBuilderOut->GetFaceCount();
const int ciMaxFaceCount = lpMeshBuilderIn->GetFaceCount();
if(!ciMaxFaceCount)
{
return hr;
}
CComPtr<IDirect3DRMFaceArray> cpD3DRMFaceArray;
hr = lpMeshBuilderIn->GetFaces(&cpD3DRMFaceArray);
if(hr != D3DRM_OK)
{
return hr;
}
D3DVECTOR *lpvctrPosition = NULL;
D3DVECTOR *lpvctrFaceNormals = NULL;
DWORD dwMaxVertexCount = 0;
// By reserving space we speed things up by a factor of 20 or 30 X!
DWORD dwTotalVertexCount = lpMeshBuilderIn->GetVertexCount();
_ASSERT(dwTotalVertexCount >= 3);
if (dwTotalVertexCount/ciMaxFaceCount < 3)
{
dwTotalVertexCount = ciMaxFaceCount * 3; // There will be at least 3 vertices per face.
}
hr = lpMeshBuilderOut->ReserveSpace(dwTotalVertexCount, dwTotalVertexCount, ciMaxFaceCount);
if(hr != D3DRM_OK)
{
return hr;
}
// Need to have seperate vertices for each face in the output mesh.
int iFaceIndex = 0;
do
{
CComPtr<IDirect3DRMFace> cpd3dInFaceTemp;
CComPtr<IDirect3DRMFace2> cpd3dOutFace;
if(FAILED(hr = cpD3DRMFaceArray->GetElement((DWORD)iFaceIndex, &cpd3dInFaceTemp)))
{
break;
}
_ASSERT(cpd3dInFaceTemp);
CComPtr<IDirect3DRMFace2> cpd3dInFace;
if(FAILED(hr = cpd3dInFaceTemp->QueryInterface(
IID_IDirect3DRMFace2, (void **)&cpd3dInFace)))
{
break;
}
DWORD dwVertexCount;
cpd3dInFace->GetVertices(&dwVertexCount, NULL, NULL);
_ASSERT(dwVertexCount >= 3);
if(dwVertexCount > dwMaxVertexCount)
{
dwMaxVertexCount = dwVertexCount;
D3DVECTOR *lpTemp = lpvctrPosition;
D3DVECTOR *lpNormalTemp = lpvctrFaceNormals;
lpvctrPosition = (D3DVECTOR *)realloc(lpvctrPosition, dwMaxVertexCount * sizeof (*lpvctrPosition));
lpvctrFaceNormals = (D3DVECTOR *)realloc(lpvctrFaceNormals, dwMaxVertexCount * sizeof (*lpvctrFaceNormals));
if(!lpvctrPosition || !lpvctrFaceNormals)
{
free(lpTemp);
free(lpNormalTemp);
hr = E_OUTOFMEMORY;
break;
}
// We may have a problem in the amount of space reserved in the output meshbuilder.
if((ciMaxFaceCount - iFaceIndex) * dwMaxVertexCount > dwTotalVertexCount)
{
dwTotalVertexCount = (ciMaxFaceCount - iFaceIndex) * dwMaxVertexCount;
hr = lpMeshBuilderOut->ReserveSpace(dwTotalVertexCount, dwTotalVertexCount, ciMaxFaceCount - iFaceIndex);
if(hr != D3DRM_OK)
{
break;
}
}
}
if(FAILED(hr = cpd3dInFace->GetVertices(&dwVertexCount, lpvctrPosition, lpvctrFaceNormals)) ||
FAILED(hr = lpMeshBuilderOut->CreateFace(&cpd3dOutFace)) ||
FAILED(hr = cpd3dOutFace->SetAppData(cpd3dInFace->GetAppData())))
{
break;
}
CComPtr<IDirect3DRMMaterial2> cpMaterial;
CComPtr<IDirect3DRMTexture3> cpTexture;
BOOL bU, bV;
if(hr != D3DRM_OK ||
(hr = cpd3dInFace->GetMaterial(&cpMaterial)) != D3DRM_OK ||
(hr = cpd3dOutFace->SetMaterial(cpMaterial)) != D3DRM_OK ||
(hr = cpd3dOutFace->SetColor(cpd3dInFace->GetColor())) != D3DRM_OK ||
(hr = cpd3dInFace->GetTexture(&cpTexture)) != D3DRM_OK ||
(hr = cpd3dOutFace->SetTexture(cpTexture)) != D3DRM_OK ||
(hr = cpd3dInFace->GetTextureTopology(&bU, &bV)) != D3DRM_OK ||
(hr = cpd3dOutFace->SetTextureTopology(bU, bV)) != D3DRM_OK)
{
break;
}
DWORD dwInFaceVertex = 0;
do
{
int iVIndex = lpMeshBuilderOut->AddVertex(lpvctrPosition[dwInFaceVertex].x,
lpvctrPosition[dwInFaceVertex].y,
lpvctrPosition[dwInFaceVertex].z);
int iNIndex = lpMeshBuilderOut->AddNormal(lpvctrFaceNormals[dwInFaceVertex].x,
lpvctrFaceNormals[dwInFaceVertex].y,
lpvctrFaceNormals[dwInFaceVertex].z);
D3DVALUE U, V;
if(FAILED(hr = cpd3dOutFace->AddVertexAndNormalIndexed(iVIndex, iNIndex)) ||
FAILED(hr = cpd3dInFace->GetTextureCoordinates(dwInFaceVertex, &U, &V)) ||
FAILED(hr = cpd3dOutFace->SetTextureCoordinates(dwInFaceVertex, U, V)))
{
break;
}
} while (++dwInFaceVertex < dwVertexCount);
dwTotalVertexCount -= dwVertexCount;
} while (hr == D3DRM_OK && ++iFaceIndex < ciMaxFaceCount);
free(lpvctrPosition);
free(lpvctrFaceNormals);
return hr;
}
HRESULT TraverseSubMeshes( HRESULT (*lpCallBack)(void *lpThis,
IDirect3DRMMeshBuilder3* lpOut,
IDirect3DRMMeshBuilder3* lpIn),
void *lpThis,
IDirect3DRMMeshBuilder3* lpMeshBuilderOut,
IDirect3DRMMeshBuilder3* lpMeshBuilderIn)
{
HRESULT hr;
_ASSERT(lpCallBack);
if(FAILED(hr = (*lpCallBack)(lpThis, lpMeshBuilderOut, lpMeshBuilderIn)))
return hr;
DWORD dwInSubMeshCount;
hr = lpMeshBuilderIn->GetSubMeshes(&dwInSubMeshCount, NULL);
if(FAILED(hr) || dwInSubMeshCount == 0)
return hr;
DWORD dwOutSubMeshCount;
if(FAILED(hr = lpMeshBuilderOut->GetSubMeshes(&dwOutSubMeshCount, NULL)))
{
return hr;
}
const BOOL bCreateOutMeshes = (dwOutSubMeshCount == 0);
_ASSERT(bCreateOutMeshes || dwInSubMeshCount == dwOutSubMeshCount);
LPUNKNOWN *lplpunkInSubMeshes =
(LPUNKNOWN *)malloc(dwInSubMeshCount * sizeof(*lplpunkInSubMeshes));
LPUNKNOWN *lplpunkOutSubMeshes = (bCreateOutMeshes? NULL:
(LPUNKNOWN *)malloc(dwOutSubMeshCount * sizeof(*lplpunkOutSubMeshes)));
if(!lplpunkInSubMeshes || !bCreateOutMeshes && !lplpunkOutSubMeshes)
{
return E_OUTOFMEMORY;
}
if(FAILED(hr = lpMeshBuilderIn->GetSubMeshes(&dwInSubMeshCount, lplpunkInSubMeshes)) ||
!bCreateOutMeshes &&
FAILED(hr = lpMeshBuilderOut->GetSubMeshes(&dwOutSubMeshCount, lplpunkOutSubMeshes)))
{
return hr;
}
CComPtr<IDirect3DRMMeshBuilder3> cpInSubMesh, cpOutSubMesh;
DWORD dwSubMesh;
for(dwSubMesh = 0; SUCCEEDED(hr) && dwSubMesh < dwInSubMeshCount; dwSubMesh++)
{
cpInSubMesh = NULL;
cpOutSubMesh = NULL;
// Get the current input submesh.
hr = lplpunkInSubMeshes[dwSubMesh]->QueryInterface(IID_IDirect3DRMMeshBuilder3,
(void **)&cpInSubMesh);
if(FAILED(hr))
break;
if(bCreateOutMeshes)
{
// Create a new submesh in the output mesh to match the input submesh.
LPUNKNOWN lpunkSubmesh;
if(FAILED(hr = lpMeshBuilderOut->CreateSubMesh(&lpunkSubmesh)))
break;
hr = lpunkSubmesh->QueryInterface(IID_IDirect3DRMMeshBuilder3,
(void **)&cpOutSubMesh);
lpunkSubmesh->Release();
}
else
{
// Get the current output submesh.
hr = lplpunkOutSubMeshes[dwSubMesh]->QueryInterface(IID_IDirect3DRMMeshBuilder3,
(void **)&cpOutSubMesh);
}
if(FAILED(hr))
break;
// Do all the children for these two MeshBuilders.
hr = TraverseSubMeshes(lpCallBack, lpThis, cpOutSubMesh, cpInSubMesh);
}
for(dwSubMesh = 0; dwSubMesh < dwInSubMeshCount; dwSubMesh++)
{
lplpunkInSubMeshes[dwSubMesh]->Release();
if(lplpunkOutSubMeshes)
{
lplpunkOutSubMeshes[dwSubMesh]->Release();
}
}
free(lplpunkInSubMeshes);
free(lplpunkOutSubMeshes);
return hr;
}
HRESULT DecoupleVertices(IDirect3DRMMeshBuilder3* lpMeshBuilderOut,
IDirect3DRMMeshBuilder3* lpMeshBuilderIn)
{
DWORD dwSubMeshCount;
HRESULT hr = lpMeshBuilderOut->GetSubMeshes(&dwSubMeshCount, NULL);
if(FAILED(hr))
return hr;
if(lpMeshBuilderOut->GetFaceCount() || dwSubMeshCount)
{
if(FAILED(hr = lpMeshBuilderOut->Empty(0)))
return hr;
}
hr = TraverseSubMeshes(DecoupleOneMeshBuilder, NULL,
lpMeshBuilderOut, lpMeshBuilderIn);
return hr;
}
float GetDlgItemFloat(HWND hDlg, int id)
{
TCHAR *pEnd;
TCHAR szItemText[20];
GetDlgItemText(hDlg, id, szItemText, 20);
return (float)strtod(szItemText, &pEnd);
}
BOOL SetDlgItemFloat( HWND hDlg, int id, float f )
{
TCHAR szItem[20];
_stprintf( szItem, _T("%.2f"), f );
return SetDlgItemText( hDlg, id, szItem );
}
double GetDlgItemDouble(HWND hDlg, int id)
{
TCHAR *pEnd;
TCHAR szItemText[20];
GetDlgItemText(hDlg, id, szItemText, 20);
return strtod(szItemText, &pEnd);
}
BOOL SetDlgItemDouble( HWND hDlg, int id, double d )
{
TCHAR szItem[20];
_stprintf( szItem, _T("%.2d"), d );
return SetDlgItemText( hDlg, id, szItem );
}