Skip to content

Instantly share code, notes, and snippets.

@FlyingJester
Created December 17, 2016 01:14
Show Gist options
  • Save FlyingJester/787496b1dd8a3a635919face41495177 to your computer and use it in GitHub Desktop.
Save FlyingJester/787496b1dd8a3a635919face41495177 to your computer and use it in GitHub Desktop.
Scene Graph rought draft for CinnabarEngine
:- module scene.
%==============================================================================%
:- interface.
%==============================================================================%
:- use_module render.
:- use_module mglow.
:- include_module scene.matrix_tree.
:- include_module scene.tree.
% Recursively draws all nodes in the tree.
:- pred draw(scene.matrix_tree::in, Render::in, node(Model)::in,
mglow.window::di, mglow.window::uo) is det <= render.model(Render, Model).
% Similar to draw. First applies the given transformation without pushing
% matrices on the renderer, and will pass any further transfom nodes into
% another call to apply_transformation. This is an optimization to use a
% single matrix stack entry to handle multiple transformations in a row.
:- pred apply_transformation_and_draw(scene.matrix_tree::in, Render::in,
scene.matrix_tree.transformation::in, scene.tree.node(Model)::in,
mglow.window::di, mglow.window::uo) is det <= render.model(Render, Model).
% Translates scene.matrix_tree.transformation types into calls to render
% typeclass predicates.
:- pred apply_transformation(scene.matrix_tree.transformation::in, Render::in,
mglow.window::di, mglow.window::uo) is det <= render.render(Render).
%==============================================================================%
:- implementation.
%==============================================================================%
apply_transformation_and_draw(Tree, Render, Transformation, Node, !Window) :-
apply_transformation(Transformation, Render, !Window),
( Node = transform(NextTransformation, NextNode) ->
apply_transformation_and_draw(Tree,
Render, NextTransformation, NextNode, !Window)
;
draw(Tree, Render, Node, !Window)
).
draw(Tree, Render, transform(Transformation, Node), !Window) :-
render.push_matrix(Render, !Window),
apply_transformation_and_draw(Tree, Render, Node, !Window),
render.pop_matrix(Render, !Window).
draw(_, Render, model(Model), !Window) :-
render.draw(Render, Model, !Window).
draw(Tree, Render, group(NodeA, NodeB), !Window) :-
draw(Tree, Render, NodeA, !Window),
draw(Tree, Render, NodeB, !Window).
% TODO
apply_transformation(scale(_, _, _), _, !Window).
% TODO
apply_transformation(matrix(_), _, !Window).
apply_transformation(translate(X, Y, Z), Render) :-
render.translate(X, Y, Z, Render, !Window).
apply_transformation(rotate_x(A), Render) :-
render.rotate_x(A, Render, !Window).
apply_transformation(rotate_y(A), Render) :-
render.rotate_y(A, Render, !Window).
apply_transformation(rotate_z(A), Render) :-
render.rotate_z(A, Render, !Window).
:- module scene.matrix_tree.
%==============================================================================%
:- interface.
%==============================================================================%
:- use_module render.
:- use_module matrix.
:- type transformation --->
scale(float, float, float) ;
translate(float, float, float) ;
rotate_x(float) ;
rotate_y(float) ;
rotate_z(float) ;
matrix(matrix.matrix).
:- type matrix_tree.
:- type id == int.
:- func init = matrix_tree.
:- pred insert(transformation, matrix_tree, matrix_tree, id).
% :- mode insert(mdi, mdi, muo, uo) is semidet.
:- mode insert(in, in, out, uo) is semidet.
:- pred find(id, matrix_tree, transformation).
:- mode find(in, in, out) is semidet.
%:- mode find(in, mdi, muo) is semidet.
% :- pred find(id::in, matrix_tree::mdi, matrix_tree::muo, transformation::uo) is semidet.
:- pred remove(id, matrix_tree, matrix_tree).
:- mode remove(in, in, out) is semidet.
%:- mode remove(in, mdi, muo) is semidet.
:- pred remove_det(id, matrix_tree, matrix_tree).
:- mode remove_det(in, in, out) is det.
%:- mode remove_det(in, mdi, muo) is det.
%==============================================================================%
:- implementation.
%==============================================================================%
:- use_module rbtree.
:- use_module counter.
:- type container == rbtree.rbtree(id, transformation).
:- type matrix_tree == {container, counter.counter}.
init = {rbtree.init, counter.init(1)}.
% Shorthand to deconstruct a container while still using state variables.
:- pred deconstruct(matrix_tree, matrix_tree,
container, container, counter, counter).
:- mode deconstruct(in, out, in, out, in, out) is det.
% :- mode deconstruct(di, uo, di, uo, di, uo) is det.
deconstruct({TreeIn, CounterIn}, {TreeOut, CounterOut},
TreeIn, TreeOut, CounterIn, CounterOut).
insert(That, !MTree, ID) :-
deconstruct(!MTree, !Tree, !Counter),
counter.allocate(ID, !Counter),
rbtree.insert(ID, That, !Tree).
find(ID, Tree, Out) :- rbtree.search(Tree, ID, Out).
% TODO: If the ID was the last allocated, we may want to decrement the counter
% to reuse the ID.
remove(ID, !MTree),
deconstruct(!MTree, !Tree, !Counter),
rbtree.remove(ID, _, !Tree).
remove_det(ID, TreeIn, TreeOut) :-
( remove(ID, TreeIn, Tree) ->
TreeOut = Tree
;
TreeOut = TreeIn
).
:- module scene.tree.
%==============================================================================%
:- interface.
%==============================================================================%
:- use_module scene.matrix_tree.
% Scene graph tree structure.
:- type node(Model) --->
transform(scene.matrix_tree.transformation, node(Model)) ;
model(Model) ;
group(node(Model), node(Model)).
%==============================================================================%
:- implementation.
%==============================================================================%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment