diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw04/src/Mesh.cpp b/hw04/src/Mesh.cpp new file mode 100644 index 0000000..c3f444f --- /dev/null +++ b/hw04/src/Mesh.cpp @@ -0,0 +1,263 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include +#include +#include +#include "Mesh.h" +#include "Util.h" + +using namespace std; + +Mesh::Mesh() { + this->tris = {}; + this->pts = {}; +} + + +void Mesh::saveData(const string& fileName) { + ofstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + + for (auto vert : pts) { + file << "v\t" << vert.p[0] << "\t" << vert.p[1] << "\t" << vert.p[2] << endl; + } + + for (auto triag : tris) { + file << "f\t" << triag.iv[0]+1 << "\t" << triag.iv[1]+1 << "\t" << triag.iv[2]+1 << endl; + } + + file.close(); +} + +void Mesh::loadData(const string& fileName) { + ifstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + string key; + while( file){ + //getline( file, line); + file >> key; + if (key == "v") { + float x, y, z; + file >> x >> y >> z; + Vertex pVertex = *new Vertex(this, x, y, z); + pts.push_back(pVertex); + } else if (key == "f") { + int a, b, c; + file >> a >> b >> c; + Tri pTriangle = *new Tri(this, a-1, b-1, c-1); + tris.push_back(pTriangle); + } + } + file.close(); + + tris.pop_back(); +} + +void Mesh::connectivityAlgo() { + for (auto & pt : pts) { + pt.valence = 0; + } + + // Connectivity Algorithm + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + // Search for neighbour + for (int ti = 0; ti < tris.size(); ++ti) { + if (i == ti) continue; + Tri t = tris[ti]; + int count = 0; + int side = 0; + for (int x = 0; x < 3; ++x) { + bool hit = false; + for (int y : t.iv) { + if (triag.iv[x] == y) + hit = true; + } + if (hit) + count++; + else + side = x; + } + // if two points are the same, they are neighbours + if (count == 2) + triag.it[side] = ti; + } + + // increase valence for each vertex of triangle + ++pts[triag.iv[0]].valence; + ++pts[triag.iv[1]].valence; + ++pts[triag.iv[2]].valence; + + tris[i] = triag; + } +} + +void Mesh::subDivLoop(int count) { + for (int i = 0; i < count; ++i) { + this->subDivLoop(); + } +} + +void Mesh::subDivLoop() { + this->connectivityAlgo(); + + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + Vertex a = pts[triag.iv[0]]; + Vertex b = pts[triag.iv[1]]; + Vertex c = pts[triag.iv[2]]; + + for (int tI = 0; tI < 3; ++tI) { + Tri t = tris[triag.it[tI]]; + int otherEI = 0; + for (int j = 0; j < 3; ++j) { + if (t.it[j] == i) { + otherEI = j; + break; + } + } + if (i < triag.it[tI]) { + Vertex d = pts[t.iv[otherEI]]; + Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); + triag.ie[tI] = pts.size(); + pts.push_back(e); + } else { + // edge-mask already calculated + + triag.ie[tI] = t.ie[otherEI]; + } + } + + tris[i] = triag; + } + + for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta + int n = pts[i].valence; // n = valence of v_i + if (n < 3) continue; + float beta = Util::beta_n( n); +// cout << i << " " << n << " " << beta << " " <drawWireframe = this->drawWireframe; + copy->drawOutline = this->drawOutline; + + for (auto vert : this->pts) { + copy->pts.push_back(*vert.copy(copy)); + } + for (auto tri : this->tris) { + copy->tris.push_back(*tri.copy(copy)); + } + + + return copy; +} diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw04/src/Mesh.cpp b/hw04/src/Mesh.cpp new file mode 100644 index 0000000..c3f444f --- /dev/null +++ b/hw04/src/Mesh.cpp @@ -0,0 +1,263 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include +#include +#include +#include "Mesh.h" +#include "Util.h" + +using namespace std; + +Mesh::Mesh() { + this->tris = {}; + this->pts = {}; +} + + +void Mesh::saveData(const string& fileName) { + ofstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + + for (auto vert : pts) { + file << "v\t" << vert.p[0] << "\t" << vert.p[1] << "\t" << vert.p[2] << endl; + } + + for (auto triag : tris) { + file << "f\t" << triag.iv[0]+1 << "\t" << triag.iv[1]+1 << "\t" << triag.iv[2]+1 << endl; + } + + file.close(); +} + +void Mesh::loadData(const string& fileName) { + ifstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + string key; + while( file){ + //getline( file, line); + file >> key; + if (key == "v") { + float x, y, z; + file >> x >> y >> z; + Vertex pVertex = *new Vertex(this, x, y, z); + pts.push_back(pVertex); + } else if (key == "f") { + int a, b, c; + file >> a >> b >> c; + Tri pTriangle = *new Tri(this, a-1, b-1, c-1); + tris.push_back(pTriangle); + } + } + file.close(); + + tris.pop_back(); +} + +void Mesh::connectivityAlgo() { + for (auto & pt : pts) { + pt.valence = 0; + } + + // Connectivity Algorithm + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + // Search for neighbour + for (int ti = 0; ti < tris.size(); ++ti) { + if (i == ti) continue; + Tri t = tris[ti]; + int count = 0; + int side = 0; + for (int x = 0; x < 3; ++x) { + bool hit = false; + for (int y : t.iv) { + if (triag.iv[x] == y) + hit = true; + } + if (hit) + count++; + else + side = x; + } + // if two points are the same, they are neighbours + if (count == 2) + triag.it[side] = ti; + } + + // increase valence for each vertex of triangle + ++pts[triag.iv[0]].valence; + ++pts[triag.iv[1]].valence; + ++pts[triag.iv[2]].valence; + + tris[i] = triag; + } +} + +void Mesh::subDivLoop(int count) { + for (int i = 0; i < count; ++i) { + this->subDivLoop(); + } +} + +void Mesh::subDivLoop() { + this->connectivityAlgo(); + + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + Vertex a = pts[triag.iv[0]]; + Vertex b = pts[triag.iv[1]]; + Vertex c = pts[triag.iv[2]]; + + for (int tI = 0; tI < 3; ++tI) { + Tri t = tris[triag.it[tI]]; + int otherEI = 0; + for (int j = 0; j < 3; ++j) { + if (t.it[j] == i) { + otherEI = j; + break; + } + } + if (i < triag.it[tI]) { + Vertex d = pts[t.iv[otherEI]]; + Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); + triag.ie[tI] = pts.size(); + pts.push_back(e); + } else { + // edge-mask already calculated + + triag.ie[tI] = t.ie[otherEI]; + } + } + + tris[i] = triag; + } + + for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta + int n = pts[i].valence; // n = valence of v_i + if (n < 3) continue; + float beta = Util::beta_n( n); +// cout << i << " " << n << " " << beta << " " <drawWireframe = this->drawWireframe; + copy->drawOutline = this->drawOutline; + + for (auto vert : this->pts) { + copy->pts.push_back(*vert.copy(copy)); + } + for (auto tri : this->tris) { + copy->tris.push_back(*tri.copy(copy)); + } + + + return copy; +} diff --git a/hw04/src/Mesh.h b/hw04/src/Mesh.h new file mode 100644 index 0000000..eb672dd --- /dev/null +++ b/hw04/src/Mesh.h @@ -0,0 +1,39 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_MESH_H +#define OPENGL_EXAMPLE_MESH_H + +#include +#include "Vertex.h" +#include "Tri.h" + +using namespace std; + + +class Mesh { +public: + vector pts; + vector tris; + bool drawWireframe = false; + bool drawOutline = false; + + Mesh(); + void loadData(const string& fileName); + void saveData(const string& fileName); + + void connectivityAlgo(); + void subDivLoop(); + void subDivLoop(int count); + void subDivEdgeMidpoint(); + + Mesh* copy(); + +}; + + +#endif //OPENGL_EXAMPLE_MESH_H diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw04/src/Mesh.cpp b/hw04/src/Mesh.cpp new file mode 100644 index 0000000..c3f444f --- /dev/null +++ b/hw04/src/Mesh.cpp @@ -0,0 +1,263 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include +#include +#include +#include "Mesh.h" +#include "Util.h" + +using namespace std; + +Mesh::Mesh() { + this->tris = {}; + this->pts = {}; +} + + +void Mesh::saveData(const string& fileName) { + ofstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + + for (auto vert : pts) { + file << "v\t" << vert.p[0] << "\t" << vert.p[1] << "\t" << vert.p[2] << endl; + } + + for (auto triag : tris) { + file << "f\t" << triag.iv[0]+1 << "\t" << triag.iv[1]+1 << "\t" << triag.iv[2]+1 << endl; + } + + file.close(); +} + +void Mesh::loadData(const string& fileName) { + ifstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + string key; + while( file){ + //getline( file, line); + file >> key; + if (key == "v") { + float x, y, z; + file >> x >> y >> z; + Vertex pVertex = *new Vertex(this, x, y, z); + pts.push_back(pVertex); + } else if (key == "f") { + int a, b, c; + file >> a >> b >> c; + Tri pTriangle = *new Tri(this, a-1, b-1, c-1); + tris.push_back(pTriangle); + } + } + file.close(); + + tris.pop_back(); +} + +void Mesh::connectivityAlgo() { + for (auto & pt : pts) { + pt.valence = 0; + } + + // Connectivity Algorithm + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + // Search for neighbour + for (int ti = 0; ti < tris.size(); ++ti) { + if (i == ti) continue; + Tri t = tris[ti]; + int count = 0; + int side = 0; + for (int x = 0; x < 3; ++x) { + bool hit = false; + for (int y : t.iv) { + if (triag.iv[x] == y) + hit = true; + } + if (hit) + count++; + else + side = x; + } + // if two points are the same, they are neighbours + if (count == 2) + triag.it[side] = ti; + } + + // increase valence for each vertex of triangle + ++pts[triag.iv[0]].valence; + ++pts[triag.iv[1]].valence; + ++pts[triag.iv[2]].valence; + + tris[i] = triag; + } +} + +void Mesh::subDivLoop(int count) { + for (int i = 0; i < count; ++i) { + this->subDivLoop(); + } +} + +void Mesh::subDivLoop() { + this->connectivityAlgo(); + + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + Vertex a = pts[triag.iv[0]]; + Vertex b = pts[triag.iv[1]]; + Vertex c = pts[triag.iv[2]]; + + for (int tI = 0; tI < 3; ++tI) { + Tri t = tris[triag.it[tI]]; + int otherEI = 0; + for (int j = 0; j < 3; ++j) { + if (t.it[j] == i) { + otherEI = j; + break; + } + } + if (i < triag.it[tI]) { + Vertex d = pts[t.iv[otherEI]]; + Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); + triag.ie[tI] = pts.size(); + pts.push_back(e); + } else { + // edge-mask already calculated + + triag.ie[tI] = t.ie[otherEI]; + } + } + + tris[i] = triag; + } + + for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta + int n = pts[i].valence; // n = valence of v_i + if (n < 3) continue; + float beta = Util::beta_n( n); +// cout << i << " " << n << " " << beta << " " <drawWireframe = this->drawWireframe; + copy->drawOutline = this->drawOutline; + + for (auto vert : this->pts) { + copy->pts.push_back(*vert.copy(copy)); + } + for (auto tri : this->tris) { + copy->tris.push_back(*tri.copy(copy)); + } + + + return copy; +} diff --git a/hw04/src/Mesh.h b/hw04/src/Mesh.h new file mode 100644 index 0000000..eb672dd --- /dev/null +++ b/hw04/src/Mesh.h @@ -0,0 +1,39 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_MESH_H +#define OPENGL_EXAMPLE_MESH_H + +#include +#include "Vertex.h" +#include "Tri.h" + +using namespace std; + + +class Mesh { +public: + vector pts; + vector tris; + bool drawWireframe = false; + bool drawOutline = false; + + Mesh(); + void loadData(const string& fileName); + void saveData(const string& fileName); + + void connectivityAlgo(); + void subDivLoop(); + void subDivLoop(int count); + void subDivEdgeMidpoint(); + + Mesh* copy(); + +}; + + +#endif //OPENGL_EXAMPLE_MESH_H diff --git a/hw04/src/Tri.cpp b/hw04/src/Tri.cpp new file mode 100644 index 0000000..1650e2c --- /dev/null +++ b/hw04/src/Tri.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Tri.h" +#include "Mesh.h" +#include + +using namespace std; + +Tri::Tri(Mesh* mesh) { + this->mesh = mesh; + + it[0] = -1; + it[1] = -1; + it[2] = -1; + ie[0] = -1; + ie[1] = -1; + ie[2] = -1; +} + +Tri::Tri(Mesh* mesh, int *i) : Tri(mesh) { +} + +Tri::Tri(Mesh* mesh, int i, int j, int k) : Tri(mesh) { + iv[0] = i; + iv[1] = j; + iv[2] = k; +} + +void Tri::Print() { + cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; + this->mesh->pts[iv[0]].Print(); + cout << " - "; + this->mesh->pts[iv[1]].Print(); + cout << " - "; + this->mesh->pts[iv[2]].Print(); + cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; +// pts[ie[0]].Print(); +// pts[ie[1]].Print(); +// pts[ie[2]].Print(); + + cout << endl; +} + +Tri *Tri::copy(Mesh* mesh) { + Tri *copy = new Tri(mesh); + for (int i = 0; i < 3; ++i) { + copy->iv[i] = this->iv[i]; + copy->ie[i] = this->ie[i]; + copy->it[i] = this->it[i]; + } + + return copy; +} diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw04/src/Mesh.cpp b/hw04/src/Mesh.cpp new file mode 100644 index 0000000..c3f444f --- /dev/null +++ b/hw04/src/Mesh.cpp @@ -0,0 +1,263 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include +#include +#include +#include "Mesh.h" +#include "Util.h" + +using namespace std; + +Mesh::Mesh() { + this->tris = {}; + this->pts = {}; +} + + +void Mesh::saveData(const string& fileName) { + ofstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + + for (auto vert : pts) { + file << "v\t" << vert.p[0] << "\t" << vert.p[1] << "\t" << vert.p[2] << endl; + } + + for (auto triag : tris) { + file << "f\t" << triag.iv[0]+1 << "\t" << triag.iv[1]+1 << "\t" << triag.iv[2]+1 << endl; + } + + file.close(); +} + +void Mesh::loadData(const string& fileName) { + ifstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + string key; + while( file){ + //getline( file, line); + file >> key; + if (key == "v") { + float x, y, z; + file >> x >> y >> z; + Vertex pVertex = *new Vertex(this, x, y, z); + pts.push_back(pVertex); + } else if (key == "f") { + int a, b, c; + file >> a >> b >> c; + Tri pTriangle = *new Tri(this, a-1, b-1, c-1); + tris.push_back(pTriangle); + } + } + file.close(); + + tris.pop_back(); +} + +void Mesh::connectivityAlgo() { + for (auto & pt : pts) { + pt.valence = 0; + } + + // Connectivity Algorithm + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + // Search for neighbour + for (int ti = 0; ti < tris.size(); ++ti) { + if (i == ti) continue; + Tri t = tris[ti]; + int count = 0; + int side = 0; + for (int x = 0; x < 3; ++x) { + bool hit = false; + for (int y : t.iv) { + if (triag.iv[x] == y) + hit = true; + } + if (hit) + count++; + else + side = x; + } + // if two points are the same, they are neighbours + if (count == 2) + triag.it[side] = ti; + } + + // increase valence for each vertex of triangle + ++pts[triag.iv[0]].valence; + ++pts[triag.iv[1]].valence; + ++pts[triag.iv[2]].valence; + + tris[i] = triag; + } +} + +void Mesh::subDivLoop(int count) { + for (int i = 0; i < count; ++i) { + this->subDivLoop(); + } +} + +void Mesh::subDivLoop() { + this->connectivityAlgo(); + + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + Vertex a = pts[triag.iv[0]]; + Vertex b = pts[triag.iv[1]]; + Vertex c = pts[triag.iv[2]]; + + for (int tI = 0; tI < 3; ++tI) { + Tri t = tris[triag.it[tI]]; + int otherEI = 0; + for (int j = 0; j < 3; ++j) { + if (t.it[j] == i) { + otherEI = j; + break; + } + } + if (i < triag.it[tI]) { + Vertex d = pts[t.iv[otherEI]]; + Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); + triag.ie[tI] = pts.size(); + pts.push_back(e); + } else { + // edge-mask already calculated + + triag.ie[tI] = t.ie[otherEI]; + } + } + + tris[i] = triag; + } + + for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta + int n = pts[i].valence; // n = valence of v_i + if (n < 3) continue; + float beta = Util::beta_n( n); +// cout << i << " " << n << " " << beta << " " <drawWireframe = this->drawWireframe; + copy->drawOutline = this->drawOutline; + + for (auto vert : this->pts) { + copy->pts.push_back(*vert.copy(copy)); + } + for (auto tri : this->tris) { + copy->tris.push_back(*tri.copy(copy)); + } + + + return copy; +} diff --git a/hw04/src/Mesh.h b/hw04/src/Mesh.h new file mode 100644 index 0000000..eb672dd --- /dev/null +++ b/hw04/src/Mesh.h @@ -0,0 +1,39 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_MESH_H +#define OPENGL_EXAMPLE_MESH_H + +#include +#include "Vertex.h" +#include "Tri.h" + +using namespace std; + + +class Mesh { +public: + vector pts; + vector tris; + bool drawWireframe = false; + bool drawOutline = false; + + Mesh(); + void loadData(const string& fileName); + void saveData(const string& fileName); + + void connectivityAlgo(); + void subDivLoop(); + void subDivLoop(int count); + void subDivEdgeMidpoint(); + + Mesh* copy(); + +}; + + +#endif //OPENGL_EXAMPLE_MESH_H diff --git a/hw04/src/Tri.cpp b/hw04/src/Tri.cpp new file mode 100644 index 0000000..1650e2c --- /dev/null +++ b/hw04/src/Tri.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Tri.h" +#include "Mesh.h" +#include + +using namespace std; + +Tri::Tri(Mesh* mesh) { + this->mesh = mesh; + + it[0] = -1; + it[1] = -1; + it[2] = -1; + ie[0] = -1; + ie[1] = -1; + ie[2] = -1; +} + +Tri::Tri(Mesh* mesh, int *i) : Tri(mesh) { +} + +Tri::Tri(Mesh* mesh, int i, int j, int k) : Tri(mesh) { + iv[0] = i; + iv[1] = j; + iv[2] = k; +} + +void Tri::Print() { + cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; + this->mesh->pts[iv[0]].Print(); + cout << " - "; + this->mesh->pts[iv[1]].Print(); + cout << " - "; + this->mesh->pts[iv[2]].Print(); + cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; +// pts[ie[0]].Print(); +// pts[ie[1]].Print(); +// pts[ie[2]].Print(); + + cout << endl; +} + +Tri *Tri::copy(Mesh* mesh) { + Tri *copy = new Tri(mesh); + for (int i = 0; i < 3; ++i) { + copy->iv[i] = this->iv[i]; + copy->ie[i] = this->ie[i]; + copy->it[i] = this->it[i]; + } + + return copy; +} diff --git a/hw04/src/Tri.h b/hw04/src/Tri.h new file mode 100644 index 0000000..f9eacd2 --- /dev/null +++ b/hw04/src/Tri.h @@ -0,0 +1,29 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_TRI_H +#define OPENGL_EXAMPLE_TRI_H + +class Mesh; + +class Tri { +public: + int iv[3]{}; // vertex indices + int it[3]{}; // adjacent triangle indices + int ie[3]{}; // edge vertex indices + Mesh *mesh; // parent mesh + + explicit Tri(Mesh* mesh); + explicit Tri(Mesh* mesh, int i[3]); + Tri(Mesh* mesh, int i, int j, int k); + void Print(); + + Tri* copy(Mesh* mesh); +}; + + +#endif //OPENGL_EXAMPLE_TRI_H diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw04/src/Mesh.cpp b/hw04/src/Mesh.cpp new file mode 100644 index 0000000..c3f444f --- /dev/null +++ b/hw04/src/Mesh.cpp @@ -0,0 +1,263 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include +#include +#include +#include "Mesh.h" +#include "Util.h" + +using namespace std; + +Mesh::Mesh() { + this->tris = {}; + this->pts = {}; +} + + +void Mesh::saveData(const string& fileName) { + ofstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + + for (auto vert : pts) { + file << "v\t" << vert.p[0] << "\t" << vert.p[1] << "\t" << vert.p[2] << endl; + } + + for (auto triag : tris) { + file << "f\t" << triag.iv[0]+1 << "\t" << triag.iv[1]+1 << "\t" << triag.iv[2]+1 << endl; + } + + file.close(); +} + +void Mesh::loadData(const string& fileName) { + ifstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + string key; + while( file){ + //getline( file, line); + file >> key; + if (key == "v") { + float x, y, z; + file >> x >> y >> z; + Vertex pVertex = *new Vertex(this, x, y, z); + pts.push_back(pVertex); + } else if (key == "f") { + int a, b, c; + file >> a >> b >> c; + Tri pTriangle = *new Tri(this, a-1, b-1, c-1); + tris.push_back(pTriangle); + } + } + file.close(); + + tris.pop_back(); +} + +void Mesh::connectivityAlgo() { + for (auto & pt : pts) { + pt.valence = 0; + } + + // Connectivity Algorithm + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + // Search for neighbour + for (int ti = 0; ti < tris.size(); ++ti) { + if (i == ti) continue; + Tri t = tris[ti]; + int count = 0; + int side = 0; + for (int x = 0; x < 3; ++x) { + bool hit = false; + for (int y : t.iv) { + if (triag.iv[x] == y) + hit = true; + } + if (hit) + count++; + else + side = x; + } + // if two points are the same, they are neighbours + if (count == 2) + triag.it[side] = ti; + } + + // increase valence for each vertex of triangle + ++pts[triag.iv[0]].valence; + ++pts[triag.iv[1]].valence; + ++pts[triag.iv[2]].valence; + + tris[i] = triag; + } +} + +void Mesh::subDivLoop(int count) { + for (int i = 0; i < count; ++i) { + this->subDivLoop(); + } +} + +void Mesh::subDivLoop() { + this->connectivityAlgo(); + + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + Vertex a = pts[triag.iv[0]]; + Vertex b = pts[triag.iv[1]]; + Vertex c = pts[triag.iv[2]]; + + for (int tI = 0; tI < 3; ++tI) { + Tri t = tris[triag.it[tI]]; + int otherEI = 0; + for (int j = 0; j < 3; ++j) { + if (t.it[j] == i) { + otherEI = j; + break; + } + } + if (i < triag.it[tI]) { + Vertex d = pts[t.iv[otherEI]]; + Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); + triag.ie[tI] = pts.size(); + pts.push_back(e); + } else { + // edge-mask already calculated + + triag.ie[tI] = t.ie[otherEI]; + } + } + + tris[i] = triag; + } + + for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta + int n = pts[i].valence; // n = valence of v_i + if (n < 3) continue; + float beta = Util::beta_n( n); +// cout << i << " " << n << " " << beta << " " <drawWireframe = this->drawWireframe; + copy->drawOutline = this->drawOutline; + + for (auto vert : this->pts) { + copy->pts.push_back(*vert.copy(copy)); + } + for (auto tri : this->tris) { + copy->tris.push_back(*tri.copy(copy)); + } + + + return copy; +} diff --git a/hw04/src/Mesh.h b/hw04/src/Mesh.h new file mode 100644 index 0000000..eb672dd --- /dev/null +++ b/hw04/src/Mesh.h @@ -0,0 +1,39 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_MESH_H +#define OPENGL_EXAMPLE_MESH_H + +#include +#include "Vertex.h" +#include "Tri.h" + +using namespace std; + + +class Mesh { +public: + vector pts; + vector tris; + bool drawWireframe = false; + bool drawOutline = false; + + Mesh(); + void loadData(const string& fileName); + void saveData(const string& fileName); + + void connectivityAlgo(); + void subDivLoop(); + void subDivLoop(int count); + void subDivEdgeMidpoint(); + + Mesh* copy(); + +}; + + +#endif //OPENGL_EXAMPLE_MESH_H diff --git a/hw04/src/Tri.cpp b/hw04/src/Tri.cpp new file mode 100644 index 0000000..1650e2c --- /dev/null +++ b/hw04/src/Tri.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Tri.h" +#include "Mesh.h" +#include + +using namespace std; + +Tri::Tri(Mesh* mesh) { + this->mesh = mesh; + + it[0] = -1; + it[1] = -1; + it[2] = -1; + ie[0] = -1; + ie[1] = -1; + ie[2] = -1; +} + +Tri::Tri(Mesh* mesh, int *i) : Tri(mesh) { +} + +Tri::Tri(Mesh* mesh, int i, int j, int k) : Tri(mesh) { + iv[0] = i; + iv[1] = j; + iv[2] = k; +} + +void Tri::Print() { + cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; + this->mesh->pts[iv[0]].Print(); + cout << " - "; + this->mesh->pts[iv[1]].Print(); + cout << " - "; + this->mesh->pts[iv[2]].Print(); + cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; +// pts[ie[0]].Print(); +// pts[ie[1]].Print(); +// pts[ie[2]].Print(); + + cout << endl; +} + +Tri *Tri::copy(Mesh* mesh) { + Tri *copy = new Tri(mesh); + for (int i = 0; i < 3; ++i) { + copy->iv[i] = this->iv[i]; + copy->ie[i] = this->ie[i]; + copy->it[i] = this->it[i]; + } + + return copy; +} diff --git a/hw04/src/Tri.h b/hw04/src/Tri.h new file mode 100644 index 0000000..f9eacd2 --- /dev/null +++ b/hw04/src/Tri.h @@ -0,0 +1,29 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_TRI_H +#define OPENGL_EXAMPLE_TRI_H + +class Mesh; + +class Tri { +public: + int iv[3]{}; // vertex indices + int it[3]{}; // adjacent triangle indices + int ie[3]{}; // edge vertex indices + Mesh *mesh; // parent mesh + + explicit Tri(Mesh* mesh); + explicit Tri(Mesh* mesh, int i[3]); + Tri(Mesh* mesh, int i, int j, int k); + void Print(); + + Tri* copy(Mesh* mesh); +}; + + +#endif //OPENGL_EXAMPLE_TRI_H diff --git a/hw04/src/Util.cpp b/hw04/src/Util.cpp new file mode 100644 index 0000000..9166092 --- /dev/null +++ b/hw04/src/Util.cpp @@ -0,0 +1,18 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Util.h" +#include + +#define PI 3.14159265358979323846 + +float Util::beta_n( int n) +{ + float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); + + return (8.0f/5.0f)*an - (3.0f/5.0f); +} \ No newline at end of file diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw04/src/Mesh.cpp b/hw04/src/Mesh.cpp new file mode 100644 index 0000000..c3f444f --- /dev/null +++ b/hw04/src/Mesh.cpp @@ -0,0 +1,263 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include +#include +#include +#include "Mesh.h" +#include "Util.h" + +using namespace std; + +Mesh::Mesh() { + this->tris = {}; + this->pts = {}; +} + + +void Mesh::saveData(const string& fileName) { + ofstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + + for (auto vert : pts) { + file << "v\t" << vert.p[0] << "\t" << vert.p[1] << "\t" << vert.p[2] << endl; + } + + for (auto triag : tris) { + file << "f\t" << triag.iv[0]+1 << "\t" << triag.iv[1]+1 << "\t" << triag.iv[2]+1 << endl; + } + + file.close(); +} + +void Mesh::loadData(const string& fileName) { + ifstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + string key; + while( file){ + //getline( file, line); + file >> key; + if (key == "v") { + float x, y, z; + file >> x >> y >> z; + Vertex pVertex = *new Vertex(this, x, y, z); + pts.push_back(pVertex); + } else if (key == "f") { + int a, b, c; + file >> a >> b >> c; + Tri pTriangle = *new Tri(this, a-1, b-1, c-1); + tris.push_back(pTriangle); + } + } + file.close(); + + tris.pop_back(); +} + +void Mesh::connectivityAlgo() { + for (auto & pt : pts) { + pt.valence = 0; + } + + // Connectivity Algorithm + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + // Search for neighbour + for (int ti = 0; ti < tris.size(); ++ti) { + if (i == ti) continue; + Tri t = tris[ti]; + int count = 0; + int side = 0; + for (int x = 0; x < 3; ++x) { + bool hit = false; + for (int y : t.iv) { + if (triag.iv[x] == y) + hit = true; + } + if (hit) + count++; + else + side = x; + } + // if two points are the same, they are neighbours + if (count == 2) + triag.it[side] = ti; + } + + // increase valence for each vertex of triangle + ++pts[triag.iv[0]].valence; + ++pts[triag.iv[1]].valence; + ++pts[triag.iv[2]].valence; + + tris[i] = triag; + } +} + +void Mesh::subDivLoop(int count) { + for (int i = 0; i < count; ++i) { + this->subDivLoop(); + } +} + +void Mesh::subDivLoop() { + this->connectivityAlgo(); + + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + Vertex a = pts[triag.iv[0]]; + Vertex b = pts[triag.iv[1]]; + Vertex c = pts[triag.iv[2]]; + + for (int tI = 0; tI < 3; ++tI) { + Tri t = tris[triag.it[tI]]; + int otherEI = 0; + for (int j = 0; j < 3; ++j) { + if (t.it[j] == i) { + otherEI = j; + break; + } + } + if (i < triag.it[tI]) { + Vertex d = pts[t.iv[otherEI]]; + Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); + triag.ie[tI] = pts.size(); + pts.push_back(e); + } else { + // edge-mask already calculated + + triag.ie[tI] = t.ie[otherEI]; + } + } + + tris[i] = triag; + } + + for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta + int n = pts[i].valence; // n = valence of v_i + if (n < 3) continue; + float beta = Util::beta_n( n); +// cout << i << " " << n << " " << beta << " " <drawWireframe = this->drawWireframe; + copy->drawOutline = this->drawOutline; + + for (auto vert : this->pts) { + copy->pts.push_back(*vert.copy(copy)); + } + for (auto tri : this->tris) { + copy->tris.push_back(*tri.copy(copy)); + } + + + return copy; +} diff --git a/hw04/src/Mesh.h b/hw04/src/Mesh.h new file mode 100644 index 0000000..eb672dd --- /dev/null +++ b/hw04/src/Mesh.h @@ -0,0 +1,39 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_MESH_H +#define OPENGL_EXAMPLE_MESH_H + +#include +#include "Vertex.h" +#include "Tri.h" + +using namespace std; + + +class Mesh { +public: + vector pts; + vector tris; + bool drawWireframe = false; + bool drawOutline = false; + + Mesh(); + void loadData(const string& fileName); + void saveData(const string& fileName); + + void connectivityAlgo(); + void subDivLoop(); + void subDivLoop(int count); + void subDivEdgeMidpoint(); + + Mesh* copy(); + +}; + + +#endif //OPENGL_EXAMPLE_MESH_H diff --git a/hw04/src/Tri.cpp b/hw04/src/Tri.cpp new file mode 100644 index 0000000..1650e2c --- /dev/null +++ b/hw04/src/Tri.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Tri.h" +#include "Mesh.h" +#include + +using namespace std; + +Tri::Tri(Mesh* mesh) { + this->mesh = mesh; + + it[0] = -1; + it[1] = -1; + it[2] = -1; + ie[0] = -1; + ie[1] = -1; + ie[2] = -1; +} + +Tri::Tri(Mesh* mesh, int *i) : Tri(mesh) { +} + +Tri::Tri(Mesh* mesh, int i, int j, int k) : Tri(mesh) { + iv[0] = i; + iv[1] = j; + iv[2] = k; +} + +void Tri::Print() { + cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; + this->mesh->pts[iv[0]].Print(); + cout << " - "; + this->mesh->pts[iv[1]].Print(); + cout << " - "; + this->mesh->pts[iv[2]].Print(); + cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; +// pts[ie[0]].Print(); +// pts[ie[1]].Print(); +// pts[ie[2]].Print(); + + cout << endl; +} + +Tri *Tri::copy(Mesh* mesh) { + Tri *copy = new Tri(mesh); + for (int i = 0; i < 3; ++i) { + copy->iv[i] = this->iv[i]; + copy->ie[i] = this->ie[i]; + copy->it[i] = this->it[i]; + } + + return copy; +} diff --git a/hw04/src/Tri.h b/hw04/src/Tri.h new file mode 100644 index 0000000..f9eacd2 --- /dev/null +++ b/hw04/src/Tri.h @@ -0,0 +1,29 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_TRI_H +#define OPENGL_EXAMPLE_TRI_H + +class Mesh; + +class Tri { +public: + int iv[3]{}; // vertex indices + int it[3]{}; // adjacent triangle indices + int ie[3]{}; // edge vertex indices + Mesh *mesh; // parent mesh + + explicit Tri(Mesh* mesh); + explicit Tri(Mesh* mesh, int i[3]); + Tri(Mesh* mesh, int i, int j, int k); + void Print(); + + Tri* copy(Mesh* mesh); +}; + + +#endif //OPENGL_EXAMPLE_TRI_H diff --git a/hw04/src/Util.cpp b/hw04/src/Util.cpp new file mode 100644 index 0000000..9166092 --- /dev/null +++ b/hw04/src/Util.cpp @@ -0,0 +1,18 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Util.h" +#include + +#define PI 3.14159265358979323846 + +float Util::beta_n( int n) +{ + float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); + + return (8.0f/5.0f)*an - (3.0f/5.0f); +} \ No newline at end of file diff --git a/hw04/src/Util.h b/hw04/src/Util.h new file mode 100644 index 0000000..6b2633a --- /dev/null +++ b/hw04/src/Util.h @@ -0,0 +1,19 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_UTIL_H +#define OPENGL_EXAMPLE_UTIL_H + + +class Util { +public: + static float beta_n( int n); + +}; + + +#endif //OPENGL_EXAMPLE_UTIL_H diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw04/src/Mesh.cpp b/hw04/src/Mesh.cpp new file mode 100644 index 0000000..c3f444f --- /dev/null +++ b/hw04/src/Mesh.cpp @@ -0,0 +1,263 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include +#include +#include +#include "Mesh.h" +#include "Util.h" + +using namespace std; + +Mesh::Mesh() { + this->tris = {}; + this->pts = {}; +} + + +void Mesh::saveData(const string& fileName) { + ofstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + + for (auto vert : pts) { + file << "v\t" << vert.p[0] << "\t" << vert.p[1] << "\t" << vert.p[2] << endl; + } + + for (auto triag : tris) { + file << "f\t" << triag.iv[0]+1 << "\t" << triag.iv[1]+1 << "\t" << triag.iv[2]+1 << endl; + } + + file.close(); +} + +void Mesh::loadData(const string& fileName) { + ifstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + string key; + while( file){ + //getline( file, line); + file >> key; + if (key == "v") { + float x, y, z; + file >> x >> y >> z; + Vertex pVertex = *new Vertex(this, x, y, z); + pts.push_back(pVertex); + } else if (key == "f") { + int a, b, c; + file >> a >> b >> c; + Tri pTriangle = *new Tri(this, a-1, b-1, c-1); + tris.push_back(pTriangle); + } + } + file.close(); + + tris.pop_back(); +} + +void Mesh::connectivityAlgo() { + for (auto & pt : pts) { + pt.valence = 0; + } + + // Connectivity Algorithm + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + // Search for neighbour + for (int ti = 0; ti < tris.size(); ++ti) { + if (i == ti) continue; + Tri t = tris[ti]; + int count = 0; + int side = 0; + for (int x = 0; x < 3; ++x) { + bool hit = false; + for (int y : t.iv) { + if (triag.iv[x] == y) + hit = true; + } + if (hit) + count++; + else + side = x; + } + // if two points are the same, they are neighbours + if (count == 2) + triag.it[side] = ti; + } + + // increase valence for each vertex of triangle + ++pts[triag.iv[0]].valence; + ++pts[triag.iv[1]].valence; + ++pts[triag.iv[2]].valence; + + tris[i] = triag; + } +} + +void Mesh::subDivLoop(int count) { + for (int i = 0; i < count; ++i) { + this->subDivLoop(); + } +} + +void Mesh::subDivLoop() { + this->connectivityAlgo(); + + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + Vertex a = pts[triag.iv[0]]; + Vertex b = pts[triag.iv[1]]; + Vertex c = pts[triag.iv[2]]; + + for (int tI = 0; tI < 3; ++tI) { + Tri t = tris[triag.it[tI]]; + int otherEI = 0; + for (int j = 0; j < 3; ++j) { + if (t.it[j] == i) { + otherEI = j; + break; + } + } + if (i < triag.it[tI]) { + Vertex d = pts[t.iv[otherEI]]; + Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); + triag.ie[tI] = pts.size(); + pts.push_back(e); + } else { + // edge-mask already calculated + + triag.ie[tI] = t.ie[otherEI]; + } + } + + tris[i] = triag; + } + + for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta + int n = pts[i].valence; // n = valence of v_i + if (n < 3) continue; + float beta = Util::beta_n( n); +// cout << i << " " << n << " " << beta << " " <drawWireframe = this->drawWireframe; + copy->drawOutline = this->drawOutline; + + for (auto vert : this->pts) { + copy->pts.push_back(*vert.copy(copy)); + } + for (auto tri : this->tris) { + copy->tris.push_back(*tri.copy(copy)); + } + + + return copy; +} diff --git a/hw04/src/Mesh.h b/hw04/src/Mesh.h new file mode 100644 index 0000000..eb672dd --- /dev/null +++ b/hw04/src/Mesh.h @@ -0,0 +1,39 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_MESH_H +#define OPENGL_EXAMPLE_MESH_H + +#include +#include "Vertex.h" +#include "Tri.h" + +using namespace std; + + +class Mesh { +public: + vector pts; + vector tris; + bool drawWireframe = false; + bool drawOutline = false; + + Mesh(); + void loadData(const string& fileName); + void saveData(const string& fileName); + + void connectivityAlgo(); + void subDivLoop(); + void subDivLoop(int count); + void subDivEdgeMidpoint(); + + Mesh* copy(); + +}; + + +#endif //OPENGL_EXAMPLE_MESH_H diff --git a/hw04/src/Tri.cpp b/hw04/src/Tri.cpp new file mode 100644 index 0000000..1650e2c --- /dev/null +++ b/hw04/src/Tri.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Tri.h" +#include "Mesh.h" +#include + +using namespace std; + +Tri::Tri(Mesh* mesh) { + this->mesh = mesh; + + it[0] = -1; + it[1] = -1; + it[2] = -1; + ie[0] = -1; + ie[1] = -1; + ie[2] = -1; +} + +Tri::Tri(Mesh* mesh, int *i) : Tri(mesh) { +} + +Tri::Tri(Mesh* mesh, int i, int j, int k) : Tri(mesh) { + iv[0] = i; + iv[1] = j; + iv[2] = k; +} + +void Tri::Print() { + cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; + this->mesh->pts[iv[0]].Print(); + cout << " - "; + this->mesh->pts[iv[1]].Print(); + cout << " - "; + this->mesh->pts[iv[2]].Print(); + cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; +// pts[ie[0]].Print(); +// pts[ie[1]].Print(); +// pts[ie[2]].Print(); + + cout << endl; +} + +Tri *Tri::copy(Mesh* mesh) { + Tri *copy = new Tri(mesh); + for (int i = 0; i < 3; ++i) { + copy->iv[i] = this->iv[i]; + copy->ie[i] = this->ie[i]; + copy->it[i] = this->it[i]; + } + + return copy; +} diff --git a/hw04/src/Tri.h b/hw04/src/Tri.h new file mode 100644 index 0000000..f9eacd2 --- /dev/null +++ b/hw04/src/Tri.h @@ -0,0 +1,29 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_TRI_H +#define OPENGL_EXAMPLE_TRI_H + +class Mesh; + +class Tri { +public: + int iv[3]{}; // vertex indices + int it[3]{}; // adjacent triangle indices + int ie[3]{}; // edge vertex indices + Mesh *mesh; // parent mesh + + explicit Tri(Mesh* mesh); + explicit Tri(Mesh* mesh, int i[3]); + Tri(Mesh* mesh, int i, int j, int k); + void Print(); + + Tri* copy(Mesh* mesh); +}; + + +#endif //OPENGL_EXAMPLE_TRI_H diff --git a/hw04/src/Util.cpp b/hw04/src/Util.cpp new file mode 100644 index 0000000..9166092 --- /dev/null +++ b/hw04/src/Util.cpp @@ -0,0 +1,18 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Util.h" +#include + +#define PI 3.14159265358979323846 + +float Util::beta_n( int n) +{ + float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); + + return (8.0f/5.0f)*an - (3.0f/5.0f); +} \ No newline at end of file diff --git a/hw04/src/Util.h b/hw04/src/Util.h new file mode 100644 index 0000000..6b2633a --- /dev/null +++ b/hw04/src/Util.h @@ -0,0 +1,19 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_UTIL_H +#define OPENGL_EXAMPLE_UTIL_H + + +class Util { +public: + static float beta_n( int n); + +}; + + +#endif //OPENGL_EXAMPLE_UTIL_H diff --git a/hw04/src/Vertex.cpp b/hw04/src/Vertex.cpp new file mode 100644 index 0000000..9f294f8 --- /dev/null +++ b/hw04/src/Vertex.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include "Vertex.h" +using namespace std; + +Vertex::Vertex() { // empty constructor + + this->valence = 0; +} + +Vertex::Vertex(Mesh* mesh) : Vertex() { + this->mesh = mesh; +} + +Vertex::Vertex(Mesh* mesh, float x, float y, float z) : Vertex(mesh) { // constructor with initialization + p[0] = x; + p[1] = y; + p[2] = z; +} + +Vertex::Vertex(Mesh* mesh, float *point) : Vertex(mesh) { + copy_n(point, 3, p); +} + +Vertex operator+( Vertex a, Vertex b) { // add pts or vectors + return *new Vertex(a.mesh, a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); +} +Vertex operator-( Vertex a, Vertex b) { // subtract pts or vectors + return *new Vertex(a.mesh, a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); +} +Vertex operator*( float a, Vertex b) { // product between scalar and vector + return *new Vertex(b.mesh, a*b.p[0], a*b.p[1], a*b.p[2]); +} +float operator*( Vertex a, Vertex b) { // scalar product + return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; +} +Vertex operator%( Vertex a, Vertex b) { // cross product + return *new Vertex(a.mesh, a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); +} +bool operator==(Vertex a, Vertex b) { // check if coords are the same + return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); +} +void Vertex::operator*=( float a) { + this->p[0] *= a; + this->p[1] *= a; + this->p[2] *= a; +} +void Vertex::operator+=( Vertex a) { + this->p[0] += a.p[0]; + this->p[1] += a.p[1]; + this->p[2] += a.p[2]; +} + +Vertex *Vertex::copy(Mesh *mesh) { + auto *copy = new Vertex(mesh); + copy->valence = this->valence; + for (int i = 0; i < 3; ++i) { + copy->p[i] = this->p[i]; + } + + return copy; +} diff --git a/hw03/oglwidget.cpp b/hw03/oglwidget.cpp index d7c5f71..b225032 100644 --- a/hw03/oglwidget.cpp +++ b/hw03/oglwidget.cpp @@ -270,11 +270,11 @@ for (auto vert : points) { if (vert.isNext) { glEnd(); - glLineWidth(2*abs(vert._z)); +// glLineWidth(2*abs(vert._z)); glColor3f(1.0f, 0.0f, 0.0f); glBegin( GL_LINE_STRIP); } - glVertex3f(vert._x, vert._y, vert._z); + glVertex3f(vert._x, vert._y + vert._z, 0); } glEnd(); } @@ -383,10 +383,10 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects - glRotated( alpha, 0, 3, 1); // continuous rotation - alpha += 2; +// glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( 2.5, 1.8, 2.0); // scale objects +// glRotated( alpha, 0, 3, 1); // continuous rotation +// alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b SetMaterialColor( 1, 0, .2, .2); // front color is red diff --git a/hw04/CMakeLists.txt b/hw04/CMakeLists.txt index 4d596e0..4c6060f 100644 --- a/hw04/CMakeLists.txt +++ b/hw04/CMakeLists.txt @@ -18,7 +18,7 @@ mainwindow.cpp mainwindow.h oglwidget.cpp - oglwidget.h) + oglwidget.h src/Vertex.cpp src/Vertex.h src/Tri.cpp src/Tri.h src/Mesh.cpp src/Mesh.h src/Util.cpp src/Util.h) if (NOT CMAKE_PREFIX_PATH) message(WARNING "CMAKE_PREFIX_PATH is not defined, you may need to set it " diff --git a/hw04/mainwindow.cpp b/hw04/mainwindow.cpp index ff258c4..43656fd 100644 --- a/hw04/mainwindow.cpp +++ b/hw04/mainwindow.cpp @@ -9,6 +9,13 @@ ui(new Ui::MainWindow) { ui->setupUi(this); + + connect(ui->parentSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(parentSubdiv(int))); + connect(ui->childSpinBox, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(childSubdiv(int))); + connect(ui->drawWireframe, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawWireframe(int))); + connect(ui->drawOutline, SIGNAL(stateChanged(int)), ui->glwidget, SLOT(drawOutline(int))); + + connect(ui->scale, SIGNAL(valueChanged(int)), ui->glwidget, SLOT(setScale(int))); } MainWindow::~MainWindow() diff --git a/hw04/mainwindow.ui b/hw04/mainwindow.ui index 5e1745e..9f9248a 100644 --- a/hw04/mainwindow.ui +++ b/hw04/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 548 - 415 + 1044 + 718 @@ -25,6 +25,107 @@ + + + + + + + + + 0 + 0 + + + + Parent Subdivisons + + + + + + + 10 + + + + + + + Draw Parent + + + + + + + + + + + + 0 + 0 + + + + Child Subdivisons + + + + + + + 1 + + + 10 + + + + + + + Draw Wireframe + + + + + + + + + + + Scale + + + + + + + 10 + + + 100 + + + 20 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + @@ -32,7 +133,7 @@ 0 0 - 548 + 1044 21 diff --git a/hw04/oglwidget.cpp b/hw04/oglwidget.cpp index 0078d70..3c2f9bb 100644 --- a/hw04/oglwidget.cpp +++ b/hw04/oglwidget.cpp @@ -2,10 +2,7 @@ // All rights reserved. #include "oglwidget.h" -#include -#include -#include -#include +#include "src/Mesh.h" #include #include @@ -14,437 +11,60 @@ static double alpha = 45.0; // rotation angle -class Vertex{ -public: - float p[3]; // coordinates +Mesh *originalMesh; +Mesh *parentMesh; +Mesh *childMesh; - Vertex(); - Vertex( float point[3]); - Vertex( float x, float y, float z); - void Print() { - cout << p[0] << " " << p[1] << " " << p[2] << endl; +bool childWireframe = false; +bool drawParent = false; +int parentSubdivCount = 0; +int childSubdivCount = 1; +float scale = 2.0f; + +void drawMesh(Mesh mesh) { + glPolygonMode(GL_FRONT_AND_BACK , mesh.drawWireframe ? GL_LINE : GL_FILL); + if (mesh.drawWireframe) + glDisable(GL_CULL_FACE); + else + glEnable(GL_CULL_FACE); + + glBegin( GL_TRIANGLES); + for (auto tri : mesh.tris) { + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; + Vertex nvec = ((b-a)%(c-a)); + + glNormal3fv(nvec.p); + + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); + } - void operator*=( float a); - void operator+=( Vertex a); - // print coordinates on screen + glEnd(); + if (!mesh.drawOutline) return; -}; + for (auto tri : mesh.tris) { + glLineWidth(3); + glBegin( GL_LINE_STRIP); + Vertex a = mesh.pts[tri.iv[0]]; + Vertex b = mesh.pts[tri.iv[1]]; + Vertex c = mesh.pts[tri.iv[2]]; -Vertex::Vertex(){}; // empty constructor + glVertex3fv(a.p); + glVertex3fv(b.p); + glVertex3fv(c.p); -Vertex::Vertex(float x, float y, float z){ // constructor with initialization - p[0] = x; - p[1] = y; - p[2] = z; -} - -Vertex::Vertex(float *point) { - copy_n(point, 3, p); -} - -Vertex operator+( Vertex a, Vertex b) // add pts or vectors -{ - return *new Vertex(a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); -} -Vertex operator-( Vertex a, Vertex b)// subtract pts or vectors -{ - return *new Vertex(a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); -} -Vertex operator*( float a, Vertex b) // product between scalar and vector -{ - return *new Vertex(a*b.p[0], a*b.p[1], a*b.p[2]); -} -float operator*( Vertex a, Vertex b) // scalar product -{ - return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; -} -Vertex operator%( Vertex a, Vertex b) // cross product -{ - return *new Vertex(a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); -} -bool operator==(Vertex a, Vertex b) // check if coords are the same -{ - return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); -} -void Vertex::operator*=( float a) -{ - this->p[0] *= a; - this->p[1] *= a; - this->p[2] *= a; -} -void Vertex::operator+=( Vertex a) -{ - this->p[0] += a.p[0]; - this->p[1] += a.p[1]; - this->p[2] += a.p[2]; -} - -class Tri -{ -public: - int iv[3]; // vertex indices - int it[3]; // adjacent triangle indices - int ie[3]; // edge vertex indices - Tri(); - Tri( int i[3]); - Tri( int i, int j, int k); - void Print(); -}; - -float beta_n( int n); -void subDivEdgeMidpoint(); - -void saveData(); - -void subDivLoop(); - -int matchEdge(Tri tri, int vertex, int vertex1); - -void connectivityAlgo(); - -Tri::Tri() { - it[0] = -1; - it[1] = -1; - it[2] = -1; - ie[0] = -1; - ie[1] = -1; - ie[2] = -1; -} - -Tri::Tri(int *i) { - new (this) Tri(); - -} - -Tri::Tri(int i, int j, int k) { - new (this) Tri(); - - iv[0] = i; - iv[1] = j; - iv[2] = k; -} - - -vector pts; -vector valences; // valence list (no. of triangles for every point -vector tris; - -void Tri::Print() { - cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; - cout << valences[iv[0]] << "x "; - pts[iv[0]].Print(); - cout << " - " << valences[iv[1]] << "x "; - pts[iv[1]].Print(); - cout << " - " << valences[iv[2]] << "x "; - pts[iv[2]].Print(); - cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; -// pts[ie[0]].Print(); -// pts[ie[1]].Print(); -// pts[ie[2]].Print(); - - cout << endl; -} - -float beta_n( int n) -{ - float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); - - return (8.0f/5.0f)*an - (3.0f/5.0f); -} - - -void loadData() -{ - string fname = R"(C:\CLionProjects\cg\hw04\mesh1.obj)"; - ifstream file( fname); - if (!file){ - cout << "error opening file" << endl; - return; - } - string key; - while( file){ - //getline( file, line); - file >> key; - if (key == "v") { - float x, y, z; - file >> x >> y >> z; - Vertex pVertex = *new Vertex(x, y, z); - pts.push_back(pVertex); - valences.push_back(0); - } else if (key == "f") { - int a, b, c; - file >> a >> b >> c; - Tri pTriangle = *new Tri(a-1, b-1, c-1); - tris.push_back(pTriangle); - } - } - file.close(); - - tris.pop_back(); - -// subDivEdgeMidpoint(); -// subDivEdgeMidpoint(); - - - -// for (auto triag : tris) { -// triag.Print(); -// } - -} - -void connectivityAlgo() { - for (int i = 0; i < pts.size(); ++i) { - valences[i] = 0; - } - - // Connectivity Algorithm - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - // Search for neighbour - for (int ti = 0; ti < tris.size(); ++ti) { - if (i == ti) continue; - Tri t = tris[ti]; - int count = 0; - int side = 0; - for (int x = 0; x < 3; ++x) { - bool hit = false; - for (int y : t.iv) { - if (triag.iv[x] == y) - hit = true; - } - if (hit) - count++; - else - side = x; - } - // if two points are the same, they are neighbours - if (count == 2) - triag.it[side] = ti; - } - - // increase valence for each vertex of triangle - valences[triag.iv[0]]++; - valences[triag.iv[1]]++; - valences[triag.iv[2]]++; - - tris[i] = triag; - } -} - -void subDivLoop() { - - for (int i = 0; i < tris.size(); ++i) { - Tri triag = tris[i]; - Vertex a = pts[triag.iv[0]]; - Vertex b = pts[triag.iv[1]]; - Vertex c = pts[triag.iv[2]]; - - for (int tI = 0; tI < 3; ++tI) { - Tri t = tris[triag.it[tI]]; - int otherEI = 0; - for (int j = 0; j < 3; ++j) { - if (t.it[j] == i) { - otherEI = j; - break; - } - } - if (i < triag.it[tI]) { - Vertex d = pts[t.iv[otherEI]]; - Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); - triag.ie[tI] = pts.size(); - pts.push_back(e); - valences.push_back(0); - } else { - // edge-mask already calculated - - triag.ie[tI] = t.ie[otherEI]; - } - } - - tris[i] = triag; - } - - for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta - int n = valences[i]; // n = valence of v_i - if (n < 3) continue; - float beta = beta_n( n); - cout << i << " " << n << " " << beta << " " <loadData(R"(C:\CLionProjects\cg\hw04\mesh1.obj)"); - connectivityAlgo(); - subDivLoop(); + OGLWidget::childSubdiv(1); - saveData(); +// childMesh->saveData( R"(C:\CLionProjects\cg\hw04\test2.obj)"); + + OGLWidget::parentSubdiv(0); + +} + +void update() { } @@ -557,13 +183,13 @@ // draw the scene glMatrixMode( GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix - glTranslated( 0 ,0 ,-10.0); // Move 10 units backwards in z, since camera is at origin - glScaled( 2.0, 2.0, 2.0); // scale objects + glTranslated( 0 ,-5 ,-10.0); // Move 10 units backwards in z, since camera is at origin + glScaled( scale, scale, scale); // scale objects glRotated( alpha, 0, 3, 1); // continuous rotation alpha += 2; // define color: 1=front, 2=back, 3=both, followed by r, g, and b - SetMaterialColor( 1, 0, .2, .2); // front color is red + SetMaterialColor( 1, 1.0, .2, .2); // front color is red SetMaterialColor( 2, 0.2, 0.2, 1.0); // back color is blue // draw a cylinder with default resolution @@ -579,3 +205,33 @@ glViewport(0,0,w,h); } +void OGLWidget::parentSubdiv(int i) { + parentSubdivCount = i; + + parentMesh = originalMesh->copy(); + parentMesh->drawWireframe = true; + parentMesh->subDivLoop(parentSubdivCount); +} + +void OGLWidget::childSubdiv(int i) { + childSubdivCount = i; + + childMesh = originalMesh->copy(); + childMesh->drawWireframe = childWireframe; + childMesh->subDivLoop(childSubdivCount); +} + +void OGLWidget::drawOutline(int i) { + drawParent = i == 2; +} + +void OGLWidget::drawWireframe(int i) { + childWireframe = i == 2; + childMesh->drawWireframe = childWireframe; +} + +void OGLWidget::setScale(int i) { + + scale = float(i) / 10.0f; +} + diff --git a/hw04/oglwidget.h b/hw04/oglwidget.h index a536f6a..91200f7 100644 --- a/hw04/oglwidget.h +++ b/hw04/oglwidget.h @@ -19,6 +19,11 @@ public slots: void stepAnimation(); + void parentSubdiv(int i); + void childSubdiv(int i); + void drawOutline(int i); + void drawWireframe(int i); + void setScale(int i); protected: void initializeGL(); diff --git a/hw04/src/Mesh.cpp b/hw04/src/Mesh.cpp new file mode 100644 index 0000000..c3f444f --- /dev/null +++ b/hw04/src/Mesh.cpp @@ -0,0 +1,263 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include +#include +#include +#include "Mesh.h" +#include "Util.h" + +using namespace std; + +Mesh::Mesh() { + this->tris = {}; + this->pts = {}; +} + + +void Mesh::saveData(const string& fileName) { + ofstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + + for (auto vert : pts) { + file << "v\t" << vert.p[0] << "\t" << vert.p[1] << "\t" << vert.p[2] << endl; + } + + for (auto triag : tris) { + file << "f\t" << triag.iv[0]+1 << "\t" << triag.iv[1]+1 << "\t" << triag.iv[2]+1 << endl; + } + + file.close(); +} + +void Mesh::loadData(const string& fileName) { + ifstream file( fileName); + if (!file){ + cout << "error opening file" << endl; + return; + } + string key; + while( file){ + //getline( file, line); + file >> key; + if (key == "v") { + float x, y, z; + file >> x >> y >> z; + Vertex pVertex = *new Vertex(this, x, y, z); + pts.push_back(pVertex); + } else if (key == "f") { + int a, b, c; + file >> a >> b >> c; + Tri pTriangle = *new Tri(this, a-1, b-1, c-1); + tris.push_back(pTriangle); + } + } + file.close(); + + tris.pop_back(); +} + +void Mesh::connectivityAlgo() { + for (auto & pt : pts) { + pt.valence = 0; + } + + // Connectivity Algorithm + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + // Search for neighbour + for (int ti = 0; ti < tris.size(); ++ti) { + if (i == ti) continue; + Tri t = tris[ti]; + int count = 0; + int side = 0; + for (int x = 0; x < 3; ++x) { + bool hit = false; + for (int y : t.iv) { + if (triag.iv[x] == y) + hit = true; + } + if (hit) + count++; + else + side = x; + } + // if two points are the same, they are neighbours + if (count == 2) + triag.it[side] = ti; + } + + // increase valence for each vertex of triangle + ++pts[triag.iv[0]].valence; + ++pts[triag.iv[1]].valence; + ++pts[triag.iv[2]].valence; + + tris[i] = triag; + } +} + +void Mesh::subDivLoop(int count) { + for (int i = 0; i < count; ++i) { + this->subDivLoop(); + } +} + +void Mesh::subDivLoop() { + this->connectivityAlgo(); + + for (int i = 0; i < tris.size(); ++i) { + Tri triag = tris[i]; + Vertex a = pts[triag.iv[0]]; + Vertex b = pts[triag.iv[1]]; + Vertex c = pts[triag.iv[2]]; + + for (int tI = 0; tI < 3; ++tI) { + Tri t = tris[triag.it[tI]]; + int otherEI = 0; + for (int j = 0; j < 3; ++j) { + if (t.it[j] == i) { + otherEI = j; + break; + } + } + if (i < triag.it[tI]) { + Vertex d = pts[t.iv[otherEI]]; + Vertex e = (1.0f/8.0f)*((((tI == 1 || tI == 2) ? 3.0f : 1.0f)*a) + (((tI == 0 || tI == 2) ? 3.0f : 1.0f)*b) + (((tI == 1 || tI == 0) ? 3.0f : 1.0f)*c) + d); + triag.ie[tI] = pts.size(); + pts.push_back(e); + } else { + // edge-mask already calculated + + triag.ie[tI] = t.ie[otherEI]; + } + } + + tris[i] = triag; + } + + for( int i=0; i< pts.size(); i++){ // multiply every vertex with beta + int n = pts[i].valence; // n = valence of v_i + if (n < 3) continue; + float beta = Util::beta_n( n); +// cout << i << " " << n << " " << beta << " " <drawWireframe = this->drawWireframe; + copy->drawOutline = this->drawOutline; + + for (auto vert : this->pts) { + copy->pts.push_back(*vert.copy(copy)); + } + for (auto tri : this->tris) { + copy->tris.push_back(*tri.copy(copy)); + } + + + return copy; +} diff --git a/hw04/src/Mesh.h b/hw04/src/Mesh.h new file mode 100644 index 0000000..eb672dd --- /dev/null +++ b/hw04/src/Mesh.h @@ -0,0 +1,39 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_MESH_H +#define OPENGL_EXAMPLE_MESH_H + +#include +#include "Vertex.h" +#include "Tri.h" + +using namespace std; + + +class Mesh { +public: + vector pts; + vector tris; + bool drawWireframe = false; + bool drawOutline = false; + + Mesh(); + void loadData(const string& fileName); + void saveData(const string& fileName); + + void connectivityAlgo(); + void subDivLoop(); + void subDivLoop(int count); + void subDivEdgeMidpoint(); + + Mesh* copy(); + +}; + + +#endif //OPENGL_EXAMPLE_MESH_H diff --git a/hw04/src/Tri.cpp b/hw04/src/Tri.cpp new file mode 100644 index 0000000..1650e2c --- /dev/null +++ b/hw04/src/Tri.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Tri.h" +#include "Mesh.h" +#include + +using namespace std; + +Tri::Tri(Mesh* mesh) { + this->mesh = mesh; + + it[0] = -1; + it[1] = -1; + it[2] = -1; + ie[0] = -1; + ie[1] = -1; + ie[2] = -1; +} + +Tri::Tri(Mesh* mesh, int *i) : Tri(mesh) { +} + +Tri::Tri(Mesh* mesh, int i, int j, int k) : Tri(mesh) { + iv[0] = i; + iv[1] = j; + iv[2] = k; +} + +void Tri::Print() { + cout << "Tri:" << endl << " neighbour: " << it[0] << " " << it[1] << " " << it[2] << endl << " - "; + this->mesh->pts[iv[0]].Print(); + cout << " - "; + this->mesh->pts[iv[1]].Print(); + cout << " - "; + this->mesh->pts[iv[2]].Print(); + cout << endl << "Edges: " << ie[0] << " " << ie[1] << " " << ie[2] << endl; +// pts[ie[0]].Print(); +// pts[ie[1]].Print(); +// pts[ie[2]].Print(); + + cout << endl; +} + +Tri *Tri::copy(Mesh* mesh) { + Tri *copy = new Tri(mesh); + for (int i = 0; i < 3; ++i) { + copy->iv[i] = this->iv[i]; + copy->ie[i] = this->ie[i]; + copy->it[i] = this->it[i]; + } + + return copy; +} diff --git a/hw04/src/Tri.h b/hw04/src/Tri.h new file mode 100644 index 0000000..f9eacd2 --- /dev/null +++ b/hw04/src/Tri.h @@ -0,0 +1,29 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_TRI_H +#define OPENGL_EXAMPLE_TRI_H + +class Mesh; + +class Tri { +public: + int iv[3]{}; // vertex indices + int it[3]{}; // adjacent triangle indices + int ie[3]{}; // edge vertex indices + Mesh *mesh; // parent mesh + + explicit Tri(Mesh* mesh); + explicit Tri(Mesh* mesh, int i[3]); + Tri(Mesh* mesh, int i, int j, int k); + void Print(); + + Tri* copy(Mesh* mesh); +}; + + +#endif //OPENGL_EXAMPLE_TRI_H diff --git a/hw04/src/Util.cpp b/hw04/src/Util.cpp new file mode 100644 index 0000000..9166092 --- /dev/null +++ b/hw04/src/Util.cpp @@ -0,0 +1,18 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include "Util.h" +#include + +#define PI 3.14159265358979323846 + +float Util::beta_n( int n) +{ + float an = (3.0f/8.0f) + float(pow((3.0f/8.0f) + (1.0f/4.0f)*cos(2.0f*PI/n), 2)); + + return (8.0f/5.0f)*an - (3.0f/5.0f); +} \ No newline at end of file diff --git a/hw04/src/Util.h b/hw04/src/Util.h new file mode 100644 index 0000000..6b2633a --- /dev/null +++ b/hw04/src/Util.h @@ -0,0 +1,19 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_UTIL_H +#define OPENGL_EXAMPLE_UTIL_H + + +class Util { +public: + static float beta_n( int n); + +}; + + +#endif //OPENGL_EXAMPLE_UTIL_H diff --git a/hw04/src/Vertex.cpp b/hw04/src/Vertex.cpp new file mode 100644 index 0000000..9f294f8 --- /dev/null +++ b/hw04/src/Vertex.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#include +#include "Vertex.h" +using namespace std; + +Vertex::Vertex() { // empty constructor + + this->valence = 0; +} + +Vertex::Vertex(Mesh* mesh) : Vertex() { + this->mesh = mesh; +} + +Vertex::Vertex(Mesh* mesh, float x, float y, float z) : Vertex(mesh) { // constructor with initialization + p[0] = x; + p[1] = y; + p[2] = z; +} + +Vertex::Vertex(Mesh* mesh, float *point) : Vertex(mesh) { + copy_n(point, 3, p); +} + +Vertex operator+( Vertex a, Vertex b) { // add pts or vectors + return *new Vertex(a.mesh, a.p[0] + b.p[0], a.p[1] + b.p[1],a.p[2] + b.p[2]); +} +Vertex operator-( Vertex a, Vertex b) { // subtract pts or vectors + return *new Vertex(a.mesh, a.p[0] - b.p[0], a.p[1] - b.p[1],a.p[2] - b.p[2]); +} +Vertex operator*( float a, Vertex b) { // product between scalar and vector + return *new Vertex(b.mesh, a*b.p[0], a*b.p[1], a*b.p[2]); +} +float operator*( Vertex a, Vertex b) { // scalar product + return a.p[0] * b.p[0] + a.p[1] * b.p[1] + a.p[2] * b.p[2]; +} +Vertex operator%( Vertex a, Vertex b) { // cross product + return *new Vertex(a.mesh, a.p[1]*b.p[2] - a.p[2]*b.p[1], a.p[2]*b.p[0] - a.p[0]*b.p[2], a.p[0]*b.p[1] - a.p[1]*b.p[0]); +} +bool operator==(Vertex a, Vertex b) { // check if coords are the same + return (a.p[0] == b.p[0]) && (a.p[1] == b.p[1]) && (a.p[2] == b.p[2]); +} +void Vertex::operator*=( float a) { + this->p[0] *= a; + this->p[1] *= a; + this->p[2] *= a; +} +void Vertex::operator+=( Vertex a) { + this->p[0] += a.p[0]; + this->p[1] += a.p[1]; + this->p[2] += a.p[2]; +} + +Vertex *Vertex::copy(Mesh *mesh) { + auto *copy = new Vertex(mesh); + copy->valence = this->valence; + for (int i = 0; i < 3; ++i) { + copy->p[i] = this->p[i]; + } + + return copy; +} diff --git a/hw04/src/Vertex.h b/hw04/src/Vertex.h new file mode 100644 index 0000000..3d217b3 --- /dev/null +++ b/hw04/src/Vertex.h @@ -0,0 +1,45 @@ +// Copyright (c) 2021. Pascal Syma and Antonio Martinez Casadesus . +// All rights reserved. + +// +// Created by Pascal on 17.05.2021. +// + +#ifndef OPENGL_EXAMPLE_VERTEX_H +#define OPENGL_EXAMPLE_VERTEX_H + +#include +class Mesh; + +using namespace std; + +class Vertex { +public: + + float p[3]{}; // coordinates + Mesh *mesh{}; // parent mesh + int valence; + + Vertex(); + explicit Vertex(Mesh* mesh); + explicit Vertex(Mesh* mesh, float point[3]); + Vertex(Mesh* mesh, float x, float y, float z); + void Print() { + cout << valence << "x " << p[0] << " " << p[1] << " " << p[2] << endl; + } + void operator*=( float a); + void operator+=( Vertex a); + + Vertex* copy(Mesh* mesh); + +}; + +Vertex operator+( Vertex a, Vertex b); +Vertex operator-( Vertex a, Vertex b); +Vertex operator*( float a, Vertex b); +float operator*( Vertex a, Vertex b); +Vertex operator%( Vertex a, Vertex b); +bool operator==(Vertex a, Vertex b); + + +#endif //OPENGL_EXAMPLE_VERTEX_H