/* This file is part of moth. moth is a program for creating and editing textured 3D models. Copyright (C) 2004 Peter Uray. moth is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. moth is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with moth; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include M3DView::M3DView(QWidget *parent, const char *name) : MGLView(parent, name) { setFocusPolicy(QWidget::StrongFocus); setMouseTracking(true); onResetView(); _selectedAxis = NoAxis; } void M3DView::renderView(void) { MVector camAxis; MVector cameraPosition; float cphi; float viewAspect; float openingAngle; float nearClippingDistance; float farClippingDistance; if(!isVisible()) return; viewAspect = ((float)width()) / ((float)height()); openingAngle = MPreferences::get()->getCameraAngle(); nearClippingDistance = MPreferences::get()->getNCD(); farClippingDistance = MPreferences::get()->getFCD(); _camera.createPerspectiveView(openingAngle, viewAspect, nearClippingDistance, farClippingDistance, width(), height()); cphi = _cameraPhi - 90.0; cameraPosition[0] = _cameraR*cos(M_PI*cphi/180.0)*sin(M_PI*_cameraTheta/180.0); cameraPosition[1] = _cameraR*sin(M_PI*cphi/180.0)*sin(M_PI*_cameraTheta/180.0); cameraPosition[2] = _cameraR*cos(M_PI*_cameraTheta/180.0); cameraPosition += _lookAt; _camera.setPosition(cameraPosition); _camera.setDirection(_lookAt - cameraPosition); _camera.setUp(((cameraPosition - _lookAt) ^ e3) ^ (cameraPosition - _lookAt)); _camera.render(); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); glViewport(0, 0, (GLint)width(), (GLint)height()); glClearColor(_backgroundColor.red() / 256.0, _backgroundColor.green() / 256.0, _backgroundColor.blue() / 256.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LIGHTING); glDepthFunc(GL_LEQUAL); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); MGlobalLight::get()->render(); MSceneGraph::get()->updateData(); MSceneGraph::get()->render(); MCoordinateSystem::get()->readParameters(); MCoordinateSystem::get()->render(); MItemManipulator::get()->render(); } void M3DView::onSelectModel(void) { MSceneGraph::get()->setSelectionHotSpot(_newMouseX, height() - _newMouseY); updateGL(); MDocument::get()->setSelectedItem(MSceneGraph::get()->getSelectedItem()); MStructureView::get()->setSelectedItem(MSceneGraph::get()->getSelectedItem()); updateGL(); } void M3DView::onSelectShape(void) { } void M3DView::onSelectLight(void) { } void M3DView::onZoomIn(void) { MLine viewRay; MVector p0, p1; MVector distance; float lambda; float nearClippingDistance; nearClippingDistance = MPreferences::get()->getNCD(); if(_cameraR > 2.0*nearClippingDistance) { viewRay = _camera.getViewRay(width()/2, height()/2); lambda = viewRay[0][2] / (viewRay[0][2] - viewRay[1][2]); p0 = viewRay[0] + lambda*(viewRay[1] - viewRay[0]); viewRay = _camera.getViewRay(_newMouseX, _newMouseY); lambda = viewRay[0][2] / (viewRay[0][2] - viewRay[1][2]); p1 = viewRay[0] + lambda*(viewRay[1] - viewRay[0]); _lookAt += p1 - p0; _cameraR *= 0.9; MModelView::get()->repaint(); } } void M3DView::onZoomOut(void) { MLine viewRay; MVector p0, p1; MVector distance; float lambda; float farClippingDistance; farClippingDistance = MPreferences::get()->getFCD(); if(_cameraR < 0.5*farClippingDistance) { viewRay = _camera.getViewRay(width()/2, height()/2); lambda = viewRay[0][2] / (viewRay[0][2] - viewRay[1][2]); p0 = viewRay[0] + lambda*(viewRay[1] - viewRay[0]); viewRay = _camera.getViewRay(_newMouseX, _newMouseY); lambda = viewRay[0][2] / (viewRay[0][2] - viewRay[1][2]); p1 = viewRay[0] + lambda*(viewRay[1] - viewRay[0]); _lookAt += p1 - p0; _cameraR *= 1.1; MModelView::get()->repaint(); } } void M3DView::onMoveModelInit(void) { MLine viewRay; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onMoveModelPerform(void) { MVector dir; float way; MModelManipulator mm; MVector newPosition; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } way = 0.1*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: dir = MDocument::get()->getSelectedModel()->getDirection(); dir.normalize(); dir *= way; break; case MGLView::YAxis: dir = MDocument::get()->getSelectedModel()->getUp() ^ MDocument::get()->getSelectedModel()->getDirection(); dir.normalize(); dir *= way; break; case MGLView::ZAxis: dir = MDocument::get()->getSelectedModel()->getUp(); dir.normalize(); dir *= way; break; default: break; } newPosition = MDocument::get()->getSelectedModel()->getPosition() + dir; MCoordinateSystem::get()->snap(newPosition); dir = newPosition - MDocument::get()->getSelectedModel()->getPosition(); mm.set(MDocument::get()->getSelectedModel()); if(_state & RightButton) mm.setChangeGeometry(false); mm.move(dir); MModelView::get()->repaint(); } void M3DView::onMoveModelFinish(void) { _selectedAxis = MGLView::NoAxis; MDocument::get()->unlock(); } void M3DView::onMoveShapeInit(void) { MLine viewRay; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onMoveShapePerform(void) { MVector dir; float way; MVector newPosition; MShapeManipulator sm; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } way = 0.1*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: dir = MDocument::get()->getSelectedShape()->getDirection(); dir.normalize(); dir *= way; break; case MGLView::YAxis: dir = MDocument::get()->getSelectedShape()->getDirection() ^ MDocument::get()->getSelectedShape()->getUp(); dir.normalize(); dir *= way; break; case MGLView::ZAxis: dir = MDocument::get()->getSelectedShape()->getUp(); dir.normalize(); dir *= way; break; default: break; } //if(_state & RightButton) MDocumentHistory::get()->getSelectedModel()->moveRel(dir, true); // else MDocumentHistory::get()->getSelectedModel()->moveRel(dir, false); newPosition = MDocument::get()->getSelectedShape()->getPosition() + dir; MCoordinateSystem::get()->snap(newPosition); dir = newPosition - MDocument::get()->getSelectedShape()->getPosition(); sm.set(MDocument::get()->getSelectedShape()); if(_state & RightButton) sm.setChangeGeometry(false); sm.move(dir); MModelView::get()->repaint(); } void M3DView::onMoveShapeFinish(void) { _selectedAxis = MGLView::NoAxis; MDocument::get()->unlock(); } void M3DView::onMoveLightInit(void) { MLine viewRay; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onMoveLightPerform(void) { MVector dir; float way; MLightSourceManipulator lm; MVector newPosition; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } way = 0.1*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: dir = MDocument::get()->getSelectedLightSource()->getDirection(); dir.normalize(); dir *= way; break; case MGLView::YAxis: dir = MDocument::get()->getSelectedLightSource()->getUp() ^ MDocument::get()->getSelectedLightSource()->getDirection(); dir.normalize(); dir *= way; break; case MGLView::ZAxis: dir = MDocument::get()->getSelectedLightSource()->getUp(); dir.normalize(); dir *= way; break; default: break; } //if(_state & RightButton) MDocumentHistory::get()->getSelectedModel()->moveRel(dir, true); // else MDocumentHistory::get()->getSelectedModel()->moveRel(dir, false); newPosition = MDocument::get()->getSelectedLightSource()->getPosition() + dir; MCoordinateSystem::get()->snap(newPosition); dir = newPosition - MDocument::get()->getSelectedLightSource()->getPosition(); lm.set(MDocument::get()->getSelectedLightSource()); lm.move(dir); MModelView::get()->repaint(); } void M3DView::onMoveLightFinish(void) { _selectedAxis = MGLView::NoAxis; MDocument::get()->unlock(); } void M3DView::onRotateModelInit(void) { MLine viewRay; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onRotateModelPerform(void) { float angle; MVector axis; MModelManipulator mm; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } angle = 0.5*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleX()); axis = MDocument::get()->getSelectedModel()->getDirection(); break; case MGLView::YAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleY()); axis = MDocument::get()->getSelectedModel()->getDirection() ^ MDocument::get()->getSelectedModel()->getUp(); break; case MGLView::ZAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleZ()); axis = MDocument::get()->getSelectedModel()->getUp(); break; default: break; } mm.set(MDocument::get()->getSelectedModel()); if(_state & RightButton) mm.setChangeGeometry(false); mm.rotate(angle, axis); MModelView::get()->repaint(); } void M3DView::onRotateModelFinish(void) { _selectedAxis = MGLView::NoAxis; MDocument::get()->unlock(); } void M3DView::onRotateShapeInit(void) { MLine viewRay; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onRotateShapePerform(void) { float angle; MVector axis; MShapeManipulator sm; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } angle = 0.5*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleX()); axis = MDocument::get()->getSelectedShape()->getDirection(); break; case MGLView::YAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleY()); axis = MDocument::get()->getSelectedShape()->getDirection() ^ MDocument::get()->getSelectedShape()->getUp(); break; case MGLView::ZAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleZ()); axis = MDocument::get()->getSelectedShape()->getUp(); break; default: return; break; } sm.set(MDocument::get()->getSelectedShape()); if(_state & RightButton) sm.setChangeGeometry(false); sm.rotate(angle, axis); MModelView::get()->repaint(); } void M3DView::onRotateShapeFinish(void) { _selectedAxis = MGLView::NoAxis; MDocument::get()->unlock(); } void M3DView::onRotateLightInit(void) { MLine viewRay; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onRotateLightPerform(void) { float angle; MVector axis; MLightSourceManipulator lm; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } angle = 0.5*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleX()); axis = MDocument::get()->getSelectedLightSource()->getDirection(); break; case MGLView::YAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleY()); axis = MDocument::get()->getSelectedLightSource()->getDirection() ^ MDocument::get()->getSelectedLightSource()->getUp(); break; case MGLView::ZAxis: if(MCoordinateSystem::get()->getSnapAngleMode()) angle = MCoordinateSystem::get()->snapFunc(2.0*_mouseDX, MCoordinateSystem::get()->getSnapAngleZ()); axis = MDocument::get()->getSelectedLightSource()->getUp(); break; default: break; } lm.set(MDocument::get()->getSelectedLightSource()); lm.rotate(angle, axis); MModelView::get()->repaint(); } void M3DView::onRotateLightFinish(void) { _selectedAxis = MGLView::NoAxis; MDocument::get()->unlock(); } void M3DView::onScaleModelInit(void) { MLine viewRay; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onScaleModelPerform(void) { MVector axis; float factor; MModelManipulator mm; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } factor = 0.01*_mouseDXF; if(factor <= -0.2) factor = -0.2; switch(_selectedAxis) { case MGLView::XAxis: axis = MDocument::get()->getSelectedModel()->getDirection(); mm.set(MDocument::get()->getSelectedModel()); mm.scale(1.0 + factor, axis); break; case MGLView::YAxis: axis = MDocument::get()->getSelectedModel()->getUp() ^ MDocument::get()->getSelectedModel()->getDirection(); mm.set(MDocument::get()->getSelectedModel()); mm.scale(1.0 + factor, axis); break; case MGLView::ZAxis: axis = MDocument::get()->getSelectedModel()->getUp(); mm.set(MDocument::get()->getSelectedModel()); mm.scale(1.0 + factor, axis); break; case MGLView::NoAxis: mm.set(MDocument::get()->getSelectedModel()); mm.scale(1.0 + factor, e1); mm.scale(1.0 + factor, e2); mm.scale(1.0 + factor, e3); break; default: break; } MModelView::get()->repaint(); } void M3DView::onScaleModelFinish(void) { _selectedAxis = MGLView::NoAxis; MDocument::get()->unlock(); } void M3DView::onScaleShapeInit(void) { MLine viewRay; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onScaleShapePerform(void) { MVector axis; float factor; MShapeManipulator sm; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } factor = 0.01*_mouseDXF; if(factor <= -0.2) factor = -0.2; switch(_selectedAxis) { case MGLView::XAxis: axis = MDocument::get()->getSelectedShape()->getDirection(); sm.set(MDocument::get()->getSelectedShape()); sm.scale(1.0 + factor, axis); break; case MGLView::YAxis: axis = MDocument::get()->getSelectedShape()->getUp() ^ MDocument::get()->getSelectedShape()->getDirection(); sm.set(MDocument::get()->getSelectedShape()); sm.scale(1.0 + factor, axis); break; case MGLView::ZAxis: axis = MDocument::get()->getSelectedShape()->getUp(); sm.set(MDocument::get()->getSelectedShape()); sm.scale(1.0 + factor, axis); break; case MGLView::NoAxis: sm.set(MDocument::get()->getSelectedShape()); sm.scale(1.0 + factor, e1); sm.scale(1.0 + factor, e2); sm.scale(1.0 + factor, e3); break; default: break; } MModelView::get()->repaint(); } void M3DView::onScaleShapeFinish(void) { _selectedAxis = MGLView::NoAxis; MDocument::get()->unlock(); } void M3DView::onSelectVertexInit(void) { MLine ray; if(!MDocument::get()->getSelectedShape()) return; MItemManipulator::get()->setEraseVertexTo(false); if((_state & RightButton)) { MItemManipulator::get()->setEraseVertexTo(true); } if((_state & ControlButton)) { } else { MItemManipulator::get()->clearVertexStack(); } ray = _camera.getViewRay(_newMouseX, _newMouseY); MItemManipulator::get()->selectVertices(ray); MModelView::get()->repaint(); } void M3DView::onSelectVertexPerform(void) { MLine ray; if(!MDocument::get()->getSelectedShape()) return; ray = _camera.getViewRay(_newMouseX, _newMouseY); MItemManipulator::get()->selectVertices(ray); MModelView::get()->repaint(); } void M3DView::onSelectVertexFinish(void) { } void M3DView::onCreateVertex(void) { } void M3DView::onCreateTriangle(void) { int i1, i2, i3; MLine ray; if(!MDocument::get()->getSelectedShape()) return; if(MDocument::get()->getSelectedShape()) { if(MItemManipulator::get()->getVertexStackSize() < 3) { MItemManipulator::get()->setEraseVertexTo(false); ray = _camera.getViewRay(_newMouseX, _newMouseY); MItemManipulator::get()->selectVertices(ray); } if(MItemManipulator::get()->getVertexStackSize() >= 3) { i1 = MItemManipulator::get()->getVertexStackEntry(0); i2 = MItemManipulator::get()->getVertexStackEntry(1); i3 = MItemManipulator::get()->getVertexStackEntry(2); MDocument::get()->commit(); MDocument::get()->getSelectedShape()->addFacet(new MFacet(i1, i2, i3)); MItemManipulator::get()->clearVertexStack(); } MModelView::get()->repaint(); } } void M3DView::onMoveVertexInit(void) { MLine viewRay; if(!MDocument::get()->getSelectedShape()) return; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onMoveVertexPerform(void) { MVector dir; float way; unsigned int i; MVector newPosition; MVector dx; MVertex *v; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } way = 0.1*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: dx = MDocument::get()->getSelectedShape()->getDirection(); break; case MGLView::YAxis: dx = MDocument::get()->getSelectedShape()->getDirection() ^ MDocument::get()->getSelectedShape()->getUp(); break; case MGLView::ZAxis: dx = MDocument::get()->getSelectedShape()->getUp(); break; default: break; } dx = way*dx; if(_selectedAxis) { for(i = 0; i < MItemManipulator::get()->getVertexStackSize(); i++) { v = MDocument::get()->getSelectedShape()->getVertex(MItemManipulator::get()->getVertexStackEntry(i)); newPosition = v->getPosition() + dx; v->setPosition(newPosition); } } MModelView::get()->repaint(); } void M3DView::onMoveVertexFinish(void) { unsigned int i; MVector newPosition; MVertex *v; MDocument::get()->unlock(); for(i = 0; i < MItemManipulator::get()->getVertexStackSize(); i++) { v = MDocument::get()->getSelectedShape()->getVertex(MItemManipulator::get()->getVertexStackEntry(i)); newPosition = v->getPosition(); MCoordinateSystem::get()->snap(newPosition); v->setPosition(newPosition); } MModelView::get()->repaint(); } void M3DView::onRotateVertexInit(void) { MLine viewRay; if(!MDocument::get()->getSelectedShape()) return; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onRotateVertexPerform(void) { MVector dir; float angle; unsigned int i; MVector pos, newPosition; MVector axis; MVertex *v; MMatrix R; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } angle = 3.0*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: axis = MDocument::get()->getSelectedItem()->getDirection(); break; case MGLView::YAxis: axis = MDocument::get()->getSelectedItem()->getDirection() ^ MDocument::get()->getSelectedItem()->getUp(); break; case MGLView::ZAxis: axis = MDocument::get()->getSelectedItem()->getUp(); break; default: angle = 0.0; break; } R.loadRotation(angle, axis); if(_selectedAxis) { pos = MDocument::get()->getSelectedItem()->getPosition(); for(i = 0; i < MItemManipulator::get()->getVertexStackSize(); i++) { v = MDocument::get()->getSelectedShape()->getVertex(MItemManipulator::get()->getVertexStackEntry(i)); newPosition = R*(v->getPosition() - pos) + pos; v->setPosition(newPosition); } } MModelView::get()->repaint(); } void M3DView::onRotateVertexFinish(void) { unsigned int i; MVector newPosition; MVertex *v; MDocument::get()->unlock(); for(i = 0; i < MItemManipulator::get()->getVertexStackSize(); i++) { v = MDocument::get()->getSelectedShape()->getVertex(MItemManipulator::get()->getVertexStackEntry(i)); newPosition = v->getPosition(); MCoordinateSystem::get()->snap(newPosition); v->setPosition(newPosition); } MModelView::get()->repaint(); } void M3DView::onScaleVertexInit(void) { MLine viewRay; if(!MDocument::get()->getSelectedShape()) return; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onScaleVertexPerform(void) { MVector dir; float way; unsigned int i; MVector newPosition; MVertex *v; MVector pos, dx; MMatrix S; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } way = 0.1*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: dx = way*MDocument::get()->getSelectedItem()->getDirection(); break; case MGLView::YAxis: dx = way*(MDocument::get()->getSelectedItem()->getDirection() ^ MDocument::get()->getSelectedItem()->getUp()); break; case MGLView::ZAxis: dx = way*MDocument::get()->getSelectedItem()->getUp(); break; default: dx[0] = way; dx[1] = way; dx[2] = way; break; } S.loadDiagonal(1.0 + dx[0], 1.0 + dx[1], 1.0 + dx[2]); pos = MDocument::get()->getSelectedItem()->getPosition(); for(i = 0; i < MItemManipulator::get()->getVertexStackSize(); i++) { v = MDocument::get()->getSelectedShape()->getVertex(MItemManipulator::get()->getVertexStackEntry(i)); newPosition = S*(v->getPosition() - pos) + pos; v->setPosition(newPosition); } MModelView::get()->repaint(); } void M3DView::onScaleVertexFinish(void) { // unsigned int i; MVector newPosition; // MVertex *v; MDocument::get()->unlock(); MModelView::get()->repaint(); } void M3DView::onMagnetInit(void) { MLine viewRay; if(!MDocument::get()->getSelectedShape()) return; viewRay = _camera.getViewRay(_newMouseX, _newMouseY); // adaptive radius pending.. _selectedAxis = MItemManipulator::get()->findAxis(viewRay, 0.1); } void M3DView::onMagnetPerform(void) { MVector dir; float way, displacement, lambda; MVector p1, p2; MVector newPosition; MVector dx; MVertex *v; unsigned int i; if(_mouseDS > 0.0) { MDocument::get()->commit(); MDocument::get()->lock(); } way = 0.1*_mouseDX; switch(_selectedAxis) { case MGLView::XAxis: dx = MDocument::get()->getSelectedShape()->getDirection(); break; case MGLView::YAxis: dx = MDocument::get()->getSelectedShape()->getDirection() ^ MDocument::get()->getSelectedShape()->getUp(); break; case MGLView::ZAxis: dx = MDocument::get()->getSelectedShape()->getUp(); break; default: break; } dx = way*dx; p1 = MDocument::get()->getSelectedShape()->getPosition(); lambda = 1.0 / (MMainWindow::get()->getToolStrength() * MCoordinateSystem::get()->getSize() / 10.0); if(_selectedAxis) { if(MItemManipulator::get()->getVertexStackSize() > 0) { for(i = 0; i < MItemManipulator::get()->getVertexStackSize(); i++) { v = MDocument::get()->getSelectedShape()->getVertex(MItemManipulator::get()->getVertexStackEntry(i)); p2 = v->getPosition(); displacement = exp(-lambda*dist(p1, p2)); v->setPosition(v->getPosition() + displacement*dx); } } else { QPtrList &vertices = MDocument::get()->getSelectedShape()->getVertexList(); for(v = vertices.first(); v; v = vertices.next()) { p2 = v->getPosition(); displacement = exp(-lambda*dist(p1, p2)); v->setPosition(v->getPosition() + displacement*dx); } } } MModelView::get()->repaint(); } void M3DView::onMagnetFinish(void) { MVector newPosition; MDocument::get()->unlock(); MModelView::get()->repaint(); } void M3DView::onFlipEdge(void) { int i1, i2, i3, i4; int ti1, ti2, ti3, ti4, ti5, ti6; MLine ray; QPtrList flipFacets; MFacet *f; if(!MDocument::get()->getSelectedShape()) return; if(MDocument::get()->getSelectedShape()) { if(MItemManipulator::get()->getVertexStackSize() < 2) { MItemManipulator::get()->setEraseVertexTo(false); ray = _camera.getViewRay(_newMouseX, _newMouseY); MItemManipulator::get()->selectVertices(ray); } if(MItemManipulator::get()->getVertexStackSize() >= 2) { i1 = MItemManipulator::get()->getVertexStackEntry(0); i2 = MItemManipulator::get()->getVertexStackEntry(1); QPtrList &facetList = MDocument::get()->getSelectedShape()->getFacetList(); for(f = facetList.first(); f; f = facetList.next()) { if(f->containsVertex(i1) && f->containsVertex(i2)) { flipFacets.append(f); } } if(flipFacets.count() >= 2) { MDocument::get()->commit(); i3 = flipFacets.at(0)->remainingVertex(i1, i2); i4 = flipFacets.at(1)->remainingVertex(i1, i2); ti1 = flipFacets.at(0)->vertex2TextureVertex(i1); ti2 = flipFacets.at(0)->vertex2TextureVertex(i3); ti3 = flipFacets.at(1)->vertex2TextureVertex(i4); ti4 = flipFacets.at(1)->vertex2TextureVertex(i2); ti5 = flipFacets.at(1)->vertex2TextureVertex(i4); ti6 = flipFacets.at(0)->vertex2TextureVertex(i3); flipFacets.at(0)->setVertexRef(0, i1); flipFacets.at(0)->setVertexRef(1, i3); flipFacets.at(0)->setVertexRef(2, i4); flipFacets.at(0)->setTextureVertexRef(0, ti1); flipFacets.at(0)->setTextureVertexRef(1, ti2); flipFacets.at(0)->setTextureVertexRef(2, ti3); flipFacets.at(1)->setVertexRef(0, i2); flipFacets.at(1)->setVertexRef(1, i4); flipFacets.at(1)->setVertexRef(2, i3); flipFacets.at(1)->setTextureVertexRef(0, ti4); flipFacets.at(1)->setTextureVertexRef(1, ti5); flipFacets.at(1)->setTextureVertexRef(2, ti6); } MItemManipulator::get()->clearVertexStack(); } MModelView::get()->repaint(); } } void M3DView::onSnapToMaster(void) { int i, j; MLine ray; if(!MDocument::get()->getSelectedShape()) return; if(MDocument::get()->getSelectedShape() == MDocument::get()->getMaster()) return; if(MDocument::get()->getSelectedShape()) { ray = _camera.getViewRay(_newMouseX, _newMouseY); if(MItemManipulator::get()->getVertexStackSize() < 1) { MItemManipulator::get()->setEraseVertexTo(false); MItemManipulator::get()->selectVertices(ray); } else { i = MItemManipulator::get()->getVertexStackEntry(0); j = MItemManipulator::get()->selectMasterVertex(ray); if(j >= 0) { MDocument::get()->commit(); MDocument::get()->getSelectedShape()->getVertex(i)->setPosition(MDocument::get()->getMaster()->getVertex(j)->getPosition()); } MItemManipulator::get()->clearVertexStack(); } MModelView::get()->repaint(); } } void M3DView::onRotateView(void) { if(abs(_mouseDX) > abs(_mouseDY)) { rotatePhi((float)_mouseDX); } else { rotateTheta((float)_mouseDY); } updateGL(); } void M3DView::onZoomView(void) { float nearClippingDistance = MPreferences::get()->getNCD(); float farClippingDistance = MPreferences::get()->getFCD(); if((_mouseDY < 0) && (_cameraR < 0.7*farClippingDistance)) { _cameraR *= 1.05; } if((_mouseDY > 0) && (_cameraR > 2.0*nearClippingDistance)) { _cameraR *= 0.95; } updateGL(); } void M3DView::onMoveView(void) { if(abs(_mouseDX) > abs(_mouseDY)) { _lookAt -= (0.2*(float)_mouseDX)*(_camera.getDirection() ^ _camera.getUp()); } else { _lookAt += (0.2*(float)_mouseDY)*_camera.getUp(); } updateGL(); } void M3DView::onResetView(void) { _cameraR = MPreferences::get()->getRDefault(); _cameraPhi = MPreferences::get()->getPhiDefault(); _cameraTheta = MPreferences::get()->getThetaDefault(); _lookAt = O; updateGL(); } void M3DView::rotatePhi(float angle) { if(angle > 5.0) angle = 5.0; if(angle < -5.0) angle = -5.0; _cameraPhi -= angle; if(_cameraPhi < 0.0) _cameraPhi += 360.0; if(_cameraPhi > 360.0) _cameraPhi -= 360.0; } void M3DView::rotateTheta(float angle) { if(angle > 5.0) angle = 5.0; if(angle < -5.0) angle = -5.0; _cameraTheta -= angle; if(_cameraTheta >= 175.0) _cameraTheta = 175.0; if(_cameraTheta < 5.0) _cameraTheta = 5.0; }