如何控制Javafx scalafx FXyz 3D形状

时间:2015-08-23 05:30:10

标签: javafx scalafx javafx-3d

我有以下测试代码,我有一个ClothMesh(来自FXyz lib) 可以拖动,旋转和拖动我的圆形手柄。一切顺利,FXyz很棒。现在我想使用SegmentedSphereMesh,除了我的圆形手柄是2D并且没有围绕球体缠绕之外,它主要起作用。我知道混合2D和3D的可能问题。然而,它是如此接近工作;如何让我的手柄与球体一起工作,或者是另一种方法来做同样的功能。 注意,我不想通过移动相机来控制形状/网格。

import org.fxyz.shapes.complex.cloth.ClothMesh
import org.fxyz.shapes.primitives.SegmentedSphereMesh

import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.beans.property.DoubleProperty
import scalafx.collections.ObservableFloatArray
import scalafx.scene.image.Image
import scalafx.scene.input.{MouseButton, MouseEvent}
import scalafx.scene.paint.PhongMaterial
import scalafx.scene.shape._
import scalafx.scene.transform.Rotate
import scalafx.scene._
import scalafx.scene.paint.Color

/**
 * left mouse to drag the meshView and also to drag the handles
 * right mouse drag + ctrl to rotate about X axis
 * right mouse drag + alt to rotate about Y axis
 * right mouse drag + shift to rotate about Z axis
 */

object ClothTest2 extends JFXApp {
  private var dx = 0.0
  private var dy = 0.0

  stage = new PrimaryStage {
    scene = new Scene(600, 600, true, SceneAntialiasing.Balanced) {
      fill = Color.LightGray
      val testImg = "https://upload.wikimedia.org/wikipedia/commons/c/c4/PM5544_with_non-PAL_signals.png"
      val img = new Image(testImg, 400, 400, false, true)

      val meshView = new SegmentedSphereMesh(20, 4, 2, 200d)
    //  val meshView = new ClothMesh(4, 4, 200, 200, 0.5, 0.5, 1.0)

      meshView.setDrawMode(DrawMode.Fill)
      meshView.setCullFace(CullFace.None)
      meshView.style = "-fx-background-color: #00000000"
      meshView.setMaterial(new PhongMaterial(Color.White, img, null, null, null))
      val controller = new MeshController(meshView.getMesh().asInstanceOf[javafx.scene.shape.TriangleMesh].points)
      val viewGroup = new Group(meshView, controller)
      root = new Group(new AmbientLight(Color.White), viewGroup) { translateX = 70; translateY = 70 }
      camera = new PerspectiveCamera(true) {
        nearClip = 0.0
        farClip = 100000.0
        fieldOfView = 42
        verticalFieldOfView = true
        translateZ = -900
      }
      val rotHandler = new RotHandler(viewGroup)
      onMouseDragged = (event: MouseEvent) => {
        rotHandler.onMouseDragged(event)
        if (event.button == MouseButton.PRIMARY) {
          viewGroup.layoutX = event.sceneX + dx
          viewGroup.layoutY = event.sceneY + dy
          event.consume()
        }
      }
      onMousePressed = (event: MouseEvent) => {
        rotHandler.onMousePressed(event)
        dx = viewGroup.layoutX.value - event.sceneX
        dy = viewGroup.layoutY.value - event.sceneY
        event.consume()
      }
    }
  }
}

class CircleHandle(color: Color) extends Circle {
  radius = 8
  var dx = 0.0
  var dy = 0.0
  fill <== when(hover) choose Color.Red.deriveColor(1, 1, 1, 0.4) otherwise color.deriveColor(1, 1, 1, 0.4)
  strokeWidth <== when(hover) choose 3 otherwise 2
  stroke = color
  onMousePressed = (event: MouseEvent) => {
    dx = centerX.value - event.x
    dy = centerY.value - event.y
    event.consume()
  }
  onMouseDragged = (event: MouseEvent) => {
    centerX = event.x + dx
    centerY = event.y + dy
    event.consume()
  }
}

class MeshController(thePoints: ObservableFloatArray) extends Group {
  children = for (i <- 0 until thePoints.size by 3) yield new CircleHandle(Color.Yellow) {
      centerX() = thePoints.get(i)
      centerX.onChange { (obs, oldVal, newVal) => thePoints.set(i, newVal.floatValue()) }
      centerY() = thePoints.get(i + 1)
      centerY.onChange { (obs, oldVal, newVal) => thePoints.set(i + 1, newVal.floatValue()) }
    }
}

class RotHandler(val viewer: Group) {
  private val angleX = DoubleProperty(0)
  private val angleY = DoubleProperty(0)
  private val angleZ = DoubleProperty(0)
  private var anchorX = 0d
  private var anchorY = 0d
  private val rotX = new Rotate { angle <== angleX; axis = Rotate.XAxis }
  private val rotY = new Rotate { angle <== angleY; axis = Rotate.YAxis }
  private val rotZ = new Rotate { angle <== angleZ; axis = Rotate.ZAxis }
  viewer.transforms = Seq(rotX, rotY, rotZ)
  def onMousePressed(event: MouseEvent) = {
    anchorX = event.sceneX
    anchorY = event.sceneY
    event.consume()
  }
  def onMouseDragged(event: MouseEvent) = {
    // right mouse only
    if (event.button == MouseButton.SECONDARY) {
      event match {
        // rotation about the Y axis, dragging the mouse in the x direction
        case ev if ev.altDown => angleY() = anchorX - event.sceneX
        // rotation about the X axis, dragging the mouse in the y direction
        case ev if ev.controlDown => angleX() = anchorY - event.sceneY
        // rotation about the Z axis, dragging the mouse in the x direction
        case ev if ev.shiftDown => angleZ() = anchorX - event.sceneX
        case _ => // ignore everything else
      }
    }
    event.consume()
  }
}

0 个答案:

没有答案