save code

This commit is contained in:
xsl
2025-12-18 22:05:10 +08:00
parent 9ee028248d
commit e38da96e37
40 changed files with 853 additions and 123 deletions
+19 -8
View File
@@ -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);
}
+6 -4
View File
@@ -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,
+112 -74
View File
@@ -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)
+34 -20
View File
@@ -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;
+57 -17
View File
@@ -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();