动画编码完成

This commit is contained in:
xsl
2025-10-31 14:22:08 +08:00
parent dfbef7caf1
commit 2555047190
80 changed files with 332 additions and 92 deletions
@@ -1,23 +1,18 @@
package com.hmwl.face_sdk;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class Motion {
public String type = "no";
public String technique = "no";
public String step = "no";
public String show_type = "no";
public String png_name = "no";
public int png_num;
public List<String> png_names = new ArrayList<>();
public JSONObject toJsonObject() {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("type", type);
jsonObject.put("technique", technique);
jsonObject.put("step", step);
jsonObject.put("show_type", show_type);
jsonObject.put("png_name", png_name);
jsonObject.put("png_num", png_num);
jsonObject.put("png_names", png_names);
return jsonObject;
} catch (Exception e) {
e.printStackTrace();
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@@ -0,0 +1,125 @@
{
"11": [
"11.png"
],
"12": [
"12.png"
],
"13": [
"13.png"
],
"14": [
"14.png"
],
"21": [
"21.png"
],
"23": [
"23.png"
],
"24": [
"24.png"
],
"25": [
"25.png"
],
"26": [
"26.png"
],
"27": [
"27.png"
],
"32": [
"32.png"
],
"37": [
"37.png"
],
"4": [
"4.png"
],
"40": [
"40.png"
],
"41": [
"41.png"
],
"45": [
"45.png"
],
"48": [
"48.png"
],
"49": [
"49.png"
],
"5": [
"5.png"
],
"53": [
"53.png"
],
"56": [
"56.png"
],
"59": [
"59.png"
],
"6": [
"6.png"
],
"62": [
"62.png"
],
"65": [
"65.png"
],
"68": [
"68.png"
],
"7": [
"7.png"
],
"71": [
"71.png"
],
"76": [
"76.png"
],
"77": [
"77.png"
],
"78": [
"78.png"
],
"81": [
"81.png"
],
"action24": [
"000000.png",
"000001.png",
"000002.png",
"000003.png",
"000004.png",
"000005.png",
"000006.png",
"000007.png",
"000008.png",
"000009.png",
"000010.png",
"000011.png",
"000012.png",
"000013.png",
"000014.png",
"000015.png",
"000016.png",
"000017.png",
"000018.png",
"000019.png",
"000020.png",
"000021.png",
"000022.png",
"000023.png",
"000024.png"
]
}
@@ -21,7 +21,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class MainActivity extends FaceActivity
{
@@ -30,13 +33,8 @@ public class MainActivity extends FaceActivity
protected void onCreate(Bundle savedInstanceState)
{
Motion motion = new Motion();
motion.type = "底妆";
motion.technique = "基础上妆";
motion.step = "2按压";
motion.show_type = "方向示意图";
motion.png_name = "4.png";
motion.png_num = 1;
motion.type = "4";
motion.png_names.add("4.png");
InitArg initArg = new InitArg();
initArg.action_fps = 3;
initArg.zoom = 1.5f;
@@ -52,8 +50,7 @@ public class MainActivity extends FaceActivity
String GetCurMotionState(int index)
{
Motion motion = new Motion();
motion.png_name = pngFilenames.get(index);
motion.png_num = 1;
motion.png_names = pngFilesByFolder.get(index).getFileList();
return motion.toJson();
}
@@ -77,26 +74,38 @@ public class MainActivity extends FaceActivity
// 手指抬起
Log.d("TouchEvent", "手指抬起");
curIndex++;
if(curIndex > pngFilenames.size()-1)
if(curIndex > pngFilesByFolder.size()-1)
{
curIndex = 0;
}
ChangeState(GetCurMotionState(curIndex));
Toast.makeText(this, pngFilenames.get(curIndex), Toast.LENGTH_LONG).show();
Toast.makeText(this, pngFilesByFolder.get(curIndex).folderName, Toast.LENGTH_LONG).show();
break;
}
return true; // 表示已处理该事件
}
List<String> pngFilenames = null;
int curIndex = 0;
private void FaceInit(Context context){
pngFilenames = readPngFilenamesFromAssets(context, "pic/png_filenames.json");
private class FolderInfo {
private String folderName;
private List<String> fileList;
public FolderInfo(String folderName, List<String> fileList) {
this.folderName = folderName;
this.fileList = fileList;
}
public String getFolderName() {
return folderName;
}
public List<String> getFileList() {
return fileList;
}
}
private List<String> readPngFilenamesFromAssets(Context context, String filename) {
List<String> pngFilenames = new ArrayList<>();
private List<FolderInfo> readPngFilenamesFromAssets(Context context, String filename) {
List<FolderInfo> folderList = new ArrayList<>();
try {
InputStream is = context.getAssets().open(filename);
@@ -107,9 +116,20 @@ public class MainActivity extends FaceActivity
stringBuilder.append(line);
}
JSONArray jsonArray = new JSONArray(stringBuilder.toString());
for (int i = 0; i < jsonArray.length(); i++) {
pngFilenames.add(jsonArray.getString(i));
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
// 遍历所有文件夹
Iterator<String> folderIterator = jsonObject.keys();
while (folderIterator.hasNext()) {
String folderName = folderIterator.next();
JSONArray fileArray = jsonObject.getJSONArray(folderName);
List<String> filesInFolder = new ArrayList<>();
for (int i = 0; i < fileArray.length(); i++) {
filesInFolder.add(fileArray.getString(i));
}
folderList.add(new FolderInfo(folderName, filesInFolder));
}
reader.close();
@@ -118,6 +138,12 @@ public class MainActivity extends FaceActivity
e.printStackTrace();
}
return pngFilenames;
return folderList;
}
int curIndex = 0;
List<FolderInfo> pngFilesByFolder = null;
private void FaceInit(Context context){
pngFilesByFolder = readPngFilenamesFromAssets(context, "pic/motion_data.json");
}
}
+54
View File
@@ -0,0 +1,54 @@
import os
import shutil
from pathlib import Path
def process_png_files(target_path):
"""
在指定路径中查找所有PNG图片,为每个PNG文件创建同名文件夹,并将图片复制到文件夹中
"""
# 将路径转换为Path对象
path = Path(target_path)
# 检查路径是否存在
if not path.exists():
print(f"错误:路径 '{target_path}' 不存在")
return
# 查找所有的PNG文件(不区分大小写)
png_files = list(path.glob("*.png")) + list(path.glob("*.PNG"))
if not png_files:
print(f"在路径 '{target_path}' 中没有找到PNG文件")
return
print(f"找到 {len(png_files)} 个PNG文件")
# 处理每个PNG文件
for png_file in png_files:
try:
# 获取文件名(不含扩展名)
file_stem = png_file.stem
# 创建同名文件夹
folder_path = path / file_stem
folder_path.mkdir(exist_ok=True)
# 目标文件路径
destination = folder_path / png_file.name
# 复制文件
shutil.copy2(png_file, destination)
print(f"✓ 已处理: {png_file.name} -> {folder_path.name}/")
except Exception as e:
print(f"✗ 处理文件 {png_file.name} 时出错: {e}")
if __name__ == "__main__":
# 请修改为你实际的路径
target_path = r"../example/src/main/assets/pic" # 修改为你的实际路径
print(f"开始处理路径: {target_path}")
process_png_files(target_path)
print("处理完成!")
+71 -30
View File
@@ -1,51 +1,92 @@
import os
import json
def simple_collect_png_filenames(folder_path, output_file="../example/src/main/assets/pic/png_filenames.json"):
def collect_png_from_subfolders(base_path=".", output_file="../example/src/main/assets/pic/motion_data.json"):
"""
简化版的PNG文件名收集器(不遍历子文件夹)
"""
# 检查文件夹是否存在
if not os.path.exists(folder_path):
print(f"错误:文件夹 '{folder_path}' 不存在")
return []
遍历当前路径下所有的子文件夹(只遍历一层),收集PNG文件名并保存到JSON文件
# 获取文件夹中的所有文件
Args:
base_path: 基础路径,默认为当前目录
output_file: 输出的JSON文件名
"""
# 检查基础路径是否存在
if not os.path.exists(base_path):
print(f"错误:路径 '{base_path}' 不存在")
return {}
# 获取所有子文件夹
try:
all_files = os.listdir(folder_path)
all_items = os.listdir(base_path)
except PermissionError:
print(f"错误:没有权限访问文件夹 '{folder_path}'")
return []
print(f"错误:没有权限访问路径 '{base_path}'")
return {}
# 筛选PNG文件
png_filenames = []
for file in all_files:
file_path = os.path.join(folder_path, file)
if os.path.isfile(file_path) and file.lower().endswith('.png'):
png_filenames.append(file)
# 筛选出子文件夹(只遍历一层)
subfolders = []
for item in all_items:
item_path = os.path.join(base_path, item)
if os.path.isdir(item_path):
subfolders.append(item)
# 按文件名排序
png_filenames.sort()
# 按文件名排序
subfolders.sort()
# 收集每个子文件夹中的PNG文件
all_png_files = {}
for folder in subfolders:
folder_path = os.path.join(base_path, folder)
try:
folder_files = os.listdir(folder_path)
except PermissionError:
print(f"警告:没有权限访问文件夹 '{folder}',跳过")
continue
# 筛选PNG文件
png_filenames = []
for file in folder_files:
file_path = os.path.join(folder_path, file)
if os.path.isfile(file_path) and file.lower().endswith('.png'):
png_filenames.append(file)
# 按文件名排序
png_filenames.sort()
# 如果有PNG文件,添加到结果中
if png_filenames:
all_png_files[folder] = png_filenames
# 保存到JSON文件
try:
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(png_filenames, f, ensure_ascii=False, indent=2)
print(f"找到 {len(png_filenames)}PNG文件,文件名已保存到 {output_file}")
json.dump(all_png_files, f, ensure_ascii=False, indent=2)
print(f"PNG文件信息已保存到 {output_file}")
except Exception as e:
print(f"保存文件时出错: {e}")
# 显示找到的文件
if png_filenames:
print("\n找到的PNG文件:")
for filename in png_filenames:
print(f" - {filename}")
# 显示统计信息
total_folders = len(all_png_files)
total_files = sum(len(files) for files in all_png_files.values())
return png_filenames
print(f"\n统计信息:")
print(f" 扫描了 {len(subfolders)} 个子文件夹")
print(f" 其中 {total_folders} 个文件夹包含PNG文件")
print(f" 总共找到 {total_files} 个PNG文件")
# 显示找到的文件
if all_png_files:
print("\n找到的PNG文件:")
for folder, files in all_png_files.items():
print(f" {folder}/:")
for filename in files:
print(f" - {filename}")
return all_png_files
# 使用方法
if __name__ == "__main__":
# 指定要遍历的文件夹
folder_to_scan = '../example/src/main/assets/pic'
# 可以指定要遍历的基础路径,默认为当前目录
base_path_to_scan = '../example/src/main/assets/pic' # 当前目录
simple_collect_png_filenames(folder_to_scan)
collect_png_from_subfolders(base_path_to_scan)
+1 -1
View File
@@ -20,7 +20,7 @@ void Application::initWindow()
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(480*2, 480*2, "Vulkan", nullptr, nullptr);
window = glfwCreateWindow(480, 480, "Vulkan", nullptr, nullptr);
#else
#endif
+9 -9
View File
@@ -460,16 +460,16 @@ void FaceApp::setup_descriptor_pool()
{
// 保守估计:假设每个描述符集可能有多个绑定
const uint32_t setsCount = kMaxTexture;
const uint32_t multiplier = 3; // 安全系数
//const uint32_t multiplier = 3; // 安全系数
std::vector<VkDescriptorPoolSize> pool_sizes = {
{
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = setsCount * multiplier
.descriptorCount = 3
},
{
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = setsCount * multiplier
.descriptorCount = setsCount + 4
},
// 如果需要其他类型的描述符,在这里添加
};
@@ -478,7 +478,7 @@ void FaceApp::setup_descriptor_pool()
descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptor_pool_info.poolSizeCount = static_cast<uint32_t>(pool_sizes.size());
descriptor_pool_info.pPoolSizes = pool_sizes.data();
descriptor_pool_info.maxSets = setsCount * 2; // 额外预留一些集合
descriptor_pool_info.maxSets = setsCount + 7; // 额外预留一些集合
descriptor_pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
VK_CHECK(vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, &descriptor_pool));
@@ -652,7 +652,7 @@ void FaceApp::render(VkCommandBuffer commandBuffer, long long frameTime)
if (game_time > actionTime)
{
_curTexIndex++;
if (_curTexIndex >= _curMotion.png_num)
if (_curTexIndex >= _curMotion.png_names.size())
{
_curTexIndex = 0;
}
@@ -1151,23 +1151,23 @@ void FaceApp::changeMotion(Motion& motion)
return;
}
_curMotion = motion;
for (int i = 0; i < _curMotion.png_num; ++i)
for (int i = 0; i < _curMotion.png_names.size(); ++i)
{
#ifdef _WIN32
//string path = _curMotion.type + "/" + _curMotion.technique + "/" + _curMotion.step + "/" + _curMotion.show_type;
string path = "pic";
string path_name = path + "/" + _curMotion.png_name;// +std::to_string(i) + ".png";
string path_name = path + "/" + _curMotion.type + "/" + _curMotion.png_names[i];// +std::to_string(i) + ".png";
loadTextureExample(UTF8ToWideString(path_name), m_texs[i], true);
if (kThick)
{
string path_name_ex = path + "/" + _curMotion.png_name + std::to_string(i) + "_thick.png";
string path_name_ex = path + "/" + _curMotion.type + "/" + _curMotion.png_names[i] + std::to_string(i) + "_thick.png";
loadTextureExample(UTF8ToWideString(path_name_ex), m_texs_ex[i], true);
}
#else
//string path = _curMotion.type + "/" + _curMotion.technique + "/" + _curMotion.step + "/" + _curMotion.show_type;
string path = "pic";
string path_name = path + "/" + _curMotion.png_name;// +std::to_string(i) + ".png";
string path_name = path + "/" + _curMotion.type + "/" + _curMotion.png_names[i];// +std::to_string(i) + ".png";
loadTexture(path_name, m_texs[i], true);
if (kThick)
{
+4 -8
View File
@@ -13,15 +13,11 @@ using json = nlohmann::json;
struct Motion {
string type;
string technique;
string step;
string show_type;
string png_name;
int png_num;
vector<string> png_names;
string getMotionId() {
return type + technique + step + show_type + png_name;
return type;
}
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Motion, type, technique, step, show_type, png_name, png_num)
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Motion, type, png_names)
};
struct InitArg
@@ -104,7 +100,7 @@ private:
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
vector<VkDescriptorSet> m_descriptor_sets;
const int kMaxTexture = 2;
const int kMaxTexture = 30;
vector<Texture> m_texs;
vector<Texture> m_texs_ex;
+16 -13
View File
@@ -49,24 +49,27 @@ int main() {
InitArg init_arg;
Motion motion;
motion.type = "底妆";
motion.technique = "基础上妆";
motion.step = "2按压";
motion.show_type = "方向示意图";
motion.png_name = "4.png";
motion.png_num = 1;
motion.type = "action24";
for (int i = 0; i < 25; ++i)
{
if (i < 10)
{
motion.png_names.push_back("00000" + std::to_string(i) + ".png");
}
else
{
motion.png_names.push_back("0000" + std::to_string(i) + ".png");
}
}
#
init_arg.motion = motion;
//motion.type = "底妆";
//motion.technique = "基础上妆";
//motion.step = "2按压";
//motion.show_type = "区域";
//motion.png_name = "pic";
//motion.png_num = 1;
init_arg.action_fps = 3;
init_arg.action_fps = 10;
init_arg.zoom = 1.5f;
string json_str = json(init_arg).dump();