diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1f9675ca..e4ddf55a 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -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: | diff --git a/doc/en/item-properties.md b/doc/en/item-properties.md index 0ec4bf73..4b10793a 100644 --- a/doc/en/item-properties.md +++ b/doc/en/item-properties.md @@ -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* diff --git a/doc/en/scripting/builtins/libitem.md b/doc/en/scripting/builtins/libitem.md index 2b695202..58dd7ba9 100644 --- a/doc/en/scripting/builtins/libitem.md +++ b/doc/en/scripting/builtins/libitem.md @@ -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 ``` diff --git a/doc/ru/item-properties.md b/doc/ru/item-properties.md index 50f82f2c..6251278f 100644 --- a/doc/ru/item-properties.md +++ b/doc/ru/item-properties.md @@ -11,6 +11,12 @@ - items (генерируется из png файлов в `res/textures/items/`) - `block` - отображает предпросмотр блока. В icon указывается строковый id блока который нужно отображать. Пример `base:wood` +### Модель предмета - `model-name` + +Имя модели предмета. Модель будет загружена автоматически. +Значение по-умолчанию - `packid:itemname.model`. +Если модель не указана, будет сгенерирована автоматическию + ## Поведение ### Устанавливаемый блок - `placing-block` diff --git a/doc/ru/scripting/builtins/libitem.md b/doc/ru/scripting/builtins/libitem.md index 0bbfcd2a..4d0b9a62 100644 --- a/doc/ru/scripting/builtins/libitem.md +++ b/doc/ru/scripting/builtins/libitem.md @@ -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 ``` diff --git a/res/content/base/blocks/water.json b/res/content/base/blocks/water.json index de702de1..943640e8 100644 --- a/res/content/base/blocks/water.json +++ b/res/content/base/blocks/water.json @@ -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 -} \ No newline at end of file +} diff --git a/res/content/base/models/block.obj b/res/content/base/models/block.obj deleted file mode 100644 index 2e307e52..00000000 --- a/res/content/base/models/block.obj +++ /dev/null @@ -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 diff --git a/res/content/base/models/demo.vec3 b/res/content/base/models/demo.vec3 deleted file mode 100644 index c780c716..00000000 Binary files a/res/content/base/models/demo.vec3 and /dev/null differ diff --git a/res/content/base/models/drop-block.obj b/res/content/base/models/drop-block.obj deleted file mode 100644 index be4cf551..00000000 --- a/res/content/base/models/drop-block.obj +++ /dev/null @@ -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 diff --git a/res/content/base/models/drop-block.vec3 b/res/content/base/models/drop-block.vec3 new file mode 100644 index 00000000..b9c3a10c Binary files /dev/null and b/res/content/base/models/drop-block.vec3 differ diff --git a/res/content/base/models/drop-item.obj b/res/content/base/models/drop-item.obj deleted file mode 100644 index a12cca01..00000000 --- a/res/content/base/models/drop-item.obj +++ /dev/null @@ -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 diff --git a/res/content/base/models/player-body.obj b/res/content/base/models/player-body.obj deleted file mode 100644 index 4cfbad54..00000000 --- a/res/content/base/models/player-body.obj +++ /dev/null @@ -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 diff --git a/res/content/base/models/player-body.vec3 b/res/content/base/models/player-body.vec3 new file mode 100644 index 00000000..8734c9c7 Binary files /dev/null and b/res/content/base/models/player-body.vec3 differ diff --git a/res/content/base/models/player-hand.obj b/res/content/base/models/player-hand.obj deleted file mode 100644 index a7752299..00000000 --- a/res/content/base/models/player-hand.obj +++ /dev/null @@ -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 diff --git a/res/content/base/models/player-hand.vec3 b/res/content/base/models/player-hand.vec3 new file mode 100644 index 00000000..c134ce94 Binary files /dev/null and b/res/content/base/models/player-hand.vec3 differ diff --git a/res/content/base/models/player-head.obj b/res/content/base/models/player-head.obj deleted file mode 100644 index c8baf870..00000000 --- a/res/content/base/models/player-head.obj +++ /dev/null @@ -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 diff --git a/res/content/base/models/player-head.vec3 b/res/content/base/models/player-head.vec3 new file mode 100644 index 00000000..71f47c10 Binary files /dev/null and b/res/content/base/models/player-head.vec3 differ diff --git a/res/content/base/scripts/components/drop.lua b/res/content/base/scripts/components/drop.lua index 90e4810f..195c5270 100644 --- a/res/content/base/scripts/components/drop.lua +++ b/res/content/base/scripts/components/drop.lua @@ -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 diff --git a/res/content/base/scripts/components/player_animator.lua b/res/content/base/scripts/components/player_animator.lua index d1a4c0be..871284d5 100644 --- a/res/content/base/scripts/components/player_animator.lua +++ b/res/content/base/scripts/components/player_animator.lua @@ -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() diff --git a/res/content/base/textures/blocks/water.png b/res/content/base/textures/blocks/water.png index 00dac81b..e06e127d 100644 Binary files a/res/content/base/textures/blocks/water.png and b/res/content/base/textures/blocks/water.png differ diff --git a/res/models/block.vec3 b/res/models/block.vec3 new file mode 100644 index 00000000..0b274e75 Binary files /dev/null and b/res/models/block.vec3 differ diff --git a/res/models/drop-item.vec3 b/res/models/drop-item.vec3 new file mode 100644 index 00000000..d40f7704 Binary files /dev/null and b/res/models/drop-item.vec3 differ diff --git a/res/modules/item_models.lua b/res/modules/item_models.lua deleted file mode 100644 index 6c2c955e..00000000 --- a/res/modules/item_models.lua +++ /dev/null @@ -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, -} diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index a49bdfa8..b332c02f 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -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))); diff --git a/src/assets/Assets.hpp b/src/assets/Assets.hpp index 86d6fb22..2642e005 100644 --- a/src/assets/Assets.hpp +++ b/src/assets/Assets.hpp @@ -5,11 +5,13 @@ #include #include #include +#include #include #include #include #include +#include "util/stringutil.hpp" #include "graphics/core/TextureAnimation.hpp" class Assets; @@ -84,6 +86,15 @@ public: return static_cast(found->second.get()); } + template + T& require(const std::string& name) const { + T* asset = get(name); + if (asset == nullptr) { + throw std::runtime_error(util::quote(name) + " not found"); + } + return *asset; + } + template std::optional getMap() const { const auto& mapIter = assets.find(typeid(T)); diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index f3f575df..9fecf7da 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -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 + ); + } + } } } diff --git a/src/assets/assets_util.cpp b/src/assets/assets_util.cpp new file mode 100644 index 00000000..bdd7795a --- /dev/null +++ b/src/assets/assets_util.cpp @@ -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(name), UVRegion(0,0,1,1)}; + } else { + auto atlas = assets.get(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()}; +} diff --git a/src/assets/assets_util.hpp b/src/assets/assets_util.hpp new file mode 100644 index 00000000..db7dc361 --- /dev/null +++ b/src/assets/assets_util.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +#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 + ); +} diff --git a/src/coders/vec3.cpp b/src/coders/vec3.cpp index d6fb5c08..63edc21e 100644 --- a/src/coders/vec3.cpp +++ b/src/coders/vec3.cpp @@ -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 attributes; for (int i = 0; i < attributeCount; i++) { attributes.push_back(load_attribute(reader)); diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index df367b96..7bad427e 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -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(); @@ -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; diff --git a/src/core_defs.cpp b/src/core_defs.cpp index 7186aa72..c62900f7 100644 --- a/src/core_defs.cpp +++ b/src/core_defs.cpp @@ -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; diff --git a/src/engine.cpp b/src/engine.cpp index c13e817b..7cc35b32 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -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( + ModelsGenerator::generate(*def, *content, *assets) + ), + name + ".model" + ); + } + } } static void load_configs(const fs::path& root) { diff --git a/src/frontend/LevelFrontend.cpp b/src/frontend/LevelFrontend.cpp index 68f308c8..6c54a83d 100644 --- a/src/frontend/LevelFrontend.cpp +++ b/src/frontend/LevelFrontend.cpp @@ -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(); } diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 73e235d7..8824d640 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -48,7 +48,7 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr 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); diff --git a/src/graphics/core/Batch2D.cpp b/src/graphics/core/Batch2D.cpp index d9cc0ec2..13b48586 100644 --- a/src/graphics/core/Batch2D.cpp +++ b/src/graphics/core/Batch2D.cpp @@ -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; } diff --git a/src/graphics/core/Batch2D.hpp b/src/graphics/core/Batch2D.hpp index 4e38ffe5..2877f5bd 100644 --- a/src/graphics/core/Batch2D.hpp +++ b/src/graphics/core/Batch2D.hpp @@ -17,7 +17,7 @@ class Batch2D : public Flushable { std::unique_ptr 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); diff --git a/src/graphics/core/Batch3D.cpp b/src/graphics/core/Batch3D.cpp index d3e369a0..dd6261e5 100644 --- a/src/graphics/core/Batch3D.cpp +++ b/src/graphics/core/Batch3D.cpp @@ -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(); diff --git a/src/graphics/core/Batch3D.hpp b/src/graphics/core/Batch3D.hpp index 2cfe4bcc..bd5f7b4e 100644 --- a/src/graphics/core/Batch3D.hpp +++ b/src/graphics/core/Batch3D.hpp @@ -18,7 +18,7 @@ class Batch3D : public Flushable { std::unique_ptr 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; diff --git a/src/graphics/core/Cubemap.cpp b/src/graphics/core/Cubemap.cpp index 5da69e3e..3267b25e 100644 --- a/src/graphics/core/Cubemap.cpp +++ b/src/graphics/core/Cubemap.cpp @@ -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); } diff --git a/src/graphics/core/Cubemap.hpp b/src/graphics/core/Cubemap.hpp index 72d29a21..3a80bda8 100644 --- a/src/graphics/core/Cubemap.hpp +++ b/src/graphics/core/Cubemap.hpp @@ -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; }; diff --git a/src/graphics/core/GLTexture.cpp b/src/graphics/core/GLTexture.cpp index 9572f415..4781536e 100644 --- a/src/graphics/core/GLTexture.cpp +++ b/src/graphics/core/GLTexture.cpp @@ -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); } diff --git a/src/graphics/core/GLTexture.hpp b/src/graphics/core/GLTexture.hpp index 7f9e8f22..b5f82384 100644 --- a/src/graphics/core/GLTexture.hpp +++ b/src/graphics/core/GLTexture.hpp @@ -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(); diff --git a/src/graphics/core/Model.cpp b/src/graphics/core/Model.cpp index 78e15354..3da5d897 100644 --- a/src/graphics/core/Model.cpp +++ b/src/graphics/core/Model.cpp @@ -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( diff --git a/src/graphics/core/Model.hpp b/src/graphics/core/Model.hpp index 786b9ac9..b92fb030 100644 --- a/src/graphics/core/Model.hpp +++ b/src/graphics/core/Model.hpp @@ -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 { diff --git a/src/graphics/core/Texture.hpp b/src/graphics/core/Texture.hpp index 4b3f1651..ba5b066e 100644 --- a/src/graphics/core/Texture.hpp +++ b/src/graphics/core/Texture.hpp @@ -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; diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp index bda65de3..f6a1b58b 100644 --- a/src/graphics/render/ModelBatch.cpp +++ b/src/graphics/render/ModelBatch.cpp @@ -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(name)); - } else { - auto atlas = assets->get(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(); } diff --git a/src/graphics/render/ModelBatch.hpp b/src/graphics/render/ModelBatch.hpp index fc3b1295..523eb300 100644 --- a/src/graphics/render/ModelBatch.hpp +++ b/src/graphics/render/ModelBatch.hpp @@ -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); }; diff --git a/src/graphics/render/ModelsGenerator.cpp b/src/graphics/render/ModelsGenerator.cpp new file mode 100644 index 00000000..edec061c --- /dev/null +++ b/src/graphics/render/ModelsGenerator.cpp @@ -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("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("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(); + } +} diff --git a/src/graphics/render/ModelsGenerator.hpp b/src/graphics/render/ModelsGenerator.hpp new file mode 100644 index 00000000..ec7ea873 --- /dev/null +++ b/src/graphics/render/ModelsGenerator.hpp @@ -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 + ); +}; diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index 420f0ec7..22927b3c 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -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("background"); +void Skybox::drawBackground( + const Camera& camera, const Assets& assets, int width, int height +) { + auto backShader = assets.get("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("ui3d"); + auto p_shader = assets.get("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(sprite.texture)); + batch3d->texture(assets.get(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]); diff --git a/src/graphics/render/Skybox.hpp b/src/graphics/render/Skybox.hpp index 01bffab7..2781a95a 100644 --- a/src/graphics/render/Skybox.hpp +++ b/src/graphics/render/Skybox.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #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; std::unique_ptr batch3d; std::vector 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; + } }; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 56cd662b..4b13a23f 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -9,6 +9,7 @@ #include #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("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(CHUNK_W) - 0.5f; - float pz = camera->position.z / static_cast(CHUNK_D) - 0.5f; + float px = camera.position.x / static_cast(CHUNK_W) - 0.5f; + float pz = camera.position.z / static_cast(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(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("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(engine->getDelta() * speed)); + rotation = glm::mat4_cast(finalRot); + matrix = rotation * matrix * + glm::rotate( + glm::mat4(1.0f), -glm::pi() * 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(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(vp.getHeight()); + camera.aspect = vp.getWidth() / static_cast(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("lines"); + const auto& assets = *engine->getAssets(); + auto linesShader = assets.get("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("screen"); + auto screenShader = assets.get("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("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 ) { diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 06e4bb63..c5d7040e 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -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; 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 diff --git a/src/graphics/ui/elements/InventoryView.cpp b/src/graphics/ui/elements/InventoryView.cpp index 1b759a57..fa3d836c 100644 --- a/src/graphics/ui/elements/InventoryView.cpp +++ b/src/graphics/ui/elements/InventoryView.cpp @@ -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(name)); - } else { - std::string atlasname = item.icon.substr(0, index); - auto atlas = assets->get(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; } } diff --git a/src/items/ItemDef.cpp b/src/items/ItemDef.cpp index 321f7be7..8d0cdd66 100644 --- a/src/items/ItemDef.cpp +++ b/src/items/ItemDef.cpp @@ -14,4 +14,5 @@ void ItemDef::cloneTo(ItemDef& dst) { dst.icon = icon; dst.placingBlock = placingBlock; dst.scriptName = scriptName; + dst.modelName = modelName; } diff --git a/src/items/ItemDef.hpp b/src/items/ItemDef.hpp index a306dce2..999b190f 100644 --- a/src/items/ItemDef.hpp +++ b/src/items/ItemDef.hpp @@ -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; diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 35d92b95..64e2a40c 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -41,7 +41,7 @@ CameraControl::CameraControl( const std::shared_ptr& 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); diff --git a/src/logic/scripting/lua/libs/libitem.cpp b/src/logic/scripting/lua/libs/libitem.cpp index 5a4ef4de..a5ba27e5 100644 --- a/src/logic/scripting/lua/libs/libitem.cpp +++ b/src/logic/scripting/lua/libs/libitem.cpp @@ -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}, - {"name", lua::wrap}, - {"stack_size", lua::wrap}, - {"defs_count", lua::wrap}, - {"icon", lua::wrap}, - {"caption", lua::wrap}, + {"index", lua::wrap}, + {"name", lua::wrap}, + {"stack_size", lua::wrap}, + {"defs_count", lua::wrap}, + {"icon", lua::wrap}, + {"caption", lua::wrap}, + {"placing_block", lua::wrap}, + {"model_name", lua::wrap}, {NULL, NULL}}; diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index fb4c9f0f..0d0a7223 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -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; } diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index d0e19c85..5b925f58 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -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 Player::getInventory() const { +const std::shared_ptr& 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); diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index c2a923e9..985aba55 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -52,7 +52,7 @@ class Player : public Object, public Serializable { entityid_t eid; entityid_t selectedEid; public: - std::shared_ptr camera, spCamera, tpCamera; + std::shared_ptr fpCamera, spCamera, tpCamera; std::shared_ptr currentCamera; bool debug = false; glm::vec3 cam {}; @@ -91,7 +91,7 @@ public: entityid_t getSelectedEntity() const; - std::shared_ptr getInventory() const; + const std::shared_ptr& getInventory() const; glm::vec3 getPosition() const { return position; diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index d09cbd99..963a0928 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -141,6 +141,7 @@ void Block::cloneTo(Block& dst) { dst.uiLayout = uiLayout; dst.inventorySize = inventorySize; dst.tickInterval = tickInterval; + dst.overlayTexture = overlayTexture; } static std::set> RESERVED_BLOCK_FIELDS { diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index e9b91664..2d2cdf90 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #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 textureFaces; // -x,x, -y,y, -z,z std::vector modelTextures = {}; std::vector 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; diff --git a/src/window/Camera.cpp b/src/window/Camera.cpp index 5e9dd36a..def9ff7c 100644 --- a/src/window/Camera.cpp +++ b/src/window/Camera.cpp @@ -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); } diff --git a/src/window/Camera.hpp b/src/window/Camera.hpp index 639a27df..1c2ecd60 100644 --- a/src/window/Camera.hpp +++ b/src/window/Camera.hpp @@ -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; diff --git a/test/coders/vec3.cpp b/test/coders/vec3.cpp index e4643921..cb699bc3 100644 --- a/test/coders/vec3.cpp +++ b/test/coders/vec3.cpp @@ -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);