Compare commits
12 Commits
094847caca
...
50188813f8
| Author | SHA1 | Date | |
|---|---|---|---|
| 50188813f8 | |||
| 7428b86b9e | |||
| ba2247068b | |||
| 9ed9f70ec5 | |||
| c987c0330b | |||
| a0e922975a | |||
| e6d4fbd182 | |||
| f890e4e550 | |||
| 3469ccacfd | |||
| 8ce7ca035a | |||
| 9d97d6448e | |||
| 75bafe50af |
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,4 +6,5 @@
|
|||||||
main
|
main
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
__pycache__
|
__pycache__
|
||||||
|
minecraft/region*.lights.vtx
|
||||||
4
Makefile
4
Makefile
@ -19,7 +19,9 @@ LDFLAGS += $(shell pkg-config --libs glfw3)
|
|||||||
OBJS = \
|
OBJS = \
|
||||||
src/gl.o \
|
src/gl.o \
|
||||||
src/opengl.o \
|
src/opengl.o \
|
||||||
src/test.o
|
src/test.o \
|
||||||
|
src/font.o \
|
||||||
|
src/window.o
|
||||||
|
|
||||||
all: test.so
|
all: test.so
|
||||||
|
|
||||||
|
|||||||
BIN
font/terminus_128x128_8x16.data
Normal file
BIN
font/terminus_128x128_8x16.data
Normal file
Binary file not shown.
BIN
font/terminus_128x64_6x12.data
Normal file
BIN
font/terminus_128x64_6x12.data
Normal file
Binary file not shown.
BIN
font/terminus_256x128_10x18.data
Normal file
BIN
font/terminus_256x128_10x18.data
Normal file
Binary file not shown.
BIN
font/terminus_256x128_12x24.data
Normal file
BIN
font/terminus_256x128_12x24.data
Normal file
Binary file not shown.
BIN
font/terminus_256x256_16x32.data
Normal file
BIN
font/terminus_256x256_16x32.data
Normal file
Binary file not shown.
@ -8,3 +8,12 @@ short index_buffer_configuration_offsets[] = {
|
|||||||
768, 780, 798, 816, 840, 858, 882, 906,
|
768, 780, 798, 816, 840, 858, 882, 906,
|
||||||
936, 954, 978, 1002, 1032, 1056, 1086, 1116,
|
936, 954, 978, 1002, 1032, 1056, 1086, 1116,
|
||||||
};
|
};
|
||||||
|
struct {
|
||||||
|
short offset;
|
||||||
|
short count;
|
||||||
|
} index_buffer_custom_offsets[] = {
|
||||||
|
{1152, 12}, // tallgrass.obj
|
||||||
|
{1164, 36}, // fence.obj
|
||||||
|
{1200, 36}, // torch.obj
|
||||||
|
{1236, 24}, // wheat.obj
|
||||||
|
};
|
||||||
|
|||||||
68
include/font.h
Normal file
68
include/font.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace font {
|
||||||
|
|
||||||
|
struct font_desc {
|
||||||
|
char const * const path;
|
||||||
|
int const texture_width;
|
||||||
|
int const texture_height;
|
||||||
|
int const glyph_width;
|
||||||
|
int const glyph_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
font_desc const terminus[] = {
|
||||||
|
{
|
||||||
|
.path = "font/terminus_128x64_6x12.data",
|
||||||
|
.texture_width = 128,
|
||||||
|
.texture_height = 64,
|
||||||
|
.glyph_width = 6,
|
||||||
|
.glyph_height = 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.path = "font/terminus_128x128_8x16.data",
|
||||||
|
.texture_width = 128,
|
||||||
|
.texture_height = 128,
|
||||||
|
.glyph_width = 8,
|
||||||
|
.glyph_height = 16,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.path = "font/terminus_256x128_10x18.data",
|
||||||
|
.texture_width = 256,
|
||||||
|
.texture_height = 128,
|
||||||
|
.glyph_width = 10,
|
||||||
|
.glyph_height = 18,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.path = "font/terminus_256x128_12x24.data",
|
||||||
|
.texture_width = 256,
|
||||||
|
.texture_height = 128,
|
||||||
|
.glyph_width = 12,
|
||||||
|
.glyph_height = 24,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.path = "font/terminus_256x256_16x32.data",
|
||||||
|
.texture_width = 256,
|
||||||
|
.texture_height = 256,
|
||||||
|
.glyph_width = 16,
|
||||||
|
.glyph_height = 32,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
int const terminus_length = (sizeof (terminus)) / (sizeof (font_desc));
|
||||||
|
|
||||||
|
struct font {
|
||||||
|
font_desc const * desc;
|
||||||
|
unsigned int texture;
|
||||||
|
int stride;
|
||||||
|
struct {
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
} cell;
|
||||||
|
};
|
||||||
|
|
||||||
|
void load_shader();
|
||||||
|
font load_font(font_desc const& desc);
|
||||||
|
void load_fonts(font * const fonts, font_desc const * const descs, int length);
|
||||||
|
int best_font(font_desc const * const descs, int length);
|
||||||
|
void draw_start(font const& font, unsigned int vertex_array_object, unsigned int index_buffer);
|
||||||
|
void draw_string(font const& font, char const * const s, int x, int y);
|
||||||
|
}
|
||||||
@ -4,6 +4,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern char const * g_source_path;
|
||||||
|
extern int g_source_path_length;
|
||||||
|
|
||||||
void * read_file(const char * filename, int * out_size);
|
void * read_file(const char * filename, int * out_size);
|
||||||
|
|
||||||
unsigned int compile_from_files(const char * vertex_path,
|
unsigned int compile_from_files(const char * vertex_path,
|
||||||
|
|||||||
@ -4,9 +4,11 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void load();
|
void load(const char * source_path);
|
||||||
void draw();
|
void draw();
|
||||||
void update(float lx, float ly, float ry);
|
void update(float lx, float ly, float rx, float ry, float tl, float tr,
|
||||||
|
int up, int down, int left, int right,
|
||||||
|
int a, int b, int x, int y);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
13
include/window.h
Normal file
13
include/window.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern float g_window_width;
|
||||||
|
extern float g_window_height;
|
||||||
|
void update_window(int width, int height);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
35
main.lua
35
main.lua
@ -5,21 +5,36 @@ function init()
|
|||||||
joysticks = love.joystick.getJoysticks()
|
joysticks = love.joystick.getJoysticks()
|
||||||
|
|
||||||
ffi.cdef[[
|
ffi.cdef[[
|
||||||
void load();
|
void load(const char * source_path);
|
||||||
|
void update_window(int width, int height);
|
||||||
void draw();
|
void draw();
|
||||||
void update(float lx, float ly, float ry);
|
void update(float lx, float ly, float rx, float ry, float tl, float tr,
|
||||||
|
int up, int down, int left, int right,
|
||||||
|
int a, int b, int x, int y);
|
||||||
]]
|
]]
|
||||||
test = ffi.load("./test.so")
|
local source_path = love.filesystem.getSource()
|
||||||
test.load()
|
test = ffi.load(source_path .. "/test.so")
|
||||||
|
test.load(source_path)
|
||||||
|
print(love.filesystem.getWorkingDirectory())
|
||||||
end
|
end
|
||||||
|
|
||||||
local update = function(dt)
|
local update = function(dt)
|
||||||
for _, joystick in ipairs(joysticks) do
|
for _, joystick in ipairs(joysticks) do
|
||||||
local lx = joystick:getGamepadAxis("leftx")
|
local lx = joystick:getGamepadAxis("leftx")
|
||||||
local ly = joystick:getGamepadAxis("lefty")
|
local ly = joystick:getGamepadAxis("lefty")
|
||||||
|
local rx = joystick:getGamepadAxis("rightx")
|
||||||
local ry = joystick:getGamepadAxis("righty")
|
local ry = joystick:getGamepadAxis("righty")
|
||||||
test.update(lx, ly, ry)
|
local tl = joystick:getGamepadAxis("triggerleft")
|
||||||
|
local tr = joystick:getGamepadAxis("triggerright")
|
||||||
|
local up = joystick:isGamepadDown("dpup")
|
||||||
|
local down = joystick:isGamepadDown("dpdown")
|
||||||
|
local left = joystick:isGamepadDown("dpleft")
|
||||||
|
local right = joystick:isGamepadDown("dpright")
|
||||||
|
local a = joystick:isGamepadDown("a")
|
||||||
|
local b = joystick:isGamepadDown("b")
|
||||||
|
local x = joystick:isGamepadDown("x")
|
||||||
|
local y = joystick:isGamepadDown("y")
|
||||||
|
test.update(lx, ly, rx, ry, tl, tr, up, down, left, right, a, b, x, y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -42,6 +57,12 @@ function love.run()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local width
|
||||||
|
local height
|
||||||
|
local flags
|
||||||
|
width, height, flags = love.window.getMode()
|
||||||
|
test.update_window(width, height)
|
||||||
|
|
||||||
local dt = love.timer.step()
|
local dt = love.timer.step()
|
||||||
update(dt)
|
update(dt)
|
||||||
|
|
||||||
@ -50,6 +71,6 @@ function love.run()
|
|||||||
love.graphics.present()
|
love.graphics.present()
|
||||||
love.timer.sleep(0.001)
|
love.timer.sleep(0.001)
|
||||||
local fps = love.timer.getFPS( )
|
local fps = love.timer.getFPS( )
|
||||||
print(fps)
|
--print(fps)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
BIN
minecraft/block_id_to_texture_id.data
Normal file
BIN
minecraft/block_id_to_texture_id.data
Normal file
Binary file not shown.
Binary file not shown.
@ -1,106 +1,13 @@
|
|||||||
import struct
|
import struct
|
||||||
|
import data
|
||||||
|
import sys
|
||||||
|
|
||||||
def id_to_px(i):
|
unk = 253
|
||||||
x = i % 16
|
|
||||||
y = i // 16
|
|
||||||
return x * 16, y * 16
|
|
||||||
|
|
||||||
def px_to_id(px, py):
|
with open(sys.argv[1], "wb") as f:
|
||||||
x = px // 16
|
|
||||||
y = py // 16
|
|
||||||
i = y * 16 + x
|
|
||||||
return i
|
|
||||||
|
|
||||||
unk = 185
|
|
||||||
|
|
||||||
mapping = [
|
|
||||||
(1, 1, "stone"),
|
|
||||||
(2, 0, "grass"),
|
|
||||||
(31, 0, "grass"), # fixme actually tallgrass
|
|
||||||
(3, 2, "dirt"),
|
|
||||||
(4, 16, "stonebrick"),
|
|
||||||
(5, 4, "wood"),
|
|
||||||
(6, 15, "sapling"),
|
|
||||||
(7, 17, "bedrock"),
|
|
||||||
(8, 205, "water"), # flowing
|
|
||||||
(9, 205, "water"), # still
|
|
||||||
(10, 237, "lava"), # flowing
|
|
||||||
(11, 237, "lava"), # still
|
|
||||||
(12, 18, "sand"),
|
|
||||||
(13, 19, "gravel"),
|
|
||||||
(14, 32, "oreGold"),
|
|
||||||
(15, 33, "oreIron"),
|
|
||||||
(16, 34, "oreCoal"),
|
|
||||||
(17, 20, "log"),
|
|
||||||
(18, 52, "leaves"),
|
|
||||||
(19, 48, "sponge"),
|
|
||||||
(20, 49, "glass"),
|
|
||||||
(35, 64, "cloth"),
|
|
||||||
(37, 13, "flower"),
|
|
||||||
(38, 12, "rose"),
|
|
||||||
(39, 29, "mushroom"),
|
|
||||||
(40, 28, "mushroom"),
|
|
||||||
(41, 39, "blockGold"),
|
|
||||||
(42, 38, "blockIron"),
|
|
||||||
(43, 5, "stoneSlab"), # double
|
|
||||||
(44, 5, "stoneSlab"), # single
|
|
||||||
(45, 7, "brick"),
|
|
||||||
(46, 8, "tnt"),
|
|
||||||
(47, 35, "bookshelf"),
|
|
||||||
(48, 36, "stoneMoss"),
|
|
||||||
(49, 37, "obsidian"),
|
|
||||||
(50, 80, "torch"),
|
|
||||||
(51, 31, "fire"),
|
|
||||||
(52, 65, "mobSpawner"),
|
|
||||||
(53, 4, "stairsWood"),
|
|
||||||
(54, 27, "chest"),
|
|
||||||
(55, 84, "redstoneDust"),
|
|
||||||
(56, 50, "oreDiamond"),
|
|
||||||
(57, 40, "blockDiamond"),
|
|
||||||
(58, 43, "workbench"),
|
|
||||||
(59, 88, "crops"),
|
|
||||||
(60, 87, "farmland"),
|
|
||||||
(61, 44, "furnace"), # off
|
|
||||||
(62, 61, "furnace"), # burning
|
|
||||||
(63, unk, "sign"),
|
|
||||||
(64, 81, "doorWood"),
|
|
||||||
(65, 83, "ladder"),
|
|
||||||
(66, 128, "rail"),
|
|
||||||
(67, 16, "stairsStone"),
|
|
||||||
(68, unk, "sign"),
|
|
||||||
(69, 96, "lever"),
|
|
||||||
(70, 6, "pressurePlate"),
|
|
||||||
(71, 82, "doorIron"),
|
|
||||||
(72, 6, "pressurePlate"),
|
|
||||||
(73, 51, "oreRedstone"),
|
|
||||||
(74, 51, "oreRedstone"),
|
|
||||||
(75, 115, "notGate"),
|
|
||||||
(76, 99, "notGate"),
|
|
||||||
(77, unk, "button"),
|
|
||||||
(78, 66, "snow"),
|
|
||||||
(79, 67, "ice"),
|
|
||||||
(80, 66, "snow"),
|
|
||||||
(81, 70, "cactus"),
|
|
||||||
(82, 72, "clay"),
|
|
||||||
(83, 73, "reeds"),
|
|
||||||
(84, 74, "jukebox"),
|
|
||||||
(85, 4, "fence"),
|
|
||||||
(86, 102, "pumpkin"),
|
|
||||||
(87, 103, "hellrock"),
|
|
||||||
(88, 104, "hellsand"),
|
|
||||||
(89, 105, "lightgem"),
|
|
||||||
(90, 14, "portal"),
|
|
||||||
(91, 102, "pumpkin"),
|
|
||||||
]
|
|
||||||
|
|
||||||
lookup = {
|
|
||||||
k: v for k, v, _ in mapping
|
|
||||||
}
|
|
||||||
|
|
||||||
with open("block_id_to_texture_id.data", "wb") as f:
|
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
value = lookup.get(i, unk)
|
if i in data.tiles_by_id:
|
||||||
|
value = data.tiles_by_id[i].texture
|
||||||
|
else:
|
||||||
|
value = unk
|
||||||
f.write(struct.pack("<i", value))
|
f.write(struct.pack("<i", value))
|
||||||
print(str(value).rjust(3), end=', ')
|
|
||||||
if i % 16 == 15:
|
|
||||||
print()
|
|
||||||
|
|||||||
4
minecraft/gen/blocks.sh
Normal file
4
minecraft/gen/blocks.sh
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
set -eux
|
||||||
|
cd ./minecraft/gen
|
||||||
|
PYTHON=pypy3.11
|
||||||
|
$PYTHON blocks.py ../block_id_to_texture_id.data
|
||||||
36
minecraft/gen/cube.obj
Normal file
36
minecraft/gen/cube.obj
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Blender 5.0.0
|
||||||
|
# www.blender.org
|
||||||
|
o Cube
|
||||||
|
v 1.000000 1.000000 -1.000000
|
||||||
|
v 1.000000 -1.000000 -1.000000
|
||||||
|
v 1.000000 1.000000 1.000000
|
||||||
|
v 1.000000 -1.000000 1.000000
|
||||||
|
v -1.000000 1.000000 -1.000000
|
||||||
|
v -1.000000 -1.000000 -1.000000
|
||||||
|
v -1.000000 1.000000 1.000000
|
||||||
|
v -1.000000 -1.000000 1.000000
|
||||||
|
vn -0.0000 1.0000 -0.0000
|
||||||
|
vn -0.0000 -0.0000 1.0000
|
||||||
|
vn -1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -1.0000 -0.0000
|
||||||
|
vn 1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -0.0000 -1.0000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt -0.000000 0.000000
|
||||||
|
vt 1.000000 -0.000000
|
||||||
|
s 0
|
||||||
|
f 5/1/1 3/2/1 1/3/1
|
||||||
|
f 3/4/2 8/5/2 4/6/2
|
||||||
|
f 7/4/3 6/5/3 8/6/3
|
||||||
|
f 2/1/4 8/2/4 6/3/4
|
||||||
|
f 1/4/5 4/5/5 2/6/5
|
||||||
|
f 5/4/6 2/5/6 6/6/6
|
||||||
|
f 5/1/1 7/4/1 3/2/1
|
||||||
|
f 3/4/2 7/2/2 8/5/2
|
||||||
|
f 7/4/3 5/2/3 6/5/3
|
||||||
|
f 2/1/4 4/4/4 8/2/4
|
||||||
|
f 1/4/5 3/2/5 4/5/5
|
||||||
|
f 5/4/6 1/2/6 2/5/6
|
||||||
@ -1,134 +0,0 @@
|
|||||||
positions = [
|
|
||||||
(1.0, 1.0, -1.0),
|
|
||||||
(1.0, -1.0, -1.0),
|
|
||||||
(1.0, 1.0, 1.0),
|
|
||||||
(1.0, -1.0, 1.0),
|
|
||||||
(-1.0, 1.0, -1.0),
|
|
||||||
(-1.0, -1.0, -1.0),
|
|
||||||
(-1.0, 1.0, 1.0),
|
|
||||||
(-1.0, -1.0, 1.0)
|
|
||||||
]
|
|
||||||
|
|
||||||
normals = [
|
|
||||||
(0.0, 1.0, 0.0),
|
|
||||||
(0.0, 0.0, 1.0),
|
|
||||||
(-1.0, 0.0, 0.0),
|
|
||||||
(0.0, -1.0, 0.0),
|
|
||||||
(1.0, 0.0, 0.0),
|
|
||||||
(0.0, 0.0, -1.0),
|
|
||||||
]
|
|
||||||
|
|
||||||
textures = [
|
|
||||||
(1.0, 0.0),
|
|
||||||
(0.0, 1.0),
|
|
||||||
(0.0, 0.0),
|
|
||||||
(1.0, 1.0),
|
|
||||||
(0.0, 0.0),
|
|
||||||
(1.0, 0.0),
|
|
||||||
]
|
|
||||||
|
|
||||||
indices = [
|
|
||||||
[
|
|
||||||
[4, 0, 0],
|
|
||||||
[2, 1, 0],
|
|
||||||
[0, 2, 0],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[2, 3, 1],
|
|
||||||
[7, 4, 1],
|
|
||||||
[3, 5, 1],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[6, 3, 2],
|
|
||||||
[5, 4, 2],
|
|
||||||
[7, 5, 2],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[1, 0, 3],
|
|
||||||
[7, 1, 3],
|
|
||||||
[5, 2, 3],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[0, 3, 4],
|
|
||||||
[3, 4, 4],
|
|
||||||
[1, 5, 4],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[4, 3, 5],
|
|
||||||
[1, 4, 5],
|
|
||||||
[5, 5, 5],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[4, 0, 0],
|
|
||||||
[6, 3, 0],
|
|
||||||
[2, 1, 0],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[2, 3, 1],
|
|
||||||
[6, 1, 1],
|
|
||||||
[7, 4, 1],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[6, 3, 2],
|
|
||||||
[4, 1, 2],
|
|
||||||
[5, 4, 2],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[1, 0, 3],
|
|
||||||
[3, 3, 3],
|
|
||||||
[7, 1, 3],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[0, 3, 4],
|
|
||||||
[2, 1, 4],
|
|
||||||
[3, 4, 4],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
[4, 3, 5],
|
|
||||||
[0, 1, 5],
|
|
||||||
[1, 4, 5],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
|
|
||||||
vertex_buffer = []
|
|
||||||
index_buffer = []
|
|
||||||
index_lookup = {}
|
|
||||||
|
|
||||||
for triangle in indices:
|
|
||||||
for p_ix, t_ix, n_ix in triangle:
|
|
||||||
key = (p_ix, n_ix, t_ix)
|
|
||||||
if key not in index_lookup:
|
|
||||||
position = positions[p_ix]
|
|
||||||
normal = normals[n_ix]
|
|
||||||
texture = textures[t_ix]
|
|
||||||
index = len(vertex_buffer)
|
|
||||||
index_lookup[key] = index
|
|
||||||
vertex_buffer.append((tuple(position),
|
|
||||||
tuple(normal),
|
|
||||||
tuple(texture)))
|
|
||||||
|
|
||||||
index_buffer.append(index_lookup[key])
|
|
||||||
|
|
||||||
def gen():
|
|
||||||
for position, normal, texture in vertex_buffer:
|
|
||||||
p = ", ".join(map(str, map(float, position)))
|
|
||||||
n = ", ".join(map(str, map(float, normal)))
|
|
||||||
t = ", ".join(map(str, map(float, texture)))
|
|
||||||
print(f"vertex_t(vec3({p}), vec3({n}), vec2({t})),")
|
|
||||||
|
|
||||||
for i in range(len(index_buffer) // 3):
|
|
||||||
tri = ", ".join(str(index_buffer[i * 3 + n]) for n in range(3))
|
|
||||||
print(f"{tri},")
|
|
||||||
|
|
||||||
from collections import defaultdict
|
|
||||||
by_normal = defaultdict(list)
|
|
||||||
for i in range(len(index_buffer) // 3):
|
|
||||||
tri = [index_buffer[i * 3 + n] for n in range(3)]
|
|
||||||
s = set(vertex_buffer[j][1] for j in tri)
|
|
||||||
assert len(s) == 1
|
|
||||||
normal, = iter(s)
|
|
||||||
by_normal[normal].append(tri)
|
|
||||||
|
|
||||||
from pprint import pprint
|
|
||||||
pprint(dict(by_normal))
|
|
||||||
pprint(vertex_buffer)
|
|
||||||
364
minecraft/gen/data.py
Normal file
364
minecraft/gen/data.py
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
class BlockID:
|
||||||
|
AIR = 0
|
||||||
|
STONE = 1
|
||||||
|
GRASS = 2
|
||||||
|
DIRT = 3
|
||||||
|
STONEBRICK = 4
|
||||||
|
WOOD = 5
|
||||||
|
SAPLING = 6
|
||||||
|
BEDROCK = 7
|
||||||
|
WATER = 8
|
||||||
|
WATER_CALM = 9
|
||||||
|
LAVA = 10
|
||||||
|
LAVA_CALM = 11
|
||||||
|
SAND = 12
|
||||||
|
GRAVEL = 13
|
||||||
|
ORE_GOLD = 14
|
||||||
|
ORE_IRON = 15
|
||||||
|
ORE_COAL = 16
|
||||||
|
TREE_TRUNK = 17
|
||||||
|
LEAVES = 18
|
||||||
|
SPONGE = 19
|
||||||
|
GLASS = 20
|
||||||
|
ORE_LAPIS = 21
|
||||||
|
BLOCK_LAPIS = 22
|
||||||
|
DISPENSER = 23
|
||||||
|
SANDSTONE = 24
|
||||||
|
NOTE_BLOCK = 25
|
||||||
|
BED = 26
|
||||||
|
RAIL_POWERED = 27
|
||||||
|
RAIL_ACTIVATOR = 28
|
||||||
|
PISTON_STICKY = 29
|
||||||
|
COBWEB = 30
|
||||||
|
TALL_GRASS = 31
|
||||||
|
DEAD_BUSH = 32
|
||||||
|
PISTON = 33
|
||||||
|
PISTON_HEAD = 34
|
||||||
|
CLOTH = 35
|
||||||
|
PISTON_MOVING = 36
|
||||||
|
FLOWER = 37
|
||||||
|
ROSE = 38
|
||||||
|
MUSHROOM_1 = 39
|
||||||
|
MUSHROOM_2 = 40
|
||||||
|
BLOCK_GOLD = 41
|
||||||
|
BLOCK_IRON = 42
|
||||||
|
STONESLAB_FULL = 43
|
||||||
|
STONESLAB_HALF = 44
|
||||||
|
BRICKS = 45
|
||||||
|
TNT = 46
|
||||||
|
BOOKSHELF = 47
|
||||||
|
MOSS_STONE = 48
|
||||||
|
OBSIDIAN = 49
|
||||||
|
TORCH = 50
|
||||||
|
FIRE = 51
|
||||||
|
SPAWNER = 52
|
||||||
|
STAIRS_WOOD = 53
|
||||||
|
CHEST = 54
|
||||||
|
WIRE = 55
|
||||||
|
ORE_EMERALD = 56
|
||||||
|
BLOCK_EMERALD = 57
|
||||||
|
WORKBENCH = 58
|
||||||
|
WHEAT = 59
|
||||||
|
FARMLAND = 60
|
||||||
|
FURNACE = 61
|
||||||
|
FURNACE_LIT = 62
|
||||||
|
SIGN = 63
|
||||||
|
DOOR_WOOD = 64
|
||||||
|
LADDER = 65
|
||||||
|
RAIL = 66
|
||||||
|
STAIRS_STONE = 67
|
||||||
|
SIGN_WALL = 68
|
||||||
|
LEVER = 69
|
||||||
|
PLATE_STONE = 70
|
||||||
|
DOOR_IRON = 71
|
||||||
|
PLATE_WOOD = 72
|
||||||
|
ORE_REDSTONE = 73
|
||||||
|
ORE_REDSTONE_LIT = 74
|
||||||
|
NOT_GATE_OFF = 75
|
||||||
|
NOT_GATE_ON = 76
|
||||||
|
BUTTON_STONE = 77
|
||||||
|
TOPSNOW = 78
|
||||||
|
ICE = 79
|
||||||
|
SNOW = 80
|
||||||
|
CACTUS = 81
|
||||||
|
CLAY = 82
|
||||||
|
REEDS = 83
|
||||||
|
JUKEBOX = 84
|
||||||
|
FENCE = 85
|
||||||
|
PUMPKIN = 86
|
||||||
|
NETHERRACK = 87
|
||||||
|
SOUL_SAND = 88
|
||||||
|
GLOWSTONE = 89
|
||||||
|
PORTAL = 90
|
||||||
|
PUMPKIN_LIT = 91
|
||||||
|
CAKE = 92
|
||||||
|
REPEATER_OFF = 93
|
||||||
|
REPEATER_ON = 94
|
||||||
|
INVISIBLE = 95
|
||||||
|
TRAPDOOR = 96
|
||||||
|
STONE_MONSTER_EGG = 97
|
||||||
|
STONE_BRICKS = 98
|
||||||
|
MUSHROOM1_BLOCK = 99
|
||||||
|
MUSHROOM2_BLOCK = 100
|
||||||
|
CLOTH_00 = 101
|
||||||
|
CLOTH_10 = 102
|
||||||
|
CLOTH_20 = 103
|
||||||
|
CLOTH_30 = 104
|
||||||
|
CLOTH_40 = 105
|
||||||
|
CLOTH_50 = 106
|
||||||
|
CLOTH_60 = 107
|
||||||
|
CLOTH_70 = 108
|
||||||
|
CLOTH_01 = 109
|
||||||
|
CLOTH_11 = 110
|
||||||
|
CLOTH_21 = 111
|
||||||
|
CLOTH_31 = 112
|
||||||
|
CLOTH_41 = 113
|
||||||
|
CLOTH_51 = 114
|
||||||
|
CLOTH_61 = 115
|
||||||
|
|
||||||
|
# modded
|
||||||
|
YELLOW_COBBLE = 128
|
||||||
|
MARBLE_YELLOW = 248
|
||||||
|
|
||||||
|
class Texture:
|
||||||
|
GRASS_TOP = 0
|
||||||
|
STONE = 1
|
||||||
|
DIRT = 2
|
||||||
|
GRASS_SIDE = 3
|
||||||
|
PLANKS = 4
|
||||||
|
STONE_SLAB_SIDE = 5
|
||||||
|
STONE_SLAB_TOP = 6
|
||||||
|
BRICKS = 7
|
||||||
|
TNT_SIDE = 8
|
||||||
|
TNT_TOP = 9
|
||||||
|
TNT_BOTTOM = 10
|
||||||
|
COBWEB = 11
|
||||||
|
ROSE = 12
|
||||||
|
FLOWER = 13
|
||||||
|
WATER_STATIC = 14
|
||||||
|
SAPLING = 15
|
||||||
|
STONEBRICK = 16
|
||||||
|
BEDROCK = 17
|
||||||
|
SAND = 18
|
||||||
|
GRAVEL = 19
|
||||||
|
LOG_SIDE = 20
|
||||||
|
LOG_TOP = 21
|
||||||
|
IRON = 22
|
||||||
|
GOLD = 23
|
||||||
|
EMERALD = 24
|
||||||
|
CHEST_ONE_TOP = 25
|
||||||
|
CHEST_ONE_SIDE = 26
|
||||||
|
CHEST_ONE_FRONT = 27
|
||||||
|
MUSHROOM_RED = 28
|
||||||
|
MUSHROOM_BROWN = 29
|
||||||
|
OBSIDIAN_CRYING = 30
|
||||||
|
FIRE1 = 31
|
||||||
|
ORE_GOLD = 32
|
||||||
|
ORE_IRON = 33
|
||||||
|
ORE_COAL = 34
|
||||||
|
BOOKSHELF = 35
|
||||||
|
MOSSY_STONE = 36
|
||||||
|
OBSIDIAN = 37
|
||||||
|
GRASS_SIDE_OVERLAY = 38
|
||||||
|
TALL_GRASS = 39
|
||||||
|
NONE40 = 40
|
||||||
|
CHEST_TWO_FRONT_LEFT = 41
|
||||||
|
CHEST_TWO_FRONT_RIGHT = 42
|
||||||
|
WORKBENCH_TOP = 43
|
||||||
|
FURNACE_FRONT = 44
|
||||||
|
FURNACE_SIDE = 45
|
||||||
|
DISPENSER_SIDE = 46
|
||||||
|
FIRE2 = 47
|
||||||
|
SPONGE = 48
|
||||||
|
GLASS = 49
|
||||||
|
ORE_EMERALD = 50
|
||||||
|
ORE_RED_STONE = 51
|
||||||
|
LEAVES_TRANSPARENT = 52
|
||||||
|
LEAVES_OPAQUE = 53
|
||||||
|
NONE54 = 54
|
||||||
|
DEAD_BUSH = 55
|
||||||
|
NONE56 = 56
|
||||||
|
CHEST_TWO_BACK_LEFT = 57
|
||||||
|
CHEST_TWO_BACK_RIGHT = 58
|
||||||
|
WORKBENCH_SIDE_1 = 59
|
||||||
|
WORKBENCH_SIDE_2 = 60
|
||||||
|
FURNACE_LIT = 61
|
||||||
|
FURNACE_TOP = 62
|
||||||
|
NONE63 = 63
|
||||||
|
CLOTH_64 = 64
|
||||||
|
SPAWNER = 65
|
||||||
|
SNOW = 66
|
||||||
|
ICE = 67
|
||||||
|
GRASS_SIDE_SNOW = 68
|
||||||
|
CACTUS_TOP = 69
|
||||||
|
CACTUS_SIDE = 70
|
||||||
|
CACTUS_BOTTOM = 71
|
||||||
|
CLAY = 72
|
||||||
|
REEDS = 73
|
||||||
|
JUKEBOX_SIDE = 74
|
||||||
|
JUKEBOX_TOP = 75
|
||||||
|
NONE76 = 76
|
||||||
|
NONE77 = 77
|
||||||
|
NONE78 = 78
|
||||||
|
NONE79 = 79
|
||||||
|
TORCH_LIT = 80
|
||||||
|
DOOR_TOP = 81
|
||||||
|
DOOR_IRON_TOP = 82
|
||||||
|
LADDER = 83
|
||||||
|
TRAPDOOR = 84
|
||||||
|
NONE85 = 85
|
||||||
|
FARMLAND = 86
|
||||||
|
FARMLAND_DRY = 87
|
||||||
|
WHEAT_0 = 88
|
||||||
|
WHEAT_1 = 89
|
||||||
|
WHEAT_2 = 90
|
||||||
|
WHEAT_3 = 91
|
||||||
|
WHEAT_4 = 92
|
||||||
|
WHEAT_5 = 93
|
||||||
|
WHEAT_6 = 94
|
||||||
|
WHEAT_7 = 95
|
||||||
|
LEVER = 96
|
||||||
|
DOOR_BOTTOM = 97
|
||||||
|
DOOR_IRON_BOTTOM = 98
|
||||||
|
TORCH_RED_STONE = 99
|
||||||
|
NONE100 = 100
|
||||||
|
NONE101 = 101
|
||||||
|
PUMPKIN_TOP = 102
|
||||||
|
BLOODSTONE = 103
|
||||||
|
SOULSAND = 104
|
||||||
|
GLOWSTONE = 105
|
||||||
|
STICKY_PISTON = 106
|
||||||
|
PISTON = 107
|
||||||
|
NONE108 = 108
|
||||||
|
NONE109 = 109
|
||||||
|
NONE110 = 110
|
||||||
|
NONE111 = 111
|
||||||
|
RAIL_CURVED = 112
|
||||||
|
CLOTH_112 = 113
|
||||||
|
CLOTH_113 = 114
|
||||||
|
TORCH_RED_STONE_OFF = 115
|
||||||
|
LOG_SPRUCE = 116
|
||||||
|
LOG_BIRCH = 117
|
||||||
|
PUMPKIN_SIDE = 118
|
||||||
|
PUMPKIN_FACE = 119
|
||||||
|
PUMPKIN_FACE_LIT = 120
|
||||||
|
CAKE_TOP = 121
|
||||||
|
CAKE_SIDE = 122
|
||||||
|
CAKE_SIDE_BIT = 123
|
||||||
|
CAKE_BOTTOM = 124
|
||||||
|
NONE125 = 125
|
||||||
|
NONE126 = 126
|
||||||
|
NONE127 = 127
|
||||||
|
RAIL = 128
|
||||||
|
|
||||||
|
LAPIS = 144
|
||||||
|
ORE_LAPIS = 160
|
||||||
|
POWERED_RAIL = 163
|
||||||
|
REDSTONE_DUST = 164
|
||||||
|
REDSTONE_DUST_LINE = 165
|
||||||
|
|
||||||
|
DETECTOR_RAIL = 195
|
||||||
|
|
||||||
|
SANDSTONE_TOP = 176
|
||||||
|
SANDSTONE_SIDE = 192
|
||||||
|
WATER = 205
|
||||||
|
SANDSTONE_BOTTOM = 208
|
||||||
|
|
||||||
|
LAVA = 237
|
||||||
|
|
||||||
|
INFO_UPDATEGAME1 = 252
|
||||||
|
INFO_UPDATEGAME2 = 253
|
||||||
|
|
||||||
|
LAVA_PLACEHOLDER = 255
|
||||||
|
|
||||||
|
# modded
|
||||||
|
YELLOW_COBBLE = 213
|
||||||
|
MARBLE_YELLOW = 214
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Tile:
|
||||||
|
block_id: BlockID
|
||||||
|
texture: Texture
|
||||||
|
|
||||||
|
tiles = [
|
||||||
|
Tile(BlockID.STONE, Texture.STONE),
|
||||||
|
Tile(BlockID.GRASS, Texture.GRASS_TOP), # fixme
|
||||||
|
Tile(BlockID.DIRT, Texture.DIRT),
|
||||||
|
Tile(BlockID.STONEBRICK, Texture.STONEBRICK),
|
||||||
|
Tile(BlockID.WOOD, Texture.PLANKS),
|
||||||
|
Tile(BlockID.BEDROCK, Texture.BEDROCK),
|
||||||
|
Tile(BlockID.WATER, Texture.WATER), # fixme
|
||||||
|
Tile(BlockID.WATER_CALM, Texture.WATER), # fixme
|
||||||
|
Tile(BlockID.LAVA, Texture.LAVA), # fixme
|
||||||
|
Tile(BlockID.LAVA_CALM, Texture.LAVA), # fixme
|
||||||
|
Tile(BlockID.SAND, Texture.SAND),
|
||||||
|
Tile(BlockID.GRAVEL, Texture.GRAVEL),
|
||||||
|
Tile(BlockID.ORE_GOLD, Texture.ORE_GOLD),
|
||||||
|
Tile(BlockID.ORE_IRON, Texture.ORE_IRON),
|
||||||
|
Tile(BlockID.ORE_COAL, Texture.ORE_COAL),
|
||||||
|
Tile(BlockID.TREE_TRUNK, Texture.LOG_SIDE), # fixme
|
||||||
|
Tile(BlockID.LEAVES, Texture.LEAVES_TRANSPARENT), # fixme
|
||||||
|
Tile(BlockID.GLASS, Texture.GLASS),
|
||||||
|
Tile(BlockID.ORE_LAPIS, Texture.ORE_LAPIS),
|
||||||
|
Tile(BlockID.BLOCK_LAPIS, Texture.LAPIS),
|
||||||
|
Tile(BlockID.SANDSTONE, Texture.SANDSTONE_SIDE),
|
||||||
|
Tile(BlockID.CLOTH, Texture.CLOTH_64), # wool, colored
|
||||||
|
Tile(BlockID.FLOWER, Texture.FLOWER),
|
||||||
|
Tile(BlockID.ROSE, Texture.ROSE),
|
||||||
|
Tile(BlockID.MUSHROOM_1, Texture.MUSHROOM_BROWN),
|
||||||
|
Tile(BlockID.MUSHROOM_2, Texture.MUSHROOM_RED),
|
||||||
|
Tile(BlockID.BLOCK_GOLD, Texture.GOLD),
|
||||||
|
Tile(BlockID.BLOCK_IRON, Texture.IRON),
|
||||||
|
Tile(BlockID.STONESLAB_FULL, Texture.STONE_SLAB_SIDE), # fixme
|
||||||
|
Tile(BlockID.STONESLAB_HALF, Texture.STONE_SLAB_SIDE), # fixme
|
||||||
|
Tile(BlockID.BRICKS, Texture.BRICKS),
|
||||||
|
Tile(BlockID.TNT, Texture.TNT_SIDE),
|
||||||
|
Tile(BlockID.BOOKSHELF, Texture.BOOKSHELF),
|
||||||
|
Tile(BlockID.MOSS_STONE, Texture.MOSSY_STONE),
|
||||||
|
Tile(BlockID.OBSIDIAN, Texture.OBSIDIAN),
|
||||||
|
Tile(BlockID.TORCH, Texture.TORCH_LIT),
|
||||||
|
Tile(BlockID.STAIRS_WOOD, Texture.PLANKS), # fixme
|
||||||
|
Tile(BlockID.WIRE, Texture.REDSTONE_DUST),
|
||||||
|
Tile(BlockID.ORE_EMERALD, Texture.ORE_EMERALD),
|
||||||
|
Tile(BlockID.BLOCK_EMERALD, Texture.EMERALD),
|
||||||
|
Tile(BlockID.FARMLAND, Texture.FARMLAND), # fixme
|
||||||
|
Tile(BlockID.DOOR_WOOD, Texture.DOOR_TOP), # fixme
|
||||||
|
Tile(BlockID.LADDER, Texture.LADDER),
|
||||||
|
Tile(BlockID.STAIRS_STONE, Texture.STONEBRICK),
|
||||||
|
Tile(BlockID.DOOR_IRON, Texture.DOOR_IRON_TOP), # fixme
|
||||||
|
Tile(BlockID.ORE_REDSTONE, Texture.ORE_RED_STONE), # fixme
|
||||||
|
Tile(BlockID.ORE_REDSTONE_LIT, Texture.ORE_RED_STONE), # fixme
|
||||||
|
Tile(BlockID.TOPSNOW, Texture.SNOW),
|
||||||
|
Tile(BlockID.ICE, Texture.ICE),
|
||||||
|
Tile(BlockID.SNOW, Texture.SNOW),
|
||||||
|
Tile(BlockID.CACTUS, Texture.CACTUS_SIDE),
|
||||||
|
Tile(BlockID.CLAY, Texture.CLAY),
|
||||||
|
Tile(BlockID.REEDS, Texture.REEDS),
|
||||||
|
Tile(BlockID.FENCE, Texture.PLANKS),
|
||||||
|
Tile(BlockID.INVISIBLE, Texture.STONE),
|
||||||
|
Tile(BlockID.WOOD, Texture.PLANKS),
|
||||||
|
#Tile(BlockID.LEAVES_CARRIED, Texture.LEAVES_TRANSPARENT), # fixme
|
||||||
|
Tile(BlockID.FIRE, Texture.FIRE1),
|
||||||
|
Tile(BlockID.SAPLING, Texture.SAPLING),
|
||||||
|
Tile(BlockID.SPONGE, Texture.SPONGE),
|
||||||
|
Tile(BlockID.TALL_GRASS, Texture.TALL_GRASS),
|
||||||
|
Tile(BlockID.DEAD_BUSH, Texture.DEAD_BUSH),
|
||||||
|
Tile(BlockID.PUMPKIN, Texture.PUMPKIN_FACE), # fixme
|
||||||
|
Tile(BlockID.PUMPKIN_LIT, Texture.PUMPKIN_FACE_LIT), # fixme
|
||||||
|
Tile(BlockID.NETHERRACK, Texture.BLOODSTONE),
|
||||||
|
Tile(BlockID.SOUL_SAND, Texture.SOULSAND),
|
||||||
|
Tile(BlockID.GLOWSTONE, Texture.GLOWSTONE),
|
||||||
|
Tile(BlockID.COBWEB, Texture.COBWEB),
|
||||||
|
Tile(BlockID.WORKBENCH, Texture.WORKBENCH_TOP), # fixme
|
||||||
|
Tile(BlockID.WHEAT, Texture.WHEAT_0),
|
||||||
|
|
||||||
|
# modded blocks
|
||||||
|
Tile(BlockID.YELLOW_COBBLE, Texture.YELLOW_COBBLE),
|
||||||
|
Tile(BlockID.MARBLE_YELLOW, Texture.MARBLE_YELLOW),
|
||||||
|
]
|
||||||
|
|
||||||
|
tiles_by_id = {
|
||||||
|
tile.block_id: tile for tile in tiles
|
||||||
|
}
|
||||||
48
minecraft/gen/fence.obj
Normal file
48
minecraft/gen/fence.obj
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Blender 5.0.0
|
||||||
|
# www.blender.org
|
||||||
|
o Cube
|
||||||
|
v 0.250000 1.000000 -0.250000
|
||||||
|
v 0.250000 -1.000000 -0.250000
|
||||||
|
v 0.250000 1.000000 0.250000
|
||||||
|
v 0.250000 -1.000000 0.250000
|
||||||
|
v -0.250000 1.000000 -0.250000
|
||||||
|
v -0.250000 -1.000000 -0.250000
|
||||||
|
v -0.250000 1.000000 0.250000
|
||||||
|
v -0.250000 -1.000000 0.250000
|
||||||
|
vn -0.0000 1.0000 -0.0000
|
||||||
|
vn -0.0000 -0.0000 1.0000
|
||||||
|
vn -1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -1.0000 -0.0000
|
||||||
|
vn 1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -0.0000 -1.0000
|
||||||
|
vt 0.250000 1.250000
|
||||||
|
vt 0.500000 1.000000
|
||||||
|
vt 0.500000 1.250000
|
||||||
|
vt 0.250050 0.000100
|
||||||
|
vt 0.500000 0.999900
|
||||||
|
vt 0.250050 0.999900
|
||||||
|
vt 0.500000 0.000100
|
||||||
|
vt 0.749950 0.999900
|
||||||
|
vt 0.250000 0.000000
|
||||||
|
vt 0.500000 -0.250000
|
||||||
|
vt 0.500000 0.000000
|
||||||
|
vt 0.000100 0.000100
|
||||||
|
vt 0.000100 0.999900
|
||||||
|
vt 0.749950 0.000100
|
||||||
|
vt 0.999900 0.999900
|
||||||
|
vt 0.250000 1.000000
|
||||||
|
vt 0.250000 -0.250000
|
||||||
|
vt 0.999900 0.000100
|
||||||
|
s 0
|
||||||
|
f 5/1/1 3/2/1 1/3/1
|
||||||
|
f 3/4/2 8/5/2 4/6/2
|
||||||
|
f 7/7/3 6/8/3 8/5/3
|
||||||
|
f 2/9/4 8/10/4 6/11/4
|
||||||
|
f 1/12/5 4/6/5 2/13/5
|
||||||
|
f 5/14/6 2/15/6 6/8/6
|
||||||
|
f 5/1/1 7/16/1 3/2/1
|
||||||
|
f 3/4/2 7/7/2 8/5/2
|
||||||
|
f 7/7/3 5/14/3 6/8/3
|
||||||
|
f 2/9/4 4/17/4 8/10/4
|
||||||
|
f 1/12/5 3/4/5 4/6/5
|
||||||
|
f 5/14/6 1/18/6 2/15/6
|
||||||
@ -3,10 +3,15 @@ import struct
|
|||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
import functools
|
||||||
|
import os
|
||||||
|
|
||||||
import mcregion
|
import mcregion
|
||||||
import vec3
|
import vec3
|
||||||
import vertex_buffer
|
import vertex_buffer
|
||||||
|
import data
|
||||||
|
|
||||||
|
FAST = "FAST" in os.environ
|
||||||
|
|
||||||
def wrap_n(nc, chunk_c):
|
def wrap_n(nc, chunk_c):
|
||||||
if nc < 0:
|
if nc < 0:
|
||||||
@ -17,48 +22,79 @@ def wrap_n(nc, chunk_c):
|
|||||||
chunk_c = chunk_c + 1
|
chunk_c = chunk_c + 1
|
||||||
return nc, chunk_c
|
return nc, chunk_c
|
||||||
|
|
||||||
|
custom_blocks = [
|
||||||
|
{ # "tallgrass" model
|
||||||
|
data.BlockID.TALL_GRASS,
|
||||||
|
data.BlockID.MUSHROOM_1,
|
||||||
|
data.BlockID.MUSHROOM_2,
|
||||||
|
data.BlockID.FLOWER,
|
||||||
|
data.BlockID.ROSE,
|
||||||
|
data.BlockID.SAPLING,
|
||||||
|
},
|
||||||
|
{ # "fence" model
|
||||||
|
data.BlockID.FENCE,
|
||||||
|
},
|
||||||
|
{ # "torch" model
|
||||||
|
data.BlockID.TORCH,
|
||||||
|
},
|
||||||
|
{ # "wheat" model
|
||||||
|
data.BlockID.WHEAT,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
non_solid_blocks = set(chain.from_iterable(custom_blocks))
|
||||||
|
|
||||||
|
hack_non_solid_blocks = set([
|
||||||
|
data.BlockID.LADDER,
|
||||||
|
data.BlockID.WIRE,
|
||||||
|
])
|
||||||
|
|
||||||
|
def neighbor_exists(level_table, chunk_x, chunk_z, nx, ny, nz):
|
||||||
|
if ny > 127 or ny < 0:
|
||||||
|
return False
|
||||||
|
nx, n_chunk_x = wrap_n(nx, chunk_x)
|
||||||
|
nz, n_chunk_z = wrap_n(nz, chunk_z)
|
||||||
|
assert nx <= 15 and nx >= 0
|
||||||
|
assert nz <= 15 and nz >= 0
|
||||||
|
key = (n_chunk_x, n_chunk_z)
|
||||||
|
if key not in level_table:
|
||||||
|
return True
|
||||||
|
n_block_index = mcregion.block_index_from_xyz(nx, ny, nz)
|
||||||
|
n_block_id = level_table[key].blocks[n_block_index]
|
||||||
|
|
||||||
|
has_neighbor = (n_block_id != data.BlockID.AIR) and (n_block_id not in non_solid_blocks) and (n_block_id not in hack_non_solid_blocks)
|
||||||
|
return has_neighbor
|
||||||
|
|
||||||
def block_neighbors(level_table, chunk_x, chunk_z, block_index):
|
def block_neighbors(level_table, chunk_x, chunk_z, block_index):
|
||||||
block_id = level_table[(chunk_x, chunk_z)].blocks[block_index]
|
block_id = level_table[(chunk_x, chunk_z)].blocks[block_index]
|
||||||
if block_id == 0:
|
if block_id == data.BlockID.AIR:
|
||||||
return
|
return
|
||||||
|
|
||||||
def neighbor_exists(nx, ny, nz):
|
block_data = level_table[(chunk_x, chunk_z)].data[block_index // 2]
|
||||||
if ny > 127 or ny < 0:
|
block_data = (block_data >> (1 - (block_index % 2)) * 4) & 0xf
|
||||||
return False
|
|
||||||
nx, n_chunk_x = wrap_n(nx, chunk_x)
|
|
||||||
nz, n_chunk_z = wrap_n(nz, chunk_z)
|
|
||||||
if nx > 15 or nx < 0:
|
|
||||||
return True
|
|
||||||
if nz > 15 or nz < 0:
|
|
||||||
return True
|
|
||||||
n_block_index = mcregion.block_index_from_xyz(nx, ny, nz)
|
|
||||||
key = (n_chunk_x, n_chunk_z)
|
|
||||||
if key not in level_table:
|
|
||||||
return True
|
|
||||||
n_block_id = level_table[key].blocks[n_block_index]
|
|
||||||
return n_block_id != 0
|
|
||||||
|
|
||||||
x, y, z = mcregion.xyz_from_block_index(block_index)
|
xyz = mcregion.xyz_from_block_index(block_index)
|
||||||
|
|
||||||
center_position = vec3.add((x, y, z), (chunk_x * 16, 0, chunk_z * 16))
|
center_position = vec3.add(xyz, (chunk_x * 16, 0, chunk_z * 16))
|
||||||
|
|
||||||
def find_non_neighbors():
|
def find_non_neighbors():
|
||||||
for i, normal in enumerate(vertex_buffer.normals):
|
for i, normal in enumerate(vertex_buffer.normals):
|
||||||
neighbor = vec3.add(normal, (x, y, z))
|
neighbor = vec3.add(normal, xyz)
|
||||||
if not neighbor_exists(*neighbor):
|
if not neighbor_exists(level_table, chunk_x, chunk_z, *neighbor):
|
||||||
yield i
|
yield i
|
||||||
|
|
||||||
normal_indices = list(find_non_neighbors())
|
normal_indices = list(find_non_neighbors())
|
||||||
if normal_indices:
|
if block_id in non_solid_blocks or block_id in hack_non_solid_blocks or normal_indices:
|
||||||
yield center_position, block_id, normal_indices
|
yield center_position, block_id, block_data, normal_indices
|
||||||
|
|
||||||
def devoxelize_region(level_table):
|
def devoxelize_region(level_table, level_table_keys):
|
||||||
for chunk_x, chunk_z in level_table.keys():
|
for chunk_x, chunk_z in level_table_keys:
|
||||||
for block_index in range(128 * 16 * 16):
|
for block_index in range(128 * 16 * 16):
|
||||||
yield from block_neighbors(level_table, chunk_x, chunk_z, block_index)
|
yield from block_neighbors(level_table, chunk_x, chunk_z, block_index)
|
||||||
|
if FAST:
|
||||||
|
return
|
||||||
|
|
||||||
def build_level_table(mem, locations):
|
def build_level_table(level_table, mem, locations):
|
||||||
level_table = {}
|
|
||||||
for location in locations:
|
for location in locations:
|
||||||
try:
|
try:
|
||||||
level = mcregion.parse_location(mem, location)
|
level = mcregion.parse_location(mem, location)
|
||||||
@ -82,38 +118,84 @@ def build_block_configuration_table():
|
|||||||
indices.extend(vertex_buffer.faces_by_normal[vertex_buffer.normals[j]])
|
indices.extend(vertex_buffer.faces_by_normal[vertex_buffer.normals[j]])
|
||||||
yield indices
|
yield indices
|
||||||
|
|
||||||
|
def pack_instance_data(position, block_id, block_data):
|
||||||
|
packed = struct.pack("<hhhBB",
|
||||||
|
position[0], position[1], position[2],
|
||||||
|
block_id,
|
||||||
|
block_data)
|
||||||
|
return packed
|
||||||
|
|
||||||
|
def pack_light_data(position, block_id):
|
||||||
|
packed = struct.pack("<ffff", position[0], position[1], position[2], block_id)
|
||||||
|
return packed
|
||||||
|
|
||||||
def build_block_instances(blocks):
|
def build_block_instances(blocks):
|
||||||
by_configuration = defaultdict(list)
|
by_configuration = defaultdict(list)
|
||||||
|
|
||||||
for position, block_id, normal_indices in blocks:
|
deferred_blocks = defaultdict(list)
|
||||||
|
|
||||||
|
light_sources = []
|
||||||
|
|
||||||
|
def is_deferred_block(position, block_id, block_data):
|
||||||
|
for i, custom_block_types in enumerate(custom_blocks):
|
||||||
|
if block_id in custom_block_types:
|
||||||
|
deferred_blocks[i].append((position, block_id, block_data))
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
for position, block_id, block_data, normal_indices in blocks:
|
||||||
|
if block_id == data.BlockID.TORCH:
|
||||||
|
light_sources.append((position, block_id))
|
||||||
|
if is_deferred_block(position, block_id, block_data):
|
||||||
|
assert block_id in non_solid_blocks
|
||||||
|
continue
|
||||||
configuration = normal_indices_as_block_configuration(normal_indices)
|
configuration = normal_indices_as_block_configuration(normal_indices)
|
||||||
#print(position, block_id, block_configuration)
|
by_configuration[configuration].append((position, block_id, block_data))
|
||||||
by_configuration[configuration].append((position, block_id))
|
|
||||||
|
|
||||||
offset = 0
|
offset = 0
|
||||||
configuration_instance_count_offset = []
|
configuration_instance_count_offset = []
|
||||||
with open(f"{data_path}.instance.vtx", "wb") as f:
|
with open(f"{data_path}.instance.vtx", "wb") as f:
|
||||||
|
######################################################################
|
||||||
|
# cubes
|
||||||
|
######################################################################
|
||||||
for configuration in range(64):
|
for configuration in range(64):
|
||||||
if configuration not in by_configuration:
|
if configuration not in by_configuration:
|
||||||
configuration_instance_count_offset.append((0, 0))
|
configuration_instance_count_offset.append((0, 0))
|
||||||
continue
|
continue
|
||||||
blocks = by_configuration[configuration]
|
_blocks = by_configuration[configuration]
|
||||||
configuration_instance_count_offset.append((len(blocks), offset))
|
configuration_instance_count_offset.append((len(_blocks), offset))
|
||||||
for position, block_id in blocks:
|
for position, block_id, block_data in _blocks:
|
||||||
packed = struct.pack("<hhhBB",
|
assert block_id not in non_solid_blocks, block_id
|
||||||
position[0], position[1], position[2],
|
packed = pack_instance_data(position, block_id, block_data)
|
||||||
block_id,
|
|
||||||
0)
|
|
||||||
f.write(packed)
|
f.write(packed)
|
||||||
offset += len(packed)
|
offset += len(packed)
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# non-cubes
|
||||||
|
######################################################################
|
||||||
|
for custom_block_ix in range(len(custom_blocks)):
|
||||||
|
nc_offset = offset
|
||||||
|
nc_instance_count = 0
|
||||||
|
for position, block_id, block_data in deferred_blocks[custom_block_ix]:
|
||||||
|
assert block_id in non_solid_blocks, block_id
|
||||||
|
packed = pack_instance_data(position, block_id, block_data)
|
||||||
|
f.write(packed)
|
||||||
|
offset += len(packed)
|
||||||
|
nc_instance_count += 1
|
||||||
|
configuration_instance_count_offset.append((nc_instance_count, nc_offset))
|
||||||
|
|
||||||
with open(f"{data_path}.instance.cfg", "wb") as f:
|
with open(f"{data_path}.instance.cfg", "wb") as f:
|
||||||
for instance_count, offset in configuration_instance_count_offset:
|
for instance_count, offset in configuration_instance_count_offset:
|
||||||
print(instance_count, offset)
|
#print(instance_count, offset)
|
||||||
f.write(struct.pack("<ii", instance_count, offset))
|
f.write(struct.pack("<ii", instance_count, offset))
|
||||||
|
|
||||||
def main(mcr_path, data_path):
|
with open(f"{data_path}.lights.vtx", "wb") as f:
|
||||||
with open(mcr_path, "rb") as f:
|
for position, block_id in light_sources:
|
||||||
|
packed = pack_light_data(position, block_id)
|
||||||
|
f.write(packed)
|
||||||
|
|
||||||
|
def level_table_from_path(level_table, path):
|
||||||
|
with open(path, "rb") as f:
|
||||||
buf = f.read()
|
buf = f.read()
|
||||||
mem = memoryview(buf)
|
mem = memoryview(buf)
|
||||||
|
|
||||||
@ -122,13 +204,34 @@ def main(mcr_path, data_path):
|
|||||||
offset, timestamps = mcregion.parse_timestamps(mem, offset)
|
offset, timestamps = mcregion.parse_timestamps(mem, offset)
|
||||||
assert offset == 0x2000
|
assert offset == 0x2000
|
||||||
|
|
||||||
level_table = build_level_table(mem, locations)
|
build_level_table(level_table, mem, locations)
|
||||||
blocks = devoxelize_region(level_table)
|
|
||||||
|
all_paths = [
|
||||||
|
"/home/bilbo/Love2DWorld/region/r.0.0.mcr",
|
||||||
|
"/home/bilbo/Love2DWorld/region/r.-1.-1.mcr",
|
||||||
|
"/home/bilbo/Love2DWorld/region/r.0.-1.mcr",
|
||||||
|
"/home/bilbo/Love2DWorld/region/r.-1.0.mcr",
|
||||||
|
]
|
||||||
|
|
||||||
|
def main2(level_table, level_table_keys):
|
||||||
|
blocks = devoxelize_region(level_table, level_table_keys)
|
||||||
build_block_instances(blocks)
|
build_block_instances(blocks)
|
||||||
|
|
||||||
#pprint(list(build_block_configuration_table()))
|
def main(mcr_path, data_path):
|
||||||
|
assert mcr_path in all_paths
|
||||||
|
level_table = {}
|
||||||
|
level_table_from_path(level_table, mcr_path)
|
||||||
|
level_table_keys = list(level_table.keys())
|
||||||
|
for path in all_paths:
|
||||||
|
if path == mcr_path:
|
||||||
|
continue
|
||||||
|
level_table_from_path(level_table, path)
|
||||||
|
|
||||||
|
main2(level_table, level_table_keys)
|
||||||
|
#import cProfile
|
||||||
|
#cProfile.runctx("main2(level_table, level_table_keys)", {},
|
||||||
|
# {"level_table_keys": level_table_keys, "level_table": level_table, "main2": main2})
|
||||||
|
|
||||||
mcr_path = sys.argv[1]
|
mcr_path = sys.argv[1]
|
||||||
data_path = sys.argv[2]
|
data_path = sys.argv[2]
|
||||||
|
|
||||||
main(mcr_path, data_path)
|
main(mcr_path, data_path)
|
||||||
|
|||||||
11
minecraft/gen/mc.sh
Normal file
11
minecraft/gen/mc.sh
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
set -eux
|
||||||
|
cd ./minecraft/gen
|
||||||
|
PYTHON=pypy3.11
|
||||||
|
$PYTHON mc.py ~/Love2DWorld/region/r.0.0.mcr ../region.0.0 &
|
||||||
|
$PYTHON mc.py ~/Love2DWorld/region/r.-1.-1.mcr ../region.-1.-1 &
|
||||||
|
$PYTHON mc.py ~/Love2DWorld/region/r.0.-1.mcr ../region.0.-1 &
|
||||||
|
$PYTHON mc.py ~/Love2DWorld/region/r.-1.0.mcr ../region.-1.0 &
|
||||||
|
|
||||||
|
wait
|
||||||
|
|
||||||
|
cat ../region*.lights.vtx > ../global.lights.vtx
|
||||||
@ -217,15 +217,30 @@ def parse_location(mem, location):
|
|||||||
level = level_from_tag(tag)
|
level = level_from_tag(tag)
|
||||||
return level
|
return level
|
||||||
|
|
||||||
def xyz_from_block_index(block_index):
|
def _xyz_from_block_index(block_index):
|
||||||
assert block_index >= 0 and block_index < (128 * 16 * 16)
|
assert block_index >= 0 and block_index < (128 * 16 * 16)
|
||||||
x = int(block_index / (128 * 16))
|
x = block_index // (128 * 16)
|
||||||
y = int(block_index % 128)
|
y = block_index % 128
|
||||||
z = int(int(block_index / 128) % 16)
|
z = (block_index // 128) % 16
|
||||||
return x, y, z
|
return x, y, z
|
||||||
|
|
||||||
def block_index_from_xyz(x, y, z):
|
def _block_index_from_xyz(x, y, z):
|
||||||
assert x >= 0 and x < 16
|
assert x >= 0 and x < 16
|
||||||
assert y >= 0 and y < 128
|
assert y >= 0 and y < 128
|
||||||
assert z >= 0 and z < 16
|
assert z >= 0 and z < 16
|
||||||
return int(y + z * 128 + x * 128 * 16)
|
return int(y + z * 128 + x * 128 * 16)
|
||||||
|
|
||||||
|
xyz_to_block_index = {}
|
||||||
|
block_index_to_xyz = {}
|
||||||
|
|
||||||
|
for i in range(128 * 16 * 16):
|
||||||
|
xyz = _xyz_from_block_index(i)
|
||||||
|
assert _block_index_from_xyz(*xyz) == i
|
||||||
|
xyz_to_block_index[xyz] = i
|
||||||
|
block_index_to_xyz[i] = xyz
|
||||||
|
|
||||||
|
def xyz_from_block_index(block_index):
|
||||||
|
return block_index_to_xyz[block_index]
|
||||||
|
|
||||||
|
def block_index_from_xyz(x, y, z):
|
||||||
|
return xyz_to_block_index[(x, y, z)]
|
||||||
|
|||||||
150
minecraft/gen/missing_block_id.py
Normal file
150
minecraft/gen/missing_block_id.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
import struct
|
||||||
|
from collections import defaultdict
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import data
|
||||||
|
|
||||||
|
files = sys.argv[1:]
|
||||||
|
|
||||||
|
by_block_id = defaultdict(list)
|
||||||
|
no_tile = defaultdict(list)
|
||||||
|
|
||||||
|
block_ids = {
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
38,
|
||||||
|
39,
|
||||||
|
40,
|
||||||
|
41,
|
||||||
|
42,
|
||||||
|
43,
|
||||||
|
44,
|
||||||
|
45,
|
||||||
|
46,
|
||||||
|
47,
|
||||||
|
48,
|
||||||
|
49,
|
||||||
|
50,
|
||||||
|
51,
|
||||||
|
52,
|
||||||
|
53,
|
||||||
|
54,
|
||||||
|
55,
|
||||||
|
56,
|
||||||
|
57,
|
||||||
|
58,
|
||||||
|
59,
|
||||||
|
60,
|
||||||
|
61,
|
||||||
|
62,
|
||||||
|
63,
|
||||||
|
64,
|
||||||
|
65,
|
||||||
|
66,
|
||||||
|
67,
|
||||||
|
68,
|
||||||
|
69,
|
||||||
|
70,
|
||||||
|
71,
|
||||||
|
72,
|
||||||
|
73,
|
||||||
|
74,
|
||||||
|
75,
|
||||||
|
76,
|
||||||
|
77,
|
||||||
|
78,
|
||||||
|
79,
|
||||||
|
80,
|
||||||
|
81,
|
||||||
|
82,
|
||||||
|
83,
|
||||||
|
84,
|
||||||
|
85,
|
||||||
|
86,
|
||||||
|
87,
|
||||||
|
88,
|
||||||
|
89,
|
||||||
|
90,
|
||||||
|
91,
|
||||||
|
92,
|
||||||
|
93,
|
||||||
|
94,
|
||||||
|
95,
|
||||||
|
96,
|
||||||
|
97,
|
||||||
|
98,
|
||||||
|
99,
|
||||||
|
100,
|
||||||
|
101,
|
||||||
|
102,
|
||||||
|
103,
|
||||||
|
104,
|
||||||
|
105,
|
||||||
|
106,
|
||||||
|
107,
|
||||||
|
108,
|
||||||
|
109,
|
||||||
|
110,
|
||||||
|
111,
|
||||||
|
112,
|
||||||
|
113,
|
||||||
|
114,
|
||||||
|
115,
|
||||||
|
}
|
||||||
|
|
||||||
|
for filename in files:
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
buf = f.read()
|
||||||
|
for i in range(len(buf) // 8):
|
||||||
|
x, y, z, block_id, block_data = struct.unpack("<hhhBB", buf[i*8:i*8+8])
|
||||||
|
if block_id == 35:
|
||||||
|
print(x, y, z, block_data)
|
||||||
|
|
||||||
|
if block_id not in block_ids and block_id not in data.tiles_by_id:
|
||||||
|
by_block_id[block_id].append((x, y, z, block_data))
|
||||||
|
elif block_id not in data.tiles_by_id:
|
||||||
|
no_tile[block_id].append((x, y, z, block_data))
|
||||||
|
|
||||||
|
print("no block id:")
|
||||||
|
for key in sorted(by_block_id.keys()):
|
||||||
|
print(" ", key, len(by_block_id[key]), by_block_id[key][0])
|
||||||
|
|
||||||
|
print("no tile:")
|
||||||
|
for key in sorted(no_tile.keys()):
|
||||||
|
print(" ", key, len(no_tile[key]), no_tile[key][0])
|
||||||
80
minecraft/gen/obj.py
Normal file
80
minecraft/gen/obj.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
def ignore(state, line):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def normalize_float(s):
|
||||||
|
f = float(s)
|
||||||
|
if f == -0.0:
|
||||||
|
return 0.0
|
||||||
|
return f
|
||||||
|
|
||||||
|
def parse_float_components(s, length):
|
||||||
|
components = s.split()
|
||||||
|
assert len(components) == length
|
||||||
|
return tuple(map(normalize_float, components))
|
||||||
|
|
||||||
|
def parse_position(state, line):
|
||||||
|
position = parse_float_components(line, 3)
|
||||||
|
state.position.append(position)
|
||||||
|
|
||||||
|
def parse_normal(state, line):
|
||||||
|
normal = parse_float_components(line, 3)
|
||||||
|
state.normal.append(normal)
|
||||||
|
|
||||||
|
def parse_texture(state, line):
|
||||||
|
texture = parse_float_components(line, 2)
|
||||||
|
state.texture.append(texture)
|
||||||
|
|
||||||
|
def parse_ptn(s):
|
||||||
|
ptn = tuple(int(i) - 1 for i in s.split("/"))
|
||||||
|
assert all(c >= 0 for c in ptn), ptn
|
||||||
|
assert len(ptn) == 3, ptn
|
||||||
|
return ptn
|
||||||
|
|
||||||
|
def parse_triangle(state, line):
|
||||||
|
indices = line.split()
|
||||||
|
assert len(indices) == 3, line
|
||||||
|
triangle = tuple(map(parse_ptn, indices))
|
||||||
|
state.triangle.append(triangle)
|
||||||
|
|
||||||
|
prefixes = [
|
||||||
|
("#", ignore),
|
||||||
|
("o ", ignore),
|
||||||
|
("s ", ignore),
|
||||||
|
("v ", parse_position),
|
||||||
|
("vn ", parse_normal),
|
||||||
|
("vt ", parse_texture),
|
||||||
|
("f ", parse_triangle),
|
||||||
|
]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ObjState:
|
||||||
|
position: list
|
||||||
|
normal: list
|
||||||
|
texture: list
|
||||||
|
triangle: list
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.position = []
|
||||||
|
self.normal = []
|
||||||
|
self.texture = []
|
||||||
|
self.triangle = []
|
||||||
|
|
||||||
|
def parse_obj(s):
|
||||||
|
state = ObjState()
|
||||||
|
lines = s.strip().split("\n")
|
||||||
|
for line in lines:
|
||||||
|
for prefix, func in prefixes:
|
||||||
|
if line.startswith(prefix):
|
||||||
|
line = line.removeprefix(prefix)
|
||||||
|
func(state, line)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
assert False, line
|
||||||
|
return state
|
||||||
|
|
||||||
|
def parse_obj_from_filename(filename):
|
||||||
|
with open(filename, "r") as f:
|
||||||
|
buf = f.read()
|
||||||
|
return parse_obj(buf)
|
||||||
25
minecraft/gen/obj_state.py
Normal file
25
minecraft/gen/obj_state.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from collections import defaultdict
|
||||||
|
import obj
|
||||||
|
|
||||||
|
def append_triangles(state, vertex_buffer, index_buffer, index_lookup):
|
||||||
|
for triangle in state.triangle:
|
||||||
|
for p_ix, t_ix, n_ix in triangle:
|
||||||
|
key = (p_ix, n_ix, t_ix)
|
||||||
|
if key not in index_lookup:
|
||||||
|
position = state.position[p_ix]
|
||||||
|
normal = state.normal[n_ix]
|
||||||
|
texture = state.texture[t_ix]
|
||||||
|
index = len(vertex_buffer)
|
||||||
|
index_lookup[key] = index
|
||||||
|
vertex_buffer.append((position, normal, texture))
|
||||||
|
index_buffer.append(index_lookup[key])
|
||||||
|
|
||||||
|
def build_faces_by_normal(vertex_buffer, index_buffer):
|
||||||
|
by_normal = defaultdict(list)
|
||||||
|
for i in range(len(index_buffer) // 3):
|
||||||
|
tri = [index_buffer[i * 3 + n] for n in range(3)]
|
||||||
|
s = set(vertex_buffer[j][1] for j in tri)
|
||||||
|
assert len(s) == 1, s
|
||||||
|
normal, = iter(s)
|
||||||
|
by_normal[normal].extend(tri)
|
||||||
|
return by_normal
|
||||||
24
minecraft/gen/tallgrass.obj
Normal file
24
minecraft/gen/tallgrass.obj
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Blender 5.0.0
|
||||||
|
# www.blender.org
|
||||||
|
o TallGrass
|
||||||
|
v 0.800000 0.600000 0.800000
|
||||||
|
v 0.800000 -1.000000 0.800000
|
||||||
|
v -0.800000 -1.000000 0.800000
|
||||||
|
v -0.800000 0.600000 0.800000
|
||||||
|
v -0.800000 0.600000 -0.800000
|
||||||
|
v -0.800000 -1.000000 -0.800000
|
||||||
|
v 0.800000 -1.000000 -0.800000
|
||||||
|
v 0.800000 0.600000 -0.800000
|
||||||
|
vn 0.7071 -0.0000 0.7071
|
||||||
|
vn 0.7071 -0.0000 -0.7071
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt 0.000000 -0.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt -0.000000 1.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
s 0
|
||||||
|
f 3/1/1 8/2/1 4/3/1
|
||||||
|
f 5/2/2 2/4/2 6/5/2
|
||||||
|
f 3/1/1 7/5/1 8/2/1
|
||||||
|
f 5/2/2 1/6/2 2/4/2
|
||||||
40
minecraft/gen/torch.obj
Normal file
40
minecraft/gen/torch.obj
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Blender 5.0.0
|
||||||
|
# www.blender.org
|
||||||
|
o Cube
|
||||||
|
v 0.125000 0.250000 -0.125000
|
||||||
|
v 0.125000 -1.000000 -0.125000
|
||||||
|
v 0.125000 0.250000 0.125000
|
||||||
|
v 0.125000 -1.000000 0.125000
|
||||||
|
v -0.125000 0.250000 -0.125000
|
||||||
|
v -0.125000 -1.000000 -0.125000
|
||||||
|
v -0.125000 0.250000 0.125000
|
||||||
|
v -0.125000 -1.000000 0.125000
|
||||||
|
vn -0.0000 1.0000 -0.0000
|
||||||
|
vn -0.0000 -0.0000 1.0000
|
||||||
|
vn -1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -1.0000 -0.0000
|
||||||
|
vn 1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -0.0000 -1.0000
|
||||||
|
vt 0.531250 0.406250
|
||||||
|
vt 0.468750 0.468750
|
||||||
|
vt 0.468750 0.406250
|
||||||
|
vt 0.437500 0.375000
|
||||||
|
vt 0.562500 1.000000
|
||||||
|
vt 0.437500 1.000000
|
||||||
|
vt 0.562500 0.875000
|
||||||
|
vt 0.437500 0.875000
|
||||||
|
vt 0.531250 0.468750
|
||||||
|
vt 0.562500 0.375000
|
||||||
|
s 0
|
||||||
|
f 5/1/1 3/2/1 1/3/1
|
||||||
|
f 3/4/2 8/5/2 4/6/2
|
||||||
|
f 7/4/3 6/5/3 8/6/3
|
||||||
|
f 2/7/4 8/6/4 6/8/4
|
||||||
|
f 1/4/5 4/5/5 2/6/5
|
||||||
|
f 5/4/6 2/5/6 6/6/6
|
||||||
|
f 5/1/1 7/9/1 3/2/1
|
||||||
|
f 3/4/2 7/10/2 8/5/2
|
||||||
|
f 7/4/3 5/10/3 6/5/3
|
||||||
|
f 2/7/4 4/5/4 8/6/4
|
||||||
|
f 1/4/5 3/10/5 4/5/5
|
||||||
|
f 5/4/6 1/10/6 2/5/6
|
||||||
@ -1,41 +1,8 @@
|
|||||||
import struct
|
import struct
|
||||||
import vec3
|
import vec3
|
||||||
|
import obj
|
||||||
vertex_table = [
|
import obj_state
|
||||||
((-1.0, 1.0, -1.0), (0.0, 1.0, 0.0), (1.0, 0.0)),
|
import sys
|
||||||
((1.0, 1.0, 1.0), (0.0, 1.0, 0.0), (0.0, 1.0)),
|
|
||||||
((1.0, 1.0, -1.0), (0.0, 1.0, 0.0), (0.0, 0.0)),
|
|
||||||
((1.0, 1.0, 1.0), (0.0, 0.0, 1.0), (1.0, 1.0)),
|
|
||||||
((-1.0, -1.0, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0)),
|
|
||||||
((1.0, -1.0, 1.0), (0.0, 0.0, 1.0), (1.0, 0.0)),
|
|
||||||
((-1.0, 1.0, 1.0), (-1.0, 0.0, 0.0), (1.0, 1.0)),
|
|
||||||
((-1.0, -1.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 0.0)),
|
|
||||||
((-1.0, -1.0, 1.0), (-1.0, 0.0, 0.0), (1.0, 0.0)),
|
|
||||||
((1.0, -1.0, -1.0), (0.0, -1.0, 0.0), (1.0, 0.0)),
|
|
||||||
((-1.0, -1.0, 1.0), (0.0, -1.0, 0.0), (0.0, 1.0)),
|
|
||||||
((-1.0, -1.0, -1.0), (0.0, -1.0, 0.0), (0.0, 0.0)),
|
|
||||||
((1.0, 1.0, -1.0), (1.0, 0.0, 0.0), (1.0, 1.0)),
|
|
||||||
((1.0, -1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 0.0)),
|
|
||||||
((1.0, -1.0, -1.0), (1.0, 0.0, 0.0), (1.0, 0.0)),
|
|
||||||
((-1.0, 1.0, -1.0), (0.0, 0.0, -1.0), (1.0, 1.0)),
|
|
||||||
((1.0, -1.0, -1.0), (0.0, 0.0, -1.0), (0.0, 0.0)),
|
|
||||||
((-1.0, -1.0, -1.0), (0.0, 0.0, -1.0), (1.0, 0.0)),
|
|
||||||
((-1.0, 1.0, 1.0), (0.0, 1.0, 0.0), (1.0, 1.0)),
|
|
||||||
((-1.0, 1.0, 1.0), (0.0, 0.0, 1.0), (0.0, 1.0)),
|
|
||||||
((-1.0, 1.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 1.0)),
|
|
||||||
((1.0, -1.0, 1.0), (0.0, -1.0, 0.0), (1.0, 1.0)),
|
|
||||||
((1.0, 1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0)),
|
|
||||||
((1.0, 1.0, -1.0), (0.0, 0.0, -1.0), (0.0, 1.0))
|
|
||||||
]
|
|
||||||
|
|
||||||
faces_by_normal = {
|
|
||||||
(-1.0, 0.0, 0.0): [6, 7, 8, 6, 20, 7],
|
|
||||||
(0.0, -1.0, 0.0): [9, 10, 11, 9, 21, 10],
|
|
||||||
(0.0, 0.0, -1.0): [15, 16, 17, 15, 23, 16],
|
|
||||||
(0.0, 0.0, 1.0): [3, 4, 5, 3, 19, 4],
|
|
||||||
(0.0, 1.0, 0.0): [0, 1, 2, 0, 18, 1],
|
|
||||||
(1.0, 0.0, 0.0): [12, 13, 14, 12, 22, 13]
|
|
||||||
}
|
|
||||||
|
|
||||||
normals = [
|
normals = [
|
||||||
(-1.0, 0.0, 0.0),
|
(-1.0, 0.0, 0.0),
|
||||||
@ -46,7 +13,9 @@ normals = [
|
|||||||
(1.0, 0.0, 0.0),
|
(1.0, 0.0, 0.0),
|
||||||
]
|
]
|
||||||
|
|
||||||
def build_configuration_index_buffers(f):
|
def build_configuration_index_buffers(f, faces_by_normal, index_buffer):
|
||||||
|
assert(set(normals) == set(faces_by_normal.keys()))
|
||||||
|
|
||||||
offset = 0
|
offset = 0
|
||||||
configuration_offsets = []
|
configuration_offsets = []
|
||||||
for configuration in range(64):
|
for configuration in range(64):
|
||||||
@ -58,6 +27,7 @@ def build_configuration_index_buffers(f):
|
|||||||
indices = faces_by_normal[normal]
|
indices = faces_by_normal[normal]
|
||||||
for index in indices:
|
for index in indices:
|
||||||
f.write(struct.pack("<B", index))
|
f.write(struct.pack("<B", index))
|
||||||
|
index_buffer.append(index)
|
||||||
offset += 1
|
offset += 1
|
||||||
|
|
||||||
for i, offset in enumerate(configuration_offsets):
|
for i, offset in enumerate(configuration_offsets):
|
||||||
@ -65,14 +35,49 @@ def build_configuration_index_buffers(f):
|
|||||||
if i % 8 == 7:
|
if i % 8 == 7:
|
||||||
print()
|
print()
|
||||||
|
|
||||||
def build_vertex_buffer(f):
|
def build_vertex_buffer(f, vertex_buffer):
|
||||||
for position, normal, texture in vertex_table:
|
for position, normal, texture in vertex_buffer:
|
||||||
position = vec3.mul(position, 0.5)
|
position = vec3.mul(position, 0.5)
|
||||||
f.write(struct.pack("<eeeeeeee", *position, *normal, *texture))
|
f.write(struct.pack("<eeeeeeee", *position, *normal, *texture))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def write_indices(f, index_buffer, start, count):
|
||||||
with open("configuration.idx", "wb") as f:
|
for i in range(count):
|
||||||
build_configuration_index_buffers(f)
|
f.write(struct.pack("<B", index_buffer[start + i]))
|
||||||
|
|
||||||
with open("per_vertex.vtx", "wb") as f:
|
def write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, path):
|
||||||
build_vertex_buffer(f)
|
index_start = len(index_buffer)
|
||||||
|
state = obj.parse_obj_from_filename(path)
|
||||||
|
obj_state.append_triangles(state, vertex_buffer, index_buffer, index_lookup)
|
||||||
|
index_count = len(index_buffer) - index_start
|
||||||
|
write_indices(f, index_buffer, index_start, index_count)
|
||||||
|
print(f"{index_start}, {index_count}, // {path}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
cube_index_buffer = []
|
||||||
|
cube_index_lookup = {}
|
||||||
|
|
||||||
|
vertex_buffer = []
|
||||||
|
index_buffer = []
|
||||||
|
index_lookup = {}
|
||||||
|
|
||||||
|
cube_state = obj.parse_obj_from_filename("cube.obj")
|
||||||
|
|
||||||
|
obj_state.append_triangles(cube_state, vertex_buffer, cube_index_buffer, cube_index_lookup)
|
||||||
|
cube_faces_by_normal = obj_state.build_faces_by_normal(vertex_buffer, cube_index_buffer)
|
||||||
|
|
||||||
|
with open("../configuration.idx", "wb") as f:
|
||||||
|
build_configuration_index_buffers(f, cube_faces_by_normal, index_buffer)
|
||||||
|
index_lookup = {}
|
||||||
|
write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, "tallgrass.obj")
|
||||||
|
index_lookup = {}
|
||||||
|
write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, "fence.obj")
|
||||||
|
index_lookup = {}
|
||||||
|
write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, "torch.obj")
|
||||||
|
index_lookup = {}
|
||||||
|
write_custom_obj(f, vertex_buffer, index_buffer, index_lookup, "wheat.obj")
|
||||||
|
|
||||||
|
with open("../per_vertex.vtx", "wb") as f:
|
||||||
|
build_vertex_buffer(f, vertex_buffer)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
36
minecraft/gen/wheat.obj
Normal file
36
minecraft/gen/wheat.obj
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Blender 5.0.0
|
||||||
|
# www.blender.org
|
||||||
|
o Cube
|
||||||
|
v -0.500000 -1.000000 -1.000000
|
||||||
|
v -0.500000 1.000000 -1.000000
|
||||||
|
v 1.000000 -1.000000 0.500000
|
||||||
|
v 1.000000 1.000000 0.500000
|
||||||
|
v 0.500000 1.000000 -1.000000
|
||||||
|
v 0.500000 -1.000000 -1.000000
|
||||||
|
v 0.500000 1.000000 1.000000
|
||||||
|
v 0.500000 -1.000000 1.000000
|
||||||
|
v 1.000000 1.000000 -0.500000
|
||||||
|
v 1.000000 -1.000000 -0.500000
|
||||||
|
v -1.000000 1.000000 -0.500000
|
||||||
|
v -1.000000 -1.000000 -0.500000
|
||||||
|
v -0.500000 1.000000 1.000000
|
||||||
|
v -0.500000 -1.000000 1.000000
|
||||||
|
v -1.000000 1.000000 0.500000
|
||||||
|
v -1.000000 -1.000000 0.500000
|
||||||
|
vn -0.0000 -0.0000 1.0000
|
||||||
|
vn 1.0000 -0.0000 -0.0000
|
||||||
|
vn -0.0000 -0.0000 -1.0000
|
||||||
|
vn -1.0000 -0.0000 -0.0000
|
||||||
|
vt 0.000000 -0.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt -0.000000 1.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
s 0
|
||||||
|
f 4/1/1 16/2/1 3/3/1
|
||||||
|
f 5/1/2 8/2/2 6/3/2
|
||||||
|
f 11/1/3 10/2/3 12/3/3
|
||||||
|
f 13/1/4 1/2/4 14/3/4
|
||||||
|
f 4/1/1 15/4/1 16/2/1
|
||||||
|
f 5/1/2 7/4/2 8/2/2
|
||||||
|
f 11/1/3 9/4/3 10/2/3
|
||||||
|
f 13/1/4 2/4/4 1/2/4
|
||||||
BIN
minecraft/global.lights.vtx
Normal file
BIN
minecraft/global.lights.vtx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 65 KiB |
18
shader/font.frag
Normal file
18
shader/font.frag
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
uniform sampler2D TextureSampler;
|
||||||
|
|
||||||
|
uniform vec2 Cell;
|
||||||
|
uniform vec2 Glyph;
|
||||||
|
|
||||||
|
out vec4 g_color;
|
||||||
|
|
||||||
|
in vec4 PixelTexture;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 sample = texture(TextureSampler, PixelTexture.xy * Cell + Cell * Glyph);
|
||||||
|
float px = sample.x == 0.0 ? 0.0 : 1.0;
|
||||||
|
|
||||||
|
g_color = vec4(vec3(px), 1.0);
|
||||||
|
}
|
||||||
39
shader/font.vert
Normal file
39
shader/font.vert
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
const vec2 vtx[4] = vec2[](vec2(-1.0, 1.0), // tl
|
||||||
|
vec2( 1.0, 1.0), // tr
|
||||||
|
vec2( 1.0, -1.0), // br
|
||||||
|
vec2(-1.0, -1.0)); // bl
|
||||||
|
|
||||||
|
/*
|
||||||
|
tl tr
|
||||||
|
br
|
||||||
|
|
||||||
|
0 1 2
|
||||||
|
tr tl br
|
||||||
|
1 0 2
|
||||||
|
|
||||||
|
tl
|
||||||
|
bl br
|
||||||
|
|
||||||
|
2 1 3
|
||||||
|
br tl bl
|
||||||
|
2 0 3
|
||||||
|
|
||||||
|
1 0 2 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
uniform mat4 Transform;
|
||||||
|
|
||||||
|
out vec4 PixelTexture;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 vertex = vtx[gl_VertexID];
|
||||||
|
|
||||||
|
PixelTexture = vec4(vertex * vec2(0.5, -0.5) + 0.5, 0, 0);
|
||||||
|
|
||||||
|
vertex = vertex * vec2(0.5, 0.5) + vec2(0.5, -0.5);
|
||||||
|
|
||||||
|
gl_Position = Transform * vec4(vertex, 0.0, 1.0);
|
||||||
|
}
|
||||||
40
shader/lighting.frag
Normal file
40
shader/lighting.frag
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
uniform sampler2D PositionSampler;
|
||||||
|
uniform sampler2D NormalSampler;
|
||||||
|
uniform sampler2D ColorSampler;
|
||||||
|
|
||||||
|
uniform float Linear;
|
||||||
|
uniform float Quadratic;
|
||||||
|
uniform vec3 Eye;
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 Color;
|
||||||
|
|
||||||
|
in vec4 PixelTexture;
|
||||||
|
|
||||||
|
layout (std140) uniform Lights
|
||||||
|
{
|
||||||
|
vec4 light[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 position = texture(PositionSampler, PixelTexture.xy);
|
||||||
|
vec4 normal = texture(NormalSampler, PixelTexture.xy);
|
||||||
|
vec4 color = texture(ColorSampler, PixelTexture.xy);
|
||||||
|
|
||||||
|
vec3 out_color = color.xyz * 0.1;
|
||||||
|
for (int i = 0; i < 82; i++) {
|
||||||
|
vec3 light_position = light[i].xzy;
|
||||||
|
float light_distance = length(light_position - position.xyz);
|
||||||
|
vec3 light_direction = normalize(light_position - position.xyz);
|
||||||
|
float diffuse = max(dot(normal.xyz, light_direction), 0.0);
|
||||||
|
//float attenuation = 1.0 / (1.0 + Linear * light_distance + Quadratic * light_distance * light_distance);
|
||||||
|
|
||||||
|
float attenuation = 1.0 / (1.0 + Quadratic * light_distance * light_distance);
|
||||||
|
out_color += color.xyz * attenuation * diffuse;
|
||||||
|
//out_color = vec3(diffuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color = vec4(out_color, 1.0);
|
||||||
|
}
|
||||||
13
shader/quad.frag
Normal file
13
shader/quad.frag
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
uniform sampler2D TextureSampler;
|
||||||
|
|
||||||
|
layout (location = 0) out vec4 Color;
|
||||||
|
|
||||||
|
in vec4 PixelTexture;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 sample = texture(TextureSampler, PixelTexture.xy);
|
||||||
|
Color = vec4(sample.xyz, 1.0);
|
||||||
|
}
|
||||||
17
shader/quad.vert
Normal file
17
shader/quad.vert
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
const vec2 vtx[4] = vec2[](vec2(-1.0, 1.0), // tl
|
||||||
|
vec2( 1.0, 1.0), // tr
|
||||||
|
vec2( 1.0, -1.0), // br
|
||||||
|
vec2(-1.0, -1.0)); // bl
|
||||||
|
|
||||||
|
out vec4 PixelTexture;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 vertex = vtx[gl_VertexID];
|
||||||
|
|
||||||
|
PixelTexture = vec4(vertex * 0.5 + 0.5, 0, 0);
|
||||||
|
|
||||||
|
gl_Position = vec4(vertex, 0.0, 1.0);
|
||||||
|
}
|
||||||
@ -1,40 +1,50 @@
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
|
|
||||||
in VS_OUT {
|
in VS_OUT {
|
||||||
|
vec3 Position; // world coordinates
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec2 Texture;
|
vec2 Texture;
|
||||||
flat int BlockID;
|
flat int BlockID;
|
||||||
|
flat int Data;
|
||||||
} fs_in;
|
} fs_in;
|
||||||
|
|
||||||
out vec4 FragColor;
|
layout (location = 0) out vec3 Position;
|
||||||
|
layout (location = 1) out vec3 Normal;
|
||||||
|
layout (location = 2) out vec3 Color;
|
||||||
|
|
||||||
uniform sampler2D TerrainSampler;
|
uniform sampler2D TerrainSampler;
|
||||||
|
|
||||||
int Textures[256] = int[256](
|
layout (std140) uniform TextureID
|
||||||
185, 1, 0, 2, 16, 4, 15, 17, 205, 205, 237, 237, 18, 19, 32, 33,
|
{
|
||||||
34, 20, 52, 48, 49, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 0,
|
ivec4 block_id_to_texture_id[256 / 4];
|
||||||
185, 185, 185, 64, 185, 13, 12, 29, 28, 39, 38, 5, 5, 7, 8, 35,
|
};
|
||||||
36, 37, 80, 31, 65, 4, 27, 84, 50, 40, 43, 88, 87, 44, 61, 185,
|
|
||||||
81, 83, 128, 16, 185, 96, 6, 82, 6, 51, 51, 115, 99, 185, 66, 67,
|
int wool[16] = int[16]( 64, // 0 64
|
||||||
66, 70, 72, 73, 74, 4, 102, 103, 104, 105, 14, 102, 185, 185, 185, 185,
|
210, // 32 208
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
194, // 32 192
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
178, // 32 176
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
162, // 32 160
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
146, // 32 144
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
130, // 32 128
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
114, // 32 112
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
225, // 16 224
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
209, // 16 208
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
|
193, // 16 192
|
||||||
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185
|
177, // 16 176
|
||||||
);
|
161, // 16 160
|
||||||
|
145, // 16 144
|
||||||
|
129, // 16 128
|
||||||
|
113 // 16 112
|
||||||
|
);
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 light_direction = normalize(vec3(-1, -0.5, 0.5));
|
int terrain_ix;
|
||||||
float diffuse_intensity = max(dot(normalize(fs_in.Normal), light_direction), 0.0);
|
if (fs_in.BlockID == 35) // cloth
|
||||||
|
terrain_ix = wool[fs_in.Data];
|
||||||
|
else
|
||||||
|
terrain_ix = block_id_to_texture_id[fs_in.BlockID / 4][fs_in.BlockID % 4];
|
||||||
|
|
||||||
int terrain_ix = int(Textures[int(fs_in.BlockID)]);
|
|
||||||
int terrain_x = terrain_ix % 16;
|
int terrain_x = terrain_ix % 16;
|
||||||
int terrain_y = terrain_ix / 16;
|
int terrain_y = terrain_ix / 16;
|
||||||
ivec2 coord = ivec2(terrain_x, terrain_y) * 16;
|
ivec2 coord = ivec2(terrain_x, terrain_y) * 16;
|
||||||
@ -46,11 +56,10 @@ void main()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (int(fs_in.BlockID) == 18) // leaves
|
if (fs_in.BlockID == 18 || fs_in.BlockID == 31) // leaves
|
||||||
texture_color.xyz *= vec3(0.125, 0.494, 0.027);
|
texture_color.xyz *= vec3(0.125, 0.494, 0.027);
|
||||||
|
|
||||||
if (diffuse_intensity < 0.1)
|
Position = fs_in.Position.xzy;
|
||||||
diffuse_intensity = 0.1;
|
Normal = normalize(fs_in.Normal.xzy);
|
||||||
|
Color = texture_color.xyz;
|
||||||
FragColor = vec4(texture_color.xyz * vec3(diffuse_intensity), 1.0);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,20 +7,27 @@ in vec2 Texture;
|
|||||||
// per-instance:
|
// per-instance:
|
||||||
in vec3 BlockPosition;
|
in vec3 BlockPosition;
|
||||||
in float BlockID;
|
in float BlockID;
|
||||||
|
in float Data;
|
||||||
|
|
||||||
out VS_OUT {
|
out VS_OUT {
|
||||||
|
vec3 Position;
|
||||||
vec3 Normal;
|
vec3 Normal;
|
||||||
vec2 Texture;
|
vec2 Texture;
|
||||||
flat int BlockID;
|
flat int BlockID;
|
||||||
|
flat int Data;
|
||||||
} vs_out;
|
} vs_out;
|
||||||
|
|
||||||
uniform mat4 Transform;
|
uniform mat4 Transform;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vs_out.Normal = Normal.xzy;
|
vec3 position = Position + BlockPosition; // world coordinates
|
||||||
|
|
||||||
|
vs_out.Position = position;
|
||||||
|
vs_out.Normal = Normal;
|
||||||
vs_out.Texture = Texture;
|
vs_out.Texture = Texture;
|
||||||
vs_out.BlockID = int(BlockID);
|
vs_out.BlockID = int(BlockID);
|
||||||
|
vs_out.Data = int(Data);
|
||||||
|
|
||||||
gl_Position = Transform * vec4((Position + BlockPosition).xzy, 1.0);
|
gl_Position = Transform * vec4(position.xzy, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
167
src/font.cpp
Normal file
167
src/font.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "directxmath/directxmath.h"
|
||||||
|
#include "glad/gl.h"
|
||||||
|
#include "opengl.h"
|
||||||
|
|
||||||
|
#include "font.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
namespace font {
|
||||||
|
|
||||||
|
struct location {
|
||||||
|
struct {
|
||||||
|
unsigned int transform;
|
||||||
|
unsigned int texture_sampler;
|
||||||
|
unsigned int cell;
|
||||||
|
unsigned int glyph;
|
||||||
|
} uniform;
|
||||||
|
};
|
||||||
|
|
||||||
|
static location location;
|
||||||
|
|
||||||
|
static unsigned int font_program = -1;
|
||||||
|
|
||||||
|
void load_shader()
|
||||||
|
{
|
||||||
|
unsigned int program = compile_from_files("shader/font.vert",
|
||||||
|
NULL, // geom
|
||||||
|
"shader/font.frag");
|
||||||
|
|
||||||
|
location.uniform.transform = glGetUniformLocation(program, "Transform");
|
||||||
|
location.uniform.texture_sampler = glGetUniformLocation(program, "TextureSampler");
|
||||||
|
location.uniform.cell = glGetUniformLocation(program, "Cell");
|
||||||
|
location.uniform.glyph = glGetUniformLocation(program, "Glyph");
|
||||||
|
printf("font program:\n");
|
||||||
|
printf(" uniforms:\n transform %u\n texture_sampler %u\n cell %u\n glyph %u\n",
|
||||||
|
location.uniform.transform,
|
||||||
|
location.uniform.texture_sampler,
|
||||||
|
location.uniform.cell,
|
||||||
|
location.uniform.glyph
|
||||||
|
);
|
||||||
|
|
||||||
|
font_program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
font load_font(font_desc const& desc)
|
||||||
|
{
|
||||||
|
unsigned int texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
int texture_data_size;
|
||||||
|
void * texture_data = read_file(desc.path, &texture_data_size);
|
||||||
|
assert(texture_data != nullptr);
|
||||||
|
|
||||||
|
int width = desc.texture_width;
|
||||||
|
int height = desc.texture_height;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, texture_data);
|
||||||
|
|
||||||
|
free(texture_data);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return (font){
|
||||||
|
.desc = &desc,
|
||||||
|
.texture = texture,
|
||||||
|
.stride = desc.texture_width / desc.glyph_width,
|
||||||
|
.cell = { (float)desc.glyph_width / (float)desc.texture_width,
|
||||||
|
(float)desc.glyph_height / (float)desc.texture_height },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int min(int a, int b)
|
||||||
|
{
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int best_font(font_desc const * const descs, int length)
|
||||||
|
{
|
||||||
|
int dimension = min(g_window_width, g_window_height);
|
||||||
|
int ideal_height = (16 * dimension) / 1024;
|
||||||
|
//printf("ideal_height: %d\n", ideal_height);
|
||||||
|
int nearest = dimension;
|
||||||
|
int nearest_ix = -1;
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
font_desc const& desc = descs[i];
|
||||||
|
int distance = abs(desc.glyph_height - ideal_height);
|
||||||
|
if (distance < nearest) {
|
||||||
|
nearest = distance;
|
||||||
|
nearest_ix = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(nearest_ix != -1);
|
||||||
|
//printf("selected %d\n", descs[nearest_ix].glyph_height);
|
||||||
|
return nearest_ix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_fonts(font * const fonts, font_desc const * const descs, int length)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
fonts[i] = load_font(descs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static XMFLOAT2 glyph_coordinate(font const& font, int ord)
|
||||||
|
{
|
||||||
|
int c = ord - 32;
|
||||||
|
int x = c % font.stride;
|
||||||
|
int y = c / font.stride;
|
||||||
|
XMVECTOR coord = XMVectorSet(x, y, 0, 0);
|
||||||
|
XMFLOAT2 coordf;
|
||||||
|
XMStoreFloat2(&coordf, coord);
|
||||||
|
return coordf;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static XMFLOAT4X4 glyph_transform(font const& font, int x, int y)
|
||||||
|
{
|
||||||
|
XMMATRIX transform =
|
||||||
|
XMMatrixScaling(font.desc->glyph_width, font.desc->glyph_height, 0)
|
||||||
|
* XMMatrixTranslation(x, -y, 0)
|
||||||
|
* XMMatrixScaling(2.0f / g_window_width, 2.0f / g_window_height, 0)
|
||||||
|
* XMMatrixTranslation(-1, 1, 0);
|
||||||
|
XMFLOAT4X4 transformf;
|
||||||
|
XMStoreFloat4x4(&transformf, transform);
|
||||||
|
return transformf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_start(font const& font, unsigned int vertex_array_object, unsigned int index_buffer)
|
||||||
|
{
|
||||||
|
glUseProgram(font_program);
|
||||||
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, font.texture);
|
||||||
|
|
||||||
|
glUniform1i(location.uniform.texture_sampler, 0);
|
||||||
|
glUniform2fv(location.uniform.cell, 1, (float *)&font.cell);
|
||||||
|
|
||||||
|
glBindVertexArray(vertex_array_object);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_string(font const& font, char const * const s, int x, int y)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (s[i] != 0) {
|
||||||
|
char c = s[i++];
|
||||||
|
if (!(c <= 0x20 || c > 0x7f)) {
|
||||||
|
XMFLOAT4X4 transform = glyph_transform(font, x, y);
|
||||||
|
glUniformMatrix4fv(location.uniform.transform, 1, GL_FALSE, (float *)&transform);
|
||||||
|
XMFLOAT2 glyph = glyph_coordinate(font, c);
|
||||||
|
glUniform2fv(location.uniform.glyph, 1, (float *)&glyph);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
x += font.desc->glyph_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/opengl.c
24
src/opengl.c
@ -7,8 +7,30 @@
|
|||||||
#include "glad/gl.h"
|
#include "glad/gl.h"
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
|
|
||||||
void * read_file(const char * filename, int * out_size)
|
char const * g_source_path = NULL;
|
||||||
|
int g_source_path_length = 0;
|
||||||
|
|
||||||
|
char const * join_path(char * buf, const char * filename)
|
||||||
{
|
{
|
||||||
|
if (filename[0] == '/')
|
||||||
|
return filename;
|
||||||
|
|
||||||
|
int filename_length = strlen(filename);
|
||||||
|
assert(filename_length + g_source_path_length + 2 < 1024);
|
||||||
|
|
||||||
|
memcpy(buf, g_source_path, g_source_path_length);
|
||||||
|
buf[g_source_path_length] = '/';
|
||||||
|
|
||||||
|
memcpy(&buf[g_source_path_length + 1], filename, filename_length);
|
||||||
|
buf[g_source_path_length + 1 + filename_length] = 0;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * read_file(const char * r_filename, int * out_size)
|
||||||
|
{
|
||||||
|
char tmp[1024];
|
||||||
|
char const * filename = join_path(tmp, r_filename);
|
||||||
|
|
||||||
FILE * f = fopen(filename, "rb");
|
FILE * f = fopen(filename, "rb");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
fprintf(stderr, "fopen(%s): %s\n", filename, strerror(errno));
|
fprintf(stderr, "fopen(%s): %s\n", filename, strerror(errno));
|
||||||
|
|||||||
656
src/test.cpp
656
src/test.cpp
@ -6,27 +6,58 @@
|
|||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
#include "directxmath/directxmath.h"
|
#include "directxmath/directxmath.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
#include "font.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
#include "data.inc"
|
#include "data.inc"
|
||||||
|
|
||||||
struct location {
|
struct test_location {
|
||||||
struct {
|
struct {
|
||||||
unsigned int position;
|
unsigned int position;
|
||||||
unsigned int normal;
|
unsigned int normal;
|
||||||
unsigned int texture;
|
unsigned int texture;
|
||||||
unsigned int block_position;
|
unsigned int block_position;
|
||||||
unsigned int block_id;
|
unsigned int block_id;
|
||||||
//unsigned int configuration;
|
unsigned int data;
|
||||||
} attrib;
|
} attrib;
|
||||||
struct {
|
struct {
|
||||||
unsigned int transform;
|
unsigned int transform;
|
||||||
unsigned int terrain_sampler;
|
unsigned int terrain_sampler;
|
||||||
|
|
||||||
|
unsigned int texture_id;
|
||||||
|
} uniform;
|
||||||
|
struct {
|
||||||
|
unsigned int texture_id;
|
||||||
|
} binding;
|
||||||
|
};
|
||||||
|
static unsigned int test_program;
|
||||||
|
static test_location test_location;
|
||||||
|
|
||||||
|
struct quad_location {
|
||||||
|
struct {
|
||||||
|
unsigned int texture_sampler;
|
||||||
} uniform;
|
} uniform;
|
||||||
};
|
};
|
||||||
|
static unsigned int quad_program;
|
||||||
|
static quad_location quad_location;
|
||||||
|
|
||||||
// state
|
struct lighting_location {
|
||||||
static unsigned int test_program;
|
struct {
|
||||||
static struct location location;
|
unsigned int position_sampler;
|
||||||
|
unsigned int normal_sampler;
|
||||||
|
unsigned int color_sampler;
|
||||||
|
unsigned int quadratic;
|
||||||
|
unsigned int linear;
|
||||||
|
unsigned int eye;
|
||||||
|
|
||||||
|
unsigned int lights;
|
||||||
|
} uniform;
|
||||||
|
struct {
|
||||||
|
unsigned int lights;
|
||||||
|
} binding;
|
||||||
|
};
|
||||||
|
static unsigned int lighting_program;
|
||||||
|
static lighting_location lighting_location;
|
||||||
|
|
||||||
struct char_tpl {
|
struct char_tpl {
|
||||||
const char * vtx;
|
const char * vtx;
|
||||||
@ -34,73 +65,147 @@ struct char_tpl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const int region_count = 4;
|
static const int region_count = 4;
|
||||||
static const char_tpl vertex_paths[region_count] = {
|
static const char_tpl vertex_paths[] = {
|
||||||
{ "minecraft/region.0.0.instance.vtx", "minecraft/region.0.0.instance.cfg" },
|
{ "minecraft/region.0.0.instance.vtx", "minecraft/region.0.0.instance.cfg" },
|
||||||
{ "minecraft/region.-1.0.instance.vtx", "minecraft/region.-1.0.instance.cfg" },
|
{ "minecraft/region.-1.0.instance.vtx", "minecraft/region.-1.0.instance.cfg" },
|
||||||
{ "minecraft/region.0.-1.instance.vtx", "minecraft/region.0.-1.instance.cfg" },
|
{ "minecraft/region.0.-1.instance.vtx", "minecraft/region.0.-1.instance.cfg" },
|
||||||
{ "minecraft/region.-1.-1.instance.vtx", "minecraft/region.-1.-1.instance.cfg" },
|
{ "minecraft/region.-1.-1.instance.vtx", "minecraft/region.-1.-1.instance.cfg" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int vertex_array_objects[region_count];
|
static unsigned int vertex_array_object;
|
||||||
static unsigned int vertex_buffers[region_count];
|
static unsigned int per_instance_vertex_buffers[region_count];
|
||||||
static unsigned int vertex_count[region_count];
|
|
||||||
static unsigned int index_buffer;
|
static unsigned int index_buffer;
|
||||||
static unsigned int per_vertex_buffer;
|
static unsigned int per_vertex_buffer;
|
||||||
|
|
||||||
static const int vertex_size = 8;
|
static const int vertex_size = 8;
|
||||||
static const int per_vertex_size = (3 + 3 + 2) * 2;
|
static const int per_vertex_size = (3 + 3 + 2) * 2;
|
||||||
|
|
||||||
|
// also update index_buffer_custom_offsets in data.inc
|
||||||
|
static const int custom_block_types = 4;
|
||||||
|
static const int instance_cfg_length = 64 + custom_block_types;
|
||||||
|
|
||||||
struct instance_cfg {
|
struct instance_cfg {
|
||||||
struct {
|
struct region_instance {
|
||||||
int instance_count;
|
int instance_count;
|
||||||
int offset;
|
int offset;
|
||||||
} cfg[64];
|
} cfg[instance_cfg_length];
|
||||||
};
|
};
|
||||||
|
|
||||||
static instance_cfg instance_cfg[region_count];
|
static instance_cfg instance_cfg[region_count];
|
||||||
|
|
||||||
void load_program()
|
static unsigned int empty_vertex_array_object = -1;
|
||||||
|
static unsigned int quad_index_buffer = -1;
|
||||||
|
|
||||||
|
void load_quad_index_buffer()
|
||||||
|
{
|
||||||
|
uint8_t const data[] = {
|
||||||
|
1, 0, 2, 3,
|
||||||
|
};
|
||||||
|
int const data_size = (sizeof (data));
|
||||||
|
|
||||||
|
glGenBuffers(1, &quad_index_buffer);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size, data, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &empty_vertex_array_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_test_program()
|
||||||
{
|
{
|
||||||
unsigned int program = compile_from_files("shader/test.vert",
|
unsigned int program = compile_from_files("shader/test.vert",
|
||||||
NULL, //"shader/test.geom",
|
NULL,
|
||||||
"shader/test.frag");
|
"shader/test.frag");
|
||||||
|
|
||||||
location.attrib.position = glGetAttribLocation(program, "Position");
|
test_location.attrib.position = glGetAttribLocation(program, "Position");
|
||||||
location.attrib.normal = glGetAttribLocation(program, "Normal");
|
test_location.attrib.normal = glGetAttribLocation(program, "Normal");
|
||||||
location.attrib.texture = glGetAttribLocation(program, "Texture");
|
test_location.attrib.texture = glGetAttribLocation(program, "Texture");
|
||||||
|
|
||||||
location.attrib.block_position = glGetAttribLocation(program, "BlockPosition");
|
test_location.attrib.block_position = glGetAttribLocation(program, "BlockPosition");
|
||||||
location.attrib.block_id = glGetAttribLocation(program, "BlockID");
|
test_location.attrib.block_id = glGetAttribLocation(program, "BlockID");
|
||||||
printf("attributes:\n position %u\n normal %u\n texture %u\n block_position %u\n block_id %u\n\n",
|
test_location.attrib.data = glGetAttribLocation(program, "Data");
|
||||||
location.attrib.position,
|
printf("test program:\n");
|
||||||
location.attrib.normal,
|
printf(" attributes:\n position %u\n normal %u\n texture %u\n block_position %u\n block_id %u\n block_id %u\n",
|
||||||
location.attrib.texture,
|
test_location.attrib.position,
|
||||||
location.attrib.block_position,
|
test_location.attrib.normal,
|
||||||
location.attrib.block_id);
|
test_location.attrib.texture,
|
||||||
|
test_location.attrib.block_position,
|
||||||
|
test_location.attrib.block_id,
|
||||||
|
test_location.attrib.data);
|
||||||
|
|
||||||
location.uniform.transform = glGetUniformLocation(program, "Transform");
|
test_location.uniform.transform = glGetUniformLocation(program, "Transform");
|
||||||
location.uniform.terrain_sampler = glGetUniformLocation(program, "TerrainSampler");
|
test_location.uniform.terrain_sampler = glGetUniformLocation(program, "TerrainSampler");
|
||||||
printf("uniforms:\n transform %u\n terrain_sampler %u\n",
|
test_location.uniform.texture_id = glGetUniformBlockIndex(program, "TextureID");
|
||||||
location.uniform.transform,
|
printf(" uniforms:\n transform %u\n terrain_sampler %u\n texture_id %u\n",
|
||||||
location.uniform.terrain_sampler);
|
test_location.uniform.transform,
|
||||||
|
test_location.uniform.terrain_sampler,
|
||||||
|
test_location.uniform.texture_id);
|
||||||
|
|
||||||
|
test_location.binding.texture_id = 0;
|
||||||
|
glUniformBlockBinding(program, test_location.uniform.texture_id, test_location.binding.texture_id);
|
||||||
|
|
||||||
test_program = program;
|
test_program = program;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_vertex_buffer(int i)
|
void load_quad_program()
|
||||||
|
{
|
||||||
|
unsigned int program = compile_from_files("shader/quad.vert",
|
||||||
|
NULL,
|
||||||
|
"shader/quad.frag");
|
||||||
|
|
||||||
|
quad_location.uniform.texture_sampler = glGetUniformLocation(program, "TextureSampler");
|
||||||
|
printf("quad program:\n");
|
||||||
|
printf(" uniforms:\n texture_sampler %u\n",
|
||||||
|
quad_location.uniform.texture_sampler);
|
||||||
|
|
||||||
|
quad_program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_lighting_program()
|
||||||
|
{
|
||||||
|
unsigned int program = compile_from_files("shader/quad.vert",
|
||||||
|
NULL,
|
||||||
|
"shader/lighting.frag");
|
||||||
|
|
||||||
|
lighting_location.uniform.position_sampler = glGetUniformLocation(program, "PositionSampler");
|
||||||
|
lighting_location.uniform.normal_sampler = glGetUniformLocation(program, "NormalSampler");
|
||||||
|
lighting_location.uniform.color_sampler = glGetUniformLocation(program, "ColorSampler");
|
||||||
|
lighting_location.uniform.quadratic = glGetUniformLocation(program, "Quadratic");
|
||||||
|
lighting_location.uniform.linear = glGetUniformLocation(program, "Linear");
|
||||||
|
lighting_location.uniform.eye = glGetUniformLocation(program, "Eye");
|
||||||
|
lighting_location.uniform.lights = glGetUniformBlockIndex(program, "Lights");
|
||||||
|
|
||||||
|
fprintf(stderr, "lighting program:\n");
|
||||||
|
fprintf(stderr, " uniforms:\n position_sampler %u normal_sampler %u color_sampler %u lights %u\n",
|
||||||
|
lighting_location.uniform.position_sampler,
|
||||||
|
lighting_location.uniform.normal_sampler,
|
||||||
|
lighting_location.uniform.color_sampler,
|
||||||
|
lighting_location.uniform.lights);
|
||||||
|
|
||||||
|
lighting_location.binding.lights = 0;
|
||||||
|
glUniformBlockBinding(program, lighting_location.uniform.lights, lighting_location.binding.lights);
|
||||||
|
|
||||||
|
lighting_program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_per_instance_vertex_buffer(int i)
|
||||||
{
|
{
|
||||||
int vertex_buffer_data_size;
|
int vertex_buffer_data_size;
|
||||||
void * vertex_buffer_data = read_file(vertex_paths[i].vtx, &vertex_buffer_data_size);
|
void * vertex_buffer_data = read_file(vertex_paths[i].vtx, &vertex_buffer_data_size);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers[i]);
|
glBindBuffer(GL_ARRAY_BUFFER, per_instance_vertex_buffers[i]);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW);
|
||||||
vertex_count[i] = vertex_buffer_data_size / vertex_size;
|
|
||||||
|
|
||||||
free(vertex_buffer_data);
|
free(vertex_buffer_data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_per_vertex_buffer()
|
void load_per_vertex_buffer()
|
||||||
{
|
{
|
||||||
|
glGenBuffers(1, &per_vertex_buffer);
|
||||||
|
|
||||||
int vertex_buffer_data_size;
|
int vertex_buffer_data_size;
|
||||||
void * vertex_buffer_data = read_file("minecraft/per_vertex.vtx", &vertex_buffer_data_size);
|
void * vertex_buffer_data = read_file("minecraft/per_vertex.vtx", &vertex_buffer_data_size);
|
||||||
|
|
||||||
@ -108,10 +213,14 @@ void load_per_vertex_buffer()
|
|||||||
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW);
|
||||||
|
|
||||||
free(vertex_buffer_data);
|
free(vertex_buffer_data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_index_buffer()
|
void load_index_buffer()
|
||||||
{
|
{
|
||||||
|
glGenBuffers(1, &index_buffer);
|
||||||
|
|
||||||
int index_buffer_data_size;
|
int index_buffer_data_size;
|
||||||
void * index_buffer_data = read_file("minecraft/configuration.idx", &index_buffer_data_size);
|
void * index_buffer_data = read_file("minecraft/configuration.idx", &index_buffer_data_size);
|
||||||
|
|
||||||
@ -119,94 +228,145 @@ void load_index_buffer()
|
|||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_data_size, index_buffer_data, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_data_size, index_buffer_data, GL_STATIC_DRAW);
|
||||||
|
|
||||||
free(index_buffer_data);
|
free(index_buffer_data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_vertex_attributes(int i)
|
void load_test_vertex_attributes()
|
||||||
{
|
{
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, per_vertex_buffer);
|
glGenVertexArrays(1, &vertex_array_object);
|
||||||
|
glBindVertexArray(vertex_array_object);
|
||||||
|
|
||||||
glVertexAttribPointer(location.attrib.position,
|
glVertexBindingDivisor(0, 0);
|
||||||
3,
|
glVertexBindingDivisor(1, 1);
|
||||||
GL_HALF_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
per_vertex_size,
|
|
||||||
(void*)(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
glVertexAttribPointer(location.attrib.normal,
|
glEnableVertexAttribArray(test_location.attrib.position);
|
||||||
3,
|
glVertexAttribFormat(test_location.attrib.position, 3, GL_HALF_FLOAT, GL_FALSE, 0);
|
||||||
GL_HALF_FLOAT,
|
glVertexAttribBinding(test_location.attrib.position, 0);
|
||||||
GL_FALSE,
|
|
||||||
per_vertex_size,
|
|
||||||
(void*)(6)
|
|
||||||
);
|
|
||||||
|
|
||||||
glVertexAttribPointer(location.attrib.texture,
|
glEnableVertexAttribArray(test_location.attrib.normal);
|
||||||
2,
|
glVertexAttribFormat(test_location.attrib.normal, 3, GL_HALF_FLOAT, GL_FALSE, 6);
|
||||||
GL_HALF_FLOAT,
|
glVertexAttribBinding(test_location.attrib.normal, 0);
|
||||||
GL_FALSE,
|
|
||||||
per_vertex_size,
|
|
||||||
(void*)(12)
|
|
||||||
);
|
|
||||||
glEnableVertexAttribArray(location.attrib.position);
|
|
||||||
glEnableVertexAttribArray(location.attrib.normal);
|
|
||||||
glEnableVertexAttribArray(location.attrib.texture);
|
|
||||||
glVertexAttribDivisor(location.attrib.position, 0);
|
|
||||||
glVertexAttribDivisor(location.attrib.normal, 0);
|
|
||||||
glVertexAttribDivisor(location.attrib.texture, 0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers[i]);
|
glEnableVertexAttribArray(test_location.attrib.texture);
|
||||||
|
glVertexAttribFormat(test_location.attrib.texture, 2, GL_HALF_FLOAT, GL_FALSE, 12);
|
||||||
|
glVertexAttribBinding(test_location.attrib.texture, 0);
|
||||||
|
|
||||||
glVertexAttribPointer(location.attrib.block_position,
|
glEnableVertexAttribArray(test_location.attrib.block_position);
|
||||||
3,
|
glVertexAttribFormat(test_location.attrib.block_position, 3, GL_SHORT, GL_FALSE, 0);
|
||||||
GL_SHORT,
|
glVertexAttribBinding(test_location.attrib.block_position, 1);
|
||||||
GL_FALSE,
|
|
||||||
vertex_size,
|
glEnableVertexAttribArray(test_location.attrib.block_id);
|
||||||
(void*)(0)
|
glVertexAttribFormat(test_location.attrib.block_id, 1, GL_UNSIGNED_BYTE, GL_FALSE, 6);
|
||||||
);
|
glVertexAttribBinding(test_location.attrib.block_id, 1);
|
||||||
glVertexAttribPointer(location.attrib.block_id,
|
|
||||||
1,
|
glEnableVertexAttribArray(test_location.attrib.data);
|
||||||
GL_UNSIGNED_BYTE,
|
glVertexAttribFormat(test_location.attrib.data, 1, GL_UNSIGNED_BYTE, GL_FALSE, 7);
|
||||||
GL_FALSE,
|
glVertexAttribBinding(test_location.attrib.data, 1);
|
||||||
vertex_size,
|
|
||||||
(void*)(6)
|
glBindVertexArray(0);
|
||||||
);
|
|
||||||
glEnableVertexAttribArray(location.attrib.block_position);
|
|
||||||
glEnableVertexAttribArray(location.attrib.block_id);
|
|
||||||
glVertexAttribDivisor(location.attrib.block_position, 1);
|
|
||||||
glVertexAttribDivisor(location.attrib.block_id, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_instance_cfg(int i)
|
void load_instance_cfg(int i)
|
||||||
{
|
{
|
||||||
int data_size;
|
int data_size;
|
||||||
void * data = read_file(vertex_paths[i].cfg, &data_size);
|
void * data = read_file(vertex_paths[i].cfg, &data_size);
|
||||||
assert(data_size == 512);
|
assert(data_size == (sizeof (struct instance_cfg)));
|
||||||
|
|
||||||
memcpy(&instance_cfg[i], data, data_size);
|
memcpy(&instance_cfg[i], data, data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct target_name {
|
||||||
|
enum {
|
||||||
|
POSITION = 0,
|
||||||
|
NORMAL = 1,
|
||||||
|
COLOR = 2,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int render_target_count>
|
||||||
|
struct geometry_buffer {
|
||||||
|
unsigned int framebuffer;
|
||||||
|
unsigned int target[render_target_count]; // textures
|
||||||
|
unsigned int renderbuffer;
|
||||||
|
int initialized;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct target_type {
|
||||||
|
GLint internal_format;
|
||||||
|
GLenum attachment;
|
||||||
|
};
|
||||||
|
|
||||||
|
static geometry_buffer<3> geometry_buffer_pnc = {};
|
||||||
|
static target_type const geometry_buffer_pnc_types[3] = {
|
||||||
|
[target_name::POSITION] = { GL_RGBA16F, GL_COLOR_ATTACHMENT0 },
|
||||||
|
[target_name::NORMAL] = { GL_RGBA16F, GL_COLOR_ATTACHMENT1 },
|
||||||
|
[target_name::COLOR] = { GL_RGBA8, GL_COLOR_ATTACHMENT2 },
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int render_target_count>
|
||||||
|
void init_geometry_buffer(geometry_buffer<render_target_count>& geometry_buffer, target_type const * const types)
|
||||||
|
{
|
||||||
|
int width = g_window_width;
|
||||||
|
int height = g_window_height;
|
||||||
|
|
||||||
|
if ((geometry_buffer.initialized == 1) && (width == geometry_buffer.width) && (height == geometry_buffer.height)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geometry_buffer.initialized) {
|
||||||
|
glDeleteFramebuffers(1, &geometry_buffer.framebuffer);
|
||||||
|
glDeleteTextures(render_target_count, geometry_buffer.target);
|
||||||
|
glDeleteRenderbuffers(1, &geometry_buffer.renderbuffer);
|
||||||
|
}
|
||||||
|
glGenFramebuffers(1, &geometry_buffer.framebuffer);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, geometry_buffer.framebuffer);
|
||||||
|
|
||||||
|
glGenTextures(render_target_count, geometry_buffer.target);
|
||||||
|
for (int i = 0; i < render_target_count; i++) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, geometry_buffer.target[i]);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, types[i].internal_format, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, types[i].attachment, GL_TEXTURE_2D, geometry_buffer.target[i], 0);
|
||||||
|
}
|
||||||
|
static_assert(render_target_count == 3);
|
||||||
|
GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
|
||||||
|
glDrawBuffers(3, attachments); // bound to GL_DRAW_FRAMEBUFFER
|
||||||
|
|
||||||
|
glGenRenderbuffers(1, &geometry_buffer.renderbuffer);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, geometry_buffer.renderbuffer);
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
|
||||||
|
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, geometry_buffer.renderbuffer);
|
||||||
|
|
||||||
|
assert(glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
geometry_buffer.initialized = 1;
|
||||||
|
geometry_buffer.width = width;
|
||||||
|
geometry_buffer.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
void load_buffers()
|
void load_buffers()
|
||||||
{
|
{
|
||||||
|
load_test_vertex_attributes();
|
||||||
|
|
||||||
// per-vertex buffer
|
// per-vertex buffer
|
||||||
glGenBuffers(1, &per_vertex_buffer);
|
|
||||||
load_per_vertex_buffer();
|
load_per_vertex_buffer();
|
||||||
|
|
||||||
// per-instance buffer
|
// per-instance buffer
|
||||||
glGenVertexArrays(region_count, vertex_array_objects);
|
glGenBuffers(region_count, per_instance_vertex_buffers);
|
||||||
glGenBuffers(region_count, vertex_buffers);
|
|
||||||
|
|
||||||
for (int i = 0; i < region_count; i++) {
|
for (int i = 0; i < region_count; i++) {
|
||||||
glBindVertexArray(vertex_array_objects[i]);
|
load_per_instance_vertex_buffer(i);
|
||||||
|
|
||||||
load_vertex_buffer(i);
|
|
||||||
load_vertex_attributes(i);
|
|
||||||
load_instance_cfg(i);
|
load_instance_cfg(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// index buffer
|
// index buffer
|
||||||
|
|
||||||
glGenBuffers(1, &index_buffer);
|
|
||||||
load_index_buffer();
|
load_index_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,54 +391,144 @@ void load_textures()
|
|||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
|
||||||
|
|
||||||
free(texture_data);
|
free(texture_data);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int textures_ubo;
|
static unsigned int light_uniform_buffer;
|
||||||
|
static unsigned int texture_id_uniform_buffer;
|
||||||
|
|
||||||
void load_texture_shader_storage()
|
unsigned int load_uniform_buffer(char const * const path)
|
||||||
{
|
{
|
||||||
unsigned int buffer;
|
unsigned int buffer;
|
||||||
glGenBuffers(1, &buffer);
|
glGenBuffers(1, &buffer);
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
|
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
|
||||||
|
|
||||||
int textures_data_size;
|
int data_size;
|
||||||
void * textures_data = read_file("minecraft/block_id_to_texture_id.data", &textures_data_size);
|
void * data = read_file(path, &data_size);
|
||||||
assert(textures_data != NULL);
|
assert(data != NULL);
|
||||||
|
|
||||||
glBufferData(GL_UNIFORM_BUFFER, textures_data_size, textures_data, GL_STATIC_DRAW);
|
glBufferData(GL_UNIFORM_BUFFER, data_size, data, GL_STATIC_DRAW);
|
||||||
free(textures_data);
|
free(data);
|
||||||
|
|
||||||
textures_ubo = buffer;
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_light_uniform_buffer()
|
||||||
|
{
|
||||||
|
light_uniform_buffer = load_uniform_buffer("minecraft/global.lights.vtx");
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_texture_id_uniform_buffer()
|
||||||
|
{
|
||||||
|
texture_id_uniform_buffer = load_uniform_buffer("minecraft/block_id_to_texture_id.data");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void * SDL_GL_GetProcAddress(const char *proc);
|
void * SDL_GL_GetProcAddress(const char *proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load()
|
struct view_state {
|
||||||
|
XMVECTOR up;
|
||||||
|
XMVECTOR eye;
|
||||||
|
XMVECTOR forward;
|
||||||
|
XMVECTOR direction;
|
||||||
|
float fov;
|
||||||
|
float pitch;
|
||||||
|
};
|
||||||
|
|
||||||
|
view_state view_state;
|
||||||
|
|
||||||
|
font::font * terminus_fonts;
|
||||||
|
|
||||||
|
void load(const char * source_path)
|
||||||
{
|
{
|
||||||
|
g_source_path_length = strlen(source_path);
|
||||||
|
assert(source_path[g_source_path_length - 1] != '/');
|
||||||
|
g_source_path = source_path;
|
||||||
|
|
||||||
fprintf(stderr, "getproc %p\n", SDL_GL_GetProcAddress);
|
fprintf(stderr, "getproc %p\n", SDL_GL_GetProcAddress);
|
||||||
gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress);
|
gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress);
|
||||||
|
|
||||||
load_program();
|
load_test_program();
|
||||||
load_buffers();
|
load_buffers();
|
||||||
load_textures();
|
load_textures();
|
||||||
//load_texture_shader_storage();
|
load_texture_id_uniform_buffer();
|
||||||
|
|
||||||
//unsigned int textures_layout = glGetUniformBlockIndex(test_program, "TexturesLayout");
|
view_state.up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
//glUniformBlockBinding(test_program, textures_layout, 0);
|
view_state.eye = XMVectorSet(-55.5f, 48.25f, 50.0f, 1);
|
||||||
//printf("textures_layout %d\n", textures_layout);
|
view_state.forward = XMVectorSet(-0.63, 0.78, 0, 0);
|
||||||
|
view_state.direction = view_state.forward;
|
||||||
|
view_state.pitch = -0.11;
|
||||||
|
|
||||||
|
view_state.fov = 1.5;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// font
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
font::load_shader();
|
||||||
|
|
||||||
|
terminus_fonts = (font::font *)malloc((sizeof (font::font)) * font::terminus_length);
|
||||||
|
font::load_fonts(terminus_fonts, font::terminus, font::terminus_length);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// quad
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
load_quad_program();
|
||||||
|
load_quad_index_buffer();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// lighting
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
load_lighting_program();
|
||||||
|
load_light_uniform_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
static float vx = 0.0;
|
float _ry = 0.0;
|
||||||
static float vy = 0.0;
|
|
||||||
static float vz = 0.0;
|
|
||||||
|
|
||||||
void update(float lx, float ly, float ry)
|
struct light_parameters {
|
||||||
|
float quadratic;
|
||||||
|
float linear;
|
||||||
|
};
|
||||||
|
light_parameters lighting = {
|
||||||
|
.quadratic = 1.0,
|
||||||
|
.linear = 1.0
|
||||||
|
};
|
||||||
|
|
||||||
|
void update(float lx, float ly, float rx, float ry, float tl, float tr,
|
||||||
|
int up, int down, int left, int right,
|
||||||
|
int a, int b, int x, int y)
|
||||||
{
|
{
|
||||||
vx += 2.5 * lx;
|
//view_state.yaw += rx;
|
||||||
vy += -2.5 * ry;
|
XMMATRIX mrz = XMMatrixRotationZ(rx * -0.035);
|
||||||
vz += -2.5 * ly;
|
|
||||||
|
view_state.forward = XMVector3Transform(XMVector3NormalizeEst(view_state.forward), mrz);
|
||||||
|
XMVECTOR normal = XMVector3NormalizeEst(XMVector3Cross(view_state.forward, view_state.up));
|
||||||
|
|
||||||
|
view_state.pitch += ry * -0.035;
|
||||||
|
if (view_state.pitch > 1.57f) view_state.pitch = 1.57f;
|
||||||
|
if (view_state.pitch < -1.57f) view_state.pitch = -1.57f;
|
||||||
|
|
||||||
|
XMMATRIX mrn = XMMatrixRotationAxis(normal, view_state.pitch);
|
||||||
|
view_state.direction = XMVector3Transform(view_state.forward, mrn);
|
||||||
|
|
||||||
|
view_state.eye += view_state.forward * -ly + normal * lx + view_state.up * (tl - tr);
|
||||||
|
|
||||||
|
float new_fov = view_state.fov + 0.01 * up + -0.01 * down;
|
||||||
|
if (new_fov > 0.00001f) {
|
||||||
|
view_state.fov = new_fov;
|
||||||
|
}
|
||||||
|
lighting.quadratic += 0.01 * a + -0.01 * b;
|
||||||
|
if (lighting.quadratic < 0.0f)
|
||||||
|
lighting.quadratic = 0.0f;
|
||||||
|
lighting.linear += 0.01 * x + -0.01 * y;
|
||||||
|
if (lighting.linear < 0.0f)
|
||||||
|
lighting.linear = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int popcount(int x)
|
static inline int popcount(int x)
|
||||||
@ -286,45 +536,107 @@ static inline int popcount(int x)
|
|||||||
return __builtin_popcount(x);
|
return __builtin_popcount(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw()
|
template <typename T>
|
||||||
|
void labeled_value(char * const buf, char const * const label, char const * const format, T value)
|
||||||
{
|
{
|
||||||
XMVECTOR eye = XMVectorSet(vx + -50.0f, vz + -50.0f, vy + 150.0f, 0.0f);
|
const int label_length = strlen(label);
|
||||||
XMVECTOR at = XMVectorSet(vx + 50.0f, vz + 50.0f, vy + 50.0f, 0.0f);
|
memcpy(buf, label, label_length);
|
||||||
XMVECTOR up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
|
int len = snprintf(&buf[label_length], 511 - label_length, format, value);
|
||||||
XMMATRIX view = XMMatrixLookAtRH(eye, at, up);
|
buf[label_length + len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
float fov_angle_y = XMConvertToRadians(45 * 0.75);
|
inline static float draw_vector(font::font const& ter_best, char * const buf, float y, char const * const label, XMVECTOR vec)
|
||||||
float aspect_ratio = 1.0;
|
{
|
||||||
|
labeled_value<float>(buf, label, ".x: %.2f", XMVectorGetX(vec));
|
||||||
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
y += ter_best.desc->glyph_height;
|
||||||
|
labeled_value<float>(buf, label, ".y: %.2f", XMVectorGetY(vec));
|
||||||
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
y += ter_best.desc->glyph_height;
|
||||||
|
labeled_value<float>(buf, label, ".z: %.2f", XMVectorGetZ(vec));
|
||||||
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
y += ter_best.desc->glyph_height;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_hud()
|
||||||
|
{
|
||||||
|
char buf[512];
|
||||||
|
|
||||||
|
float y = 10.0f;
|
||||||
|
|
||||||
|
int font_ix = font::best_font(font::terminus, font::terminus_length);
|
||||||
|
font::font const& ter_best = terminus_fonts[font_ix];
|
||||||
|
|
||||||
|
font::draw_start(ter_best, empty_vertex_array_object, quad_index_buffer);
|
||||||
|
|
||||||
|
labeled_value<float>(buf, "fov: ", "%.3f", view_state.fov);
|
||||||
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
y += ter_best.desc->glyph_height;
|
||||||
|
|
||||||
|
labeled_value<int>(buf, "font_height: ", "%d", ter_best.desc->glyph_height);
|
||||||
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
y += ter_best.desc->glyph_height;
|
||||||
|
|
||||||
|
labeled_value<float>(buf, "lighting.quadratic: ", "%.2f", lighting.quadratic);
|
||||||
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
y += ter_best.desc->glyph_height;
|
||||||
|
|
||||||
|
labeled_value<float>(buf, "lighting.linear: ", "%.2f", lighting.linear);
|
||||||
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
y += ter_best.desc->glyph_height;
|
||||||
|
|
||||||
|
y = draw_vector(ter_best, buf, y, "eye", view_state.eye);
|
||||||
|
y = draw_vector(ter_best, buf, y, "forward", view_state.forward);
|
||||||
|
|
||||||
|
labeled_value<float>(buf, "pitch: ", "%.9f", view_state.pitch);
|
||||||
|
font::draw_string(ter_best, buf, 10, y);
|
||||||
|
y += ter_best.desc->glyph_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_minecraft()
|
||||||
|
{
|
||||||
|
// possibly re-initialize geometry buffer if window width/height changes
|
||||||
|
init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types);
|
||||||
|
|
||||||
|
XMVECTOR at = XMVectorAdd(view_state.eye, view_state.direction);
|
||||||
|
XMMATRIX view = XMMatrixLookAtRH(view_state.eye, at, view_state.up);
|
||||||
|
|
||||||
|
float fov_angle_y = XMConvertToRadians(45 * view_state.fov);
|
||||||
|
float aspect_ratio = g_window_width / g_window_height;
|
||||||
float near_z = 1.0;
|
float near_z = 1.0;
|
||||||
float far_z = 0.1;
|
float far_z = 0.1;
|
||||||
XMMATRIX projection = XMMatrixPerspectiveFovRH(fov_angle_y, aspect_ratio, near_z, far_z);
|
XMMATRIX projection = XMMatrixPerspectiveFovRH(fov_angle_y, aspect_ratio, near_z, far_z);
|
||||||
XMMATRIX transform = view * projection;
|
XMMATRIX transform = view * projection;
|
||||||
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
|
|
||||||
glClearDepth(-1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
glUseProgram(test_program);
|
glUseProgram(test_program);
|
||||||
|
|
||||||
|
glBlendFunc(GL_ONE, GL_ZERO);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_GREATER);
|
glDepthFunc(GL_GREATER);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
glUniformMatrix4fv(location.uniform.transform, 1, false, (float *)&transform);
|
glUniformMatrix4fv(test_location.uniform.transform, 1, false, (float *)&transform);
|
||||||
glUniform1i(location.uniform.terrain_sampler, 0);
|
glUniform1i(test_location.uniform.terrain_sampler, 0);
|
||||||
|
|
||||||
//glBindBuffer(GL_UNIFORM_BUFFER, textures_ubo);
|
glBindBufferBase(GL_UNIFORM_BUFFER, test_location.binding.texture_id, texture_id_uniform_buffer);
|
||||||
//glBindBufferBase(GL_UNIFORM_BUFFER, 0, textures_ubo);
|
|
||||||
|
|
||||||
//glEnable(GL_CULL_FACE);
|
//glEnable(GL_CULL_FACE);
|
||||||
//glCullFace(GL_FRONT);
|
//glCullFace(GL_FRONT);
|
||||||
//glFrontFace(GL_CCW);
|
//glFrontFace(GL_CCW);
|
||||||
|
|
||||||
|
glBindVertexArray(vertex_array_object);
|
||||||
|
glBindVertexBuffer(0, per_vertex_buffer, 0, per_vertex_size);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
|
||||||
|
|
||||||
for (int region_index = 0; region_index < region_count; region_index++) {
|
for (int region_index = 0; region_index < region_count; region_index++) {
|
||||||
glBindVertexArray(vertex_array_objects[region_index]);
|
glBindVertexBuffer(1, per_instance_vertex_buffers[region_index], 0, vertex_size);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// cube blocks
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
for (int configuration = 1; configuration < 64; configuration++) {
|
for (int configuration = 1; configuration < 64; configuration++) {
|
||||||
int element_count = 6 * popcount(configuration);
|
int element_count = 6 * popcount(configuration);
|
||||||
const void * indices = (void *)((ptrdiff_t)index_buffer_configuration_offsets[configuration]); // index into configuration.idx
|
const void * indices = (void *)((ptrdiff_t)index_buffer_configuration_offsets[configuration]); // index into configuration.idx
|
||||||
@ -337,5 +649,91 @@ void draw()
|
|||||||
|
|
||||||
glDrawElementsInstancedBaseInstance(GL_TRIANGLES, element_count, GL_UNSIGNED_BYTE, indices, instance_count, base_instance);
|
glDrawElementsInstancedBaseInstance(GL_TRIANGLES, element_count, GL_UNSIGNED_BYTE, indices, instance_count, base_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// custom blocks
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
for (int i = 0; i < custom_block_types; i++) {
|
||||||
|
int element_count = index_buffer_custom_offsets[i].count;
|
||||||
|
const void * indices = (void *)((ptrdiff_t)index_buffer_custom_offsets[i].offset);
|
||||||
|
int instance_count = instance_cfg[region_index].cfg[64 + i].instance_count;
|
||||||
|
int base_instance = instance_cfg[region_index].cfg[64 + i].offset / vertex_size; // index into region.0.0.instance.vtx
|
||||||
|
if (instance_count == 0)
|
||||||
|
continue;
|
||||||
|
glDrawElementsInstancedBaseInstance(GL_TRIANGLES, element_count, GL_UNSIGNED_BYTE, indices, instance_count, base_instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_quad()
|
||||||
|
{
|
||||||
|
glUseProgram(quad_program);
|
||||||
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, geometry_buffer_pnc.target[1]);
|
||||||
|
|
||||||
|
glUniform1i(quad_location.uniform.texture_sampler, 0);
|
||||||
|
|
||||||
|
glBindVertexArray(empty_vertex_array_object);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool near_zero(float a)
|
||||||
|
{
|
||||||
|
return (fabsf(a) < 0.00001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_lighting()
|
||||||
|
{
|
||||||
|
glUseProgram(lighting_program);
|
||||||
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, geometry_buffer_pnc.target[0]);
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, geometry_buffer_pnc.target[1]);
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, geometry_buffer_pnc.target[2]);
|
||||||
|
|
||||||
|
glUniform1i(lighting_location.uniform.position_sampler, 0);
|
||||||
|
glUniform1i(lighting_location.uniform.normal_sampler, 1);
|
||||||
|
glUniform1i(lighting_location.uniform.color_sampler, 2);
|
||||||
|
|
||||||
|
float quadratic = near_zero(lighting.quadratic) ? 0.0 : 1.0f / lighting.quadratic;
|
||||||
|
float linear = near_zero(lighting.linear) ? 0.0 : 1.0f / lighting.linear;
|
||||||
|
glUniform1f(lighting_location.uniform.quadratic, quadratic);
|
||||||
|
glUniform1f(lighting_location.uniform.linear, linear);
|
||||||
|
|
||||||
|
|
||||||
|
XMFLOAT3 eye;
|
||||||
|
XMStoreFloat3(&eye, view_state.eye);
|
||||||
|
glUniform3fv(lighting_location.uniform.eye, 1, (float*)&eye);
|
||||||
|
|
||||||
|
glBindBufferBase(GL_UNIFORM_BUFFER, lighting_location.binding.lights, light_uniform_buffer);
|
||||||
|
|
||||||
|
glBindVertexArray(empty_vertex_array_object);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_index_buffer);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw()
|
||||||
|
{
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
glClearDepth(-1.0f);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, geometry_buffer_pnc.framebuffer);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
draw_minecraft();
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
draw_lighting();
|
||||||
|
//draw_quad();
|
||||||
|
draw_hud();
|
||||||
|
}
|
||||||
|
|||||||
10
src/window.cpp
Normal file
10
src/window.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
float g_window_width = 1;
|
||||||
|
float g_window_height = 1;
|
||||||
|
|
||||||
|
void update_window(int width, int height)
|
||||||
|
{
|
||||||
|
g_window_width = width;
|
||||||
|
g_window_height = height;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user