컴퓨터 공학/Graphics

Traverse a Mesh with the half-edge structure

코딩하는 Español되기 2024. 6. 12. 13:28

Attributes Add Code

 

mesh.add_face_property<DATATYPE>("NAME");

auto VARNAME = mesh.get_face_property<DATATYPE>("NAME");

 

void DrawComponent::AddAttributes()
{
    mesh.add_face_property<pmp::Color>("f:color");

    // Compute vertex normals
    pmp::vertex_normals(mesh);

    // Compute face normals
    pmp::face_normals(mesh);

    // Colorize faces based on normals
    auto fn = mesh.get_face_property<pmp::Normal>("f:normal");
    auto fc = mesh.get_face_property<pmp::Color>("f:color");

    for (auto f : mesh.faces()) {
        auto n = fn[f];
        pmp::Color c(std::abs(n[0]), std::abs(n[1]), std::abs(n[2]));
        fc[f] = c;
    }
}

Traverse the mesh

glColor3f(0,0,0)l
for(auto f : mesh.faces()) {
	DrawFace(f, true);
}

//3-2. Draw a vertex which index is 0 with red.
	pmp::Vertex startV(0);
	glColor3f(1, 0, 0);
	glBegin(GL_POINTS);
	glVertex3dv(mesh.position(startV).data());
	glEnd();

	//3-3. Draw face(s) which has vertex(0) with blue.
	for (auto f : mesh.faces(startV)) {
	    glColor3f(0, 0, 1);
	    DrawFace(f);
	}

	//3-4. Draw vertices which are connected with vertex(0) with green.
	glColor3f(0, 1, 0);
	glBegin(GL_POINTS);
	for (auto v : mesh.vertices(startV)) {
	    auto p = mesh.position(v);
	    glVertex3dv(p.data());
	}
	glEnd();
     //3-5. Draw faces which has green vertices but no red vertex,
	 //							   with yellow.
	glColor3f(1, 1, 0);

    std::set<pmp::Face> visitedFaces;	  
    for (auto f : mesh.faces(startV))
    visitedFaces.insert(f);
    
    for (auto v : mesh.vertices(startV)) {
    	for (auto f : mesh.faces(v)) {
        	if (visitedFaces.find(f) == visitedFaces.end())
		    {
				DrawFace(f);
		    }
		}
	}

 

전체 틀 코드

DrawComponent.cpp

#include "DrawComponent.h"
#include "gl/freeglut.h"
#include <chrono>
#include <queue>
#include <set>

#include "pmp/io/io.h"
#include "pmp/algorithms/normals.h"

void DrawComponent::Init()
{
    //1. Load file or Create mesh.
    InitMyMesh(); // 기존에 사용하던 고양이 모양 대신 정육면체를 사용하려면 이 부분을 주석처리하고
    // InitMyMesh(); // 주석 처리된 부분을 활성화합니다.
    InitLoadFile();

    //2. Add attributes.
    AddAttributes();

    pmp::write(mesh, "output.obj");
}

void DrawComponent::InitLoadFile()
{
    pmp::read(mesh, "obj\\kitten.obj");
    pmp::vertex_normals(mesh);
    pmp::face_normals(mesh);
}

void DrawComponent::InitMyMesh()
{

    const auto v0 = mesh.add_vertex(pmp::Point(0, 0, 0));
    const auto v1 = mesh.add_vertex(pmp::Point(1, 0, 0));
    const auto v2 = mesh.add_vertex(pmp::Point(1, 1, 0));
    const auto v3 = mesh.add_vertex(pmp::Point(0, 1, 0));
    const auto v4 = mesh.add_vertex(pmp::Point(0, 0, 1));
    const auto v5 = mesh.add_vertex(pmp::Point(1, 0, 1));
    const auto v6 = mesh.add_vertex(pmp::Point(1, 1, 1));
    const auto v7 = mesh.add_vertex(pmp::Point(0, 1, 1));

    mesh.add_quad(v4, v5, v6, v7);
    mesh.add_quad(v0, v3, v2, v1);
    mesh.add_quad(v0, v4, v7, v3);

    //Add more quads!




    std::cout << "vertices: " << mesh.n_vertices() << std::endl;
    std::cout << "edges: " << mesh.n_edges() << std::endl;
    std::cout << "faces: " << mesh.n_faces() << std::endl;

    pmp::vertex_normals(mesh);
    pmp::face_normals(mesh);
}

void DrawComponent::Draw()
{
    auto vn = mesh.get_vertex_property<pmp::Normal>("v:normal");
    auto fn = mesh.get_face_property<pmp::Normal>("f:normal");
    auto fc = mesh.get_face_property<pmp::Color>("f:color");

    //1. Basic drawing
    if (false)
    for (auto f : mesh.faces()) {
	glNormal3dv(fn[f].data());
	DrawFace(f);
    }

    //2. Color with normals
    if(false)
    for (auto f : mesh.faces())
    {
	glColor3dv(fc[f].data());
	DrawFace(f);
    }

    //3. Traverse the mesh
    if(true)
    {
	glLineWidth(1.0);
	glPointSize(20.0);

	//3-1. Draw the mesh with wireframe.
	glColor3f(0, 0, 0);
	for (auto f : mesh.faces()) {
	    DrawFace(f, true);
	}

	//3-2. Draw a vertex which index is 0 with red.
	pmp::Vertex startV(0);
	glColor3f(1, 0, 0);
	glBegin(GL_POINTS);
	glVertex3dv(mesh.position(startV).data());
	glEnd();

	//3-3. Draw face(s) which has vertex(0) with blue.
	for (auto f : mesh.faces(startV)) {
	    glColor3f(0, 0, 1);
	    DrawFace(f);
	}

	//3-4. Draw vertices which are connected with vertex(0) with green.
	glColor3f(0, 1, 0);
	glBegin(GL_POINTS);
	for (auto v : mesh.vertices(startV)) {
	    auto p = mesh.position(v);
	    glVertex3dv(p.data());
	}
	glEnd();

	if (true) {
	    //3-5. Draw faces which has green vertices but no red vertex,
	    //							   with yellow.
	    glColor3f(1, 1, 0);

	    std::set<pmp::Face> visitedFaces;
	    for (auto f : mesh.faces(startV))
		visitedFaces.insert(f);

	    for (auto v : mesh.vertices(startV)) {
		for (auto f : mesh.faces(v)) {
		    if (visitedFaces.find(f) == visitedFaces.end())
		    {
			DrawFace(f);
		    }
		}
	    }
	}
    }
}

void DrawComponent::DrawFace(pmp::Face f, bool isWire) {
    glBegin(isWire ? GL_LINE_LOOP: GL_POLYGON);
    for (auto v : mesh.vertices(f))
	glVertex3dv(mesh.position(v).data());
    glEnd();
}

void DrawComponent::AddAttributes()
{
    mesh.add_face_property<pmp::Color>("f:color");

    // compute vertex normals
    pmp::vertex_normals(mesh);

    // compute face normals
    pmp::face_normals(mesh);

    // colorize faces based on normals
    auto fn = mesh.get_face_property<pmp::Normal>("f:normal");
    auto fc = mesh.get_face_property<pmp::Color>("f:color");

    for (auto f : mesh.faces())
    {
	auto n = fn[f];
	pmp::Color c(std::abs(n[0]), std::abs(n[1]), std::abs(n[2]));
	fc[f] = c;
    }
}

Main.cpp

#include "QTViewer.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTViewer w;
    w.show();
    return a.exec();
}

QTViewer.cpp

#include "QTViewer.h"

QTViewer::QTViewer(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
}

QTViewer::~QTViewer()
{}

Viewer.cpp

#include <qKeyEvent>
#include "Viewer.h"

Viewer::Viewer(QWidget* parent) : QGLViewer(parent)
{
    setParent(parent);
}

Viewer::~Viewer()
{
}

void Viewer::initializeGL()
{
    glClearColor(1, 1, 1, 1);
    glClearDepth(1.0);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_NORMALIZE);
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glFrontFace(GL_CCW);
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    GLfloat ambient[] = { 0.1,0.1,0.1 };
    GLfloat diffuse[] = { 0.4,0.4,0.4 };
    GLfloat light0Pos[] = { 100,100,100,0 };
    GLfloat light1Pos[] = { -100,100,100,0 };
    GLfloat specular[] = { 0.4,0.4,0.4 };
    glEnable(GL_LIGHTING);
    glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
    glEnable(GL_LIGHT0);
    //glLightfv(GL_LIGHT1, GL_POSITION, light1Pos);
    //glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
    //glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
    //glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
    //glEnable(GL_LIGHT1);
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
    glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 10);


    glPointSize(10);
    glLineWidth(3.0);
    //restoreStateFromFile();

    dc.Init();
}

void Viewer::draw()
{
    dc.Draw();
}

void Viewer::keyPressEvent(QKeyEvent* e)
{
    int key = e->key();
    if (key == Qt::Key_S)
    {
	saveStateToFile();
    }
    else if (key == Qt::Key_L)
    {
	restoreStateFromFile();
    }
    else if (key == Qt::Key_Comma)
    {
	setSceneRadius(sceneRadius() * 0.1);
    }
    else if (key == Qt::Key_Period)
    {
	setSceneRadius(sceneRadius() * 10.0);
    }
    else
	QGLViewer::keyPressEvent(e);

    update();

}

void Viewer::mousePressEvent(QMouseEvent* e)
{
    QGLViewer::mousePressEvent(e);
}

void Viewer::mouseMoveEvent(QMouseEvent* e)
{
    QGLViewer::mouseMoveEvent(e);
}

void Viewer::mouseReleaseEvent(QMouseEvent* e)
{
    QGLViewer::mouseReleaseEvent(e);
}