Animation blending
- transition smoothly between idle and run animations - use quaternions (versors) instead of yaw/pitch/roll - hide mouse and enable free-look mode by default on startup - rotate model 180 degrees in Blender so it faces away from the camera by default - add some makefile commands
This commit is contained in:
10
makefile
10
makefile
@@ -14,7 +14,7 @@ OBJDIRS := $(patsubst $(SRC)%, $(OBJ)%, $(shell find $(SRC) -type d))
|
|||||||
CLEANDIRS := $(addsuffix /.clean, $(OBJDIRS));
|
CLEANDIRS := $(addsuffix /.clean, $(OBJDIRS));
|
||||||
|
|
||||||
# Explicit targets
|
# Explicit targets
|
||||||
.PHONY: all release clean
|
.PHONY: all release clean rebuild run
|
||||||
.DEFAULT_GOAL := all
|
.DEFAULT_GOAL := all
|
||||||
|
|
||||||
# Build executable
|
# Build executable
|
||||||
@@ -39,3 +39,11 @@ clean: $(CLEANDIRS)
|
|||||||
rm -f $(EXE) $(REL)
|
rm -f $(EXE) $(REL)
|
||||||
%.clean:
|
%.clean:
|
||||||
rm -f $**.o
|
rm -f $**.o
|
||||||
|
|
||||||
|
rebuild:
|
||||||
|
make clean
|
||||||
|
make all
|
||||||
|
|
||||||
|
run:
|
||||||
|
make all
|
||||||
|
./$(EXE)
|
||||||
|
|||||||
Binary file not shown.
35
src/camera.c
35
src/camera.c
@@ -10,11 +10,8 @@ void Camera_Init(Camera* c)
|
|||||||
c->width[1] = 5.8f;
|
c->width[1] = 5.8f;
|
||||||
c->width[2] = 0.6f;
|
c->width[2] = 0.6f;
|
||||||
glm_vec3_zero(c->velocity);
|
glm_vec3_zero(c->velocity);
|
||||||
glm_vec3_zero(c->look);
|
glm_quat_identity(c->rotation);
|
||||||
glm_vec3_zero(c->up);
|
Camera_UpdateVectors(c);
|
||||||
glm_vec3_zero(c->front);
|
|
||||||
glm_vec3_zero(c->right);
|
|
||||||
glm_vec3_zero(c->rotation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera_GetViewMatrix(Camera* c, mat4 m)
|
void Camera_GetViewMatrix(Camera* c, mat4 m)
|
||||||
@@ -24,30 +21,10 @@ void Camera_GetViewMatrix(Camera* c, mat4 m)
|
|||||||
|
|
||||||
void Camera_UpdateVectors(Camera* c)
|
void Camera_UpdateVectors(Camera* c)
|
||||||
{
|
{
|
||||||
if (c->rotation[0] > 180.0f) c->rotation[0] -= 360.0f;
|
glm_quat_rotatev(c->rotation, GLM_FORWARD, c->front);
|
||||||
else if (c->rotation[0] <= -180.0f) c->rotation[0] += 360.0f;
|
glm_quat_rotatev(c->rotation, GLM_YUP, c->up);
|
||||||
|
glm_quat_rotatev(c->rotation, GLM_XUP, c->right);
|
||||||
c->rotation[1] = glm_clamp(c->rotation[1], -89.0f, 89.0f);
|
|
||||||
c->rotation[2] = glm_clamp(c->rotation[2], -30.0f, 30.0f);
|
|
||||||
|
|
||||||
// calculate the front facing unit vector by yaw and pitch
|
|
||||||
c->front[0] = cos(glm_rad(c->rotation[0])) * cos(glm_rad(c->rotation[1]));
|
|
||||||
c->front[1] = sin(glm_rad(c->rotation[1]));
|
|
||||||
c->front[2] = sin(glm_rad(c->rotation[0])) * cos(glm_rad(c->rotation[1]));
|
|
||||||
|
|
||||||
// the look vector is the position + front
|
// the look vector is the position + front
|
||||||
glm_vec3_add(c->position, c->front, c->look);
|
glm_vec3_add(c->position, c->front, c->look);
|
||||||
|
|
||||||
// reset the up vector
|
|
||||||
c->up[0] = 0.0f;
|
|
||||||
c->up[1] = 1.0f;
|
|
||||||
c->up[2] = 0.0f;
|
|
||||||
// cross product points to the right, perpendicular to both front and up
|
|
||||||
glm_vec3_cross(c->front, c->up, c->right);
|
|
||||||
// pitch up or down, around the axis of the cross product
|
|
||||||
glm_vec3_rotate(c->up, glm_rad(c->rotation[1]), c->right);
|
|
||||||
// roll around the axis of the front vector
|
|
||||||
glm_vec3_rotate(c->up, glm_rad(c->rotation[2]), c->front);
|
|
||||||
// recalculate right vector after rolling
|
|
||||||
glm_vec3_cross(c->front, c->up, c->right);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ typedef struct
|
|||||||
vec3 up;
|
vec3 up;
|
||||||
vec3 front;
|
vec3 front;
|
||||||
vec3 right;
|
vec3 right;
|
||||||
vec3 rotation;
|
versor rotation;
|
||||||
} Camera;
|
} Camera;
|
||||||
|
|
||||||
void Camera_Init(Camera* c);
|
void Camera_Init(Camera* c);
|
||||||
|
|||||||
63
src/game.c
63
src/game.c
@@ -1,5 +1,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
#include "SDL2/SDL_timer.h"
|
#include "SDL2/SDL_timer.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
@@ -13,6 +14,7 @@ GameState *Game_New()
|
|||||||
if (!Render_Init(gs)) return NULL;
|
if (!Render_Init(gs)) return NULL;
|
||||||
|
|
||||||
gs->running = true;
|
gs->running = true;
|
||||||
|
gs->input.freeLook = true;
|
||||||
return gs;
|
return gs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +40,6 @@ void Game_Update(GameState *gs)
|
|||||||
|
|
||||||
Camera_UpdateVectors(&gs->camera);
|
Camera_UpdateVectors(&gs->camera);
|
||||||
|
|
||||||
const float speed = 0.3f;
|
|
||||||
vec3 move, front, right;
|
vec3 move, front, right;
|
||||||
glm_vec3_zero(move);
|
glm_vec3_zero(move);
|
||||||
front[0] = gs->camera.front[0];
|
front[0] = gs->camera.front[0];
|
||||||
@@ -50,6 +51,7 @@ void Game_Update(GameState *gs)
|
|||||||
right[2] = gs->camera.right[2];
|
right[2] = gs->camera.right[2];
|
||||||
glm_vec3_normalize(right);
|
glm_vec3_normalize(right);
|
||||||
|
|
||||||
|
// get player's desired movement direction
|
||||||
if (gs->input.w) glm_vec3_add(move, front, move);
|
if (gs->input.w) glm_vec3_add(move, front, move);
|
||||||
else if (gs->input.s) glm_vec3_sub(move, front, move);
|
else if (gs->input.s) glm_vec3_sub(move, front, move);
|
||||||
if (gs->input.a) glm_vec3_sub(move, right, move);
|
if (gs->input.a) glm_vec3_sub(move, right, move);
|
||||||
@@ -57,15 +59,70 @@ void Game_Update(GameState *gs)
|
|||||||
if (gs->input.q) move[1] = 1.0f;
|
if (gs->input.q) move[1] = 1.0f;
|
||||||
else if (gs->input.e) move[1] = -1.0f;
|
else if (gs->input.e) move[1] = -1.0f;
|
||||||
|
|
||||||
glm_vec3_scale_as(move, speed, move);
|
gs->charIsMoving = gs->input.w || gs->input.s || gs->input.a || gs->input.d;
|
||||||
|
|
||||||
|
// blend idle and run animations
|
||||||
|
if (gs->charIsMoving)
|
||||||
|
{
|
||||||
|
gs->animBlend += delta / 500.0f;
|
||||||
|
if (gs->animBlend > 1.0f) gs->animBlend = 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gs->animBlend -= delta / 500.0f;
|
||||||
|
if (gs->animBlend < 0.0f) gs->animBlend = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply acceleration
|
||||||
ShapeInstance *target = &(gs->testModel.instance);
|
ShapeInstance *target = &(gs->testModel.instance);
|
||||||
|
float accel = 0.005f * delta;
|
||||||
|
glm_vec3_scale_as(move, accel, move);
|
||||||
|
glm_vec3_add(target->velocity, move, target->velocity);
|
||||||
|
glm_vec3_clamp(target->velocity, -1.0f, 1.0f);
|
||||||
|
|
||||||
|
// apply velocity, make camera follow
|
||||||
vec3 displacement;
|
vec3 displacement;
|
||||||
glm_vec3_scale(gs->camera.front, -30.0f, displacement);
|
glm_vec3_scale(gs->camera.front, -30.0f, displacement);
|
||||||
displacement[1] += 10.0f;
|
displacement[1] += 10.0f;
|
||||||
glm_vec3_add(target->position, move, target->position);
|
glm_vec3_add(target->position, target->velocity, target->position);
|
||||||
glm_vec3_add(target->position, displacement, gs->camera.position);
|
glm_vec3_add(target->position, displacement, gs->camera.position);
|
||||||
|
|
||||||
|
// decelerate
|
||||||
|
glm_vec3_scale(target->velocity, 1.0f / ((0.01f * delta) + 1.0f), target->velocity);
|
||||||
|
|
||||||
|
if (gs->charIsMoving)
|
||||||
|
{
|
||||||
|
// gradually rotate model to face toward direction of velocity
|
||||||
|
float alpha = delta > 200.0f ? 1.0f : delta / 200.0f;
|
||||||
|
versor velQuat;
|
||||||
|
glm_quat_for(target->velocity, GLM_YUP, velQuat);
|
||||||
|
glm_quat_slerp(target->rotation, velQuat, alpha, target->rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gs->input.freeLook)
|
||||||
|
{
|
||||||
|
// stay within a certain angle relative to the camera yaw
|
||||||
|
const float pi = 3.14159265358979323846f;
|
||||||
|
const float turnThreshold = pi / 3.0f;
|
||||||
|
|
||||||
|
versor camRot, inverse, difference;
|
||||||
|
glm_quat_from_vecs(GLM_FORWARD, front, camRot);
|
||||||
|
glm_quat_inv(target->rotation, inverse);
|
||||||
|
glm_quat_mul(camRot, inverse, difference);
|
||||||
|
|
||||||
|
vec3 axis;
|
||||||
|
glm_quat_axis(difference, axis);
|
||||||
|
float angle = glm_quat_angle(difference);
|
||||||
|
if (angle > pi) angle -= pi + pi;
|
||||||
|
|
||||||
|
if (fabsf(angle) > turnThreshold)
|
||||||
|
{
|
||||||
|
angle += angle < 0.0f ? turnThreshold : -turnThreshold;
|
||||||
|
glm_quatv(difference, angle, axis);
|
||||||
|
glm_quat_mul(target->rotation, difference, target->rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Camera_UpdateVectors(&gs->camera);
|
Camera_UpdateVectors(&gs->camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
bool running;
|
bool running;
|
||||||
|
bool charIsMoving;
|
||||||
|
float animBlend;
|
||||||
uint64_t previousTicks;
|
uint64_t previousTicks;
|
||||||
InputState input;
|
InputState input;
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
|
|||||||
22
src/input.c
22
src/input.c
@@ -48,10 +48,26 @@ static void HandleKeyUp(GameState *gs, SDL_KeyCode sym)
|
|||||||
|
|
||||||
static void HandleMouseMotion(SDL_MouseMotionEvent e, GameState* gs)
|
static void HandleMouseMotion(SDL_MouseMotionEvent e, GameState* gs)
|
||||||
{
|
{
|
||||||
const float sensitivity = 0.4f;
|
const float sensitivity = 0.01f;
|
||||||
Camera *camera = &gs->camera;
|
Camera *camera = &gs->camera;
|
||||||
camera->rotation[0] += e.xrel * sensitivity;
|
vec3 front;
|
||||||
camera->rotation[1] -= e.yrel * sensitivity;
|
glm_vec3_copy(camera->front, front);
|
||||||
|
|
||||||
|
// extract the pitch angle and clamp it so the camera can't go upside down
|
||||||
|
float pitch = glm_deg(glm_rad(90) - glm_vec3_angle(GLM_YUP, front) - (e.yrel * sensitivity));
|
||||||
|
pitch = glm_rad(glm_clamp(pitch, -89.0f, 89.0f));
|
||||||
|
|
||||||
|
// apply the new pitch using the existing "right" vector
|
||||||
|
front[1] = 0.0f;
|
||||||
|
glm_vec3_normalize(front);
|
||||||
|
glm_vec3_rotate(front, pitch, camera->right);
|
||||||
|
|
||||||
|
// apply yaw (invalidates the "right" vector, that's why pitch is applied first)
|
||||||
|
glm_vec3_rotate(front, -e.xrel * sensitivity, GLM_YUP);
|
||||||
|
|
||||||
|
// update camera
|
||||||
|
glm_quat_for(front, GLM_YUP, camera->rotation);
|
||||||
|
Camera_UpdateVectors(camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleMouseDown(SDL_MouseButtonEvent e, GameState* gs)
|
static void HandleMouseDown(SDL_MouseButtonEvent e, GameState* gs)
|
||||||
|
|||||||
17
src/model.c
17
src/model.c
@@ -87,6 +87,7 @@ Model Model_LoadGltf(char *path)
|
|||||||
printf("Loading glTF model file...\n");
|
printf("Loading glTF model file...\n");
|
||||||
Model model = {0};
|
Model model = {0};
|
||||||
model.instance.scale = 4.0f;
|
model.instance.scale = 4.0f;
|
||||||
|
glm_quat_identity(model.instance.rotation);
|
||||||
cgltf_options options = {0};
|
cgltf_options options = {0};
|
||||||
cgltf_data *data = NULL;
|
cgltf_data *data = NULL;
|
||||||
cgltf_result result = cgltf_parse_file(&options, path, &data);
|
cgltf_result result = cgltf_parse_file(&options, path, &data);
|
||||||
@@ -217,6 +218,22 @@ Model Model_LoadGltf(char *path)
|
|||||||
printf("skin: %s, joints: %d\n", skin->name, skin->joints_count);
|
printf("skin: %s, joints: %d\n", skin->name, skin->joints_count);
|
||||||
model.jointMatrices = calloc(skin->joints_count, sizeof(mat4));
|
model.jointMatrices = calloc(skin->joints_count, sizeof(mat4));
|
||||||
|
|
||||||
|
for (int i = 0; i < data->animations_count; i++)
|
||||||
|
{
|
||||||
|
cgltf_animation *anim = data->animations + i;
|
||||||
|
|
||||||
|
if (0 == strncmp(anim->name, "run", 3))
|
||||||
|
{
|
||||||
|
printf("run animation: %s\n", anim->name);
|
||||||
|
model.run = anim;
|
||||||
|
}
|
||||||
|
else if (0 == strncmp(anim->name, "idle", 4))
|
||||||
|
{
|
||||||
|
printf("idle animation: %s\n", anim->name);
|
||||||
|
model.idle = anim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < skin->joints_count; i++)
|
for (int i = 0; i < skin->joints_count; i++)
|
||||||
{
|
{
|
||||||
cgltf_node *joint = skin->joints[i];
|
cgltf_node *joint = skin->joints[i];
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ typedef struct
|
|||||||
void *data;
|
void *data;
|
||||||
void *skin;
|
void *skin;
|
||||||
void *head;
|
void *head;
|
||||||
|
void *idle;
|
||||||
|
void *run;
|
||||||
mat4 *jointMatrices;
|
mat4 *jointMatrices;
|
||||||
GLuint *vbos;
|
GLuint *vbos;
|
||||||
GLuint vao;
|
GLuint vao;
|
||||||
|
|||||||
96
src/render.c
96
src/render.c
@@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
#include "SDL2/SDL.h"
|
#include "SDL2/SDL.h"
|
||||||
#include "GL/glew.h"
|
#include "GL/glew.h"
|
||||||
#include "SDL2/SDL_opengl.h"
|
#include "SDL2/SDL_opengl.h"
|
||||||
@@ -220,6 +221,7 @@ bool Render_Init(GameState *gs)
|
|||||||
|
|
||||||
gs->window = SDL_CreateWindow("Sandbox", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1920, 1080, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);;
|
gs->window = SDL_CreateWindow("Sandbox", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1920, 1080, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);;
|
||||||
gs->glContext = SDL_GL_CreateContext(gs->window);
|
gs->glContext = SDL_GL_CreateContext(gs->window);
|
||||||
|
SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||||
printf("Created OpenGL window.\n");
|
printf("Created OpenGL window.\n");
|
||||||
|
|
||||||
if (SDL_GL_SetSwapInterval(1) == 0) printf("Enabled VSync.\n");
|
if (SDL_GL_SetSwapInterval(1) == 0) printf("Enabled VSync.\n");
|
||||||
@@ -318,10 +320,7 @@ static void Transform(ShapeInstance *instance, mat4 *matrix)
|
|||||||
glm_mat4_identity(tempMat);
|
glm_mat4_identity(tempMat);
|
||||||
|
|
||||||
glm_translate(tempMat, instance->position);
|
glm_translate(tempMat, instance->position);
|
||||||
|
glm_quat_rotate(tempMat, instance->rotation, tempMat);
|
||||||
glm_rotate_x(tempMat, instance->rotation[0], tempMat);
|
|
||||||
glm_rotate_y(tempMat, instance->rotation[1], tempMat);
|
|
||||||
glm_rotate_z(tempMat, instance->rotation[2], tempMat);
|
|
||||||
|
|
||||||
vec3 scale;
|
vec3 scale;
|
||||||
scale[0] = instance->scale;
|
scale[0] = instance->scale;
|
||||||
@@ -332,43 +331,8 @@ static void Transform(ShapeInstance *instance, mat4 *matrix)
|
|||||||
memcpy(matrix, tempMat, sizeof(mat4));
|
memcpy(matrix, tempMat, sizeof(mat4));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawModel(GameState *gs)
|
static void ApplyAnim(cgltf_animation *anim, float t, float blend)
|
||||||
{
|
{
|
||||||
Model *model = &gs->testModel;
|
|
||||||
ShapeInstance instance = model->instance;
|
|
||||||
cgltf_data *data = model->data;
|
|
||||||
cgltf_skin *skin = model->skin;
|
|
||||||
cgltf_animation *anim = data->animations;
|
|
||||||
mat4 modelMatrix;
|
|
||||||
glm_mat4_identity(modelMatrix);
|
|
||||||
|
|
||||||
if (!gs->input.freeLook)
|
|
||||||
{
|
|
||||||
// rotate the whole model to stay within this angle relative to the camera yaw
|
|
||||||
const float turnThreshold = 1.047197f; // 60 degrees
|
|
||||||
const float deg180 = 3.14159f;
|
|
||||||
const float deg360 = 6.28318f;
|
|
||||||
// convert camera yaw (rotation around Y axis) to radians and add 90 degrees so it aligns with the gltf model
|
|
||||||
float camYawRadsGltf = (gs->camera.rotation[0] / -57.295828f) + 1.570795f;
|
|
||||||
if (camYawRadsGltf > deg180) camYawRadsGltf = camYawRadsGltf - deg360;
|
|
||||||
float *modelYaw = model->instance.rotation + 1;
|
|
||||||
float diff = camYawRadsGltf - *modelYaw;
|
|
||||||
if (diff > deg180) diff -= deg360;
|
|
||||||
else if (diff < -deg180) diff += deg360;
|
|
||||||
|
|
||||||
if (turnThreshold < diff)
|
|
||||||
*modelYaw = camYawRadsGltf - turnThreshold;
|
|
||||||
else if (diff < -turnThreshold)
|
|
||||||
*modelYaw = camYawRadsGltf + turnThreshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform(&model->instance, &modelMatrix);
|
|
||||||
|
|
||||||
uint64_t ticks = SDL_GetTicks64();
|
|
||||||
float t = ticks / 1000.0f;
|
|
||||||
while (t > 1.0f) t -= 1.0f;
|
|
||||||
|
|
||||||
// apply local transformations for each bone for the current animation frame
|
|
||||||
for (int i = 0; i < anim->channels_count; i++)
|
for (int i = 0; i < anim->channels_count; i++)
|
||||||
{
|
{
|
||||||
cgltf_animation_channel* channel = &anim->channels[i];
|
cgltf_animation_channel* channel = &anim->channels[i];
|
||||||
@@ -406,7 +370,9 @@ static void DrawModel(GameState *gs)
|
|||||||
cgltf_accessor_read_float(sampler->output, k + 1, p1, 3);
|
cgltf_accessor_read_float(sampler->output, k + 1, p1, 3);
|
||||||
glm_vec3_lerp(p0, p1, alpha, result);
|
glm_vec3_lerp(p0, p1, alpha, result);
|
||||||
// glm_vec3_copy is not used here due to potential struct alignment issues
|
// glm_vec3_copy is not used here due to potential struct alignment issues
|
||||||
for (int x = 0; x < 3; x++) node->translation[x] = result[x];
|
memcpy(p0, node->translation, sizeof(vec3));
|
||||||
|
glm_vec3_lerp(p0, result, blend, result);
|
||||||
|
memcpy(node->translation, result, sizeof(vec3));
|
||||||
node->has_translation = true;
|
node->has_translation = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -417,7 +383,10 @@ static void DrawModel(GameState *gs)
|
|||||||
cgltf_accessor_read_float(sampler->output, k + 1, q1, 4);
|
cgltf_accessor_read_float(sampler->output, k + 1, q1, 4);
|
||||||
// slerp (not lerp) for rotation
|
// slerp (not lerp) for rotation
|
||||||
glm_quat_slerp(q0, q1, alpha, result);
|
glm_quat_slerp(q0, q1, alpha, result);
|
||||||
for (int x = 0; x < 4; x++) node->rotation[x] = result[x];
|
memcpy(q0, node->rotation, sizeof(versor));
|
||||||
|
glm_quat_slerp(q0, result, blend, result);
|
||||||
|
memcpy(node->rotation, result, sizeof(versor));
|
||||||
|
|
||||||
node->has_rotation = true;
|
node->has_rotation = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -427,7 +396,9 @@ static void DrawModel(GameState *gs)
|
|||||||
cgltf_accessor_read_float(sampler->output, k, s0, 3);
|
cgltf_accessor_read_float(sampler->output, k, s0, 3);
|
||||||
cgltf_accessor_read_float(sampler->output, k + 1, s1, 3);
|
cgltf_accessor_read_float(sampler->output, k + 1, s1, 3);
|
||||||
glm_vec3_lerp(s0, s1, alpha, result);
|
glm_vec3_lerp(s0, s1, alpha, result);
|
||||||
for (int x = 0; x < 3; x++) node->scale[x] = result[x];
|
memcpy(s0, node->scale, sizeof(vec3));
|
||||||
|
glm_vec3_lerp(s0, result, blend, result);
|
||||||
|
memcpy(node->scale, result, sizeof(vec3));
|
||||||
node->has_scale = true;
|
node->has_scale = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -435,25 +406,40 @@ static void DrawModel(GameState *gs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawModel(GameState *gs)
|
||||||
|
{
|
||||||
|
Model *model = &gs->testModel;
|
||||||
|
ShapeInstance *instance = &model->instance;
|
||||||
|
cgltf_data *data = model->data;
|
||||||
|
cgltf_skin *skin = model->skin;
|
||||||
|
mat4 modelMatrix;
|
||||||
|
glm_mat4_identity(modelMatrix);
|
||||||
|
Transform(instance, &modelMatrix);
|
||||||
|
|
||||||
|
uint64_t ticks = SDL_GetTicks64();
|
||||||
|
float t = ticks / 1000.0f;
|
||||||
|
while (t > 1.0f) t -= 1.0f;
|
||||||
|
|
||||||
|
// apply local transformations for each bone for the current animation frame
|
||||||
|
ApplyAnim(model->idle, t, 1.0f);
|
||||||
|
ApplyAnim(model->run, t, gs->animBlend);
|
||||||
|
|
||||||
if (!gs->input.freeLook)
|
if (!gs->input.freeLook)
|
||||||
{
|
{
|
||||||
// make head look where camera is looking
|
// make head look where camera is looking
|
||||||
cgltf_node *head = model->head;
|
cgltf_node *head = model->head;
|
||||||
vec3 a, b, yAxis;
|
vec3 modelFront, camFront;
|
||||||
glm_vec3_zero(a);
|
glm_quat_rotatev(instance->rotation, GLM_FORWARD, modelFront);
|
||||||
glm_vec3_zero(b);
|
glm_vec3_copy(gs->camera.front, camFront);
|
||||||
glm_vec3_zero(yAxis);
|
modelFront[1] = 0.0f;
|
||||||
yAxis[1] = 1.0f;
|
camFront[1] = 0.0f;
|
||||||
a[2] = 1.0f;
|
|
||||||
glm_vec3_rotate(a, model->instance.rotation[1], yAxis);
|
|
||||||
b[0] = gs->camera.front[0];
|
|
||||||
b[2] = gs->camera.front[2];
|
|
||||||
versor desiredRotation, temp;
|
versor desiredRotation, temp;
|
||||||
glm_quat_from_vecs(a, b, desiredRotation);
|
glm_quat_from_vecs(modelFront, camFront, desiredRotation);
|
||||||
for (int i = 0; i < 4; i++) temp[i] = head->rotation[i];
|
memcpy(temp, head->rotation, sizeof(versor));
|
||||||
glm_quat_mul(temp, desiredRotation, temp);
|
glm_quat_mul(temp, desiredRotation, temp);
|
||||||
for (int i = 0; i < 4; i++) head->rotation[i] = temp[i];
|
memcpy(head->rotation, temp, sizeof(versor));
|
||||||
}
|
}
|
||||||
|
|
||||||
// recalculate the joint matrices
|
// recalculate the joint matrices
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ Shape *Shape_New(GLfloat *vertices, int numVertices, GLushort *indices, int numI
|
|||||||
instance->scale = 2.0f;
|
instance->scale = 2.0f;
|
||||||
instance->collisionRadius = 1.0f;
|
instance->collisionRadius = 1.0f;
|
||||||
glm_vec3_zero(instance->velocity);
|
glm_vec3_zero(instance->velocity);
|
||||||
glm_vec3_zero(instance->rotation);
|
glm_quat_identity(instance->rotation);
|
||||||
float *textureId = shape->instanceData + (i * 17);
|
float *textureId = shape->instanceData + (i * 17);
|
||||||
*textureId = 6;
|
*textureId = 6;
|
||||||
mat4 *matrix = (void*)(textureId + 1);
|
mat4 *matrix = (void*)(textureId + 1);
|
||||||
@@ -105,7 +105,7 @@ Shape *Shape_MakePyramid(int numInstances)
|
|||||||
instance->scale = 1.0f;
|
instance->scale = 1.0f;
|
||||||
instance->collisionRadius = 1.0f;
|
instance->collisionRadius = 1.0f;
|
||||||
glm_vec3_zero(instance->velocity);
|
glm_vec3_zero(instance->velocity);
|
||||||
glm_vec3_zero(instance->rotation);
|
glm_quat_identity(instance->rotation);
|
||||||
float *textureId = shape->instanceData + (i * 17);
|
float *textureId = shape->instanceData + (i * 17);
|
||||||
*textureId = i;
|
*textureId = i;
|
||||||
mat4 *matrix = (void*)(textureId + 1);
|
mat4 *matrix = (void*)(textureId + 1);
|
||||||
@@ -154,7 +154,7 @@ Shape *Shape_MakePlane()
|
|||||||
instance->scale = 1.0f;
|
instance->scale = 1.0f;
|
||||||
instance->collisionRadius = 1.0f;
|
instance->collisionRadius = 1.0f;
|
||||||
glm_vec3_zero(instance->velocity);
|
glm_vec3_zero(instance->velocity);
|
||||||
glm_vec3_zero(instance->rotation);
|
glm_quat_identity(instance->rotation);
|
||||||
float *textureId = shape->instanceData + (0 * 17);
|
float *textureId = shape->instanceData + (0 * 17);
|
||||||
*textureId = 5;
|
*textureId = 5;
|
||||||
mat4 *matrix = (void*)(textureId + 1);
|
mat4 *matrix = (void*)(textureId + 1);
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ enum
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
vec3 position;
|
vec3 position;
|
||||||
vec3 rotation;
|
|
||||||
vec3 velocity;
|
vec3 velocity;
|
||||||
float scale;
|
float scale;
|
||||||
float collisionRadius;
|
float collisionRadius;
|
||||||
|
versor rotation;
|
||||||
} ShapeInstance;
|
} ShapeInstance;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
Reference in New Issue
Block a user