Added ai generated animation
This commit is contained in:
parent
7840bfdb4e
commit
a96d0b207a
192
blender scripts/bone_anim_script01.py
Normal file
192
blender scripts/bone_anim_script01.py
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
import bpy
|
||||||
|
import bmesh
|
||||||
|
|
||||||
|
# Имена mesh и арматуры
|
||||||
|
mesh_name = "arm"
|
||||||
|
armature_name = "Reference"
|
||||||
|
|
||||||
|
# Находим объект mesh по имени
|
||||||
|
mesh_obj = bpy.data.objects.get(mesh_name)
|
||||||
|
|
||||||
|
# Находим объект арматуры по имени
|
||||||
|
armature_obj = bpy.data.objects.get(armature_name)
|
||||||
|
|
||||||
|
# Устанавливаем текущий кадр на 0
|
||||||
|
bpy.context.scene.frame_set(0)
|
||||||
|
|
||||||
|
# Принудительно обновляем сцену, чтобы применить анимацию
|
||||||
|
bpy.context.view_layer.update()
|
||||||
|
|
||||||
|
# Открываем файл для записи
|
||||||
|
with open("C:\\Work\\Projects\\witcher001\\resources\\w\\zombie002.txt", "w") as file:
|
||||||
|
# Обработка арматуры и анимации
|
||||||
|
if armature_obj and armature_obj.type == 'ARMATURE':
|
||||||
|
file.write("=== Armature Matrix ===\n")
|
||||||
|
for row in armature_obj.matrix_world:
|
||||||
|
file.write(f"{row}\n")
|
||||||
|
file.write(f"=== Armature Bones: {len(armature_obj.data.bones)}\n")
|
||||||
|
for bone in armature_obj.data.bones:
|
||||||
|
# Записываем имя кости, длину и связи
|
||||||
|
file.write(f"Bone: {bone.name}\n")
|
||||||
|
file.write(f" HEAD_LOCAL: {bone.head_local}\n")
|
||||||
|
file.write(f" TAIL_LOCAL: {bone.tail_local}\n")
|
||||||
|
file.write(f" Length: {(bone.tail_local - bone.head_local).length}\n")
|
||||||
|
for row in bone.matrix:
|
||||||
|
file.write(f" {row}\n")
|
||||||
|
file.write(f" Parent: {bone.parent.name if bone.parent else 'None'}\n")
|
||||||
|
file.write(f" Children: {[child.name for child in bone.children]}\n")
|
||||||
|
|
||||||
|
# Обработка mesh
|
||||||
|
if mesh_obj and mesh_obj.type == 'MESH':
|
||||||
|
# Создаем копию mesh, чтобы не изменять оригинал
|
||||||
|
mesh_copy = mesh_obj.copy()
|
||||||
|
mesh_copy.data = mesh_obj.data.copy()
|
||||||
|
bpy.context.collection.objects.link(mesh_copy)
|
||||||
|
|
||||||
|
# Убедимся, что объект активен
|
||||||
|
bpy.context.view_layer.objects.active = mesh_copy
|
||||||
|
mesh_copy.select_set(True)
|
||||||
|
|
||||||
|
# Применяем модификатор Armature (если он есть)
|
||||||
|
for modifier in mesh_copy.modifiers:
|
||||||
|
if modifier.type == 'ARMATURE':
|
||||||
|
# Включаем модификатор, если он отключен
|
||||||
|
if not modifier.show_viewport:
|
||||||
|
modifier.show_viewport = True
|
||||||
|
if not modifier.show_render:
|
||||||
|
modifier.show_render = True
|
||||||
|
|
||||||
|
# Проверяем, что модификатор связан с арматурой
|
||||||
|
if modifier.object is None:
|
||||||
|
print(f"Модификатор Armature на объекте {mesh_copy.name} не связан с арматурой. Пропускаем.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Временно применяем модификатор, чтобы получить правильные координаты вершин
|
||||||
|
try:
|
||||||
|
bpy.ops.object.modifier_apply(modifier=modifier.name)
|
||||||
|
except RuntimeError as e:
|
||||||
|
print(f"Ошибка при применении модификатора Armature: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Переходим в режим редактирования
|
||||||
|
bpy.ops.object.mode_set(mode='EDIT')
|
||||||
|
|
||||||
|
# Получаем BMesh представление mesh
|
||||||
|
bm = bmesh.from_edit_mesh(mesh_copy.data)
|
||||||
|
|
||||||
|
# Записываем список вершин
|
||||||
|
file.write(f"===Vertices: {len(bm.verts)}\n")
|
||||||
|
for vertex in bm.verts:
|
||||||
|
file.write(f"Vertex {vertex.index}: {vertex.co}\n")
|
||||||
|
|
||||||
|
# Убедимся, что у меша есть UV слой
|
||||||
|
uv_layer = bm.loops.layers.uv.active
|
||||||
|
if not uv_layer:
|
||||||
|
file.write("UV слой не найден.\n")
|
||||||
|
|
||||||
|
if uv_layer:
|
||||||
|
file.write(f"===UV Coordinates:\n")
|
||||||
|
file.write(f"Face count: {len(bm.faces)}\n")
|
||||||
|
|
||||||
|
for face in bm.faces:
|
||||||
|
file.write(f"Face {face.index}\n")
|
||||||
|
file.write(f"UV Count: {len(face.loops)}\n")
|
||||||
|
for loop in face.loops:
|
||||||
|
uv_coords = loop[uv_layer].uv
|
||||||
|
file.write(f" UV {uv_coords}\n")
|
||||||
|
|
||||||
|
# Записываем нормали
|
||||||
|
file.write(f"===Normals:\n")
|
||||||
|
for vertex in bm.verts:
|
||||||
|
file.write(f"Vertex {vertex.index}: Normal {vertex.normal}\n")
|
||||||
|
|
||||||
|
# Записываем треугольники (индексы вершин)
|
||||||
|
file.write(f"===Triangles: {len(bm.faces)}\n")
|
||||||
|
for face in bm.faces:
|
||||||
|
if len(face.verts) == 3: # Проверяем, что это треугольник
|
||||||
|
verts_indices = [vert.index for vert in face.verts]
|
||||||
|
file.write(f"Triangle: {verts_indices}\n")
|
||||||
|
|
||||||
|
# Возвращаемся в объектный режим
|
||||||
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
|
# Записываем веса вершин
|
||||||
|
file.write("=== Vertex Weights ===\n")
|
||||||
|
for vertex in mesh_copy.data.vertices:
|
||||||
|
file.write(f"Vertex {vertex.index}:\n")
|
||||||
|
file.write(f"Vertex groups: {len(vertex.groups)}\n")
|
||||||
|
for group in vertex.groups:
|
||||||
|
group_name = mesh_copy.vertex_groups[group.group].name
|
||||||
|
file.write(f" Group: '{group_name}', Weight: {group.weight}\n")
|
||||||
|
|
||||||
|
# Удаляем временную копию mesh
|
||||||
|
bpy.data.objects.remove(mesh_copy)
|
||||||
|
else:
|
||||||
|
file.write(f"Объект с именем '{mesh_name}' не найден или не является mesh.\n")
|
||||||
|
|
||||||
|
# Обработка арматуры и анимации
|
||||||
|
if armature_obj and armature_obj.type == 'ARMATURE':
|
||||||
|
|
||||||
|
# Получаем все ключевые кадры для арматуры
|
||||||
|
file.write("=== Animation Keyframes ===\n")
|
||||||
|
if armature_obj.animation_data and armature_obj.animation_data.action:
|
||||||
|
action = armature_obj.animation_data.action
|
||||||
|
|
||||||
|
# Собираем все уникальные ключевые кадры
|
||||||
|
keyframes = set()
|
||||||
|
|
||||||
|
# Логика для Blender 5.0 (Strip-based / ChannelBag structure)
|
||||||
|
if hasattr(action, "layers"):
|
||||||
|
for layer in action.layers:
|
||||||
|
if hasattr(layer, "strips"):
|
||||||
|
for strip in layer.strips:
|
||||||
|
# Проверяем наличие channelbags (согласно вашему dir(strip))
|
||||||
|
if hasattr(strip, "channelbags"):
|
||||||
|
for bag in strip.channelbags:
|
||||||
|
for fcurve in bag.fcurves:
|
||||||
|
for keyframe in fcurve.keyframe_points:
|
||||||
|
keyframes.add(int(keyframe.co[0]))
|
||||||
|
|
||||||
|
# На случай, если в этой версии используется единственное число
|
||||||
|
elif hasattr(strip, "channelbag") and strip.channelbag:
|
||||||
|
for fcurve in strip.channelbag.fcurves:
|
||||||
|
for keyframe in fcurve.keyframe_points:
|
||||||
|
keyframes.add(int(keyframe.co[0]))
|
||||||
|
|
||||||
|
# Фоллбек для Legacy экшенов
|
||||||
|
if not keyframes and hasattr(action, "fcurves"):
|
||||||
|
for fcurve in action.fcurves:
|
||||||
|
for keyframe in fcurve.keyframe_points:
|
||||||
|
keyframes.add(int(keyframe.co[0]))
|
||||||
|
|
||||||
|
keyframes = sorted(keyframes)
|
||||||
|
|
||||||
|
# Сортируем ключевые кадры
|
||||||
|
keyframes = sorted(keyframes)
|
||||||
|
|
||||||
|
# Сохраняем координаты и матрицы поворота для каждой кости на каждом ключевом кадре
|
||||||
|
file.write("=== Bone Transforms per Keyframe ===\n")
|
||||||
|
file.write(f"Keyframes: {len(keyframes)}\n")
|
||||||
|
for frame in keyframes:
|
||||||
|
# Устанавливаем текущий кадр
|
||||||
|
bpy.context.scene.frame_set(frame)
|
||||||
|
bpy.context.view_layer.update() # Обновляем сцену
|
||||||
|
|
||||||
|
file.write(f"Frame: {frame}\n")
|
||||||
|
for bone in armature_obj.pose.bones:
|
||||||
|
# Получаем координаты и матрицу поворота кости в мировом пространстве
|
||||||
|
matrix = bone.matrix
|
||||||
|
location = matrix.translation
|
||||||
|
rotation = matrix.to_euler()
|
||||||
|
|
||||||
|
# Записываем данные
|
||||||
|
file.write(f" Bone: {bone.name}\n")
|
||||||
|
file.write(f" Location: {location}\n")
|
||||||
|
file.write(f" Rotation: {rotation}\n")
|
||||||
|
file.write(f" Matrix:\n")
|
||||||
|
for row in matrix:
|
||||||
|
file.write(f" {row}\n")
|
||||||
|
else:
|
||||||
|
file.write(f"Объект с именем '{armature_name}' не найден или не является арматурой.\n")
|
||||||
|
|
||||||
|
print("Данные сохранены в файл 'mesh_armature_and_animation_data.txt'")
|
||||||
464461
resources/w/zombie002.txt
Normal file
464461
resources/w/zombie002.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -33,8 +33,8 @@ Eigen::Vector2f Environment::tapDownCurrentPos = { 0, 0 };
|
|||||||
|
|
||||||
ClientState Environment::shipState;
|
ClientState Environment::shipState;
|
||||||
|
|
||||||
const float Environment::CONST_Z_NEAR = 5.f;
|
const float Environment::CONST_Z_NEAR = 0.1f;
|
||||||
const float Environment::CONST_Z_FAR = 5000.f;
|
const float Environment::CONST_Z_FAR = 100.f;
|
||||||
|
|
||||||
float Environment::projectionWidth = 1280.0f;
|
float Environment::projectionWidth = 1280.0f;
|
||||||
float Environment::projectionHeight = 720.0f;
|
float Environment::projectionHeight = 720.0f;
|
||||||
|
|||||||
115
src/Game.cpp
115
src/Game.cpp
@ -174,6 +174,8 @@ namespace ZL
|
|||||||
violaIdleModel.LoadFromFile("resources/idleviola_uv010.txt", CONST_ZIP_FILE);
|
violaIdleModel.LoadFromFile("resources/idleviola_uv010.txt", CONST_ZIP_FILE);
|
||||||
violaWalkModel.LoadFromFile("resources/walkviola_uv010.txt", CONST_ZIP_FILE);
|
violaWalkModel.LoadFromFile("resources/walkviola_uv010.txt", CONST_ZIP_FILE);
|
||||||
|
|
||||||
|
zombieModel.LoadFromFile("resources/w/zombie002.txt", CONST_ZIP_FILE);
|
||||||
|
|
||||||
violaTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/viola.png", CONST_ZIP_FILE));
|
violaTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/viola.png", CONST_ZIP_FILE));
|
||||||
|
|
||||||
loadingCompleted = true;
|
loadingCompleted = true;
|
||||||
@ -211,7 +213,9 @@ namespace ZL
|
|||||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||||
//renderer.TranslateMatrix({ 0, -6.f, 0 });
|
//renderer.TranslateMatrix({ 0, -6.f, 0 });
|
||||||
|
|
||||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI * 30 / 180.f, Eigen::Vector3f::UnitX())).toRotationMatrix());
|
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(cameraInclination, Eigen::Vector3f::UnitX())).toRotationMatrix());
|
||||||
|
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(cameraAzimuth, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||||
|
renderer.TranslateMatrix({ -violaPosition.x(), -violaPosition.y(), -violaPosition.z() });
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, roomTexture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, roomTexture->getTexID());
|
||||||
renderer.DrawVertexRenderStruct(roomMesh);
|
renderer.DrawVertexRenderStruct(roomMesh);
|
||||||
@ -224,10 +228,20 @@ namespace ZL
|
|||||||
renderer.DrawVertexRenderStruct(benchMesh);
|
renderer.DrawVertexRenderStruct(benchMesh);
|
||||||
|
|
||||||
|
|
||||||
|
renderer.PushMatrix();
|
||||||
|
renderer.TranslateMatrix({ 0,0,-15 });
|
||||||
|
renderer.ScaleMatrix(0.01);
|
||||||
|
zombieModelMutable.AssignFrom(zombieModel.mesh);
|
||||||
|
zombieModelMutable.RefreshVBO();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, violaTexture->getTexID());
|
||||||
|
renderer.DrawVertexRenderStruct(zombieModelMutable);
|
||||||
|
renderer.PopMatrix();
|
||||||
|
|
||||||
renderer.PushMatrix();
|
renderer.PushMatrix();
|
||||||
|
|
||||||
renderer.ScaleMatrix(0.2);
|
renderer.TranslateMatrix({ violaPosition.x(), violaPosition.y(), violaPosition.z() });
|
||||||
|
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-violaFacingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||||
|
renderer.ScaleMatrix(0.12);
|
||||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5f, Eigen::Vector3f::UnitX())).toRotationMatrix());
|
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5f, Eigen::Vector3f::UnitX())).toRotationMatrix());
|
||||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ())).toRotationMatrix());
|
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ())).toRotationMatrix());
|
||||||
|
|
||||||
@ -327,6 +341,36 @@ namespace ZL
|
|||||||
|
|
||||||
lastTickCount = newTickCount;
|
lastTickCount = newTickCount;
|
||||||
|
|
||||||
|
// Move Viola toward target
|
||||||
|
Eigen::Vector3f toTarget = violaTarget - violaPosition;
|
||||||
|
toTarget.y() = 0.f;
|
||||||
|
float dist = toTarget.norm();
|
||||||
|
if (dist > VIOLA_WALK_THRESHOLD) {
|
||||||
|
Eigen::Vector3f dir = toTarget / dist;
|
||||||
|
float moveAmount = VIOLA_WALK_SPEED * delta / 1000.f;
|
||||||
|
if (moveAmount >= dist) {
|
||||||
|
violaPosition = violaTarget;
|
||||||
|
violaPosition.y() = 0.f;
|
||||||
|
} else {
|
||||||
|
violaPosition += dir * moveAmount;
|
||||||
|
}
|
||||||
|
violaTargetFacingAngle = atan2(dir.x(), -dir.z());
|
||||||
|
violaCurrentAnimation = 1;
|
||||||
|
} else {
|
||||||
|
violaCurrentAnimation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate Viola toward target facing angle at constant angular speed
|
||||||
|
float angleDiff = violaTargetFacingAngle - violaFacingAngle;
|
||||||
|
while (angleDiff > M_PI) angleDiff -= 2.f * static_cast<float>(M_PI);
|
||||||
|
while (angleDiff < -M_PI) angleDiff += 2.f * static_cast<float>(M_PI);
|
||||||
|
float rotStep = VIOLA_ROTATION_SPEED * delta / 1000.f;
|
||||||
|
if (std::fabs(angleDiff) <= rotStep) {
|
||||||
|
violaFacingAngle = violaTargetFacingAngle;
|
||||||
|
} else {
|
||||||
|
violaFacingAngle += (angleDiff > 0.f ? rotStep : -rotStep);
|
||||||
|
}
|
||||||
|
|
||||||
if (violaCurrentAnimation == 0) {
|
if (violaCurrentAnimation == 0) {
|
||||||
|
|
||||||
violaCurrentIdleFrame += delta / 24.f;
|
violaCurrentIdleFrame += delta / 24.f;
|
||||||
@ -354,6 +398,17 @@ namespace ZL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
zombieCurrentIdleFrame += delta / 24.f;
|
||||||
|
|
||||||
|
while (zombieCurrentIdleFrame >= 90) {
|
||||||
|
zombieCurrentIdleFrame -= 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int(zombieCurrentIdleFrame) != zombieLastIdleFrame) {
|
||||||
|
zombieModel.Interpolate(int(zombieCurrentIdleFrame));
|
||||||
|
zombieLastIdleFrame = int(zombieCurrentIdleFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -435,18 +490,68 @@ namespace ZL
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
|
if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
|
||||||
|
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||||
// Преобразуем экранные пиксели в проекционные единицы
|
// Преобразуем экранные пиксели в проекционные единицы
|
||||||
int mx = static_cast<int>((float)event.button.x / Environment::width * Environment::projectionWidth);
|
int mx = static_cast<int>((float)event.button.x / Environment::width * Environment::projectionWidth);
|
||||||
int my = static_cast<int>((float)event.button.y / Environment::height * Environment::projectionHeight);
|
int my = static_cast<int>((float)event.button.y / Environment::height * Environment::projectionHeight);
|
||||||
|
if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||||
|
handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
||||||
|
|
||||||
if (event.type == SDL_MOUSEBUTTONDOWN) handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
// Unproject click to ground plane (y=0) for Viola's walk target
|
||||||
else handleUp(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
float ndcX = 2.0f * event.button.x / Environment::width - 1.0f;
|
||||||
//std::cout << "Mouse button " << (event.type == SDL_MOUSEBUTTONDOWN ? "down" : "up") << ": x=" << mx << " y=" << my << std::endl;
|
float ndcY = 1.0f - 2.0f * event.button.y / Environment::height;
|
||||||
|
float aspect = (float)Environment::width / (float)Environment::height;
|
||||||
|
float tanHalfFov = tan(CAMERA_FOV_Y * 0.5f);
|
||||||
|
|
||||||
|
float cosAzim = cos(cameraAzimuth), sinAzim = sin(cameraAzimuth);
|
||||||
|
float cosIncl = cos(cameraInclination), sinIncl = sin(cameraInclination);
|
||||||
|
|
||||||
|
Eigen::Vector3f camRight(cosAzim, 0.f, sinAzim);
|
||||||
|
Eigen::Vector3f camForward(sinAzim * cosIncl, -sinIncl, -cosAzim * cosIncl);
|
||||||
|
Eigen::Vector3f camUp(sinAzim * sinIncl, cosIncl, -cosAzim * sinIncl);
|
||||||
|
Eigen::Vector3f camPos = violaPosition + Eigen::Vector3f(-sinAzim * cosIncl, sinIncl, cosAzim * cosIncl) * Environment::zoom;
|
||||||
|
|
||||||
|
Eigen::Vector3f rayDir = (camForward + camRight * (ndcX * aspect * tanHalfFov) + camUp * (ndcY * tanHalfFov)).normalized();
|
||||||
|
|
||||||
|
if (rayDir.y() < -0.001f) {
|
||||||
|
float t = -camPos.y() / rayDir.y();
|
||||||
|
Eigen::Vector3f hit = camPos + rayDir * t;
|
||||||
|
violaTarget = Eigen::Vector3f(hit.x(), 0.f, hit.z());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleUp(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.button.button == SDL_BUTTON_RIGHT) {
|
||||||
|
if (event.type == SDL_MOUSEBUTTONDOWN) {
|
||||||
|
rightMouseDown = true;
|
||||||
|
lastMouseX = event.button.x;
|
||||||
|
lastMouseY = event.button.y;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rightMouseDown = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (event.type == SDL_MOUSEMOTION) {
|
else if (event.type == SDL_MOUSEMOTION) {
|
||||||
int mx = static_cast<int>((float)event.motion.x / Environment::width * Environment::projectionWidth);
|
int mx = static_cast<int>((float)event.motion.x / Environment::width * Environment::projectionWidth);
|
||||||
int my = static_cast<int>((float)event.motion.y / Environment::height * Environment::projectionHeight);
|
int my = static_cast<int>((float)event.motion.y / Environment::height * Environment::projectionHeight);
|
||||||
handleMotion(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
handleMotion(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
|
||||||
|
|
||||||
|
if (rightMouseDown) {
|
||||||
|
int dx = event.motion.x - lastMouseX;
|
||||||
|
int dy = event.motion.y - lastMouseY;
|
||||||
|
lastMouseX = event.motion.x;
|
||||||
|
lastMouseY = event.motion.y;
|
||||||
|
|
||||||
|
const float sensitivity = 0.005f;
|
||||||
|
cameraAzimuth += dx * sensitivity;
|
||||||
|
cameraInclination += dy * sensitivity;
|
||||||
|
|
||||||
|
const float minInclination = M_PI * 30.f / 180.f;
|
||||||
|
const float maxInclination = M_PI * 0.5f;
|
||||||
|
cameraInclination = max(minInclination, min(maxInclination, cameraInclination));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type == SDL_MOUSEWHEEL) {
|
if (event.type == SDL_MOUSEWHEEL) {
|
||||||
|
|||||||
24
src/Game.h
24
src/Game.h
@ -63,8 +63,14 @@ namespace ZL {
|
|||||||
BoneSystem violaWalkModel;
|
BoneSystem violaWalkModel;
|
||||||
VertexRenderStruct violaWalkModelMutable;
|
VertexRenderStruct violaWalkModelMutable;
|
||||||
|
|
||||||
|
BoneSystem zombieModel;
|
||||||
|
VertexRenderStruct zombieModelMutable;
|
||||||
|
|
||||||
std::shared_ptr<Texture> violaTexture;
|
std::shared_ptr<Texture> violaTexture;
|
||||||
|
|
||||||
|
float zombieCurrentIdleFrame = 0;
|
||||||
|
int zombieLastIdleFrame = 0;
|
||||||
|
|
||||||
float violaCurrentIdleFrame = 0;
|
float violaCurrentIdleFrame = 0;
|
||||||
float violaCurrentWalkFrame = 0;
|
float violaCurrentWalkFrame = 0;
|
||||||
|
|
||||||
@ -72,7 +78,25 @@ namespace ZL {
|
|||||||
int violaLastWalkFrame = 0;
|
int violaLastWalkFrame = 0;
|
||||||
|
|
||||||
int violaCurrentAnimation = 0;
|
int violaCurrentAnimation = 0;
|
||||||
|
|
||||||
|
float cameraAzimuth = 0.0f;
|
||||||
|
float cameraInclination = M_PI * 30.f / 180.f;
|
||||||
|
|
||||||
|
Eigen::Vector3f violaPosition = Eigen::Vector3f(0.f, 0.f, 0.f);
|
||||||
|
Eigen::Vector3f violaTarget = Eigen::Vector3f(0.f, 0.f, 0.f);
|
||||||
|
float violaFacingAngle = 0.0f;
|
||||||
private:
|
private:
|
||||||
|
bool rightMouseDown = false;
|
||||||
|
int lastMouseX = 0;
|
||||||
|
int lastMouseY = 0;
|
||||||
|
|
||||||
|
static constexpr float CAMERA_FOV_Y = 1.0f / 1.5f;
|
||||||
|
static constexpr float VIOLA_WALK_SPEED = 3.0f;
|
||||||
|
static constexpr float VIOLA_WALK_THRESHOLD = 0.05f;
|
||||||
|
static constexpr float VIOLA_ROTATION_SPEED = 8.0f; // radians per second
|
||||||
|
|
||||||
|
float violaTargetFacingAngle = 0.0f;
|
||||||
|
|
||||||
int64_t getSyncTimeMs();
|
int64_t getSyncTimeMs();
|
||||||
void processTickCount();
|
void processTickCount();
|
||||||
void drawScene();
|
void drawScene();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user