diff options
Diffstat (limited to 'morpher/src')
| -rw-r--r-- | morpher/src/morphmesh.cpp | 141 | ||||
| -rw-r--r-- | morpher/src/morphmesh.h | 24 | ||||
| -rw-r--r-- | morpher/src/testApp.cpp | 22 |
3 files changed, 149 insertions, 38 deletions
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); |
