summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2012-04-09 22:02:25 +0100
committerTim Redfern <tim@eclectronics.org>2012-04-09 22:02:25 +0100
commit1d7efc8eba12b05ad96af2c6e68ba037b2138140 (patch)
tree4ea2347ffdb8dfa2788390c5a18340553dae390a
parent1039fe7789a990eee6e00896cf85bc097e9009dc (diff)
sequence blending almost there
-rw-r--r--morpher/morpher.layout6
-rw-r--r--morpher/src/morphmesh.cpp141
-rw-r--r--morpher/src/morphmesh.h24
-rw-r--r--morpher/src/testApp.cpp22
4 files changed, 152 insertions, 41 deletions
diff --git a/morpher/morpher.layout b/morpher/morpher.layout
index d273f51..19ecc35 100644
--- a/morpher/morpher.layout
+++ b/morpher/morpher.layout
@@ -8,10 +8,10 @@
<Cursor position="478" topLine="0" />
</File>
<File name="src/morphmesh.cpp" open="1" top="1" tabpos="6">
- <Cursor position="815" topLine="23" />
+ <Cursor position="3075" topLine="87" />
</File>
<File name="src/morphmesh.h" open="1" top="0" tabpos="5">
- <Cursor position="1187" topLine="35" />
+ <Cursor position="2727" topLine="67" />
</File>
<File name="src/normBindTexture.cpp" open="1" top="0" tabpos="2">
<Cursor position="0" topLine="3" />
@@ -20,7 +20,7 @@
<Cursor position="0" topLine="0" />
</File>
<File name="src/testApp.cpp" open="1" top="0" tabpos="4">
- <Cursor position="1167" topLine="25" />
+ <Cursor position="524" topLine="0" />
</File>
<File name="src/testApp.h" open="1" top="0" tabpos="3">
<Cursor position="597" topLine="0" />
diff --git a/morpher/src/morphmesh.cpp b/morpher/src/morphmesh.cpp
index e68e526..63d58f7 100644
--- a/morpher/src/morphmesh.cpp
+++ b/morpher/src/morphmesh.cpp
@@ -1,9 +1,5 @@
#include "morphmesh.h"
-sequence::sequence()
-{
-}
-
track::track()
{
}
@@ -19,17 +15,49 @@ float track::evaluate(float time)
{
//interpolate key track
if (time<=keys.begin()->first) return keys.begin()->second;
- if (time>keys.rbegin()->first) return keys.rbegin()->second;
- multimap< float,float >::iterator key2=keys.upper_bound( time );
- multimap< float,float >::iterator key1=key2--;
+ if (time>=keys.rbegin()->first) return keys.rbegin()->second;
+ map< float,float >::iterator key2=keys.upper_bound( time );
+ map< float,float >::iterator key1=key2--;
float interval=key2->first-key1->first;
return (((1.0-((key2->first-time)/interval))*key2->second)+((1.0-((time-key1->first)/interval))*key1->second));
}
+sequence::sequence(string _name,float _length,float _fadeinTime,float _fadeoutTime)
+{
+ name=_name;
+ length=_length;
+ startTime=0.0;
+ stopTime=0.0;
+ fadeinTime=_fadeinTime;
+ fadeoutTime=_fadeoutTime;
+ active=false;
+}
+
+void sequence::start(){
+ active=true;
+ startTime=ofGetElapsedTimef();
+}
+void sequence::stop(){
+ active=true;
+}
+
+vector<morphWeight> sequence::evaluate(float time){
+ float seqtime=time-startTime;
+ float fadeWeight=(seqtime<fadeinTime?seqtime/fadeinTime:seqtime>stopTime-fadeoutTime&&stopTime>0&&fadeoutTime>0?(seqtime-fadeoutTime)/(stopTime-fadeoutTime):1.0);
+ vector<morphWeight> weights;
+ map<string,track>::iterator i;
+ for( i = tracks.begin(); i != tracks.end(); i++ ) {
+ weights.push_back(morphWeight(i->first,(i->second.evaluate(seqtime))*fadeWeight));
+ }
+ return weights;
+}
+
+
morphmesh::morphmesh()
{
loaded=false;
- /*
+
+ /*
//testing track function
track testrack;
testrack.keys.insert( pair<float,float>(0.0,2.0) );
@@ -38,7 +66,7 @@ morphmesh::morphmesh()
for (float f=-0.4;f<1.4;f+=0.1) {
printf("%f : %f\n",f,testrack.evaluate(f));
}
- */
+ */
}
morphmesh::morphmesh(string filename)
@@ -51,6 +79,9 @@ morphmesh::morphmesh(string filename)
int morphmesh::getNumTargets(){
return morphs.size();
}
+int morphmesh::getNumSequences(){
+ return sequences.size();
+}
void morphmesh::draw() {
draw(0);
}
@@ -64,26 +95,101 @@ void morphmesh::draw(string target){
addVertices(morphs[target]);
ofMesh::draw();
}
-void morphmesh::draw(const vector<string>& targets, const vector<float>& weights){
+void morphmesh::draw(const vector<morphWeight>& weights){
+ morphWeight mw[2];
+ for (int i=0;i<weights.size();i++) mw[i]=weights[i];
clearVertices();
//normalise weights
- int targetsNum=min(targets.size(),morphs.size());
float totalWeights=0;
- for (int i=0;i<targetsNum;i++) totalWeights+=weights[i];
+ for (int i=0;i<weights.size();i++) totalWeights+=weights[i].weight;
float weightFactor=1.0/totalWeights;
float bx,by,bz;
- for (int j=0;j<morphs[targets[0]].size();j++) {
+ for (int j=0;j<morphs.begin()->second.size();j++) {
bx=by=bz=0;
- for (int i=0;i<targetsNum;i++) {
- bx+=morphs[targets[i]][j].x*weights[i];
- by+=morphs[targets[i]][j].y*weights[i];
- bz+=morphs[targets[i]][j].z*weights[i];
+ for (int i=0;i<weights.size();i++) {
+ bx+=morphs[weights[i].name][j].x*weights[i].weight;
+ by+=morphs[weights[i].name][j].y*weights[i].weight;
+ bz+=morphs[weights[i].name][j].z*weights[i].weight;
}
addVertex(ofVec3f(bx*weightFactor,by*weightFactor,bz*weightFactor));
}
ofMesh::draw();
}
+void morphmesh::drawAnimated(){
+ float time=ofGetElapsedTimef();
+ vector<morphWeight> weights;
+ map<string,sequence>::iterator i;
+ for( i = sequences.begin(); i != sequences.end(); i++ ) {
+ if (i->second.active) {
+ vector<morphWeight> newWeights=i->second.evaluate(fmod(time-i->second.startTime,i->second.length));
+ int nnw= newWeights.size(); //test
+ weights.insert(weights.end(),newWeights.begin(),newWeights.end());
+ int nw= weights.size(); //test
+ if (i->second.stopTime>0&&time>i->second.stopTime) i->second.active=false;
+ }
+ }
+ draw(weights);
+}
+
+
+bool morphmesh::loadSeqs(string filename){
+ loaded=false;
+ ofxXmlSettings XML;
+ if( !XML.loadFile(filename) ){
+ printf("unable to load %s check data/ folder\n",filename.c_str());
+ }else{
+ if(XML.pushTag("Gauntletanim")) {
+ int numSeqs=XML.getNumTags("Sequence");
+ vector<string> seqnames;
+ for (int i=0;i<numSeqs;i++) seqnames.push_back(XML.getAttribute("Sequence","Name","none",i));
+ for (int i=0;i<numSeqs;i++) {
+ float length=ofToFloat(XML.getAttribute("Sequence","Length","0",i));
+ float fadeinTime=ofToFloat(XML.getAttribute("Sequence","Fadein","0",i));
+ float fadeoutTime=ofToFloat(XML.getAttribute("Sequence","Fadeout","0",i));
+ sequence seq=sequence(seqnames[i],length,fadeinTime,fadeoutTime);
+
+ XML.pushTag("Sequence",i);
+ int numTargs=XML.getNumTags("Target");
+ vector<string> targnames;
+ for (int j=0;j<numTargs;j++) targnames.push_back(XML.getAttribute("Target","Name","none",j));
+ for (int j=0;j<numTargs;j++) {
+ XML.pushTag("Target",j);
+
+ vector<float> times;
+ string keystring=XML.getAttribute("Keys","Times","none",0);
+ stringstream ks(keystring);
+ istream_iterator<string> kbegin(ks);
+ istream_iterator<string> kend;
+ vector<string> kstrings(kbegin, kend);
+
+ vector<float> values;
+ string valstring=XML.getAttribute("Keys","Values","none",0);
+ stringstream vs(valstring);
+ istream_iterator<string> vbegin(vs);
+ istream_iterator<string> vend;
+ vector<string> vstrings(vbegin, vend);
+
+ track tr;
+
+ for (int k=0;k<min(kstrings.size(),vstrings.size());k++) tr.keys[ofToFloat(kstrings[k])]=ofToFloat(vstrings[k]);
+
+ seq.tracks[targnames[j]]=tr;
+
+ XML.popTag();
+ }
+ sequences[seqnames[i]]=seq;
+ loaded=true;
+ XML.popTag();
+ }
+ XML.popTag();
+ }
+ }
+ return loaded;
+}
+
+
+
bool morphmesh::loadMesh(string filename){
loaded=false;
ofxXmlSettings XML;
@@ -99,7 +205,6 @@ bool morphmesh::loadMesh(string filename){
XML.pushTag("Mesh",i);
if (XML.pushTag("AttributeList")) {
vector<ofVec3f> verts;
-
string vertstring=XML.getAttribute("Attribute","Data","none",0);
stringstream ss(vertstring);
istream_iterator<string> begin(ss);
diff --git a/morpher/src/morphmesh.h b/morpher/src/morphmesh.h
index 18463a8..5293f9d 100644
--- a/morpher/src/morphmesh.h
+++ b/morpher/src/morphmesh.h
@@ -36,8 +36,9 @@ These could be parameterised on top of the rest?
*/
struct morphWeight
{
- string name;
- float weight;
+ morphWeight(string _name="",float _weight=1.0) {name=_name;weight=_weight;}
+ string name;
+ float weight;
};
struct key
@@ -52,8 +53,7 @@ class track
//a single morph channel. keys a single morph target within a single sequence
public:
track();
- string target;
- multimap<float,float> keys;
+ map<float,float> keys;
float evaluate(float time);
};
@@ -67,15 +67,18 @@ class sequence
//sequencer keeps track of playback time and start/stop of sequences
//tracks is a map of time,value pairs - built in interpolation via multimap
public:
- sequence();
+ sequence(string _name="",float _length=1.0,float _fadeinTime=0.0,float _fadeoutTime=0.0);
+ string name;
map<string,track> tracks;
- vector<morphWeight> evaluate();
- private:
+ vector<morphWeight> evaluate(float time);
+ void start();
+ void stop();
float length;
float startTime;
+ float stopTime;
float fadeinTime;
float fadeoutTime;
- bool loop,active;
+ bool active;
};
@@ -90,10 +93,11 @@ class morphmesh : public ofMesh
void draw();
void draw(int target);
void draw(string target);
- void draw(const vector<string>& targets, const vector<float>& weights);
+ void draw(const vector<morphWeight>& weights);
void drawAnimated(); //evaluates all active sequences via iterator and builds a collection of targets and weights for above
int getNumTargets();
- map< string,sequence > sequences; //public for direct access
+ int getNumSequences();
+ map<string,sequence> sequences; //public for direct access
protected:
private:
map< string,vector<ofVec3f> > morphs;
diff --git a/morpher/src/testApp.cpp b/morpher/src/testApp.cpp
index 04ecd26..31dffb4 100644
--- a/morpher/src/testApp.cpp
+++ b/morpher/src/testApp.cpp
@@ -4,7 +4,12 @@
void testApp::setup(){
//mesh.loadfile("Bird-test1.xml");
if (mesh.loadMesh("Bird-test.xml")) printf("mesh loaded with %i vertices, %i face indices, %i targets\n",mesh.getNumVertices(),mesh.getNumIndices(),mesh.getNumTargets());
- else printf("XML not parsed\n");
+ else printf("mesh XML file not parsed\n");
+
+ if (mesh.loadSeqs("Bird-anim-test.xml")) printf("animation loaded with %i sequences\n",mesh.getNumSequences());
+ else printf("animation XML file not parsed\n");
+
+ mesh.sequences["flap"].start();
texture.loadImage("texture2.jpg");
@@ -27,14 +32,10 @@ void testApp::update(){
void testApp::draw(){
//calculate morph targets
float segment=(sin(ofGetElapsedTimef())*0.5)+0.5;
- vector<string> targets;
- vector<float> weights;
- targets.push_back("bird 2");
- weights.push_back(segment);
- targets.push_back("bird");
- weights.push_back(1.0-segment);
- //printf("drawing %f %f\n",segment,1.0-segment);
-
+ vector<morphWeight> testweight;
+ testweight.push_back(morphWeight("bird 2",segment));
+ testweight.push_back(morphWeight("bird",1.0-segment));
+
ofBackground(0,0,0);
bindTexture(texture);
ofPushMatrix();
@@ -43,7 +44,8 @@ void testApp::draw(){
ofRotate(yr,1,0,0);
ofRotate(180,1,0,0);
ofScale(2.0,2.0,2.0);
- mesh.draw(targets,weights);
+ //mesh.draw(testweight);
+ mesh.drawAnimated();
ofPopMatrix();
unbindTexture(texture);