Skip to content

Instantly share code, notes, and snippets.

@squircledev
Last active June 6, 2021 03:18
Show Gist options
  • Save squircledev/bf8335e2962970bb2da972018e905443 to your computer and use it in GitHub Desktop.
Save squircledev/bf8335e2962970bb2da972018e905443 to your computer and use it in GitHub Desktop.
gltf loader
function __trace()
{
var _r:string = "";
for(var i = 0; i < argument_count; i++)
{
_r += string(argument[i]);
}
show_debug_message(_r);
}
function Camera(_fov, _aspect, _znear, _zfar) constructor
{
camera = camera_create();
proj_mat = matrix_build_projection_perspective_fov(_fov, _aspect,_znear, _zfar);
camera_set_proj_mat(camera, proj_mat);
x = 0;
y = 0;
z = 0;
xto = 0;
yto = 0;
zto = 0;
static SetView = function(_view)
{
view_enabled = true;//Enable the use of views
view_set_visible(_view, true);//Make this view visible
view_set_camera(_view, camera);
}
static SetViewMat = function(_view)
{
camera_set_view_mat(view_camera[_view], matrix_build_lookat(x,y,z, xto,yto,zto, 0,0,1));
}
static SetPosition = function(_x, _y, _z)
{
x = _x;
y = _y;
z = _z;
}
static SetLookAt = function(_xto, _yto, _zto)
{
xto = _xto;
yto = _yto;
zto = _zto;
}
}
function Vector2(_x, _y) constructor
{
x = _x;
y = _y;
}
function Vector3(_x, _y, _z) constructor
{
x = _x;
y = _y;
z = _z;
}
function Vector4(_x, _y, _z, _w) constructor
{
x = _x;
y = _y;
z = _z;
w = _w;
}
function Mat3(_array) constructor
{
array = _array;
static Set = function(_x, _y, _value)
{
array[_x + _y * 3] = _value;
}
static Get = function(_x, _y)
{
return array[_x + _y * 3];
}
}
function Mat4(_array) constructor
{
array = _array;
static Set = function(_x, _y, _value)
{
array[_x + _y * 4] = _value;
}
static Get = function(_x, _y)
{
return array[_x + _y * 4];
}
}
function GltfObject() constructor
{
asset = {};
scene = 0;
scenes = [];
nodes = [];
animations = [];
skins = [];
materials = [];
meshes = [];
accessors = [];
buffer_views = [];
buffers = [];
static SceneAdd = function(_scene)
{
array_push(scenes, _scene);
}
static NodeAdd = function(_node)
{
array_push(nodes, _node);
}
static MaterialAdd = function(_material)
{
array_push(materials, _material);
}
static MeshAdd = function(_mesh)
{
array_push(meshes, _mesh);
}
static AccessorAdd = function(_accessor)
{
array_push(accessors, _accessor);
}
static BufferViewAdd = function(_buffer_view)
{
array_push(buffer_views, _buffer_view);
}
static BufferAdd = function(_buffer)
{
array_push(buffers, _buffer);
}
static AnimationAdd = function(_animation)
{
array_push(animations, _animation);
}
static SkinAdd = function(_skin)
{
array_push(skins, _skin);
}
static BoneMatrixGet = function(_time)
{
}
static VertexBufferCreate = function(_mesh_index)
{
var _return = [];
var _mesh = meshes[_mesh_index];
var _attributes = _mesh.primitives[0].attributes;
vertex_format_begin();
if(variable_struct_exists(_attributes, "POSITION"))
{
vertex_format_add_position_3d();
}
if(variable_struct_exists(_attributes, "NORMAL"))
{
vertex_format_add_normal();
}
if(variable_struct_exists(_attributes, "TEXCOORD_0"))
{
vertex_format_add_texcoord();
}
if(variable_struct_exists(_attributes, "TEXCOORD_1"))
{
vertex_format_add_texcoord();
}
if(variable_struct_exists(_attributes, "JOINTS_0"))
{
vertex_format_add_custom(vertex_type_float4, vertex_usage_blendindices);
}
if(variable_struct_exists(_attributes, "WEIGHTS_0"))
{
vertex_format_add_custom(vertex_type_float4, vertex_usage_blendweight);
}
vertex_format_add_color();
_return[0] = vertex_format_end();
var _vbuff = vertex_create_buffer();
vertex_begin(_vbuff, _return[0]);
for(var i = 0; i < array_length(_mesh.primitives[0].indices); i++)
{
var _ind = _mesh.primitives[0].indices[i];
if(variable_struct_exists(_attributes, "POSITION"))
{
vertex_position_3d(_vbuff, _attributes.POSITION[_ind].x, _attributes.POSITION[_ind].y, -_attributes.POSITION[_ind].z);
}
if(variable_struct_exists(_attributes, "NORMAL"))
{
vertex_normal(_vbuff, _attributes.NORMAL[_ind].x, _attributes.NORMAL[_ind].y, -_attributes.NORMAL[_ind].z);
}
if(variable_struct_exists(_attributes, "TEXCOORD_0"))
{
vertex_texcoord(_vbuff, _attributes.TEXCOORD_0[_ind].x, _attributes.TEXCOORD_0[_ind].y);
}
if(variable_struct_exists(_attributes, "TEXCOORD_1"))
{
vertex_texcoord(_vbuff, _attributes.TEXCOORD_1[_ind].x, _attributes.TEXCOORD_1[_ind].y);
}
if(variable_struct_exists(_attributes, "JOINTS_0"))
{
__trace(_attributes.JOINTS_0[_ind]);
vertex_float4(_vbuff, _attributes.JOINTS_0[_ind].x, _attributes.JOINTS_0[_ind].y, _attributes.JOINTS_0[_ind].z, _attributes.JOINTS_0[_ind].w);
}
if(variable_struct_exists(_attributes, "WEIGHTS_0"))
{
vertex_float4(_vbuff, _attributes.WEIGHTS_0[_ind].x, _attributes.WEIGHTS_0[_ind].y, _attributes.WEIGHTS_0[_ind].z, _attributes.WEIGHTS_0[_ind].w);
}
vertex_color(_vbuff, c_white, 1);
}
vertex_end(_vbuff);
_return[1] = _vbuff;
return _return;
}
}
function GltfScene(_name) constructor
{
name = _name;
nodes = [];
static NodeAdd = function(_node)
{
array_push(nodes, _node);
}
}
function GltfNode(_name) constructor
{
name = _name;
mesh = noone;
translation = new Vector3(0, 0, 0);
children = [];
static SetMesh = function(_mesh)
{
mesh = _mesh;
}
static SetTranslation = function(_x, _y, _z)
{
translation.x = _x;
translation.y = _y;
translation.z = _z;
}
static ChildAdd = function(_child)
{
array_push(children, _child);
}
}
function GltfAnimation(_name) constructor
{
name = _name;
channels = [];
samplers = [];
static ChannelAdd = function(_channel)
{
array_push(channels, _channel);
}
static SamplerAdd = function(_sampler)
{
array_push(samplers, _sampler);
}
}
function GltfAnimationChannel(_sampler, _target) constructor
{
sampler = _sampler;
target = _target;
}
function GltfAnimationChannelTarget(_node, _path) constructor
{
node = _node;
path = _path;
}
function GltfAnimationSampler(_input, _interpolation, _output) constructor
{
input = _input;
interpolation = _interpolation;
output = _output;
}
function GltfSkin(_name, _joints, _inverse_bind_matrices) constructor
{
name = _name;
joints = _joints;
inverse_bind_matrices = _inverse_bind_matrices;
}
function GltfMaterial(_name) constructor
{
name = _name;
}
function GltfMesh(_name) constructor
{
name = _name;
primitives = [];
static PrimitiveAdd = function(_primitive)
{
array_push(primitives, _primitive);
}
}
function GltfPrimitive(_attribute_struct, _indices) constructor
{
attributes = _attribute_struct;
indices = _indices;
material = noone;
static SetMaterial = function(_material)
{
material = _material;
}
}
function GltfAccessor(_buffer_view, _component_type, _count, _type) constructor
{
buffer_view = _buffer_view;
component_type = _component_type;
count = _count;
minimum = [];
maximum = [];
type = _type;
static BufferRead = function(_bin)
{
var _read_type = buffer_f32;
switch(component_type)
{
case(5120):
{
_read_type = buffer_s8;
break;
}
case(5121):
{
_read_type = buffer_u8;
break;
}
case(5122):
{
_read_type = buffer_s16;
break;
}
case(5123):
{
_read_type = buffer_u16;
break;
}
case(5124):
{
_read_type = buffer_u32;
break;
}
case(5126):
{
_read_type = buffer_f32;
break;
}
default:
{
show_error("Component type not known: " + string(component_type), true);
break;
}
}
var _buff = buffer_view.buffer.buffer;
var _b = buffer_create(buffer_view.buffer.byte_length, buffer_fixed, 1);
buffer_copy(_buff, 0, buffer_view.buffer.byte_length,_b,0);
buffer_seek(_b, buffer_seek_start, buffer_view.byte_offset);
var _values = [];
__trace("im reading ", component_type);
if(type == "VEC4")
{
repeat(count)
{
var _x = buffer_read(_b, _read_type);
var _y = buffer_read(_b, _read_type);
var _z = buffer_read(_b, _read_type);
var _w = buffer_read(_b, _read_type);
// __trace(_x, " ", _y, " ", _z, " ", _w);
var _v4 = new Vector4(_x, _y, _z, _w);
array_push(_values, _v4);
}
}
else if(type == "VEC3")
{
repeat(count)
{
var _x = buffer_read(_b, _read_type);
var _y = buffer_read(_b, _read_type);
var _z = buffer_read(_b, _read_type);
// __trace(_x, " ", _y, " ", _z);
var _v3 = new Vector3(_x, _y, _z);
array_push(_values, _v3);
}
}
else if(type == "VEC2")
{
repeat(count)
{
var _x = buffer_read(_b, _read_type);
var _y = buffer_read(_b, _read_type);
// __trace(_x, " ", _y);
var _v2 = new Vector2(_x, _y);
array_push(_values, _v2);
}
}
else if(type == "SCALAR")
{
repeat(count)
{
var _s = buffer_read(_b, _read_type);
// __trace(_s);
array_push(_values, _s);
}
}
else if(type == "MAT3")
{
repeat(count)
{
var _array = [];
repeat(9)
{
array_push(_array, buffer_read(_b, _read_type));
}
var _m3 = new Mat3(_array);
array_push(_values, _m3);
}
}
else if(type == "MAT4")
{
repeat(count)
{
var _array = [];
repeat(16)
{
array_push(_array, buffer_read(_b, _read_type));
}
var _m4 = new Mat4(_array);
array_push(_values, _m4);
}
}
buffer_delete(_b);
return _values;
}
}
function GltfBufferView(_buffer, _byte_length, _byte_offset) constructor
{
buffer = _buffer;
byte_length = _byte_length;
byte_offset = _byte_offset;
}
function GltfBuffer(_byte_length, _bin) constructor
{
byte_length = _byte_length;
bin = _bin;
buffer = buffer_load(_bin);
}
function gltf_parse(_gltf, _bin)
{
/*
PARSE ORDER:
1. buffers
2. buffer views
3. accessors
4. materials
5. meshes
6. nodes
7. animations
a. samplers
b. channels
8. skins
9. scenes
10. scene
11. asset
need to be in this order because the bottom ones reference the above ones.
*/
var _obj = new GltfObject(); ///@is {GltfObject}
var _gltf_file = file_text_open_read(_gltf);
var _gltf_text = "";
while(file_text_eof(_gltf_file) == false)
{
_gltf_text += file_text_readln(_gltf_file);
}
file_text_close(_gltf_file);
var _json_struct = json_parse(_gltf_text);
// BUFFERS
var _buffers_array = _json_struct.buffers;
for(var i = 0; i < array_length(_buffers_array); i++)
{
var _buff = _buffers_array[i];
var _byte_length = _buff.byteLength;
var _uri = _buff.uri;
_obj.BufferAdd(new GltfBuffer(_byte_length, _bin));
}
// BUFFER VIEWS
var _buffer_view_array = _json_struct.bufferViews;
for(var i = 0; i < array_length(_buffer_view_array); i++)
{
var _bv = _buffer_view_array[i];
var _buffer_index = _bv.buffer;
var _buffer = _obj.buffers[_buffer_index];
var _byte_length = _bv.byteLength;
var _byte_offset = _bv.byteOffset;
var _uri = _buff.uri;
_obj.BufferViewAdd(new GltfBufferView(_buffer, _byte_length, _byte_offset));
}
// ACCESSORS
var _accessor_array = _json_struct.accessors;
for(var i = 0; i < array_length(_accessor_array); i++)
{
var _a = _accessor_array[i];
var _buffer_view_index = _a.bufferView;
var _buffer_view = _obj.buffer_views[_buffer_view_index];
var _component_type = _a.componentType;
var _count = _a.count;
var _type = _a.type;
_obj.AccessorAdd(new GltfAccessor(_buffer_view, _component_type, _count, _type));
}
// MATERIALS
if(variable_struct_exists(_json_struct, "materials"))
{
var _material_array = _json_struct.materials;
for(var i = 0; i < array_length(_material_array); i++)
{
var _mat = _material_array[i];
var _name = _mat.name;
_obj.MaterialAdd(new GltfMaterial(_name));
}
}
// MESHES
__trace("reading meshes");
var _mesh_array = _json_struct.meshes;
for(var i = 0; i < array_length(_mesh_array); i++)
{
var _mesh = _mesh_array[i];
var _name = _mesh.name;
var _mesh_obj = new GltfMesh(_name);
for(var j = 0; j < array_length(_mesh.primitives); j++)
{
var _p = _mesh.primitives[j];
var _attributes = {};
var _vars = variable_struct_get_names(_p.attributes);
__trace(_vars);
for(var k = 0; k < array_length(_vars); k++)
{
var _accessor_index = variable_struct_get(_p.attributes, _vars[k]);
var _accessor_obj = _obj.accessors[_accessor_index];
var _values = _accessor_obj.BufferRead(_bin);
var _component_type = _accessor_obj.component_type;
variable_struct_set(_attributes, _vars[k], _values);
}
var _ind = _obj.accessors[_p.indices].BufferRead(_bin);
var _primitive = new GltfPrimitive(_attributes, _ind);
if(variable_struct_exists(_p, "material"))
{
_primitive.SetMaterial(_p.material);
}
_mesh_obj.PrimitiveAdd(_primitive);
}
_obj.MeshAdd(_mesh_obj);
}
// NODES
var _node_array = _json_struct.nodes;
for(var i = 0; i < array_length(_node_array); i++)
{
var _node = _node_array[i];
var _name = _node.name;
var _node_obj = new GltfNode(_name);
if(variable_struct_exists(_node, "mesh"))
{
var _mesh = _obj.meshes[_node.mesh];
_node_obj.SetMesh(_mesh);
}
if(variable_struct_exists(_node, "translation"))
{
_node_obj.SetTranslation(_node.translation[0], _node.translation[1], _node.translation[2]);
}
_obj.NodeAdd(_node_obj);
}
// ANIMATIONS
var _animation_array = _json_struct.animations;
for(var i = 0; i < array_length(_animation_array); i++)
{
var _animation = _animation_array[i];
var _anim_obj = new GltfAnimation(_animation.name);
var _samplers = _animation.samplers;
for(var j = 0; j < array_length(_samplers); j++)
{
var _sampler = _samplers[j];
var _sampler_obj = new GltfAnimationSampler(_obj.accessors[_sampler.input], _sampler.interpolation, _obj.accessors[_sampler.output]);
_anim_obj.SamplerAdd(_sampler_obj);
}
var _channels = _animation.channels;
for(var j = 0; j < array_length(_channels); j++)
{
var _channel = _channels[j];
var _sampler = _anim_obj.samplers[_channel.sampler];
var _target = new GltfAnimationChannelTarget(_obj.nodes[_channel.target.node], _channel.target.path);
var _channel_obj = new GltfAnimationChannel(_sampler, _target);
_anim_obj.ChannelAdd(_channel_obj);
}
_obj.AnimationAdd(_anim_obj);
}
// SKINS
var _skin_array = _json_struct.skins;
for(var i = 0; i < array_length(_skin_array); i++)
{
var _skin = _skin_array[i];
var _inverse_bind_matrices = _obj.accessors[_skin.inverseBindMatrices].BufferRead();
var _joints = _skin.joints;
var _joint_array = [];
for(var j = 0; j < array_length(_joints); j++)
{
var _joint = _obj.nodes[_joints[j]];
array_push(_joint_array, _joint);
}
_obj.SkinAdd(new GltfSkin(_skin.name, _joint_array, _inverse_bind_matrices));
}
// SCENES
var _scene_array = _json_struct.scenes;
for(var i = 0; i < array_length(_scene_array); i++)
{
var _scene = _scene_array[i];
var _name = _scene.name;
var _nodes = [];
var _scene_obj = new GltfScene(_name);
for(var j = 0; j < array_length(_scene.nodes); j++)
{
_scene_obj.NodeAdd(_obj.nodes[_scene.nodes[j]]);
}
_obj.SceneAdd(_scene_obj);
}
// SCENE
_obj.scene = _json_struct.scene;
// ASSET
// todo... seems unimportant right now
return _obj;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment