我有以下测试代码,我有一个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()
}
}