컴퓨터 공학/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);
}