summaryrefslogtreecommitdiff
path: root/vtf/cvtf.h
blob: 3965de94a1da38d7434f527a04d0679b3a2d000e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Local header for CVTFTexture class declaration - allows platform-specific
//			implementation to be placed in separate cpp files.
//
// $NoKeywords: $
//===========================================================================//

#ifndef CVTF_H
#define CVTF_H

#ifdef _WIN32
#pragma once
#endif

#include "s3tc_decode.h"
#include "vtf/vtf.h"
#include "byteswap.h"
#include "filesystem.h"

class CEdgePos
{
public:
	CEdgePos() {}
	CEdgePos( int ix, int iy )
	{
		x = ix;
		y = iy;
	}

	void operator +=( const CEdgePos &other ) 
	{ 
		x += other.x;
		y += other.y;
	}

	void operator /=( int val )
	{ 
		x /= val;
		y /= val;
	}

	CEdgePos operator >>( int shift )
	{ 
		return CEdgePos( x >> shift, y >> shift );
	}

	CEdgePos operator *( int shift )
	{ 
		return CEdgePos( x * shift, y * shift );
	}

	CEdgePos operator -( const CEdgePos &other ) 
	{ 
		return CEdgePos( x - other.x, y - other.y );
	}

	CEdgePos operator +( const CEdgePos &other ) 
	{ 
		return CEdgePos( x + other.x, y + other.y );
	}

	bool operator!=( const CEdgePos &other )
	{
		return !( *this == other );
	}

	bool operator==( const CEdgePos &other )
	{
		return x==other.x && y==other.y;
	}

	int x, y;
};


class CEdgeIncrements
{
public:
	CEdgePos iFace1Start, iFace1End;
	CEdgePos iFace1Inc, iFace2Inc;
	CEdgePos iFace2Start, iFace2End;
};


class CEdgeMatch
{
public:
	int m_iFaces[2];	// Which faces are touching.
	int m_iEdges[2];	// Which edge on each face is touching.
	int m_iCubeVerts[2];// Which of the cube's verts comprise this edge?
	bool m_bFlipFace2Edge;
};


class CCornerMatch
{
public:
	// The info for the 3 edges that match at this corner.
	int m_iFaces[3];
	int m_iFaceEdges[3];
};


class CEdgeFaceIndex
{
public:
	int m_iEdge;
	int m_iFace;
};


#define NUM_EDGE_MATCHES	12
#define NUM_CORNER_MATCHES	8


//-----------------------------------------------------------------------------
// Implementation of the VTF Texture
//-----------------------------------------------------------------------------
class CVTFTexture : public IVTFTexture
{
public:
	CVTFTexture();
	virtual ~CVTFTexture();

	virtual bool Init( int nWidth, int nHeight, int nDepth, ImageFormat fmt, int iFlags, int iFrameCount, int nForceMipCount );

	// Methods to initialize the low-res image
	virtual void InitLowResImage( int nWidth, int nHeight, ImageFormat fmt );

	virtual void *SetResourceData( uint32 eType, void const *pData, size_t nDataSize );
	virtual void *GetResourceData( uint32 eType, size_t *pDataSize ) const;

	// Locates the resource entry info if it's present, easier than crawling array types
	virtual bool HasResourceEntry( uint32 eType ) const;

	// Retrieve available resource types of this IVTFTextures
	//		arrTypesBuffer			buffer to be filled with resource types available.
	//		numTypesBufferElems		how many resource types the buffer can accomodate.
	// Returns:
	//		number of resource types available (can be greater than "numTypesBufferElems"
	//		in which case only first "numTypesBufferElems" are copied to "arrTypesBuffer")
	virtual unsigned int GetResourceTypes( uint32 *arrTypesBuffer, int numTypesBufferElems ) const;

	// Methods to set other texture fields
	virtual void SetBumpScale( float flScale );
	virtual void SetReflectivity( const Vector &vecReflectivity );

	// These are methods to help with optimization of file access
	virtual void LowResFileInfo( int *pStartLocation, int *pSizeInBytes ) const;
	virtual void ImageFileInfo( int nFrame, int nFace, int nMip, int *pStartLocation, int *pSizeInBytes) const;
	virtual int FileSize( int nMipSkipCount = 0 ) const;

	// When unserializing, we can skip a certain number of mip levels,
	// and we also can just load everything but the image data
	virtual bool Unserialize( CUtlBuffer &buf, bool bBufferHeaderOnly = false, int nSkipMipLevels = 0 );
	virtual bool UnserializeEx( CUtlBuffer &buf, bool bHeaderOnly = false, int nForceFlags = 0, int nSkipMipLevels = 0 );
	virtual bool Serialize( CUtlBuffer &buf );

	virtual void GetMipmapRange( int* pOutFinest, int* pOutCoarsest );

	// Attributes...
	virtual int Width() const;
	virtual int Height() const;
	virtual int Depth() const;
	virtual int MipCount() const;

	virtual int RowSizeInBytes( int nMipLevel ) const;
	virtual int FaceSizeInBytes( int nMipLevel ) const;

	virtual ImageFormat Format() const;
	virtual int FaceCount() const;
	virtual int FrameCount() const;
	virtual int Flags() const;

	virtual float BumpScale() const;
	virtual const Vector &Reflectivity() const;

	virtual bool IsCubeMap() const;
	virtual bool IsNormalMap() const;
	virtual bool IsVolumeTexture() const;

	virtual int LowResWidth() const;
	virtual int LowResHeight() const;
	virtual ImageFormat LowResFormat() const;

	// Computes the size (in bytes) of a single mipmap of a single face of a single frame 
	virtual int ComputeMipSize( int iMipLevel ) const;

	// Computes the size (in bytes) of a single face of a single frame
	// All mip levels starting at the specified mip level are included
	virtual int ComputeFaceSize( int iStartingMipLevel = 0 ) const;

	// Computes the total size of all faces, all frames
	virtual int ComputeTotalSize( ) const;

	// Computes the dimensions of a particular mip level
	virtual void ComputeMipLevelDimensions( int iMipLevel, int *pWidth, int *pHeight, int *pMipDepth ) const;

	// Computes the size of a subrect (specified at the top mip level) at a particular lower mip level
	virtual void ComputeMipLevelSubRect( Rect_t* pSrcRect, int nMipLevel, Rect_t *pSubRect ) const;

	// Returns the base address of the image data
	virtual unsigned char *ImageData();

	// Returns a pointer to the data associated with a particular frame, face, and mip level
	virtual unsigned char *ImageData( int iFrame, int iFace, int iMipLevel );

	// Returns a pointer to the data associated with a particular frame, face, mip level, and offset
	virtual unsigned char *ImageData( int iFrame, int iFace, int iMipLevel, int x, int y, int z );

	// Returns the base address of the low-res image data
	virtual unsigned char *LowResImageData();

	// Converts the texture's image format. Use IMAGE_FORMAT_DEFAULT
	virtual void ConvertImageFormat( ImageFormat fmt, bool bNormalToDUDV );

	// Generate spheremap based on the current cube faces (only works for cubemaps)
	// The look dir indicates the direction of the center of the sphere
	virtual void GenerateSpheremap( LookDir_t lookDir );

	virtual void GenerateHemisphereMap( unsigned char *pSphereMapBitsRGBA, int targetWidth, 
		int targetHeight, LookDir_t lookDir, int iFrame );

	// Fixes the cubemap faces orientation from our standard to the
	// standard the material system needs.
	virtual void FixCubemapFaceOrientation( );

	// Normalize the top mip level if necessary
	virtual void NormalizeTopMipLevel();
	
	// Generates mipmaps from the base mip levels
	virtual void GenerateMipmaps();

	// Put 1/miplevel (1..n) into alpha.
	virtual void PutOneOverMipLevelInAlpha();

	// Computes the reflectivity
	virtual void ComputeReflectivity( );

	// Computes the alpha flags
	virtual void ComputeAlphaFlags();

	// Gets the texture all internally consistent assuming you've loaded
	// mip 0 of all faces of all frames
	virtual void PostProcess(bool bGenerateSpheremap, LookDir_t lookDir = LOOK_DOWN_Z, bool bAllowFixCubemapOrientation = true);
	virtual void SetPostProcessingSettings( VtfProcessingOptions const *pOptions );

	// Generate the low-res image bits
	virtual bool ConstructLowResImage();

	virtual void MatchCubeMapBorders( int iStage, ImageFormat finalFormat, bool bSkybox );

	// Sets threshhold values for alphatest mipmapping
	virtual void SetAlphaTestThreshholds( float flBase, float flHighFreq );

#if defined( _X360 )
	virtual int UpdateOrCreate( const char *pFilename, const char *pPathID = NULL, bool bForce = false );
	virtual int FileSize( bool bPreloadOnly, int nMipSkipCount ) const;
	virtual bool UnserializeFromBuffer( CUtlBuffer &buf, bool bBufferIsVolatile, bool bHeaderOnly, bool bPreloadOnly, int nMipSkipCount );
	virtual bool IsPreTiled() const;
	virtual int MappingWidth() const;
	virtual int MappingHeight() const;
	virtual int MappingDepth() const;
	virtual int MipSkipCount() const;
	virtual unsigned char *LowResImageSample();
	virtual void ReleaseImageMemory();
#endif

private:
	// Unserialization
	bool ReadHeader( CUtlBuffer &buf, VTFFileHeader_t &header );

	void BlendCubeMapEdgePalettes(
		int iFrame,
		int iMipLevel,
		const CEdgeMatch *pMatch );

	void BlendCubeMapCornerPalettes(
		int iFrame,
		int iMipLevel,
		const CCornerMatch *pMatch );

	void MatchCubeMapS3TCPalettes(
		CEdgeMatch edgeMatches[NUM_EDGE_MATCHES],
		CCornerMatch cornerMatches[NUM_CORNER_MATCHES]
		);
	
	void SetupFaceVert( int iMipLevel, int iVert, CEdgePos &out );
	void SetupEdgeIncrement( CEdgePos &start, CEdgePos &end, CEdgePos &inc );

	void SetupTextureEdgeIncrements( 
		int iMipLevel,
		int iFace1Edge,
		int iFace2Edge,
		bool bFlipFace2Edge,
		CEdgeIncrements *incs );
	
	void BlendCubeMapFaceEdges(
		int iFrame,
		int iMipLevel,
		const CEdgeMatch *pMatch );

	void BlendCubeMapFaceCorners(
		int iFrame,
		int iMipLevel,
		const CCornerMatch *pMatch );

	void BuildCubeMapMatchLists( CEdgeMatch edgeMatches[NUM_EDGE_MATCHES], CCornerMatch cornerMatches[NUM_CORNER_MATCHES], bool bSkybox );

	// Allocate image data blocks with an eye toward re-using memory
	bool AllocateImageData( int nMemorySize );
	bool AllocateLowResImageData( int nMemorySize );

	// Compute the mip count based on the size + flags
	int ComputeMipCount( ) const;

	// Unserialization of low-res data
	bool LoadLowResData( CUtlBuffer &buf );

	// Unserialization of new resource data
	bool LoadNewResources( CUtlBuffer &buf );

	// Unserialization of image data
	bool LoadImageData( CUtlBuffer &buf, const VTFFileHeader_t &header, int nSkipMipLevels );

	// Shutdown
	void Shutdown();
	void ReleaseResources();

	// Makes a single frame of spheremap
	void ComputeSpheremapFrame( unsigned char **ppCubeFaces, unsigned char *pSpheremap, LookDir_t lookDir );

	// Makes a single frame of spheremap
	void ComputeHemispheremapFrame( unsigned char **ppCubeFaces, unsigned char *pSpheremap, LookDir_t lookDir );

	// Serialization of image data
	bool WriteImageData( CUtlBuffer &buf );

	// Computes the size (in bytes) of a single mipmap of a single face of a single frame 
	int ComputeMipSize( int iMipLevel, ImageFormat fmt ) const;

	// Computes the size (in bytes) of a single face of a single frame
	// All mip levels starting at the specified mip level are included
	int ComputeFaceSize( int iStartingMipLevel, ImageFormat fmt ) const;

	// Computes the total size of all faces, all frames
	int ComputeTotalSize( ImageFormat fmt ) const;

	// Computes the location of a particular face, frame, and mip level
	int GetImageOffset( int iFrame, int iFace, int iMipLevel, ImageFormat fmt ) const;

	// Determines if the vtf or vtfx file needs to be swapped to the current platform
	bool SetupByteSwap( CUtlBuffer &buf );

	// Locates the resource entry info if it's present
	ResourceEntryInfo *FindResourceEntryInfo( unsigned int eType );
	ResourceEntryInfo const *FindResourceEntryInfo( unsigned int eType ) const;
	
	// Inserts the resource entry info if it's not present
	ResourceEntryInfo *FindOrCreateResourceEntryInfo( unsigned int eType );

	// Removes the resource entry info if it's present
	bool RemoveResourceEntryInfo( unsigned int eType );

#if defined( _X360 )
	bool ReadHeader( CUtlBuffer &buf, VTFFileHeaderX360_t &header );
	bool LoadImageData( CUtlBuffer &buf, bool bBufferIsVolatile, int nMipSkipCount );
#endif

private:
	// This is to make sure old-format .vtf files are read properly
	int				m_nVersion[2];

	int				m_nWidth;
	int				m_nHeight;
	int 			m_nDepth;
	ImageFormat		m_Format;

	int				m_nMipCount;
	int				m_nFaceCount;
	int				m_nFrameCount;

	int				m_nImageAllocSize;
	int				m_nFlags;
	unsigned char	*m_pImageData;

	Vector			m_vecReflectivity;
	float			m_flBumpScale;
	
	// FIXME: Do I need this?
	int				m_iStartFrame;

	// Low res data
	int				m_nLowResImageAllocSize;
	ImageFormat		m_LowResImageFormat;
	int				m_nLowResImageWidth;
	int				m_nLowResImageHeight;
	unsigned char	*m_pLowResImageData;

	// Used while fixing mipmap edges.
	CUtlVector<S3RGBA> m_OriginalData;

	// Alpha threshholds
	float			m_flAlphaThreshhold;
	float			m_flAlphaHiFreqThreshhold;

	CByteswap		m_Swap;

	int				m_nFinestMipmapLevel;
	int				m_nCoarsestMipmapLevel;

#if defined( _X360 )
	int				m_iPreloadDataSize;
	int				m_iCompressedSize;
	// resolves actual dimensions to/from mapping dimensions due to pre-picmipping
	int				m_nMipSkipCount;
	unsigned char	m_LowResImageSample[4];
#endif

	CUtlVector< ResourceEntryInfo > m_arrResourcesInfo;

	struct ResourceMemorySection
	{
		ResourceMemorySection() { memset( this, 0, sizeof( *this ) ); }

		int				m_nDataAllocSize;
		int				m_nDataLength;
		unsigned char	*m_pData;

		bool AllocateData( int nMemorySize );
		bool LoadData( CUtlBuffer &buf, CByteswap &byteSwap );
		bool WriteData( CUtlBuffer &buf ) const;
	};
	CUtlVector< ResourceMemorySection > m_arrResourcesData;
	CUtlVector< ResourceMemorySection > m_arrResourcesData_ForReuse;	// Maintained to keep allocated memory blocks when unserializing from files

	VtfProcessingOptions m_Options;
};

#endif	// CVTF_H