save code
|
After Width: | Height: | Size: 445 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 205 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 35 KiB |
@@ -0,0 +1,530 @@
|
||||
{
|
||||
"4": {
|
||||
"001.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"002.png": {
|
||||
"x": 360,
|
||||
"y": 0
|
||||
},
|
||||
"003.png": {
|
||||
"x": 720,
|
||||
"y": 0
|
||||
},
|
||||
"004.png": {
|
||||
"x": 1080,
|
||||
"y": 0
|
||||
},
|
||||
"005.png": {
|
||||
"x": 1440,
|
||||
"y": 0
|
||||
},
|
||||
"006.png": {
|
||||
"x": 1800,
|
||||
"y": 0
|
||||
},
|
||||
"007.png": {
|
||||
"x": 2160,
|
||||
"y": 0
|
||||
},
|
||||
"008.png": {
|
||||
"x": 2520,
|
||||
"y": 0
|
||||
},
|
||||
"009.png": {
|
||||
"x": 0,
|
||||
"y": 360
|
||||
},
|
||||
"010.png": {
|
||||
"x": 360,
|
||||
"y": 360
|
||||
},
|
||||
"011.png": {
|
||||
"x": 720,
|
||||
"y": 360
|
||||
},
|
||||
"012.png": {
|
||||
"x": 1080,
|
||||
"y": 360
|
||||
},
|
||||
"013.png": {
|
||||
"x": 1440,
|
||||
"y": 360
|
||||
},
|
||||
"014.png": {
|
||||
"x": 1800,
|
||||
"y": 360
|
||||
},
|
||||
"015.png": {
|
||||
"x": 2160,
|
||||
"y": 360
|
||||
},
|
||||
"016.png": {
|
||||
"x": 2520,
|
||||
"y": 360
|
||||
},
|
||||
"017.png": {
|
||||
"x": 0,
|
||||
"y": 720
|
||||
},
|
||||
"018.png": {
|
||||
"x": 360,
|
||||
"y": 720
|
||||
},
|
||||
"019.png": {
|
||||
"x": 720,
|
||||
"y": 720
|
||||
},
|
||||
"020.png": {
|
||||
"x": 1080,
|
||||
"y": 720
|
||||
},
|
||||
"021.png": {
|
||||
"x": 1440,
|
||||
"y": 720
|
||||
},
|
||||
"022.png": {
|
||||
"x": 1800,
|
||||
"y": 720
|
||||
},
|
||||
"023.png": {
|
||||
"x": 2160,
|
||||
"y": 720
|
||||
},
|
||||
"024.png": {
|
||||
"x": 2520,
|
||||
"y": 720
|
||||
},
|
||||
"025.png": {
|
||||
"x": 0,
|
||||
"y": 1080
|
||||
},
|
||||
"026.png": {
|
||||
"x": 360,
|
||||
"y": 1080
|
||||
},
|
||||
"027.png": {
|
||||
"x": 720,
|
||||
"y": 1080
|
||||
},
|
||||
"028.png": {
|
||||
"x": 1080,
|
||||
"y": 1080
|
||||
},
|
||||
"029.png": {
|
||||
"x": 1440,
|
||||
"y": 1080
|
||||
},
|
||||
"030.png": {
|
||||
"x": 1800,
|
||||
"y": 1080
|
||||
},
|
||||
"031.png": {
|
||||
"x": 2160,
|
||||
"y": 1080
|
||||
},
|
||||
"032.png": {
|
||||
"x": 2520,
|
||||
"y": 1080
|
||||
},
|
||||
"033.png": {
|
||||
"x": 0,
|
||||
"y": 1440
|
||||
},
|
||||
"034.png": {
|
||||
"x": 360,
|
||||
"y": 1440
|
||||
},
|
||||
"035.png": {
|
||||
"x": 720,
|
||||
"y": 1440
|
||||
},
|
||||
"036.png": {
|
||||
"x": 1080,
|
||||
"y": 1440
|
||||
},
|
||||
"037.png": {
|
||||
"x": 1440,
|
||||
"y": 1440
|
||||
},
|
||||
"038.png": {
|
||||
"x": 1800,
|
||||
"y": 1440
|
||||
},
|
||||
"039.png": {
|
||||
"x": 2160,
|
||||
"y": 1440
|
||||
},
|
||||
"040.png": {
|
||||
"x": 2520,
|
||||
"y": 1440
|
||||
},
|
||||
"041.png": {
|
||||
"x": 0,
|
||||
"y": 1800
|
||||
},
|
||||
"042.png": {
|
||||
"x": 360,
|
||||
"y": 1800
|
||||
},
|
||||
"043.png": {
|
||||
"x": 720,
|
||||
"y": 1800
|
||||
},
|
||||
"044.png": {
|
||||
"x": 1080,
|
||||
"y": 1800
|
||||
},
|
||||
"045.png": {
|
||||
"x": 1440,
|
||||
"y": 1800
|
||||
},
|
||||
"046.png": {
|
||||
"x": 1800,
|
||||
"y": 1800
|
||||
},
|
||||
"047.png": {
|
||||
"x": 2160,
|
||||
"y": 1800
|
||||
},
|
||||
"048.png": {
|
||||
"x": 2520,
|
||||
"y": 1800
|
||||
},
|
||||
"049.png": {
|
||||
"x": 0,
|
||||
"y": 2160
|
||||
},
|
||||
"050.png": {
|
||||
"x": 360,
|
||||
"y": 2160
|
||||
},
|
||||
"051.png": {
|
||||
"x": 720,
|
||||
"y": 2160
|
||||
},
|
||||
"052.png": {
|
||||
"x": 1080,
|
||||
"y": 2160
|
||||
},
|
||||
"053.png": {
|
||||
"x": 1440,
|
||||
"y": 2160
|
||||
},
|
||||
"054.png": {
|
||||
"x": 1800,
|
||||
"y": 2160
|
||||
},
|
||||
"055.png": {
|
||||
"x": 2160,
|
||||
"y": 2160
|
||||
},
|
||||
"056.png": {
|
||||
"x": 2520,
|
||||
"y": 2160
|
||||
},
|
||||
"057.png": {
|
||||
"x": 0,
|
||||
"y": 2520
|
||||
},
|
||||
"058.png": {
|
||||
"x": 360,
|
||||
"y": 2520
|
||||
},
|
||||
"059.png": {
|
||||
"x": 720,
|
||||
"y": 2520
|
||||
},
|
||||
"060.png": {
|
||||
"x": 1080,
|
||||
"y": 2520
|
||||
}
|
||||
},
|
||||
"5": {
|
||||
"5.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"6": {
|
||||
"6.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"7": {
|
||||
"7.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"002.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"003.png": {
|
||||
"x": 360,
|
||||
"y": 0
|
||||
},
|
||||
"004.png": {
|
||||
"x": 720,
|
||||
"y": 0
|
||||
},
|
||||
"005.png": {
|
||||
"x": 1080,
|
||||
"y": 0
|
||||
},
|
||||
"006.png": {
|
||||
"x": 1440,
|
||||
"y": 0
|
||||
},
|
||||
"007.png": {
|
||||
"x": 1800,
|
||||
"y": 0
|
||||
},
|
||||
"008.png": {
|
||||
"x": 2160,
|
||||
"y": 0
|
||||
},
|
||||
"009.png": {
|
||||
"x": 2520,
|
||||
"y": 0
|
||||
},
|
||||
"010.png": {
|
||||
"x": 0,
|
||||
"y": 360
|
||||
},
|
||||
"011.png": {
|
||||
"x": 360,
|
||||
"y": 360
|
||||
},
|
||||
"11.png": {
|
||||
"x": 720,
|
||||
"y": 360
|
||||
},
|
||||
"012.png": {
|
||||
"x": 1080,
|
||||
"y": 360
|
||||
}
|
||||
},
|
||||
"12": {
|
||||
"12.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"13": {
|
||||
"001.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"002.png": {
|
||||
"x": 360,
|
||||
"y": 0
|
||||
},
|
||||
"003.png": {
|
||||
"x": 720,
|
||||
"y": 0
|
||||
},
|
||||
"004.png": {
|
||||
"x": 1080,
|
||||
"y": 0
|
||||
},
|
||||
"005.png": {
|
||||
"x": 1440,
|
||||
"y": 0
|
||||
},
|
||||
"006.png": {
|
||||
"x": 1800,
|
||||
"y": 0
|
||||
},
|
||||
"007.png": {
|
||||
"x": 2160,
|
||||
"y": 0
|
||||
},
|
||||
"008.png": {
|
||||
"x": 2520,
|
||||
"y": 0
|
||||
},
|
||||
"009.png": {
|
||||
"x": 0,
|
||||
"y": 360
|
||||
},
|
||||
"010.png": {
|
||||
"x": 360,
|
||||
"y": 360
|
||||
},
|
||||
"011.png": {
|
||||
"x": 720,
|
||||
"y": 360
|
||||
},
|
||||
"012.png": {
|
||||
"x": 1080,
|
||||
"y": 360
|
||||
},
|
||||
"013.png": {
|
||||
"x": 1440,
|
||||
"y": 360
|
||||
},
|
||||
"13.png": {
|
||||
"x": 1800,
|
||||
"y": 360
|
||||
},
|
||||
"014.png": {
|
||||
"x": 2160,
|
||||
"y": 360
|
||||
}
|
||||
},
|
||||
"14": {
|
||||
"14.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"21": {
|
||||
"21.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"23": {
|
||||
"23.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"24": {
|
||||
"24.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"26": {
|
||||
"26.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"27": {
|
||||
"27.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"32": {
|
||||
"32.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"37": {
|
||||
"37.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"40": {
|
||||
"40.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"45": {
|
||||
"45.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"48": {
|
||||
"48.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"49": {
|
||||
"49.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"53": {
|
||||
"53.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"56": {
|
||||
"56.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"59": {
|
||||
"59.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"62": {
|
||||
"62.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"65": {
|
||||
"65.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"68": {
|
||||
"68.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"71": {
|
||||
"71.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"76": {
|
||||
"76.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"77": {
|
||||
"77.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"78": {
|
||||
"78.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"80": {
|
||||
"80.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"81": {
|
||||
"81.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
},
|
||||
"82": {
|
||||
"82.png": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import json
|
||||
from PIL import Image
|
||||
import os
|
||||
|
||||
# 全局变量定义分辨率
|
||||
RESIZE_TO = (360, 360)
|
||||
LARGE_IMAGE_SIZE = (2880, 2880)
|
||||
IMAGE_COUNT = 64
|
||||
|
||||
ROOT_DIR = '../example/src/main/assets/pic'
|
||||
|
||||
def load_json(file_path):
|
||||
with open(file_path, 'r') as file:
|
||||
return json.load(file)
|
||||
|
||||
def remove_white_border(image):
|
||||
"""
|
||||
去除图片边缘的一个像素宽的白色边框。
|
||||
:param image: 输入的PIL Image对象。
|
||||
:return: 处理后的PIL Image对象。
|
||||
"""
|
||||
# 获取图像尺寸
|
||||
width, height = image.size
|
||||
|
||||
# 定义白色阈值,允许一定的误差范围
|
||||
white_threshold = (250, 250, 250)
|
||||
|
||||
# 查找左边界
|
||||
left = 0
|
||||
while left < width and all(image.getpixel((left, y))[:3] >= white_threshold for y in range(height)):
|
||||
left += 1
|
||||
|
||||
# 查找右边界
|
||||
right = width - 1
|
||||
while right > 0 and all(image.getpixel((right, y))[:3] >= white_threshold for y in range(height)):
|
||||
right -= 1
|
||||
|
||||
# 查找上边界
|
||||
top = 0
|
||||
while top < height and all(image.getpixel((x, top))[:3] >= white_threshold for x in range(width)):
|
||||
top += 1
|
||||
|
||||
# 查找下边界
|
||||
bottom = height - 1
|
||||
while bottom > 0 and all(image.getpixel((x, bottom))[:3] >= white_threshold for x in range(width)):
|
||||
bottom -= 1
|
||||
|
||||
# 如果发现有白色边框,则裁剪它们
|
||||
if left < right and top < bottom:
|
||||
image = image.crop((left, top, right + 1, bottom + 1))
|
||||
|
||||
return image
|
||||
|
||||
def resize_image(image_path):
|
||||
image = Image.open(image_path).convert('RGBA')
|
||||
image = remove_white_border(image)
|
||||
return image.resize(RESIZE_TO)
|
||||
|
||||
def main(json_file_path):
|
||||
# 确保使用完整路径
|
||||
json_file_path = os.path.join(ROOT_DIR, json_file_path)
|
||||
data = load_json(json_file_path)
|
||||
|
||||
new_data = {}
|
||||
|
||||
for folder_name, images in data.items():
|
||||
large_image = Image.new('RGBA', LARGE_IMAGE_SIZE, color=(0, 0, 0, 0))
|
||||
images_coordinates = {}
|
||||
index = 0
|
||||
|
||||
for image_name in images:
|
||||
if index >= IMAGE_COUNT:
|
||||
break
|
||||
# 图片位于子文件夹内
|
||||
img_path = os.path.join(ROOT_DIR, folder_name, image_name)
|
||||
img = resize_image(img_path)
|
||||
x = (index % 8) * RESIZE_TO[0]
|
||||
y = (index // 8) * RESIZE_TO[1]
|
||||
large_image.paste(img, (x, y))
|
||||
images_coordinates[image_name] = {'x': x, 'y': y}
|
||||
index += 1
|
||||
|
||||
output_image_path = os.path.join(ROOT_DIR, folder_name, f"{folder_name}ex.png")
|
||||
large_image.save(output_image_path, format='png')
|
||||
|
||||
# 将坐标信息直接保存到new_data字典中
|
||||
new_data[folder_name] = images_coordinates
|
||||
|
||||
# 输出新的json文件
|
||||
output_json_path = os.path.join(ROOT_DIR, 'motion_data_ex.json')
|
||||
with open(output_json_path, 'w') as outfile:
|
||||
json.dump(new_data, outfile, indent=4)
|
||||
|
||||
# 使用示例
|
||||
main('motion_data.json')
|
||||
@@ -404,6 +404,17 @@ void Application::createCommandPool() {
|
||||
if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to create command pool!");
|
||||
}
|
||||
|
||||
queueFamilyIndices = findQueueFamilies(physicalDevice, surface);
|
||||
|
||||
VkCommandPoolCreateInfo poolInfo_ex{};
|
||||
poolInfo_ex.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
poolInfo_ex.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
|
||||
poolInfo_ex.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // 添加标志
|
||||
|
||||
if (vkCreateCommandPool(device, &poolInfo_ex, nullptr, &commandPool_ex) != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to create command pool!");
|
||||
}
|
||||
}
|
||||
|
||||
void Application::createCommandBuffer()
|
||||
@@ -641,30 +652,30 @@ uint32_t Application::findMemoryType(VkPhysicalDevice physicalDevice, uint32_t t
|
||||
throw std::runtime_error("Failed to find suitable memory type!");
|
||||
}
|
||||
|
||||
void Application::loadTexture(std::string path, Texture& tex, bool srgb)
|
||||
void Application::loadTexture(std::string path, Texture& tex, bool srgb, VkCommandPool pool)
|
||||
{
|
||||
std::vector<unsigned char> data = readFileUnsignedChar(path, false);
|
||||
std::vector<unsigned char> image;
|
||||
unsigned w, h;
|
||||
unsigned error = lodepng::decode(image, w, h, data, LCT_RGBA, 8);
|
||||
processWithVulkan(image.data(), w, h, w * 4, image.size(), tex, srgb);
|
||||
processWithVulkan(image.data(), w, h, w * 4, image.size(), tex, srgb, pool);
|
||||
//return tex;
|
||||
}
|
||||
|
||||
void Application::loadTexture(std::vector<unsigned char>& image_data, size_t image_size, int w, int h, Texture& tex, bool srgb)
|
||||
void Application::loadTexture(std::vector<unsigned char>& image_data, size_t image_size, int w, int h, Texture& tex, bool srgb, VkCommandPool pool)
|
||||
{
|
||||
processWithVulkan(image_data.data(), w, h, w * 4, image_size, tex, srgb);
|
||||
processWithVulkan(image_data.data(), w, h, w * 4, image_size, tex, srgb, pool);
|
||||
//return tex;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void Application::loadTextureExample(std::wstring path, Texture& tex, bool srgb)
|
||||
void Application::loadTextureExample(std::wstring path, Texture& tex, bool srgb, VkCommandPool pool)
|
||||
{
|
||||
std::vector<unsigned char> data = readFileUnsignedCharWin32(path, true);
|
||||
std::vector<unsigned char> image;
|
||||
unsigned w, h;
|
||||
unsigned error = lodepng::decode(image, w, h, data, LCT_RGBA, 8);
|
||||
processWithVulkan(image.data(), w, h, w * 4, image.size(), tex, srgb);
|
||||
processWithVulkan(image.data(), w, h, w * 4, image.size(), tex, srgb, pool);
|
||||
//return tex;
|
||||
}
|
||||
|
||||
@@ -772,7 +783,7 @@ void Application::createTexture(VkDevice device, VkPhysicalDevice physicalDevice
|
||||
texture.device = device;
|
||||
}
|
||||
|
||||
void Application::processWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& out_texture, bool srgb)
|
||||
void Application::processWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& out_texture, bool srgb, VkCommandPool pool)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
if (out_texture.image == VK_NULL_HANDLE)
|
||||
@@ -781,7 +792,7 @@ void Application::processWithVulkan(uint8_t* data, int width, int height, int ro
|
||||
|
||||
}
|
||||
|
||||
updateTexture(device, physicalDevice, commandPool, graphicsQueue, data, width, height,
|
||||
updateTexture(device, physicalDevice, pool, graphicsQueue, data, width, height,
|
||||
rowStride, dataSize, out_texture);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
virtual void render(VkCommandBuffer commandBuffer, long long frameTime);
|
||||
virtual bool isInited() { return inited; }
|
||||
|
||||
void processWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& out_texture, bool srgb);
|
||||
void processWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& out_texture, bool srgb, VkCommandPool pool);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -73,7 +73,9 @@ protected:
|
||||
std::vector<VkFramebuffer> swapChainFramebuffers; // 帧缓冲区
|
||||
VkQueue presentQueue; // 呈现队列
|
||||
|
||||
public:
|
||||
VkCommandPool commandPool;
|
||||
VkCommandPool commandPool_ex;
|
||||
std::vector<VkCommandBuffer> commandBuffers;
|
||||
std::vector<VkSemaphore> imageAvailableSemaphores; // 每个交换链图像一个
|
||||
std::vector<VkSemaphore> renderFinishedSemaphores; // 每个交换链图像一个
|
||||
@@ -85,10 +87,10 @@ protected:
|
||||
|
||||
|
||||
protected:
|
||||
void loadTexture(std::string path, Texture& tex, bool srgb);
|
||||
void loadTexture(std::vector<unsigned char>& image_data, size_t image_size, int w, int h, Texture& tex, bool srgb);
|
||||
void loadTexture(std::string path, Texture& tex, bool srgb, VkCommandPool pool);
|
||||
void loadTexture(std::vector<unsigned char>& image_data, size_t image_size, int w, int h, Texture& tex, bool srgb, VkCommandPool pool);
|
||||
#ifdef _WIN32
|
||||
void loadTextureExample(std::wstring path, Texture& tex, bool srgb);
|
||||
void loadTextureExample(std::wstring path, Texture& tex, bool srgb, VkCommandPool pool);
|
||||
#endif
|
||||
|
||||
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter,
|
||||
|
||||
@@ -17,6 +17,9 @@ FaceApp::FaceApp(/* args */)
|
||||
|
||||
FaceApp::~FaceApp()
|
||||
{
|
||||
if (worker_.joinable()) {
|
||||
worker_.join();
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiveFacePoint(float* pos, int pointCount, int width, int height)
|
||||
@@ -106,7 +109,8 @@ void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowS
|
||||
oldestFrame.rowStride,
|
||||
oldestFrame.dataSize,
|
||||
tex_bg,
|
||||
false
|
||||
false,
|
||||
FaceApp::Get()->commandPool
|
||||
);
|
||||
|
||||
frameQueue.pop();
|
||||
@@ -660,7 +664,7 @@ void FaceApp::render(VkCommandBuffer commandBuffer, long long frameTime)
|
||||
|
||||
|
||||
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &m_descriptor_sets[_curTexIndex], 0, NULL);
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &m_descriptor_sets[_curMotionIndex], 0, NULL);
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline);
|
||||
|
||||
vkCmdPushConstants(commandBuffer, m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float), &myFloatValue);
|
||||
@@ -718,22 +722,22 @@ void FaceApp::initVulkan()
|
||||
m_texs_ex.resize(kMaxTexture);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> data = readFileUnsignedChar("demo0.png", false);
|
||||
std::vector<unsigned char> data = readFileUnsignedChar("dummy.png", false);
|
||||
std::vector<unsigned char> image;
|
||||
unsigned w, h;
|
||||
unsigned error = lodepng::decode(image, w, h, data, LCT_RGBA, 8);
|
||||
|
||||
for (int i = 0; i < kMaxTexture; ++i)
|
||||
{
|
||||
loadTexture(image, image.size(), w, h, m_texs[i], true);
|
||||
loadTexture(image, image.size(), w, h, m_texs_next[i], true);
|
||||
loadTexture(image, image.size(), w, h, m_texs[i], true, commandPool);
|
||||
loadTexture(image, image.size(), w, h, m_texs_next[i], true, commandPool);
|
||||
if (kThick)
|
||||
{
|
||||
loadTexture(image, image.size(), w, h, m_texs_ex[i], true);
|
||||
loadTexture(image, image.size(), w, h, m_texs_ex[i], true, commandPool);
|
||||
}
|
||||
}
|
||||
|
||||
loadTexture("out.png", tex_bg, true);
|
||||
loadTexture("out.png", tex_bg, true, commandPool);
|
||||
createVertexBuffer();
|
||||
createUniformBuffer();
|
||||
setup_descriptor_pool();
|
||||
@@ -1271,6 +1275,8 @@ void FaceApp::cleanup()
|
||||
// vmaDestroyAllocator(allocator);
|
||||
// allocator = VK_NULL_HANDLE;
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1287,57 +1293,74 @@ void FaceApp::drawFrame(long long frameTime)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_motionState == loading_next_motion)
|
||||
{
|
||||
int i = _nextMotionIndex;
|
||||
//for (int i = 0; i < _curMotion.png_names.size(); ++i)
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
string path = "pic";
|
||||
string path_name = path + "/" + _nextMotion.type + "/" + _nextMotion.png_names[i];// +std::to_string(i) + ".png";
|
||||
loadTextureExample(UTF8ToWideString(path_name), m_texs_next[i], true);
|
||||
#else
|
||||
//string path = _curMotion.type + "/" + _curMotion.technique + "/" + _curMotion.step + "/" + _curMotion.show_type;
|
||||
string path = "pic";
|
||||
string path_name = path + "/" + _nextMotion.type + "/" + _nextMotion.png_names[i];// +std::to_string(i) + ".png";
|
||||
loadTexture(path_name, m_texs_next[i], true);
|
||||
#endif // _WIN32
|
||||
|
||||
_nextMotionIndex++;
|
||||
if (_nextMotionIndex >= _nextMotion.png_names.size())
|
||||
{
|
||||
_motionState = load_next_motion_finished;
|
||||
_callback(_nextMotion.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (_motionState == loading_next_motion)
|
||||
// {
|
||||
// int i = _nextMotionIndex;
|
||||
// //for (int i = 0; i < _curMotion.png_names.size(); ++i)
|
||||
// {
|
||||
//
|
||||
//#ifdef _WIN32
|
||||
// string path = "pic";
|
||||
// string path_name = path + "/" + _nextMotion.name + "/" + _nextMotion.png_names[i];// +std::to_string(i) + ".png";
|
||||
// loadTextureExample(UTF8ToWideString(path_name), m_texs_next[i], true);
|
||||
//#else
|
||||
// //string path = _curMotion.type + "/" + _curMotion.technique + "/" + _curMotion.step + "/" + _curMotion.show_type;
|
||||
// string path = "pic";
|
||||
// string path_name = path + "/" + _nextMotion.type + "/" + _nextMotion.png_names[i];// +std::to_string(i) + ".png";
|
||||
// loadTexture(path_name, m_texs_next[i], true);
|
||||
//#endif // _WIN32
|
||||
//
|
||||
// _nextMotionIndex++;
|
||||
// if (_nextMotionIndex >= _nextMotion.png_names.size())
|
||||
// {
|
||||
// _motionState = load_next_motion_finished;
|
||||
// _callback_loadfinish(_nextMotion.name);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
std::unique_lock lock(changeMotionMtx);
|
||||
static long long game_time = 0;
|
||||
game_time += frameTime;
|
||||
long long actionTime = (1000 / _initArg.action_fps);
|
||||
if (game_time > actionTime)
|
||||
{
|
||||
_curTexIndex++;
|
||||
if (_curTexIndex >= _curMotion_png_size)
|
||||
{
|
||||
if(_animationFinishedCallback != nullptr)
|
||||
{
|
||||
_animationFinishedCallback();
|
||||
}
|
||||
|
||||
if (_animationLoop)
|
||||
if (_curMotions.size() > 0)
|
||||
{
|
||||
static long long game_time = 0;
|
||||
game_time += frameTime;
|
||||
long long actionTime = (1000 / _initArg.action_fps);
|
||||
if (game_time > actionTime)
|
||||
{
|
||||
if (_curFrameIndex < _curMotions[_curMotionIndex].frames.size() - 1)
|
||||
{
|
||||
_curTexIndex = 0;
|
||||
_curFrameIndex += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_curTexIndex = _curMotion_png_size - 1;
|
||||
if (_curMotionIndex < _curMotions.size() - 1)
|
||||
{
|
||||
_curMotionIndex++;
|
||||
_curFrameIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_animationFinishedCallback != nullptr)
|
||||
{
|
||||
_animationFinishedCallback();
|
||||
}
|
||||
|
||||
if (_animationLoop)
|
||||
{
|
||||
_curMotionIndex = 0;
|
||||
_curFrameIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_animationFinishedCallback = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
game_time = game_time - actionTime;
|
||||
}
|
||||
game_time = game_time - actionTime;
|
||||
}
|
||||
|
||||
Application::drawFrame(frameTime);
|
||||
}
|
||||
|
||||
@@ -1347,36 +1370,52 @@ void FaceApp::drawFrame(long long frameTime)
|
||||
// changeMotion(motion);
|
||||
//}
|
||||
|
||||
string FaceApp::preReadyMotion(const std::string& json, Callback callback)
|
||||
string FaceApp::preLoadMotionList(const vector<string>& motions, Callback callback)
|
||||
{
|
||||
if (_motionState == loading_next_motion)
|
||||
if (_isLoadMotion)
|
||||
{
|
||||
return "busy on loading:" + _nextMotion.type;
|
||||
return "failue load not finished";
|
||||
}
|
||||
else if (_motionState == load_next_motion_finished)
|
||||
_isLoadMotion = true;
|
||||
_callback_loadfinish = callback;
|
||||
_preLoadMotions.clear();
|
||||
for (auto s : motions)
|
||||
{
|
||||
return "waitting change next action:" + _nextMotion.type;
|
||||
json j = json::parse(s);
|
||||
Motion motion = j.get<Motion>();
|
||||
_preLoadMotions.push_back(motion);
|
||||
}
|
||||
else if (_motionState == ready)
|
||||
{
|
||||
Motion motion = json::parse(json);
|
||||
_nextMotion = motion;
|
||||
_motionState = loading_next_motion;
|
||||
_nextMotionIndex = 0;
|
||||
_callback = callback;
|
||||
return "success";
|
||||
}
|
||||
return "failure";
|
||||
worker_ = std::thread(&FaceApp::loadMotionThread, this);
|
||||
return "ok";
|
||||
}
|
||||
|
||||
void FaceApp::changeMotion(const string motion_type, AnimationFinishedCallback callback, bool loop)
|
||||
void FaceApp::loadMotionThread()
|
||||
{
|
||||
if (_curMotion_type == motion_type)
|
||||
for (int i = 0; i < _preLoadMotions.size(); ++i)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!_running)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (_motionState != load_next_motion_finished)
|
||||
#ifdef _WIN32
|
||||
string path = "pic";
|
||||
string path_name = path + "/" + _preLoadMotions[i].name + "/" + _preLoadMotions[i].name + "ex.png";
|
||||
loadTextureExample(UTF8ToWideString(path_name), m_texs_next[i], true, commandPool_ex);
|
||||
#else
|
||||
string path = "pic";
|
||||
string path_name = path + "/" + _preLoadMotions[i].name + "/" + _preLoadMotions[i].name + "ex.png";
|
||||
loadTexture(path_name, m_texs_next[i], true, commandPool_ex);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
_isLoadMotion = false;
|
||||
_callback_loadfinish();
|
||||
}
|
||||
|
||||
void FaceApp::changeMotionList(AnimationFinishedCallback callback, bool loop)
|
||||
{
|
||||
if (_isLoadMotion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1384,24 +1423,23 @@ void FaceApp::changeMotion(const string motion_type, AnimationFinishedCallback c
|
||||
std::unique_lock<std::mutex> lock_changeMotion(changeMotionMtx);
|
||||
|
||||
|
||||
for (int i = 0; i < _nextMotion.png_names.size(); ++i)
|
||||
for (int i = 0; i < _preLoadMotions.size(); ++i)
|
||||
{
|
||||
destroyTexture(device, m_texs[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _nextMotion.png_names.size(); ++i)
|
||||
for (int i = 0; i < _preLoadMotions.size(); ++i)
|
||||
{
|
||||
m_texs[i] = m_texs_next[i];
|
||||
m_texs_next[i].reset();
|
||||
}
|
||||
|
||||
update_descriptor_set(m_texs);
|
||||
_curMotion_type = motion_type;
|
||||
_curMotion_png_size = _nextMotion.png_names.size();
|
||||
_motionState = ready;
|
||||
_curMotions = _preLoadMotions;
|
||||
_animationFinishedCallback = callback;
|
||||
_animationLoop = loop;
|
||||
_curTexIndex = 0;
|
||||
_curFrameIndex = 0;
|
||||
_curMotionIndex = 0;
|
||||
|
||||
|
||||
// for (int i = 0; i < _curMotion.png_names.size(); ++i)
|
||||
|
||||
@@ -12,13 +12,20 @@
|
||||
using namespace std;
|
||||
using json = nlohmann::json;
|
||||
|
||||
struct Frame {
|
||||
string name;
|
||||
float x;
|
||||
float y;
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Frame, name, x, y)
|
||||
};
|
||||
|
||||
struct Motion {
|
||||
string type;
|
||||
vector<string> png_names;
|
||||
string name;
|
||||
vector< Frame> frames;
|
||||
string getMotionId() {
|
||||
return type;
|
||||
return name;
|
||||
}
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Motion, type, png_names)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Motion, name, frames)
|
||||
};
|
||||
|
||||
struct InitArg
|
||||
@@ -34,7 +41,7 @@ struct PushConstants {
|
||||
float myValue;
|
||||
};
|
||||
|
||||
using Callback = std::function<void(const std::string&)>;
|
||||
using Callback = std::function<void()>;
|
||||
using AnimationFinishedCallback = std::function<void()>;
|
||||
|
||||
class FaceApp :public Application
|
||||
@@ -103,7 +110,7 @@ private:
|
||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
|
||||
vector<VkDescriptorSet> m_descriptor_sets;
|
||||
const uint32_t kMaxTexture = 60;
|
||||
const uint32_t kMaxTexture = 10;
|
||||
vector<Texture> m_texs;
|
||||
vector<Texture> m_texs_next;
|
||||
vector<Texture> m_texs_ex;
|
||||
@@ -139,28 +146,35 @@ private:
|
||||
|
||||
|
||||
public:
|
||||
Callback _callback;
|
||||
void loadMotionThread();
|
||||
std::thread worker_;
|
||||
bool _isLoadMotion = false;
|
||||
Callback _callback_loadfinish;
|
||||
AnimationFinishedCallback _animationFinishedCallback;
|
||||
bool _animationLoop = true;
|
||||
string preReadyMotion(const std::string& json, Callback callback);
|
||||
void changeMotion(const string motion_type, AnimationFinishedCallback callback, bool loop);
|
||||
string preLoadMotionList(const vector<string>& motions, Callback callback);
|
||||
vector<Motion>_preLoadMotions;
|
||||
vector<Motion>_curMotions;
|
||||
void changeMotionList(AnimationFinishedCallback callback, bool loop);
|
||||
|
||||
//void changeMotion(Motion& motion);
|
||||
InitArg _initArg;
|
||||
//Motion _curMotion;
|
||||
string _curMotion_type;
|
||||
int _curMotion_png_size;
|
||||
Motion _nextMotion;
|
||||
int _nextMotionIndex;
|
||||
//string _curMotion_type;
|
||||
//int _curMotion_png_size;
|
||||
//Motion _nextMotion;
|
||||
//int _nextMotionIndex;
|
||||
|
||||
enum MotionState {
|
||||
ready,
|
||||
loading_next_motion,
|
||||
load_next_motion_finished,
|
||||
};
|
||||
//enum MotionState {
|
||||
// ready,
|
||||
// loading_next_motion,
|
||||
// load_next_motion_finished,
|
||||
//};
|
||||
|
||||
MotionState _motionState = ready;
|
||||
//MotionState _motionState = ready;
|
||||
|
||||
int _curTexIndex = 0;
|
||||
int _curFrameIndex = 0;
|
||||
int _curMotionIndex = 0;
|
||||
void SetInitArg(const char* arg);
|
||||
|
||||
void drawFrame(long long frameTime)override;
|
||||
|
||||
@@ -47,9 +47,44 @@ void CppAnimationFinishedCallback()
|
||||
std::cout << "call CppAnimationFinishedCallback\n";
|
||||
}
|
||||
|
||||
void CppCallback(const string& motion_type)
|
||||
void CppCallback()
|
||||
{
|
||||
g_app->changeMotion(motion_type.c_str(), CppAnimationFinishedCallback, true);
|
||||
g_app->changeMotionList(CppAnimationFinishedCallback, true);
|
||||
}
|
||||
|
||||
// 读取JSON文件并填充到motions容器中
|
||||
void loadMotions(const std::string& filePath, std::map<std::string, Motion>& motions) {
|
||||
// 读取json文件
|
||||
std::ifstream i(filePath);
|
||||
if (!i.is_open()) {
|
||||
std::cerr << "无法打开文件" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
json j;
|
||||
try {
|
||||
i >> j;
|
||||
}
|
||||
catch (json::parse_error& ex) { // 捕获解析错误
|
||||
std::cerr << "JSON解析错误: " << ex.what() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历json对象并填充到motions中
|
||||
for (auto& motionEntry : j.items()) {
|
||||
Motion motion;
|
||||
motion.name = motionEntry.key();
|
||||
|
||||
for (auto& frameEntry : motionEntry.value().items()) {
|
||||
Frame frame;
|
||||
frame.name = frameEntry.key();
|
||||
frame.x = frameEntry.value()["x"].get<float>();
|
||||
frame.y = frameEntry.value()["y"].get<float>();
|
||||
motion.frames.push_back(frame);
|
||||
}
|
||||
|
||||
motions[motion.getMotionId()] = motion;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,23 +97,25 @@ int main() {
|
||||
|
||||
InitArg init_arg;
|
||||
Motion motion;
|
||||
motion.type = "4";
|
||||
motion.name = "4";
|
||||
//motion.png_names.push_back("4.png");
|
||||
for (int i = 1; i < 61; ++i)
|
||||
{
|
||||
if (i < 10)
|
||||
{
|
||||
motion.png_names.push_back("00" + std::to_string(i) + ".png");
|
||||
}
|
||||
else
|
||||
{
|
||||
motion.png_names.push_back("0" + std::to_string(i) + ".png");
|
||||
//for (int i = 1; i < 61; ++i)
|
||||
//{
|
||||
// if (i < 10)
|
||||
// {
|
||||
// motion.png_names.push_back("00" + std::to_string(i) + ".png");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// motion.png_names.push_back("0" + std::to_string(i) + ".png");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
#
|
||||
|
||||
std::map<string, Motion> motions;
|
||||
loadMotions("example/src/main/assets/pic/motion_data_ex.json", motions);
|
||||
|
||||
//init_arg.motion = motion;
|
||||
|
||||
@@ -103,8 +140,11 @@ int main() {
|
||||
std::cout << "Warning: Empty motion string" << std::endl;
|
||||
}
|
||||
|
||||
vector<string> s_motions;
|
||||
json j = motions["4"];
|
||||
s_motions.push_back(j.dump());
|
||||
|
||||
app.preReadyMotion(motion_str, CppCallback);
|
||||
app.preLoadMotionList(s_motions, CppCallback);
|
||||
app.mainLoop();
|
||||
//try {
|
||||
// app.mainLoop();
|
||||
|
||||