collada: draw ship20 (untextured)

This commit is contained in:
Zack Buhman 2026-03-16 19:16:28 -05:00
parent 7f01fd0483
commit 829cea09ba
20 changed files with 1959 additions and 3 deletions

View File

@ -2,7 +2,7 @@
CC=$(PREFIX)gcc CC=$(PREFIX)gcc
CXX=$(PREFIX)g++ CXX=$(PREFIX)g++
OPT = -O2 -march=x86-64-v3 OPT = -O0 -march=x86-64-v3
CSTD = -std=gnu23 CSTD = -std=gnu23
CXXSTD = -std=gnu++23 CXXSTD = -std=gnu++23
@ -35,7 +35,11 @@ OBJS = \
src/collision_scene.o \ src/collision_scene.o \
src/line_art.o \ src/line_art.o \
src/boids.o \ src/boids.o \
src/boids_scene.o src/boids_scene.o \
src/collada/scene.o \
src/collada/effect.o \
src/collada/node_state.o \
data/scenes/ship20/ship20.o
all: test.so all: test.so

427
data/scenes/ship20.cpp Normal file
View File

@ -0,0 +1,427 @@
#include "collada/types.h"
namespace ship20 {
using namespace collada::types;
light const light_environmentambientlight = {
.type = light_type::AMBIENT,
.color = { 0.0f, 0.0f, 0.0f },
};
light const light_omni002_light = {
.type = light_type::POINT,
.color = { 1.0f, 1.0f, 1.0f },
};
light const light_omni003_light = {
.type = light_type::POINT,
.color = { 1.0f, 1.0f, 1.0f },
};
// shipple2_png
image const image_shipple2_png = {
.resource_name = "_0_SHIPPLE2_PNG",
};
image const * const images[] = {
&image_shipple2_png,
};
effect const effect_diffusetexture = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.588f, 0.588f, 0.588f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.5f, 0.5f, 0.5f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
effect const effect_cyanengine = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.9647059f, 1.0f, 1.0f},
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
effect const effect_emissivetexture = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.588f, 0.588f, 0.588f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
material const material_diffusetexture_material = {
.effect = &effect_diffusetexture,
};
material const material_cyanengine_material = {
.effect = &effect_cyanengine,
};
material const material_emissivetexture_material = {
.effect = &effect_emissivetexture,
};
input_element const input_elements_position_0_3_normal_0_3_texcoord_0_3[] = {
{
.semantic = "POSITION",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
{
.semantic = "NORMAL",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
{
.semantic = "TEXCOORD",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
};
triangles const triangles_geom_ship[] = {
{
.count = 2949, // triangles
.index_offset = 0, // indices
.inputs_index = 0, // index into inputs_list
},
{
.count = 60, // triangles
.index_offset = 8847, // indices
.inputs_index = 0, // index into inputs_list
},
{
.count = 239, // triangles
.index_offset = 9027, // indices
.inputs_index = 0, // index into inputs_list
},
};
geometry const geometry_geom_ship = {
.mesh = {
.triangles = triangles_geom_ship,
.triangles_count = 3,
.vertex_buffer_offset = 0,
.vertex_buffer_size = 133272,
.index_buffer_offset = 0,
.index_buffer_size = 38976,
}
};
geometry const * const geometries[] = {
&geometry_geom_ship,
};
transform const transforms_node_environmentambientlight[] = {
};
instance_geometry const instance_geometries_node_environmentambientlight[] = {
};
instance_controller const instance_controllers_node_environmentambientlight[] = {
};
instance_light const instance_lights_node_environmentambientlight[] = {
{
.light = &light_environmentambientlight,
}
};
channel const * const node_channels_node_environmentambientlight[] = {};
node const node_node_environmentambientlight = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_environmentambientlight,
.transforms_count = 0,
.instance_geometries = instance_geometries_node_environmentambientlight,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_environmentambientlight,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_environmentambientlight,
.instance_lights_count = 1,
.channels = node_channels_node_environmentambientlight,
.channels_count = 0,
};
transform const transforms_node_ship[] = {
{
.type = transform_type::ROTATE,
.rotate = {0.0f, 0.0f, 1.0f, -180.0f},
},
};
instance_material const instance_geometry_instance_materials_node_ship_0[] = {
{
.element_index = 1, // an index into mesh.triangles
.material = &material_cyanengine_material,
.emission = { .input_set = -1 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = -1 },
.specular = { .input_set = -1 },
},
{
.element_index = 0, // an index into mesh.triangles
.material = &material_diffusetexture_material,
.emission = { .input_set = -1 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = 0 },
.specular = { .input_set = -1 },
},
{
.element_index = 2, // an index into mesh.triangles
.material = &material_emissivetexture_material,
.emission = { .input_set = 0 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = 0 },
.specular = { .input_set = -1 },
},
};
instance_geometry const instance_geometries_node_ship[] = {
{
.geometry = &geometry_geom_ship,
.instance_materials = instance_geometry_instance_materials_node_ship_0,
.instance_materials_count = 3,
},
};
instance_controller const instance_controllers_node_ship[] = {
};
instance_light const instance_lights_node_ship[] = {
};
channel const * const node_channels_node_ship[] = {
};
node const node_node_ship = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_ship,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_ship,
.instance_geometries_count = 1,
.instance_controllers = instance_controllers_node_ship,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_ship,
.instance_lights_count = 0,
.channels = node_channels_node_ship,
.channels_count = 0,
};
transform const transforms_node_omni002[] = {
{
.type = transform_type::TRANSLATE,
.translate = {-286.5521f, 395.7583f, 161.5579f},
},
};
instance_geometry const instance_geometries_node_omni002[] = {
};
instance_controller const instance_controllers_node_omni002[] = {
};
instance_light const instance_lights_node_omni002[] = {
{
.light = &light_omni002_light,
}
};
channel const * const node_channels_node_omni002[] = {
};
node const node_node_omni002 = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_omni002,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_omni002,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_omni002,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_omni002,
.instance_lights_count = 1,
.channels = node_channels_node_omni002,
.channels_count = 0,
};
transform const transforms_node_omni003[] = {
{
.type = transform_type::TRANSLATE,
.translate = {333.2103f, -314.4593f, 161.5578f},
},
};
instance_geometry const instance_geometries_node_omni003[] = {
};
instance_controller const instance_controllers_node_omni003[] = {
};
instance_light const instance_lights_node_omni003[] = {
{
.light = &light_omni003_light,
}
};
channel const * const node_channels_node_omni003[] = {
};
node const node_node_omni003 = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_omni003,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_omni003,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_omni003,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_omni003,
.instance_lights_count = 1,
.channels = node_channels_node_omni003,
.channels_count = 0,
};
node const * const nodes[] = {
&node_node_environmentambientlight, // 0
&node_node_ship, // 1
&node_node_omni002, // 2
&node_node_omni003, // 3
};
inputs const inputs_list[] = {
{
.elements = input_elements_position_0_3_normal_0_3_texcoord_0_3,
.elements_count = 3,
},
};
types::descriptor const descriptor = {
.nodes = nodes,
.nodes_count = (sizeof (nodes)) / (sizeof (nodes[0])),
.inputs_list = inputs_list,
.inputs_list_count = (sizeof (inputs_list)) / (sizeof (inputs_list[0])),
.images = images,
.images_count = (sizeof (images)) / (sizeof (images[0])),
.position_normal_texture_buffer = "RES_SCENES_SHIP20_VTX",
.joint_weight_buffer = "RES_SCENES_SHIP20_VJW",
.index_buffer = "RES_SCENES_SHIP20_IDX",
};
}

View File

@ -0,0 +1,429 @@
#include "collada/types.h"
#include "data/scenes/ship20.h"
namespace ship20 {
using namespace collada::types;
light const light_environmentambientlight = {
.type = light_type::AMBIENT,
.color = { 0.0f, 0.0f, 0.0f },
};
light const light_omni002_light = {
.type = light_type::POINT,
.color = { 1.0f, 1.0f, 1.0f },
};
light const light_omni003_light = {
.type = light_type::POINT,
.color = { 1.0f, 1.0f, 1.0f },
};
// shipple2_png
image const image_shipple2_png = {
.resource_name = "_0_SHIPPLE2_PNG",
};
image const * const images[] = {
&image_shipple2_png,
};
effect const effect_diffusetexture = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.588f, 0.588f, 0.588f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.5f, 0.5f, 0.5f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
effect const effect_cyanengine = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.9647059f, 1.0f, 1.0f},
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
effect const effect_emissivetexture = {
.type = effect_type::BLINN,
.blinn = {
.emission = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.ambient = {
.type = color_or_texture_type::COLOR,
.color = {0.588f, 0.588f, 0.588f, 1.0f},
},
.diffuse = {
.type = color_or_texture_type::TEXTURE,
.texture = { .image_index = 0 }, // shipple2_png
},
.specular = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.shininess = 10.0f,
.reflective = {
.type = color_or_texture_type::COLOR,
.color = {0.0f, 0.0f, 0.0f, 1.0f},
},
.reflectivity = 0.0f,
.transparent = {
.type = color_or_texture_type::COLOR,
.color = {1.0f, 1.0f, 1.0f, 1.0f},
},
.transparency = 1.0f,
.index_of_refraction = 0.0f,
}
};
material const material_diffusetexture_material = {
.effect = &effect_diffusetexture,
};
material const material_cyanengine_material = {
.effect = &effect_cyanengine,
};
material const material_emissivetexture_material = {
.effect = &effect_emissivetexture,
};
input_element const input_elements_position_0_3_normal_0_3_texcoord_0_3[] = {
{
.semantic = "POSITION",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
{
.semantic = "NORMAL",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
{
.semantic = "TEXCOORD",
.semantic_index = 0,
.format = input_format::FLOAT3,
},
};
triangles const triangles_geom_ship[] = {
{
.count = 2949, // triangles
.index_offset = 0, // indices
.inputs_index = 0, // index into inputs_list
},
{
.count = 60, // triangles
.index_offset = 8847, // indices
.inputs_index = 0, // index into inputs_list
},
{
.count = 239, // triangles
.index_offset = 9027, // indices
.inputs_index = 0, // index into inputs_list
},
};
geometry const geometry_geom_ship = {
.mesh = {
.triangles = triangles_geom_ship,
.triangles_count = 3,
.vertex_buffer_offset = 0,
.vertex_buffer_size = 133272,
.index_buffer_offset = 0,
.index_buffer_size = 38976,
}
};
geometry const * const geometries[] = {
&geometry_geom_ship,
};
transform const transforms_node_environmentambientlight[] = {
};
instance_geometry const instance_geometries_node_environmentambientlight[] = {
};
instance_controller const instance_controllers_node_environmentambientlight[] = {
};
instance_light const instance_lights_node_environmentambientlight[] = {
{
.light = &light_environmentambientlight,
}
};
channel const * const node_channels_node_environmentambientlight[] = {};
node const node_node_environmentambientlight = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_environmentambientlight,
.transforms_count = 0,
.instance_geometries = instance_geometries_node_environmentambientlight,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_environmentambientlight,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_environmentambientlight,
.instance_lights_count = 1,
.channels = node_channels_node_environmentambientlight,
.channels_count = 0,
};
transform const transforms_node_ship[] = {
{
.type = transform_type::ROTATE,
.rotate = {0.0f, 0.0f, 1.0f, -180.0f},
},
};
instance_material const instance_geometry_instance_materials_node_ship_0[] = {
{
.element_index = 1, // an index into mesh.triangles
.material = &material_cyanengine_material,
.emission = { .input_set = -1 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = -1 },
.specular = { .input_set = -1 },
},
{
.element_index = 0, // an index into mesh.triangles
.material = &material_diffusetexture_material,
.emission = { .input_set = -1 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = 0 },
.specular = { .input_set = -1 },
},
{
.element_index = 2, // an index into mesh.triangles
.material = &material_emissivetexture_material,
.emission = { .input_set = 0 },
.ambient = { .input_set = -1 },
.diffuse = { .input_set = 0 },
.specular = { .input_set = -1 },
},
};
instance_geometry const instance_geometries_node_ship[] = {
{
.geometry = &geometry_geom_ship,
.instance_materials = instance_geometry_instance_materials_node_ship_0,
.instance_materials_count = 3,
},
};
instance_controller const instance_controllers_node_ship[] = {
};
instance_light const instance_lights_node_ship[] = {
};
channel const * const node_channels_node_ship[] = {
};
node const node_node_ship = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_ship,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_ship,
.instance_geometries_count = 1,
.instance_controllers = instance_controllers_node_ship,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_ship,
.instance_lights_count = 0,
.channels = node_channels_node_ship,
.channels_count = 0,
};
transform const transforms_node_omni002[] = {
{
.type = transform_type::TRANSLATE,
.translate = {-286.5521f, 395.7583f, 161.5579f},
},
};
instance_geometry const instance_geometries_node_omni002[] = {
};
instance_controller const instance_controllers_node_omni002[] = {
};
instance_light const instance_lights_node_omni002[] = {
{
.light = &light_omni002_light,
}
};
channel const * const node_channels_node_omni002[] = {
};
node const node_node_omni002 = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_omni002,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_omni002,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_omni002,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_omni002,
.instance_lights_count = 1,
.channels = node_channels_node_omni002,
.channels_count = 0,
};
transform const transforms_node_omni003[] = {
{
.type = transform_type::TRANSLATE,
.translate = {333.2103f, -314.4593f, 161.5578f},
},
};
instance_geometry const instance_geometries_node_omni003[] = {
};
instance_controller const instance_controllers_node_omni003[] = {
};
instance_light const instance_lights_node_omni003[] = {
{
.light = &light_omni003_light,
}
};
channel const * const node_channels_node_omni003[] = {
};
node const node_node_omni003 = {
.parent_index = -1,
.type = node_type::NODE,
.transforms = transforms_node_omni003,
.transforms_count = 1,
.instance_geometries = instance_geometries_node_omni003,
.instance_geometries_count = 0,
.instance_controllers = instance_controllers_node_omni003,
.instance_controllers_count = 0,
.instance_lights = instance_lights_node_omni003,
.instance_lights_count = 1,
.channels = node_channels_node_omni003,
.channels_count = 0,
};
node const * const nodes[] = {
&node_node_environmentambientlight, // 0
&node_node_ship, // 1
&node_node_omni002, // 2
&node_node_omni003, // 3
};
inputs const inputs_list[] = {
{
.elements = input_elements_position_0_3_normal_0_3_texcoord_0_3,
.elements_count = 3,
},
};
collada::types::descriptor const descriptor = {
.nodes = nodes,
.nodes_count = (sizeof (nodes)) / (sizeof (nodes[0])),
.inputs_list = inputs_list,
.inputs_list_count = (sizeof (inputs_list)) / (sizeof (inputs_list[0])),
.images = images,
.images_count = (sizeof (images)) / (sizeof (images[0])),
.position_normal_texture_buffer = "data/scenes/ship20/ship20.vtx",
.joint_weight_buffer = "data/scenes/ship20/ship20.vjw",
.index_buffer = "data/scenes/ship20/ship20.idx",
};
}

Binary file not shown.

View File

Binary file not shown.

8
include/collada/effect.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
namespace collada::effect {
extern unsigned int program_static;
extern unsigned int program_skinned;
void load_effects();
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "directxmath/directxmath.h"
#include "collada/types.h"
namespace collada::instance_types {
struct __attribute__((aligned(16))) lookat {
XMVECTOR eye;
XMVECTOR at;
XMVECTOR up;
};
struct __attribute__((aligned(16))) transform {
union {
instance_types::lookat lookat;
XMMATRIX matrix;
XMVECTOR vector;
};
types::transform_type type;
};
struct node_instance {
transform * transforms = NULL;
XMMATRIX world;
};
}

32
include/collada/scene.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include "collada/types.h"
namespace collada::scene {
struct static_skinned {
unsigned int static_mesh;
unsigned int skinned_mesh;
};
struct state {
types::descriptor const * descriptor;
unsigned int vertex_buffer_pnt;
unsigned int vertex_buffer_jw;
unsigned int index_buffer;
static_skinned * vertex_arrays;
int * vertex_buffer_strides;
void load_layouts();
void load_scene(types::descriptor const * const descriptor);
void draw_geometry(types::geometry const & geometry,
types::instance_material const * const instance_materials,
int const instance_materials_count);
void draw_instance_geometries(types::instance_geometry const * const instance_geometries,
int const instance_geometries_count);
void draw_node(types::node const & node);
void draw();
};
}

407
include/collada/types.h Normal file
View File

@ -0,0 +1,407 @@
#pragma once
namespace collada::types {
struct float2 {
float const x;
float const y;
};
struct float3 {
float const x;
float const y;
float const z;
};
struct float4 {
float const x;
float const y;
float const z;
float const w;
};
struct float7 {
float const a;
float const b;
float const c;
float const d;
float const e;
float const f;
float const g;
};
struct matrix {
float const _11, _12, _13, _14;
float const _21, _22, _23, _24;
float const _31, _32, _33, _34;
float const _41, _42, _43, _44;
};
//////////////////////////////////////////////////////////////////////
// geometry
//////////////////////////////////////////////////////////////////////
enum class input_format {
FLOAT1,
FLOAT2,
FLOAT3,
FLOAT4,
INT1,
INT2,
INT3,
INT4,
};
struct input_element {
char const * const semantic;
int const semantic_index;
enum input_format const format;
};
// inputs uniqueness is by evaluted pointer
struct inputs {
input_element const * const elements;
int const elements_count;
};
struct triangles {
int const count;
int const index_offset;
int const inputs_index;
};
struct mesh {
// `triangles` must become a union if non-triangles are implemented.
// instance_geometry is an index into this array.
types::triangles const * triangles;
int const triangles_count;
int const vertex_buffer_offset;
int const vertex_buffer_size;
int const index_buffer_offset;
int const index_buffer_size;
};
struct geometry {
types::mesh mesh;
};
//////////////////////////////////////////////////////////////////////
// light
//////////////////////////////////////////////////////////////////////
enum class light_type {
AMBIENT,
DIRECTIONAL,
POINT,
SPOT,
};
struct light {
light_type type;
float3 color;
};
//////////////////////////////////////////////////////////////////////
// image
//////////////////////////////////////////////////////////////////////
struct image {
const char * resource_name;
};
//////////////////////////////////////////////////////////////////////
// effect
//////////////////////////////////////////////////////////////////////
enum class color_or_texture_type {
COLOR,
TEXTURE,
};
struct texture {
int const image_index; // index in to images
};
struct color_or_texture {
color_or_texture_type type;
union {
float4 color;
types::texture texture;
};
};
struct blinn {
color_or_texture const emission;
color_or_texture const ambient;
color_or_texture const diffuse;
color_or_texture const specular;
float const shininess;
color_or_texture const reflective;
float const reflectivity;
color_or_texture const transparent;
float const transparency;
float const index_of_refraction;
};
struct lambert {
color_or_texture const emission;
color_or_texture const ambient;
color_or_texture const diffuse;
color_or_texture const reflective;
float const reflectivity;
color_or_texture const transparent;
float const transparency;
float const index_of_refraction;
};
struct phong {
color_or_texture const emission;
color_or_texture const ambient;
color_or_texture const diffuse;
color_or_texture const specular;
float const shininess;
color_or_texture const reflective;
float const reflectivity;
color_or_texture const transparent;
float const transparency;
float const index_of_refraction;
};
struct constant {
float4 const color;
color_or_texture const reflective;
float const reflectivity;
color_or_texture const transparent;
float const transparency;
float const index_of_refraction;
};
enum class effect_type {
BLINN,
LAMBERT,
PHONG,
CONSTANT,
};
struct effect {
effect_type const type;
union {
types::blinn const blinn;
types::lambert const lambert;
types::phong const phong;
types::constant const constant;
};
};
//////////////////////////////////////////////////////////////////////
// node
//////////////////////////////////////////////////////////////////////
struct lookat {
float3 const eye;
float3 const at;
float3 const up;
};
enum class transform_type {
LOOKAT,
MATRIX,
ROTATE,
SCALE,
SKEW,
TRANSLATE,
};
struct transform {
transform_type const type;
union {
types::lookat const lookat;
types::matrix const matrix;
float4 const rotate;
float3 const scale;
float7 const skew;
float3 const translate;
};
};
enum class node_type {
JOINT,
NODE,
};
struct material {
types::effect const * const effect;
};
struct bind_vertex_input {
int input_set; // TEXCOORD semantic input slot
};
struct instance_material {
int const element_index; // an index into mesh.triangles
types::material const * const material;
// heavily simplified from collada data model
bind_vertex_input const emission;
bind_vertex_input const ambient;
bind_vertex_input const diffuse;
bind_vertex_input const specular;
};
struct instance_geometry {
types::geometry const * const geometry;
instance_material const * const instance_materials;
int const instance_materials_count;
};
struct skin {
types::geometry const * const geometry; // source
matrix const * const inverse_bind_matrices; // one per joint
int const vertex_buffer_offset;
int const vertex_buffer_size;
};
struct controller {
types::skin skin;
};
struct instance_controller {
types::controller const * const controller;
//node const * const skeleton; // a reference to the root of the joint heirarchy
int const * const joint_node_indices; // one per joint
int const joint_count;
instance_material const * const instance_materials;
int const instance_materials_count;
};
struct instance_light {
types::light const * const light;
};
//////////////////////////////////////////////////////////////////////
// animation
//////////////////////////////////////////////////////////////////////
enum class interpolation {
LINEAR,
BEZIER,
};
struct source {
union {
float const * const float_array;
enum interpolation const * const interpolation_array;
};
int const count;
int const stride;
};
struct sampler {
source const input;
source const output;
source const in_tangent;
source const out_tangent;
source const interpolation;
};
enum class target_attribute {
A, // alpha color component
ANGLE, // euler angle
B, // blue color component
G, // green color component
P, // third texture component
Q, // fourth texture component
R, // red color component
S, // first texture coordinate
T, // second texture coordinate
TIME, // time in seconds
U, // first generic parameter
V, // second generic parameter
W, // fourth cartesian coordinate
X, // first cartesian coordinate
Y, // second cartesian coordinate
Z, // third cartesian coordinate
ALL,
};
struct channel {
sampler const * const source_sampler;
int const target_node_index; // an index into the nodes array
int const target_transform_index;
types::target_attribute const target_attribute;
};
/*
struct animation {
animation const * const animations; // nested animations
int const animations_count;
channels const * const channels;
int const channels_count;
};
*/
struct camera {
float xfov;
float yfov;
float znear;
float zfar;
float aspect_ratio;
};
//////////////////////////////////////////////////////////////////////
// scene
//////////////////////////////////////////////////////////////////////
struct node {
int const parent_index;
node_type const type;
transform const * const transforms;
int const transforms_count;
instance_geometry const * const instance_geometries;
int const instance_geometries_count;
instance_controller const * const instance_controllers;
int const instance_controllers_count;
instance_light const * const instance_lights;
int const instance_lights_count;
channel const * const * const channels;
int const channels_count;
//node const * const * const nodes;
//int const nodes_count;
};
struct descriptor {
// these are only the top-level nodes; nodes may have children
node const * const * const nodes;
int const nodes_count;
inputs const * const inputs_list;
int const inputs_list_count;
image const * const * const images;
int const images_count;
//animation const * const animations;
//int const animations_count;
// hmm, this part is not really platform-agnostic:
char const * const position_normal_texture_buffer;
char const * const joint_weight_buffer;
char const * const index_buffer;
};
}

View File

@ -0,0 +1,7 @@
#pragma once
#include "collada/types.h"
namespace collada_scene::ship20 {
extern collada::types::descriptor const descriptor;
}

View File

@ -0,0 +1,3 @@
namespace ship20 {
extern collada::types::descriptor const descriptor;
}

9
include/new.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <stdlib.h>
template <typename T>
T * New(int elements)
{
return (T *)aligned_alloc(16, (sizeof (T)) * elements);
}

View File

@ -0,0 +1,8 @@
#version 430 core
out vec4 Color;
void main()
{
Color = vec4(1, 0, 0, 1);
}

View File

@ -0,0 +1,12 @@
#version 430 core
layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Normal;
layout (location = 2) in vec3 Texture;
layout (location = 0) uniform mat4 Transform;
void main()
{
gl_Position = Transform * vec4(Position, 1);
}

205
src/collada/animate.cpp Normal file
View File

@ -0,0 +1,205 @@
static inline float fract(float f)
{
return f - floorf(f);
}
static inline float loop(float f, float n)
{
return fract(f / n) * n;
}
static inline int find_frame_ix(source const& source, float t)
{
for (int i = 0; i < source.count - 1; i++) {
if (source.float_array[i] <= t && source.float_array[i+1] > t) {
return i;
}
}
return -1;
}
static inline float linear_interpolate_iv(source const& source, int frame_ix, float t)
{
float prev = source.float_array[(frame_ix+0) * source.stride];
float next = source.float_array[(frame_ix+1) * source.stride];
return (t - prev) / (next - prev);
}
static inline float linear_interpolate_value(source const& source, int frame_ix, int parameter_ix, float iv)
{
float prev = source.float_array[(frame_ix+0) * source.stride + parameter_ix];
float next = source.float_array[(frame_ix+1) * source.stride + parameter_ix];
return prev + iv * (next - prev);
}
static inline float pow3(float f)
{
return f * f * f;
}
static inline float pow2(float f)
{
return f * f;
}
static inline XMVECTOR bezier(XMVECTOR p0, XMVECTOR c0, XMVECTOR c1, XMVECTOR p1, float s)
{
return
p0 * pow3(1 - s)
+ 3 * c0 * s * pow2(1 - s)
+ 3 * c1 * pow2(s) * (1 - s)
+ p1 * pow3(s);
}
static inline float bezier_binary_search(XMVECTOR p0, XMVECTOR c0, XMVECTOR c1, XMVECTOR p1, float want)
{
float low = 0.0f;
float high = 1.0f;
int iterations = 0;
while (iterations < 20) {
iterations += 1;
float s = (high + low) * 0.5f;
XMVECTOR bs = bezier(p0, c0, c1, p1, s);
float t = XMVectorGetX(bs);
const float epsilon = 0.001f;
if (fabsf(t - want) < epsilon) {
return XMVectorGetY(bs);
}
if (t > want) {
high = s;
} else {
low = s;
}
}
print("%f %f\n", XMVectorGetX(p0), XMVectorGetY(p0));
print("%f %f\n", XMVectorGetX(c0), XMVectorGetY(c0));
print("%f %f\n", XMVectorGetX(c1), XMVectorGetY(c1));
print("%f %f\n", XMVectorGetX(p1), XMVectorGetY(p1));
assert(false);
}
static inline XMFLOAT2 const * tangent_index(source const& source, int frame_ix, int parameter_ix)
{
int ix = frame_ix * source.stride + parameter_ix * 2;
return (XMFLOAT2 const *)&source.float_array[ix];
}
static float bezier_sampler(sampler const * const sampler, int frame_ix, int parameter_ix, float t)
{
/*
P0 is (INPUT[i] , OUTPUT[i])
C0 (or T0) is (OUT_TANGENT[i][0] , OUT_TANGENT[i][1])
C1 (or T1) is (IN_TANGENT[i+1][0], IN_TANGENT[i+1][1])
P1 is (INPUT[i+1], OUTPUT[i+1])
*/
float frame0_input = sampler->input.float_array[frame_ix+0];
float frame1_input = sampler->input.float_array[frame_ix+1];
float frame0_output = sampler->output.float_array[(frame_ix+0) * sampler->output.stride + parameter_ix];
float frame1_output = sampler->output.float_array[(frame_ix+1) * sampler->output.stride + parameter_ix];
XMVECTOR p0 = XMVectorSet(frame0_input, frame0_output, 0, 0);
XMVECTOR c0 = XMLoadFloat2(tangent_index(sampler->out_tangent, frame_ix + 0, parameter_ix));
XMVECTOR c1 = XMLoadFloat2(tangent_index(sampler->in_tangent, frame_ix + 1, parameter_ix));
XMVECTOR p1 = XMVectorSet(frame1_input, frame1_output, 0, 0);
return bezier_binary_search(p0, c0, c1, p1, t);
}
static void apply_transform_target(transform& transform,
enum target_attribute channel_target_attribute,
float value)
{
switch (transform.type) {
case transform_type::TRANSLATE: __attribute__((fallthrough));
case transform_type::SCALE:
switch (channel_target_attribute) {
case target_attribute::X: transform.vector = XMVectorSetX(transform.vector, value); return;
case target_attribute::Y: transform.vector = XMVectorSetY(transform.vector, value); return;
case target_attribute::Z: transform.vector = XMVectorSetZ(transform.vector, value); return;
default: assert(false);
}
case transform_type::ROTATE:
switch (channel_target_attribute) {
case target_attribute::X: transform.vector = XMVectorSetX(transform.vector, value); return;
case target_attribute::Y: transform.vector = XMVectorSetY(transform.vector, value); return;
case target_attribute::Z: transform.vector = XMVectorSetZ(transform.vector, value); return;
case target_attribute::ANGLE: transform.vector = XMVectorSetW(transform.vector, value); return;
default: assert(false);
}
default:
assert(false);
break;
}
}
static enum target_attribute const rotate_target_attributes[] = {
target_attribute::X,
target_attribute::Y,
target_attribute::Z,
target_attribute::ANGLE,
};
static enum target_attribute const translate_scale_target_attributes[] = {
target_attribute::X,
target_attribute::Y,
target_attribute::Z,
};
static void animate_channel_segment(channel const& channel,
transform& transform,
int frame_ix, float t)
{
enum target_attribute const * target_attributes = &channel.target_attribute;
int target_attributes_count = 1;
if (channel.target_attribute == target_attribute::ALL) {
switch (transform.type) {
case transform_type::TRANSLATE: __attribute__((fallthrough));
case transform_type::SCALE:
target_attributes = translate_scale_target_attributes;
target_attributes_count = 3;
break;
case transform_type::ROTATE:
target_attributes = rotate_target_attributes;
target_attributes_count = 4;
break;
default:
assert(false);
break;
}
}
for (int parameter_ix = 0; parameter_ix < target_attributes_count; parameter_ix++) {
enum collada::interpolation interpolation = channel.source_sampler->interpolation.interpolation_array[frame_ix];
float value;
if (interpolation == interpolation::BEZIER) {
value = bezier_sampler(channel.source_sampler, frame_ix, parameter_ix, t);
} else {
float iv = linear_interpolate_iv(channel.source_sampler->input, frame_ix, t);
value = linear_interpolate_value(channel.source_sampler->output, frame_ix, parameter_ix, iv);
}
apply_transform_target(transform, target_attributes[parameter_ix], value);
}
}
static void animate_node(node const& node, node_instance& node_instance, float t)
{
for (int i = 0; i < node.channels_count; i++) {
channel const& channel = *node.channels[i];
transform& transform = node_instance.transforms[channel.target_transform_index];
int frame_ix = find_frame_ix(channel.source_sampler->input, t);
assert(frame_ix >= 0); // animation is missing a key frame
animate_channel_segment(channel, transform, frame_ix, t);
}
}

16
src/collada/effect.cpp Normal file
View File

@ -0,0 +1,16 @@
#include "opengl.h"
#include "collada/effect.h"
namespace collada::effect {
unsigned int program_static;
unsigned int program_skinned;
void load_effects()
{
program_static = compile_from_files("shader/collada/static.vert",
nullptr,
"shader/collada/generic.frag");
}
}

View File

@ -0,0 +1,67 @@
#include "directxmath/directxmath.h"
#include "collada/types.h"
#include "collada/instance_types.h"
namespace collada::node_state {
inline static void load_transform(instance_types::transform * instance_transform,
types::transform const & transform)
{
switch (transform.type) {
case types::transform_type::LOOKAT:
instance_transform->lookat.eye = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.eye);
instance_transform->lookat.at = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.at);
instance_transform->lookat.up = XMLoadFloat3((XMFLOAT3 *)&transform.lookat.up);
break;
case types::transform_type::MATRIX:
instance_transform->matrix = XMLoadFloat4x4((XMFLOAT4X4 *)&transform.matrix);
break;
case types::transform_type::ROTATE:
instance_transform->vector = XMLoadFloat4((XMFLOAT4 *)&transform.rotate);
break;
case types::transform_type::SCALE:
instance_transform->vector = XMLoadFloat3((XMFLOAT3*)&transform.scale);
break;
case types::transform_type::TRANSLATE:
instance_transform->vector = XMLoadFloat3((XMFLOAT3*)&transform.translate);
break;
default:
assert(false);
}
}
void initialize_node_transforms(types::node const * const node,
instance_types::node_instance * const node_instance)
{
for (int i = 0; i < node->transforms_count; i++) {
load_transform(&node_instance->transforms[i],
node->transforms[i]);
}
}
inline static bool vector_equal(XMVECTOR V1, XMVECTOR V2)
{
uint32_t CR;
XMVectorEqualR(&CR, V1, V2);
return XMComparisonAllTrue(CR);
}
inline static XMMATRIX transform_matrix(instance_types::transform const& transform)
{
switch (transform.type) {
case types::transform_type::TRANSLATE:
return XMMatrixTranslationFromVector(transform.vector);
case types::transform_type::ROTATE:
assert(!vector_equal(XMVectorSetW(transform.vector, 0), XMVectorZero()));
return XMMatrixRotationNormal(transform.vector,
XMConvertToRadians(XMVectorGetW(transform.vector)));
case types::transform_type::SCALE:
return XMMatrixScalingFromVector(transform.vector);
case types::transform_type::MATRIX:
return transform.matrix;
default:
assert(false);
break;
}
}
}

280
src/collada/scene.cpp Normal file
View File

@ -0,0 +1,280 @@
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "glad/gl.h"
#include "directxmath/directxmath.h"
#include "new.h"
#include "file.h"
#include "view.h"
#include "collada/types.h"
#include "collada/instance_types.h"
#include "collada/scene.h"
#include "collada/effect.h"
namespace collada::scene {
struct layout {
struct {
unsigned int position;
unsigned int normal;
unsigned int texture;
unsigned int blend_indices;
unsigned int blend_weight;
} attribute;
struct {
unsigned int transform;
} uniform;
};
const layout layout = {
.attribute = {
.position = 0,
.normal = 1,
.texture = 2,
.blend_indices = 3,
.blend_weight = 4,
},
.uniform = {
.transform = 0,
},
};
unsigned int attribute_location(char const * const semantic,
int semantic_index)
{
if (strcmp(semantic, "POSITION") == 0 && semantic_index == 0) {
return layout.attribute.position;
}
if (strcmp(semantic, "NORMAL") == 0 && semantic_index == 0) {
return layout.attribute.normal;
}
if (strcmp(semantic, "TEXCOORD") == 0 && semantic_index == 0) {
return layout.attribute.texture;
}
if (strcmp(semantic, "BLENDINDICES") == 0 && semantic_index == 0) {
return layout.attribute.blend_indices;
}
if (strcmp(semantic, "BLENDWEIGHT") == 0 && semantic_index == 0) {
return layout.attribute.blend_weight;
}
printf("unknown semantic %s index %d\n",semantic, semantic_index);
assert(false);
}
unsigned int input_format_gl_size(types::input_format format)
{
switch (format) {
case types::input_format::FLOAT1: return 1;
case types::input_format::FLOAT2: return 2;
case types::input_format::FLOAT3: return 3;
case types::input_format::FLOAT4: return 4;
case types::input_format::INT1: return 1;
case types::input_format::INT2: return 2;
case types::input_format::INT3: return 3;
case types::input_format::INT4: return 4;
default: assert(false);
}
}
unsigned int input_format_gl_type(types::input_format format)
{
switch (format) {
case types::input_format::FLOAT1: return GL_FLOAT;
case types::input_format::FLOAT2: return GL_FLOAT;
case types::input_format::FLOAT3: return GL_FLOAT;
case types::input_format::FLOAT4: return GL_FLOAT;
case types::input_format::INT1: return GL_INT;
case types::input_format::INT2: return GL_INT;
case types::input_format::INT3: return GL_INT;
case types::input_format::INT4: return GL_INT;
default: assert(false);
}
}
// return stride
static inline int load_layout(types::inputs const & inputs,
int binding,
int start_offset,
unsigned int vertex_array)
{
glBindVertexArray(vertex_array);
int offset = start_offset;
for (int i = 0; i < inputs.elements_count; i++) {
unsigned int location = attribute_location(inputs.elements[i].semantic, inputs.elements[i].semantic_index);
glEnableVertexAttribArray(location);
unsigned int gl_size = input_format_gl_size(inputs.elements[i].format);
unsigned int gl_type = input_format_gl_type(inputs.elements[i].format);
glVertexAttribFormat(location, gl_size, gl_type, GL_FALSE, offset);
glVertexAttribBinding(location, binding);
offset += gl_size * 4;
}
int stride = offset - start_offset;
glBindVertexArray(0);
return stride;
}
types::input_element const input_elements_blendindices_0_4_blendweight_0_4[] = {
{
.semantic = "BLENDINDICES",
.semantic_index = 0,
.format = types::input_format::INT4,
},
{
.semantic = "BLENDWEIGHT",
.semantic_index = 0,
.format = types::input_format::FLOAT4,
},
};
types::inputs const skin_inputs = {
.elements = input_elements_blendindices_0_4_blendweight_0_4,
.elements_count = 2,
};
void state::load_layouts()
{
vertex_arrays = New<static_skinned>(descriptor->inputs_list_count);
vertex_buffer_strides = New<int>(descriptor->inputs_list_count);
glGenVertexArrays(2 * descriptor->inputs_list_count, (unsigned int *)vertex_arrays);
for (int i = 0; i < descriptor->inputs_list_count; i++) {
// static
int stride = load_layout(descriptor->inputs_list[i],
0, // binding
0, // start_offset
vertex_arrays[i].static_mesh);
vertex_buffer_strides[i] = stride;
// skinned
load_layout(descriptor->inputs_list[i],
0, // binding
0, // start_offset
vertex_arrays[i].skinned_mesh);
load_layout(skin_inputs,
1, // binding
0, // start_offset
vertex_arrays[i].skinned_mesh);
}
}
unsigned int load_vertex_buffer(const char * filename)
{
int size;
void * data = read_file(filename, &size);
assert(data != NULL);
unsigned int vertex_buffer;
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
free(data);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return vertex_buffer;
}
unsigned int load_index_buffer(const char * filename)
{
int size;
void * data = read_file(filename, &size);
assert(data != NULL);
printf("%s %d\n", filename, size);
unsigned int index_buffer;
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
free(data);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return index_buffer;
}
void state::load_scene(types::descriptor const * const descriptor)
{
this->descriptor = descriptor;
load_layouts();
vertex_buffer_pnt = load_vertex_buffer(descriptor->position_normal_texture_buffer);
vertex_buffer_jw = load_vertex_buffer(descriptor->joint_weight_buffer);
index_buffer = load_index_buffer(descriptor->index_buffer);
}
void state::draw_geometry(types::geometry const & geometry,
types::instance_material const * const instance_materials,
int const instance_materials_count)
{
glUseProgram(collada::effect::program_static);
types::mesh const& mesh = geometry.mesh;
for (int j = 0; j < instance_materials_count; j++) {
types::instance_material const& instance_material = instance_materials[j];
types::triangles const& triangles = mesh.triangles[instance_material.element_index];
//set_instance_material(instance_material);
unsigned int vertex_buffer_offset = mesh.vertex_buffer_offset;
unsigned int vertex_buffer_stride = vertex_buffer_strides[triangles.inputs_index];
unsigned int vertex_array = vertex_arrays[triangles.inputs_index].static_mesh;
glBindVertexArray(vertex_array);
glBindVertexBuffer(0, vertex_buffer_pnt, vertex_buffer_offset, vertex_buffer_stride);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
unsigned int index_count = triangles.count * 3;
unsigned int indices = triangles.index_offset * (sizeof (unsigned int)) + mesh.index_buffer_offset;
unsigned int instance_count = 1;
unsigned int base_vertex = 0;
unsigned int base_instance = 1;
glDrawElementsInstancedBaseVertexBaseInstance(GL_TRIANGLES,
index_count,
GL_UNSIGNED_INT,
(void *)((ptrdiff_t)indices),
instance_count,
base_vertex,
base_instance);
}
}
void state::draw_instance_geometries(types::instance_geometry const * const instance_geometries,
int const instance_geometries_count)
{
for (int i = 0; i < instance_geometries_count; i++) {
types::instance_geometry const &instance_geometry = instance_geometries[i];
draw_geometry(*instance_geometry.geometry,
instance_geometry.instance_materials,
instance_geometry.instance_materials_count);
}
}
void state::draw_node(types::node const & node)
{
draw_instance_geometries(node.instance_geometries, node.instance_geometries_count);
}
void state::draw()
{
glUseProgram(collada::effect::program_static);
glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&view::state.float_transform);
for (int i = 0; i < descriptor->nodes_count; i++) {
types::node const & node = *descriptor->nodes[i];
// joints are not drawn
if (node.type != types::node_type::NODE)
continue;
draw_node(node);
}
}
}

View File

@ -21,6 +21,10 @@
#include "collision_scene.h" #include "collision_scene.h"
#include "collision.h" #include "collision.h"
#include "boids_scene.h" #include "boids_scene.h"
#include "collada/effect.h"
#include "collada/scene.h"
#include "collada/types.h"
#include "data/scenes/ship20.h"
struct line_location { struct line_location {
struct { struct {
@ -50,6 +54,8 @@ static quad_location quad_location;
// globals // globals
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
static collada::scene::state scene_state;
unsigned int empty_vertex_array_object = -1; unsigned int empty_vertex_array_object = -1;
unsigned int quad_index_buffer = -1; unsigned int quad_index_buffer = -1;
@ -290,6 +296,13 @@ void load(const char * source_path)
line_art::load(); line_art::load();
collision_scene::load(); collision_scene::load();
boids_scene::load(); boids_scene::load();
//////////////////////////////////////////////////////////////////////
// collada
//////////////////////////////////////////////////////////////////////
collada::effect::load_effects();
scene_state.load_scene(&ship20::descriptor);
} }
void update_keyboard(int up, int down, int left, int right, void update_keyboard(int up, int down, int left, int right,
@ -569,7 +582,8 @@ void draw()
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//collision_scene::draw(); //collision_scene::draw();
boids_scene::draw(); //boids_scene::draw();
scene_state.draw();
} }
last_frame_time = current_time; last_frame_time = current_time;