185 lines
5.1 KiB
C
185 lines
5.1 KiB
C
/**
|
|
* Copyright (c) 2021 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "vncharacter.h"
|
|
|
|
void vnCharacterInit(vncharacter_t *character, texture_t *texture) {
|
|
character->x = 0;
|
|
character->y = 0;
|
|
character->z = 0;
|
|
|
|
character->yaw = 0;
|
|
character->pitch = 0;
|
|
character->roll = 0;
|
|
|
|
character->scaleX = 1;
|
|
character->scaleY = 1;
|
|
character->layerCount = 0;
|
|
character->texture = texture;
|
|
|
|
character->layerEyes = 0xFF;
|
|
character->layerMouth = 0xFF;
|
|
character->layerEyebrows = 0xFF;
|
|
character->breathing = true;
|
|
character->blinkStart = 0;
|
|
|
|
// Init the primitive.
|
|
primitiveInit(&character->primitive,
|
|
QUAD_VERTICE_COUNT * VN_CHARACTER_LAYERS_MAX,
|
|
QUAD_INDICE_COUNT * VN_CHARACTER_LAYERS_MAX
|
|
);
|
|
}
|
|
|
|
void vnCharacterUpdate(vncharacter_t *character, engine_t *engine) {
|
|
float t, n;
|
|
float speed, amount;
|
|
|
|
// Setup frames based on the emotion.
|
|
if(character->layerEyes != 0xFF) {
|
|
n = (engine->time.current-character->blinkStart)*VN_CHARACTER_BLINK_SPEED;
|
|
if(n > 1.0f) {
|
|
character->blinkStart = engine->time.current + randFloatRange(
|
|
1, VN_CHARACTER_BLINK_TIME_RANGE_MAX
|
|
);
|
|
} else if(n > 0) {
|
|
n = (
|
|
easeInQuad(animForwardAndBackwardScaled(n)) *
|
|
character->layers[character->layerEyes].frames
|
|
);
|
|
vnCharacterLayerSetFrame(character, character->layerEyes, (int32_t)n);
|
|
}
|
|
}
|
|
|
|
// mouth = character->emotion % 0x04;
|
|
// eyes = (character->emotion/0x04) % 0x04;
|
|
// eyebrows = ((character->emotion/0x04)/0x04) % 0x05;
|
|
|
|
// _vnCharacterFaceBuffer(character, eyebrows, VN_CHARACTER_QUAD_EYEBROWS);
|
|
// _vnCharacterFaceBuffer(character, eyes, VN_CHARACTER_QUAD_EYES);
|
|
|
|
// mouth *= VN_CHARACTER_TALKING_FRAME_COUNT;
|
|
// if(character->talking) {
|
|
// t = animForwardAndBackwardScaled(mathModFloat(
|
|
// engine->time.current * animTimeScaleFromFrameTime(3, 0.2f), 1.0f
|
|
// ));
|
|
// mouth += (uint8_t)(t * VN_CHARACTER_TALKING_FRAME_COUNT);
|
|
// }
|
|
// _vnCharacterFaceBuffer(character, mouth, VN_CHARACTER_QUAD_MOUTH);
|
|
// float n;
|
|
// // Update the blinking frames
|
|
// n = (engine->time.current - character->blinkStart) * 3.0f;
|
|
// if(n > 1.0f) {
|
|
// character->blinkStart = engine->time.current + randFloatRange(
|
|
// 1, VN_CHARACTER_BLINK_TIME_RANGE_MAX
|
|
// );
|
|
// } else if(n > 0) {
|
|
// n = easeInQuad(easeTimeToForwardAndBackward(n) * 4);
|
|
// _vnCharacterFaceBuffer(character,
|
|
// (int32_t)n, 1, VN_CHARACTER_QUAD_EYES
|
|
// );
|
|
// }
|
|
// if(character->talking) {
|
|
// n = easeTimeToForwardAndBackward(
|
|
// mathModFloat(engine->time.current * 1.6, 1)
|
|
// ) * 6.0f;
|
|
// _vnCharacterFaceBuffer(character,
|
|
// (int32_t)n, 2, VN_CHARACTER_QUAD_MOUTH
|
|
// );
|
|
// } else {
|
|
// _vnCharacterFaceBuffer(character,
|
|
// 0, 2, VN_CHARACTER_QUAD_MOUTH
|
|
// );
|
|
// }
|
|
|
|
// Update the scale frames for breathing / talk breathing
|
|
if(character->breathing) {
|
|
speed = 0.2f;
|
|
amount = 90.0f;
|
|
t = animForwardAndBackwardScaled(
|
|
mathModFloat(engine->time.current, 1 / speed) * speed
|
|
);
|
|
t = easeInOutQuad(t) / amount - (1/(amount*2));
|
|
character->scaleX = 1 + t;
|
|
character->scaleY = 1 - t;
|
|
} else {
|
|
character->scaleX = 1;
|
|
character->scaleY = 1;
|
|
}
|
|
}
|
|
|
|
|
|
uint8_t vnCharacterLayerAdd(vncharacter_t *character,
|
|
uint8_t frames,
|
|
int16_t lx, int16_t ly,
|
|
int16_t x, int16_t y,
|
|
int16_t width, int16_t height
|
|
) {
|
|
uint8_t i;
|
|
vncharacterlayer_t *layer;
|
|
|
|
i = character->layerCount++;
|
|
layer = character->layers + i;
|
|
|
|
layer->frames = frames;
|
|
layer->lx = lx;
|
|
layer->ly = ly;
|
|
layer->x = x;
|
|
layer->y =y;
|
|
layer->width = width;
|
|
layer->height = height;
|
|
|
|
vnCharacterLayerSetFrame(character, i, 0);
|
|
return i;
|
|
}
|
|
|
|
void vnCharacterLayerSetFrame(vncharacter_t *character, uint8_t l, uint8_t f) {
|
|
vncharacterlayer_t *layer;
|
|
vncharacterlayer_t *base;
|
|
|
|
layer = character->layers + l;
|
|
base = character->layers;
|
|
f = f % layer->frames;
|
|
|
|
float ps = 1.0f / (float)base->height;
|
|
float tpx = 1.0f / (float)character->texture->width;
|
|
float tpy = 1.0f / (float)character->texture->height;
|
|
|
|
int32_t x = layer->x - (base->width / 2);
|
|
int32_t y = layer->y + (base->height / 2);
|
|
int32_t tx = layer->lx + (layer->width * f);
|
|
|
|
quadBuffer(&character->primitive, 0.001f * (float)l,
|
|
(float)x * ps, 1 - (float)y * ps,
|
|
(float)tx * tpx,
|
|
(float)layer->ly * tpy,
|
|
|
|
(float)(x + layer->width) * ps,
|
|
1 - (float)(y + layer->height) * ps,
|
|
(float)(tx + layer->width) * tpx,
|
|
(float)(layer->ly + layer->height) * tpy,
|
|
l * QUAD_VERTICE_COUNT, l * QUAD_INDICE_COUNT
|
|
);
|
|
}
|
|
|
|
void vnCharacterRender(
|
|
vncharacter_t *character, shader_t *shader,
|
|
shaderuniform_t uniformModel, shaderuniform_t uniformTexture
|
|
) {
|
|
shaderUsePositionAndScale(shader, uniformModel,
|
|
character->x, character->y, character->z,
|
|
character->pitch, character->yaw, character->roll,
|
|
character->scaleX, character->scaleY, 1
|
|
);
|
|
shaderUseTexture(shader, uniformTexture, character->texture);
|
|
primitiveDraw(
|
|
&character->primitive, 0, character->layerCount * QUAD_INDICE_COUNT
|
|
);
|
|
}
|
|
|
|
void vnCharacterDispose(vncharacter_t *character) {
|
|
primitiveDispose(&character->primitive);
|
|
} |