1 /****************************************************************************
2 * MeshLab o o *
3 * A versatile mesh processing toolbox o o *
4 * _ O _ *
5 * Copyright(C) 2005 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23 /****************************************************************************
24 History
25 $Log: meshedit.cpp,v $
26 ****************************************************************************/
27
28 #include "edit_align.h"
29 #include <common/GLExtensionsManager.h>
30 #include <meshlab/glarea.h>
31 #include <meshlab/stdpardialog.h>
32 #include <wrap/qt/trackball.h>
33 #include "AlignPairWidget.h"
34 #include "AlignPairDialog.h"
35 #include "align/align_parameter.h"
36 #include <vcg/space/point_matching.h>
37 using namespace vcg;
38
EditAlignPlugin()39 EditAlignPlugin::EditAlignPlugin()
40 {
41 alignDialog=0;
42 qFont.setFamily("Helvetica");
43 qFont.setPixelSize(10);
44
45 trackball.center=Point3f(0, 0, 0);
46 trackball.radius= 1;
47 }
48
Info()49 const QString EditAlignPlugin::Info()
50 {
51 return tr("Allows one to align different layers together.");
52 }
53
suggestedRenderingData(MeshModel &,MLRenderingData & dt)54 void EditAlignPlugin::suggestedRenderingData(MeshModel & /*m*/, MLRenderingData& dt)
55 {
56 MLPerViewGLOptions opts;
57 dt.get(opts);
58 for (MLRenderingData::PRIMITIVE_MODALITY pr = MLRenderingData::PRIMITIVE_MODALITY(0); pr < MLRenderingData::PR_ARITY; pr = MLRenderingData::next(pr))
59 {
60 MLRenderingData::RendAtts atts;
61 dt.get(pr, atts);
62
63 atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = false;
64 if (pr == MLRenderingData::PR_SOLID)
65 atts[MLRenderingData::ATT_NAMES::ATT_FACECOLOR] = false;
66 dt.set(pr, atts);
67 }
68
69 opts._perpoint_fixed_color_enabled = false;
70 opts._perwire_fixed_color_enabled = false;
71 opts._persolid_fixed_color_enabled = false;
72
73 opts._perpoint_mesh_color_enabled = true;
74 opts._perwire_mesh_color_enabled = true;
75 opts._persolid_mesh_color_enabled = true;
76
77 dt.set(opts);
78
79 /*switch (mode)
80 {
81 case ALIGN_MOVE:
82 {
83 _shared->setRenderingDataPerMeshView(m.id(), _gla->context(), dt);
84 m.visible = false;
85 break;
86 }
87 case ALIGN_IDLE:
88 {
89
90 MLPerViewGLOptions opts;
91 dt.get(opts);
92 opts._perbbox_enabled = true;
93 dt.set(opts);
94
95 _shared->setRenderingDataPerMeshView(m.id(), _gla->context(), dt);
96 }
97 case ALIGN_INSPECT_ARC:
98 {
99 break;
100 }
101 }*/
102 }
103
StartEdit(MeshDocument & md,GLArea * gla,MLSceneGLSharedDataContext * cont)104 bool EditAlignPlugin::StartEdit(MeshDocument& md, GLArea * gla, MLSceneGLSharedDataContext* cont)
105 {
106 _md=&md;
107 _gla= gla;
108 _shared = cont;
109
110 if ((_gla == NULL) || (_shared == NULL) || (md.meshList.size() < 1))
111 return false;
112
113 //mainW->addDockWidget(Qt::LeftDockWidgetArea,alignDialog);
114 mode = ALIGN_IDLE;
115 int numOfMeshes = _md->meshList.size();
116 meshTree.clear();
117 foreach(MeshModel *mm, _md->meshList)
118 {
119
120 // assigns random color: if less than 50 meshes, color is truly unique, and the less meshes, the more different they will be
121 // if above 50, truly unique color would geenrate too similar colors, so total number of unique color
122 // is capped to 50 and the color reused, id that are close will have different color anyway
123 if (mm != NULL)
124 {
125 if (numOfMeshes < 50)
126 mm->cm.C() = Color4b::Scatter(numOfMeshes + 1, mm->id(), .2f, .7f);
127 else
128 mm->cm.C() = Color4b::Scatter(51, mm->id() % 50, .2f, .7f);
129 mm->updateDataMask(MeshModel::MM_COLOR);
130 // meshTree.nodeList.push_back(new MeshNode(mm));
131 meshTree.nodeMap[mm->id()]=new MeshNode(mm);
132 }
133 }
134
135 //for(QMap<int,RenderMode>::iterator it = _gla->rendermodemap.begin();it != _gla->rendermodemap.end();++it)
136 // it.value().colorMode=GLW::CMPerMesh;
137
138 _gla->setCursor(QCursor(QPixmap(":/images/cur_align.png"),1,1));
139 if(alignDialog==0)
140 {
141 if (!GLExtensionsManager::initializeGLextensions_notThrowing())
142 return false;
143
144 alignDialog=new AlignDialog(_gla->window(),this);
145 connect(alignDialog->ui.meshTreeParamButton,SIGNAL(clicked()),this,SLOT(meshTreeParam()));
146 connect(alignDialog->ui.icpParamButton,SIGNAL(clicked()),this,SLOT(alignParam()));
147 connect(alignDialog->ui.icpParamDefMMButton, SIGNAL(clicked()), this, SLOT(setAlignParamMM()));
148 connect(alignDialog->ui.icpParamDefMButton, SIGNAL(clicked()), this, SLOT(setAlignParamM()));
149 connect(alignDialog->ui.icpParamCurrentButton,SIGNAL(clicked()),this,SLOT(alignParamCurrent()));
150 connect(alignDialog->ui.icpButton,SIGNAL(clicked()),this,SLOT(process()));
151 connect(alignDialog->ui.manualAlignButton,SIGNAL(clicked()),this,SLOT(glueManual()));
152 connect(alignDialog->ui.pointBasedAlignButton,SIGNAL(clicked()),this,SLOT(glueByPicking()));
153 connect(alignDialog->ui.glueHereButton,SIGNAL(clicked()),this,SLOT(glueHere()));
154 connect(alignDialog->ui.glueHereAllButton,SIGNAL(clicked()),this,SLOT(glueHereVisible()));
155 connect(alignDialog->ui.recalcButton, SIGNAL(clicked()) , this, SLOT(recalcCurrentArc() ) );
156 connect(alignDialog->ui.hideRevealButton, SIGNAL(clicked()) , this, SLOT(hideRevealGluedMesh() ) );
157 connect(alignDialog, SIGNAL(updateMeshSetVisibilities() ), _gla,SLOT(updateMeshSetVisibilities()));
158 connect(alignDialog->ui.baseMeshButton, SIGNAL(clicked()) , this, SLOT(setBaseMesh() ) );
159 connect(alignDialog->ui.badArcButton, SIGNAL(clicked()) , this, SLOT(selectBadArc() ) );
160 }
161
162 //alignDialog->setCurrentNode(meshTree.find(gla->mm()) );
163 alignDialog->setTree(& meshTree);
164 alignDialog->show();
165 //alignDialog->adjustSize();
166
167 connect(this, SIGNAL(suspendEditToggle()),_gla,SLOT(suspendEditToggle()) );
168 connect(alignDialog, SIGNAL(closing()),_gla,SLOT(endEdit()) );
169 connect(_md,SIGNAL(currentMeshChanged(int)),alignDialog,SLOT(currentMeshChanged(int)));
170 suspendEditToggle();
171 return true;
172 }
173
Decorate(MeshModel & mm,GLArea * gla)174 void EditAlignPlugin::Decorate(MeshModel & mm, GLArea * gla)
175 {
176 glPushAttrib(GL_ALL_ATTRIB_BITS);
177
178 _gla = gla;
179 if (mode == ALIGN_IDLE)
180 {
181 MLRenderingData tmp;
182 MLPerViewGLOptions opts;
183 tmp.get(opts);
184 opts._perbbox_enabled = true;
185 tmp.set(opts);
186 _shared->drawAllocatedAttributesSubset(mm.id(), _gla->context(), tmp);
187 if ((alignDialog != NULL) && (alignDialog->currentArc != 0))
188 DrawArc(alignDialog->currentArc);
189 }
190
191 if (mode == ALIGN_MOVE)
192 {
193 MLRenderingData dt;
194 _shared->getRenderInfoPerMeshView(mm.id(), _gla->context(), dt);
195 MLPerViewGLOptions opts;
196 dt.get(opts);
197 opts._perbbox_enabled = false;
198 dt.set(opts);
199
200 glPushMatrix();
201 trackball.GetView();
202 trackball.Apply();
203 _shared->drawAllocatedAttributesSubset(mm.id(), _gla->context(),dt);
204 glPopMatrix();
205 }
206 glPopAttrib();
207 }
208
EndEdit(MeshModel &,GLArea *,MLSceneGLSharedDataContext *)209 void EditAlignPlugin::EndEdit(MeshModel &/*m*/, GLArea * /*parent*/, MLSceneGLSharedDataContext* /*cont*/)
210 {
211
212 // some cleaning at the end.
213 qDebug("EndEdit: cleaning everything");
214 meshTree.clear();
215 delete alignDialog;
216 alignDialog=0;
217 }
218
hideRevealGluedMesh()219 void EditAlignPlugin::hideRevealGluedMesh()
220 {
221 // foreach(MeshNode *mn, meshTree.nodeList)
222 for(auto ni=meshTree.nodeMap.begin();ni!=meshTree.nodeMap.end();++ni)
223 {
224 MeshNode *mn=ni->second;
225 if(!mn->glued) mn->m->visible=!(mn->m->visible);
226 }
227 alignDialog->rebuildTree();
228 _gla->update();
229 alignDialog->updateMeshVisibilities();
230 }
231
setBaseMesh()232 void EditAlignPlugin::setBaseMesh()
233 {
234 Matrix44d oldTr = Matrix44d::Construct(_md->mm()->cm.Tr);
235 Matrix44d inv = Inverse(oldTr);
236 _md->mm()->cm.Tr.SetIdentity();
237
238 //foreach(MeshNode *mn, meshTree.nodeList)
239 for(auto ni=meshTree.nodeMap.begin();ni!=meshTree.nodeMap.end();++ni)
240 {
241 MeshNode *mn=ni->second;
242 if(mn->glued && (mn->m != _md->mm()) )
243 mn->m->cm.Tr.Import(inv*Matrix44d::Construct(mn->m->cm.Tr));
244 }
245
246 alignDialog->rebuildTree();
247 _gla->update();
248 }
249
250
glueByPicking()251 void EditAlignPlugin::glueByPicking()
252 {
253 if(meshTree.gluedNum()<1)
254 {
255 QMessageBox::warning(0,"Align tool", "Point-based aligning requires at least one glued mesh");
256 return;
257 }
258
259 //Matrix44f oldTr = md->mm()->cm.Tr;
260 AlignPairDialog *dd=new AlignPairDialog(_gla,this->alignDialog);
261 dd->aa->initMesh(currentNode(), &meshTree);
262 dd->exec();
263
264 if(dd->result()==QDialog::Rejected)
265 return;
266
267 // i picked points sono in due sistemi di riferimento.
268
269 std::vector<vcg::Point3f>freePnt = dd->aa->freePickedPointVec;
270 std::vector<vcg::Point3f>gluedPnt= dd->aa->gluedPickedPointVec;
271
272 if( (freePnt.size() != gluedPnt.size()) || (freePnt.size()==0) ) {
273 QMessageBox::warning(0,"Align tool", "ERROR: alignment requires the same number of chosen points");
274 return;
275 }
276
277 Matrix44f res;
278 if ((dd != NULL) && (dd->aa != NULL) && (dd->aa->allowscaling))
279 ComputeSimilarityMatchMatrix(gluedPnt,freePnt,res);
280 else
281 ComputeRigidMatchMatrix(gluedPnt,freePnt,res);
282
283 //md->mm()->cm.Tr=res;
284 currentNode()->tr() = currentNode()->tr() * res;
285 QString buf;
286 // for(size_t i=0;i<freePnt.size();++i)
287 // meshTree.cb(0,qUtf8Printable(buf.sprintf("%f %f %f -- %f %f %f \n",freePnt[i][0],freePnt[i][1],freePnt[i][2],gluedPnt[i][0],gluedPnt[i][1],gluedPnt[i][2])));
288
289 assert(currentNode()->glued==false);
290
291 currentNode()->glued=true;
292 alignDialog->rebuildTree();
293 _gla->update();
294 }
295
296
glueManual()297 void EditAlignPlugin::glueManual()
298 {
299 assert(currentNode()->glued==false);
300
301 if ((_md == NULL) || (_md->mm() == NULL) || (_gla == NULL) || (_gla->mvc() == NULL))
302 return;
303
304 MeshModel *mm=_md->mm();
305
306 static QString oldLabelButton;
307 Matrix44f tran,mtran, tmp;
308
309 switch(mode)
310 {
311 case ALIGN_IDLE:
312 {
313 emit suspendEditToggle();
314 mode = ALIGN_MOVE;
315 mm->visible = false;
316 trackball.Reset();
317 trackball.center.Import(mm->cm.trBB().Center());
318 trackball.radius = mm->cm.trBB().Diag() / 2.0;
319 toggleButtons();
320 oldLabelButton = alignDialog->ui.manualAlignButton->text();
321 alignDialog->ui.manualAlignButton->setText("Accept Transformation");
322 break;
323 }
324
325 case ALIGN_MOVE: // stop manual alignment and freeze the mesh
326 {
327 emit suspendEditToggle();
328 mode = ALIGN_IDLE;
329 toggleButtons();
330 tran.SetTranslate(trackball.center);
331 mtran.SetTranslate(-trackball.center);
332 tmp.Import(mm->cm.Tr);
333 mm->cm.Tr.Import((tran)* trackball.track.Matrix()*(mtran)* tmp);
334 mm->visible = true;
335 alignDialog->ui.manualAlignButton->setText(oldLabelButton);
336 currentNode()->glued = true;
337 alignDialog->rebuildTree();
338 break;
339 }
340 default : assert("entered in the GlueManual slot in the wrong state"==0);
341 }
342
343 _gla->update();
344 }
345
alignParamCurrent()346 void EditAlignPlugin:: alignParamCurrent()
347 {
348 assert(currentArc());
349
350 RichParameterSet alignParamSet;
351 QString titleString=QString("Current Arc (%1 -> %2) Alignment Parameters").arg(currentArc()->MovName).arg(currentArc()->FixName);
352 AlignParameter::AlignPairParamToRichParameterSet(currentArc()->ap, alignParamSet);
353
354 GenericParamDialog ad(alignDialog,&alignParamSet,titleString);
355 ad.setWindowFlags(Qt::Dialog);
356 ad.setWindowModality(Qt::WindowModal);
357 int result=ad.exec();
358 if(result != QDialog::Accepted) return;
359
360 // Dialog accepted. get back the values
361 AlignParameter::RichParameterSetToAlignPairParam(alignParamSet, currentArc()->ap);
362 }
363
meshTreeParam()364 void EditAlignPlugin:: meshTreeParam()
365 {
366 RichParameterSet meshTreeParamSet;
367 AlignParameter::MeshTreeParamToRichParameterSet(defaultMTP, meshTreeParamSet);
368 GenericParamDialog ad(alignDialog,&meshTreeParamSet,"Default Alignment Parameters");
369 ad.setWindowFlags(Qt::Dialog);
370 ad.setWindowModality(Qt::WindowModal);
371 int result=ad.exec();
372 if(result != QDialog::Accepted) return;
373 // Dialog accepted. get back the values
374 AlignParameter::RichParameterSetToMeshTreeParam(meshTreeParamSet, defaultMTP);
375
376 }
377
alignParam()378 void EditAlignPlugin:: alignParam()
379 {
380 RichParameterSet alignParamSet;
381 AlignParameter::AlignPairParamToRichParameterSet(defaultAP, alignParamSet);
382 GenericParamDialog ad(alignDialog,&alignParamSet,"Default Alignment Parameters");
383 ad.setWindowFlags(Qt::Dialog);
384 ad.setWindowModality(Qt::WindowModal);
385 int result=ad.exec();
386 if(result != QDialog::Accepted) return;
387 // Dialog accepted. get back the values
388 AlignParameter::RichParameterSetToAlignPairParam(alignParamSet, defaultAP);
389 }
390
setAlignParamMM()391 void EditAlignPlugin::setAlignParamMM()
392 {
393 defaultAP.SampleNum = 2000;
394 defaultAP.MinDistAbs = 10.0;
395 defaultAP.TrgDistAbs = 0.005;
396 defaultAP.MaxIterNum = 75;
397 defaultAP.ReduceFactorPerc = 0.8;
398 defaultAP.PassHiFilter = 0.75;
399 defaultAP.MatchMode = AlignPair::Param::MMRigid;
400 QMessageBox::warning(0, "Align tool", "ICP Default Parameters set for MILLIMETERS");
401 }
402
setAlignParamM()403 void EditAlignPlugin::setAlignParamM()
404 {
405 defaultAP.SampleNum = 2000;
406 defaultAP.MinDistAbs = 0.3;
407 defaultAP.TrgDistAbs = 0.0005;
408 defaultAP.MaxIterNum = 75;
409 defaultAP.ReduceFactorPerc = 0.8;
410 defaultAP.PassHiFilter = 0.75;
411 defaultAP.MatchMode = AlignPair::Param::MMRigid;
412 QMessageBox::warning(0, "Align tool", "ICP Default Parameters set for METERS");
413 }
414
glueHere()415 void EditAlignPlugin::glueHere()
416 {
417 MeshNode *mn=currentNode();
418 if(mn->glued)
419 meshTree.deleteResult(mn);
420
421 mn->glued = !mn->glued;
422 alignDialog->rebuildTree();
423 }
424
glueHereVisible()425 void EditAlignPlugin::glueHereVisible()
426 {
427 for(auto ni=meshTree.nodeMap.begin();ni!=meshTree.nodeMap.end();++ni)
428 // foreach(MeshNode *mn, meshTree.nodeList)
429 if(ni->second->m->visible) ni->second->glued=true;
430
431 alignDialog->rebuildTree();
432 }
433
selectBadArc()434 void EditAlignPlugin::selectBadArc()
435 {
436 float maxErr=0;
437 AlignPair::Result *worseArc=0;
438 for(QList<vcg::AlignPair::Result>::iterator li=meshTree.resultList.begin();li!=meshTree.resultList.end();++li)
439 {
440 if(li->err > maxErr)
441 {
442 maxErr=li->err;
443 worseArc=&*li;
444 }
445 }
446 if(worseArc)
447 alignDialog->setCurrentArc(worseArc);
448 }
449
450
process()451 void EditAlignPlugin::process()
452 {
453 if(meshTree.gluedNum()<2)
454 {
455 QMessageBox::warning(0,"Align tool", "ICP Process can only work when at least two layers have been glued");
456 return;
457 }
458 alignDialog->setEnabled(false);
459 meshTree.Process(defaultAP, defaultMTP);
460 alignDialog->rebuildTree();
461 _gla->update();
462 alignDialog->setEnabled(true);
463 }
464
recalcCurrentArc()465 void EditAlignPlugin::recalcCurrentArc()
466 {
467 assert(currentArc());
468
469 alignDialog->setEnabled(false);
470 meshTree.ProcessArc(currentArc()->FixName,currentArc()->MovName,*currentArc(),currentArc()->ap);
471 meshTree.ProcessGlobal(currentArc()->ap);
472 AlignPair::Result *recomputedArc = currentArc();
473 alignDialog->rebuildTree();
474 alignDialog->setCurrentArc(recomputedArc);
475 alignDialog->setEnabled(true);
476 _gla->update();
477 }
478
479
mousePressEvent(QMouseEvent * e,MeshModel &,GLArea *)480 void EditAlignPlugin::mousePressEvent(QMouseEvent *e, MeshModel &, GLArea * )
481 {
482 if(mode==ALIGN_MOVE)
483 {
484 trackball.MouseDown(e->x(),_gla->height()-e->y(), QT2VCG(e->button(), e->modifiers() ) );
485 _gla->update();
486 }
487 }
488
mouseMoveEvent(QMouseEvent * e,MeshModel &,GLArea *)489 void EditAlignPlugin::mouseMoveEvent(QMouseEvent *e, MeshModel &, GLArea * )
490 {
491 if(mode==ALIGN_MOVE)
492 {
493 trackball.MouseMove(e->x(),_gla->height()-e->y() );
494 _gla->update();
495 }
496
497 }
498
mouseReleaseEvent(QMouseEvent * e,MeshModel &,GLArea *)499 void EditAlignPlugin::mouseReleaseEvent(QMouseEvent * e, MeshModel &/*m*/, GLArea * )
500 {
501 if(mode==ALIGN_MOVE)
502 {
503 trackball.MouseUp(e->x(),_gla->height()-e->y(), QT2VCG(e->button(), e->modifiers() ) );
504 _gla->update();
505 }
506 }
507
508
509 // this function toggles on and off all the buttons (according to the "modal" states of the interface),
510 // do not confuse it with the updatebuttons function of the alignDialog class.
toggleButtons()511 void EditAlignPlugin::toggleButtons()
512 {
513 switch(mode)
514 {
515 case ALIGN_MOVE:
516 alignDialog->ui.manualAlignButton->setEnabled(true);
517 alignDialog->ui.glueHereButton->setEnabled(false);
518 alignDialog->ui.glueHereAllButton->setEnabled(false);
519 alignDialog->ui.pointBasedAlignButton->setEnabled(false);
520 alignDialog->ui.baseMeshButton->setEnabled(false);
521 alignDialog->ui.hideRevealButton->setEnabled(false);
522 alignDialog->ui.icpButton->setEnabled(false);
523 alignDialog->ui.icpParamButton->setEnabled(false);
524 alignDialog->ui.icpParamDefMMButton->setEnabled(false);
525 alignDialog->ui.icpParamDefMButton->setEnabled(false);
526 alignDialog->ui.meshTreeParamButton->setEnabled(false);
527 alignDialog->ui.badArcButton->setEnabled(false);
528 alignDialog->ui.icpParamCurrentButton->setEnabled(false);
529 alignDialog->ui.recalcButton->setEnabled(false);
530 alignDialog->ui.alignTreeWidget->setEnabled(false);
531
532 break;
533 case ALIGN_IDLE:
534 alignDialog->ui.manualAlignButton->setEnabled(true);
535 alignDialog->ui.glueHereButton->setEnabled(true);
536 alignDialog->ui.glueHereAllButton->setEnabled(true);
537 alignDialog->ui.pointBasedAlignButton->setEnabled(true);
538 alignDialog->ui.baseMeshButton->setEnabled(true);
539 alignDialog->ui.hideRevealButton->setEnabled(true);
540 alignDialog->ui.icpButton->setEnabled(true);
541 alignDialog->ui.icpParamButton->setEnabled(true);
542 alignDialog->ui.icpParamDefMMButton->setEnabled(true);
543 alignDialog->ui.icpParamDefMButton->setEnabled(true);
544 alignDialog->ui.meshTreeParamButton->setEnabled(true);
545 alignDialog->ui.badArcButton->setEnabled(true);
546 alignDialog->ui.icpParamCurrentButton->setEnabled(true);
547 alignDialog->ui.recalcButton->setEnabled(true);
548 alignDialog->ui.alignTreeWidget->setEnabled(true);
549 alignDialog->updateButtons();
550 break;
551 }
552 }
553
DrawArc(vcg::AlignPair::Result * A)554 void EditAlignPlugin::DrawArc(vcg::AlignPair::Result *A )
555 {
556 unsigned int i;
557 AlignPair::Result &r=*A;
558 MeshNode *fix=meshTree.find(r.FixName);
559 MeshNode *mov=meshTree.find(r.MovName);
560 //int mov=FindMesh(r.MovName);
561 double nl=2.0*(*fix).bbox().Diag()/100.0;
562 glPushAttrib(GL_ENABLE_BIT );
563
564 glDisable(GL_LIGHTING);
565
566 glPushMatrix();
567 glMultMatrix(fix->tr());
568 glPointSize(5.0f);
569 glColor3f(1,0,0);
570 glBegin(GL_POINTS);
571 for(i=0;i<r.Pfix.size();i++) glVertex(r.Pfix[i]);
572 glEnd();
573 glPointSize(1.0f);
574 //glColor((*fix).mi.c);
575 if(r.Nfix.size()==r.Pfix.size())
576 {
577 glBegin(GL_LINES);
578 for(i=0;i<r.Pfix.size();i++) {
579 glVertex(r.Pfix[i]);
580 glVertex(r.Pfix[i]+r.Nfix[i]*nl);
581 }
582 glEnd();
583 }
584
585 glPopMatrix();
586 glPushMatrix();
587 glMultMatrix(mov->tr());
588
589 glPointSize(5.0f);
590 glColor3f(0,0,1);
591 glBegin(GL_POINTS);
592 for(i=0;i<r.Pmov.size();i++) glVertex(r.Pmov[i]);
593 glEnd();
594 glPointSize(1.0f);
595 //glColor((*mov).mi.c);
596 if(r.Nmov.size()==r.Pmov.size())
597 {
598 glBegin(GL_LINES);
599 for(i=0;i<r.Pmov.size();i++) {
600 glVertex(r.Pmov[i]);
601 glVertex(r.Pmov[i]+r.Nmov[i]*nl);
602 }
603 glEnd();
604 }
605 glPopMatrix();
606 /*
607 // Now Draw the histogram
608
609 int HSize = ViewPort[2]-100;
610 r.H.glDraw(Point4i(20,80,HSize,100),dlFont,r.as.I[0].MinDistAbs,1);
611 */
612 glPopAttrib();
613
614 }
615
616
617
618