Skip to content

Commit 646b6dc

Browse files
committed
something works!
1 parent add4bdb commit 646b6dc

File tree

3 files changed

+86
-24
lines changed

3 files changed

+86
-24
lines changed

src/hexdoc/graphics/render.py

+55-22
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
from __future__ import annotations
44

5+
import math
56
from dataclasses import dataclass
67
from pathlib import Path
78
from typing import Any
89

910
import importlib_resources as resources
11+
import moderngl
1012
import moderngl_window as mglw
1113
import numpy as np
1214
from moderngl import Context, Uniform
@@ -28,19 +30,21 @@
2830
LIGHT_UP = 0.98
2931
LIGHT_LEFT = 0.8
3032
LIGHT_RIGHT = 0.608
31-
32-
FACE_ORDER = list[FaceName](["south", "east", "down", "west", "north", "up"])
33+
LIGHT_BACK = 0.25
3334

3435

3536
@dataclass
3637
class BlockRenderer:
3738
loader: ModResourceLoader
3839

3940
def __post_init__(self):
40-
self.window = HeadlessWindow()
41-
self.config = BlockRendererConfig(ctx=self.window.ctx, wnd=self.window)
41+
self.window = HeadlessWindow(
42+
size=(300, 300),
43+
)
4244

45+
self.config = BlockRendererConfig(ctx=self.window.ctx, wnd=self.window)
4346
self.window.config = self.config
47+
4448
self.window.swap_buffers()
4549
self.window.set_default_viewport()
4650

@@ -110,12 +114,7 @@ def __init__(self, ctx: Context, wnd: HeadlessWindow):
110114
)
111115
self.uniform("m_proj").write(self.projection)
112116

113-
self.camera = Matrix44.look_at(
114-
eye=(256, 64, 16),
115-
target=(0, 0, 16),
116-
up=(0, 1, 0),
117-
dtype="f4",
118-
)
117+
self.camera = pitch_yaw_camera(30, -135)
119118
self.uniform("m_camera").write(self.camera)
120119

121120
# TODO: implement animations
@@ -134,13 +133,15 @@ def render_block(
134133
textures = dict[str, int]()
135134
for i, (name, info) in enumerate(texture_vars.items()):
136135
textures[name] = i
137-
self.load_texture_array(
136+
texture = self.load_texture_array(
138137
path=str(info.image_path),
139138
layers=info.layers,
140-
).use(i)
139+
)
140+
texture.filter = (moderngl.NEAREST, moderngl.NEAREST)
141+
texture.use(i)
141142

142143
model_transform = Matrix44.identity(dtype="f4")
143-
# model_transform *= Matrix44.from_translation((-8, -8, -8))
144+
model_transform *= Matrix44.from_translation((-8, -8, -8))
144145

145146
# TODO: order??? (see docstring)
146147
# if gui := model.display.get("gui"):
@@ -158,25 +159,28 @@ def render_block(
158159

159160
self.uniform("m_model").write(element_transform)
160161

161-
for direction in FACE_ORDER:
162-
if not (face := element.faces.get(direction)):
162+
# TODO: face order stuff...
163+
for direction in ["down", "west", "north", "south", "east", "up"]:
164+
# TODO: face.rotation
165+
if direction not in element.faces:
163166
continue
164167

165-
# TODO: face.rotation
168+
face = element.faces[direction]
166169

167170
match direction:
168-
case "up" | "down":
171+
case "up":
169172
light = LIGHT_UP
170-
case "north" | "south":
171-
light = LIGHT_LEFT
172-
case "east" | "west":
173+
case "south":
173174
light = LIGHT_RIGHT
175+
case "east":
176+
light = LIGHT_LEFT
177+
case _:
178+
light = LIGHT_BACK
174179

175180
self.uniform("light").value = light
176181
self.uniform("texture0").value = textures[face.texture.lstrip("#")]
177182

178183
vao = get_element_face_vao(element, direction)
179-
180184
vao.render(self.prog)
181185

182186
self.ctx.finish()
@@ -185,7 +189,7 @@ def render_block(
185189
mode="RGBA",
186190
size=self.wnd.fbo.size,
187191
data=self.wnd.fbo.read(components=4),
188-
).transpose(Image.FLIP_TOP_BOTTOM)
192+
)
189193

190194
image.save("out.png", format="png")
191195

@@ -366,3 +370,32 @@ def get_default_uv(element: ModelElement, direction: FaceName):
366370
max(u_from, u_to),
367371
max(v_from, v_to),
368372
)
373+
374+
375+
def pitch_yaw_camera(pitch: float, yaw: float):
376+
"""Both values are in degrees."""
377+
378+
eye = np.matmul(
379+
(-64, 0, 0, 1),
380+
(
381+
Matrix44.identity(dtype="f4")
382+
* Matrix44.from_y_rotation(math.radians(yaw))
383+
* Matrix44.from_z_rotation(math.radians(pitch))
384+
),
385+
)[:3]
386+
387+
up = np.matmul(
388+
(-1, 0, 0, 1),
389+
(
390+
Matrix44.identity(dtype="f4")
391+
* Matrix44.from_y_rotation(math.radians(yaw))
392+
* Matrix44.from_z_rotation(math.radians(90 - pitch))
393+
),
394+
)[:3]
395+
396+
return Matrix44.look_at(
397+
eye=eye,
398+
target=(0, 0, 0),
399+
up=up,
400+
dtype="f4",
401+
)

src/hexdoc/minecraft/models/base.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,12 @@ class ModelElement(HexdocModel):
130130
https://minecraft.wiki/w/Tutorials/Models
131131
"""
132132

133-
from_: Vec3[Annotated[float, clamped(16, 32)]] = Field(alias="from")
133+
from_: Vec3[Annotated[float, clamped(-16, 32)]] = Field(alias="from")
134134
"""Start point of a cuboid according to the scheme [x, y, z].
135135
136136
Values must be between -16 and 32.
137137
"""
138-
to: Vec3[Annotated[float, clamped(16, 32)]]
138+
to: Vec3[Annotated[float, clamped(-16, 32)]]
139139
"""Stop point of a cuboid according to the scheme [x, y, z].
140140
141141
Values must be between -16 and 32.

test.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from pathlib import Path
2+
3+
from hexdoc.cli.utils.load import load_common_data
4+
from hexdoc.core import ModResourceLoader, ResourceLocation
5+
from hexdoc.graphics.render import BlockRenderer
6+
from hexdoc.minecraft.models import load_model
7+
from hexdoc.minecraft.models.item import ItemModel
8+
9+
BLOCK_ID = "minecraft:oak_log"
10+
11+
12+
def main():
13+
props_file = Path("submodules/HexMod/doc/hexdoc.toml")
14+
props, pm, *_ = load_common_data(props_file, branch="")
15+
16+
with ModResourceLoader.load_all(props, pm, export=False) as loader:
17+
_, model = load_model(loader, "item" / ResourceLocation.from_str(BLOCK_ID))
18+
while isinstance(model, ItemModel) and model.parent:
19+
_, model = load_model(loader, model.parent)
20+
21+
if isinstance(model, ItemModel):
22+
raise ValueError(f"Invalid block id: {BLOCK_ID}")
23+
24+
with BlockRenderer(loader) as renderer:
25+
renderer.render_block_model(model)
26+
27+
28+
if __name__ == "__main__":
29+
main()

0 commit comments

Comments
 (0)