Package artofillusion

Source Code of artofillusion.TaperMeshTool

/* 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.*;

/** TaperMeshTool is an EditingTool used for tapering the vertices of TriangleMesh objects. */

public class TaperMeshTool extends MeshEditingTool
{
  private boolean dragInProgress, taperAll, towardCenter;
  private Point clickPoint;
  private HandlePosition whichHandle;
  private double boundsHeight, boundsWidth;
  private Vec3 baseVertPos[];
  private UndoRecord undo;
  private final NinePointManipulator manipulator;

  public static final int HANDLE_SIZE = 5;

  public TaperMeshTool(EditingWindow fr, MeshEditController controller)
  {
    super(fr, controller);
    initButton("taperPoints");
    manipulator = new NinePointManipulator(new Image[] {
      NinePointManipulator.ARROWS_S_E, null, NinePointManipulator.ARROWS_S_W,
      null, null, null,
      NinePointManipulator.ARROWS_N_E, null, NinePointManipulator.ARROWS_N_W});
    manipulator.addEventLink(HandlePressedEvent.class, this, "handlePressed");
    manipulator.addEventLink(HandleDraggedEvent.class, this, "handleDragged");
    manipulator.addEventLink(HandleReleasedEvent.class, this, "handleReleased");
  }

  public int whichClicks()
  {
    return ALL_CLICKS;
  }

  public boolean allowSelectionChanges()
  {
    return !dragInProgress;
  }

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

  public void drawOverlay(ViewerCanvas view)
  {
    BoundingBox selectionBounds = findSelectionBounds(view.getCamera());
    if (selectionBounds != null)
    {
      if (!dragInProgress)
        manipulator.draw(view, selectionBounds);
      theWindow.setHelpText(Translate.text("taperMeshTool.helpText"));
    }
    else
      theWindow.setHelpText(Translate.text("taperMeshTool.errorText"));
  }

  public void mousePressed(WidgetMouseEvent e, ViewerCanvas view)
  {
    BoundingBox selectionBounds = findSelectionBounds(view.getCamera());
    dragInProgress = false;
    if (selectionBounds != null)
      dragInProgress = manipulator.mousePressed(e, view, selectionBounds);
  }

  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();
    whichHandle = ev.getHandle();
    taperAll = ev.getMouseEvent().isShiftDown();
    towardCenter = ev.getMouseEvent().isControlDown();
    Rectangle r = ev.getScreenBounds();
    boundsHeight = (double) r.height;
    boundsWidth = (double) r.width;
    baseVertPos = mesh.getVertexPositions();
  }
 
  protected void handleDragged(HandleDraggedEvent ev)
  {
    Mesh mesh = (Mesh) controller.getObject().getObject();
    if (undo == null)
      undo = new UndoRecord(theWindow, false, UndoRecord.COPY_VERTEX_POSITIONS, new Object [] {mesh, mesh.getVertexPositions()});
    Vec3 v[] = findTaperedPositions(baseVertPos, ev.getMouseEvent().getPoint(), ev.getSelectionBounds(), (MeshViewer) ev.getView());
    mesh.setVertexPositions(v);
    controller.objectChanged();
    theWindow.updateImage();
  }

  protected void handleReleased(HandleReleasedEvent ev)
  {
    Mesh mesh = (Mesh) controller.getObject().getObject();
    if (undo != null)
      theWindow.setUndoRecord(undo);
    Vec3 v[] = findTaperedPositions(baseVertPos, ev.getMouseEvent().getPoint(), ev.getSelectionBounds(), (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 [] findTaperedPositions(Vec3 vert[], Point pos, BoundingBox bounds, MeshViewer view)
  {
    Vec3 v[] = new Vec3 [vert.length];
    int selected[] = controller.getSelectionDistance();
    Camera cam = view.getCamera();
    double clickX, clickY, posX, posY, taper;
    Vec3 center;
    Mat4 m1, m2;
    int i, direction;
   
    clickX = (double) clickPoint.x;
    clickY = (double) clickPoint.y;
    posX = (double) pos.x;
    posY = (double) pos.y;
   
    // Figure out which way to taper the mesh, and toward which point.
   
    direction = (Math.abs(posX-clickX) > Math.abs(posY-clickY)) ? 0 : 1;
    center = new Vec3(0.0, 0.0, (bounds.minz+bounds.maxz)/2.0);
    if (bounds.minx == bounds.maxx || bounds.miny == bounds.maxy)
      taper = 0.0;
    else if (direction == 0)
      {
        if (towardCenter)
          center.x = (bounds.minx+bounds.maxx)/2.0;
        else if (whichHandle.isWest())
          center.x = bounds.minx;
        else
          center.x = bounds.maxx;
        if (whichHandle.isNorth())
          center.y = bounds.miny;
        else
          center.y = bounds.maxy;
        if (whichHandle.isWest())
          taper = (posX-clickX)/boundsWidth;
        else
          taper = (clickX-posX)/boundsWidth;
        if (taper > 1.0)
          taper = 1.0;
        if (whichHandle.isSouth())
          taper *= -1.0;
      }
    else
      {
        if (towardCenter)
          center.y = (bounds.miny+bounds.maxy)/2.0;
        else if (whichHandle.isNorth())
          center.y = bounds.miny;
        else
          center.y = bounds.maxy;
        if (whichHandle.isWest())
          center.x = bounds.minx;
        else
          center.x = bounds.maxx;
        if (whichHandle.isNorth())
          taper = (posY-clickY)/boundsHeight;
        else
          taper = (clickY-posY)/boundsHeight;
        if (taper > 1.0)
          taper = 1.0;
        if (whichHandle.isEast())
          taper *= -1.0;
      }

    // If the points are not being tapered, just copy them over.
   
    if (taper == 0.0)
      {
        for (i = 0; i < vert.length; i++)
          v[i] = new Vec3(vert[i]);
        return v;
      }

    // Find the transformation matrix.
   
    m1 = cam.getObjectToView();
    m1 = Mat4.translation(-center.x, -center.y, -center.z).times(m1);
    m2 = Mat4.translation(center.x, center.y, center.z);
    m2 = cam.getViewToWorld().times(m2);
    m2 = view.getDisplayCoordinates().toLocal().times(m2);
   
    // Determine the deltas.
   
    for (i = 0; i < vert.length; i++)
      {
        if (selected[i] == 0)
          {
            v[i] = m1.times(vert[i]);
            if (direction == 0)
              {
                v[i].x *= 1.0 - taper*v[i].y/(bounds.maxy-bounds.miny);
                if (taperAll)
                  v[i].z *= 1.0 - taper*v[i].y/(bounds.maxy-bounds.miny);
              }
            else
              {
                v[i].y *= 1.0 - taper*v[i].x/(bounds.maxx-bounds.minx);
                if (taperAll)
                  v[i].z *= 1.0 - taper*v[i].x/(bounds.maxx-bounds.minx);
              }
            v[i] = m2.times(v[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;
  }
}
TOP

Related Classes of artofillusion.TaperMeshTool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.