Level hot reload working
This commit is contained in:
parent
bb6498a193
commit
8b8e4f9513
BIN
assets/blender/test_level_blend/NurbsPath.glb
(Stored with Git LFS)
BIN
assets/blender/test_level_blend/NurbsPath.glb
(Stored with Git LFS)
Binary file not shown.
BIN
assets/blender/test_level_blend/Plane.glb
(Stored with Git LFS)
BIN
assets/blender/test_level_blend/Plane.glb
(Stored with Git LFS)
Binary file not shown.
@ -1,45 +1,45 @@
|
||||
(inst
|
||||
:model "assets/blender/testblend_blend/Bakery.glb"
|
||||
:pos (0.000000 0.000000 12.000000)
|
||||
:pos (1.000000 0.000000 -13.000000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (1.000000 1.000000 1.000000))
|
||||
(inst
|
||||
:model "assets/blender/test_level_blend/Plane.glb"
|
||||
:pos (0.000000 -1.000000 0.000000)
|
||||
:pos (0.000000 -1.000000 -0.000000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (22.469545 22.469545 22.469545))
|
||||
(inst
|
||||
:model "assets/blender/testblend_blend/Fire_Station.glb"
|
||||
:pos (9.000000 0.000000 13.000000)
|
||||
:pos (10.500000 0.000000 -22.500000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (1.000000 1.000000 1.000000))
|
||||
(inst
|
||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
||||
:pos (-8.000000 0.000000 11.000000)
|
||||
:pos (-7.000000 0.000000 -12.000000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (1.000000 1.000000 1.000000))
|
||||
(inst
|
||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
||||
:pos (-16.000000 0.000000 11.000000)
|
||||
:pos (-16.000000 0.000000 -11.000000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (1.000000 1.000000 1.000000))
|
||||
(inst
|
||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
||||
:pos (-15.559284 1.609015 0.259853)
|
||||
:pos (-20.000000 -1.000000 -1.000000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (1.000000 1.000000 1.000000))
|
||||
(inst
|
||||
:model "assets/blender/testblend_blend/Green_House.glb"
|
||||
:pos (14.000000 0.000000 -7.000000)
|
||||
:pos (14.000000 0.000000 7.000000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (1.000000 1.000000 1.000000))
|
||||
(inst
|
||||
:model "assets/blender/testblend_blend/Hotel.glb"
|
||||
:pos (8.000000 0.000000 -18.000000)
|
||||
:pos (8.000000 0.000000 18.000000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (1.000000 1.000000 1.000000))
|
||||
(inst
|
||||
:model "assets/blender/test_level_blend/NurbsPath.glb"
|
||||
:pos (0.000000 1.000000 0.000000)
|
||||
:pos (-4.000000 0.000000 12.000000)
|
||||
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||
:scale (1.000000 1.000000 1.000000))
|
||||
|
BIN
assets/blender/testblend_blend/Bakery.glb
(Stored with Git LFS)
BIN
assets/blender/testblend_blend/Bakery.glb
(Stored with Git LFS)
Binary file not shown.
BIN
assets/blender/testblend_blend/Fire_Station.glb
(Stored with Git LFS)
BIN
assets/blender/testblend_blend/Fire_Station.glb
(Stored with Git LFS)
Binary file not shown.
BIN
assets/blender/testblend_blend/Gas_Station_Shop.glb
(Stored with Git LFS)
BIN
assets/blender/testblend_blend/Gas_Station_Shop.glb
(Stored with Git LFS)
Binary file not shown.
BIN
assets/blender/testblend_blend/Green_House.glb
(Stored with Git LFS)
BIN
assets/blender/testblend_blend/Green_House.glb
(Stored with Git LFS)
Binary file not shown.
BIN
assets/blender/testblend_blend/Hotel.glb
(Stored with Git LFS)
BIN
assets/blender/testblend_blend/Hotel.glb
(Stored with Git LFS)
Binary file not shown.
@ -1,6 +1,7 @@
|
||||
import bpy
|
||||
import os
|
||||
import pathlib
|
||||
import contextlib
|
||||
|
||||
# Ensure blend file is saved
|
||||
blend_filepath = bpy.data.filepath
|
||||
@ -9,6 +10,26 @@ if not blend_filepath:
|
||||
|
||||
assert bpy.context.scene is not None
|
||||
|
||||
@contextlib.contextmanager
|
||||
def temp_scene(name: str):
|
||||
original_scene = bpy.context.scene
|
||||
assert original_scene is not None
|
||||
temp_scene = bpy.data.scenes.new(name)
|
||||
assert bpy.context.window is not None
|
||||
|
||||
try:
|
||||
bpy.context.window.scene = temp_scene
|
||||
yield temp_scene
|
||||
finally:
|
||||
assert bpy.context.window is not None
|
||||
bpy.context.window.scene = original_scene
|
||||
print(f'removing scene {temp_scene}')
|
||||
bpy.data.scenes.remove(temp_scene)
|
||||
|
||||
scene = bpy.context.scene
|
||||
|
||||
export_scene = bpy.data.scenes.new('__export')
|
||||
|
||||
def clean_blend_path(blend_path: str) -> str:
|
||||
return os.path.join(os.path.dirname(blend_path), bpy.path.clean_name(os.path.basename(blend_path)))
|
||||
|
||||
@ -39,13 +60,18 @@ def export_object_as_glb(obj: bpy.types.Object, export_path: str):
|
||||
full_export_path = os.path.join(assets_path, export_path)
|
||||
pathlib.Path(os.path.dirname(full_export_path)).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
obj.select_set(True)
|
||||
if obj.instance_type == 'COLLECTION' and obj.instance_collection:
|
||||
with temp_scene('__export') as scn:
|
||||
scn.collection.children.link(obj.instance_collection)
|
||||
bpy.ops.export_scene.gltf(filepath=full_export_path, use_active_scene=True, export_apply=True)
|
||||
else:
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
obj.select_set(True)
|
||||
assert bpy.context.view_layer is not None
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
|
||||
assert bpy.context.view_layer is not None
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
bpy.ops.export_scene.gltf(filepath=full_export_path, use_selection=True, export_apply=True)
|
||||
|
||||
bpy.ops.export_scene.gltf(filepath=full_export_path, use_selection=True, export_apply=True)
|
||||
print(f"Exported {obj.name} -> {export_path}")
|
||||
|
||||
# Collect all visible, non-hidden objects in the scene
|
||||
@ -70,7 +96,7 @@ for obj in visible_objects:
|
||||
instance_sexpr = (
|
||||
'(inst'
|
||||
f'\n\t:model "assets/{model_path}"'
|
||||
f'\n\t:pos ({loc.x:.6f} {loc.z:.6f} {loc.y:.6f})'
|
||||
f'\n\t:pos ({loc.x:.6f} {loc.z:.6f} {-loc.y:.6f})'
|
||||
f'\n\t:rot ({rot.x:.6f} {rot.y:.6f} {rot.z:.6f} {rot.w:.6f})'
|
||||
f'\n\t:scale ({scale.x:.6f} {scale.y:.6f} {scale.z:.6f}))'
|
||||
)
|
||||
|
@ -5,6 +5,7 @@ package name
|
||||
import "core:mem"
|
||||
import "core:strings"
|
||||
import "core:sync"
|
||||
import "libs:tracy"
|
||||
|
||||
// When enabled name globals will be initialized automatically
|
||||
NAME_STATIC_INIT :: #config(NAME_STATIC_INIT, true)
|
||||
@ -61,23 +62,36 @@ when NAME_STATIC_INIT {
|
||||
}
|
||||
|
||||
from_string :: proc(str: string) -> Name {
|
||||
sync.atomic_rw_mutex_guard(&global_container.lock)
|
||||
existing, ok := global_container.names_lookup[str]
|
||||
tracy.Zone()
|
||||
|
||||
existing: Name
|
||||
ok: bool
|
||||
{
|
||||
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
|
||||
existing, ok = global_container.names_lookup[str]
|
||||
}
|
||||
if ok {
|
||||
return existing
|
||||
} else {
|
||||
new_str := strings.clone(
|
||||
sync.atomic_rw_mutex_guard(&global_container.lock)
|
||||
|
||||
new_str := strings.clone_to_cstring(
|
||||
str,
|
||||
mem.dynamic_arena_allocator(&global_container.names_allocator),
|
||||
)
|
||||
idx := u32(len(global_container.names_array))
|
||||
append(&global_container.names_array, new_str)
|
||||
append(&global_container.names_array, string(new_str))
|
||||
global_container.names_lookup[str] = Name(idx)
|
||||
return Name(idx)
|
||||
}
|
||||
}
|
||||
|
||||
from_cstring :: proc(str: cstring) -> Name {
|
||||
return from_string(string(str))
|
||||
}
|
||||
|
||||
to_string :: proc(name: Name) -> string {
|
||||
tracy.Zone()
|
||||
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
|
||||
return global_container.names_array[name]
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,13 @@ import "core:bytes"
|
||||
import "core:encoding/csv"
|
||||
import "core:io"
|
||||
import "core:log"
|
||||
import lg "core:math/linalg"
|
||||
import "core:strconv"
|
||||
import "game:debug"
|
||||
import "game:halfedge"
|
||||
import "game:physics/collision"
|
||||
import rl "libs:raylib"
|
||||
import rlgl "libs:raylib/rlgl"
|
||||
|
||||
CSV_Parse_Error :: enum {
|
||||
Ok,
|
||||
@ -69,7 +75,7 @@ parse_csv_2d :: proc(
|
||||
data: []byte,
|
||||
allocator := context.allocator,
|
||||
) -> (
|
||||
curve: Loaded_Curve_2D,
|
||||
curve: Curve_2D,
|
||||
error: CSV_Parse_Error,
|
||||
) {
|
||||
bytes_reader: bytes.Reader
|
||||
@ -125,8 +131,400 @@ parse_csv_2d :: proc(
|
||||
append(&tmp_result, [2]f32{f32(key), f32(val)})
|
||||
}
|
||||
|
||||
curve.points = make([][2]f32, len(tmp_result), allocator)
|
||||
copy(curve.points, tmp_result[:])
|
||||
curve = make([][2]f32, len(tmp_result), allocator)
|
||||
copy(curve, tmp_result[:])
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
parse_convex :: proc(bytes: []byte, allocator := context.allocator) -> (Loaded_Convex, bool) {
|
||||
Parse_Ctx :: struct {
|
||||
bytes: []byte,
|
||||
it: int,
|
||||
line: int,
|
||||
}
|
||||
|
||||
advance :: proc(ctx: ^Parse_Ctx, by: int = 1) -> bool {
|
||||
ctx.it = min(ctx.it + by, len(ctx.bytes) + 1)
|
||||
return ctx.it < len(ctx.bytes)
|
||||
}
|
||||
|
||||
is_whitespace :: proc(b: byte) -> bool {
|
||||
return b == ' ' || b == '\t' || b == '\r' || b == '\n'
|
||||
}
|
||||
|
||||
skip_line :: proc(ctx: ^Parse_Ctx) {
|
||||
for ctx.it < len(ctx.bytes) && ctx.bytes[ctx.it] != '\n' {
|
||||
advance(ctx) or_break
|
||||
}
|
||||
advance(ctx)
|
||||
ctx.line += 1
|
||||
}
|
||||
|
||||
skip_whitespase :: proc(ctx: ^Parse_Ctx) {
|
||||
switch ctx.bytes[ctx.it] {
|
||||
case ' ', '\t', '\r', '\n':
|
||||
if ctx.bytes[ctx.it] == '\n' {
|
||||
ctx.line += 1
|
||||
}
|
||||
advance(ctx) or_break
|
||||
case '#':
|
||||
skip_line(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
Edge :: [2]u16
|
||||
edges_map := make_map(map[Edge]halfedge.Edge_Index, context.temp_allocator)
|
||||
|
||||
edges := make_dynamic_array([dynamic]halfedge.Half_Edge, context.temp_allocator)
|
||||
vertices := make_dynamic_array([dynamic]halfedge.Vertex, context.temp_allocator)
|
||||
faces := make_dynamic_array([dynamic]halfedge.Face, context.temp_allocator)
|
||||
min_pos, max_pos: rl.Vector3 = max(f32), min(f32)
|
||||
|
||||
// Parse obj file directly into halfedge data structure
|
||||
{
|
||||
ctx := Parse_Ctx {
|
||||
bytes = bytes,
|
||||
line = 1,
|
||||
}
|
||||
|
||||
for ctx.it < len(ctx.bytes) {
|
||||
skip_whitespase(&ctx)
|
||||
switch ctx.bytes[ctx.it] {
|
||||
case 'v':
|
||||
// vertex
|
||||
advance(&ctx) or_break
|
||||
|
||||
vertex: rl.Vector3
|
||||
|
||||
coord_idx := 0
|
||||
for ctx.bytes[ctx.it] != '\n' && ctx.bytes[ctx.it] != '\r' {
|
||||
skip_whitespase(&ctx)
|
||||
s := string(ctx.bytes[ctx.it:])
|
||||
coord_val, nr, ok := strconv.parse_f32_prefix(s)
|
||||
if !ok {
|
||||
log.errorf(
|
||||
"failed to parse float %v %s at line %d",
|
||||
coord_idx,
|
||||
ctx.bytes[ctx.it:][:12],
|
||||
ctx.line,
|
||||
)
|
||||
return {}, false
|
||||
}
|
||||
advance(&ctx, nr) or_break
|
||||
|
||||
vertex[coord_idx] = coord_val
|
||||
coord_idx += 1
|
||||
}
|
||||
append(&vertices, halfedge.Vertex{pos = vertex, edge = -1})
|
||||
min_pos = lg.min(vertex, min_pos)
|
||||
max_pos = lg.max(vertex, max_pos)
|
||||
|
||||
if ctx.bytes[ctx.it] == '\r' {
|
||||
advance(&ctx)
|
||||
}
|
||||
advance(&ctx)
|
||||
ctx.line += 1
|
||||
case 'f':
|
||||
advance(&ctx) or_break
|
||||
|
||||
MAX_FACE_VERTS :: 10
|
||||
|
||||
indices_buf: [MAX_FACE_VERTS]u16
|
||||
index_count := 0
|
||||
|
||||
for ctx.bytes[ctx.it] != '\n' && ctx.bytes[ctx.it] != '\r' {
|
||||
skip_whitespase(&ctx)
|
||||
index_f, nr, ok := strconv.parse_f32_prefix(string(ctx.bytes[ctx.it:]))
|
||||
if !ok {
|
||||
log.errorf("failed to parse index at line %d", ctx.line)
|
||||
return {}, false
|
||||
}
|
||||
advance(&ctx, nr) or_break
|
||||
index := u16(index_f) - 1
|
||||
indices_buf[index_count] = u16(index)
|
||||
index_count += 1
|
||||
}
|
||||
if ctx.bytes[ctx.it] == '\r' {
|
||||
advance(&ctx)
|
||||
}
|
||||
advance(&ctx)
|
||||
ctx.line += 1
|
||||
|
||||
assert(index_count >= 3)
|
||||
indices := indices_buf[:index_count]
|
||||
|
||||
append(&faces, halfedge.Face{})
|
||||
face_idx := len(faces) - 1
|
||||
face := &faces[face_idx]
|
||||
|
||||
first_edge_idx := len(edges)
|
||||
|
||||
face.edge = halfedge.Edge_Index(first_edge_idx)
|
||||
|
||||
plane: collision.Plane
|
||||
{
|
||||
i1, i2, i3 := indices[0], indices[1], indices[2]
|
||||
v1, v2, v3 := vertices[i1].pos, vertices[i2].pos, vertices[i3].pos
|
||||
|
||||
plane = collision.plane_from_point_normal(
|
||||
v1,
|
||||
lg.normalize0(lg.cross(v2 - v1, v3 - v1)),
|
||||
)
|
||||
}
|
||||
face.normal = plane.normal
|
||||
|
||||
for index in indices[3:] {
|
||||
assert(
|
||||
abs(collision.signed_distance_plane(vertices[index].pos, plane)) < 0.01,
|
||||
"mesh has non planar faces",
|
||||
)
|
||||
}
|
||||
|
||||
first_vert_pos := vertices[indices[0]].pos
|
||||
|
||||
for i in 0 ..< len(indices) {
|
||||
edge_idx := halfedge.Edge_Index(first_edge_idx + i)
|
||||
prev_edge_relative := i == 0 ? len(indices) - 1 : i - 1
|
||||
next_edge_relative := (i + 1) % len(indices)
|
||||
i1, i2 := indices[i], indices[next_edge_relative]
|
||||
v1, v2 := &vertices[i1], &vertices[i2]
|
||||
|
||||
assert(
|
||||
lg.dot(
|
||||
lg.cross(v1.pos - first_vert_pos, v2.pos - first_vert_pos),
|
||||
plane.normal,
|
||||
) >=
|
||||
0,
|
||||
"non convex face or non ccw winding",
|
||||
)
|
||||
|
||||
if v1.edge == -1 {
|
||||
v1.edge = edge_idx
|
||||
}
|
||||
|
||||
edge := halfedge.Half_Edge {
|
||||
origin = halfedge.Vertex_Index(i1),
|
||||
face = halfedge.Face_Index(face_idx),
|
||||
twin = -1,
|
||||
next = halfedge.Edge_Index(first_edge_idx + next_edge_relative),
|
||||
prev = halfedge.Edge_Index(first_edge_idx + prev_edge_relative),
|
||||
}
|
||||
|
||||
stable_index := [2]u16{min(i1, i2), max(i1, i2)}
|
||||
if stable_index in edges_map {
|
||||
edge.twin = edges_map[stable_index]
|
||||
twin_edge := &edges[edge.twin]
|
||||
assert(twin_edge.twin == -1, "edge has more than two faces attached")
|
||||
twin_edge.twin = edge_idx
|
||||
} else {
|
||||
edges_map[stable_index] = edge_idx
|
||||
}
|
||||
|
||||
append(&edges, edge)
|
||||
}
|
||||
case:
|
||||
skip_line(&ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
center := (max_pos + min_pos) * 0.5
|
||||
extent := (max_pos - min_pos) * 0.5
|
||||
|
||||
center_of_mass: rl.Vector3
|
||||
|
||||
final_vertices := make([]halfedge.Vertex, len(vertices), allocator)
|
||||
final_edges := make([]halfedge.Half_Edge, len(edges), allocator)
|
||||
final_faces := make([]halfedge.Face, len(faces), allocator)
|
||||
copy(final_vertices, vertices[:])
|
||||
copy(final_edges, edges[:])
|
||||
copy(final_faces, faces[:])
|
||||
|
||||
mesh := halfedge.Half_Edge_Mesh {
|
||||
vertices = final_vertices,
|
||||
edges = final_edges,
|
||||
faces = final_faces,
|
||||
center = center,
|
||||
extent = extent,
|
||||
}
|
||||
|
||||
// Center of mass calculation
|
||||
total_volume := f32(0.0)
|
||||
{
|
||||
tri_idx := 0
|
||||
for face_idx in 0 ..< len(faces) {
|
||||
face := faces[face_idx]
|
||||
// for all triangles
|
||||
it := halfedge.iterator_face_edges(mesh, halfedge.Face_Index(face_idx))
|
||||
i := 0
|
||||
tri: [3]rl.Vector3
|
||||
for edge in halfedge.iterate_next_edge(&it) {
|
||||
switch i {
|
||||
case 0 ..< 3:
|
||||
tri[i] = mesh.vertices[edge.origin].pos
|
||||
case:
|
||||
tri[1] = tri[2]
|
||||
tri[2] = mesh.vertices[edge.origin].pos
|
||||
}
|
||||
|
||||
if i >= 2 {
|
||||
plane := collision.plane_from_point_normal(tri[0], -face.normal)
|
||||
|
||||
h := max(0, collision.signed_distance_plane(center, plane))
|
||||
tri_area :=
|
||||
lg.dot(lg.cross(tri[1] - tri[0], tri[2] - tri[0]), face.normal) * 0.5
|
||||
tetra_volume := 1.0 / 3.0 * tri_area * h
|
||||
total_volume += tetra_volume
|
||||
|
||||
tetra_centroid := (tri[0] + tri[1] + tri[2] + center) * 0.25
|
||||
center_of_mass += tetra_volume * tetra_centroid
|
||||
|
||||
tri_idx += 1
|
||||
}
|
||||
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(total_volume > 0, "degenerate convex hull")
|
||||
center_of_mass /= total_volume
|
||||
|
||||
inertia_tensor: lg.Matrix3f32
|
||||
// Find inertia tensor
|
||||
{
|
||||
tri_idx := 0
|
||||
for face_idx in 0 ..< len(faces) {
|
||||
// for all triangles
|
||||
it := halfedge.iterator_face_edges(mesh, halfedge.Face_Index(face_idx))
|
||||
i := 0
|
||||
tri: [3]rl.Vector3
|
||||
for edge in halfedge.iterate_next_edge(&it) {
|
||||
switch i {
|
||||
case 0 ..< 3:
|
||||
tri[i] = mesh.vertices[edge.origin].pos
|
||||
case:
|
||||
tri[1] = tri[2]
|
||||
tri[2] = mesh.vertices[edge.origin].pos
|
||||
}
|
||||
|
||||
if i >= 2 {
|
||||
tet := Tetrahedron {
|
||||
p = {tri[0], tri[1], tri[2], center_of_mass},
|
||||
}
|
||||
|
||||
inertia_tensor += tetrahedron_inertia_tensor(tet, center_of_mass)
|
||||
|
||||
tri_idx += 1
|
||||
}
|
||||
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
inertia_tensor = inertia_tensor
|
||||
|
||||
return Loaded_Convex {
|
||||
mesh = mesh,
|
||||
center_of_mass = center_of_mass,
|
||||
inertia_tensor = inertia_tensor,
|
||||
total_volume = total_volume,
|
||||
},
|
||||
true
|
||||
}
|
||||
|
||||
// TODO: move convex stuff out of assets.odin
|
||||
Tetrahedron :: struct {
|
||||
p: [4]rl.Vector3,
|
||||
}
|
||||
|
||||
tetrahedron_volume :: #force_inline proc(tet: Tetrahedron) -> f32 {
|
||||
return(
|
||||
1.0 /
|
||||
6.0 *
|
||||
abs(lg.dot(lg.cross(tet.p[1] - tet.p[0], tet.p[2] - tet.p[0]), tet.p[3] - tet.p[0])) \
|
||||
)
|
||||
}
|
||||
|
||||
square :: #force_inline proc(val: f32) -> f32 {
|
||||
return val * val
|
||||
}
|
||||
|
||||
tetrahedron_inertia_tensor :: proc(tet: Tetrahedron, o: rl.Vector3) -> lg.Matrix3f32 {
|
||||
p1, p2, p3, p4 := tet.p[0] - o, tet.p[1] - o, tet.p[2] - o, tet.p[3] - o
|
||||
// Jacobian determinant is 6*Volume
|
||||
det_j := abs(6.0 * tetrahedron_volume(tet))
|
||||
|
||||
moment_of_inertia_term :: proc(p1, p2, p3, p4: rl.Vector3, axis: int) -> f32 {
|
||||
return(
|
||||
square(p1[axis]) +
|
||||
p1[axis] * p2[axis] +
|
||||
square(p2[axis]) +
|
||||
p1[axis] * p3[axis] +
|
||||
p2[axis] * p3[axis] +
|
||||
square(p3[axis]) +
|
||||
p1[axis] * p4[axis] +
|
||||
p2[axis] * p4[axis] +
|
||||
p3[axis] * p4[axis] +
|
||||
square(p4[axis]) \
|
||||
)
|
||||
}
|
||||
|
||||
product_of_inertia_term :: proc(p1, p2, p3, p4: rl.Vector3, axis1, axis2: int) -> f32 {
|
||||
return(
|
||||
2.0 * p1[axis1] * p1[axis2] +
|
||||
p2[axis1] * p1[axis2] +
|
||||
p3[axis1] * p1[axis2] +
|
||||
p4[axis1] * p1[axis2] +
|
||||
p1[axis1] * p2[axis2] +
|
||||
2.0 * p2[axis1] * p2[axis2] +
|
||||
p3[axis1] * p2[axis2] +
|
||||
p4[axis1] * p2[axis2] +
|
||||
p1[axis1] * p3[axis2] +
|
||||
p2[axis1] * p3[axis2] +
|
||||
2.0 * p3[axis1] * p3[axis2] +
|
||||
p4[axis1] * p3[axis2] +
|
||||
p1[axis1] * p4[axis2] +
|
||||
p2[axis1] * p4[axis2] +
|
||||
p3[axis1] * p4[axis2] +
|
||||
2.0 * p4[axis1] * p4[axis2] \
|
||||
)
|
||||
}
|
||||
|
||||
MOMENT_OF_INERTIA_DENOM :: 1.0 / 60.0
|
||||
PRODUCT_OF_INERTIA_DENOM :: 1.0 / 120.0
|
||||
|
||||
x_term := moment_of_inertia_term(p1, p2, p3, p4, 0)
|
||||
y_term := moment_of_inertia_term(p1, p2, p3, p4, 1)
|
||||
z_term := moment_of_inertia_term(p1, p2, p3, p4, 2)
|
||||
|
||||
// Moments of intertia with respect to XYZ
|
||||
// Integral(y^2 + z^2)
|
||||
a := det_j * (y_term + z_term) * MOMENT_OF_INERTIA_DENOM
|
||||
// Integral(x^2 + z^2)
|
||||
b := det_j * (x_term + z_term) * MOMENT_OF_INERTIA_DENOM
|
||||
// Integral(x^2 + y^2)
|
||||
c := det_j * (x_term + y_term) * MOMENT_OF_INERTIA_DENOM
|
||||
|
||||
// Products of inertia
|
||||
a_ := product_of_inertia_term(p1, p2, p3, p4, axis1 = 1, axis2 = 2) * PRODUCT_OF_INERTIA_DENOM
|
||||
b_ := product_of_inertia_term(p1, p2, p3, p4, axis1 = 0, axis2 = 2) * PRODUCT_OF_INERTIA_DENOM
|
||||
c_ := product_of_inertia_term(p1, p2, p3, p4, axis1 = 0, axis2 = 1) * PRODUCT_OF_INERTIA_DENOM
|
||||
|
||||
return {a, -b_, -c_, -b_, b, -a_, -c_, -a_, c}
|
||||
}
|
||||
|
||||
debug_draw_tetrahedron_wires :: proc(tri: [3]rl.Vector3, p: rl.Vector3, color: rl.Color) {
|
||||
rlgl.Begin(rlgl.LINES)
|
||||
defer rlgl.End()
|
||||
|
||||
debug.rlgl_color(color)
|
||||
|
||||
debug.rlgl_vertex3v2(tri[0], tri[1])
|
||||
debug.rlgl_vertex3v2(tri[1], tri[2])
|
||||
debug.rlgl_vertex3v2(tri[2], tri[0])
|
||||
debug.rlgl_vertex3v2(tri[0], p)
|
||||
debug.rlgl_vertex3v2(tri[1], p)
|
||||
debug.rlgl_vertex3v2(tri[2], p)
|
||||
}
|
||||
|
145
game/assets/watcher.odin
Normal file
145
game/assets/watcher.odin
Normal file
@ -0,0 +1,145 @@
|
||||
package assets
|
||||
|
||||
import "base:runtime"
|
||||
import "common:name"
|
||||
import "core:log"
|
||||
import "core:sync/chan"
|
||||
import "core:thread"
|
||||
import "libs:physfs"
|
||||
|
||||
ASSET_WATCHER_OPS_BUFFER :: 256
|
||||
|
||||
// Add asset to watch list
|
||||
Asset_Watcher_Op_Add :: struct {
|
||||
type: Asset_Type,
|
||||
path: name.Name,
|
||||
modtime: physfs.sint64,
|
||||
}
|
||||
// Remove asset from watch list
|
||||
Asset_Watcher_Op_Remove :: struct {
|
||||
type: Asset_Type,
|
||||
path: name.Name,
|
||||
}
|
||||
|
||||
Asset_Watcher_Op :: union #no_nil {
|
||||
Asset_Watcher_Op_Add,
|
||||
Asset_Watcher_Op_Remove,
|
||||
}
|
||||
|
||||
Watcher_Asset :: struct {
|
||||
type: Asset_Type,
|
||||
path: name.Name,
|
||||
modtime: physfs.sint64,
|
||||
}
|
||||
|
||||
Asset_Modtime_Watcher :: struct {
|
||||
ops: chan.Chan(Asset_Watcher_Op),
|
||||
modified_assets: chan.Chan(Watcher_Asset),
|
||||
loaded_assets: [dynamic]Watcher_Asset,
|
||||
thread: ^thread.Thread,
|
||||
}
|
||||
|
||||
modtime_watcher_init :: proc(watcher: ^Asset_Modtime_Watcher, allocator := context.allocator) {
|
||||
err: runtime.Allocator_Error
|
||||
watcher.ops, err = chan.create_buffered(
|
||||
chan.Chan(Asset_Watcher_Op),
|
||||
ASSET_WATCHER_OPS_BUFFER,
|
||||
allocator,
|
||||
)
|
||||
assert(err == nil)
|
||||
watcher.modified_assets, err = chan.create_buffered(
|
||||
chan.Chan(Watcher_Asset),
|
||||
ASSET_WATCHER_OPS_BUFFER,
|
||||
allocator,
|
||||
)
|
||||
watcher.loaded_assets = make_dynamic_array([dynamic]Watcher_Asset, allocator)
|
||||
|
||||
watcher.thread = thread.create(modtime_watcher_thread_proc)
|
||||
watcher.thread.data = watcher
|
||||
watcher_context := runtime.default_context()
|
||||
watcher_context.logger = context.logger
|
||||
watcher_context.allocator = context.allocator
|
||||
watcher.thread.init_context = watcher_context
|
||||
thread.start(watcher.thread)
|
||||
}
|
||||
|
||||
modtime_watcher_deinit :: proc(watcher: ^Asset_Modtime_Watcher) {
|
||||
if !chan.is_closed(&watcher.ops) {
|
||||
chan.close(&watcher.ops)
|
||||
thread.join(watcher.thread)
|
||||
watcher.thread = nil
|
||||
}
|
||||
|
||||
chan.destroy(&watcher.ops)
|
||||
chan.close(&watcher.modified_assets)
|
||||
chan.destroy(&watcher.modified_assets)
|
||||
delete(watcher.loaded_assets)
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
modtime_watcher_thread_proc :: proc(t: ^thread.Thread) {
|
||||
watcher := cast(^Asset_Modtime_Watcher)t.data
|
||||
|
||||
log.debugf("watcher thread")
|
||||
|
||||
for !chan.is_closed(&watcher.ops) {
|
||||
for recv_op in chan.try_recv(watcher.ops) {
|
||||
switch op in recv_op {
|
||||
case Asset_Watcher_Op_Add:
|
||||
log.debugf("add [{}] {}", op.type, name.to_string(op.path))
|
||||
append(
|
||||
&watcher.loaded_assets,
|
||||
Watcher_Asset{type = op.type, path = op.path, modtime = op.modtime},
|
||||
)
|
||||
case Asset_Watcher_Op_Remove:
|
||||
log.debugf("remove [{}] {}", op.type, name.to_string(op.path))
|
||||
i := 0
|
||||
for i < len(watcher.loaded_assets) {
|
||||
if op.path == watcher.loaded_assets[i].path &&
|
||||
op.type == watcher.loaded_assets[i].type {
|
||||
unordered_remove(&watcher.loaded_assets, i)
|
||||
} else {
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for &asset in watcher.loaded_assets {
|
||||
modtime := physfs.getLastModTime(name.to_cstring(asset.path))
|
||||
|
||||
if asset.modtime != modtime {
|
||||
log.debugf("change [{}] {}", asset.type, name.to_string(asset.path))
|
||||
ok := chan.send(
|
||||
watcher.modified_assets,
|
||||
Watcher_Asset{type = asset.type, path = asset.path, modtime = modtime},
|
||||
)
|
||||
assert(ok)
|
||||
}
|
||||
asset.modtime = modtime
|
||||
}
|
||||
|
||||
// To avoid busy loop just in case
|
||||
thread.yield()
|
||||
}
|
||||
}
|
||||
|
||||
modtime_watcher_add_asset :: proc(
|
||||
watcher: ^Asset_Modtime_Watcher,
|
||||
type: Asset_Type,
|
||||
path: name.Name,
|
||||
modtime: physfs.sint64,
|
||||
) -> bool {
|
||||
return chan.send(
|
||||
watcher.ops,
|
||||
Asset_Watcher_Op_Add{type = type, path = path, modtime = modtime},
|
||||
)
|
||||
}
|
||||
|
||||
modtime_watcher_remove_asset :: proc(
|
||||
watcher: ^Asset_Modtime_Watcher,
|
||||
type: Asset_Type,
|
||||
path: name.Name,
|
||||
) -> bool {
|
||||
return chan.send(watcher.ops, Asset_Watcher_Op_Remove{type = type, path = path})
|
||||
}
|
@ -63,7 +63,8 @@ scene_destroy :: proc(world: ^World, scene: ^Scene) {
|
||||
}
|
||||
|
||||
immediate_scene :: proc(world: ^World, scene: ^Scene, path: cstring) {
|
||||
path_name := name.from_string(string(path))
|
||||
tracy.Zone()
|
||||
path_name := name.from_cstring(path)
|
||||
|
||||
desc, reloaded := assets.get_scene_desc(&g_mem.assetman, path_name)
|
||||
|
||||
@ -71,15 +72,16 @@ immediate_scene :: proc(world: ^World, scene: ^Scene, path: cstring) {
|
||||
scene_destroy(world, scene)
|
||||
|
||||
scene.scene_desc_path = path_name
|
||||
scene.level_geoms = make([]physics.Level_Geom_Handle, len(desc.instances))
|
||||
|
||||
sim_state := physics.get_sim_state(&world.physics_scene)
|
||||
for inst in desc.instances {
|
||||
physics.add_level_geom(
|
||||
for inst, i in desc.instances {
|
||||
scene.level_geoms[i] = physics.add_level_geom(
|
||||
sim_state,
|
||||
physics.Level_Geom_Config {
|
||||
position = inst.pos,
|
||||
rotation = inst.rot,
|
||||
source = physics.Level_Geometry_Asset(name.to_string(inst.model)),
|
||||
source = physics.Level_Geometry_Asset(inst.model),
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -87,6 +89,7 @@ immediate_scene :: proc(world: ^World, scene: ^Scene, path: cstring) {
|
||||
}
|
||||
|
||||
scene_copy :: proc(dst, src: ^Scene) {
|
||||
tracy.Zone()
|
||||
dst.scene_desc_path = src.scene_desc_path
|
||||
if len(dst.level_geoms) != len(src.level_geoms) {
|
||||
delete(dst.level_geoms)
|
||||
@ -101,7 +104,7 @@ scene_draw :: proc(scene: ^Scene) {
|
||||
render.draw_model(
|
||||
assets.get_model(&g_mem.assetman, name.to_cstring(geo.model)),
|
||||
{},
|
||||
auto_cast linalg.matrix4_from_trs(geo.pos, geo.rot, geo.scale),
|
||||
auto_cast linalg.matrix4_from_trs(geo.pos, geo.rot, 1),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1437,6 +1440,8 @@ game_update :: proc() -> bool {
|
||||
tracy.Zone()
|
||||
defer tracy.FrameMark()
|
||||
|
||||
assets.assetman_tick(&g_mem.assetman)
|
||||
|
||||
update()
|
||||
draw()
|
||||
|
||||
@ -1474,7 +1479,6 @@ game_init :: proc() {
|
||||
init_physifs_raylib_callbacks()
|
||||
|
||||
assets.assetman_init(&g_mem.assetman)
|
||||
assets.init(&g_mem.assetman)
|
||||
|
||||
editor_state_init(&g_mem.es, 100)
|
||||
runtime_world_init(&g_mem.runtime_world, DEV_BUILD ? 100 : 2)
|
||||
|
@ -265,8 +265,7 @@ query_separation_edges :: proc(
|
||||
a_edge = -1
|
||||
b_edge = -1
|
||||
|
||||
temp := runtime.default_temp_allocator_temp_begin()
|
||||
defer runtime.default_temp_allocator_temp_end(temp)
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
|
||||
checked_pairs: bit_array.Bit_Array
|
||||
bit_array.init(&checked_pairs, len(a.edges) * len(b.edges), 0, context.temp_allocator)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package physics
|
||||
|
||||
import "base:runtime"
|
||||
import "bvh"
|
||||
import "common:name"
|
||||
import "core:fmt"
|
||||
@ -9,6 +10,7 @@ import lg "core:math/linalg"
|
||||
import "core:mem"
|
||||
import "core:slice"
|
||||
import "core:strings"
|
||||
import "game:assets"
|
||||
import "game:debug"
|
||||
import he "game:halfedge"
|
||||
import "game:ui"
|
||||
@ -61,7 +63,14 @@ init_debug_state :: proc(debug_state: ^Debug_State) {
|
||||
draw_debug_scene :: proc(scene: ^Scene, debug_state: ^Debug_State) {
|
||||
tracy.Zone()
|
||||
|
||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
|
||||
sim_state := get_sim_state(scene)
|
||||
sim_cache: Sim_Cache
|
||||
sim_cache.level_geom_asset_bvh = make_map(
|
||||
map[Level_Geom_Handle]assets.Loaded_BVH,
|
||||
context.temp_allocator,
|
||||
)
|
||||
|
||||
// Static_TLAS
|
||||
if true && sim_state.static_tlas.built {
|
||||
@ -73,22 +82,27 @@ draw_debug_scene :: proc(scene: ^Scene, debug_state: ^Debug_State) {
|
||||
|
||||
it := bvh.iterator(&sim_state.static_tlas.bvh_tree)
|
||||
|
||||
for node in bvh.iterator_next(&it) {
|
||||
if bvh.is_leaf_node(node) {
|
||||
prim_start := node.child_or_prim_start
|
||||
if false {
|
||||
for node in bvh.iterator_next(&it) {
|
||||
if bvh.is_leaf_node(node) {
|
||||
prim_start := node.child_or_prim_start
|
||||
|
||||
for level_geom_idx in prim_start ..< prim_start + node.prim_len {
|
||||
level_geom_handle := index_to_level_geom(int(level_geom_idx))
|
||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||
blas := get_level_geom_blas(sim_state, level_geom_handle)
|
||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
||||
for level_geom_idx in prim_start ..< prim_start + node.prim_len {
|
||||
level_geom_handle := index_to_level_geom(int(level_geom_idx))
|
||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||
blas, vertices, indices := get_level_geom_data(
|
||||
sim_state,
|
||||
&sim_cache,
|
||||
level_geom_handle,
|
||||
)
|
||||
|
||||
bvh.debug_draw_bvh_bounds_mesh(
|
||||
&blas,
|
||||
bvh.Mesh{vertices = vertices, indices = indices},
|
||||
level_geom.x,
|
||||
0,
|
||||
)
|
||||
bvh.debug_draw_bvh_bounds_mesh(
|
||||
&blas,
|
||||
bvh.Mesh{vertices = vertices, indices = indices},
|
||||
level_geom.x,
|
||||
0,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -300,6 +300,7 @@ body_get_convex_shapes_world :: proc(
|
||||
|
||||
level_geom_get_convex_shape :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
level_geom_handle: Level_Geom_Handle,
|
||||
tri_idx: int,
|
||||
allocator := context.temp_allocator,
|
||||
@ -307,7 +308,7 @@ level_geom_get_convex_shape :: proc(
|
||||
mesh: collision.Convex,
|
||||
) {
|
||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
||||
_, vertices, indices := get_level_geom_data(sim_state, sim_cache, level_geom_handle)
|
||||
return collision.double_sided_triangle_to_convex(
|
||||
get_transformed_triangle(vertices, indices, tri_idx, level_geom.x, level_geom.q),
|
||||
allocator,
|
||||
@ -353,7 +354,7 @@ rotate_extent :: proc(extent: Vec3, q: Quat) -> Vec3 {
|
||||
return result
|
||||
}
|
||||
|
||||
aabb_transform :: proc(local_aabb: AABB, x: Vec3, q: Quat) -> (aabb: AABB) {
|
||||
aabb_transform_phys :: proc(local_aabb: AABB, x: Vec3, q: Quat) -> (aabb: AABB) {
|
||||
aabb.center = lg.quaternion_mul_vector3(q, local_aabb.center) + x
|
||||
|
||||
aabb.extent = rotate_extent(local_aabb.extent, q)
|
||||
@ -361,6 +362,34 @@ aabb_transform :: proc(local_aabb: AABB, x: Vec3, q: Quat) -> (aabb: AABB) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: consolidate formats, please
|
||||
aabb_transform_bvh :: proc(local_aabb: bvh.AABB, x: Vec3, q: Quat) -> (aabb: bvh.AABB) {
|
||||
phys_aabb := bvh_aabb_to_phys_aabb(local_aabb)
|
||||
phys_aabb = aabb_transform(phys_aabb, x, q)
|
||||
|
||||
aabb.min = phys_aabb.center - phys_aabb.extent
|
||||
aabb.max = phys_aabb.center + phys_aabb.extent
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
aabb_transform :: proc {
|
||||
aabb_transform_phys,
|
||||
aabb_transform_bvh,
|
||||
}
|
||||
|
||||
aabb_inv_transform :: proc(local_aabb: bvh.AABB, x: Vec3, q: Quat) -> (aabb: bvh.AABB) {
|
||||
phys_aabb := bvh_aabb_to_phys_aabb(local_aabb)
|
||||
inv_q := lg.quaternion_inverse(q)
|
||||
phys_aabb.center = lg.quaternion_mul_vector3(inv_q, phys_aabb.center - x)
|
||||
phys_aabb.extent = rotate_extent(phys_aabb.extent, inv_q)
|
||||
|
||||
aabb.min = phys_aabb.center - phys_aabb.extent
|
||||
aabb.max = phys_aabb.center + phys_aabb.extent
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
input_shape_get_aabb :: proc(shapes: []Input_Shape) -> (aabb: AABB) {
|
||||
min, max: Vec3 = max(f32), min(f32)
|
||||
|
||||
|
@ -4,7 +4,6 @@ import "bvh"
|
||||
import "collision"
|
||||
import "common:name"
|
||||
import lg "core:math/linalg"
|
||||
import "core:strings"
|
||||
import "game:assets"
|
||||
import "game:container/spanpool"
|
||||
import "libs:tracy"
|
||||
@ -476,9 +475,6 @@ Suspension_Constraint_Ptr :: #soa^#soa[]Suspension_Constraint
|
||||
Engine_Ptr :: ^Engine
|
||||
Level_Geom_Ptr :: ^Level_Geom
|
||||
|
||||
_invalid_body: #soa[1]Body
|
||||
_invalid_body_slice := _invalid_body[:]
|
||||
|
||||
_invalid_suspension_constraint: #soa[1]Suspension_Constraint
|
||||
_invalid_suspension_constraint_slice := _invalid_suspension_constraint[:]
|
||||
|
||||
@ -507,8 +503,12 @@ flip_sim_state :: proc(scene: ^Scene) {
|
||||
|
||||
/// Returns pointer to soa slice. NEVER STORE IT
|
||||
get_body :: proc(sim_state: ^Sim_State, handle: Body_Handle) -> Body_Ptr {
|
||||
@(static) _invalid_body: #soa[1]Body
|
||||
@(static) _invalid_body_slice: #soa[]Body
|
||||
|
||||
index := int(handle) - 1
|
||||
if index < 0 || index >= len(sim_state.bodies_slice) {
|
||||
_invalid_body_slice = _invalid_body[:]
|
||||
_invalid_body_slice[0] = {
|
||||
alive = true,
|
||||
q = lg.QUATERNIONF32_IDENTITY,
|
||||
@ -602,7 +602,7 @@ Engine_Config :: struct {
|
||||
axle: Drive_Axle_Config,
|
||||
}
|
||||
|
||||
Level_Geometry_Asset :: distinct string
|
||||
Level_Geometry_Asset :: distinct name.Name
|
||||
|
||||
Level_Geometry_Mesh :: struct {
|
||||
vertices: []Vec3,
|
||||
@ -949,8 +949,10 @@ get_level_geom :: proc(sim_state: ^Sim_State, handle: Level_Geom_Handle) -> Leve
|
||||
|
||||
get_level_geom_data :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
handle: Level_Geom_Handle,
|
||||
) -> (
|
||||
blas: bvh.BVH,
|
||||
vertices: []Vec3,
|
||||
indices: []u16,
|
||||
) {
|
||||
@ -958,17 +960,28 @@ get_level_geom_data :: proc(
|
||||
|
||||
switch s in level_geom.source {
|
||||
case Level_Geom_Source_Local:
|
||||
blas.nodes = spanpool.resolve_slice(&sim_state.blas_nodes_pool, s.blas.nodes)
|
||||
blas.primitives = spanpool.resolve_slice(
|
||||
&sim_state.blas_primitives_pool,
|
||||
s.blas.primitives,
|
||||
)
|
||||
blas.nodes_used = i32(len(blas.nodes))
|
||||
vertices = spanpool.resolve_slice(&sim_state.geometry_vertices_pool, s.geometry.vertices)
|
||||
indices = spanpool.resolve_slice(&sim_state.geometry_indices_pool, s.geometry.indices)
|
||||
case Level_Geom_Source_Asset:
|
||||
loaded_bvh, reloaded := assets.get_bvh(
|
||||
sim_state.scene.assetman,
|
||||
strings.unsafe_string_to_cstring(name.to_string(s.assetpath)),
|
||||
)
|
||||
if reloaded {
|
||||
level_geom.aabb = bvh_aabb_to_phys_aabb(loaded_bvh.aabb)
|
||||
level_geom.aabb = aabb_transform(level_geom.aabb, level_geom.x, level_geom.q)
|
||||
loaded_bvh, ok := sim_cache.level_geom_asset_bvh[handle]
|
||||
|
||||
if !ok {
|
||||
reloaded: bool
|
||||
loaded_bvh, reloaded = assets.get_bvh(sim_state.scene.assetman, s.assetpath)
|
||||
if reloaded {
|
||||
level_geom.aabb = bvh_aabb_to_phys_aabb(loaded_bvh.aabb)
|
||||
level_geom.aabb = aabb_transform(level_geom.aabb, level_geom.x, level_geom.q)
|
||||
}
|
||||
// sim_cache.level_geom_asset_bvh[handle] = loaded_bvh
|
||||
}
|
||||
|
||||
blas = loaded_bvh.bvh
|
||||
vertices = loaded_bvh.vertices
|
||||
indices = loaded_bvh.indices
|
||||
}
|
||||
@ -976,28 +989,6 @@ get_level_geom_data :: proc(
|
||||
return
|
||||
}
|
||||
|
||||
get_level_geom_blas :: proc(sim_state: ^Sim_State, handle: Level_Geom_Handle) -> (bvh: bvh.BVH) {
|
||||
level_geom := get_level_geom(sim_state, handle)
|
||||
switch s in level_geom.source {
|
||||
case Level_Geom_Source_Local:
|
||||
bvh.nodes = spanpool.resolve_slice(&sim_state.blas_nodes_pool, s.blas.nodes)
|
||||
bvh.primitives = spanpool.resolve_slice(&sim_state.blas_primitives_pool, s.blas.primitives)
|
||||
bvh.nodes_used = i32(len(bvh.nodes))
|
||||
case Level_Geom_Source_Asset:
|
||||
loaded_bvh, reloaded := assets.get_bvh(
|
||||
sim_state.scene.assetman,
|
||||
strings.unsafe_string_to_cstring(name.to_string(s.assetpath)),
|
||||
)
|
||||
if reloaded {
|
||||
level_geom.aabb = bvh_aabb_to_phys_aabb(loaded_bvh.aabb)
|
||||
level_geom.aabb = aabb_transform(level_geom.aabb, level_geom.x, level_geom.q)
|
||||
}
|
||||
|
||||
bvh = loaded_bvh.bvh
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
update_level_geom_from_config :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
level_geom: Level_Geom_Ptr,
|
||||
@ -1063,13 +1054,10 @@ add_level_geom :: proc(sim_state: ^Sim_State, config: Level_Geom_Config) -> Leve
|
||||
level_geom.source = source
|
||||
case Level_Geometry_Asset:
|
||||
level_geom.source = Level_Geom_Source_Asset {
|
||||
assetpath = name.from_string(string(s)),
|
||||
assetpath = name.Name(s),
|
||||
}
|
||||
|
||||
bvh, _ := assets.get_bvh(
|
||||
sim_state.scene.assetman,
|
||||
strings.unsafe_string_to_cstring(string(s)),
|
||||
)
|
||||
bvh, _ := assets.get_bvh(sim_state.scene.assetman, name.Name(s))
|
||||
level_geom.aabb = AABB {
|
||||
center = (bvh.aabb.max + bvh.aabb.min) * 0.5,
|
||||
extent = (bvh.aabb.max - bvh.aabb.min) * 0.5,
|
||||
@ -1104,6 +1092,11 @@ remove_level_geom :: proc(sim_state: ^Sim_State, handle: Level_Geom_Handle) {
|
||||
spanpool.free(&sim_state.blas_primitives_pool, s.blas.primitives)
|
||||
case Level_Geom_Source_Asset:
|
||||
}
|
||||
|
||||
level_geom.alive = false
|
||||
level_geom.next_plus_one = sim_state.first_free_level_geom_plus_one
|
||||
sim_state.first_free_level_geom_plus_one = i32(handle)
|
||||
sim_state.num_level_geoms -= 1
|
||||
}
|
||||
|
||||
_get_first_free_body :: proc(sim_state: ^Sim_State) -> i32 {
|
||||
|
@ -11,6 +11,7 @@ import "core:math"
|
||||
import lg "core:math/linalg"
|
||||
import "core:math/rand"
|
||||
import "core:slice"
|
||||
import "game:assets"
|
||||
import "game:debug"
|
||||
import he "game:halfedge"
|
||||
import "libs:tracy"
|
||||
@ -174,8 +175,10 @@ dynamic_tlas_destroy :: proc(dyn_tlas: ^Dynamic_TLAS) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
raycasts_level :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
tlas: ^Static_TLAS,
|
||||
origin, dir: Vec3,
|
||||
distance := max(f32),
|
||||
@ -201,32 +204,31 @@ raycasts_level :: proc(
|
||||
int(tlas.bvh_tree.primitives[leaf_node.child_or_prim_start + j]),
|
||||
)
|
||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||
blas := get_level_geom_blas(sim_state, level_geom_handle)
|
||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
||||
blas, vertices, indices := get_level_geom_data(sim_state, sim_cache, level_geom_handle)
|
||||
|
||||
// TODO: transform ray into blas space and back
|
||||
|
||||
blas_it := bvh.iterator_intersect_leaf_ray(&blas, ray, distance)
|
||||
inv_q := lg.quaternion_inverse(level_geom.q)
|
||||
local_ray := ray
|
||||
local_ray.origin = lg.quaternion_mul_vector3(inv_q, ray.origin - level_geom.x)
|
||||
local_ray.dir = lg.quaternion_mul_vector3(inv_q, ray.dir)
|
||||
local_ray.dir_inv = 1.0 / local_ray.dir
|
||||
|
||||
blas_it := bvh.iterator_intersect_leaf_ray(&blas, local_ray, distance)
|
||||
for blas_leaf_node in bvh.iterator_intersect_leaf_next(&blas_it) {
|
||||
for k in 0 ..< blas_leaf_node.prim_len {
|
||||
tri_idx := int(blas.primitives[blas_leaf_node.child_or_prim_start + k])
|
||||
|
||||
tri := get_transformed_triangle(
|
||||
vertices,
|
||||
indices,
|
||||
tri_idx,
|
||||
level_geom.x,
|
||||
level_geom.q,
|
||||
)
|
||||
tri := get_triangle(vertices, indices, tri_idx)
|
||||
|
||||
hit_t, tmp_normal, _, ok := collision.intersect_ray_triangle(
|
||||
{origin, origin + dir},
|
||||
{local_ray.origin, local_ray.origin + local_ray.dir},
|
||||
tri,
|
||||
)
|
||||
|
||||
if ok && (!hit || hit_t < t) {
|
||||
t = hit_t
|
||||
normal = tmp_normal
|
||||
normal = lg.quaternion_mul_vector3(level_geom.q, tmp_normal)
|
||||
hit = true
|
||||
}
|
||||
}
|
||||
@ -294,6 +296,7 @@ raycast_bodies :: proc(
|
||||
|
||||
raycast :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
static_tlas: ^Static_TLAS,
|
||||
dyn_tlas: ^Dynamic_TLAS,
|
||||
origin, dir: Vec3,
|
||||
@ -305,7 +308,7 @@ raycast :: proc(
|
||||
) {
|
||||
t = distance
|
||||
|
||||
t1, normal1, hit1 := raycasts_level(sim_state, static_tlas, origin, dir, t)
|
||||
t1, normal1, hit1 := raycasts_level(sim_state, sim_cache, static_tlas, origin, dir, t)
|
||||
t2, normal2, hit2 := raycast_bodies(sim_state, dyn_tlas, origin, dir, t)
|
||||
|
||||
hit = hit1 || hit2
|
||||
@ -329,6 +332,14 @@ raycast :: proc(
|
||||
return
|
||||
}
|
||||
|
||||
// Cache used during simulation to avoid complex computations
|
||||
Sim_Cache :: struct {
|
||||
// Looking up bvh can be expensive because assetman touches the filesystem each time. We assume that during simulation it cannot change
|
||||
// so it's safe to cache
|
||||
level_geom_asset_bvh: map[Level_Geom_Handle]assets.Loaded_BVH,
|
||||
}
|
||||
|
||||
|
||||
get_triangle :: proc(vertices: []Vec3, indices: []u16, tri_idx: int) -> (tri: [3]Vec3) {
|
||||
i1, i2, i3 := indices[tri_idx * 3 + 0], indices[tri_idx * 3 + 1], indices[tri_idx * 3 + 2]
|
||||
tri[0], tri[1], tri[2] = vertices[i1], vertices[i2], vertices[i3]
|
||||
@ -361,6 +372,7 @@ get_triangle_aabb :: proc(tri: [3]Vec3) -> (aabb: bvh.AABB) {
|
||||
|
||||
remove_invalid_contacts :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
static_tlas: Static_TLAS,
|
||||
dyn_tlas: Dynamic_TLAS,
|
||||
) {
|
||||
@ -394,7 +406,11 @@ remove_invalid_contacts :: proc(
|
||||
|
||||
if !should_remove {
|
||||
tri_idx := int(contact.local_tri_idx)
|
||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
||||
_, vertices, indices := get_level_geom_data(
|
||||
sim_state,
|
||||
sim_cache,
|
||||
level_geom_handle,
|
||||
)
|
||||
should_remove |= tri_idx * 3 >= len(indices)
|
||||
|
||||
if !should_remove {
|
||||
@ -453,6 +469,7 @@ remove_invalid_contacts :: proc(
|
||||
// TODO: free intermediate temp allocs
|
||||
find_new_contacts :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
static_tlas: ^Static_TLAS,
|
||||
dyn_tlas: ^Dynamic_TLAS,
|
||||
) {
|
||||
@ -559,10 +576,16 @@ find_new_contacts :: proc(
|
||||
)
|
||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||
if level_geom.alive {
|
||||
blas := get_level_geom_blas(sim_state, level_geom_handle)
|
||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
||||
blas, vertices, indices := get_level_geom_data(
|
||||
sim_state,
|
||||
sim_cache,
|
||||
level_geom_handle,
|
||||
)
|
||||
|
||||
blas_it := bvh.iterator_intersect_leaf_aabb(&blas, body_aabb)
|
||||
blas_it := bvh.iterator_intersect_leaf_aabb(
|
||||
&blas,
|
||||
aabb_inv_transform(body_aabb, level_geom.x, level_geom.q),
|
||||
)
|
||||
for blas_leaf_node in bvh.iterator_intersect_leaf_next(&blas_it) {
|
||||
for k in 0 ..< blas_leaf_node.prim_len {
|
||||
tri_idx := int(
|
||||
@ -653,9 +676,16 @@ simulate :: proc(
|
||||
prune_immediate(scene)
|
||||
|
||||
copy_sim_state(get_next_sim_state(scene), get_sim_state(scene))
|
||||
|
||||
sim_state := get_next_sim_state(scene)
|
||||
|
||||
// runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||
|
||||
sim_cache: Sim_Cache
|
||||
sim_cache.level_geom_asset_bvh = make_map(
|
||||
map[Level_Geom_Handle]assets.Loaded_BVH,
|
||||
context.temp_allocator,
|
||||
)
|
||||
|
||||
num_steps := 0
|
||||
switch step_mode {
|
||||
case .Accumulated_Time:
|
||||
@ -666,11 +696,11 @@ simulate :: proc(
|
||||
state.accumulated_time -= config.timestep
|
||||
|
||||
if num_steps < MAX_STEPS {
|
||||
simulate_step(scene, sim_state, config)
|
||||
simulate_step(scene, sim_state, &sim_cache, config)
|
||||
}
|
||||
}
|
||||
case .Single:
|
||||
simulate_step(scene, get_next_sim_state(scene), config)
|
||||
simulate_step(scene, get_next_sim_state(scene), &sim_cache, config)
|
||||
num_steps += 1
|
||||
}
|
||||
|
||||
@ -718,7 +748,7 @@ Contact :: struct {
|
||||
applied_normal_correction: [4]f32,
|
||||
}
|
||||
|
||||
update_contacts :: proc(sim_state: ^Sim_State, static_tlas: ^Static_TLAS) {
|
||||
update_contacts :: proc(sim_state: ^Sim_State, sim_cache: ^Sim_Cache, static_tlas: ^Static_TLAS) {
|
||||
tracy.Zone()
|
||||
|
||||
temp := runtime.default_temp_allocator_temp_begin()
|
||||
@ -824,7 +854,7 @@ update_contacts :: proc(sim_state: ^Sim_State, static_tlas: ^Static_TLAS) {
|
||||
case .Body_vs_Level:
|
||||
level_geom_handle := Level_Geom_Handle(contact.b)
|
||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
||||
_, vertices, indices := get_level_geom_data(sim_state, sim_cache, level_geom_handle)
|
||||
tri := get_transformed_triangle(
|
||||
vertices,
|
||||
indices,
|
||||
@ -1232,6 +1262,7 @@ calculate_ground_vel :: proc(
|
||||
|
||||
pgs_solve_suspension :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
static_tlas: ^Static_TLAS,
|
||||
dyn_tlas: ^Dynamic_TLAS,
|
||||
config: Solver_Config,
|
||||
@ -1249,6 +1280,7 @@ pgs_solve_suspension :: proc(
|
||||
dir := body_local_to_world_vec(body, v.rel_dir)
|
||||
v.hit_t, v.hit_normal, v.hit = raycast(
|
||||
sim_state,
|
||||
sim_cache,
|
||||
static_tlas,
|
||||
dyn_tlas,
|
||||
wheel_world_pos,
|
||||
@ -1438,6 +1470,7 @@ pgs_solve_suspension :: proc(
|
||||
|
||||
pgs_substep :: proc(
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
static_tlas: ^Static_TLAS,
|
||||
dyn_tlas: ^Dynamic_TLAS,
|
||||
config: Solver_Config,
|
||||
@ -1559,7 +1592,7 @@ pgs_substep :: proc(
|
||||
apply_bias := true
|
||||
pgs_solve_contacts(sim_state, config, dt, inv_dt, apply_bias)
|
||||
pgs_solve_engines(sim_state, config, dt, inv_dt)
|
||||
pgs_solve_suspension(sim_state, static_tlas, dyn_tlas, config, dt, inv_dt)
|
||||
pgs_solve_suspension(sim_state, sim_cache, static_tlas, dyn_tlas, config, dt, inv_dt)
|
||||
|
||||
for i in 0 ..< len(sim_state.bodies_slice) {
|
||||
body := &sim_state.bodies_slice[i]
|
||||
@ -1600,7 +1633,12 @@ pgs_substep :: proc(
|
||||
// pgs_solve_suspension(sim_state, config, dt, inv_dt, apply_bias)
|
||||
}
|
||||
|
||||
simulate_step :: proc(scene: ^Scene, sim_state: ^Sim_State, config: Solver_Config) {
|
||||
simulate_step :: proc(
|
||||
scene: ^Scene,
|
||||
sim_state: ^Sim_State,
|
||||
sim_cache: ^Sim_Cache,
|
||||
config: Solver_Config,
|
||||
) {
|
||||
tracy.Zone()
|
||||
|
||||
substeps := config.substreps_minus_one + 1
|
||||
@ -1614,9 +1652,9 @@ simulate_step :: proc(scene: ^Scene, sim_state: ^Sim_State, config: Solver_Confi
|
||||
build_static_tlas(sim_state, &sim_state.static_tlas)
|
||||
build_dynamic_tlas(sim_state, config, &sim_state.dynamic_tlas)
|
||||
|
||||
remove_invalid_contacts(sim_state, sim_state.static_tlas, sim_state.dynamic_tlas)
|
||||
find_new_contacts(sim_state, &sim_state.static_tlas, &sim_state.dynamic_tlas)
|
||||
update_contacts(sim_state, &sim_state.static_tlas)
|
||||
remove_invalid_contacts(sim_state, sim_cache, sim_state.static_tlas, sim_state.dynamic_tlas)
|
||||
find_new_contacts(sim_state, sim_cache, &sim_state.static_tlas, &sim_state.dynamic_tlas)
|
||||
update_contacts(sim_state, sim_cache, &sim_state.static_tlas)
|
||||
|
||||
Solver :: enum {
|
||||
XPBD,
|
||||
@ -1634,6 +1672,7 @@ simulate_step :: proc(scene: ^Scene, sim_state: ^Sim_State, config: Solver_Confi
|
||||
for _ in 0 ..< substeps {
|
||||
pgs_substep(
|
||||
sim_state,
|
||||
sim_cache,
|
||||
&sim_state.static_tlas,
|
||||
&sim_state.dynamic_tlas,
|
||||
config,
|
||||
|
@ -220,4 +220,4 @@ EaseElasticInOut :: proc(t, b, c, d: f32) -> f32 {
|
||||
|
||||
postFix := a*math.pow(2.0, -10.0*t)
|
||||
return (postFix*math.sin((t*d-s)*(2.0*PI)/p)*0.5 + c + b)
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -523,7 +523,7 @@ Vector3Unproject :: proc "c" (source: Vector3, projection: Matrix, view: Matrix)
|
||||
|
||||
quat: Quaternion
|
||||
quat.x = source.x
|
||||
quat.y = source.z
|
||||
quat.y = source.y
|
||||
quat.z = source.z
|
||||
quat.w = 1
|
||||
|
||||
@ -831,8 +831,8 @@ fmaxf :: proc "contextless" (x, y: f32) -> f32 {
|
||||
return x
|
||||
}
|
||||
|
||||
if math.signbit(x) != math.signbit(y) {
|
||||
return y if math.signbit(x) else x
|
||||
if math.sign_bit(x) != math.sign_bit(y) {
|
||||
return y if math.sign_bit(x) else x
|
||||
}
|
||||
|
||||
return y if x < y else x
|
||||
|
@ -107,8 +107,8 @@
|
||||
|
||||
package rlgl
|
||||
|
||||
import rl "../."
|
||||
import "core:c"
|
||||
import rl "../."
|
||||
|
||||
VERSION :: "5.0"
|
||||
|
||||
@ -132,17 +132,17 @@ when ODIN_OS == .Windows {
|
||||
foreign import lib "system:raylib"
|
||||
}
|
||||
|
||||
GRAPHICS_API_OPENGL_11 :: false
|
||||
GRAPHICS_API_OPENGL_21 :: true
|
||||
GRAPHICS_API_OPENGL_33 :: GRAPHICS_API_OPENGL_21 // default currently
|
||||
GRAPHICS_API_OPENGL_11 :: false
|
||||
GRAPHICS_API_OPENGL_21 :: true
|
||||
GRAPHICS_API_OPENGL_33 :: GRAPHICS_API_OPENGL_21 // default currently
|
||||
GRAPHICS_API_OPENGL_ES2 :: false
|
||||
GRAPHICS_API_OPENGL_43 :: false
|
||||
GRAPHICS_API_OPENGL_43 :: false
|
||||
GRAPHICS_API_OPENGL_ES3 :: false
|
||||
|
||||
when GRAPHICS_API_OPENGL_ES3 {
|
||||
GRAPHICS_API_OPENGL_ES2 :: true
|
||||
}
|
||||
|
||||
|
||||
when !GRAPHICS_API_OPENGL_ES2 {
|
||||
// This is the maximum amount of elements (quads) per batch
|
||||
// NOTE: Be careful with text, every letter maps to a quad
|
||||
@ -154,100 +154,100 @@ when !GRAPHICS_API_OPENGL_ES2 {
|
||||
DEFAULT_BATCH_BUFFER_ELEMENTS :: 2048
|
||||
}
|
||||
|
||||
DEFAULT_BATCH_BUFFERS :: 1 // Default number of batch buffers (multi-buffering)
|
||||
DEFAULT_BATCH_DRAWCALLS :: 256 // Default number of batch draw calls (by state changes: mode, texture)
|
||||
DEFAULT_BATCH_MAX_TEXTURE_UNITS :: 4 // Maximum number of additional textures that can be activated on batch drawing (SetShaderValueTexture())
|
||||
DEFAULT_BATCH_BUFFERS :: 1 // Default number of batch buffers (multi-buffering)
|
||||
DEFAULT_BATCH_DRAWCALLS :: 256 // Default number of batch draw calls (by state changes: mode, texture)
|
||||
DEFAULT_BATCH_MAX_TEXTURE_UNITS :: 4 // Maximum number of additional textures that can be activated on batch drawing (SetShaderValueTexture())
|
||||
|
||||
// Internal Matrix stack
|
||||
MAX_MATRIX_STACK_SIZE :: 32 // Maximum size of Matrix stack
|
||||
MAX_MATRIX_STACK_SIZE :: 32 // Maximum size of Matrix stack
|
||||
|
||||
// Shader limits
|
||||
MAX_SHADER_LOCATIONS :: 32 // Maximum number of shader locations supported
|
||||
MAX_SHADER_LOCATIONS :: 32 // Maximum number of shader locations supported
|
||||
|
||||
// Projection matrix culling
|
||||
CULL_DISTANCE_NEAR :: 0.01 // Default near cull distance
|
||||
CULL_DISTANCE_FAR :: 1000.0 // Default far cull distance
|
||||
CULL_DISTANCE_NEAR :: 0.01 // Default near cull distance
|
||||
CULL_DISTANCE_FAR :: 1000.0 // Default far cull distance
|
||||
|
||||
// Texture parameters (equivalent to OpenGL defines)
|
||||
TEXTURE_WRAP_S :: 0x2802 // GL_TEXTURE_WRAP_S
|
||||
TEXTURE_WRAP_T :: 0x2803 // GL_TEXTURE_WRAP_T
|
||||
TEXTURE_MAG_FILTER :: 0x2800 // GL_TEXTURE_MAG_FILTER
|
||||
TEXTURE_MIN_FILTER :: 0x2801 // GL_TEXTURE_MIN_FILTER
|
||||
TEXTURE_WRAP_S :: 0x2802 // GL_TEXTURE_WRAP_S
|
||||
TEXTURE_WRAP_T :: 0x2803 // GL_TEXTURE_WRAP_T
|
||||
TEXTURE_MAG_FILTER :: 0x2800 // GL_TEXTURE_MAG_FILTER
|
||||
TEXTURE_MIN_FILTER :: 0x2801 // GL_TEXTURE_MIN_FILTER
|
||||
|
||||
TEXTURE_FILTER_NEAREST :: 0x2600 // GL_NEAREST
|
||||
TEXTURE_FILTER_LINEAR :: 0x2601 // GL_LINEAR
|
||||
TEXTURE_FILTER_MIP_NEAREST :: 0x2700 // GL_NEAREST_MIPMAP_NEAREST
|
||||
TEXTURE_FILTER_NEAREST_MIP_LINEAR :: 0x2702 // GL_NEAREST_MIPMAP_LINEAR
|
||||
TEXTURE_FILTER_LINEAR_MIP_NEAREST :: 0x2701 // GL_LINEAR_MIPMAP_NEAREST
|
||||
TEXTURE_FILTER_MIP_LINEAR :: 0x2703 // GL_LINEAR_MIPMAP_LINEAR
|
||||
TEXTURE_FILTER_ANISOTROPIC :: 0x3000 // Anisotropic filter (custom identifier)
|
||||
TEXTURE_FILTER_NEAREST :: 0x2600 // GL_NEAREST
|
||||
TEXTURE_FILTER_LINEAR :: 0x2601 // GL_LINEAR
|
||||
TEXTURE_FILTER_MIP_NEAREST :: 0x2700 // GL_NEAREST_MIPMAP_NEAREST
|
||||
TEXTURE_FILTER_NEAREST_MIP_LINEAR :: 0x2702 // GL_NEAREST_MIPMAP_LINEAR
|
||||
TEXTURE_FILTER_LINEAR_MIP_NEAREST :: 0x2701 // GL_LINEAR_MIPMAP_NEAREST
|
||||
TEXTURE_FILTER_MIP_LINEAR :: 0x2703 // GL_LINEAR_MIPMAP_LINEAR
|
||||
TEXTURE_FILTER_ANISOTROPIC :: 0x3000 // Anisotropic filter (custom identifier)
|
||||
|
||||
TEXTURE_WRAP_REPEAT :: 0x2901 // GL_REPEAT
|
||||
TEXTURE_WRAP_CLAMP :: 0x812F // GL_CLAMP_TO_EDGE
|
||||
TEXTURE_WRAP_MIRROR_REPEAT :: 0x8370 // GL_MIRRORED_REPEAT
|
||||
TEXTURE_WRAP_MIRROR_CLAMP :: 0x8742 // GL_MIRROR_CLAMP_EXT
|
||||
TEXTURE_WRAP_REPEAT :: 0x2901 // GL_REPEAT
|
||||
TEXTURE_WRAP_CLAMP :: 0x812F // GL_CLAMP_TO_EDGE
|
||||
TEXTURE_WRAP_MIRROR_REPEAT :: 0x8370 // GL_MIRRORED_REPEAT
|
||||
TEXTURE_WRAP_MIRROR_CLAMP :: 0x8742 // GL_MIRROR_CLAMP_EXT
|
||||
|
||||
// Matrix modes (equivalent to OpenGL)
|
||||
MODELVIEW :: 0x1700 // GL_MODELVIEW
|
||||
PROJECTION :: 0x1701 // GL_PROJECTION
|
||||
TEXTURE :: 0x1702 // GL_TEXTURE
|
||||
MODELVIEW :: 0x1700 // GL_MODELVIEW
|
||||
PROJECTION :: 0x1701 // GL_PROJECTION
|
||||
TEXTURE :: 0x1702 // GL_TEXTURE
|
||||
|
||||
// Primitive assembly draw modes
|
||||
LINES :: 0x0001 // GL_LINES
|
||||
TRIANGLES :: 0x0004 // GL_TRIANGLES
|
||||
QUADS :: 0x0007 // GL_QUADS
|
||||
LINES :: 0x0001 // GL_LINES
|
||||
TRIANGLES :: 0x0004 // GL_TRIANGLES
|
||||
QUADS :: 0x0007 // GL_QUADS
|
||||
|
||||
// GL equivalent data types
|
||||
UNSIGNED_BYTE :: 0x1401 // GL_UNSIGNED_BYTE
|
||||
FLOAT :: 0x1406 // GL_FLOAT
|
||||
UNSIGNED_BYTE :: 0x1401 // GL_UNSIGNED_BYTE
|
||||
FLOAT :: 0x1406 // GL_FLOAT
|
||||
|
||||
// Buffer usage hint
|
||||
STREAM_DRAW :: 0x88E0 // GL_STREAM_DRAW
|
||||
STREAM_READ :: 0x88E1 // GL_STREAM_READ
|
||||
STREAM_COPY :: 0x88E2 // GL_STREAM_COPY
|
||||
STATIC_DRAW :: 0x88E4 // GL_STATIC_DRAW
|
||||
STATIC_READ :: 0x88E5 // GL_STATIC_READ
|
||||
STATIC_COPY :: 0x88E6 // GL_STATIC_COPY
|
||||
DYNAMIC_DRAW :: 0x88E8 // GL_DYNAMIC_DRAW
|
||||
DYNAMIC_READ :: 0x88E9 // GL_DYNAMIC_READ
|
||||
DYNAMIC_COPY :: 0x88EA // GL_DYNAMIC_COPY
|
||||
STREAM_DRAW :: 0x88E0 // GL_STREAM_DRAW
|
||||
STREAM_READ :: 0x88E1 // GL_STREAM_READ
|
||||
STREAM_COPY :: 0x88E2 // GL_STREAM_COPY
|
||||
STATIC_DRAW :: 0x88E4 // GL_STATIC_DRAW
|
||||
STATIC_READ :: 0x88E5 // GL_STATIC_READ
|
||||
STATIC_COPY :: 0x88E6 // GL_STATIC_COPY
|
||||
DYNAMIC_DRAW :: 0x88E8 // GL_DYNAMIC_DRAW
|
||||
DYNAMIC_READ :: 0x88E9 // GL_DYNAMIC_READ
|
||||
DYNAMIC_COPY :: 0x88EA // GL_DYNAMIC_COPY
|
||||
|
||||
// GL Shader type
|
||||
FRAGMENT_SHADER :: 0x8B30 // GL_FRAGMENT_SHADER
|
||||
VERTEX_SHADER :: 0x8B31 // GL_VERTEX_SHADER
|
||||
COMPUTE_SHADER :: 0x91B9 // GL_COMPUTE_SHADER
|
||||
FRAGMENT_SHADER :: 0x8B30 // GL_FRAGMENT_SHADER
|
||||
VERTEX_SHADER :: 0x8B31 // GL_VERTEX_SHADER
|
||||
COMPUTE_SHADER :: 0x91B9 // GL_COMPUTE_SHADER
|
||||
|
||||
// GL blending factors
|
||||
ZERO :: 0 // GL_ZERO
|
||||
ONE :: 1 // GL_ONE
|
||||
SRC_COLOR :: 0x0300 // GL_SRC_COLOR
|
||||
ONE_MINUS_SRC_COLOR :: 0x0301 // GL_ONE_MINUS_SRC_COLOR
|
||||
SRC_ALPHA :: 0x0302 // GL_SRC_ALPHA
|
||||
ONE_MINUS_SRC_ALPHA :: 0x0303 // GL_ONE_MINUS_SRC_ALPHA
|
||||
DST_ALPHA :: 0x0304 // GL_DST_ALPHA
|
||||
ONE_MINUS_DST_ALPHA :: 0x0305 // GL_ONE_MINUS_DST_ALPHA
|
||||
DST_COLOR :: 0x0306 // GL_DST_COLOR
|
||||
ONE_MINUS_DST_COLOR :: 0x0307 // GL_ONE_MINUS_DST_COLOR
|
||||
SRC_ALPHA_SATURATE :: 0x0308 // GL_SRC_ALPHA_SATURATE
|
||||
CONSTANT_COLOR :: 0x8001 // GL_CONSTANT_COLOR
|
||||
ONE_MINUS_CONSTANT_COLOR :: 0x8002 // GL_ONE_MINUS_CONSTANT_COLOR
|
||||
CONSTANT_ALPHA :: 0x8003 // GL_CONSTANT_ALPHA
|
||||
ONE_MINUS_CONSTANT_ALPHA :: 0x8004 // GL_ONE_MINUS_CONSTANT_ALPHA
|
||||
ZERO :: 0 // GL_ZERO
|
||||
ONE :: 1 // GL_ONE
|
||||
SRC_COLOR :: 0x0300 // GL_SRC_COLOR
|
||||
ONE_MINUS_SRC_COLOR :: 0x0301 // GL_ONE_MINUS_SRC_COLOR
|
||||
SRC_ALPHA :: 0x0302 // GL_SRC_ALPHA
|
||||
ONE_MINUS_SRC_ALPHA :: 0x0303 // GL_ONE_MINUS_SRC_ALPHA
|
||||
DST_ALPHA :: 0x0304 // GL_DST_ALPHA
|
||||
ONE_MINUS_DST_ALPHA :: 0x0305 // GL_ONE_MINUS_DST_ALPHA
|
||||
DST_COLOR :: 0x0306 // GL_DST_COLOR
|
||||
ONE_MINUS_DST_COLOR :: 0x0307 // GL_ONE_MINUS_DST_COLOR
|
||||
SRC_ALPHA_SATURATE :: 0x0308 // GL_SRC_ALPHA_SATURATE
|
||||
CONSTANT_COLOR :: 0x8001 // GL_CONSTANT_COLOR
|
||||
ONE_MINUS_CONSTANT_COLOR :: 0x8002 // GL_ONE_MINUS_CONSTANT_COLOR
|
||||
CONSTANT_ALPHA :: 0x8003 // GL_CONSTANT_ALPHA
|
||||
ONE_MINUS_CONSTANT_ALPHA :: 0x8004 // GL_ONE_MINUS_CONSTANT_ALPHA
|
||||
|
||||
// GL blending functions/equations
|
||||
FUNC_ADD :: 0x8006 // GL_FUNC_ADD
|
||||
MIN :: 0x8007 // GL_MIN
|
||||
MAX :: 0x8008 // GL_MAX
|
||||
FUNC_SUBTRACT :: 0x800A // GL_FUNC_SUBTRACT
|
||||
FUNC_REVERSE_SUBTRACT :: 0x800B // GL_FUNC_REVERSE_SUBTRACT
|
||||
BLEND_EQUATION :: 0x8009 // GL_BLEND_EQUATION
|
||||
BLEND_EQUATION_RGB :: 0x8009 // GL_BLEND_EQUATION_RGB // (Same as BLEND_EQUATION)
|
||||
BLEND_EQUATION_ALPHA :: 0x883D // GL_BLEND_EQUATION_ALPHA
|
||||
BLEND_DST_RGB :: 0x80C8 // GL_BLEND_DST_RGB
|
||||
BLEND_SRC_RGB :: 0x80C9 // GL_BLEND_SRC_RGB
|
||||
BLEND_DST_ALPHA :: 0x80CA // GL_BLEND_DST_ALPHA
|
||||
BLEND_SRC_ALPHA :: 0x80CB // GL_BLEND_SRC_ALPHA
|
||||
BLEND_COLOR :: 0x8005 // GL_BLEND_COLOR
|
||||
FUNC_ADD :: 0x8006 // GL_FUNC_ADD
|
||||
MIN :: 0x8007 // GL_MIN
|
||||
MAX :: 0x8008 // GL_MAX
|
||||
FUNC_SUBTRACT :: 0x800A // GL_FUNC_SUBTRACT
|
||||
FUNC_REVERSE_SUBTRACT :: 0x800B // GL_FUNC_REVERSE_SUBTRACT
|
||||
BLEND_EQUATION :: 0x8009 // GL_BLEND_EQUATION
|
||||
BLEND_EQUATION_RGB :: 0x8009 // GL_BLEND_EQUATION_RGB // (Same as BLEND_EQUATION)
|
||||
BLEND_EQUATION_ALPHA :: 0x883D // GL_BLEND_EQUATION_ALPHA
|
||||
BLEND_DST_RGB :: 0x80C8 // GL_BLEND_DST_RGB
|
||||
BLEND_SRC_RGB :: 0x80C9 // GL_BLEND_SRC_RGB
|
||||
BLEND_DST_ALPHA :: 0x80CA // GL_BLEND_DST_ALPHA
|
||||
BLEND_SRC_ALPHA :: 0x80CB // GL_BLEND_SRC_ALPHA
|
||||
BLEND_COLOR :: 0x8005 // GL_BLEND_COLOR
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
@ -258,13 +258,14 @@ VertexBufferIndexType :: c.ushort when GRAPHICS_API_OPENGL_ES2 else c.uint
|
||||
|
||||
// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
|
||||
VertexBuffer :: struct {
|
||||
elementCount: c.int, // Number of elements in the buffer (QUADS)
|
||||
vertices: [^]f32, // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||
texcoords: [^]f32, // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||
colors: [^]u8, // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||
indices: [^]VertexBufferIndexType, // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
|
||||
vaoId: c.uint, // OpenGL Vertex Array Object id
|
||||
vboId: [4]c.uint, // OpenGL Vertex Buffer Objects id (4 types of vertex data)
|
||||
elementCount: c.int, // Number of elements in the buffer (QUADS)
|
||||
|
||||
vertices: [^]f32, // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||
texcoords: [^]f32, // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||
colors: [^]u8, // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||
indices: [^]VertexBufferIndexType, // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
|
||||
vaoId: c.uint, // OpenGL Vertex Array Object id
|
||||
vboId: [4]c.uint, // OpenGL Vertex Buffer Objects id (4 types of vertex data)
|
||||
}
|
||||
|
||||
// Draw call type
|
||||
@ -272,30 +273,31 @@ VertexBuffer :: struct {
|
||||
// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any
|
||||
// of those state-change happens (this is done in core module)
|
||||
DrawCall :: struct {
|
||||
mode: c.int, // Drawing mode: LINES, TRIANGLES, QUADS
|
||||
vertexCount: c.int, // Number of vertex of the draw
|
||||
vertexAlignment: c.int, // Number of vertex required for index alignment (LINES, TRIANGLES)
|
||||
textureId: c.uint, // Texture id to be used on the draw -> Use to create new draw call if changes
|
||||
mode: c.int, // Drawing mode: LINES, TRIANGLES, QUADS
|
||||
vertexCount: c.int, // Number of vertex of the draw
|
||||
vertexAlignment: c.int, // Number of vertex required for index alignment (LINES, TRIANGLES)
|
||||
textureId: c.uint, // Texture id to be used on the draw -> Use to create new draw call if changes
|
||||
}
|
||||
|
||||
// RenderBatch type
|
||||
RenderBatch :: struct {
|
||||
bufferCount: c.int, // Number of vertex buffers (multi-buffering support)
|
||||
currentBuffer: c.int, // Current buffer tracking in case of multi-buffering
|
||||
bufferCount: c.int, // Number of vertex buffers (multi-buffering support)
|
||||
currentBuffer: c.int, // Current buffer tracking in case of multi-buffering
|
||||
vertexBuffer: [^]VertexBuffer, // Dynamic buffer(s) for vertex data
|
||||
draws: [^]DrawCall, // Draw calls array, depends on textureId
|
||||
drawCounter: c.int, // Draw calls counter
|
||||
currentDepth: f32, // Current depth value for next draw
|
||||
|
||||
draws: [^]DrawCall, // Draw calls array, depends on textureId
|
||||
drawCounter: c.int, // Draw calls counter
|
||||
currentDepth: f32, // Current depth value for next draw
|
||||
}
|
||||
|
||||
// OpenGL version
|
||||
GlVersion :: enum c.int {
|
||||
OPENGL_11 = 1, // OpenGL 1.1
|
||||
OPENGL_21, // OpenGL 2.1 (GLSL 120)
|
||||
OPENGL_33, // OpenGL 3.3 (GLSL 330)
|
||||
OPENGL_43, // OpenGL 4.3 (using GLSL 330)
|
||||
OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100)
|
||||
OPENGL_ES_30, // OpenGL ES 3.0 (GLSL 300 es)
|
||||
OPENGL_11 = 1, // OpenGL 1.1
|
||||
OPENGL_21, // OpenGL 2.1 (GLSL 120)
|
||||
OPENGL_33, // OpenGL 3.3 (GLSL 330)
|
||||
OPENGL_43, // OpenGL 4.3 (using GLSL 330)
|
||||
OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100)
|
||||
OPENGL_ES_30, // OpenGL ES 3.0 (GLSL 300 es)
|
||||
}
|
||||
|
||||
PixelFormat :: rl.PixelFormat
|
||||
@ -306,25 +308,25 @@ ShaderUniformDataType :: rl.ShaderUniformDataType
|
||||
|
||||
// Shader attribute data types
|
||||
ShaderAttributeDataType :: enum c.int {
|
||||
FLOAT = 0, // Shader attribute type: float
|
||||
VEC2, // Shader attribute type: vec2 (2 float)
|
||||
VEC3, // Shader attribute type: vec3 (3 float)
|
||||
VEC4, // Shader attribute type: vec4 (4 float)
|
||||
FLOAT = 0, // Shader attribute type: float
|
||||
VEC2, // Shader attribute type: vec2 (2 float)
|
||||
VEC3, // Shader attribute type: vec3 (3 float)
|
||||
VEC4, // Shader attribute type: vec4 (4 float)
|
||||
}
|
||||
|
||||
// Framebuffer attachment type
|
||||
// NOTE: By default up to 8 color channels defined, but it can be more
|
||||
FramebufferAttachType :: enum c.int {
|
||||
COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
|
||||
COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1
|
||||
COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2
|
||||
COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3
|
||||
COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4
|
||||
COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5
|
||||
COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6
|
||||
COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7
|
||||
DEPTH = 100, // Framebuffer attachment type: depth
|
||||
STENCIL = 200, // Framebuffer attachment type: stencil
|
||||
COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
|
||||
COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1
|
||||
COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2
|
||||
COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3
|
||||
COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4
|
||||
COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5
|
||||
COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6
|
||||
COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7
|
||||
DEPTH = 100, // Framebuffer attachment type: depth
|
||||
STENCIL = 200, // Framebuffer attachment type: stencil
|
||||
}
|
||||
|
||||
// Framebuffer texture attachment type
|
||||
@ -335,8 +337,8 @@ FramebufferAttachTextureType :: enum c.int {
|
||||
CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side
|
||||
CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side
|
||||
CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side
|
||||
TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d
|
||||
RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
|
||||
TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d
|
||||
RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
|
||||
}
|
||||
|
||||
CullMode :: enum c.int {
|
||||
@ -346,37 +348,39 @@ CullMode :: enum c.int {
|
||||
|
||||
Matrix :: rl.Matrix
|
||||
|
||||
@(default_calling_convention = "c", link_prefix = "rl")
|
||||
@(default_calling_convention="c", link_prefix="rl")
|
||||
foreign lib {
|
||||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration - Matrix operations
|
||||
//------------------------------------------------------------------------------------
|
||||
MatrixMode :: proc(mode: c.int) --- // Choose the current matrix to be transformed
|
||||
PushMatrix :: proc() --- // Push the current matrix to stack
|
||||
PopMatrix :: proc() --- // Pop lattest inserted matrix from stack
|
||||
LoadIdentity :: proc() --- // Reset current matrix to identity matrix
|
||||
Translatef :: proc(x, y, z: f32) --- // Multiply the current matrix by a translation matrix
|
||||
Rotatef :: proc(angleDeg: f32, x, y, z: f32) --- // Multiply the current matrix by a rotation matrix
|
||||
Scalef :: proc(x, y, z: f32) --- // Multiply the current matrix by a scaling matrix
|
||||
MultMatrixf :: proc(matf: [^]f32) --- // Multiply the current matrix by another matrix
|
||||
Frustum :: proc(left, right, bottom, top, znear, zfar: f64) ---
|
||||
Ortho :: proc(left, right, bottom, top, znear, zfar: f64) ---
|
||||
Viewport :: proc(x, y, width, height: c.int) --- // Set the viewport area
|
||||
SetClipPlanes :: proc(nearPlane, farPlane: f64) --- // Set clip planes
|
||||
MatrixMode :: proc(mode: c.int) --- // Choose the current matrix to be transformed
|
||||
PushMatrix :: proc() --- // Push the current matrix to stack
|
||||
PopMatrix :: proc() --- // Pop lattest inserted matrix from stack
|
||||
LoadIdentity :: proc() --- // Reset current matrix to identity matrix
|
||||
Translatef :: proc(x, y, z: f32) --- // Multiply the current matrix by a translation matrix
|
||||
Rotatef :: proc(angleDeg: f32, x, y, z: f32) --- // Multiply the current matrix by a rotation matrix
|
||||
Scalef :: proc(x, y, z: f32) --- // Multiply the current matrix by a scaling matrix
|
||||
MultMatrixf :: proc(matf: [^]f32) --- // Multiply the current matrix by another matrix
|
||||
Frustum :: proc(left, right, bottom, top, znear, zfar: f64) ---
|
||||
Ortho :: proc(left, right, bottom, top, znear, zfar: f64) ---
|
||||
Viewport :: proc(x, y, width, height: c.int) --- // Set the viewport area
|
||||
SetClipPlanes :: proc(near, far: f64) --- // Set clip planes distances
|
||||
GetCullDistanceNear :: proc() -> f64 --- // Get cull plane distance near
|
||||
GetCullDistanceFar :: proc() -> f64 --- // Get cull plane distance far
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration - Vertex level operations
|
||||
//------------------------------------------------------------------------------------
|
||||
Begin :: proc(mode: c.int) --- // Initialize drawing mode (how to organize vertex)
|
||||
End :: proc() --- // Finish vertex providing
|
||||
Vertex2i :: proc(x, y: c.int) --- // Define one vertex (position) - 2 int
|
||||
Vertex2f :: proc(x, y: f32) --- // Define one vertex (position) - 2 f32
|
||||
Vertex3f :: proc(x, y, z: f32) --- // Define one vertex (position) - 3 f32
|
||||
TexCoord2f :: proc(x, y: f32) --- // Define one vertex (texture coordinate) - 2 f32
|
||||
Normal3f :: proc(x, y, z: f32) --- // Define one vertex (normal) - 3 f32
|
||||
Color4ub :: proc(r, g, b, a: u8) --- // Define one vertex (color) - 4 byte
|
||||
Color3f :: proc(x, y, z: f32) --- // Define one vertex (color) - 3 f32
|
||||
Color4f :: proc(x, y, z, w: f32) --- // Define one vertex (color) - 4 f32
|
||||
Begin :: proc(mode: c.int) --- // Initialize drawing mode (how to organize vertex)
|
||||
End :: proc() --- // Finish vertex providing
|
||||
Vertex2i :: proc(x, y: c.int) --- // Define one vertex (position) - 2 int
|
||||
Vertex2f :: proc(x, y: f32) --- // Define one vertex (position) - 2 f32
|
||||
Vertex3f :: proc(x, y, z: f32) --- // Define one vertex (position) - 3 f32
|
||||
TexCoord2f :: proc(x, y: f32) --- // Define one vertex (texture coordinate) - 2 f32
|
||||
Normal3f :: proc(x, y, z: f32) --- // Define one vertex (normal) - 3 f32
|
||||
Color4ub :: proc(r, g, b, a: u8) --- // Define one vertex (color) - 4 byte
|
||||
Color3f :: proc(x, y, z: f32) --- // Define one vertex (color) - 3 f32
|
||||
Color4f :: proc(x, y, z, w: f32) --- // Define one vertex (color) - 4 f32
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration - OpenGL style functions (common to 1.1, 3.3+, ES2)
|
||||
@ -385,176 +389,176 @@ foreign lib {
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Vertex buffers state
|
||||
EnableVertexArray :: proc(vaoId: c.uint) -> bool --- // Enable vertex array (VAO, if supported)
|
||||
DisableVertexArray :: proc() --- // Disable vertex array (VAO, if supported)
|
||||
EnableVertexBuffer :: proc(id: c.uint) --- // Enable vertex buffer (VBO)
|
||||
DisableVertexBuffer :: proc() --- // Disable vertex buffer (VBO)
|
||||
EnableVertexBufferElement :: proc(id: c.uint) --- // Enable vertex buffer element (VBO element)
|
||||
DisableVertexBufferElement :: proc() --- // Disable vertex buffer element (VBO element)
|
||||
EnableVertexAttribute :: proc(index: c.uint) --- // Enable vertex attribute index
|
||||
DisableVertexAttribute :: proc(index: c.uint) --- // Disable vertex attribute index
|
||||
EnableVertexArray :: proc(vaoId: c.uint) -> bool --- // Enable vertex array (VAO, if supported)
|
||||
DisableVertexArray :: proc() --- // Disable vertex array (VAO, if supported)
|
||||
EnableVertexBuffer :: proc(id: c.uint) --- // Enable vertex buffer (VBO)
|
||||
DisableVertexBuffer :: proc() --- // Disable vertex buffer (VBO)
|
||||
EnableVertexBufferElement :: proc(id: c.uint) --- // Enable vertex buffer element (VBO element)
|
||||
DisableVertexBufferElement :: proc() --- // Disable vertex buffer element (VBO element)
|
||||
EnableVertexAttribute :: proc(index: c.uint) --- // Enable vertex attribute index
|
||||
DisableVertexAttribute :: proc(index: c.uint) --- // Disable vertex attribute index
|
||||
when GRAPHICS_API_OPENGL_11 {
|
||||
EnableStatePointer :: proc(vertexAttribType: c.int, buffer: rawptr) ---
|
||||
DisableStatePointer :: proc(vertexAttribType: c.int) ---
|
||||
}
|
||||
|
||||
// Textures state
|
||||
ActiveTextureSlot :: proc(slot: c.int) --- // Select and active a texture slot
|
||||
EnableTexture :: proc(id: c.uint) --- // Enable texture
|
||||
DisableTexture :: proc() --- // Disable texture
|
||||
EnableTextureCubemap :: proc(id: c.uint) --- // Enable texture cubemap
|
||||
DisableTextureCubemap :: proc() --- // Disable texture cubemap
|
||||
TextureParameters :: proc(id: c.uint, param: c.int, value: c.int) --- // Set texture parameters (filter, wrap)
|
||||
CubemapParameters :: proc(id: i32, param: c.int, value: c.int) --- // Set cubemap parameters (filter, wrap)
|
||||
ActiveTextureSlot :: proc(slot: c.int) --- // Select and active a texture slot
|
||||
EnableTexture :: proc(id: c.uint) --- // Enable texture
|
||||
DisableTexture :: proc() --- // Disable texture
|
||||
EnableTextureCubemap :: proc(id: c.uint) --- // Enable texture cubemap
|
||||
DisableTextureCubemap :: proc() --- // Disable texture cubemap
|
||||
TextureParameters :: proc(id: c.uint, param: c.int, value: c.int) --- // Set texture parameters (filter, wrap)
|
||||
CubemapParameters :: proc(id: i32, param: c.int, value: c.int) --- // Set cubemap parameters (filter, wrap)
|
||||
|
||||
// Shader state
|
||||
EnableShader :: proc(id: c.uint) --- // Enable shader program
|
||||
DisableShader :: proc() --- // Disable shader program
|
||||
EnableShader :: proc(id: c.uint) --- // Enable shader program
|
||||
DisableShader :: proc() --- // Disable shader program
|
||||
|
||||
// Framebuffer state
|
||||
EnableFramebuffer :: proc(id: c.uint) --- // Enable render texture (fbo)
|
||||
DisableFramebuffer :: proc() --- // Disable render texture (fbo), return to default framebuffer
|
||||
ActiveDrawBuffers :: proc(count: c.int) --- // Activate multiple draw color buffers
|
||||
BlitFramebuffer :: proc(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask: c.int) --- // Blit active framebuffer to main framebuffer
|
||||
EnableFramebuffer :: proc(id: c.uint) --- // Enable render texture (fbo)
|
||||
DisableFramebuffer :: proc() --- // Disable render texture (fbo), return to default framebuffer
|
||||
ActiveDrawBuffers :: proc(count: c.int) --- // Activate multiple draw color buffers
|
||||
BlitFramebuffer :: proc(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask: c.int) --- // Blit active framebuffer to main framebuffer
|
||||
|
||||
// General render state
|
||||
EnableColorBlend :: proc() --- // Enable color blending
|
||||
DisableColorBlend :: proc() --- // Disable color blending
|
||||
EnableDepthTest :: proc() --- // Enable depth test
|
||||
DisableDepthTest :: proc() --- // Disable depth test
|
||||
EnableDepthMask :: proc() --- // Enable depth write
|
||||
DisableDepthMask :: proc() --- // Disable depth write
|
||||
EnableBackfaceCulling :: proc() --- // Enable backface culling
|
||||
DisableBackfaceCulling :: proc() --- // Disable backface culling
|
||||
SetCullFace :: proc(mode: CullMode) --- // Set face culling mode
|
||||
EnableScissorTest :: proc() --- // Enable scissor test
|
||||
DisableScissorTest :: proc() --- // Disable scissor test
|
||||
Scissor :: proc(x, y, width, height: c.int) --- // Scissor test
|
||||
EnableWireMode :: proc() --- // Enable wire mode
|
||||
EnablePointMode :: proc() --- // Enable point mode
|
||||
DisableWireMode :: proc() --- // Disable wire and point modes
|
||||
SetLineWidth :: proc(width: f32) --- // Set the line drawing width
|
||||
GetLineWidth :: proc() -> f32 --- // Get the line drawing width
|
||||
EnableSmoothLines :: proc() --- // Enable line aliasing
|
||||
DisableSmoothLines :: proc() --- // Disable line aliasing
|
||||
EnableStereoRender :: proc() --- // Enable stereo rendering
|
||||
DisableStereoRender :: proc() --- // Disable stereo rendering
|
||||
IsStereoRenderEnabled :: proc() -> bool --- // Check if stereo render is enabled
|
||||
EnableColorBlend :: proc() --- // Enable color blending
|
||||
DisableColorBlend :: proc() --- // Disable color blending
|
||||
EnableDepthTest :: proc() --- // Enable depth test
|
||||
DisableDepthTest :: proc() --- // Disable depth test
|
||||
EnableDepthMask :: proc() --- // Enable depth write
|
||||
DisableDepthMask :: proc() --- // Disable depth write
|
||||
EnableBackfaceCulling :: proc() --- // Enable backface culling
|
||||
DisableBackfaceCulling :: proc() --- // Disable backface culling
|
||||
SetCullFace :: proc(mode: CullMode) --- // Set face culling mode
|
||||
EnableScissorTest :: proc() --- // Enable scissor test
|
||||
DisableScissorTest :: proc() --- // Disable scissor test
|
||||
Scissor :: proc(x, y, width, height: c.int) --- // Scissor test
|
||||
EnableWireMode :: proc() --- // Enable wire mode
|
||||
EnablePointMode :: proc() --- // Enable point mode
|
||||
DisableWireMode :: proc() --- // Disable wire and point modes
|
||||
SetLineWidth :: proc(width: f32) --- // Set the line drawing width
|
||||
GetLineWidth :: proc() -> f32 --- // Get the line drawing width
|
||||
EnableSmoothLines :: proc() --- // Enable line aliasing
|
||||
DisableSmoothLines :: proc() --- // Disable line aliasing
|
||||
EnableStereoRender :: proc() --- // Enable stereo rendering
|
||||
DisableStereoRender :: proc() --- // Disable stereo rendering
|
||||
IsStereoRenderEnabled :: proc() -> bool --- // Check if stereo render is enabled
|
||||
|
||||
|
||||
ClearColor :: proc(r, g, b, a: u8) --- // Clear color buffer with color
|
||||
ClearScreenBuffers :: proc() --- // Clear used screen buffers (color and depth)
|
||||
CheckErrors :: proc() --- // Check and log OpenGL error codes
|
||||
SetBlendMode :: proc(mode: c.int) --- // Set blending mode
|
||||
SetBlendFactors :: proc(glSrcFactor, glDstFactor, glEquation: c.int) --- // Set blending mode factor and equation (using OpenGL factors)
|
||||
ClearColor :: proc(r, g, b, a: u8) --- // Clear color buffer with color
|
||||
ClearScreenBuffers :: proc() --- // Clear used screen buffers (color and depth)
|
||||
CheckErrors :: proc() --- // Check and log OpenGL error codes
|
||||
SetBlendMode :: proc(mode: c.int) --- // Set blending mode
|
||||
SetBlendFactors :: proc(glSrcFactor, glDstFactor, glEquation: c.int) --- // Set blending mode factor and equation (using OpenGL factors)
|
||||
SetBlendFactorsSeparate :: proc(glSrcRGB, glDstRGB, glSrcAlpha, glDstAlpha, glEqRGB, glEqAlpha: c.int) --- // Set blending mode factors and equations separately (using OpenGL factors)
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration - rlgl functionality
|
||||
//------------------------------------------------------------------------------------
|
||||
// rlgl initialization functions
|
||||
@(link_prefix = "rlgl")
|
||||
Init :: proc(width, height: c.int) --- // Initialize rlgl (buffers, shaders, textures, states)
|
||||
@(link_prefix = "rlgl")
|
||||
Close :: proc() --- // De-initialize rlgl (buffers, shaders, textures)
|
||||
LoadExtensions :: proc(loader: rawptr) --- // Load OpenGL extensions (loader function required)
|
||||
GetVersion :: proc() -> GlVersion --- // Get current OpenGL version
|
||||
SetFramebufferWidth :: proc(width: c.int) --- // Set current framebuffer width
|
||||
GetFramebufferWidth :: proc() -> c.int --- // Get default framebuffer width
|
||||
SetFramebufferHeight :: proc(height: c.int) --- // Set current framebuffer height
|
||||
GetFramebufferHeight :: proc() -> c.int --- // Get default framebuffer height
|
||||
@(link_prefix="rlgl")
|
||||
Init :: proc(width, height: c.int) --- // Initialize rlgl (buffers, shaders, textures, states)
|
||||
@(link_prefix="rlgl")
|
||||
Close :: proc() --- // De-initialize rlgl (buffers, shaders, textures)
|
||||
LoadExtensions :: proc(loader: rawptr) --- // Load OpenGL extensions (loader function required)
|
||||
GetVersion :: proc() -> GlVersion --- // Get current OpenGL version
|
||||
SetFramebufferWidth :: proc(width: c.int) --- // Set current framebuffer width
|
||||
GetFramebufferWidth :: proc() -> c.int --- // Get default framebuffer width
|
||||
SetFramebufferHeight :: proc(height: c.int) --- // Set current framebuffer height
|
||||
GetFramebufferHeight :: proc() -> c.int --- // Get default framebuffer height
|
||||
|
||||
|
||||
GetTextureIdDefault :: proc() -> c.uint --- // Get default texture id
|
||||
GetShaderIdDefault :: proc() -> c.uint --- // Get default shader id
|
||||
GetTextureIdDefault :: proc() -> c.uint --- // Get default texture id
|
||||
GetShaderIdDefault :: proc() -> c.uint --- // Get default shader id
|
||||
GetShaderLocsDefault :: proc() -> [^]c.int --- // Get default shader locations
|
||||
|
||||
// Render batch management
|
||||
// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
|
||||
// but this render batch API is exposed in case of custom batches are required
|
||||
LoadRenderBatch :: proc(numBuffers, bufferElements: c.int) -> RenderBatch --- // Load a render batch system
|
||||
UnloadRenderBatch :: proc(batch: RenderBatch) --- // Unload render batch system
|
||||
DrawRenderBatch :: proc(batch: ^RenderBatch) --- // Draw render batch data (Update->Draw->Reset)
|
||||
SetRenderBatchActive :: proc(batch: ^RenderBatch) --- // Set the active render batch for rlgl (NULL for default internal)
|
||||
DrawRenderBatchActive :: proc() --- // Update and draw internal render batch
|
||||
CheckRenderBatchLimit :: proc(vCount: c.int) -> c.int --- // Check internal buffer overflow for a given number of vertex
|
||||
LoadRenderBatch :: proc(numBuffers, bufferElements: c.int) -> RenderBatch --- // Load a render batch system
|
||||
UnloadRenderBatch :: proc(batch: RenderBatch) --- // Unload render batch system
|
||||
DrawRenderBatch :: proc(batch: ^RenderBatch) --- // Draw render batch data (Update->Draw->Reset)
|
||||
SetRenderBatchActive :: proc(batch: ^RenderBatch) --- // Set the active render batch for rlgl (NULL for default internal)
|
||||
DrawRenderBatchActive :: proc() --- // Update and draw internal render batch
|
||||
CheckRenderBatchLimit :: proc(vCount: c.int) -> c.int --- // Check internal buffer overflow for a given number of vertex
|
||||
|
||||
SetTexture :: proc(id: c.uint) --- // Set current texture for render batch and check buffers limits
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Vertex buffers management
|
||||
LoadVertexArray :: proc() -> c.uint --- // Load vertex array (vao) if supported
|
||||
LoadVertexBuffer :: proc(buffer: rawptr, size: c.int, is_dynamic: bool) -> c.uint --- // Load a vertex buffer attribute
|
||||
LoadVertexBufferElement :: proc(buffer: rawptr, size: c.int, is_dynamic: bool) -> c.uint --- // Load a new attributes element buffer
|
||||
UpdateVertexBuffer :: proc(bufferId: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update GPU buffer with new data
|
||||
UpdateVertexBufferElements :: proc(id: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update vertex buffer elements with new data
|
||||
UnloadVertexArray :: proc(vaoId: c.uint) ---
|
||||
UnloadVertexBuffer :: proc(vboId: c.uint) ---
|
||||
SetVertexAttribute :: proc(index: c.uint, compSize: c.int, type: c.int, normalized: bool, stride: c.int, pointer: rawptr) ---
|
||||
SetVertexAttributeDivisor :: proc(index: c.uint, divisor: c.int) ---
|
||||
SetVertexAttributeDefault :: proc(locIndex: c.int, value: rawptr, attribType: c.int, count: c.int) --- // Set vertex attribute default value
|
||||
DrawVertexArray :: proc(offset: c.int, count: c.int) ---
|
||||
DrawVertexArrayElements :: proc(offset: c.int, count: c.int, buffer: rawptr) ---
|
||||
DrawVertexArrayInstanced :: proc(offset: c.int, count: c.int, instances: c.int) ---
|
||||
LoadVertexArray :: proc() -> c.uint --- // Load vertex array (vao) if supported
|
||||
LoadVertexBuffer :: proc(buffer: rawptr, size: c.int, is_dynamic: bool) -> c.uint --- // Load a vertex buffer attribute
|
||||
LoadVertexBufferElement :: proc(buffer: rawptr, size: c.int, is_dynamic: bool) -> c.uint --- // Load a new attributes element buffer
|
||||
UpdateVertexBuffer :: proc(bufferId: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update GPU buffer with new data
|
||||
UpdateVertexBufferElements :: proc(id: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update vertex buffer elements with new data
|
||||
UnloadVertexArray :: proc(vaoId: c.uint) ---
|
||||
UnloadVertexBuffer :: proc(vboId: c.uint) ---
|
||||
SetVertexAttribute :: proc(index: c.uint, compSize: c.int, type: c.int, normalized: bool, stride: c.int, offset: c.int) ---
|
||||
SetVertexAttributeDivisor :: proc(index: c.uint, divisor: c.int) ---
|
||||
SetVertexAttributeDefault :: proc(locIndex: c.int, value: rawptr, attribType: c.int, count: c.int) --- // Set vertex attribute default value
|
||||
DrawVertexArray :: proc(offset: c.int, count: c.int) ---
|
||||
DrawVertexArrayElements :: proc(offset: c.int, count: c.int, buffer: rawptr) ---
|
||||
DrawVertexArrayInstanced :: proc(offset: c.int, count: c.int, instances: c.int) ---
|
||||
DrawVertexArrayElementsInstanced :: proc(offset: c.int, count: c.int, buffer: rawptr, instances: c.int) ---
|
||||
|
||||
// Textures management
|
||||
LoadTexture :: proc(data: rawptr, width, height: c.int, format: c.int, mipmapCount: c.int) -> c.uint --- // Load texture in GPU
|
||||
LoadTextureDepth :: proc(width, height: c.int, useRenderBuffer: bool) -> c.uint --- // Load depth texture/renderbuffer (to be attached to fbo)
|
||||
LoadTextureCubemap :: proc(data: rawptr, size: c.int, format: c.int) -> c.uint --- // Load texture cubemap
|
||||
UpdateTexture :: proc(id: c.uint, offsetX, offsetY: c.int, width, height: c.int, format: c.int, data: rawptr) --- // Update GPU texture with new data
|
||||
GetGlTextureFormats :: proc(format: c.int, glInternalFormat, glFormat, glType: ^c.uint) --- // Get OpenGL internal formats
|
||||
GetPixelFormatName :: proc(format: c.uint) -> cstring --- // Get name string for pixel format
|
||||
UnloadTexture :: proc(id: c.uint) --- // Unload texture from GPU memory
|
||||
GenTextureMipmaps :: proc(id: c.uint, width, height: c.int, format: c.int, mipmaps: ^c.int) --- // Generate mipmap data for selected texture
|
||||
ReadTexturePixels :: proc(id: c.uint, width, height: c.int, format: c.int) -> rawptr --- // Read texture pixel data
|
||||
ReadScreenPixels :: proc(width, height: c.int) -> [^]byte --- // Read screen pixel data (color buffer)
|
||||
LoadTexture :: proc(data: rawptr, width, height: c.int, format: c.int, mipmapCount: c.int) -> c.uint --- // Load texture in GPU
|
||||
LoadTextureDepth :: proc(width, height: c.int, useRenderBuffer: bool) -> c.uint --- // Load depth texture/renderbuffer (to be attached to fbo)
|
||||
LoadTextureCubemap :: proc(data: rawptr, size: c.int, format: c.int) -> c.uint --- // Load texture cubemap
|
||||
UpdateTexture :: proc(id: c.uint, offsetX, offsetY: c.int, width, height: c.int, format: c.int, data: rawptr) --- // Update GPU texture with new data
|
||||
GetGlTextureFormats :: proc(format: c.int, glInternalFormat, glFormat, glType: ^c.uint) --- // Get OpenGL internal formats
|
||||
GetPixelFormatName :: proc(format: c.uint) -> cstring --- // Get name string for pixel format
|
||||
UnloadTexture :: proc(id: c.uint) --- // Unload texture from GPU memory
|
||||
GenTextureMipmaps :: proc(id: c.uint, width, height: c.int, format: c.int, mipmaps: ^c.int) --- // Generate mipmap data for selected texture
|
||||
ReadTexturePixels :: proc(id: c.uint, width, height: c.int, format: c.int) -> rawptr --- // Read texture pixel data
|
||||
ReadScreenPixels :: proc(width, height: c.int) -> [^]byte --- // Read screen pixel data (color buffer)
|
||||
|
||||
// Framebuffer management (fbo)
|
||||
LoadFramebuffer :: proc(width, height: c.int) -> c.uint --- // Load an empty framebuffer
|
||||
FramebufferAttach :: proc(fboId, texId: c.uint, attachType: c.int, texType: c.int, mipLevel: c.int) --- // Attach texture/renderbuffer to a framebuffer
|
||||
FramebufferComplete :: proc(id: c.uint) -> bool --- // Verify framebuffer is complete
|
||||
UnloadFramebuffer :: proc(id: c.uint) --- // Delete framebuffer from GPU
|
||||
LoadFramebuffer :: proc() -> c.uint --- // Load an empty framebuffer
|
||||
FramebufferAttach :: proc(fboId, texId: c.uint, attachType: c.int, texType: c.int, mipLevel: c.int) --- // Attach texture/renderbuffer to a framebuffer
|
||||
FramebufferComplete :: proc(id: c.uint) -> bool --- // Verify framebuffer is complete
|
||||
UnloadFramebuffer :: proc(id: c.uint) --- // Delete framebuffer from GPU
|
||||
|
||||
// Shaders management
|
||||
LoadShaderCode :: proc(vsCode, fsCode: cstring) -> c.uint --- // Load shader from code strings
|
||||
CompileShader :: proc(shaderCode: cstring, type: c.int) -> c.uint --- // Compile custom shader and return shader id (type: VERTEX_SHADER, FRAGMENT_SHADER, COMPUTE_SHADER)
|
||||
LoadShaderProgram :: proc(vShaderId, fShaderId: c.uint) -> c.uint --- // Load custom shader program
|
||||
UnloadShaderProgram :: proc(id: c.uint) --- // Unload shader program
|
||||
GetLocationUniform :: proc(shaderId: c.uint, uniformName: cstring) -> c.int --- // Get shader location uniform
|
||||
GetLocationAttrib :: proc(shaderId: c.uint, attribName: cstring) -> c.int --- // Get shader location attribute
|
||||
SetUniform :: proc(locIndex: c.int, value: rawptr, uniformType: c.int, count: c.int) --- // Set shader value uniform
|
||||
SetUniformMatrix :: proc(locIndex: c.int, mat: Matrix) --- // Set shader value matrix
|
||||
SetUniformSampler :: proc(locIndex: c.int, textureId: c.uint) --- // Set shader value sampler
|
||||
SetShader :: proc(id: c.uint, locs: [^]c.int) --- // Set shader currently active (id and locations)
|
||||
LoadShaderCode :: proc(vsCode, fsCode: cstring) -> c.uint --- // Load shader from code strings
|
||||
CompileShader :: proc(shaderCode: cstring, type: c.int) -> c.uint --- // Compile custom shader and return shader id (type: VERTEX_SHADER, FRAGMENT_SHADER, COMPUTE_SHADER)
|
||||
LoadShaderProgram :: proc(vShaderId, fShaderId: c.uint) -> c.uint --- // Load custom shader program
|
||||
UnloadShaderProgram :: proc(id: c.uint) --- // Unload shader program
|
||||
GetLocationUniform :: proc(shaderId: c.uint, uniformName: cstring) -> c.int --- // Get shader location uniform
|
||||
GetLocationAttrib :: proc(shaderId: c.uint, attribName: cstring) -> c.int --- // Get shader location attribute
|
||||
SetUniform :: proc(locIndex: c.int, value: rawptr, uniformType: c.int, count: c.int) --- // Set shader value uniform
|
||||
SetUniformMatrix :: proc(locIndex: c.int, mat: Matrix) --- // Set shader value matrix
|
||||
SetUniformSampler :: proc(locIndex: c.int, textureId: c.uint) --- // Set shader value sampler
|
||||
SetShader :: proc(id: c.uint, locs: [^]c.int) --- // Set shader currently active (id and locations)
|
||||
|
||||
// Compute shader management
|
||||
LoadComputeShaderProgram :: proc(shaderId: c.uint) -> c.uint --- // Load compute shader program
|
||||
ComputeShaderDispatch :: proc(groupX, groupY, groupZ: c.uint) --- // Dispatch compute shader (equivalent to *draw* for graphics pipeline)
|
||||
LoadComputeShaderProgram :: proc(shaderId: c.uint) -> c.uint --- // Load compute shader program
|
||||
ComputeShaderDispatch :: proc(groupX, groupY, groupZ: c.uint) --- // Dispatch compute shader (equivalent to *draw* for graphics pipeline)
|
||||
|
||||
// Shader buffer storage object management (ssbo)
|
||||
LoadShaderBuffer :: proc(size: c.uint, data: rawptr, usageHint: c.int) -> c.uint --- // Load shader storage buffer object (SSBO)
|
||||
UnloadShaderBuffer :: proc(ssboId: c.uint) --- // Unload shader storage buffer object (SSBO)
|
||||
UpdateShaderBuffer :: proc(id: c.uint, data: rawptr, dataSize: c.uint, offset: c.uint) --- // Update SSBO buffer data
|
||||
BindShaderBuffer :: proc(id: c.uint, index: c.uint) --- // Bind SSBO buffer
|
||||
ReadShaderBuffer :: proc(id: c.uint, dest: rawptr, count: c.uint, offset: c.uint) --- // Read SSBO buffer data (GPU->CPU)
|
||||
CopyShaderBuffer :: proc(destId, srcId: c.uint, destOffset, srcOffset: c.uint, count: c.uint) --- // Copy SSBO data between buffers
|
||||
GetShaderBufferSize :: proc(id: c.uint) -> c.uint --- // Get SSBO buffer size
|
||||
LoadShaderBuffer :: proc(size: c.uint, data: rawptr, usageHint: c.int) -> c.uint --- // Load shader storage buffer object (SSBO)
|
||||
UnloadShaderBuffer :: proc(ssboId: c.uint) --- // Unload shader storage buffer object (SSBO)
|
||||
UpdateShaderBuffer :: proc(id: c.uint, data: rawptr, dataSize: c.uint, offset: c.uint) --- // Update SSBO buffer data
|
||||
BindShaderBuffer :: proc(id: c.uint, index: c.uint) --- // Bind SSBO buffer
|
||||
ReadShaderBuffer :: proc(id: c.uint, dest: rawptr, count: c.uint, offset: c.uint) --- // Read SSBO buffer data (GPU->CPU)
|
||||
CopyShaderBuffer :: proc(destId, srcId: c.uint, destOffset, srcOffset: c.uint, count: c.uint) --- // Copy SSBO data between buffers
|
||||
GetShaderBufferSize :: proc(id: c.uint) -> c.uint --- // Get SSBO buffer size
|
||||
|
||||
// Buffer management
|
||||
BindImageTexture :: proc(id: c.uint, index: c.uint, format: c.int, readonly: bool) --- // Bind image texture
|
||||
BindImageTexture :: proc(id: c.uint, index: c.uint, format: c.int, readonly: bool) --- // Bind image texture
|
||||
|
||||
// Matrix state management
|
||||
GetMatrixModelview :: proc() -> Matrix --- // Get internal modelview matrix
|
||||
GetMatrixProjection :: proc() -> Matrix --- // Get internal projection matrix
|
||||
GetMatrixTransform :: proc() -> Matrix --- // Get internal accumulated transform matrix
|
||||
GetMatrixModelview :: proc() -> Matrix --- // Get internal modelview matrix
|
||||
GetMatrixProjection :: proc() -> Matrix --- // Get internal projection matrix
|
||||
GetMatrixTransform :: proc() -> Matrix --- // Get internal accumulated transform matrix
|
||||
GetMatrixProjectionStereo :: proc(eye: c.int) -> Matrix --- // Get internal projection matrix for stereo render (selected eye)
|
||||
GetMatrixViewOffsetStereo :: proc(eye: c.int) -> Matrix --- // Get internal view offset matrix for stereo render (selected eye)
|
||||
SetMatrixProjection :: proc(proj: Matrix) --- // Set a custom projection matrix (replaces internal projection matrix)
|
||||
SetMatrixModelview :: proc(view: Matrix) --- // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||
SetMatrixProjectionStereo :: proc(right, left: Matrix) --- // Set eyes projection matrices for stereo rendering
|
||||
SetMatrixViewOffsetStereo :: proc(right, left: Matrix) --- // Set eyes view offsets matrices for stereo rendering
|
||||
SetMatrixProjection :: proc(proj: Matrix) --- // Set a custom projection matrix (replaces internal projection matrix)
|
||||
SetMatrixModelview :: proc(view: Matrix) --- // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||
SetMatrixProjectionStereo :: proc(right, left: Matrix) --- // Set eyes projection matrices for stereo rendering
|
||||
SetMatrixViewOffsetStereo :: proc(right, left: Matrix) --- // Set eyes view offsets matrices for stereo rendering
|
||||
|
||||
// Quick and dirty cube/quad buffers load->draw->unload
|
||||
LoadDrawCube :: proc() --- // Load and draw a cube
|
||||
|
BIN
src_assets/test_level.blend
(Stored with Git LFS)
BIN
src_assets/test_level.blend
(Stored with Git LFS)
Binary file not shown.
BIN
src_assets/test_level.blend1
(Stored with Git LFS)
BIN
src_assets/test_level.blend1
(Stored with Git LFS)
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user