Files
ngzz-mc/cmd/client/entities_gl.go
NianGao Dev b0b632df05 feat(client): 手持物品渲染 + 动物方块模型 + 实体贴图 alpha test
- 手持非放置物品(工具/食物):实体图集物品图标小四边形(原版倾斜角,
  双面、alpha test),随挥动动画平移;可放置方块仍为六面立方体
- 动物(牛/猪/羊/鸡)改为方块组合模型(身体+头+腿),按原版皮肤布局
  取子矩形贴图,水平面向相机;修复动物 VAO 未捕获 EBO 导致的驱动崩溃
- 僵尸/村民/掉落物广告牌开启 alpha test(透明区域不再显黑块)
2026-08-16 23:23:30 +08:00

127 lines
4.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//go:build gl
// 实体可视映射:实体类型 → 贴图键/身高/动物模型(渲染.md §5.3)。
// 动物用方块组合模型(身体+头+四腿)近似原版外观;僵尸/村民用交叉广告牌;
// 掉落物用物品图标小广告牌。
package main
import (
"mc/internal/entity"
"mc/internal/item"
"mc/internal/render"
)
// entityVisual 返回实体的贴图键与身高(米)。
// 动物额外返回外观变体(0 牛 / 1 猪 / 2 羊 / 3 鸡),供方块模型选择。
func entityVisual(e *entity.Entity, items *item.Registry) (key string, height float32, variant int) {
switch e.Kind {
case entity.KindZombie:
return "entity/zombie/zombie", 1.95, -1
case entity.KindVillager:
return "entity/villager/villager", 1.95, -1
case entity.KindAnimal:
switch e.ID % 4 {
case 0:
return "entity/cow/cow_temperate", 1.4, 0
case 1:
return "entity/pig/pig_temperate", 0.9, 1
case 2:
return "entity/sheep/sheep", 1.3, 2
default:
return "entity/chicken/chicken_temperate", 0.7, 3
}
case entity.KindItemDrop:
d, ok := e.Data.(*entity.Drop)
if !ok || items == nil {
return "", 0, -1
}
def, ok := items.Get(d.Item)
if !ok {
return "", 0, -1
}
return def.Texture, 0.45, -1
default:
return "", 0, -1
}
}
// rect 构造图集 tile 内归一化子矩形。
func rect(u0, v0, u1, v1 float32) [4]float32 { return [4]float32{u0, v0, u1, v1} }
// boxPart 构造模型部件:六面统一用 side 矩形,前/后取中间条带,顶取上条带,底取下条带。
func boxPart(cx, cy, cz, w, h, d float32, side [4]float32) render.AnimalPart {
u0, v0, u1, v1 := side[0], side[1], side[2], side[3]
uw, vh := u1-u0, v1-v0
front := rect(u0+uw*0.35, v0, u0+uw*0.65, v1) // 前/后面:中间三分之一
top := rect(u0, v0, u1, v0+vh*0.3)
bottom := rect(u0, v1-vh*0.3, u1, v1)
var uv [6][4]float32
// 顺序同 cubeFaces:顶/底/东/西/南(前)/北(后)
uv[0], uv[1] = top, bottom
uv[2], uv[3] = side, side
uv[4], uv[5] = front, front
return render.AnimalPart{CX: cx, CY: cy, CZ: cz, W: w, H: h, D: d, UV: uv}
}
// animalModel 返回动物方块模型(variant:0 牛 / 1 猪 / 2 羊 / 3 鸡)。
// 贴图子矩形按原版皮肤布局:头部在纹理左侧、身体在右侧、腿在下部。
// 图集 tile 内纹理被等比拉伸成 64×64(64×32 原图纵向拉长一倍,矩形已按拉伸后比例折算)。
func animalModel(variant int) render.AnimalModel {
switch variant {
case 0: // 牛:纹理 64×64,内容在上半(v 0–0.5)
head := rect(0.02, 0.02, 0.48, 0.48)
body := rect(0.52, 0.02, 0.98, 0.48)
legs := rect(0.55, 0.30, 0.98, 0.50)
var m render.AnimalModel
m.Parts = append(m.Parts,
boxPart(0, 0.72, 0, 0.92, 0.62, 1.28, body),
boxPart(0, 1.26, 0.60, 0.56, 0.50, 0.56, head),
boxPart(-0.34, 0.24, 0.50, 0.22, 0.48, 0.22, legs),
boxPart(0.34, 0.24, 0.50, 0.22, 0.48, 0.22, legs),
boxPart(-0.34, 0.24, -0.50, 0.22, 0.48, 0.22, legs),
boxPart(0.34, 0.24, -0.50, 0.22, 0.48, 0.22, legs),
)
return m
case 1: // 猪:纹理 64×64,内容在上半
head := rect(0.14, 0.03, 0.48, 0.45)
body := rect(0.52, 0.03, 0.98, 0.45)
legs := rect(0.60, 0.30, 0.98, 0.50)
var m render.AnimalModel
m.Parts = append(m.Parts,
boxPart(0, 0.50, 0, 0.76, 0.44, 1.02, body),
boxPart(0, 0.86, 0.50, 0.50, 0.42, 0.50, head),
boxPart(-0.28, 0.15, 0.42, 0.18, 0.30, 0.18, legs),
boxPart(0.28, 0.15, 0.42, 0.18, 0.30, 0.18, legs),
boxPart(-0.28, 0.15, -0.42, 0.18, 0.30, 0.18, legs),
boxPart(0.28, 0.15, -0.42, 0.18, 0.30, 0.18, legs),
)
return m
case 2: // 羊:纹理 64×32(tile 内 v 拉长一倍)
head := rect(0.02, 0.02, 0.26, 0.40)
body := rect(0.50, 0.15, 1.00, 0.72)
legs := rect(0.62, 0.50, 0.95, 0.85)
var m render.AnimalModel
m.Parts = append(m.Parts,
boxPart(0, 0.72, 0, 0.92, 0.60, 1.26, body),
boxPart(0, 1.20, 0.60, 0.50, 0.46, 0.50, head),
boxPart(-0.33, 0.21, 0.50, 0.20, 0.42, 0.20, legs),
boxPart(0.33, 0.21, 0.50, 0.20, 0.42, 0.20, legs),
boxPart(-0.33, 0.21, -0.50, 0.20, 0.42, 0.20, legs),
boxPart(0.33, 0.21, -0.50, 0.20, 0.42, 0.20, legs),
)
return m
default: // 鸡:纹理 64×32
head := rect(0.02, 0.05, 0.28, 0.55)
body := rect(0.28, 0.10, 0.70, 0.75)
legs := rect(0.30, 0.55, 0.60, 0.80)
var m render.AnimalModel
m.Parts = append(m.Parts,
boxPart(0, 0.36, 0, 0.44, 0.40, 0.52, body),
boxPart(0, 0.66, 0.24, 0.32, 0.30, 0.32, head),
boxPart(-0.14, 0.10, 0.18, 0.09, 0.20, 0.09, legs),
boxPart(0.14, 0.10, 0.18, 0.09, 0.20, 0.09, legs),
)
return m
}
}