Mesh_Entities!
This commit is contained in:
@@ -158,11 +158,12 @@ animation_time_normalized :: (e: *Entity) -> float {
|
|||||||
|
|
||||||
sample_animation_state :: (e: *Entity, index: s32, weight: float) {
|
sample_animation_state :: (e: *Entity, index: s32, weight: float) {
|
||||||
state := *e.animator.states[index];
|
state := *e.animator.states[index];
|
||||||
|
model := get_model_by_handle(e.renderable.model);
|
||||||
|
|
||||||
if state.type == {
|
if state.type == {
|
||||||
case .SINGLE;
|
case .SINGLE;
|
||||||
{
|
{
|
||||||
animation := *e.renderable.model.animations[state.single.index];
|
animation := *model.animations[state.single.index];
|
||||||
sample_animation(e, animation, min(state.single.time, cast(float)animation.duration - 0.0001), weight);
|
sample_animation(e, animation, min(state.single.time, cast(float)animation.duration - 0.0001), weight);
|
||||||
}
|
}
|
||||||
case .BLEND_TREE_1D;
|
case .BLEND_TREE_1D;
|
||||||
@@ -187,8 +188,8 @@ sample_animation_state :: (e: *Entity, index: s32, weight: float) {
|
|||||||
range := p1_position - p0_position;
|
range := p1_position - p0_position;
|
||||||
alpha := position / range;
|
alpha := position / range;
|
||||||
|
|
||||||
anim0 := e.renderable.model.animations[state.blend_tree.points[p0].index];
|
anim0 := model.animations[state.blend_tree.points[p0].index];
|
||||||
anim1 := e.renderable.model.animations[state.blend_tree.points[p1].index];
|
anim1 := model.animations[state.blend_tree.points[p1].index];
|
||||||
time0 := state.blend_tree.points[p0].time;
|
time0 := state.blend_tree.points[p0].time;
|
||||||
time1 := state.blend_tree.points[p1].time;
|
time1 := state.blend_tree.points[p1].time;
|
||||||
|
|
||||||
@@ -213,13 +214,14 @@ transition_to_animation_state :: (e: *Entity, index: s32, transition_duration: f
|
|||||||
|
|
||||||
update_animation_state :: (e: *Entity, index: s32, dt: float) {
|
update_animation_state :: (e: *Entity, index: s32, dt: float) {
|
||||||
state := *e.animator.states[index];
|
state := *e.animator.states[index];
|
||||||
|
model := get_model_by_handle(e.renderable.model);
|
||||||
|
|
||||||
if state.type == {
|
if state.type == {
|
||||||
case .SINGLE;
|
case .SINGLE;
|
||||||
{
|
{
|
||||||
state.single.time += dt * state.single.multiplier;
|
state.single.time += dt * state.single.multiplier;
|
||||||
|
|
||||||
animation := *e.renderable.model.animations[state.single.index];
|
animation := *model.animations[state.single.index];
|
||||||
|
|
||||||
if state.single.time > animation.duration {
|
if state.single.time > animation.duration {
|
||||||
if state.single.looping {
|
if state.single.looping {
|
||||||
@@ -238,7 +240,7 @@ update_animation_state :: (e: *Entity, index: s32, dt: float) {
|
|||||||
for *p: state.blend_tree.points {
|
for *p: state.blend_tree.points {
|
||||||
p.time += dt * p.multiplier;
|
p.time += dt * p.multiplier;
|
||||||
|
|
||||||
animation := *e.renderable.model.animations[p.index];
|
animation := *model.animations[p.index];
|
||||||
|
|
||||||
if p.time > animation.duration {
|
if p.time > animation.duration {
|
||||||
if p.looping {
|
if p.looping {
|
||||||
@@ -259,7 +261,6 @@ update_animator :: (e: *Entity, animator: *Animator, dt: float) {
|
|||||||
it.transform.position = .{0,0,0};
|
it.transform.position = .{0,0,0};
|
||||||
it.transform.scale = .{0,0,0};
|
it.transform.scale = .{0,0,0};
|
||||||
it.transform.orientation = .{0,0,0,0};
|
it.transform.orientation = .{0,0,0,0};
|
||||||
it.has_sampled_animation = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if animator.playing_transition {
|
if animator.playing_transition {
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ Node_Render_Data :: struct {
|
|||||||
enabled : bool = true;
|
enabled : bool = true;
|
||||||
transform: Transform;
|
transform: Transform;
|
||||||
material : Entity_Material;
|
material : Entity_Material;
|
||||||
has_sampled_animation: bool;
|
|
||||||
|
|
||||||
// Buffers
|
// Buffers
|
||||||
transform_buffer: Buffer_Handle;
|
transform_buffer: Buffer_Handle;
|
||||||
@@ -45,9 +44,11 @@ Renderable :: struct {
|
|||||||
visible: bool = true;
|
visible: bool = true;
|
||||||
type : Renderable_Type; @DontSerialize
|
type : Renderable_Type; @DontSerialize
|
||||||
|
|
||||||
model: *Model; @DontSerialize
|
model: Model_Handle; @DontSerialize
|
||||||
nodes: [MAX_NODES] Node_Render_Data; @DontSerialize
|
nodes: [MAX_NODES] Node_Render_Data; @DontSerialize
|
||||||
num_nodes: s64; @DontSerialize
|
num_nodes: s64; @DontSerialize
|
||||||
|
|
||||||
|
//node_buffer : Buffer_Handle; // Structure buffer with all transform + material // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
MAX_CHILDREN :: 16;
|
MAX_CHILDREN :: 16;
|
||||||
@@ -114,8 +115,10 @@ set_parent :: (e: *Entity, parent: *Entity, node_name: string = "") {
|
|||||||
|
|
||||||
set_base_color :: (e: *Entity, color: Vector4, node_name: string = "") {
|
set_base_color :: (e: *Entity, color: Vector4, node_name: string = "") {
|
||||||
if e.renderable.type == .MODEL {
|
if e.renderable.type == .MODEL {
|
||||||
|
model := get_model_by_handle(e.renderable.model);
|
||||||
|
|
||||||
for i: 0..e.renderable.num_nodes-1 {
|
for i: 0..e.renderable.num_nodes-1 {
|
||||||
actual_node := e.renderable.model.nodes[i];
|
actual_node := model.nodes[i];
|
||||||
if node_name.count == 0 || node_name == actual_node.name {
|
if node_name.count == 0 || node_name == actual_node.name {
|
||||||
data := *e.renderable.nodes[i];
|
data := *e.renderable.nodes[i];
|
||||||
if data.material_buffer > 0 {
|
if data.material_buffer > 0 {
|
||||||
@@ -140,13 +143,15 @@ set_node_enabled :: (e: *Entity, node_name: string, enabled : bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
load_model_into_entity :: (e: *Entity, model: *Model) {
|
load_model_into_entity :: (e: *Entity, handle: Model_Handle) {
|
||||||
|
model := get_model_by_handle(handle);
|
||||||
|
|
||||||
e.renderable.type = .MODEL;
|
e.renderable.type = .MODEL;
|
||||||
|
|
||||||
assert(model.nodes.count <= MAX_NODES);
|
assert(model.nodes.count <= MAX_NODES);
|
||||||
|
|
||||||
e.renderable.num_nodes = model.nodes.count;
|
e.renderable.num_nodes = model.nodes.count;
|
||||||
e.renderable.model = model;
|
e.renderable.model = handle;
|
||||||
|
|
||||||
for *model.nodes {
|
for *model.nodes {
|
||||||
data : Node_Render_Data;
|
data : Node_Render_Data;
|
||||||
|
|||||||
42
core/mesh_entity.jai
Normal file
42
core/mesh_entity.jai
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
Mesh_Entity :: struct {
|
||||||
|
using #as entity: Entity;
|
||||||
|
entity.flags = .RENDERABLE;
|
||||||
|
entity.type = Mesh_Entity;
|
||||||
|
|
||||||
|
model_path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_entity :: (e: *Mesh_Entity) {
|
||||||
|
if e.model_path.count > 0 {
|
||||||
|
load_model_into_entity(e, get_or_load_model(e.model_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh_entity_files : [..] Mesh_Entity_Info;
|
||||||
|
|
||||||
|
Mesh_Entity_Info :: struct {
|
||||||
|
full_path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh_entity_visitor :: (info : *File_Visit_Info, files: *[..] Mesh_Entity_Info) {
|
||||||
|
if info.is_directory
|
||||||
|
return;
|
||||||
|
path, basename, ext := path_decomp (info.full_name);
|
||||||
|
|
||||||
|
// Entity text files
|
||||||
|
if ext == "fbx" {
|
||||||
|
file_info : Mesh_Entity_Info;
|
||||||
|
file_info.full_path = copy_string(info.full_name);
|
||||||
|
array_add(files, file_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
find_all_mesh_entities :: () {
|
||||||
|
path := "../assets/models/level_design/";
|
||||||
|
|
||||||
|
visit_files(path, true, *mesh_entity_files, mesh_entity_visitor);
|
||||||
|
|
||||||
|
for mesh_entity_files {
|
||||||
|
print(it.full_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -194,7 +194,11 @@ ray_entity_intersect :: (ray: Ray, e: *Entity) -> bool, float, Vector3 {
|
|||||||
closest : float = 10000000;
|
closest : float = 10000000;
|
||||||
closest_normal : Vector3;
|
closest_normal : Vector3;
|
||||||
|
|
||||||
for n: e.renderable.model.nodes {
|
if e.renderable.model == 0 return false, 0.0, .{};
|
||||||
|
|
||||||
|
model := get_model_by_handle(e.renderable.model);
|
||||||
|
|
||||||
|
for n: model.nodes {
|
||||||
render_node := e.renderable.nodes[it_index];
|
render_node := e.renderable.nodes[it_index];
|
||||||
for handle: n.meshes {
|
for handle: n.meshes {
|
||||||
m := parray_get(*engine.renderer.meshes, handle);
|
m := parray_get(*engine.renderer.meshes, handle);
|
||||||
|
|||||||
@@ -248,9 +248,11 @@ update_entity_node :: (e: *Entity, model_node: Node, index: s64, parent_matrix:
|
|||||||
|
|
||||||
n.transform.world_matrix = parent_matrix * n.transform.model_matrix;
|
n.transform.world_matrix = parent_matrix * n.transform.model_matrix;
|
||||||
|
|
||||||
|
model := get_model_by_handle(e.renderable.model);
|
||||||
|
|
||||||
for children_index: 0..model_node.children.count-1 {
|
for children_index: 0..model_node.children.count-1 {
|
||||||
index := model_node.children[children_index]-1;
|
index := model_node.children[children_index]-1;
|
||||||
mn := e.renderable.model.nodes[index];
|
mn := model.nodes[index];
|
||||||
update_entity_node(e, mn, xx index, n.transform.world_matrix);
|
update_entity_node(e, mn, xx index, n.transform.world_matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,9 +272,12 @@ update_entity_transform :: (e: *Entity, parent_matrix: Matrix4 = Matrix4_Identit
|
|||||||
}
|
}
|
||||||
|
|
||||||
if e.flags & .RENDERABLE {
|
if e.flags & .RENDERABLE {
|
||||||
for model_node, i: e.renderable.model.nodes {
|
if e.renderable.model != 0 {
|
||||||
if model_node.parent == 0 {
|
model := get_model_by_handle(e.renderable.model);
|
||||||
update_entity_node(e, model_node, i, e.transform.world_matrix);
|
for model_node, i: model.nodes {
|
||||||
|
if model_node.parent == 0 {
|
||||||
|
update_entity_node(e, model_node, i, e.transform.world_matrix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,33 @@ editor_ui :: () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
|
|
||||||
|
ImGui.Begin("Create Mesh Entity", flags=ImGui.WindowFlags.NoResize);
|
||||||
|
|
||||||
|
for mesh_entity_files {
|
||||||
|
ImGui.PushID(to_temp_c_string(it.full_path)) ;
|
||||||
|
defer ImGui.PopID();
|
||||||
|
|
||||||
|
if ImGui.Button(to_temp_c_string(it.full_path)) {
|
||||||
|
mesh_entity := new_mesh_entity(init=false);
|
||||||
|
mesh_entity.model_path = it.full_path;
|
||||||
|
init_entity(mesh_entity);
|
||||||
|
new_entity = mesh_entity;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//set_position(*new_entity.transform, engine.editor.camera.position + engine.editor.camera.forward * 20.0);
|
||||||
|
//engine.editor.selected_entities.count = 0;
|
||||||
|
//array_add(*engine.editor.selected_entities, new_entity);
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
|
||||||
|
if new_entity != null {
|
||||||
|
set_position(*new_entity.transform, engine.editor.camera.position + engine.editor.camera.forward * 20.0);
|
||||||
|
engine.editor.selected_entities.count = 0;
|
||||||
|
array_add(*engine.editor.selected_entities, new_entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.Begin("Entities");
|
ImGui.Begin("Entities");
|
||||||
|
|||||||
@@ -784,6 +784,7 @@ PLACEHOLDER :: #string DONE
|
|||||||
#poke_name Coven delete_entity;
|
#poke_name Coven delete_entity;
|
||||||
#poke_name Coven deserialize_entity;
|
#poke_name Coven deserialize_entity;
|
||||||
#poke_name Coven serialize_entity;
|
#poke_name Coven serialize_entity;
|
||||||
|
#poke_name Coven new_mesh_entity;
|
||||||
|
|
||||||
#if EDITOR {
|
#if EDITOR {
|
||||||
#poke_name Coven editor_ui_entity_creation;
|
#poke_name Coven editor_ui_entity_creation;
|
||||||
|
|||||||
@@ -82,6 +82,8 @@ coven_init :: (window_title: string, window_width: u32, window_height: u32, full
|
|||||||
init_editor();
|
init_editor();
|
||||||
ui_init();
|
ui_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
find_all_mesh_entities();
|
||||||
}
|
}
|
||||||
|
|
||||||
coven_run :: (game_update_proc: (float), game_editor_update_proc: (float), game_update_post_physics_proc: (float)) {
|
coven_run :: (game_update_proc: (float), game_editor_update_proc: (float), game_update_post_physics_proc: (float)) {
|
||||||
@@ -206,6 +208,7 @@ switch_engine_mode :: (to_mode: Engine_Mode) {
|
|||||||
#load "windowing/window.jai";
|
#load "windowing/window.jai";
|
||||||
#load "physics/physics.jai";
|
#load "physics/physics.jai";
|
||||||
|
|
||||||
|
#load "core/mesh_entity.jai";
|
||||||
#load "core/string_helpers.jai";
|
#load "core/string_helpers.jai";
|
||||||
#load "core/math.jai";
|
#load "core/math.jai";
|
||||||
#load "core/ray.jai";
|
#load "core/ray.jai";
|
||||||
|
|||||||
@@ -408,10 +408,12 @@ calculate_aabbs :: (scene: *Scene) {
|
|||||||
for e: scene.entities {
|
for e: scene.entities {
|
||||||
if e.flags & .COLLISION && e.flags & .RENDERABLE {
|
if e.flags & .COLLISION && e.flags & .RENDERABLE {
|
||||||
if e.collider.override_aabb continue;
|
if e.collider.override_aabb continue;
|
||||||
|
if e.renderable.model == 0 continue;
|
||||||
|
|
||||||
aabb : AABB;
|
aabb : AABB;
|
||||||
|
model := get_model_by_handle(e.renderable.model);
|
||||||
|
|
||||||
for n : e.renderable.model.nodes {
|
for n : model.nodes {
|
||||||
if n.parent == 0 {
|
if n.parent == 0 {
|
||||||
bake_aabb(*aabb, Matrix4_Identity, e, n);
|
bake_aabb(*aabb, Matrix4_Identity, e, n);
|
||||||
}
|
}
|
||||||
@@ -459,9 +461,11 @@ bake_aabb :: (aabb: *AABB, parent_matrix: Matrix4, e: *Entity, n: Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model := get_model_by_handle(e.renderable.model);
|
||||||
|
|
||||||
for n.children {
|
for n.children {
|
||||||
child := *e.renderable.model.nodes[it - 1];
|
child := *model.nodes[it - 1];
|
||||||
bake_aabb(aabb, node_matrix, e, child);
|
bake_aabb(aabb, node_matrix, e, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,10 @@ sync_engine_buffers :: () {
|
|||||||
if it.flags & .RENDERABLE {
|
if it.flags & .RENDERABLE {
|
||||||
if it.renderable.type == {
|
if it.renderable.type == {
|
||||||
case .MODEL; {
|
case .MODEL; {
|
||||||
for n, i: it.renderable.model.nodes {
|
if it.renderable.model == 0 continue;
|
||||||
|
|
||||||
|
model := get_model_by_handle(it.renderable.model);
|
||||||
|
for n, i: model.nodes {
|
||||||
if n.meshes.count > 0 {
|
if n.meshes.count > 0 {
|
||||||
node_data := *it.renderable.nodes[i];
|
node_data := *it.renderable.nodes[i];
|
||||||
upload_data_to_buffer(engine.renderer, node_data.transform_buffer, *node_data.transform.world_matrix, size_of(Matrix4));
|
upload_data_to_buffer(engine.renderer, node_data.transform_buffer, *node_data.transform.world_matrix, size_of(Matrix4));
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
Node_Handle :: #type, distinct u32;
|
Node_Handle :: #type, distinct u32;
|
||||||
Material_Handle :: #type, distinct u32;
|
Material_Handle :: #type, distinct u32;
|
||||||
|
Model_Handle :: #type, isa u32;
|
||||||
|
|
||||||
|
Model_Asset :: struct {
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
MAX_BONES :: 128;
|
MAX_BONES :: 128;
|
||||||
MAX_WEIGHTS :: 4;
|
MAX_WEIGHTS :: 4;
|
||||||
@@ -66,7 +71,9 @@ Model :: struct {
|
|||||||
materials : [..] Model_Material;
|
materials : [..] Model_Material;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_first_mesh_from_model :: (model: Model) -> Mesh_Handle, bool {
|
get_first_mesh_from_model :: (handle: Model_Handle) -> Mesh_Handle, bool {
|
||||||
|
model := get_model_by_handle(handle);
|
||||||
|
|
||||||
for model.nodes {
|
for model.nodes {
|
||||||
for m: it.meshes {
|
for m: it.meshes {
|
||||||
return m, true;
|
return m, true;
|
||||||
@@ -377,7 +384,9 @@ parse_fbx_node :: (model: *Model, fbx_node: *ufbx_node) {
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
array_add(*node.meshes, parray_add(*engine.renderer.meshes, mesh));
|
array_add(*node.meshes, parray_add(*engine.renderer.meshes, mesh));struct {
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
array_add(*node.material_defaults, model.materials[mesh_mat.material.typed_id]); // @Incomplete
|
array_add(*node.material_defaults, model.materials[mesh_mat.material.typed_id]); // @Incomplete
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -580,7 +589,7 @@ load_fbx_texture :: (map: ufbx_material_map, format: Format) -> Texture_Handle {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
load_fbx :: (path: string) -> *Model, bool {
|
load_fbx :: (path: string) -> Model_Handle, bool {
|
||||||
opts : ufbx_load_opts = .{};
|
opts : ufbx_load_opts = .{};
|
||||||
opts.load_external_files = true;
|
opts.load_external_files = true;
|
||||||
opts.generate_missing_normals = true;
|
opts.generate_missing_normals = true;
|
||||||
@@ -597,10 +606,11 @@ load_fbx :: (path: string) -> *Model, bool {
|
|||||||
|
|
||||||
if scene == null {
|
if scene == null {
|
||||||
log_error("FBX '%' could not be loaded", path);
|
log_error("FBX '%' could not be loaded", path);
|
||||||
return null, false;
|
return 0, false;
|
||||||
}
|
}
|
||||||
|
|
||||||
model, locator := find_and_occupy_empty_slot(*engine.renderer.model_lib);
|
model : Model;
|
||||||
|
|
||||||
model.path = copy_string(path);
|
model.path = copy_string(path);
|
||||||
model.name = copy_string(path);
|
model.name = copy_string(path);
|
||||||
|
|
||||||
@@ -643,24 +653,27 @@ load_fbx :: (path: string) -> *Model, bool {
|
|||||||
|
|
||||||
for i: 0..scene.nodes.count-1 {
|
for i: 0..scene.nodes.count-1 {
|
||||||
node := scene.nodes.data[i];
|
node := scene.nodes.data[i];
|
||||||
parse_fbx_node(model, node);
|
parse_fbx_node(*model, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load animations
|
// Load animations
|
||||||
array_resize(*model.animations, xx scene.anim_stacks.count);
|
array_resize(*model.animations, xx scene.anim_stacks.count);
|
||||||
for 0..model.animations.count-1 {
|
for 0..model.animations.count-1 {
|
||||||
parse_anim_stack(*model.animations[it], scene.anim_stacks.data[it], scene, model);
|
parse_anim_stack(*model.animations[it], scene.anim_stacks.data[it], scene, *model);
|
||||||
}
|
}
|
||||||
|
|
||||||
ufbx_free_scene(scene);
|
ufbx_free_scene(scene);
|
||||||
|
|
||||||
return model, false;
|
array_add(*engine.renderer.model_lib, model);
|
||||||
|
handle := cast(Model_Handle)engine.renderer.model_lib.count;
|
||||||
|
|
||||||
|
return handle, false;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_or_load_model :: (path: string) -> *Model {
|
get_or_load_model :: (path: string) -> Model_Handle {
|
||||||
for * engine.renderer.model_lib {
|
for * engine.renderer.model_lib {
|
||||||
if it.path == path {
|
if it.path == path {
|
||||||
return it;
|
return xx (it_index + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -586,7 +586,7 @@ Renderer :: struct {
|
|||||||
fonts : [..] Font;
|
fonts : [..] Font;
|
||||||
|
|
||||||
render_graph : *Render_Graph;
|
render_graph : *Render_Graph;
|
||||||
model_lib : Bucket_Array(Model, 128);
|
model_lib : Static_Array(Model, 128);
|
||||||
|
|
||||||
callbacks : struct {
|
callbacks : struct {
|
||||||
get_custom_material_parameter_mapping: (mapping_str: string) -> bool, Material_Mapping_Info;
|
get_custom_material_parameter_mapping: (mapping_str: string) -> bool, Material_Mapping_Info;
|
||||||
@@ -605,7 +605,7 @@ Renderer :: struct {
|
|||||||
render_target_height: u32;
|
render_target_height: u32;
|
||||||
|
|
||||||
default_models : struct {
|
default_models : struct {
|
||||||
sphere: Model;
|
sphere: Model_Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
default_meshes : struct {
|
default_meshes : struct {
|
||||||
@@ -1627,6 +1627,12 @@ create_material_from_pipeline :: (pipeline: Pipeline_State_Handle) -> Material_O
|
|||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_model_by_handle :: (handle: Model_Handle) -> *Model {
|
||||||
|
if handle == 0 return null;
|
||||||
|
|
||||||
|
return *engine.renderer.model_lib[handle-1];
|
||||||
|
}
|
||||||
|
|
||||||
check_for_shader_modifications :: () {
|
check_for_shader_modifications :: () {
|
||||||
changed, needs_wait, wait_seconds := process_changes(*engine.renderer.watcher);
|
changed, needs_wait, wait_seconds := process_changes(*engine.renderer.watcher);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user