如何使用JavaFX JCSG和FXyz在网格中创建一个洞

时间:2015-07-25 06:58:22

标签: javafx scalafx javafx-3d

我试图通过使用以下测试代码来理解JCSG库,我将采取不同之处 在FXyz网格/布料和球体之间,在网格中创建一个洞,以便显示 底层网格图像。有可能这样做,如果是这样的话怎么样? 我的所有尝试都会产生一个红圈。

import org.fxyz.shapes.primitives.SpheroidMesh
import org.fxyz.utils.MeshUtils
import org.fxyz.shapes.complex.cloth.ClothMesh
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.scene.image.Image
import scalafx.scene.paint.PhongMaterial
import scalafx.scene.shape._
import scalafx.scene.{Group, PerspectiveCamera, Scene, SceneAntialiasing}
import scalafx.scene.paint.Color
import scala.collection.JavaConversions._

object ClothTest1 extends JFXApp {
  stage = new PrimaryStage {
    scene = new Scene(600, 600, true, SceneAntialiasing.Balanced) {
      fill = Color.LightGray
      val rose = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Redoute_-_Rosa_gallica_purpuro-violacea_magna.jpg/800px-Redoute_-_Rosa_gallica_purpuro-violacea_magna.jpg"
      val img = new Image(rose, 400, 400, false, true)

      val meshView = new ClothMesh(4, 4, 400, 400)
      meshView.setDrawMode(DrawMode.Fill)
      meshView.setCullFace(CullFace.None)
      meshView.setStyle("-fx-background-color: #00000000") // transparent
      meshView.setWidth(img.width.value)
      meshView.setHeight(img.height.value)
      meshView.setMaterial(new PhongMaterial(Color.White, img, null, null, null))

      val fxyzSphere = new SpheroidMesh(120.0) {
        setDrawMode(DrawMode.Fill)
        setStyle("-fx-background-color: #00000000") // transparent
      }
      val csgHole = MeshUtils.mesh2CSG(fxyzSphere.getMesh())
      val csgMesh = MeshUtils.mesh2CSG(meshView.getMesh())
      val fxMesh = csgMesh.difference(csgHole).toJavaFXMesh.getAsMeshViews.head

      root = new Group() {
        children += fxMesh
        translateX = 250
        translateY = 250
      }
      camera = new PerspectiveCamera(false)
    }
  }
}

1 个答案:

答案 0 :(得分:1)

FXyz和JSCG是不同的JavaFX 3D库。为了能够将对象从一个交换到另一个,我们在FXyz中创建了这个method

public static CSG mesh2CSG(MeshView mesh);

获取JavaFX 3D对象的TriangleMesh(不是来自API上的那些)并通过填充其多边形和顶点生成CSG,但不带纹理。所以在这个过程中,初始对象所具有的任何纹理都会丢失。

据我所知,JCSG原语没有纹理。

所以我们还在FXyz上添加了这个classCSGMesh,以便根据CSG原语创建TriangleMesh使用接近纹理。

由于显而易见的原因,纹理坐标基于主体的几何形状,一旦执行布尔运算,您就无法控制结果。

使用CSGMesh,我们创建一个TexturedMesh,允许:

  • 任何漫反射颜色
  • 基于顶点坐标的任何密度图,等高线图
  • 任何基于面孔的密度图

但它不允许带有图像或图案的漫反射贴图。

现在你可以拍摄两个FXyz 3D形状,将它们转换为CSG基元,对它们执行布尔运算,并且生成的CSG基元可以转换回纹理' FXyz对象,但没有真正的纹理坐标。

举个例子:

鉴于这两种FXyz形状:

CuboidMesh cuboidMesh = new CuboidMesh(400f,400f,4f,4,new Point3D(0f, 0f, 0f));
cuboidMesh.setTextureModeNone(Color.FIREBRICK);

SegmentedSphereMesh spheroidMesh = new SegmentedSphereMesh(40,0,0,120,new Point3D(0f,0f,0f)); 
spheroidMesh.setTextureModeNone(Color.GREENYELLOW);

Two FXyz shapes

您可以生成两者的CSG对象,并获得差异:

CSG csgMesh = MeshUtils.mesh2CSG(cuboidMesh.getMesh());
CSG csgHole = MeshUtils.mesh2CSG(spheroidMesh.getMesh());
CSG difference = csgMesh.difference(csgHole);

将此原语转换为TexturedMesh

CSGMesh meshResult = new CSGMesh(difference);
meshResult.setTextureModeNone(Color.FORESTGREEN);

Resulting FXyz shape

你可以看到,生成的网格很难设置纹理坐标。

最后,我们可以为每个顶点应用具有(x,y,z)坐标函数的密度图:

meshResult.setTextureModeVertices3D(1530,p->(double)p.x*p.y);

Density map

除非你有一些标准,比如我们有一个2D网格(Z值可以忽略),我们可以用顶点的(x,y)坐标映射纹理坐标...这在FXyz上还没有完成,你欢迎尝试。