collada: render instance controllers

This commit is contained in:
Zack Buhman 2026-03-17 11:57:07 -05:00
parent 5e24166ac8
commit 0489f33243
15 changed files with 2714 additions and 23 deletions

View File

@ -40,7 +40,8 @@ OBJS = \
src/collada/scene.o \ src/collada/scene.o \
src/collada/effect.o \ src/collada/effect.o \
src/collada/node_state.o \ src/collada/node_state.o \
data/scenes/ship20/ship20.o data/scenes/ship20/ship20.o \
data/scenes/noodle/noodle.o
all: test.so all: test.so

11
build_collada.sh Normal file
View File

@ -0,0 +1,11 @@
set -eux
PYTHONPATH=~/d3d10 python -m collada.main \
path/to/noodle.DAE \
data/scenes/noodle/noodle.cpp \
data/scenes/noodle/noodle.vtx \
data/scenes/noodle/noodle.vjw \
data/scenes/noodle/noodle.idx
PYTHONPATH=~/d3d10 python -m collada.main \
include/data/scenes/noodle.h

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -23,7 +23,7 @@ light const light_omni003_light = {
// shipple2_png // shipple2_png
image const image_shipple2_png = { image const image_shipple2_png = {
.resource_name = "data/scenes/ship20/shipple2.dds", .uri = "data/scenes/ship20/shipple2.dds",
}; };
image const * const images[] = { image const * const images[] = {

View File

@ -16,7 +16,7 @@ namespace collada::scene {
unsigned int index_buffer; unsigned int index_buffer;
static_skinned * vertex_arrays; static_skinned * vertex_arrays;
int * vertex_buffer_strides; int * vertex_buffer_strides_pnt;
unsigned int * textures; unsigned int * textures;
@ -34,6 +34,12 @@ namespace collada::scene {
int const instance_materials_count); int const instance_materials_count);
void draw_instance_geometries(types::instance_geometry const * const instance_geometries, void draw_instance_geometries(types::instance_geometry const * const instance_geometries,
int const instance_geometries_count); int const instance_geometries_count);
void draw_skin(types::skin const& skin,
types::instance_material const * const instance_materials,
int const instance_materials_count);
void draw_instance_controllers(types::instance_controller const * const instance_controllers,
int const instance_controllers_count);
void draw_node(types::node const & node); void draw_node(types::node const & node);
void draw(); void draw();
}; };

View File

@ -108,7 +108,7 @@ namespace collada::types {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
struct image { struct image {
const char * resource_name; const char * uri;
}; };
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

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

View File

@ -0,0 +1,18 @@
#version 430 core
layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Normal;
layout (location = 2) in vec2 Texture;
layout (location = 0) uniform mat4 Transform;
out vec3 PixelNormal;
out vec2 PixelTexture;
void main()
{
PixelNormal = Normal;
PixelTexture = vec2(Texture.x, 1.0 - Texture.y);
gl_Position = Transform * vec4(Position, 1);
}

View File

@ -12,5 +12,9 @@ namespace collada::effect {
program_static = compile_from_files("shader/collada/static.vert", program_static = compile_from_files("shader/collada/static.vert",
nullptr, nullptr,
"shader/collada/generic.frag"); "shader/collada/generic.frag");
program_skinned = compile_from_files("shader/collada/skinned.vert",
nullptr,
"shader/collada/generic.frag");
} }
} }

View File

@ -177,10 +177,14 @@ namespace collada::scene {
.elements_count = 2, .elements_count = 2,
}; };
const int vertex_buffer_stride_jw
= input_format_gl_size(skin_inputs.elements[0].format)
+ input_format_gl_size(skin_inputs.elements[1].format);
void state::load_layouts() void state::load_layouts()
{ {
vertex_arrays = New<static_skinned>(descriptor->inputs_list_count); vertex_arrays = New<static_skinned>(descriptor->inputs_list_count);
vertex_buffer_strides = New<int>(descriptor->inputs_list_count); vertex_buffer_strides_pnt = New<int>(descriptor->inputs_list_count);
glGenVertexArrays(2 * descriptor->inputs_list_count, (unsigned int *)vertex_arrays); glGenVertexArrays(2 * descriptor->inputs_list_count, (unsigned int *)vertex_arrays);
@ -190,7 +194,7 @@ namespace collada::scene {
0, // binding 0, // binding
0, // start_offset 0, // start_offset
vertex_arrays[i].static_mesh); vertex_arrays[i].static_mesh);
vertex_buffer_strides[i] = stride; vertex_buffer_strides_pnt[i] = stride;
// skinned // skinned
load_layout(descriptor->inputs_list[i], load_layout(descriptor->inputs_list[i],
@ -226,7 +230,6 @@ namespace collada::scene {
int size; int size;
void * data = read_file(filename, &size); void * data = read_file(filename, &size);
assert(data != NULL); assert(data != NULL);
printf("%s %d\n", filename, size);
unsigned int index_buffer; unsigned int index_buffer;
glGenBuffers(1, &index_buffer); glGenBuffers(1, &index_buffer);
@ -255,7 +258,7 @@ namespace collada::scene {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
load_dds_texture_2D(image->resource_name); load_dds_texture_2D(image->uri);
} }
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
@ -339,20 +342,18 @@ namespace collada::scene {
types::mesh const& mesh = geometry.mesh; types::mesh const& mesh = geometry.mesh;
for (int j = 0; j < instance_materials_count; j++) { for (int j = 0; j < instance_materials_count; j++) {
//if (j != 1)
//continue;
types::instance_material const& instance_material = instance_materials[j]; types::instance_material const& instance_material = instance_materials[j];
types::triangles const& triangles = mesh.triangles[instance_material.element_index]; types::triangles const& triangles = mesh.triangles[instance_material.element_index];
set_instance_material(instance_material); 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; unsigned int vertex_array = vertex_arrays[triangles.inputs_index].static_mesh;
unsigned int vertex_buffer_offset_pnt = mesh.vertex_buffer_offset;
unsigned int vertex_buffer_stride_pnt = vertex_buffer_strides_pnt[triangles.inputs_index];
glBindVertexArray(vertex_array); glBindVertexArray(vertex_array);
glBindVertexBuffer(0, vertex_buffer_pnt, vertex_buffer_offset, vertex_buffer_stride); glBindVertexBuffer(0, vertex_buffer_pnt, vertex_buffer_offset_pnt, vertex_buffer_stride_pnt);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
unsigned int index_count = triangles.count * 3; unsigned int index_count = triangles.count * 3;
@ -382,19 +383,77 @@ namespace collada::scene {
} }
} }
void state::draw_skin(types::skin const& skin,
types::instance_material const * const instance_materials,
int const instance_materials_count)
{
glUseProgram(collada::effect::program_skinned);
types::mesh const& mesh = skin.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_array = vertex_arrays[triangles.inputs_index].skinned_mesh;
unsigned int vertex_buffer_offset_pnt = mesh.vertex_buffer_offset;
unsigned int vertex_buffer_stride_pnt = vertex_buffer_strides_pnt[triangles.inputs_index];
unsigned int vertex_buffer_offset_jw = skin.vertex_buffer_offset;
glBindVertexArray(vertex_array);
glBindVertexBuffer(0, vertex_buffer_pnt, vertex_buffer_offset_pnt, vertex_buffer_stride_pnt);
glBindVertexBuffer(1, vertex_buffer_jw, vertex_buffer_offset_jw, vertex_buffer_stride_jw);
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 = 0;
glDrawElementsInstancedBaseVertexBaseInstance(GL_TRIANGLES,
index_count,
GL_UNSIGNED_INT,
(void *)((ptrdiff_t)indices),
instance_count,
base_vertex,
base_instance);
}
}
void state::draw_instance_controllers(types::instance_controller const * const instance_controllers,
int const instance_controllers_count)
{
for (int i = 0; i < instance_controllers_count; i++) {
types::instance_controller const &instance_controller = instance_controllers[i];
types::skin const &skin = instance_controller.controller->skin;
draw_skin(skin,
instance_controller.instance_materials,
instance_controller.instance_materials_count);
}
}
void state::draw_node(types::node const & node) void state::draw_node(types::node const & node)
{ {
draw_instance_geometries(node.instance_geometries, node.instance_geometries_count); draw_instance_geometries(node.instance_geometries, node.instance_geometries_count);
draw_instance_controllers(node.instance_controllers, node.instance_controllers_count);
} }
void state::draw() void state::draw()
{ {
glUseProgram(collada::effect::program_static); unsigned int effects[] = {collada::effect::program_static, collada::effect::program_skinned};
for (int i = 0; i < 2; i++) {
glUseProgram(effects[i]);
glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&view::state.float_transform); glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&view::state.float_transform);
glUniform1i(layout.uniform.emission_sampler, 0); glUniform1i(layout.uniform.emission_sampler, 0);
glUniform1i(layout.uniform.ambient_sampler, 1); glUniform1i(layout.uniform.ambient_sampler, 1);
glUniform1i(layout.uniform.diffuse_sampler, 2); glUniform1i(layout.uniform.diffuse_sampler, 2);
glUniform1i(layout.uniform.specular_sampler, 3); glUniform1i(layout.uniform.specular_sampler, 3);
}
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GREATER); glDepthFunc(GL_GREATER);

View File

@ -24,7 +24,9 @@
#include "collada/effect.h" #include "collada/effect.h"
#include "collada/scene.h" #include "collada/scene.h"
#include "collada/types.h" #include "collada/types.h"
#include "data/scenes/ship20.h" #include "data/scenes/ship20.h"
#include "data/scenes/noodle.h"
struct line_location { struct line_location {
struct { struct {
@ -302,7 +304,7 @@ void load(const char * source_path)
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
collada::effect::load_effects(); collada::effect::load_effects();
scene_state.load_scene(&ship20::descriptor); scene_state.load_scene(&noodle::descriptor);
} }
void update_keyboard(int up, int down, int left, int right, void update_keyboard(int up, int down, int left, int right,

View File

@ -104,7 +104,9 @@ namespace view {
state.direction = get_direction(); // on forward/normal/pitch change state.direction = get_direction(); // on forward/normal/pitch change
// position // position
state.eye = XMVectorSet(-45.5f, 43.25f, 63.0f, 1); //state.eye = XMVectorSet(-45.5f, 43.25f, 63.0f, 1);
state.at = state.eye + state.direction * at_distance; //state.at = state.eye + state.direction * at_distance;
state.at = XMVectorSet(0, 0, 0, 1);
state.eye = XMVectorSet(0, -10, 0, 1);
} }
} }