commit
f7ac76064b
2
.github/workflows/macos.yml
vendored
2
.github/workflows/macos.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
||||
run: ./dev/fix_dylibs.sh VoxelEngine Release build
|
||||
|
||||
- name: Run tests
|
||||
run: ctest --test-dir build
|
||||
run: ctest --output-on-failure --test-dir build
|
||||
|
||||
- name: Create DMG
|
||||
run: |
|
||||
|
||||
@ -12,6 +12,12 @@ Icon type defines a source of an item image displayed in inventory.
|
||||
- **items** (generated from *png* files in *res/textures/items/*)
|
||||
- **block** - block preview. Block ID must be specified in **icon** property. Example: *base:wood*.
|
||||
|
||||
### Item model - `model-name`
|
||||
|
||||
Name of the item model. The model will be loaded automatically.
|
||||
Default value is `packid:itemname.model`.
|
||||
If the model is not specified, an automatic one will be generated.
|
||||
|
||||
## Behaviour
|
||||
|
||||
### *placing-block*
|
||||
|
||||
@ -18,4 +18,10 @@ item.defs_count() -> int
|
||||
|
||||
-- Returns item icon name to use in 'src' property of an image element
|
||||
item.icon(itemid: int) -> str
|
||||
|
||||
-- Returns the integer id 'placing-block' or 0
|
||||
item.placing_block(itemid: int) -> int
|
||||
|
||||
-- Returns the value of the `model-name` property
|
||||
item.model_name(itemid: int) -> str
|
||||
```
|
||||
|
||||
@ -11,6 +11,12 @@
|
||||
- items (генерируется из png файлов в `res/textures/items/`)
|
||||
- `block` - отображает предпросмотр блока. В icon указывается строковый id блока который нужно отображать. Пример `base:wood`
|
||||
|
||||
### Модель предмета - `model-name`
|
||||
|
||||
Имя модели предмета. Модель будет загружена автоматически.
|
||||
Значение по-умолчанию - `packid:itemname.model`.
|
||||
Если модель не указана, будет сгенерирована автоматическию
|
||||
|
||||
## Поведение
|
||||
|
||||
### Устанавливаемый блок - `placing-block`
|
||||
|
||||
@ -8,7 +8,7 @@ item.name(itemid: int) -> str
|
||||
item.index(name: str) -> int
|
||||
|
||||
-- Возвращает название предмета, отображаемое в интерфейсе.
|
||||
item.caption(blockid: int) -> str
|
||||
item.caption(itemid: int) -> str
|
||||
|
||||
-- Возвращает максимальный размер стопки для предмета.
|
||||
item.stack_size(itemid: int) -> int
|
||||
@ -18,6 +18,12 @@ item.defs_count() -> int
|
||||
|
||||
-- Возвращает имя иконки предмета для использования в свойстве 'src' элемента image
|
||||
item.icon(itemid: int) -> str
|
||||
|
||||
-- Возвращает числовой id блока, назначенного как 'placing-block' или 0
|
||||
item.placing_block(itemid: int) -> int
|
||||
|
||||
-- Возвращает значение свойства `model-name`
|
||||
item.model_name(itemid: int) -> str
|
||||
```
|
||||
|
||||
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
{
|
||||
"texture": "water",
|
||||
"overlay-texture": "blocks:water",
|
||||
"draw-group": 3,
|
||||
"light-passing": true,
|
||||
"sky-light-passing": false,
|
||||
"obstacle": false,
|
||||
"selectable": false,
|
||||
"replaceable": true
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
o Cube
|
||||
v 0.5 -0.5 -0.5
|
||||
v 0.5 -0.5 0.5
|
||||
v -0.5 -0.5 0.5
|
||||
v -0.5 -0.5 -0.5
|
||||
v 0.5 0.5 -0.5
|
||||
v 0.5 0.5 0.5
|
||||
v -0.5 0.5 0.5
|
||||
v -0.5 0.5 -0.5
|
||||
vt 0.0 0.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
vt 0.0 1.0
|
||||
vt 0.0 0.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
vt 0.0 1.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
vt 0.0 0.0
|
||||
vt 1.0 0.0
|
||||
vt 0.0 1.0
|
||||
vt 0.0 0.0
|
||||
vt 0.0 1.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
vt 1.0 1.0
|
||||
vt 0.0 1.0
|
||||
vt 0.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 1.0 -0.0 0.0
|
||||
vn -1.0 -0.0 -0.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn -0.0 -0.0 1.0
|
||||
usemtl $2
|
||||
s off
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
||||
usemtl $3
|
||||
f 5/5/2 8/6/2 7/7/2 6/8/2
|
||||
usemtl $0
|
||||
f 1/9/3 5/10/3 6/8/3 2/11/3
|
||||
usemtl $1
|
||||
f 3/12/4 7/7/4 8/13/4 4/14/4
|
||||
usemtl $4
|
||||
f 5/15/5 1/1/5 4/16/5 8/17/5
|
||||
usemtl $5
|
||||
f 2/2/6 6/18/6 7/19/6 3/20/6
|
||||
Binary file not shown.
@ -1,48 +0,0 @@
|
||||
o Cube
|
||||
v 0.125 -0.125 -0.125
|
||||
v 0.125 -0.125 0.125
|
||||
v -0.125 -0.125 0.125
|
||||
v -0.125 -0.125 -0.125
|
||||
v 0.125 0.125 -0.125
|
||||
v 0.125 0.125 0.125
|
||||
v -0.125 0.125 0.125
|
||||
v -0.125 0.125 -0.125
|
||||
vt 0.0 0.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
vt 0.0 1.0
|
||||
vt 0.0 0.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
vt 0.0 1.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
vt 0.0 0.0
|
||||
vt 1.0 0.0
|
||||
vt 0.0 1.0
|
||||
vt 0.0 0.0
|
||||
vt 0.0 1.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
vt 1.0 1.0
|
||||
vt 0.0 1.0
|
||||
vt 0.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 1.0 -0.0 0.0
|
||||
vn -1.0 -0.0 -0.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn -0.0 -0.0 1.0
|
||||
usemtl $2
|
||||
s off
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
||||
usemtl $3
|
||||
f 5/5/2 8/6/2 7/7/2 6/8/2
|
||||
usemtl $0
|
||||
f 1/9/3 5/10/3 6/8/3 2/11/3
|
||||
usemtl $1
|
||||
f 3/12/4 7/7/4 8/13/4 4/14/4
|
||||
usemtl $4
|
||||
f 5/15/5 1/1/5 4/16/5 8/17/5
|
||||
usemtl $5
|
||||
f 2/2/6 6/18/6 7/19/6 3/20/6
|
||||
BIN
res/content/base/models/drop-block.vec3
Normal file
BIN
res/content/base/models/drop-block.vec3
Normal file
Binary file not shown.
@ -1,113 +0,0 @@
|
||||
o Cube
|
||||
v 0.282501 -0.000054 -0.282500
|
||||
v -0.282501 -0.000054 -0.282501
|
||||
v -0.282501 -0.000054 0.282500
|
||||
v 0.282500 -0.000054 0.282501
|
||||
v 0.282501 0.012502 -0.282500
|
||||
v -0.282501 0.012502 -0.282501
|
||||
v -0.282501 0.012502 0.282500
|
||||
v 0.282500 0.012502 0.282501
|
||||
v 0.282501 0.012502 -0.282500
|
||||
v 0.282500 0.012502 0.282501
|
||||
v -0.282501 0.012502 0.282500
|
||||
v -0.282501 0.012502 -0.282501
|
||||
v 0.282501 -0.000054 -0.282500
|
||||
v 0.282500 -0.000054 0.282501
|
||||
v -0.282501 -0.000054 0.282500
|
||||
v -0.282501 -0.000054 -0.282501
|
||||
v 0.282501 0.012502 -0.282500
|
||||
v -0.282501 0.012502 -0.282501
|
||||
v -0.282501 0.012502 0.282500
|
||||
v 0.282500 0.012502 0.282501
|
||||
v 0.282501 0.012502 -0.282500
|
||||
v 0.282500 0.012502 0.282501
|
||||
v -0.282501 0.012502 0.282500
|
||||
v -0.282501 0.012502 -0.282501
|
||||
v 0.282501 -0.015821 -0.282500
|
||||
v -0.282501 -0.015821 -0.282501
|
||||
v -0.282501 -0.015821 0.282500
|
||||
v 0.282500 -0.015821 0.282501
|
||||
v 0.282501 0.027439 -0.282500
|
||||
v -0.282501 0.027439 -0.282501
|
||||
v -0.282501 0.027439 0.282500
|
||||
v 0.282500 0.027439 0.282501
|
||||
v 0.282501 0.027439 -0.282500
|
||||
v 0.282500 0.027439 0.282501
|
||||
v -0.282501 0.027439 0.282500
|
||||
v -0.282501 0.027439 -0.282501
|
||||
v 0.282501 -0.015821 -0.282500
|
||||
v 0.282500 -0.015821 0.282501
|
||||
v -0.282501 -0.015821 0.282500
|
||||
v -0.282501 -0.015821 -0.282501
|
||||
v 0.282501 0.027439 -0.282500
|
||||
v -0.282501 0.027439 -0.282501
|
||||
v -0.282501 0.027439 0.282500
|
||||
v 0.282500 0.027439 0.282501
|
||||
v 0.282501 0.027439 -0.282500
|
||||
v 0.282500 0.027439 0.282501
|
||||
v -0.282501 0.027439 0.282500
|
||||
v -0.282501 0.027439 -0.282501
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 1.000000 0.000000
|
||||
vn -0.0000 1.0000 0.0000
|
||||
vn 0.0000 -1.0000 -0.0000
|
||||
usemtl $0
|
||||
s 1
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
||||
f 5/5/1 6/6/1 7/7/1 8/8/1
|
||||
f 9/9/2 10/10/2 11/11/2 12/12/2
|
||||
f 13/13/2 14/14/2 15/15/2 16/16/2
|
||||
f 17/17/1 18/18/1 19/19/1 20/20/1
|
||||
f 21/21/2 22/22/2 23/23/2 24/24/2
|
||||
f 25/25/1 26/26/1 27/27/1 28/28/1
|
||||
f 29/29/1 30/30/1 31/31/1 32/32/1
|
||||
f 33/33/2 34/34/2 35/35/2 36/36/2
|
||||
f 37/37/2 38/38/2 39/39/2 40/40/2
|
||||
f 41/41/1 42/42/1 43/43/1 44/44/1
|
||||
f 45/45/2 46/46/2 47/47/2 48/48/2
|
||||
@ -1,47 +0,0 @@
|
||||
# Blender v2.79 (sub 0) OBJ File: 'player.blend'
|
||||
# www.blender.org
|
||||
mtllib player-body.mtl
|
||||
o Cube.001
|
||||
v -0.125000 -0.900000 0.070903
|
||||
v -0.125000 -0.900000 -0.070903
|
||||
v 0.125000 -0.900000 -0.070903
|
||||
v 0.125000 -0.900000 0.070903
|
||||
v -0.125000 0.491919 0.070903
|
||||
v 0.125000 0.491919 0.070903
|
||||
v 0.125000 0.491919 -0.070903
|
||||
v -0.125000 0.491919 -0.070903
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vt 0.112175 0.434439
|
||||
vt 0.311556 0.434439
|
||||
vt 0.311556 0.633819
|
||||
vt 0.112175 0.633819
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vn 0.0000 -1.0000 0.0000
|
||||
vn 0.0000 1.0000 0.0000
|
||||
vn -1.0000 0.0000 0.0000
|
||||
vn -0.0000 -0.0000 -1.0000
|
||||
vn 1.0000 0.0000 0.0000
|
||||
vn 0.0000 0.0000 1.0000
|
||||
usemtl entities/player
|
||||
s 1
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
||||
f 5/5/2 6/6/2 7/7/2 8/8/2
|
||||
f 1/1/3 5/9/3 8/10/3 2/11/3
|
||||
f 2/12/4 8/13/4 7/14/4 3/15/4
|
||||
f 3/16/5 7/17/5 6/18/5 4/4/5
|
||||
f 5/5/6 1/19/6 4/20/6 6/21/6
|
||||
BIN
res/content/base/models/player-body.vec3
Normal file
BIN
res/content/base/models/player-body.vec3
Normal file
Binary file not shown.
@ -1,42 +0,0 @@
|
||||
# Blender v2.79 (sub 0) OBJ File: 'player.blend'
|
||||
# www.blender.org
|
||||
mtllib player-hand.mtl
|
||||
o Cube.000_Cube.002
|
||||
v 0.062480 -0.613786 -0.062480
|
||||
v 0.062480 -0.613786 0.062480
|
||||
v -0.062480 -0.613786 0.062480
|
||||
v -0.062480 -0.613786 -0.062480
|
||||
v 0.062480 0.070352 -0.062480
|
||||
v -0.062480 0.070352 -0.062480
|
||||
v -0.062480 0.070352 0.062480
|
||||
v 0.062480 0.070352 0.062480
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vt 0.436482 0.280393
|
||||
vt 0.433740 0.937829
|
||||
vt 0.436146 0.914519
|
||||
vt 0.438665 0.292591
|
||||
vt 0.492515 0.918221
|
||||
vt 0.493194 0.293103
|
||||
vt 0.493371 0.941872
|
||||
vt 0.494058 0.280870
|
||||
vn 0.0000 -1.0000 0.0000
|
||||
vn 0.0000 1.0000 -0.0000
|
||||
vn 1.0000 -0.0000 0.0000
|
||||
vn -0.0000 -0.0000 1.0000
|
||||
vn -1.0000 0.0000 0.0000
|
||||
vn 0.0000 0.0000 -1.0000
|
||||
usemtl entities/player
|
||||
s 1
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
||||
f 5/5/2 6/6/2 7/7/2 8/8/2
|
||||
f 1/9/3 5/10/3 8/11/3 2/12/3
|
||||
f 2/12/4 8/11/4 7/13/4 3/14/4
|
||||
f 3/14/5 7/13/5 6/15/5 4/16/5
|
||||
f 5/10/6 1/9/6 4/16/6 6/15/6
|
||||
BIN
res/content/base/models/player-hand.vec3
Normal file
BIN
res/content/base/models/player-hand.vec3
Normal file
Binary file not shown.
@ -1,48 +0,0 @@
|
||||
# Blender v2.79 (sub 0) OBJ File: 'player.blend'
|
||||
# www.blender.org
|
||||
mtllib player-head.mtl
|
||||
o Cube.002_Cube.003
|
||||
v -0.206512 0.031837 0.206512
|
||||
v -0.206512 0.444861 0.206512
|
||||
v -0.206512 0.444861 -0.206512
|
||||
v -0.206512 0.031837 -0.206512
|
||||
v 0.206512 0.444861 -0.206512
|
||||
v 0.206512 0.031837 -0.206512
|
||||
v 0.206512 0.444861 0.206512
|
||||
v 0.206512 0.031837 0.206512
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vt 0.735873 0.213345
|
||||
vt 0.735873 0.739780
|
||||
vt 0.209439 0.739780
|
||||
vt 0.209439 0.213345
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.209065
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.982503 0.209065
|
||||
vt 0.783122 0.009685
|
||||
vt 0.982503 0.009685
|
||||
vt 0.783122 0.209065
|
||||
vn -1.0000 -0.0000 -0.0000
|
||||
vn 0.0000 0.0000 -1.0000
|
||||
vn 1.0000 0.0000 0.0000
|
||||
vn -0.0000 -0.0000 1.0000
|
||||
vn 0.0000 -1.0000 -0.0000
|
||||
vn -0.0000 1.0000 0.0000
|
||||
usemtl entities/player
|
||||
s 1
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
||||
f 4/5/2 3/6/2 5/7/2 6/8/2
|
||||
f 6/9/3 5/10/3 7/11/3 8/12/3
|
||||
f 8/13/4 7/14/4 2/15/4 1/16/4
|
||||
f 4/17/5 6/18/5 8/19/5 1/16/5
|
||||
f 5/20/6 3/21/6 2/15/6 7/22/6
|
||||
BIN
res/content/base/models/player-head.vec3
Normal file
BIN
res/content/base/models/player-head.vec3
Normal file
Binary file not shown.
@ -1,5 +1,3 @@
|
||||
local item_models = require "core:item_models"
|
||||
|
||||
local tsf = entity.transform
|
||||
local body = entity.rigidbody
|
||||
local rig = entity.skeleton
|
||||
@ -27,7 +25,7 @@ end
|
||||
|
||||
do -- setup visuals
|
||||
local matrix = mat4.idt()
|
||||
scale = item_models.setup(dropitem.id, rig, 0)
|
||||
rig:set_model(0, item.model_name(dropitem.id))
|
||||
local bodysize = math.min(scale[1], scale[2], scale[3]) * DROP_SCALE
|
||||
body:set_size({scale[1] * DROP_SCALE, bodysize, scale[3] * DROP_SCALE})
|
||||
mat4.mul(matrix, rotation, matrix)
|
||||
@ -38,9 +36,7 @@ end
|
||||
function on_grounded(force)
|
||||
local matrix = mat4.idt()
|
||||
mat4.rotate(matrix, {0, 1, 0}, math.random()*360, matrix)
|
||||
if model == "aabb" then
|
||||
mat4.rotate(matrix, {1, 0, 0}, 90, matrix)
|
||||
end
|
||||
mat4.rotate(matrix, {1, 0, 0}, 90, matrix)
|
||||
mat4.scale(matrix, scale, matrix)
|
||||
rig:set_matrix(0, matrix)
|
||||
inair = false
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
local item_models = require "core:item_models"
|
||||
|
||||
local tsf = entity.transform
|
||||
local body = entity.rigidbody
|
||||
local rig = entity.skeleton
|
||||
@ -9,12 +7,8 @@ local itemIndex = rig:index("item")
|
||||
|
||||
local function refresh_model(id)
|
||||
itemid = id
|
||||
if id == 0 then
|
||||
rig:set_model(itemIndex, "")
|
||||
else
|
||||
local scale = item_models.setup(itemid, rig, itemIndex)
|
||||
rig:set_matrix(itemIndex, mat4.scale(scale))
|
||||
end
|
||||
rig:set_model(itemIndex, item.model_name(itemid))
|
||||
rig:set_matrix(itemIndex, mat4.rotate({0, 1, 0}, -80))
|
||||
end
|
||||
|
||||
function on_render()
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 6.1 KiB |
BIN
res/models/block.vec3
Normal file
BIN
res/models/block.vec3
Normal file
Binary file not shown.
BIN
res/models/drop-item.vec3
Normal file
BIN
res/models/drop-item.vec3
Normal file
Binary file not shown.
@ -1,33 +0,0 @@
|
||||
local function setup(id, rig, index)
|
||||
rig:set_model(index, "drop-block")
|
||||
local icon = item.icon(id)
|
||||
local size = {1.0, 1.0, 1.0}
|
||||
if icon:find("^block%-previews%:") then
|
||||
local bid = block.index(icon:sub(16))
|
||||
model = block.get_model(bid)
|
||||
if model == "X" then
|
||||
size = {1.0, 0.3, 1.0}
|
||||
rig:set_model(index, "drop-item")
|
||||
rig:set_texture("$0", icon)
|
||||
else
|
||||
if model == "aabb" then
|
||||
local rot = block.get_rotation_profile(bid) == "pipe" and 4 or 0
|
||||
size = block.get_hitbox(bid, rot)[2]
|
||||
vec3.mul(size, 2.0, size)
|
||||
end
|
||||
local textures = block.get_textures(bid)
|
||||
for i,t in ipairs(textures) do
|
||||
rig:set_texture("$"..tostring(i-1), "blocks:"..textures[i])
|
||||
end
|
||||
end
|
||||
else
|
||||
size = {1.0, 0.3, 1.0}
|
||||
rig:set_model(index, "drop-item")
|
||||
rig:set_texture("$0", icon)
|
||||
end
|
||||
return size
|
||||
end
|
||||
|
||||
return {
|
||||
setup=setup,
|
||||
}
|
||||
@ -16,7 +16,7 @@ void main() {
|
||||
float depth = (a_distance/256.0);
|
||||
float alpha = a_color.a * tex_color.a;
|
||||
// anyway it's any alpha-test alternative required
|
||||
if (alpha < 0.3f)
|
||||
if (alpha < 0.9f)
|
||||
discard;
|
||||
f_color = mix(a_color * tex_color, vec4(fogColor,1.0),
|
||||
min(1.0, pow(depth*u_fogFactor, u_fogCurve)));
|
||||
|
||||
@ -5,11 +5,13 @@
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "util/stringutil.hpp"
|
||||
#include "graphics/core/TextureAnimation.hpp"
|
||||
|
||||
class Assets;
|
||||
@ -84,6 +86,15 @@ public:
|
||||
return static_cast<T*>(found->second.get());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T& require(const std::string& name) const {
|
||||
T* asset = get<T>(name);
|
||||
if (asset == nullptr) {
|
||||
throw std::runtime_error(util::quote(name) + " not found");
|
||||
}
|
||||
return *asset;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::optional<const assets_map*> getMap() const {
|
||||
const auto& mapIter = assets.find(typeid(T));
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "objects/rigging.hpp"
|
||||
#include "util/ThreadPool.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "items/ItemDef.hpp"
|
||||
#include "Assets.hpp"
|
||||
#include "assetload_funcs.hpp"
|
||||
|
||||
@ -240,6 +241,15 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& [_, def] : content->items.getDefs()) {
|
||||
if (def->modelName.find(':') == std::string::npos) {
|
||||
loader.add(
|
||||
AssetType::MODEL,
|
||||
MODELS_FOLDER + "/" + def->modelName,
|
||||
def->modelName
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
24
src/assets/assets_util.cpp
Normal file
24
src/assets/assets_util.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "assets_util.hpp"
|
||||
|
||||
#include "assets/Assets.hpp"
|
||||
#include "graphics/core/Atlas.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
|
||||
util::TextureRegion util::get_texture_region(
|
||||
const Assets& assets, const std::string& name, const std::string& fallback
|
||||
) {
|
||||
size_t sep = name.find(':');
|
||||
if (sep == std::string::npos) {
|
||||
return {assets.get<Texture>(name), UVRegion(0,0,1,1)};
|
||||
} else {
|
||||
auto atlas = assets.get<Atlas>(name.substr(0, sep));
|
||||
if (atlas) {
|
||||
if (auto reg = atlas->getIf(name.substr(sep+1))) {
|
||||
return {atlas->getTexture(), *reg};
|
||||
} else if (!fallback.empty()){
|
||||
return util::get_texture_region(assets, fallback, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
return {nullptr, UVRegion()};
|
||||
}
|
||||
21
src/assets/assets_util.hpp
Normal file
21
src/assets/assets_util.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "maths/UVRegion.hpp"
|
||||
|
||||
class Assets;
|
||||
class Texture;
|
||||
|
||||
namespace util {
|
||||
struct TextureRegion {
|
||||
const Texture* texture;
|
||||
UVRegion region;
|
||||
};
|
||||
|
||||
TextureRegion get_texture_region(
|
||||
const Assets& assets,
|
||||
const std::string& name,
|
||||
const std::string& fallback
|
||||
);
|
||||
}
|
||||
@ -125,7 +125,6 @@ static model::Mesh load_mesh(
|
||||
if (flags == FLAG_ZLIB) {
|
||||
throw std::runtime_error("compression is not supported yet");
|
||||
}
|
||||
assert(flags == 0);
|
||||
std::vector<VertexAttribute> attributes;
|
||||
for (int i = 0; i < attributeCount; i++) {
|
||||
attributes.push_back(load_attribute(reader));
|
||||
|
||||
@ -326,6 +326,7 @@ void ContentLoader::loadBlock(
|
||||
root.at("ui-layout").get(def.uiLayout);
|
||||
root.at("inventory-size").get(def.inventorySize);
|
||||
root.at("tick-interval").get(def.tickInterval);
|
||||
root.at("overlay-texture").get(def.overlayTexture);
|
||||
|
||||
if (root.has("fields")) {
|
||||
def.dataStruct = std::make_unique<StructLayout>();
|
||||
@ -418,17 +419,18 @@ void ContentLoader::loadItem(
|
||||
std::string iconTypeStr = "";
|
||||
root.at("icon-type").get(iconTypeStr);
|
||||
if (iconTypeStr == "none") {
|
||||
def.iconType = item_icon_type::none;
|
||||
def.iconType = ItemIconType::NONE;
|
||||
} else if (iconTypeStr == "block") {
|
||||
def.iconType = item_icon_type::block;
|
||||
def.iconType = ItemIconType::BLOCK;
|
||||
} else if (iconTypeStr == "sprite") {
|
||||
def.iconType = item_icon_type::sprite;
|
||||
def.iconType = ItemIconType::SPRITE;
|
||||
} else if (iconTypeStr.length()) {
|
||||
logger.error() << name << ": unknown icon type" << iconTypeStr;
|
||||
}
|
||||
root.at("icon").get(def.icon);
|
||||
root.at("placing-block").get(def.placingBlock);
|
||||
root.at("script-name").get(def.scriptName);
|
||||
root.at("model-name").get(def.modelName);
|
||||
root.at("stack-size").get(def.stackSize);
|
||||
|
||||
// item light emission [r, g, b] where r,g,b in range [0..15]
|
||||
@ -532,7 +534,7 @@ void ContentLoader::loadBlock(
|
||||
auto& item = builder.items.create(full + BLOCK_ITEM_SUFFIX);
|
||||
item.generated = true;
|
||||
item.caption = def.caption;
|
||||
item.iconType = item_icon_type::block;
|
||||
item.iconType = ItemIconType::BLOCK;
|
||||
item.icon = full;
|
||||
item.placingBlock = full;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
|
||||
}
|
||||
{
|
||||
ItemDef& item = builder->items.create(CORE_EMPTY);
|
||||
item.iconType = item_icon_type::none;
|
||||
item.iconType = ItemIconType::NONE;
|
||||
}
|
||||
|
||||
auto bindsFile = paths->getResourcesFolder()/fs::path("bindings.toml");
|
||||
@ -43,7 +43,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
|
||||
block.hitboxes = {AABB()};
|
||||
block.breakable = false;
|
||||
ItemDef& item = builder->items.create(CORE_OBSTACLE+".item");
|
||||
item.iconType = item_icon_type::block;
|
||||
item.iconType = ItemIconType::BLOCK;
|
||||
item.icon = CORE_OBSTACLE;
|
||||
item.placingBlock = CORE_OBSTACLE;
|
||||
item.caption = block.caption;
|
||||
@ -59,7 +59,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
|
||||
block.hitboxes = {AABB()};
|
||||
block.obstacle = false;
|
||||
ItemDef& item = builder->items.create(CORE_STRUCT_AIR+".item");
|
||||
item.iconType = item_icon_type::block;
|
||||
item.iconType = ItemIconType::BLOCK;
|
||||
item.icon = CORE_STRUCT_AIR;
|
||||
item.placingBlock = CORE_STRUCT_AIR;
|
||||
item.caption = block.caption;
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "frontend/menu.hpp"
|
||||
#include "frontend/screens/Screen.hpp"
|
||||
#include "frontend/screens/MenuScreen.hpp"
|
||||
#include "graphics/render/ModelsGenerator.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/ImageData.hpp"
|
||||
@ -280,6 +281,17 @@ void Engine::loadAssets() {
|
||||
}
|
||||
}
|
||||
assets = std::move(new_assets);
|
||||
|
||||
if (content) {
|
||||
for (auto& [name, def] : content->items.getDefs()) {
|
||||
assets->store(
|
||||
std::make_unique<model::Model>(
|
||||
ModelsGenerator::generate(*def, *content, *assets)
|
||||
),
|
||||
name + ".model"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void load_configs(const fs::path& root) {
|
||||
|
||||
@ -37,10 +37,10 @@ LevelFrontend::LevelFrontend(
|
||||
auto soundsCamera = currentPlayer->currentCamera.get();
|
||||
if (soundsCamera == currentPlayer->spCamera.get() ||
|
||||
soundsCamera == currentPlayer->tpCamera.get()) {
|
||||
soundsCamera = currentPlayer->camera.get();
|
||||
soundsCamera = currentPlayer->fpCamera.get();
|
||||
}
|
||||
bool relative = player == currentPlayer &&
|
||||
soundsCamera == currentPlayer->camera.get();
|
||||
soundsCamera == currentPlayer->fpCamera.get();
|
||||
if (!relative) {
|
||||
pos = player->getPosition();
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr<Level> level)
|
||||
worldRenderer->clear();
|
||||
}));
|
||||
keepAlive(settings.camera.fov.observe([=](double value) {
|
||||
controller->getPlayer()->camera->setFov(glm::radians(value));
|
||||
controller->getPlayer()->fpCamera->setFov(glm::radians(value));
|
||||
}));
|
||||
keepAlive(Events::getBinding(BIND_CHUNKS_RELOAD).onactived.add([=](){
|
||||
controller->getLevel()->chunks->saveAndClear();
|
||||
@ -93,7 +93,7 @@ void LevelScreen::saveWorldPreview() {
|
||||
int previewSize = settings.ui.worldPreviewSize.get();
|
||||
|
||||
// camera special copy for world preview
|
||||
Camera camera = *player->camera;
|
||||
Camera camera = *player->fpCamera;
|
||||
camera.setFov(glm::radians(70.0f));
|
||||
|
||||
DrawContext pctx(nullptr, {Window::width, Window::height}, batch.get());
|
||||
@ -101,7 +101,7 @@ void LevelScreen::saveWorldPreview() {
|
||||
Viewport viewport(previewSize * 1.5, previewSize);
|
||||
DrawContext ctx(&pctx, viewport, batch.get());
|
||||
|
||||
worldRenderer->draw(ctx, &camera, false, true, 0.0f, postProcessing.get());
|
||||
worldRenderer->draw(ctx, camera, false, true, 0.0f, postProcessing.get());
|
||||
auto image = postProcessing->toImage();
|
||||
image->flipY();
|
||||
imageio::write(paths->resolve("world:preview.png").u8string(), image.get());
|
||||
@ -164,7 +164,9 @@ void LevelScreen::draw(float delta) {
|
||||
Viewport viewport(Window::width, Window::height);
|
||||
DrawContext ctx(nullptr, viewport, batch.get());
|
||||
|
||||
worldRenderer->draw(ctx, camera.get(), hudVisible, hud->isPause(), delta, postProcessing.get());
|
||||
worldRenderer->draw(
|
||||
ctx, *camera, hudVisible, hud->isPause(), delta, postProcessing.get()
|
||||
);
|
||||
|
||||
if (hudVisible) {
|
||||
hud->draw(ctx);
|
||||
|
||||
@ -75,7 +75,7 @@ void Batch2D::vertex(
|
||||
buffer[index++] = a;
|
||||
}
|
||||
|
||||
void Batch2D::texture(Texture* new_texture){
|
||||
void Batch2D::texture(const Texture* new_texture){
|
||||
if (currentTexture == new_texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ class Batch2D : public Flushable {
|
||||
std::unique_ptr<Texture> blank;
|
||||
size_t index;
|
||||
glm::vec4 color;
|
||||
Texture* currentTexture;
|
||||
const Texture* currentTexture;
|
||||
DrawPrimitive primitive = DrawPrimitive::triangle;
|
||||
UVRegion region {0.0f, 0.0f, 1.0f, 1.0f};
|
||||
|
||||
@ -40,7 +40,7 @@ public:
|
||||
~Batch2D();
|
||||
|
||||
void begin();
|
||||
void texture(Texture* texture);
|
||||
void texture(const Texture* texture);
|
||||
void untexture();
|
||||
void setRegion(UVRegion region);
|
||||
void sprite(float x, float y, float w, float h, const UVRegion& region, glm::vec4 tint);
|
||||
|
||||
@ -106,7 +106,7 @@ void Batch3D::face(
|
||||
tint.r, tint.g, tint.b, tint.a);
|
||||
}
|
||||
|
||||
void Batch3D::texture(Texture* new_texture){
|
||||
void Batch3D::texture(const Texture* new_texture){
|
||||
if (currentTexture == new_texture)
|
||||
return;
|
||||
flush();
|
||||
|
||||
@ -18,7 +18,7 @@ class Batch3D : public Flushable {
|
||||
std::unique_ptr<Texture> blank;
|
||||
size_t index;
|
||||
|
||||
Texture* currentTexture;
|
||||
const Texture* currentTexture;
|
||||
|
||||
void vertex(
|
||||
float x, float y, float z,
|
||||
@ -47,11 +47,36 @@ public:
|
||||
~Batch3D();
|
||||
|
||||
void begin();
|
||||
void texture(Texture* texture);
|
||||
void sprite(glm::vec3 pos, glm::vec3 up, glm::vec3 right, float w, float h, const UVRegion& uv, glm::vec4 tint);
|
||||
void xSprite(float w, float h, const UVRegion& uv, const glm::vec4 tint, bool shading=true);
|
||||
void cube(const glm::vec3 coords, const glm::vec3 size, const UVRegion(&texfaces)[6], const glm::vec4 tint, bool shading=true);
|
||||
void blockCube(const glm::vec3 size, const UVRegion(&texfaces)[6], const glm::vec4 tint, bool shading=true);
|
||||
void texture(const Texture* texture);
|
||||
void sprite(
|
||||
glm::vec3 pos,
|
||||
glm::vec3 up,
|
||||
glm::vec3 right,
|
||||
float w,
|
||||
float h,
|
||||
const UVRegion& uv,
|
||||
glm::vec4 tint
|
||||
);
|
||||
void xSprite(
|
||||
float w,
|
||||
float h,
|
||||
const UVRegion& uv,
|
||||
const glm::vec4 tint,
|
||||
bool shading = true
|
||||
);
|
||||
void cube(
|
||||
const glm::vec3 coords,
|
||||
const glm::vec3 size,
|
||||
const UVRegion (&texfaces)[6],
|
||||
const glm::vec4 tint,
|
||||
bool shading = true
|
||||
);
|
||||
void blockCube(
|
||||
const glm::vec3 size,
|
||||
const UVRegion (&texfaces)[6],
|
||||
const glm::vec4 tint,
|
||||
bool shading = true
|
||||
);
|
||||
void vertex(glm::vec3 pos, glm::vec2 uv, glm::vec4 tint);
|
||||
void point(glm::vec3 pos, glm::vec4 tint);
|
||||
void flush() override;
|
||||
|
||||
@ -30,10 +30,10 @@ Cubemap::Cubemap(uint width, uint height, ImageFormat imageFormat)
|
||||
}
|
||||
}
|
||||
|
||||
void Cubemap::bind(){
|
||||
void Cubemap::bind() const {
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
||||
}
|
||||
|
||||
void Cubemap::unbind() {
|
||||
void Cubemap::unbind() const {
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
|
||||
@ -7,6 +7,6 @@ class Cubemap : public GLTexture {
|
||||
public:
|
||||
Cubemap(uint width, uint height, ImageFormat format);
|
||||
|
||||
virtual void bind() override;
|
||||
virtual void unbind() override;
|
||||
virtual void bind() const override;
|
||||
virtual void unbind() const override;
|
||||
};
|
||||
|
||||
@ -33,11 +33,11 @@ GLTexture::~GLTexture() {
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
|
||||
void GLTexture::bind(){
|
||||
void GLTexture::bind() const {
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
}
|
||||
|
||||
void GLTexture::unbind() {
|
||||
void GLTexture::unbind() const {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@ public:
|
||||
GLTexture(const ubyte* data, uint width, uint height, ImageFormat format);
|
||||
virtual ~GLTexture();
|
||||
|
||||
virtual void bind() override;
|
||||
virtual void unbind() override;
|
||||
virtual void bind() const override;
|
||||
virtual void unbind() const override;
|
||||
virtual void reload(const ubyte* data);
|
||||
|
||||
void setNearestFilter();
|
||||
|
||||
@ -29,6 +29,11 @@ void Mesh::addBox(glm::vec3 pos, glm::vec3 size) {
|
||||
addPlane(pos-X*size, Z*size, Y*size, -X);
|
||||
}
|
||||
|
||||
void Mesh::scale(const glm::vec3& size) {
|
||||
for (auto& vertex : vertices) {
|
||||
vertex.coord *= size;
|
||||
}
|
||||
}
|
||||
|
||||
void Model::clean() {
|
||||
meshes.erase(
|
||||
|
||||
@ -17,6 +17,7 @@ namespace model {
|
||||
|
||||
void addPlane(glm::vec3 pos, glm::vec3 right, glm::vec3 up, glm::vec3 norm);
|
||||
void addBox(glm::vec3 pos, glm::vec3 size);
|
||||
void scale(const glm::vec3& size);
|
||||
};
|
||||
|
||||
struct Model {
|
||||
|
||||
@ -17,8 +17,8 @@ public:
|
||||
|
||||
virtual ~Texture() {}
|
||||
|
||||
virtual void bind() = 0;
|
||||
virtual void unbind() = 0;
|
||||
virtual void bind() const = 0;
|
||||
virtual void unbind() const = 0;
|
||||
|
||||
virtual void reload(const ImageData& image) = 0;
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "ModelBatch.hpp"
|
||||
|
||||
#include "assets/assets_util.hpp"
|
||||
#include "graphics/core/Mesh.hpp"
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/core/Atlas.hpp"
|
||||
@ -77,6 +78,7 @@ void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix,
|
||||
const texture_names_map* varTextures,
|
||||
bool backlight) {
|
||||
glm::vec3 gpos = matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
gpos += lightsOffset;
|
||||
light_t light = chunks->getLight(
|
||||
std::floor(gpos.x),
|
||||
std::floor(std::min(CHUNK_H-1.0f, gpos.y)),
|
||||
@ -137,9 +139,13 @@ void ModelBatch::render() {
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
void ModelBatch::setLightsOffset(const glm::vec3& offset) {
|
||||
lightsOffset = offset;
|
||||
}
|
||||
|
||||
void ModelBatch::setTexture(const std::string& name,
|
||||
const texture_names_map* varTextures) {
|
||||
if (name.at(0) == '$') {
|
||||
if (varTextures && name.at(0) == '$') {
|
||||
const auto& found = varTextures->find(name);
|
||||
if (found == varTextures->end()) {
|
||||
return setTexture(nullptr);
|
||||
@ -147,25 +153,13 @@ void ModelBatch::setTexture(const std::string& name,
|
||||
return setTexture(found->second, varTextures);
|
||||
}
|
||||
}
|
||||
size_t sep = name.find(':');
|
||||
if (sep == std::string::npos) {
|
||||
setTexture(assets->get<Texture>(name));
|
||||
} else {
|
||||
auto atlas = assets->get<Atlas>(name.substr(0, sep));
|
||||
if (atlas == nullptr) {
|
||||
setTexture(nullptr);
|
||||
} else {
|
||||
setTexture(atlas->getTexture());
|
||||
if (auto reg = atlas->getIf(name.substr(sep+1))) {
|
||||
region = *reg;
|
||||
} else {
|
||||
setTexture("blocks:notfound", varTextures);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto textureRegion = util::get_texture_region(*assets, name, "blocks:notfound");
|
||||
setTexture(textureRegion.texture);
|
||||
region = textureRegion.region;
|
||||
}
|
||||
|
||||
void ModelBatch::setTexture(Texture* texture) {
|
||||
void ModelBatch::setTexture(const Texture* texture) {
|
||||
if (texture == nullptr) {
|
||||
texture = blank.get();
|
||||
}
|
||||
|
||||
@ -31,9 +31,10 @@ class ModelBatch {
|
||||
|
||||
Assets* assets;
|
||||
Chunks* chunks;
|
||||
Texture* texture = nullptr;
|
||||
const Texture* texture = nullptr;
|
||||
UVRegion region {0.0f, 0.0f, 1.0f, 1.0f};
|
||||
const EngineSettings* settings;
|
||||
glm::vec3 lightsOffset {};
|
||||
|
||||
static inline glm::vec3 SUN_VECTOR {0.411934f, 0.863868f, -0.279161f};
|
||||
|
||||
@ -71,7 +72,7 @@ class ModelBatch {
|
||||
bool backlight);
|
||||
void setTexture(const std::string& name,
|
||||
const texture_names_map* varTextures);
|
||||
void setTexture(Texture* texture);
|
||||
void setTexture(const Texture* texture);
|
||||
void flush();
|
||||
|
||||
struct DrawEntry {
|
||||
@ -96,4 +97,6 @@ public:
|
||||
const model::Model* model,
|
||||
const texture_names_map* varTextures);
|
||||
void render();
|
||||
|
||||
void setLightsOffset(const glm::vec3& offset);
|
||||
};
|
||||
|
||||
74
src/graphics/render/ModelsGenerator.cpp
Normal file
74
src/graphics/render/ModelsGenerator.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "ModelsGenerator.hpp"
|
||||
|
||||
#include "assets/Assets.hpp"
|
||||
#include "items/ItemDef.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
|
||||
static debug::Logger logger("models-generator");
|
||||
|
||||
static void configure_textures(
|
||||
model::Model& model,
|
||||
const Block& blockDef,
|
||||
const Assets& assets
|
||||
) {
|
||||
for (auto& mesh : model.meshes) {
|
||||
auto& texture = mesh.texture;
|
||||
if (texture.empty() || texture.at(0) != '$') {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
int index = std::stoi(texture.substr(1));
|
||||
texture = "blocks:"+blockDef.textureFaces.at(index);
|
||||
} catch (const std::invalid_argument& err) {
|
||||
} catch (const std::runtime_error& err) {
|
||||
logger.error() << err.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static model::Model create_flat_model(
|
||||
const std::string& texture, const Assets& assets
|
||||
) {
|
||||
auto model = assets.require<model::Model>("drop-item");
|
||||
for (auto& mesh : model.meshes) {
|
||||
if (mesh.texture == "$0") {
|
||||
mesh.texture = texture;
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
model::Model ModelsGenerator::generate(
|
||||
const ItemDef& def, const Content& content, const Assets& assets
|
||||
) {
|
||||
if (def.iconType == ItemIconType::BLOCK) {
|
||||
auto model = assets.require<model::Model>("block");
|
||||
const auto& blockDef = content.blocks.require(def.icon);
|
||||
if (blockDef.model == BlockModel::xsprite) {
|
||||
return create_flat_model(
|
||||
"blocks:" + blockDef.textureFaces.at(0), assets
|
||||
);
|
||||
}
|
||||
for (auto& mesh : model.meshes) {
|
||||
switch (blockDef.model) {
|
||||
case BlockModel::aabb: {
|
||||
glm::vec3 size = blockDef.hitboxes.at(0).size();
|
||||
float m = glm::max(size.x, glm::max(size.y, size.z));
|
||||
m = glm::min(1.0f, m);
|
||||
mesh.scale(size / m);
|
||||
break;
|
||||
} default:
|
||||
break;
|
||||
}
|
||||
mesh.scale(glm::vec3(0.3f));
|
||||
}
|
||||
configure_textures(model, blockDef, assets);
|
||||
return model;
|
||||
} else if (def.iconType == ItemIconType::SPRITE) {
|
||||
return create_flat_model(def.icon, assets);
|
||||
} else {
|
||||
return model::Model();
|
||||
}
|
||||
}
|
||||
14
src/graphics/render/ModelsGenerator.hpp
Normal file
14
src/graphics/render/ModelsGenerator.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics/core/Model.hpp"
|
||||
|
||||
struct ItemDef;
|
||||
class Assets;
|
||||
class Content;
|
||||
|
||||
class ModelsGenerator {
|
||||
public:
|
||||
static model::Model generate(
|
||||
const ItemDef& def, const Content& content, const Assets& assets
|
||||
);
|
||||
};
|
||||
@ -58,11 +58,13 @@ Skybox::Skybox(uint size, Shader* shader)
|
||||
|
||||
Skybox::~Skybox() = default;
|
||||
|
||||
void Skybox::drawBackground(Camera* camera, Assets* assets, int width, int height) {
|
||||
auto backShader = assets->get<Shader>("background");
|
||||
void Skybox::drawBackground(
|
||||
const Camera& camera, const Assets& assets, int width, int height
|
||||
) {
|
||||
auto backShader = assets.get<Shader>("background");
|
||||
backShader->use();
|
||||
backShader->uniformMatrix("u_view", camera->getView(false));
|
||||
backShader->uniform1f("u_zoom", camera->zoom*camera->getFov()/(M_PI*0.5f));
|
||||
backShader->uniformMatrix("u_view", camera.getView(false));
|
||||
backShader->uniform1f("u_zoom", camera.zoom*camera.getFov()/(M_PI*0.5f));
|
||||
backShader->uniform1f("u_ar", float(width)/float(height));
|
||||
backShader->uniform1i("u_cubemap", 1);
|
||||
bind();
|
||||
@ -93,8 +95,8 @@ void Skybox::drawStars(float angle, float opacity) {
|
||||
|
||||
void Skybox::draw(
|
||||
const DrawContext& pctx,
|
||||
Camera* camera,
|
||||
Assets* assets,
|
||||
const Camera& camera,
|
||||
const Assets& assets,
|
||||
float daytime,
|
||||
float fog)
|
||||
{
|
||||
@ -107,9 +109,9 @@ void Skybox::draw(
|
||||
DrawContext ctx = pctx.sub();
|
||||
ctx.setBlendMode(BlendMode::addition);
|
||||
|
||||
auto p_shader = assets->get<Shader>("ui3d");
|
||||
auto p_shader = assets.get<Shader>("ui3d");
|
||||
p_shader->use();
|
||||
p_shader->uniformMatrix("u_projview", camera->getProjView(false));
|
||||
p_shader->uniformMatrix("u_projview", camera.getProjView(false));
|
||||
p_shader->uniformMatrix("u_apply", glm::mat4(1.0f));
|
||||
batch3d->begin();
|
||||
|
||||
@ -117,7 +119,7 @@ void Skybox::draw(
|
||||
float opacity = glm::pow(1.0f-fog, 7.0f);
|
||||
|
||||
for (auto& sprite : sprites) {
|
||||
batch3d->texture(assets->get<Texture>(sprite.texture));
|
||||
batch3d->texture(assets.get<Texture>(sprite.texture));
|
||||
|
||||
float sangle = daytime * float(M_PI)*2.0 + sprite.phase;
|
||||
float distance = sprite.distance;
|
||||
@ -136,6 +138,7 @@ void Skybox::draw(
|
||||
}
|
||||
|
||||
void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality) {
|
||||
float dayTime = t;
|
||||
DrawContext ctx = pctx.sub();
|
||||
ctx.setDepthMask(false);
|
||||
ctx.setDepthTest(false);
|
||||
@ -180,10 +183,12 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality)
|
||||
};
|
||||
t *= M_PI*2.0f;
|
||||
|
||||
lightDir = glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f));
|
||||
shader->uniform1i("u_quality", quality);
|
||||
shader->uniform1f("u_mie", mie);
|
||||
shader->uniform1f("u_fog", mie - 1.0f);
|
||||
shader->uniform3f("u_lightDir", glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f)));
|
||||
shader->uniform3f("u_lightDir", lightDir);
|
||||
shader->uniform1f("u_dayTime", dayTime);
|
||||
for (uint face = 0; face < 6; face++) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap->getId(), 0);
|
||||
shader->uniform3f("u_xaxis", xaxs[face]);
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
#include "typedefs.hpp"
|
||||
#include "maths/fastmaths.hpp"
|
||||
|
||||
@ -27,21 +28,24 @@ class Skybox {
|
||||
Shader* shader;
|
||||
bool ready = false;
|
||||
FastRandom random;
|
||||
glm::vec3 lightDir;
|
||||
|
||||
std::unique_ptr<Mesh> mesh;
|
||||
std::unique_ptr<Batch3D> batch3d;
|
||||
std::vector<skysprite> sprites;
|
||||
|
||||
void drawStars(float angle, float opacity);
|
||||
void drawBackground(Camera* camera, Assets* assets, int width, int height);
|
||||
void drawBackground(
|
||||
const Camera& camera, const Assets& assets, int width, int height
|
||||
);
|
||||
public:
|
||||
Skybox(uint size, Shader* shader);
|
||||
~Skybox();
|
||||
|
||||
void draw(
|
||||
const DrawContext& pctx,
|
||||
Camera* camera,
|
||||
Assets* assets,
|
||||
const Camera& camera,
|
||||
const Assets& assets,
|
||||
float daytime,
|
||||
float fog
|
||||
);
|
||||
@ -52,4 +56,8 @@ public:
|
||||
bool isReady() const {
|
||||
return ready;
|
||||
}
|
||||
|
||||
const glm::vec3 getLightDir() const {
|
||||
return lightDir;
|
||||
}
|
||||
};
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "assets/Assets.hpp"
|
||||
#include "assets/assets_util.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "frontend/LevelFrontend.hpp"
|
||||
@ -78,17 +79,17 @@ WorldRenderer::WorldRenderer(
|
||||
WorldRenderer::~WorldRenderer() = default;
|
||||
|
||||
bool WorldRenderer::drawChunk(
|
||||
size_t index, Camera* camera, Shader* shader, bool culling
|
||||
size_t index, const Camera& camera, Shader* shader, bool culling
|
||||
) {
|
||||
auto chunk = level->chunks->getChunks()[index];
|
||||
if (!chunk->flags.lighted) {
|
||||
return false;
|
||||
}
|
||||
float distance = glm::distance(
|
||||
camera->position,
|
||||
camera.position,
|
||||
glm::vec3(
|
||||
(chunk->x + 0.5f) * CHUNK_W,
|
||||
camera->position.y,
|
||||
camera.position.y,
|
||||
(chunk->z + 0.5f) * CHUNK_D
|
||||
)
|
||||
);
|
||||
@ -113,7 +114,9 @@ bool WorldRenderer::drawChunk(
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
||||
void WorldRenderer::drawChunks(
|
||||
Chunks* chunks, const Camera& camera, Shader* shader
|
||||
) {
|
||||
auto assets = engine->getAssets();
|
||||
auto atlas = assets->get<Atlas>("blocks");
|
||||
|
||||
@ -127,8 +130,8 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
||||
if (chunks->getChunks()[i] == nullptr) continue;
|
||||
indices.emplace_back(i);
|
||||
}
|
||||
float px = camera->position.x / static_cast<float>(CHUNK_W) - 0.5f;
|
||||
float pz = camera->position.z / static_cast<float>(CHUNK_D) - 0.5f;
|
||||
float px = camera.position.x / static_cast<float>(CHUNK_W) - 0.5f;
|
||||
float pz = camera.position.z / static_cast<float>(CHUNK_D) - 0.5f;
|
||||
std::sort(indices.begin(), indices.end(), [chunks, px, pz](auto i, auto j) {
|
||||
const auto& chunksBuffer = chunks->getChunks();
|
||||
const auto a = chunksBuffer[i].get();
|
||||
@ -141,7 +144,7 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
||||
});
|
||||
bool culling = engine->getSettings().graphics.frustumCulling.get();
|
||||
if (culling) {
|
||||
frustumCulling->update(camera->getProjView());
|
||||
frustumCulling->update(camera.getProjView());
|
||||
}
|
||||
chunks->visible = 0;
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
@ -151,20 +154,21 @@ void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
|
||||
|
||||
void WorldRenderer::setupWorldShader(
|
||||
Shader* shader,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
float fogFactor
|
||||
) {
|
||||
shader->use();
|
||||
shader->uniformMatrix("u_model", glm::mat4(1.0f));
|
||||
shader->uniformMatrix("u_proj", camera->getProjection());
|
||||
shader->uniformMatrix("u_view", camera->getView());
|
||||
shader->uniformMatrix("u_proj", camera.getProjection());
|
||||
shader->uniformMatrix("u_view", camera.getView());
|
||||
shader->uniform1f("u_timer", timer);
|
||||
shader->uniform1f("u_gamma", settings.graphics.gamma.get());
|
||||
shader->uniform1f("u_fogFactor", fogFactor);
|
||||
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve.get());
|
||||
shader->uniform1f("u_dayTime", level->getWorld()->getInfo().daytime);
|
||||
shader->uniform3f("u_cameraPos", camera->position);
|
||||
shader->uniform2f("u_lightDir", skybox->getLightDir());
|
||||
shader->uniform3f("u_cameraPos", camera.position);
|
||||
shader->uniform1i("u_cubemap", 1);
|
||||
|
||||
auto indices = level->content->getIndices();
|
||||
@ -186,7 +190,7 @@ void WorldRenderer::setupWorldShader(
|
||||
|
||||
void WorldRenderer::renderLevel(
|
||||
const DrawContext&,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
float delta,
|
||||
bool pause
|
||||
@ -251,10 +255,10 @@ void WorldRenderer::renderBlockSelection() {
|
||||
}
|
||||
|
||||
void WorldRenderer::renderLines(
|
||||
Camera* camera, Shader* linesShader, const DrawContext& pctx
|
||||
const Camera& camera, Shader* linesShader, const DrawContext& pctx
|
||||
) {
|
||||
linesShader->use();
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
||||
linesShader->uniformMatrix("u_projview", camera.getProjView());
|
||||
if (player->selection.vox.id != BLOCK_VOID) {
|
||||
renderBlockSelection();
|
||||
}
|
||||
@ -268,7 +272,7 @@ void WorldRenderer::renderLines(
|
||||
}
|
||||
|
||||
void WorldRenderer::renderDebugLines(
|
||||
const DrawContext& pctx, Camera* camera, Shader* linesShader
|
||||
const DrawContext& pctx, const Camera& camera, Shader* linesShader
|
||||
) {
|
||||
DrawContext ctx = pctx.sub(lineBatch.get());
|
||||
const auto& viewport = ctx.getViewport();
|
||||
@ -280,8 +284,8 @@ void WorldRenderer::renderDebugLines(
|
||||
linesShader->use();
|
||||
|
||||
if (showChunkBorders) {
|
||||
linesShader->uniformMatrix("u_projview", camera->getProjView());
|
||||
glm::vec3 coord = player->camera->position;
|
||||
linesShader->uniformMatrix("u_projview", camera.getProjView());
|
||||
glm::vec3 coord = player->fpCamera->position;
|
||||
if (coord.x < 0) coord.x--;
|
||||
if (coord.z < 0) coord.z--;
|
||||
int cx = floordiv(static_cast<int>(coord.x), CHUNK_W);
|
||||
@ -310,7 +314,7 @@ void WorldRenderer::renderDebugLines(
|
||||
-length,
|
||||
length
|
||||
) * model *
|
||||
glm::inverse(camera->rotation)
|
||||
glm::inverse(camera.rotation)
|
||||
);
|
||||
|
||||
ctx.setDepthTest(false);
|
||||
@ -327,9 +331,70 @@ void WorldRenderer::renderDebugLines(
|
||||
lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
void WorldRenderer::renderHands(const Camera& camera, const Assets& assets) {
|
||||
auto entityShader = assets.get<Shader>("entity");
|
||||
auto indices = level->content->getIndices();
|
||||
|
||||
// get current chosen item
|
||||
const auto& inventory = player->getInventory();
|
||||
int slot = player->getChosenSlot();
|
||||
const ItemStack& stack = inventory->getSlot(slot);
|
||||
const auto& def = indices->items.require(stack.getItemId());
|
||||
|
||||
// prepare modified HUD camera
|
||||
Camera hudcam = camera;
|
||||
hudcam.far = 100.0f;
|
||||
hudcam.setFov(1.2f);
|
||||
hudcam.position = {};
|
||||
|
||||
// configure model matrix
|
||||
const glm::vec3 itemOffset(0.08f, 0.035f, -0.1);
|
||||
|
||||
static glm::mat4 prevRotation(1.0f);
|
||||
|
||||
const float speed = 24.0f;
|
||||
glm::mat4 matrix = glm::translate(glm::mat4(1.0f), itemOffset);
|
||||
matrix = glm::scale(matrix, glm::vec3(0.1f));
|
||||
glm::mat4 rotation = camera.rotation;
|
||||
glm::quat rot0 = glm::quat_cast(prevRotation);
|
||||
glm::quat rot1 = glm::quat_cast(rotation);
|
||||
glm::quat finalRot =
|
||||
glm::slerp(rot0, rot1, static_cast<float>(engine->getDelta() * speed));
|
||||
rotation = glm::mat4_cast(finalRot);
|
||||
matrix = rotation * matrix *
|
||||
glm::rotate(
|
||||
glm::mat4(1.0f), -glm::pi<float>() * 0.5f, glm::vec3(0, 1, 0)
|
||||
);
|
||||
prevRotation = rotation;
|
||||
auto offset = -(camera.position - player->getPosition());
|
||||
float angle = glm::radians(player->cam.x - 90);
|
||||
float cos = glm::cos(angle);
|
||||
float sin = glm::sin(angle);
|
||||
|
||||
float newX = offset.x * cos - offset.z * sin;
|
||||
float newZ = offset.x * sin + offset.z * cos;
|
||||
offset = glm::vec3(newX, offset.y, newZ);
|
||||
matrix = matrix * glm::translate(glm::mat4(1.0f), offset);
|
||||
|
||||
// render
|
||||
modelBatch->setLightsOffset(camera.position);
|
||||
modelBatch->draw(
|
||||
matrix,
|
||||
glm::vec3(1.0f),
|
||||
assets.get<model::Model>(def.modelName),
|
||||
nullptr
|
||||
);
|
||||
Window::clearDepth();
|
||||
setupWorldShader(entityShader, hudcam, engine->getSettings(), 0.0f);
|
||||
skybox->bind();
|
||||
modelBatch->render();
|
||||
modelBatch->setLightsOffset(glm::vec3());
|
||||
skybox->unbind();
|
||||
}
|
||||
|
||||
void WorldRenderer::draw(
|
||||
const DrawContext& pctx,
|
||||
Camera* camera,
|
||||
Camera& camera,
|
||||
bool hudVisible,
|
||||
bool pause,
|
||||
float delta,
|
||||
@ -338,15 +403,15 @@ void WorldRenderer::draw(
|
||||
timer += delta * !pause;
|
||||
auto world = level->getWorld();
|
||||
const Viewport& vp = pctx.getViewport();
|
||||
camera->aspect = vp.getWidth() / static_cast<float>(vp.getHeight());
|
||||
camera.aspect = vp.getWidth() / static_cast<float>(vp.getHeight());
|
||||
|
||||
const auto& settings = engine->getSettings();
|
||||
const auto& worldInfo = world->getInfo();
|
||||
|
||||
skybox->refresh(pctx, worldInfo.daytime, 1.0f + worldInfo.fog * 2.0f, 4);
|
||||
|
||||
auto assets = engine->getAssets();
|
||||
auto linesShader = assets->get<Shader>("lines");
|
||||
const auto& assets = *engine->getAssets();
|
||||
auto linesShader = assets.get<Shader>("lines");
|
||||
|
||||
// World render scope with diegetic HUD included
|
||||
{
|
||||
@ -367,22 +432,70 @@ void WorldRenderer::draw(
|
||||
// Debug lines
|
||||
if (hudVisible) {
|
||||
renderLines(camera, linesShader, ctx);
|
||||
if (player->currentCamera == player->fpCamera) {
|
||||
renderHands(camera, assets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hudVisible && player->debug) {
|
||||
renderDebugLines(wctx, camera, linesShader);
|
||||
}
|
||||
renderBlockOverlay(wctx, assets);
|
||||
}
|
||||
|
||||
// Rendering fullscreen quad with
|
||||
auto screenShader = assets->get<Shader>("screen");
|
||||
auto screenShader = assets.get<Shader>("screen");
|
||||
screenShader->use();
|
||||
screenShader->uniform1f("u_timer", timer);
|
||||
screenShader->uniform1f("u_dayTime", worldInfo.daytime);
|
||||
postProcessing->render(pctx, screenShader);
|
||||
}
|
||||
|
||||
void WorldRenderer::renderBlockOverlay(const DrawContext& wctx, const Assets& assets) {
|
||||
int x = std::floor(player->currentCamera->position.x);
|
||||
int y = std::floor(player->currentCamera->position.y);
|
||||
int z = std::floor(player->currentCamera->position.z);
|
||||
auto block = level->chunks->get(x, y, z);
|
||||
if (block && block->id) {
|
||||
const auto& def =
|
||||
level->content->getIndices()->blocks.require(block->id);
|
||||
if (def.overlayTexture.empty()) {
|
||||
return;
|
||||
}
|
||||
auto textureRegion = util::get_texture_region(
|
||||
assets, def.overlayTexture, "blocks:notfound"
|
||||
);
|
||||
DrawContext ctx = wctx.sub();
|
||||
ctx.setDepthTest(false);
|
||||
ctx.setCullFace(false);
|
||||
|
||||
auto& shader = assets.require<Shader>("ui3d");
|
||||
shader.use();
|
||||
batch3d->begin();
|
||||
shader.uniformMatrix("u_projview", glm::mat4(1.0f));
|
||||
shader.uniformMatrix("u_apply", glm::mat4(1.0f));
|
||||
auto light = level->chunks->getLight(x, y, z);
|
||||
float s = Lightmap::extract(light, 3) / 15.0f;
|
||||
glm::vec4 tint(
|
||||
glm::min(1.0f, Lightmap::extract(light, 0) / 15.0f + s),
|
||||
glm::min(1.0f, Lightmap::extract(light, 1) / 15.0f + s),
|
||||
glm::min(1.0f, Lightmap::extract(light, 2) / 15.0f + s),
|
||||
1.0f
|
||||
);
|
||||
batch3d->texture(textureRegion.texture);
|
||||
batch3d->sprite(
|
||||
glm::vec3(),
|
||||
glm::vec3(0, 1, 0),
|
||||
glm::vec3(1, 0, 0),
|
||||
2,
|
||||
2,
|
||||
textureRegion.region,
|
||||
tint
|
||||
);
|
||||
batch3d->flush();
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::drawBorders(
|
||||
int sx, int sy, int sz, int ex, int ey, int ez
|
||||
) {
|
||||
|
||||
@ -23,6 +23,7 @@ class Skybox;
|
||||
class PostProcessing;
|
||||
class DrawContext;
|
||||
class ModelBatch;
|
||||
class Assets;
|
||||
struct EngineSettings;
|
||||
|
||||
namespace model {
|
||||
@ -41,16 +42,20 @@ class WorldRenderer {
|
||||
std::unique_ptr<ModelBatch> modelBatch;
|
||||
float timer = 0.0f;
|
||||
|
||||
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling);
|
||||
void drawChunks(Chunks* chunks, Camera* camera, Shader* shader);
|
||||
bool drawChunk(size_t index, const Camera& camera, Shader* shader, bool culling);
|
||||
void drawChunks(Chunks* chunks, const Camera& camera, Shader* shader);
|
||||
|
||||
/// @brief Render block selection lines
|
||||
void renderBlockSelection();
|
||||
|
||||
void renderHands(const Camera& camera, const Assets& assets);
|
||||
|
||||
/// @brief Render lines (selection and debug)
|
||||
/// @param camera active camera
|
||||
/// @param linesShader shader used
|
||||
void renderLines(Camera* camera, Shader* linesShader, const DrawContext& pctx);
|
||||
void renderLines(
|
||||
const Camera& camera, Shader* linesShader, const DrawContext& pctx
|
||||
);
|
||||
|
||||
/// @brief Render all debug lines (chunks borders, coord system guides)
|
||||
/// @param context graphics context
|
||||
@ -58,13 +63,15 @@ class WorldRenderer {
|
||||
/// @param linesShader shader used
|
||||
void renderDebugLines(
|
||||
const DrawContext& context,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
Shader* linesShader
|
||||
);
|
||||
|
||||
void renderBlockOverlay(const DrawContext& context, const Assets& assets);
|
||||
|
||||
void setupWorldShader(
|
||||
Shader* shader,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
float fogFactor
|
||||
);
|
||||
@ -77,7 +84,7 @@ public:
|
||||
|
||||
void draw(
|
||||
const DrawContext& context,
|
||||
Camera* camera,
|
||||
Camera& camera,
|
||||
bool hudVisible,
|
||||
bool pause,
|
||||
float delta,
|
||||
@ -91,7 +98,7 @@ public:
|
||||
/// @param settings engine settings
|
||||
void renderLevel(
|
||||
const DrawContext& context,
|
||||
Camera* camera,
|
||||
const Camera& camera,
|
||||
const EngineSettings& settings,
|
||||
float delta,
|
||||
bool pause
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "InventoryView.hpp"
|
||||
|
||||
#include "assets/Assets.hpp"
|
||||
#include "assets/assets_util.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "frontend/LevelFrontend.hpp"
|
||||
#include "frontend/locale.hpp"
|
||||
@ -161,9 +162,9 @@ void SlotView::draw(const DrawContext* pctx, Assets* assets) {
|
||||
|
||||
auto& item = indices->items.require(stack.getItemId());
|
||||
switch (item.iconType) {
|
||||
case item_icon_type::none:
|
||||
case ItemIconType::NONE:
|
||||
break;
|
||||
case item_icon_type::block: {
|
||||
case ItemIconType::BLOCK: {
|
||||
const Block& cblock = content->blocks.require(item.icon);
|
||||
batch->texture(previews->getTexture());
|
||||
|
||||
@ -173,23 +174,14 @@ void SlotView::draw(const DrawContext* pctx, Assets* assets) {
|
||||
0, 0, 0, region, false, true, tint);
|
||||
break;
|
||||
}
|
||||
case item_icon_type::sprite: {
|
||||
size_t index = item.icon.find(':');
|
||||
std::string name = item.icon.substr(index+1);
|
||||
UVRegion region(0.0f, 0.0, 1.0f, 1.0f);
|
||||
if (index == std::string::npos) {
|
||||
batch->texture(assets->get<Texture>(name));
|
||||
} else {
|
||||
std::string atlasname = item.icon.substr(0, index);
|
||||
auto atlas = assets->get<Atlas>(atlasname);
|
||||
if (atlas && atlas->has(name)) {
|
||||
region = atlas->get(name);
|
||||
batch->texture(atlas->getTexture());
|
||||
}
|
||||
}
|
||||
case ItemIconType::SPRITE: {
|
||||
auto textureRegion =
|
||||
util::get_texture_region(*assets, item.icon, "blocks:notfound");
|
||||
|
||||
batch->texture(textureRegion.texture);
|
||||
batch->rect(
|
||||
pos.x, pos.y, slotSize, slotSize,
|
||||
0, 0, 0, region, false, true, tint);
|
||||
0, 0, 0, textureRegion.region, false, true, tint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,4 +14,5 @@ void ItemDef::cloneTo(ItemDef& dst) {
|
||||
dst.icon = icon;
|
||||
dst.placingBlock = placingBlock;
|
||||
dst.scriptName = scriptName;
|
||||
dst.modelName = modelName;
|
||||
}
|
||||
|
||||
@ -12,10 +12,10 @@ struct item_funcs_set {
|
||||
bool on_block_break_by : 1;
|
||||
};
|
||||
|
||||
enum class item_icon_type {
|
||||
none, // invisible (core:empty) must not be rendered
|
||||
sprite, // textured quad: icon is `atlas_name:texture_name`
|
||||
block, // block preview: icon is string block id
|
||||
enum class ItemIconType {
|
||||
NONE, // invisible (core:empty) must not be rendered
|
||||
SPRITE, // textured quad: icon is `atlas_name:texture_name`
|
||||
BLOCK, // block preview: icon is string block id
|
||||
};
|
||||
|
||||
struct ItemDef {
|
||||
@ -29,12 +29,14 @@ struct ItemDef {
|
||||
bool generated = false;
|
||||
uint8_t emission[4] {0, 0, 0, 0};
|
||||
|
||||
item_icon_type iconType = item_icon_type::sprite;
|
||||
ItemIconType iconType = ItemIconType::SPRITE;
|
||||
std::string icon = "blocks:notfound";
|
||||
|
||||
std::string placingBlock = "core:air";
|
||||
std::string scriptName = name.substr(name.find(':') + 1);
|
||||
|
||||
std::string modelName = name + ".model";
|
||||
|
||||
struct {
|
||||
itemid_t id;
|
||||
blockid_t placingBlock;
|
||||
|
||||
@ -41,7 +41,7 @@ CameraControl::CameraControl(
|
||||
const std::shared_ptr<Player>& player, const CameraSettings& settings
|
||||
)
|
||||
: player(player),
|
||||
camera(player->camera),
|
||||
camera(player->fpCamera),
|
||||
settings(settings),
|
||||
offset(0.0f, 0.7f, 0.0f) {
|
||||
}
|
||||
@ -353,7 +353,7 @@ static void pick_block(
|
||||
voxel* PlayerController::updateSelection(float maxDistance) {
|
||||
auto indices = level->content->getIndices();
|
||||
auto chunks = level->chunks.get();
|
||||
auto camera = player->camera.get();
|
||||
auto camera = player->fpCamera.get();
|
||||
auto& selection = player->selection;
|
||||
|
||||
glm::vec3 end;
|
||||
@ -416,7 +416,7 @@ voxel* PlayerController::updateSelection(float maxDistance) {
|
||||
void PlayerController::processRightClick(const Block& def, const Block& target) {
|
||||
const auto& selection = player->selection;
|
||||
auto chunks = level->chunks.get();
|
||||
auto camera = player->camera.get();
|
||||
auto camera = player->fpCamera.get();
|
||||
|
||||
blockstate state {};
|
||||
state.rotation = determine_rotation(&def, selection.normal, camera->dir);
|
||||
|
||||
@ -10,55 +10,71 @@ static const ItemDef* get_item_def(lua::State* L, int idx) {
|
||||
return indices->items.get(id);
|
||||
}
|
||||
|
||||
static int l_item_name(lua::State* L) {
|
||||
static int l_name(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
return lua::pushstring(L, def->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_item_index(lua::State* L) {
|
||||
static int l_index(lua::State* L) {
|
||||
auto name = lua::require_string(L, 1);
|
||||
return lua::pushinteger(L, content->items.require(name).rt.id);
|
||||
}
|
||||
|
||||
static int l_item_stack_size(lua::State* L) {
|
||||
static int l_stack_size(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
return lua::pushinteger(L, def->stackSize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_item_defs_count(lua::State* L) {
|
||||
static int l_defs_count(lua::State* L) {
|
||||
return lua::pushinteger(L, indices->items.count());
|
||||
}
|
||||
|
||||
static int l_item_get_icon(lua::State* L) {
|
||||
static int l_get_icon(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
switch (def->iconType) {
|
||||
case item_icon_type::none:
|
||||
case ItemIconType::NONE:
|
||||
return 0;
|
||||
case item_icon_type::sprite:
|
||||
case ItemIconType::SPRITE:
|
||||
return lua::pushstring(L, def->icon);
|
||||
case item_icon_type::block:
|
||||
case ItemIconType::BLOCK:
|
||||
return lua::pushstring(L, "block-previews:" + def->icon);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_item_caption(lua::State* L) {
|
||||
static int l_caption(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
return lua::pushstring(L, def->caption);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_placing_block(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
return lua::pushinteger(L, def->rt.placingBlock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_model_name(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
return lua::pushstring(L, def->modelName);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg itemlib[] = {
|
||||
{"index", lua::wrap<l_item_index>},
|
||||
{"name", lua::wrap<l_item_name>},
|
||||
{"stack_size", lua::wrap<l_item_stack_size>},
|
||||
{"defs_count", lua::wrap<l_item_defs_count>},
|
||||
{"icon", lua::wrap<l_item_get_icon>},
|
||||
{"caption", lua::wrap<l_item_caption>},
|
||||
{"index", lua::wrap<l_index>},
|
||||
{"name", lua::wrap<l_name>},
|
||||
{"stack_size", lua::wrap<l_stack_size>},
|
||||
{"defs_count", lua::wrap<l_defs_count>},
|
||||
{"icon", lua::wrap<l_get_icon>},
|
||||
{"caption", lua::wrap<l_caption>},
|
||||
{"placing_block", lua::wrap<l_placing_block>},
|
||||
{"model_name", lua::wrap<l_model_name>},
|
||||
{NULL, NULL}};
|
||||
|
||||
@ -85,7 +85,7 @@ static int l_set_rot(lua::State* L) {
|
||||
|
||||
static int l_get_dir(lua::State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
return lua::pushvec3(L, player->camera->front);
|
||||
return lua::pushvec3(L, player->fpCamera->front);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -40,11 +40,11 @@ Player::Player(
|
||||
position(position),
|
||||
inventory(std::move(inv)),
|
||||
eid(eid),
|
||||
camera(level->getCamera("core:first-person")),
|
||||
fpCamera(level->getCamera("core:first-person")),
|
||||
spCamera(level->getCamera("core:third-person-front")),
|
||||
tpCamera(level->getCamera("core:third-person-back")),
|
||||
currentCamera(camera) {
|
||||
camera->setFov(glm::radians(90.0f));
|
||||
currentCamera(fpCamera) {
|
||||
fpCamera->setFov(glm::radians(90.0f));
|
||||
spCamera->setFov(glm::radians(90.0f));
|
||||
tpCamera->setFov(glm::radians(90.0f));
|
||||
}
|
||||
@ -93,16 +93,16 @@ void Player::updateInput(PlayerInput& input, float delta) {
|
||||
|
||||
glm::vec3 dir(0, 0, 0);
|
||||
if (input.moveForward) {
|
||||
dir += camera->dir;
|
||||
dir += fpCamera->dir;
|
||||
}
|
||||
if (input.moveBack) {
|
||||
dir -= camera->dir;
|
||||
dir -= fpCamera->dir;
|
||||
}
|
||||
if (input.moveRight) {
|
||||
dir += camera->right;
|
||||
dir += fpCamera->right;
|
||||
}
|
||||
if (input.moveLeft) {
|
||||
dir -= camera->right;
|
||||
dir -= fpCamera->right;
|
||||
}
|
||||
if (glm::length(dir) > 0.0f) {
|
||||
dir = glm::normalize(dir);
|
||||
@ -166,7 +166,7 @@ void Player::postUpdate() {
|
||||
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
|
||||
skeleton.visible = currentCamera != camera;
|
||||
skeleton.visible = currentCamera != fpCamera;
|
||||
|
||||
auto body = skeleton.config->find("body");
|
||||
auto head = skeleton.config->find("head");
|
||||
@ -252,7 +252,7 @@ entityid_t Player::getSelectedEntity() const {
|
||||
return selectedEid;
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> Player::getInventory() const {
|
||||
const std::shared_ptr<Inventory>& Player::getInventory() const {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@ -289,7 +289,7 @@ void Player::deserialize(const dv::value& src) {
|
||||
const auto& posarr = src["position"];
|
||||
|
||||
dv::get_vec(posarr, position);
|
||||
camera->position = position;
|
||||
fpCamera->position = position;
|
||||
|
||||
const auto& rotarr = src["rotation"];
|
||||
dv::get_vec(rotarr, cam);
|
||||
|
||||
@ -52,7 +52,7 @@ class Player : public Object, public Serializable {
|
||||
entityid_t eid;
|
||||
entityid_t selectedEid;
|
||||
public:
|
||||
std::shared_ptr<Camera> camera, spCamera, tpCamera;
|
||||
std::shared_ptr<Camera> fpCamera, spCamera, tpCamera;
|
||||
std::shared_ptr<Camera> currentCamera;
|
||||
bool debug = false;
|
||||
glm::vec3 cam {};
|
||||
@ -91,7 +91,7 @@ public:
|
||||
|
||||
entityid_t getSelectedEntity() const;
|
||||
|
||||
std::shared_ptr<Inventory> getInventory() const;
|
||||
const std::shared_ptr<Inventory>& getInventory() const;
|
||||
|
||||
glm::vec3 getPosition() const {
|
||||
return position;
|
||||
|
||||
@ -141,6 +141,7 @@ void Block::cloneTo(Block& dst) {
|
||||
dst.uiLayout = uiLayout;
|
||||
dst.inventorySize = inventorySize;
|
||||
dst.tickInterval = tickInterval;
|
||||
dst.overlayTexture = overlayTexture;
|
||||
}
|
||||
|
||||
static std::set<std::string, std::less<>> RESERVED_BLOCK_FIELDS {
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "maths/UVRegion.hpp"
|
||||
#include "maths/aabb.hpp"
|
||||
@ -111,7 +112,7 @@ public:
|
||||
std::string caption;
|
||||
|
||||
/// @brief Textures set applied to block sides
|
||||
std::string textureFaces[6]; // -x,x, -y,y, -z,z
|
||||
std::array<std::string, 6> textureFaces; // -x,x, -y,y, -z,z
|
||||
|
||||
std::vector<std::string> modelTextures = {};
|
||||
std::vector<BoxModel> modelBoxes = {};
|
||||
@ -184,6 +185,9 @@ public:
|
||||
/// @brief Block will be used instead of this if generated on surface
|
||||
std::string surfaceReplacement = name;
|
||||
|
||||
/// @brief Texture will be shown on screen if camera is inside of the block
|
||||
std::string overlayTexture;
|
||||
|
||||
/// @brief Default block layout will be used by hud.open_block(...)
|
||||
std::string uiLayout = name;
|
||||
|
||||
|
||||
@ -29,21 +29,21 @@ void Camera::rotate(float x, float y, float z) {
|
||||
updateVectors();
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getProjection() {
|
||||
glm::mat4 Camera::getProjection() const {
|
||||
constexpr float epsilon = 1e-6f; // 0.000001
|
||||
float aspect_ratio = this->aspect;
|
||||
if (std::fabs(aspect_ratio) < epsilon) {
|
||||
aspect_ratio = (float)Window::width / (float)Window::height;
|
||||
}
|
||||
if (perspective)
|
||||
return glm::perspective(fov * zoom, aspect_ratio, 0.05f, 1500.0f);
|
||||
return glm::perspective(fov * zoom, aspect_ratio, near, far);
|
||||
else if (flipped)
|
||||
return glm::ortho(0.0f, fov * aspect_ratio, fov, 0.0f);
|
||||
else
|
||||
return glm::ortho(0.0f, fov * aspect_ratio, 0.0f, fov);
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getView(bool pos) {
|
||||
glm::mat4 Camera::getView(bool pos) const {
|
||||
glm::vec3 camera_pos = this->position;
|
||||
if (!pos) {
|
||||
camera_pos = glm::vec3(0.0f);
|
||||
@ -55,7 +55,7 @@ glm::mat4 Camera::getView(bool pos) {
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 Camera::getProjView(bool pos) {
|
||||
glm::mat4 Camera::getProjView(bool pos) const {
|
||||
return getProjection() * getView(pos);
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ public:
|
||||
bool perspective = true;
|
||||
bool flipped = false;
|
||||
float aspect = 0.0f;
|
||||
float near = 0.05f;
|
||||
float far = 1500.0f;
|
||||
|
||||
Camera() {
|
||||
updateVectors();
|
||||
@ -27,9 +29,9 @@ public:
|
||||
void updateVectors();
|
||||
void rotate(float x, float y, float z);
|
||||
|
||||
glm::mat4 getProjection();
|
||||
glm::mat4 getView(bool position = true);
|
||||
glm::mat4 getProjView(bool position = true);
|
||||
glm::mat4 getProjection() const;
|
||||
glm::mat4 getView(bool position = true) const;
|
||||
glm::mat4 getProjView(bool position = true) const;
|
||||
|
||||
void setFov(float fov);
|
||||
float getFov() const;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
TEST(VEC3, Decode) {
|
||||
auto file = std::filesystem::u8path(
|
||||
"../res/content/base/models/demo.vec3"
|
||||
"../res/models/block.vec3"
|
||||
);
|
||||
auto bytes = files::read_bytes_buffer(file);
|
||||
auto model = vec3::load(file.u8string(), bytes);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user