1 class CBIKMaterial
2 {
3 public:
4 CBIKMaterial();
5 ~CBIKMaterial();
6
7 bool Init(const char *pFileName);
8 void Shutdown(void);
9 bool Update(void);
10 int GetTexture(void);
11 void GetFrameSize(int *pWidth, int *pHeight);
12 int GetFrameRate(void);
13 int GetFrameCount(void);
14 void SetFrame(float flFrame);
15 void SetLoop(bool state);
16
17 private:
18 void CreateProceduralTexture(void);
19 void DestroyProceduralTexture(void);
20
21 int m_Texture;
22
23 HBINK m_pHBINK;
24
25 U8 *m_pBuffer;
26 U32 m_nBufferSize;
27
28 int m_nBIKWidth;
29 int m_nBIKHeight;
30
31 int m_nFrameRate;
32 int m_nFrameCount;
33
34 bool m_bLoop;
35
36 HBINKTRACK m_hTrack;
37
38 U8 *m_pSampleData;
39 U32 m_nSampleSize;
40
41 public:
42 float *m_pWaveData;
43 U32 m_nWaveSize;
44 };
45
46 CBIKMaterial::CBIKMaterial()
47 {
48 m_pHBINK = NULL;
49 }
50
51 CBIKMaterial::~CBIKMaterial()
52 {
53 }
54
55 bool CBIKMaterial::Init(const char *pFileName)
56 {
57 m_pHBINK = BinkOpen(pFileName, BINKSNDTRACK);
58
59 if (!m_pHBINK)
60 {
61 m_nBIKWidth = 64;
62 m_nBIKHeight = 64;
63 m_nFrameRate = 1;
64 m_nFrameCount = 1;
65
66 return false;
67 }
68
69 m_nBIKWidth = m_pHBINK->Width;
70 m_nBIKHeight = m_pHBINK->Height;
71
72 m_nFrameRate = (int)((float)m_pHBINK->FrameRate / (float)m_pHBINK->FrameRateDiv);
73 m_nFrameCount = m_pHBINK->Frames;
74
75 m_nBufferSize = m_nBIKWidth * m_nBIKHeight * 3; // RGB(A)
76
77 m_pBuffer = new U8[m_nBufferSize];
78 memset(m_pBuffer, 0, m_nBufferSize);
79
80 CreateProceduralTexture();
81
82 if (m_pHBINK->NumTracks)
83 {
84 m_hTrack = BinkOpenTrack(m_pHBINK, 0);
85
86 BINKTRACK *track = (BINKTRACK *)m_hTrack;
87
88 m_nSampleSize = track->MaxSize;
89 m_pSampleData = new U8[m_nSampleSize];
90
91 m_nWaveSize = 2048;
92 m_pWaveData = new float[m_nWaveSize];
93 }
94
95 for (int i = 0; i < m_pHBINK->NumTracks; ++i)
96 {
97 BinkSetVolume(m_pHBINK, BinkGetTrackID(m_pHBINK, i), 0xFFFF);
98 }
99
100 return true;
101 }
102
103 void CBIKMaterial::Shutdown(void)
104 {
105 DestroyProceduralTexture();
106
107 if (m_pHBINK)
108 {
109 BinkClose(m_pHBINK);
110 m_pHBINK = NULL;
111 }
112
113 if (m_pBuffer)
114 {
115 delete[] m_pBuffer;
116 m_pBuffer = NULL;
117 }
118 }
119
120 bool CBIKMaterial::Update(void)
121 {
122 BinkDoFrame(m_pHBINK);
123
124 if (BinkWait(m_pHBINK))
125 return true;
126
127 while (BinkShouldSkip(m_pHBINK))
128 {
129 BinkNextFrame(m_pHBINK);
130 BinkDoFrame(m_pHBINK);
131 }
132
133 if (m_pHBINK->FrameNum == m_pHBINK->Frames)
134 {
135 if (m_bLoop)
136 {
137 BinkGoto(m_pHBINK, 0, 0);
138 }
139
140 return false;
141 }
142
143 BinkCopyToBuffer(m_pHBINK, m_pBuffer, m_nBIKWidth * 3, m_nBIKHeight, 0, 0, BINKSURFACE24R);
144 glBindTexture(GL_TEXTURE_2D, m_Texture);
145 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_nBIKWidth, m_nBIKHeight, GL_RGB, GL_UNSIGNED_BYTE, m_pBuffer);
146
147 if (m_pHBINK->NumTracks && m_pSampleData)
148 {
149 memset(m_pSampleData, 0, m_nSampleSize);
150 BinkGetTrackData(m_hTrack, m_pSampleData);
151
152 BINKTRACK *track = (BINKTRACK *)m_hTrack;
153 int i, n;
154
155 memset(m_pWaveData, 0, m_nWaveSize);
156
157 if (track->Channels == 1 && track->Bits == 8)
158 {
159 for (i = 0, n = 0; i < m_nSampleSize && n < m_nWaveSize; )
160 {
161 m_pWaveData[n] = (float)m_pSampleData[i] / 128.0f;
162 ++i;
163 ++n;
164 }
165 }
166 else if (track->Channels == 2 && track->Bits == 8)
167 {
168 for (i = 0, n = 0; i < m_nSampleSize && n < m_nWaveSize; )
169 {
170 float l = (float)m_pSampleData[i] / 128.0f;
171 ++i;
172 float r = (float)m_pSampleData[i] / 128.0f;
173 ++i;
174
175 m_pWaveData[n] = (l + r) / 2.0f;
176 ++n;
177 }
178 }
179 else if (track->Channels == 1 && track->Bits == 16)
180 {
181 for (i = 0, n = 0; i < m_nSampleSize && n < m_nWaveSize; )
182 {
183 m_pWaveData[n] = (float)( (m_pSampleData[i + 1] << 8) +
184 m_pSampleData[i]) / 32767.0f;
185
186 i += 2;
187 ++n;
188 }
189 }
190 else if (track->Channels == 2 && track->Bits == 16)
191 {
192 for (i = 0, n = 0; i < m_nSampleSize && n < m_nWaveSize; )
193 {
194 float l = (float)( (m_pSampleData[i + 1] << 8) +
195 m_pSampleData[i]) / 32767.0f;
196 float r = (float)( (m_pSampleData[i + 3] << 8) +
197 m_pSampleData[i + 2]) / 32767.0f;
198
199 i += 4;
200
201 m_pWaveData[n] = (l + r) / 2.0f;
202 ++n;
203 }
204 }
205 }
206
207 BinkNextFrame(m_pHBINK);
208
209 return true;
210 }
211
212 int CBIKMaterial::GetTexture(void)
213 {
214 return m_Texture;
215 }
216
217 void CBIKMaterial::GetFrameSize(int *pWidth, int *pHeight)
218 {
219 *pWidth = m_nBIKWidth;
220 *pHeight = m_nBIKHeight;
221 }
222
223 int CBIKMaterial::GetFrameRate(void)
224 {
225 return m_nFrameRate;
226 }
227
228 int CBIKMaterial::GetFrameCount(void)
229 {
230 return m_nFrameCount;
231 }
232
233 void CBIKMaterial::SetFrame(float flFrame)
234 {
235 U32 iFrame = (U32)flFrame + 1;
236
237 if (m_pHBINK->LastFrameNum != iFrame)
238 {
239 BinkGoto(m_pHBINK, iFrame, 0);
240 }
241 }
242
243 void CBIKMaterial::SetLoop(bool state)
244 {
245 m_bLoop = state;
246 }
247
248 void CBIKMaterial::CreateProceduralTexture(void)
249 {
250 glGenTextures(1, (GLuint *)&m_Texture);
251
252 glBindTexture(GL_TEXTURE_2D, m_Texture);
253 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_nBIKWidth, m_nBIKHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pBuffer);
254 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
255 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
256 }
257
258 void CBIKMaterial::DestroyProceduralTexture(void)
259 {
260 glDeleteTextures(1, (GLuint *)&m_Texture);
261 }