Files
ngzz-mc/internal/mesh/mesh_test.go

96 lines
2.7 KiB
Go
Raw Normal View History

package mesh
import (
"path/filepath"
"testing"
"mc/internal/block"
"mc/internal/chunk"
)
// loadReg 加载注册表。
func loadReg(t *testing.T) *block.Registry {
t.Helper()
r, err := block.Load(filepath.Join("..", "..", "assets", "config", "blocks.json"))
if err != nil {
t.Fatalf("加载注册表失败: %v", err)
}
return r
}
// airNb 邻居查询:全部视为空气(不剔除任何面)。
func airNb(x, y, z int32) block.State { return block.Air }
// dummyUV 固定 UV(测试不关心贴图坐标)。
func dummyUV(key string) (float32, float32, float32, float32, bool) {
return 0, 0, 1, 1, true
}
// TestSingleBlock 单方块 6 面全生成:24 顶点(6 面 × 4 顶点四边形)。
func TestSingleBlock(t *testing.T) {
reg := loadReg(t)
stone, _ := reg.ID("stone")
c := chunk.New(0, 0)
c.Fill(0, 0, 0, block.NewState(stone, 0))
c.SetBlockLight(0, 0, 0, 10)
b := NewBuilder(reg, dummyUV)
m := b.Build(c, airNb)
if len(m.Opaque) != 24 {
t.Fatalf("不透明顶点期望 24,实际 %d", len(m.Opaque))
}
if len(m.Cutout) != 0 || len(m.Translucent) != 0 {
t.Fatalf("其他通道应为空: cutout=%d translucent=%d", len(m.Cutout), len(m.Translucent))
}
// 顶点光照传递
for _, v := range m.Opaque {
if v.Block != 10 {
t.Fatalf("顶点方块光期望 10,实际 %d", v.Block)
}
}
}
// TestFaceCulling 相邻不透明方块剔除共享面:2 块相邻 → 各 5 面 → 40 顶点。
func TestFaceCulling(t *testing.T) {
reg := loadReg(t)
stone, _ := reg.ID("stone")
c := chunk.New(0, 0)
c.Fill(0, 0, 0, block.NewState(stone, 0))
c.Fill(1, 0, 0, block.NewState(stone, 0))
// 邻居查询:跨区块查空气,区块内查实际方块
nb := func(x, y, z int32) block.State {
if x < 0 || x >= 16 || y < 0 || y >= chunk.Height || z < 0 || z >= 16 {
return block.Air
}
return c.Block(int(x), int(y), int(z))
}
b := NewBuilder(reg, dummyUV)
m := b.Build(c, nb)
if len(m.Opaque) != 40 {
t.Fatalf("面剔除后顶点期望 40,实际 %d", len(m.Opaque))
}
}
// TestChannels 透明分类:火把→cutout,水→translucent(渲染.md §6)。
func TestChannels(t *testing.T) {
reg := loadReg(t)
torch, _ := reg.ID("torch")
water, _ := reg.ID("water")
c := chunk.New(0, 0)
c.Fill(0, 0, 0, block.NewState(torch, 0))
c.Fill(2, 0, 0, block.NewState(water, 0))
b := NewBuilder(reg, dummyUV)
m := b.Build(c, airNb)
if len(m.Cutout) != 24 {
t.Fatalf("火把 cutout 顶点期望 24,实际 %d", len(m.Cutout))
}
if len(m.Translucent) != 24 {
t.Fatalf("水 translucent 顶点期望 24,实际 %d", len(m.Translucent))
}
if len(m.Opaque) != 0 {
t.Fatalf("不应有不透明顶点,实际 %d", len(m.Opaque))
}
}