函数CreateMaterials()用于创建网格模型中所需的材质和纹理,我们来看看CreateMaterials()的实现:
HRESULT CDXUTMesh::CreateMaterials( LPCWSTR strPath, IDirect3DDevice9 *pd3dDevice,
D3DXMATERIAL* d3dxMtrls, DWORD dwNumMaterials )
{
// Get material info for the mesh, get the array of materials out of the buffer.
m_dwNumMaterials = dwNumMaterials;
if( d3dxMtrls && m_dwNumMaterials > 0 )
{
// Allocate memory for the materials and textures
m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
if( m_pMaterials == NULL )
return E_OUTOFMEMORY;
m_pTextures = new LPDIRECT3DBASETEXTURE9[m_dwNumMaterials];
if( m_pTextures == NULL )
return E_OUTOFMEMORY;
m_strMaterials = new CHAR[m_dwNumMaterials][MAX_PATH];
if( m_strMaterials == NULL )
return E_OUTOFMEMORY;
// Copy each material and create its texture
for( DWORD i=0; i<m_dwNumMaterials; i++ )
{
// Copy the material
m_pMaterials[i] = d3dxMtrls[i].MatD3D;
m_pMaterials[i].Ambient = m_pMaterials[i].Diffuse; // add by me
m_pTextures[i] = NULL;
// Create a texture
if( d3dxMtrls[i].pTextureFilename )
{
StringCchCopyA( m_strMaterials[i], MAX_PATH, d3dxMtrls[i].pTextureFilename );
WCHAR strTexture[MAX_PATH];
WCHAR strTextureTemp[MAX_PATH];
D3DXIMAGE_INFO ImgInfo;
// First attempt to look for texture in the same folder as the input folder.
MultiByteToWideChar( CP_ACP, 0, d3dxMtrls[i].pTextureFilename, -1, strTextureTemp, MAX_PATH );
strTextureTemp[MAX_PATH-1] = 0;
StringCchCopy( strTexture, MAX_PATH, strPath );
StringCchCat( strTexture, MAX_PATH, strTextureTemp );
// Inspect the texture file to determine the texture type.
if( FAILED( D3DXGetImageInfoFromFile( strTexture, &ImgInfo ) ) )
{
// Search the media folder
if( FAILED( DXUTFindDXSDKMediaFileCch( strTexture, MAX_PATH, strTextureTemp ) ) )
continue; // Can't find. Skip.
D3DXGetImageInfoFromFile( strTexture, &ImgInfo );
}
// Call the appropriate loader according to the texture type.
switch( ImgInfo.ResourceType )
{
case D3DRTYPE_TEXTURE:
{
IDirect3DTexture9 *pTex;
if( SUCCEEDED( D3DXCreateTextureFromFileW( pd3dDevice, strTexture, &pTex ) ) )
{
// Obtain the base texture interface
pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
// Release the specialized instance
pTex->Release();
}
break;
}
case D3DRTYPE_CUBETEXTURE:
{
IDirect3DCubeTexture9 *pTex;
if( SUCCEEDED( D3DXCreateCubeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
{
// Obtain the base texture interface
pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
// Release the specialized instance
pTex->Release();
}
break;
}
case D3DRTYPE_VOLUMETEXTURE:
{
IDirect3DVolumeTexture9 *pTex;
if( SUCCEEDED( D3DXCreateVolumeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
{
// Obtain the base texture interface
pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
// Release the specialized instance
pTex->Release();
}
break;
}
}
}
}
}
return S_OK;
}
函数首先根据材质数来创建相应的材质缓存、纹理缓存、纹理文件名缓存:
m_dwNumMaterials = dwNumMaterials;
if( d3dxMtrls && m_dwNumMaterials > 0 )
{
// Allocate memory for the materials and textures
m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
if( m_pMaterials == NULL )
return E_OUTOFMEMORY;
m_pTextures = new LPDIRECT3DBASETEXTURE9[m_dwNumMaterials];
if( m_pTextures == NULL )
return E_OUTOFMEMORY;
m_strMaterials = new CHAR[m_dwNumMaterials][MAX_PATH];
if( m_strMaterials == NULL )
return E_OUTOFMEMORY;
接下来复制材质数据:
// Copy each material and create its texture
for( DWORD i=0; i<m_dwNumMaterials; i++ )
{
// Copy the material
m_pMaterials[i] = d3dxMtrls[i].MatD3D;
m_pMaterials[i].Ambient = m_pMaterials[i].Diffuse; // add by me
m_pTextures[i] = NULL;
如果模型中指定纹理文件名则创建纹理缓存,首先将pTextureFilename复制到m_strMaterials中,接着根据strPath和strTextureTemp生成纹理图的完整路径(可能是绝对路径也可能是相对路径):
// Create a texture
if( d3dxMtrls[i].pTextureFilename )
{
StringCchCopyA( m_strMaterials[i], MAX_PATH, d3dxMtrls[i].pTextureFilename );
WCHAR strTexture[MAX_PATH];
WCHAR strTextureTemp[MAX_PATH];
D3DXIMAGE_INFO ImgInfo;
// First attempt to look for texture in the same folder as the input folder.
MultiByteToWideChar( CP_ACP, 0, d3dxMtrls[i].pTextureFilename, -1, strTextureTemp, MAX_PATH );
strTextureTemp[MAX_PATH-1] = 0;
StringCchCopy( strTexture, MAX_PATH, strPath );
StringCchCat( strTexture, MAX_PATH, strTextureTemp );
StringCchCat()的声明如下:
StringCchCat is a replacement for strcat. The size, in
characters, of the destination buffer is provided to the function to ensure
that StringCchCat does not write past the end of this buffer.
Syntax
HRESULT StringCchCat(
LPTSTR pszDest,
size_t cchDest,
LPCTSTR pszSrc
);
Parameters
- pszDest
- [in, out] Pointer to a buffer containing
the string to which pszSrc is concatenated, and which
contains the entire resultant string. The string at pszSrc is
added to the end of the string at pszDest.
- cchDest
- [in] Size of the destination buffer, in
characters. This value must equal the length of pszSrc
plus the length of pszDest plus 1 to account for both strings
and the terminating null character. The maximum number of characters
allowed is STRSAFE_MAX_CCH.
- pszSrc
- [in] Pointer to a buffer containing the
source string that is concatenated to the end of pszDest.
This source string must be null-terminated.
Return Value
Note that this function returns an HRESULT
as opposed to strcat, which returns a pointer. It is strongly
recommended that you use the SUCCEEDED and FAILED macros to test the return value of
this function.
S_OK |
Source data was present, the strings were fully concatenated
without truncation, and the resultant destination buffer is
null-terminated. |
STRSAFE_E_INVALID_PARAMETER |
The value in cchDest is either 0 or larger than
STRSAFE_MAX_CCH, or the destination buffer is already full. |
STRSAFE_E_INSUFFICIENT_BUFFER |
The concatenation operation failed due to insufficient buffer
space. The destination buffer contains a truncated,
null-terminated version of the intended result. In situations
where truncation is acceptable, this may not necessarily be seen
as a failure condition. |
Remarks
StringCchCat provides additional
processing for proper buffer handling in your code. Poor buffer handling
is implicated in many security issues that involve buffer overruns.
StringCchCat always null-terminates a non-zero-length
destination buffer.
StringCchCat can be used in its generic
form, or specifically as StringCchCatA (for ANSI strings) or
StringCchCatW (for Unicode strings). The form to use is determined
by your data.
String Data Type |
String Literal |
Function |
char |
"string" |
StringCchCatA |
TCHAR |
TEXT("string") |
StringCchCat |
WCHAR |
L"string" |
StringCchCatW |
StringCchCat and its ANSI and Unicode
variants are replacements for these functions:
- strcat
- wcscat
- lstrcat
- strcat
- StrCatBuff
- _tcscat
- _ftcscat
Behavior is undefined if the strings pointed to
by pszSrc and pszDest overlap.
Neither pszSrc nor pszDest should
be NULL. See StringCchCatEx if you require
the handling of null string pointer values.
接下来调用D3DXGetImageInfoFromFile()从文件中获取图像数据,如果获取失败,则在搜索路径中增加一层目录media来搜索:
// Inspect the texture file to determine the texture type.
if( FAILED( D3DXGetImageInfoFromFile( strTexture, &ImgInfo ) ) )
{
// Search the media folder
if( FAILED( DXUTFindDXSDKMediaFileCch( strTexture, MAX_PATH, strTextureTemp ) ) )
continue; // Can't find. Skip.
D3DXGetImageInfoFromFile( strTexture, &ImgInfo );
}
D3DXGetImageInfoFromFile()的声明如下:
Retrieves information about a given image file.
HRESULT D3DXGetImageInfoFromFile(
LPCSTR pSrcFile,
D3DXIMAGE_INFO * pSrcInfo
);
Parameters
- pSrcFile
- [in] File name of image to retrieve information
about. If UNICODE or _UNICODE are defined, this parameter type is LPCWSTR,
otherwise, the type is LPCSTR.
- pSrcInfo
- [in] Pointer to a D3DXIMAGE_INFO structure to be
filled with the description of the data in the source file.
Return Values
If the function succeeds, the return value is D3D_OK.
If the function fails, the return value can be the following: D3DERR_INVALIDCALL
Remarks
This function supports both Unicode and ANSI strings.
D3DXIMAGE_INFO
Returns a description of the original contents of an
image file.
typedef struct D3DXIMAGE_INFO {
UINT Width;
UINT Height;
UINT Depth;
UINT MipLevels;
D3DFORMAT Format;
D3DRESOURCETYPE ResourceType;
D3DXIMAGE_FILEFORMAT ImageFileFormat;
} D3DXIMAGE_INFO, *LPD3DXIMAGE_INFO;
Members
- Width
- Width of original image in pixels.
- Height
- Height of original image in pixels.
- Depth
- Depth of original image in pixels.
- MipLevels
- Number of mip levels in original image.
- Format
- A value from the D3DFORMAT enumerated type that
most closely describes the data in the original image.
- ResourceType
- Represents the type of the texture stored in the
file. It is either D3DRTYPE_TEXTURE, D3DRTYPE_VOLUMETEXTURE, or
D3DRTYPE_CubeTexture.
- ImageFileFormat
- Represents the format of the image file.
D3DXIMAGE_FILEFORMAT
Describes the supported image file formats. See Remarks
for descriptions of these formats.
typedef enum D3DXIMAGE_FILEFORMAT
{
D3DXIFF_BMP = 0,
D3DXIFF_JPG = 1,
D3DXIFF_TGA = 2,
D3DXIFF_PNG = 3,
D3DXIFF_DDS = 4,
D3DXIFF_PPM = 5,
D3DXIFF_DIB = 6,
D3DXIFF_HDR = 7,
D3DXIFF_PFM = 8,
D3DXIFF_FORCE_DWORD = 0x7fffffff,
} D3DXIMAGE_FILEFORMAT, *LPD3DXIMAGE_FILEFORMAT;
Constants
- D3DXIFF_BMP
- Windows bitmap (BMP) file format.
- D3DXIFF_JPG
- Joint Photographics Experts Group (JPEG)
compressed file format.
- D3DXIFF_TGA
- Truevision (Targa, or TGA) image file format.
- D3DXIFF_PNG
- Portable Network Graphics (PNG) file format.
- D3DXIFF_DDS
- DirectDraw surface (DDS) file format.
- D3DXIFF_PPM
- Portable pixmap (PPM) file format.
- D3DXIFF_DIB
- Windows device-independent bitmap (DIB) file
format.
- D3DXIFF_HDR
- High dynamic range (HDR) file format.
- D3DXIFF_PFM
- Portable float map file format.
- D3DXIFF_FORCE_DWORD
- Forces this enumeration to compile to 32 bits in
size. Without this value, some compilers would allow this enumeration to
compile to a size other than 32 bits. This value is not used.
Remarks
Functions that begin with D3DXLoadxxx support all of
the formats listed. Functions that begin with D3DXSavexxx support all but the
Truevision (.tga) and portable pixmap (.ppm) formats.
The following table lists the available input and
output formats.
File
Extension |
Description |
.bmp |
Windows bitmap format.
Contains a header that describes the resolution of the device on which
the rectangle of pixels was created, the dimensions of the rectangle,
the size of the array of bits, a logical palette, and an array of bits
that defines the relationship between pixels in the bitmapped image and
entries in the logical palette. |
.dds |
DirectDraw Surface file
format. Stores textures, volume textures, and cubic environment maps,
with or without mipmap levels, and with or without pixel compression.
See DDS File Reference. |
.dib |
Windows DIB. Contains
an array of bits combined with structures that specify width and height
of the bitmapped image, color format of the device where the image was
created, and resolution of the device used to create that image. |
.hdr |
HDR format. Encodes
each pixel as an RGBE 32-bit color, with 8 bits of mantissa for red,
green, and blue, and a shared 8-bit exponent. Each channel is separately
compressed with run-length encoding (RLE). |
.jpg |
JPEG standard.
Specifies variable compression of 24-bit RGB color and 8-bit gray-scale
Tagged Image File Format (TIFF) image document files. |
.pfm |
Portable float map
format. A raw floating point image format, without any compression. The
file header specifies image width, height, monochrome or color, and
machine word order. Pixel data is stored as 32-bit floating point
values, with 3 values per pixel for color, and one value per pixel for
monochrome. |
.png |
PNG format. A
non-proprietary bitmap format using lossless compression. |
.ppm |
Portable Pixmap format.
A binary or ASCII file format for color images that includes image
height and width and the maximum color component value. |
.tga |
Targa or Truevision
Graphics Adapter format. Supports depths of 8, 15, 16, 24, and 32 bits,
including 8-bit gray scale, and contains optional color palette data,
image (x, y) origin and size data, and pixel data. |
See Types of Bitmaps (GDI+) for more information on
some of these formats.
接下来根据图像的资源类型来创建纹理,如果是纹理资源,则调用D3DXCreateTextureFromFile()来创建纹理,并调用QueryInterface()来请求该类型的接口:
// Call the appropriate loader according to the texture type.
switch( ImgInfo.ResourceType )
{
case D3DRTYPE_TEXTURE:
{
IDirect3DTexture9 *pTex;
if( SUCCEEDED( D3DXCreateTextureFromFileW( pd3dDevice, strTexture, &pTex ) ) )
{
// Obtain the base texture interface
pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
// Release the specialized instance
pTex->Release();
}
break;
}
QueryInterface()的声明如下:
Determines whether the object supports a particular COM
interface. If it does, the system increases the object's reference count, and
the application can use that interface immediately.
HRESULT QueryInterface(
REFIID riid,
LPVOID * ppvObj
);
Parameters
- riid
- Reference identifier of the interface being
requested.
- ppvObj
- Address of a pointer to fill with the interface
pointer if the query succeeds.
Return Values
If the method succeeds, the return value is S_OK.
If the method fails, the return value may be
E_NOINTERFACE. Some components also have their own definitions of these error
values in their header files.
Remarks
If the application does not need to use the interface
retrieved by a call to this method, it must call the IUnknown::Release method
for that interface to free it. The IUnknown::QueryInterface method makes it
possible to extend objects without interfering with functionality.
如果立方体纹理资源则调用D3DXCreateCubeTextureFromFile()来创建立方体纹理缓存,如果是D3DRTYPE_VOLUMETEXTURE类型的资源,则调用D3DXCreateVolumeTextureFromFile()来创建该类型的纹理资源:
case D3DRTYPE_CUBETEXTURE:
{
IDirect3DCubeTexture9 *pTex;
if( SUCCEEDED( D3DXCreateCubeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
{
// Obtain the base texture interface
pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
// Release the specialized instance
pTex->Release();
}
break;
}
case D3DRTYPE_VOLUMETEXTURE:
{
IDirect3DVolumeTexture9 *pTex;
if( SUCCEEDED( D3DXCreateVolumeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
{
// Obtain the base texture interface
pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
// Release the specialized instance
pTex->Release();
}
break;
}
D3DXCreateCubeTextureFromFile()的声明如下:
Creates a cube texture from a file.
HRESULT D3DXCreateCubeTextureFromFile(
LPDIRECT3DDEVICE9 pDevice,
LPCTSTR pSrcFile,
LPDIRECT3DCUBETEXTURE9 * ppCubeTexture
);
Parameters
- pDevice
- [in] Pointer to an IDirect3DDevice9 interface,
representing the device to be associated with the cube texture.
- pSrcFile
- [in] Pointer to a string that specifies the
filename. If the compiler settings require Unicode, the data type LPCTSTR
resolves to LPCWSTR. Otherwise, the string data type resolves to LPCSTR. See
Remarks.
- ppCubeTexture
- [out] Address of a pointer to an
IDirect3DCubeTexture9 interface, representing the created cube texture
object.
Return Values
If the function succeeds, the return value is D3D_OK.
If the function fails, the return value can be one of the following values:
D3DERR_INVALIDCALL.
D3DERR_NOTAVAILABLED3DERR_OUTOFVIDEOMEMORYD3DXERR_INVALIDDATAE_OUTOFMEMORY
Remarks
The compiler setting also determines the function
version. If Unicode is defined, the function call resolves to
D3DXCreateCubeTextureFromFileW. Otherwise, the function call resolves to
D3DXCreateCubeTextureFromFileA because ANSI strings are being used.
The function is equivalent to
D3DXCreateCubeTextureFromFileEx(pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT,
0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL,
ppCubeTexture).
This function supports the following file formats:
.bmp, .dds, .dib, .hdr, .jpg, .pfm, .png, .ppm, and .tga. See
D3DXIMAGE_FILEFORMAT.
Note that a resource created with this function will be
placed in the memory class denoted by D3DPOOL_MANAGED.
Filtering is automatically applied to a texture created
using this method. The filtering is equivalent to D3DX_FILTER_TRIANGLE |
D3DX_FILTER_DITHER in D3DX_FILTER.
D3DXCreateCubeTextureFromFile uses the
DirectDraw surface (DDS) file format. The DirectX Texture Editor (dxtex.exe)
enables you to generate a cube map from other file formats and save it in the
DDS file format.
D3DXCreateVolumeTextureFromFile()的声明如下:
Creates a volume texture from a file.
HRESULT D3DXCreateVolumeTextureFromFile(
LPDIRECT3DDEVICE9 pDevice,
LPCTSTR pSrcFile,
LPDIRECT3DVOLUMETEXTURE9 * ppVolumeTexture
);
Parameters
- pDevice
- [in] Pointer to an IDirect3DDevice9 interface,
representing the device to be associated with the volume texture.
- pSrcFile
- [in] Pointer to a string that specifies the file
name. If the compiler settings require Unicode, the data type LPCTSTR
resolves to LPCWSTR. Otherwise, the string data type resolves to LPCSTR. See
Remarks.
- ppVolumeTexture
- [out] Address of a pointer to an
IDirect3DVolumeTexture9 interface representing the created texture object.
Return Values
If the function succeeds, the return value is D3D_OK.
If the function fails, the return value can be one of the following:
D3DERR_NOTAVAILABLED3DERR_OUTOFVIDEOMEMORYD3DERR_INVALIDCALLD3DXERR_INVALIDDATAE_OUTOFMEMORY
Remarks
The compiler setting also determines the function
version. If Unicode is defined, the function call resolves to
D3DXCreateVolumeTextureFromFileW. Otherwise, the function call resolves to
D3DXCreateVolumeTextureFromFileA because ANSI strings are being used.
The function is equivalent to
D3DXCreateVolumeTextureFromFileEx(pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT,
D3DX_DEFAULT, 0, NULL, NULL, ppVolumeTexture).
This function supports the following file formats:
.bmp, .dds, .dib, .hdr, .jpg, .pfm, .png, .ppm, and .tga. See
D3DXIMAGE_FILEFORMAT.
Mipmapped textures automatically have each level filled
with the loaded texture.
When loading images into mipmapped textures, some
devices are unable to go to a 1x1 image and this function will fail. If this
happens, then the images need to be loaded manually.
Note that a resource created with this function will be
placed in the memory class denoted by D3DPOOL_MANAGED.
Filtering is automatically applied to a texture created
using this method. The filtering is equivalent to D3DX_FILTER_TRIANGLE |
D3DX_FILTER_DITHER in D3DX_FILTER.