|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-20 00:40:33
|
Module: performous
Branch: master
Commit: 979c781f3b86a62081764d51bbdc3a5ae15c052a
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jul 20 02:32:52 2009 +0300
Proper BPM handling for guitar loading and render.
---
game/guitargraph.cc | 38 ++++++++++++++++++++++++++------------
game/midifile.cc | 3 ++-
game/midifile.hh | 1 +
game/song.cc | 1 +
game/song.hh | 2 ++
game/songparser-ini.cc | 2 +-
6 files changed, 33 insertions(+), 14 deletions(-)
diff --git a/game/guitargraph.cc b/game/guitargraph.cc
index 2578334..17c8c5d 100644
--- a/game/guitargraph.cc
+++ b/game/guitargraph.cc
@@ -4,6 +4,7 @@ namespace {
const float past = -0.3f;
const float future = 3.0f;
const float timescale = 30.0f;
+ const float texCoordStep = -0.5f; // Two beat lines per neck texture => 0.5 tex units per beat
// Note: t is difference from playback time so it must be in range [past, future]
float time2y(float t) { return -timescale * (t - past) / (future - past); }
float time2a(float t) { return 1.0f - t / future; } // Note: we want 1.0 alpha already at zero t.
@@ -19,22 +20,25 @@ void GuitarGraph::draw(double time) {
glTranslatef(0.0f, dimensions.y2(), 0.0f);
glRotatef(80.0f, 1.0f, 0.0f, 0.0f);
{ float s = dimensions.w() / 5.0f; glScalef(s, s, s); }
+ // Draw the neck
{
UseTexture tex(m_neck);
glutil::Begin block(GL_TRIANGLE_STRIP);
- glTexCoord2f(0.0f, -(time + future)); glColor4f(1.0f, 1.0f, 1.0f, 0.0f); glVertex2f(-2.5f, time2y(future));
- glTexCoord2f(1.0f, -(time + future)); glColor4f(1.0f, 1.0f, 1.0f, 0.0f); glVertex2f(2.5f, time2y(future));
- glTexCoord2f(0.0f, -(time + past)); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glVertex2f(-2.5f, time2y(past));
- glTexCoord2f(1.0f, -(time + past)); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glVertex2f(2.5f, time2y(past));
+ float texCoord = 0.0f;
+ float tBeg = 0.0f, tEnd;
+ for (Song::Beats::const_iterator it = m_song.beats.begin(); it != m_song.beats.end() && tBeg < future; ++it, texCoord += texCoordStep, tBeg = tEnd) {
+ tEnd = *it - time;
+ //if (tEnd < past) continue;
+ if (tEnd > future) {
+ // Crop the end off
+ texCoord -= texCoordStep * (tEnd - future) / (tEnd - tBeg);
+ tEnd = future;
+ }
+ glColor4f(1.0f, 1.0f, 1.0f, time2a(tEnd));
+ glTexCoord2f(0.0f, texCoord); glVertex2f(-2.5f, time2y(tEnd));
+ glTexCoord2f(1.0f, texCoord); glVertex2f(2.5f, time2y(tEnd));
+ }
}
- {
- glutil::Begin block(GL_TRIANGLE_STRIP);
- glColor3f(1.0f, 1.0f, 1.0f);
- glVertex2f(-2.5f, time2y(0.01f));
- glVertex2f(2.5f, time2y(0.01f));
- glVertex2f(-2.5f, time2y(-0.01f));
- glVertex2f(2.5f, time2y(-0.01f));
- }
enum Difficulty {
DIFFICULTY_SUPAEASY,
DIFFICULTY_EASY,
@@ -59,6 +63,7 @@ void GuitarGraph::draw(double time) {
glutil::Color(0.0f, 0.0f, 1.0f),
glutil::Color(1.0f, 0.5f, 0.0f)
};
+ // Draw the notes
NoteMap const& nm = m_song.tracks.begin()->second;
for (int fret = 0; fret < 5; ++fret) {
float x = -2.0f + fret;
@@ -89,4 +94,13 @@ void GuitarGraph::draw(double time) {
}
}
glColor3f(1.0f, 1.0f, 1.0f);
+ // Draw the cursor
+ {
+ glutil::Begin block(GL_TRIANGLE_STRIP);
+ glVertex2f(-2.5f, time2y(0.01f));
+ glVertex2f(2.5f, time2y(0.01f));
+ glVertex2f(-2.5f, time2y(-0.01f));
+ glVertex2f(2.5f, time2y(-0.01f));
+ }
}
+
diff --git a/game/midifile.cc b/game/midifile.cc
index 939fe99..a1f4a0b 100644
--- a/game/midifile.cc
+++ b/game/midifile.cc
@@ -117,7 +117,7 @@ void MidiStream::Riff::seek_back(size_t o) {
MidiFileParser::MidiFileParser(std::string name):
- format(0), division(0)
+ format(0), division(0), ts_last(0)
{
MidiStream stream(name.c_str());
size_t ntracks = parse_header(stream);
@@ -213,6 +213,7 @@ MidiFileParser::Track MidiFileParser::read_track(MidiStream& stream) {
process_midi_event(track, event >> 4, arg1, arg2, miditime);
}
}
+ if (miditime > ts_last) ts_last = miditime;
return track;
}
diff --git a/game/midifile.hh b/game/midifile.hh
index f80162c..2ce9c46 100644
--- a/game/midifile.hh
+++ b/game/midifile.hh
@@ -86,6 +86,7 @@ class MidiFileParser{
/** Ticks per beat == number of divisions per every quarter note **/
uint16_t division;
+ uint32_t ts_last;
private:
std::string m_lyric;
};
diff --git a/game/song.cc b/game/song.cc
index 7bcac8b..31de0c2 100644
--- a/game/song.cc
+++ b/game/song.cc
@@ -6,6 +6,7 @@
void Song::reload(bool errorIgnore) {
notes.clear();
tracks.clear();
+ beats.clear();
category.clear();
genre.clear();
edition.clear();
diff --git a/game/song.hh b/game/song.hh
index 9975662..39e58d1 100644
--- a/game/song.hh
+++ b/game/song.hh
@@ -38,6 +38,8 @@ class Song: boost::noncopyable {
int randomIdx; ///< sorting index used for random order
Notes notes; ///< notes for song (only used for singing)
Tracks tracks; ///< guitar etc. notes for this song
+ typedef std::vector<double> Beats;
+ Beats beats;
int noteMin, ///< lowest note
noteMax; ///< highest note
std::string path; ///< path of songfile
diff --git a/game/songparser-ini.cc b/game/songparser-ini.cc
index 71bb0f6..5dc2160 100644
--- a/game/songparser-ini.cc
+++ b/game/songparser-ini.cc
@@ -42,7 +42,7 @@ void SongParser::iniParse() {
testAndAdd(s, "drums.ogg");
testAndAdd(s, "vocals.ogg");
MidiFileParser midi(s.path + "/notes.mid");
- for (MidiFileParser::TempoChanges::const_iterator it = midi.tempochanges.begin(); it != midi.tempochanges.end(); ++it) addBPM(it->miditime * 4, it->value);
+ for (uint32_t ts = 0; ts <= midi.ts_last; ts += midi.division) s.beats.push_back(midi.get_seconds(ts));
for (MidiFileParser::Tracks::const_iterator it = midi.tracks.begin(); it != midi.tracks.end(); ++it) {
// Figure out the track name
std::string name = it->name;
|