// // bvh.h // #ifndef animation_h #define animation_h #include <fstream> #include <iostream> #include <string> #include <vector> class bvh { private: struct Bone { std::string name; unsigned int id; float offset[3]; unsigned short n; std::string channels; unsigned int hierarchy; unsigned int parent; std::vector <unsigned int> children; bool noRot; std::vector <float> data; }; float time; unsigned int frames; float frameTime; std::string load(std::string filename); unsigned int parent(unsigned int id, unsigned int hierarchy); void parseHierarchy(std::string str); void parseMotion(std::string str); public: bvh(std::string filename); ~bvh(); bool active; std::vector <Bone> bone; void demo(); unsigned int getFrames(); float getFrameTime(); unsigned int play(); void rotate(unsigned int frame, unsigned int id); void show(); }; #endif // // bvh.cpp // #include "bvh.h" #include <GL/freeglut.h> // https://github.com/BandaiNamcoResearchInc/Bandai-Namco-Research-Motiondataset/find/master bvh::bvh(std::string filename) { this->active = true; this->time = 0; std::string doc = this->load(filename); int p = doc.find("MOTION"); std::string hierarchy = doc.substr(0, p); std::string motion = doc.substr(p); this->parseHierarchy(hierarchy); this->parseMotion(motion); } bvh::~bvh() { } void bvh::demo() { glPointSize(8); glLineWidth(3); for(unsigned int id = 0; id < this->bone.size(); id++) { glPushMatrix(); glTranslated(this->bone[id].offset[0], this->bone[id].offset[1], this->bone[id].offset[2]); this->rotate((unsigned int)time, id); glBegin(GL_POINTS); glVertex3f(0, 0, 0); glEnd(); for(unsigned int k = 0; k < this->bone[id].children.size(); k++) { glBegin(GL_LINES); glVertex3f(0, 0, 0); glVertex3fv(this->bone[this->bone[id].children[k]].offset); glEnd(); glBegin(GL_POINTS); glVertex3fv(this->bone[this->bone[id].children[k]].offset); glEnd(); } int u = -1; if(id == this->bone.size() - 1) { u = this->bone[id].hierarchy; } else { u = this->bone[id].hierarchy - this->bone[id + 1].hierarchy; } if(u > 0) { for(unsigned int k = 0; k < (unsigned int)u + 1; k++) { glPopMatrix(); } } } this->play(); } unsigned int bvh::getFrames() { return this->frames; } float bvh::getFrameTime() { return this->frameTime; } std::string bvh::load(std::string filename) { std::ifstream in; in.open(filename, std::ios::in); if(in.is_open()) { std::string s, tp; while(!in.eof()) { getline(in, s); tp += s + "\n"; } in.close(); return tp; } else { in.close(); std::cout << "file: " << filename << " not found. ERROR\n"; system("pause"); exit(0); } } unsigned int bvh::parent(unsigned int id, unsigned int hierarchy) { unsigned int i = id - 1; while(this->bone[i].hierarchy != hierarchy - 1) // si risale nel vettore finchè l'elemento di gerarchia hierarchy non incontra un elemento di gerarchia hierarchy - 1 { i--; } return i; } void bvh::parseHierarchy(std::string str) { std::string row; unsigned int id = 0, hierarchy = 0; Bone current; bool h = true; while(h) { int line_feed = str.find("\n"); if(line_feed != -1) // finchè il documento ha una nuova riga { row = str.substr(0, line_feed); if(row.find("ROOT") != -1) { current.name = row.substr(row.find("ROOT") + 5); // viene ricavato il nome del primo elemento della gerarchia current.id = id; current.hierarchy = hierarchy; current.noRot = false; id++; } else if(row.find("{") != -1) { } else if(row.find("OFFSET") != -1) { std::string s = row.substr(row.find("OFFSET") + 7); // vengono estrapolati i 3 valori dell'offset current.offset[0] = atof(s.substr(0, s.find(" ")).c_str()); s = s.substr(s.find(" ") + 1); current.offset[1] = atof(s.substr(0, s.find(" ")).c_str()); s = s.substr(s.find(" ") + 1); current.offset[2] = atof(s.substr(0, s.find(" ")).c_str()); } else if(row.find("CHANNELS") != -1) { std::string s = row.substr(row.find("CHANNELS") + 9); unsigned short n = atoi(s.substr(0, s.find(" ")).c_str()); // numero di canali (3 o 6) s = s.substr(s.find(" ") + 1); if(n == 6) { s = s.substr(30); // salta le stringhe XYZposition } current.n = n; // viene salvato anche il numero di canali current.channels += s[0]; // la stringa channels contiene l'ordine di rotazione s = s.substr(10); current.channels += s[0]; s = s.substr(10); current.channels += s[0]; } else if(row.find("JOINT") != -1) { this->bone.push_back(current); std::string s = row.substr(row.find("JOINT") + 6); current.name = s; current.id = id; current.channels = ""; hierarchy++; current.hierarchy = hierarchy; current.noRot = false; current.parent = this->parent(id, hierarchy); id++; } else if(row.find("End Site") != -1) { this->bone.push_back(current); current.name = "End Site"; current.id = id; current.channels = ""; hierarchy++; current.hierarchy = hierarchy; current.noRot = true; current.parent = this->parent(id, hierarchy); id++; } else if(row.find("}") != -1) { hierarchy--; } str = str.substr(line_feed + 1); // viene eliminata la riga appena letta } else // arrivato alla fine del documento { this->bone.push_back(current); // viene salvato il dato corrente for(unsigned int id = 1; id < this->bone.size(); id++) // ricava i figli di ogni elemento { this->bone[this->bone[id].parent].children.push_back(id); } h = false; // e chiuso il ciclo } } } void bvh::parseMotion(std::string str) { int line_feed = str.find("\n"); str = str.substr(line_feed + 1); // viene eliminata la riga MOTION // line_feed = str.find("\n"); std::string row = str.substr(0, line_feed); // viene letta la riga Frames std::string s = row.substr(row.find("Frames:") + 8); this->frames = atoi(s.c_str()); str = str.substr(line_feed + 1); // viene eliminata la riga Frames // line_feed = str.find("\n"); row = str.substr(0, line_feed); // viene letta la riga Frame Time s = row.substr(row.find("Frame Time:") + 12); this->frameTime = atof(s.c_str()); str = str.substr(line_feed + 1); // viene eliminata la riga Frame Time // for(unsigned int i = 0; i < this->frames; i++) { line_feed = str.find("\n"); row = str.substr(0, line_feed); for(unsigned int j = 0; j < this->bone.size(); j++) // per ogni elemento { if(!this->bone[j].noRot) // solo gli elementi che presentano dati di rotazione { if(this->bone[j].n == 6) // { for(unsigned short k = 0; k < 3; k++) { row = row.substr(row.find(" ") + 1); // sono ignorate le traslazioni } } for(unsigned short k = 0; k < 3; k++) // vengono salvati solo i dati delle rotazioni { s = row.substr(0, row.find(" ")); this->bone[j].data.push_back(atof(s.c_str())); row = row.substr(row.find(" ") + 1); } } } str = str.substr(line_feed + 1); // elimina la riga letta e passa alla successiva } } unsigned int bvh::play() { this->time += .5; if(this->time > (this->frames - 1)) { this->time = 0; } return (unsigned int) this->time; } void bvh::rotate(unsigned int frame, unsigned int id) { if(this->active) { if(id < this->bone.size()) // la rotazione si applica solo alle ossa contenute nel vettore { if(frame > this->frames - 1) // se viene inserito un frame oltre il limite viene richiamato il frame corrispondente { frame = frame % this->frames; } std::string p = this->bone[id].channels; if(p == "XYZ") { glRotated(this->bone[id].data[frame * 3 ], 1, 0, 0); glRotated(this->bone[id].data[frame * 3 + 1], 0, 1, 0); glRotated(this->bone[id].data[frame * 3 + 2], 0, 0, 1); } else if(p == "XZY") { glRotated(this->bone[id].data[frame * 3 ], 1, 0, 0); glRotated(this->bone[id].data[frame * 3 + 1], 0, 0, 1); glRotated(this->bone[id].data[frame * 3 + 2], 0, 1, 0); } else if(p == "YXZ") { glRotated(this->bone[id].data[frame * 3 ], 0, 1, 0); glRotated(this->bone[id].data[frame * 3 + 1], 1, 0, 0); glRotated(this->bone[id].data[frame * 3 + 2], 0, 0, 1); } else if(p == "YZX") { glRotated(this->bone[id].data[frame * 3 ], 0, 1, 0); glRotated(this->bone[id].data[frame * 3 + 1], 0, 0, 1); glRotated(this->bone[id].data[frame * 3 + 2], 1, 0, 0); } else if(p == "ZXY") { glRotated(this->bone[id].data[frame * 3 ], 0, 0, 1); glRotated(this->bone[id].data[frame * 3 + 1], 1, 0, 0); glRotated(this->bone[id].data[frame * 3 + 2], 0, 1, 0); } else if(p == "ZYX") { glRotated(this->bone[id].data[frame * 3 ], 0, 0, 1); glRotated(this->bone[id].data[frame * 3 + 1], 0, 1, 0); glRotated(this->bone[id].data[frame * 3 + 2], 1, 0, 0); } } else { std::cout << "ERROR: bone over size in rotate method...\n"; system("pause"); exit(0); } } } void bvh::show() { for(unsigned int i = 0; i < this->bone.size(); i++) { std::cout << "id : " << this->bone[i].id << "\n"; std::cout << "name : " << this->bone[i].name << "\n"; std::cout << "hierarchy : " << this->bone[i].hierarchy << "\n"; if(i > 0) { std::cout << "parent : " << this->bone[this->bone[i].parent].name << "\n"; } else { std::cout << "parent :\n"; } std::cout << "children : "; for(unsigned int k = 0; k < this->bone[i].children.size(); k++){std::cout << this->bone[i].children[k] << " ";} std::cout << "\n"; std::cout << "offset : " << this->bone[i].offset[0] << " " << this->bone[i].offset[1] << " " << this->bone[i].offset[2] << "\n"; std::cout << "n channels : " << this->bone[i].n << "\n"; std::cout << "channels : " << this->bone[i].channels << "\n"; std::cout << "\n"; } system("pause"); } // main.cpp #include <GL/freeglut.h> #include <stdlib.h> #include <fstream> #include <iostream> #include <string> #include "bvh.h" int TIME = 0; unsigned int f = 0; const float CAMERA_DISTANCE = 10.0f; int screenWidth; int screenHeight; bool mouseLeftDown; bool mouseRightDown; bool mouseMiddleDown; float mouseX, mouseY; float cameraAngleX; float cameraAngleY; float cameraDistance; bvh *myBvh; void resizeCallback(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)(width)/(GLfloat)(height), 0.1f, 1000.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void boneX(float y, float z, float t) { float A[3] = {0, y/2.0f,-z/2.0f}; float B[3] = {0, y/2.0f, z/2.0f}; float C[3] = {0,-y/2.0f, z/2.0f}; float D[3] = {0,-y/2.0f,-z/2.0f}; float E[3] = {t, y/2.0f, z/2.0f}; float F[3] = {t, y/2.0f,-z/2.0f}; float G[3] = {t,-y/2.0f,-z/2.0f}; float H[3] = {t,-y/2.0f, z/2.0f}; glBegin(GL_QUADS); glVertex3fv(A); glVertex3fv(B); glVertex3fv(C); glVertex3fv(D); glVertex3fv(E); glVertex3fv(F); glVertex3fv(G); glVertex3fv(H); glVertex3fv(B); glVertex3fv(E); glVertex3fv(H); glVertex3fv(C); glVertex3fv(F); glVertex3fv(A); glVertex3fv(D); glVertex3fv(G); glVertex3fv(A); glVertex3fv(F); glVertex3fv(E); glVertex3fv(B); glVertex3fv(D); glVertex3fv(C); glVertex3fv(H); glVertex3fv(G); glEnd(); } void boneY(float x, float z, float t) { float A[3] = { x/2.0f, 0,-z/2.0f}; float B[3] = { x/2.0f, 0, z/2.0f}; float C[3] = {-x/2.0f, 0, z/2.0f}; float D[3] = {-x/2.0f, 0,-z/2.0f}; float E[3] = { x/2.0f, t, z/2.0f}; float F[3] = { x/2.0f, t,-z/2.0f}; float G[3] = {-x/2.0f, t,-z/2.0f}; float H[3] = {-x/2.0f, t, z/2.0f}; glBegin(GL_QUADS); glVertex3fv(A); glVertex3fv(B); glVertex3fv(C); glVertex3fv(D); glVertex3fv(E); glVertex3fv(F); glVertex3fv(G); glVertex3fv(H); glVertex3fv(B); glVertex3fv(E); glVertex3fv(H); glVertex3fv(C); glVertex3fv(F); glVertex3fv(A); glVertex3fv(D); glVertex3fv(G); glVertex3fv(A); glVertex3fv(F); glVertex3fv(E); glVertex3fv(B); glVertex3fv(D); glVertex3fv(C); glVertex3fv(H); glVertex3fv(G); glEnd(); } void boneZ(float x, float y, float t) { float A[3] = { x/2.0f,-y/2.0f, 0}; float B[3] = { x/2.0f, y/2.0f, 0}; float C[3] = {-x/2.0f, y/2.0f, 0}; float D[3] = {-x/2.0f,-y/2.0f, 0}; float E[3] = { x/2.0f, y/2.0f, t}; float F[3] = { x/2.0f,-y/2.0f, t}; float G[3] = {-x/2.0f,-y/2.0f, t}; float H[3] = {-x/2.0f, y/2.0f, t}; glBegin(GL_QUADS); glVertex3fv(A); glVertex3fv(B); glVertex3fv(C); glVertex3fv(D); glVertex3fv(E); glVertex3fv(F); glVertex3fv(G); glVertex3fv(H); glVertex3fv(B); glVertex3fv(E); glVertex3fv(H); glVertex3fv(C); glVertex3fv(F); glVertex3fv(A); glVertex3fv(D); glVertex3fv(G); glVertex3fv(A); glVertex3fv(F); glVertex3fv(E); glVertex3fv(B); glVertex3fv(D); glVertex3fv(C); glVertex3fv(H); glVertex3fv(G); glEnd(); } void axis() { glLineWidth(1); glPushMatrix(); glBegin(GL_LINES); glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(200.0f, 0.0f, 0.0f); glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 200.0f, 0.0f); glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 200.0f); glColor3f(1.0f, 1.0f, 1.0f); glEnd(); glPopMatrix(); } void shapeBandai() { glPushMatrix(); myBvh->rotate(f, 1); boneX(20,10,-10); // bacino glPushMatrix(); myBvh->rotate(f, 2); boneX(10,15,20); // addome glPushMatrix(); glTranslated(20,0,0); myBvh->rotate(f, 3); boneX(10,30,15); // petto glPushMatrix(); glTranslated(15,0,10); myBvh->rotate(f, 7); boneX(10,10,10); // spalla sx glPushMatrix(); glTranslated(10,0,0); myBvh->rotate(f, 8); boneX(10,10,30); // braccio sx glPushMatrix(); glTranslated(30,0,0); myBvh->rotate(f, 9); boneX(10,10,30); // avambraccio sx glPushMatrix(); glTranslated(30,0,0); myBvh->rotate(f, 10); boneX(5,5,10); // mano sx glPopMatrix(); glPopMatrix(); glPopMatrix(); glPopMatrix(); glPushMatrix(); glTranslated(15,0,-10); myBvh->rotate(f, 12); boneX(10,10,-10); // spalla dx glPushMatrix(); glTranslated(-10,0,0); myBvh->rotate(f, 13); boneX(10,10,-30); // braccio dx glPushMatrix(); glTranslated(-30,0,0); myBvh->rotate(f, 14); boneX(10,10,-30); // avambraccio dx glPushMatrix(); glTranslated(-30,0,0); myBvh->rotate(f, 15); boneX(5,5,-10); // mano dx glPopMatrix(); glPopMatrix(); glPopMatrix(); glPopMatrix(); glPushMatrix(); glTranslated(15,0,0); myBvh->rotate(f, 4); boneX(8,8,5); // collo glPushMatrix(); glTranslated(5,0,0); myBvh->rotate(f, 5); boneX(10,10,10); // testa glPopMatrix(); glPopMatrix(); glPopMatrix(); glPopMatrix(); glPushMatrix(); glTranslated(-10,5,0); myBvh->rotate(f, 22); boneX(10,10,-50); // gamba dx glPushMatrix(); glTranslated(-50,0,0); myBvh->rotate(f, 23); boneX(10,10,-50); // tibia dx glPushMatrix(); glTranslated(-50,0,0); myBvh->rotate(f, 24); boneX(5,5,-10); // piede dx glPopMatrix(); glPopMatrix(); glPopMatrix(); glPushMatrix(); glTranslated(-10,-5,0); myBvh->rotate(f, 17); boneX(10,10,50); // gamba dx glPushMatrix(); glTranslated(50,0,0); myBvh->rotate(f, 18); boneX(10,10,50); // tibia dx glPushMatrix(); glTranslated(50,0,0); myBvh->rotate(f, 24); boneX(5,5,10); // piede dx glPopMatrix(); glPopMatrix(); glPopMatrix(); glPopMatrix(); f = myBvh->play(); } void displayCallback() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glPushMatrix(); glTranslatef(0, 0, -cameraDistance); glRotatef(cameraAngleX, 1, 0, 0); glRotatef(cameraAngleY, 0, 1, 0); axis(); //myBvh->demo(); shapeBandai(); glPopMatrix(); glutSwapBuffers(); } std::string readText(std::string filename) { std::fstream file; file.open(filename, std::ios::in); std::string r; if(file.is_open()) { getline(file, r); file.close(); } return r; } void init() { mouseLeftDown = mouseRightDown = mouseMiddleDown = false; mouseX = mouseY = 0; cameraAngleX = cameraAngleY = 0.0f; cameraDistance = CAMERA_DISTANCE; glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); myBvh = new bvh(readText("test.txt")); } void mouseCallback(int button, int state, int x, int y) { mouseX = x; mouseY = y; if(button == GLUT_LEFT_BUTTON) { if(state == GLUT_DOWN) { mouseLeftDown = true; } else if(state == GLUT_UP) { mouseLeftDown = false; } } else if(button == GLUT_RIGHT_BUTTON) { if(state == GLUT_DOWN) { mouseRightDown = true; } else if(state == GLUT_UP) { mouseRightDown = false; } } else if(button == GLUT_MIDDLE_BUTTON) { if(state == GLUT_DOWN) { mouseMiddleDown = true; } else if(state == GLUT_UP) { mouseMiddleDown = false; } } } void mouseMotionCallback(int x, int y) { if(mouseLeftDown) { cameraAngleY += (x - mouseX); cameraAngleX += (y - mouseY); mouseX = x; mouseY = y; } if(mouseRightDown) { cameraDistance -= (y - mouseY) * 0.2f; mouseY = y; } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(0, 0); glutInitWindowSize(640, 480); glutCreateWindow("bvh"); glutDisplayFunc(displayCallback); glutReshapeFunc(resizeCallback); glutIdleFunc(displayCallback); glutMouseFunc(mouseCallback); glutMotionFunc(mouseMotionCallback); init(); glutMainLoop(); return 1; }
Mi chiamo Cosimo Saccone e sono un programmatore napoletano di 44 anni con oltre 35 anni di esperienza nella programmazione (BASIC, Assembly). Realizzo progetti e programmi utilizzando i principali e più diffusi linguaggi (C, C++, PHP, Javascript, HTML) e software per la grafica (Photoshop, Illustrator, 3dsMax). Anche se la grafica rappresenta il mio principale settore di interesse, non disdegno il lavoro di back-end e di organizzazione dati e sono attento agli aspetti di efficienza e di risparmio delle risorse tipica della programmazione di basso livello (specie nel settore della grafica 3d). Realizzo siti internet, applicativi desktop e servizi di vario tipo. Ho una buona conoscenza della libreria OpenGL per lo sviluppo di applicazioni 3d interattive in C/C++. Cerco di adottare uno stile di programmazione fortemente ordinato e modulare. Possiedo, inoltre, una buona capacità di elaborazione della documentazione. Ho vari hobbies tra cui la pittura, la ginnastica e le lunghe passeggiate in solitudine.
Al fine di migliorare l’esperienza di navigazione sul nostro sito noi di cosimosaccone.com e i nostri partner selezionati elaboriamo i dati personali, compreso l’indirizzo IP e le pagine visitate, in relazione alla tua navigazione nei contenuti del sito, per i seguenti scopi:
Accesso alle informazioni
Dati precisi di geolocalizzazione
Misurazione del pubblico
Pubblicità e contenuti personalizzati
Ti ricordiamo che il termine cookie si riferisce a una porzione di dati inviati al tuo browser da un web server. Il cookie viene memorizzato sul tuo dispositivo e riconosciuto dal sito web che lo ha inviato in ogni navigazione successiva. Se vuoi saperne di più e compiere una scelta diversa, come il rifiuto del trattamento dei tuoi dati personali, clicca qui sulla nostra privacy policy. Potrai sempre modificare le tue scelte e impostare i singolo cookies selezionando il bottone qui sotto.
OK