Tartalom
Fairing [OpenMesh]
Pontmozgatás
Név szerinti szelekció [OpenGL]
Szelekciós segédfüggvények [libQGLViewer]
Kitérő egyenesek metszése
Negyedik fázis
Fairing
Laplace-féle simítás
Normális irányban mozgat
OpenMesh-be beépített
Pontmozgatás
XYZ tengelyek megjelenítése
libQGLViewer/OpenGL: kiválasztás támogatása
Problémás:
Takarás kezelése (választható pontok / tengelyek)
Tengelyméret (elvileg nem függ modelltől/nézettől)
Itt: egyszerű, de nem tökéletes megoldás
Fairing
Beépített függvény segítségével:#include <OpenMesh/Tools/Smoother/JacobiLaplaceSmootherT.hh>
void Mesh::fair () {
OpenMesh::Smoother::JacobiLaplaceSmootherT<BaseMesh> smoother (mesh) ;
smoother.initialize (OpenMesh::Smoother::SmootherT<BaseMesh>::Normal,
OpenMesh::Smoother::SmootherT<BaseMesh>::C1);
smoother.smooth (10 );
}
initialize(mozgatás_iránya, megtartandó_folytonosság)
Irány lehet: Tangential
, Normal
, Tangential_and_Normal
Folytonosság lehet: C0
, C1
, C2
smooth(iterációk_száma)
GUI kontroll
void Viewer::keyPressEvent (QKeyEvent *e) {
if (e->modifiers () == Qt::NoModifier)
switch (e->key ()) {
case Qt::Key_F:
{
std::vector<Mesh *> meshes;
for (auto o : objects)
try {
meshes.push_back (dynamic_cast <Mesh *>(o.get ()));
} catch (std::bad_cast &) { }
emit startComputation (tr("Fairing meshes..." )) ;
for (size_t i = 1 ; i <= 10 ; ++i) {
for (auto m : meshes)
m->fair ();
emit midComputation (i * 10 ) ;
}
for (auto m : meshes)
m->updateBaseMesh ();
emit endComputation () ;
}
update ();
break ;
default :
QGLViewer::keyPressEvent (e);
} else
QGLViewer::keyPressEvent (e);
}
OpenGL szelekció - két módszer
Sugármetszés
Szemből kurzoron át menő vektor
Metszés az objektummal (manuális)
Előny: koordinátákat ad
Név szerinti szelekció
Újból renderelés
Elég csak a kurzor körül
Elég csak a választható dolgokat
De kellenek a takaró objektumok is
Keret:glPushName (int )
glPopName ()
libQGLViewer támogatás
Sugármetszés
Camera::convertClickToLine(pont, szem, irány)
Visszaadja adott ponthoz a szem/irány vektorokat
Camera::pointUnderPixel(pont, talált-e)
Kurzorpozíció alatti objektumpontot adja vissza
Nagy színtérre pontatlan (valójában nem metszés)
Szem- és világkoordinátarendszer konverziók
Név szerinti szelekció
Shift+click : szelekció
drawWithNames()
, postSelection()
Néhány hasznos property:
selectRegionWidth
/ selectRegionHeight
, selectedName
Szerkezet
Ha a tengelyek nem láthatóak
Minden csúcs kiválasztható
Szelekciókor...
Idehelyezzük és megjelenítjük a tengelyeket
Elmentjük az aktuális pozíciót
Ha a tengelyek láthatóak
Csak a tengelyek választhatóak ki
Szelekciókor...
Megjegyezzük, melyik tengely
Elmentjük a klikkelt helyet
Egérmozgatáskor (szelekció után)
Tengelyek (és a csúcs) mozognak
class Viewer : public QGLViewer {
protected :
virtual void drawWithNames () override ;
virtual void postSelection (const QPoint &p) override ;
virtual void mouseMoveEvent (QMouseEvent *e) override ;
private :
int selected_vertex;
size_t selected_object;
struct ModificationAxes {
bool shown;
float size;
int selected_axis;
Vector position, grabbed_pos, original_pos;
} axes;
};
Rajzolás tengelyekkel
void Viewer::draw () {
for (auto o : objects)
o->draw (vis);
if (axes.shown) {
using qglviewer::Vec;
const auto &p = Vec (axes.position);
glColor3d (1.0 , 0.0 , 0.0 );
drawArrow (p, p + Vec (axes.size, 0.0 , 0.0 ), axes.size / 50.0 );
glColor3d (0.0 , 1.0 , 0.0 );
drawArrow (p, p + Vec (0.0 , axes.size, 0.0 ), axes.size / 50.0 );
glColor3d (0.0 , 0.0 , 1.0 );
drawArrow (p, p + Vec (0.0 , 0.0 , axes.size), axes.size / 50.0 );
}
}
Rajzolás nevekkel
void Viewer::drawWithNames () {
if (axes.shown) {
using qglviewer::Vec;
const auto &p = Vec (axes.position);
glPushName (0 );
drawArrow (p, p + Vec (axes.size, 0.0 , 0.0 ), axes.size / 50.0 );
glPopName ();
glPushName (1 );
drawArrow (p, p + Vec (0.0 , axes.size, 0.0 ), axes.size / 50.0 );
glPopName ();
glPushName (2 );
drawArrow (p, p + Vec (0.0 , 0.0 , axes.size), axes.size / 50.0 );
glPopName ();
} else {
for (size_t i = 0 ; i < objects.size (); ++i) {
glPushName (i);
objects[i]->drawWithNames (vis);
glPopName ();
}
}
}
Objektumok szelekciós függvényei
class Object {
public :
virtual void drawWithNames (const Visualization &vis) const = 0 ;
virtual Vector postSelection (int selected) = 0 ;
virtual void movement (int selected, const Vector &pos) = 0 ;
};
class Mesh : public Object {
public :
virtual void drawWithNames (const Visualization &vis) const override ;
virtual Vector postSelection (int selected) override ;
virtual void movement (int selected, const Vector &pos) override ;
};
Mesh nevesített rajzolása & csúcsok mozgatása
void Mesh::drawWithNames (const Visualization &vis) const {
if (!vis.show_wireframe)
return ;
for (auto v : mesh.vertices ()) {
glPushName (v.idx ());
glRasterPos3dv (mesh.point (v).data ());
glPopName ();
}
}
Vector Mesh::postSelection (int selected) {
return mesh.point (BaseMesh::VertexHandle (selected));
}
void Mesh::movement (int selected, const Vector &pos) {
mesh.set_point (BaseMesh::VertexHandle (selected), pos);
}
Szelekció
void Viewer::postSelection (const QPoint &p) {
int sel = selectedName ();
if (sel == -1 ) {
axes.shown = false ;
return ;
}
if (axes.shown) {
axes.selected_axis = sel;
bool found;
axes.grabbed_pos = toVector (camera ()->pointUnderPixel (p, found));
axes.original_pos = axes.position;
if (!found)
axes.shown = false ;
return ;
}
Szelekció (folytatás) - tengelyek mérete
using qglviewer::Vec;
selected_vertex = sel;
axes.position = objects[selected_object]->postSelection (sel);
double depth = camera ()->projectedCoordinatesOf (Vec (axes.position))[2 ];
Vec q1 = camera ()->unprojectedCoordinatesOf (Vec (0.0 , 0.0 , depth));
Vec q2 = camera ()->unprojectedCoordinatesOf (Vec (width (), height (), depth));
axes.size = (q1 - q2).norm () / 10.0 ;
axes.shown = true ;
axes.selected_axis = -1 ;
}
static inline Vector toVector (const qglviewer::Vec &v) {
return Vector (static_cast <const qreal *>(v));
}
void Viewer::mouseMoveEvent (QMouseEvent *e) {
if (!axes.shown ||
(axes.selected_axis < 0 && !(e->modifiers () & Qt::ControlModifier)) ||
!(e->modifiers () & (Qt::ShiftModifier | Qt::ControlModifier)) ||
!(e->buttons () & Qt::LeftButton))
return QGLViewer::mouseMoveEvent (e);
using qglviewer::Vec;
if (e->modifiers () & Qt::ControlModifier) {
double depth = camera ()->projectedCoordinatesOf (Vec (axes.position))[2 ];
auto pos = camera ()->unprojectedCoordinatesOf (Vec (e->pos ().x (), e->pos ().y (), depth));
axes.position = toVector (pos);
} else { ... }
objects[selected_object]->movement (selected_vertex, axes.position);
objects[selected_object]->updateBaseMesh ();
updateMeanMinMax (); update ();
}
void Viewer::mouseMoveEvent (QMouseEvent *e) {
if (!axes.shown ||
(axes.selected_axis < 0 && !(e->modifiers () & Qt::ControlModifier)) ||
!(e->modifiers () & (Qt::ShiftModifier | Qt::ControlModifier)) ||
!(e->buttons () & Qt::LeftButton))
return QGLViewer::mouseMoveEvent (e);
using qglviewer::Vec;
if (...) { ... } else {
Vec from, dir, axis (axes.selected_axis == 0 , axes.selected_axis == 1 , axes.selected_axis == 2 );
camera ()->convertClickToLine (e->pos (), from, dir);
auto p = intersectLines (axes.grabbed_pos, toVector (axis), toVector (from), toVector (dir));
float d = (p - axes.grabbed_pos) | toVector (axis);
axes.position[axes.selected_axis] = axes.original_pos[axes.selected_axis] + d;
}
objects[selected_object]->movement (selected_vertex, axes.position);
objects[selected_object]->updateBaseMesh ();
updateMeanMinMax (); update ();
}
Kitérő egyenesek metszése
Legközelebbi pontok: és
merőleges mindkét egyenesre
és
Kétismeretlenes egyenletrendszer
és ,
ahol , , ,
,
Nekünk csak a kell
ahol
, , , ,
Itt: ap
= , ad
= és bp
= , bd
=
static Vector intersectLines (const Vector &ap, const Vector &ad,
const Vector &bp, const Vector &bd) {
double a = ad.sqrnorm (), b = ad | bd, c = bd.sqrnorm ();
double d = ad | (ap - bp), e = bd | (ap - bp);
if (a * c - b * b < 1.0e-7 )
return ap;
double s = (b * e - c * d) / (a * c - b * b);
return ap + s * ad;
}
A selected_object
beállítása
A default implementáció, picit átírva
void Viewer::endSelection (const QPoint &) {
glFlush ();
GLint nbHits = glRenderMode (GL_RENDER);
if (nbHits <= 0 )
setSelectedName (-1 );
else {
const GLuint *ptr = selectBuffer ();
GLuint zMin = std::numeric_limits<GLuint>::max ();
for (int i = 0 ; i < nbHits; ++i, ptr += 4 ) {
GLuint names = ptr[0 ];
if (ptr[1 ] < zMin) {
zMin = ptr[1 ];
if (names == 2 ) {
selected_object = ptr[3 ];
ptr++;
}
setSelectedName (ptr[3 ]);
} else if (names == 2 )
ptr++;
}
}
}
Kész a negyedik fázis
Hiányosságok:
Takart pontok is kiválaszthatóak
A tengelyek mérete nem teljesen nézetfüggetlen
Previous slide Page 1 of 21 Next slide Toggle fullscreen Open presenter view