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
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Bakery.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/test_level_blend/Plane.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (22.469545 22.469545 22.469545))
|
:scale (22.469545 22.469545 22.469545))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Fire_Station.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Gas_Station_Shop.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Green_House.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/testblend_blend/Hotel.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.000000 1.000000))
|
:scale (1.000000 1.000000 1.000000))
|
||||||
(inst
|
(inst
|
||||||
:model "assets/blender/test_level_blend/NurbsPath.glb"
|
: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)
|
:rot (0.000000 0.000000 0.000000 1.000000)
|
||||||
:scale (1.000000 1.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 bpy
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import contextlib
|
||||||
|
|
||||||
# Ensure blend file is saved
|
# Ensure blend file is saved
|
||||||
blend_filepath = bpy.data.filepath
|
blend_filepath = bpy.data.filepath
|
||||||
@ -9,6 +10,26 @@ if not blend_filepath:
|
|||||||
|
|
||||||
assert bpy.context.scene is not None
|
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:
|
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)))
|
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)
|
full_export_path = os.path.join(assets_path, export_path)
|
||||||
pathlib.Path(os.path.dirname(full_export_path)).mkdir(parents=True, exist_ok=True)
|
pathlib.Path(os.path.dirname(full_export_path)).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
bpy.ops.object.select_all(action='DESELECT')
|
if obj.instance_type == 'COLLECTION' and obj.instance_collection:
|
||||||
obj.select_set(True)
|
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.ops.export_scene.gltf(filepath=full_export_path, use_selection=True, export_apply=True)
|
||||||
bpy.context.view_layer.objects.active = obj
|
|
||||||
|
|
||||||
bpy.ops.export_scene.gltf(filepath=full_export_path, use_selection=True, export_apply=True)
|
|
||||||
print(f"Exported {obj.name} -> {export_path}")
|
print(f"Exported {obj.name} -> {export_path}")
|
||||||
|
|
||||||
# Collect all visible, non-hidden objects in the scene
|
# Collect all visible, non-hidden objects in the scene
|
||||||
@ -70,7 +96,7 @@ for obj in visible_objects:
|
|||||||
instance_sexpr = (
|
instance_sexpr = (
|
||||||
'(inst'
|
'(inst'
|
||||||
f'\n\t:model "assets/{model_path}"'
|
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: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}))'
|
f'\n\t:scale ({scale.x:.6f} {scale.y:.6f} {scale.z:.6f}))'
|
||||||
)
|
)
|
||||||
|
@ -5,6 +5,7 @@ package name
|
|||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:sync"
|
import "core:sync"
|
||||||
|
import "libs:tracy"
|
||||||
|
|
||||||
// When enabled name globals will be initialized automatically
|
// When enabled name globals will be initialized automatically
|
||||||
NAME_STATIC_INIT :: #config(NAME_STATIC_INIT, true)
|
NAME_STATIC_INIT :: #config(NAME_STATIC_INIT, true)
|
||||||
@ -61,23 +62,36 @@ when NAME_STATIC_INIT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
from_string :: proc(str: string) -> Name {
|
from_string :: proc(str: string) -> Name {
|
||||||
sync.atomic_rw_mutex_guard(&global_container.lock)
|
tracy.Zone()
|
||||||
existing, ok := global_container.names_lookup[str]
|
|
||||||
|
existing: Name
|
||||||
|
ok: bool
|
||||||
|
{
|
||||||
|
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
|
||||||
|
existing, ok = global_container.names_lookup[str]
|
||||||
|
}
|
||||||
if ok {
|
if ok {
|
||||||
return existing
|
return existing
|
||||||
} else {
|
} else {
|
||||||
new_str := strings.clone(
|
sync.atomic_rw_mutex_guard(&global_container.lock)
|
||||||
|
|
||||||
|
new_str := strings.clone_to_cstring(
|
||||||
str,
|
str,
|
||||||
mem.dynamic_arena_allocator(&global_container.names_allocator),
|
mem.dynamic_arena_allocator(&global_container.names_allocator),
|
||||||
)
|
)
|
||||||
idx := u32(len(global_container.names_array))
|
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)
|
global_container.names_lookup[str] = Name(idx)
|
||||||
return Name(idx)
|
return Name(idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
from_cstring :: proc(str: cstring) -> Name {
|
||||||
|
return from_string(string(str))
|
||||||
|
}
|
||||||
|
|
||||||
to_string :: proc(name: Name) -> string {
|
to_string :: proc(name: Name) -> string {
|
||||||
|
tracy.Zone()
|
||||||
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
|
sync.atomic_rw_mutex_shared_guard(&global_container.lock)
|
||||||
return global_container.names_array[name]
|
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:encoding/csv"
|
||||||
import "core:io"
|
import "core:io"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
import lg "core:math/linalg"
|
||||||
import "core:strconv"
|
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 {
|
CSV_Parse_Error :: enum {
|
||||||
Ok,
|
Ok,
|
||||||
@ -69,7 +75,7 @@ parse_csv_2d :: proc(
|
|||||||
data: []byte,
|
data: []byte,
|
||||||
allocator := context.allocator,
|
allocator := context.allocator,
|
||||||
) -> (
|
) -> (
|
||||||
curve: Loaded_Curve_2D,
|
curve: Curve_2D,
|
||||||
error: CSV_Parse_Error,
|
error: CSV_Parse_Error,
|
||||||
) {
|
) {
|
||||||
bytes_reader: bytes.Reader
|
bytes_reader: bytes.Reader
|
||||||
@ -125,8 +131,400 @@ parse_csv_2d :: proc(
|
|||||||
append(&tmp_result, [2]f32{f32(key), f32(val)})
|
append(&tmp_result, [2]f32{f32(key), f32(val)})
|
||||||
}
|
}
|
||||||
|
|
||||||
curve.points = make([][2]f32, len(tmp_result), allocator)
|
curve = make([][2]f32, len(tmp_result), allocator)
|
||||||
copy(curve.points, tmp_result[:])
|
copy(curve, tmp_result[:])
|
||||||
|
|
||||||
return
|
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) {
|
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)
|
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_destroy(world, scene)
|
||||||
|
|
||||||
scene.scene_desc_path = path_name
|
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)
|
sim_state := physics.get_sim_state(&world.physics_scene)
|
||||||
for inst in desc.instances {
|
for inst, i in desc.instances {
|
||||||
physics.add_level_geom(
|
scene.level_geoms[i] = physics.add_level_geom(
|
||||||
sim_state,
|
sim_state,
|
||||||
physics.Level_Geom_Config {
|
physics.Level_Geom_Config {
|
||||||
position = inst.pos,
|
position = inst.pos,
|
||||||
rotation = inst.rot,
|
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) {
|
scene_copy :: proc(dst, src: ^Scene) {
|
||||||
|
tracy.Zone()
|
||||||
dst.scene_desc_path = src.scene_desc_path
|
dst.scene_desc_path = src.scene_desc_path
|
||||||
if len(dst.level_geoms) != len(src.level_geoms) {
|
if len(dst.level_geoms) != len(src.level_geoms) {
|
||||||
delete(dst.level_geoms)
|
delete(dst.level_geoms)
|
||||||
@ -101,7 +104,7 @@ scene_draw :: proc(scene: ^Scene) {
|
|||||||
render.draw_model(
|
render.draw_model(
|
||||||
assets.get_model(&g_mem.assetman, name.to_cstring(geo.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()
|
tracy.Zone()
|
||||||
defer tracy.FrameMark()
|
defer tracy.FrameMark()
|
||||||
|
|
||||||
|
assets.assetman_tick(&g_mem.assetman)
|
||||||
|
|
||||||
update()
|
update()
|
||||||
draw()
|
draw()
|
||||||
|
|
||||||
@ -1474,7 +1479,6 @@ game_init :: proc() {
|
|||||||
init_physifs_raylib_callbacks()
|
init_physifs_raylib_callbacks()
|
||||||
|
|
||||||
assets.assetman_init(&g_mem.assetman)
|
assets.assetman_init(&g_mem.assetman)
|
||||||
assets.init(&g_mem.assetman)
|
|
||||||
|
|
||||||
editor_state_init(&g_mem.es, 100)
|
editor_state_init(&g_mem.es, 100)
|
||||||
runtime_world_init(&g_mem.runtime_world, DEV_BUILD ? 100 : 2)
|
runtime_world_init(&g_mem.runtime_world, DEV_BUILD ? 100 : 2)
|
||||||
|
@ -265,8 +265,7 @@ query_separation_edges :: proc(
|
|||||||
a_edge = -1
|
a_edge = -1
|
||||||
b_edge = -1
|
b_edge = -1
|
||||||
|
|
||||||
temp := runtime.default_temp_allocator_temp_begin()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
defer runtime.default_temp_allocator_temp_end(temp)
|
|
||||||
|
|
||||||
checked_pairs: bit_array.Bit_Array
|
checked_pairs: bit_array.Bit_Array
|
||||||
bit_array.init(&checked_pairs, len(a.edges) * len(b.edges), 0, context.temp_allocator)
|
bit_array.init(&checked_pairs, len(a.edges) * len(b.edges), 0, context.temp_allocator)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package physics
|
package physics
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
import "bvh"
|
import "bvh"
|
||||||
import "common:name"
|
import "common:name"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
@ -9,6 +10,7 @@ import lg "core:math/linalg"
|
|||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
import "game:assets"
|
||||||
import "game:debug"
|
import "game:debug"
|
||||||
import he "game:halfedge"
|
import he "game:halfedge"
|
||||||
import "game:ui"
|
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) {
|
draw_debug_scene :: proc(scene: ^Scene, debug_state: ^Debug_State) {
|
||||||
tracy.Zone()
|
tracy.Zone()
|
||||||
|
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
sim_state := get_sim_state(scene)
|
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
|
// Static_TLAS
|
||||||
if true && sim_state.static_tlas.built {
|
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)
|
it := bvh.iterator(&sim_state.static_tlas.bvh_tree)
|
||||||
|
|
||||||
for node in bvh.iterator_next(&it) {
|
if false {
|
||||||
if bvh.is_leaf_node(node) {
|
for node in bvh.iterator_next(&it) {
|
||||||
prim_start := node.child_or_prim_start
|
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 {
|
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_handle := index_to_level_geom(int(level_geom_idx))
|
||||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||||
blas := get_level_geom_blas(sim_state, level_geom_handle)
|
blas, vertices, indices := get_level_geom_data(
|
||||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
sim_state,
|
||||||
|
&sim_cache,
|
||||||
|
level_geom_handle,
|
||||||
|
)
|
||||||
|
|
||||||
bvh.debug_draw_bvh_bounds_mesh(
|
bvh.debug_draw_bvh_bounds_mesh(
|
||||||
&blas,
|
&blas,
|
||||||
bvh.Mesh{vertices = vertices, indices = indices},
|
bvh.Mesh{vertices = vertices, indices = indices},
|
||||||
level_geom.x,
|
level_geom.x,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,6 +300,7 @@ body_get_convex_shapes_world :: proc(
|
|||||||
|
|
||||||
level_geom_get_convex_shape :: proc(
|
level_geom_get_convex_shape :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
|
sim_cache: ^Sim_Cache,
|
||||||
level_geom_handle: Level_Geom_Handle,
|
level_geom_handle: Level_Geom_Handle,
|
||||||
tri_idx: int,
|
tri_idx: int,
|
||||||
allocator := context.temp_allocator,
|
allocator := context.temp_allocator,
|
||||||
@ -307,7 +308,7 @@ level_geom_get_convex_shape :: proc(
|
|||||||
mesh: collision.Convex,
|
mesh: collision.Convex,
|
||||||
) {
|
) {
|
||||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
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(
|
return collision.double_sided_triangle_to_convex(
|
||||||
get_transformed_triangle(vertices, indices, tri_idx, level_geom.x, level_geom.q),
|
get_transformed_triangle(vertices, indices, tri_idx, level_geom.x, level_geom.q),
|
||||||
allocator,
|
allocator,
|
||||||
@ -353,7 +354,7 @@ rotate_extent :: proc(extent: Vec3, q: Quat) -> Vec3 {
|
|||||||
return result
|
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.center = lg.quaternion_mul_vector3(q, local_aabb.center) + x
|
||||||
|
|
||||||
aabb.extent = rotate_extent(local_aabb.extent, q)
|
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
|
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) {
|
input_shape_get_aabb :: proc(shapes: []Input_Shape) -> (aabb: AABB) {
|
||||||
min, max: Vec3 = max(f32), min(f32)
|
min, max: Vec3 = max(f32), min(f32)
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import "bvh"
|
|||||||
import "collision"
|
import "collision"
|
||||||
import "common:name"
|
import "common:name"
|
||||||
import lg "core:math/linalg"
|
import lg "core:math/linalg"
|
||||||
import "core:strings"
|
|
||||||
import "game:assets"
|
import "game:assets"
|
||||||
import "game:container/spanpool"
|
import "game:container/spanpool"
|
||||||
import "libs:tracy"
|
import "libs:tracy"
|
||||||
@ -476,9 +475,6 @@ Suspension_Constraint_Ptr :: #soa^#soa[]Suspension_Constraint
|
|||||||
Engine_Ptr :: ^Engine
|
Engine_Ptr :: ^Engine
|
||||||
Level_Geom_Ptr :: ^Level_Geom
|
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: #soa[1]Suspension_Constraint
|
||||||
_invalid_suspension_constraint_slice := _invalid_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
|
/// Returns pointer to soa slice. NEVER STORE IT
|
||||||
get_body :: proc(sim_state: ^Sim_State, handle: Body_Handle) -> Body_Ptr {
|
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
|
index := int(handle) - 1
|
||||||
if index < 0 || index >= len(sim_state.bodies_slice) {
|
if index < 0 || index >= len(sim_state.bodies_slice) {
|
||||||
|
_invalid_body_slice = _invalid_body[:]
|
||||||
_invalid_body_slice[0] = {
|
_invalid_body_slice[0] = {
|
||||||
alive = true,
|
alive = true,
|
||||||
q = lg.QUATERNIONF32_IDENTITY,
|
q = lg.QUATERNIONF32_IDENTITY,
|
||||||
@ -602,7 +602,7 @@ Engine_Config :: struct {
|
|||||||
axle: Drive_Axle_Config,
|
axle: Drive_Axle_Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
Level_Geometry_Asset :: distinct string
|
Level_Geometry_Asset :: distinct name.Name
|
||||||
|
|
||||||
Level_Geometry_Mesh :: struct {
|
Level_Geometry_Mesh :: struct {
|
||||||
vertices: []Vec3,
|
vertices: []Vec3,
|
||||||
@ -949,8 +949,10 @@ get_level_geom :: proc(sim_state: ^Sim_State, handle: Level_Geom_Handle) -> Leve
|
|||||||
|
|
||||||
get_level_geom_data :: proc(
|
get_level_geom_data :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
|
sim_cache: ^Sim_Cache,
|
||||||
handle: Level_Geom_Handle,
|
handle: Level_Geom_Handle,
|
||||||
) -> (
|
) -> (
|
||||||
|
blas: bvh.BVH,
|
||||||
vertices: []Vec3,
|
vertices: []Vec3,
|
||||||
indices: []u16,
|
indices: []u16,
|
||||||
) {
|
) {
|
||||||
@ -958,17 +960,28 @@ get_level_geom_data :: proc(
|
|||||||
|
|
||||||
switch s in level_geom.source {
|
switch s in level_geom.source {
|
||||||
case Level_Geom_Source_Local:
|
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)
|
vertices = spanpool.resolve_slice(&sim_state.geometry_vertices_pool, s.geometry.vertices)
|
||||||
indices = spanpool.resolve_slice(&sim_state.geometry_indices_pool, s.geometry.indices)
|
indices = spanpool.resolve_slice(&sim_state.geometry_indices_pool, s.geometry.indices)
|
||||||
case Level_Geom_Source_Asset:
|
case Level_Geom_Source_Asset:
|
||||||
loaded_bvh, reloaded := assets.get_bvh(
|
loaded_bvh, ok := sim_cache.level_geom_asset_bvh[handle]
|
||||||
sim_state.scene.assetman,
|
|
||||||
strings.unsafe_string_to_cstring(name.to_string(s.assetpath)),
|
if !ok {
|
||||||
)
|
reloaded: bool
|
||||||
if reloaded {
|
loaded_bvh, reloaded = assets.get_bvh(sim_state.scene.assetman, s.assetpath)
|
||||||
level_geom.aabb = bvh_aabb_to_phys_aabb(loaded_bvh.aabb)
|
if reloaded {
|
||||||
level_geom.aabb = aabb_transform(level_geom.aabb, level_geom.x, level_geom.q)
|
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
|
vertices = loaded_bvh.vertices
|
||||||
indices = loaded_bvh.indices
|
indices = loaded_bvh.indices
|
||||||
}
|
}
|
||||||
@ -976,28 +989,6 @@ get_level_geom_data :: proc(
|
|||||||
return
|
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(
|
update_level_geom_from_config :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
level_geom: Level_Geom_Ptr,
|
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
|
level_geom.source = source
|
||||||
case Level_Geometry_Asset:
|
case Level_Geometry_Asset:
|
||||||
level_geom.source = Level_Geom_Source_Asset {
|
level_geom.source = Level_Geom_Source_Asset {
|
||||||
assetpath = name.from_string(string(s)),
|
assetpath = name.Name(s),
|
||||||
}
|
}
|
||||||
|
|
||||||
bvh, _ := assets.get_bvh(
|
bvh, _ := assets.get_bvh(sim_state.scene.assetman, name.Name(s))
|
||||||
sim_state.scene.assetman,
|
|
||||||
strings.unsafe_string_to_cstring(string(s)),
|
|
||||||
)
|
|
||||||
level_geom.aabb = AABB {
|
level_geom.aabb = AABB {
|
||||||
center = (bvh.aabb.max + bvh.aabb.min) * 0.5,
|
center = (bvh.aabb.max + bvh.aabb.min) * 0.5,
|
||||||
extent = (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)
|
spanpool.free(&sim_state.blas_primitives_pool, s.blas.primitives)
|
||||||
case Level_Geom_Source_Asset:
|
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 {
|
_get_first_free_body :: proc(sim_state: ^Sim_State) -> i32 {
|
||||||
|
@ -11,6 +11,7 @@ import "core:math"
|
|||||||
import lg "core:math/linalg"
|
import lg "core:math/linalg"
|
||||||
import "core:math/rand"
|
import "core:math/rand"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
|
import "game:assets"
|
||||||
import "game:debug"
|
import "game:debug"
|
||||||
import he "game:halfedge"
|
import he "game:halfedge"
|
||||||
import "libs:tracy"
|
import "libs:tracy"
|
||||||
@ -174,8 +175,10 @@ dynamic_tlas_destroy :: proc(dyn_tlas: ^Dynamic_TLAS) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
raycasts_level :: proc(
|
raycasts_level :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
|
sim_cache: ^Sim_Cache,
|
||||||
tlas: ^Static_TLAS,
|
tlas: ^Static_TLAS,
|
||||||
origin, dir: Vec3,
|
origin, dir: Vec3,
|
||||||
distance := max(f32),
|
distance := max(f32),
|
||||||
@ -201,32 +204,31 @@ raycasts_level :: proc(
|
|||||||
int(tlas.bvh_tree.primitives[leaf_node.child_or_prim_start + j]),
|
int(tlas.bvh_tree.primitives[leaf_node.child_or_prim_start + j]),
|
||||||
)
|
)
|
||||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||||
blas := get_level_geom_blas(sim_state, level_geom_handle)
|
blas, vertices, indices := get_level_geom_data(sim_state, sim_cache, level_geom_handle)
|
||||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
|
||||||
|
|
||||||
// TODO: transform ray into blas space and back
|
// 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 blas_leaf_node in bvh.iterator_intersect_leaf_next(&blas_it) {
|
||||||
for k in 0 ..< blas_leaf_node.prim_len {
|
for k in 0 ..< blas_leaf_node.prim_len {
|
||||||
tri_idx := int(blas.primitives[blas_leaf_node.child_or_prim_start + k])
|
tri_idx := int(blas.primitives[blas_leaf_node.child_or_prim_start + k])
|
||||||
|
|
||||||
tri := get_transformed_triangle(
|
tri := get_triangle(vertices, indices, tri_idx)
|
||||||
vertices,
|
|
||||||
indices,
|
|
||||||
tri_idx,
|
|
||||||
level_geom.x,
|
|
||||||
level_geom.q,
|
|
||||||
)
|
|
||||||
|
|
||||||
hit_t, tmp_normal, _, ok := collision.intersect_ray_triangle(
|
hit_t, tmp_normal, _, ok := collision.intersect_ray_triangle(
|
||||||
{origin, origin + dir},
|
{local_ray.origin, local_ray.origin + local_ray.dir},
|
||||||
tri,
|
tri,
|
||||||
)
|
)
|
||||||
|
|
||||||
if ok && (!hit || hit_t < t) {
|
if ok && (!hit || hit_t < t) {
|
||||||
t = hit_t
|
t = hit_t
|
||||||
normal = tmp_normal
|
normal = lg.quaternion_mul_vector3(level_geom.q, tmp_normal)
|
||||||
hit = true
|
hit = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,6 +296,7 @@ raycast_bodies :: proc(
|
|||||||
|
|
||||||
raycast :: proc(
|
raycast :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
|
sim_cache: ^Sim_Cache,
|
||||||
static_tlas: ^Static_TLAS,
|
static_tlas: ^Static_TLAS,
|
||||||
dyn_tlas: ^Dynamic_TLAS,
|
dyn_tlas: ^Dynamic_TLAS,
|
||||||
origin, dir: Vec3,
|
origin, dir: Vec3,
|
||||||
@ -305,7 +308,7 @@ raycast :: proc(
|
|||||||
) {
|
) {
|
||||||
t = distance
|
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)
|
t2, normal2, hit2 := raycast_bodies(sim_state, dyn_tlas, origin, dir, t)
|
||||||
|
|
||||||
hit = hit1 || hit2
|
hit = hit1 || hit2
|
||||||
@ -329,6 +332,14 @@ raycast :: proc(
|
|||||||
return
|
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) {
|
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]
|
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]
|
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(
|
remove_invalid_contacts :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
|
sim_cache: ^Sim_Cache,
|
||||||
static_tlas: Static_TLAS,
|
static_tlas: Static_TLAS,
|
||||||
dyn_tlas: Dynamic_TLAS,
|
dyn_tlas: Dynamic_TLAS,
|
||||||
) {
|
) {
|
||||||
@ -394,7 +406,11 @@ remove_invalid_contacts :: proc(
|
|||||||
|
|
||||||
if !should_remove {
|
if !should_remove {
|
||||||
tri_idx := int(contact.local_tri_idx)
|
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)
|
should_remove |= tri_idx * 3 >= len(indices)
|
||||||
|
|
||||||
if !should_remove {
|
if !should_remove {
|
||||||
@ -453,6 +469,7 @@ remove_invalid_contacts :: proc(
|
|||||||
// TODO: free intermediate temp allocs
|
// TODO: free intermediate temp allocs
|
||||||
find_new_contacts :: proc(
|
find_new_contacts :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
|
sim_cache: ^Sim_Cache,
|
||||||
static_tlas: ^Static_TLAS,
|
static_tlas: ^Static_TLAS,
|
||||||
dyn_tlas: ^Dynamic_TLAS,
|
dyn_tlas: ^Dynamic_TLAS,
|
||||||
) {
|
) {
|
||||||
@ -559,10 +576,16 @@ find_new_contacts :: proc(
|
|||||||
)
|
)
|
||||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
level_geom := get_level_geom(sim_state, level_geom_handle)
|
||||||
if level_geom.alive {
|
if level_geom.alive {
|
||||||
blas := get_level_geom_blas(sim_state, level_geom_handle)
|
blas, vertices, indices := get_level_geom_data(
|
||||||
vertices, indices := get_level_geom_data(sim_state, level_geom_handle)
|
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 blas_leaf_node in bvh.iterator_intersect_leaf_next(&blas_it) {
|
||||||
for k in 0 ..< blas_leaf_node.prim_len {
|
for k in 0 ..< blas_leaf_node.prim_len {
|
||||||
tri_idx := int(
|
tri_idx := int(
|
||||||
@ -653,9 +676,16 @@ simulate :: proc(
|
|||||||
prune_immediate(scene)
|
prune_immediate(scene)
|
||||||
|
|
||||||
copy_sim_state(get_next_sim_state(scene), get_sim_state(scene))
|
copy_sim_state(get_next_sim_state(scene), get_sim_state(scene))
|
||||||
|
|
||||||
sim_state := get_next_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
|
num_steps := 0
|
||||||
switch step_mode {
|
switch step_mode {
|
||||||
case .Accumulated_Time:
|
case .Accumulated_Time:
|
||||||
@ -666,11 +696,11 @@ simulate :: proc(
|
|||||||
state.accumulated_time -= config.timestep
|
state.accumulated_time -= config.timestep
|
||||||
|
|
||||||
if num_steps < MAX_STEPS {
|
if num_steps < MAX_STEPS {
|
||||||
simulate_step(scene, sim_state, config)
|
simulate_step(scene, sim_state, &sim_cache, config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .Single:
|
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
|
num_steps += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,7 +748,7 @@ Contact :: struct {
|
|||||||
applied_normal_correction: [4]f32,
|
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()
|
tracy.Zone()
|
||||||
|
|
||||||
temp := runtime.default_temp_allocator_temp_begin()
|
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:
|
case .Body_vs_Level:
|
||||||
level_geom_handle := Level_Geom_Handle(contact.b)
|
level_geom_handle := Level_Geom_Handle(contact.b)
|
||||||
level_geom := get_level_geom(sim_state, level_geom_handle)
|
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(
|
tri := get_transformed_triangle(
|
||||||
vertices,
|
vertices,
|
||||||
indices,
|
indices,
|
||||||
@ -1232,6 +1262,7 @@ calculate_ground_vel :: proc(
|
|||||||
|
|
||||||
pgs_solve_suspension :: proc(
|
pgs_solve_suspension :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
|
sim_cache: ^Sim_Cache,
|
||||||
static_tlas: ^Static_TLAS,
|
static_tlas: ^Static_TLAS,
|
||||||
dyn_tlas: ^Dynamic_TLAS,
|
dyn_tlas: ^Dynamic_TLAS,
|
||||||
config: Solver_Config,
|
config: Solver_Config,
|
||||||
@ -1249,6 +1280,7 @@ pgs_solve_suspension :: proc(
|
|||||||
dir := body_local_to_world_vec(body, v.rel_dir)
|
dir := body_local_to_world_vec(body, v.rel_dir)
|
||||||
v.hit_t, v.hit_normal, v.hit = raycast(
|
v.hit_t, v.hit_normal, v.hit = raycast(
|
||||||
sim_state,
|
sim_state,
|
||||||
|
sim_cache,
|
||||||
static_tlas,
|
static_tlas,
|
||||||
dyn_tlas,
|
dyn_tlas,
|
||||||
wheel_world_pos,
|
wheel_world_pos,
|
||||||
@ -1438,6 +1470,7 @@ pgs_solve_suspension :: proc(
|
|||||||
|
|
||||||
pgs_substep :: proc(
|
pgs_substep :: proc(
|
||||||
sim_state: ^Sim_State,
|
sim_state: ^Sim_State,
|
||||||
|
sim_cache: ^Sim_Cache,
|
||||||
static_tlas: ^Static_TLAS,
|
static_tlas: ^Static_TLAS,
|
||||||
dyn_tlas: ^Dynamic_TLAS,
|
dyn_tlas: ^Dynamic_TLAS,
|
||||||
config: Solver_Config,
|
config: Solver_Config,
|
||||||
@ -1559,7 +1592,7 @@ pgs_substep :: proc(
|
|||||||
apply_bias := true
|
apply_bias := true
|
||||||
pgs_solve_contacts(sim_state, config, dt, inv_dt, apply_bias)
|
pgs_solve_contacts(sim_state, config, dt, inv_dt, apply_bias)
|
||||||
pgs_solve_engines(sim_state, config, dt, inv_dt)
|
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) {
|
for i in 0 ..< len(sim_state.bodies_slice) {
|
||||||
body := &sim_state.bodies_slice[i]
|
body := &sim_state.bodies_slice[i]
|
||||||
@ -1600,7 +1633,12 @@ pgs_substep :: proc(
|
|||||||
// pgs_solve_suspension(sim_state, config, dt, inv_dt, apply_bias)
|
// 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()
|
tracy.Zone()
|
||||||
|
|
||||||
substeps := config.substreps_minus_one + 1
|
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_static_tlas(sim_state, &sim_state.static_tlas)
|
||||||
build_dynamic_tlas(sim_state, config, &sim_state.dynamic_tlas)
|
build_dynamic_tlas(sim_state, config, &sim_state.dynamic_tlas)
|
||||||
|
|
||||||
remove_invalid_contacts(sim_state, sim_state.static_tlas, sim_state.dynamic_tlas)
|
remove_invalid_contacts(sim_state, sim_cache, sim_state.static_tlas, sim_state.dynamic_tlas)
|
||||||
find_new_contacts(sim_state, &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_state.static_tlas)
|
update_contacts(sim_state, sim_cache, &sim_state.static_tlas)
|
||||||
|
|
||||||
Solver :: enum {
|
Solver :: enum {
|
||||||
XPBD,
|
XPBD,
|
||||||
@ -1634,6 +1672,7 @@ simulate_step :: proc(scene: ^Scene, sim_state: ^Sim_State, config: Solver_Confi
|
|||||||
for _ in 0 ..< substeps {
|
for _ in 0 ..< substeps {
|
||||||
pgs_substep(
|
pgs_substep(
|
||||||
sim_state,
|
sim_state,
|
||||||
|
sim_cache,
|
||||||
&sim_state.static_tlas,
|
&sim_state.static_tlas,
|
||||||
&sim_state.dynamic_tlas,
|
&sim_state.dynamic_tlas,
|
||||||
config,
|
config,
|
||||||
|
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: Quaternion
|
||||||
quat.x = source.x
|
quat.x = source.x
|
||||||
quat.y = source.z
|
quat.y = source.y
|
||||||
quat.z = source.z
|
quat.z = source.z
|
||||||
quat.w = 1
|
quat.w = 1
|
||||||
|
|
||||||
@ -831,8 +831,8 @@ fmaxf :: proc "contextless" (x, y: f32) -> f32 {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
if math.signbit(x) != math.signbit(y) {
|
if math.sign_bit(x) != math.sign_bit(y) {
|
||||||
return y if math.signbit(x) else x
|
return y if math.sign_bit(x) else x
|
||||||
}
|
}
|
||||||
|
|
||||||
return y if x < y else x
|
return y if x < y else x
|
||||||
|
@ -107,8 +107,8 @@
|
|||||||
|
|
||||||
package rlgl
|
package rlgl
|
||||||
|
|
||||||
import rl "../."
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
import rl "../."
|
||||||
|
|
||||||
VERSION :: "5.0"
|
VERSION :: "5.0"
|
||||||
|
|
||||||
@ -132,11 +132,11 @@ when ODIN_OS == .Windows {
|
|||||||
foreign import lib "system:raylib"
|
foreign import lib "system:raylib"
|
||||||
}
|
}
|
||||||
|
|
||||||
GRAPHICS_API_OPENGL_11 :: false
|
GRAPHICS_API_OPENGL_11 :: false
|
||||||
GRAPHICS_API_OPENGL_21 :: true
|
GRAPHICS_API_OPENGL_21 :: true
|
||||||
GRAPHICS_API_OPENGL_33 :: GRAPHICS_API_OPENGL_21 // default currently
|
GRAPHICS_API_OPENGL_33 :: GRAPHICS_API_OPENGL_21 // default currently
|
||||||
GRAPHICS_API_OPENGL_ES2 :: false
|
GRAPHICS_API_OPENGL_ES2 :: false
|
||||||
GRAPHICS_API_OPENGL_43 :: false
|
GRAPHICS_API_OPENGL_43 :: false
|
||||||
GRAPHICS_API_OPENGL_ES3 :: false
|
GRAPHICS_API_OPENGL_ES3 :: false
|
||||||
|
|
||||||
when GRAPHICS_API_OPENGL_ES3 {
|
when GRAPHICS_API_OPENGL_ES3 {
|
||||||
@ -154,100 +154,100 @@ when !GRAPHICS_API_OPENGL_ES2 {
|
|||||||
DEFAULT_BATCH_BUFFER_ELEMENTS :: 2048
|
DEFAULT_BATCH_BUFFER_ELEMENTS :: 2048
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_BATCH_BUFFERS :: 1 // Default number of batch buffers (multi-buffering)
|
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_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_MAX_TEXTURE_UNITS :: 4 // Maximum number of additional textures that can be activated on batch drawing (SetShaderValueTexture())
|
||||||
|
|
||||||
// Internal Matrix stack
|
// 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
|
// 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
|
// Projection matrix culling
|
||||||
CULL_DISTANCE_NEAR :: 0.01 // Default near cull distance
|
CULL_DISTANCE_NEAR :: 0.01 // Default near cull distance
|
||||||
CULL_DISTANCE_FAR :: 1000.0 // Default far cull distance
|
CULL_DISTANCE_FAR :: 1000.0 // Default far cull distance
|
||||||
|
|
||||||
// Texture parameters (equivalent to OpenGL defines)
|
// Texture parameters (equivalent to OpenGL defines)
|
||||||
TEXTURE_WRAP_S :: 0x2802 // GL_TEXTURE_WRAP_S
|
TEXTURE_WRAP_S :: 0x2802 // GL_TEXTURE_WRAP_S
|
||||||
TEXTURE_WRAP_T :: 0x2803 // GL_TEXTURE_WRAP_T
|
TEXTURE_WRAP_T :: 0x2803 // GL_TEXTURE_WRAP_T
|
||||||
TEXTURE_MAG_FILTER :: 0x2800 // GL_TEXTURE_MAG_FILTER
|
TEXTURE_MAG_FILTER :: 0x2800 // GL_TEXTURE_MAG_FILTER
|
||||||
TEXTURE_MIN_FILTER :: 0x2801 // GL_TEXTURE_MIN_FILTER
|
TEXTURE_MIN_FILTER :: 0x2801 // GL_TEXTURE_MIN_FILTER
|
||||||
|
|
||||||
TEXTURE_FILTER_NEAREST :: 0x2600 // GL_NEAREST
|
TEXTURE_FILTER_NEAREST :: 0x2600 // GL_NEAREST
|
||||||
TEXTURE_FILTER_LINEAR :: 0x2601 // GL_LINEAR
|
TEXTURE_FILTER_LINEAR :: 0x2601 // GL_LINEAR
|
||||||
TEXTURE_FILTER_MIP_NEAREST :: 0x2700 // GL_NEAREST_MIPMAP_NEAREST
|
TEXTURE_FILTER_MIP_NEAREST :: 0x2700 // GL_NEAREST_MIPMAP_NEAREST
|
||||||
TEXTURE_FILTER_NEAREST_MIP_LINEAR :: 0x2702 // GL_NEAREST_MIPMAP_LINEAR
|
TEXTURE_FILTER_NEAREST_MIP_LINEAR :: 0x2702 // GL_NEAREST_MIPMAP_LINEAR
|
||||||
TEXTURE_FILTER_LINEAR_MIP_NEAREST :: 0x2701 // GL_LINEAR_MIPMAP_NEAREST
|
TEXTURE_FILTER_LINEAR_MIP_NEAREST :: 0x2701 // GL_LINEAR_MIPMAP_NEAREST
|
||||||
TEXTURE_FILTER_MIP_LINEAR :: 0x2703 // GL_LINEAR_MIPMAP_LINEAR
|
TEXTURE_FILTER_MIP_LINEAR :: 0x2703 // GL_LINEAR_MIPMAP_LINEAR
|
||||||
TEXTURE_FILTER_ANISOTROPIC :: 0x3000 // Anisotropic filter (custom identifier)
|
TEXTURE_FILTER_ANISOTROPIC :: 0x3000 // Anisotropic filter (custom identifier)
|
||||||
|
|
||||||
TEXTURE_WRAP_REPEAT :: 0x2901 // GL_REPEAT
|
TEXTURE_WRAP_REPEAT :: 0x2901 // GL_REPEAT
|
||||||
TEXTURE_WRAP_CLAMP :: 0x812F // GL_CLAMP_TO_EDGE
|
TEXTURE_WRAP_CLAMP :: 0x812F // GL_CLAMP_TO_EDGE
|
||||||
TEXTURE_WRAP_MIRROR_REPEAT :: 0x8370 // GL_MIRRORED_REPEAT
|
TEXTURE_WRAP_MIRROR_REPEAT :: 0x8370 // GL_MIRRORED_REPEAT
|
||||||
TEXTURE_WRAP_MIRROR_CLAMP :: 0x8742 // GL_MIRROR_CLAMP_EXT
|
TEXTURE_WRAP_MIRROR_CLAMP :: 0x8742 // GL_MIRROR_CLAMP_EXT
|
||||||
|
|
||||||
// Matrix modes (equivalent to OpenGL)
|
// Matrix modes (equivalent to OpenGL)
|
||||||
MODELVIEW :: 0x1700 // GL_MODELVIEW
|
MODELVIEW :: 0x1700 // GL_MODELVIEW
|
||||||
PROJECTION :: 0x1701 // GL_PROJECTION
|
PROJECTION :: 0x1701 // GL_PROJECTION
|
||||||
TEXTURE :: 0x1702 // GL_TEXTURE
|
TEXTURE :: 0x1702 // GL_TEXTURE
|
||||||
|
|
||||||
// Primitive assembly draw modes
|
// Primitive assembly draw modes
|
||||||
LINES :: 0x0001 // GL_LINES
|
LINES :: 0x0001 // GL_LINES
|
||||||
TRIANGLES :: 0x0004 // GL_TRIANGLES
|
TRIANGLES :: 0x0004 // GL_TRIANGLES
|
||||||
QUADS :: 0x0007 // GL_QUADS
|
QUADS :: 0x0007 // GL_QUADS
|
||||||
|
|
||||||
// GL equivalent data types
|
// GL equivalent data types
|
||||||
UNSIGNED_BYTE :: 0x1401 // GL_UNSIGNED_BYTE
|
UNSIGNED_BYTE :: 0x1401 // GL_UNSIGNED_BYTE
|
||||||
FLOAT :: 0x1406 // GL_FLOAT
|
FLOAT :: 0x1406 // GL_FLOAT
|
||||||
|
|
||||||
// Buffer usage hint
|
// Buffer usage hint
|
||||||
STREAM_DRAW :: 0x88E0 // GL_STREAM_DRAW
|
STREAM_DRAW :: 0x88E0 // GL_STREAM_DRAW
|
||||||
STREAM_READ :: 0x88E1 // GL_STREAM_READ
|
STREAM_READ :: 0x88E1 // GL_STREAM_READ
|
||||||
STREAM_COPY :: 0x88E2 // GL_STREAM_COPY
|
STREAM_COPY :: 0x88E2 // GL_STREAM_COPY
|
||||||
STATIC_DRAW :: 0x88E4 // GL_STATIC_DRAW
|
STATIC_DRAW :: 0x88E4 // GL_STATIC_DRAW
|
||||||
STATIC_READ :: 0x88E5 // GL_STATIC_READ
|
STATIC_READ :: 0x88E5 // GL_STATIC_READ
|
||||||
STATIC_COPY :: 0x88E6 // GL_STATIC_COPY
|
STATIC_COPY :: 0x88E6 // GL_STATIC_COPY
|
||||||
DYNAMIC_DRAW :: 0x88E8 // GL_DYNAMIC_DRAW
|
DYNAMIC_DRAW :: 0x88E8 // GL_DYNAMIC_DRAW
|
||||||
DYNAMIC_READ :: 0x88E9 // GL_DYNAMIC_READ
|
DYNAMIC_READ :: 0x88E9 // GL_DYNAMIC_READ
|
||||||
DYNAMIC_COPY :: 0x88EA // GL_DYNAMIC_COPY
|
DYNAMIC_COPY :: 0x88EA // GL_DYNAMIC_COPY
|
||||||
|
|
||||||
// GL Shader type
|
// GL Shader type
|
||||||
FRAGMENT_SHADER :: 0x8B30 // GL_FRAGMENT_SHADER
|
FRAGMENT_SHADER :: 0x8B30 // GL_FRAGMENT_SHADER
|
||||||
VERTEX_SHADER :: 0x8B31 // GL_VERTEX_SHADER
|
VERTEX_SHADER :: 0x8B31 // GL_VERTEX_SHADER
|
||||||
COMPUTE_SHADER :: 0x91B9 // GL_COMPUTE_SHADER
|
COMPUTE_SHADER :: 0x91B9 // GL_COMPUTE_SHADER
|
||||||
|
|
||||||
// GL blending factors
|
// GL blending factors
|
||||||
ZERO :: 0 // GL_ZERO
|
ZERO :: 0 // GL_ZERO
|
||||||
ONE :: 1 // GL_ONE
|
ONE :: 1 // GL_ONE
|
||||||
SRC_COLOR :: 0x0300 // GL_SRC_COLOR
|
SRC_COLOR :: 0x0300 // GL_SRC_COLOR
|
||||||
ONE_MINUS_SRC_COLOR :: 0x0301 // GL_ONE_MINUS_SRC_COLOR
|
ONE_MINUS_SRC_COLOR :: 0x0301 // GL_ONE_MINUS_SRC_COLOR
|
||||||
SRC_ALPHA :: 0x0302 // GL_SRC_ALPHA
|
SRC_ALPHA :: 0x0302 // GL_SRC_ALPHA
|
||||||
ONE_MINUS_SRC_ALPHA :: 0x0303 // GL_ONE_MINUS_SRC_ALPHA
|
ONE_MINUS_SRC_ALPHA :: 0x0303 // GL_ONE_MINUS_SRC_ALPHA
|
||||||
DST_ALPHA :: 0x0304 // GL_DST_ALPHA
|
DST_ALPHA :: 0x0304 // GL_DST_ALPHA
|
||||||
ONE_MINUS_DST_ALPHA :: 0x0305 // GL_ONE_MINUS_DST_ALPHA
|
ONE_MINUS_DST_ALPHA :: 0x0305 // GL_ONE_MINUS_DST_ALPHA
|
||||||
DST_COLOR :: 0x0306 // GL_DST_COLOR
|
DST_COLOR :: 0x0306 // GL_DST_COLOR
|
||||||
ONE_MINUS_DST_COLOR :: 0x0307 // GL_ONE_MINUS_DST_COLOR
|
ONE_MINUS_DST_COLOR :: 0x0307 // GL_ONE_MINUS_DST_COLOR
|
||||||
SRC_ALPHA_SATURATE :: 0x0308 // GL_SRC_ALPHA_SATURATE
|
SRC_ALPHA_SATURATE :: 0x0308 // GL_SRC_ALPHA_SATURATE
|
||||||
CONSTANT_COLOR :: 0x8001 // GL_CONSTANT_COLOR
|
CONSTANT_COLOR :: 0x8001 // GL_CONSTANT_COLOR
|
||||||
ONE_MINUS_CONSTANT_COLOR :: 0x8002 // GL_ONE_MINUS_CONSTANT_COLOR
|
ONE_MINUS_CONSTANT_COLOR :: 0x8002 // GL_ONE_MINUS_CONSTANT_COLOR
|
||||||
CONSTANT_ALPHA :: 0x8003 // GL_CONSTANT_ALPHA
|
CONSTANT_ALPHA :: 0x8003 // GL_CONSTANT_ALPHA
|
||||||
ONE_MINUS_CONSTANT_ALPHA :: 0x8004 // GL_ONE_MINUS_CONSTANT_ALPHA
|
ONE_MINUS_CONSTANT_ALPHA :: 0x8004 // GL_ONE_MINUS_CONSTANT_ALPHA
|
||||||
|
|
||||||
// GL blending functions/equations
|
// GL blending functions/equations
|
||||||
FUNC_ADD :: 0x8006 // GL_FUNC_ADD
|
FUNC_ADD :: 0x8006 // GL_FUNC_ADD
|
||||||
MIN :: 0x8007 // GL_MIN
|
MIN :: 0x8007 // GL_MIN
|
||||||
MAX :: 0x8008 // GL_MAX
|
MAX :: 0x8008 // GL_MAX
|
||||||
FUNC_SUBTRACT :: 0x800A // GL_FUNC_SUBTRACT
|
FUNC_SUBTRACT :: 0x800A // GL_FUNC_SUBTRACT
|
||||||
FUNC_REVERSE_SUBTRACT :: 0x800B // GL_FUNC_REVERSE_SUBTRACT
|
FUNC_REVERSE_SUBTRACT :: 0x800B // GL_FUNC_REVERSE_SUBTRACT
|
||||||
BLEND_EQUATION :: 0x8009 // GL_BLEND_EQUATION
|
BLEND_EQUATION :: 0x8009 // GL_BLEND_EQUATION
|
||||||
BLEND_EQUATION_RGB :: 0x8009 // GL_BLEND_EQUATION_RGB // (Same as BLEND_EQUATION)
|
BLEND_EQUATION_RGB :: 0x8009 // GL_BLEND_EQUATION_RGB // (Same as BLEND_EQUATION)
|
||||||
BLEND_EQUATION_ALPHA :: 0x883D // GL_BLEND_EQUATION_ALPHA
|
BLEND_EQUATION_ALPHA :: 0x883D // GL_BLEND_EQUATION_ALPHA
|
||||||
BLEND_DST_RGB :: 0x80C8 // GL_BLEND_DST_RGB
|
BLEND_DST_RGB :: 0x80C8 // GL_BLEND_DST_RGB
|
||||||
BLEND_SRC_RGB :: 0x80C9 // GL_BLEND_SRC_RGB
|
BLEND_SRC_RGB :: 0x80C9 // GL_BLEND_SRC_RGB
|
||||||
BLEND_DST_ALPHA :: 0x80CA // GL_BLEND_DST_ALPHA
|
BLEND_DST_ALPHA :: 0x80CA // GL_BLEND_DST_ALPHA
|
||||||
BLEND_SRC_ALPHA :: 0x80CB // GL_BLEND_SRC_ALPHA
|
BLEND_SRC_ALPHA :: 0x80CB // GL_BLEND_SRC_ALPHA
|
||||||
BLEND_COLOR :: 0x8005 // GL_BLEND_COLOR
|
BLEND_COLOR :: 0x8005 // GL_BLEND_COLOR
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// 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)
|
// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
|
||||||
VertexBuffer :: struct {
|
VertexBuffer :: struct {
|
||||||
elementCount: c.int, // Number of elements in the buffer (QUADS)
|
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)
|
vertices: [^]f32, // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||||
colors: [^]u8, // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
texcoords: [^]f32, // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||||
indices: [^]VertexBufferIndexType, // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
|
colors: [^]u8, // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||||
vaoId: c.uint, // OpenGL Vertex Array Object id
|
indices: [^]VertexBufferIndexType, // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
|
||||||
vboId: [4]c.uint, // OpenGL Vertex Buffer Objects id (4 types of vertex data)
|
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
|
// 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
|
// 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)
|
// of those state-change happens (this is done in core module)
|
||||||
DrawCall :: struct {
|
DrawCall :: struct {
|
||||||
mode: c.int, // Drawing mode: LINES, TRIANGLES, QUADS
|
mode: c.int, // Drawing mode: LINES, TRIANGLES, QUADS
|
||||||
vertexCount: c.int, // Number of vertex of the draw
|
vertexCount: c.int, // Number of vertex of the draw
|
||||||
vertexAlignment: c.int, // Number of vertex required for index alignment (LINES, TRIANGLES)
|
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
|
textureId: c.uint, // Texture id to be used on the draw -> Use to create new draw call if changes
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderBatch type
|
// RenderBatch type
|
||||||
RenderBatch :: struct {
|
RenderBatch :: struct {
|
||||||
bufferCount: c.int, // Number of vertex buffers (multi-buffering support)
|
bufferCount: c.int, // Number of vertex buffers (multi-buffering support)
|
||||||
currentBuffer: c.int, // Current buffer tracking in case of multi-buffering
|
currentBuffer: c.int, // Current buffer tracking in case of multi-buffering
|
||||||
vertexBuffer: [^]VertexBuffer, // Dynamic buffer(s) for vertex data
|
vertexBuffer: [^]VertexBuffer, // Dynamic buffer(s) for vertex data
|
||||||
draws: [^]DrawCall, // Draw calls array, depends on textureId
|
|
||||||
drawCounter: c.int, // Draw calls counter
|
draws: [^]DrawCall, // Draw calls array, depends on textureId
|
||||||
currentDepth: f32, // Current depth value for next draw
|
drawCounter: c.int, // Draw calls counter
|
||||||
|
currentDepth: f32, // Current depth value for next draw
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenGL version
|
// OpenGL version
|
||||||
GlVersion :: enum c.int {
|
GlVersion :: enum c.int {
|
||||||
OPENGL_11 = 1, // OpenGL 1.1
|
OPENGL_11 = 1, // OpenGL 1.1
|
||||||
OPENGL_21, // OpenGL 2.1 (GLSL 120)
|
OPENGL_21, // OpenGL 2.1 (GLSL 120)
|
||||||
OPENGL_33, // OpenGL 3.3 (GLSL 330)
|
OPENGL_33, // OpenGL 3.3 (GLSL 330)
|
||||||
OPENGL_43, // OpenGL 4.3 (using GLSL 330)
|
OPENGL_43, // OpenGL 4.3 (using GLSL 330)
|
||||||
OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100)
|
OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100)
|
||||||
OPENGL_ES_30, // OpenGL ES 3.0 (GLSL 300 es)
|
OPENGL_ES_30, // OpenGL ES 3.0 (GLSL 300 es)
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelFormat :: rl.PixelFormat
|
PixelFormat :: rl.PixelFormat
|
||||||
@ -306,25 +308,25 @@ ShaderUniformDataType :: rl.ShaderUniformDataType
|
|||||||
|
|
||||||
// Shader attribute data types
|
// Shader attribute data types
|
||||||
ShaderAttributeDataType :: enum c.int {
|
ShaderAttributeDataType :: enum c.int {
|
||||||
FLOAT = 0, // Shader attribute type: float
|
FLOAT = 0, // Shader attribute type: float
|
||||||
VEC2, // Shader attribute type: vec2 (2 float)
|
VEC2, // Shader attribute type: vec2 (2 float)
|
||||||
VEC3, // Shader attribute type: vec3 (3 float)
|
VEC3, // Shader attribute type: vec3 (3 float)
|
||||||
VEC4, // Shader attribute type: vec4 (4 float)
|
VEC4, // Shader attribute type: vec4 (4 float)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Framebuffer attachment type
|
// Framebuffer attachment type
|
||||||
// NOTE: By default up to 8 color channels defined, but it can be more
|
// NOTE: By default up to 8 color channels defined, but it can be more
|
||||||
FramebufferAttachType :: enum c.int {
|
FramebufferAttachType :: enum c.int {
|
||||||
COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
|
COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
|
||||||
COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1
|
COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1
|
||||||
COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2
|
COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2
|
||||||
COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3
|
COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3
|
||||||
COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4
|
COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4
|
||||||
COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5
|
COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5
|
||||||
COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6
|
COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6
|
||||||
COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7
|
COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7
|
||||||
DEPTH = 100, // Framebuffer attachment type: depth
|
DEPTH = 100, // Framebuffer attachment type: depth
|
||||||
STENCIL = 200, // Framebuffer attachment type: stencil
|
STENCIL = 200, // Framebuffer attachment type: stencil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Framebuffer texture attachment type
|
// Framebuffer texture attachment type
|
||||||
@ -335,8 +337,8 @@ FramebufferAttachTextureType :: enum c.int {
|
|||||||
CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side
|
CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side
|
||||||
CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side
|
CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side
|
||||||
CUBEMAP_NEGATIVE_Z = 5, // 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
|
TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d
|
||||||
RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
|
RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
CullMode :: enum c.int {
|
CullMode :: enum c.int {
|
||||||
@ -346,37 +348,39 @@ CullMode :: enum c.int {
|
|||||||
|
|
||||||
Matrix :: rl.Matrix
|
Matrix :: rl.Matrix
|
||||||
|
|
||||||
@(default_calling_convention = "c", link_prefix = "rl")
|
@(default_calling_convention="c", link_prefix="rl")
|
||||||
foreign lib {
|
foreign lib {
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Functions Declaration - Matrix operations
|
// Functions Declaration - Matrix operations
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
MatrixMode :: proc(mode: c.int) --- // Choose the current matrix to be transformed
|
MatrixMode :: proc(mode: c.int) --- // Choose the current matrix to be transformed
|
||||||
PushMatrix :: proc() --- // Push the current matrix to stack
|
PushMatrix :: proc() --- // Push the current matrix to stack
|
||||||
PopMatrix :: proc() --- // Pop lattest inserted matrix from stack
|
PopMatrix :: proc() --- // Pop lattest inserted matrix from stack
|
||||||
LoadIdentity :: proc() --- // Reset current matrix to identity matrix
|
LoadIdentity :: proc() --- // Reset current matrix to identity matrix
|
||||||
Translatef :: proc(x, y, z: f32) --- // Multiply the current matrix by a translation 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
|
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
|
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
|
MultMatrixf :: proc(matf: [^]f32) --- // Multiply the current matrix by another matrix
|
||||||
Frustum :: proc(left, right, bottom, top, znear, zfar: f64) ---
|
Frustum :: proc(left, right, bottom, top, znear, zfar: f64) ---
|
||||||
Ortho :: 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
|
Viewport :: proc(x, y, width, height: c.int) --- // Set the viewport area
|
||||||
SetClipPlanes :: proc(nearPlane, farPlane: f64) --- // Set clip planes
|
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
|
// Functions Declaration - Vertex level operations
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
Begin :: proc(mode: c.int) --- // Initialize drawing mode (how to organize vertex)
|
Begin :: proc(mode: c.int) --- // Initialize drawing mode (how to organize vertex)
|
||||||
End :: proc() --- // Finish vertex providing
|
End :: proc() --- // Finish vertex providing
|
||||||
Vertex2i :: proc(x, y: c.int) --- // Define one vertex (position) - 2 int
|
Vertex2i :: proc(x, y: c.int) --- // Define one vertex (position) - 2 int
|
||||||
Vertex2f :: proc(x, y: f32) --- // Define one vertex (position) - 2 f32
|
Vertex2f :: proc(x, y: f32) --- // Define one vertex (position) - 2 f32
|
||||||
Vertex3f :: proc(x, y, z: f32) --- // Define one vertex (position) - 3 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
|
TexCoord2f :: proc(x, y: f32) --- // Define one vertex (texture coordinate) - 2 f32
|
||||||
Normal3f :: proc(x, y, z: f32) --- // Define one vertex (normal) - 3 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
|
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
|
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
|
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)
|
// Functions Declaration - OpenGL style functions (common to 1.1, 3.3+, ES2)
|
||||||
@ -385,176 +389,176 @@ foreign lib {
|
|||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Vertex buffers state
|
// Vertex buffers state
|
||||||
EnableVertexArray :: proc(vaoId: c.uint) -> bool --- // Enable vertex array (VAO, if supported)
|
EnableVertexArray :: proc(vaoId: c.uint) -> bool --- // Enable vertex array (VAO, if supported)
|
||||||
DisableVertexArray :: proc() --- // Disable vertex array (VAO, if supported)
|
DisableVertexArray :: proc() --- // Disable vertex array (VAO, if supported)
|
||||||
EnableVertexBuffer :: proc(id: c.uint) --- // Enable vertex buffer (VBO)
|
EnableVertexBuffer :: proc(id: c.uint) --- // Enable vertex buffer (VBO)
|
||||||
DisableVertexBuffer :: proc() --- // Disable vertex buffer (VBO)
|
DisableVertexBuffer :: proc() --- // Disable vertex buffer (VBO)
|
||||||
EnableVertexBufferElement :: proc(id: c.uint) --- // Enable vertex buffer element (VBO element)
|
EnableVertexBufferElement :: proc(id: c.uint) --- // Enable vertex buffer element (VBO element)
|
||||||
DisableVertexBufferElement :: proc() --- // Disable vertex buffer element (VBO element)
|
DisableVertexBufferElement :: proc() --- // Disable vertex buffer element (VBO element)
|
||||||
EnableVertexAttribute :: proc(index: c.uint) --- // Enable vertex attribute index
|
EnableVertexAttribute :: proc(index: c.uint) --- // Enable vertex attribute index
|
||||||
DisableVertexAttribute :: proc(index: c.uint) --- // Disable vertex attribute index
|
DisableVertexAttribute :: proc(index: c.uint) --- // Disable vertex attribute index
|
||||||
when GRAPHICS_API_OPENGL_11 {
|
when GRAPHICS_API_OPENGL_11 {
|
||||||
EnableStatePointer :: proc(vertexAttribType: c.int, buffer: rawptr) ---
|
EnableStatePointer :: proc(vertexAttribType: c.int, buffer: rawptr) ---
|
||||||
DisableStatePointer :: proc(vertexAttribType: c.int) ---
|
DisableStatePointer :: proc(vertexAttribType: c.int) ---
|
||||||
}
|
}
|
||||||
|
|
||||||
// Textures state
|
// Textures state
|
||||||
ActiveTextureSlot :: proc(slot: c.int) --- // Select and active a texture slot
|
ActiveTextureSlot :: proc(slot: c.int) --- // Select and active a texture slot
|
||||||
EnableTexture :: proc(id: c.uint) --- // Enable texture
|
EnableTexture :: proc(id: c.uint) --- // Enable texture
|
||||||
DisableTexture :: proc() --- // Disable texture
|
DisableTexture :: proc() --- // Disable texture
|
||||||
EnableTextureCubemap :: proc(id: c.uint) --- // Enable texture cubemap
|
EnableTextureCubemap :: proc(id: c.uint) --- // Enable texture cubemap
|
||||||
DisableTextureCubemap :: proc() --- // Disable texture cubemap
|
DisableTextureCubemap :: proc() --- // Disable texture cubemap
|
||||||
TextureParameters :: proc(id: c.uint, param: c.int, value: c.int) --- // Set texture parameters (filter, wrap)
|
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)
|
CubemapParameters :: proc(id: i32, param: c.int, value: c.int) --- // Set cubemap parameters (filter, wrap)
|
||||||
|
|
||||||
// Shader state
|
// Shader state
|
||||||
EnableShader :: proc(id: c.uint) --- // Enable shader program
|
EnableShader :: proc(id: c.uint) --- // Enable shader program
|
||||||
DisableShader :: proc() --- // Disable shader program
|
DisableShader :: proc() --- // Disable shader program
|
||||||
|
|
||||||
// Framebuffer state
|
// Framebuffer state
|
||||||
EnableFramebuffer :: proc(id: c.uint) --- // Enable render texture (fbo)
|
EnableFramebuffer :: proc(id: c.uint) --- // Enable render texture (fbo)
|
||||||
DisableFramebuffer :: proc() --- // Disable render texture (fbo), return to default framebuffer
|
DisableFramebuffer :: proc() --- // Disable render texture (fbo), return to default framebuffer
|
||||||
ActiveDrawBuffers :: proc(count: c.int) --- // Activate multiple draw color buffers
|
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
|
BlitFramebuffer :: proc(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask: c.int) --- // Blit active framebuffer to main framebuffer
|
||||||
|
|
||||||
// General render state
|
// General render state
|
||||||
EnableColorBlend :: proc() --- // Enable color blending
|
EnableColorBlend :: proc() --- // Enable color blending
|
||||||
DisableColorBlend :: proc() --- // Disable color blending
|
DisableColorBlend :: proc() --- // Disable color blending
|
||||||
EnableDepthTest :: proc() --- // Enable depth test
|
EnableDepthTest :: proc() --- // Enable depth test
|
||||||
DisableDepthTest :: proc() --- // Disable depth test
|
DisableDepthTest :: proc() --- // Disable depth test
|
||||||
EnableDepthMask :: proc() --- // Enable depth write
|
EnableDepthMask :: proc() --- // Enable depth write
|
||||||
DisableDepthMask :: proc() --- // Disable depth write
|
DisableDepthMask :: proc() --- // Disable depth write
|
||||||
EnableBackfaceCulling :: proc() --- // Enable backface culling
|
EnableBackfaceCulling :: proc() --- // Enable backface culling
|
||||||
DisableBackfaceCulling :: proc() --- // Disable backface culling
|
DisableBackfaceCulling :: proc() --- // Disable backface culling
|
||||||
SetCullFace :: proc(mode: CullMode) --- // Set face culling mode
|
SetCullFace :: proc(mode: CullMode) --- // Set face culling mode
|
||||||
EnableScissorTest :: proc() --- // Enable scissor test
|
EnableScissorTest :: proc() --- // Enable scissor test
|
||||||
DisableScissorTest :: proc() --- // Disable scissor test
|
DisableScissorTest :: proc() --- // Disable scissor test
|
||||||
Scissor :: proc(x, y, width, height: c.int) --- // Scissor test
|
Scissor :: proc(x, y, width, height: c.int) --- // Scissor test
|
||||||
EnableWireMode :: proc() --- // Enable wire mode
|
EnableWireMode :: proc() --- // Enable wire mode
|
||||||
EnablePointMode :: proc() --- // Enable point mode
|
EnablePointMode :: proc() --- // Enable point mode
|
||||||
DisableWireMode :: proc() --- // Disable wire and point modes
|
DisableWireMode :: proc() --- // Disable wire and point modes
|
||||||
SetLineWidth :: proc(width: f32) --- // Set the line drawing width
|
SetLineWidth :: proc(width: f32) --- // Set the line drawing width
|
||||||
GetLineWidth :: proc() -> f32 --- // Get the line drawing width
|
GetLineWidth :: proc() -> f32 --- // Get the line drawing width
|
||||||
EnableSmoothLines :: proc() --- // Enable line aliasing
|
EnableSmoothLines :: proc() --- // Enable line aliasing
|
||||||
DisableSmoothLines :: proc() --- // Disable line aliasing
|
DisableSmoothLines :: proc() --- // Disable line aliasing
|
||||||
EnableStereoRender :: proc() --- // Enable stereo rendering
|
EnableStereoRender :: proc() --- // Enable stereo rendering
|
||||||
DisableStereoRender :: proc() --- // Disable stereo rendering
|
DisableStereoRender :: proc() --- // Disable stereo rendering
|
||||||
IsStereoRenderEnabled :: proc() -> bool --- // Check if stereo render is enabled
|
IsStereoRenderEnabled :: proc() -> bool --- // Check if stereo render is enabled
|
||||||
|
|
||||||
|
|
||||||
ClearColor :: proc(r, g, b, a: u8) --- // Clear color buffer with color
|
ClearColor :: proc(r, g, b, a: u8) --- // Clear color buffer with color
|
||||||
ClearScreenBuffers :: proc() --- // Clear used screen buffers (color and depth)
|
ClearScreenBuffers :: proc() --- // Clear used screen buffers (color and depth)
|
||||||
CheckErrors :: proc() --- // Check and log OpenGL error codes
|
CheckErrors :: proc() --- // Check and log OpenGL error codes
|
||||||
SetBlendMode :: proc(mode: c.int) --- // Set blending mode
|
SetBlendMode :: proc(mode: c.int) --- // Set blending mode
|
||||||
SetBlendFactors :: proc(glSrcFactor, glDstFactor, glEquation: c.int) --- // Set blending mode factor and equation (using OpenGL factors)
|
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)
|
SetBlendFactorsSeparate :: proc(glSrcRGB, glDstRGB, glSrcAlpha, glDstAlpha, glEqRGB, glEqAlpha: c.int) --- // Set blending mode factors and equations separately (using OpenGL factors)
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Functions Declaration - rlgl functionality
|
// Functions Declaration - rlgl functionality
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// rlgl initialization functions
|
// rlgl initialization functions
|
||||||
@(link_prefix = "rlgl")
|
@(link_prefix="rlgl")
|
||||||
Init :: proc(width, height: c.int) --- // Initialize rlgl (buffers, shaders, textures, states)
|
Init :: proc(width, height: c.int) --- // Initialize rlgl (buffers, shaders, textures, states)
|
||||||
@(link_prefix = "rlgl")
|
@(link_prefix="rlgl")
|
||||||
Close :: proc() --- // De-initialize rlgl (buffers, shaders, textures)
|
Close :: proc() --- // De-initialize rlgl (buffers, shaders, textures)
|
||||||
LoadExtensions :: proc(loader: rawptr) --- // Load OpenGL extensions (loader function required)
|
LoadExtensions :: proc(loader: rawptr) --- // Load OpenGL extensions (loader function required)
|
||||||
GetVersion :: proc() -> GlVersion --- // Get current OpenGL version
|
GetVersion :: proc() -> GlVersion --- // Get current OpenGL version
|
||||||
SetFramebufferWidth :: proc(width: c.int) --- // Set current framebuffer width
|
SetFramebufferWidth :: proc(width: c.int) --- // Set current framebuffer width
|
||||||
GetFramebufferWidth :: proc() -> c.int --- // Get default framebuffer width
|
GetFramebufferWidth :: proc() -> c.int --- // Get default framebuffer width
|
||||||
SetFramebufferHeight :: proc(height: c.int) --- // Set current framebuffer height
|
SetFramebufferHeight :: proc(height: c.int) --- // Set current framebuffer height
|
||||||
GetFramebufferHeight :: proc() -> c.int --- // Get default framebuffer height
|
GetFramebufferHeight :: proc() -> c.int --- // Get default framebuffer height
|
||||||
|
|
||||||
|
|
||||||
GetTextureIdDefault :: proc() -> c.uint --- // Get default texture id
|
GetTextureIdDefault :: proc() -> c.uint --- // Get default texture id
|
||||||
GetShaderIdDefault :: proc() -> c.uint --- // Get default shader id
|
GetShaderIdDefault :: proc() -> c.uint --- // Get default shader id
|
||||||
GetShaderLocsDefault :: proc() -> [^]c.int --- // Get default shader locations
|
GetShaderLocsDefault :: proc() -> [^]c.int --- // Get default shader locations
|
||||||
|
|
||||||
// Render batch management
|
// Render batch management
|
||||||
// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
|
// 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
|
// 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
|
LoadRenderBatch :: proc(numBuffers, bufferElements: c.int) -> RenderBatch --- // Load a render batch system
|
||||||
UnloadRenderBatch :: proc(batch: RenderBatch) --- // Unload render batch system
|
UnloadRenderBatch :: proc(batch: RenderBatch) --- // Unload render batch system
|
||||||
DrawRenderBatch :: proc(batch: ^RenderBatch) --- // Draw render batch data (Update->Draw->Reset)
|
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)
|
SetRenderBatchActive :: proc(batch: ^RenderBatch) --- // Set the active render batch for rlgl (NULL for default internal)
|
||||||
DrawRenderBatchActive :: proc() --- // Update and draw internal render batch
|
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
|
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
|
SetTexture :: proc(id: c.uint) --- // Set current texture for render batch and check buffers limits
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Vertex buffers management
|
// Vertex buffers management
|
||||||
LoadVertexArray :: proc() -> c.uint --- // Load vertex array (vao) if supported
|
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
|
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
|
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
|
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
|
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) ---
|
UnloadVertexArray :: proc(vaoId: c.uint) ---
|
||||||
UnloadVertexBuffer :: proc(vboId: 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) ---
|
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) ---
|
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
|
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) ---
|
DrawVertexArray :: proc(offset: c.int, count: c.int) ---
|
||||||
DrawVertexArrayElements :: proc(offset: c.int, count: c.int, buffer: rawptr) ---
|
DrawVertexArrayElements :: proc(offset: c.int, count: c.int, buffer: rawptr) ---
|
||||||
DrawVertexArrayInstanced :: proc(offset: c.int, count: c.int, instances: c.int) ---
|
DrawVertexArrayInstanced :: proc(offset: c.int, count: c.int, instances: c.int) ---
|
||||||
DrawVertexArrayElementsInstanced :: proc(offset: c.int, count: c.int, buffer: rawptr, instances: c.int) ---
|
DrawVertexArrayElementsInstanced :: proc(offset: c.int, count: c.int, buffer: rawptr, instances: c.int) ---
|
||||||
|
|
||||||
// Textures management
|
// Textures management
|
||||||
LoadTexture :: proc(data: rawptr, width, height: c.int, format: c.int, mipmapCount: c.int) -> c.uint --- // Load texture in GPU
|
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)
|
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
|
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
|
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
|
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
|
GetPixelFormatName :: proc(format: c.uint) -> cstring --- // Get name string for pixel format
|
||||||
UnloadTexture :: proc(id: c.uint) --- // Unload texture from GPU memory
|
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
|
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
|
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)
|
ReadScreenPixels :: proc(width, height: c.int) -> [^]byte --- // Read screen pixel data (color buffer)
|
||||||
|
|
||||||
// Framebuffer management (fbo)
|
// Framebuffer management (fbo)
|
||||||
LoadFramebuffer :: proc(width, height: c.int) -> c.uint --- // Load an empty framebuffer
|
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
|
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
|
FramebufferComplete :: proc(id: c.uint) -> bool --- // Verify framebuffer is complete
|
||||||
UnloadFramebuffer :: proc(id: c.uint) --- // Delete framebuffer from GPU
|
UnloadFramebuffer :: proc(id: c.uint) --- // Delete framebuffer from GPU
|
||||||
|
|
||||||
// Shaders management
|
// Shaders management
|
||||||
LoadShaderCode :: proc(vsCode, fsCode: cstring) -> c.uint --- // Load shader from code strings
|
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)
|
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
|
LoadShaderProgram :: proc(vShaderId, fShaderId: c.uint) -> c.uint --- // Load custom shader program
|
||||||
UnloadShaderProgram :: proc(id: c.uint) --- // Unload shader program
|
UnloadShaderProgram :: proc(id: c.uint) --- // Unload shader program
|
||||||
GetLocationUniform :: proc(shaderId: c.uint, uniformName: cstring) -> c.int --- // Get shader location uniform
|
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
|
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
|
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
|
SetUniformMatrix :: proc(locIndex: c.int, mat: Matrix) --- // Set shader value matrix
|
||||||
SetUniformSampler :: proc(locIndex: c.int, textureId: c.uint) --- // Set shader value sampler
|
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)
|
SetShader :: proc(id: c.uint, locs: [^]c.int) --- // Set shader currently active (id and locations)
|
||||||
|
|
||||||
// Compute shader management
|
// Compute shader management
|
||||||
LoadComputeShaderProgram :: proc(shaderId: c.uint) -> c.uint --- // Load compute shader program
|
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)
|
ComputeShaderDispatch :: proc(groupX, groupY, groupZ: c.uint) --- // Dispatch compute shader (equivalent to *draw* for graphics pipeline)
|
||||||
|
|
||||||
// Shader buffer storage object management (ssbo)
|
// Shader buffer storage object management (ssbo)
|
||||||
LoadShaderBuffer :: proc(size: c.uint, data: rawptr, usageHint: c.int) -> c.uint --- // Load shader storage buffer object (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)
|
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
|
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
|
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)
|
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
|
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
|
GetShaderBufferSize :: proc(id: c.uint) -> c.uint --- // Get SSBO buffer size
|
||||||
|
|
||||||
// Buffer management
|
// 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
|
// Matrix state management
|
||||||
GetMatrixModelview :: proc() -> Matrix --- // Get internal modelview matrix
|
GetMatrixModelview :: proc() -> Matrix --- // Get internal modelview matrix
|
||||||
GetMatrixProjection :: proc() -> Matrix --- // Get internal projection matrix
|
GetMatrixProjection :: proc() -> Matrix --- // Get internal projection matrix
|
||||||
GetMatrixTransform :: proc() -> Matrix --- // Get internal accumulated transform matrix
|
GetMatrixTransform :: proc() -> Matrix --- // Get internal accumulated transform matrix
|
||||||
GetMatrixProjectionStereo :: proc(eye: c.int) -> Matrix --- // Get internal projection matrix for stereo render (selected eye)
|
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)
|
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)
|
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)
|
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
|
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
|
SetMatrixViewOffsetStereo :: proc(right, left: Matrix) --- // Set eyes view offsets matrices for stereo rendering
|
||||||
|
|
||||||
// Quick and dirty cube/quad buffers load->draw->unload
|
// Quick and dirty cube/quad buffers load->draw->unload
|
||||||
LoadDrawCube :: proc() --- // Load and draw a cube
|
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