99namespace libprojectM {
1010namespace MilkdropPreset {
1111
12- static constexpr int CustomWaveformMaxSamples = std::max(libprojectM:: Audio::WaveformSamples, libprojectM:: Audio::SpectrumSamples);
12+ static constexpr int CustomWaveformMaxSamples = std::max(Audio::WaveformSamples, Audio::SpectrumSamples);
1313
1414CustomWaveform::CustomWaveform (PresetState& presetState)
15- : RenderItem()
16- , m_presetState(presetState)
15+ : m_presetState(presetState)
1716 , m_perFrameContext(presetState.globalMemory, &presetState.globalRegisters)
1817 , m_perPointContext(presetState.globalMemory, &presetState.globalRegisters)
18+ , m_mesh(Renderer::VertexBufferUsage::StreamDraw, true , false )
1919{
20- RenderItem::Init ();
21-
2220 m_perFrameContext.RegisterBuiltinVariables ();
2321 m_perPointContext.RegisterBuiltinVariables ();
24- }
25-
26- void CustomWaveform::InitVertexAttrib ()
27- {
28- glEnableVertexAttribArray (0 );
29- glEnableVertexAttribArray (1 );
3022
31- glVertexAttribPointer (0 , 2 , GL_FLOAT, GL_FALSE, sizeof (ColoredPoint), nullptr ); // points
32- glVertexAttribPointer (1 , 4 , GL_FLOAT, GL_FALSE, sizeof (ColoredPoint), reinterpret_cast <void *>(sizeof (float ) * 2 )); // colors
33-
34- std::vector<ColoredPoint> vertexData;
35- vertexData.resize (std::max (libprojectM::Audio::SpectrumSamples, libprojectM::Audio::WaveformSamples) * 2 + 2 );
36- glBufferData (GL_ARRAY_BUFFER, sizeof (ColoredPoint) * vertexData.size (), vertexData.data (), GL_STREAM_DRAW);
23+ // Allocate space for max number of vertices possible, so we won't have to resize the vertex
24+ // buffers, which may change on each frame.
25+ m_mesh.SetVertexCount (std::max (Audio::SpectrumSamples, Audio::WaveformSamples) * 2 + 2 );
3726}
3827
39- void CustomWaveform::Initialize (::libprojectM:: PresetFileParser& parsedFile, int index)
28+ void CustomWaveform::Initialize (PresetFileParser& parsedFile, int index)
4029{
4130 std::string const wavecodePrefix = " wavecode_" + std::to_string (index) + " _" ;
4231 std::string const wavePrefix = " wave_" + std::to_string (index) + " _" ;
4332
4433 m_index = index;
45- m_enabled = parsedFile.GetInt (wavecodePrefix + " enabled" , m_enabled);
34+ m_enabled = parsedFile.GetBool (wavecodePrefix + " enabled" , m_enabled);
4635 m_samples = parsedFile.GetInt (wavecodePrefix + " samples" , m_samples);
4736 m_sep = parsedFile.GetInt (wavecodePrefix + " sep" , m_sep);
4837 m_spectrum = parsedFile.GetBool (wavecodePrefix + " bSpectrum" , m_spectrum);
@@ -56,6 +45,7 @@ void CustomWaveform::Initialize(::libprojectM::PresetFileParser& parsedFile, int
5645 m_b = parsedFile.GetFloat (wavecodePrefix + " b" , m_b);
5746 m_a = parsedFile.GetFloat (wavecodePrefix + " a" , m_a);
5847
48+ m_mesh.SetRenderPrimitiveType (m_useDots ? Renderer::Mesh::PrimitiveType::Points : Renderer::Mesh::PrimitiveType::LineStrip);
5949}
6050
6151void CustomWaveform::CompileCodeAndRunInitExpressions (const PerFrameContext& presetPerFrameContext)
@@ -74,15 +64,15 @@ void CustomWaveform::CompileCodeAndRunInitExpressions(const PerFrameContext& pre
7464
7565void CustomWaveform::Draw (const PerFrameContext& presetPerFrameContext)
7666{
77- static_assert (libprojectM:: Audio::WaveformSamples <= WaveformMaxPoints, " WaveformMaxPoints is larger than WaveformSamples" );
78- static_assert (libprojectM:: Audio::SpectrumSamples <= WaveformMaxPoints, " WaveformMaxPoints is larger than SpectrumSamples" );
67+ static_assert (Audio::WaveformSamples <= WaveformMaxPoints, " WaveformMaxPoints is larger than WaveformSamples" );
68+ static_assert (Audio::SpectrumSamples <= WaveformMaxPoints, " WaveformMaxPoints is larger than SpectrumSamples" );
7969
8070 if (!m_enabled)
8171 {
8272 return ;
8373 }
8474
85- int const maxSampleCount{m_spectrum ? libprojectM:: Audio::SpectrumSamples : libprojectM:: Audio::WaveformSamples};
75+ int const maxSampleCount{m_spectrum ? Audio::SpectrumSamples : Audio::WaveformSamples};
8676
8777 // Initialize and execute per-frame code
8878 LoadPerFrameEvaluationVariables (presetPerFrameContext);
@@ -108,7 +98,6 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext)
10898 : m_presetState.audioData .waveformRight .data ();
10999
110100 const float mult = m_scaling * m_presetState.waveScale * (m_spectrum ? 0 .15f : 0 .004f );
111- // const float mult = m_scaling * m_presetState.waveScale * (m_spectrum ? 0.05f : 1.0f);
112101
113102 // PCM data smoothing
114103 const int offset1 = m_spectrum ? 0 : (maxSampleCount - sampleCount) / 2 - m_sep / 2 ;
@@ -144,7 +133,8 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext)
144133 sampleDataR[sample] *= mult;
145134 }
146135
147- std::vector<ColoredPoint> pointsTransformed (sampleCount);
136+ std::vector<Renderer::Point> points (sampleCount);
137+ std::vector<Renderer::Color> colors (sampleCount);
148138
149139 float const sampleMultiplicator = sampleCount > 1 ? 1 .0f / static_cast <float >(sampleCount - 1 ) : 0 .0f ;
150140 for (int sample = 0 ; sample < sampleCount; sample++)
@@ -154,17 +144,16 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext)
154144
155145 m_perPointContext.ExecutePerPointCode ();
156146
157- pointsTransformed [sample]. x = static_cast <float >((*m_perPointContext.x * 2.0 - 1.0 ) * m_presetState.renderContext .invAspectX );
158- pointsTransformed[sample]. y = static_cast <float >((*m_perPointContext.y * -2.0 + 1.0 ) * m_presetState.renderContext .invAspectY );
147+ points [sample] = Renderer::Point ( static_cast <float >((*m_perPointContext.x * 2.0 - 1.0 ) * m_presetState.renderContext .invAspectX ),
148+ static_cast <float >((*m_perPointContext.y * -2.0 + 1.0 ) * m_presetState.renderContext .invAspectY ) );
159149
160- pointsTransformed [sample]. r = Renderer::color_modulo ( *m_perPointContext.r );
161- pointsTransformed[sample]. g = Renderer::color_modulo (*m_perPointContext.g );
162- pointsTransformed[sample]. b = Renderer::color_modulo (*m_perPointContext.b );
163- pointsTransformed[sample]. a = Renderer::color_modulo (*m_perPointContext.a );
150+ colors [sample] = Renderer::Color::Modulo ( Renderer::Color ( static_cast < float >( *m_perPointContext.r ),
151+ static_cast < float > (*m_perPointContext.g ),
152+ static_cast < float > (*m_perPointContext.b ),
153+ static_cast < float > (*m_perPointContext.a )) );
164154 }
165155
166- std::vector<ColoredPoint> pointsSmoothed (sampleCount * 2 );
167- auto smoothedVertexCount = SmoothWave (pointsTransformed.data (), sampleCount, pointsSmoothed.data ());
156+ SmoothWave (points, colors);
168157
169158#ifndef USE_GLES
170159 glDisable (GL_LINE_SMOOTH);
@@ -192,10 +181,9 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext)
192181 auto incrementX = 1 .0f / static_cast <float >(m_presetState.renderContext .viewportSizeX );
193182 auto incrementY = 1 .0f / static_cast <float >(m_presetState.renderContext .viewportSizeX );
194183
195- GLuint drawType = m_useDots ? GL_POINTS : GL_LINE_STRIP ;
184+ size_t smoothedVertexCount = m_mesh. Indices (). Size () ;
196185
197- glBindVertexArray (m_vaoID);
198- glBindBuffer (GL_ARRAY_BUFFER, m_vboID);
186+ auto & vertices = m_mesh.Vertices ();
199187
200188 // If thick outline is used, draw the shape four times with slight offsets
201189 // (top left, top right, bottom right, bottom left).
@@ -208,34 +196,32 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext)
208196 break ;
209197
210198 case 1 :
211- for (auto j = 0 ; j < smoothedVertexCount; j++)
199+ for (size_t j = 0 ; j < smoothedVertexCount; j++)
212200 {
213- pointsSmoothed [j].x += incrementX;
201+ vertices [j].SetX (vertices[j]. X () + incrementX) ;
214202 }
215203 break ;
216204
217205 case 2 :
218- for (auto j = 0 ; j < smoothedVertexCount; j++)
206+ for (size_t j = 0 ; j < smoothedVertexCount; j++)
219207 {
220- pointsSmoothed [j].y += incrementY;
208+ vertices [j].SetY (vertices[j]. Y () + incrementY) ;
221209 }
222210 break ;
223211
224212 case 3 :
225- for (auto j = 0 ; j < smoothedVertexCount; j++)
213+ for (size_t j = 0 ; j < smoothedVertexCount; j++)
226214 {
227- pointsSmoothed [j].x -= incrementX;
215+ vertices [j].SetX (vertices[j]. X () - incrementX) ;
228216 }
229217 break ;
230218 }
231219
232- glBufferSubData (GL_ARRAY_BUFFER, 0 , sizeof (ColoredPoint) * smoothedVertexCount, pointsSmoothed. data () );
233- glDrawArrays (drawType, 0 , smoothedVertexCount );
220+ m_mesh. Update ( );
221+ m_mesh. Draw ( );
234222 }
235223
236- glBindBuffer (GL_ARRAY_BUFFER, 0 );
237- glBindVertexArray (0 );
238-
224+ m_mesh.Unbind ();
239225 Renderer::Shader::Unbind ();
240226
241227 glDisable (GL_BLEND);
@@ -272,35 +258,44 @@ void CustomWaveform::LoadPerPointEvaluationVariables(float sample, float value1,
272258 *m_perPointContext.a = *m_perFrameContext.a ;
273259}
274260
275- int CustomWaveform::SmoothWave (const CustomWaveform::ColoredPoint* inputVertices,
276- int vertexCount,
277- CustomWaveform::ColoredPoint* outputVertices)
261+ void CustomWaveform::SmoothWave (const std::vector<Renderer::Point>& points, const std::vector<Renderer::Color>& colors)
278262{
279263 constexpr float c1{-0 .15f };
280264 constexpr float c2{1 .15f };
281265 constexpr float c3{1 .15f };
282266 constexpr float c4{-0 .15f };
283267 constexpr float inverseSum{1 .0f / (c1 + c2 + c3 + c4)};
284268
285- int outputIndex = 0 ;
286- int iBelow = 0 ;
287- int iAbove2 = 1 ;
269+ size_t outputIndex = 0 ;
270+ size_t iBelow = 0 ;
271+ size_t iAbove2 = 1 ;
272+
273+ size_t vertexCount = points.size ();
274+
275+ auto & outVertices = m_mesh.Vertices ();
276+ auto & outColors = m_mesh.Colors ();
288277
289- for (auto inputIndex = 0 ; inputIndex < vertexCount - 1 ; inputIndex++)
278+ for (size_t inputIndex = 0 ; inputIndex < vertexCount - 1 ; inputIndex++)
290279 {
291- int const iAbove = iAbove2;
280+ size_t const iAbove = iAbove2;
292281 iAbove2 = std::min (vertexCount - 1 , inputIndex + 2 );
293- outputVertices[outputIndex] = inputVertices[inputIndex];
294- outputVertices[outputIndex + 1 ] = inputVertices[inputIndex];
295- outputVertices[outputIndex + 1 ].x = (c1 * inputVertices[iBelow].x + c2 * inputVertices[inputIndex].x + c3 * inputVertices[iAbove].x + c4 * inputVertices[iAbove2].x ) * inverseSum;
296- outputVertices[outputIndex + 1 ].y = (c1 * inputVertices[iBelow].y + c2 * inputVertices[inputIndex].y + c3 * inputVertices[iAbove].y + c4 * inputVertices[iAbove2].y ) * inverseSum;
282+ outVertices[outputIndex] = points[inputIndex];
283+ outColors[outputIndex] = colors[inputIndex];
284+ outColors[outputIndex + 1 ] = colors[inputIndex];
285+ auto & smoothedPoint = outVertices[outputIndex + 1 ];
286+ smoothedPoint = points[inputIndex];
287+ smoothedPoint.SetX ((c1 * points[iBelow].X () + c2 * points[inputIndex].X () + c3 * points[iAbove].X () + c4 * points[iAbove2].X ()) * inverseSum);
288+ smoothedPoint.SetY ((c1 * points[iBelow].Y () + c2 * points[inputIndex].Y () + c3 * points[iAbove].Y () + c4 * points[iAbove2].Y ()) * inverseSum);
297289 iBelow = inputIndex;
298290 outputIndex += 2 ;
299291 }
300292
301- outputVertices[outputIndex] = inputVertices[vertexCount - 1 ];
293+ outVertices[outputIndex] = points[vertexCount - 1 ];
294+ outColors[outputIndex] = colors[vertexCount - 1 ];
302295
303- return outputIndex + 1 ;
296+ auto & indices = m_mesh.Indices ();
297+ indices.Resize (outputIndex + 1 );
298+ indices.MakeContinuous ();
304299}
305300
306301} // namespace MilkdropPreset
0 commit comments