JavaFX3d:奇怪的剪辑或错误的z缓冲区,我猜



因此,我正在进行一个关于perlin噪声生成网格的小项目,除了渲染之外,所有项目都很好。我不知道我做错了什么。从一边看(+z方向)一切似乎都很好,但从另一边看(-z方向)一切看起来都很奇怪。

演示视频:(抱歉质量不好)
https://drive.google.com/file/d/1q7tsSzVr4VVw4Tr5Y-WNTdlO5wo6DoKg/view?usp=sharing

主要类别:

package ch.imgajeed.world_generator
import javafx.application.Application
import javafx.beans.property.SimpleDoubleProperty
import javafx.scene.DepthTest
import javafx.scene.Group
import javafx.scene.PerspectiveCamera
import javafx.scene.Scene
import javafx.scene.input.ScrollEvent
import javafx.scene.paint.Color
import javafx.scene.shape.DrawMode
import javafx.scene.transform.Rotate
import javafx.stage.Stage
const val SCREEN_WIDTH = 1000.0
const val SCREEN_HEIGHT = 800.0
var screenInFocus = true
class Main : Application() {
var anchorX = 0.0
var anchorY = 0.0
var anchorAngleX = 0.0
var anchorAngleY = 0.0
var angleX = SimpleDoubleProperty(20.0)
var angleY = SimpleDoubleProperty(90.0)
override fun start(stage: Stage) {
stage.title = "World Generator"
setupRenderer(stage)
stage.show()
}
private fun setupRenderer(stage: Stage) {
// val heightList = pngToHeightList("src/main/resources/ch/imgajeed/world_generator/Test-Height-Map.png", 0.5f)
val generator = MapGenerator(resolution = 1000)
generator.modifiers.add(PerlinNoise(0.0,300f, 0.5f))
generator.modifiers.add(PerlinNoise(1.0,200f, 5f))
generator.modifiers.add(PerlinNoise(2.0,100f, 2f))
generator.modifiers.add(PerlinNoise(3.0,50f, 5f))
generator.modifiers.add(PerlinNoise(4.0,10f, 15f))
generator.modifiers.add(PerlinNoise(5.0,1f, 150f))
generator.modifiers.add(PerlinNoise(6.0,0.1f, 250f))
val heightList = generator.generate()
val terrain3d = Terrain3d(300f, 300f, 1)
val obj = terrain3d.generateMesh(heightList,true, false, 4)
obj.drawMode = DrawMode.FILL
val group = Group()
group.children.add(obj)
group.depthTest = DepthTest.ENABLE
val camera = PerspectiveCamera()
val scene = Scene(group, SCREEN_WIDTH, SCREEN_HEIGHT)
scene.fill = Color.BLACK
scene.camera = camera
camera.translateX = -(SCREEN_WIDTH / 2)
camera.translateY = -(SCREEN_HEIGHT / 2)
camera.translateZ = 0.0
camera.nearClip = 0.00000001
camera.farClip = 1000.0
initMouseController(group, scene, stage)
stage.scene = scene
}
private fun initMouseController(group: Group, scene: Scene, stage: Stage) {
val rotatorX = Rotate(0.0, Rotate.X_AXIS)
val rotatorY = Rotate(0.0, Rotate.Y_AXIS)
rotatorX.angleProperty().bind(angleX)
rotatorY.angleProperty().bind(angleY)
group.transforms.addAll(rotatorX, rotatorY)
scene.setOnMousePressed { event ->
anchorX = event.sceneX
anchorY = event.sceneY
anchorAngleX = angleX.get()
anchorAngleY = angleY.get()
}
scene.setOnMouseDragged { event ->
angleX.set(anchorAngleX - (anchorY - event.sceneY))
angleY.set(anchorAngleY + anchorX - event.sceneX)
if (angleX.get() < 1) {
angleX.set(1.0)
}
}
stage.addEventHandler(ScrollEvent.SCROLL) { event ->
val movement = event.deltaY
group.translateZ -= movement
}
}
}
fun main() {
Application.launch(Main::class.java)
}

地形类别:

package ch.imgajeed.world_generator
import javafx.scene.shape.MeshView
import javafx.scene.shape.TriangleMesh
import java.awt.Color
import java.io.File
import javax.imageio.ImageIO
class Terrain3d(var width: Float = 5f, var height: Float = 5f, var resolution: Int = 5) {
fun generateMesh(heightList: ArrayList<ArrayList<Float>>, hlr: Boolean = false, doubleSided: Boolean = false, divider: Int = 1): MeshView {
if (heightList.size != heightList[0].size) {
error("HeightList size must be a square.")
}
if (hlr) {
resolution = heightList.size / divider
}
if (heightList.size / divider != resolution || heightList[0].size / divider != resolution) {
error("Size of HeightList and resolution does not match. If you want to use the HeightLists resolution set hlr to true.")
}
val vertices = arrayListOf<Float>()
val texCoords = arrayListOf<Float>()
val faces = arrayListOf<Int>()
val tileWidth = (width / resolution)
val tileHeight = (height / resolution)
for (x in 0 until resolution) {
for (y in 0 until resolution) {
vertices.addAll(
arrayListOf(
x * tileWidth - width / 2f, -heightList[y * divider][x * divider], y * tileHeight - height / 2f
)
)
texCoords.addAll(
arrayListOf(
(x.toFloat() / resolution.toFloat()), (y.toFloat() / resolution.toFloat())
)
)
}
}
var faceCountA = 0
var faceCountB = 0
for (i in 0 until vertices.size / 3) {
val ps = vertices.size / 3
val a1: Int = i
val a2: Int = i + resolution
val a3: Int = i + 1
val a1OK = ((a1 + 1) % resolution != 0) && a1 < ps - resolution
val a2OK = a2 < ps
val a3OK = a3 < ps
if (a1OK && a2OK && a3OK) {
faces.add(a1)
faces.add(a1)
faces.add(a2)
faces.add(a2)
faces.add(a3)
faces.add(a3)
if (doubleSided) {
// other side
faces.add(a3)
faces.add(a3)
faces.add(a2)
faces.add(a2)
faces.add(a1)
faces.add(a1)
}
faceCountA += 1
}

val b1: Int = i
val b2: Int = i - resolution
val b3: Int = i - 1
val b1OK = b1 > resolution && b1 % resolution != 0
val b2OK = b2 > 0 && b2 < ps - resolution
val b3OK = b3 > 0 && b3 < ps
if (b1OK && b2OK && b3OK) {
faces.add(b1)
faces.add(b1)
faces.add(b2)
faces.add(b2)
faces.add(b3)
faces.add(b3)
if (doubleSided) {
// other side
faces.add(b3)
faces.add(b3)
faces.add(b2)
faces.add(b2)
faces.add(b1)
faces.add(b1)
}
faceCountB += 1
}
}
println("Resolution: $resolution")
println("Vertices: ${vertices.size}")
println("TexCoords: ${texCoords.size}")
println("Faces: ${faces.size}")
val mesh = TriangleMesh()
for (vertex in vertices) {
mesh.points.addAll(vertex)
}
for (coord in texCoords) {
mesh.texCoords.addAll(coord)
}
for (face in faces) {
mesh.faces.addAll(face)
}
mesh.normals.addAll(0f)
mesh.normals.addAll(-1f)
mesh.normals.addAll(0f)
val meshView = MeshView()
meshView.mesh = mesh
println("Terrain mesh created")

return meshView
}
}
fun pngToHeightList(png: String, scaler: Float = 1f): ArrayList<ArrayList<Float>> {
val img = ImageIO.read(File(png))
val heightList = arrayListOf<ArrayList<Float>>()
for (x in 0 until img.width) {
val line = arrayListOf<Float>()
for (y in 0 until img.height) {
val color = Color(img.getRGB(x, y))
val graylevel: Float = color.red.toFloat() * scaler
line.add(graylevel)
}
heightList.add(line)
}
return heightList
}

有人有办法解决这个问题吗?(项目以Kotlin书写)

已修复。

只需要更改这条线路

camera.nearClip = 0.00000001

到这个

camera.nearClip = 0.01

现在一切都很好。

最新更新