collada: animate eidelwind walking inside grandlecturn

This commit is contained in:
Zack Buhman 2026-03-31 20:10:35 -05:00
parent 5724fde489
commit e98e45beac
10 changed files with 175 additions and 77 deletions

View File

@ -84,7 +84,7 @@ all: main
$(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(OPT) $(DEBUG) -c $< -o $@ $(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(OPT) $(DEBUG) -c $< -o $@
PACK_FILENAMES = $(shell cat filenames.txt) PACK_FILENAMES = $(shell cat filenames.txt)
test.pack: tool/pack_file $(PACK_FILENAMES) test.pack: tool/pack_file $(PACK_FILENAMES) filenames.txt
./tool/pack_file $@ $(PACK_FILENAMES) ./tool/pack_file $@ $(PACK_FILENAMES)
test.pack.o: test.pack test.pack.o: test.pack

View File

@ -1,56 +1,53 @@
shader/minecraft.vert data/scenes/eidelwind/images/0_map_face_only.dds
shader/minecraft.frag data/scenes/eidelwind/scene.idx
minecraft/per_vertex.vtx data/scenes/eidelwind/scene.vjw
minecraft/configuration.idx data/scenes/eidelwind/scene.vtx
minecraft/terrain2.data
minecraft/grandlecturn/region.0.0.instance.vtx
minecraft/grandlecturn/region.0.0.instance.cfg
minecraft/grandlecturn/region.-1.0.instance.vtx
minecraft/grandlecturn/region.-1.0.instance.cfg
minecraft/grandlecturn/region.0.-1.instance.vtx
minecraft/grandlecturn/region.0.-1.instance.cfg
minecraft/grandlecturn/region.-1.-1.instance.vtx
minecraft/grandlecturn/region.-1.-1.instance.cfg
minecraft/grandlecturn/global.lights.vtx
minecraft/grandlecturn/global.dump
minecraft/midnightmeadow/region.0.0.instance.vtx
minecraft/midnightmeadow/region.0.0.instance.cfg
minecraft/midnightmeadow/region.-1.0.instance.vtx
minecraft/midnightmeadow/region.-1.0.instance.cfg
minecraft/midnightmeadow/region.0.-1.instance.vtx
minecraft/midnightmeadow/region.0.-1.instance.cfg
minecraft/midnightmeadow/region.-1.-1.instance.vtx
minecraft/midnightmeadow/region.-1.-1.instance.cfg
minecraft/midnightmeadow/global.lights.vtx
minecraft/midnightmeadow/global.dump
shader/font.vert
shader/font.frag
font/bitmap/terminus_128x64_6x12.data
font/bitmap/terminus_128x128_8x16.data font/bitmap/terminus_128x128_8x16.data
font/bitmap/terminus_128x64_6x12.data
font/bitmap/terminus_256x128_10x18.data font/bitmap/terminus_256x128_10x18.data
font/bitmap/terminus_256x128_12x24.data font/bitmap/terminus_256x128_12x24.data
font/bitmap/terminus_256x256_16x32.data font/bitmap/terminus_256x256_16x32.data
shader/font.vert
shader/font_outline.frag
font/outline/uncial_antiqua_36.data font/outline/uncial_antiqua_36.data
shader/quad.vert minecraft/configuration.idx
shader/quad.frag minecraft/flame.data
shader/quad.vert minecraft/grandlecturn/global.dump
shader/lighting.frag minecraft/grandlecturn/global.lights.vtx
shader/non_block.vert minecraft/grandlecturn/region.0.0.instance.cfg
shader/non_block.frag minecraft/grandlecturn/region.0.0.instance.vtx
minecraft/grandlecturn/region.0.-1.instance.cfg
minecraft/grandlecturn/region.0.-1.instance.vtx
minecraft/grandlecturn/region.-1.0.instance.cfg
minecraft/grandlecturn/region.-1.0.instance.vtx
minecraft/grandlecturn/region.-1.-1.instance.cfg
minecraft/grandlecturn/region.-1.-1.instance.vtx
minecraft/midnightmeadow/global.dump
minecraft/midnightmeadow/global.lights.vtx
minecraft/midnightmeadow/region.0.0.instance.cfg
minecraft/midnightmeadow/region.0.0.instance.vtx
minecraft/midnightmeadow/region.0.-1.instance.cfg
minecraft/midnightmeadow/region.0.-1.instance.vtx
minecraft/midnightmeadow/region.-1.0.instance.cfg
minecraft/midnightmeadow/region.-1.0.instance.vtx
minecraft/midnightmeadow/region.-1.-1.instance.cfg
minecraft/midnightmeadow/region.-1.-1.instance.vtx
minecraft/non_block.idx minecraft/non_block.idx
minecraft/non_block.vtx minecraft/non_block.vtx
shader/line_art.vert minecraft/per_vertex.vtx
shader/line_art.frag minecraft/terrain2.data
shader/collada/static.vert shader/collada/generic_geometry.frag
shader/collada/generic.frag
shader/collada/skinned.vert shader/collada/skinned.vert
shader/collada/generic.frag shader/collada/static.vert
data/scenes/eidelwind/scene.vtx
data/scenes/eidelwind/scene.vjw
data/scenes/eidelwind/scene.idx
data/scenes/eidelwind/images/0_map_face_only.dds
shader/flame.vert
shader/flame.frag shader/flame.frag
minecraft/flame.data shader/flame.vert
shader/font.frag
shader/font_outline.frag
shader/font.vert
shader/lighting.frag
shader/line_art.frag
shader/line_art.vert
shader/minecraft.frag
shader/minecraft.vert
shader/non_block.frag
shader/non_block.vert
shader/quad.frag
shader/quad.vert

View File

@ -48,8 +48,8 @@ namespace collada::scene {
void draw_instance_controllers(types::instance_controller const * const instance_controllers, void draw_instance_controllers(types::instance_controller const * const instance_controllers,
int const instance_controllers_count); int const instance_controllers_count);
void draw_node(types::node const & node, instance_types::node const & node_instance); void draw_node(XMMATRIX const & ext_transform, types::node const & node, instance_types::node const & node_instance);
void draw(); void draw(XMMATRIX const & ext_transform);
// state updates // state updates
void update(float t); void update(float t);

View File

@ -0,0 +1,64 @@
#version 430 core
in VS_OUT {
vec3 Position; // world coordinates
vec3 Normal;
vec2 Texture;
} fs_in;
layout (location = 10) uniform vec4 EmissionColor;
layout (location = 11) uniform vec4 AmbientColor;
layout (location = 12) uniform vec4 DiffuseColor;
layout (location = 13) uniform vec4 SpecularColor;
layout (location = 14) uniform float shininess;
layout (location = 15) uniform sampler2D EmissionSampler;
layout (location = 16) uniform sampler2D AmbientSampler;
layout (location = 17) uniform sampler2D DiffuseSampler;
layout (location = 18) uniform sampler2D SpecularSampler;
layout (location = 19) uniform ivec4 TextureChannel;
layout (location = 0) out vec4 Position;
layout (location = 1) out vec4 Normal;
layout (location = 2) out vec4 Color;
layout (location = 3) out vec4 Block;
void main()
{
vec4 emission;
vec4 ambient;
vec4 diffuse;
vec4 specular;
if (TextureChannel.x >= 0) { // emission
emission = texture(EmissionSampler, fs_in.Texture.xy);
} else {
emission = EmissionColor;
}
if (TextureChannel.y >= 0) { // ambient
ambient = texture(AmbientSampler, fs_in.Texture.xy);
} else {
ambient = AmbientColor;
}
if (TextureChannel.z >= 0) { // diffuse
diffuse = texture(DiffuseSampler, fs_in.Texture.xy);
} else {
diffuse = DiffuseColor;
}
if (TextureChannel.w >= 0) { // specular
specular = texture(SpecularSampler, fs_in.Texture.xy);
} else {
specular = SpecularColor;
}
vec3 color = emission.xyz * 0;
color += ambient.xyz * 0.05;
color += diffuse.xyz * 1;
color += specular.xyz * 0 * 0.3;
Position = vec4(fs_in.Position, 1.0);
Normal = vec4(fs_in.Normal, 0.0);
Color = vec4(color, 1.0);
Block = vec4(0, 0, 0, 0);
}

View File

@ -7,20 +7,21 @@ layout (location = 3) in ivec4 BlendIndices;
layout (location = 4) in vec4 BlendWeight; layout (location = 4) in vec4 BlendWeight;
layout (location = 0) uniform mat4 Transform; layout (location = 0) uniform mat4 Transform;
layout (location = 1) uniform mat4 WorldTransform;
layout (std140, binding = 0) uniform JointsLayout layout (std140, binding = 0) uniform JointsLayout
{ {
mat4 Joints[64]; mat4 Joints[64];
}; };
out vec3 PixelNormal; out VS_OUT {
out vec2 PixelTexture; vec3 Position;
vec3 Normal;
vec2 Texture;
} vs_out;
void main() void main()
{ {
PixelNormal = Normal;
PixelTexture = vec2(Texture.x, 1.0 - Texture.y);
mat4 skin mat4 skin
= BlendWeight.x * Joints[BlendIndices.x] = BlendWeight.x * Joints[BlendIndices.x]
+ BlendWeight.y * Joints[BlendIndices.y] + BlendWeight.y * Joints[BlendIndices.y]
@ -30,5 +31,9 @@ void main()
vec4 position = skin * vec4(Position, 1); vec4 position = skin * vec4(Position, 1);
vs_out.Position = (WorldTransform * position).xyz;
vs_out.Normal = Normal;
vs_out.Texture = vec2(Texture.x, 1.0 - Texture.y);
gl_Position = Transform * position; gl_Position = Transform * position;
} }

View File

@ -5,14 +5,19 @@ layout (location = 1) in vec3 Normal;
layout (location = 2) in vec2 Texture; layout (location = 2) in vec2 Texture;
layout (location = 0) uniform mat4 Transform; layout (location = 0) uniform mat4 Transform;
layout (location = 1) uniform mat4 WorldTransform;
out vec3 PixelNormal; out VS_OUT {
out vec2 PixelTexture; vec3 Position;
vec3 Normal;
vec2 Texture;
} vs_out;
void main() void main()
{ {
PixelNormal = Normal; vs_out.Position = Position;
PixelTexture = vec2(Texture.x, 1.0 - Texture.y); vs_out.Normal = Normal;
vs_out.Texture = vec2(Texture.x, 1.0 - Texture.y);
gl_Position = Transform * vec4(Position, 1); gl_Position = Transform * vec4(Position, 1);
} }

View File

@ -29,7 +29,7 @@ void main()
if (LightCount != 0) { if (LightCount != 0) {
for (int i = 0; i < LightCount; i++) { for (int i = 0; i < LightCount; i++) {
vec3 light_position = light[i].xzy + vec3(0, 0, 0.5); vec3 light_position = light[i].xzy + vec3(0, 0, 0.5);
float light_distance = length(light_position - position.xyz); float light_distance = length(light_position - position.xyz) * 0.5;
vec3 light_direction = normalize(light_position - position.xyz); vec3 light_direction = normalize(light_position - position.xyz);
float diffuse = max(dot(normal.xyz, light_direction), 0.0); float diffuse = max(dot(normal.xyz, light_direction), 0.0);
if (normal.w == 1.0) // two-sided if (normal.w == 1.0) // two-sided

View File

@ -11,10 +11,10 @@ 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_geometry.frag");
program_skinned = compile_from_files("shader/collada/skinned.vert", program_skinned = compile_from_files("shader/collada/skinned.vert",
nullptr, nullptr,
"shader/collada/generic.frag"); "shader/collada/generic_geometry.frag");
} }
} }

View File

@ -29,6 +29,7 @@ namespace collada::scene {
struct { struct {
// vertex // vertex
unsigned int transform; unsigned int transform;
unsigned int world_transform;
// fragment // fragment
unsigned int emission_color; unsigned int emission_color;
unsigned int ambient_color; unsigned int ambient_color;
@ -66,6 +67,7 @@ namespace collada::scene {
.uniform = { .uniform = {
// vertex // vertex
.transform = 0, .transform = 0,
.world_transform = 1,
// fragment // fragment
.emission_color = 10, .emission_color = 10,
.ambient_color = 11, .ambient_color = 11,
@ -481,30 +483,38 @@ namespace collada::scene {
} }
} }
void state::draw_node(types::node const & node, instance_types::node const & node_instance) void state::draw_node(XMMATRIX const& ext_transform, types::node const & node, instance_types::node const & node_instance)
{ {
XMMATRIX transform = node_instance.world * view::state.transform;
XMFLOAT4X4 float_transform;
XMStoreFloat4x4(&float_transform, transform);
if (node.instance_geometries_count) { if (node.instance_geometries_count) {
XMMATRIX world_transform = node_instance.world * ext_transform;
XMMATRIX transform = world_transform * view::state.transform;
XMFLOAT4X4 float_transform;
XMStoreFloat4x4(&float_transform, transform);
XMFLOAT4X4 float_world_transform;
XMStoreFloat4x4(&float_world_transform, world_transform);
glUseProgram(collada::effect::program_static); glUseProgram(collada::effect::program_static);
glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&float_transform); glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&float_transform);
glUniformMatrix4fv(layout.uniform.world_transform, 1, false, (float *)&float_world_transform);
draw_instance_geometries(node.instance_geometries, node.instance_geometries_count); draw_instance_geometries(node.instance_geometries, node.instance_geometries_count);
} }
if (node.instance_controllers_count) { if (node.instance_controllers_count) {
XMMATRIX transform = view::state.transform; XMMATRIX world_transform = ext_transform;
XMMATRIX transform = world_transform * view::state.transform;
XMFLOAT4X4 float_transform; XMFLOAT4X4 float_transform;
XMStoreFloat4x4(&float_transform, transform); XMStoreFloat4x4(&float_transform, transform);
XMFLOAT4X4 float_world_transform;
XMStoreFloat4x4(&float_world_transform, world_transform);
glUseProgram(collada::effect::program_skinned); glUseProgram(collada::effect::program_skinned);
glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&float_transform); glUniformMatrix4fv(layout.uniform.transform, 1, false, (float *)&float_transform);
glUniformMatrix4fv(layout.uniform.world_transform, 1, false, (float *)&float_world_transform);
draw_instance_controllers(node.instance_controllers, node.instance_controllers_count); draw_instance_controllers(node.instance_controllers, node.instance_controllers_count);
} }
} }
void state::draw() void state::draw(XMMATRIX const& ext_transform)
{ {
unsigned int effects[] = {collada::effect::program_static, collada::effect::program_skinned}; unsigned int effects[] = {collada::effect::program_static, collada::effect::program_skinned};
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -528,7 +538,7 @@ namespace collada::scene {
if (((node_draw_type & 0b10) == 0) && (node.type == types::node_type::JOINT)) if (((node_draw_type & 0b10) == 0) && (node.type == types::node_type::JOINT))
continue; continue;
draw_node(node, node_state.node_instances[i]); draw_node(ext_transform, node, node_state.node_instances[i]);
} }
} }

View File

@ -25,6 +25,7 @@
#include "boids_scene.h" #include "boids_scene.h"
#include "collada/effect.h" #include "collada/effect.h"
#include "collada/scene.h" #include "collada/scene.h"
#include "collada/animate.h"
#include "collada/types.h" #include "collada/types.h"
#include "collada/instance_types.h" #include "collada/instance_types.h"
#include "flame.h" #include "flame.h"
@ -188,16 +189,18 @@ void load()
scene_state.load_scene(&eidelwind::descriptor); scene_state.load_scene(&eidelwind::descriptor);
node_eye = scene_state.find_node_by_name("Camera001"); node_eye = scene_state.find_node_by_name("Camera001");
assert(node_eye != nullptr); assert(node_eye != nullptr);
view::state.eye = XMVector3Transform(XMVectorZero(), node_eye->world); view::state.eye = XMVectorSet(26.85, 10.71, 53.34, 0);
//view::state.eye = XMVector3Transform(XMVectorZero(), node_eye->world);
node_at = scene_state.find_node_by_name("Camera001.Target"); node_at = scene_state.find_node_by_name("Camera001.Target");
assert(node_at != nullptr); assert(node_at != nullptr);
view::state.at = XMVector3Transform(XMVectorZero(), node_at->world); view::state.at = XMVectorSet(17.07, 10.61, 51.38, 0);
//view::state.at = XMVector3Transform(XMVectorZero(), node_at->world);
view::state.direction = XMVector3Normalize(view::state.at - view::state.eye); view::state.direction = XMVector3Normalize(view::state.at - view::state.eye);
view::state.normal = XMVector3Cross(view::state.direction, view::state.up); view::state.normal = XMVector3Cross(view::state.direction, view::state.up);
view::state.forward = -XMVector3Cross(view::state.normal, view::state.up); view::state.forward = -XMVector3Cross(view::state.normal, view::state.up);
view::state.pitch = 0; view::state.pitch = -0.19;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// flame // flame
@ -350,7 +353,7 @@ void update_joystick(float lx, float ly,
int leftshoulder, int rightshoulder, int leftshoulder, int rightshoulder,
int start) int start)
{ {
float translate_rate = 2.0; float translate_rate = 0.5;
float forward = -ly * translate_rate; float forward = -ly * translate_rate;
float strafe = lx * translate_rate; float strafe = lx * translate_rate;
@ -399,11 +402,15 @@ void update_joystick(float lx, float ly,
*/ */
} }
static float ext_position = 0;
void update(float time) void update(float time)
{ {
current_time = time; current_time = time;
scene_state.update(time); scene_state.update(time);
ext_position = collada::animate::loop(time, 10);
/* /*
view::state.eye = XMVector3Transform(XMVectorZero(), node_eye->world); view::state.eye = XMVector3Transform(XMVectorZero(), node_eye->world);
if (node_at == nullptr) if (node_at == nullptr)
@ -477,7 +484,7 @@ void draw()
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(-1.0f); glClearDepth(-1.0f);
if (false) { if (true) {
// possibly re-initialize geometry buffer if window width/height changes // possibly re-initialize geometry buffer if window width/height changes
init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types); init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types);
@ -486,11 +493,21 @@ void draw()
minecraft::draw(); minecraft::draw();
non_block::draw(); //non_block::draw();
flame::draw(minecraft::current_world->light_uniform_buffer, flame::draw(minecraft::current_world->light_uniform_buffer,
minecraft::current_world->light_count); minecraft::current_world->light_count);
float scale = 0.03f;
float pos = ext_position * 51.228f * scale * 2.0f;
XMMATRIX ext_transform
= XMMatrixScaling(scale, scale, scale)
* XMMatrixRotationZ(XM_PI * 0.5f)
* XMMatrixTranslation(8 + pos, 11, 50.5);
scene_state.draw(ext_transform);
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);
@ -506,7 +523,7 @@ void draw()
} else { } else {
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);
scene_state.draw(); //scene_state.draw();
hud::draw(); hud::draw();
} }