1

我试图通过使用以下测试代码来理解 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)
    }
  }
}
4

1 回答 1

1

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

public static CSG mesh2CSG(MeshView mesh);

它采用TriangleMeshJavaFX 3D 对象(不是来自 API 上的对象)并通过填充其多边形和顶点来生成 CSG 对象,但没有纹理。所以在这个过程中,初始对象所拥有的任何纹理都会丢失。

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

所以我们还在FXyz: 上添加了这个CSGMesh,以便创建一个TriangleMesh基于 CSG 基元的,具有接近纹理的东西。

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

使用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);

两个 FXyz 形状

您可以生成两者的 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);

生成的 FXyz 形状

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

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

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

密度图

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

于 2015-07-25T10:00:39.190 回答