DXUT源码分析 ---- 类CDXUTMesh(2)
函数CreateMaterials()用于创建网格模型中所需的材质和纹理,我们来看看CreateMaterials()的实现:
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()的声明如下:
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_OUTOFMEMORYRemarks
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_OUTOFMEMORYRemarks
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.