3D-s számítógépes geometria és alakzatrekonstrukció

Tesztkörnyezet V

http://cg.iit.bme.hu/portal/node/312
https://portal.vik.bme.hu/kepzes/targyak/VIIIMA25

Dr. Várady Tamás, Dr. Salvi Péter
BME, Villamosmérnöki és Informatikai Kar
Irányítástechnika és Informatika Tanszék

Ötödik fázis

  • Bézier felületek megjelenítése
    • Saját (egyszerű) fájlformátum
  • Megjelenítés
    • Mint eddig (sima, átlaggörbület, fényvonalak)
    • Fix felbontással mesh generálás
    • Háromszögháló alapján minden működik
      • Előny: nem kell vele dolgozni
      • Hátrány: kevésbé pontos
  • Kontrollpontok mozgatása
    • Felület (mesh) automatikus módosítása
    • Normálisok, görbületek újraszámolása

Szerkezet

  • Szinte minden az új osztályba kerül, csak a beolvasásnál kell módosítás
  • A Window::open() függvényben:
    auto filename =
      QFileDialog::getOpenFileName(this, tr("Open File"), last_directory,
                                   tr("Readable files (*.obj *.ply *.stl *.bzr);;"
                                      "Mesh (*.obj *.ply *.stl);;"
                                      "Bézier surface (*.bzr);;"
                                      "All files (*.*)"));
    
  • Valamint a Viewer osztályban:
    #include "bezier.hh"
    bool Viewer::open(std::string filename) {
      std::shared_ptr<Object> surface;
      if (filename.ends_with(".bzr"))
        surface = std::make_shared<Bezier>(filename);
      else surface = std::make_shared<Mesh>(filename);
      // ...
    }
    

Kontrollpontok ki/be kapcsolása

  • ... és a vizualizációs beállításoknál van egy új Boolean változó
  • a C gomb lenyomására változik az értéke (a show_solid mintájára)
struct Visualization {
  bool show_control_points;
  // ...
};

Visualization::Visualization() :
  type(VisType::PLAIN),
  show_control_points(true), show_solid(true), show_wireframe(false),
  mean_min(0.0), mean_max(0.0), cutoff_ratio(0.05)
{
}

Az új objektumtípus

#pragma once

#include "object.hh"

class Bezier : public Object {
public:
  Bezier(std::string filename);
  virtual ~Bezier();
  virtual void draw(const Visualization &vis) const override;
  virtual void drawWithNames(const Visualization &vis) const override;
  virtual Vector postSelection(int selected) override;
  virtual void movement(int selected, const Vector &pos) override;
  virtual void updateBaseMesh() override;
  virtual bool reload() override;
private:
  size_t degree[2];
  std::vector<Vector> control_points;
};

Konstruktor

#include "bezier.hh"

Bezier::Bezier(std::string filename)
  : Object(filename)
{
  reload(); 
}

A .bzr fájlformátum

n m
P00x P00y P00z
...
P0mx P0my P0mz
P10x P10y P10z
...
Pnmx Pnmy Pnmz

Beolvasás

#include <fstream>

bool Bezier::reload() {
  size_t n, m;
  try {
    std::ifstream f(filename);
    f.exceptions(std::ios::failbit | std::ios::badbit);
    f >> n >> m;
    degree[0] = n++; degree[1] = m++;
    control_points.resize(n * m);
    for (size_t i = 0, index = 0; i < n; ++i)
      for (size_t j = 0; j < m; ++j, ++index)
        f >> control_points[index][0]
          >> control_points[index][1]
          >> control_points[index][2];
  } catch(std::ifstream::failure &) {
    return false;
  }
  updateBaseMesh();
  return true;
}

Kontrollpontok rajzolása

void Bezier::draw(const Visualization &vis) const {
  Object::draw(vis);
  if (vis.show_control_points) {
    glDisable(GL_LIGHTING);
    glLineWidth(3.0); glColor3d(0.3, 0.3, 1.0);
    size_t m = degree[1] + 1;
    for (size_t k = 0; k < 2; ++k)
      for (size_t i = 0; i <= degree[k]; ++i) {
        glBegin(GL_LINE_STRIP);
        for (size_t j = 0; j <= degree[1-k]; ++j) {
          size_t const index = k ? j * m + i : i * m + j;
          const auto &p = control_points[index];
          glVertex3dv(p.data());
        }
        glEnd();
      }
    glLineWidth(1.0); glPointSize(8.0); glColor3d(1.0, 0.0, 1.0);
    glBegin(GL_POINTS);
    for (const auto &p : control_points)
      glVertex3dv(p.data());
    glEnd();
    glPointSize(1.0);
    glEnable(GL_LIGHTING);
  }
}

A csúcsok kiértékelése

void Bezier::updateBaseMesh() {
  size_t resolution = 50;
  mesh.clear();
  std::vector<BaseMesh::VertexHandle> handles, tri;
  size_t n = degree[0], m = degree[1];
  std::vector<double> coeff_u, coeff_v;
  for (size_t i = 0; i < resolution; ++i) {
    double u = (double)i / (double)(resolution - 1);
    bernstein(n, u, coeff_u);
    for (size_t j = 0; j < resolution; ++j) {
      double v = (double)j / (double)(resolution - 1);
      bernstein(m, v, coeff_v);
      Vector p(0.0, 0.0, 0.0);
      for (size_t k = 0, index = 0; k <= n; ++k)
        for (size_t l = 0; l <= m; ++l, ++index)
          p += control_points[index] * coeff_u[k] * coeff_v[l];
      handles.push_back(mesh.add_vertex(p));
    }
  }
  // ... lapok készítése ...
  Object::updateBaseMesh();
}

A lapok készítése

void Bezier::updateBaseMesh() {
  size_t resolution = 50;
  mesh.clear();
  std::vector<BaseMesh::VertexHandle> handles, tri;
  // ... csúcsok kiértékelése ...
  for (size_t i = 0; i < resolution - 1; ++i)
    for (size_t j = 0; j < resolution - 1; ++j) {
      tri.clear();
      tri.push_back(handles[i * resolution + j]);
      tri.push_back(handles[i * resolution + j + 1]);
      tri.push_back(handles[(i + 1) * resolution + j]);
      mesh.add_face(tri);
      tri.clear();
      tri.push_back(handles[(i + 1) * resolution + j]);
      tri.push_back(handles[i * resolution + j + 1]);
      tri.push_back(handles[(i + 1) * resolution + j + 1]);
      mesh.add_face(tri);
    }
  Object::updateBaseMesh();
}

Módosítás

void Bezier::drawWithNames(const Visualization &vis) const {
  if (!vis.show_control_points)
    return;
  for (size_t i = 0; i < control_points.size(); ++i) {
    const auto &p = control_points[i];
    glPushName(i);
    glRasterPos3dv(p.data());
    glPopName();
  }
}

Vector Bezier::postSelection(int selected) {
  return control_points[selected];
}

void Bezier::movement(int selected, const Vector &pos) {
  control_points[selected] = pos;
}

Kész az ötödik fázis

Phase 5 complete

  • Vannak még egyéb funkciók, érdemes körülnézni