RotateMeshTool.java :  » Graphic-3D » Art-of-Illusion » ArtOfIllusion » Java Open Source

Java Open Source » Graphic 3D » Art of Illusion 
Art of Illusion » ArtOfIllusion » RotateMeshTool.java
/* Copyright (C) 1999-2007 by Peter Eastman

   This program 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.

   This program 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. */

package artofillusion;

import artofillusion.math.*;
import artofillusion.object.*;
import artofillusion.ui.*;
import artofillusion.ui.NinePointManipulator.*;
import buoy.event.*;
import java.awt.*;

/** RotateMeshTool is an EditingTool used for rotating the vertices of TriangleMesh objects. */

public class RotateMeshTool extends MeshEditingTool
{
  private boolean dragInProgress, selectionCanChange;
  private Point clickPoint;
  private Vec3 rotCenter, baseVertPos[];
  private int hdirection, vdirection, whichAxis;
  private UndoRecord undo;
  private final NinePointManipulator manipulator;
  private int lastSelectionDistance[];

  public static final int HANDLE_SIZE = 5;
  private static final double DRAG_SCALE = Math.PI/360.0;
  private static final int XAXIS = 0;
  private static final int YAXIS = 1;
  private static final int ZAXIS = 2;

  public RotateMeshTool(EditingWindow fr, MeshEditController controller, boolean only2D)
  {
    super(fr, controller);
    initButton("rotatePoints");
    if (only2D)
      manipulator = new NinePointManipulator(new Image[] {
        NinePointManipulator.ROTATE_TOPLEFT, null, NinePointManipulator.ROTATE_TOPRIGHT,
        null, null, null,
        NinePointManipulator.ROTATE_BOTTOMLEFT, null, NinePointManipulator.ROTATE_BOTTOMRIGHT});
    else
      manipulator = new NinePointManipulator(new Image[] {
        NinePointManipulator.ROTATE_TOPLEFT, NinePointManipulator.ROTATE_TOP, NinePointManipulator.ROTATE_TOPRIGHT,
        NinePointManipulator.ROTATE_LEFT, null, NinePointManipulator.ROTATE_RIGHT,
        NinePointManipulator.ROTATE_BOTTOMLEFT, NinePointManipulator.ROTATE_BOTTOM, NinePointManipulator.ROTATE_BOTTOMRIGHT});
    manipulator.addEventLink(HandlePressedEvent.class, this, "handlePressed");
    manipulator.addEventLink(HandleDraggedEvent.class, this, "handleDragged");
    manipulator.addEventLink(HandleReleasedEvent.class, this, "handleReleased");
  }

  public void activate()
  {
    super.activate();
    lastSelectionDistance = null;
    checkForSelectionChanged();
  }

  public int whichClicks()
  {
    return ALL_CLICKS;
  }

  public boolean allowSelectionChanges()
  {
    return selectionCanChange;
  }

  private void checkForSelectionChanged()
  {
    // See whether the selection has changed.

    int selected[] = controller.getSelectionDistance();
    boolean changed = (lastSelectionDistance == null || lastSelectionDistance.length != selected.length);
    for (int i = 0; !changed && i < selected.length; i++)
      changed = (lastSelectionDistance[i] != selected[i]);
    lastSelectionDistance = selected;
    if (!changed)
      return;

    // It has, so update the center point.

    Camera cam = theWindow.getView().getCamera();
    BoundingBox bounds = findSelectionBounds(cam);
    if (bounds != null)
    {
      rotCenter = new Vec3((bounds.minx+bounds.maxx)/2.0, (bounds.miny+bounds.maxy)/2.0, (bounds.minz+bounds.maxz)/2.0);
      rotCenter = cam.getViewToWorld().times(rotCenter);
    }
  }

  public String getToolTipText()
  {
    return Translate.text("rotateMeshTool.tipText");
  }

  public void drawOverlay(ViewerCanvas view)
  {
    checkForSelectionChanged();
    BoundingBox selectionBounds = findSelectionBounds(view.getCamera());
    if (!dragInProgress)
    {
      if (selectionBounds != null)
      {
        manipulator.draw(view, selectionBounds);
        theWindow.setHelpText(Translate.text("rotateMeshTool.helpText"));
      }
      else
        theWindow.setHelpText(Translate.text("rotateMeshTool.errorText"));
    }
    if (selectionBounds != null)
    {
      Vec2 p = view.getCamera().getWorldToScreen().timesXY(rotCenter);
      int px = (int) p.x;
      int py = (int) p.y;
      view.drawLine(new Point(px-HANDLE_SIZE, py-HANDLE_SIZE), new Point(px+HANDLE_SIZE, py+HANDLE_SIZE), ViewerCanvas.handleColor);
      view.drawLine(new Point(px-HANDLE_SIZE, py+HANDLE_SIZE), new Point(px+HANDLE_SIZE, py-HANDLE_SIZE), ViewerCanvas.handleColor);
    }
  }

  public void mousePressed(WidgetMouseEvent e, ViewerCanvas view)
  {
    if (e.isControlDown())
    {
      // For a control-click, just move the center of rotation.

      double depth = view.getCamera().getWorldToView().times(rotCenter).z;
      rotCenter = view.getCamera().convertScreenToWorld(e.getPoint(), depth);
      selectionCanChange = false;
      view.repaint();
      return;
    }
    BoundingBox selectionBounds = findSelectionBounds(view.getCamera());
    dragInProgress = false;
    if (selectionBounds != null)
      dragInProgress = manipulator.mousePressed(e, view, selectionBounds);
    selectionCanChange = !dragInProgress;
  }

  public void mouseDragged(WidgetMouseEvent e, ViewerCanvas view)
  {
    manipulator.mouseDragged(e, view);
  }

  public void mouseReleased(WidgetMouseEvent e, ViewerCanvas view)
  {
    manipulator.mouseReleased(e, view);
  }

  protected void handlePressed(HandlePressedEvent ev)
  {
    Mesh mesh = (Mesh) controller.getObject().getObject();
    clickPoint =  ev.getMouseEvent().getPoint();
    HandlePosition handle = ev.getHandle();
    if (!handle.isEast() && !handle.isWest())
      {
         whichAxis = XAXIS;
         hdirection = 0;
         vdirection = -1;
      }
    else if (!handle.isNorth() && !handle.isSouth())
      {
         whichAxis = YAXIS;
         vdirection = 0;
         hdirection = 1;
      }
    else
      {
         whichAxis = ZAXIS;
         if (handle.isWest())
           vdirection = -1;
         else
           vdirection = 1;
         if (handle.isNorth())
           hdirection = 1;
         else
           hdirection = -1;
      }
    baseVertPos = mesh.getVertexPositions();
  }
  
  protected void handleDragged(HandleDraggedEvent ev)
  {
    Mesh mesh = (Mesh) controller.getObject().getObject();
    Point dragPoint = ev.getMouseEvent().getPoint();
    if (undo == null)
      undo = new UndoRecord(theWindow, false, UndoRecord.COPY_VERTEX_POSITIONS, new Object [] {mesh, mesh.getVertexPositions()});
    double angle = DRAG_SCALE*((dragPoint.x-clickPoint.x)*hdirection + (dragPoint.y-clickPoint.y)*vdirection);
    Vec3 v[] = findRotatedPositions(baseVertPos, angle, (MeshViewer) ev.getView());
    mesh.setVertexPositions(v);
    controller.objectChanged();
    theWindow.updateImage();
    theWindow.setHelpText(Translate.text("rotateMeshTool.dragText", Double.toString(Math.round(angle*1e5*180.0/Math.PI)/1e5)));
  }

  protected void handleReleased(HandleReleasedEvent ev)
  {
    Mesh mesh = (Mesh) controller.getObject().getObject();
    Point dragPoint = ev.getMouseEvent().getPoint();

    double angle = DRAG_SCALE*((dragPoint.x-clickPoint.x)*hdirection + (dragPoint.y-clickPoint.y)*vdirection);
    if (undo != null)
      theWindow.setUndoRecord(undo);
    Vec3 v[] = findRotatedPositions(baseVertPos, angle, (MeshViewer) ev.getView());
    mesh.setVertexPositions(v);
    controller.objectChanged();
    theWindow.updateImage();
    undo = null;
    baseVertPos = null;
    dragInProgress = false;
  }

  /**
   * Find the new positions of the vertices after scaling.
   */

  private Vec3 [] findRotatedPositions(Vec3 vert[], double angle, MeshViewer view)
  {
    Vec3 v[] = new Vec3 [vert.length], axis;
    int selected[] = controller.getSelectionDistance();
    Camera cam = view.getCamera();
    CoordinateSystem coords = view.getDisplayCoordinates();
    Mat4 m;
    int i;
    
    // Determine whether the coordinate system is right or left handed.
    
    Vec3 xdir = cam.getWorldToView().timesDirection(Vec3.vx());
    Vec3 ydir = cam.getWorldToView().timesDirection(Vec3.vy());
    Vec3 zdir = cam.getWorldToView().timesDirection(Vec3.vz());
    if (xdir.cross(ydir).dot(zdir) < 0.0)
      angle = -angle;
    
    // Find the transformation matrix.
    
    m = coords.fromLocal();
    m = Mat4.translation(-rotCenter.x, -rotCenter.y, -rotCenter.z).times(m);
    if (whichAxis == XAXIS)
      axis = cam.getViewToWorld().timesDirection(Vec3.vx());
    else if (whichAxis == YAXIS)
      axis = cam.getViewToWorld().timesDirection(Vec3.vy());
    else
      axis = cam.getViewToWorld().timesDirection(Vec3.vz());
    m = Mat4.axisRotation(axis, angle).times(m);
    m = Mat4.translation(rotCenter.x, rotCenter.y, rotCenter.z).times(m);
    m = coords.toLocal().times(m);
    
    // Determine the deltas.
    
    for (i = 0; i < vert.length; i++)
      {
         if (selected[i] == 0)
           v[i] = m.times(vert[i]).minus(vert[i]);
         else
           v[i] = new Vec3();
      }
    if (theFrame instanceof MeshEditorWindow)
      ((MeshEditorWindow) theFrame).adjustDeltas(v);
    for (i = 0; i < vert.length; i++)
      v[i].add(vert[i]);
    return v;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.